Module:Sandbox/TheThomanski/Esc

- Cell colors - local COL_FST = 'gold'			-- 1st place local COL_SND = 'silver'		-- 2nd place local COL_TRD = '#C96'			-- 3rd place local COL_LST = '#FE8080'		-- Last place local COL_SFQ = 'navajowhite'	-- Semi-Final qualifier local COL_BJQ = 'paleturquoise'	-- Backup jury qualifier local COL_DSQ = '#A4EAA9'		-- Disqualifed / withdrawn entry

- Text - local AQ        = 'Automatic qualifier' local NQ        = 'Failed to qualify' local NOSEMI    = 'No semi-finals' local NA        = 'N/A' local MILLSTREET = 'Kvalifikacija za Millstreet' local ESC1996Q  = 'Eurovision Song Contest 1996#Qualifying round'

local getArgs = require('Module:Arguments').getArgs local p = {}

local amountOfEntries local usedLanguages = {}

function p.entry(f)		return main(f, 'entry')		end function p.year(f)		return main(f, 'year')		end function p.country(f)	return main(f, 'country')	end function p.list(f)		return main(f, 'list')		end

function main(f, reqOutput) local args = getArgs(f) local html = '' local contest = getContest(args['cont']) local id     = args['id'] local country = args['cnty'] local year   = args['y'] local show   = args['s'] local entryNo = args['no'] local sortMethod = '' if not show   then show = 'gf' end if not entryNo then entryNo = 1 end if show == 'gf' then sortMethod = 'draw' end local entries if reqOutput == 'year' or reqOutput == 'list' then	-- Get all entries from country entries = getAllEntriesFrom{contest=contest.id, from='year', year=year, show=show, sortMethod=sortMethod} elseif reqOutput == 'country' then					-- Get all entries from year entries = getAllEntriesFrom{contest=contest.id, from='country', country=country} else end amountOfEntries = tableLen(entries) local function getEntryNo(entry) local entryNo = 1 if entry.cntye then entryNo = entry.cntye end return entryNo end if reqOutput == 'entry' then if country and year then html = table.concat(createEntryRow{reqOutput=reqOutput, contest=contest, entryNo=entryNo, country=country, year=year}) elseif id then entryNo = getEntryNo(getEntry{contest=contest, id=id}) html = table.concat(createEntryRow{reqOutput=reqOutput, contest=contest, entryNo=entryNo, id=id}) end else for _, entry in ipairs(entries) do			entryNo = getEntryNo(entry) html = html .. table.concat(createEntryRow{reqOutput=reqOutput, contest=contest, show=show, entryNo=entryNo, country=entry.cnty, year=entry.y}) end end return html end

--

local row = 0 local spannedRows = {} local spannedCols = {} function createEntryRow(args) local html = {} local f   = mw.getCurrentFrame local contest  = args.contest local year     = args.year local country  = args.country if country and country['name'] then for i, name in ipairs(country['name']) do			if name[2] then if contest.dates[tostring(year)] < name[2] then country = name[1] break end end country = name[1] end end local id       = args.id	local entryNo   = args.entryNo local reqOutput = args.reqOutput local show     = args.show local entry if country and year then entry = getEntry{contest=contest, country=country, year=year, entryNo=entryNo} elseif id then entry = getEntry{contest=contest, id=id} end if entry then row = row + 1 spannedCols = {} local id = entry.id		local year = f:expandTemplate{title = 'Escyr', args = {entry.y, entry.c.id}} local draw local sf_draw = insertZeroBeforeSingleDigit(entry.sf_d) local gf_draw = insertZeroBeforeSingleDigit(entry.gf_d) if not sf_draw then sf_draw = entry.sf_h end if not gf_draw then gf_draw = entry.gf_h end local pl, pt		local sf_pl = entry.sf_pl local gf_pl = entry.gf_pl local sf_pt = entry.sf_pt local gf_pt = entry.gf_pt if show then if show == 'gf' then draw = gf_draw pl  = gf_pl pt  = gf_pt else draw = sf_draw pl  = sf_pl pt  = sf_pt end else if sf_draw then if gf_draw then -- Took part in both semi-final and grand-final pl = gf_pl pt = gf_pt draw = gf_draw else -- Only took part in semi-final pl = sf_pl pt = sf_pt draw = sf_draw end elseif gf_draw then -- Only took part in grand final pl = gf_pl pt = gf_pt draw = gf_draw end end local flag if entry.cnty['flag'] then for _, version in ipairs(entry.cnty['flag']) do				if contest.dates[tostring(entry.y)] < version[2] then flag = version[1] break end end end country = f:expandTemplate{title = 'Esc', args = {country, flag, y = entry.y}} local country_entry = getEntryNoFromCountry(contest, id) local artist = entry.art local song  = entry.song local lang = {} local function createLangLink(songLang) if songLang[2] then songLang =  .. songLang[2] ..  else songLang =  .. songLang[1] ..  end return songLang end for _, songLang in ipairs(entry.lang) do			if usedLanguages[1] then local found = false for _, usedLang in ipairs(usedLanguages) do					if songLang[1] == usedLang then if songLang[2] then table.insert(lang, songLang[2]) else table.insert(lang, songLang[1]) end found = true end end if not found then table.insert(lang, createLangLink(songLang)) table.insert(usedLanguages, songLang[1]) end else table.insert(lang, createLangLink(songLang)) table.insert(usedLanguages, songLang[1]) end end if reqOutput == 'entry' then entryData	 = {artist, song} entryDataText = {'artist', 'song'} replaceNilValues(entryData, entryData) elseif reqOutput == 'year' then entryData	 = {draw, country, artist, song, lang, pl, pt} entryDataText = {'draw', 'country', 'artist', 'song', 'lang', 'pl', 'pt'} replaceNilValues(entryData, entryData) elseif reqOutput == 'country' then entryData	 = {year, artist, song, lang, gf_pl, gf_pt, sf_pl, sf_pt} entryDataText = {'year', 'artist', 'song', 'lang', 'gf_pl', 'gf_pt', 'sf_pl', 'sf_pt'} replaceNilValues(entryData, entryDataText) elseif reqOutput == 'list' then entryData	 = {id, draw, country, country_entry, artist, song, lang, pl} entryDataText = {'id', 'draw', 'country', 'country_entry', 'artist', 'song', 'lang', 'pl'} replaceNilValues(entryData, entryData) end local function isNil(row) if entryData[row] == 'nil_' .. row then return true else return false end end local tr = ' \n' -- Default no row styling local rowStyling = '' if reqOutput == 'year' then if (show == 'gf') and gf_pl == 1 then rowStyling = 'font-weight:bold; background:' .. COL_FST .. ';'			elseif (show == 'sf' or show == 'sf1' or show == 'sf2') and (gf_draw or entry.q) then if entry.jury then rowStyling = 'font-weight:bold; background:' .. COL_BJQ .. ';'				else rowStyling = 'font-weight:bold; background:' .. COL_SFQ .. ';'				end end end tr = '\n' table.insert(html, tr) if entryData then for i, data in ipairs(entryData) do				if not getIndex(spannedRows, row) and not getIndex(spannedCols, entryDataText[i]) then local cellStyling = '' if type(data) == 'string' and string.sub(data, 1, 4) == 'nil_' then -- If the value is nil data = nil if reqOutput == 'country' then local gf_pl = getIndex(entryDataText, 'gf_pl') local gf_pt = getIndex(entryDataText, 'gf_pt') local sf_pl = getIndex(entryDataText, 'sf_pl') local sf_pt = getIndex(entryDataText, 'sf_pt') local colspan = 1 if not entry.id and entry.dq then if entryDataText[i] == 'gf_pl' then if entry.y == 2020 then data = 'Contest cancelled' else data = entry.dq									end data = data .. ' X' colspan = 4 else break end else if gf_pt and isNil(gf_pt) then -- If no gf points if not isNil(sf_pl) or not isNil(sf_pt) then if entryDataText[i] == 'gf_pl' and gf_pl and isNil(gf_pl) then -- If no gf points and no gf placement data = NQ											if contest.id == 'esc' then if entry.y == 1993 then data = '' .. NQ .. ' X' end if entry.y == 1996 then data = '' .. NQ .. ' X' end end colspan = 2 end else if entryDataText[i] == 'gf_pt' and not isNil(gf_pl) then -- If no gf points but there is placement (e.g. ESC 1956) data = NA										end end elseif not gf_pt then if entryDataText[i] == 'gf_pl' and gf_pl and isNil(gf_pl) then -- If no gf points and no gf placement data = NQ									end end if entryDataText[i] == 'sf_pl' and sf_pl then if isNil(sf_pl) then -- if no semi results if contest.id == 'esc' and entry.y == 1993 then data = f:expandTemplate{title = 'Nowrap', args = { .. MILLSTREET .. }} colspan = 2 elseif contest.id == 'esc' and entry.y >= 2004 then if (not isNil(gf_pl) and not isNil(gf_pt)) or entry.q then data = AQ												colspan = 2 end else data = NOSEMI colspan = 2 end end end end if data then cellStyling = f:expandTemplate{title = 'N/a'} else data = '' end if colspan > 1 then cellStyling = cellStyling .. '; colspan="' .. colspan .. '"' if data == rowspanData then cellStyling = cellStyling .. '; rowspan="' .. spannedRows .. '"' --cellStyling = cellStyling .. '; colspan="2"' table.insert(spannedRows, row + 1) else spannedRows = 1 end table.insert(spannedCols, entryDataText[i + 1]) end end if not data then data = '' end elseif entryDataText[i] == 'id' or entryDataText[i] == 'country_entry' then cellStyling = 'text-align:right' if show == 'gf' and sf_draw then data = ' ''' .. data .. ''' '						end elseif entryDataText[i] == 'draw' then if (show == 'gf' and not entry.gf_d and entry.gf_h) or (show == 'sf1' or show == 'sf2' or show == 'sf' and not entry.gf_d and entry.gf_h) then if data == 1 then data = '1st half' end if data == 2 then data = '2nd half' end end cellStyling = 'text-align:center' elseif entryDataText[i] == 'year' then -- Year column cellStyling = 'text-align:center' elseif entryDataText[i] == 'song' then local title = song local og_title = '' if entry.tlang then -- If it's a non-English song title if entry.og then -- If it's a transliterated title title = f:expandTemplate{title = 'Transl', args = {entry.tlang, title, italics = 'no'}} og_title = ' (' .. f:expandTemplate{title = 'Lang', args = {entry.tlang, entry.og, italics = 'no'}} .. ') ' else title = f:expandTemplate{title = 'Lang', args = {entry.tlang, title, italics = 'no'}} end end data = '"' .. title .. '" ' .. og_title elseif entryDataText[i] == 'lang' then if type(data) == 'table' then data = processTable(data) end if entry.langm then -- If there are 'minor' languages local function createNote(lang) lang = createLangLink(lang) data = data .. f:expandTemplate{title = 'Efn', args = {'Contains words or phrases in ' .. lang, name=lang}} end if type(entry.langm) == 'table' then for _, v in ipairs(entry.langm) do									createNote(v) end else createNote(langm) end end elseif entryDataText[i] == 'pl'	or entryDataText[i] == 'pt'	or entryDataText[i] == 'gf_pl' or entryDataText[i] == 'gf_pt' or entryDataText[i] == 'sf_pl' or entryDataText[i] == 'sf_pt'	then cellStyling = 'text-align:right;' if reqOutput == 'list' or reqOutput == 'country' then if reqOutput == 'country' then if entryDataText[i] == 'gf_pl' or entryDataText[i] == 'gf_pt' then show = 'gf' elseif entryDataText[i] == 'sf_pl' or entryDataText[i] == 'sf_pt' then semi = getSemi(contest, entry.id) if semi then show = semi end end end if show then calcAmountOfEntries(contest.id, entry.y, show) end if ((entryDataText[i] == 'sf_pl' or entryDataText[i] == 'sf_pt') and sf_pl == amountOfEntries) or							  ((entryDataText[i] == 'gf_pl' or entryDataText[i] == 'gf_pt') and gf_pl == amountOfEntries) or							   ((entryDataText[i] == 'pl' or entryDataText[i] == 'pt') and pl == amountOfEntries) then cellStyling = cellStyling .. ' background:' .. COL_LST .. '"'								--data = tostring(data) .. ' ◁'							else								if show == 'gf' or reqOutput == 'country' then									local pl = gf_pl									if entryDataText[i] == 'sf_pl' or entryDataText[i] == 'sf_pt' then pl = sf_pl end									if pl == 1 then cellStyling = cellStyling .. ' background:' .. COL_FST .. '"' end if pl == 2 then cellStyling = cellStyling .. ' background:' .. COL_SND .. '"' end									if pl == 3 then cellStyling = cellStyling .. ' background:' .. COL_TRD .. '"' end elseif (show == 'sf' or show == 'sf1' or show == 'sf2') and (gf_pl or gf_pt) then if entry.jury then cellStyling = cellStyling .. ' background:' .. COL_BJQ .. '"'										--data = tostring(data) .. ' ‡'									else										cellStyling = cellStyling .. ' background:' .. COL_SFQ .. '"' --data = tostring(data) .. ' †'									end end end end if data == 0 then data = ' .. data .. ' end -- Make digit bold if nul points end if reqOutput == 'country' and entryDataText[i] ~= 'year' and entryDataText[i] ~= 'sf_pl' and entryDataText[i] ~= 'sf_pt' then calcAmountOfEntries(contest.id, entry.y, 'gf') local x = amountOfEntries if gf_pl == 1 then cellStyling = cellStyling .. ' background:' .. COL_FST end if gf_pl == 2 then cellStyling = cellStyling .. ' background:' .. COL_SND end if gf_pl == 3 then cellStyling = cellStyling .. ' background:' .. COL_TRD end if gf_pl == x then cellStyling = cellStyling .. ' background:' .. COL_LST end if entry.dq or entry.nq then cellStyling = cellStyling .. ' background:' .. COL_DSQ end end if i == 1 then cell     = '\n' cellClose = ' \n' else cell     = '\n' cellClose = ' \n' end table.insert(html, cell .. data .. ' \n') end end table.insert(html, ' \n') end end return html end

function getContest(x) local contests = mw.loadData('Module:Sandbox/TheThomanski/Esc/data').contests local reqContest = 'esc' -- Default ESC if x then reqContest = string.lower(x) end local result for _, contest in ipairs(contests) do -- For every contest do		if contest.id == reqContest then result = contest end end return result end

function getEntry(args) local result local contest = args.contest local country = args.country -- Table, macedonia local year   = args.year local id     = args.id local entryNo = args.entryNo -- For multiple entries per country in a year (e.g. ESC 1956) if type(contest) == 'string' then contest = getContest(contest) end for _, entry in ipairs(contest.values) do -- For every entry in the contest do		result = nil if country and year then if (hasValue(entry.cnty, country)) then -- If the entry is from the requested country if (entry.y == year) then -- If the entry is from the requested year result = entry end end elseif id then if (entry.id == tonumber(id)) then -- If the entry is the requested entry then result = entry end end if result then if entryNo and entryNo > 1 then entryNo = entryNo - 1 else return result end end end return result end

function getAllEntriesFrom(args) local contest = getContest(args.contest) local entries = {} local draw = 1 local q_d = 0 local firstEntry = nil for i, entry in ipairs(contest.values) do -- For every entry in the contest do		if args.from == 'year' and entry.y == tonumber(args.year) then -- Get all entries from year if args.show then if	(args.show == 'sf' and entry.sf_d and not entry.sf) or -- Get all entries from Semi-Final (args.show == 'sf1' and entry.sf == 1) or -- Get all entries from Semi-Final 1 (args.show == 'sf2' and entry.sf == 2) or -- Get all entries from Semi-Final 2 (args.show == 'gf' and (entry.gf_d or entry.q)) -- Get all entries from Grand Final then if args.show == 'gf' and args.sortMethod == 'draw' and entry.id then local found = false local oldEntry = entry.id						local newEntry = entry.id						if firstEntry == nil then firstEntry = entry end local gf_d = entry.gf_d while not found do							if entry.q then q_d = q_d + 1 gf_d = q_d end if gf_d == draw then table.insert(entries, entry) draw = draw + 1 found = true else newEntry = newEntry + 1 entry = getEntry{contest=contest, id=newEntry} if not entry or entry.y ~= firstEntry.y then entry = firstEntry newEntry = entry.id								end gf_d = entry.gf_d end end else table.insert(entries, entry) end end else table.insert(entries, entry) end elseif args.from == 'country' and hasValue(entry.cnty, args.country) then -- Get all entries from country table.insert(entries, entry) end end return entries end

function getEntryNoFromCountry(contest, id) if id then local entry = getEntry{contest=contest, id=id} local country = entry.cnty if country['name'] then country = country['name'][1][1] end local entries = getAllEntriesFrom{contest=contest.id, from='country', country=country} local extraEntries = {} -- For more than one entry in a year (e.g. ESC 1956) for i, v in ipairs(entries) do			if extraEntries[v.y] then extraEntries[v.y] = extraEntries[v.y] + 1 else extraEntries[v.y] = 0 end if v.id == entry.id then local removal = 0 for _, v in pairs(extraEntries) do					removal = removal + v				end local result = i - removal if entry.cntye then result = result .. ' (' .. entry.cntye .. ') ' end return result end end end end

function getSemi(contest, id) local entry = getEntry{contest=contest, id=id} if entry then if entry.sf then return 'sf' .. tostring(entry.sf) elseif entry.sf_d then return 'sf' end end return nil end

function replaceNilValues(entryData, entryDataText) local length = tableLen(entryDataText) for i = 1, length do		if not entryData[i] then entryData[i] = 'nil_' .. i		end end end

function calcAmountOfEntries(contest, year, show) amountOfEntries = tableLen(getAllEntriesFrom{contest=contest, from='year', year=year, show=show}) end

--

function insertZeroBeforeSingleDigit(x) if x then if x < 10 then x = '0' .. x		end end return x end

function getIndex(tab, reqV) if type(tab) == 'table' then for i, v in ipairs(tab) do			if v == reqV then return i			end end end return nil end

function processTable(tab) local str = '' if type(tab) == 'table' then for i, v in ipairs(tab) do str = str .. v			if i ~= tableLen(tab) then str = str .. ', '			end end return str else return tab end end

function tableLen(tab) local x = 0 if tab then for _ in pairs(tab) do	 	x = x + 1 end end return x end

function hasValue(tab, val) if tab then if type(tab) == 'table' then for _, v in pairs(tab) do		       if v == val or (type(v) == 'table' and hasValue(v, val)) then return val end end elseif type(tab) == 'string' then if tab == val then return val end end end return false end

return p