Module:Infobox/Descriptif course cycliste/Bac à sable

 Documentation[voir] [modifier] [historique] [purger]

Cette page définit un module d'infobox. Pour les conseils sur l'usage de ce module, voyez Modèle:Infobox Descriptif course cycliste/Bac à sable.


local wikidata = require "Module:Wikidata"
local general = require "Module:Infobox/Fonctions"
local sports = require "Module:Infobox/Fonctions/Compétition sportive"
local wikibase = mw.wikibase
local contentLanguage = mw.getContentLanguage()
local itemID  --we work with ID instead of entity
flag_table = {}
wiki="fr"
local Circuitlink

local t = {race={
			raceId,
			raceDate,
			future,
			}, 
		  vainqueur= {},
		  lastEditionMonth, 
		  lastEditionYear, 
		  numberOfEditions,
		  lastLink,
		  nextLink,
		  lastWinner,
		  maxWinner,
		  }
--
local class = { "Q22231106", "Q22231107", "Q22231108", "Q22231109", "Q22231110", "Q22231111", "Q22231112",
	"Q22231113", "Q22231114", "Q22231115", "Q22231116", "Q22231117", "Q22231118", "Q22231119", "Q23015458",
	"Q23005601", "Q23005603" }

-- ##### Functions from Cycling Race module #####
-- Note they are copied here to avoid problem when Cycling Race is updated

local function nextStatement(state, i)
	local s
	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

local function firstValue(QID, PID, field)
	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
end

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 Wikidata statement for an entity and property valid at the given timevalue ]]
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

local function getOfficialName(teamID, timeOfRace,season) -- for team
	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
		return p1448.mainsnak.datavalue.value.text, false
	end
	local label=wikibase.getLabel(teamID)
	if season and season==true then
		if label then return string.sub(label,1,label:len()-5) end -- 
	else
		return label -- No official name, try label
	end
end

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 flags = {
		Q16 = {'CAN', {'Flag of Canada.svg', '+1965-02-15'}},
		Q17 = {'JPN', {'Flag of Japan.svg', '+1999-08-13'}},
		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'}},
		Q40 = {'AUT', {'Flag of Austria.svg', '+1945-05-01'}},
		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'}},
		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'}},
		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'}},
		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'}},
		Q664 = {'NZL', {'Flag of New Zealand.svg'}},
		Q711 = {'MGL', {'Flag of Mongolia.svg'}},
		Q717 = {'VEN', {'Flag of Venezuela.svg', '+2006'}},
		Q736 = {'ECU', {'Flag of Ecuador.svg'}},
		Q739 = {'COL', {'Flag of Colombia.svg'}},
		Q750 = {'BOL', {'Flag of Bolivia.svg', '+1851-10-31'}},
		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'}},
		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'}},
		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'}},
		Q884 = {'KOR', {'Flag of South Korea.svg', '+1997-10'}},
		Q928 = {'PHI', {'Flag of the Philippines.svg', '+1998'}},
		Q948 = {'TUN', {'Flag of Tunisia.svg', '+1999-07-03'}},
		Q965 = {'BUR', {'Flag of Burkina Faso.svg'}},
		Q986 = {'ERI', {'Flag of Eritrea.svg'}},
		Q1000 = {'GAB', {'Flag of Gabon.svg', '+1960-08-09'}},
		Q1008 = {'CIV', {"Flag of Côte d'Ivoire.svg"}},
		Q1009 = {'CMR', {'Flag of Cameroon.svg'}},
		Q1028 = {'MAR', {'Flag of Morocco.svg'}},
		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'}},
		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'}},
		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'}},
		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)
		Q713750 = {'FRG', {'Flag of Germany.svg'}}, --West 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 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
	if file then
		return '[[Fichier:' .. file .. '|border|20px|' .. 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 '[[Fichier:' .. p41[1].mainsnak.datavalue.value .. '|border|20px|(Wikidata:' .. countryID .. ')]]' .. trackingCategory
		end
	else
		-- Search flag for specific date
		local p41 = getStatementForTime(countryID, "P41", date) -- P41 is flag image
		if p41 then
			return '[[Fichier:' .. p41.mainsnak.datavalue.value .. '|border|20px|(Wikidata:' .. countryID .. ')]]' .. trackingCategory
		end
	end
	return trackingCategory
end

function black_list(wiki, Label)
	--[[ 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. ]]
	local black_list = {}
	if wiki=='de' then black_list={ ["Ryan Anderson"]=true, ["Chris Butler"]=true, ["Josef Černý"]=true, ["Brad Evans"]=true, ["Robert Fontaine"]=true,
		["Carlos Giménez"]=true, ["George Harper"]=true, ["Mathias Jørgensen"]=true, ["Luis Lemus"]=true, ["David Lozano"]=true, ["Jan Maas"]=true,
		["James McLaughlin"]=true, ["Nikolaj Michajlow"]=true, ["Antonio Molina"]=true, ["Ben O'Connor"]=true, ["Andrea Peron"]=true, ["Cristian Rodríguez"]=true,
		["Nick Schultz"]=true, ["Adam Stachowiak"]=true, ["Michel Vermote"]=true, ["Johannes Weber"]=true, ["Martin Weiss"]=true, ["Christopher Williams"]=true,
		["Samuel Williams"]=true, ["Peter Williams"]=true, ['Stephen Williams']=true, ["Michael Woods"]=true, ["Michael Wright"] = true, ["Edoardo Zardini"]=true,
		["Georg Zimmermann"]=true } end
	if wiki=='en' then black_list={ ["Tiago da Silva"]=true, ["Jan Maas"]=true, ["Alexander Meier"]=true, ["James McLaughlin"]=true, ["Andrea Nencini"]=true,
		["Johannes Weber"]=true } end
	if wiki=='fr' then black_list={['Pierre Barbier']=true, ['Jessica Cutler']=true, ['Fernanda da Silva']=true, ['Guillaume Delvaux']=true, ['Willy De Waele']=true,
		['Jules Dubois']=true, ['Jean Dupont']=true, ['Robert Fontaine']=true, ['René Fournier']=true, ['Pierre Gauthier']=true, ['Marc Goossens']=true,
		['Claude Guyot']=true, ['Amy Hill']=true, ['Liang Hongyu']=true, ['Marcus Johansson']=true, ['Mathias Jørgensen']=true, ['José Mendoza']=true,
		['Daniel Müller']=true, ['Henri Parmentier']=true, ['Jean Raynal']=true, ['Pascal Robert']=true, ['Jean-Yves Roy']=true, ['Michael Shermer']=true,
		['Juris Silovs']=true, ['Jacques Simon']=true, ['Guy Thomas']=true, ['Ryan Thomas']=true, ['Hans Vonk']=true, ['Jan Wijnants']=true } end
	return black_list[Label]
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

--[[ Iterator to get all statements for an entity and property which are not deprecated and have a value]]
local function getRiderLink(riderID)
	local sitelink = wikibase.getSitelink(riderID)
	if sitelink then
		if wiki == "de" then
			-- Russian riders get label as alias, to shorten the name
			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 .. "]]"
					end
				end
			end
		end
		return "[[" .. sitelink .. "|" .. mw.text.trim(mw.ustring.gsub(sitelink, "%b()", "")) .. "]]"
	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
			local title = mw.title.new(label)
			if title and title.exists then
				link = label
			else
				link = mw.getCurrentFrame():expandTemplate{ title = 'Ill-WD2',
						args = {id=riderID,target='en',label=Label} } --"[[" .. Label.. "]]"
			end
		else
			if black_list(wiki, 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
	end

	-- No label in the local language. Try other languages, but don't link.
	if wiki == 'ar' then
		link = getLabelFallback(riderID, {'en', 'fr', 'de'})
	else
		link = getLabelFallback(riderID, {'en', 'de'})
	end
	if link then
		link = mw.ustring.gsub(link, "%b()", "")
	else
		link = "(label missing)"
	end
	return link
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)
	local name, sitelink, parentID
	-- Find team category
	local catID = firstValue(teamID, 'P31', 'id') -- P31 is 'instance of'
	-- Find country if needed
	local countryID
	if country or catID == 'Q23726798' or catID == 'Q20738667' then
		countryID = firstValue(teamID, 'P17', 'id') -- P17 is country
	end
	if countryID and (catID == 'Q23726798' or catID == 'Q20738667') 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
		sitelink = getRawTeamLink(teamID)
	else
		-- It is not a national cycling team
		local isLocal
		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

		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

function getTeam(riderID, timeOfRace, q)
	-- q: qualifiers of statement in race entity where the rider is the value
	local teamID, link
	if 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
		p54 = getStatementForTime(riderID, 'P54', timeOfRace)
		if p54 then
			teamID = p54.mainsnak.datavalue.value.id
			link = getTeamLinkCat(teamID, timeOfRace)
		end
	end
	return link
end

function WPlinkBest(Qnumber, ...)  --Simplified
	local link=''
	local Sitelink = wikibase.getSitelink(Qnumber)
	local Label_fr = wikibase.getLabelByLang(Qnumber, wiki)--'fr'

	if Sitelink ~= nil  then 
		link = "[[" .. Sitelink .. "|" .. mw.text.trim(mw.ustring.gsub(Sitelink, "%b()", "")..' ') .. "]]"
	elseif Label_fr ~= nil  then
		link = "[[" ..Label_fr .. "]]"
	else
		link = "Unknown ID"
	end	
	return link
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

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

-- ##### Code of Infobox #####
--winnerId added to Module:Cycling race function
local function winner(raceID, winners, timeOfRace, country, WDlink_on, team, ref, winnersId)
	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)
								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 winnersId and winnersId[wOf] then
							if disqualified or ((not wID) and wCriterion) then 
								winnersId[wOf]= 'Q666' --to identify disqualification
							else
								winnersId[wOf]= wID --identify cancelled
							end
						end
						if winners[wOf] == '' then
							winners[wOf] = riderLink
						else
							winners[wOf] = winners[wOf] .. '<br/>' .. riderLink
						end
					end
				end
			end
		end
	end
end

local function getFormerNames( )
	local names, periods = {}, {}
	for i, p1448 in statements(itemID, 'P1448') do  --_, p527
		table.insert(names, wikidata.formatStatement(p1448))
		table.insert(periods, wikidata.getFormattedDate(p1448, {linktopic = '-', precision = 'day'}))
	end
	return names, periods
end

local function formerNamesTable( localdata ) -- retourne une table de lignes contenant les anciens noms de l'équipe
	itemID=localdata.item:getId()
	local names, periods = localdata['ancien_nom'], localdata['saison']
	local rows = {}
	if names then
		names =  mw.text.split(names, '<br>')
		periods = mw.text.split(periods or '', '<br>')
	else
		names, periods = getFormerNames( localdata.item )
	end
	if not names then  --no former name
		table.insert( rows, {type = 'row', label = "label", value = nil})	
		return {type = 'table', title = 'label', rows = rows}
	end
	
	for i, period in pairs(periods) do
		table.insert( rows, {type = 'row', label = period, value = function () return names[i] end})	
	end
	local title = 'Noms officiels'
	if #names == 1 then
		title = 'Nom officiel'
	end
	return {type = 'table', title = title, rows = rows}
end

local function siteofficiel()
	local p856 = wikibase.getBestStatements(itemID, 'P856')
	if p856[1] and p856[1].mainsnak.snaktype == 'value' then
		return wikidata.formatAndCat{claims = links, property = 'P856', displayformat = 'weblink', showlang = true, text = 'Site officiel'}
	end
end

local function compareDate(tdate) --test future
	local today=os.date("*t") 
	local _, _, y, m, d = string.find(tdate, "(%d+)%p(%d+)%p(%d+)")
	local tYear=tonumber(y)
	local tMonth=tonumber(m)
	local tDay=tonumber(d)
	
	if tYear>today['year'] then
		return true
	elseif tYear<today['year'] then
		return false  --the last race is the future
	else
		if tMonth>today['month'] then
			return true
		elseif  tMonth<today['month'] then
			return false
		else
			if tDay>today['day'] then	
				return true
			elseif  tDay<today['day'] then	
				return false
			else
				return false --arbitrary
			end
		end
	end
end

local function evaluateWinnerMax()
	local winners = t.vainqueur
	local result
	local most_wins = 0
	local most_wins_ID = {}
	for winnerID, winner in pairs(winners) do
		if winner.count > most_wins then
			most_wins = winner.count
			most_wins_ID = { winnerID }
		elseif winner.count == most_wins then
			most_wins_ID[#most_wins_ID + 1] = winnerID
		end
	end

	if most_wins > 1 then
		for _, id in pairs(most_wins_ID) do
			if not result then
				result=winners[id].link
			else
				result=result.."<br>"..winners[id].link
			end
		end
		result=result.."<br>("..most_wins.." victoires)"
	end
	t.maxWinner=result
end

local function listOfWinners()
	local winners = {	Q20882667 = '',}-- Q20882667 is 'overall winner general classification'
	local winnersId={	Q20882667 = '',}--to detect disqualification
	local WDlink_on, sitelink

	-- WDlink_on is used to decide if a Wikidata flag will be shown
	if wiki == "mk" or wiki == "ja" or wiki == "ru" then WDlink_on = true else WDlink_on = false end

    -- Get the date to sort the editions
	for _, p527 in statements(itemID, 'P527') do  --_, p527
		local raceDate, year, raceID, entity_race, a, b 
		raceId = 'Q'..p527.mainsnak.datavalue.value['numeric-id'] -- Qnumbers of the parts of a tour
		
		local p580 = wikibase.getBestStatements(raceId, "P580")
		if p580[1] and p580[1].mainsnak.snaktype == 'value' then
			raceDate= p580[1].mainsnak.datavalue.value.time
		else
			local p585 = wikibase.getBestStatements(raceId, "P585") --Lastrace -- P585 is point in time
			if p585[1] and p585[1].mainsnak.snaktype == 'value' then
				raceDate= p585[1].mainsnak.datavalue.value.time
			end
		end

		table.insert(t.race, { raceId=raceId, raceDate=raceDate, future=compareDate(raceDate)} ) --check if future
		table.sort(t.race, function(a,b) return a['raceDate'] < b['raceDate'] end) -- t.race is sorted after year
	end 
	--look for the next race
	local lastRunEdition, lastEditionDate, nextEdition
	
	for num, race in ipairs(t.race) do
		if race['future'] then
			nextEdition=num
			break
		end
	end
		--Get the winners
	local numberOfEditions=0
	local lastWinner, winnerId

	for num=1,#t.race do
		winners.Q20882667=''
		winnersId.Q20882667=''
		winner(t.race[num]['raceId'], winners, t.race[num]['raceDate'], false, WDlink_on, nil, nil, winnersId )
		if t.race[num]['future']==false then --in the past
			if winnersId.Q20882667~="Q30108381" then --cancelled
				numberOfEditions=numberOfEditions+1
				lastRunEdition=num
				lastEditionDate=t.race[num]['raceDate']
				lastWinner=winners.Q20882667
			end
		end
	
		winnerId=winnersId.Q20882667
		if winnerId~=nil and winnerId~='' and winnerId~='Q666' then --code for disqualification
			if not t.vainqueur[winnerId] then
				t.vainqueur[winnerId]={}
				t.vainqueur[winnerId].link=winners.Q20882667
				t.vainqueur[winnerId].count=0
			end
			t.vainqueur[winnerId].count=t.vainqueur[winnerId].count+1
		end	
	end

	local monthId=firstValue(itemID, 'P2922','id') 
	if monthId then 
		t.lastEditionMonth=getLabelFallback(monthId, {wiki, 'en', 'fr', 'de'}) or ''
	else
		t.lastEditionMonth=mw.getLanguage('fr'):formatDate("M", lastEditionDate)
	end

	t.lastEditionYear=mw.getLanguage('fr'):formatDate("Y", lastEditionDate)
	t.numberOfEditions=numberOfEditions
	evaluateWinnerMax(t)

	if lastRunEdition then
		t.lastWinner=lastWinner or '' --t.vainqueur[lastRunEdition]['link']
		sitelink = wikibase.getSitelink(t.race[lastRunEdition]['raceId'])
		if sitelink ~= nil then
			t.lastLink = "[[" .. sitelink .. "]]"
		else
			t.lastLink = nil
		end
	end
	
	if nextEdition then 
		sitelink = wikibase.getSitelink(t.race[nextEdition]['raceId'])
		if sitelink ~= nil then
			t.nextLink = "[[" .. sitelink .. "]]"
		else
			t.nextLink = nil
		end
	end	
end

local function displayCountry()
	local ttt = {tour={}, country={}}

	local ss = wikibase.getAllStatements(itemID, 'P17')
	for i, p17 in pairs(ss) do
		if p17 and p17.mainsnak.snaktype == 'value' then
   			ttt.country[i] = "C" .. p17.mainsnak.datavalue.value["numeric-id"]
   		end
 	end		

 	local k
	local tab = ""
	for k in pairs(ttt) do -- "^C" ttt.country, "^T" ttt.tour
		if ttt[k][1]~=nil and string.find(ttt[k][1], "^C") then for i=1,#ttt[k] do ttt[k][i] = string.gsub(ttt[k][i], "C", "Q") ttt[k][i] = flag(ttt[k][i], timeofrace).." ".. WPlinkBest( ttt[k][i] ) end end
		if ttt[k][1]~=nil and string.find(ttt[k][1], "^T") then for i=1,#ttt[k] do ttt[k][i] = string.gsub(ttt[k][i], "T", "Q") ttt[k][i] = WPlinkBest( ttt[k][i], 'race') end end
	end	
	if ttt.country[1] == nil then 
		tab = tab
	else	
		for i=1,#ttt.country do 
			tab = tab .. ttt.country[i].."<br>" 
		end 
 	end
 	return tab
end

local function getType()
	local result, typeID
	typeID =firstValue(itemID, 'P31', 'id')
	if typeID ~= nil then
		if typeID=="Q2912397" then
			result="[[Cyclisme_sur_route#Épreuve_d'un_jour|Course d'un jour]]"
		else
			result=WPlinkBest(typeID)
		end
	end --else result=nil
   	return result  
end

local function getClass(item)
	local str=''
	local circuitID
	for ii, p279 in statements(itemID, 'P279') do
		if p279 and p279.mainsnak.snaktype == 'value' then
			d = p279.mainsnak.datavalue.value['numeric-id']
			for jj=1,#class do -- #class = number of elements in class
				if "Q"..d == class[jj] then class_text = wikibase.label('Q'..d) break end
			end
			link = class_text
			if link ~= '' and link~=nil then
				--catch circuit
				circuitID=nil
				if "Q"..d== 'Q23005601' or "Q"..d== 'Q23005603' then --1WWT 2WWT clear
					circuitID = 'Q21075974'
				elseif "Q"..d=='Q22231106' or "Q"..d=='Q22231107' then --1UWT 2UWT clear
					circuitID = 'Q635366'
				else
					local q=p279.qualifiers
					local wOf
					if q then
						wOf = (q.P642 and q.P642[1].snaktype == 'value' and q.P642[1].datavalue.value.id)
						if wOf then	
							circuitID = q.P642[1].datavalue.value.id
						end
					end
				end--else nil
				if not circuitID then
					Sitelink = link
				else
		  			Sitelink = 	wikibase.getSitelink(circuitID)
					if Sitelink~= nil then 
						Sitelink = '[[:fr:'..Sitelink..'|'..link..']]' 
						Circuitlink = WPlinkBest(circuitID) 
					else
						Sitelink = link
					end
				end
				--add period
				args={entity = item,
							property = 'P279',
							showdate = true,
							textformat = textformat,
							linkback = true, 
							linktopic = '-'}
				tableperiod=formatStatements( args )
				Sitelink = Sitelink .. " <small>"..tableperiod[ii].."</small>"  
				str=str..Sitelink..'<br>'
			end --link =nil
		else
			return nil
		end
  end
  return str
end

function formatStatements( args )--Format statement and concat them cleanly
	local claims = {}
	for j, p279 in statements(itemID, 'P279') do
		claims[j] = getPeriod(p279, args)
	end
	return claims
end

function getPeriod( statement, args )
	local str = ''
	local period = wikidata.getFormattedDate(statement, args, "-") -- 3 arguments indicate the we should not use additional qualifiers, alrady added by wd.formatStatement
	if period then
		str = str .. " <small>(" .. period ..")</small>"
	end
	return str
end

return {
	maincolor = '#FFDF80',
	parts = {
		general.title('cyclisme'),
		general.mainimage('Article à illustrer Compétition sportive'),
		formerNamesTable,
		{type = 'table', title = 'Généralités', rows = {
		{type = 'row', label = 'Sport', value = 'sport', property = 'P641'},
		{type = 'row', label = 'Création', value = 'creation', property = 'P571'},
		{type = 'row', label = 'Disparition', value = 'disparition', property = 'P576'},
		{
				type = 'row',
				value = "nombre d'éditions",
				wikidata = function ( item ) -- suppose que P527 ne contienne que des saisons, et contienne toutes les saisons
					listOfWinners() --populate t
					local str = tostring(t.numberOfEditions).." (en "..tostring(t.lastEditionYear)..")"
					str = wikidata.addLinkBack(str, item, 'P527')
					str = str .. wikidata.addTrackingCat('P527')
					return str
				end,
				label = function () --"Nombre d'éditions""Nombre d'éditions"
					if (not t.numberOfEditions) or t.numberOfEditions == 1 then
						return 	"Nombre d'édition"
					end
					return 	"Nombre d'éditions"
				end,
		},
		{
				type = 'row', 
				label = 'Périodicité',
				value = 'périodicité',
				wikidata = function ()
					local p = wikibase.getBestStatements(itemID, 'P2257')
					if p[1] and p[1].mainsnak.snaktype == 'value' then
						local period=p[1].mainsnak.datavalue.value.amount
						local periodunit=p[1].mainsnak.datavalue.value.unit
						if tonumber(period)==1 and periodunit == 'http://www.wikidata.org/entity/Q577' then
							return "annuelle".." ("..t.lastEditionMonth ..")"
						elseif tonumber(period)==1 and periodunit == 'http://www.wikidata.org/entity/Q5151' then
							return "mensuel"
						else
							return nil
						end
					else
						return nil
					end
				end,
			},
		{type = 'row', label = 'Type / Format', value = 'type', 
			wikidata=function()
				return getType()
			end
		},
		{type = 'row', label = 'Lieu(x)', value = 'lieu', 
			wikidata=function()
				return displayCountry()
				end,
		},
		{
				type = 'row',
				label = function ( localdata )
					local claims = wikibase.getAllStatements(itemID, 'P279')
					if (not claims) or #claims == 1 then
						return "Catégorie"
					end
					return "Catégories"
				end,
				value = "catégorie",
				wikidata = function (item)
					return getClass(item)
					end,
		},
		{
				type = 'row',
				label = 'Circuit',
				value='circuit',
				wikidata = function ()
					return Circuitlink
					end,
		},
			{
				type = 'row',
				label = 'Ancien nom',
				value='ancien nom',
			},
			{
				type = 'row',
				label = 'Organisateur',
				value='organisateur',
				property = 'P664',
			},
			{
				type = 'row',
				label = 'Directeur',
				value='directeur',
			},
			{
				type = 'row',
				label = 'Nations',
				value='nations ',
			},
			{
				type = 'row',
				label = 'Participants',
				value='participants',
			},
			{
				type = 'row',
				label = 'Statut des joueurs',
				value='statut des joueurs',
			},
			{
				type = 'row',
				label = 'Site web officiel',
				value='site web',
				wikidata = function ( item )
						return siteofficiel(item)
					end,
			},
		}},
		{type = 'table', title = 'Palmarès', rows = {
		{
				type = 'row', 
				label = 'Dernier vainqueur',
				value = 'dernière vainqueur',
				wikidata = function ()
					if t.lastWinner then 
						return t.lastWinner 
					else 	
						return ""
					end
				end,
			},
			{
				type = 'row', 
				label = 'Plus titré(s)',
				value = 'Plus titré',
				wikidata = function ()
					if t.maxWinner then 
						return t.maxWinner
					else	
						return ""
					end
				end,
		},
		}},
		{type = 'table', title = 'Compétitions actuelles', rows = {
		{
				type = 'row', 
				value = 'saison dernière',
				wikidata = function ()
					if t.lastLink then
						return "[[Fichier:Crystal Clear app kworldclock.png|left|37px]] pour la dernière compétition voir :<br>'''"..t.lastLink.."'''"
					else
						return nil
					end
				end,
		},
		{
				type = 'row', 
				value = 'Saison en cours',
				wikidata = function ()
					if t.nextLink then
						return "[[Fichier:Crystal Clear app kworldclock.png|left|37px]] pour la prochaine compétition voir :<br>'''"..t.nextLink.."'''"
					else
						return nil
					end
				end,
			},

	}},
	}
}