Module:ItemSources

From Outward Wiki
Jump to navigation Jump to search

Lua module used by ItemSources template.


local p = {}

function p.sources(frame)
    if frame == mw.getCurrentFrame() then
		args = require('Module:ProcessArgs').merge(true)
	else
		frame = mw.getCurrentFrame()
    end
    
    local _itemName = args.name or mw.title.getCurrentTitle().text

    local fields = '_pageName, itemName, minQty, maxQty, chance, type, location, notes, DLC'

    local wheres = 'ItemSource.itemName="' .. _itemName .. '" AND ItemSource._pageName NOT LIKE "%Quick guide%"'
    if (args.type ~= nil) then
        wheres = wheres .. 'AND type="' .. args.type .. '"'
    end

    local cargoArgs = {
        where = wheres, 
        orderBy = 'ItemSource.chance DESC, ItemSource._pageName',
        limit = args.Limit or args.limit or 15
    }

    local result = p.doQuery(_itemName, fields, cargoArgs)
	if not result then
		return ''
    end

	formattedResult = p.formatResult(result, frame, args)

    --mw.logObject(formattedResult)
    return p.makeTable(formattedResult, frame)    
end


function p.doQuery(_itemName, fields, cargoArgs)
    local result = mw.ext.cargo.query('ItemSource', fields, cargoArgs)
	if not next(result) then
		return nil
	else
		return result
    end    
end

function p.formatResult(result,frame,args)
    local formatted = {}
	for k,row in ipairs(result) do
        --formatted[k] = p.formatRow(row,frame,args,formatted)
        
        local formattedRow = {}

        local qtyTxt = ''
        if row.minQty >= row.maxQty then
            qtyTxt = string.format('%s', row.minQty)
        else
            qtyTxt = string.format('%s - %s', row.minQty, row.maxQty)
        end

        local dlc = ''
        if row.DLC ~= nil and row.DLC ~= '' then
            dlc = frame:preprocess('{{' .. row.DLC .. '}} ')
        end

        --local addedExisting = 0
        -- Sources with "chance"
        if (args.type == 'Merchant' or args.type == 'Enemy' or args.type == 'LootContainer' or args.type == 'Gatherable') then
            local chance = row.chance or 100
            if (tonumber(chance) <= 0) then
                chance = 100
            end

            
            if (args.type == 'Merchant' or args.type == 'LootContainer') then
                local locationsTxt = ''
                local tbl = split(row.location, ',')
                table.sort(tbl)
                for i, v in ipairs(tbl) do
                    if locationsTxt ~= '' then locationsTxt = locationsTxt .. ', ' end
                    locationsTxt = locationsTxt .. '[[' .. v .. ']]'
                end
                if (args.type == 'Merchant') then
                    local name = row._pageName
                    if (string.find(name, 'Soroborean Caravanner') ~= nil) then
                        name = 'Soroborean Caravanner'
                    end
                    formattedRow = {
                        name=       frame:preprocess(string.format("[[%s]]", name)),
                        chance=     frame:preprocess(chance),
                        quantity =  qtyTxt,
                        location=   frame:preprocess(locationsTxt)
                    }
                elseif (args.type == 'LootContainer') then
                    formattedRow = {
                        name=       frame:preprocess(string.format("[[%s]]", row._pageName)),
                        chance=     frame:preprocess(chance),
                        quantity =  qtyTxt,
                        location=   frame:preprocess(locationsTxt)
                    }
                end
            else -- Enemy or Gatherable
                formattedRow = {
                    name =      frame:preprocess(string.format("[[%s]]", row._pageName)),
                    chance =    frame:preprocess(chance),
                    quantity =  qtyTxt
                }
            end
            -- for data sort
            formattedRow.maxQty = row.maxQty

            formattedRow.name = formattedRow.name .. ' ' .. dlc

        else --Sources without "chance" (Quest, Spawn, Unique/Other, DefeatScenario)
            local nameLink = '[[' .. row._pageName .. ']] ' .. dlc 
			local s = nameLink .. '(x' .. qtyTxt .. ')'
			if (row.notes ~= nil and row.notes ~= '') then
				s = s .. ' - ' .. row.notes
			end
            formattedRow = {
                frame:preprocess(s)
            }
        end

        formatted[k] = formattedRow
    end
    return formatted    
end




function p.tablefind(tab,el)
    for index, row in pairs(tab) do
        if row == el then
            return index
        end
	end
	return -1
end

function p.round(num, numDecimalPlaces)
    return tonumber(string.format("%." .. (numDecimalPlaces or 0) .. "f", num))
end

function p.makeTable(formatted, frame)
    local html = mw.html.create()

    local s = ''
    if (args.type == 'Enemy') then
        s = 'Enemy Drops'
    elseif (args.type == 'Merchant') then
        s = 'Merchant Sources'
    elseif (args.type == 'LootContainer') then
        s = 'Loot Container Sources'
    elseif (args.type == 'Gatherable') then
        s = 'Gatherable Sources'
    elseif (args.type == 'Quest') then
        s = 'Quest Sources'
    elseif (args.type == 'Spawn') then
        s = 'World Spawns'
    elseif (args.type == 'Unique') then
        s = 'Unique Sources'
    elseif (args.type == 'DefeatScenario') then
    	s = "Defeat Scenarios"    	
    end
    html:wikitext(frame:preprocess(string.format('<span class="heading" style="font-size: 13pt; font-weight: 600">%s</span>', s)))

    if (args.type == 'Quest' or args.type == 'Spawn' or args.type == 'Unique' or args.type == 'DefeatScenario') then
        local ul = html:tag('ul')
        for _, row in ipairs(formatted) do
            ul:tag('li'):wikitext(row[1])
        end
    elseif (args.type == 'Enemy' or args.type == 'Merchant' or args.type == 'LootContainer' or args.type == 'Gatherable') then
        local tbl = html:tag('table'):addClass('wikitable sortable')
        local tr = tbl:tag('tr')
        tr:tag('th'):wikitext('Source'):cssText('min-width:85px')
        tr:tag('th'):wikitext('Quantity')
        tr:tag('th'):wikitext('Chance')

        if (args.type == 'LootContainer' or args.type == 'Merchant') then
            local minwidth = 0
            for _, row in ipairs(formatted) do
                local n = string.len(row.location)
                if n > minwidth then minwidth = n end
            end
            local widthtext = tostring(minwidth * 8)
            tr:tag('th'):cssText('min-width:' .. minwidth .. 'px;'):wikitext('Locations')
        end

        for _, row in ipairs(formatted) do 
            tr = tbl:tag('tr')

            tr:tag('td'):css('text-align','left'):wikitext(row.name)

            tr:tag('td'):attr('data-sort-value', row.maxQty):css('text-align','center'):wikitext(row.quantity)

            local color = ''
            local chance = tonumber(row.chance)
            local v = p.round(chance, 1)
            tr:tag('td'):addClass(p.getRarity(chance)):css('text-align','center'):wikitext(string.format('%s%%', v))

            if (args.type == 'LootContainer' or args.type == 'Merchant') then
                
                tr:tag('td'):wikitext(row.location)
            end
        end
    end

    return html
end

function p.getRarity(chance)
    local color = ''
    if chance == 100 then
        color = 'rarity-always'     -- Guaranteed (blue)
    elseif chance > 24 then
        color = 'rarity-common'     -- Common (green)
    elseif chance > 11 then
        color = 'rarity-uncommon'   -- Uncommon (yellow)
    elseif chance > 4 then
        color = 'rarity-rare'       -- Rare (orange)
    else
        color = 'rarity-veryrare'   -- Very rare (dark red)
    end
    return color
end

function split(inputstr, sep)
    if sep == nil then
        sep = "%s"
    end
    local t={}
    for str in string.gmatch(inputstr or '', "([^"..sep.."]+)") do
        table.insert(t, str)
    end
    return t
end

return p