Module:Team appearances list/sandbox

-- This module implements Template:Team appearances list.

local p = {}

local data_competitions local data_old_names local function load_data(frame) -- Load data module (or its sandbox) and set variables from its exported data. if not data_competitions then frame = frame or mw.getCurrentFrame local sandbox = frame:getTitle:find('sandbox', 1, true) and '/sandbox' or '' local datamod = mw.loadData('Module:Team appearances list/data' .. sandbox) data_competitions = datamod.competitions data_old_names = datamod.old_names end end

local function strip_to_nil(text) -- If text is a string, return its trimmed content, or nil if empty. -- Otherwise return text (which may, for example, be nil). if type(text) == 'string' then text = text:match('(%S.-)%s*$') end return text end

local function make_options(args) -- Return table of options from validated args or throw error. local options = {} local function valid_integer(name, min, max, is_optional) local arg = args[name] if arg == nil or arg == '' then if is_optional then return nil end error('Parameter ' .. name .. ' is missing') end arg = tonumber(arg) if type(arg) ~= 'number' then error('Parameter ' .. name .. ' is not a number') end if math.floor(arg) ~= arg then error('Parameter ' .. name .. ' is not an integer') end if not (min <= arg and arg <= max) then error('Parameter ' .. name .. ' is not valid') end return arg end local function valid_text(name) local arg = args[name] if arg == nil or arg == '' then error('Parameter ' .. name .. ' is missing') end if type(arg) ~= 'string' then error('Parameter ' .. name .. ' is not a string') end return arg end options.competition = valid_text('competition') options.team = valid_text('team') -- Check ROC/TPE if options.team=='Republic of China' then local pageYear = tonumber(mw.ustring.match(mw.title.getCurrentTitle.text, '[%d]+')) -- mw.title.getCurrentTitle.text:match('^%d+') if pageYear and pageYear > 1950 and pageYear < 1980 then options.team = 'Chinese Taipei' end end -- end of ROC/TPE check options.competitions = data_competitions[options.competition] or data_competitions[data_old_names[options.competition]] local begin_optional if options.competitions then begin_optional = true else options.interval = valid_integer('interval', 1, 30) end options.begin_year = valid_integer('begin_year', 1800, 2100, begin_optional) options.end_year = valid_integer('end_year', 1800, 2100, true) if options.begin_year and options.end_year then if options.begin_year > options.end_year then error('Parameter end_year must not be before begin_year') end end options.disqualified_year = valid_integer('disqualified_year', 1800, 2100, true) return options end

local function extract_range(text) -- Return first (if text is a single year), or first, last if a range. -- The returned values are numbers. -- Return nothing if text is invalid. local year = text:match('^(%d+)$') if year then if #year == 4 then return tonumber(year) end return end local first, dash, last = text:match('^(%d+)(%D+)(%d+)$') if not (first and #first == 4) then return end dash = strip_to_nil(dash) if not (dash == '-' or dash == '–') then return end if #last ~= 4 then if #last == 2 then last = first:sub(1, 2) .. last else return end end first = tonumber(first) last = tonumber(last) if first < last then return first, last elseif first == last then return first end end

local function competition_absences(data) -- Return two tables with absent years and absent year ranges. -- Parameter data is an array of strings from template parameters, or -- numbers or strings from built-in data. -- Parameters that are blank or not numbers or strings are ignored. local absent_years, absent_ranges = {}, {} for _, item in ipairs(data) do		if type(item) == 'number' then absent_years[item] = true else item = strip_to_nil(item) if type(item) == 'string' then local first, last = extract_range(item) if not first then error('Year ' .. item .. ' is not valid') end if last then table.insert(absent_ranges, {first, last}) else absent_years[first] = true end end end end return absent_years, absent_ranges end

local function competition_information(args) -- Return four tables with competition and team information: -- * List of competition years that the team attended or could have attended. -- * Table of disqualified years (the team was absent, but there is an	--  article regarding the absent year). -- * Table of absent years (when the team did not attend). -- * List of pairs of years (absent for each year in range, inclusive). local options = make_options(args) local absences local comp_years = {} local begin_year = options.begin_year local end_year = options.end_year local competitions = options.competitions if competitions then absences = competitions[options.team] or competitions[data_old_names[options.team]] begin_year = begin_year or (absences and absences.begin_year) or 0 end_year = end_year or (absences and absences.end_year) or 9999 for _, y in ipairs(competitions) do			if y > end_year then break elseif y >= begin_year then table.insert(comp_years, y)			end end else end_year = end_year or (os.date('!*t').year + options.interval) for y = begin_year, end_year, options.interval do			table.insert(comp_years, y)		end end local disqualified_years = {} if options.disqualified_year then -- Input currently only allows entry of a single disqualified year. -- However processing works for any number of such years. disqualified_years[options.disqualified_year] = true end return comp_years, disqualified_years, competition_absences(absences or args) end

local function gameName(year, inputName) -- Modifies output of display being sent back to the list -- for games that have had a name change but are still considered -- the same competition. if inputName=="World Athletics Championships" or inputName=="World Championships in Athletics" then if year <= 2017 then return "World Championships in Athletics" else return "World Athletics Championships" end elseif (inputName=="British Empire Games"		or inputName=="British Empire and Commonwealth Games"		or inputName=="British Commonwealth Games"		or inputName=="Commonwealth Games") then if year <= 1950 then return "British Empire Games" elseif year <= 1966 then return "British Empire and Commonwealth Games" elseif year <= 1974 then return "British Commonwealth Games" else return "Commonwealth Games" end elseif inputName=="Southeast Asian Peninsular Games" or inputName=="Southeast Asian Games" then if year <= 1975 then return "Southeast Asian Peninsular Games" else return "Southeast Asian Games" end elseif inputName=="Asian Indoor Games" or inputName=="Asian Indoor and Martial Arts Games" then if year <= 2009 then return "Asian Indoor Games" else return "Asian Indoor and Martial Arts Games" end elseif inputName=="Southern Cross Games" or inputName=="South American Games" then if year <= 1982 then return "Southern Cross Games" else return "South American Games" end elseif inputName=="All-Africa Games" or inputName=="African Games" then if year <= 2011 then return "All-Africa Games" else return "African Games" end else return inputName end end

local function teamName(year, inputName, comp) -- Modifies output of display being sent back to the list -- for games that have had a name change but are still considered -- the same competition. if inputName=="Eswatini" or inputName=="Swaziland" then if year < 2018 or year == 2018 and comp == 'Commonwealth Games' then return "Swaziland" else return "Eswatini" end elseif inputName=="Southern Rhodesia" or inputName=="Rhodesia" or inputName=="Zimbabwe" then if year < 1980 then if (comp=="British Empire Games"					or comp=="British Empire and Commonwealth Games"					or comp=="British Commonwealth Games"					or comp=="Commonwealth Games") then return "Southern Rhodesia" elseif comp=="Summer Olympics" or comp=="Summer Paralympics" then return "Rhodesia" end else return "Zimbabwe" end elseif (inputName=="Republic of China"			or inputName=="Formosa"			or inputName=="Taiwan"			or inputName=="Chinese Taipei") then if year <= 1956 or year == 1972 or year == 1976 then return "Republic of China" elseif year==1960 then return "Republic of China (Formosa)" elseif year==1964 or year==1968 then return "Taiwan" elseif year > 1976 then return "Chinese Taipei" end elseif inputName=="Northern Rhodesia" or inputName=="Zambia" then if year <= 1964 then return "Northern Rhodesia" else return "Zambia" end elseif inputName=="Aden" or inputName=="South Arabia" or inputName=="Federation of South Arabia" then if year < 1966 then return "Aden" else return "South Arabia" end elseif inputName=="British Guiana" or inputName=="Guyana" then if year < 1966 then return "British Guiana" else return "Guyana" end elseif inputName=="Tanzania" or inputName=="Tanganyika" then if year < 1966 then return "Tanganyika" else return "Tanzania" end elseif inputName=="Ceylon" or inputName=="Sri Lanka" then if year <= 1972 then return "Ceylon" else return "Sri Lanka" end elseif inputName=="British Honduras" or inputName=="Belize" then if year <= 1973 then return "British Honduras" else return "Belize" end elseif inputName=="Dahomey" or inputName=="Benin" then if year <= 1975 then return "Dahomey" else return "Benin" end elseif inputName=="Upper Volta" or inputName=="Burkina Faso" then if year <= 1983 then return "Upper Volta" else return "Burkina Faso" end elseif inputName=="Burma" or inputName=="Myanmar" then if year < 1990 then return "Burma" else return "Myanmar" end elseif inputName=="Germany" or inputName=="West Germany" then if comp == "Summer Paralympics" or comp == "Winter Paralympics" then if year < 1992 then return "West Germany" else return "Germany" end end elseif inputName=="Democratic Republic of the Congo" or inputName=="Zaire" then if year >= 1984 and year <=1996 then return "Zaire" else return "Democratic Republic of the Congo" end elseif (inputName=="Individual Olympic Athletes" 		or inputName=="Independent Olympic Athletes" 		or inputName=="Independent Olympic Participants"		or inputName=="Olympic Athletes from Russia"		or inputName=="ROC") then if year == 1992 or year==2014 then return "Independent Olympic Participants" elseif year == 2000 then return "Individual Olympic Athletes" elseif year == 2012 or year==2016 then return "Independent Olympic Athletes" elseif year == 2018 then return "Olympic Athletes from Russia" elseif year == 2020 then return "Russian Olympic Committee athletes" else return inputName end elseif inputName=="Serbia and Montenegro" or inputName=="FR Yugoslavia" then if year < 2004 then if comp == "Mediterranean Games" then return "FR Yugoslavia" else return "Yugoslavia" end else return "Serbia and Montenegro" end elseif (inputName=="Refugee Olympic Team" 		or inputName=="IOC Refugee Olympic Team") then if year == 2016 then return "Refugee Olympic Team" elseif year == 2020 then return "IOC Refugee Olympic Team" else return inputName end elseif (inputName=="Independent Paralympic Participants" 		or inputName=="Individual Paralympic Athletes" 		or inputName=="Independent Paralympic Athletes"		or inputName=="RPC"		or inputName=="Neutral Paralympic Athletes") then if year == 1992 then return "Independent Paralympic Participants" elseif year == 2000 then return "Individual Paralympic Athletes" elseif year==2016 then return "Independent Paralympic Athletes" elseif year==2018 then return "Neutral Paralympic Athletes" elseif year == 2020 or year==2022 then return "Russian Paralympic Committee athletes" else return inputName end elseif inputName=="North Macedonia" or inputName=="Macedonia" then if year < 2019 then return "Macedonia" else return "North Macedonia" end elseif inputName=="Malaysia" or inputName=="Malaya" then if year < 1963 then return "Malaya" else return "Malaysia" end elseif inputName=="Ghana" or inputName=="Gold Coast" then if year < 1957 then return "Gold Coast" else return "Ghana" end end return inputName end

function p._main(args) load_data -- in case this function is called by another module local list = require('Module:List').horizontal local competitions, disqualified_years, absent_years, absent_ranges = competition_information(args) local current_year = os.date('!*t').year local function is_absent(y) if absent_years[y] then return true end for _, range in ipairs(absent_ranges) do			if range[1] <= y and y <= range[2] then return true end end return false end local appearances = {} local absent_first, absent_last for i = 1, #competitions + 1 do -- +1 to handle any trailing absences local y = competitions[i] if y and is_absent(y) then if absent_first then absent_last = y			else absent_first = y			end else if absent_first then table.insert(appearances,					' ' ..					(absent_last and (absent_first .. '–' .. absent_last) or absent_first) ..					' ') absent_first, absent_last = nil, nil end if y then local display = tostring(y) if y > current_year then display =  .. display .. 				end if disqualified_years[y] then display = ' ' .. display .. ' '				end local compName = gameName(y, args.competition) local teamOut = teamName(y, args.team, args.competition) if compName == 'FIS Alpine World Ski Championships' then table.insert(appearances, string.format( '%s', teamOut, compName, y, display ))				else table.insert(appearances, string.format( '%s', teamOut, y, compName, display ))				end end end end return list(appearances) end function p.main(frame) load_data(frame) return p._main(frame.args['team'] and frame.args or frame:getParent.args) end

return p