Module:Sandbox/Kawesa01/nocMedals

--[[

build a table of Olymipc medals and country ranks for an individual country. This example supports Mexico and Serbia. Needs better data organization but serves as proof of concept

]]

require ('strict') -- local data_t = mw.loadData ('Module:Sandbox/Kawesa01/nocMedals/data'); local format_strings_t = { athletes = '%s',							-- country name; year; 'Winter' or 'Summer'; number of athletes caption = '%s at the %s Olympic Games',									-- country name; 'Winter' or 'Summer' game = '',											-- either of 'SOG' or 'WOG'; year	-- TODO: incorporate the data from that template in this module rank = '%s',								-- year; 'Winter' or 'Summer'; rank for that year } local messages_t = { future = "future event", DNP = "did not participate", }

--[[--< G A M E S _ T E M P L A T E _ M A K E >

when is a number, returns a template for that year; when not a number, returns as is

TODO: avoid the template call by implementing within this module (the template would invoke this module when used outside of the creation of these medal tables)

]]

local function games_template_make (games, year) if tonumber (year) then														-- if is a number or can be converted to a number return string.format (format_strings_t.game, games, year);		-- return a template else return year;															-- return as plain text else end end

--[[--< H T M L _ T A B L E _ B U I L D >--

create summer and winter Olympic games medals table

country_data_t =
 * 1)  NEW ##############

]]

local function html_table_build (frame) local args = require ('Module:Arguments').getArgs (frame); local country_data_t = mw.text.jsonEncode(args[3])

if not args[1] or '' == args[1] then return ' missing required ISO 3166 country tag ' end --args[1] = 'MEX' local tag = args[1]:upper;												-- args[1] is Olympics country tag if not country_data_t[tag] then return ' no country data for ISO 3166 country tag: ' .. tag .. ' ';	end

local games = args[2]:upper;												-- SOG or WOG if 'SOG' ~= games and 'WOG' ~= games then return ' unknown games: ' .. games .. ' ';	end --games='WOG'

local html_tbl = mw.html.create ('table');									-- create the wikitable html_tbl :attr ('class', 'wikitable'):attr ('style', 'text-align:center')		-- add table attributes :tag ('caption'):wikitext (string.format (format_strings_t.caption, country_data_t[tag].country, ('SOG' == games) and 'Summer' or 'Winter')):done	-- caption for accessibility :tag ('tr') :tag ('th'):wikitext ('Games')											-- add table headers :tag ('th'):wikitext ('Athletes') :tag ('th'):attr ('scope', 'col'):wikitext ('Gold') :tag ('th'):attr ('scope', 'col'):wikitext ('Silver') :tag ('th'):attr ('scope', 'col'):wikitext ('Bronze') :tag ('th'):attr ('scope', 'col'):attr ('style', 'width:3em; font-weight:bold;'):wikitext ('Total') :tag ('th'):attr ('scope', 'col'):attr ('style', 'width:3em; font-weight:bold;'):wikitext ('Rank') local gold_total = 0;														-- we will accumulate totals here local silver_total = 0; local bronze_total = 0; local total_total = 0;														-- total of totals

local row_count = 0;														-- used as flag when rowspan used for future and no_participate messaging for _, row_t in ipairs (country_data_t[tag][games]) do				-- for each row sequence in the data table local games_template = games_template_make (games, row_t.year); if row_t.athletes then													-- only when there are athletes local athletes = string.format (format_strings_t.athletes, country_data_t[tag].country, row_t.year, ('SOG' == games) and 'Summer' or 'Winter', row_t.athletes); local rank = string.format (format_strings_t.rank, row_t.year, ('SOG' == games) and 'Summer' or 'Winter', row_t.rank); local tr = html_tbl:tag('tr'):attr('style', ('yes' == row_t.host) and 'border: 3px solid purple' or nil) -- create an html row and populate with tr:tag('td'):attr('style', 'text-align:left'):wikitext(games_template):done -- game name tr:tag('td'):wikitext(athletes):done -- number of athletes tr:tag('td'):wikitext(row_t.gold):done -- number of medals tr:tag('td'):wikitext(row_t.silver):done tr:tag('td'):wikitext(row_t.bronze):done tr:tag('td'):wikitext(row_t.gold + row_t.silver + row_t.bronze):done -- calculate the total number of medals for the row -- country rank and set background color based on rank for 1 to 3 local td = tr:tag('td') if row_t.rank == 1 then td:attr('style', 'background-color:#F7F6A8;'):wikitext(rank):done elseif row_t.rank == 2 then td:attr('style', 'background-color:#DCE5E5;'):wikitext(rank):done elseif row_t.rank == 3 then td:attr('style', 'background-color:#FFDAB9;'):wikitext(rank):done else td:wikitext(rank):done end

gold_total = gold_total + row_t.gold;								-- update totals silver_total = silver_total + row_t.silver; bronze_total = bronze_total + row_t.bronze; total_total = total_total + row_t.gold + row_t.silver + row_t.bronze	-- update total of totals elseif row_t.message then if row_t.rowspan then row_count = row_t.rowspan - 1; html_tbl:tag ('tr') :tag ('td'):attr ('style', 'text-align:left'):wikitext (games_template):done	-- game name :tag ('td'):attr ('colspan', 6):attr ('rowspan', row_t.rowspan):wikitext (messages_t[row_t.message] or row_t.message):done else																-- here when single-row message (no rowspan) html_tbl:tag ('tr') :tag ('td'):attr ('style', 'text-align:left'):wikitext (games_template):done	-- game name :tag ('td'):attr ('colspan', 6):attr ('rowspan', row_t.rowspan):wikitext (messages_t[row_t.message] or row_t.message):done end -- here when no  and no  elseif 0 < row_count then												-- when not 0, must be in a rowspan row_count = row_count - 1;											-- count down the counter html_tbl:tag ('tr')													-- add row that is				:tag ('td'):attr ('style', 'text-align:left'):wikitext (games_template):done	-- games name only end end

html_tbl :tag ('tr')																-- and create the bottom header :tag ('th'):attr ('colspan', '2'):wikitext ('Totals')					-- with all of the totals :tag ('th'):attr ('class', 'combined_medals'):wikitext (gold_total) :tag ('th'):wikitext (silver_total) :tag ('th'):wikitext (bronze_total) :tag ('th'):wikitext (total_total) :tag ('th'):wikitext ( .. country_data_t[tag].all_time_rank .. ) mw.log (tostring (html_tbl)) return frame:preprocess (tostring (html_tbl));								-- make a big string, preprocess the game templates, and done end

--[[--< T O T A L _ M E D A L S _ G E T >--

calculate total gold/silver/bronze medal totals from country's data in ~/data for use in

]]

local function total_medals_get (frame) local args = require ('Module:Arguments').getArgs (frame);

local country_data_t = mw.text.jsonEncode(args[3]) local country = args[1]:upper; local award = args[2]:lower;

if not country_data_t[country] then return ' unknown country: ' .. args[1] .. ' ';	end if not ({['gold']=true, ['silver']=true, ['bronze']=true,})[award] then return ' unknown award: ' .. args[2] .. ' ';	end

local total = 0;

for _, games in ipairs ({'SOG', 'WOG'}) do		for _, v_t in ipairs (country_data_t[country][games]) do			if v_t[award] then total = total + v_t[award] end end end return total; end

local function get_combined_SOG_WOG(frame) local args = require('Module:Arguments').getArgs(frame) local award = args[1]:lower; local fullpage = mw.title.getCurrentTitle.prefixedText local text = mw.title.new(fullpage):getContent;-- Get the wikitext as a parameter

-- Use the mw.text.unstrip function to process the wikitext text = mw.text.unstrip(text)

-- Use mw.text.split to split the wikitext into lines local lines = mw.text.split(text, '\n')

local inSOGTable = false -- Flag to track if we are inside the SOG table local goldValues = {}

for _, line in ipairs(lines) do       -- Check if we've entered the SOG table if line:match('{%s*SOG%s*=%s*{') then inSOGTable = true end

-- If we're inside the SOG table, look for lines containing "gold =" if inSOGTable then local goldValue = line:match('gold%s*=%s*(%d+)') if goldValue then table.insert(goldValues, tonumber(goldValue)) end

-- Check if we've reached the end of the SOG table if line:match('}%s*}') then break end end end

-- Calculate the sum of gold values local goldSum = 0 for _, value in ipairs(goldValues) do       goldSum = goldSum + value end

return goldSum end

----< E X P O R T E D  F U N C T I O N S >--

return {	html_table_build = html_table_build, total_medals_get = total_medals_get, get_combined_SOG_WOG = get_combined_SOG_WOG, }