Module:Team appearances list

-- This module implements [[Template:Team appearances list]].

local p = {}

local data_competitions
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
	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')
	options.competitions = data_competitions[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
	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 three tables with information for the specified competition:
	-- * List of competition years.
	-- * Table of absent years.
	-- * 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]
		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
	return comp_years, competition_absences(absences or args)
end

function p._main(args)
	load_data()  -- in case this function is called by another module
	local hlist = require('Module:List').horizontal
	local competitions, absent_years, absent_ranges = competition_information(args)
	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,
					'<span style="color:gray">' ..
					(absent_last and (absent_first .. '–' .. absent_last) or absent_first) ..
					'</span>')
				absent_first, absent_last = nil, nil
			end
			if y then
				table.insert(appearances, string.format(
					'[[%s at the %d %s|%d]]',
					args.team, y, args.competition, y
				))
			end
		end
	end
	return hlist(appearances)
end

function p.main(frame)
	load_data(frame)
	return p._main(frame:getParent().args)
end

return p

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.