Module:GAN-Cycling-race

 Documentation[créer] [purger]
local p = {}
local wiki = string.match(mw.site.server, "%a+")
if wiki == "www" then
	wiki = "fr"
end
--import translation
local l10n = mw.loadData("Module:GAN-Cycling-race/l10n")

--import data
local data = mw.loadData("Module:GAN-Cycling-race/data")

local contentLanguage = mw.getContentLanguage()
local wikilang = contentLanguage:getCode()
local wikibase = mw.wikibase
local localframe  -- Value may be given by functions which use frame functions like getReference

-- == Structure of the code ==
-- I) Constant
-- II) Translation
-- III) Basic functions
-- IV) Functions less basic called from other functions
-----A) Time functions
-----B) Link functions
-----C) Functions for the output, like table
-----D) Jersey, flag functions
-----E) Other (winner)
-- V) Main functions
----- A) Function race reference
----- B) Calendar
----- C) Victory
----- Cbis) Function for infobox
----- D) Stage infobox
----- E) List of teams
----- F) Classifications
----- G) Infobox
----- GG) infoboxseason
----- GGG) infoboxChamp
----- H) Team roster
----- I) Function list of winners (palmarès)
----- frame --> listofwinners_main
----- frame --> listofwinners_custom
----- J) List of stages
----- K) List of stages classification
----- M) Start list
----- N) Rider ranking
--Tip: search "--==" to navigate between the sections

--== I) Classes declared as global ==
-- Class of a cycling race. Class is: 1.UWT, 2.UWT, 1.HC, ... add new classes, no problem

--Data that requires # functions and cannot be called with mw.loadData
	local class = { "Q22231106", "Q22231107", "Q22231108", "Q22231109", "Q22231110", "Q22231111", "Q22231112",
	"Q22231113", "Q22231114", "Q22231115", "Q22231116", "Q22231117", "Q22231118", "Q22231119", "Q23015458",
	"Q23005601", "Q23005603", "Q74275170", "Q74275176" }

	local class_without2x = { "Q22231106", "Q22231108", "Q22231110", "Q22231111", "Q22231114", "Q22231116",
	"Q22231118", "Q22231119", "Q23015458", "Q23005601", "Q74275170" }

	local class_champ = { "Q22231118", "Q22231119", "Q23015458"}
	local stages = {'Q18131152', 'Q20646667', 'Q20646670', 'Q20680270', 'Q20646668', 'Q20679712', 'Q2348250', 'Q2266066', 'Q485321'}
	local UCI_Circuits = {'Q1194340', 'Q1063423', 'Q1063430', 'Q268357', 'Q1039648', 'Q1329578', 'Q12270097', 'Q635366', 'Q21075974', 'Q1693153', "Q71580493"}
	local class_2x = {"Q22231107", "Q23005603", "Q22231115", "Q22231109", "Q22231112", "Q22231113", "Q22231117", "Q74275176"}

--dictionnaries
local classes=data.classes 
local class_sort=data.class_sort
local bg_color_table = data.bg_color_table

local available, translations = pcall(require, "Module:GAN-Cycling-race/lang")
local available_list = available and type(translations.list) == "function"
local available_lang_priority = available == true and type(translations.lang_priority) == "table"

local textalign = "left"
local floattable = "left"
local floatinfobox = "right"
if wiki == "ar" or wiki == "fa" or wiki == "ur" or wiki == "he" then
	textalign = "right"
	floattable = "right"
	floatinfobox = "left"
end

local standardtablecss=data.standardtablecss_part1..textalign..data.standardtablecss_part2

local no_country_calendar={'ru'}
local no_country_victories={'ru'}
local no_country_classification={'es','da','no','ru'}
local no_roll_startlist={'fr','no','ar'}



--== II) Translation ==
local function translate(func_name_short, index, title)
	if index == nil then index=1 end -- for prologue
	if index==1000 then --code for some custom function
		return title
	else
		if func_name_short then
			local func_name=func_name_short.."_translate"
			if l10n[func_name][index] then 
				return l10n[func_name][index]
			elseif func_name_short=="listofwinners" then
				if index>4 then 
					if index<12 then
						index =index+17
					else
						index=index+23
					end
				end
				return l10n["infobox_translate"][index]
			end
		else 
			return "error: no func_name found"
		end
	end
end

function black_list( Label)
	local black_list=l10n.black_list
	--[[ List of Wikipedia articles with the same lemma as the non existing rider article. Those lemmas are printed
		as text "black" in the tables, not "blue" or "red". This way there will be no false wikilinks at the WhatLinksHere entry.
		List should be updated maybe once a year. ]]
	return black_list[Label]
end

local function stageLink(x, a, b) -- x= 10a: a = 10, b = a. x = 5: a = 5, b = ""
	local l10nDef = {["fr"]="étape", ["en"]="stage", ["ar"]="مرحلة", ["br"]="Tennad", ["ca"]="etapa", ["cs"]="etapa", ["de"]="Etappe", ["da"]="etape", ["eo"]="Etapo",
	["es"]="etapa", ["eu"]="Etapa", ["fi"]="Etappi", ["fo"]="teinur", ["hu"]="szakasz", ["it"]="Tappa", ["ja"]="ステージ", ["la"]="Statio", ["lb"]="Etapp",
	["lv"]="Posms", ["mk"]="Етапа", ["nl"]="Etappe", ["no"]="etappe", ["pl"]="Etap", ["pt"]="Etapa", ["ro"]="Etapa", ["ru"]="Этап", ["sk"]="Etapa",
	["sv"]="Etapp", ["ast"]="etapa" }

	local word1, word2
	word2=l10nDef[wiki]
	if word2 == nil then word2=l10nDef["en"] end -- if no translation, show en translation
	local word = word2

	if wiki=="ar" then return word2 .. " " .. ( a or "" ) , "#" .. word2 .. " " .. ( a or "" ) end

-- fr: {{1re}} étape, {{2e}} étape
	if wiki=="fr" then
		if b == "" then -- series_ordinal without character
			if a == "1" then word1 = "1<sup>re</sup> "..word else word1 = a.."<sup>e</sup> "..word end -- table text = {{1re}} étape, {{2ae}} étape,
			if a == "1" then word2 = "#1re "..word else word2 = "#"..a.."e  "..word end --text of section header = #1re étape, #2e étape
			return word1, word2
		end
		if b ~= "" then -- series_ordinal with character: instead of eg "1a re" it is "1re a"
			if a == "1" then word1 = "1<sup>re</sup> "..b.." "..word else word1 = a.."<sup>e</sup> "..b.." "..word end -- table text = {{1re}} étape, {{2ae}} étape,
			if a == "1" then word2 = "#1re "..b.." "..word else word2 = "#"..a.."e"..b.." "..word end --text of section header = #1re étape, #2e étape
			return word1, word2
		end
	end
	if wiki=="hu" then
		if b == "" then return a..". "..word, "#"..a..". "..word
		else return a..b.." "..word, "#"..a..b.." "..word end
	end
	if wiki=="de" or wiki=="da" or wiki=="fo" or wiki=="lb" or wiki=="no" then return a..". "..b.." "..word, "#"..a..". "..b.." "..word end
	if wiki=="ca" then return a.."a "..b.." "..word, "#"..a..". "..b.." "..word end
	if wiki=="es" then return a..".ª "..word.." "..b, "#"..a..".ª "..word.." "..b end
	if wiki=="ast" then
		if b == "" then -- series_ordinal without character
			if a == "1" or a == "3" then word1 = a.."ᵉʳ "..word else word1 = a.."ª "..word end -- table text = 1ᵉʳ etapa, 2ª etapa, 3ᵉʳ etapa,
			if a == "1" or a == "3" then word2 = "#"..a.."ᵉʳ "..word else word2 = "#"..a.."ª  "..word end --text of section header = #1ᵉʳ etapa, #2ª etapa, #3ᵉʳ etapa
			return word1, word2
		end
		if b ~= "" then -- series_ordinal with character: instead of eg "1a re" it is "1re a"
			if a == "1" or a == "3" then word1 = a.."ᵉʳ "..b.." "..word else word1 = a.."ª "..b.." "..word end -- table text = {{1ᵉʳ}} etapa, {{2ª}} etapa,
			if a == "1" or a == "3" then word2 = "#"..a.."ᵉʳ "..b.." "..word else word2 = "#"..a.."ª"..b.." "..word end --text of section header = #1ᵉʳ etapa, #2ª etapa
			return word1, word2
		end
	end

	-- default
	word1 = x                  -- table text = 1, 2a, 3
	word2 = "#"..word.." ".. x -- text of section header = #Etappe 2a, #Stage 4
	return word1, word2
end

local function typeofstage(x, typ, noborder)
	-- plain, hilly, inter, ... must be "" or "any text"
	-- l10nDef[""] = {plain = "", hilly="", inter='', mount='', time_prologue='', time_team='', time_indiv='', uphill='', rest=''}
	local l10nDef = {
		["ar"] = {plain = "مرحلة مستوية", hilly="مرحلة التلال", inter='مرحلة متوسطة', mount='مرحلة جبلية', time_prologue='مرحلة سباق ضد الساعة', time_team='مرحلة سباق الفرق ضد الساعة', time_indiv='مرحلة سباق فردي ضد الساعة', uphill='مرحلة تسلق الجبل ضد الساعة', rest='يوم راحة'},
		["ast"] = {plain = "etapa llana", hilly="etapa escarpada", inter='etapa de mediu monte', mount='etapa de monte', time_prologue='prólogu', time_team='contrarreló per equipos', time_indiv='contrarreló individual', uphill='cronoescalada', rest='xornada de descansu'},
		["fr"] = {plain = "étape de plaine", hilly="étape vallonnée", inter='étape de moyenne montagne', mount='étape de montagne', time_prologue='prologue', time_team='contre-la-montre par équipes', time_indiv='contre-la-montre individuel', uphill='contre-la-montre en côte', rest='étape de repos'},
		["en"] = {plain = "plain stage", hilly="hilly stage", inter='intermediate stage', mount='mountain stage', time_prologue='time trial stage', time_team='team time trial stage', time_indiv='individual time trial stage', uphill='uphill time trial stage', rest='rest day'},
		["br"] = {plain = "tennad plaen", hilly="tennad digompez", inter='tennad damveneziek', mount='tennad meneziek', time_prologue='prolog', time_team='ABEU a-skipailhoù', time_indiv='ABEU', uphill='', rest='devezh diskuizh'},
		["ca"] = {plain = "etapa plana", hilly="etapa accidentada", inter='etapa de mitja muntanya', mount='etapa de muntanya', time_prologue='pròleg', time_team='contrarellotge per equips', time_indiv='contrarellotge individual', uphill='', rest='etapa de descans'},
		["cs"] = {plain = "rovinatá etapa", hilly="", inter='kopcovitá etapa', mount='horská etapa', time_prologue='prolog', time_team='týmová časovka', time_indiv='individuální časovka', uphill='', rest=''},
		["da"] = {plain = "flad etape", hilly="kuperet etape", inter='middel bjergetape', mount='bjergetape', time_prologue='prolog', time_team='holdtidskørsel', time_indiv='enkeltstart', uphill='bjergenkeltstart', rest='hviledag'},
		["de"] = {plain = "Flachetappe", hilly="Hügelige Etappe", inter='Mittelschwere Etappe', mount='Hochgebirgsetappe', time_prologue='Prolog', time_team='Teamzeitfahren', time_indiv='Einzelzeitfahren', uphill='Bergzeitfahren', rest='Ruhetag'},
		["eo"] = {plain = "ebena etapo", hilly="malebena etapo", inter='mezgranda montaro etapo', mount='montara etapo', time_prologue='prologo', time_team='teama kontraux-la-kronometro', time_indiv='individua kontraux-la-kronometro', uphill='malebena kontraux-la-kronometro', rest='ripoza etapo'},
		["es"] = {plain = "etapa llana", hilly="etapa escarpada", inter='etapa de media montaña', mount='etapa de montaña', time_prologue='prólogo', time_team='contrarreloj por equipos', time_indiv='contrarreloj individual', uphill='cronoescalada', rest='jornada de descanso'},
		["eu"] = {plain = "etapa laua", hilly="etapa gorabeheratsua", inter='bitarteko etapa', mount='mendiko etapa', time_prologue='aitzinetapa', time_team='taldekako erlojupekoa', time_indiv='banakako erlojupekoa', uphill='erlojupeko igoera', rest='atseden eguna'},
		["fi"] = {plain = "Tasamaaetappi", hilly="Mäkietappi", inter='Keskivaikea vuorietappi', mount='Vuorietappi', time_prologue='', time_team='Joukkueaika-ajo', time_indiv='Henkilökohtainen aika-ajo', uphill='mäkiaika-ajo', rest='välipäivä'},
		["fo"] = {plain = "Slætt", hilly="Slætt við brúgvasteinum", inter='Óslætt', mount='Fjallateinur', time_prologue='Forteinur', time_team='Liðsúkkling', time_indiv='Einkultstartur', uphill='', rest='Hvílidagur'},
		["hu"] = {plain = "sík szakasz", hilly="dombos szakasz", inter='közepes hegyi szakasz', mount='hegyi szakasz', time_prologue='prolog', time_team='csapat időfutam', time_indiv='egyéni időfutam', uphill='hegyi időfutam', rest=''},
		["ja"] = {plain = "平坦ステージ", hilly="丘陵ステージ", inter='中間ステージ', mount='山岳ステージ', time_prologue='タイムトライアルステージ', time_team='チームタイムトライアルステージ', time_indiv='個人タイムトライアルステージ', uphill='アップヒルタイムトライアルステージ', rest='休養日'},
		["lb"] = {plain = "Flaach Etapp", hilly="Hiwweleg Etapp", inter='Mëttelschwéier Etapp', mount='Biergetapp', time_prologue='Prolog', time_team='Contre-la-montre (Ekipp)', time_indiv='Contre-la-montre (Eenzel)', uphill='Biergcourse', rest='Roudag'},
		["lv"] = {plain = "līdzenuma posms", hilly="paugurains posms", inter='vidēju kalnu posms', mount='kalnu posms', time_prologue='individuālais brauciens', time_team='komandu brauciens', time_indiv='individuālais brauciens', uphill='individuālais brauciens kalnā', rest='atpūtas diena'},
		["mk"] = {plain = "рамна етапа", hilly="ридеста етапа", inter='среднопланинска етапа', mount='планинска етапа', time_prologue='пролог', time_team='екипен хронометар', time_indiv='индивидуален хронометар', uphill='', rest='ден за одмор'},
		["nl"] = {plain = "vlakke rit", hilly="heuvelrit", inter='heuvelrit', mount='bergrit', time_prologue='proloog', time_team='ploegentijdrit', time_indiv='individuele tijdrit', uphill='klimtijdrit', rest='rustdag'},
		["no"] = {plain = "flat etappe", hilly="kupert etappe", inter='middels klatreetappe', mount='klatreetappe', time_prologue='prolog', time_team='lagtempo', time_indiv='temporitt', uphill='klatretempoetappe', rest='hviledag'},
		["pl"] = {plain = "płaski", hilly="", inter='pagórkowaty', mount='górski', time_prologue='prologu', time_team='jazda drużynowa na czas', time_indiv='jazda indywidualna na czas', uphill='', rest=''},
		["pt"] = {plain = "etapa plana", hilly="etapa escarpada", inter='média montanha', mount='alta montanha', time_prologue='prólogo', time_team='contrarrelógio por equipes', time_indiv='contrarrelógio individual', uphill='cronoescalada', rest='jornada de descanso'},
		["ro"] = {plain = "etapă de plat", hilly="etapă valonată", inter='etapă intermediară', mount='etapă de munte', time_prologue='prolog', time_team='contratimp pe echipe', time_indiv='contratimp individual', uphill='', rest='zi de repaus'},
		["ru"] = {plain = "равнинный", hilly="холмистый", inter='среднегорный', mount='горный', time_prologue='пролог', time_team='командная разделка', time_indiv='индивидуальная разделка', uphill='горная разделка', rest='день отдыха'},
		["sv"] = {plain = "Flack etapp", hilly="", inter='Kuperat', mount='Bergsetapp', time_prologue='Prolog', time_team='Lagtempoetapp', time_indiv='Tempoetapp', uphill='', rest='Vilodag'},
	}
	local l10n = l10nDef[wiki]
	if not l10n then l10n = l10nDef["en"] end  -- default

	local border
	if noborder then border="" else border="|border|right" end
 
	if x=='plain stage' then return "[[File:Plainstage.svg"..border.."|20px|"..l10n.plain.."]]" end
	if x=='hilly stage' then return "[[File:Hillystage.svg"..border.."|20px|"..l10n.hilly.."]]" end
	if x=='intermediate stage' then return "[[File:Mediummountainstage.svg"..border.."|20px|"..l10n.inter.."]]" end
	if x=='mountain stage' then return "[[File:Mountainstage.svg"..border.."|20px|"..l10n.mount.."]]" end
	if x=='uphill time trial stage' then return "[[File:Mountain Time Trial Stage.svg"..border.."|20px|"..l10n.uphill.."]]" end
	if x=='rest day' then return "[[File:Stage rest day.svg"..border.."|20px|"..l10n.rest.."]]" end
	if x=='time trial stage' then
		if noborder then border="" else border="|right" end
		if typ==2348250 then return "[[File:Team Time Trial Stage.svg"..border.."|20px|"..l10n.time_team.."]]" end
		if typ==2266066 then return "[[File:Time Trial.svg"..border.."|20px|"..l10n.time_indiv.."]]" end
		if typ==485321  then return "[[File:Time Trial.svg"..border.."|20px|"..l10n.time_prologue.."]]" end
	end
end

local function typeofstagelogo(stageID, noborder)
	local sType 
	p = mw.wikibase.getBestStatements(stageID, 'P31') -- P31 is 'instance of'
	for _,t in pairs(p) do
		if t.mainsnak.snaktype == 'value' then
			local iOf = t.mainsnak.datavalue.value['numeric-id']
			if iOf == 20646667 then sType = typeofstage('plain stage', nil, noborder) break end
			if iOf == 20646670 then sType = typeofstage('hilly stage', nil,moborder) break end
			if iOf == 20680270 then sType = typeofstage('intermediate stage', nil,noborder) break end
			if iOf == 20646668 then sType = typeofstage('mountain stage',nil, noborder) break end
			if iOf == 485321 then sType = typeofstage('time trial stage', 485321, noborder) break end -- prologue
			if iOf == 2266066 then sType = typeofstage('time trial stage', 2266066, noborder) break end -- individual time trial
			if iOf == 2348250 then sType = typeofstage('time trial stage', 2348250, noborder) break end -- team time trial
			if iOf == 20679712 then sType = typeofstage('uphill time trial stage', nil, noborder) break end
		end
	end
	return sType or ''
end

--== III) basic functions
--[[ Get any value for a property which is not deprecated ]]
local function firstValue(QID, PID, field)
	if QID then
		local ss = wikibase.getAllStatements(QID, PID)
		for _, s in pairs(ss) do
			if s.rank ~= 'deprecated' and s.mainsnak.snaktype == 'value' then
				return field and s.mainsnak.datavalue.value[field] or s.mainsnak.datavalue.value
			end
		end
	else
		return nil
	end
end

--[[ Go from season of a team to the team ]]
local function getParentID(teamID)
	return firstValue(teamID, 'P361', 'id') -- P361 is 'part of'
		or firstValue(teamID, 'P5138', 'id') -- P5138 is 'season of club or team'
end

--[[ Get a label in any of the languages in the fallback list of language codes ]]
local function getLabelFallback(itemID, fallback)
	local label
	for _, lang in ipairs(fallback) do
		label = mw.wikibase.getLabelByLang(itemID, lang)
		if label then break end
	end
	return label
end

--[[ Get a sitelink from the local wiki or from the fallback list of language codes ]]
local function getSitelinkFallback(itemID, fallback)
	local link = mw.wikibase.getSitelink(itemID)
	if link then return link end
	for _, lang in ipairs(fallback) do
		link = mw.wikibase.getSitelink(itemID, lang .. 'wiki')
		if link then return link end
	end
	return nil
end

local function make_IllWD2_link(q, label)
	return mw.getCurrentFrame():expandTemplate{ title = 'Ill-WD2', args = {id= q ,target='en',label = label } }
end

--[[ Iterator to get all statements for an entity and property which are not deprecated and have a value]]
local function nextStatement(state, i)
	repeat
		i = i + 1
		local s = state[i]
		if s and s.rank ~= 'deprecated' and s.mainsnak.snaktype == 'value' then
			return i, s
		end
	until s == nil
end
local function statements(QID, PID)
	return nextStatement, wikibase.getAllStatements(QID, PID), 0
end

--[[ Iterator to get all qualifier values for a property for a statement]]
local function nextQualifier(state, i)
	repeat
		i = i + 1
		local q = state[i]
		if q and q.snaktype == 'value' then
			return i, q.datavalue
		end
	until q == nil
end
local function qualifiers(statement, PID)
	return nextQualifier, statement.qualifiers and statement.qualifiers[PID] or {}, 0
end

local function qualifieramount(element, property)
	local result
	for _, q in qualifiers(element, property) do
		result = tonumber(q.value.amount)
		break
	end
	return result
end

--== IV) Functions less basic called from other functions ==
--=== A) Time functions ===
--[[ Get a Wikidata statement for an entity and property valid at the given timevalue ]]
local function checktime(s,q, time)
	local start, startPrecision, END, endPrecision
	if q.P580 and q.P580[1] and q.P580[1].snaktype == 'value' then -- P580 is start time
		start = q.P580[1].datavalue.value.time
		startPrecision = q.P580[1].datavalue.value.precision
		if startPrecision == 9 then -- precision is years
			start = string.sub(start, 1, 5) -- Cut of everything after year
		elseif startPrecision == 10 then -- precision is months
			start = string.sub(start, 1, 8) -- Cut of everything after month
		end
	end
	if q.P582 and q.P582[1] and q.P582[1].snaktype == 'value' then -- P582 is end time
		END = q.P582[1].datavalue.value.time
		endPrecision = q.P582[1].datavalue.value.precision
	end
	if not start or start <= time then
		if not END then
			return s
		end
		if endPrecision == 9 then -- precision 9 is 'years'
			END = string.sub(END, 1, 6) .. '13' -- Set month to 13
		elseif endPrecision == 10 then -- precision 10 is 'months'
			END = string.sub(END, 1, 9) .. '32' -- Set day to 32
		end
		if END > time then
			return s
		end
	end
	return nil
end

local function getStatementForTime(ID, property, time)
	for _, s in statements(ID, property) do
		local start, startPrecision, END, endPrecision
		local q = s.qualifiers
		if q then
			if q.P580 and q.P580[1] and q.P580[1].snaktype == 'value' then -- P580 is start time
				start = q.P580[1].datavalue.value.time
				startPrecision = q.P580[1].datavalue.value.precision
				if startPrecision == 9 then -- precision is years
					start = string.sub(start, 1, 5) -- Cut of everything after year
				elseif startPrecision == 10 then -- precision is months
					start = string.sub(start, 1, 8) -- Cut of everything after month
				end
			end
			if q.P582 and q.P582[1] and q.P582[1].snaktype == 'value' then -- P582 is end time
				END = q.P582[1].datavalue.value.time
				endPrecision = q.P582[1].datavalue.value.precision
			end
		end
		if not start or start <= time then
			if not END then
				return s
			end
			if endPrecision == 9 then -- precision 9 is 'years'
				END = string.sub(END, 1, 6) .. '13' -- Set month to 13
			elseif endPrecision == 10 then -- precision 10 is 'months'
				END = string.sub(END, 1, 9) .. '32' -- Set day to 32
			end
			if END >= time then
				return s
			end
		end
	end
end

--[[ Get start time of race as a timevalue ('+2016-01-01T00:00:00Z') or nil ]]
local function gettimeOfRace (raceID)
	local timeOfRace
	local p580 = mw.wikibase.getBestStatements(raceID, "P580") -- P580 is start time
	if p580[1] and p580[1].mainsnak.snaktype == 'value' then
		timeOfRace = p580[1].mainsnak.datavalue.value.time
	else
		local p585 = mw.wikibase.getBestStatements(raceID, "P585") -- P585 is point in time
		if p585[1] and p585[1].mainsnak.snaktype == 'value' then
			timeOfRace = p585[1].mainsnak.datavalue.value.time
		else
			local link = getSitelinkFallback(raceID, {'en', 'fr', 'de'})
			if link then
				local year = string.match(link, '%d%d%d%d')
				if year then
					timeOfRace = year .. '-01-01T00:00:00Z'
				end
			end
		end
	end
	return timeOfRace, '> Wikidata is missing data about start time (P580) or point in time (P582)'
end

local function getStartEndTime(sTime, eTime, mode)
	-- Note: Add the formats to "formats" and use func_date
	local lang = contentLanguage
	local starttime, endtime
	--local format = formats[wiki] or formats['']
	if mode==nil then mode='long' end
	-- Timevalues is like "+2015-07-04T00:00:00Z"
	local y, m = string.match(sTime, "(%d+)-(%d+)-%d+")
	local y2, m2 = string.match(eTime, "(%d+)-(%d+)-%d+")
	
	if m=='00' then --manage the 30 November issue
		if  mode=='long' then
			starttime =lang:formatDate( "Y", sTime )
		else
			starttime ='-'
		end
	else
		if y ~= y2 then
			if mode=='long' then
				starttime = lang:formatDate( "j F Y", sTime )
			else
				starttime = lang:formatDate( "j M Y", sTime )
			end
		elseif m ~= m2 then
			if mode=='long' then
				starttime = lang:formatDate( "j F", sTime )
			else
				starttime = lang:formatDate( "j M", sTime )
			end
		else
			starttime = lang:formatDate( "j", sTime )
		end
	
		if wiki == "ar" then
			if y ~= y2 then starttime = lang:formatDate( "d F Y", sTime )
			elseif m ~= m2 then starttime = lang:formatDate( "d F", sTime )
			else starttime = lang:formatDate( "d ", sTime ) end
		elseif wiki == "br" then
			if y ~= y2 then starttime = lang:formatDate( "j", sTime ) .." a viz ".. lang:formatDate( "F Y", sTime )
			elseif m ~= m2 then starttime = lang:formatDate( "j", sTime ) .." a viz ".. lang:formatDate( "F", sTime )
			else starttime = lang:formatDate( "j", sTime ) .." "
			end
		elseif wiki == "ca" or wiki == "es" or wiki == "ast" then
			if y ~= y2 then
				starttime = lang:formatDate( "j", sTime ) .." de ".. lang:formatDate( "F", sTime ) .." de ".. lang:formatDate( "Y", sTime )
			elseif m ~= m2 then
				starttime = lang:formatDate( "j", sTime ) .." de ".. lang:formatDate( "F", sTime )
			else starttime = lang:formatDate( "j", sTime ) .." "
			end
		elseif wiki == "cs" then
			if y ~= y2 then starttime = lang:formatDate( "j. xg Y", sTime )
			elseif m ~= m2 then starttime = lang:formatDate( "j. xg", sTime )
			else starttime = lang:formatDate( "j", sTime )
			end
		elseif wiki == "de" or wiki == "da" or wiki == "fo" or wiki == "lb" or wiki == "no" then
			if y ~= y2 then starttime = lang:formatDate( "j. F Y", sTime )
			elseif m ~= m2 then starttime = lang:formatDate( "j. F", sTime )
			else starttime = lang:formatDate( "j.", sTime )
			end
		elseif wiki == "fi" then
			if y ~= y2 then starttime = lang:formatDate( 'j. F"ta" Y', sTime )
			elseif m ~= m2 then starttime = lang:formatDate( 'j. F"ta"', sTime )
			else starttime = lang:formatDate( "j.", sTime )
			end
		elseif wiki == "eo" then
			if y ~= y2 then starttime = lang:formatDate( "j", sTime ) .."-a de ".. lang:formatDate( "F Y", sTime )
			elseif m ~= m2 then starttime = lang:formatDate( "j", sTime ) .."-a de ".. lang:formatDate( "F", sTime )
			else starttime = lang:formatDate( "j", sTime ) .."-a "
			end
		elseif wiki == "eu" then
			if y ~= y2 then starttime = lang:formatDate( "Y", sTime ) ..".eko ".. lang:formatDate( "F", sTime ) .."k ".. lang:formatDate( "j", sTime )
			elseif m ~= m2 then starttime = lang:formatDate( "F", sTime ) .."k ".. lang:formatDate( "j", sTime )
			else starttime = lang:formatDate( "F", sTime ) .."k ".. lang:formatDate( "j", sTime )
			end
		elseif wiki == "hu" then
			starttime = lang:formatDate( "Y. F j.", sTime)
		elseif wiki == "ja" then
			if y ~= y2 then starttime = lang:formatDate( "Y年m月d日", sTime )
			elseif m ~= m2 then starttime = lang:formatDate( "Y年m月d日", sTime )
			else starttime = lang:formatDate( "Y年m月d日", sTime )
			end
		elseif wiki == "lv" then
			if m ~= m2 then starttime = lang:formatDate( "Y. \\g\\a\\d\\a j. F", sTime )
			else starttime = lang:formatDate( "Y. \\g\\a\\d\\a j.", sTime )
			end
		elseif wiki == "pl" then
			local date_pl = {"stycznia", "lutego", "marca", "kwietnia", "maja", "czerwca", "lipca", "sierpnia", "września", "października", "listopada", "grudnia"}
			if y ~= y2 then starttime = lang:formatDate( "j ", sTime ) .. date_pl[tonumber(lang:formatDate( "n", sTime ))] .. lang:formatDate( " Y", sTime )
			elseif m ~= m2 then starttime = lang:formatDate( "j ", sTime ) .. date_pl[tonumber(lang:formatDate( "n", sTime ))]
			else starttime = lang:formatDate( "j", sTime )
			end
		end
	end
	
	if m2=='00' then --manage the 30 November issue
		if  mode=='long' then
			endtime= lang:formatDate( "Y", eTime )
		else
			endtime= '-'
		end
	else

		if mode=='long' or y ~= y2 then
			endtime = lang:formatDate("j F Y", eTime)
		else
			endtime = lang:formatDate("j M", eTime)
		end
		if wiki == "ar" then
			if mode=='long' or y ~= y2 then endtime = lang:formatDate( "d F Y", eTime )
			elseif m ~= m2 then endtime = lang:formatDate( "d F Y", eTime )
			else endtime = lang:formatDate( "d F Y", eTime )
			end
		elseif wiki == "br" then endtime = lang:formatDate( "j", eTime ) .." a viz ".. lang:formatDate( "F Y", eTime )
		elseif wiki == "ca" or wiki == "es" or wiki == "ast" then
			if mode=='long' or y ~= y2 then
				endtime = lang:formatDate( "j", eTime ) .." de "..
				lang:formatDate( "F", eTime ) .." de ".. lang:formatDate( "Y", eTime )
			else
				endtime = lang:formatDate( "j", eTime ) .." de "..
				lang:formatDate( "F", eTime )
			end
		elseif wiki == "cs" then endtime = lang:formatDate( "j. xg Y", eTime )
		elseif wiki == "de" or wiki == "da" or wiki == "fi" or wiki == "fo" or wiki == "lb" or wiki == "no" then
			if mode=='long' or y ~= y2 then
				endtime = lang:formatDate( "j. F Y", eTime )
			else
				endtime = lang:formatDate( "j. M", eTime )
			end
		elseif wiki == "eo" then endtime = lang:formatDate( "j", eTime ) .."-a de ".. lang:formatDate( "F Y", eTime )
		elseif wiki == "eu" then endtime = lang:formatDate( "Y", eTime ) ..".eko ".. lang:formatDate( "F", eTime ) .."k "..
			lang:formatDate( "j", eTime )
		elseif wiki == "fi" then endtime = lang:formatDate('j F"ta" Y', eTime)
		elseif wiki == "hu" then
			if y ~= y2 then endtime = lang:formatDate( "Y. F j.", eTime )
			elseif m ~= m2 then endtime = lang:formatDate( "F j.", eTime )
			else endtime = lang:formatDate( "j.", eTime )
			end
			--endtime = lang:formatDate( "Y", eTime ) ..". ".. lang:formatDate( "F j", eTime ) .."."
		elseif wiki == "ja" then
			if y ~= y2 then endtime = lang:formatDate( "Y年m月d日", eTime )
			elseif m ~= m2 then endtime = lang:formatDate( "m月d日", eTime )
			else endtime = lang:formatDate( "d日", eTime )
			end
		elseif wiki == "lv" then
			if y ~= y2 then endtime = lang:formatDate( "Y. \\g\\a\\d\\a j. F", eTime )
			else endtime = lang:formatDate( "j. F", eTime )
			end
		elseif wiki == "pl" then
			local date_pl = {"stycznia", "lutego", "marca", "kwietnia", "maja", "czerwca", "lipca", "sierpnia",
				"września", "października", "listopada", "grudnia"}
			endtime = lang:formatDate( "j ", eTime ) .. date_pl[tonumber(lang:formatDate( "n", eTime ))] ..
			lang:formatDate( " Y", eTime )
		end
	end
	return starttime, endtime
end

local formats = data.formats 

local function func_date(date, mode)
	-- local date = '+2016-05-20'
	-- local mode = 'small'
	local format = formats[wiki] or formats['']
    local lang = contentLanguage

	--handle problems with lack of precision
	local daycorrect=true
	local monthcorrect=true
	if string.sub(date,10,11)=='00' then daycorrect=false end
	if string.sub(date,7,8)=='00' then monthcorrect=false end
	
	if daycorrect and monthcorrect then
		return contentLanguage:formatDate(format[mode], date)
	else
		if daycorrect or (monthcorrect==false and daycorrect==false) then --no month
			if mode=='long' then
				return string.sub(date,2,5) --only year, note: contentLanguage:formatDate("Y", date) returns the wrong year
			else --otherwise we don't know
				return '-'
			end
		else --month correct, but day incorrect
			if mode=='onlyday' then
				return '-'
			else
				local newdate=string.sub(date,1,9).."01"..string.sub(date,12)
				return string.sub(contentLanguage:formatDate(format[mode], newdate), 3) --cut the day
			end
		end
	end	
end

--[[ get the year for a race as a string, or an empty string]]
local function getYear(raceID)
	local year = firstValue(raceID, 'P580', 'time') or -- P580 is 'start time'
		firstValue(raceID, 'P585', 'time') -- P585 is 'point in time'
	if year then
		return string.sub(year, 2, 5)
	end
	return ''
end

function isdisqualified(p,q) --disqualification can use deprecated or P1534
	local cancelled=""
	local disqualified=false
	
	if p and p.rank=='deprecated' then
		cancelled='text-decoration:line-through;'
		disqualified=true
	else
		if q and q.P1534 and q.P1534[1].snaktype == 'value' then
			local tempdsq=q.P1534[1].datavalue.value.id
			if tempdsq=='Q1229261' then 
				cancelled='text-decoration:line-through;'
				disqualified=true
			end --disqualified
		end
	end
	return cancelled, disqualified
end

--=== B) Link functions ===
local function getOfficialName(teamID, timeOfRace,season) -- for team
	--return officialName, isLocal
	local slavicWikis = {mk = true, ru = true}
	local wikiisslavic = slavicWikis[wiki]

	local p1448 = getStatementForTime(teamID, 'P1448', timeOfRace) -- P1448 is official name
	if p1448 then
		if available_lang_priority and p1448.qualifiers and p1448.qualifiers.P1448 then
			local q = p1448.qualifiers.P1448
			local wantedLanguages = {}
			local best = 999
			local name
			for i, lang in ipairs(translations.lang_priority) do
				wantedLanguages[lang] = i
			end
			for _, l in pairs(q) do
				if l.snaktype == 'value' then
					local lang = l.datavalue.value.language
					if wantedLanguages[lang] and wantedLanguages[lang] < best then
						best = wantedLanguages[lang]
						name = l.datavalue.value.text
					end
				end
			end
			if name then return name, true end
		end
		lang=p1448.mainsnak.datavalue.value.language
		if not wikiisslavic and slavicWikis[lang]==nil then
			return p1448.mainsnak.datavalue.value.text, false --then prefer label
		end
	end
	local label=wikibase.getLabel(teamID)
	if season and season==true then
		if label then return string.sub(label,1,label:len()-5),true end -- 
	else
		return label, true -- No official name, try label
	end
end

local function revertfirstlast(name)
	local nametable = mw.text.split(name, ",")
	if nametable[2] then --there is a coma
		return nametable[2].." "..nametable[1]
	else
		return nametable[1]
	end
end

local function getRiderLink(riderID, startOfSeason) --startOfSeason optional
	--Priority order
	--#1 P1813, short name, in correct alphabet, correct time
	--#2 P1448, official name, in correct alphabet, correct time
	--#3 sitelink (so label from wikipedia) in correct language
	--#4 label from wikidata in correct language
	--#5 label from wikidata in another language
	local slavicWikis = {mk = true, ru = true}
	local sitelink = wikibase.getSitelink(riderID)
	local officialname,officialnametemp, language, name
	local wikiisslavic = slavicWikis[wiki]
	local correctlanguage=true
	local listOfProperty={'P1813','P1448'}

	for _, prop in ipairs(listOfProperty) do
		for _, p1813 in statements(riderID, prop) do
			if not officialname then
				language = p1813.mainsnak.datavalue.value.language
				officialnametemp = p1813.mainsnak.datavalue.value.text
				if wikiisslavic then
					if wiki==language then
						name=officialnametemp --only exact language
					end
				else
					if slavicWikis[language]==nil then
						name=officialnametemp --any language latin
					end
				end
				if startOfSeason~= nil then
					local q = p1813.qualifiers
					if q then
						local temp = checktime(name,q,startOfSeason)
						if temp then officialname = name end--if the time is correct than it is finished
					else
						officialname = name
					end
				end
			end
		end
	end

	if sitelink and officialname then --if there is an official name, then use it
		return "[[" .. sitelink .. "|" ..officialname.."]]", correctlanguage
	else
		if officialname then return officialname end
		if sitelink then
			if wiki == "de" then
				local label = wikibase.getLabelByLang(riderID, wiki)
				if label then
					local p27 = wikibase.getBestStatements(riderID, 'P27') -- P27 is country of citizenship
					if p27[1] and p27[1].mainsnak.snaktype == 'value' then
						local c = p27[1].mainsnak.datavalue.value['numeric-id']
						if c==159 or c==184 or c==212 or c==232 then -- Q159, Q184, Q212, Q232 is Russia, Belarus, Ukraine, Kazakhstan
							return "[[" .. sitelink .. "|" .. label .. "]]", correctlanguage
						end
					end
				end
			end
			if wiki == 'ru' then
				local label = revertfirstlast(mw.text.trim(string.gsub(sitelink, "%b()", "")))
				return "[[" .. sitelink .. "|" .. label.. "]]", correctlanguage
			else
				return "[[" .. sitelink .. "|" .. mw.text.trim(string.gsub(sitelink, "%b()", "")) .. "]]", correctlanguage
			end
		end

		-- No WP article. Display label, and make it a red link if no other article uses the title
		local link
		local label = wikibase.getLabelByLang(riderID, wiki)
		if label then
			if wiki == 'ar' then
				link = make_IllWD2_link(riderID)
			else
				if wiki=='ru' then
					label=revertfirstlast(label)
				end

				if black_list( label) then
					link = label
				else
					local title = mw.title.new(label)
					if title and title.exists then
						link = label
					else
						link = "[[" .. label.. "]]"
					end
				end
			end
			return link, correctlanguage
		end

		-- No label in the local language. Try other languages, but don't link.
		correctlanguage=false
		if wiki == 'ar' then
			link = make_IllWD2_link(riderID)
		else
			link = getLabelFallback(riderID, {'en', 'de', 'fr','es'})
			if link then
				link = string.gsub(link, "%b()", "")
			else
				link = "(label missing)"
			end
		end
		return link, correctlanguage
	end
end

--[[ Get the name of a country ]]
local function getCountryName(countryID)
	local name = ''
	if available_list then
		name = translations.list(countryID)
	end
	if name == '' then
		local label, lang = wikibase.getLabelWithLang(countryID)
		--[[ Uses standard language fallback. Should not return nil, nil, as all countries have English labels. ]]
		if lang == wikilang then
			name = label
		elseif lang then
			name = label .. ' (' .. lang .. ')'
		end
	end
	return name
end

--[[ Get sitelink with no wiki no formating ]]
local function getRawTeamLink(teamID)
	local sitelink
	local parentID = getParentID(teamID)
	if parentID then -- try parent team first
		sitelink = mw.wikibase.getSitelink(parentID)
	end
	if not sitelink then
		sitelink = mw.wikibase.getSitelink(teamID)
	end
	return sitelink
end

--[[ Get sitelink, categoryID and maybe country for a team.
	Returns sitelink, team category ID, countryID (only countryID if country arg is true ]]
local function getTeamLinkCat(teamID, timeOfRace, country, season)
	local name, sitelink, parentID, catID
	-- Find team category
	local teamCats = {
		Q6154783 = true, Q20638319 = true, Q382927 = true, Q1756006 = true, Q23726798 = true,
		Q20738667 = true, Q28492441 = true, Q20639848 = true, Q20639847 = true, Q20652655 = true,
		Q20653563 = true, Q20653564 = true, Q20653566 = true, Q2466826 = true, Q26849121 = true,
		Q78464255 = true, Q80425135=true, Q54660600=true, Q54555994=true, Q99658502=true, Q20653570=true
	}
	for _, p31 in statements(teamID, 'P31') do
		local natureID = p31.mainsnak.datavalue.value.id
		if teamCats[natureID] then
			catID = natureID
			break
		end
	end
	if not catID then
		parentID = getParentID(teamID)
		if parentID then
			local p31 = getStatementForTime(parentID, 'P31',timeOfRace)
			if p31 then catID = p31.mainsnak.datavalue.value.id end
		end
		catID = catID or 'Q53534649'
	end
	-- Find country if needed
	local countryID
	if country or catID == 'Q23726798' or catID == 'Q20738667' or catID == 'Q54660600' or catID == 'Q54555994' or catID == 'Q99658502' then
		countryID = firstValue(teamID, 'P1532', 'id') -- P17 is country for sport
		if countryID == nil then
			countryID = firstValue(teamID, 'P17', 'id') -- P17 is country
		end
	end
	if countryID and (catID == 'Q23726798' or catID == 'Q20738667' or catID == 'Q54660600' or catID == 'Q54555994' or catID == 'Q99658502') then
		-- It is a national cycling team
		name = getCountryName(countryID)
		if catID == 'Q20738667' then -- national cycling team U23
			local s
			if wiki == 'fr' then s = ' espoirs'
			elseif wiki == 'mk' then s = ' под 23 години'
			elseif wiki == 'ar' then s = ' تحت 23'
			elseif wiki == 'es' then s = ' sub-23'
			else s = ' U23'
			end
			name = name .. s
		end
		if catID == 'Q54555994' then -- national cycling team U19
			local s
			if wiki == 'fr' then s = ' juniors'
			elseif wiki == 'mk' then s = ' под 19 години'
			elseif wiki == 'ar' then s = ' تحت 19'
			elseif wiki == 'es' then s = ' sub-19'
			else s = ' U19'
			end
			name = name .. s
		end	
		if catID == 'Q99658502' then -- national cycling team "B"
			local s
			if wiki == 'fr' then s = ' "B"'
			elseif wiki == 'mk' then s = ' "B"'
			elseif wiki == 'ar' then s = ' "B"'
			elseif wiki == 'es' then s = ' "B"'
			else s = ' "B"'
			end
			name = name .. s
		end	
		
	if countryID and (catID == 'Q20653570') then -- trying to display the region that the team represents		
		countryID = firstValue(teamID, 'P1532', 'id') -- P17 is country for sport
		if countryID == nil then
			countryID = firstValue(teamID, 'P17', 'id') -- P17 is country
		end
	end		
		
				sitelink = getRawTeamLink(teamID)
	else
		-- It is not a national cycling team
		local isLocal
		if season and season == true then
			sitelink = wikibase.getSitelink(teamID)
			name, isLocal = getOfficialName(teamID, timeOfRace,true)
			if not sitelink then
				parentID = getParentID(teamID)
				if parentID then sitelink = wikibase.getSitelink(parentID) end
			end
		else
			parentID = getParentID(teamID)
			if parentID then -- try parent team first
				sitelink = wikibase.getSitelink(parentID)
				name, isLocal = getOfficialName(parentID, timeOfRace)
			end
			if not sitelink then
				sitelink = wikibase.getSitelink(teamID)
			end
		end

		if not name or (not isLocal and available_lang_priority) then
			local partName, partIsLocal = getOfficialName(teamID, timeOfRace)
			if partName and (not name or partIsLocal) then
				name = partName
			end
		end
	end
	if sitelink then
		if name then
			sitelink = '[[' .. sitelink .. '|' .. name .. ']]'
		else
			sitelink = '[[' .. sitelink .. ']]'
		end
	else
		if name then
			sitelink = name
		else
			sitelink = (parentID and wikibase.getLabel(parentID)) or
				wikibase.getLabel(teamID) or 'No name'
		end
	end
	return sitelink, catID, countryID
end

local function getTeamCodeCat(teamID, timeOfRace)
	-- Find team category
	local codeUCI
	local p1998 =getStatementForTime(teamID, 'P1998', timeOfRace)
	if p1998 then
		codeUCI = p1998.mainsnak.datavalue.value
	else
		local parentID = getParentID(teamID)
		if parentID then
			p1998 =getStatementForTime(parentID, 'P1998', timeOfRace)
			if p1998 then
				codeUCI = p1998.mainsnak.datavalue.value
			end
		end
	end
	return codeUCI
end

local function getReference(statement, outputLocal)
	local function formatRefDate(date, precision)
		if precision == 9 then -- Precision is year
			return string.sub(date, 2, 5)
		elseif precision == 10 then -- Precision is month
			return contentLanguage:formatDate("F Y", string.sub(date, 2, 8))
		elseif precision >= 11 then -- Precision is day (or less)
			return func_date(date, 'long')
		end
	end

	local ref = statement.references
	if not ref or not ref[1] then
		return nil
	end
	ref = ref[1].snaks
	if ref.P854 and ref.P854[1] and ref.P854[1].snaktype == 'value' then -- P854 is 'reference URL'
		local refURL = ref.P854[1].datavalue.value
		local refTitle = ''
		local refDate = ''
		local refRetrieved = ''
		local refLang = ''
		if ref.P1476 and ref.P1476[1] and ref.P1476[1].snaktype == 'value' then -- P1476 is 'title URL'
			refTitle = ref.P1476[1].datavalue.value.text
			local lang = ref.P1476[1].datavalue.value.language
			if lang ~= wikilang then
				refLang = '(' .. lang .. ')'
			end
		end
		if ref.P577 and ref.P577[1] and ref.P577[1].snaktype == 'value' then -- P577 is 'publication date'
			local value = ref.P577[1].datavalue.value
			refDate = formatRefDate(value.time, value.precision)
			if (wiki == 'ar') then refDate = '، ' .. refDate
			else refDate = ', ' .. refDate
			end
		end
		if ref.P813 and ref.P813[1] and ref.P813[1].snaktype == 'value' then -- P813 is 'retrieved'
			local value = ref.P813[1].datavalue.value
			refRetrieved = formatRefDate(value.time, value.precision)
			if wiki == "de" then
				refRetrieved = ", (abgerufen am " .. refRetrieved .. ')'
			elseif wiki == "ar" then
				refRetrieved = " تاريخ الوصول " .. refRetrieved .. '.'
			elseif wiki == "fr" then
				refRetrieved = " (consulté le " .. refRetrieved .. ')'
			elseif wiki == "da" then
				refRetrieved = " Hentet " .. refRetrieved .. '.'
			else
				refRetrieved = " Retrieved " .. refRetrieved .. '.'
			end
		end
		local domain = string.match(refURL, '//([^/]+)')
		if string.sub(domain, 1, 4) == 'www.' then
			domain = string.sub(domain, 5)
		end
		local refText
		if wiki == "fr" then
			-- fr: "(en) « Lloyd Mondory ... EPO », sur velonews.competitor.com (consulté le 30 april 2016), 30 octobre 2015."
			local sur = ', sur <span style="font-style:italic;"> ' .. domain .. '</span>'
			refText = refLang .. ' « ['.. refURL .. ' '.. refTitle .. '] »' .. sur .. refRetrieved .. refDate .. '.'
		elseif wiki == "de" then
			local In = ' In: <span style="font-style:italic;">' .. domain .. '</span>'
			refText = '<span style="font-style:italic;">['.. refURL.. ' '.. refTitle.. '.]</span> ' ..
				In .. refDate .. refRetrieved ..'.'
		else
			local at = ', <span style="font-style:italic;"> ' .. domain .. '</span>'
			refText = refLang .. ' [' .. refURL .. ' ' .. refTitle .. ']' .. at .. refDate .. '.' .. refRetrieved
		end
		if outputLocal==1 then
			return refText
		else
			return localframe:extensionTag('ref', refText, {name=refText})
		end
	end
end

local function getImage(QID)
	local p18 = wikibase.getBestStatements(QID, 'P18') -- P18 is 'image'
	local first
	for _, image in pairs(p18) do
		if image.mainsnak.snaktype == 'value' then
			if not first then
				first = image.mainsnak.datavalue.value
			end
			local q = image.qualifiers
			if q and q.P2096 then
				for _, caption in pairs(q.P2096) do -- P2096 is 'caption'
					if caption.snaktype == 'value' and caption.datavalue.value.language == wikilang then
						return image.mainsnak.datavalue.value, caption.datavalue.value.text
					end
				end
			end
		end
	end
	return first
end

--[[ Get link for race or competition]]
local function raceLink(QID)
	local sitelink = wikibase.getSitelink(QID)
	local instanceOf = firstValue(QID, 'P31', 'id') -- P31 is 'instance of'
	if instanceOf == 'Q1137352' then -- Q1137352 is 'French Road Cycling Cup'
		local label2 = wikibase.getLabel(instanceOf)
		if sitelink then
			if label2 then return '[[' .. sitelink .. '|' .. label2 .. ']]' end
			return '[[' .. sitelink .. ']]'
		end
		local sitelink2 = wikibase.getSitelink(instanceOf)
		if sitelink2 then return '[[' .. sitelink2 ..'|' .. string.gsub(sitelink2, " %b()", "") .. ']]' end
		if label2 then return label2 end
	end
	if sitelink then return "[[".. sitelink.. "]]" end
	return wikibase.getLabel(QID) or ''
end

local function getPlaceLink(placeID)
	local sitelink = wikibase.getSitelink(placeID)
	local name = ''
	if available_list then
		name = translations.list(placeID)
	end
	if sitelink then
		-- Delete " (...)" form e.g. "Unley (South Australia)"
		if name ~='' then
			return '[[' .. sitelink .. '|' .. name .. ']]'
		else
			return '[[' .. sitelink .. '|' .. string.gsub(sitelink, ' %b()', '') .. ']]'
			end
		end
	local label = wikibase.getLabel(placeID) or ''
	if wiki == 'ar' then
		return make_IllWD2_link( placeID,label)
			-- '[[' .. label.. ']]'
	end
	return contentLanguage:ucfirst(label)
end		


local function classLink(class)
	local link = wikibase.getSitelink('Q22348500') -- Q22348500 is 'cycling race class'
	local label = getLabelFallback(class, {wikilang, 'en', 'fr', 'de'})
	if label and link then
		link = '[[' .. link .. '|' .. label .. ']]'
	elseif link then
		link = '[[' .. link .. ']]'
	elseif label then
		link = label
	else
		link=''
	end
	if wiki == "ar" then-- right now Q22348500 has no link in "ar"
		link = make_IllWD2_link(class , "")
	end
	return link
end
--[[ Get local content to a infoboxe from template args ]]
local function getLocalContent(contents, args)

	for _, content in pairs(contents) do
		local name = content.name
		local nameNoShy = string.gsub(name, '&#173;', '')  -- filter soft hyphen out
		local name_plural = content.name_plural
		local name_pluralNoShy = name_plural and string.gsub(name_plural, '&#173;', '')  -- filter soft hyphen out
		if args[nameNoShy] and args[nameNoShy] ~= '' then
			if content.special then
				local newname, value = string.match(args[nameNoShy], '([^:]+):(.*)')
				if value and mw.text.trim(value) ~= '' then
					content.name = mw.text.trim(newname)
					content.content = mw.text.trim(value)
				end
			else
				content.content = mw.text.trim(args[nameNoShy])
			end
		elseif args[name_pluralNoShy] and args[name_pluralNoShy] ~= '' then
			content.name = content.name_plural
			content.content = mw.text.trim(args[name_pluralNoShy])
		end
	end
end

local function getTeam(riderID, timeOfRace, q)
	-- q: qualifiers of statement in race entity where the rider is the value
	local teamID, link
	if q and q.P54 and q.P54[1].snaktype == 'value' then -- P54 is member of sports team
		teamID = q.P54[1].datavalue.value.id
		link = getTeamLinkCat(teamID, timeOfRace)
	else
		local p54 = getStatementForTime(riderID, 'P54', timeOfRace)
		if p54 then
			teamID = p54.mainsnak.datavalue.value.id
			link = getTeamLinkCat(teamID, timeOfRace)
		end
	end
	return link, teamID
end

local function getTeamCode(riderID, timeOfRace, q)
	-- q: qualifiers of statement in race entity where the rider is the value
	local teamID, code
	if q and q.P54 and q.P54[1].snaktype == 'value' then -- P54 is member of sports team
		teamID = q.P54[1].datavalue.value.id
		code = getTeamCodeCat(teamID, timeOfRace)
	else
		local p54 = getStatementForTime(riderID, 'P54', timeOfRace)
		if p54 then
			teamID = p54.mainsnak.datavalue.value.id
			code= getTeamCodeCat(teamID, timeOfRace)
		end
	end
	return code
end

local function seasonToTeamID(teamID)
	if teamID then
		local parentID=getParentID(teamID)
		if parentID then--season was used
			return parentID
		else
			return teamID
		end
	else
		return nil
	end
end

local function wdLink(id)
	return "[[File:Wikidata-logo S.svg|12px|link=d:" .. id .. "]]"
end

local function WPlinkpure(Qnumber)
	local link=''
	local Sitelink = wikibase.getSitelink(Qnumber) -- link to WParticle
	local Label = getLabelFallback(Qnumber, {wikilang, 'en', 'fr', 'de'}) or ''

	if Sitelink ~= nil then link = "[[" .. Sitelink .. "|" .. mw.text.trim(string.gsub(Sitelink, "%b()", "")..' ') .. "]]"
	elseif wiki == 'ar' then
		link = make_IllWD2_link(Qnumber , Label)
	else link = mw.ustring.gsub(Label, "^(%a)", function (x) return mw.ustring.upper(x) end)
	end

	return link
end

--=== C) Function for the output ===
local function getcoutrybool (no_country_list)
	local country = true
	for _, value in pairs(no_country_list) do -- get data if country should be printed in this wiki
		if value == wiki then country = false end
	end
	return country
end

local function tableA(s)
	local error_message = ''
	if wiki == "ar" and s.item == "" or not s.item then return "" end
	if s.error_message == 1 then
		error_message = func_error_message( 1)
		error_message = mw.ustring.gsub(error_message, "<1>", s.property)
		error_message = mw.ustring.gsub(error_message, "<2>", mw.wikibase.label( s.item ))
		error_message = mw.ustring.gsub(error_message, "<3>", s.item)
		error_message = ' [[File:Exclam icon.svg|12px|'.. error_message .. ']]'
	end
	
	local table = mw.html.create('table')
		:addClass('sortable')
		:attr('cellpadding', '0')
		:attr('cellspacing', '0')
		:css('border' , '1px solid rgb(200,200,200)')
		:css('padding', '3px')
	
	local title =translate(s.header_function,s.header_1, s.title) 
	if s.header_1 == 19 and wiki == "ar" then title = title .. " " .. s.year end	
		
	local caption = table:tag('tr'):tag('th'):attr('colspan', tostring(#s.header_2 + 1)):cssText('padding:2px; text-align:center; background-color:#FFDF80; line-height: 1.8em;')
	caption:tag('span'):cssText('float:left; margin: 0 5px'):wikitext('[[File:Wikidata-logo S.svg|12px|link=d:'.. s.item.. '#'.. s.property..']] '.. error_message)
	caption:wikitext(title)

	local country=getcoutrybool (s.no_country)

	local header = table:tag('tr')
	for i,k in ipairs(s.header_2) do
		if i == s.country_column then
			if available_list and country == true then
				header:tag('th')
					:cssText('text-align:center;padding:2px 20px 2px 2px;white-space:nowrap')
					:wikitext(translate(s.header_function,k))
			end
		end
		if i ~= s.country_column then
			local column = header:tag('th')
					:cssText('text-align:center;padding:2px 20px 2px 2px;white-space:nowrap')
					:wikitext(translate(s.header_function,k))
			if s.data_sort_type[i] == 'unsortable' then
				column:addClass('unsortable')
			end
		end
	end

	return table
end

local function tableB(s) --for startlist
	local error_message = ''
	if wiki == "ar" and s.item == "" or not s.item then return "" end
	if s.error_message == 1 then
		error_message = func_error_message( 1)
		error_message = mw.ustring.gsub(error_message, "<1>", s.property)
		error_message = mw.ustring.gsub(error_message, "<2>", mw.wikibase.label( s.item ))
		error_message = mw.ustring.gsub(error_message, "<3>", s.item)
		error_message = ' [[File:Exclam icon.svg|12px|'.. error_message .. ']]'
	end
	
	local roll = true
	for _, value in pairs(s.no_roll_startlist) do -- get data if country should be printed in this wiki
		if value == wiki then roll = false end
	end

	local cssTable= "border: 1px solid rgb(200,200,200); margin: 0 0 0.5em 0;"..
				"background-color: rgb(255, 255, 255); padding: 5px; float: left;"..
				"clear: left; ; text-align: left; vertical-align: top; font-size: 85%; line-height: 1.8em;"
	local wdLink = '[[File:Wikidata-logo S.svg|12px|link=d:'.. s.item.. '#'.. s.property..']] '.. error_message
	
	if roll == true then
		local rollTable1 = mw.html.create('div'):addClass("NavFrame")
		:cssText('center = margin: 0 0.5em 0;clear:both; border: 1px solid rgb(200,200,200);' ..
		'cellpadding="4" cellspacing="0" style="width:100%; background-color: rgb(255, 255, 255);padding: 5px;'..
		'margin-bottom:1em; background-color:#FFDF80;')
		:attr('title','['..translate("startlist",14)..']/['..translate("startlist",15)..']')
		local tDiv= rollTable1:tag('div'):addClass("NavHead")
		:cssText('text-align:'.. textalign .." =;height:1.8em;background-color:#FFDF80; color:black;font-weight:bold;")
		tDiv:tag('span')
		
		local tSpan=tDiv:tag('span'):cssText('float:' .. floattable):wikitext(wdLink)
		tSpan:wikitext(title)
		tDiv:wikitext(translate("startlist",1))
		
		tDiv = rollTable1:tag('div'):addClass("NavContent"):cssText("margin:0; background:white; display:block; text-align:left;")
	
		local tTable= tDiv:tag('table'):cssText("border:1px solid rgb(200,200,200)")
		local tCell = tTable:tag('tr'):tag('td')
		local insideTable =tCell:tag('table'):attr('cellpadding','4')  -- cellspacing="0" style="width:100%;"  color: black;
		:cssText(cssTable)

		return rollTable1, insideTable
	else
		--otherwise problem of clear
		local tab = mw.html.create('table')
		tCell=tab:tag('td')
		
		local tTable =tCell:tag('table')
		:attr('cellpadding','4')
		:cssText(cssTable)
		tCell = tTable:tag('tr'):tag('th'):cssText("background-color:#FFDF80;"):attr('colspan','3'):attr('align','center')
		tCell:tag('span'):cssText('float:left'):wikitext(wdLink)
		tCell:wikitext(translate("startlist",1))
	    local tRow=tCell:tag('tr')

		return tab, tRow
	end
end

--=== D) Jersey, flag functions ===
--used from 2 functions
local flags = {
		Q16 = {'CAN', {'Flag of Canada.svg', '+1965-02-15'}},
		Q17 = {'JPN', {'Flag of Japan.svg', '+1999-08-13'},
			{'Flag of Japan (1870–1999).svg', '+1870-02-27', '+1999-08-12'}},
		Q20 = {'NOR', {'Flag of Norway.svg', '+1821-07-13'}},
		Q27 = {'IRL', {'Flag of Ireland.svg', '+1937-12-29'}},
		Q28 = {'HUN', {'Flag of Hungary.svg', '+1957-05-23'}},
		Q29 = {'ESP', {'Flag of Spain.svg', '+1981-12-06'},
			{'Flag of Spain (1977–1981).svg', '+1977-01-21', '+1981-12-06'},
			{'Flag of Spain (1945–1977).svg', '+1945-10-11', '+1977-01-21'},
			{'Flag of Spain (1938–1945).svg', '+1939', '+1945-10-11'},
			{'Flag of the Second Spanish Republic.svg', '+1931-04-14', '+1939'},
			{'Flag of Spain (1785–1873, 1875–1931).svg', '+1874', '+1931-04-13'}},
		Q30 = {'USA', {'Flag of the United States.svg', '+1960-07-04'}},
		Q31 = {'BEL', {'Flag of Belgium (civil).svg'}},
		Q32 = {'LUX', {'Flag of Luxembourg.svg'}},
		Q33 = {'FIN', {'Flag of Finland.svg', '+1918-05-29'}},
		Q34 = {'SWE', {'Flag of Sweden.svg'}},
		Q35 = {'DEN', {'Flag of Denmark.svg'}},
		Q36 = {'POL', {'Flag of Poland.svg'}},
		Q37 = {'LTU', {'Flag of Lithuania.svg', '+2004-09-01'},
			{'Flag of Lithuania (1988-2004).svg', '+1990-03-11', '+2004-09-01'}},
		Q38 = {'ITA', {'Flag of Italy.svg', '+1946-06-19'},
			{'Flag of Italy (1861–1946).svg', '+1861', '+1946-06-19'}},
		Q39 = {'SUI', {'Flag of Switzerland.svg', '+1889-12-12'},
			{'Flag of Switzerland.svg', '+1879-01-01'}},
		Q40 = {'AUT', {'Flag of Austria.svg', '+1945-05-01'},
			{'Flag of Austria.svg', '+1919-10-21', '+1938-03-13'}},
		Q41 = {'GRE', {'Flag of Greece.svg', '+1978'}},
		Q43 = {'TUR', {'Flag of Turkey.svg'}},
		Q45 = {'POR', {'Flag of Portugal.svg', '+1911-06-30'}},
		Q55 = {'NED', {'Flag of the Netherlands.svg', '+1806'}},
		Q77 = {'URU', {'Flag of Uruguay.svg'}},
		Q96 = {'MEX', {'Flag of Mexico.svg', '+1968-09-16'},
			{'Flag of Mexico (1934-1968).svg', '+1934', '+1968-09-16'}},
		Q114 = {'KEN', {'Flag of Kenya.svg'}},
		Q115 = {'ETH', {'Flag of Ethiopia.svg', '+1996-10-31'}},
		Q117 = {'GHA', {'Flag of Ghana.svg', '+1966-02-28'}},
		Q142 = {'FRA', {'Flag of France.svg', '+1794-05-20'}},
		Q145 = {'GBR', {'Flag of the United Kingdom.svg'}},
		Q148 = {'CHN', {"Flag of the People's Republic of China.svg", '+1985'}},
		Q155 = {'BRA', {'Flag of Brazil.svg', '+1992-05-11'},
			{'Flag of Brazil (1968–1992).svg', '+1968-05-28', '+1992-05-11'}},
		Q159 = {'RUS', {'Flag of Russia.svg', '+1993-12-11'},
			{'Flag of Russia (1991–1993).svg', '+1991-08-22', '+1993-12-11'},
			{'Flag of the Russian Soviet Federative Socialist Republic.svg', '+1954', '+1991-08-22'},
			{'Flag of the Russian Soviet Federative Socialist Republic (1937–1954).svg', '+1937', '+1954'}},
		Q183 = {'GER', {'Flag of Germany.svg', '+1949-05-23'},
			{'Flag of the German Reich (1935–1945).svg', '+1935-09-15', '+1945-05-23'},
			{'Flag of the German Reich (1933–1935).svg', '+1933-03-12', '+1935-09-15'},
			{'Flag of Germany (3-2 aspect ratio).svg', '+1919-04-11', '+1933-03-12'},
			{'Flag of the German Empire.svg', '+1871-04-16', '+1919-04-11'}},
		Q184 = {'BLR', {'Flag of Belarus.svg', '+2012-05-11'},
			{'Flag of Belarus (1995–2012).svg', '+1995-06-07', '+2012-05-11'},
			{'Flag of Belarus (1918, 1991–1995).svg', '+1991-09-19', '1995-06-07'}},
		Q189 = {'ISL', {'Flag of Iceland.svg', '+1944-06-17'}},
		Q191 = {'EST', {'Flag of Estonia.svg'}},
		Q211 = {'LAT', {'Flag of Latvia.svg'}},
		Q212 = {'UKR', {'Flag of Ukraine.svg', '+1992-01-28'}},
		Q213 = {'CZE', {'Flag of the Czech Republic.svg', '+1920-03-30'}},
		Q214 = {'SVK', {'Flag of Slovakia.svg'}},
		Q215 = {'SLO', {'Flag of Slovenia.svg'}},
		Q217 = {'MDA', {'Flag of Moldova.svg'}},
		Q218 = {'ROU', {'Flag of Romania.svg', '+1989-12-27'},
			{'Flag of Romania (1965-1989).svg', '+1989-12-27', '+1965'},
			{'Flag of Romania (1952-1965).svg', '+1952', '+1965'},
			{'Flag of Romania (1948-1952).svg', '+1948-01-08', '+1952'},
			{'Flag of Romania.svg', '12. april 1867-04-12', '+1948-01-08'}},
		Q219 = {'BUL', {'Flag of Bulgaria.svg', '+1990-11-22'},
			{'Flag of Bulgaria (1971 – 1990).svg', '+1971-05-18', '+1990-11-22'}},
		Q222 = {'ALB', {'Flag of Albania.svg', '+1992'}},
		Q224 = {'CRO', {'Flag of Croatia.svg', '+1990-12-21'},
			{'Flag of Croatia (white chequy).svg', '+1990-06-27', '+1990-12-21'}},
		Q227 = {'AZE', {'Flag of Azerbaijan.svg'}},
		Q228 = {'AND', {'Flag of Andorra.svg'}},
		Q229 = {'CYP', {'Flag of Cyprus.svg', '+2006-08-20'},
			{'Flag of Cyprus (1960-2006).svg', '+1960-08-16', '+2006-08-20'}},
		Q232 = {'KAZ', {'Flag of Kazakhstan.svg'}},
		Q235 = {'MON', {'Flag of Monaco.svg'}},
		Q238 = {'SMR', {'Flag of San Marino.svg'}},
		Q241 = {'CUB', {'Flag of Cuba.svg'}},
		Q252 = {'INA', {'Flag of Indonesia.svg'}},
		Q258 = {'RSA', {'Flag of South Africa.svg', '+1994-04-27'},
			{'Flag of South Africa (1928–1994).svg', '+1928-05-31', '+1994-04-27'}},
		Q262 = {'ALG', {'Flag of Algeria.svg'}},
		Q265 = {'UZB', {'Flag of Uzbekistan.svg'}},
		Q298 = {'CHI', {'Flag of Chile.svg'}},
		Q334 = {'SGP', {'Flag of Singapore.svg'}},
		Q347 = {'LIE', {'Flag of Liechtenstein.svg'}},
		Q398 = {'BRN', {'Flag of Bahrain.svg', '+2002-02-14'}},
		Q403 = {'SRB', {'Flag of Serbia.svg', '+2004-08-18'},
			{'Flag of Serbia (1992–2004).svg', '+1992-04-27', '+2004-08-17'}},
		Q408 = {'AUS', {'Flag of Australia.svg'}},
		Q414 = {'ARG', {'Flag of Argentina.svg'}},
		Q419 = {'PER', {'Flag of Peru.svg', '+1950'},
			{'Flag of Peru (1825-1950).svg', '+1825-02-25', '+1950'}},
		Q664 = {'NZL', {'Flag of New Zealand.svg'}},
		Q711 = {'MGL', {'Flag of Mongolia.svg'}},
		Q717 = {'VEN', {'Flag of Venezuela.svg', '+2006-03-12'},
			{'Flag of Venezuela (1930–2006).svg', '+1930','+2006-03-12'}},
		Q733 = {'PAR', {'Flag of Paraguay.svg', '+2013-07-15'},
			{'Flag of Paraguay (1990–2013).svg', '+1990', '+2013-07-14'}},
		Q736 = {'ECU', {'Flag of Ecuador.svg'}},
		Q739 = {'COL', {'Flag of Colombia.svg'}},
		Q750 = {'BOL', {'Flag of Bolivia.svg', '+1851-10-31'}},
		Q754 = {'TTO', {'Flag of Trinidad and Tobago.svg'}},
		Q774 = {'GUA', {'Flag of Guatemala.svg'}},
		Q778 = {'BAH', {'Flag of the Bahamas.svg'}, '+1973-07-10'},
		Q783 = {'HON', {'Flag of Honduras.svg'}, '+1949'},
		Q786 = {'DOM', {'Flag of the Dominican Republic.svg'}},
		Q794 = {'IRI', {'Flag of Iran.svg', '+1980-07-29'},
			{'Flag of Iran (1964–1980).svg', '+1964', '+1980-07-29'}},
		Q800 = {'CRC', {'Flag of Costa Rica (state).svg', '+1906-11-27'}},
		Q801 = {'ISR', {'Flag of Israel.svg'}},
		Q804 = {'PAN', {'Flag of Panama.svg'}},
		Q813 = {'KGZ', {'Flag of Kyrgyzstan.svg', '+1992-03-03'}},
		Q817 = {'KUW', {'Flag of Kuwait.svg', '+1961-09-07'}},
		Q833 = {'MAS', {'Flag of Malaysia.svg', '+1963-09-16'}},
		Q842 = {'OMA', {'Flag of Oman.svg', '+1995'}},
		Q846 = {'QAT', {'Flag of Qatar.svg'}},
		Q858 = {'SYR', {'Flag of Syria.svg', '+1980-03-29'}},
		Q865 = {'TPE', {'Flag of the Republic of China.svg', '+1928-12-17'}},
		Q869 = {'THA', {'Flag of Thailand.svg'}},
		Q878 = {'UAE', {'Flag of the United Arab Emirates.svg'}},
		Q881 = {'VIE', {'Flag of Vietnam.svg', '+1976-02-07'}},
		Q884 = {'KOR', {'Flag of South Korea.svg', '+1997-10'}},
		Q916 = {'ANG', {'Flag of Angola.svg', '+1975-11-11'}},
		Q921 = {'BRU', {'Flag of Brunei.svg', '+1959-09-29'}},
		Q928 = {'PHI', {'Flag of the Philippines.svg', '+1998'}},
		Q948 = {'TUN', {'Flag of Tunisia.svg', '+1999-07-03'}},
		Q954 = {'ZIM', {'Flag of Zimbabwe.svg', '+1980-04-18'}},
		Q965 = {'BUR', {'Flag of Burkina Faso.svg'}},
		Q983 = {'GEQ', {'Flag of Equatorial Guinea.svg', '+1979-08-21'},
			{'Flag of Equatorial Guinea (1973–1979).svg', '+1973', '+1979-08-21'},
			{'Flag of Equatorial Guinea (without coat of arms).svg', '+1968-10-12', '+1973'}},
		Q986 = {'ERI', {'Flag of Eritrea.svg'}},
		Q1000 = {'GAB', {'Flag of Gabon.svg', '+1960-08-09'}},
		Q1007 = {'GBS', {'Flag of Guinea-Bissau.svg', '+1973-09-24'}},
		Q1008 = {'CIV', {"Flag of Côte d'Ivoire.svg"}},
		Q1009 = {'CMR', {'Flag of Cameroon.svg'}},
		Q1027 = {'MRI', {'Flag of Mauritius.svg', '+1968-03-13'}},
		Q1028 = {'MAR', {'Flag of Morocco.svg'}},
		Q1030 = {'NAM', {'Flag of Namibia.svg', '+1990-03-21'}},
		Q1036 = {'UGA', {'Flag of Uganda.svg', '+1962-10-09'}},
		Q1037 = {'RWA', {'Flag of Rwanda.svg', '+2001-10-25'},
			{'Flag of Rwanda (1962–2001).svg', '+1962', '+2001-10-25'}},
		Q9676 = {'IMN', {'Flag of the Isle of Man.svg'}},
		Q15180 = {'URS', {'Flag of the Soviet Union.svg', '+1980-08-15', '+1991-12-25'},
			{'Flag of the Soviet Union (1955–1980).svg', '+1955-08-19', '+1980-08-14'},
			{'Flag of the Soviet Union (1924–1955).svg', '+1923-11-13', '+1955-08-18'}},
		Q16957 = {'GDR', {'Flag of East Germany.svg', '+1959-10-01'},
			{'Flag of Germany.svg', '+1949-10-07', '+1959-10-01'}}, --German Democratic Republic
		Q8646 = {'HKG', {'Flag of Hong Kong.svg'}},
		Q25228 = {'AIA', {'Flag of Anguilla.svg'}},
		Q29999 = {'NED', {'Flag of the Netherlands.svg', '+1690'}}, --Kingdom of the Netherlands
		Q33946 = {'TCH', {'Flag of the Czech Republic.svg', '+1920'}}, -- Czechoslovakia (1918–1992)
		Q36704 = {'YUG', {'Flag of Yugoslavia (1992–2003).svg', '+1992-04-27', '+2003-02-04'}, --Yugoslavia
			{'Flag of Yugoslavia (1943–1992).svg', '+1946', '+1992-04-27'}},
		Q41304 = {'GER', {'Flag of Germany (3-2 aspect ratio).svg', '+1918-11-09'}}, -- Weimar Republic
		Q83286 = {'YUG', {'Flag of Yugoslavia (1943–1992).svg'}}, --Socialist Federal Republic of Yugoslavia
		Q172579 = {'ITA', {'Flag of Italy (1861–1946).svg'}}, --Kingdom of Italy (1861-1946)
		Q216923 = {'TPE', {'Flag of Chinese Taipei for Olympic games.svg'}}, -- Chinese Taipei
		Q268970 = {'AUT', {'Flag of Austria.svg', '+1918-11-12', '+1919-09-10'}}, -- German-Austria (1918-1919)
		Q713750 = {'FRG', {'Flag of Germany.svg'}}, --West Germany
		Q853348 = {'TCH', {'Flag of the Czech Republic.svg'}, '+1960-07-11', '+1990-03-29'}, -- Czechoslovak Socialist Republic (1960-1990)
		Q2415901 = {'GER', {'Merchant flag of Germany (1946–1949).svg', '+1945-05-09', '+1949-05-23'}}, -- Allied-occupied Germany
		Q13474305 = {'ESP', {'Flag of Spain (1945–1977).svg', '+1945-10-11', '+1977-01-21'}, -- Francoist Spain (1935-1976)
			{'Flag of Spain (1938–1945).svg', '+1939', '+1945-10-11'},
			{'Flag of the Second Spanish Republic.svg', '+1931-04-14', '+1939'}},
	}

local function flag(countryID, date)
	local trackingCategory = ''
	--[[ If you uncomment the line under this comment, all pages with look-up misses in
	the flag table will be placed in a tracking category. You can use this to find more flags
	to add to the table. ]]
	-- trackingCategory = '[[Category:Missing flag in Module:Cycling race]]'

	
	local entry = flags[countryID]
	local IOC
	local file
	if entry then
		for i, v in ipairs(entry) do
			if i == 1 then
				IOC = v
			else
				if not date then
					file = v[1]
					break
				else
					local from = v[2]
					local to = v[3]
					if (not from or from <= date) and (not to or to > date) then
						file = v[1]
						break
					end
				end
			end
		end
	end
	local flagpxSize = '20px'
	if countryID == 'Q39' then flagpxSize = '16px'end -- Small size for an square flag as Switzerland
	if file then
		return '[[File:' .. file .. '|border|' .. flagpxSize ..'|' .. IOC .. ']]'
	elseif not date then
		local p41 = mw.wikibase.getBestStatements(countryID, "P41") -- P41 is flag image
		if p41[1] and p41[1].mainsnak.snaktype == 'value' then
			return '[[File:' .. p41[1].mainsnak.datavalue.value .. '|border|' .. flagpxSize ..'|(Wikidata:' .. countryID .. ')]]' .. trackingCategory
		end
	else
		-- Search flag for specific date
		local p41 = getStatementForTime(countryID, "P41", date) -- P41 is flag image
		if p41 then
			return '[[File:' .. p41.mainsnak.datavalue.value .. '|border|' .. flagpxSize ..'|(Wikidata:' .. countryID .. ')]]' .. trackingCategory
		end
	end
	return trackingCategory
end

local function ucicodeCountry(countryID)
    local ucicode, countryName 
    local blacklist={Q736=true}
	if countryID then
		--get UCI code
		if flags[countryID] then
			ucicode=flags[countryID][1]
		end
		--get link, assumed for a country the label is equal to the link, where not correct in the blacklist
		--if the black list becomes too long, we could create a second list for the sitelinks
		if available_list then
			if type(translations.list) == "function" then
				countryName = translations.list(countryID)
			end
		end
		if countryName == nil or countryName=='' or blacklist[countryID] then
			countryName = mw.wikibase.getSitelink(countryID)
		end
		if ucicode and countryName then
			return ' <small>([['..countryName..'|'..ucicode..']])</small> '
		else
			return ''
		end
	else
		return ''
	end
end

local function jersey_infobox( winner_classification, item, timeOfRace)
	local jersey, jersey_name = '', ''
	local jerseyWPID = ''

	-- 1. Item of race, e.g. Tour de France = 'Q33881'
	-- 2. type of winner, names are the ones in variable t_s
	-- 3. and 4. start and end time. '+2500' means year 2500. Always beginning with a '+'
	-- 5. item of the jersey
	-- 6. item of the Wikipedia article of that jersey

	local data = {
		{'Q33881', 'montagne', '+1975', '+2500', 'Q25265958', 'Q927157'}, -- Tour de France
		{'Q33881', 'leader', '+1919', '+2500', 'Q24257871', 'Q738903'},
		{'Q33881', 'points', '+1953', '+1967', 'Q24645209', 'Q175399'}, -- Jersey green.svg
		{'Q33881', 'points', '+1968', '+1968', 'Q26919974', 'Q175399'}, -- Jersey red.svg
		{'Q33881', 'points', '+1969', '+2500', 'Q24645209', 'Q175399'}, -- Jersey green.svg
		{'Q33881', 'jeune', '+1975', '+2500', 'Q24645383', 'Q2254180'}, -- Jersey white.svg
		{'Q33881', 'winner_fighting', '+2003', '+2500', 'Q27644113', 'Q2094179'}, -- Jersey red number.svg
		{'Q33881', 'winner_fighting2', '+2003', '+2500', 'Q27644113', 'Q2094179'}, -- Jersey red number.svg
		{'Q33881', 'equipe', '+2006', '+2500', 'Q27644112', 'Q1436680'}, -- Jersey yellow number.svg

		{'Q33861', 'leader', '+1931', '+2500', 'Q24257763', 'Q1164275'}, -- Giro d'Italia, Jersey pink.svg
		{'Q33861', 'points', '+1967', '+1968', 'Q26919974', 'Q641083'}, -- Jersey red.svg
		{'Q33861', 'points', '+1969', '+2009', 'Q26945272', 'Q641083'}, -- Jersey violet.svg
		{'Q33861', 'points', '+2010', '+2016', 'Q26919974', 'Q641083'}, -- Jersey red.svg
		{'Q33861', 'points', '+2017', '+2500', 'Q26945272', 'Q641083'}, -- Jersey violet.svg
		{'Q33861', 'montagne', '+1974', '+2011', 'Q24645209', 'Q641060'}, -- Jersey green.svg
		{'Q33861', 'montagne', '+2012', '+2500', 'Q24687409', 'Q641060'}, -- Jersey blue.svg
		{'Q33861', 'jeune', '+1976', '+2500', 'Q24645383', 'Q641662'}, -- Jersey white.svg

		{'Q33937', 'leader', '+1935', '+1936', 'Q24258056', 'Q3278226'}, -- Vuelta a España, Jersey orange.svg
		{'Q33937', 'leader', '+1941', '+1941', 'Q26696171', 'Q640430'}, -- Jersey white.svg
		{'Q33937', 'leader', '+1942', '+1942', 'Q24258056', 'Q3278226'}, -- Jersey orange.svg
		{'Q33937', 'leader', '+1945', '+1945', 'Q24257872', 'Q2534046'}, -- Jersey red.svg
		{'Q33937', 'leader', '+1946', '+1950', 'Q26696171', 'Q640430'}, -- Jersey white.svg
		{'Q33937', 'leader', '+1955', '+1976', 'Q24257871', 'Q738903'}, -- Jersey yellow.svg
		{'Q33937', 'leader', '+1977', '+1977', 'Q24258056', 'Q3278226'}, -- Jersey orange.svg
		{'Q33937', 'leader', '+1978', '+1998', 'Q24257871', 'Q738903'}, -- Jersey yellow.svg
		{'Q33937', 'leader', '+1999', '+2009', 'Q24257991', 'Q27665179'}, -- Jersey gold.svg
		{'Q33937', 'leader', '+2010', '+2500', 'Q24257872', 'Q2534046'}, -- Jersey red.svg
		{'Q33937', 'points', '+1945', '+1986', 'Q24687409', 'Q2746711'}, -- Jersey blue.svg
		{'Q33937', 'points', '+1987', '+1989', 'Q24645209', 'Q11638007'}, -- Jersey green.svg
		{'Q33937', 'points', '+1990', '+2009', 'Q24687409', 'Q2746711'}, -- Jersey blue.svg
		{'Q33937', 'points', '+2010', '+2500', 'Q24645209', 'Q11638007'}, -- Jersey green.svg
		{'Q33937', 'montagne', '+1935', '+1985', 'Q27670182', 'Q11638007'}, -- Jersey green.svg
		{'Q33937', 'montagne', '+1986', '+1986', 'Q27670174', 'Q3278226'}, -- Jersey orange.svg
		{'Q33937', 'montagne', '+1987', '+1987', 'Q27670178', 'Q2534046'}, -- Jersey red.svg
		{'Q33937', 'montagne', '+1988', '+1989', 'Q27670105', 'Q27670115'}, -- Jersey blackdots.png
		{'Q33937', 'montagne', '+1990', '+2005', 'Q27670182', 'Q11638007'}, -- Jersey green.svg
		{'Q33937', 'montagne', '+2006', '+2008', 'Q27670174', 'Q3278226'}, -- Jersey orange.svg
		{'Q33937', 'montagne', '+2009', '+2009', 'Q27670126', 'Q27670163'}, -- Jersey granate.svg
		{'Q33937', 'montagne', '+2010', '+2500', 'Q25265959', 'Q27670167'}, -- Jersey bluedots.svg
		{'Q33937', 'jeune', '+2019', '+2500', 'Q24645383', 'Q60233927'}, -- Jersey white.svg

		{'Q2091354', 'leader', '+2011', '+2500', 'Q24257871'}, -- Tour of Norway, Jersey yellow.svg
		{'Q2091354', 'sprints', '+2011', '+2011', 'Q26806427'}, -- Jersey green.svg
		{'Q2091354', 'points', '+2012', '+2017', 'Q24645209'}, -- Jersey green.svg
		{'Q2091354', 'points', '+2018', '+2018', 'Q28820618'}, -- MaillotCyan.PNG
		{'Q2091354', 'points', '+2019', '+2500', 'Q47945989'}, -- Jersey dark blue.svg
		{'Q2091354', 'montagne', '+2011', '+2015', 'Q25265958'}, -- Jersey polkadot.svg
		{'Q2091354', 'montagne', '+2016', '+2017', 'Q27670174'}, -- Jersey orange.svg
		{'Q2091354', 'montagne', '+2018', '+2500', 'Q25265958'}, -- Jersey polkadot.svg
		{'Q2091354', 'jeune', '+2011', '+2500', 'Q24645383'}, -- Jersey white.svg
		{'Q2091354', 'winner_fighting', '+2017', '+2017', 'Q29957114'}, -- MaillotCyan.PNG
		{'Q128713', 'leader', '+2013', '+2017', 'Q24257871'}, -- Tour des Fjords, Jersey yellow.svg
		{'Q128713', 'leader', '+2018', '+2018', 'Q29594434'}, -- MaillotCyan.PNG
		{'Q128713', 'points', '+2013', '+2014', 'Q24645209'}, -- Jersey green.svg
		{'Q128713', 'points', '+2015', '+2017', 'Q24687409'}, -- Jersey blue.svg
		{'Q128713', 'points', '+2018', '+2018', 'Q25265938'}, -- Jersey violet.svg
		{'Q128713', 'montagne', '+2013', '+2018', 'Q25265958'}, -- Jersey polkadot.svg
		{'Q128713', 'jeune', '+2013', '+2018', 'Q24645383'}, -- Jersey white.svg
		{'Q128713', 'winner_fighting', '+2015', '+2015', 'Q30035038'}, -- Jersey green.svg
		{'Q128713', 'winner_fighting', '+2016', '+2017', 'Q30035039'}, -- Jersey orange.svg
		{'Q128961', 'leader', '+2013', '+2500', 'Q24687408'}, -- Arctic Race of Norway, Jersey blue.svg
		{'Q128961', 'points', '+2013', '+2500', 'Q24645209'}, -- Jersey green.svg
		{'Q128961', 'montagne', '+2013', '+2014', 'Q27670178'}, -- Jersey red.svg
		{'Q128961', 'montagne', '+2015', '+2500', 'Q27670174'}, -- Jersey orange.svg
		{'Q128961', 'jeune', '+2013', '+2500', 'Q24645383'}, -- Jersey white.svg
		{'Q128961', 'winner_fighting', '+2014', '+2500', 'Q27644113'}, -- Jersey red number.svg
		{'Q17619325', 'leader', '+2014', '+2014', 'Q24257871'}, -- Ladies Tour of Norway, Jersey yellow.svg
		{'Q17619325', 'leader', '+2015', '+2016', 'Q26945272'}, -- Jersey violet.svg
		{'Q17619325', 'leader', '+2017', '+2500', 'Q24257871'}, -- Jersey yellow.svg
		{'Q17619325', 'points', '+2014', '+2500', 'Q24645209'}, -- Jersey green.svg
		{'Q17619325', 'montagne', '+2014', '+2500', 'Q25265958'}, -- Jersey polkadot.svg
		{'Q17619325', 'jeune', '+2014', '+2500', 'Q24645383'}, -- Jersey white.svg
		{'Q17619325', 'winner_fighting', '+2016', '+2500', 'Q30035039'}, -- Jersey orange.svg
	}
	--timeOfRace = '+1968-07-01T00:00:00Z'
	timeOfRace = string.match(timeOfRace, "+%d%d%d%d") or ''
	for _, v in pairs(item) do
		for _, value in pairs(data) do
			if v == value[1] then
				if winner_classification == value[2] then
					if (timeOfRace >= value[3]) and (timeOfRace <= value[4]) then
						jersey = value[5]
						jerseyWPID = value[6]
					end
				end
			end
		end
	end

	-- local starttime, endtime = '', '+2500'
	if jersey ~= '' then --and (timeOfRace > starttime) and (timeOfRace < endtime) then
		local entity_jersey = mw.wikibase.getEntity(jersey)
			jersey = entity_jersey.claims['P18'][1].mainsnak.datavalue.value
			jersey_name = entity_jersey:getLabel(wikilang) or ''
		if jerseyWPID ~= '' then
			local entity = mw.wikibase.getEntity( jerseyWPID )
			local Sitelink = entity:getSitelink(wiki..'wiki') -- link to WParticle
			if Sitelink ~= nil then jerseyWPID = wiki..':'..Sitelink else jerseyWPID = '' end
		end
		return jersey, jersey_name, jerseyWPID
	else return '', '', ''
	end
end

local function jersey(h)
	local jersey_string = ' '
	local jerseys = {
	['Q24257871'] = {file = 'Jersey yellow.svg',
		name_ar = 'قميص أصفر لمتصدر الترتيب العام',
		name_fr = 'maillot jaune de leader du classement général',
		name_es = 'maillot amarillo de líder de la clasificación general',
		name_ru = 'жёлтая майка лидера генеральной классификации'
		},
	['Q24645209'] = {file = 'Jersey green.svg',
		name_ar = 'قميص أخضر لمتصدر ترتيب النقاط',
		name_fr = 'maillot vert de leader du classement par points',
		name_es = 'maillot verde de líder de la clasificación por puntos',
		name_ca = 'mallot verd del líder de la classificació per punts',
		name_ru = 'зелёная майка лидера очковой классификации'
		},
	['Q24645383'] = {file = 'Jersey white.svg',
		name_ar = 'قميص أبيض لمتصدر ترتيب الشباب',
		name_fr = 'maillot blanc de leader du classement du meilleur jeune',
		name_es = 'maillot blanco de líder de la clasificación de los jóvenes',
		name_ru = 'белая майка лидера молодёжной классификации',
		name_de = 'weißes Trikot des Führenden der Nachwuchswertung'
		},
	}

	if type(h) == 'table' and h[1] then
		for _, v in ipairs(h) do
			local jersey_name
			if jerseys[v] then
				jersey_string = jersey_string .. '[[File:' .. jerseys[v].file .. '|20px'
				jersey_name = jerseys[v]['name_' .. wiki] or mw.wikibase.getLabel(v) or jerseys[v]['name_fr']
				if jersey_name then
					jersey_string = jersey_string .. '|' .. jersey_name
				end
				jersey_string = jersey_string .. ']]'
			else
				local p18 = mw.wikibase.getBestStatements(v, 'P18')
				if p18[1] and p18[1].mainsnak.snaktype == 'value' then
					jersey_string = jersey_string .. '[[File:' .. p18[1].mainsnak.datavalue.value .. '|20px'
					jersey_name = getLabelFallback(v, {wikilang, 'en', 'fr'})
					if jersey_name then
						jersey_string = jersey_string .. '|' .. jersey_name
					end
					jersey_string = jersey_string .. ']]'
				end
			end
		end
	end
	return jersey_string
end -- function end

--=== E) Other (winner, getkm) ===
local function isHuman(riderId)
	local isHuman = false
	if riderId then
		local p31 = wikibase.getBestStatements(riderId, 'P31')
		for _, iOf in pairs (p31) do
			if iOf.mainsnak.snaktype == 'value' and iOf.mainsnak.datavalue.value['numeric-id'] == 5 then
				isHuman = true
				break
			end
		end
	end
	return isHuman
end

local function isCountry(riderId)
	local isCountry = false
	if riderId then
		local p31 = wikibase.getBestStatements(riderId, 'P31')
		for _, iOf in pairs (p31) do
			-- exception Hong-Kong and Taiwan
			if iOf.mainsnak.snaktype == 'value' and (iOf.mainsnak.datavalue.value['numeric-id'] == 6256 or iOf.mainsnak.datavalue.value['numeric-id'] ==15634554 or iOf.mainsnak.datavalue.value['numeric-id'] ==779415) then
				isCountry = true
				break
			end
		end
	end
	return isCountry
end

local function subwinner(riderId, timeOfRace, q)
	local outputtable={}
	local riderTeam, riderLink, countryID

	if riderId then
		if isHuman(riderId) then
			riderLink = getRiderLink(riderId, timeOfRace)
			local p27 = getStatementForTime(riderId, 'P27', timeOfRace) --P27 is country of citizenship
			if p27 then
				countryID = p27.mainsnak.datavalue.value.id
			end
			if countryID then
				riderLink = flag(countryID, timeOfRace) .. ' ' .. riderLink
			end
			riderTeam = getTeam(riderId, timeOfRace, q) or ''
		else
			local _
			riderLink, _, countryID = getTeamLinkCat(riderId, timeOfRace, true)
			if countryID then
				riderLink = flag(countryID, timeOfRace) .. ' ' .. riderLink
			end
		end
	end
	return riderLink, riderTeam
end

local function winner(raceID, winners, timeOfRace, country, WDlink_on, team, ref)
	local p1346 = wikibase.getAllStatements(raceID, 'P1346') -- P1346 is 'winner'
	for _, winner in pairs(p1346) do
		local wID = winner.mainsnak.snaktype == 'value' and winner.mainsnak.datavalue.value.id
		local wOf, wCause, wCriterion, riderLink
		local q = winner.qualifiers
		if q then
			local _, disqualified =isdisqualified(winner,q)
			
			if q.P642 and q.P642[1].snaktype == 'value' then
				for _, q642 in pairs(q.P642) do
					wOf = q642.datavalue.value.id -- P642 is 'of'
					if not wOf then
						-- Try P1346 (winner) instead
						-- Assume Q20882667 ('overall winner general classification') if neither are found
						wOf = q.P1346 and q.P1346[1].snaktype == 'value' and q.P1346[1].datavalue.value.id or 'Q20882667'
					end
					wCause = q.P828 and q.P828[1].snaktype == 'value' and q.P828[1].datavalue.value.id
						-- P828 is 'has cause'
					wCriterion = q.P1013 and q.P1013[1].snaktype == 'value' and q.P1013[1].datavalue.value.id
						-- P1013 is 'criterion used'

					if winners[wOf] then
						if wID then
							local reference = ref and getReference(winner)
							local _, countryID
							if isHuman(wID) then
								riderLink = getRiderLink(wID, timeOfRace)
								if reference then
									riderLink = riderLink .. reference
								end
								if team then
									local riderTeam = getTeam(wID, timeOfRace, q)
									if riderTeam then
										riderLink = riderLink .. ' (' .. riderTeam .. ')'
									end
								end
							elseif isCountry(wID) then
								riderLink = flag(wID, timeOfRace).." "..getCountryName(wID) 
								if reference then
									riderLink = riderLink .. reference
								end
								country=true	
							else --team
								local _
								riderLink, _, countryID = getTeamLinkCat(wID, timeOfRace, country, true)
								if reference then
									riderLink = riderLink .. reference
								end
							end
							if not country then
								if not countryID then
									if isHuman(wID) then
										local p27 = getStatementForTime(wID, 'P27', timeOfRace) --P27 is country of citizenship
										if p27 then
											countryID = p27.mainsnak.datavalue.value.id
										end
									else
										local p17 = getStatementForTime(wID, 'P17', timeOfRace) --P27 is country of citizenship
										if p17 then
											countryID = p17.mainsnak.datavalue.value.id
										end
									end
								end
								if countryID then
									riderLink = flag(countryID, timeOfRace) .. ' ' .. riderLink
								end
							end
							if WDlink_on then
								riderLink = riderLink .. ' ' .. wdLink(wID)
							end
						else
							riderLink = wCriterion and contentLanguage:ucfirst(wikibase.getLabel(wCriterion) or '') or ''
							if wCause then
								local cause = wikibase.getLabel(wCause)
								if cause then
									riderLink = riderLink .. ' (' .. cause .. ')'
								end
							end
						end
						if disqualified==true then
							riderLink='<s>'..riderLink..'</s>'
						end
						if winners[wOf] == '' then
							winners[wOf] = riderLink
						else
							winners[wOf] = winners[wOf] .. '<br/>' .. riderLink
						end
					end
				end
			end
		end
	end
end

local function sortandconcat(t_Body, resulttable)
	table.sort(t_Body, function(a, b) return a[1] < b[1] end)
	for _, m in ipairs(t_Body) do resulttable:node(m[2]) end
	return resulttable
end

--------- Definition sub-functions for calendar and victory ------
local function fn_date(entityID, functionName)  --to move as a general function
	local tempdate, timeOfRace, sortkey, sortkeyDate
	local outputtable={}
	local sTime = firstValue(entityID, 'P580', 'time') -- P580 is 'start time'
	local eTime = firstValue(entityID, 'P582', 'time') -- P582 is 'end time'
	if sTime and eTime then
		local startTime, endTime = getStartEndTime(sTime, eTime, 'small')
		if functionName==nil then --calendar
			tempdate = startTime .. ' – ' .. endTime  --mettre year en option!
			sortkeyDate = sTime
		else  --victory, general classification
			tempdate =endTime
			sortkeyDate =eTime
		end
		timeOfRace = eTime
	else
		-- This function give a format to dates when P585 (date) is used in a single day race
		local pTime = firstValue(entityID, 'P585', 'time') -- P585 is 'point in time'
		if pTime then
			tempdate = func_date(pTime, 'small')
			timeOfRace = pTime
			sortkeyDate = pTime
		end
	end
	local _, _, y, m, d = string.find(sortkeyDate, "(%d+)-(%d+)-(%d+)")
	if y~= nil and m~= nil and d~=nil then
		sortkey = y..m..d
	elseif y~= nil and m~= nil then
		sortkey = y..m
	elseif y~= nil then
		sortkey = y
	else sortkey = '0000'
	end

	local tCell = mw.html.create('td'):attr('data-sort-value',sortkey)
	:cssText("style=text-align:right;padding:0 0.5em")
	:wikitext(tempdate)
	
	outputtable[1]=timeOfRace
	outputtable[2]=tostring(tCell)
	outputtable[3]=sortkey
	return outputtable
end

local function fn_country(entityID, timeOfRace,countrybool, fn_racetable)
	-- This function gives countries where the race take place
	-- parentID taken from fn_race, optional
	
	--outputtable[1] is the cell
	--outputtable[2] is the name of the country
	--outputtable[3] is the flag
	local country, countryname, outputtable= {}, {}, {}
	local countryID, parentID, raceSitelink
	
	if fn_racetable~=nil then
		raceSitelink = fn_racetable[1] --only for country false
		parentID=fn_racetable[3]
	end
	
	local cssCell="text-align:" .. textalign .. ";padding:0 0.5em"
	local tCell= mw.html.create('td'):cssText(cssCell)
	
	local listOfProperty={'P1532','P17'} -- P1512 is 'country for sport' to handle problems with Hong Kong etc.
	local listOfID = {entityID, parentID}
	
	for _, thisID in ipairs(listOfID) do
		if thisID~=nil then
			for _, prop in ipairs(listOfProperty) do
				if countryID == nil then --like "break"
					for _, p1532 in statements(thisID, prop) do 
						countryID = p1532.mainsnak.datavalue.value.id
						countryname[#countryname + 1] = getCountryName(countryID)
						if countrybool==false or not countryname[#countryname] then
							country[#country + 1]=flag(countryID, timeOfRace)
						else
							country[#country + 1]=flag(countryID, timeOfRace).." "..countryname[#countryname]
						end
						outputtable[3]=flag(countryID, timeOfRace)
					end
				end
			end
		end
	end

	if countryID == nil then outputtable[3]="no flag" end
	if countryname[1] then tCell:attr('data-sort-value',countryname[1]) end
	if countrybool==false then
		tCell:wikitext(country[1].." "..(raceSitelink or ''))
		outputtable[2]=''
	else
		if countryname[1] then
			outputtable[2]=countryname[1]
			if country[1] then tCell:wikitext(country[1]) end
		else
			outputtable[2]=''
		end
		
	end
	outputtable[1]=tCell
	return outputtable
end

local function commastage(stageID,racelabel) --how to write "stage, "
	local outputtable={}
	local stagenumber=''
	local substage = ''
	local stagenumberonly, stageletter
	outputtable[1]=''
	outputtable[2]=''

	local temp=firstValue(stageID, 'P1545')
	if temp then stagenumber = temp end

	if stagenumber=='0' then --prologue
		stagenumber= translate("victories",9)
	else
		if stagenumber==nil then
			stagenumber= translate("victories",8)
		else
			--look for substage
			local i,j = string.find(stagenumber, "%a+") --if letter in the stage number
			if i ~= nil then --we have to do something
				local k,l = string.find(stagenumber, "%d+") --select the number in the stage number
				stagenumberonly = string.sub(stagenumber, k, l)--cut the string in 2
				stageletter = string.sub(stagenumber, i, j)
				stagenumber=stagenumberonly
				if stageletter ~= nil then substage=stageletter end
			end
			if wiki == 'ar' then
				stagenumber= translate("victories",8)..' '..number('f', stagenumber, wiki)
			else
				stagenumber= number('f', stagenumber, wiki)..substage..' '..translate("victories",8)
			end
		end
	end

	local comma = ", "
	if wiki == 'ar' then comma = " ، " end
	if wiki == 'fr' then
		local correpondance={
		{name="^Trois", article= " des "},
		{name="^Quatre", article= " des "},
		{name="^Boucles", article= " des "},
		{name="^Triptyque", article= " du "},
		{name="^Tour", article= " du "},
		{name="^Grand Prix", article= " du "},
		{name="^Circuit", article= " du "},
		{name="^Mémorial", article= " du "},
		{name="^Trophée", article= " du "},
		{name="^Ronde", article= " de la "},
		{name="^Semaine", article= " de la "},
		{name="^Classica", article= " de la "},
		{name="^Flèche", article= " de la "},
		{name="^Course", article= " de la "},
		{name="^Classique", article= " de la "},
		{name="Race", article= " de la "},
		{name="^Étoile", article= " de l'"},
		{name="^La", article= " de "}
		}

		for _, v in ipairs(correpondance) do
			if string.find(racelabel, v.name) then
				comma = v.article
				break
			end
		end
	end

	if wiki == 'fr' or wiki=="ca" or wiki=="es" or wiki=="ast" then
		outputtable[1]=stagenumber..comma
	else
		--if wiki=="de" or wiki=="da" or wiki=="fo" or wiki == "lb" or wiki=="no" or wiki=="ru" or wiki=="ar" or wiki=="lv" or wiki=="pl" then
		outputtable[2]=comma..stagenumber
	end
	return outputtable
end

local function getMainRaceLink(entityID,entity_type,stageID, functionName,timeOfRace) --the link to the edition but with a general name
	local instanceOf, label, Sitelink, isclass, prefix, postfix
	
	Sitelink=wikibase.getSitelink(entityID)
	prefix=''; postfix='' --general classification
	listOfProperty={'P2561','P1448'}

	for _, p31 in statements(entityID, 'P31') do
		instanceOf = p31.mainsnak.datavalue.value.id
		isclass=false
		for _,thisClass in ipairs(class) do--we don't want the class, but the main race
			if instanceOf == thisClass then isclass=true end
		end
		if isclass==false then
			for _, prop in ipairs(listOfProperty) do
				for _, p2561 in statements(instanceOf, prop) do --name for championship
					if label==nil then
						local lang_WD = p2561.mainsnak.datavalue.value.language
						if wiki == lang_WD then
							local nametemp = p2561.mainsnak.datavalue.value.text
							if timeOfRace~= nil then
								local q = p2561.qualifiers
								if q then
									local temp = checktime(nametemp,q,timeOfRace)
									if temp then label = nametemp end--if the time is correct than it is finished
								else
									label = nametemp
								end
							end
						end
					end
				end
			end

			if label==nil then
				label=wikibase.label(instanceOf)
				if not label then
					label = getLabelFallback(entityID, {'en', 'fr', 'de'}) or ''
				end
			end
			if Sitelink==nil then --only if no link to the race direct
				Sitelink=wikibase.getSitelink(instanceOf)
			end
			if Sitelink==nil and entity_type=='champ' then --only for champ
				local temp=firstValue(instanceOf, 'P361','id')
				if temp then Sitelink= wikibase.getSitelink(temp) end
			end
		end
	end
	--affect the label
	if label==nil then
		label=wikibase.label(entityID)
		if not label then
			label = getLabelFallback(entityID, {'en', 'fr', 'de'}) or ''
		end
	end
	--look for link to the race if nothing
	--if different languages have to be added, a language table can be created
	if entity_type=='2' then
		if functionName~=nil then --calendar=nil
			if wiki == 'fr' then prefix= translate("victories",1)..', ' --general classification
			elseif wiki == 'ar' then postfix ='، '..translate("victories",1)
			else postfix = ', '..translate("victories",1)
			end
		end
	elseif entity_type=='stage' then
		--how to write "stage, " is concentrated in one function
		local commatable=commastage(stageID, label)
		prefix= commatable[1]
		postfix=commatable[2]
	end

	if Sitelink == nil then
		return prefix..label..postfix
	else
		return prefix..'[['..Sitelink..'|'..label..']]'..postfix
	end
end

local function fn_getClassInfo(entityID,displayed_class) --get the class of the race
	local display=false
	local outputtable={}
	local entity_type, class_text, sortkey_class

	if displayed_class==nil then
		display=true
	else
		for _, thisClass in ipairs(displayed_class) do
			if entityID ==thisClass then display=true break end
		end
	end
	listOfClassesList = {class_champ,class_2x, class_without2x}
	listOfClassesName = {'champ', '2','1'}
	
	for ii, thisClassesList in ipairs(listOfClassesList) do
		if entity_type==nil then
			for _, thisClass in ipairs(thisClassesList) do
				if entityID == thisClass then
					entity_type = listOfClassesName[ii]
					class_text = mw.wikibase.label(thisClass)
					sortkey_class = class_sort[thisClass]
				end
			end
		end
	end
	if entity_type==nil then entity_type = 'nada' end--to allow display of race without class...

	if display~=false then
		outputtable[1]=entity_type
		outputtable[2]=class_text
		outputtable[3]=sortkey_class
		outputtable[4]=entityID --save the class
	end
	return outputtable
end

local function fn_race(entityID,displayed_class,displayclass,timeOfRace, functionName,country)--return link to the race and class
	--first function read from victory main
	
	--outputtable[1] is the cell with the race, or sitelink if country is false
	--outputtable[2] is the cell with the class
	
	local Sitelink,instanceOf,circuitID,parentCircuitID, displayedCircuitID, Circuitlink
	local Classlink, entity_type, classID, class_text
	local inputtable, outputtable={}, {}
	local display=true -- should be true to work, bypassed
	local sortkey_class = ''
	local stageID=entityID

	for _, p31 in statements(entityID, 'P31') do
		instanceOf = p31.mainsnak.datavalue.value.id
		for i=1,#stages do --is it a stage?
			if instanceOf == stages[i] then
				entity_type = 'stage'  --then the class is one stage above!
				local parentID = getParentID(entityID)
				entityID = parentID
				outputtable[3] = parentID --as we read it here, no need to read it afterwards
				display = true
				for _, p31bis in statements(parentID, 'P31') do
					local instanceOfbis = p31bis.mainsnak.datavalue.value.id
					inputtable=fn_getClassInfo(instanceOfbis,displayed_class)
					if inputtable[1]~=nil and inputtable[1]~='nada' then
						class_text =inputtable[2]
						sortkey_class=inputtable[3]
						classID=inputtable[4]
					end
				end
			end
		end
		if entity_type==nil then  --bypass if stage
			inputtable=fn_getClassInfo(instanceOf,displayed_class)
			if inputtable[1]==nil then
			elseif inputtable[1]=='nada' then --no display="inputtable[1]==nil" inputtable[1]=='nada'--> display but empty
				display=true
			else
				display=true
				entity_type=inputtable[1]
				class_text =inputtable[2]
				sortkey_class=inputtable[3]
				classID=inputtable[4]
			end
		end
	end
	--Now we have the class and know the type of race it is
	--Get the circuit, if we display it only
	if class_text ~=nil then Classlink = class_text else Classlink ='' sortkey_class='' end

	if display then
		if entity_type == 'stage' then
			Sitelink=getMainRaceLink(entityID,entity_type,stageID, functionName,timeOfRace)
		else
			Sitelink=getMainRaceLink(entityID,entity_type,nil, functionName,timeOfRace)
		end
		if country~=false then
			local tCell=mw.html.create('td'):cssText("text-align:".. textalign ..";padding:0 2.3em"):wikitext(Sitelink)
			outputtable[1]=tostring(tCell)
		else
			outputtable[1]=Sitelink --already opened
		end
		if displayclass == true then
			if classID=='Q23005601' or classID=='Q23005603' then --1WWT 2WWT clear
				displayedCircuitID = 'Q21075974'
			elseif classID=='Q22231106' or classID=='Q22231107' then --1UWT 2UWT clear
				displayedCircuitID = 'Q635366'
			else --we have to look in the item
				for _, p361 in statements(entityID, 'P361') do
					circuitID = p361.mainsnak.datavalue.value.id
					for _, p31 in statements(circuitID, 'P31') do --is it a UCI circuit?
						parentCircuitID = p31.mainsnak.datavalue.value.id
						for i=1,#UCI_Circuits do
							if parentCircuitID == UCI_Circuits[i] then  --Yes it is
								displayedCircuitID=circuitID
								break
							end
						end
					end
				end
			end
			if displayedCircuitID~=nil then
				Circuitlink = wikibase.getSitelink(displayedCircuitID) --we display the circuit of the year
				if Circuitlink ~= nil then 
					if class_text ~= nil then 
						Classlink = '[['..Circuitlink..'|'..class_text..']]' 
						else
						Classlink = '[['..Circuitlink .. ']]' 
					end
				end
			end
			-- class
			local tCell=mw.html.create('td')
			:attr('data-sort-value',sortkey_class)
			:cssText("text-align:center;padding:0 0.5em")
			:wikitext(Classlink)
			
			outputtable[2]=tCell
		end
	end
	return outputtable
end

local function fn_rider(entityID,timeOfRace,displayteam,only_winner,country)
	local winners, countrytemp, result
	local WDlink_on = (wiki == "mk" or wiki == "ja")
	local thereisawinner=false
	
	if only_winner == 1 then
		winners = {Q20882667 = '', Q20882747=''} -- first, general or stage
	elseif only_winner == 0 then
		winners = { Q20882667 = '', Q20882668 = '',Q20882669 = ''} -- Q20882668 is 'second overall'
	else --3
		winners = { Q47640757='' } -- World Tour -- name not used here
	end
	if country==nil then countrytemp=false else countrytemp=country end
	winner(entityID, winners, timeOfRace, countrytemp, WDlink_on, displayteam, true)
	
	local tCell=mw.html.create('td'):css("text-align:".. textalign ..";padding:0 0.5em")
	
	if only_winner == 0 then
		tCell:wikitext(winners.Q20882667)
		result=tostring(tCell)
		tCell=mw.html.create('td'):css("text-align:".. textalign ..";padding:0 0.5em"):wikitext(winners.Q20882668)
		result=result..tostring(tCell)
		tCell=mw.html.create('td'):css("text-align:".. textalign ..";padding:0 0.5em"):wikitext(winners.Q20882669)
		return result..tostring(tCell)
	else
		local tempwinner
		if only_winner == 1 then
			if winners.Q20882667~=nil and winners.Q20882667~='' then
				tempwinner=winners.Q20882667
			else
				tempwinner=winners.Q20882747
			end
		else
			tempwinner=winners.Q47640757
		end
		if tempwinner~='' and tempwinner~=nil then thereisawinner=true end
		return tCell:wikitext(tempwinner), thereisawinner
	end
end

local function getKm(wiki)
	local km
	if wiki == "ar" then km = 'كم'
	elseif wiki == "mk" then km = 'км'
	elseif wiki == "ru" then km = 'км'
	elseif wiki == "ja" then km = 'キロメートル'
	else km = 'km' end
	return km
end

local function checkkm(p)
	local km, unit
	if p[1] and p[1].mainsnak.snaktype == 'value' then
		km = tonumber(p[1].mainsnak.datavalue.value.amount)
		unit = p[1].mainsnak.datavalue.value.unit
		if unit == 'http://www.wikidata.org/entity/Q828224' then
			return km
		end
	end
	return nil
end

local function getDistance(raceID, addUnit)
	local km
	local p = mw.wikibase.getBestStatements(raceID, 'P3157') -- P3157 is 'event distance'
	if not p[1] then
		p = mw.wikibase.getBestStatements(raceID, 'P2043') -- P2043 is 'length'
	end
	km =checkkm(p)
	if not km then --for stage race we can sum the distances from each stage
		local stagep, tempkm
		for _, p527 in statements(raceID,'P527') do
			stageID = p527.mainsnak.datavalue.value.id
			stagep=mw.wikibase.getBestStatements(stageID, 'P3157')
			tempkm=checkkm(stagep)
			if tempkm then
				if not km then
					km=tempkm
				else
					km=km+tempkm
				end
			end
		end
	end
	local text
	local lang = contentLanguage
	if km then
		-- The unit should always be km. Skip if it isn't.
		text = lang:formatNum(km)
		if wiki == 'fo' then
			text = string.gsub(text, "%.", ",")
		end
		if addUnit then
			text = text .. ' ' .. getKm(wiki)
		end
	end
	return text, km
end

local function getKmh(wiki)
	local kmh
	if wiki == "ar" then kmh = 'كم/س'
	elseif wiki == "da" then kmh = 'km/t'
	elseif wiki == "fo" then kmh = 'km/t'
	elseif wiki == "nl" then kmh = 'km/u'
	elseif wiki == "no" then kmh = 'km/t'
	elseif wiki == "mk" then kmh = 'км/ч'
	elseif wiki == "ru" then kmh = 'км/ч'
	elseif wiki == "ja" then kmh = 'キロメートル毎時'
	else kmh = 'km/h' end
	return kmh
end

local function getElevation(raceID)
	local temp = mw.wikibase.getBestStatements(raceID, 'P7297')
	if temp[1] and temp[1].mainsnak.snaktype == 'value' then
		local unit = temp[1].mainsnak.datavalue.value.unit
		if unit == 'http://www.wikidata.org/entity/Q11573' then
			return tonumber(temp[1].mainsnak.datavalue.value.amount)..' m'
		end
	end
    return nil
end

local function getSpeed(raceID, addUnit,kmdistance, property)
	local p = mw.wikibase.getBestStatements(raceID, 'P2052') -- P2052 is 'speed'
	local kmh, unit, text, found, timeOfRace
	local lang = contentLanguage
	if p[1] and p[1].mainsnak.snaktype == 'value' then
		kmh = tonumber(p[1].mainsnak.datavalue.value.amount)
		unit = p[1].mainsnak.datavalue.value.unit
		if unit == 'http://www.wikidata.org/entity/Q180154' then -- Q180154 is 'kilometre per hour'
			found=true
		end
	end
	if not found and kmdistance then --calculate speed
		local p2321= wikibase.getBestStatements(raceID, property) --winner supposed to be first of overall classification
		if p2321 and p2321[1] and p2321[1].mainsnak.snaktype == 'value' then
			local q = p2321[1].qualifiers
			if q and q.P1352 and q.P1352[1].snaktype == 'value' then --rank
				for _, q1352 in pairs(q.P1352) do
					rank = tonumber(q1352.datavalue.value.amount)
				end
				if rank == 1 then
					timeOfRace=qualifieramount(p2321[1], 'P2781') --get time
				end
			end

			if timeOfRace then
				found=true
				kmh=math.modf(1000*kmdistance/(timeOfRace/3600))/1000
			end
		end
	end
	if found then	
		-- The unit should always be km/h. Skip if it isn't.
		text = lang:formatNum(kmh)
		if wiki == 'fo' then
			text = string.gsub(text, "%.", ",")
		end
		if addUnit then
			text = text .. ' ' .. getKmh(wiki)
		end
	end
	return text
end

local function getgendercode(riderID, default)
	local gender
	local p21 = mw.wikibase.getBestStatements(riderID, 'P21') -- P21 is gender
	if p21[1] and p21[1].mainsnak.snaktype == 'value' then
		local g = p21[1].mainsnak.datavalue.value.id
		if g == 'Q6581097' then gender = 'm' -- Male
		elseif g == 'Q6581072' then gender = 'f' -- Female
		elseif g == 'Q1052281' then gender = 't' -- Transgenre
		end
	end
	return gender or default -- default is for teams, n or f
end

function number(gender, b, wiki)
	local str
	if b=="" then return "" end
	if wiki=="ar" then
		str = b
	elseif wiki == "ca" then
	if b==1 then str = b.."r"
		elseif b==2 then str = b.."n"
		elseif b==3 then str = b.."r"
		elseif b==4 then str = b.."t"
		else str = b.."è"
		end
	elseif wiki=="es" then
		if gender == 'm' or gender == 'n' then str = b..".º"
		elseif gender == 'f' then str = b..".ª"
		else str = b.."."
		end
	elseif wiki=="fr" then
		if b==1 then
			if gender == 'm' then str="1<sup>er</sup>"
			elseif gender == 'f' or gender == 'n' then str="1<sup>re</sup>"
			else str="1<sup>e</sup>"
			end
		else str=b.."<sup>e</sup>"
		end
	elseif wiki=="nl" then str=b.."e"
	elseif wiki=="ru" then str=b.."-й"
	elseif wiki=="eo" then str=b.."-a"
	elseif wiki=="ast" then
		if gender == 'm' or gender == 'n' then str = b.."ᵘ"
		elseif gender == 'f' then str = b.."ª"
		else str = b.."."
		end
	else str = b .. ". "
	end
	return str
end

local function calculate_time(t)
	local time = tonumber(t)
	local h, m, s = 0, 0, 0
	local str = ''

	if time == nil then return '' end
	if time < 60 then s = time
	elseif time < 3600 then m = math.modf(time/60) s = time - m*60
	else h = math.modf(time/3600) m = math.modf((time - h*3600)/60) s = time - h*3600 - m*60
	end

	if h>0 then str = str..mw.ustring.format ('%i'..translate("unit",2), h) end
	if m>=0 and h>0 then str = str.. mw.ustring.format('%02i'..translate("unit",3), m) end
	if m>0 and h==0 then str = str.. mw.ustring.format('%i'..translate("unit",3), m) end
	if s>=0 and (h>0 or m>0) then str = str.. mw.ustring.format('%02i'..translate("unit",4), s) end
	if s>=0 and h==0 and m==0 then str = str.. mw.ustring.format('%i'..translate("unit",4), s) end
	return str --time..': '..h..' '..m..' '..s
end

function func_error_message(x)
	local l10nDef = {
		["en"] = {'Property <1> is missing in item "<2>" (<3>)'},
		["ar"] = {'الخاصية <1> غير موجودة في العنصر "<2>" (<3>)'},
	}
	local l10n = l10nDef[wiki]
	if not l10n then l10n = l10nDef["en"] end  -- default
	return l10n[x]
end

local function getMissingLabelTrackingCategory()
	local l10nDef = {
		["//cs.wikipedia.org"] = '[[Kategorie:Údržba:Doplnit štítek na Wikidatech]]',
		["//lv.wikipedia.org"] = '[[Category:Vikidatos trūkst nosaukuma latviešu valodā]]',
		["//he.wikipedia.org"] = '[[קטגוריה:ויקינתונים:ערכים חסרי תווית בעברית: קבוצת אופניים]]',
	}
	local l10n = l10nDef[mw.site.server]
	if not l10n then
		l10n = ''
	end
	return l10n
end

local function getStageLabel(inp)
	local a
	local b='' 
	local this_label=''
	if inp then
		a, _ = string.gsub(inp, "%a", "") -- 20, not 20a
		if string.find(inp, "%a") then 
			b = string.sub(inp, string.find(inp, "%a"))
		end
		if inp == "0" then 
			this_label = translate("func_prologue")
		else
		    this_label = stageLink(inp, a, b)
		end
	end
	return this_label
end

--[[ Make a table row for infoboxes with links to previous and next ]]
local function getPreviousNextLine(raceID, stage)
	local previousID = firstValue(raceID, 'P155', 'id') -- P155 is 'follows'
	local nextID = firstValue(raceID, 'P156', 'id') -- P156 is 'followed by'
	if not nextID or not previousID then
		for _, s in statements(raceID, 'P3450') do		-- for items using P3450
			local q = s.qualifiers
			if q then
				if not previousID and q.P155 and q.P155[1] and	q.P155[1].snaktype == 'value' then
					previousID = q.P155[1].datavalue.value.id
				end
				if not nextID and q.P156 and q.P156[1] and	q.P156[1].snaktype == 'value' then
					nextID = q.P156[1].datavalue.value.id
				end
			end
		end
	end
	if not previousID and not nextID then
		return ''
	end

	local previousText, nextText = '', ''
	local this_label
	if previousID then
		if stage  then
			 local series_ordinal= firstValue(previousID, 'P1545', 'value')
			 this_label=getStageLabel(series_ordinal)
		else
			this_label = getYear(previousID)
		end
		local link = wikibase.getSitelink(previousID)
		if link then
			previousText = '<span style="color:#3366CC">[[' .. link .. '|&#x25C0; ' .. this_label .. ']]</span>'
		else
			previousText = '<span style="color:#3366CC">&#x25C0;</span> ' .. this_label
		end
	end
	if nextID then
		if stage then
			local series_ordinal= firstValue(nextID, 'P1545', 'value')
			this_label=getStageLabel(series_ordinal)
		else
			this_label = getYear(nextID)
		end
		local link = wikibase.getSitelink(nextID)
		if link then
			nextText = '<span style="color:#3366CC">[[' .. link .. '|' .. this_label .. ' &#x25B6;]]</span>'
		else
			nextText = this_label .. ' <span style="color:#3366CC">&#x25B6;</span>'
		end
	end
	local direction = contentLanguage:getDir()
	
	local outputTable = mw.html.create('tr')
	local tCell=outputTable:tag('td')
	tCell:cssText("text-align:" .. ((direction == 'ltr') and 'left' or 'right')):wikitext(previousText)
	if stage ~= nil and wiki=="ar" then 
		tCell:css('width','50%')
	end
	 tCell=outputTable:tag('td')
	 :cssText("text-align:" .. ((direction == 'ltr') and 'right' or 'left')):wikitext( nextText)
    if stage ~= nil and wiki=="ar" then 
		tCell:css('width','50%')
	end
	return outputTable
end

--== V) Main functions ==
--=== A) Function race reference ===
local function race_reference(raceID)
	-- Allow to display the reference below the classifications --
	local bases={
		{"ProCyclingStats", "P2327", "http://www.procyclingstats.com/race.php?id="},
		{"Cycling Quotient", "P2648", "http://www.cqranking.com/men/asp/gen/race.asp?raceid="},
		{"Cycling Archives", "P2330", "http://www.cyclingarchives.com/ritfiche.php?ritid="},
		{"Cycling Quotient", "P2708", "http://www.cqranking.com/women/asp/gen/race.asp?raceid="}
	}
	local links = {}
	local ref
	for _, base in pairs(bases) do
		local p = mw.wikibase.getBestStatements(raceID, base[2])
		if p[1] and p[1].mainsnak.snaktype == 'value' then
		    if base[2]=="P2648" and p[1].mainsnak.datavalue.value=="1" then --code for general reference of results
				ref=getReference(p[1], 1)
				if ref then	table.insert(links, ref) end
			else
				table.insert(links, ' [' .. base[3] .. p[1].mainsnak.datavalue.value .. " " .. base[1] ..']')
			end
		end
	end
	if #links == 1 then
		return translate("race_reference", 1) .. table.concat(links)
	elseif #links > 1 then
		return translate("race_reference", 2) .. table.concat(links)
	else
		return ''
	end
end

--=== B) Calendar ===
function p.calendarcustom(frame)
	----- function to display calendar of any competition -----
	local function getargs(frame, fieldname, headertemp, tempdic)
		local argindex=tempdic[fieldname][1]

		if frame.args[argindex] ~= nil and tonumber(frame.args[argindex]) ==1 then
			tempdic[fieldname][3]= tempdic[fieldname][4]
			table.insert(headertemp, tempdic[fieldname][2])
		end
		return headertemp, tempdic
	end
	
	-- position in args,  header_column, default value,other value
	local headertemp={2} --date
	local tempdic = {
		['numbering']={2, 3, false, true},
		['displayclass']={4, 6, false, true},
		['displayleader']={6, 10, false, true}
	}

	if wiki == "ar" and string.match(frame:getParent():getTitle(), '%P+') == mw.site.namespaces.Template.name
	then frame = frame:getParent() end

	if frame.args[1] ~= nil then calendarID = string.gsub(frame.args[1], "%c", "") end

	headertemp, tempdic= getargs(frame, 'numbering', headertemp, tempdic)
	if tempdic['numbering'][3] then countrycolumn=3 else countrycolumn=2 end

	local no_countrytemp={}
	if frame.args[3] ~= nil and tonumber(frame.args[3]) ==1 then no_countrytemp={wiki} end
	-- country --
	table.insert(headertemp, 5)
	--race--
	table.insert(headertemp, 4)

	headertemp, tempdic= getargs(frame, 'displayclass', headertemp, tempdic)
	
	local onlywinnertemp =1
	if frame.args[5] ~= nil and tonumber(frame.args[5]) ==1 then
		onlywinnertemp =0
	end
	table.insert(headertemp, 7) --winner
	if onlywinnertemp==0 then
		table.insert(headertemp, 8)
		table.insert(headertemp, 9)
	end
	headertemp, tempdic= getargs(frame, 'displayleader', headertemp, tempdic)	

	local displayteamtemp =false
	if frame.args[7] ~= nil and tonumber(frame.args[7]) ==1 then displayteamtemp =true end

	local data_typetemp={}
	for ii=1,#headertemp do
		table.insert(data_typetemp,'')
	end

	local s = {
		header_function = "calendar", -- translations are in function Calendar
		header_1 = 1000, -- translation 1 in function Calendar is printed in the upper part of the table header
		header_2 = headertemp,-- translations 2, 3, 4, 5, 6 in function Calendar are printed in this order
		title=wikibase.getLabel(calendarID),  -- in the lower part of the table header. The second value 3 in {4, 3} tells where the icon will go.
		country_column = countrycolumn,
		data_sort_type = data_typetemp, -- see https://meta.wikimedia.org/wiki/Help:Sorting
		item = calendarID,
		property = 'P527',
		no_country = no_countrytemp,
		only_winner = onlywinnertemp,
		numbering =  tempdic['numbering'][3],
		error_message = 0,
		displayed_class =nil,
		displayteam=displayteamtemp,
		displayclass= tempdic['displayclass'][3],
		leadercolumn= tempdic['displayleader'][3],
		frame=frame
	}
	return calendar_main(s, tableA(s))
end

function p.calendar(frame)
	----- function to display UCI calendar of one year ----
	----- based on WWTcalendar function -----
	----- author: Mr. Ibrahem -----
	local calendarID
	if wiki == "ar" then frame = frame:getParent() end
	local UCI = {}
	UCI["WT"] = { -- Q635366
		['2020'] = 'Q66739340',
		['2019'] = 'Q56966729',['2018'] = 'Q42317185',['2017'] = 'Q21857932',
		['2016'] = 'Q20970765',['2015'] = 'Q18192726',['2014'] = 'Q14979277',
		['2013'] = 'Q1031504',['2012'] = 'Q849059', ['2011'] = 'Q849092'
		}
	UCI["europe"] = { -- Q1194340
		['2020'] = 'Q74842812',
		['2019'] = 'Q57267776',['2018'] = 'Q44497477',['2017'] = 'Q27915850',
		['2016'] = 'Q21029681',['2015'] = 'Q18342122',['2014'] = 'Q15041668',
		['2013'] = 'Q1280387',['2012'] = 'Q961709',['2010–11'] = 'Q751208',
		['2009–10'] = 'Q212197',['2008–09'] = 'Q1811548',['2007–08'] = 'Q1788011',
		['2006–07'] = 'Q1780660',['2005–06'] = 'Q1455600',['2005'] = 'Q1431816'
		}
	UCI["asia"] = { -- Q1063423
		['2020'] = 'Q74121688',
		['2019'] = 'Q57267783',['2018'] = 'Q42204070',['2017'] = 'Q27679728',
		['2016'] = 'Q21622227',['2015'] = 'Q18341318',['2013–14'] = 'Q15041671',
		['2012–13'] = 'Q1606048',['2011–12'] = 'Q2117797',['2010–11'] = 'Q633349',
		['2009–10'] = 'Q630798',['2008–09'] = 'Q565160',['2007–08'] = 'Q1506934',
		['2006–07'] = 'Q966011',['2005–06'] = 'Q459817',['2005'] = 'Q469479',
		}
	UCI["america"] = { -- Q1063430
		['2020'] = 'Q73175384',
		['2019'] = 'Q57267780',['2018'] = 'Q42199340',['2017'] = 'Q27704415',
		['2016'] = 'Q21621040',['2015'] = 'Q18413668',['2013–14'] = 'Q15041669',
		['2012–13'] = 'Q129177',['2011–12'] = 'Q1239608',['2010–11'] = 'Q1849269',
		['2009–10'] = 'Q1303982',['2008–09'] = 'Q1536927',['2007–08'] = 'Q31716',
		['2006–07'] = 'Q31714',['2005–06'] = 'Q1429246',['2005'] = 'Q1431880',
		}
	UCI["africa"] = { -- Q268357
		['2020'] = 'Q74124131',
		['2019'] = 'Q57267785',['2018'] = 'Q42202027',['2017'] = 'Q27679848',
		['2016'] = 'Q21622217',['2015'] = 'Q18342124', ['2013–14'] = 'Q15041670',
		['2012–13'] = 'Q327399', ['2011–12'] = 'Q2296721',['2010–11'] = 'Q1386870',
		['2009–10'] = 'Q2067266', ['2008–09'] = 'Q1812465',['2007–08'] = 'Q676684',
		['2006–07'] = 'Q1436886', ['2005–06'] = 'Q1758917',['2005'] = 'Q1759404',
		}
	UCI["oceania"] = { -- Q1039648
		['2020'] = 'Q74843575',
		['2019'] = 'Q57267787',['2018'] = 'Q42205000', ['2017'] = 'Q27887426',
		['2016'] = 'Q21559636',['2015'] = 'Q18413671', ['2014'] = 'Q15246814',
		['2013'] = 'Q129134',['2011–12'] = 'Q1591132', ['2011'] = 'Q2298207',
		['2009–10'] = 'Q665283',['2008–09'] = 'Q964517', ['2007–08'] = 'Q1788621',
		['2006–07'] = 'Q1473640',['2005–06'] = 'Q1429165', ['2005'] = 'Q937636',
		}
	UCI["WWT"] = {
		['2020'] = 'Q70443700',
		['2019'] = 'Q57277246', ['2018'] = 'Q41787783', ['2017'] = 'Q27431192',
		['2016'] = 'Q21034783',
		}
	UCI["women"] = {
		['2020'] = 'Q74127378',
		['2019'] = 'Q57267790', ['2018'] = 'Q47005682', ['2017'] = 'Q27765666',
		['2016'] = 'Q22696468', ['2015'] = 'Q18348936', ['2014'] = 'Q15831496',
		['2013'] = 'Q6425932', ['2012'] = 'Q2466796', ['2011'] = 'Q2466792',
		['2010'] = 'Q2933831', ['2009'] = 'Q2933830', ['2008'] = 'Q2933828',
		['2007'] = 'Q3650627', ['2006'] = 'Q16154659',
		}
	UCI["Pro"] = {
		['2020'] = 'Q74279750',
		}
		
	local header_1_tab = {["WT"]=13 ,["europe"]=14 ,["asia"]=15,["america"]=16 ,["africa"]=17 ,["oceania"]=18, ["WWT"]=11, ["women"]=1, ["Pro"]=22}
	local display_code_tab=  {["WT"]=1 ,["europe"]=2 ,["asia"]=2,["america"]=2 ,["africa"]=2 ,["oceania"]=2, ["WWT"]=1, ["women"]=2, ["Pro"]=2}
	local header_1_number = 12
	
	local tempdic
	local tempdic1 = {
		header_2 =  {2, 3,5, 4, 7, 8, 9, 10},
		only_winner =0,
		numbering=true,
		displayteam=false,
		displayclass=false,
		leadercolumn=true
	}	
	local tempdic2 = {
		header_2 =   {2, 5, 4, 6, 7},
		only_winner =1,
		numbering=false,
		displayteam=true,
		displayclass=true,
		leadercolumn=false
	}

	for key, v in pairs(UCI) do
		if not calendarID  and frame.args[key] then
			local year = frame.args[key]
			year = string.gsub(year , "%c", "")
			if v[year] then
				calendarID = v[year]
				header_1_number = header_1_tab[key]
				display_code = display_code_tab[key]
			end
			if wiki == "ar" and frame.args["code"] and frame.args["code"] ~= "" then
				display_code = 1
			end
		end
	end
	if wiki == "ar" and calendarID == "" and ( frame.args["test"] or frame.args.test) then
		calendarID = frame.args["test"]  or frame.args.test
	end
	if not calendarID or calendarID == "" then return "" end
	if display_code == 1 then
		tempdic=tempdic1
	else
		tempdic=tempdic2
	end

	local s = {
		header_function = "calendar", -- translations are in function Calendar
		header_1 = header_1_number, -- t
		header_2 = tempdic.header_2,
					-- in the lower part of the table header. The second value 3 in {4, 3} tells where the icon will go.
		country_column = 3,
		data_sort_type ={'', 'unsortable', '', '', '','',''},   -- -- see https://meta.wikimedia.org/wiki/Help:Sorting
		item = calendarID,
		property = 'P527',
		no_country = no_country_calendar,
		only_winner = tempdic.only_winner,
		numbering = tempdic.numbering,
		error_message = 0,
		displayed_class = {
			"Q23005603", --
			"Q22231110", -- 1.1
			"Q22231109", -- 2.HC
			"Q22231111", -- 1.2
			"Q22231108", -- 1.HC
			"Q22231106", -- 1.UWT
			"Q74275170", -- 1.Pro
			"Q22231107", -- 2.UWT
			"Q22231113", -- 2.2
			"Q22231112", -- 2.1
			"Q22231113", -- 2.2
			"Q22231109", -- 2.HC
			"Q74275176", -- 2.Pro
			"Q22231118", -- CC
			},
		displayteam=tempdic.displayteam,
		displayclass=tempdic.displayclass,
		leadercolumn=tempdic.leadercolumn,
		frame=frame
	}
	return calendar_main(s, tableA(s))
end

function calendar_main(s, resulttable)--Display the UCI women calendar of one year
	localframe=s.frame
	local calendarID=s.item
	local sortkey
	local t_Body, fn_racetable,fn_datetable, fn_countrytable = {}, {}, {},{}
	local displayed_class=s.displayed_class

	local temp=firstValue(calendarID, s.property)
	if not temp then s.error_message = 2 return '' end

	local country=getcoutrybool (s.no_country)
	if available_list==false then country=false end --otherwise the display put no "country" column...

	----- Begin of the main part of the code
	for kk, p527 in statements(calendarID, 'P527') do
		local RaceID = p527.mainsnak.datavalue.value.id
		---- Create a row ----
		fn_datetable = fn_date(RaceID)
		local timeOfRace = fn_datetable[1]
		fn_racetable=fn_race(RaceID,displayed_class,s.displayclass,timeOfRace,nil,country)

		if fn_racetable[1]~=nil then --otherwise the class is not display
			fn_countrytable=fn_country(RaceID,timeOfRace,country,fn_racetable) 
			
			local tRow = mw.html.create('tr'):cssText( "line-height: 1.8em; padding: 5px;")
			tRow:node(fn_datetable[2])
			sortkey = fn_datetable[3]
			if s.numbering == true then
				tRow:tag('td'):cssText("text-align:center;padding:0 0.5em"):wikitext(tostring(kk))
			end
			
			tRow:node(fn_countrytable[1])
			if country then
				tRow:node(fn_racetable[1])
			end
			if fn_racetable[2] then tRow:node(fn_racetable[2]) end --class
			tRow:node(fn_rider(RaceID,timeOfRace,s.displayteam,s.only_winner))
			if s.leadercolumn==true then
				tRow:node(fn_rider(RaceID,timeOfRace,s.displayteam,3))
			end
			---- Add the row to the table
			t_Body[#t_Body + 1] = {sortkey, tRow}
		end 
	end

	return sortandconcat(t_Body, resulttable)
end

function p.nationalchampionships(frame)
	local calendarroadID, calendarITTID, year
	if wiki == "ar" then
		frame = frame:getParent()
	end
	local UCIroad, UCIITT = {},{}

	UCIroad["women"] = {
		['2020']='Q78466304', ['2019'] = 'Q66362617',
		['2018'] = 'Q66762475', ['2017'] = 'Q66762546', ['2016'] = 'Q66762540',
		['2015'] = 'Q66762534', ['2014'] = 'Q66762524', ['2013'] = 'Q66762521',
		['2012'] = 'Q66762511', ['2011'] = 'Q66762500', ['2010'] = 'Q66762491'
	}
	
	UCIITT["women"] = {
		['2020'] = 'Q78466572', ['2019'] = 'Q66736271',
		['2018'] = 'Q66762631', ['2017'] = 'Q66762614', ['2016'] = 'Q66762604',
		['2015'] = 'Q66762597', ['2014'] = 'Q66762592', ['2013'] = 'Q66762584',
		['2012'] = 'Q66762578', ['2011'] = 'Q66762569', ['2010'] = 'Q66762562'
	}
	
	UCIroad["men"] = UCIroad["women"]
	UCIITT["men"] = UCIITT["women"]
	
	local listOfCalendar={UCIroad, UCIITT}

	for ii, thisCalendar in pairs(listOfCalendar) do --road/ITT
		for key, v in pairs(thisCalendar) do --women/men
			if ((ii==1 and calendarroadID==nil) or (ii==2 and calendarITTID ==nil)) and frame.args[key] then
				year = frame.args[key]
				year = string.gsub( year , "%c", "")
				if v[year] then
					if ii==1 then
						calendarroadID = v[year]
					else
						calendarITTID = v[year]
					end
				end
			end
		end
	end

	local s = {
		header_function = "calendar", -- translations are in function Calendar
		header_1 = 19, --
		header_2 = {5, 20, 21},
		country_column = 1,
		data_sort_type = {'', '', ''},   -- -- see https://meta.wikimedia.org/wiki/Help:Sorting
		item= calendarroadID,
		calendarroadID = calendarroadID,
		calendarITTID = calendarITTID,
		property = 'P527',
		year = year,
		no_country = {}, --no sense here to hide the country
		error_message = 0,
		displayteam = true,
		displaycountrylink = true,
		frame = frame
	}
	return nationalchampionships_main(s,tableA(s))
end

function nationalchampionships_main(s, resulttable)--Display the list of national champions for one year
	localframe=s.frame
	local tableChamp, fn_countrytable, t_Body = {}, {}, {}
	local timeOfRace ='+'..tostring(s.year).."-01-01T00:00:00Z"
	local tRace, thereisawinner, parentID, parentParentID, sitelink

	local temp=firstValue(s.calendarroadID, s.property)
	if temp then else s.error_message = 2 return '' end

	local listOfCalendarID={s.calendarroadID, s.calendarITTID}

	--create the table with the information
	for ii, thisCalendarID in ipairs(listOfCalendarID) do
		if thisCalendarID ~= nil then
			for _, p527 in statements(thisCalendarID, 'P527') do
				thisID = p527.mainsnak.datavalue.value.id
				fn_countrytable=fn_country(thisID,timeOfRace,s.country)
				sortkey=string.gsub(fn_countrytable[2], 'É', 'E') --case États Unis

				--create the table
				if tableChamp[sortkey]==nil then 
					tableChamp[sortkey]={}
					tableChamp[sortkey]['countryname']=fn_countrytable[2] --raw
					tableChamp[sortkey]['roadwinner']='<td></td>'
					tableChamp[sortkey]['ITTwinner']='<td></td>'
					--look for sitelink to championship
					sitelink=nil --reinit
					if s.displaycountrylink then --expensive
						parentID = firstValue(thisID, 'P361', 'id') --part of
						if parentID then 
							parentParentID = firstValue(parentID, 'P31', 'id') 
							if parentParentID then sitelink = wikibase.getSitelink(parentParentID) end
						end
					end
					tableChamp[sortkey]['sitelink']=sitelink
					tableChamp[sortkey]['flag']=fn_countrytable[3]
				end
				
				--fill the table
				tRace, thereisawinner=fn_rider(thisID,timeOfRace,s.displayteam,1,true)
				if tableChamp[sortkey]['thereisawinner']~=true then --all other cases
					tableChamp[sortkey]['thereisawinner']=thereisawinner 
				end
				
				if ii==1 then
					tableChamp[sortkey]['roadwinner']=tRace
				else
					tableChamp[sortkey]['ITTwinner']=tRace
				end
			end
		end
	end

	-- structure the display
	for key, thisRow in pairs(tableChamp) do
		if thisRow['thereisawinner'] then --there is a winner
			local tRow = mw.html.create('tr'):cssText( "line-height: 1.8em; padding: 5px;")
			if thisRow['sitelink']~=nil then
				tRow:tag('td'):wikitext(thisRow['flag']..' [['..thisRow['sitelink']..'|'..thisRow['countryname']..']]')
			else
				tRow:tag('td'):wikitext(thisRow['flag']..' '..thisRow['countryname'])
			end
			tRow:node(thisRow['roadwinner'])
			tRow:node(thisRow['ITTwinner'])
			t_Body[#t_Body + 1] = {key, tRow}
		end --no winner
	end --end list of key

	return sortandconcat(t_Body, resulttable)  
end

--=== C) Victory ===
function p.victories(frame)
	local s = {
		header_function = "victories", -- translations are in function victories
		header_1 = 2, -- translation 1 in function victories is printed in the upper part of the table header
		header_2 = {3, 4, 5, 6, 7},-- translations 2, 3, 4, 5, 6 in function victories are printed in this order
										-- in the lower part of the table header. The second value 3 in {4, 3} tells where the icon will go.
		data_type = {'date', 'race', 'country', 'class', 'rider'},
		country_column = 3,
		data_sort_type = {'', 'unsortable', '', '', ''}, -- see https://meta.wikimedia.org/wiki/Help:Sorting
		item = frame.args[1],
		property = 'P2522',
		no_country = no_country_victories,
		error_message = 0,
		frame=frame
	}
	return victory_main(s ,tableA(s))
end

function victory_main(s, resulttable)
	localframe=s.frame
	local _
	_, _, s.item = string.find(s.item, "(%w+)")

	local temp=firstValue(s.item, s.property,'id')
	if temp then else s.error_message = 2 return '' end

	local country=getcoutrybool (s.no_country)
	if available_list==false then country=false end

	local sortkey
	local t_Body, fn_countrytable, fn_datetable, fn_racetable = {}, {}, {}, {}

	for _, p2522 in statements(s.item, 'P2522') do
		local RaceID = p2522.mainsnak.datavalue.value.id
		local tRow = mw.html.create('tr'):cssText( "line-height: 1.8em; padding: 5px;")

		fn_datetable = fn_date(RaceID, 'victory')
		local timeOfRace = fn_datetable[1]
		sortkey=fn_datetable[2]
		
		fn_racetable=fn_race(RaceID,nil ,true,timeOfRace, 'victory',country)--displayed_class=nil
		
		if fn_racetable[1]~= nil then --otherwise class not to be displayed
			fn_countrytable=fn_country(RaceID,timeOfRace,country,fn_racetable)
			
			tRow:node(fn_datetable[2])
			if country==true then
				tRow:node(fn_racetable[1])  --race site link is in fn_countrytable
			end
			tRow:node(fn_countrytable[1]) --country
			tRow:node(fn_racetable[2]) --class
			tRow:node(fn_rider(RaceID,timeOfRace,false,1))
			t_Body[#t_Body + 1] = {sortkey, tRow}
		end --no winner
	end --end list of key
	
	return sortandconcat(t_Body, resulttable)
end

--== Cbis) Functions for infobox
-- functions for both infoboxs 
local function infoGetOthers(others, entityID)
	if not others[1].content then --picture
		others[1].content, others[2].content = getImage(entityID) -- picture, caption
	end

	if not others[3].content then  -- map
		others[3].content = firstValue(entityID, 'P242') -- P242 is 'locator map image'
	end
	
	if not others[4].content then  -- map
		others[4].content = firstValue(entityID, 'P2713') -- sectional_view
	end	
end

local function infoGetCountry(details,index, entityID, timeOfRace)
	if not details[index].content then -- country
		-- This function gives countries where the race take place
		local country = {}
		for _, p17 in statements(entityID, 'P17') do -- P17 is 'country'
			local countryID = p17.mainsnak.datavalue.value.id
			country[#country + 1] = flag(countryID, timeOfRace) .. ' ' .. getCountryName(countryID)
		end
		if country[1] then
			if #country > 1 then
				details[index].name = details[index].name_plural
			end
			details[index].content = table.concat(country, '<br/>')
		end
	end
end
	
local function infoGetStartEnd(details,index, entityID)
	if not details[index].content then -- start place
		local place = firstValue(entityID, 'P1427', 'id') -- P1427 is 'start point'
		details[index].content = place and getPlaceLink(place)
	end

	if not details[index+1].content then -- end place
		local place = firstValue(entityID, 'P1444', 'id') -- P1444 is 'destination point'
		details[index+1].content = place and getPlaceLink(place)
	end
end

local function infoGetParticipants(details,index, entityID)
		-- Function that give the number of cyclists at the beginning and at the finishing of a race
	for _, p1132 in statements(entityID, 'P1132') do -- P1132 is 'number of participants'
		local amount = tonumber(p1132.mainsnak.datavalue.value.amount) -- tonumber to remove starting '+'
		for _, q in qualifiers(p1132, 'P276') do -- P276 is 'location'
			local location = q.value['numeric-id']
			if location == 529711 then -- Q529711 is 'beginning'
				if not details[index].content then details[index].content = amount end -- participants at start
			elseif location == 12769393 then -- Q12769393 is 'end'
				if not details[index+1].content then details[index+1].content = amount end -- participants at end
			end
		end
	end
end

local function infoInitTab(width, name, icon)
	if width==nil then width= '320px' end
	
	local tab = mw.html.create('table')
	if wiki == "eo" then
		tab:cssText(standardtablecss):css('width','23em')
		:addClass('infobox')
	else
		tab:attr('cellpadding','4')
		:attr('cellspacing','0')
		:cssText(standardtablecss)
		:cssText("float:"..floatinfobox.."; max-width:"..width)
	end
	local tCell=tab:tag('tr'):tag('td'):attr('colspan','2')
	:cssText('border-bottom:5px solid white; font-size:175%; background:#FFDF80; text-align:center')
	local topTable = tCell:tag('table')
	:cssText('width:100%')
	local tRow=topTable:tag('tr')
	tRow:tag('td'):wikitext(name or '')
	tRow:tag('td'):wikitext(icon or '')
	
	return tab
end

local function infoFillOthersDetails(tab, others, details,title)
		if others[1].content then -- picture
		tab:tag('tr'):tag('td'):attr('colspan','2'):css('text-align','center')
		:wikitext("[[File:" .. others[1].content .."|center|300px]]")
		if others[2].content then -- caption
			tab:tag('tr'):tag('td'):attr('colspan','2'):css('text-align','center'):css('font-size','80%')
			:wikitext(others[2].content)
		end
	end
	tab:tag('tr'):tag('td'):attr('colspan','2'):css('text-align','center'):css('background-color','#FFDF80')
	:css('font-weight','bold')
	:wikitext(title)
	for _, row in ipairs(details) do
		if row.content then
			tRow= tab:tag('tr'):css('vertical-align','top')
			tRow:tag('td'):css('width','40%'):css('font-weight','bold')
			:wikitext(row.name)
			tRow:tag('td'):wikitext(row.content)
		end
	end
end

local function infoFillOthersMap(tab, others)
	if others[3].content then -- map
		tab:tag('tr'):tag('td'):attr('colspan','2'):css('text-align','center')
		:wikitext("[[File:".. others[3].content .. "|center|300px]]")
	end
	if others[4].content then -- map
		tab:tag('tr'):tag('td'):attr('colspan','2'):css('text-align','center')
		:wikitext("[[File:".. others[4].content .. "|center|300px]]")
	end
end

local function wdDoc(tab, s, translation, ID)
	tab:tag('tr'):tag('td'):attr('colspan','2')
	:cssText('text-align:right; border-top:3px solid #FFDF80; font-size:75%')
	:wikitext("[[" .. s .. "|" .. translation .. "]] [[File:Wikidata-logo S.svg|12px|link=d:".. ID .."]]")
end

--== D) Stage infobox
function p.stageinfobox(frame)
	local details = {
		{ name = translate("stageinfobox",2)}, -- course / not used
		{ name =  translate("stageinfobox",2)}, -- competition
		{ name = translate("stageinfobox",3), name_plural = translate("infobox",4)}, -- stage type 
		{ name = translate("stageinfobox",4), name_plural = translate("infobox",7)}, -- date
		{ name = translate("stageinfobox",6)}, -- distance
		{ name = translate("stageinfobox",7), name_plural = translate("infobox",10)}, -- country
		{ name = translate("stageinfobox",9)}, -- start place
		{ name = translate("stageinfobox",10)}, -- endplace
		{ name = translate("stageinfobox",11)}, -- participants at start
		{ name = translate("stageinfobox",12)}, -- participants at end
		{ name = translate("stageinfobox",13)}, -- speed
		{ name = translate("stageinfobox",44)}, -- elevation
		{ name = translate("infobox",32), special = true}, -- special 1
		{ name = translate("infobox",33), special = true}, -- special 2
	}
	local others = {
		{ name = translate("infobox",29)}, -- picture
		{ name = translate("infobox",30)}, -- caption
		{ name = translate("infobox",31)}, -- map
		{ name = 'sectional'}
	}
			--begin of the function
	local t_P642 = {
			[20882747]={'results', 'first'}, 
			[20882748]={'results', 'second'}, 
			[20882749]={'results', 'third'}, 
			[21686770]={'results', 'winner_fighting'},
			[2250962]={'results', 'cima_coppi'}, 
			[10452933]={'results', 'cima_pantani'},
			[20882763]={'gen', 'leader'}, 
			[20882764]={'gen', 'deuxieme'}, 
			[20882765]={'gen', 'troisieme'},
			[20883213]={'annex', 'montagne'}, 
			[20883140]={'annex', 'jeune'}, 
			[20883008]={'annex', 'points'},
			[20883329]={'annex', 'sprints'}, 
			[20893984]={'annex', 'super_combatif'}, 
			[20965880]={'annex', 'combine'},
			[27104688]={'annex', 'stage_volantes'}, 
			[27104684]={'annex', 'regularite'}, 
			[20882922]={'annex', 'equipe'},
			[27104271]={'annex', 'equipe_points'},
			[20882667]={'gen', 'leader'}, 
			[20882668]={'gen', 'deuxieme'}, 
			[20882669]={'gen', 'troisieme'},
			[20883212]={'annex', 'montagne'}, 
			[20883139]={'annex', 'jeune'}, 
			[20883007]={'annex', 'points'},
			[20883328]={'annex', 'sprints'}, 
			[20893983]={'annex', 'super_combatif'}, 
			[20893979]={'annex', 'combine'},
			[27067359]={'annex', 'stage_volantes'}, 
			[27067170]={'annex', 'regularite'},
			[27907747]={'annex', 'azzurri_ditalia'}, 
			[27907748]={'annex', 'azzurri_ditalia'},
			[27907714]={'annex', 'breakaway'}, 
			[27907715]={'annex', 'breakaway'},
			[20882921]={'annex', 'equipe'}, 
			[27104269]={'annex', 'equipe_points'}
	}
	
	local entityID = mw.text.trim(frame.args[1])
	local wikibase = mw.wikibase
	if type(entityID) ~= 'string' then error('parameter must be a string') end
	if not entityID:match('Q%d+') then error ('parameter must be a valid Wikidata item (ex: Q42)') end

	local localframe
	if string.match(frame:getParent():getTitle(), '%P+') == mw.site.namespaces.Template.name then
		localframe = frame:getParent()
	else
		localframe = frame
	end
	
	getLocalContent(details, localframe.args)
	getLocalContent(others, localframe.args)

	local timeOfRace
	local temp = firstValue(entityID, 'P31','id')
	icon = ''
	if temp and temp ~= 'Q18131152' then
		if temp=='Q2266066' or temp=='Q2348250' or temp=='Q485321' then 
			icon = " [[File:Cycling (track) pictogram.svg|35px]]"
		else 
			icon = " [[File:Cycling (road) pictogram.svg|35px]]" 
		end
		details[3].content = typeofstagelogo(entityID, true).." "..WPlinkpure(temp)
	end
	
	local name =  getLabelFallback(entityID, {wikilang, 'en', 'fr', 'de'}) or ''
	if wiki == 'fr' and name ~= nil then 
		name= mw.ustring.gsub(name, "^(%d+)([re]+)", "%1<sup>%2</sup> ") 
	end
    name= mw.ustring.gsub(name, "^(%a)",function (x) return mw.ustring.upper(x) end)
		
	infoGetOthers(others, entityID)	

	--name
	if course==nil then
		temp = firstValue(entityID, 'P1545')
		if temp then
			details[2].content =getStageLabel(temp)
			raceId = firstValue(entityID, 'P361','id')
			if raceId then
				details[2].content = details[2].content or '' .. '، '.. WPlinkpure(raceId)
				for k, p31 in statements(raceId, 'P31') do
					if race==nil then race={} end
					race[k] = p31.mainsnak.datavalue.value.id --for the jersey
				end
			end
		end
	end

	-- This function give a format to dates when P585 (date) is used in a single day race
	local pTime = firstValue(entityID, 'P585', 'time') -- P585 is 'point in time'
	if pTime then
		details[4].content = func_date(pTime, 'long')
		timeOfRace = pTime
	end
	
	local kmdistance
	if not details[5].content then details[5].content, kmdistance = getDistance(entityID, true) end -- distance
	
	infoGetCountry(details,6, entityID, timeOfRace)
	infoGetStartEnd(details,7, entityID)
	infoGetParticipants(details,9, entityID)
	if not details[11].content then details[11].content = getSpeed(entityID, true, kmdistance, 'P2417') end --speed
	if not details[12].content then 
		local elevation=getElevation(entityID) 
		if  elevation ~= nil then details[12].content =elevation else details[12].content = nil end
	end --Elevation

	local jerseyWPID, jersey_name
	local t_s = {
		order={'results', 'gen', 'annex'},
		results={show=false, 
			header=15, 
			order = {'first','second','third','winner_fighting','winner_fighting2','cima_coppi','cima_pantani'},
			first={translation=16},
			second={translation=17},
			third={translation=18},
			winner_fighting={translation=19},
			winner_fighting2={translation=19}, -- two winner_fighting possible
			cima_coppi={translation=40},
			cima_pantani={translation=41}
			},
		gen={show=false, 
			header=20, 
			order = {"leader", "deuxieme", "troisieme"},
			leader={translation=21},
			deuxieme={translation=22},
			troisieme={translation=23}
			},
		annex={show=false, 
			header=24, 
			order={"points","montagne","sprints","jeune","super_combatif","combine",
			"stage_volantes","regularite","azzurri_ditalia","breakaway","equipe","equipe_points"},
			points={translation=25},
			montagne={translation=26},
			sprints={translation=27},
			jeune={translation=28},
			super_combatif={translation=29},
			combine={translation=30},
			stage_volantes={translation=31},
			regularite={translation=32},
			azzurri_ditalia={translation=42},
			breakaway={translation=43},
			equipe={translation=33},
			equipe_points={translation=34}
			}
		}

	--Winner
	for _, p1346 in statements(entityID, 'P1346') do
		local id_speed, id_time, id_time_gap, id_points_a, id_points_b, type_ofclas, name_ofclas
		local q = p1346.qualifiers
		local riderId = p1346.mainsnak.datavalue.value.id

		id_time = qualifieramount(p1346, 'P2781')
		id_time_gap =qualifieramount(p1346, 'P2911')
		id_speed =qualifieramount(p1346, 'P2052')
		id_points_a = qualifieramount(p1346, 'P1358')
		id_points_b =qualifieramount(p1346, 'P1351')

		if riderId ~= nil then
			local riderLink,riderTeam  = subwinner(riderId, timeOfRace, q) --sub function to avoid code in double
			-- looks into race item if the winner has a P642 statement for showing the type of winner (points, mountain, ..)
			if q.P642 and q.P642[1].snaktype == 'value' then
				for _, vv in pairs(q.P642) do
					local qual = vv.datavalue.value['numeric-id']
					if qual~=nil and deprecated~='deprecated' and t_P642[qual] then
						if qual==21686770 and t_s['results']['winner_fighting'][1] ~= "" then 
							t_P642[qual][2] = 'winner_fighting2' 
						end
						type_ofclas=t_P642[qual][1] --annex or gen
						name_ofclas=t_P642[qual][2] --name of ranking
						local v=t_s[type_ofclas][name_ofclas]

						v['link']=riderLink    
						v['team']=riderTeam 
						v['rank']=isdisqualified(p1346,q) 
						v['time']=id_time 
						v['gap']=id_time_gap 
						if id_points_a then v['points']=id_points_a end 
						if id_points_b then v['points']=id_points_b end
						v['speed']=id_speed 
						if qual==27104271 and t_s.annex.equipe_points['link']==nil then
							t_s.annex.equipe_points['link']=riderId 
						end
						if qual==20882922 and t_s.annex.equipe['link']==nil then 
							t_s.annex.equipe['link']=riderId 
						end
						v['genre'] = getgendercode(riderId,'f')
					end
				end
			end
		end
	end
	local rank, deprecated, prop, order, thisorder
	local listoftable = {'results','gen'}

	-- look into P2417, stage classification, then p2321 gen classification
	for ii, thistable in ipairs(listoftable) do
		if ii==1 then
			prop='P2417'
			order = {'first', 'second', 'third'}
		else
			prop='P2321'
			order = {'leader', 'deuxieme', 'troisieme'}
		end
		
		for _, p2417 in statements(entityID, prop) do
			local q = p2417.qualifiers
			if q.P1352 and q.P1352[1].snaktype == 'value' then
				for _, q1352 in pairs(q.P1352) do
					rank = tonumber(q1352.datavalue.value.amount)
				end
				if rank == 1 or rank == 2 or rank == 3 then
					thisorder=order[rank]
					local v=t_s[thistable][thisorder]
					v['rank'] = isdisqualified(p2417, q)
					local thisid= p2417.mainsnak.datavalue.value.id
					v['link'],_  = subwinner(thisid, timeOfRace, q) 

					if v['gap'] == nil and v['time'] == nil then
						v['gap'] = qualifieramount(p2417, 'P2911') 
					end
					if v['gap'] == nil and v['time'] == nil then
						v['time'] = qualifieramount(p2417, 'P2781') 
					end
					v['speed'] = qualifieramount(p2417, 'P2052') 
					v['genre'] = getgendercode(thisid, 'f')
				end
			end
		end
	end

	listoftable={t_s.results,t_s.gen,t_s.annex}
	
	for _, thistable in ipairs(listoftable) do
		for _, v in ipairs(thistable.order) do --order is the list of all classification names
			if thistable[v]['link'] then
				thistable.show = true 
			end
		end
	end
	
	---General table
	local temp
	local width= '320px' -- size standard 320px, special 340px
	if t_s.annex.show == true and (wiki == 'no' or wiki == '..') then width= '340px' end
	tab= infoInitTab(width, name, icon)
	infoFillOthersDetails(tab, others, details,translate("stageinfobox",1))

-- ranking table, general and stage
	for _, value_order in ipairs(t_s.order) do
		local thistable =t_s[value_order] --results or gen or annex
		
		if thistable.show then -- if a section of the stageinfobox should be shown
			tCell=tab:tag('tr'):tag('td'):attr('colspan','2')
			tTab=tCell:tag('table'):attr('cellpadding','0'):attr('cellspacing','0'):css('width','100%')
			tCell=tTab:tag('tr'):tag('td'):attr('colspan','3')
			:cssText('border-bottom:5px solid #fff2cc; background-color:#FFE7A0; text-align:center')
			:css('font-weight','bold')
			:wikitext(translate("stageinfobox",thistable.header))

			for key, value in ipairs(thistable.order) do --value is the name of the class
				local v=thistable[value]
				if v['link'] then
					local a1
					a1, jersey_name, jerseyWPID = jersey_infobox( value, race, timeOfRace)
					if a1~='' then v['jersey'] = a1 end
					if v['speed']  then
						if wiki == 'fo' then
							v['speed'] = string.gsub(v['speed'], "%.", ",") 
						else
							local lang = mw.language.getContentLanguage()
							v['speed'] = '('.. lang:formatNum(v['speed'])..translate("unit",5)..')'
						end
					end
					if v['points'] then
						if v['points'] > 1 then 
							temp=translate("unit",7)
						else 
						    temp=translate("unit",6) 
						end 
						v['points'] = v['points']..temp
					end
					local title, k = string.gsub(translate("stageinfobox",v['translation']), " ", "&nbsp;")
					if k > 0 then title = string.gsub(title, "&nbsp;", "<br>", 1) end --&#32;
				
					--Create an empty column on the left
					tRow=tTab:tag('tr'):css('vertical-align','top')
					tCell=tRow:tag('td')
					:css('font-weight','bold')
					if v['team']~=nil or v['speed'] ~=nil then
						tCell:attr('rowspan','2')
					end
					tCell:cssText("width:1%;background-color:#fff2cc;text-align:" .. 
					textalign .. ";padding:0 2px 0 2px;white-space:nowrap")
				
					if value_order~='annex' and v['translation']~=40 and v['translation']~=41 then -- Cima Coppi, Cima Pantani with a line break
						if v['jersey'] == nil then
							if (value_order=='results') and (value=='winner_fighting' or value=='winner_fighting2' or value=='cima_coppi' or value=='cima_pantanii') then
								tCell:wikitext(translate("stageinfobox",v['translation']))
							else
								tCell:wikitext(number(v['genre'], key, wiki))
							end
						else
							if jerseyWPID=='' then
								temp=''
							else 
								temp="|link="..jerseyWPID
							end
							tCell:wikitext("[[File:"..v['jersey'].."|20px|"..title..temp.."]]")
						end
					else
						if v['jersey'] == nil then 
							tCell:wikitext(title)
						else
							if jerseyWPID=='' then
								if jersey_name ~= '' then 
									temp = "|"..jersey_name
								else
									temp=''
								end
							else 
								temp= "|link="..jerseyWPID
							end
							tCell:wikitext("[[File:"..v['jersey'].."|20px"..temp.."]]" .. title)
						end
					end
					
					tRow:tag('td'):cssText("padding:0 0.5em 0 0.5em;"..v['rank'])
					:wikitext( v['link'])
					tCell=tRow:tag('td'):cssText('text-align:right;font-size:85%;white-space:nowrap')

					if v['time'] then 
						tCell:wikitext(calculate_time(v['time']))
					end
					if v['gap'] then 
						tCell:wikitext('+ '.. calculate_time(v['gap']))
					end
					tCell:wikitext(v['points'])
				end
				
				tCell=tTab:tag('tr'):tag('td'):attr('colspan','2')
				if v['team']~=nil and v['speed'] ~=nil then -- team row
					tTab2=tCell:tag('table'):attr('cellpadding','0'):attr('cellspacing','0'):css('width','100%')
					tRow = tTab2:tag('tr')
					tRow:tag('td'):cssText('width:100%;text-align:" .. textalign .. ";padding-left:2px')
					:wikitext("("..v['team']..")") --add the team
					tRow:tag('td'):cssText('font-size:85%;vertical-align:top;white-space:nowrap')
					:wikitext(v['speed'])
				else
					if v['team']~=nil or v['speed'] ~=nil then
						tCell:cssText("text-align:" .. textalign .. ";padding-left:2px")
						if v['team'] ~= nil then
							tCell:wikitext("("..v['team']..")") --add the team
						end
						tCell:tag('span'):cssText("float:right;font-size:85%;"):wikitext(v['speed'])
					end
				end
			end
		end
	end
	
	infoFillOthersMap(tab, others)
	tab:node(getPreviousNextLine(entityID,true))
	wdDoc(tab, "d:Wikidata:WikiProject Cycling/Documentation/stageinfobox", translate("stageinfobox",39), frame.args[1])
	return tab
end

--== E) List of teams
function p.listofteams(frame)
	local raceID = frame.args[1]
	local teams = {} -- values will be {teamLink, teamCat, sortkey, index}
	local WDlink_on = (wiki == "mk" or wiki == "ja")

	local timeOfRace, errorMessage = gettimeOfRace(raceID)
	if not timeOfRace then return errorMessage end

	local teamCats = { -- {c,d,e} c = singular team type, d = plural team type, e = print order of the team types
		["Q6154783"]  = {4,5,1},   -- WorldTeam
		["Q80425135"] = {4,5,2},   -- UCI Women’s WorldTeam
		["Q20638319"] = {6,7,3},   -- ProTeam (2005-2014)
		["Q78464255"] = {6,7,4},   -- ProTeam (2020-)
		["Q382927"]   = {8,9,5},   -- UCI Professional Continental Team (2005-2019)
		["Q1756006"]  = {10,11,6}, -- UCI Continental Team
		["Q20639847"] = {16,17,7}, -- professional cycling team		
		["Q20653563"] = {20,21,8}, -- Groupe Sportif I
		["Q20653564"] = {22,23,9}, -- Groupe Sportif II
		["Q20653566"] = {24,25,10}, -- Groupe Sportif III	
		["Q2466826"]  = {28,29,11}, -- UCI Women’s Team
		["Q23726798"] = {12,13,12}, -- national cycling team
		["Q99658502"] = {12,13,12}, -- national cycling team "B"
		["Q20738667"] = {12,13,12}, -- national cycling team U23
		["Q54555994"] = {12,13,12}, -- national cycling team U19		
		["Q28492441"] = {12,13,13}, -- national cycling team with sponsor name
		["Q20652655"] = {18,19,14}, -- amateur cycling team
		["Q26849121"] = {30,31,14}, -- Women's amateur cycling team
		["Q20639848"] = {14,15,15}, -- club and region cycling team
		["Q20653570"] = {14,15,15}, -- club and region cycling team
	}

	local p1923 = mw.wikibase.getBestStatements(raceID, 'P1923') -- P1923 is participating teams
	local no = 0 -- Index used for stable sorting
	for _, v in pairs(p1923) do
		if v.mainsnak.snaktype == 'value' then
			no = no + 1
			local teamLink, teamCat, countryID = getTeamLinkCat(v.mainsnak.datavalue.value.id, timeOfRace, true, true)
			local flagImage = countryID and flag(countryID, timeOfRace) or ''
			teams[#teams + 1] = {flagImage .. ' ' .. teamLink, teamCat,
				teamCats[teamCat] and teamCats[teamCat][3] or 999, no}
		end
	end

	table.sort(teams, function(a,b)
		if a[3] < b[3] then return true end -- First sort key: Order from table teamCats
		if a[3] > b[3] then return false end
		return a[4] < b[4] -- Second key is the index to ensure stable sorting
	end)

	local function getHeader(CatID, count)
		local header, sitelink
		if teamCats[CatID] then
			local done=false
			if CatID=="Q2466826" then --name changed after 2020
				local year = timeOfRace and tonumber(string.sub(timeOfRace, 2, 5))
				if year and year>2019 then
					if count == 1 then
						header_label = translate("headoftableIII",32) -- singular name
					else
						header_label = translate("headoftableIII",33) -- plural name
					end
					done=true
				end
			end
			
			if done==false then
				if count == 1 then
					header_label = translate("headoftableIII",teamCats[CatID][1]) -- singular name
				else
					header_label = translate("headoftableIII",teamCats[CatID][2]) -- plural name
				end
			end
			if CatID=='Q78464255' then
				sitelink=wikibase.getSitelink('Q382927') --continental
			else
				sitelink=wikibase.getSitelink(CatID)
			end

			if sitelink ~= nil then 
				header = '[['..sitelink..'|'..header_label..']]'
			else
				header= header_label
			end
		end

		local tHeader=  mw.html.create('span'):css('font-size','1.2em'):css('font-weight','bold')
		if not header then
			-- Unknown team category. Get the label for the entity to display if possible
			header = (CatID and getLabelFallback(CatID, {wikilang, 'en', 'fr', 'de'})) or 'Unknown team category'
			tHeader:css('text-transform','capitalize')
		end
		tHeader:wikitext(header)
		
		-- Set parameter to show team count in front of each category
		local tTag=''
		local showcounter = 2
		if count >= showcounter then
			tTag=mw.html.create('small'):wikitext(' (' .. count ..')')
		end
		return tostring(tHeader)..tostring(tTag)
	end

	local oldOrder = 0
	local oldCatID
	local count = 0
	local list = ''
	local header
	
	local resulttable = mw.html.create('table')
	:cssText("max-width:95%; padding:0.5em; margin-right:1em; border:1px solid rgb(200,200,200)")
	local tCell = resulttable:tag('tr'):tag('td')

	for _, team in ipairs(teams) do
		local order = team[3]
		if order ~= oldOrder then --new cat
			if oldOrder > 0 then
				header = getHeader(oldCatID, count)
				tCell:wikitext(header)
				tCell:node(tOl)
			end
			count = 1
			oldOrder = order
			tOl = mw.html.create('ul') --reinit
		else
			count = count + 1
		end
		oldCatID = team[2]
        tOl:tag('li')
		:cssText("width:20em;display:inline-block;vertical-align:text-top")
		:wikitext(team[1])
	end
	--add last row
	header = getHeader(oldCatID, count)
	tCell:wikitext(header)
	tCell:node(tOl)

	local tableFooter1=mw.html.create('tr')
	tCell=tableFooter1:tag('td')
	:addClass('navigation-only')
	:attr('colspan',2)
	:cssText('border-top: 2px #FFDF80 solid; font-size: 80%;')
	tCell:tag('span'):css("float",floattable)
	:wikitext('[[File:Wikidata-logo S.svg|12px|link=d:' ..raceID .. '#P1923]]')
	
	resulttable:node(tableFooter1)
	return resulttable
end

--== F) Classifications
function p.UCIclassification(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 19, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {1, 2, 7}, -- translations 1, 2, 3, 7 in function headoftableII are printed in this order in the lower part of the table header
		item = string.gsub(frame.args[1] or frame:getParent().args[1], "%c", ""),
		property = 'P3494', -- property to use for this table
		team_classification = false, -- it is not a team classification table, its a rider classification table
		background = 'color', -- there is a background color for the first row
		displayteam=false
		}
	return new_classification(frame, s)
end

function p.pointsclassification(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 10, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {1, 2, 3, 7}, -- translations 1, 2, 3, 7 in function headoftableII are printed in this order in the lower part of the table header
		item = string.gsub(frame.args[1], "%c", ""),
		property = 'P3494', -- property to use for this table
		team_classification = false, -- it is not a team classification table, its a rider classification table
		background = 'color' -- there is a background color for the first row
		}
	return new_classification(frame, s)
end

function p.teamsclassificationbytime(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 14, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {3, 2, 4}, -- translations 3, 2, 4 in function headoftableII are printed in this order in the lower part of the table header
		item = frame.args[1],
		property = 'P3497', -- property to use for this table
		team_classification = true, -- it is a team classification table, its not a rider classification table
		background = 'strong' -- there is no background color for the first row, but the first row is formated strong
	}
	return new_classification(frame, s)
end

function p.teamsclassificationbypoints(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 15, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {3, 2, 7}, -- translations 3, 2, 7 in function headoftableII are printed in this order in the lower part of the table header
		item = frame.args[1],
		property = 'P3496', -- property to use for this table
		team_classification = true, -- it is a team classification table, its not a rider classification table
		background = 'strong' -- there is no background color for the first row, but the first row is formated strong
		}
	return new_classification(frame, s)
end

function p.stageclassification(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 8, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {1, 2, 3, 4}, -- translations 1, 2, 3, 4 in function headoftableII are printed in this order in the lower part of the table header
		item = frame.args[1],
		property = 'P2417', -- property to use for this table
		team_classification = false, -- it is not a team classification table, its a rider classification table
		background = false, -- there is no background color for the first row
		display_ref = tonumber(frame.args[2]) == 0 and 0 or 1
		}
	return new_classification(frame, s)
end

function p.generalclassification(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 9, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {1, 2, 3, 4}, -- translations 1, 2, 3, 4 in function headoftableII are printed in this order in the lower part of the table header
		item = frame.args[1],
		property = 'P2321', -- property to use for this table
		team_classification = false, -- it is not a team classification table, its a rider classification table
		background = 'color', -- there is a background color for the first row
		display_ref = tonumber(frame.args[2]) == 0 and 0 or 1
		}
	return new_classification(frame, s)
end

function p.generalclassificationpoint(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 9, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {1, 2, 3, 7}, -- translations 1, 2, 3, 7 in function headoftableII are printed in this order in the lower part of the table header
		item = frame.args[1],
		property = 'P2321', -- property to use for this table
		team_classification = false, -- it is not a team classification table, its a rider classification table
		background = 'color', -- there is a background color for the first row
		display_ref = tonumber(frame.args[2]) == 0 and 0 or 1
		}
	return new_classification(frame, s)
end

function p.generalclassificationforttt(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 9, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {3, 2, 4, 5, 6}, -- translations 3, 2, 4, 5, 6 in function headoftableII are printed in this order in the lower part of the table header
		item = frame.args[1],
		property = 'P2321', -- property to use for this table
		team_classification = true, -- it is a team classification table, its not a rider classification table
		background = false, -- there is no background color for the first row
		display_ref = tonumber(frame.args[2]) == 0 and 0 or 1
	}
	return new_classification(frame, s)
end

function p.teamtimetrialclassification(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 8, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {3, 2, 4, 5, 6}, -- translations 3, 2, 4, 5, 6 in function headoftableII are printed in this order in the lower part of the table header
		item = frame.args[1],
		property = 'P2417', -- property to use for this table
		team_classification = true, -- it is a team classification table, its not a rider classification table
		background = false, -- there is no background color for the first row
		display_ref = tonumber(frame.args[2]) == 0 and 0 or 1
	}
	return new_classification(frame, s)
end

function p.mountainsclassification(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 11, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {1, 2, 3, 7}, -- translations 1, 2, 3, 7 in function headoftableII are printed in this order in the lower part of the table header
		item = string.gsub(frame.args[1], "%c", ""),
		property = 'P4320', -- property to use for this table
		team_classification = false, -- it is not a team classification table, its a rider classification table
		background = 'color' -- there is a background color for the first row
		}
	return new_classification(frame, s)
end

function p.sprintsclassification(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 12, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {1, 2, 3, 7}, -- translations 1, 2, 3, 7 in function headoftableII are printed in this order in the lower part of the table header
		item = string.gsub(frame.args[1], "%c", ""),
		property = 'P4322', -- property to use for this table
		team_classification = false, -- it is not a team classification table, its a rider classification table
		background = 'color' -- there is a background color for the first row
		}
	return new_classification(frame, s)
end

function p.bestyoungclassificationbypoints(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 13, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {1, 2, 3, 7}, -- translations 1, 2, 3, 7 in function headoftableII are printed in this order in the lower part of the table header
		item = string.gsub(frame.args[1], "%c", ""),
		property = 'P4323', -- property to use for this table
		team_classification = false, -- it is not a team classification table, its a rider classification table
		background = 'color' -- there is a background color for the first row
		}
	return new_classification(frame, s)
end

function p.bestyoungclassification(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 13, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {1, 2, 3, 4}, -- translations 1, 2, 3, 7 in function headoftableII are printed in this order in the lower part of the table header
		item = string.gsub(frame.args[1], "%c", ""),
		property = 'P4323', -- property to use for this table
		team_classification = false, -- it is not a team classification table, its a rider classification table
		background = 'color' -- there is a background color for the first row
		}
	return new_classification(frame, s)
end

function p.u23classification(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 18, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {1, 2, 3, 4}, -- translations 1, 2, 3, 7 in function headoftableII are printed in this order in the lower part of the table header
		item = string.gsub(frame.args[1], "%c", ""),
		property = 'P4323', -- property to use for this table (same as best young classification)
		team_classification = false, -- it is not a team classification table, its a rider classification table
		background = 'color' -- there is a background color for the first row
		}
	return new_classification(frame, s)
end

function p.combinationclassification(frame)
local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 16, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {1, 2, 3, 7}, -- translations 1, 2, 3, 7 in function headoftableII are printed in this order in the lower part of the table header
		item = string.gsub(frame.args[1], "%c", ""),
		property = 'P4324', -- property to use for this table
		team_classification = false, -- it is not a team classification table, its a rider classification table
		background = 'color' -- there is a background color for the first row
		}
	return new_classification(frame, s)
end

function p.combativeclassification(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_1 = 17, -- translation 10 in function headoftableII is printed in the upper part of the table header
		header_2 = {1, 2, 3, 7}, -- translations 1, 2, 3, 7 in function headoftableII are printed in this order in the lower part of the table header
		item = string.gsub(frame.args[1], "%c", ""),
		property = 'P4321', -- property to use for this table
		team_classification = false, -- it is not a team classification table, its a rider classification table
		background = 'color' -- there is a background color for the first row
		}
	return new_classification(frame, s)
end

function p.custompointsclassification(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_2 = {1, 2, 3, 7}, -- translations 1, 2, 3, 7 in function headoftableII are printed in this order in the lower part of the table header
		header_1_text=string.gsub(frame.args[3], "%c", ""),
		item = string.gsub(frame.args[1], "%c", ""),
		property = string.gsub(frame.args[2], "%c", ""), -- property to use for this table
		team_classification = false, -- it is not a team classification table, its a rider classification table
		background = 'color' -- there is a background color for the first row
		}
	return new_classification(frame, s)
end

function p.customtimeclassification(frame)
	local s = {
		header_function = "headoftableII", -- translations are in function headoftableII
		header_2 = {1, 2, 3, 4}, -- translations 1, 2, 3, 7 in function headoftableII are printed in this order in the lower part of the table header
		header_1_text=string.gsub(frame.args[3], "%c", ""),
		item = string.gsub(frame.args[1], "%c", ""),
		property = string.gsub(frame.args[2], "%c", ""), -- property to use for this table
		team_classification = false, -- it is not a team classification table, its a rider classification table
		background = 'color' -- there is a background color for the first row
		}
	return new_classification(frame, s)
end

function new_classification(frame, s)
	local country = true
	for _, value in pairs(no_country_classification) do -- get data if country should be printed in this wiki
		if value == wiki then country = false end
	end
	local raceID = s.item

	--[=[ It is possible to give the classification tables in the article commands to change the standard behaviour. They could look like this:
	{{Cycling race/teamsclassificationbytime|Q18574623|newline=false|country=true}}
	{{Cycling race/teamsclassificationbytime|Q18574623|country= false|newline=false}}
	{{Cycling race/teamsclassificationbypoints|Q18574623|newline =true|country=true}}
	{{Cycling race/teamsclassificationbypoints|Q18574623|newline= true}}
	{{Cycling race/teamsclassificationbypoints|Q18574623|newline = false|country=false}}
	{{Cycling race/teamsclassificationbytime|Q18574623|newline=true|country=true}}

	One additional parameter is "newline" with the values "true" or "false". "newline" says, if there is a line brake after the table. Standard is
	no line break after the tables stageclassification and teamtimetrialclassification.
	The second parameter is "country" with the values "true" or "false". "country" tells the module to print the country column or not.
	Most wikis have as standard to print the country columns, some wikis prefer as standard not to show the country column. A few lines above,
	the command "if wiki == 'da' then country = false end" tells that daWiki do not want to see the country colums as standard. You can add your wiki
	here in, if you do not want to see them as standard. With the new parameter editors are able to tell the module in the article what to do.
	]=]

	local timeOfRace, errorMessage = gettimeOfRace(raceID)
	if not timeOfRace then return errorMessage end

	local plus = ''
	if string.match(frame:getParent():getTitle(), '%P+') == mw.site.namespaces.Template.name
	then localframe = frame:getParent() else localframe = frame end
	if localframe.args[1] ~= nil then localframe.args[1] = string.gsub(localframe.args[1], "%c", "") end

	if localframe.args.country ~= nil then -- switch country column on or off in the article
		if localframe.args.country == 'true' then country = true end
		if localframe.args.country == 'false' then country = false end
	end
	local tableHeader2_size = #s.header_2

	if s.header_1_text ==nil then s.header_1_text=translate(s.header_function,s.header_1) end --for custom title

	local tableBody = mw.html.create('table')
		:addClass('sortable')
		:attr('cellpadding', '0')
		:attr('cellspacing', '0')
		:css('border' , '0')

	local thisspan= mw.html.create('span'):cssText('float:left;'):wikitext('[[File:Wikidata-logo S.svg|12px|link=d:'.. raceID .. '#' .. s.property..']]')
	tableBody:tag('tr'):tag('th')
    :attr('colspan', tostring(tableHeader2_size + 1)):cssText("padding:2px 2px; text-align:center; background-color:#FFDF80")
	:wikitext(tostring(thisspan)..s.header_1_text)

	header= tableBody:tag('tr'):cssText("text-align:center;padding:2px 2px;white-space:nowrap")
	for i, k in ipairs(s.header_2) do
		if i ~= 2 or (country and available_list) then
			local head=header:tag('th'):wikitext(translate(s.header_function,k))
			if i == 1 then
				head:attr('colspan','2')
			end
		end
	end

	local t_Body = {} --contains all rows
	local tCell, bg_color, tStyle, temp, temp2
	local claims = mw.wikibase.getAllStatements(raceID, s.property)
	for l, m in pairs(claims) do -- look into all statements
		if m.mainsnak.snaktype == 'value' then
			local riderID = m.mainsnak.datavalue.value.id
			local q = m.qualifiers or {}
			local rank, riderLink, gender, countryID, teamLink
			local flagLink, countryName = '', ''
			local h = {
				jersey = {}, -- lots of jerseyID
				value = {'', '', '', ''} -- points, time, time_gap, speed
			}
			
			if q.P1352 and q.P1352[1].snaktype == 'value' then -- P1352 is ranking
				rank = tonumber(q.P1352[1].datavalue.value.amount)
			else
				rank = ''
			end
			
			if q.P1534 and q.P1534[1].snaktype == 'value' then
				local dnf=q.P1534[1].datavalue.value.id
				if dnf=='Q1210380' then riderDNF =translate("startlist",6)--"HD","NP","DQ"
					elseif dnf=='Q54881674' or dnf=='Q7113430' then riderDNF =translate("startlist",7)
					elseif dnf=='Q1210382' then riderDNF =translate("startlist",8)
					elseif dnf=='Q1229261' then riderDNF =translate("startlist",9)
					else riderDNF=''
				end
			else 
				riderDNF=''	
			end

			local cancelled=isdisqualified(m,q)

			if wiki == 'es' or wiki == 'fr' or wiki == 'ast' then
				--[[ These wikis need the gender to display the rank correct. Other wikis can skip this. ]]
				gender = getgendercode(riderID, 'n')
			end

			h.value[1] = qualifieramount(m, 'P1358')
			h.value[2] = qualifieramount(m, 'P2781')
			if q.P2911 and q.P2911[1].snaktype == 'value' then -- P2911 is time gap
				h.value[3] = tonumber(q.P2911[1].datavalue.value.amount)
				plus = '+ '
			end
			h.value[4] = qualifieramount(m, 'P2052')
			if q.P2912 then -- P2912 is distinctive jersey
				for _, v in pairs(q.P2912) do
					if v.snaktype == 'value' then
						table.insert(h.jersey, v.datavalue.value.id)
					end
				end
			end

			if s.team_classification then
				local _
				teamLink, _, countryID = getTeamLinkCat(riderID, timeOfRace, true)
			else
				riderLink = getRiderLink(riderID,timeOfRace)..(getReference(m) or '')
				teamLink = getTeam(riderID, timeOfRace, q)
				local p27 = getStatementForTime(riderID, 'P27', timeOfRace) --P27 is country of citizenship
				if p27 then
					countryID = p27.mainsnak.datavalue.value.id
				end
			end
			if countryID then
				flagLink = flag(countryID, timeOfRace)
				if available_list and country then
					if type(translations.list) == "function" then
						countryName = translations.list(countryID)
					end
					if countryName == '' then
						local label, lang = mw.wikibase.getLabelWithLang(countryID)
						--[[ Uses standard language fallback. Should not be nil, as all countries have English labels. ]]
						if lang == wikilang then
							countryName = label
						else
							countryName = label .. ' (' .. lang .. ')'
						end
					end
				end
			end

			-- find the right background color if a rider has more then one jersey
			-- see Wikidata:WikiProject Cycling/Kit to translate/Jerseys
			bg_color=nil
			if h.jersey[1] then
				if wiki == "ca" then bg_color_table["Q24257763"] = "lightpink" end
				for _, jersey in pairs(h.jersey) do
					if bg_color_table[jersey] then
						bg_color = bg_color_table[jersey]
						break
					end
				end
			end
			
			tStyle=''
			if rank == 1 then
				if s.background then -- values are 'strong' or 'color'
					tStyle = tStyle ..'font-weight:bold;' -- winner is formated bold
					if s.background == 'color' then
						if h.jersey[1] and bg_color then -- background color of winner depending on jersey
							tStyle = tStyle .. 'background-color:' ..bg_color
						end
					end
				end
			end

			local tBody = mw.html.create('tr'):cssText(tStyle) -- a row
			tBody:tag('td'):cssText("text-align:center;padding:2px 0.5em 2px 0.5em;white-space:nowrap;"..cancelled)
			:wikitext(number(gender, rank, wiki))
			tCell= tBody:tag('td'):cssText("text-align:" .. textalign .. ";padding:0 0.2em 0 0.2em;"..cancelled)

			if not s.team_classification then
				if not teamLink then teamLink = '' end
				if not available_list then
					tCell:wikitext(flagLink .. ' '.. riderLink .. jersey(h.jersey))
					if s.displayteam~=false then
						tBody:tag('td'):wikitext(teamLink)
					end
				else
					if country == true then
						tCell:wikitext(riderLink .. jersey(h.jersey) )
						tBody:tag('td'):wikitext( flagLink ..' '.. countryName)
					else
						tCell:wikitext(flagLink .. ' ' .. riderLink .. jersey(h.jersey))
					end
					if s.displayteam~=false then
						tBody:tag('td'):cssText("text-align:".. textalign ..";padding:0 0.2em 0 0.2em")
						:wikitext(teamLink)
					end
				end
			else --team
				if available_list==true and country then
					tCell:wikitext(teamLink .. jersey(h.jersey))
					tBody:tag('td'):wikitext(flagLink .. ' ' .. countryName)
				else
					tCell:wikitext(flagLink .. ' ' .. teamLink .. jersey(h.jersey))
				end
			end

				if s.header_2[4] == 4 then -- for table stageclassification, generalclassification, adds time and time gap
				if riderDNF=='' then
					if rank == 1 and h.value[2] then
						temp=calculate_time(h.value[2])
					elseif rank == 1 and h.value[3]==nil then --avoid a plus with nothing
						temp=''
					else
						temp=plus .. calculate_time(h.value[3])
					end
				else
					temp=riderDNF
				end
				tBody:tag('td'):cssText("text-align:right;padding:0 0.2em 0 0.2em"):wikitext(temp)
			end

			if s.header_2[4] == 7 or (s.header_2[3] == 7 and s.header_2[1] == 1) then -- for table pointsclassification, adds points
				--trick for UCI classification
				if riderDNF=='' then
					if h.value[1] then temp=h.value[1] else temp='' end
					tCell=tBody:tag('td'):cssText("text-align:right;padding:0 0.2em 0 0.2em")
					:wikitext(temp)	
					if type(h.value[1]) == "number" then
						if h.value[1] > 1 then
							temp2=translate("unit",7)
						else
							temp2=translate("unit",6)
						end
						tCell:tag('span'):cssText("font-size:80%"):wikitext(temp2)	
					end
				else
					tBody:tag('td'):cssText("text-align:right;padding:0 0.2em 0 0.2em"):wikitext(riderDNF)	
				end
			end

			if s.header_2[3] == 4 then
				if s.property == 'P2417' or s.property == 'P2321' then
					-- for tables teamtimetrialclassification or generaltttclassification, adds time
					tBody:tag('td'):cssText("text-align:right;padding:0 0.2em 0 0.2em")
					:wikitext(calculate_time(h.value[2]))
				end
			end

			if s.property == 'P3497' then -- for table teambytimeclassification, adds time and time gap
				if rank == 1 then 
					temp=calculate_time(h.value[2])
				else
					temp=plus .. calculate_time(h.value[3])
				end
				tBody:tag('td'):cssText("text-align:right;padding:0 0.2em 0 0.2em"):wikitext(temp)
			end

			if s.property == 'P3496' then -- for table teambypointsclassification, adds points
				tCell=tBody:tag('td'):cssText("text-align:right;padding:0 0.2em 0 0.2em")
			    :wikitext(h.value[1])
				if type(h.value[1]) == "number" then
					if h.value[1] > 1 then
						temp2=translate("unit",7)
					else
						temp2=translate("unit",6)
					end
					tCell:tag('span'):cssText("font-size:80%"):wikitext(temp2)	
				end
			end

			if s.header_2[4] == 5 then -- for table teamtimetrialclassification, adds time gap
				if l > 1 then temp= plus else temp='' end
				tBody:tag('td'):cssText("text-align:right;padding:0 0.2em 0 0.2em"):wikitext(temp..calculate_time(h.value[3]))	
			end

			if s.header_2[5] == 6 then -- for table teamtimetrialclassification, adds speed
				tCell=tBody:tag('td'):cssText("text-align:right;padding:0 0.2em 0 0.2em")
				if type(h.value[4]) == "number" then 
					tCell:wikitext(mw.ustring.format('%.3f', h.value[4]))
					:tag('span'):cssText("font-size:80%"):wikitext(translate("unit",5))
				end
			end
			if riderDNF=='' then
				t_Body[#t_Body + 1] = {(type(rank) == 'number') and rank or 999, tostring(tBody)}
			else --disqualified should be higher than not disqualified if the ranking was revided
				t_Body[#t_Body + 1] = {(type(rank) == 'number') and rank-0.1 or 999, tostring(tBody)}
			end
		end
	end
	
    tableBody=sortandconcat(t_Body, tableBody)
	local tableFooter1,tableFooter2
	if s.display_ref == 1 then
		tableFooter1=mw.html.create('tr')
		tCell=tableFooter1:tag('td')
		:addClass('navigation-only')
		:attr('colspan',tostring(tableHeader2_size + 1))
		:cssText('border-top: 2px #FFDF80 solid; font-size: 80%;')
		tableFooter2=mw.html.create('tr')
		tCell=tableFooter2:tag('td')
		:attr('colspan',tostring(tableHeader2_size + 1))
		:cssText("text-align:right")
		tCell:tag('small')
		:wikitext(race_reference(raceID))
	end
	
	--general table style and last line
	local tableStyle, tableNewline
	if localframe.args.newline == 'false' then -- parameter newline in WP article is 'false'
		tableStyle = "float:" .. floattable .. "; margin-right:0.5em; border:1px solid rgb(200,200,200)"
		tableNewline = ''
	end
	if localframe.args.newline == 'true' then -- parameter newline in WP article is 'true'
		tableStyle = "border:1px solid rgb(200,200,200)"
		tableNewline = '<br style="clear:left;">'
	end
	if localframe.args.newline == nil then -- no second parameter, compatible to the old code
		if s.property == 'P2417' then --stageclassification
			tableStyle = "float:"..floattable.."; margin-right:0.5em; border:1px solid rgb(200,200,200)"
			tableNewline = ''
		else
			tableStyle = "border:1px solid rgb(200,200,200)"
			tableNewline = '<br style="clear:left;">' -- everything else
		end
	end

	local finalTable= mw.html.create('table'):cssText(tableStyle)
	finalTable:tag('tr'):tag('td')
	:node(tableBody)
	if tableFooter1 then
		finalTable:node(tableFooter1)
		finalTable:node(tableFooter2)
	end

	return tostring(finalTable)..tableNewline
end

--=== G) Infobox ===
function p.infobox(frame)
	localframe = frame
	-- If true, winners will have Wikidata logos with link to Wikidata
	local WDlink_on = (wiki == "mk" or wiki == "ja")

	-- If true, winners will the team of the cyclist
	local team = true

	local details = {
		{ name = translate("infobox",2)}, -- course
		{ name = translate("infobox",3), name_plural = translate("infobox",4)}, -- competition
		{ name = translate("infobox",6), name_plural = translate("infobox",7)}, -- date
		{ name = translate("infobox",5)}, -- stages		
		{ name = translate("infobox",8)}, -- distance
		{ name = translate("infobox",9), name_plural = translate("infobox",10)}, -- country
		{ name = translate("infobox",11)}, -- start place
		{ name = translate("infobox",12)}, -- endplace
		{ name = translate("infobox",13)}, -- teams
		{ name = translate("infobox",14)}, -- participants at start
		{ name = translate("infobox",15)}, -- participants at end
		{ name = translate("infobox",16)}, -- speed
		{ name = translate("infobox",43)}, -- elevation
		{ name = translate("infobox",17)}, -- cost
		{ name = translate("infobox",32), special = true}, -- special 1
		{ name = translate("infobox",33), special = true}, -- special 2
	}
	local others = {
		{ name = translate("infobox",29)}, -- picture
		{ name = translate("infobox",30)}, -- caption
		{ name = translate("infobox",31)}, -- map
		{ name = 'sectional_view '}
	}
	local winners = {
		{ name = translate("infobox",19), QID = 'Q20882667' }, -- first
		{ name = translate("infobox",20), QID = 'Q20882668' }, -- second
		{ name = translate("infobox",21), QID = 'Q20882669' }, -- third
		{ name = translate("infobox",22), QID = 'Q20883007' }, -- points
		{ name = translate("infobox",23), QID = 'Q20883212' }, -- mountains
		{ name = translate("infobox",24), QID = 'Q20883328' }, -- sprints
		{ name = translate("infobox",25), QID = 'Q20883139' }, -- youth
		{ name = translate("infobox",26), QID = 'Q20893983' }, -- combativity
		{ name = translate("infobox",35), QID = 'Q27067359' }, -- volantes
		{ name = translate("infobox",36), QID = 'Q27067170' }, -- regularity
		{ name = translate("infobox",27), QID = 'Q20893979' }, -- combination
		{ name = translate("infobox",38), QID = 'Q27907715' }, -- breakaway
		{ name = translate("infobox",39), QID = 'Q27907747' }, -- azzurri
		{ name = translate("infobox",40), QID = 'Q28092831' }, -- rookie
		{ name = translate("infobox",28), QID = 'Q20882921' }, -- teams
		{ name = translate("infobox",37), QID = 'Q27104269' }, -- teamspoints
		{ name = translate("infobox",41), QID ='Q61976850' },-- amateur
		{ name = translate("infobox",42), QID ='Q61976872' } --nationality
	}

	local entityID = mw.text.trim(frame.args[1])
	local wikibase = mw.wikibase
	if type(entityID) ~= 'string' then error('parameter must be a string') end
	if not entityID:match('Q%d+') then error ('parameter must be a valid Wikidata item (ex: Q42)') end

	local localframe
	if string.match(frame:getParent():getTitle(), '%P+') == mw.site.namespaces.Template.name then
		localframe = frame:getParent()
	else
		localframe = frame
	end
	getLocalContent(details, localframe.args)
	getLocalContent(others, localframe.args)
	getLocalContent(winners, localframe.args)

	local timeOfRace, class
	local icon = (firstValue(entityID, 'P641', 'numeric-id') == 3609) and -- P641 is 'sport', Q3609 is 'road bicycle racing'
		' [[File:Cycling (road) pictogram.svg|35px]]' or ''

	local name =  getLabelFallback(entityID, {wikilang, 'en', 'fr', 'de'}) or ''
	infoGetOthers(others, entityID)	

	if not details[1].content then -- course
		-- For FR Wiki and Wikidata, exception that permit to display 1er, 2e... for the edition number ;
		-- for RU  -й is written after the value of P393
		local nr = firstValue(entityID, 'P393') -- P393 is 'edition number'
		if nr then
			if wiki == 'fr' then nr = (nr == 1) and "1<sup>re</sup> " or (nr .. "<sup>e</sup> ")
			elseif wiki == "nl" then nr = nr .. "e "
			elseif wiki == "ru" then nr = nr .. "-й "
			elseif wiki == "eo" then nr = nr .. "-a "
			elseif wiki == "hu" then nr = nr .. ". "
			else nr = nr .. ". "
			end
		end
		local is_a
		for _, p31 in statements(entityID, 'P31') do -- P31 is 'instance of'
			local instanceOf = p31.mainsnak.datavalue.value.id
			if instanceOf == 'Q27968055' then -- Q27968055 is 'recurrent event edition'
				-- do nothing
			elseif classes[instanceOf] then
				class = classLink(instanceOf)
			elseif instanceOf == "Q27020041" then -- Q27020041 is 'sports season'
				local season = firstValue(entityID, 'P3450', 'id') -- P3450 is 'sports season of league or competition'
				if season then
					is_a = raceLink(season)
				end
			else
				is_a = raceLink(instanceOf)
			end
		end
		if nr and is_a then
			details[1].content = nr .. ' ' .. is_a
		end
	end

	if not details[2].content then -- competition
		-- Class of a cycling race. Class is: 1.UWT, 2.UWT, 1.HC, ... add new classes, no problem
		-- Competition of the cycling race : UCI World Tour 2016, UCI Europe Tour 2016...
		local tours = {}
		for _, p361 in statements(entityID, 'P361') do -- P361 is 'part of'
			tours[#tours + 1] = raceLink(p361.mainsnak.datavalue.value.id)
		end
		if tours[1] then
			if #tours > 1 then
				details[2].name = details[2].name_plural
			end
			if class then
				tours[1] = tours[1] .. ' ' .. class
			end
			details[2].content = table.concat(tours, '<br/>')
		end
	end

	if not details[3].content then -- date
		local sTime = firstValue(entityID, 'P580', 'time') -- P580 is 'start time'
		local eTime = firstValue(entityID, 'P582', 'time') -- P582 is 'end time'
		if sTime and eTime then
			local startTime, endTime = getStartEndTime(sTime, eTime)
			details[3].content = startTime .. ' – ' .. endTime
			details[3].name = details[3].name_plural
			timeOfRace = eTime
		else
			-- This function give a format to dates when P585 (date) is used in a single day race
			local pTime = firstValue(entityID, 'P585', 'time') -- P585 is 'point in time'
			if pTime then
				details[3].content = func_date(pTime, 'long')
				timeOfRace = pTime
			end
		end
	end

	if not details[4].content then -- stages
		local stages = #wikibase.getAllStatements(entityID, 'P527') -- P527 is 'has part'
		if stages > 0 then
			details[4].content = stages
		end
	end
	
	local kmdistance
	if not details[5].content then details[5].content, kmdistance = getDistance(entityID, true) end -- distance

	infoGetCountry(details,6, entityID, timeOfRace)
	infoGetStartEnd(details,7, entityID)

	if not details[9].content then -- teams
		local teams = #wikibase.getBestStatements(entityID, 'P1923') -- P1923 is 'participating teams'
		if teams > 0 then
			details[9].content = teams
		end
	end

	infoGetParticipants(details,10, entityID)
	if not details[10].content or not details[11].content then
		local Allp710= wikibase.getAllStatements(entityID, 'P710')
		if Allp710 and #Allp710~=0 then
			if not details[10].content then details[10].content=#Allp710 end
			if not details[11].content then
				local maxrank=1
				for _, p710 in pairs(Allp710) do -- look into all statements
					local q = p710.qualifiers
					if q and q.P1352 and q.P1352[1].snaktype == 'value' then -- P1352 is ranking
						local riderRank = tonumber(q.P1352[1].datavalue.value.amount)
						if riderRank > maxrank then maxrank = riderRank end
					end
				end
				if maxrank~=1 then details[11].content=maxrank end
			end
		end
	end

	if not details[12].content then details[12].content = getSpeed(entityID, true, kmdistance, 'P2321') end --speed
	if not details[13].content then 
		local elevation=getElevation(entityID) 
		if  elevation then details[13].content =elevation else details[13].content = nil end
	end --Elevation
	
	if not details[14].content then -- cost
		local cost = firstValue(entityID, 'P2130') -- P2130 is cost
		if cost then
			local unit = cost.unit
			cost = contentLanguage:formatNum(tonumber(cost.amount))
			if wiki == 'fo' then cost = string.gsub(cost, "%.", ",") end
			if unit == "http://www.wikidata.org/entity/Q4916" then cost = cost .. ' €'
			elseif unit == "http://www.wikidata.org/entity/Q4917" then cost = cost .. ' $'
			end
			details[14].content = cost
		end
	end

	tab = infoInitTab("300px", name, icon)
	infoFillOthersDetails(tab, others, details,translate("infobox",1))
	
	local winRows=''
	local win = {}
	for _, v in pairs(winners) do
		if not v.content then
			win[v.QID] = ''
		end
	end
	winner(entityID, win, timeOfRace, false, WDlink_on, team, true)
	for _, v in pairs(winners) do
		if not v.content then
			if win[v.QID] ~= '' then
				v.content = win[v.QID]
			end
		end
		if v.content then
			tRow= mw.html.create('tr') :css('vertical-align','top')
			tRow:tag('td'):css('font-weight','bold'):wikitext(v.name)
			tRow:tag('td'):wikitext(v.content)
			winRows=winRows..tostring(tRow) --not elegant
		end
	end
	if winRows~= '' then
		tab:tag('tr'):tag('td'):attr('colspan','2')
		:cssText('border-bottom:5px solid white; background-color:#FFDF80; text-align:center')
		:css('font-weight','bold')
		:wikitext(translate("infobox",18))
		tab:wikitext(winRows)
	end

	if others[3].content then -- map
		tab:tag('tr'):tag('td'):attr('colspan','2'):css('text-align','center')
		:wikitext("[[File:".. others[3].content .. "|center|300px]]")
	end
	
	tab:node(getPreviousNextLine(entityID))
	wdDoc(tab, "d:Wikidata:WikiProject Cycling/Documentation/infobox", translate("infobox",34), entityID)
	return tab
end

--=== GG) Infoboxseason === A copy of the "G) Infobox" for the tournament seasons. Unnecessary parameters are not deleted. 
function p.infoboxseason(frame)
	localframe = frame
	-- If true, winners will have Wikidata logos with link to Wikidata
	local WDlink_on = (wiki == "mk" or wiki == "ja")

	-- If true, winners will the team of the cyclist
	local team = true

	local details = {
		{ name = translate("infobox",46)}, -- edition (1)
		{ name = translate("infobox",3), name_plural = translate("infobox",4)}, -- competition (2)
		{ name = translate("infobox",6), name_plural = translate("infobox",7)}, -- date (3)
		{ name = translate("infobox",45)}, -- rasing (4)		
		{ name = translate("infobox",47), name_plural = translate("infobox",48)}, -- location (country) (5)
		{ name = translate("infobox",49), name_plural = translate("infobox",50)}, -- organizer (6)
		{ name = translate("infobox",63), name_plural = translate("infobox",63)}, -- team class (7)	

--		{ name = translate("infobox",8)}, -- distance
--		{ name = translate("infobox",9), name_plural = translate("infobox",10)}, -- country
--		{ name = translate("infobox",11)}, -- start place
--		{ name = translate("infobox",12)}, -- endplace
--		{ name = translate("infobox",13)}, -- teams
--		{ name = translate("infobox",14)}, -- participants at start
--		{ name = translate("infobox",15)}, -- participants at end
--		{ name = translate("infobox",16)}, -- speed
--		{ name = translate("infobox",43)}, -- elevation
--		{ name = translate("infobox",17)}, -- cost
		{ name = translate("infobox",32), special = true}, -- special 1
		{ name = translate("infobox",33), special = true}, -- special 2
	}
	local others = {
		{ name = translate("infobox",29)}, -- picture
		{ name = translate("infobox",30)}, -- caption
		{ name = translate("infobox",31)}, -- map
		{ name = 'sectional_view '}
	}
	local winners = {
--		{ name = translate("infobox",19), QID = 'Q20882667' }, -- first
--		{ name = translate("infobox",20), QID = 'Q20882668' }, -- second
--		{ name = translate("infobox",21), QID = 'Q20882669' }, -- third
--		{ name = translate("infobox",22), QID = 'Q20883007' }, -- points
--		{ name = translate("infobox",23), QID = 'Q20883212' }, -- mountains
--		{ name = translate("infobox",24), QID = 'Q20883328' }, -- sprints
--		{ name = translate("infobox",25), QID = 'Q20883139' }, -- youth
--		{ name = translate("infobox",26), QID = 'Q20893983' }, -- combativity
--		{ name = translate("infobox",35), QID = 'Q27067359' }, -- volantes
--		{ name = translate("infobox",36), QID = 'Q27067170' }, -- regularity
--		{ name = translate("infobox",27), QID = 'Q20893979' }, -- combination
--		{ name = translate("infobox",38), QID = 'Q27907715' }, -- breakaway
--		{ name = translate("infobox",39), QID = 'Q27907747' }, -- azzurri
--		{ name = translate("infobox",40), QID = 'Q28092831' }, -- rookie
--		{ name = translate("infobox",28), QID = 'Q20882921' }, -- teams
--		{ name = translate("infobox",37), QID = 'Q27104269' }, -- teamspoints
--		{ name = translate("infobox",41), QID ='Q61976850' },-- amateur
--		{ name = translate("infobox",42), QID ='Q61976872' }, --nationality
		
		{ name = translate("infobox",52), QID = 'Q20882667' }, -- individual (first)
		{ name = translate("infobox",53), QID = 'Q20883139' }, -- youth
		{ name = translate("infobox",54), QID = 'Q27104269' }, -- team (teamspoints)
		{ name = translate("infobox",55), QID = 'Q98959152' }, -- team GS-I
		{ name = translate("infobox",56), QID = 'Q98959153' }, -- team GS-II
		{ name = translate("infobox",57), QID = 'Q98959155' }, -- team GS-III
		{ name = translate("infobox",58), QID = 'Q72068715' }, -- country
		{ name = translate("infobox",59), QID = 'Q72068724' }  -- country U23
	}

	local entityID = mw.text.trim(frame.args[1])
	local wikibase = mw.wikibase
	if type(entityID) ~= 'string' then error('parameter must be a string') end
	if not entityID:match('Q%d+') then error ('parameter must be a valid Wikidata item (ex: Q42)') end

	local localframe
	if string.match(frame:getParent():getTitle(), '%P+') == mw.site.namespaces.Template.name then
		localframe = frame:getParent()
	else
		localframe = frame
	end
	getLocalContent(details, localframe.args)
	getLocalContent(others, localframe.args)
	getLocalContent(winners, localframe.args)

	local timeOfRace, class
	local icon = (firstValue(entityID, 'P641', 'numeric-id') == 3609) and -- P641 is 'sport', Q3609 is 'road bicycle racing'
		' [[File:Cycling (road) pictogram.svg|35px]]' or ''

	local name =  getLabelFallback(entityID, {wikilang, 'en', 'fr', 'de'}) or ''
	infoGetOthers(others, entityID)	

	if not details[1].content then -- course
		-- For FR Wiki and Wikidata, exception that permit to display 1er, 2e... for the edition number ;
		-- for RU  -й is written after the value of P393
		local nr = firstValue(entityID, 'P393') -- P393 is 'edition number'
		if nr then
			if wiki == 'fr' then nr = (nr == 1) and "1<sup>re</sup> " or (nr .. "<sup>e</sup> ")
			elseif wiki == "nl" then nr = nr .. "e "
			elseif wiki == "ru" then nr = nr .. "-й "
			elseif wiki == "eo" then nr = nr .. "-a "
			elseif wiki == "hu" then nr = nr .. ". "
			else nr = nr .. ". "
			end
		end
		local is_a
		for _, p31 in statements(entityID, 'P31') do -- P31 is 'instance of'
			local instanceOf = p31.mainsnak.datavalue.value.id
			if instanceOf == 'Q27968055' then -- Q27968055 is 'recurrent event edition'
				-- do nothing
			elseif classes[instanceOf] then
				class = classLink(instanceOf)
			elseif instanceOf == "Q27020041" then -- Q27020041 is 'sports season'
				local season = firstValue(entityID, 'P3450', 'id') -- P3450 is 'sports season of league or competition'
				if season then
					is_a = raceLink(season)
				end
			else
				is_a = raceLink(instanceOf)
			end
		end
		if nr and is_a then
			details[1].content = nr .. ' ' .. is_a
		end
	end

	if not details[2].content then -- competition
		-- Class of a cycling race. Class is: 1.UWT, 2.UWT, 1.HC, ... add new classes, no problem
		-- Competition of the cycling race : UCI World Tour 2016, UCI Europe Tour 2016...
		local tours = {}
		for _, p361 in statements(entityID, 'P361') do -- P361 is 'part of'
			tours[#tours + 1] = raceLink(p361.mainsnak.datavalue.value.id)
		end
		if tours[1] then
			if #tours > 1 then
				details[2].name = details[2].name_plural
			end
			if class then
				tours[1] = tours[1] .. ' ' .. class
			end
			details[2].content = table.concat(tours, '<br/>')
		end
	end

	if not details[3].content then -- date
		local sTime = firstValue(entityID, 'P580', 'time') -- P580 is 'start time'
		local eTime = firstValue(entityID, 'P582', 'time') -- P582 is 'end time'
		if sTime and eTime then
			local startTime, endTime = getStartEndTime(sTime, eTime)
			details[3].content = startTime .. ' – ' .. endTime
			details[3].name = details[3].name_plural
			timeOfRace = eTime
		else
			-- This function give a format to dates when P585 (date) is used in a single day race
			local pTime = firstValue(entityID, 'P585', 'time') -- P585 is 'point in time'
			if pTime then
				details[3].content = func_date(pTime, 'long')
				timeOfRace = pTime
			end
		end
	end

	if not details[4].content then -- racing
		local stages = #wikibase.getAllStatements(entityID, 'P527') -- P527 is 'has part'
		if stages > 0 then
			details[4].content = stages
		end
	end

	if not details[5].content then -- location
		-- This function gives countries where the race take place
		local location = {}
		for _, p276 in statements(entityID, 'P276') do -- P276 is 'location'
			local placeID = p276.mainsnak.datavalue.value.id
			location[#location + 1] = getPlaceLink(placeID)	
		end
		if location[1] then
			if #location > 1 then
				details[5].name = details[5].name_plural
			end
			details[5].content = table.concat(location, ', ')
		end
	end

	if not details[6].content then -- organizer sitelink
		-- This feature gives organizers who hold a tournament
		local organizer = {}
		for _, p664 in statements(entityID, 'P664') do -- P664 is 'organizer'
			local placeID = p664.mainsnak.datavalue.value.id
		 	organizer[#organizer + 1] = getPlaceLink(placeID)
		end
		if organizer[1] then
			if #organizer > 1 then
				details[6].name = details[6].name_plural
			end
			details[6].content = table.concat(organizer, ', ')
		end
	end

	if not details[7].content then -- team
		-- This feature gives organizers who hold a tournament
		local team = {}
		for _, p2670 in statements(entityID, 'P2670') do -- P664 is 'team'
			local placeID = p2670.mainsnak.datavalue.value.id
			team[#team + 1] = getPlaceLink(placeID)
		end
		if team[1] then
			if #team > 1 then
				details[7].name = details[7].name_plural
			end
			details[7].content = table.concat(team, ', ')
		end
	end

--	local kmdistance
--	if not details[5].content then details[5].content, kmdistance = getDistance(entityID, true) end -- distance

--	infoGetCountry(details,6, entityID, timeOfRace)
--	infoGetStartEnd(details,7, entityID)

--	if not details[9].content then -- teams
--		local teams = #wikibase.getBestStatements(entityID, 'P1923') -- P1923 is 'participating teams'
--		if teams > 0 then
--			details[9].content = teams
--		end
--	end

--	infoGetParticipants(details,10, entityID)
--	if not details[10].content or not details[11].content then
--		local Allp710= wikibase.getAllStatements(entityID, 'P710')
--		if Allp710 and #Allp710~=0 then
--			if not details[10].content then details[10].content=#Allp710 end
--			if not details[11].content then
--				local maxrank=1
--				for _, p710 in pairs(Allp710) do -- look into all statements
--					local q = p710.qualifiers
--					if q and q.P1352 and q.P1352[1].snaktype == 'value' then -- P1352 is ranking
--						local riderRank = tonumber(q.P1352[1].datavalue.value.amount)
--						if riderRank > maxrank then maxrank = riderRank end
--					end
--				end
--				if maxrank~=1 then details[11].content=maxrank end
--			end
--		end
--	end

--	if not details[12].content then details[12].content = getSpeed(entityID, true, kmdistance, 'P2321') end --speed
--	if not details[13].content then 
--		local elevation=getElevation(entityID) 
--		if  elevation then details[13].content =elevation else details[13].content = nil end
--	end --Elevation
	
--	if not details[14].content then -- cost
--		local cost = firstValue(entityID, 'P2130') -- P2130 is cost
--		if cost then
--			local unit = cost.unit
--			cost = contentLanguage:formatNum(tonumber(cost.amount))
--			if wiki == 'fo' then cost = string.gsub(cost, "%.", ",") end
--			if unit == "http://www.wikidata.org/entity/Q4916" then cost = cost .. ' €'
--			elseif unit == "http://www.wikidata.org/entity/Q4917" then cost = cost .. ' $'
--			end
--			details[14].content = cost
--		end
--	end

	tab = infoInitTab("300px", name, icon)
	infoFillOthersDetails(tab, others, details,translate("infobox",64))
	
	local winRows=''
	local win = {}
	for _, v in pairs(winners) do
		if not v.content then
			win[v.QID] = ''
		end
	end
	winner(entityID, win, timeOfRace, false)
	for _, v in pairs(winners) do
		if not v.content then
			if win[v.QID] ~= '' then
				v.content = win[v.QID]
			end
		end
		if v.content then
			tRow= mw.html.create('tr') :css('vertical-align','top')
			tRow:tag('td'):css('font-weight','bold'):wikitext(v.name)
			tRow:tag('td'):wikitext(v.content)
			winRows=winRows..tostring(tRow) --not elegant
		end
	end
	if winRows~= '' then
		tab:tag('tr'):tag('td'):attr('colspan','2')
		:cssText('border-bottom:5px solid white; background-color:#FFDF80; text-align:center')
		:css('font-weight','bold')
		:wikitext(translate("infobox",51))
		tab:wikitext(winRows)
	end

	if others[3].content then -- map
		tab:tag('tr'):tag('td'):attr('colspan','2'):css('text-align','center')
		:wikitext("[[File:".. others[3].content .. "|center|300px]]")
	end
	
	tab:node(getPreviousNextLine(entityID))
	wdDoc(tab, "d:Wikidata:WikiProject Cycling/Documentation/infobox", translate("infobox",34), entityID)
	return tab
end

--=== GGG) InfoboxChamp === A copy of the "G) Infobox" for the for championships. Unnecessary parameters are not deleted.
function p.infoboxChamp(frame)
	localframe = frame
	-- If true, winners will have Wikidata logos with link to Wikidata
	local WDlink_on = (wiki == "mk" or wiki == "ja")

	-- If true, winners will the team of the cyclist
	local team = true

	local details = {
		{ name = translate("infobox",46)}, -- edition (1)
--		{ name = translate("infobox",3), name_plural = translate("infobox",4)}, -- competition
		{ name = translate("infobox",6), name_plural = translate("infobox",7)}, -- date (2)
		{ name = translate("infobox",9), name_plural = translate("infobox",10)}, -- country (3)	
		{ name = translate("infobox",67), name_plural = translate("infobox",68)}, -- location (city) (4)
		{ name = translate("infobox",61), name_plural = translate("infobox",62)}, -- arena / stadion (5)
		{ name = translate("infobox",60)}, -- medals (6)
		{ name = translate("infobox",13)}, -- team (7)			
		{ name = translate("infobox",49), name_plural = translate("infobox",50)}, -- organizer (8)

--		{ name = translate("infobox",8)}, -- distance
--		{ name = translate("infobox",9), name_plural = translate("infobox",10)}, -- country
--		{ name = translate("infobox",11)}, -- start place
--		{ name = translate("infobox",12)}, -- endplace
--		{ name = translate("infobox",13)}, -- teams
--		{ name = translate("infobox",14)}, -- participants at start
--		{ name = translate("infobox",15)}, -- participants at end
--		{ name = translate("infobox",16)}, -- speed
--		{ name = translate("infobox",43)}, -- elevation
--		{ name = translate("infobox",17)}, -- cost
		{ name = translate("infobox",32), special = true}, -- special 1
		{ name = translate("infobox",33), special = true}, -- special 2
	}
	local others = {
		{ name = translate("infobox",29)}, -- picture
		{ name = translate("infobox",30)}, -- caption
		{ name = translate("infobox",31)}, -- map
		{ name = 'sectional_view '}
	}
	local winners = {
--		{ name = translate("infobox",19), QID = 'Q20882667' }, -- first
--		{ name = translate("infobox",20), QID = 'Q20882668' }, -- second
--		{ name = translate("infobox",21), QID = 'Q20882669' }, -- third
--		{ name = translate("infobox",22), QID = 'Q20883007' }, -- points
--		{ name = translate("infobox",23), QID = 'Q20883212' }, -- mountains
--		{ name = translate("infobox",24), QID = 'Q20883328' }, -- sprints
--		{ name = translate("infobox",25), QID = 'Q20883139' }, -- youth
--		{ name = translate("infobox",26), QID = 'Q20893983' }, -- combativity
--		{ name = translate("infobox",35), QID = 'Q27067359' }, -- volantes
--		{ name = translate("infobox",36), QID = 'Q27067170' }, -- regularity
--		{ name = translate("infobox",27), QID = 'Q20893979' }, -- combination
--		{ name = translate("infobox",38), QID = 'Q27907715' }, -- breakaway
--		{ name = translate("infobox",39), QID = 'Q27907747' }, -- azzurri
--		{ name = translate("infobox",40), QID = 'Q28092831' }, -- rookie
--		{ name = translate("infobox",28), QID = 'Q20882921' }, -- teams
--		{ name = translate("infobox",37), QID = 'Q27104269' }, -- teamspoints
--		{ name = translate("infobox",41), QID ='Q61976850' },-- amateur
--		{ name = translate("infobox",42), QID ='Q61976872' }, --nationality
		
--		{ name = translate("infobox",52), QID = 'Q20882667' }, -- individual (first)
--		{ name = translate("infobox",53), QID = 'Q20883139' }, -- youth
--		{ name = translate("infobox",54), QID = 'Q27104269' }, -- team (teamspoints)
--		{ name = translate("infobox",55), QID = 'Q___' }, -- team GS-I
--		{ name = translate("infobox",56), QID = 'Q___' }, -- team GS-II
--		{ name = translate("infobox",57), QID = 'Q___' }, -- team GS-III
--		{ name = translate("infobox",58), QID = 'Q72068715' }, -- country
--		{ name = translate("infobox",59), QID = 'Q72068724' }  -- country U23
	}

	local entityID = mw.text.trim(frame.args[1])
	local wikibase = mw.wikibase
	if type(entityID) ~= 'string' then error('parameter must be a string') end
	if not entityID:match('Q%d+') then error ('parameter must be a valid Wikidata item (ex: Q42)') end

	local localframe
	if string.match(frame:getParent():getTitle(), '%P+') == mw.site.namespaces.Template.name then
		localframe = frame:getParent()
	else
		localframe = frame
	end
	getLocalContent(details, localframe.args)
	getLocalContent(others, localframe.args)
	getLocalContent(winners, localframe.args)

	local timeOfRace, class
	local icon = (firstValue(entityID, 'P641', 'numeric-id') == 3609) and -- P641 is 'sport', Q3609 is 'road bicycle racing'
		' [[File:Cycling (road) pictogram.svg|35px]]' or ''

	local name =  getLabelFallback(entityID, {wikilang, 'en', 'fr', 'de'}) or ''
	infoGetOthers(others, entityID)	

	if not details[1].content then -- course
		-- For FR Wiki and Wikidata, exception that permit to display 1er, 2e... for the edition number ;
		-- for RU  -й is written after the value of P393
		local nr = firstValue(entityID, 'P393') -- P393 is 'edition number'
		if nr then
			if wiki == 'fr' then nr = (nr == 1) and "1<sup>re</sup> " or (nr .. "<sup>e</sup> ")
			elseif wiki == "nl" then nr = nr .. "e "
			elseif wiki == "ru" then nr = nr .. "-й "
			elseif wiki == "eo" then nr = nr .. "-a "
			elseif wiki == "hu" then nr = nr .. ". "
			else nr = nr .. ". "
			end
		end
		local is_a
		for _, p31 in statements(entityID, 'P31') do -- P31 is 'instance of'
			local instanceOf = p31.mainsnak.datavalue.value.id
			if instanceOf == 'Q27968055' then -- Q27968055 is 'recurrent event edition'
				-- do nothing
			elseif classes[instanceOf] then
				class = classLink(instanceOf)
			elseif instanceOf == "Q27020041" then -- Q27020041 is 'sports season'
				local season = firstValue(entityID, 'P3450', 'id') -- P3450 is 'sports season of league or competition'
				if season then
					is_a = raceLink(season)
				end
			else
				is_a = raceLink(instanceOf)
			end
		end
		if nr and is_a then
			details[1].content = nr .. ' ' .. is_a
		end
	end

--	if not details[2].content then -- competition
		-- Class of a cycling race. Class is: 1.UWT, 2.UWT, 1.HC, ... add new classes, no problem
		-- Competition of the cycling race : UCI World Tour 2016, UCI Europe Tour 2016...
--		local tours = {}
--		for _, p361 in statements(entityID, 'P361') do -- P361 is 'part of'
--			tours[#tours + 1] = raceLink(p361.mainsnak.datavalue.value.id)
--		end
--		if tours[1] then
--			if #tours > 1 then
--				details[2].name = details[2].name_plural
--			end
--			if class then
--				tours[1] = tours[1] .. ' ' .. class
--			end
--			details[2].content = table.concat(tours, '<br/>')
--		end
--	end

	if not details[2].content then -- date
		local sTime = firstValue(entityID, 'P580', 'time') -- P580 is 'start time'
		local eTime = firstValue(entityID, 'P582', 'time') -- P582 is 'end time'
		if sTime and eTime then
			local startTime, endTime = getStartEndTime(sTime, eTime)
			details[2].content = startTime .. ' – ' .. endTime
			details[2].name = details[2].name_plural
			timeOfRace = eTime
		else
			-- This function give a format to dates when P585 (date) is used in a single day race
			local pTime = firstValue(entityID, 'P585', 'time') -- P585 is 'point in time'
			if pTime then
				details[2].content = func_date(pTime, 'long')
				timeOfRace = pTime
			end
		end
	end

	infoGetCountry(details,3, entityID, timeOfRace)
	
	if not details[4].content then -- location / sity 
		-- This function gives countries where the race take place
		local location = {}
		for _, p276 in statements(entityID, 'P276') do -- P276 is 'location'
			local placeID = p276.mainsnak.datavalue.value.id
			location[#location + 1] = getPlaceLink(placeID)	
		end
		if location[1] then
			if #location > 1 then
				details[4].name = details[4].name_plural
			end
			details[4].content = table.concat(location, ', ')
		end
	end

	if not details[5].content then -- arena / stadion
		-- This function gives countries where the race take place
		local location = {}
		for _, p276 in statements(entityID, 'P115') do -- P276 is 'location'
			local placeID = p276.mainsnak.datavalue.value.id
			location[#location + 1] = getPlaceLink(placeID)	
		end
		if location[1] then
			if #location > 1 then
				details[5].name = details[5].name_plural
			end
			details[5].content = table.concat(location, ', ')
		end
	end

	if not details[6].content then -- medals (racing)
		local stages = #wikibase.getAllStatements(entityID, 'P527') -- P527 is 'has part'
		if stages > 0 then
			details[6].content = stages
		end
	end

	if not details[7].content then -- teams
		local teams = #wikibase.getBestStatements(entityID, 'P1923') -- P1923 is 'participating teams'
		if teams > 0 then
			details[7].content = teams
		end
	end

	if not details[8].content then -- organizer sitelink
		-- This feature gives organizers who hold a tournament
		local organizer = {}
		for _, p664 in statements(entityID, 'P664') do -- P664 is 'organizer'
			local placeID = p664.mainsnak.datavalue.value.id
		 	organizer[#organizer + 1] = getPlaceLink(placeID)
		end
		if organizer[1] then
			if #organizer > 1 then
				details[8].name = details[8].name_plural
			end
			details[8].content = table.concat(organizer, ', ')
		end
	end

--	local kmdistance
--	if not details[5].content then details[5].content, kmdistance = getDistance(entityID, true) end -- distance

--	infoGetCountry(details,6, entityID, timeOfRace)
--	infoGetStartEnd(details,7, entityID)

--	if not details[9].content then -- teams
--		local teams = #wikibase.getBestStatements(entityID, 'P1923') -- P1923 is 'participating teams'
--		if teams > 0 then
--			details[9].content = teams
--		end
--	end

--	infoGetParticipants(details,10, entityID)
--	if not details[10].content or not details[11].content then
--		local Allp710= wikibase.getAllStatements(entityID, 'P710')
--		if Allp710 and #Allp710~=0 then
--			if not details[10].content then details[10].content=#Allp710 end
--			if not details[11].content then
--				local maxrank=1
--				for _, p710 in pairs(Allp710) do -- look into all statements
--					local q = p710.qualifiers
--					if q and q.P1352 and q.P1352[1].snaktype == 'value' then -- P1352 is ranking
--						local riderRank = tonumber(q.P1352[1].datavalue.value.amount)
--						if riderRank > maxrank then maxrank = riderRank end
--					end
--				end
--				if maxrank~=1 then details[11].content=maxrank end
--			end
--		end
--	end

--	if not details[12].content then details[12].content = getSpeed(entityID, true, kmdistance, 'P2321') end --speed
--	if not details[13].content then 
--		local elevation=getElevation(entityID) 
--		if  elevation then details[13].content =elevation else details[13].content = nil end
--	end --Elevation
	
--	if not details[14].content then -- cost
--		local cost = firstValue(entityID, 'P2130') -- P2130 is cost
--		if cost then
--			local unit = cost.unit
--			cost = contentLanguage:formatNum(tonumber(cost.amount))
--			if wiki == 'fo' then cost = string.gsub(cost, "%.", ",") end
--			if unit == "http://www.wikidata.org/entity/Q4916" then cost = cost .. ' €'
--			elseif unit == "http://www.wikidata.org/entity/Q4917" then cost = cost .. ' $'
--			end
--			details[14].content = cost
--		end
--	end

	tab = infoInitTab("300px", name, icon)
	infoFillOthersDetails(tab, others, details,translate("infobox",65))
	
	local winRows=''
	local win = {}
	for _, v in pairs(winners) do
		if not v.content then
			win[v.QID] = ''
		end
	end
	winner(entityID, win, timeOfRace, false, WDlink_on, team, true)
	for _, v in pairs(winners) do
		if not v.content then
			if win[v.QID] ~= '' then
				v.content = win[v.QID]
			end
		end
		if v.content then
			tRow= mw.html.create('tr') :css('vertical-align','top')
			tRow:tag('td'):css('font-weight','bold'):wikitext(v.name)
			tRow:tag('td'):wikitext(v.content)
			winRows=winRows..tostring(tRow) --not elegant
		end
	end
	if winRows~= '' then
		tab:tag('tr'):tag('td'):attr('colspan','2')
		:cssText('border-bottom:5px solid white; background-color:#FFDF80; text-align:center')
		:css('font-weight','bold')
		:wikitext(translate("infobox",51))
		tab:wikitext(winRows)
	end

	if others[3].content then -- map
		tab:tag('tr'):tag('td'):attr('colspan','2'):css('text-align','center')
		:wikitext("[[File:".. others[3].content .. "|center|300px]]")
	end
	
	tab:node(getPreviousNextLine(entityID))
	wdDoc(tab, "d:Wikidata:WikiProject Cycling/Documentation/infobox", translate("infobox",34), entityID)
	return tab
end

--=== H) Team roster
function p.teamroster(frame)
	localframe=frame
	local squadID
	if frame.args[1] then squadID = string.gsub(frame.args[1], "%c", "") end
	local flags, pays = {}, {}
	local riderName, riderBirthday,riderTeam, timeTeam, correctlanguage,riderStart, riderEnd
	local riderPosition, riderReason, riderRef, errorbool, errortext
	local riderReasonTable, riderTablecorrect, riderTablenotcorrect, riderTable = {}, {}, {}, {}
	local labelMissing = false
	local teamID, startOfSeason, stagiaire

	local slavicWikis = {mk = true, ru = true}
	local wikiisslavic = slavicWikis[wiki]
	local WDlink_on = wiki == "mk" or wiki == "ja" or wiki == "ru" or wiki == "he"
	local tableEndText = ''


	local function getreason(riderReason, riderRef, p527)
		local listofproperty={'P1642','P1643','P1534'}
		local outputTable={}

		if riderReason == nil then --if no riderReason before then look for it, otherwise don't touch it
			for _,v in ipairs(listofproperty) do
				for _, q in qualifiers(p527, v) do
					riderReason = q.value.id
				end
			end
			if riderReason then
				local label = string.gsub(wikibase.label(riderReason), "%b()", "") or getLabelFallback(riderReason,{'en', 'fr', 'de'})
				riderRef = getReference(p527, 1)
				riderReason = ', ' .. label
			end
		end
		return riderReason, riderRef
	end

	local function getposition(riderPosition,v)
		local stagiaire
		if riderPosition == nil then -- find the 'position' (P39) of a rider
			for _, q in qualifiers(v, 'P39') do
				stagiaire = q.value.id
				local label = string.gsub(wikibase.label(stagiaire), "%b()", "") or getLabelFallback(stagiaire,{'en', 'fr', 'de'})
				Sitelink = wikibase.getSitelink('Q2328847')
				if Sitelink then riderPosition=', ' .. "[["..Sitelink .."|"..label.."]]" end
			end
		end
		return riderPosition
	end

	local function trans(date, month, day)
		if date ~= '' and date~=nil then
			local _, _, y, m, d = string.find(date, "(%d+)-(%d+)-(%d+)")
			if m == '00' then m = month end
			if d == '00' then d = day end
			date = '+'..y..'-'..m..'-'..d..'T00:00:00Z'
			return date
		end
		return ''
	end

	local function findlastname(label,wiki)
		if not label then label = '' end
		local _, count = string.gsub(label, " ", " ")
		local names
		local a,b,c,d = '', '', '', ''
		local done = false
		if count ~= nil then count = count + 1 else count = 1 end

		if count > 1 then
			if count == 2 then
				if label ~= '' then
					a, b = string.match(label, "(%S+)%s+(%S+)")
					names = b..' '..a
				end
			else
				local name_parts_mk = {'да', 'ди', 'де', 'Де', 'ла', 'Ле', 'тен', 'ван', 'Ван'}
				local name_parts_ru = {'да', 'ди', 'де', 'Де', 'ла', 'Ле', 'тен', 'ван', 'Ван'}
				local name_parts    = {'da', 'de', 'di', 'De', 'la', 'Le', 'ten', 'van', 'Van'}
				if count == 3 and label ~= '' then
					a, b, c = string.match(label, "(%S+)%s+(%S+)%s+(%S+)")
					if wiki == 'mk' then
						for _,v in ipairs(name_parts_mk) do if b == v then names = b..' '..c..' '..a done = true break end end
					elseif wiki == 'ru' then
						for _,v in ipairs(name_parts_ru) do if b == v then names = b..' '..c..' '..a done = true break end end
					else
						for _,v in ipairs(name_parts) do if b == v then names = b..' '..c..' '..a done = true break end end
					end
					if not done then
						names = c..' '..a..' '..b
						done = true
					end
				end
				if count > 3 and label ~= '' then
					a, b, c, d = string.find(label, "(%S+)%s+(%S+)%s+(%S+)%s+(%S+)")
					if wiki == 'mk' then
						for _,v in ipairs(name_parts_mk) do if c == v then names = c..' '..d..' '..a..' '..b done = true break end end
						for _,v in ipairs(name_parts_mk) do if b == v then names = b..' '..c..' '..d..' '..a done = true break end end
					elseif wiki == 'ru' then
						for _,v in ipairs(name_parts_ru) do if c == v then names = c..' '..d..' '..a..' '..b done = true break end end
						for _,v in ipairs(name_parts_ru) do if b == v then names = b..' '..c..' '..d..' '..a done = true break end end
					else
						for _,v in ipairs(name_parts) do if c == v then names = c..' '..d..' '..a..' '..b done = true break end end
						for _,v in ipairs(name_parts) do if b == v then names = b..' '..c..' '..d..' '..a done = true break end end
					end
					if not done then names = b..' '..c..' '..d..' '..a end
				end
			end
		end
		return names or ''
	end

	local function findsortkey(riderID, correctlanguage, wikiisslavic)
		--find the last name to sort
		if wikiisslavic and correctlanguage then
			local label = wikibase.getLabelByLang(riderID, wiki)
			if not label then
				label = getLabelFallback(riderID, {'en', 'fr', 'de', 'es'})
				return findlastname(label,wiki)
			else
				local nametable = mw.text.split(label, ",")
				if nametable[2] then --there is a coma so the lastname is first
					return nametable[1]..nametable[2]
				else --no coma
					return findlastname(label,wiki) 
				end
			end
		else
			local label = getLabelFallback(riderID, {'en', 'fr', 'de', 'es'})
			return findlastname(label,wiki)
		end
	end

	local sort
	--[[
	The word 'sort' is used to sort the riders after the surname. It could look like this in the Wikipedia article
	{{Cycling race/teamroster|Q21769847
	| sort
	}}
	A rider called 'Laurens De Vreese' is sorted after 'De Vreese Laurens'. If you want to sort after 'Vreese Laurens De'
	change that in the code. In lv mkWiki and ruWiki sorting is standard, there is no need to switch sorting on in the article
	]]
	if string.match(frame:getParent():getTitle(), '%P+') == mw.site.namespaces.Template.name
	then localframe = frame:getParent() else localframe = frame end
	if localframe.args[2] ~= nil then
		if mw.ustring.find(mw.ustring.lower(localframe.args[2]), "sort") then sort = true else sort = false end
	end
	if wiki == "lv" or wiki == "mk" or wiki == "ru" then sort = true end

	local temp = firstValue(squadID, 'P361', 'id')
	if temp then teamID = temp end

	temp = firstValue(squadID, 'P580', 'time')
	if temp then
		startOfSeason = temp
	else
		local Sitelink=getSitelinkFallback(squadID,{'en', 'fr', 'de'})
		if Sitelink == nil then return '> Wikidata is missing data about the start time (P580) and end time (P582) of the season'
		else startOfSeason = '+'..string.match(Sitelink, '%d%d%d%d' ) ..'-01-01T00:00:00Z'
		end
	end

	for _, p527 in statements(squadID, 'P527') do
		--re-init
		riderName, riderBirthday, correctlanguage=nil, nil, nil
		riderTeam, timeTeam, riderReason, riderRef=nil, nil, nil, nil
		riderStart, riderEnd=nil, nil

		errortext=''
		local riderID = p527.mainsnak.datavalue.value.id
		riderName, correctlanguage =getRiderLink(riderID, startOfSeason) --label
		if WDlink_on==true then riderName=riderName..wdLink(riderID) end
		local timeOfRace = startOfSeason

		riderBirthday=firstValue(riderID, 'P569','time')

		if not wikiisslavic then correctlanguage=true end  --actually we never take a cyrillic name if no latin is found
		local sortkey = findsortkey(riderID, correctlanguage,  wikiisslavic)

		riderReason, iderRef=getreason(riderReason,riderRef,p527)

		for _, q in qualifiers(p527, 'P580') do
			local startdate = q.value['time']
			timeOfRace = startdate
			riderStart = func_date(trans(startdate,'01', '01'), 'small')
		end
		for _, q in qualifiers(p527, 'P582') do
			local enddate=q.value['time']
			riderEnd = func_date(trans(enddate,'12', '31'), 'small')
		end
		riderPosition=getposition(riderPosition,p527)

		local y1, m1, d1, y2, m2, d2, y3, m3, d3, date1, date2, date2temp
		local changedTime = '+0000-00-00'

		if teamID == nil then
			local p54 = getStatementForTime(riderID, 'P54', timeOfRace)
			if p54 then teamID = p54.mainsnak.datavalue.value.id end
		else
			for _, v in statements(riderID, 'P54') do -- look into all P54 teams
				date1=nil date2=nil date2temp=nil stagiaire=nil errorbool=nil
				local thisteamID = v.mainsnak.datavalue.value.id
				if thisteamID == teamID then
					riderReason, riderRef=getreason(riderReason,riderRef,v)
					if v.qualifiers and v.qualifiers["P580"] and v.qualifiers["P580"][1].snaktype == 'value' then
						date1=v.qualifiers["P580"][1].datavalue.value.time
					end
					date1 = trans(date1,'01','01')
					_, _, y1, m1, d1 = string.find(date1, "(%d+)-(%d+)-(%d+)")
					if v.qualifiers and v.qualifiers["P582"] and v.qualifiers["P582"][1].snaktype == 'value' then
						date2temp=v.qualifiers["P582"][1].datavalue.value.time
					end
					if date2temp==nil then
						if y1==nil then y1='2040' errorbool=2 end
						date2='+'..y1..'-12-31T00:00:00Z'
					else date2=date2temp end
					date2 = trans(date2,'12','31')
					_, _, y2, m2, d2 = string.find(date2, "(%d+)-(%d+)-(%d+)")
					_, _, y3, m3, d3 = string.find(startOfSeason, "(%d+)-(%d+)-(%d+)")
					if (y1 == y3 or y2 == y3) and ((y1 == y3 and (m1 ~= '01' or d1 ~= '01')) or (y2 == y3 and (m2 ~= '12' or d2 ~= '31'))) then
						-- riders who start after 1 January or end earlier then 31 December in the season
						riderStart = func_date(date1, 'small')
						if date2temp==nil then
							if y1==nil then y1='2040' errorbool=1 end
							riderEnd = func_date('+'..y1..'-12-31T00:00:00Z', 'small')
						else
							riderEnd = func_date(date2temp, 'small')
						end
						riderPosition=getposition(riderPosition,v)
					end
				else
					for _, q in qualifiers(v, 'P39') do
						stagiaire =q.value.id
					end
					if not stagiaire then
						if v.qualifiers and v.qualifiers["P580"] and v.qualifiers["P580"][1].snaktype == 'value' then
							date1=v.qualifiers["P580"][1].datavalue.value.time
						end
						date1 = trans(date1,'01','01')
						_, _, y1, m1, d1 = string.find(date1, "(%d+)-(%d+)-(%d+)")
						if y1==nil then y1='2040' errorbool=2 end
						if v.qualifiers and v.qualifiers["P582"] and v.qualifiers["P582"][1].snaktype == 'value' then
							date2temp=v.qualifiers["P582"][1].datavalue.value.time
							date2=date2temp
						else
							date2='+'..y1..'-12-31T00:00:00Z'
						end
						date2 = trans(date2,'12','31')
						_, _, y2, m2, d2 = string.find(date2, "(%d+)-(%d+)-(%d+)")
						_, _, y3, m3, d3 = string.find(startOfSeason, "(%d+)-(%d+)-(%d+)")
						if y1 <= y3 then -- start time < season time
							if date2temp~=nil then
								local timeP582 = trans(date2temp,'12', '31')
								if timeP582 >= changedTime then -- find maximum end time
									-- Case Pierre-Roger Latour: Chambéry CF (2012 - 2014), time season at 2013
									-- Task: changedTime should be after start time, but before startOfSeason
									local y4 = string.match(timeP582, "(%d+)-%d+-%d+")
									if y4 > y3 then changedTime = '+'..y3..'-12-31T00:00:00Z' else changedTime = timeP582 end
								end
							end
						end
						if changedTime ~= '+0000-00-00' then
							riderTeam = getTeam(riderID, changedTime, nil)
							local _, _, y1, _, _ = string.find(changedTime, "(%d+)-(%d+)-(%d+)")
							timeTeam = ' ('..y1..')'
						end
					end
				end
				if errorbool==1 then
					errortext=errortext..' missing qualifiers by team'
				elseif errorbool==2 then
					errortext=errortext..' missing qualifiers by rider'
				end
			end
		end
		--get the country
		local countryID
		local p27 = getStatementForTime(riderID, 'P27', timeOfRace) --P27 is country of citizenship
		if p27 then
			countryID = p27.mainsnak.datavalue.value.id
		end
		if countryID then
			pays = getCountryName(countryID)
			flags = flag(countryID, timeOfRace)
		end
		--save
		if correctlanguage == true then
			table.insert(riderTablecorrect, {sortkey, riderName, riderBirthday, riderTeam, timeTeam, riderStart, riderEnd, riderPosition, riderReason, riderRef, errorbool, errortext, pays,flags})
		else
			table.insert(riderTablenotcorrect, {sortkey, riderName, riderBirthday, riderTeam, timeTeam, riderStart, riderEnd, riderPosition, riderReason, riderRef, errorbool, errortext, pays,flags})
		end
	end

	-- sorting names
	if sort == true then
		table.sort(riderTablecorrect, function(a,b) return a[1]<b[1] end)
		table.sort(riderTablenotcorrect, function(a,b) return a[1]<b[1] end)
	end
	--merge
	for _, v in pairs (riderTablecorrect) do
		table.insert(riderTable, v)
	end
	for _, v in pairs (riderTablenotcorrect) do
		table.insert(riderTable, v)
	end

	local outputTable = mw.html.create('table')
	                        :addClass('sortable')
	                        :attr('cellpadding', '2')
	                        :attr('cellspacing', '0')
	                        :css('border' , '1px solid rgb(200,200,200)')
	                        :css('padding', '3px')
	outputTable:tag('tr'):cssText('background-color:#FFDF80;line-height:1.8em;')
	    :tag('th'):attr('colspan', 4):cssText('text-align:center;white-space:nowrap')
	    :wikitext('<span style="float:left">[[File:Wikidata-logo S.svg|12px|link=d:'.. frame.args[1].. '#P527]]</span>')
	    :wikitext(translate("getSquadTableColumn",7))
	local header = outputTable:tag('tr')
	header:tag('th'):cssText('text-align:center;padding:2px 20px 2px 2px;white-space:nowrap'):wikitext(translate("getSquadTableColumn",1))
	header:tag('th'):cssText('text-align:center;padding:2px 20px 2px 2px;white-space:nowrap'):wikitext(translate("getSquadTableColumn",2))
	if available_list and wiki ~= 'lv' then
	    header:tag('th'):cssText('text-align:center;padding:2px 20px 2px 2px;white-space:nowrap'):wikitext(translate("getSquadTableColumn",6))
	end
	header:tag('th'):cssText('text-align:center;padding:2px 20px 2px 2px;white-space:nowrap'):wikitext(translate("getSquadTableColumn",3))

	local temp
	local iii = 1
	for i, v in pairs (riderTable) do
		sortkey=v[1]
		riderName=v[2]
		riderBirthday=v[3]
		riderTeam=v[4]
		timeTeam=v[5]
		riderStart=v[6]
		riderEnd=v[7]
		riderPosition=v[8]
		riderReason=v[9]
		riderRef=v[10]
		errorbool=v[11]
		errortext=v[12]
		pays=v[13]
		flags=v[14]
		
		local tRow=outputTable:tag('tr'):css('line-height','1.8em')
		local tCell= tRow:tag('td'):cssText("padding:0 1em 0 0;white-space:nowrap")

		if not available_list or wiki == 'lv' then temp=flags..' ' else temp='' end
		tCell:wikitext(temp..riderName):attr('data-sort-value',sortkey)

		if riderStart~=nil or riderEnd~=nil then
			tCell:tag('span'):cssText("font-size:80%; color:#686868")
			local note=''
			if riderReason ~= nil then
				note = ', [[#tr_'..i..frame.args[1]..'|'..translate("getSquadTableColumn",4)..']]'
				if wiki == "ar" then note = '، [[#tr_'..i..frame.args[1]..'|'..translate("getSquadTableColumn",4)..']]' end
			end
			local temp
			if riderStart~=nil and riderEnd~=nil then
				temp=' ('..riderStart..'–'..riderEnd.. (riderPosition or '')..note..')'
			elseif riderStart~=nil then
				temp=' ('..riderStart..'–'..(riderPosition or '')..note..')'
			else
				temp=' ('..'–'..(riderPosition or '')..note..')'
			end
			tCell:wikitext(temp)
		elseif riderReason then
			tCell:tag('span'):cssText("font-size:80%; color:#686868")
			:wikitext('([[#tr_'..i..frame.args[1]..'|'..translate("getSquadTableColumn",4)..']]'.. ')')
		end
		tCell=tRow:tag('td'):cssText("text-align:right;white-space:nowrap")
		if wiki == 'lv' then
			local _, _, y1, m1, d1 = string.find(startOfSeason,"(%d+)-(%d+)-0*(%d+)")
			local _, _, y2, m2, d2 = string.find(riderBirthday or '',"(%d+)-(%d+)-0*(%d+)")
			tCell:wikitext(frame:expandTemplate{ title = 'Template:Birth date and age2', args = { y1, m1, d1, y2, m2, d2 } })
		else
			tCell:wikitext(func_date(riderBirthday or '', 'long'))
			if available_list then 
				tRow:tag('td'):wikitext(flags.. ' '..pays)
			end
		end

		if wiki =='he' then
			local isRtl = (mw.ustring.find(riderTeam, '|.*[א-ת]') or (not mw.ustring.find(riderTeam, '|') and mw.ustring.find(riderTeam, '[א-ת]')))
			if isRtl then
				tCell=tRow:tag('td'):cssText("padding:0 0.5em; text-align:right")
			else
				labelMissing = true -- FIXME: labelMissing is not functional in most languages. once we have infra support for it, move it there
				tCell=tRow:tag('td'):cssText("padding:0 0.5em; text-align:left")
			end
		else
			tCell=tRow:tag('td'):cssText("padding:0 0.5em; text-align:left")
		end
		if riderTeam then
			tCell:wikitext(riderTeam.. timeTeam..errortext)
		end
		--tableEndText is not a table
		if riderReason ~= nil or errortext ~= '' then
			local temp=errortext
			if riderReason and errortext then
				temp=riderReason ..errortext
			elseif riderReason then
				temp=riderReason
			end
			if iii == 1 then
				tableEndText = tableEndText.. translate("getSquadTableColumn",5)..': '.. riderName.. temp
			else
				tableEndText = tableEndText.. '<span style="color:white">'.. translate("getSquadTableColumn",5)..': </span>'.. riderName.. temp
			end
			iii = iii + 1
			if riderRef ~= nil then tableEndText = tableEndText..
				frame:extensionTag{name='ref', content=riderRef, args = {name='tr_'..iii..frame.args[1]}} end
			tableEndText = tableEndText.. '<br>'
		end
	end
	if labelMissing then outputTable:wikitext(getMissingLabelTrackingCategory()) end
	
	local UCIlink
	if wiki=="fr" then
		UCIlink="https://www.uci.org/fr/route/%C3%A9quipe"
	else
		UCIlink="https://www.uci.org/road/teams"
	end
	
	outputTable:tag('tr'):tag('td'):addClass("navigation-only")
	:attr('data-sort-value','zz')
	:attr('colspan',4)
	:cssText("border-top: 2px #FFDF80 solid; font-size: 80%;")
	:tag('tr')
	:tag('td'):attr('colspan',4)
	:attr('data-sort-value','zzz')
	:cssText("text-align:right")
	:tag('small'):wikitext(translate("race_reference", 1).."["..UCIlink..' UCI]')
	
	return tostring(outputTable)..tableEndText
end

--== I) List of winners ==
--== frame --> listofwinners_main
-- Shows three winners (1-2-3) in any classification
function p.listofwinners(frame)
	local winnersProperty = {'Q20882667','Q20882668','Q20882669'}
	local displayteamtemp = false -- display of a rider without a team
	if tonumber(frame.args[4]) ==1 then displayteamtemp = true end -- display of the rider with the team
	local s = {
		countryflag=true,
		beginyear=tonumber(frame.args[2]) or 0,			
		endyear=tonumber(frame.args[3]) or 0,
		displayteam=displayteamtemp, -- since the answer is "args[4]"		
		shapka=tonumber(frame.args[5]) or 0,
		winnersProperty=winnersProperty
		}
	return listofwinners_main(frame, s)
end

function p.listofwinnersChamp(frame)
	local winnersProperty = {'Q20882667','Q20882668','Q20882669'}
	local s = {
		countryflag=false,
		beginyear=tonumber(frame.args[2]) or 0,			
		endyear=tonumber(frame.args[3]) or 0,
		shapka=tonumber(frame.args[4]) or 0,
		winnersProperty=winnersProperty,
		displayteam = false
		}
	return listofwinners_main(frame, s)
end

function p.listofwinnersyoung(frame)
	local winnersProperty = {'Q20883139','Q72099969','Q72099972'}
	local displayteamtemp = false -- display of a rider without a team
	if tonumber(frame.args[4]) ==1 then displayteamtemp = true end -- display of the rider with the team
	local s = {
		countryflag=true,
		beginyear=tonumber(frame.args[2]) or 0,			
		endyear=tonumber(frame.args[3]) or 0,
		displayteam=displayteamtemp, -- since the answer is "args[4]"		
		shapka=tonumber(frame.args[5]) or 0,
		winnersProperty=winnersProperty
		}
	return listofwinners_main(frame, s)
end

function p.listofwinnersteamofpoint(frame)
	local winnersProperty = {'Q27104269','Q72065970','Q72065977'}
	local displayteamtemp = false -- display of a rider without a team
	if tonumber(frame.args[4]) ==1 then displayteamtemp = true end -- display of the rider with the team
	local s = {
		countryflag=true,
		beginyear=tonumber(frame.args[2]) or 0,			
		endyear=tonumber(frame.args[3]) or 0,
		displayteam=displayteamtemp, -- since the answer is "args[4]"		
		shapka=tonumber(frame.args[5]) or 0,
		winnersProperty=winnersProperty
		}
	return listofwinners_main(frame, s)
end

function p.listofwinnersGSI(frame)
	local winnersProperty = {'Q98959152','Q98959192','Q98959196'}
	local displayteamtemp = false -- display of a rider without a team
	if tonumber(frame.args[4]) ==1 then displayteamtemp = true end -- display of the rider with the team
	local s = {
		countryflag=true,
		beginyear=tonumber(frame.args[2]) or 0,			
		endyear=tonumber(frame.args[3]) or 0,
		displayteam=displayteamtemp, -- since the answer is "args[4]"		
		shapka=tonumber(frame.args[5]) or 0,
		winnersProperty=winnersProperty
		}
	return listofwinners_main(frame, s)
end

function p.listofwinnersGSII(frame)
	local winnersProperty = {'Q98959153','Q98959194','Q98959197'}
	local displayteamtemp = false -- display of a rider without a team
	if tonumber(frame.args[4]) ==1 then displayteamtemp = true end -- display of the rider with the team
	local s = {
		countryflag=true,
		beginyear=tonumber(frame.args[2]) or 0,			
		endyear=tonumber(frame.args[3]) or 0,
		displayteam=displayteamtemp, -- since the answer is "args[4]"		
		shapka=tonumber(frame.args[5]) or 0,
		winnersProperty=winnersProperty
		}
	return listofwinners_main(frame, s)
end

function p.listofwinnersGSIII(frame)
	local winnersProperty = {'Q98959155','Q98959195','Q98959198'}
	local displayteamtemp = false -- display of a rider without a team
	if tonumber(frame.args[4]) ==1 then displayteamtemp = true end -- display of the rider with the team
	local s = {
		countryflag=true,
		beginyear=tonumber(frame.args[2]) or 0,			
		endyear=tonumber(frame.args[3]) or 0,
		displayteam=displayteamtemp, -- since the answer is "args[4]"		
		shapka=tonumber(frame.args[5]) or 0,
		winnersProperty=winnersProperty
		}
	return listofwinners_main(frame, s)
end

function p.listofwinnerscountry(frame)
	local winnersProperty = {'Q72068715','Q72068718','Q72068721'}
	local displayteamtemp = false -- display of a rider without a team
	if tonumber(frame.args[4]) ==1 then displayteamtemp = true end -- display of the rider with the team
	local s = {
		countryflag=true,
		beginyear=tonumber(frame.args[2]) or 0,			
		endyear=tonumber(frame.args[3]) or 0,
		displayteam=displayteamtemp, -- since the answer is "args[4]"		
		shapka=tonumber(frame.args[5]) or 0,
		winnersProperty=winnersProperty
		}
	return listofwinners_main(frame, s)
end

function p.listofwinnerscountryU23(frame)
	local winnersProperty = {'Q72068724','Q72068725','Q72068729'}
	local displayteamtemp = false -- display of a rider without a team
	if tonumber(frame.args[4]) ==1 then displayteamtemp = true end -- display of the rider with the team
	local s = {
		countryflag=true,
		beginyear=tonumber(frame.args[2]) or 0,			
		endyear=tonumber(frame.args[3]) or 0,
		displayteam=displayteamtemp, -- since the answer is "args[4]"		
		shapka=tonumber(frame.args[5]) or 0,
		winnersProperty=winnersProperty
		}
	return listofwinners_main(frame, s)
end

function listofwinners_main(frame, s)
	local rows = {}
	frame.args[1] = string.gsub(frame.args[1], "%c", "")
	local raceID = frame.args[1]
	local WDlink_on = (wiki == "mk") or (wiki == "ja") or (wiki == "ru")
		-- WDlink_on is used to decide if a Wikidata logo will be shown
	local WPcontent = {
		row ={},
		code = {}
	}
	local beginyear=s.beginyear or 0
	local endyear=s.endyear or 0
	local shapka=s.shapka or 0

	local titletable={
-- winner:
		[ 'Q20882667' ]=translate("listofwinners",2), -- winner
		[ 'Q20883007' ]=translate("listofwinners",2), -- points  
		[ 'Q20883212' ]=translate("listofwinners",2), -- mountains
		[ 'Q20883328' ]=translate("listofwinners",2), -- sprints
		[ 'Q20883139' ]=translate("listofwinners",2), -- youth (time or point)
		[ 'Q20893983' ]=translate("listofwinners",2), -- combativity
		[ 'Q20893979' ]=translate("listofwinners",2), -- combination
		[ 'Q20882921' ]=translate("listofwinners",2), -- team (time)
		[ 'Q27067359' ]=translate("listofwinners",2), -- volantes
		[ 'Q27067170' ]=translate("listofwinners",2), -- regularity
		[ 'Q27104269' ]=translate("listofwinners",2), -- teampoints
		[ 'Q27907715' ]=translate("listofwinners",2), -- breakaway
		[ 'Q27907747' ]=translate("listofwinners",2), -- azzurri
		[ 'Q28092831' ]=translate("listofwinners",2), -- rookie
		[ 'Q61976850' ]=translate("listofwinners",2), -- amateur
		[ 'Q61976872' ]=translate("listofwinners",2), -- nationality
		[ 'Q72068715' ]=translate("listofwinners",2), -- winner country
		[ 'Q72068724' ]=translate("listofwinners",2), -- winner countryU23
		[ 'Q98959152' ]=translate("listofwinners",2), -- winner team GS-I
		[ 'Q98959153' ]=translate("listofwinners",2), -- winner team GS-II
		[ 'Q98959155' ]=translate("listofwinners",2), -- winner team GS-III		
-- 2 place:
		[ 'Q20882668' ]=translate("listofwinners",3), -- second		
		[ 'Q72065970' ]=translate("listofwinners",3), -- second teampoints
		[ 'Q72099969' ]=translate("listofwinners",3), -- youth (time or point)		
		[ 'Q72068718' ]=translate("listofwinners",3), -- second country
		[ 'Q72068725' ]=translate("listofwinners",3), -- second countryU23
		[ 'Q98959192' ]=translate("listofwinners",3), -- second team GS-I
		[ 'Q98959194' ]=translate("listofwinners",3), -- second team GS-II
		[ 'Q98959195' ]=translate("listofwinners",3), -- second team GS-III		
-- 3 place:
		[ 'Q20882669' ]=translate("listofwinners",4), -- third	
		[ 'Q72065977' ]=translate("listofwinners",4), -- third teampoints	
		[ 'Q72099972' ]=translate("listofwinners",4), -- youth (time or point)		
		[ 'Q72068721' ]=translate("listofwinners",4), -- third country
		[ 'Q72068729' ]=translate("listofwinners",4), -- third countryU23
		[ 'Q98959196' ]=translate("listofwinners",4), -- third team GS-I
		[ 'Q98959197' ]=translate("listofwinners",4), -- third team GS-II
		[ 'Q98959198' ]=translate("listofwinners",4), -- third team GS-III		
	}

	--localframe defined as global for references
	if string.match(frame:getParent():getTitle(), '%P+') == mw.site.namespaces.Template.name then
		localframe = frame:getParent()
	else
		localframe = frame
	end
	if localframe.args[1] then
		localframe.args[1] = string.gsub(localframe.args[1], "%c", "")
	end
--[=[
It is possible to give the table listofwinners in the article commands. It could look like this:
{{Cycling race/listofwinners|Q18574623
| above row 1: '''[[aaa bbb ccc]]''' xxx
}}
"above row x" inserts a new row above row x into the table. Content is what is behind the ":".
]=]
	if localframe.args[2] then
		for num, _ in pairs(localframe.args) do
			if num > 1 and mw.ustring.find(mw.ustring.lower(localframe.args[num]), 'row') then
				local _, _, key1, val = mw.ustring.find(localframe.args[num], "([^:]+)%s*:%s*(%C+)")
				local _, _, key01, key11, key12 = mw.ustring.find(key1, "(%a+)%s*(%a+)%s*(%d+)")
				key12 = tonumber(key12) key11 = mw.ustring.lower(key01..key11)
				if key11 == 'aboverow' then WPcontent.row[key12] = val WPcontent.code[key12] = 0  end --0 is above
				if key11 == 'belowrow' then WPcontent.row[key12] = val WPcontent.code[key12] = 1  end --0 is above	
			end
		end
	end
	
	local firstyeartodisplay=100
	local parts = mw.wikibase.getAllStatements(raceID, 'P527') -- P527 is 'has part'
	for _, part in ipairs(parts) do
		if part.rank ~= 'deprecated' and part.mainsnak.snaktype == 'value' then
			local partID = part.mainsnak.datavalue.value.id
			local timeOfRace
			local p = mw.wikibase.getBestStatements(partID, 'P585') -- P585 is 'point in time'
			if p[1] and p[1].mainsnak.snaktype == 'value' then
				timeOfRace = p[1].mainsnak.datavalue.value.time
			else
				p = mw.wikibase.getBestStatements(partID, 'P582') -- P582 is 'finish time' A season can last for two calendar years. Therefore, for the correct display, the end date is used, and not the start date of the season.
				if p[1] and p[1].mainsnak.snaktype == 'value' then
					timeOfRace = p[1].mainsnak.datavalue.value.time
				end
			end
			local year = timeOfRace and string.sub(timeOfRace, 2, 5) or '?'
			local month = timeOfRace and string.sub(timeOfRace, 7, 8) or '01'	
			if year == "?" then mw.log("no year at " .. partID ) end

			if (tonumber(year) or 0) >= beginyear then
			if endyear==0 or (tonumber(year) or 0)<=endyear then

						local thereisawinner=false
						
						local sitelink = mw.wikibase.getSitelink(partID)
						if sitelink then
							sitelink = '[[' .. sitelink .. '|' .. year .. ']]'
						else
							sitelink = year
						end
						if WDlink_on then
							sitelink = sitelink .. ' ' .. wdLink(partID)
						end
						local winners = {}
						for _, property in ipairs(s.winnersProperty) do winners[property]='' end
						local tCell
						local tCellstr=''
						
		 				local temp=firstValue(partID, 'P1346','id')
						if temp and temp=='Q30108381' then --race cancelled
							local cancelledlabel = getLabelFallback('Q30108381', {wikilang, 'en', 'fr', 'de'})
							tCell=mw.html.create('td'):attr('colspan','4')
							:cssText('text-align:center; font-style: italic')
							:wikitext(cancelledlabel)
							tCellstr=tostring(tCell)
						else
							winner(partID, winners, timeOfRace, not s.countryflag, WDlink_on,s.displayteam,true)
							for _, property in ipairs(s.winnersProperty) do
								tCell=mw.html.create('td'):wikitext(winners[property])
								if winners[property]~='' then 
									thereisawinner=true 
									if tonumber(year)<firstyeartodisplay then firstyeartodisplay=tonumber(year) end
								end
								tCellstr= tCellstr..tostring(tCell)
							end
						end
						if firstyeartodisplay<=tonumber(year) then
						    rows[#rows+1]={year..month, sitelink, tCellstr}
						end
					end
				end
			end
		end
	table.sort(rows, function(a, b) return a[1] < b[1] end) -- Sort by year
	
	local clear = "left"
	if wiki == "ar" then clear = "right" end
	
	--do not use hw.html here otherwise the begin and end year won't work
	local table_first = "<table cellpadding='4' cellspacing='0' style='"..standardtablecss.."'>"

	local tTitleRow=mw.html.create('tr')
	:cssText('background:#FFDF80; text-align:center')
	local tCell=tTitleRow:tag('th')
	if WDlink_on == false then
		tCell:tag('span'):css("float","left")
		:wikitext("[[File:Wikidata-logo S.svg|12px|link=d:"..raceID .. "#P527]]")
	end
	tCell:wikitext(translate("listofwinners",1)) --year
	for _, pp in ipairs(s.winnersProperty) do
		tTitleRow:tag('th'):wikitext(titletable[pp])
	end
	
	local table_center=''
	local nb_year_inrow=1
	local lastyear
	
	for i, row in ipairs(rows) do
		sitelink=row[2]

		local tRowWD=mw.html.create('tr')
		local tCell=tRowWD:tag('td'):css('text-align','left')
		
		if lastyear and mw.ustring.sub(row[1],1,4)==lastyear then
				nb_year_inrow=nb_year_inrow+1
				tCell:wikitext(sitelink..' ('..tostring(nb_year_inrow)..')') 
		else
			tCell:wikitext(sitelink)
			nb_year_inrow=1
		end
		lastyear=mw.ustring.sub(row[1],1,4)
		tRowWD:node(row[3]) --add the end of the row
		
		if WPcontent.row[i] then
			tRow=mw.html.create('tr'):tag('td'):attr('colspan','50')
			:css('text-align','center')
			tRow:wikitext(WPcontent.row[i])

			if WPcontent.code[i]==0 then --above
				table_center=table_center..tostring(tRow)
				table_center=table_center..tostring(tRowWD)
			else --below
				table_center=table_center..tostring(tRowWD)
				table_center=table_center..tostring(tRow)
			end
		else
			table_center=table_center..tostring(tRowWD)
		end
	end
	--firstpart with header no foot
	

	if shapka == 1 then -- standard header
		return table_center .. "</table>"	
	elseif shapka == 2 then	-- you need to add a title and you can add text at the beginning
		return table_center 
	else -- you need to add a title and you can add anything and anywhere
		return table_first .. tostring(tTitleRow) .. table_center .. "</table>"
	end
end

--== frame --> listofwinners_custom ==
function p.listofwinnerscustom(frame)
	local winnersProperty ={}
	--general
	if frame.args[5] ~= nil and tonumber(frame.args[5]) ==1 then table.insert( winnersProperty,'Q20882667') end
	--podium
	if frame.args[6] ~= nil and tonumber(frame.args[6]) ==1 then 
		table.insert( winnersProperty,'Q20882668') 
		table.insert( winnersProperty,'Q20882669') 
	end
	--points
	if frame.args[7] ~= nil and tonumber(frame.args[7]) ==1 then table.insert( winnersProperty, 'Q20883007' ) end
	--mounstain
	if frame.args[8] ~= nil and tonumber(frame.args[8]) ==1 then table.insert( winnersProperty, 'Q20883212' ) end
	-- sprints
	if frame.args[9] ~= nil and tonumber(frame.args[9]) ==1 then table.insert( winnersProperty, 'Q20883328' ) end
	-- youth
	if frame.args[10] ~= nil and tonumber(frame.args[10]) ==1 then table.insert( winnersProperty, 'Q20883139' ) end
	-- combativity
	if frame.args[11] ~= nil and tonumber(frame.args[11]) ==1 then table.insert( winnersProperty, 'Q20893983' ) end
	-- volante
	if frame.args[12] ~= nil and tonumber(frame.args[12]) ==1 then table.insert( winnersProperty, 'Q27067359' ) end
	-- regularity 
	if frame.args[13] ~= nil and tonumber(frame.args[13]) ==1 then table.insert( winnersProperty, 'Q27067170' ) end
	-- combination
	if frame.args[14] ~= nil and tonumber(frame.args[14]) ==1 then table.insert( winnersProperty, 'Q20893979' ) end
	-- breakaway
	if frame.args[15] ~= nil and tonumber(frame.args[15]) ==1 then table.insert( winnersProperty, 'Q27907715' ) end
	-- azzurri
	if frame.args[16] ~= nil and tonumber(frame.args[16]) ==1 then table.insert( winnersProperty, 'Q27907747' ) end
	-- rookie
	if frame.args[17] ~= nil and tonumber(frame.args[17]) ==1 then table.insert( winnersProperty, 'Q28092831' )	end 
	-- teams
	if frame.args[18] ~= nil and tonumber(frame.args[18]) ==1 then table.insert( winnersProperty, 'Q20882921' )	end
	 -- teamspoints
	if frame.args[19] ~= nil and tonumber(frame.args[19]) ==1 then table.insert( winnersProperty, 'Q27104269' ) end	
	-- amateur
	if frame.args[20] ~= nil and tonumber(frame.args[20]) ==1 then table.insert( winnersProperty, 'Q61976850' ) end	
	 --nationality
	if frame.args[21] ~= nil and tonumber(frame.args[21]) ==1 then table.insert( winnersProperty, 'Q61976872' ) end	
	-- country
	if frame.args[22] ~= nil and tonumber(frame.args[22]) ==1 then table.insert( winnersProperty, 'Q72068715' ) end	
	-- country U-23
	if frame.args[23] ~= nil and tonumber(frame.args[23]) ==1 then table.insert( winnersProperty, 'Q72068724' ) end	
	local s = {
		countryflag=true,
		beginyear=tonumber(frame.args[2]) or 0,			
		endyear=tonumber(frame.args[3]) or 0,
		shapka=tonumber(frame.args[4]) or 0,
		displayteam = false,
		winnersProperty=winnersProperty
		}
	return listofwinners_custom(frame, s)
end

function listofwinners_custom(frame, s)
	local rows = {}
	frame.args[1] = string.gsub(frame.args[1], "%c", "")
	local raceID = frame.args[1]
	local WDlink_on = (wiki == "mk") or (wiki == "ja") or (wiki == "ru")
		-- WDlink_on is used to decide if a Wikidata logo will be shown
	local WPcontent = {
		row ={},
		code = {}
	}
	local beginyear=s.beginyear or 0
	local endyear=s.endyear or 0
	local shapka=s.shapka or 0

	local titletable={
		[ 'Q20882667' ]=translate("listofwinners",2), -- winner
		[ 'Q20882668' ]=translate("listofwinners",3), -- second		
		[ 'Q20882669' ]=translate("listofwinners",4), -- third		
		[ 'Q20883007' ]=translate("listofwinners",5), -- points  
		[ 'Q20883212' ]=translate("listofwinners",6), -- mountains
		[ 'Q20883328' ]=translate("listofwinners",7), -- sprints
		[ 'Q20883139' ]=translate("listofwinners",8), -- youth
		[ 'Q20893983' ]=translate("listofwinners",9), -- combativity
		[ 'Q20893979' ]=translate("listofwinners",10), -- combination
		[ 'Q20882921' ]=translate("listofwinners",11), -- teams
		[ 'Q27067359' ]=translate("listofwinners",12), -- volantes
		[ 'Q27067170' ]=translate("listofwinners",13), -- regularity
		[ 'Q27104269' ]=translate("listofwinners",14), -- teamspoints
		[ 'Q27907715' ]=translate("listofwinners",15), -- breakaway
		[ 'Q27907747' ]=translate("listofwinners",16), -- azzurri
		[ 'Q28092831' ]=translate("listofwinners",17), -- rookie
		[ 'Q61976850' ]=translate("listofwinners",18), -- amateur
		[ 'Q61976872' ]=translate("listofwinners",19), -- nationality
		[ 'Q72068715' ]=translate("listofwinners",23), -- winner country
		[ 'Q72068724' ]=translate("listofwinners",24), -- winner countryU23

		[ 'Q20882667' ]=translate("listofwinners",20), -- winner
		[ 'Q20883139' ]=translate("listofwinners",21), -- youth
		[ 'Q27104269' ]=translate("listofwinners",22), -- teamspoints		
		[ 'Q72068715' ]=translate("listofwinners",23), -- winner country
		[ 'Q72068724' ]=translate("listofwinners",24), -- winner countryU23
		
	
	}

	--localframe defined as global for references
	if string.match(frame:getParent():getTitle(), '%P+') == mw.site.namespaces.Template.name then
		localframe = frame:getParent()
	else
		localframe = frame
	end
	if localframe.args[1] then
		localframe.args[1] = string.gsub(localframe.args[1], "%c", "")
	end
--[=[
It is possible to give the table listofwinners in the article commands. It could look like this:
{{Cycling race/listofwinners|Q18574623
| above row 1: '''[[aaa bbb ccc]]''' xxx
}}
"above row x" inserts a new row above row x into the table. Content is what is behind the ":".
]=]
	if localframe.args[2] then
		for num, _ in pairs(localframe.args) do
			if num > 1 and mw.ustring.find(mw.ustring.lower(localframe.args[num]), 'row') then
				local _, _, key1, val = mw.ustring.find(localframe.args[num], "([^:]+)%s*:%s*(%C+)")
				local _, _, key01, key11, key12 = mw.ustring.find(key1, "(%a+)%s*(%a+)%s*(%d+)")
				key12 = tonumber(key12) key11 = mw.ustring.lower(key01..key11)
				if key11 == 'aboverow' then WPcontent.row[key12] = val WPcontent.code[key12] = 0  end --0 is above
				if key11 == 'belowrow' then WPcontent.row[key12] = val WPcontent.code[key12] = 1  end --0 is above	
			end
		end
	end
	
	local firstyeartodisplay=2100
	local parts = mw.wikibase.getAllStatements(raceID, 'P527') -- P527 is 'has part'
	for _, part in ipairs(parts) do
		if part.rank ~= 'deprecated' and part.mainsnak.snaktype == 'value' then
			local partID = part.mainsnak.datavalue.value.id
			local timeOfRace
			local p = mw.wikibase.getBestStatements(partID, 'P585') -- P585 is 'point in time'
			if p[1] and p[1].mainsnak.snaktype == 'value' then
				timeOfRace = p[1].mainsnak.datavalue.value.time
			else
				p = mw.wikibase.getBestStatements(partID, 'P580') -- P580 is 'start time'
				if p[1] and p[1].mainsnak.snaktype == 'value' then
					timeOfRace = p[1].mainsnak.datavalue.value.time
				end
			end
			local year = timeOfRace and string.sub(timeOfRace, 2, 5) or '?'
			local month = timeOfRace and string.sub(timeOfRace, 7, 8) or '01'	
			if year == "?" then mw.log("no year at " .. partID ) end

			if endyear==0 or (tonumber(year) or 0)<=endyear then
			if (tonumber(year) or 0) >= beginyear then
	
						local thereisawinner=false
						
						local sitelink = mw.wikibase.getSitelink(partID)
						if sitelink then
							sitelink = '[[' .. sitelink .. '|' .. year .. ']]'
						else
							sitelink = year
						end
						if WDlink_on then
							sitelink = sitelink .. ' ' .. wdLink(partID)
						end
						local winners = {}
						for _, property in ipairs(s.winnersProperty) do winners[property]='' end
						local tCell
						local tCellstr=''
						
		 				local temp=firstValue(partID, 'P1346','id')
						if temp and temp=='Q30108381' then --race cancelled
							local cancelledlabel = getLabelFallback('Q30108381', {wikilang, 'en', 'fr', 'de'})
							tCell=mw.html.create('td'):attr('colspan','4')
							:cssText('text-align:center; font-style: italic')
							:wikitext(cancelledlabel)
							tCellstr=tostring(tCell)
						else
							winner(partID, winners, timeOfRace, not s.countryflag, WDlink_on,s.displayteam,true)
							for _, property in ipairs(s.winnersProperty) do
								tCell=mw.html.create('td'):wikitext(winners[property])
								if winners[property]~='' then 
									thereisawinner=true 
									if tonumber(year)<firstyeartodisplay then firstyeartodisplay=tonumber(year) end
								end
								tCellstr= tCellstr..tostring(tCell)
							end
						end
						if firstyeartodisplay<=tonumber(year) then
						    rows[#rows+1]={year..month, sitelink, tCellstr}
						end
					end
				end
			end
		end
	table.sort(rows, function(a, b) return a[1] < b[1] end) -- Sort by year
	
	local clear = "left"
	if wiki == "ar" then clear = "right" end
	
	--do not use hw.html here otherwise the begin and end year won't work
	local table_first = "<table cellpadding='4' cellspacing='0' style='"..standardtablecss.."'>"

	local tTitleRow=mw.html.create('tr')
	:cssText('background:#FFDF80; text-align:center')
	local tCell=tTitleRow:tag('th')
	if WDlink_on == false then
		tCell:tag('span'):css("float","left")
		:wikitext("[[File:Wikidata-logo S.svg|12px|link=d:"..raceID .. "#P527]]")
	end
	tCell:wikitext(translate("listofwinners",1)) --year
	for _, pp in ipairs(s.winnersProperty) do
		tTitleRow:tag('th'):wikitext(titletable[pp])
	end
	
	local table_center=''
	local nb_year_inrow=1
	local lastyear
	
	for i, row in ipairs(rows) do
		sitelink=row[2]

		local tRowWD=mw.html.create('tr')
		local tCell=tRowWD:tag('td'):css('text-align','left')
		
		if lastyear and mw.ustring.sub(row[1],1,4)==lastyear then
				nb_year_inrow=nb_year_inrow+1
				tCell:wikitext(sitelink..' ('..tostring(nb_year_inrow)..')') 
		else
			tCell:wikitext(sitelink)
			nb_year_inrow=1
		end
		lastyear=mw.ustring.sub(row[1],1,4)
		tRowWD:node(row[3]) --add the end of the row
		
		if WPcontent.row[i] then
			tRow=mw.html.create('tr'):tag('td'):attr('colspan','50')
			:css('text-align','center')
			tRow:wikitext(WPcontent.row[i])

			if WPcontent.code[i]==0 then --above
				table_center=table_center..tostring(tRow)
				table_center=table_center..tostring(tRowWD)
			else --below
				table_center=table_center..tostring(tRowWD)
				table_center=table_center..tostring(tRow)
			end
		else
			table_center=table_center..tostring(tRowWD)
		end
	end
	--firstpart with header no foot
	
	if shapka == 1 then -- standard header
		return table_center .. "</table>"	
	elseif shapka == 2 then	-- you need to add a title and you can add text at the beginning
		return table_center 
	else -- you need to add a title and you can add anything and anywhere
		return table_first .. tostring(tTitleRow) .. table_center .. "</table>"
	end
end

function p.listofwinnersseason(frame)
	local winnersProperty ={}
	--general
	if frame.args[6] ~= nil and tonumber(frame.args[6]) ==1 then table.insert( winnersProperty,'Q20882667') end
	--podium
	if frame.args[7] ~= nil and tonumber(frame.args[7]) ==1 then 
		table.insert( winnersProperty,'Q20882668') 
		table.insert( winnersProperty,'Q20882669') 
	end
	-- youth
	if frame.args[8] ~= nil and tonumber(frame.args[8]) ==1 then table.insert( winnersProperty, 'Q20883139' ) end
	-- teamspoints
	if frame.args[9] ~= nil and tonumber(frame.args[9]) ==1 then table.insert( winnersProperty, 'Q27104269' ) end
	-- team GS-I
	if frame.args[10] ~= nil and tonumber(frame.args[10]) ==1 then table.insert( winnersProperty, 'Q98959152' ) end		
	-- team GS-II
	if frame.args[11] ~= nil and tonumber(frame.args[11]) ==1 then table.insert( winnersProperty, 'Q98959153' ) end	
	-- team GS-III
	if frame.args[12] ~= nil and tonumber(frame.args[12]) ==1 then table.insert( winnersProperty, 'Q98959155' ) end		
	-- country
	if frame.args[13] ~= nil and tonumber(frame.args[13]) ==1 then table.insert( winnersProperty, 'Q72068715' ) end	
	-- country U-23
	if frame.args[14] ~= nil and tonumber(frame.args[14]) ==1 then table.insert( winnersProperty, 'Q72068724' ) end	

	local displayteamtemp = false -- display of a rider without a team
	if tonumber(frame.args[4]) ==1 then displayteamtemp = true end -- display of the rider with the team
	
	local s = {
		countryflag=true,
		beginyear=tonumber(frame.args[2]) or 0,			
		endyear=tonumber(frame.args[3]) or 0,
		displayteam=displayteamtemp, -- since the answer is "args[4]"		
		shapka=tonumber(frame.args[5]) or 0,
		winnersProperty=winnersProperty
		}
--	local displayteamT =true--false
--	if frame.args[11] ~= nil and tonumber(frame.args[11]) ==1 then displayteamT =true end			
		
	return listofwinners_season(frame, s)
end

function listofwinners_season(frame, s)
	local rows = {}
	frame.args[1] = string.gsub(frame.args[1], "%c", "")
	local raceID = frame.args[1]
	local WDlink_on = (wiki == "mk") or (wiki == "ja") or (wiki == "ru")
		-- WDlink_on is used to decide if a Wikidata logo will be shown
	local WPcontent = {
		row ={},
		code = {}
	}
	local beginyear=s.beginyear or 0
	local endyear=s.endyear or 0
	local shapka=s.shapka or 0

	local titletable={
		[ 'Q20882667' ]=translate("listofwinners",20), -- winner
			[ 'Q20882668' ]=translate("listofwinners",3), -- second		
			[ 'Q20882669' ]=translate("listofwinners",4), -- third	
		[ 'Q20883139' ]=translate("listofwinners",21), -- youth
		[ 'Q27104269' ]=translate("listofwinners",22), -- teamspoints
		[ 'Q98959152' ]=translate("listofwinners",23), -- Groupe Sportif I 
		[ 'Q98959153' ]=translate("listofwinners",24), -- Groupe Sportif II	
		[ 'Q98959155' ]=translate("listofwinners",25), -- Groupe Sportif III		
		[ 'Q72068715' ]=translate("listofwinners",26), -- winner country
		[ 'Q72068724' ]=translate("listofwinners",27), -- winner countryU23
	}

	--localframe defined as global for references
	if string.match(frame:getParent():getTitle(), '%P+') == mw.site.namespaces.Template.name then
		localframe = frame:getParent()
	else
		localframe = frame
	end
	if localframe.args[1] then
		localframe.args[1] = string.gsub(localframe.args[1], "%c", "")
	end
--[=[
It is possible to give the table listofwinners in the article commands. It could look like this:
{{Cycling race/listofwinners|Q18574623
| above row 1: '''[[aaa bbb ccc]]''' xxx
}}
"above row x" inserts a new row above row x into the table. Content is what is behind the ":".
]=]
	if localframe.args[2] then
		for num, _ in pairs(localframe.args) do
			if num > 1 and mw.ustring.find(mw.ustring.lower(localframe.args[num]), 'row') then
				local _, _, key1, val = mw.ustring.find(localframe.args[num], "([^:]+)%s*:%s*(%C+)")
				local _, _, key01, key11, key12 = mw.ustring.find(key1, "(%a+)%s*(%a+)%s*(%d+)")
				key12 = tonumber(key12) key11 = mw.ustring.lower(key01..key11)
				if key11 == 'aboverow' then WPcontent.row[key12] = val WPcontent.code[key12] = 0  end --0 is above
				if key11 == 'belowrow' then WPcontent.row[key12] = val WPcontent.code[key12] = 1  end --0 is above	
			end
		end
	end
	
	local firstyeartodisplay=100
	local parts = mw.wikibase.getAllStatements(raceID, 'P527') -- P527 is 'has part'
	for _, part in ipairs(parts) do
		if part.rank ~= 'deprecated' and part.mainsnak.snaktype == 'value' then
			local partID = part.mainsnak.datavalue.value.id
			local timeOfRace
			local p = mw.wikibase.getBestStatements(partID, 'P585') -- P585 is 'point in time'
			if p[1] and p[1].mainsnak.snaktype == 'value' then
				timeOfRace = p[1].mainsnak.datavalue.value.time
			else
				p = mw.wikibase.getBestStatements(partID, 'P582') -- P582 is 'finish time' A season can last for two calendar years. Therefore, for the correct display, the end date is used, and not the start date of the season.
				if p[1] and p[1].mainsnak.snaktype == 'value' then
					timeOfRace = p[1].mainsnak.datavalue.value.time
				end
			end
			local year = timeOfRace and string.sub(timeOfRace, 2, 5) or '?'
			local month = timeOfRace and string.sub(timeOfRace, 7, 8) or '01'	
			if year == "?" then mw.log("no year at " .. partID ) end

			if endyear==0 or (tonumber(year) or 0)<=endyear then
			if (tonumber(year) or 0) >= beginyear then
	
						local thereisawinner=false
						
						local sitelink = mw.wikibase.getSitelink(partID)
						if sitelink then
							sitelink = '[[' .. sitelink .. '|' .. year .. ']]'
						else
							sitelink = year
						end
						if WDlink_on then
							sitelink = sitelink .. ' ' .. wdLink(partID)
						end
						local winners = {}
						for _, property in ipairs(s.winnersProperty) do winners[property]='' end
						local tCell
						local tCellstr=''
						
		 				local temp=firstValue(partID, 'P1346','id')
						if temp and temp=='Q30108381' then --race cancelled
							local cancelledlabel = getLabelFallback('Q30108381', {wikilang, 'en', 'fr', 'de'})
							tCell=mw.html.create('td'):attr('colspan','4')
							:cssText('text-align:center; font-style: italic')
							:wikitext(cancelledlabel)
							tCellstr=tostring(tCell)
						else
							winner(partID, winners, timeOfRace, not s.countryflag, WDlink_on,s.displayteam,true)
							for _, property in ipairs(s.winnersProperty) do
								tCell=mw.html.create('td'):wikitext(winners[property])
								if winners[property]~='' then 
									thereisawinner=true 
									if tonumber(year)<firstyeartodisplay then firstyeartodisplay=tonumber(year) end
								end
								tCellstr= tCellstr..tostring(tCell)
							end
						end
						if firstyeartodisplay<=tonumber(year) then
						    rows[#rows+1]={year..month, sitelink, tCellstr}
						end
					end
				end
			end
		end
	table.sort(rows, function(a, b) return a[1] < b[1] end) -- Sort by year
	
	local clear = "left"
	if wiki == "ar" then clear = "right" end
	
	--do not use hw.html here otherwise the begin and end year won't work
	local table_first = "<table cellpadding='4' cellspacing='0' style='"..standardtablecss.."'>"

	local tTitleRow=mw.html.create('tr')
	:cssText('background:#FFDF80; text-align:center')
	local tCell=tTitleRow:tag('th')
	if WDlink_on == false then
		tCell:tag('span'):css("float","left")
		:wikitext("[[File:Wikidata-logo S.svg|12px|link=d:"..raceID .. "#P527]]")
	end
	tCell:wikitext(translate("listofwinners",1)) --year
	for _, pp in ipairs(s.winnersProperty) do
		tTitleRow:tag('th'):wikitext(titletable[pp])
	end
	
	local table_center=''
	local nb_year_inrow=1
	local lastyear
	
	for i, row in ipairs(rows) do
		sitelink=row[2]

		local tRowWD=mw.html.create('tr')
		local tCell=tRowWD:tag('td'):css('text-align','left')
		
		if lastyear and mw.ustring.sub(row[1],1,4)==lastyear then
				nb_year_inrow=nb_year_inrow+1
				tCell:wikitext(sitelink..' ('..tostring(nb_year_inrow)..')') 
		else
			tCell:wikitext(sitelink)
			nb_year_inrow=1
		end
		lastyear=mw.ustring.sub(row[1],1,4)
		tRowWD:node(row[3]) --add the end of the row
		
		if WPcontent.row[i] then
			tRow=mw.html.create('tr'):tag('td'):attr('colspan','50')
			:css('text-align','center')
			tRow:wikitext(WPcontent.row[i])

			if WPcontent.code[i]==0 then --above
				table_center=table_center..tostring(tRow)
				table_center=table_center..tostring(tRowWD)
			else --below
				table_center=table_center..tostring(tRowWD)
				table_center=table_center..tostring(tRow)
			end
		else
			table_center=table_center..tostring(tRowWD)
		end
	end
	--firstpart with header no foot
	
	if shapka == 1 then -- standard header
		return table_center .. "</table>"	
	elseif shapka == 2 then	-- you need to add a title and you can add text at the beginning
		return table_center 
	else -- you need to add a title and you can add anything and anywhere
		return table_first .. tostring(tTitleRow) .. table_center .. "</table>"
	end
end

--== J) List of stages
function p.listofstages(frame)
	-- WDlink_on is used to decide if a Wikidata logo will be shown
	local WDlink_on = wiki == "mk" or wiki == "ja"
	local WPcontent = {}
	local raceID = frame.args[1]
	local thereiselevation=false
	local result, tableBody

	local localframe
	if string.match(frame:getParent():getTitle(), '%P+') == mw.site.namespaces.Template.name then
		localframe = frame:getParent()
	else
		localframe = frame
	end
	if localframe.args[1] then
		localframe.args[1] = string.gsub(localframe.args[1], "%c", "")
	end
--[=[ It is possible to give the table listofstages in the article commands which overwrites data from Wikidata.
It could look like this:
{{Cycling race/listofstages|Q18574623
| RoW 1: locaTION Ab : [[1a1b]]
| after row 1 : date : 99 août
| after row 1 : icon : [[File:Stage rest day.svg|vbght frthzt fdgtr]]
| after row 1: text : rest day at [[aaa bbb ccc]]
| row 4:  location A : [[4a4a]]abc
| row 3 : winner a : <sup>tzhgt</sup>
| row 4 : winner b : kjuzhgt<br />bbjje
| row 4 : icon : [[File:Mediummountainstage.svg|xcvbbgf fgtr]]
| row 4 : distance : <s>141.8</s> 122<ref>test</ref>
}}
The first paramer is "row x" or "after row x". "after row" adds a new row after row x into the table to print e.g. a rest day.
The second parameters are "location [a/b/ab]", "date", "icon", "text", "winner [a/b]" and "distance".
"a" and "b" means the first and the second location or winner. "ab" could be used if start location and
end location are the same. The file data for the icon looks this way: [[File:Stage rest day.svg|any text]]
]=]
	if localframe.args[2] then
		local WProw, WPnew_row, WPcourse, WPtext, WPdate, WPwinner, WPicon, WPdistance
			= 'row', 'afterrow', 'location', 'text', 'date', 'winner', 'icon', 'distance'
		local _, key1, key2, val
		local key01, key11, key12
		local key21, key22
		for num, var in pairs(localframe.args) do
			if num > 1 and mw.ustring.find(mw.ustring.lower(var), WProw) then
				_, _, key1, key2, val = mw.ustring.find(var, "([^:]+)%s*:?%s*([^:]*)%s*:%s*(%C+)")
				_, _, key01, key11, key12 = mw.ustring.find(key1, "(%a+)%s*(%a+)%s*(%d+)")
				key12 = tonumber(key12)
				key11 = mw.ustring.lower(key01 .. key11)
				key2 = mw.ustring.lower(mw.text.trim(key2))
				_, _, key21, key22 = mw.ustring.find(key2, "(%a+)%s*(%a*)")

				if not WPcontent[key12] then WPcontent[key12] = {} end
				if key11 == WProw and key21 == WPcourse then WPcontent[key12][key22] = val end
				if key11 == WPnew_row and key2 == WPdate then
					WPcontent[key12]['date'] = val
					WPcontent[key12]['text'] = WPcontent[key12]['text'] or ''
					WPcontent[key12]['icon (new row)'] = WPcontent[key12]['icon (new row)'] or ''
				end
				if key11 == WPnew_row and key2 == WPtext then
					WPcontent[key12]['text'] = val
					WPcontent[key12]['date'] = WPcontent[key12]['date'] or ''
					WPcontent[key12]['icon (new row)'] = WPcontent[key12]['icon (new row)'] or ''
				end
				if key11 == WPnew_row and key2 == WPicon then
					val = string.gsub(val, "|", "|border|right|20px|", 1)
					WPcontent[key12]['icon (new row)'] = val
					WPcontent[key12]['date'] = WPcontent[key12]['date'] or ''
					WPcontent[key12]['text'] = WPcontent[key12]['text'] or ''
				end
				if key11 == WProw and key21 == WPwinner and key22 == 'a' then WPcontent[key12]['stage winner'] = val end
				if key11 == WProw and key21 == WPwinner and key22 == 'b' then WPcontent[key12]['general winner'] = val end
				if key11 == WProw and key21 == WPicon then
					val = string.gsub(val, "|", "|border|right|20px|", 1)
					WPcontent[key12]['icon'] = val end
				if key11 == WProw and key21 == WPdistance then WPcontent[key12]['distance'] = val end
			end
		end
	end
	local countries = wikibase.getAllStatements(raceID, 'P17')
	local onecountry, firstcountryID
	if countries and #countries>1 then
		onecountry=false
		if countries[1] then
			firstcountryID=countries[1].mainsnak.datavalue.value.id
		end
	else
		onecountry=true
	end

	local rows = {}
	local stages = mw.wikibase.getBestStatements(raceID, 'P527') -- P527 is 'has part'
	for _, v in pairs(stages) do
		if v.mainsnak.snaktype == 'value' then
			local stageID = v.mainsnak.datavalue.value.id
			local p = mw.wikibase.getBestStatements(stageID, 'P1545') -- P1545 is 'series ordinal'
			local sOrdinal = p[1] and p[1].mainsnak.snaktype == 'value' and p[1].mainsnak.datavalue.value
				or ''
			local _, _, sNumber, sLetter = string.find(sOrdinal, '(%d+)(.*)')
			if not sNumber then sNumber = '' end
			if not sLetter then sLetter = '' end
			local WDLink = WDlink_on and wdLink(stageID) or ''
			local sitelink = mw.wikibase.getSitelink(stageID)

			p = mw.wikibase.getBestStatements(stageID, 'P585') -- P585 is 'point in time'
			local timeOfRace = p[1] and p[1].mainsnak.snaktype == 'value' and p[1].mainsnak.datavalue.value.time
				or ''
			p = mw.wikibase.getBestStatements(stageID, 'P1427') -- P1427 is 'start point'
			local sPointID = p[1] and p[1].mainsnak.snaktype == 'value' and p[1].mainsnak.datavalue.value.id
			local sPoint = sPointID and getPlaceLink(sPointID) or ''
			if sPointID and not onecountry and timeOfRace then
				local startcountry= getStatementForTime(sPointID, 'P17',timeOfRace)
				if startcountry then
					local startcountryID = startcountry.mainsnak.datavalue.value.id
					if firstcountryID ~= startcountryID then
						local sflag = flag(startcountryID, timeOfRace)
						sPoint = sflag.." "..sPoint
					end
				end
			end

			p = mw.wikibase.getBestStatements(stageID, 'P1444') -- P1444 is 'destination point'
			local dPointID = p[1] and p[1].mainsnak.snaktype == 'value' and p[1].mainsnak.datavalue.value.id
			local dPoint = dPointID and getPlaceLink(dPointID) or ''
			if dPointID and not onecountry and timeOfRace then
				local dcountry= getStatementForTime(dPointID, 'P17',timeOfRace)
				if dcountry then
					local dcountryID = dcountry.mainsnak.datavalue.value.id
					if firstcountryID ~= dcountryID then
						local dflag = flag(dcountryID, timeOfRace)
						dPoint = dflag.." "..dPoint
					end
				end
			end

			local sDistance = getDistance(stageID, false) or ''
			local sElevation = getElevation(stageID) 
			if sElevation then thereiselevation=true end
			
			local winners = {
				Q20882747 = '', -- Q20882747 is 'stage winner'
				Q20882763 = '', -- Q20882763 is 'overall leader at the end of the stage'
				Q20882667 = '', -- Q20882667 is 'overall winner' not supposed to be used
			}
			winner(stageID, winners, timeOfRace, false, WDlink_on)

			-- find the type of stage
			local sType = typeofstagelogo(stageID)
			local label, section_title
			if sOrdinal == "0" then
				label, section_title = translate("func_prologue"), "#" .. translate("func_prologue")
			else
				label, section_title = stageLink(sOrdinal, sNumber, sLetter)
			end
			-- if there is a Wikipedia article of that stage show it or show the section
			local sLink = sitelink and ("[[" .. sitelink .. "|" .. label .. "]]") or
				("[[" .. section_title .. "|" .. label .. "]]")

			local sDate = func_date(timeOfRace, 'small')
			local tempoverall
			if  winners['Q20882763']~='' then tempoverall=winners['Q20882763'] else	tempoverall=winners['Q20882667'] end
			rows[#rows + 1] = {
				tonumber(sNumber) or 0, sLetter,  -- Sort keys
				sLink, sDate, WDLink, sPoint, dPoint, sType, sDistance, sElevation, winners['Q20882747'], tempoverall -- Content
			}
		end
	end

	table.sort(rows, function(a, b)
		if a[1] ~= b[1] then return a[1] < b[1] end
		return a[2] < b[2]
	end)
	
	tab=mw.html.create('table')
	:attr('cellpadding','4' )
	:attr('cellspacing','0')
	:cssText(standardtablecss)

	local tRow=tab:tag('tr'):cssText('background:#FFDF80; text-align:center;')
	tRow:tag('th'):css('white-space','nowrap')
	:wikitext(((not WDlink_on and wdLink(string.gsub(raceID, '%s', '') .. "#P527")) or "")..
	translate("headoftable",1))
	tRow:tag('th'):wikitext(translate("headoftable",2))
	tRow:tag('th'):wikitext(translate("headoftable",3))
	tRow:tag('th'):css('color','#FFDF80'):wikitext("type")
	tRow:tag('th'):wikitext(translate("headoftable",4))
	if thereiselevation then 
		tRow:tag('th'):wikitext(translate("headoftable",7))
	end
	tRow:tag('th'):wikitext(translate("headoftable",5))
	tRow:tag('th'):wikitext(translate("headoftable",6))

	for num, row in pairs(rows) do
		local sLink, sDate, WDLink, sPoint, dPoint, sType, sDistance, sElevation, sSWin, sGWin
			= row[3], row[4], row[5], row[6], row[7], row[8], row[9], row[10], row[11], row[12]

		local WPc = WPcontent[num]
		if WPc then
			if WPc['a'] then sPoint = WPc['a'] end
			if WPc['b'] then dPoint = WPc['b'] end
			if WPc['ab'] then sPoint, dPoint = WPc['ab'], '' end
			if WPc['icon'] then sType = WPc['icon'] end
			if WPc['distance'] then sDistance = WPc['distance'] end
		end

		local tRow = tab:tag('tr')
		local tCell= tRow:tag('td'):cssText('text-align:center; white-space:nowrap'):wikitext(sLink)
		tCell:tag('span'):css('white-space','nowrap'):wikitext("&nbsp;".. WDLink )
		tRow:tag('td'):css('white-space','nowrap'):cssText("text-align:right; padding-right:0px")
		:wikitext(sDate)
		tCell=tRow:tag('td'):cssText("padding-right:0px"):wikitext( sPoint)
		if dPoint ~= '' then
			tCell:wikitext(" – " .. dPoint)
		end
		tRow:tag('td'):cssText("padding-right:0px"):wikitext(sType)
		tRow:tag('td'):css('text-align','center'):wikitext( sDistance)
		if thereiselevation then
			tRow:tag('td'):css('text-align','center'):wikitext(sElevation)
		end

		if WPc and WPc['stage winner'] then
			tRow:tag('td'):css('text-align',textalign):wikitext( WPc['stage winner'])
		else
			tRow:tag('td'):wikitext(sSWin)
		end
		if WPc and WPc['general winner'] then
			tRow:tag('td'):css('text-align',textalign):wikitext( WPc['general winner'])
		else
			tRow:tag('td'):wikitext(sGWin)
		end
		if WPc and (WPc['date'] or WPc['text'] or WPc['icon (new row)']) then
			tRow = tab:tag('tr')
			tRow:tag('td') --empty

			if WPc['icon (new row)'] == '' then
				tRow:tag('td'):cssText('text-align:right; padding:3px 0px 10px 0px;white-space:nowrap')
				:wikitext(WPc['date'])
				tRow:tag('td'):cssText("text-align:" .. textalign .. "; padding:3px 4px 10px")
				:wikitext(WPc['text'])
			else
				tRow:tag('td'):cssText('text-align:right; padding-right:0px')
				:wikitext(WPc['date'])
				tRow:tag('td'):cssText("text-align:" .. textalign)
				:wikitext(WPc['text'])
			end
			tRow:tag('td'):css('padding-top','10px'):wikitext(WPc['icon (new row)'])
			tRow:tag('td'):attr('colspan','3')
		end
	end
	return tab
end

function p.stagetitle(frame)
	-- WDlink_on is used to decide if a Wikidata logo will be shown
	local stageID = frame.args[1]
	-- from to 
	local p = mw.wikibase.getBestStatements(stageID, 'P1427') -- P1427 is 'start point'
	local sPointID = p[1] and p[1].mainsnak.snaktype == 'value' and p[1].mainsnak.datavalue.value.id
	local sPoint = sPointID and getPlaceLink(sPointID) or ''
	p = mw.wikibase.getBestStatements(stageID, 'P1444') -- P1444 is 'destination point'
	local dPointID = p[1] and p[1].mainsnak.snaktype == 'value' and p[1].mainsnak.datavalue.value.id
	local dPoint = dPointID and getPlaceLink(dPointID) or ''

	local sDistance = getDistance(stageID, true) or ''
	-- find the type of stage
	local sType = typeofstagelogo(stageID)
	
	tab=mw.html.create('table')
	tab:tag('th'):wikitext(sPoint.." - "..dPoint)
	tab:tag('td'):wikitext(sType)
	tab:tag('td'):css('font-weight','bold'):wikitext("("..sDistance..")")
	return tab
end

--[[ Give access to a local variable. Used by other modules. ]]
function p.getLocal(name)
	if name == 'getTeamLinkCat' then return getTeamLinkCat end
	if name == 'getStatementForTime' then return getStatementForTime end
end


local function champtitle(h) --!h is h.jersey
	local road, ITT, result
	local hcountry, hnotcountry = {},{}
	
	--the jersey for a stage race and the jersey from national championship should be differentiated
	--to avoid to look every time, below is a list of all national championships
	local womenRoadtable= {Q934877=true, Q50064341=true,Q50061750=true,Q31271454=true,Q54315111=true,Q30894544=true,
	Q66082905=true,Q65965631=true,Q45083914=true,Q31271492=true,Q43286073=true,Q55185740=true,Q65371835=true,
	Q31094517=true,QQ27043949=true,	Q30332924=true,Q30349395=true,Q53869580=true,Q31505332=true,Q30349364=true,
	Q31271605=true,Q43745198=true,Q30332844=true,Q30332239=true,Q30349468=true,	Q30332737=true,Q55221006=true,
	Q32161692=true,Q33083546=true,Q30332988=true,Q30556990=true,Q32604159=true,Q30557561=true,Q64624273=true,
	Q30333102=true,	Q31271010=true,Q31276622=true,Q45084873=true,Q32609249=true,Q31271644=true,Q31298588=true,
	Q45171831=true,Q30332625=true,Q30349432=true,Q31092105=true,Q30577809=true,Q30349499=true, Q45172931=true
	}
	local womenITTtable={Q2630733=true,Q50063172=true,Q50062728=true,Q31271381=true,Q54314912=true,Q30894543=true,
	QQ31093255=true,Q31271615=true,Q29642128=true,Q30349411=true,Q53869589=true,
	Q31506358=true,Q30349371=true,Q31271315=true,Q43745136=true,Q30332806=true,
	Q30332311=true,Q30349480=true,Q30332699=true,Q55220999=true,Q32163348=true,
	Q33083817=true,Q30333018=true,Q30556121=true,Q32603438=true,Q30557504=true,
	Q64624304=true,Q30333137=true,Q31271024=true,Q30456396=true,Q45084954=true,
	Q32611136=true,Q31272638=true,Q31300263=true,Q45171898=true,Q30332486=true,
	Q30349441=true,Q30584268=true,Q30577837=true,Q30349507=true,Q45172978=true
	}
	local menRoadtable={Q13603535=true,Q30894537=true,Q23069702=true,Q23889469=true,
	Q66250756=true,	Q22284173=true, Q30967435=true, Q24617852=true, Q27043944=true,
	Q24628140=true,Q27056312=true,Q62024698=true,Q26960669=true,Q22951216=true,
	Q27048382=true,Q27133468=true,Q26971246=true,Q24621530=true,Q27048391=true,
	Q27048399=true,Q27681895=true,Q27681898=true,Q27055629=true,Q26976092=true,
	Q26985335=true,Q27048419=true,Q27043957=true,Q27055631=true,Q24050070=true,
	Q26973043=true,Q27133456=true,Q26834056=true,Q27043924=true,Q27048374=true,
	Q26972921=true,Q27043324=true,Q27056303=true,Q27042502=true,Q27042790=true,
	Q27133451=true,Q27056305=true,Q24731826=true,Q27230607=true,Q22680990=true,
	Q27043353=true,Q27048408=true,Q22303186=true,Q27042375=true,Q27133460=true,
	Q27133465=true,Q22680842=true,Q27230606=true,Q27230610=true,Q26972715=true,
	Q24718413=true,Q3754283=true,Q27230604=true,Q27043932=true,Q27230611=true,
	Q24733085=true,Q27055624=true,Q24731406=true,Q27056308=true
	}
	local menITTtable={Q2557477=true,Q33315723=true,Q22284183=true, Q31023710=true,
	Q24618030=true, Q27043945=true,Q24628162=true,Q27056389=true,Q26960674=true,
	Q5147941=true,Q27048383=true,Q27133626=true,Q26971248=true,Q24621627=true,
	Q27793536=true,Q27048400=true,Q27793536=true,Q27793496=true,Q27055699=true,
	Q26976108=true, Q26985336=true, Q27048421=true,Q27043958=true,Q27055700=true,
	Q26973044=true,Q27133617=true,Q26834055=true,Q27043925=true,Q24050074=true,
	Q27048375=true,Q26972922=true,Q27043325=true,Q27056383=true,Q27042506=true,
	Q17319607=true,Q27133615=true,Q17005940=true,Q24731829=true,Q27235634=true,
	Q22680998=true,Q3754388=true,Q27048410=true,Q22303252=true,Q27042376=true,
	Q27133620=true,Q27133623=true,Q22680863=true,Q7382088=true,Q27235638=true,
	Q26972716=true,Q24718416=true,Q27043341=true,Q27230443=true,Q27043933=true,
	Q27235639=true,Q24733090=true,Q27055696=true,Q24731482=true,Q27056386=true
	}

	if type(h) == 'table' and h[1] then
		for _, v in ipairs(h) do
			roadtemp=false
			ITTtemp=false
			if womenRoadtable[v] or menRoadtable[v] then
				 road = true
				 roadtemp=true
			elseif womenITTtable[v] or menITTtable[v] then
				 ITT = true
				 ITTtemp=true
	    	else
		    	local Racelabel = mw.wikibase.getLabelByLang(v,"fr")
				if Racelabel then
					local testMenRoadrace, testMenITT, testWomenRoadrace, testWomenITT
					local Racelabelmod = string.gsub(Racelabel, '-', 'x')
					testMenRoadrace = string.find( Racelabel, 'Course en ligne masculine aux' ) 
					testMenITT = string.find( Racelabelmod, 'Contrexlaxmontre masculin aux' ) 
					testWomenRoadrace = string.find( Racelabel, 'Course en ligne féminine aux' ) 
					testWomenITT = string.find( Racelabelmod, 'Contrexlaxmontre féminin aux' ) 
					if testWomenRoadrace or testMenRoadrace then road = true roadtemp=true end
					if testWomenITT or testMenITT then ITT = true ITTtemp=true end
				end
			end
			if roadtemp or ITTtemp then
				table.insert(hcountry,v)
			else
				table.insert(hnotcountry,v)	
			end
		end
	end
	if road and ITT then
		local image = {}
		for ii, v in ipairs(hcountry) do
			local p18 = mw.wikibase.getBestStatements(v, 'P18')
			if p18[1] and p18[1].mainsnak.snaktype == 'value' then
				local temp = p18[1].mainsnak.datavalue.value
				local alreadythere = 0
				for _, vv in ipairs(image) do
					if vv==temp then alreadythere = 1 end
				end
				if alreadythere==0 then
					table.insert(image,temp)
				else hcountry[ii] = nil
				end
			end
		end
		--avoid double display of jersey
		result = "<small>("..translate("startlist",10).." "..translate("startlist",12).." "..translate("startlist",11)..")</small>"
	elseif road then
		result = "<small>("..translate("startlist",10)..")</small>"
	elseif ITT then
		result = "<small>("..translate("startlist",11)..")</small>"
	else
		result = ""
	end
	return jersey(hcountry)..result..jersey(hnotcountry)
end

-- K) List of stages classification
local function winnerjersey(raceID, winners)
	local jerseytable, bgcolortable={}, {}
	local p1346 = wikibase.getAllStatements(raceID, 'P1346') -- P1346 is 'winner'
	for _, winner in pairs(p1346) do
		local wOf, thisjersey, bg_color
		local q = winner.qualifiers
		if q then
			if q.P642 and q.P642[1].snaktype == 'value' then
				wOf = q.P642[1].datavalue.value.id -- P642 is 'of'
			end
			if q.P2912 and q.P2912[1].snaktype == 'value' then
				thisjersey=q.P2912[1].datavalue.value.id
				if bg_color_table[thisjersey] then
					bg_color = bg_color_table[thisjersey]
				end
			end
		end
		if winners[wOf] and thisjersey then
			jerseytable={}
			table.insert(jerseytable,thisjersey)
			winners[wOf] = jersey(jerseytable)
			bgcolortable[wOf] = bg_color
		end
	end
	return winners, bgcolortable
end

function p.listofstagesclassification(frame)
	-- WDlink_on is used to decide if a Wikidata logo will be shown
	local WDlink_on = wiki == "mk" or wiki == "ja"
	local displaytypeofstage = true
	local stageinfotable = {}
	local raceID = frame.args[1]
	local sType
	local localframe
	if string.match(frame:getParent():getTitle(), '%P+') == mw.site.namespaces.Template.name then
		localframe = frame:getParent()
	else
		localframe = frame
	end
	if localframe.args[1] then
		localframe.args[1] = string.gsub(localframe.args[1], "%c", "")
	end

	--link for Grand Tour
	local GTid={['Q33881']=true,['Q33861']=true,['Q33937']=true}
	local thisGT

	for _, p31 in statements(raceID, 'P31') do
		if GTid[p31.mainsnak.datavalue.value.id]==true then thisGT=p31.mainsnak.datavalue.value.id break end
	end

	local Sitelink,overallname, pointsname, mountainname, youngname, volantes, teamname, combativityname, combinedname, teamspoints
	if thisGT then
		if thisGT=='Q33881' then -- Tour de France
			Sitelink = wikibase.getSitelink('Q2267539')
			if Sitelink then overallname="[["..Sitelink .."|"..translate("infobox",66).."]]" end
			Sitelink = wikibase.getSitelink('Q175399')
			if Sitelink then pointsname="[["..Sitelink .."|"..translate("infobox",22).."]]" end
			Sitelink = wikibase.getSitelink('Q927157')
			if Sitelink then mountainname="[["..Sitelink .."|"..translate("infobox",23).."]]" end
			Sitelink = wikibase.getSitelink('Q641662')
			if Sitelink then youngname="[["..Sitelink .."|"..translate("infobox",25).."]]" end
			Sitelink = wikibase.getSitelink('Q1436680')
			if Sitelink then teamname="[["..Sitelink .."|"..translate("infobox",28).."]]" end
			Sitelink = wikibase.getSitelink('Q2094179')
			if Sitelink then combativityname="[["..Sitelink .."|"..translate("infobox",26).."]]" end
			Sitelink = wikibase.getSitelink('Q1835362')
			if Sitelink then combinedname="[["..Sitelink .."|"..translate("infobox",27).."]]" end
			Sitelink = wikibase.getSitelink('Q2071432')
			if Sitelink then volantes="[["..Sitelink .."|"..translate("infobox",35).."]]" end
			Sitelink = wikibase.getSitelink('Q1436680')
			if Sitelink then teamspoints="[["..Sitelink .."|"..translate("infobox",37).."]]" end	
		elseif thisGT=='Q33861' then -- Giro d'Italia
			Sitelink = wikibase.getSitelink('Q1164275')
			if Sitelink then overallname="[["..Sitelink .."|"..translate("infobox",66).."]]" end
			Sitelink = wikibase.getSitelink('Q641083')
			if Sitelink then pointsname="[["..Sitelink .."|"..translate("infobox",22).."]]" end
			Sitelink = wikibase.getSitelink('Q641060')
			if Sitelink then mountainname="[["..Sitelink .."|"..translate("infobox",23).."]]" end
			Sitelink = wikibase.getSitelink('Q641662')
			if Sitelink then youngname="[["..Sitelink .."|"..translate("infobox",25).."]]" end
			Sitelink = wikibase.getSitelink('Q2626253')
			if Sitelink then teamname="[["..Sitelink .."|"..translate("infobox",28).."]]" end	
			Sitelink = wikibase.getSitelink('Q2626253')
			if Sitelink then teamspoints="[["..Sitelink .."|"..translate("infobox",37).."]]" end		
		else -- Vuelta a Espana
			Sitelink = wikibase.getSitelink('Q2532554')
			if Sitelink then overallname="[["..Sitelink .."|"..translate("infobox",66).."]]" end
			Sitelink = wikibase.getSitelink('Q2241695')
			if Sitelink then pointsname="[["..Sitelink .."|"..translate("infobox",22).."]]" end
			Sitelink = wikibase.getSitelink('Q1118296')
			if Sitelink then mountainname="[["..Sitelink .."|"..translate("infobox",23).."]]" end
			Sitelink = wikibase.getSitelink('Q60233927')
			if Sitelink then youngname="[["..Sitelink .."|"..translate("infobox",25).."]]" end
			Sitelink = wikibase.getSitelink('Q20882672')
			if Sitelink then combativityname="[["..Sitelink .."|"..translate("infobox",26).."]]" end		
			Sitelink = wikibase.getSitelink('Q2330008')
			if Sitelink then combinedname="[["..Sitelink .."|"..translate("infobox",27).."]]" end
			Sitelink = wikibase.getSitelink('Q2141595')
			if Sitelink then teamname="[["..Sitelink .."|"..translate("infobox",28).."]]" end	
			Sitelink = wikibase.getSitelink('Q2141595')
			if Sitelink then teamspoints="[["..Sitelink .."|"..translate("infobox",37).."]]" end	
			
		end
	end

	local winners = {
		{ name = translate("infobox",19), QID = 'Q20882747'}, -- stage
		{ name = overallname or translate("infobox",66), QID = 'Q20882763' }, -- overall
		{ name = pointsname or translate("infobox",22), QID = 'Q20883008' }, -- points
		{ name = mountainname or translate("infobox",23), QID = 'Q20883213' }, -- mountains
		{ name = translate("infobox",24), QID= 'Q20883329' }, -- sprints
		{ name = youngname or translate("infobox",25), QID='Q20883140' }, -- youth
		{ name = combativityname or translate("infobox",26), QID= 'Q20893984' }, -- combativity
		{ name = volantes or translate("infobox",35), QID= 'Q27104688' }, -- volantes
		{ name = translate("infobox",36), QID= 'Q27104684' }, -- regularity
		{ name = combinedname or translate("infobox",27), QID='Q20965880' }, -- combination
		{ name = translate("infobox",38), QID='Q27907714' }, -- breakaway
		{ name = translate("infobox",39), QID='Q27907748' }, -- azzurri
		{ name = translate("infobox",40), QID='Q28096780'}, -- rookie
		{ name = teamname or translate("infobox",28), QID='Q20882922' }, -- teams
		{ name = teamspoints or translate("infobox",37), QID ='Q27104271' }, -- teamspoints
		{ name = translate("infobox",41), QID ='Q61976847' },-- amateur
		{ name = translate("infobox",42), QID ='Q61976871' } --nationality
	}

	local winnersgen = {
		{ QID = 'Q20882667' }, -- overall
		{ QID = 'Q20883007' }, -- points
		{ QID = 'Q20883212' }, -- mountains
		{ QID = 'Q20883328' }, -- sprints
		{ QID = 'Q20883139' }, -- youth
		{ QID = 'Q20893983' }, -- combativity
		{ QID = 'Q27067359' }, -- volantes
		{ QID = 'Q27067170' }, -- regularity
		{ QID = 'Q20893979' }, -- combination
		{ QID = 'Q27907715' }, -- breakaway
		{ QID = 'Q27907747' }, -- azzurri
		{ QID = 'Q28092831' }, -- rookie
		{ QID = 'Q20882921' },  -- teams
		{ QID = 'Q27104269' }, -- teamspoints
		{ QID = 'Q61976850' },  -- amateur
		{ QID = 'Q61976872' } --nationality
	}

	local generaltoleader = {
		['Q20882747']= nil,
		['Q20882667']= 'Q20882763', -- overall
		['Q20883007']= 'Q20883008', -- points
		['Q20883212']= 'Q20883213', -- mountains
		['Q20883328']= 'Q20883329', -- sprints
		['Q20883139']= 'Q20883140', -- youth
		['Q20893983']= 'Q20893984', -- combativity
		['Q27067359']= 'Q27104688', -- volantes
		['Q27067170']= 'Q27104684', -- regularity
		['Q20893979']= 'Q20965880', -- combination
		['Q27907715']= 'Q27907714', -- breakaway
		['Q27907747']= 'Q27907748', -- azzurri
		['Q28092831']= 'Q28096780', -- rookie
		['Q20882921']= 'Q20882922', -- teams
		['Q27104269']= 'Q27104271', -- teamspoints
		['Q61976850']= 'Q61976847', -- amateur
		['Q61976872']= 'Q61976871'  --nationality
	}

	--read stages
	local stages = mw.wikibase.getBestStatements(raceID, 'P527') -- P527 is 'has part'
	local columntable, jerseytable, bgcolortable={}, {}, {}
	for ii, v in ipairs(winners) do
		if v.QID then
			local t = {key=ii, name=v.name, jersey='', bg_color='', used=false}
			for ii = 1, #stages+1 do
				t[ii] = { {}, {}, {} }  -- ?, first stage, number of stages consecutive
			end
			columntable[v.QID] = t
		end
	end
	local function itercolumns(columntable)
		local keys = {}
		for k, v in pairs(columntable) do
			keys[v.key] = k
		end
		local upto = 1
		return function ()
			while keys[upto] do
				upto = upto + 1
				return columntable[keys[upto-1]]
			end
		end
	end

	local timeOfRace
	for ii, v in pairs(stages) do
		if v.mainsnak.snaktype == 'value' then
			local somewinner = false
			local stageID = v.mainsnak.datavalue.value.id
			local sitelink = mw.wikibase.getSitelink(stageID)
			if displaytypeofstage==true then
				sType = typeofstagelogo(stageID)
			end
			local p = mw.wikibase.getBestStatements(stageID, 'P1545') -- P1545 is 'series ordinal'
			local sOrdinal = p[1] and p[1].mainsnak.snaktype == 'value' and p[1].mainsnak.datavalue.value
				or ''
			local _, _, sNumber, sLetter = string.find(sOrdinal, '(%d+)(.*)')
			if not sNumber then sNumber = '' end
			if not sLetter then sLetter = '' end

			local label, section_title
			if sOrdinal == "0" then
				label, section_title = translate("func_prologue"), "#" .. translate("func_prologue")
			else
				label, section_title = stageLink(sOrdinal, sNumber, sLetter)
			end
			-- If there is a Wikipedia article of that stage show it or show the section.
			local sLink = sitelink and ("[[" .. sitelink .. "|" .. label .. "]]") or
				("[[" .. section_title .. "|" .. label .. "]]")

			local sTime = firstValue(stageID, 'P580', 'time') -- P580 is 'start time'
			local eTime = firstValue(stageID, 'P582', 'time') -- P582 is 'end time'
			if sTime and eTime then
				timeOfRace = eTime
			else
				-- This function give a format to dates when P585 (date) is used in a single day race.
				local pTime = firstValue(stageID, 'P585', 'time') -- P585 is 'point in time'
				if pTime then
					timeOfRace = pTime
				end
			end

			local win= {}
			for _, v in pairs(winners) do
				win[v.QID] = ''
				if ii==1 then jerseytable[v.QID]='' end
			end
			winner(stageID, win, timeOfRace, false, WDlink_on, false, false)
			if ii==1 then --only first stage
				jerseytable, bgcolortable=winnerjersey(stageID, jerseytable)
			end
			for _, v in pairs(winners) do
				if v.QID and win[v.QID] ~= '' then
					--column info
					somewinner=true
					columntable[v.QID][ii][1]=win[v.QID]
					if ii==1 then --first stage
						columntable[v.QID][ii][2]=1
						columntable[v.QID][ii][3]=1
					elseif columntable[v.QID][ii-1][1]==win[v.QID] then --same winner as past stage
						local initialstage=columntable[v.QID][ii-1][2]
						columntable[v.QID][ii][2]=initialstage
						columntable[v.QID][initialstage][3]=columntable[v.QID][initialstage][3]+1
						columntable[v.QID][ii][3]=0
					else --new winner
						columntable[v.QID][ii][2]=ii
						columntable[v.QID][ii][3]=1
					end
					columntable[v.QID].used=true
					if ii==1 then
						columntable[v.QID].jersey=jerseytable[v.QID]
						columntable[v.QID].bg_color=bgcolortable[v.QID]
					end
				end
			end
			table.insert(stageinfotable,{sLink=sLink, sType=sType, somewinner=somewinner})
		end
	end

	--read parent
	local win= {}
	for _, v in pairs(winnersgen) do
		if v.QID then
			win[v.QID] = ''
			jerseytable[v.QID]=''
		end
	end
	local thiskey
	somewinner = false
	jerseytable, bgcolortable=winnerjersey(raceID, jerseytable)
	winner(raceID, win, timeOfRace, false, WDlink_on, false, false)
	for _, v in pairs(winnersgen) do
		if win[v.QID] and win[v.QID] ~= '' then
			somewinner=true
			thiskey=generaltoleader[v.QID]
			columntable[thiskey][#stages+1][1]=win[v.QID]
			columntable[thiskey][#stages+1][2]=#stages+1
			columntable[thiskey][#stages+1][3]=1
			if type(columntable[thiskey][#stages][1])~="string" then --check nil actually, but it is a table..
				columntable[thiskey][#stages][1]=win[v.QID] --no need to fill last stage of a stage race
				if type(columntable[thiskey][#stages-1][1])=="string" and win[v.QID]==columntable[thiskey][#stages-1][1] then
					local initialstage=columntable[thiskey][#stages-1][2]
					columntable[thiskey][#stages][2]=initialstage
					columntable[thiskey][initialstage][3]=columntable[thiskey][initialstage][3]+1
					columntable[thiskey][#stages][3]=0
				else
					columntable[thiskey][#stages][2]=#stages
					columntable[thiskey][#stages][3]=1
				end
			end
			columntable[thiskey].used=true
			if jerseytable[v.QID] and jerseytable[v.QID]~='' then
				columntable[thiskey].jersey=jerseytable[v.QID]
				columntable[thiskey].bg_color=bgcolortable[v.QID]
			end
		end
	end
	table.insert(stageinfotable,{sLink=translate("listofstagesclassification",2), sType=nil, somewinner=somewinner})

	--build the table
	local	tab=mw.html.create('table')
	:attr('cellpadding','4' )
	:attr('cellspacing','0')
	:cssText(standardtablecss)
	local tRow=tab:tag('tr'):cssText('background:#FFDF80; text-align:center;')
	tRow:tag('th'):css('white-space','nowrap')
	:wikitext(((not WDlink_on and wdLink(string.gsub(raceID, '%s', '') .. "#P527")) or "")..
	translate("headoftable",1))
	
	if displaytypeofstage==true then tRow:tag('th') end

	for v in itercolumns(columntable) do
		if v.used == true then
			if v.jersey == '' then v.jersey = "_" end
			tRow:tag('th'):wikitext(v.name.."<br />"..v.jersey)
		end
	end

	local style
	--then fill the table
	for ii, v in pairs(stageinfotable) do --one stage=one row
		--stages link
		tRow=tab:tag('tr')
		local tCell=tRow:tag('td')
		if ii==#stageinfotable then 
			tCell:attr('colspan','2'):cssText('font-weight:bold; border-top: 2px black solid;')
		end
		tCell:wikitext(v.sLink)
		
		tCell=tRow:tag('td')
		if ii==#stageinfotable then
			tCell:cssText('font-weight:bold; border-top: 2px black solid;')
		end
		if displaytypeofstage == true then
			if v.sType then
				tCell:wikitext(v.sType)
			end
		end

		--add winners
		for y in itercolumns(columntable) do
			if y.used==true and not (ii==#stageinfotable and columntable['Q20882747']==y) then --only display used QID
				if type(y[ii][1])=="string" and type(y[ii][3])=="number" then --actually check nil but it is a table
					style=""
					if y[ii][3]~=0 and (columntable['Q20882747']==y)==false then
						if ii~=1 and ii~=#stageinfotable then style=style.." border-top:1px gray solid;" end
						if y.bg_color then style=style.." background-color:"..y.bg_color..";" end
						if ii==#stageinfotable then style=style.."font-weight:bold; border-top: 2px black solid;" end
						tRow:tag('td'):attr('rowspan',tostring(y[ii][3])):cssText(style):wikitext(y[ii][1])
					elseif (columntable['Q20882747']==y) then --no rowspan for stages
						tRow:tag('td'):wikitext(y[ii][1])
					end
				else
					tCell=tRow:tag('td')
					if ii~=#stageinfotable and v.somewinner==true then
						tCell:wikitext(translate("listofstagesclassification",1)) --not attributed
					elseif ii~=#stageinfotable then
						 --empty
					elseif v.somewinner==true then
						tCell:cssText('border-top: 2px black solid')
						:wikitext(translate("listofstagesclassification",1))
					else
						tCell:cssText('border-top: 2px black solid') --empty
					end
				end
			end
		end
	end
	return tab
end

--M) Start list
function p.startlist(frame)
	local IDtemp
	if frame.args[1] ~= nil then
		IDtemp=string.gsub(frame.args[1], "%c", "")
	end

	local s = {
		header_function = "startlist",
		header_1 = 1, -- translation 1 in function victories is printed in the upper part of the table header
		header_2 = {2, 3,4,5},
		item=IDtemp,
		title="Start list",
		data_sort_type={'unsortable', 'unsortable', 'unsortable'},
		property ='P710',
		no_roll_startlist=no_roll_startlist
	}

	local resulttable, tag = tableB(s)
	return startlist_main(s, resulttable, tag)  
end

function p.startlisttable(frame)
	local IDtemp
	if frame.args[1] ~= nil then
		IDtemp=string.gsub(frame.args[1], "%c", "")
	end

	local s = {
		header_function = "startlisttable",
		header_1 = 1, -- translation 1 in function victories is printed in the upper part of the table header
		header_2 = {2, 3,4,5},-- translations 2, 3, 4, 5, 6 in function victories are printed in this order
		item=IDtemp,
		title="Start list", -- in the lower part of the table header. The second value 3 in {4, 3} tells where the icon will go.
		no_country ={'fr'},
		data_sort_type={'', '', ''},
		property ='P710',
		no_roll_startlist=no_roll_startlist
	}
	return startlisttable_main(s, tableA(s))
end

local function startlist_sub(p710, timeOfRace,  WDlink_on, istable)
	local h, resulttable= {}, {}
	local tBody = '' --row in our case
	local riderID, riderTeamLink, riderTeamID, riderDossard, riderLink, riderRank, q, gender, riderTeamCode, riderDNF, DSQ

	riderID = p710.mainsnak.datavalue.value.id
	q= p710.qualifiers
	riderLink= getRiderLink(riderID, timeOfRace)
	if WDlink_on then riderLink=riderLink..wdLink(riderID) end
	if q and q.P1618 and q.P1618[1].snaktype == 'value' then
		riderDossard = q.P1618[1].datavalue.value or ''
	else
		riderDossard = ''
	end
	riderDNF='' riderRank = '' DSQ=''
	if q and q.P1352 and q.P1352[1].snaktype == 'value' then -- P1352 is ranking
		riderRank = tonumber(q.P1352[1].datavalue.value.amount)
		--look for DSQ--
		DSQ=isdisqualified(p710, q)
	else
		--look for DNF...
		if q and q.P1534 and q.P1534[1].snaktype == 'value' then
			local dnf=q.P1534[1].datavalue.value.id
			if dnf=='Q1210380' then riderDNF =translate("startlist",6)--"HD","NP","DQ"
			elseif dnf=='Q54881674' or dnf=='Q7113430' then riderDNF =translate("startlist",7)
			elseif dnf=='Q1210382' then riderDNF =translate("startlist",8)
			elseif dnf=='Q1229261' then riderDNF =translate("startlist",9)
			else riderDNF=''
			end
			if q.P1545 and q.P1545[1].snaktype == 'value' then
				local stageofdnf=q.P1545[1].datavalue.value
				if stageofdnf and string.len(stageofdnf)>1 then
					riderDNF='<small>'..riderDNF.."-"..stageofdnf..'</small>'
				else
					riderDNF=riderDNF.."-"..stageofdnf
				end
			end
		end
	end

	h = {
		jersey = {}, -- lots of jerseyID
		value = {'', '', '', ''} -- points, time, time_gap, speed
	}

	if q and q.P2912 then -- P2912 is distinctive jersey
		for _, v in pairs(q.P2912) do
			if v.snaktype == 'value' then
				table.insert(h.jersey, v.datavalue.value.id)
			end
		end
	end

	if wiki == 'es' or wiki == 'fr' or wiki == 'ast' then
		--[[ These wikis need the gender to display the rank correct. Other wikis can skip this. ]]
		gender = getgendercode(riderID, 'n')
	end

	local p27 = getStatementForTime(riderID, 'P27', timeOfRace) --P27 is country of citizenship
	if p27 then
		local countryID = p27.mainsnak.datavalue.value.id
		if countryID then
			if wiki ~= "ar" then 
				riderLink = riderLink .. ucicodeCountry(countryID)
			end
			riderLink = flag(countryID, timeOfRace) ..' '.. riderLink 
		end
	end
	
	if h.jersey[1] then
		riderLink=riderLink..champtitle(h.jersey) -- champtitle manages also the jersey
	end
	
	riderTeamLink, riderTeamID = getTeam(riderID, timeOfRace, q)
	riderTeamID=seasonToTeamID(riderTeamID)
	riderTeamCode= getTeamCode(riderID, timeOfRace, q)
	
	if riderTeam == nil then riderTeam ="" end
	local sortkey = riderDossard == "" and 0 or tonumber(riderDossard)

	tBody =   mw.html.create('tr'):cssText("line-height: 1.8em; padding: 5px;")
	tBody:tag('td'):cssText("text-align:right;padding:0 0.5em"):wikitext(riderDossard)
	tBody:tag('td'):cssText('text-align:'..textalign.. ';padding:0 0.5em;'..DSQ):wikitext(riderLink)
	if istable then
		tBody:tag('td'):cssText("text-align:right;padding:0 0.5em"):wikitext(riderTeam)
	end
	tBody:tag('td'):cssText('text-align:'..textalign.. ';padding:0 0.5em;'..DSQ):wikitext(number(gender,riderRank,wiki)..riderDNF)

	table.insert(resulttable, {sortkey=sortkey, riderTeamLink=riderTeamLink,riderTeamID=riderTeamID,riderTeamCode=riderTeamCode, tBody=tBody})
	return resulttable
end

function startlist_main(s, resulttable, tag)
	local ridertable, DStable, subtable  = {}, {}, {}, {}
	local DSID, DSLink, DSteamID, DSteam
	local WDlink_on = (wiki == "mk" or wiki == "ja" or wiki == "ru")

	local fn_datetable=fn_date(s.item)
	local timeOfRace=fn_datetable[1]

	for _,p286 in statements(s.item, 'P286') do--look for DS
		DSID = p286.mainsnak.datavalue.value.id
		DSLink= getRiderLink(DSID, timeOfRace)
		q= p286.qualifiers
		if q.P642 and q.P642[1].snaktype == 'value' then
			DSteamID=q.P642[1].datavalue.value.id
			DSteamID=seasonToTeamID(DSteamID)
		end
		table.insert(DStable, {DSLink=DSLink, DSteamID=DSteamID})
	end

	for _, p710 in statements(s.item, 'P710') do -- P710 is participants
		subtable=startlist_sub(p710, timeOfRace, WDlink_on, false)
		ridertable[#ridertable + 1] = {
			subtable[1].sortkey, 
			riderTeamLink=subtable[1].riderTeamLink, 
			riderTeamID=subtable[1].riderTeamID, 
			riderTeamCode=subtable[1].riderTeamCode, 
			tBody=subtable[1].tBody
		}
	end
	
	--sort
	table.sort(ridertable, function(a, b) return a[1] < b[1] end)

	local thisTableRow, thisTeamTable, thisDS, insideTable, test
	local tSubtitle, tTitle
	
	if wiki == "ar" then
		tSubtitle=mw.html.create('tr')
		tSubtitle:tag('td'):attr('width','30px')
		:css("align:right;text-align:right")
		:wikitext(translate("startlist",2))
		tSubtitle:tag('td'):attr('width','200px')
		:css("align:right;text-align:right")
		:wikitext(translate("startlist",3))
		tSubtitle:tag('td'):attr('width','85px')
		:css("align:right;text-align:right")
		:wikitext(translate("startlist",4))
	else
		tSubtitle=mw.html.create('tr')
		tSubtitle:tag('td'):attr('width','30px'):wikitext(translate("startlist",2))
		tSubtitle:tag('td'):attr('width','250px'):wikitext(translate("startlist",3))
		tSubtitle:tag('td'):attr('width','35px'):wikitext(translate("startlist",4))
	end

	--look for transition between teams
	local numberofteam=0
	local tDS

	if #ridertable==0 then--empty table
		return nil
	else
		for ii=1,#ridertable  do
			if ridertable[ii].riderTeamLink==nil then ridertable[ii].riderTeamLink=translate("startlist",13) end
			if ii~=1 and ridertable[ii].riderTeamID and ridertable[ii].riderTeamID==ridertable[ii-1].riderTeamID then test=0 else test=1 end--team change
				--new team
			if test==1 or ii==1 then
				if thisDS and ii~=1 then
					tDS=insideTable:tag('tr')
					tDS:tag('td'):attr('colspan','3'):attr('align','center')
					:wikitext(translate("startlist",5).." "..thisDS)
					thisDS=nil
				end
				
				numberofteam=numberofteam+1
				if math.fmod(numberofteam, 3 )==1 then
					if ii~=1 then
						tag:node(thisTableRow) --a row with 3 tables inside, save and re-init
					end
					thisTableRow=mw.html.create('tr') 
				end
				thisTeamTable= thisTableRow:tag('td'):cssText("width:33%;"):attr('valign','top')
				insideTable=thisTeamTable:tag('table') --reinit
				:attr('cellpadding','4') --solid rgb(200,200,200)
				:attr('background-color','rgb(255, 255, 255)')
				:attr('margin', '0 0 0.5em 0')
				:attr('padding','5px')
				:attr('float','left')
				:attr('text-align',textalign)
				:attr('line-height','1.8em')
				:attr('clear',floattable)

				tTitle =  mw.html.create('tr'):cssText("background-color:#FFDF80"):attr('align','center')
				local tCell=tTitle:tag('th'):attr('colspan','3')
				tCell:tag('big'):wikitext(ridertable[ii].riderTeamLink.."<br/>"..(ridertable[ii].riderTeamCode or "___"))
				
				insideTable:node(tTitle)
				insideTable:node(tSubtitle)
				
				tDS=nil
				--look for the DS of this team
				for _,v in pairs(DStable) do
					if v.DSteamID==ridertable[ii].riderTeamID then thisDS=v.DSLink break end
				end
			end
			insideTable:node(ridertable[ii].tBody)
		end
		--last DS
		if thisDS then
			tDS=insideTable:tag('tr')
			tDS:tag('td'):attr('colspan','3'):attr('align','center')
			:wikitext(translate("startlist",5).." "..thisDS)
		end
		tag:node(thisTableRow)

		return resulttable
	end
end

function startlisttable_main(s, resulttable)
	local  t_Body, fn_datetable, subtable = {}, {}, {}, {}
	local WDlink_on = (wiki == "mk" or wiki == "ja" or wiki == "ru")

	fn_datetable=fn_date(s.item)
	local timeOfRace=fn_datetable[1]

	for _, p710 in statements(s.item, 'P710') do -- P710 is participants
		subtable=startlist_sub(p710, timeOfRace, WDlink_on, true)
		t_Body[#t_Body + 1] = {subtable[1].sortkey, tostring(subtable[1].tBody)}
	end
	return sortandconcat(t_Body, resulttable)
end

-- N) Rider ranking
local function checkminmaxyear(minmaxyear,thisyear)
	if minmaxyear.minimum ==0 or thisyear<minmaxyear.minimum then
		minmaxyear.minimum=thisyear
	end
	if minmaxyear.maximum==0 or thisyear>minmaxyear.maximum then
		minmaxyear.maximum=thisyear
	end
   return minmaxyear
end

function p.riderranking(frame)
	local s = {
		gender = 1, --tonumber(frame.args[2]) 0 = men, 1 = women
		item = string.gsub(frame.args[1], "%c", ""),
		}
	return riderranking_main(frame, s)
end

function riderranking_main(frame,s)
	local thisCompetition, rank, thisyear, sitelink, q, gender
	local Resulttable, listofcalendar, UCI, UCImaster={},{},{}, {}
	local minmaxyear= {
		minimum = 0, -- lots of jerseyID
		maximum = 0 -- points, time, time_gap, speed
	}
	local calendarlistpresent={
		["UCIwomen"]=false
	}
	
	UCI["UCIwomen"] = { ['Q57267790']='2019',['Q47005682']='2018',['Q27765666']='2017',
		['Q22696468']='2016',['Q18348936']='2015', ['Q15831496']='2014',
		['Q6425932']='2013',[ 'Q2466796']='2012',['Q2466792']='2011',
		['Q2933831']='2010',['Q2933830']='2009',['Q2933828']='2008',
		['Q3650627']='2007',[ 'Q16154659']='2006',['Q17000868']='2005',
		['Q16154608']='2004',['Q97776002']='2003',['Q97776065']='2002',
		['Q97776121']='2001',['Q97776177']='2000',['Q97776227']='1999'
	}
	
	UCI["WWT"] = { ['Q57277246']='2019', ['Q41787783']='2018', ['Q27431192']='2017',
		['Q21034783']='2016'
		}
		
	UCI["WWC"] = { ['Q18589848']='2015', ['Q15076094']='2014', ['Q3000659']='2013',
		['Q326406']='2012',['Q326401']='2011',['Q120210']='2010',['Q326012']='2009',
		['Q326006']='2008',['Q326001']='2007',['Q325995']='2006',['Q127681']='2005',
		['Q80792']='2004',['Q16451']='2003',['Q746107']='2002',['Q979663']='2001',
		['Q44096']='2000',['Q44095']='1999',['Q39077']='1998'
	}	
	
	UCImaster={["UCIwomen"]='Q1693153', ['WWT']='Q21075974', ['WWC']='Q1517550'}
	UCImastername={["UCIwomen"]=translate("riderranking",2), ['WWT']=translate("riderranking",3), ['WWC']=translate("riderranking",4)}
	
	local listofwomencalendar={"UCIwomen", "WWC", "WWT"}

	if s.gender==1 then
		listofcalendar=listofwomencalendar
		gender='f'
	else
		gender='m'
	end
	
	ff=1
	--init table
	for ii=1900,2100,1 do
		Resulttable[tostring(ii)]={}
		for _, calendar  in pairs(listofcalendar) do
			Resulttable[tostring(ii)][calendar]={
				rank=nil, 
				sitelink=nil
			}
		end
	end

	--build the table
	for _, p1344 in statements(s.item, 'P1344') do
		thisCompetition = p1344.mainsnak.datavalue.value.id
	
		for _, calendar  in pairs(listofcalendar) do
			if UCI[calendar][thisCompetition] then
				thisyear=UCI[calendar][thisCompetition]
				minmaxyear=checkminmaxyear(minmaxyear,thisyear)
				q = p1344.qualifiers
				if q and q.P1352 and q.P1352[1].snaktype == 'value' then --rank
					rank = tonumber(q.P1352[1].datavalue.value.amount)
				else
					rank= nil
				end
				if rank then
					Resulttable[thisyear][calendar]["rank"]=tostring(rank)
					calendarlistpresent[calendar]=true
					sitelink=mw.wikibase.getSitelink(thisCompetition)
					Resulttable[thisyear][calendar]["sitelink"]=sitelink
				end
			end
		end
	end

	--display result
	if minmaxyear.minimum~=0 then
		local finalTable =mw.html.create('table'):attr('cellspacing','0')
		:attr("align","center"):cssText("text-align:center; border: 1px solid #999;  line-height: 1.8em;")
		
		local wdLin = wdLink(string.gsub(s.item, '%s', '') .. "#P1344")
		local tRow= finalTable:tag('tr'):tag('th'):cssText("background-color:#FFDF80"):wikitext(wdLin..' '..translate("riderranking",1))

		for ii=minmaxyear.minimum,minmaxyear.maximum,1 do
			tRow:tag('th'):attr("width","50px"):cssText("text-align:center; background-color:#FFDF80;padding:1px 1px;")
			:wikitext(tostring(ii))
		end

		for _, calendar  in pairs(listofcalendar) do
			if calendarlistpresent[calendar] then
				sitelink=mw.wikibase.getSitelink(UCImaster[calendar])
				local tRow=finalTable:tag('tr')
				local tCell = tRow:tag('th'):cssText("text-align:left;")
				if sitelink then
					tCell:wikitext('[['..sitelink..'|'..UCImastername[calendar]..']]')
				else
					tCell:wikitext(UCImastername[calendar])
				end
				
				for ii=minmaxyear.minimum,minmaxyear.maximum,1 do
					thisyear=tostring(ii)
					color="white"
					if Resulttable[	thisyear][calendar]["rank"] then
						if Resulttable[thisyear][calendar]["rank"]=="1" then
							color="gold"
						elseif (2<=tonumber(Resulttable[thisyear][calendar]["rank"])) and (tonumber(Resulttable[thisyear][calendar]["rank"])<=3) then
							color="YellowGreen"
						elseif (4<=tonumber(Resulttable[thisyear][calendar]["rank"])) and (tonumber(Resulttable[thisyear][calendar]["rank"])<=10) then
							color="silver"
						end
						
						tCell=tRow:tag('td'):attr("bgcolor",color)
						if Resulttable[thisyear][calendar]["sitelink"] then
							tCell:wikitext('[['..Resulttable[thisyear][calendar]["sitelink"]..'|'..
							number(gender,Resulttable[thisyear][calendar]["rank"],wiki)..']]')
						else
							tCell:wikitext(number(gender,Resulttable[thisyear][calendar]["rank"],wiki))
						end
					else
						tRow:tag('td'):wikitext(' - ')
					end
				end
			end
		end

		local UCIlink
		if wiki=="fr" then
			UCIlink="https://www.uci.org/fr/route/classements"
		else
			UCIlink="https://www.uci.org/road/rankings"
		end
		
		local tableyearsize=minmaxyear.maximum-minmaxyear.minimum+2
		
		finalTable:tag('tr'):tag('td'):addClass("navigation-only")
		:attr('colspan',tostring(tableyearsize))
		:cssText("border-top: 2px #FFDF80 solid; font-size: 80%;")
		:tag('tr')
		:tag('td'):attr('colspan',tostring(tableyearsize))
		:cssText("text-align:right")
		:tag('small'):wikitext(translate("race_reference", 1).."["..UCIlink..' UCI]')

		return 	finalTable
	end
end	

local function toboolean(str)
	if str=="true" then
		return true
	elseif str=="false" then
		return false
	else
		return str
	end
end

function p.testlocal(frame) --function to test local functions
	local function_name=frame.args[1]
	local argu=frame.args
	local temp

	if function_name=='firstValue' then
		return firstValue(argu[2],argu[3],argu[4])
	elseif function_name=='getOfficialName' then
		return getOfficialName(argu[2],argu[3],argu[4])
	elseif function_name=='getRiderLink' then
		temp=getRiderLink(argu[2],argu[3]) --only first arg returned
		return temp
	elseif function_name=='func_date' then
		return func_date(argu[2],argu[3])
	elseif function_name=='getTeam' then
		temp=getTeam(argu[2],argu[3],argu[4])
		if temp then return temp else return 'nil' end
	elseif function_name=='getStatementForTime' then
		temp=getStatementForTime(argu[2],argu[3],argu[4])	
		if temp then
			return temp.mainsnak.datavalue.value.id
		else
			return 'nil'
		end
	elseif function_name=='getTeamLinkCat' then
		temp=getTeamLinkCat(argu[2],argu[3],toboolean(argu[4]),toboolean(argu[5]))	
		if temp then return temp else return 'nil' end
	elseif function_name=='seasonToTeamID' then
		return seasonToTeamID(argu[2])
	elseif function_name=='translate' then
		return translate(argu[2],tonumber(argu[3]))
	elseif function_name=="classLink" then
		return classLink(argu[2])
	end
end

function p.test_import(frame)
	local function_name=frame.args[1]
	local argu=frame.args

	if function_name=='class' then
		return tostring(class[tonumber(argu[2])])
	elseif function_name=='class_2x' then
		return tostring(class_2x[tonumber(argu[2])])
	elseif function_name=='class_without2x' then
		return tostring(class_without2x[tonumber(argu[2])])
	elseif function_name=="class_sort" then
		return tostring(class_sort[argu[2]])
	elseif function_name=='classes' then
		return tostring(classes[argu[2]])
	elseif function_name=='stages' then	
		return tostring(stages[tonumber(argu[2])])
	elseif function_name=='bg_color_table' then	
		local temp = bg_color_table[argu[2]]
		temp=string.gsub(temp,'#',"")
		return temp
	end
end

return p