Jump to content

Module:Infobox

From The Perfect Tower II

Draws the infoboxes of {{Building}} (the 12 town buildings) and {{Infobox region}}, in the brand kit's .tpt-infobox style. Template:Infobox/styles.css (TemplateStyles) places the box beside the article.

  • building(frame): reads Tier, ConversionRate, Color and Image from the template; ColorCode is ignored. The title is the page name. On the 12 building pages the page name also sets the building's color (tpt-fac-*), and the hexagon shows the max tier as a Roman numeral (tiers 1 to 39). Rows, each only when given: Max. tier, Conversion (rate:1) and Resource. Adds Category:Buildings in the main namespace.
  • region(frame): reads image (default Image missing.png), lanes, enemies and the difficulty modifiers easy, medium, hard, insane, nightmare and impossible, which show as percentages through {{Number}}. Empty values show {{Unknown}}. Adds Category:Regions in the main namespace.
  • build(spec): the box itself, for other modules; returns an mw.html object. spec has title, label (the small line under the title), facility (a brand kit facility id such as trading-post), mark (text in the hexagon), image (wikitext), rows ({ { label, value }, … }) and sections ({ { heading, rows }, … }). All fields except title are optional.



-- Infoboxes in the style of the TPT2 brand kit (.tpt-infobox), placed beside the article by
-- Template:Infobox/styles.css. Used by Template:Building and Template:Infobox region.
-- Source: wiki repository, onwiki/Module/Infobox.lua.
local p = {}

-- Building page names to the brand kit's facility ids (game resource colors).
local FACILITIES = {
	['Power Plant'] = 'power-plant', ['Mine'] = 'mine', ['Factory'] = 'factory',
	['Headquarters'] = 'headquarters', ['Arcade'] = 'arcade', ['Laboratory'] = 'laboratory',
	['Shipyard'] = 'shipyard', ['Trading Post'] = 'trading-post', ['Workshop'] = 'workshop',
	['Museum'] = 'museum', ['Construction Firm'] = 'construction-firm', ['Statue of Cubos'] = 'statue-of-cubos',
}

local NUMERALS = { { 10, 'X' }, { 9, 'IX' }, { 5, 'V' }, { 4, 'IV' }, { 1, 'I' } }

local function roman(n)
	n = tonumber(n)
	if not n or n < 1 or n > 39 or n % 1 ~= 0 then return nil end
	local out = ''
	for _, v in ipairs(NUMERALS) do
		while n >= v[1] do
			out = out .. v[2]
			n = n - v[1]
		end
	end
	return out
end

local function value(args, key)
	local v = args[key]
	if v then
		v = mw.text.trim(v)
		if v ~= '' then return v end
	end
	return nil
end

local function num(v)
	return '<span class="tpt-num">' .. v .. '</span>'
end

local function rows(list)
	local dl = mw.html.create('dl'):addClass('tpt-infobox__rows')
	for _, row in ipairs(list) do
		local item = dl:tag('div')
		item:tag('dt'):wikitext(row[1])
		item:tag('dd'):wikitext(row[2])
	end
	return dl
end

-- spec: title, label, facility (id), mark (hexagon text), image (wikitext),
-- rows = { { label, value }, ... }, sections = { { heading, rows }, ... }
function p.build(spec)
	local box = mw.html.create('div'):addClass('tpt-infobox'):addClass('wiki-infobox')
	if spec.facility then box:addClass('tpt-fac-' .. spec.facility) end
	local head = box:tag('div'):addClass('tpt-infobox__head')
	if spec.mark then
		head:tag('span'):addClass('tpt-hex'):tag('span'):addClass('tpt-hex__mark'):wikitext(spec.mark)
	end
	local names = head:tag('div')
	names:tag('div'):addClass('tpt-infobox__title'):wikitext(spec.title)
	if spec.label then names:tag('span'):addClass('tpt-label'):wikitext(spec.label) end
	if spec.image then box:tag('div'):addClass('tpt-infobox__media'):wikitext(spec.image) end
	if spec.rows and #spec.rows > 0 then box:node(rows(spec.rows)) end
	for _, section in ipairs(spec.sections or {}) do
		box:tag('div'):addClass('tpt-infobox__section'):addClass('tpt-label'):wikitext(section[1])
		box:node(rows(section[2]))
	end
	return box
end

local function styles(frame)
	return frame:extensionTag('templatestyles', '', { src = 'Infobox/styles.css' })
end

local function inArticle()
	return mw.title.getCurrentTitle().namespace == 0
end

-- {{Building|Tier=|ConversionRate=|Image=|Color=}}; ColorCode is no longer needed.
function p.building(frame)
	local args = frame:getParent().args
	local name = mw.title.getCurrentTitle().text
	local facility = FACILITIES[name]
	local tier = value(args, 'Tier')
	local rate = value(args, 'ConversionRate')
	local color = value(args, 'Color')
	local image = value(args, 'Image')
	local list = {}
	if tier then table.insert(list, { 'Max. tier', num(tier) }) end
	if rate then table.insert(list, { 'Conversion', num(rate .. ':1') }) end
	if color then
		table.insert(list, { 'Resource', (facility and '<span class="tpt-swatch"></span>' or '') .. color })
	end
	local box = p.build {
		title = name,
		label = 'Town building',
		facility = facility,
		mark = roman(tier),
		image = image and ('[[File:' .. image .. '|300px|alt=' .. name .. ']]') or nil,
		rows = list,
	}
	return styles(frame) .. tostring(box) .. (inArticle() and '[[Category:Buildings]]' or '')
end

-- {{Infobox region|image=|lanes=|enemies=|easy=|medium=|hard=|insane=|nightmare=|impossible=}}
function p.region(frame)
	local args = frame:getParent().args
	local name = mw.title.getCurrentTitle().text
	local unknown = frame:expandTemplate { title = 'Unknown' }
	local difficulties = {}
	for _, d in ipairs { { 'easy', 'Easy' }, { 'medium', 'Medium' }, { 'hard', 'Hard' },
		{ 'insane', 'Insane' }, { 'nightmare', 'Nightmare' }, { 'impossible', 'Impossible' } } do
		local v = value(args, d[1])
		table.insert(difficulties, {
			d[2], v and frame:expandTemplate { title = 'Number', args = { v, suffix = '%' } } or unknown,
		})
	end
	local lanes = value(args, 'lanes')
	local box = p.build {
		title = name,
		label = 'Region',
		image = '[[File:' .. (value(args, 'image') or 'Image missing.png') .. '|300px|alt=' .. name .. ']]',
		rows = {
			{ 'Lanes', lanes and num(lanes) or unknown },
			{ 'Enemies', value(args, 'enemies') or unknown },
		},
		sections = { { 'Difficulties', difficulties } },
	}
	return styles(frame) .. tostring(box) .. (inArticle() and '[[Category:Regions]]' or '')
end

return p