Module:Team appearances list

Documentation for this module may be created at Module:Team appearances list/doc

-- This module implements [[Template:Team appearances list]].local p = {}local data_competitionslocal function load_data(frame)-- Load data module (or its sandbox) and set variables from its exported data.if not data_competitions thenframe = 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.competitionsendendlocal 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' thentext = text:match('(%S.-)%s*$')endreturn textendlocal 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 == '' thenif is_optional thenreturn nilenderror('Parameter ' .. name .. ' is missing')endarg = tonumber(arg)if type(arg) ~= 'number' thenerror('Parameter ' .. name .. ' is not a number')endif math.floor(arg) ~= arg thenerror('Parameter ' .. name .. ' is not an integer')endif not (min <= arg and arg <= max) thenerror('Parameter ' .. name .. ' is not valid')endreturn argendlocal function valid_text(name)local arg = args[name]if arg == nil or arg == '' thenerror('Parameter ' .. name .. ' is missing')endif type(arg) ~= 'string' thenerror('Parameter ' .. name .. ' is not a string')endreturn argendoptions.competition = valid_text('competition')options.team = valid_text('team')options.competitions = data_competitions[options.competition]local begin_optionalif options.competitions thenbegin_optional = trueelseoptions.interval = valid_integer('interval', 1, 30)endoptions.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 thenif options.begin_year > options.end_year thenerror('Parameter end_year must not be before begin_year')endendoptions.disqualified_year = valid_integer('disqualified_year', 1800, 2100, true)return optionsendlocal 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 thenif #year == 4 thenreturn tonumber(year)endreturnendlocal first, dash, last = text:match('^(%d+)(%D+)(%d+)$')if not (first and #first == 4) thenreturnenddash = strip_to_nil(dash)if not (dash == '-' or dash == '–') thenreturnendif #last ~= 4 thenif #last == 2 thenlast = first:sub(1, 2) .. lastelsereturnendendfirst = tonumber(first)last = tonumber(last)if first < last thenreturn first, lastelseif first == last thenreturn firstendendlocal 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) doif type(item) == 'number' thenabsent_years[item] = trueelseitem = strip_to_nil(item)if type(item) == 'string' thenlocal first, last = extract_range(item)if not first thenerror('Year ' .. item .. ' is not valid')endif last thentable.insert(absent_ranges, {first, last})elseabsent_years[first] = trueendendendendreturn absent_years, absent_rangesendlocal 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 absenceslocal comp_years = {}local begin_year = options.begin_yearlocal end_year = options.end_yearlocal competitions = options.competitionsif competitions thenabsences = competitions[options.team]begin_year = begin_year or (absences and absences.begin_year) or 0end_year = end_year or (absences and absences.end_year) or 9999for _, y in ipairs(competitions) doif y > end_year thenbreakelseif y >= begin_year thentable.insert(comp_years, y)endendelseend_year = end_year or (os.date('!*t').year + options.interval)for y = begin_year, end_year, options.interval dotable.insert(comp_years, y)endendlocal 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] = trueendreturn comp_years, disqualified_years, competition_absences(absences or args)endfunction p._main(args)load_data()  -- in case this function is called by another modulelocal hlist = require('Module:List').horizontallocal competitions, disqualified_years, absent_years, absent_ranges = competition_information(args)local current_year = os.date('!*t').yearlocal function is_absent(y)if absent_years[y] thenreturn trueendfor _, range in ipairs(absent_ranges) doif range[1] <= y and y <= range[2] thenreturn trueendendreturn falseendlocal appearances = {}local absent_first, absent_lastfor i = 1, #competitions + 1 do  -- +1 to handle any trailing absenceslocal y = competitions[i]if y and is_absent(y) thenif absent_first thenabsent_last = yelseabsent_first = yendelseif absent_first thentable.insert(appearances,'<span style="color:gray">' ..(absent_last and (absent_first .. '–' .. absent_last) or absent_first) ..'</span>')absent_first, absent_last = nil, nilendif y thenlocal display = tostring(y)if y > current_year thendisplay = '<i>' .. display .. '</i>'endif disqualified_years[y] thendisplay = '<del>' .. display .. '</del>'endtable.insert(appearances, string.format('[[%s at the %d %s|%s]]',args.team, y, args.competition, display))endendendreturn hlist(appearances)endfunction p.main(frame)load_data(frame)return p._main(frame:getParent().args)endreturn p