Module:Variants

Revision as of 01:26, 18 December 2024 by Im Wired In (talk | contribs) (Only link to a page once)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Creates a section containing all items with the same Variant property, ordered by the sum of the profession level requirements in ascending order.

If a variant does not have a profession level, 0 is used as a fallback, meaning items with unknown level requirements will always appear first in the list.

Usage:

{{Variants|Eel}}

Result:

Lesser • Gray • Rocky • Rord • Moray • Conger • Leopard • Greater

require('Module:Mw.html extension')
local p = {}

function sort_entries(entry1, entry2)
	-- Sort the variants based on the sum of the profession levels
	local entry1_value = (entry1['Profession Level A'] or 0) + (entry1['Profession Level B'] or 0)
	local entry2_value = (entry2['Profession Level A'] or 0) + (entry2['Profession Level B'] or 0)
	return entry1_value < entry2_value
end

function get_table_info(args, get_images)
	local variant_name = args.variant or mw.title.getCurrentTitle().fullText
	local query = {
		'[[Variant of::'..variant_name..']]',
		'?Profession A #', -- Adding a # to this query makes it return plaintext instead of a link
		'?Profession B #',
		'?Profession Level A',
		'?Profession Level B',
		'?Profession Level A High',
		'?Profession Level B High',
		'?Variant name',
		'?Version anchor',
		'?-Has subobject #',
		'?#-',
		get_images and '?Image#64px;x64px = Image' or nil,
		limit = args.limit or 500,
	}
	local smw_data = mw.smw.ask(query)
	if not smw_data then
		return nil
	end
	table.sort(smw_data, sort_entries)
	return smw_data
end

function p.variants_header(args)
	local smw_data = get_table_info(args)
	local contents
	if smw_data then
		local formatted, pageList = {}, {}
		for _, entry in ipairs(smw_data) do
			local variant_name = entry['Variant name']
			if variant_name then
				local page = entry['-Has subobject'] or entry[1]
				if page:sub(1, 1 + #variant_name + #' (grade ') == ':' .. variant_name .. ' (grade ' and page:sub(-1) == ')' then
					local grade_number = page:sub(2 + #variant_name + #' (grade ', -2)
					mw.log('"' .. grade_number .. '"')
					variant_name = 'Grade ' .. grade_number
				end

				if not pageList[page] then
					table.insert(formatted, ('[[%s|%s]]'):format(page, variant_name))
					pageList[page] = true
				end
			else
				table.insert(formatted, ('[[%s]]'):format(entry[1]))
			end
		end
		contents = table.concat(formatted, ' •&nbsp;')
	else
		contents = '[[Category:Empty variant list]]'
	end
	return mw.html.create('div')
		:addClass('variants-header')
		:wikitext(contents)
	:done()
end

function p.main(frame)
	local args = frame:getParent().args
	args.variant = args[1] or args.variant
	return p.variants_header(args)
end

function p.variants_table(args)
	local smw_data = get_table_info(args, true)
	if not smw_data then
		return ':No variants found.'
	end
	
	local profession_b_flag = false
	for _, entry in ipairs(smw_data) do
		if entry['Profession B'] or entry['Profession Level B']	then
			profession_b_flag = true
		end
		break
	end
	
	local table = mw.html.create('table')
		:addClass('sortable wikitable')
		:tag('tr')
			:tag('th')
				:attr{ colspan = '2' }
				:wikitext('Item')
			:done()
			:tag('th')
				:wikitext('Level')
				:attrIf(profession_b_flag, 'colspan', 2)
			:done()
		:done()
	
	local function formatProfessionLevel(profession, level, high)
		if not (profession or level) then
			return nil
		end
		profession = profession or 'Unknown profession'
		local level_text = tostring(level or '?')
		if high then
			level_text = ('%s➨%d'):format(level_text, high)
		end
		return ('%s [[File:%s small icon.png|21x21px|link=%s]]'):format(level_text, profession, profession)
	end

	for _, entry in ipairs(smw_data) do
		local profession_level_a = entry['Profession Level A'] or '?'
		local profession_level_b = entry['Profession Level B'] or '?'
		local profession_a = entry['Profession A'] or ''
		local profession_b = entry['Profession B'] or ''
		table
			:tag('tr')
				:tag('td')
					:css{ ['border-right'] = 'none' }
					:wikitext(entry.Image)
				:done()
				:tag('td')
					:css{ ['border-left'] = 'none' }
					:wikitext(('[[%s]]'):format(entry[1]))
				:done()
				:tag('td')
					:css{ ['text-align'] = 'right' }
					:wikitext(formatProfessionLevel(entry['Profession A'], entry['Profession Level A'], entry['Profession Level A High']))
				:IF(profession_b_flag)
					:tag('td')
					:IF(entry['Profession B'])
						:css{ ['text-align'] = 'right' }
						:wikitext(formatProfessionLevel(entry['Profession B'], entry['Profession Level B'], entry['Profession Level B High']))
					:done()
				:END()
			:done()
	end

	return table
end

function p.main_table(frame)
	local args = frame:getParent().args
	args.variant = args[1] or args.variant
	return p.variants_table(args)
end

return p