Module:Get production info

Revision as of 21:22, 4 November 2021 by Admin (talk | contribs) (1 revision imported)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Documentation for this module may be created at Module:Get production info/doc

-- <pre>
local p = {}
local geprice = require('Module:ExchangeLite').price
local commas = require('Module:Addcommas')
local skillpic = require('Module:Skill_clickpic')._main
local hc = require('Module:Paramtest').has_content
local yesno = require('Module:Yesno')
local purge = require('Module:Purge')._purge
local lang = mw.getContentLanguage()
local aliases = mw.loadData('Module:Get production info/aliases')

local sortskillmap = { ['agility']=1000, ['construction']=2000, ['cooking']=3000, ['crafting']=4000, ['divination']=5000, ['dungeoneering']=6000, ['farming']=7000,
	['firemaking']=8000, ['fishing']=9000, ['fletching']=10000, ['herblore']=11000, ['hunter']=12000, ['invention']=13000, ['magic']=14000, ['melee']=15000, ['mining']=16000,
	['prayer']=17000, ['ranged']=18000, ['runecrafting']=19000, ['smithing']=20000, ['slayer']=21000, ['summoning']=22000, ['thieving']=23000, ['woodcutting']=24000 }

local function cleanName(name)
	local cleaned = string.gsub(name, "%p", "")

	if #cleaned then
		return cleaned
	end

	return name
end

local function cleanNameSort(t1, t2)
	local clean1 = cleanName(t1[1])
	local clean2 = cleanName(t2[1])

	return clean1 < clean2
end

function p.main(frame)
	return p._main(frame:getParent())
end
function p._main(frame)
	local args = frame.args
	local material = args[1] or args.material or mw.title.getCurrentTitle().text
	local showxp = yesno(args.xp) or false
	local showprofit = yesno(args.profit) or false
	local skillsort =  false
	if hc(args.skillsort) then
		skillsort = args.skillsort
	end
	local methodfilter = 'no method filter'
	if hc(args.exclude) then
		methodfilter = args.exclude
	end

    local query = {
        '[[Made from item::'..material..']]',
        '[[Production JSON::+]]',
        '?=#',
        '?Category:Removed content=Removed',
        '?Category:Pages using information from game APIs or cache=CacheOnly',
        '?Production JSON',
        limit = args.limit or 100,
        sort = args.sort,
        order = args.order
    }
    local smwdata = mw.smw.ask(query)

    local alias = ''
    if aliases[material] then
    	alias = string.lower(aliases[material].name)

    	local aQuery = {
	        '[[Made from item::'..aliases[material].name..']]',
	        '?=#',
	        '?Category:Removed content=Removed',
	        '?Category:Pages using information from game APIs or cache=CacheOnly',
	        '?Production JSON',
	        limit = args.limit or 100,
	        sort = args.sort,
	        order = args.order
	    }
	    local aSmwdata = mw.smw.ask(aQuery)

	    if aSmwdata then
	    	if not smwdata then
	    		smwdata = {}
	    	end
	    	for i,v in pairs(aSmwdata) do
	    		v.isalias = true
	    		v.amtadj = aliases[material].adj
	    		table.insert(smwdata, v)
	    	end
	    else
	    	if not smwdata then
		        return string.format('Failed to find products with that material or its alias ("%s")- ensure it is spelled correctly. (ERR: no results from SMW)[[Category:Empty drop lists]]', aliases[material].name)
		    end
	    end
    end

    if smwdata then
    	for i, v in ipairs(smwdata) do
    		if v.Removed or v.CacheOnly then
    			table.remove(smwdata, i)
			end
		end
	end

    if not smwdata or #smwdata == 0 then
        return 'Failed to find products with that material - ensure it is spelled correctly. (ERR: no results from SMW)[[Category:Empty drop lists]]'
    end

    local intro = string.format("<div class='seealso prodlistintro'>This is an auto-generated list (%s), and shows the first %s items alphabetically. For all items, click <span class='plainlinks'>[%s here]</span>.</div>", purge('Products', 'update now', 'span'), (args.limit or 100), tostring(mw.uri.fullUrl('Special:Ask', { q = '[[Made from item::'..material..']]', ['p[format]'] = 'table', ['p[limit]'] = 500, ['p[intro]'] = 'All items made from: '..material })))

    local mat = string.lower(material)
    local t = mw.html.create('table')
    t   :addClass('wikitable sortable products-list align-right-2 align-right-4 align-right-5 sticky-header')
    local ttlrow = t:tag('tr')
            :tag('th')
                :wikitext('Item')
            :done()
            :tag('th')
                :wikitext('Skills')
            :done()
            :tag('th')
                :wikitext('Materials')
            :done()
            :tag('th')
                :wikitext('GE price')
            :done()
    if showxp then
    	ttlrow:tag('th')
    		:wikitext('XP')
    	:done()
    end
    if showprofit then
    	ttlrow:tag('th')
    		:wikitext('Profit')
    	:done()
    end
    local rows = 0

    table.sort(smwdata, cleanNameSort)

    for _,smw_item in ipairs(smwdata) do
        local prod = smw_item['Production JSON']
        if type(prod) == 'string' then
            prod = { prod }
        end
        for _,prod_json in ipairs(prod) do
            local json_good, prod_t = pcall(mw.text.jsonDecode, mw.text.decode(prod_json))
            if json_good then
                local _found = false
                for _,mat_info in ipairs(prod_t.mats) do
                    if smw_item.isalias and mat_info.name:lower() == alias then
                    	_found = true
                        break
                    elseif mat_info.name:lower() == mat then
                        _found = true
                        break
                    end
                end
                if _found and methodfilter ~= 'no method filter' then
                	if prod_t.method == methodfilter then
                		_found = false
                	end
                end
                if _found then
                    local namestr
                    local prodLink = prod_t.link or prod_t.product
                    local editbtn = '['..tostring(mw.uri.fullUrl(prod_t.product,'action=edit'))..' '..('edit')..']'
                    if (prod_t.quantity or 1) > 1 then
                        namestr = string.format('%s&nbsp;[[%s|%s]] × %s', prod_t.image, prodLink, prod_t.product, prod_t.quantity)
                    else
                        namestr = string.format('%s&nbsp;[[%s|%s]]', prod_t.image, prodLink, prod_t.product)
                    end
                    if (tonumber(prod_t.improved) or 0) > 0 then
                    	namestr = namestr..string.format('<br /><i>(Improved +%s recipe)</i>', prod_t.improved)
                    elseif string.find(prod_t.method or '', '%S') then
                    	namestr = namestr..string.format('<br /><i>(%s)</i>', prod_t.method)
                    end
                    local skills_cell = mw.html.create('td')
                    local skills_ul = skills_cell:tag('ul')
                    skills_ul:addClass('skills-list')
                        :css({
                            ['list-style-type'] = 'none',
                            ['list-style-image'] = 'none',
                            margin = 0
                        })
                    local lvlsort = 0
                    if prod_t.skill == '?' then
                		local skill_li = skills_ul:tag('li')
                		skill_li:wikitext('<small>Unknown</small></br>'..editbtn)
                    elseif prod_t.skill ~= 'no' then
                    	local skill_li = skills_ul:tag('li')
                    	skill_li:wikitext(string.format('%s&nbsp;%s', prod_t.level, skillpic(lang:ucfirst(prod_t.skill))))
                    	if skillsort and string.lower(skillsort) == string.lower(prod_t.skill) then
                			lvlsort = prod_t.level
                		elseif not skillsort and tonumber(prod_t.level) then
                			lvlsort = prod_t.level + (sortskillmap[string.lower(prod_t.skill)] or 0)
                		end
                	else
                		local skill_li = skills_ul:tag('li')
                		skills_cell:addClass('table-na')
                		skill_li:wikitext(string.format('None'))
                	end
                    if prod_t.level2 ~= '?' then
                    	local skill_li = skills_ul:tag('li')
                        skill_li:wikitext(string.format('%s&nbsp;%s', prod_t.level2, skillpic(lang:ucfirst(prod_t.skill2))))
                        if skillsort and skillsort == prod_t.skill2 then
                			lvlsort = prod_t.level2
                		end
                    end
                    if prod_t.level3 ~= '?' and prod_t.level3 ~= nil then
                    	local skill_li = skills_ul:tag('li')
                        skill_li:wikitext(string.format('%s&nbsp;%s', prod_t.level3, skillpic(lang:ucfirst(prod_t.skill3))))
                        if skillsort and skillsort == prod_t.skill3 then
                			lvlsort = prod_t.level3
                		end
                    end
                    skills_cell:attr('data-sort-value', lvlsort)
                    local mats_ul = mw.html.create('ul')
                    mats_ul:addClass('products-materials')
                        :css({
                            ['list-style-type'] = 'none',
                            ['list-style-image'] = 'none',
                            margin = 0
                        })
                    local mats_sort = 0
                    local cost_raw = 0
                    for _, mat_info in ipairs(prod_t.mats) do
                        local mat_li = mats_ul:tag('li')
                        local qty = string.gsub(mat_info.quantity, '%-', '–')
                        local matnm = mat_info.name
                        if mat_info.name:lower() == mat then
                            mat_li:addClass('production-selected')
                            mats_sort = tonumber(qty) or 0
                        elseif smw_item.isalias and mat_info.name:lower() == alias then
                        	mat_li:addClass('production-selected')
                        	if tonumber(qty, 10) then
                            	qty = tonumber(qty, 10) * smw_item.amtadj
                            end
                            matnm = material
                            mats_sort = tonumber(qty) or 0
                        end
                        mat_li:wikitext(string.format('%s × [[%s]]', qty, matnm))
                            local price = geprice(matnm) or 0
                            cost_raw = cost_raw + price * (qty or 1)
                        end

                    local price_cell = mw.html.create('td')
                    local price_raw = geprice(prod_t.product)
                    if price_raw then
                        price_cell:wikitext(commas._add(price_raw * (prod_t.quantity or 1)))
                        	:attr('data-sort-value', price_raw * (prod_t.quantity or 1))
                    else
                        price_cell:wikitext('N/A')
                        	:addClass('table-na')
                        	:attr({ ['title']='This item has no available GE price.', ['data-sort-value']=0 })
                    end

                    local prow = t:tag('tr')
                        :tag('td')
                        	:attr('data-sort-value', cleanName(prod_t.product))
                            :wikitext(namestr)
                        :done()
                        :node(skills_cell)
                        :tag('td')
                        	:attr('data-sort-value', mats_sort)
                            :node(mats_ul)
                        :done()
                        :node(price_cell)
                    rows = rows + 1

                    if showxp then
                    	local xpul = mw.html.create('ul')
                    	local hasxp, unknownxp = false, false
                    	xpul:addClass('skills-list')
	                    	:css({
	                            ['list-style-type'] = 'none',
	                            ['list-style-image'] = 'none',
	                            margin = 0
	                        })
	                    local xpsort = 0
                    	if prod_t.exp and prod_t.exp ~= '?' then
                    		hasxp = true
                    		xpul:tag('li')
                    			:wikitext( string.format( '%s&nbsp;%s', commas._add(prod_t.exp), skillpic(lang:ucfirst(prod_t.skill)) ) )
                    		if skillsort and skillsort == prod_t.skill then
                    			xpsort = prod_t.exp
                    		elseif not skillsort and tonumber(prod_t.exp) then
                    			xpsort = xpsort + prod_t.exp
                    		end
                		elseif prod_t.exp == '?' then
                			unknownxp = true
                    	end
                    	if prod_t.exp2 and prod_t.exp2 ~= '?' then
                    		hasxp = true
                    		xpul:tag('li')
                    			:wikitext( string.format( '%s&nbsp;%s', commas._add(prod_t.exp2), skillpic(lang:ucfirst(prod_t.skill2)) ) )
                    		if skillsort and skillsort == prod_t.skill2 then
                    			xpsort = prod_t.exp2
                    		elseif not skillsort and tonumber(prod_t.exp2) then
                    			xpsort = xpsort + prod_t.exp2
                    		end
                		elseif prod_t.exp2 == '?' then
                			unknownxp = true
                    	end
                    	if prod_t.exp3 and prod_t.exp3 ~= '?' then
                    		hasxp = true
                    		xpul:tag('li')
                    			:wikitext( string.format( '%s&nbsp;%s', commas._add(prod_t.exp3), skillpic(lang:ucfirst(prod_t.skill3)) ) )
                    		if skillsort and skillsort == prod_t.skill3 then
                    			xpsort = prod_t.exp3
                    		elseif not skillsort and tonumber(prod_t.exp3) then
                    			xpsort = xpsort + prod_t.exp3
                    		end
                		elseif prod_t.exp3 == '?' then
                			unknownxp = true
                    	end
                    	if hasxp then
	                    	prow:tag('td')
	                    		:attr('data-sort-value', xpsort)
	                    		:node(xpul)
	                    	:done()
	                    elseif unknownxp then
                    		prow:tag('td')
                    			:wikitext('<small>Unknown</small></br>'..editbtn)
                			:done()
            			else
	                    	prow:tag('td')
	                    		:addClass('table-na')
	                    		:attr({ ['title']='This item gives no experience.', ['data-sort-value']=0 })
	                    		:wikitext('N/A')
	                    	:done()
	                    end
                    end

                    if showprofit then
                        if price_raw then
                            local profit1 = price_raw * (prod_t.quantity or 1) - cost_raw
                            local profclass = 'text-green'
                            if profit1 < 0 then
                                profclass = 'text-red'
                            end
                            prow
                                :tag('td')
                                :wikitext( commas._add(profit1))
                                :addClass(profclass)
                                :attr('data-sort-value',profit1)
                        else
                            prow
                                :tag('td')
                                :wikitext('N/A')
                                :addClass('table-na')
                                :attr({ ['title']='This item has no available GE price.', ['data-sort-value']=0 })
                        end
                    end
                end
            end
        end
    end

    if rows == 0 then
        return 'Failed to find products with that material - ensure it is spelled correctly. (ERR: no mat found in results)[[Category:Empty drop lists]]'
    end

    return intro..'\n'..tostring(t)
end

return p
--</pre>