Module:Uses skill list: Difference between revisions

From RuneRealm Wiki
Jump to navigation Jump to search
Content added Content deleted
(Created page with "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 -- Sorting function for two item objects, first by name, then by sub-text function sortItemsByNameSubtext(item1, item2) if (item1.output.name < item2.output.name) then return true elseif (item1.output.name > item2.out...")
 
No edit summary
 
(10 intermediate revisions by the same user not shown)
Line 24: Line 24:


function p._main(args)
function p._main(args)
local materials = {}
local skills = {}
local materials_lowered = {}
local skills_lowered = {}
local category = args.category and trim(args.category) or nil
-- Process skill arguments
if (args == nil) then
if args == nil then
table.insert(materials, mw.title.getCurrentTitle().text)
table.insert(skills, mw.title.getCurrentTitle().text)
else
else
local i = 1
local i = 1
Line 35: Line 37:
local arg = trim(args[i])
local arg = trim(args[i])
table.insert(materials, arg)
table.insert(skills, arg)
materials_lowered[arg:lower()] = true
skills_lowered[arg:lower()] = true
i = i + 1
i = i + 1
Line 42: Line 44:
end
end


-- Fetch data
-- Build SMW query
local query = {
local query = {
'[[Uses skill::'..table.concat(materials, '||')..']]',
'[[Uses skill::' .. table.concat(skills, '||') .. ']]',
'[[Production JSON::+]]',
'[[Production JSON::+]]',
'?=#-',
'?=#-',
Line 51: Line 53:
}
}
-- Add category filter if provided
if category then
table.insert(query, '[[RecipeCategory::' .. category .. ']]')
end

-- Fetch data
local t1 = os.clock()
local t1 = os.clock()
local smw_data = mw.smw.ask(query)
local smw_data = mw.smw.ask(query)
Line 84: Line 92:
-- Render page
-- Render page
local t = mw.html.create('table')
local t = mw.html.create('table')
t:addClass('wikitable sortable products-list align-center-1 align-right-3 align-right-4')
t:addClass('wikitable sortable products-list align-center-1 align-right-3 align-right-4 autosort=3,a')


local ttlrow = t:tag('tr')
local ttlrow = t:tag('tr')
Line 110: Line 118:
-- Render rows
-- Render rows
for _, item in ipairs(data) do
for _, item in ipairs(data) do
local _found = false
local skill_match = false
for _, skill_info in ipairs(item.skills) do

for _, mat_info in ipairs(item.materials) do
if skills_lowered[skill_info.name:lower()] then
skill_match = true
if materials_lowered[mat_info.name:lower()] then
_found = true
break
break
end
end
end
end


if _found then
if skill_match then
local name_str
local name_str


Line 184: Line 191:
local qty = mat_info.quantity:gsub('%-', '–')
local qty = mat_info.quantity:gsub('%-', '–')
local mat_name = mat_info.name
local mat_name = mat_info.name

for _, mat in ipairs(materials_lowered) do
if mat_name:lower() == mat then
mat_li:addClass('production-selected')
end
end

if materials_lowered[mat_name:lower()] then
mat_li:addClass('production-selected')
end
if mat_sort_val == nil then
if mat_sort_val == nil then
Line 223: Line 220:


if rows == 0 then
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]]'
return 'Failed to find products with those skills - ensure they are spelled correctly. (ERR: no skills found in results)[[Category:Empty drop lists]]'
end
end



Latest revision as of 22:04, 13 November 2024

Module documentation
This documentation is transcluded from Module:Uses skill list/doc. [edit] [history] [purge]
Module:Uses skill list's function main is invoked by Template:Uses skill list.
Module:Uses skill list requires Module:Addcommas.
Module:Uses skill list requires Module:Exchange.
Module:Uses skill list requires Module:SCP.
Module:Uses skill list requires Module:Yesno.

Generates {{Uses skill list}}.


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

-- Sorting function for two item objects, first by name, then by sub-text
function sortItemsByNameSubtext(item1, item2)
	if (item1.output.name < item2.output.name) then
		return true
	elseif (item1.output.name > item2.output.name) then
		return false
	else
		return (item1.output.subtxt or '') < (item2.output.subtxt or '')
	end
end

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

function p._main(args)
	local skills = {}
	local skills_lowered = {}
    local category = args.category and trim(args.category) or nil
	
    -- Process skill arguments
    if args == nil then
		table.insert(skills, mw.title.getCurrentTitle().text)
	else
		local i = 1
		
		while args[i] do
			local arg = trim(args[i])
			
			table.insert(skills, arg)
	    	skills_lowered[arg:lower()] = true
	    	
			i = i + 1
		end
	end

    -- Build SMW query
    local query = {
        '[[Uses skill::' .. table.concat(skills, '||') .. ']]',
        '[[Production JSON::+]]',
        '?=#-',
        '?Production JSON = json',
        limit = args.limit or 500,
    }
    
    -- Add category filter if provided
    if category then
        table.insert(query, '[[RecipeCategory::' .. category .. ']]')
    end

    -- Fetch data
    local t1 = os.clock()
    local smw_data = mw.smw.ask(query)
    local t2 = os.clock()

    if not smw_data then
        return 'Failed to find products with those skills - 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.', #smw_data, (t2 - t1) * 1000))

    -- Post-process
    data = {}

    for _, e in ipairs(smw_data) do
    	if type(e.json) == 'string' then
            local json = mw.text.jsonDecode(e.json)
            table.insert(data, json)
        elseif type(e.json) == 'table' then
        	for _, f in ipairs(e.json) do
        		local json = mw.text.jsonDecode(f)
                table.insert(data, json)
        	end
    	end
    end
    
    smw_data = nil
    
    -- Items with different variants (e.g. Divine battlemage potion has (1), (2), (3), (4) variants)
    -- or methods (e.g. "4-dose oil" vs "3-dose oil" for pyre logs) may not come in sorted, so now do a final alphabetical sort on name, sub-text
    table.sort(data, sortItemsByNameSubtext)

    -- Render page
    local t = mw.html.create('table')
    t:addClass('wikitable sortable products-list align-center-1 align-right-3 align-right-4 autosort=3,a')

    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 skill_match = false
        for _, skill_info in ipairs(item.skills) do
            if skills_lowered[skill_info.name:lower()] then
                skill_match = true
                break
            end
        end

        if skill_match then
            local name_str

            if (tonumber(item.output.quantity) or 0) > 1 then
                name_str = string.format('[[%s]] × %s', item.output.name, item.output.quantity)
            else
                name_str = string.format('[[%s]]', item.output.name)
            end
            
            if item.output.subtxt then
            	name_str = string.format('%s <br /><small>(%s)</small>', name_str, item.output.subtxt)	
            end
            
            local member_str

            if item.members == 'Yes' then
				member_str = "[[File:Member icon.png|center|link=Members|alt=Members]]"	
			elseif item.members == 'No' then
				member_str = "[[File:Free-to-play icon.png|center|link=Free-to-play|alt=Free-to-play]]"	
			end
		
            local experience_cell = mw.html.create('td')
            experience_cell:addClass('plainlist')

            local experience_ul = experience_cell:tag('ul')
            experience_ul:addClass('skills-list')

            local skills_cell = mw.html.create('td')
            skills_cell:addClass('plainlist')

            local skills_ul = skills_cell:tag('ul')
            skills_ul:addClass('skills-list')

            if #item.skills == 0 then
        		local skill_li = skills_ul:tag('li')
        		local experience_li = experience_ul:tag('li')

        		experience_cell:addClass('table-na'):css('text-align', 'center')
        		experience_li:wikitext(string.format('None'))
        		skills_cell:addClass('table-na'):css('text-align', 'center')
        		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 = v.experience:gsub(',', '')

            		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')

            local mat_sort_val = nil

            for _, mat_info in ipairs(item.materials) do
                local mat_li = mats_ul:tag('li')
                local qty = mat_info.quantity:gsub('%-', '–')
                local mat_name = mat_info.name
                
                if mat_sort_val == nil then
                	mat_sort_val = qty
                end
                
                mat_li:wikitext(string.format('%s × [[%s]]', commas._add(qty), mat_name))
            end

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

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

    return t
end

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

return p