Vorlagenprogrammierung Diskussionen Lua Unterseiten
Modul Deutsch English

Modul: Dokumentation

Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus


--[=[ 2021-08-21
Unterstützung für {{Vorlagen:Grand-Tour-Platzierungen}}, {{Vorlage:Monumente-des-Radsports-Platzierungen}} etc.
f()
]=]

-- configurations, loaded from [[/config]]
local gConfig = {}

-- legends, activated in printCell if there is a trigger value
local gLegend = {
	DNF = false,
	DSQ = false,
	DNS = false,
	IP  = false
}

local function getCellColor(event, year, rank)
	-- determines the cell color based on the reached ranking
	-- parameters:
	--   event: (string) event short code (see event config)
	--   year:  (string) staging year
	--   rank:  (string) value given as ranking parameter
	-- returns:
	--   (string) hex color code or false
	
	local color		-- hex color code or false if no coloring
	local maxyear	-- maximum jersey color year 
	
	-- initialisation
	color   = false
	maxyear = 0
	
	-- rank is no number (DNF or skipped etc.), no coloring for these cases
	if rank == nil then
		return false
	end
	
	-- mark top ten results with extra color
	if rank <= 10 then
		color = gConfig.ranks.topten
	end
	
	-- Grand Tours have their own victory color based on the leader's jersey in this year
	if event == "Tour" or event == "Giro" or event == "Vuelta" then
		if rank == 1 then
			for y, c in pairs(gConfig.ranks[1][event]) do
				if tonumber(year) >= tonumber(y) and tonumber(y) > maxyear then
					color = c
					maxyear = tonumber(y)
				end
			end
		end
	else
		-- use standard gold, silver, bronze colors for other events
		if gConfig.ranks[rank] ~= nil then
			color = gConfig.ranks[rank].general
		end
	end
	
	return color or false
end

local function getLegendText(mode, legend)
	-- returns the text to display in the legend
	-- parameters:
	--   mode:   (string) template mode
	--   legend: (string) legend type
	-- returns:
	--   (string) legend text
	
	local text	-- legend text
	local elem	-- text definition element
	
	-- initialisation
	text = ""
	elem = gConfig.legends[legend]
	
	if elem[mode] ~= nil then
		-- use defined text for given mode
		text = elem[mode]
	else
		-- use general text for all modes
		text = elem.general
	end
	
	return text
end

local function printCell(event, year, text)
	-- prints a single result cell for a staging of an event with link, color and ranking
	-- parameters: 
	--   event: (string) event short code (see event config)
	--   year:  (string) staging year
	--   text:  (string) value given as ranking parameter, may be number, text oder sign
	-- returns:
	--   (bool) cell filled or not
	--   (obj) cell html object
	
	local cell		-- cell html object 
	local color 	-- cell color retrieved from getCellColor
	local link  	-- link to event article (see event config)
	local content	-- cell content
	local legend	-- converted text for legend check
	local filled	-- cell filled or not
	
	-- create cell object
	cell = mw.html.create("td")
	
	if text == "" or text == nil then
		-- unknown status, empty cell
		content = ""
		filled  = false
	elseif text == "-" or text == "–" or text == "—" then
		-- do not link skipped stagings
		content = "–"
		filled = true
	else
		-- use year link from event config if wanted
		link = gConfig.events[event].year
		if link == false then
			content = text
		else
			content = "[[" .. link .. " " .. year .. "|" .. text .."]]"
		end
		filled = true
	end
	
	-- add content to cell
	cell:wikitext(content)
	
	-- get color and add it to the cell if necessary
	color = getCellColor(event, year, tonumber(text))
	if color ~= false then
		cell:css("background-color", color)
	end
	
	-- check if a legend for the abbreviations is needed
	if text ~= nil then
		legend = mw.ustring.upper(text)
		if legend == "DNF" then gLegend.DNF = true end
		if legend == "DSQ" then gLegend.DSQ = true end
		if legend == "DNS" then gLegend.DNS = true end
		if legend == "IP"  then gLegend.IP  = true end
	end
	
	return filled, cell
end

local function printRow(args, event, yearcount, maxyear)
	-- prints a row for one event with every year given in the template call
	-- parameters:
	--	 args:      (table)  template parameters
	--	 event: 	(string) event short code (see event config)
	--   yearcount: (number) number of years with results (starting with 1)
	--   maxyear:   (number) highest result year
	-- returns:
	--   (obj) row html object or nil if row is empty
	
	local row		-- row html object
	local index		-- two-char results index
	local value		-- value given in the staging parameter
	local year		-- year retrieved from yearindex
	local oldyear	-- comparison year in iteration
	local pict		-- pictogram table
	local first		-- content in the first cell (head)
	local name		-- event name (desktop or mobile)
	local inner		-- inner text (desktop or mobile)
	local mobile	-- mobile alternative name set
	local filledc	-- cell filled with something
	local filledr	-- number of filled cells in row
	local cell		-- cell html object
	
	-- initialisation
	first   = ""
	name	= {}
	inner	= {}
	year	= ""
	oldyear = 0
	filledr = 0
	mobile	= false
	
	-- get pictogram, if defined
	if gConfig.events[event].pict ~= nil then
		pict = false
		for y, p in pairs(gConfig.events[event].pict) do
			if maxyear >= tonumber(y) and tonumber(y) > oldyear then
				pict = p
				oldyear = tonumber(y)
			end
		end
		
		-- insert pictogram wikisyntax to first cell content
		if pict ~= false then
			first = first .. "[[Datei:" .. pict.file .. "|20px|link=" .. pict.link .. "|" .. pict.text .. "]]&nbsp;"
		end
	end
	
	-- determine if there is also an alternative text for mobile viewports
	name["desktop"] = mw.html.create("span")
	if gConfig.events[event].mobi ~= nil then
		mobile = true
		name["desktop"]:addClass("m-radsportplatzierungen-desktop")
		
		name["mobile"] = mw.html.create("span")
								:addClass("m-radsportplatzierungen-mobile")
	end
	
	-- set event text
	if gConfig.events[event].link ~= false then
		if gConfig.events[event].link == gConfig.events[event].text then
			inner["desktop"] = "[[" .. gConfig.events[event].text .. "]]"
		else
			inner["desktop"] = "[[" .. gConfig.events[event].link .. "|" .. gConfig.events[event].text .. "]]"
		end
		if mobile == true then
			inner["mobile"] = "[[" .. gConfig.events[event].link .. "|" .. gConfig.events[event].mobi .. "]]"
		end
	else
		inner["desktop"] = gConfig.events[event].text
		if mobile == true then
			inner["mobile"] = gConfig.events[event].mobi
		end
	end
	
	-- assign event text to first cell content
	name["desktop"]:wikitext(inner["desktop"])
	first = first .. tostring(name["desktop"])
	if mobile == true then
		name["mobile"]:wikitext(inner["mobile"])
		first = first .. tostring(name["mobile"])
	end
	
	-- create html row object and insert the head content
	row = mw.html.create("tr")
			:node(mw.html.create("th")
					:wikitext(first))
	
	-- loop through all significant years
	for yearindex = 1, yearcount, 1 do
		
		-- get results index from year index
		if yearindex < 10 then
			index = "0" .. tostring(yearindex)
		else
			index = tostring(yearindex)
		end
		
		-- get content of staging result parameter
		value = args[event .. index]
		if value == nil then
			-- backward compatibility for old parameter format
			value = args[event .. index .. "P"]
		end
		
		-- get year by yearindex
		year = args["Jahr" .. index]
		
		-- print a single cell and add it to the row
		filledc, cell = printCell(event, year, value)
		if filledc == true then
			-- increment count of filled cells in row
			filledr = filledr + 1
		end
		
		-- add html object to the row
		row:node(cell)
	end
	
	if filledr == 0 then
		return nil
	else
		row:newline()
		return row
	end
end

local function printTableHeadCell(mode, year)
	-- prints one cell of the table header containing the reference year of the results
	-- parameters:
	--   mode: (string) template mode
	--   year: (string) reference year
	-- returns:
	--   (obj) cell html object
	
	local cell	-- head cell html object
	
	cell = mw.html.create("th")
	
	-- Vorlage:Straßenradsport-Weltmeisterschafts-Platzierungen needs years linked to the staging, other events just contain the plain year
	if mode == "WM-Straße" then
		cell:wikitext("[[Straßenradsport-Weltmeisterschaften " .. year .. "|" .. year .. "]]")
	else
		cell:wikitext(year)
	end	
	
	return cell
end

local function getTextsFromMode(mode)
	-- gets description texts based on the template mode
	-- parameters:
	--   mode: (string) template mode
	-- returns:
	--   (string) text in upper left cell
	--   (string) table caption
	
	if mode == "Grand-Tour" then
		return gConfig.texts.gtrUpleft, gConfig.texts.gtrCaption
	elseif mode == "Monument" then
		return gConfig.texts.monUpleft, gConfig.texts.monCaption
	elseif mode == "WM-Straße" then
		return gConfig.texts.wmsUpleft, gConfig.texts.wmsCaption
	end	
	
end

local function printTable(args, mode)
	-- prints the full results table with wrapper
	-- parameters:
	--   args: (table) template parameters
	--   mode: (string) template mode
	-- returns:
	--   (string) wrapper and table html
	
	local result	-- full html object
	local grid		-- table html object
	local head		-- head html object
	local upleft	-- text in the upper left cell of the table (refers to mode)
	local caption   -- table caption
	local index		-- two-char results index
	local yearcount	-- number of years with results (starting with 1)
	local year      -- current year in loop
	local maxyear   -- highest year given
	
	-- initialisation
	upleft    = ""
	index	  = ""
	yearcount = 0
	maxyear   = 0
	
	result = mw.html.create("div")
					:addClass("m-radsportplatzierungen-wrapper")
	
	-- create table and fill it
	grid = mw.html.create("table")
					:addClass("wikitable")
	
	-- get caption and upleft value
	upleft, caption = getTextsFromMode(mode)
	
	-- add table caption if needed
	if args["Titel"] ~= nil then
		grid:node(mw.html.create("caption")
						:wikitext(caption))
	end
	
	-- create table head row and fill it
	head = mw.html.create("tr")
				:node(mw.html.create("th")
					:wikitext(upleft))
	
	-- loop through all available years (1 to 99)
	for i = 1, 99, 1 do
		
		-- get results index
		if i < 10 then
			index = "0" .. tostring(i)
		else
			index = tostring(i)
		end
		
		if args["Jahr" .. index] ~= nil then
			year = args["Jahr" .. index]
			
			-- maximum yearindex so far
			yearcount = i
			
			-- add head cell for this year
			head:node(printTableHeadCell(mode, year))
			
			-- check if this is the new highest year so far
			if tonumber(year) > maxyear then
				maxyear = tonumber(year)
			end
		else
			-- yearindex without allocation, aborting
			break
		end
	end
	
	-- append head to table
	grid:node(head)
		  :newline()
	
	-- get rows dependent on template mode
	if mode == "Grand-Tour" then
		-- order of grand tours changed in 1995
		if maxyear > 1994 then
			grid:node(printRow(args, "Giro", yearcount, maxyear))
			grid:node(printRow(args, "Tour", yearcount, maxyear))
			grid:node(printRow(args, "Vuelta", yearcount, maxyear))
		else
			grid:node(printRow(args, "Vuelta", yearcount, maxyear))
			grid:node(printRow(args, "Giro", yearcount, maxyear))
			grid:node(printRow(args, "Tour", yearcount, maxyear))
		end
	elseif mode == "Monument" then
		grid:node(printRow(args, "Mailand", yearcount, maxyear))
		grid:node(printRow(args, "Flandern", yearcount, maxyear))
		grid:node(printRow(args, "Paris", yearcount, maxyear))
		grid:node(printRow(args, "Lüttich", yearcount, maxyear))
		grid:node(printRow(args, "Lombardei", yearcount, maxyear))
	elseif mode == "WM-Straße" then
		grid:node(printRow(args, "1er-Straße", yearcount, maxyear))
		grid:node(printRow(args, "EZF", yearcount, maxyear))
		grid:node(printRow(args, "MZF", yearcount, maxyear))
	end
	
	-- append table to wrapper
	result:node(grid)
	
	return tostring(result)
end

local function loadConfig(cfg)
	-- load config from submodule
	-- parameters:
	--   cfg: (string) path to config submodule
	-- returns:
	--   (bool) true or false by success/fault
	
	local success, c = pcall(mw.loadData, cfg)
	if type(c) == "table" then
		gConfig = c
	end
	
	return success
end

local function getParams(frame)
	-- get validated params from environment frame
	-- parameters:
	--   frame: (table) wiki environment frame
	-- returns:
	--   (table) template parameters
	
	local raw	-- raw parameters
	local val	-- validated parameters
	
	-- initialisation
	raw = {}
	val = {}
	
	-- only pass non-empty params
	raw = frame:getParent().args
	for k, v in pairs(raw) do
		if v ~= "" then
			val[k] = v
		end
	end
	
	-- pass mode param from inside-template frame
	val.MODE = frame.args.MODE
	
	return val
end

local function main(args)
	-- main function
	-- parameters:
	--   args: (table) template parameters
	-- returns:
	--   (string) module output
	
	local text		-- returned text
	local mode		-- template mode
	local legend	-- legend text
	local div		-- legend div
	
	-- initialisation
	mode   = args.MODE
	text   = ""
	legend = ""
	
	-- print the table
	text = text .. printTable(args, mode)
	
	-- add maintenance category for Grand Tours
	if mode == "Grand-Tour" and args["Karriereende"] == nil then
		text = text .. gConfig.texts.gtrMaintenanceCat
	end
	
	-- add legend
	if args["Legende"] == nil then
		if gLegend.DNF == true then legend = legend .. getLegendText(mode, "DNF") end
		if gLegend.DSQ == true then legend = legend .. getLegendText(mode, "DSQ") end
		if gLegend.DNS == true then legend = legend .. getLegendText(mode, "DNS") end
		if gLegend.IP  == true then legend = legend .. getLegendText(mode, "IP")  end
	else
		if mw.ustring.find(args["Legende"], "DNF", 0, true) ~= nil then legend = legend .. getLegendText(mode, "DNF") end
		if mw.ustring.find(args["Legende"], "DSQ", 0, true) ~= nil then legend = legend .. getLegendText(mode, "DSQ") end
		if mw.ustring.find(args["Legende"], "DNS", 0, true) ~= nil then legend = legend .. getLegendText(mode, "DNS") end
		if mw.ustring.find(args["Legende"], "IP",  0, true) ~= nil then legend = legend .. getLegendText(mode, "IP")  end
	end
		
	if legend ~= "" then
		div = mw.html.create("div")
					:css("font-size", "small")
					:wikitext("Legende: " .. legend)
		text = text .. tostring(div)
	end
	
	return text
end

local p = {}

function p.f(frame)
	-- access from templates
	-- parameters:
	--   frame: (table) wiki environment frame
	-- returns:
	--   (string) template output
	
	local args	-- arguments of template call
	
	-- load configuration
	loadConfig(frame:getTitle() .. "/config")
	
	-- load template parameters
	args = getParams(frame)
	
	-- call main
	local success, r = pcall(main, args)
	
	if success then
		-- include templatestyles
		r = r .. frame:extensionTag("templatestyles", "", {src = gConfig.texts.templateStyles})
		
		return r
	end
end

return p