Module:Sandbox/User:Jakesterwars/Uses material list

Module documentation
This documentation is transcluded from Template:Module sandbox/doc. [edit] [history] [purge]
Module:Sandbox/User:Jakesterwars/Uses material list requires Module:Addcommas.
Module:Sandbox/User:Jakesterwars/Uses material list requires Module:Exchange.
Module:Sandbox/User:Jakesterwars/Uses material list requires Module:SCP.
Module:Sandbox/User:Jakesterwars/Uses material list requires Module:Yesno.

This module is a sandbox for Jakesterwars. It can be used to test changes to existing modules, prototype new modules, or just experimenting with lua features.

Invocations of this sandbox should be kept in userspace; if the module is intended for use in other namespaces, it should be moved out of the sandbox into a normal module and template.

This default documentation can be overridden by creating the /doc subpage of this module, as normal.

local p = {}

local geprice = require('Module:Exchange')._price
local commas = require('Module:Addcommas')
local skillpic = require('Module:SCP')._main
local yesno = require('Module:Yesno')
local lang = mw.getContentLanguage()
local trim = mw.text.trim
local split = mw.text.split

function p.main(frame)
	return p._main(frame:getParent().args)
end

function p._main(args)
	local materials = {}
	if (args == nil) then
		table.insert(materials, mw.title.getCurrentTitle().text)
	else
		local splitMultiple = {}
		for type in string.gmatch(args[1], '([^,]+)') do
			table.insert(splitMultiple, type)
		end
		
		for _, v in ipairs(splitMultiple) do
			mw.log(v)
			table.insert(materials, trim(v))
		end
	end
	
	local materialsLowered = {}
	for index, material in pairs(materials) do
	    materialsLowered[material:lower()] = true
	end

    -- Fetch data
    local query = {
        '[[Uses material::'..table.concat(materials, '||')..']]',
        '[[Production JSON::+]]',
        '?=#-',
        '?Production JSON = json',
        limit = args.limit or 500,
    }
    local t1 = os.clock()
    local smwdata = mw.smw.ask(query)
    local t2 = os.clock()

    if not smwdata then
        return 'Failed to find products with those materials - ensure they are spelled correctly. (ERR: no results from SMW)[[Category:Empty drop lists]]'
    end
    mw.log(string.format('SMW: entries %d, time elapsed: %.3f ms.', #smwdata, (t2 - t1) * 1000))

    -- Post-process
    data = {}
    for _, e in ipairs(smwdata) do
    	if type(e['json']) == 'string' then
            local j = mw.text.jsonDecode(e['json'])
            table.insert(data, j)
        elseif type(e['json']) == 'table' then
        	for _, f in ipairs(e['json']) do
        		local j = mw.text.jsonDecode(f)
                table.insert(data, j)
        	end
    	end
    end
    smwdata = nil

    -- Render page
    local t = mw.html.create('table')
    t:addClass('wikitable sortable products-list align-center-1 align-right-3 align-right-4')
    local ttlrow = t:tag('tr')
            :tag('th')
            	:attr('colspan', '2')
                :wikitext('Item')
            :done()
            :tag('th')
                :wikitext('Members')
               :done()
            :tag('th')
            	:attr('data-sort-type', 'number')
                :wikitext('Skills')
            :done()
            :tag('th')
            	:attr('data-sort-type', 'number')
            	:wikitext('XP')
            :done()
            :tag('th')
                :wikitext('Materials')
            :done()

    local rows = 0

    -- Render rows
    for _, item in ipairs(data) do
        local _found = false
        for _,mat_info in ipairs(item.materials) do
            if materialsLowered[mat_info.name:lower()] == true then
                _found = true
                break
            end
        end
        if _found then
            local namestr
            if (tonumber(item.output.quantity) or 1) > 1 then
                namestr = string.format('[[%s]] × %s', item.output.name, item.output.quantity)
            else
                namestr = string.format('[[%s]]', item.output.name)
            end
            
            if item.output.subtxt then
            	namestr = string.format('%s <br /><small>(%s)</small>', namestr, item.output.subtxt)	
            end
            
            local memberstr
            members = item.members
            if members == 'Yes' then
				memberstr = "[[File:Member icon.png|center|link=Members]]"	
			elseif members == 'No' then
				memberstr = "[[File:Free-to-play icon.png|center|link=Free-to-play]]"	
			end
		
            local experience_cell = mw.html.create('td')
            local experience_ul = experience_cell:tag('ul')
            experience_ul:addClass('skills-list')
                :css({
                    ['list-style-type'] = 'none',
                    ['list-style-image'] = 'none',
                    margin = 0
                })
            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
                })
            if #item.skills == 0 then
        		local skill_li = skills_ul:tag('li')
        		local experience_li = experience_ul:tag('li')
        		experience_cell:addClass('table-na')
        		experience_li:wikitext(string.format('None'))
        		skills_cell:addClass('table-na')
        		skill_li:wikitext(string.format('None'))
        	else
        		for index, v in ipairs(item.skills) do
            		local skill_li = skills_ul:tag('li')
            		local experience_li = experience_ul:tag('li')
            		local stripped_experience = string.gsub(v.experience, ',', '')
            		skill_li:attr('data-sort-value', index == 1 and v.level or ''):wikitext(skillpic(lang:ucfirst(v.name), v.level))
            		experience_li:attr('data-sort-value', index == 1 and v.experience or ''):wikitext(tonumber(stripped_experience) ~= nil and skillpic(lang:ucfirst(v.name), v.experience) or v.experience)
        		end
        	end
            local mats_ul = mw.html.create('ul')
            mats_ul:addClass('products-materials')
                :css({
                    ['list-style-type'] = 'none',
                    ['list-style-image'] = 'none',
                    margin = 0
                })
            local materialsortvalue = nil
            for _, mat_info in ipairs(item.materials) do
                local mat_li = mats_ul:tag('li')
                local qty = string.gsub(mat_info.quantity, '%-', '–')
                local matnm = mat_info.name
            	for _,mat in ipairs(materialsLowered) do
            		if mat_info.name:lower() == mat then
            			mat_li:addClass('production-selected')
            		end
            	end
                if materialsLowered[mat_info.name:lower()] == true then
                    mat_li:addClass('production-selected')
                end
                
                if materialsortvalue == nil then
                	materialsortvalue = qty
                end
                
                mat_li:wikitext(string.format('%s × [[%s]]', commas._add(qty), matnm))
            end

            local prow = t:tag('tr')
            	:tag('td')
            		:wikitext(item.output.image)
                :tag('td')
                	:attr('data-sort-value', item.product)
                    :wikitext(namestr)
                :done()
                :tag('td')
                	:wikitext(memberstr)
                :node(skills_cell)
                :node(experience_cell)
                :tag('td')
                	:attr('data-sort-value', materialsortvalue)
                    :node(mats_ul)
                :done()
            rows = rows + 1
        end
    end

    if rows == 0 then
        return 'Failed to find products with those materials - ensure they are spelled correctly. (ERR: no mats found in results)[[Category:Empty drop lists]]'
    end

    return t
end

--[[ DEBUG COPYPASTA
= p._main({'Mithril bar'})
--]]

return p