Jump to content

Module:CreoTable

From Creopedia

Documentation for this module may be created at Module:CreoTable/doc

require( 'strict' )

local TableLua = require( 'Module:TableLua' )
local Element = require( 'Module:Element' )
local CreoLink = require( 'Module:CreoLink' )

local p = {}

--- The full getGameData payload is far too large to decode inside Scribunto
--- (see the disabled fetch in Module:GameData/EvoCreo2), so this reads a
--- pre-reduced name -> elements index instead. Regenerate it with
--- .claude/tools/creoindex.py when the game data changes.
local INDEX = 'Module:GameData/EvoCreo2/CreoElementIndex.json'

local COLUMNS = {
	{ label = 'Creo' },
	{ label = 'Type' },
	{ label = 'Elements' }
}

--- @param elements table
--- @return string
local function renderElements( elements )
	local badges = {}

	for _, elementName in ipairs( elements ) do
		table.insert( badges, Element._main( elementName ) )
	end

	return table.concat( badges, ' ' )
end

--- Split the index into the Creo whose primary element matches and those
--- whose secondary element matches. Each list is sorted by name, since
--- pairs() over the loaded JSON has no guaranteed order.
---
--- @param elementName string
--- @return table, table
local function collect( elementName )
	local index = mw.loadJsonData( INDEX )
	local target = elementName:upper()
	local primary = {}
	local secondary = {}

	for name, elements in pairs( index ) do
		if type( elements[1] ) == 'string' and elements[1]:upper() == target then
			table.insert( primary, { name = name, elements = elements } )
		elseif type( elements[2] ) == 'string' and elements[2]:upper() == target then
			table.insert( secondary, { name = name, elements = elements } )
		end
	end

	local function byName( a, b )
		return a.name < b.name
	end

	table.sort( primary, byName )
	table.sort( secondary, byName )

	return primary, secondary
end

--- @param entries table
--- @param role string
--- @param rows table
local function addRows( entries, role, rows )
	for _, entry in ipairs( entries ) do
		table.insert( rows, {
			CreoLink._main( { name = entry.name } ),
			role,
			renderElements( entry.elements )
		} )
	end
end

--- Wikitext entry point for the module
---
--- @param frame mw.frame
--- @return string
function p.main( frame )
	local getArgs = require( 'Module:Arguments' ).getArgs
	return p._main( getArgs( frame ) )
end

--- Lua entry point for the module
---
--- @param args table
--- @return string
function p._main( args )
	args = args or {}

	local elementName = args.element or args[1]

	if type( elementName ) ~= 'string' or elementName == '' then
		error( 'Module:CreoTable requires an element name' )
	end

	local primary, secondary = collect( elementName )
	local rows = {}

	addRows( primary, 'Primary', rows )
	addRows( secondary, 'Secondary', rows )

	return TableLua.render( {
		caption = string.format( '%s Creo', elementName ),
		hideCaption = true,
		columns = COLUMNS,
		data = rows,
		class = 'sortable'
	} )
end

return p