Module:Sandbox/Miria~01
Appearance
local p = {}
-- Load the flagicon data module used to map years to host country flags
local flagicon_data = require("Module:Medals table country/data")
function p.render(frame)
-- Get arguments passed from the parent template
local args = frame:getParent().args
local country = args["country"] or "Country"
local maxRows = 50
-- Control flags
local show_dual_ranks = args["show_dual_ranks"] == "yes"
local show_games_flag = args["show_games_flag"] == "yes"
-- Determine if the table is for Summer or Winter Olympics
local season = (args["season"] or "summer"):lower()
local is_winter = (season == "winter")
local season_name = is_winter and "Winter" or "Summer"
-------------------------------------------------------------------
-- Step 1: Collect raw input rows from arguments into a raw_rows list
-------------------------------------------------------------------
local raw_rows = {}
for i = 1, maxRows do
local games = args["row"..i.."_games"]
if games and games ~= "" then
local athletes_val = args["row"..i.."_athletes"]
local participation = args["row"..i.."_participation"]
local is_host = args["row"..i.."_host"] == "yes"
-- If explicitly marked as "no", override participation text
if athletes_val == "no" then
participation = "''did not participate''"
end
-- Helper: extract leading numeric value for calculations while preserving full text for display
local function extract_number_and_text(val)
val = tostring(val or "")
local num = val:match("^%s*(%d+)")
return tonumber(num) or 0, val
end
-- Parse medals
local gold_num, gold_text = extract_number_and_text(args["row"..i.."_gold"])
local silver_num, silver_text = extract_number_and_text(args["row"..i.."_silver"])
local bronze_num, bronze_text = extract_number_and_text(args["row"..i.."_bronze"])
local rank_raw = args["row"..i.."_rank"] or ""
local total_rank_raw = args["row"..i.."_total_rank"] or ""
-- Add row to list
table.insert(raw_rows, {
games = games,
athletes_val = athletes_val,
participation = participation,
gold = gold_num,
silver = silver_num,
bronze = bronze_num,
gold_display = gold_text,
silver_display = silver_text,
bronze_display = bronze_text,
rank_raw = rank_raw,
total_rank_raw = total_rank_raw,
is_host = is_host,
})
end
end
-------------------------------------------------------------------
-- Step 2: Process rows and merge participation rows with rowspan
-------------------------------------------------------------------
local rows = {}
local i = 1
while i <= #raw_rows do
local row = raw_rows[i]
-- Merge rows that have identical participation notes
if row.participation and row.participation ~= "" then
local rowspan = 1
local is_host_in_merged = row.is_host
for j = i + 1, #raw_rows do
if raw_rows[j].participation == row.participation then
rowspan = rowspan + 1
if raw_rows[j].is_host then
is_host_in_merged = true
end
else
break
end
end
local merged_games = {}
for k = i, i + rowspan - 1 do
table.insert(merged_games, raw_rows[k].games)
end
table.insert(rows, {
participation = row.participation,
rowspan = rowspan,
games_list = merged_games,
merged = true,
is_host = is_host_in_merged,
})
i = i + rowspan
else
-- Regular row: build structured row with medals and rankings
local year = row.games:match("(%d%d%d%d)") or ""
local athletes_num = tonumber(row.athletes_val) or 0
local athletes_cell = string.format("[[%s at the %s %s Olympics|%d]]", country, year, season_name, athletes_num)
-- Medal totals
local total = row.gold + row.silver + row.bronze
-- Helper: build medal table rank links
local function make_rank_link(rank_raw)
local rank_num = tonumber(rank_raw)
local medal_table_title = string.format("%s %s Olympics medal table", year, season_name)
if rank_num then
return string.format("[[%s|%d]]", medal_table_title, rank_num), rank_num
elseif rank_raw == "–" then
return string.format("[[%s|–]]", medal_table_title), nil
elseif rank_raw ~= "" then
return rank_raw, nil
else
return "", nil
end
end
-- Rank links
local gold_rank_link, gold_rank_num = make_rank_link(row.rank_raw)
local total_rank_link, total_rank_num = make_rank_link(row.total_rank_raw)
-- Background color for top 3 ranks
local function rank_color(rank)
if rank == 1 then return "#F7F6A8"
elseif rank == 2 then return "#dce5e5"
elseif rank == 3 then return "#ffdab9"
else return ""
end
end
local bgcolor_gold = rank_color(gold_rank_num)
local bgcolor_total = rank_color(total_rank_num)
-- Add full row to output list
table.insert(rows, {
games = row.games,
athletes = athletes_cell,
gold = row.gold,
silver = row.silver,
bronze = row.bronze,
gold_display = row.gold_display,
silver_display = row.silver_display,
bronze_display = row.bronze_display,
total = total,
gold_rank = gold_rank_link,
total_rank = total_rank_link,
bgcolor_gold = bgcolor_gold,
bgcolor_total = bgcolor_total,
is_host = row.is_host,
merged = false
})
i = i + 1
end
end
-------------------------------------------------------------------
-- Step 3: Compute max medals and totals
-------------------------------------------------------------------
local max_gold, max_silver, max_bronze, max_total = 0, 0, 0, 0
local total_gold, total_silver, total_bronze = 0, 0, 0
for _, row in ipairs(rows) do
if not row.merged then
total_gold = total_gold + row.gold
total_silver = total_silver + row.silver
total_bronze = total_bronze + row.bronze
if row.gold > max_gold then max_gold = row.gold end
if row.silver > max_silver then max_silver = row.silver end
if row.bronze > max_bronze then max_bronze = row.bronze end
if row.total > max_total then max_total = row.total end
end
end
-- Final totals and total rank links
local total_medals = total_gold + total_silver + total_bronze
local total_rank_raw = args["total_rank"] or ""
local total_total_rank_raw = args["total_total_rank"] or ""
local total_rank = total_rank_raw ~= "" and
string.format("[[All-time Olympic Games medal table#Complete ranked medals (excluding precursors)|%s]]", total_rank_raw) or ""
local total_total_rank = total_total_rank_raw ~= "" and
string.format("[[All-time Olympic Games medal table#Complete ranked medals (excluding precursors)|%s]]", total_total_rank_raw) or ""
-------------------------------------------------------------------
-- Step 4: Build the wikitable header
-------------------------------------------------------------------
local sticky_header = frame:expandTemplate{ title = "sticky-header" }
local wikitext = '{| class="wikitable sticky-header" style="text-align:center; font-size:90%;"\n'
wikitext = wikitext .. "|-\n! Games !! Athletes"
wikitext = wikitext .. ' !! style="background:gold; width:3.7em; font-weight:bold;"| Gold'
wikitext = wikitext .. ' !! style="background:silver; width:3em; font-weight:bold;"| Silver'
wikitext = wikitext .. ' !! style="background:#c96; width:3.7em; font-weight:bold;"| Bronze'
wikitext = wikitext .. ' !! style="width:3.7em; font-weight:bold;"| Total'
-- Column headers for rank (1 or 2 columns depending on config)
if show_dual_ranks then
wikitext = wikitext .. ' !! style="width:4em; font-weight:bold;"| [[Olympic medal table|<small>{{abbr|Gold Medals|Ranking Gold Medals Table}}</small>]]'
wikitext = wikitext .. ' !! style="width:4em; font-weight:bold;"| [[Olympic medal table|<small>{{abbr|Total Medals|Ranking Total Medals Table}}</small>]]\n'
else
wikitext = wikitext .. ' !! style="width:3em; font-weight:bold;"| Rank\n'
end
-- Helper: bold value if it’s the max
local function bold_if_max(val, max)
return val > 0 and val == max and ("'''" .. val .. "'''") or tostring(val)
end
-- Helper: process flag icon with optional flagicon
local function format_game_with_flag(game)
local expanded_game = frame:preprocess(game)
local year = expanded_game:match("(%d%d%d%d)")
if show_games_flag and year then
local flag_name = flagicon_data[season] and flagicon_data[season][year]
if flag_name then
return string.format("{{flagicon|%s}} %s", flag_name, expanded_game)
end
end
return expanded_game
end
-------------------------------------------------------------------
-- Step 5: Render each table row
-------------------------------------------------------------------
for _, row in ipairs(rows) do
if row.merged then
-- Participation row with rowspan
local colspan_val = show_dual_ranks and 7 or 6
wikitext = wikitext .. string.format(
"|-\n| align=left %s | %s || colspan=%d rowspan=%d %s | %s\n",
row.is_host and 'style="border-top:3px solid purple; border-left:3px solid purple; border-bottom:3px solid purple;"' or "",
format_game_with_flag(row.games_list[1]),
colspan_val,
row.rowspan,
row.is_host and 'style="border-top:3px solid purple; border-bottom:3px solid purple; border-right:3px solid purple;"' or "",
row.participation
)
for i = 2, row.rowspan do
wikitext = wikitext .. string.format(
"|-\n| align=left %s | %s\n",
row.is_host and 'style="border-top:3px solid purple; border-bottom:3px solid purple;"' or "",
format_game_with_flag(row.games_list[i])
)
end
else
-- Regular medal row
local line = "|-\n"
local game_display = format_game_with_flag(row.games)
if row.is_host then
local middle_border = 'border-top: 3px solid purple; border-bottom: 3px solid purple;'
local right_border = middle_border .. ' border-right: 3px solid purple;'
line = line .. string.format('| align=left style="border-left: 3px solid purple; %s" | %s', middle_border, game_display)
line = line .. string.format(' || style="%s" | %s', middle_border, row.athletes)
line = line .. string.format(' || style="%s" | %s', middle_border, bold_if_max(row.gold, max_gold))
line = line .. string.format(' || style="%s" | %s', middle_border, bold_if_max(row.silver, max_silver))
line = line .. string.format(' || style="%s" | %s', middle_border, bold_if_max(row.bronze, max_bronze))
line = line .. string.format(' || style="%s" | %s', middle_border, bold_if_max(row.total, max_total))
if show_dual_ranks then
line = line .. string.format(' || style="%s%s" | %s', row.bgcolor_gold ~= "" and 'background-color:' .. row.bgcolor_gold .. '; ' or "", middle_border, row.gold_rank)
line = line .. string.format(' || style="%s%s" | %s', row.bgcolor_total ~= "" and 'background-color:' .. row.bgcolor_total .. '; ' or "", right_border, row.total_rank)
else
line = line .. string.format(' || style="%s%s" | %s', row.bgcolor_gold ~= "" and 'background-color:' .. row.bgcolor_gold .. '; ' or "", right_border, row.gold_rank)
end
else
-- Regular non-hosted row
line = line .. "| align=left | " .. game_display
line = line .. " || " .. row.athletes
line = line .. " || " .. (row.gold == max_gold and ("'''" .. row.gold_display .. "'''") or row.gold_display)
line = line .. " || " .. (row.silver == max_silver and ("'''" .. row.silver_display .. "'''") or row.silver_display)
line = line .. " || " .. (row.bronze == max_bronze and ("'''" .. row.bronze_display .. "'''") or row.bronze_display)
line = line .. " || " .. bold_if_max(row.total, max_total)
if show_dual_ranks then
line = line .. (row.bgcolor_gold ~= "" and (' || style="background-color:' .. row.bgcolor_gold .. '" | ' .. row.gold_rank) or (" || " .. row.gold_rank))
line = line .. (row.bgcolor_total ~= "" and (' || style="background-color:' .. row.bgcolor_total .. '" | ' .. row.total_rank) or (" || " .. row.total_rank))
else
line = line .. (row.bgcolor_gold ~= "" and (' || style="background-color:' .. row.bgcolor_gold .. '" | ' .. row.gold_rank) or (" || " .. row.gold_rank))
end
end
wikitext = wikitext .. line .. "\n"
end
end
-------------------------------------------------------------------
-- Step 6: Add total row at bottom of table
-------------------------------------------------------------------
wikitext = wikitext .. "|-\n! colspan=2 | Total"
wikitext = wikitext .. string.format(" !! %d !! %d !! %d !! %d", total_gold, total_silver, total_bronze, total_medals)
if show_dual_ranks then
wikitext = wikitext .. " !! " .. total_rank .. " !! " .. total_total_rank .. "\n"
else
wikitext = wikitext .. " !! " .. total_rank .. "\n"
end
wikitext = wikitext .. "|}"
-------------------------------------------------------------------
-- Final output
-------------------------------------------------------------------
local full_wikitext = sticky_header .. "\n" .. wikitext
return frame:preprocess(full_wikitext)
end
return p