Modul:Sportdata
Utseende
Dokumentation [visa] [redigera] [historik] [rensa sidcachen]
Detta är en hjälpmodul som innehåller funktioner som används av flera andra moduler, som :
För att använda funktionerna behöver du skriva require( 'Modul:Sportdata') i modulen som använder funktionerna. Modulen utnyttjar själv modulerna Modul:Sportdata localisation (för att underlätta översättning till andra språk ligger alla textsträngar som är språkberoende här), Modul:Sportdata rankings (ranking för olika idrottstävlingar för att t.ex. prioritera VM & OS högre än spel i lägre divisionerna i den nationella ligan) samt Modul:Referenshantering (för att visa referenser).
Funktioner
[redigera wikitext]competitionData
[redigera wikitext]isClub
[redigera wikitext]- Syfte: Avgöra om en entitet är en klubb (till skillnad från ett landslag)
- Returnerar: sant/falskt
- Argument:
- id – id (Q följt av ett nummer, som t.ex. 'Q3149147') för för det objekt som du vill testa ifall den är en klubb (t.ex. Imoco Volley (Q3149147))
- txtProperty – den egenskap som du vill använda för utvärderingen. Ska sättas till 'P31' (instans av (P31)) vid anrop (däremot anropar funktionen sig själv med underklass till (P279))
- Vad funktionen gör: funktionen loopar igenom alla värden för objektets instans av (P31).
- Om landslag (Q1194951) returnerar den falskt.
- Om idrottsförening (Q847017), idrottslag (Q12973014), volleybollklubb (Q108395614) eller multisportklubb (Q13580678) returnerar den sant
- Om den har något annat värde anropar den funktionen sig själv för att undersöka om värdet är en underklass till (P279) till något av de ovanstående.
isNationalTeam
[redigera wikitext]- Syfte: Avgöra om en entitet är ett landslag (till skillnad från en klubb)
- Returnerar: sant/falskt
- Argument:
- id – id (Q följt av ett nummer, som t.ex. 'Q3873841') för det objekt som du vill testa ifall den är ett landslag (t.ex. Sveriges damlandslag i volleyboll (Q3873841))
- txtProperty – den egenskap som du vill använda för utvärderingen. Ska sättas till 'P31' (instans av (P31)) vid anrop (däremot anropar funktionen sig själv med underklass till (P279))
- Vad funktionen gör: funktionen loopar igenom alla värden för objektets instans av (P31).
- Om dess värde är landslag (Q1194951) returnerar den sant.
- Om den har något annat värde anropar den funktionen sig själv för att undersöka om värdet är en underklass till (P279) till landslag (Q1194951)
processDates
[redigera wikitext]tblSeasonData
[redigera wikitext]tblTeamInfo
[redigera wikitext]txtDate
[redigera wikitext]txtPosition
[redigera wikitext]- Syfte: Skapa tabellcell med en person/ett lags placering i en tävling, som är färgsatt om de kom på medaljplats
- Returnerar: textsträng (html-kod för cellen)
- Argument:
- iPosition – placeringen i tävlingen
- Vad funktionen gör:
- Skapar en tabellcell med placering
- Placeringen är 1 (█), 2 (█) eller 3 (█) får cellen respektive färg, annars ingen bakgrund.
txtTeamname
[redigera wikitext]- Syfte: Avgöra namnet på ett lag under ett visst år
- Returnerar: textsträng (lagnamnet som wikilänk)
- Argument:
- idTeam – id (Q följt av ett nummer, som t.ex. 'Q3873841' för Sveriges damlandslag i volleyboll (Q3873841)) för lagets objekt
- year – årtalet för vilket du vill veta klubbens namn
- Vad funktionen gör: undersöker klubbens officiellt namn (P1448). Om det är satt loopar den igenom alla värden
- Om värdet har bestämningarna att
- startdatum (P580) <= year och det inte finns slutdatum (P582)
- startdatum (P580) <= year och slutdatum (P582) >= year
- Det inte fanns startdatum (P580) och slutdatum (P582) >= year,
- så returnerar funktionen det värdet (namnet) för den bestämningen
- ett undantag är om namnet är tomt (nil) då returnerar funktionen istället 'Namn ej inlagt på svenska än'
- Om funktionen inte hittar något värde där bestämningarna uppfyller villkoren ovan returnerar funktionen 'Namn finns inte för det årtalet'
- Om värdet har bestämningarna att
txtYears
[redigera wikitext]- Syfte: Formatera en textsträng med start- och/eller slutår
- Returnerar: textsträng
- Argument:
- startyear – startår (kan vara tom)
- endyear – slutår (kan vara tom)
- Vad funktionen gör (returnerar):
- Om både startyear och endyear finns:
- Om de är olika: returnerar startyear–endyear
- Om de är samma: returnerar startyear
- Om startyear finns, men inte endyear: returnerar startyear–
- Om endyear finns, men inte startyear: returnerar –endyear
- Om var sig startyear eller endyear finns: returnerar tom sträng
- Om både startyear och endyear finns:
years
[redigera wikitext]localisation = require( 'Modul:Sportdata localisation' )
local sdr = require( 'Modul:Sportdata rankings' )
settings = require( 'Modul:Sportdata settings' )
local rm = require( 'Modul:Referenshantering' )
localisation.txtLocationLackCountryForGivenDate='(land saknas)'
localisation.txtLocationLackCountryForGivenDateRef='I Wikidata finns ingen uppgift om vilket land orten tillhörde vid aktuell tidpunkt'
localisation.txtLocationLackCountryForGivenDateCategory='Artiklar med orter som saknar uppgift om land vid aktuell tidpunkt'
local sd={}
local veryearly="+0001-01-01T00:00:00Z"
arrayFlagCountries={ Q29999 ='Q55'} -- Cases where on object will not produce a flag and hence another object will be used
function txtShowLink(tblItem)
if (tblItem.txtSitelink) then
return '[[' .. tblItem.txtSitelink .. '|' .. tblItem.txtLabel .. ']]'
else
return tblItem.txtLabel
end
end
p.competitions_without_ranking=function(frame)
p.frame=frame
p=p.data()
local results=p.filter(p,"results","iCompetitionRank",9999999)
txt=localisation.txtDescriptionMissingRanks .. "<table class='wikitable'><tr><th>" .. localisation.txtId_ltabel .. "</th><th>" .. localisation.txtLabel_label .. "</th></tr>"
for i=1,#results do
txt=txt.."<tr><td>" .. results[i].competitiontype.qid .. "</td><td>" .. results[i].competitiontype.txtLabel .. "</td>"
end
txt=txt.."</table>"
return txt
end
p.lastchecked=function()
local results=p.all(p,"results")
local latestdate=findlatestdate(results)
if not latestdate then
latestdate=veryearly
end
if (p.age) then -- If a person and not a club
local teams_played=p.all(p,"teams_played")
if (teams_played) then
local latestdate_teams_played=findlatestdate(teams_played)
if (latestdate_teams_played>latestdate) then
latestdate=latestdate_teams_played
end
end
if (teams_coached) then
local teams coached=p.all(p,"teams_coached")
local latestdate_teams_coached=findlatestdate(teams_coached)
if (latestdate_teams_coached>latestdate) then
latestdate=latestdate_teams_coached
end
end
else
p.alive=not p.dissolved
end
local latestyear=tonumber(string.sub(latestdate,2,5))
local yearsince = tonumber(os.date("%Y"))-latestyear
local potentially_active= yearsince<settings.iCareerAssumedEndedIfNothingNewInThisManyYears
local bNoDateFormat=true
if ((localisation.dateformat=='YYYY-MM-DD') or (localisation.dateformat=='DD-MM-YYYY')) then
bNoDateFormat=false
end
local txtLastChecked=p.frame.args['lastchecked']
if (not (bNoDateFormat or isempty(txtLastChecked))) and ((#txtLastChecked==8) or (#txtLastChecked==10)) then
local yearLastChecked,monthLastChecked,dayLastChecked
if (#txtLastChecked==8) then
if (localisation.dateformat=='YYYY-MM-DD') then
yearLastChecked=tonumber(string.sub(txtLastChecked,1,4))
monthLastChecked=tonumber(string.sub(txtLastChecked,5,6))
dayLastChecked=tonumber(string.sub(txtLastChecked,7,8))
end
if (localisation.dateformat=='DD-MM-YYYY') then
dayLastChecked=tonumber(string.sub(txtLastChecked,1,2))
monthLastChecked=tonumber(string.sub(txtLastChecked,3,4))
yearLastChecked=tonumber(string.sub(txtLastChecked,5,8))
end
end
if (#txtLastChecked==10) then
if (localisation.dateformat=='YYYY-MM-DD') then
yearLastChecked=tonumber(string.sub(txtLastChecked,1,4))
monthLastChecked=tonumber(string.sub(txtLastChecked,6,7))
dayLastChecked=tonumber(string.sub(txtLastChecked,9,10))
end
if (localisation.dateformat=='DD-MM-YYYY') then
dayLastChecked=tonumber(string.sub(txtLastChecked,1,2))
monthLastChecked=tonumber(string.sub(txtLastChecked,4,5))
yearLastChecked=tonumber(string.sub(txtLastChecked,7,10))
end
end
local argsLastChecked={dayLastChecked,monthLastChecked,yearLastChecked}
local iYearsBeforeUpdateNeeded
if p.alive then
if potentially_active then
iYearsBeforeUpdateNeeded=settings.iCheckFrequencyWhenActive -- Need to check frquently
else
iYearsBeforeUpdateNeeded=settings.iCheckFrequencyLikelyNoLongerActive -- No need to check frquently if career likely to have ended (but can let it pop up after a long time in case some information was missed or restarted career, for example as a coach)
end
else
iYearsBeforeUpdateNeeded=settings.iCheckFrequencyWhenDead -- No need to check frquently if dead (but can let it pop up after a long time in case some information was missed)
end
local argsUpdateAfter={yearLastChecked+iYearsBeforeUpdateNeeded,monthLastChecked,dayLastChecked,"","[[" .. txtCategory .. ":" .. txtNotUpdatedCategory .. "]]"}
--Empty row added for esthetic reasons, to separate the date from the rest of the infobox
p.iCounter=p.iCounter+1
myArgs[txtContent .. p.iCounter]=" "
--Write out the when data last checked, include a note about what is meant by the date
p.iCounter=p.iCounter+1
myArgs[txtLabel .. p.iCounter]=txtLastCheckedLabel .. p.frame:extensionTag("ref", txtLastCheckedLabel_Clarification)
myArgs[txtContent .. p.iCounter]=p.frame:expandTemplate{title=localisation.txtDMYtemplate,args=argsLastChecked} .. p.frame:expandTemplate{title=localisation.txtShowAftertemplate,args=argsUpdateAfter}
else
if (p.alive and potentially_active) then
p.iCounter=p.iCounter+1
myArgs['under']=myArgs['under']..'[[' .. txtCategory .. ':' .. localisation.txtNoLastCheckedDate .. ']]'
end
end
end
-- Function to find the element with the latest date
function findlatestdate(tbl)
if #tbl == 0 then return veryearly end
local latestElement = tbl[1]
latestElement.date=veryearly
for _, element in ipairs(tbl) do
bFound=false
if (element.txtDateTo) then
element.date=element.txtDateTo
bFound=true
end
if (not bFound) and (element.txtDateFrom) then
element.date=element.txtDateFrom
bFound=true
end
if (not bFound) and element.to and element.to.raw then
element.date=element.to.raw
bFound=true
end
if (not bFound) and element.from and element.from.raw then
element.date=element.from.raw
bFound=true
end
if not (bFound) then
element.date=veryearly
end
if element.date > latestElement.date then
latestElement = element
end
end
return latestElement.date
end
function txtPosition(iPosition,txtIsQualifier)
local bMedal=0
if (iPosition==999999) then
iPosition=nil
end
if (iPosition==999998) then
iPosition=txtQualifier
end
if not (iPosition==nil) then
if ((iPosition==1) or (iPosition=="1")) then
txtPosColour='gold'
bMedal=1
end
if ((iPosition==2) or (iPosition=="2")) then
txtPosColour='silver'
bMedal=1
end
if ((iPosition==3) or (iPosition=="3")) then
txtPosColour='#CC9966'
bMedal=1
end
if (bMedal==1) then
return '<td align="center" bgcolor="' .. txtPosColour .. '">' .. iPosition .. '</td>'
else
return '<td>' .. iPosition .. '</td>'
end
else
return '<td></td>'
end
end
function txtYears(startyear,endyear,txtSeparator)
if (not (txtSeparator)) then
txtSeparator='–'
end
if (startyear=='' or startyear==nil) then
if (endyear=='' or endyear==nil) then
if (endyear=='' or endyear==nil) then
return ''
else
return txtSeparator
end
else
return txtSeparator .. endyear
end
else
if (endyear==startyear) then
return startyear
else
return startyear .. txtSeparator .. endyear
end
end
end
function processDates_model(entityid,txtSeparator)
txtDateFrom=''
txtDateTo=''
local p580=mw.wikibase.getAllStatements(entityid, 'P580' )
local hasstart=next(p580)
p582=mw.wikibase.getAllStatements(entityid, 'P582' )
local hasend=next(p582)
if hasstart then
txtDateFrom=read(p580[1],'time')
end
if hasend then
txtDateTo=read(p582[1],'time')
end
--For sorting purposes set date from and to date to the same if one of them is lacking
if hasend and not hasstart then
txtDateFrom=txtDateTo
end
if hasstart and not hasend then
txtDateTo=txtDateFrom
end
hasanydate=hasstart or hasend
return hasanydate,txtDateFrom,txtDateTo
end
function years(value)
if value['qualifiers'] then
if value['qualifiers']['P580'] then
startdate=readQualifier(value.qualifiers.P580[1],'time') or '' -- readQualifier returns nil when P580 is "somevalue"
startyear=string.sub(startdate,2,5)
else
startdate=''
startyear=''
end
if value['qualifiers']['P582'] then
enddate=readQualifier(value.qualifiers.P582[1],'time') or '' -- readQualifier returns nil when P582 is "somevalue"
endyear=string.sub(enddate,2,5)
else
enddate=''
endyear=''
end
return startyear,endyear,startdate,enddate
end
return '','','',''
end
function readDate(value,pid)
if value['qualifiers'] then
if value['qualifiers'][pid] then
if value['qualifiers'][pid][1] then
local date={}
datesnak=value['qualifiers'][pid][1]
date.raw=readQualifier(datesnak,'time')
date.precision=readQualifier(datesnak,'precision')
if (date.raw) then
date.year=string.sub(date.raw,2,5)
else
return nil
end
date.formatted=mw.wikibase.formatValue(datesnak)
return date
end
end
end
return nil
end
function readStatementAtDate(qid,pid,type,asofdate)
local ret={}
if not(asofdate) then
asofdate=rm.now()
end
local claims = mw.wikibase.getAllStatements(qid,pid) -- If the club have had many names, loop through to find the one that was used when the player played at the club
if (next(claims)) then
if (type=='text') then
return rm.readtext(claims, asofdate)
else
-- Loop through results
for key, value in pairs( claims ) do
local datefrom,dateto = readDates(value)
local txtFrom,txtTo
if (datefrom) then
txtFrom=datefrom.raw
if isempty(txtFrom) then datefrom=nil end
end
if (dateto) then
txtTo=dateto.raw
if isempty(txtTo) then dateto=nil end
end
if (not(datefrom) and not(dateto)) or (datefrom and not(dateto) and asofdate >= txtFrom) or (not(datefrom) and dateto and asofdate <= txtTo) or (datefrom and dateto and asofdate >= txtFrom and asofdate <= txtTo) then
return true,read(value,type)
end
end
end
end
return false
end
function readDates(value)
local startdate=readDate(value,'P580')
local enddate=readDate(value,'P582')
if not (startdate or enddate) then
startdate=readDate(value,'P585')
enddate=startdate
end
return startdate,enddate
end
function txtDate (iYear,iMonth,iDay)
bHasMonth=not isempty(iMonth)
bHasDay=not isempty(iDay)
if (bHasMonth and bHasDay) then
return mw.getCurrentFrame():preprocess('{{#time:[[j F]] [[Y]]|'..iYear..'-'..iMonth..'-'..iDay..'}}')
else
if (bHasMonth) then
return mw.getCurrentFrame():preprocess('{{#time:F [[Y]]|'..iYear..'-'..iMonth..'-01}}')
else
return '[[' .. iYear .. ']]'
end
end
end
function isClub( id,txtProperty,iLevel )
if isempty(id) then
return false
end
if not (iLevel) then
iLevel=1
end
if (iLevel==1) then
if (isNationalTeam( id,txtProperty,iLevel)) then return false end
end--Start by checking it is not a national team
local instanceofs=mw.wikibase.getBestStatements(id, txtProperty )
local key, value
for key, value in pairs( instanceofs ) do
local txtId=read(value,'id')
if (txtId == 'Q847017' or txtId == 'Q12973014' or txtId=='Q108395614' or txtId=='Q13580678' or txtId=='Q115898316' or txtId=='Q15944511' or txtId=='Q476028') then return true end
if (iLevel<4) then
if (isClub(txtId,'P279',iLevel+1)) then return true end
end
end
return false
end
function isNationalTeam( id,txtProperty,iLevel)
if isempty(id) then
return false
end
if not (iLevel) then
iLevel=1
end
local instanceofs=mw.wikibase.getBestStatements(id, txtProperty );
for key, value in pairs( instanceofs ) do
local txtId=read(value,'id')
if txtId=='Q1194951' then return true end
if (iLevel<4) then
if (isNationalTeam(txtId,'P279',iLevel+1)) then return true end
end
end
return false
end
function allsame(tbl,property)
bAllSame=true
iLastType=nil
local key,value
for key, value in pairs(tbl) do
if (bAllSame and (value[property])) then --Only loop till a different value has been found
if (iLastType==nil) then --If first item set value for iLastType, otherwise compare if same as last one
iLastType=value[property]
else
bAllSame=iLastType==value[property]
end
end
end
return bAllSame
end
function getImage(qid,pid)
img=mw.wikibase.getBestStatements(qid, pid )
bDescription=false -- variable to check if a description has been found
if next(img) then
image={}
image.txtFilename = img[1]['mainsnak']['datavalue']['value']
-- txtFilename = read(img[1],'value')
if img[1].qualifiers and img[1].qualifiers.P2096 then
-- Loop through all descriptions
for key, value in pairs(img[1].qualifiers.P2096) do
-- Only add if has the same language code as the local wikipedia
language=readQualifier(value,'language')
if (language==txtLanguageCode) then
bDescription=true -- description found!
image.txtDescription=readQualifier(value,'text') -- add description (+ pen to make it easier to edit)
end
end
end
image.width,image.height=getImageSize(image.txtFilename)
image.qid=qid
image.pid=pid
-- add image to the infobox array
-- myArgs[txtImage]='[[File:' .. wdImage .. '|' .. txtWidth_px .. ']]'
return image
end
return
end
function getImageSize(imageName)
local title = mw.title.new(imageName, 'File')
if not title then
return nil, nil, "Invalid image name"
end
local file = title and title.file
if not file then
return nil, nil, "File not found"
end
return file.width, file.height
end
function showImage(tblImage)
myArgs[localisation.txtImage]='[[File:' .. tblImage.txtFilename .. '|' .. settings.iWidth_px .. 'px]]'
if (tblImage.txtDescription) then
myArgs[localisation.txtCaption]=tblImage.txtDescription..txtEditPen(tblImage.qid,tblImage.pid)
else
myArgs[localisation.txtImage]=myArgs[localisation.txtImage]..txtEditPen(tblImage.qid,tblImage.pid)
end
end
-- Custom comparison function
--
function compareUP(a, b)
-- Handle nil values
-- if isempty(a) then
if (a==nil) then
return false
-- elseif isempty(b) then
elseif (b==nil) then
return true
-- return false
end
-- Compare the attributes (assuming a and b are strings or numbers)
return a < b
end
function compareDOWN(a, b)
-- Handle nil values
-- if (isempty(a)) then
if (a==nil) then
return true
-- elseif (isempty(b)) then
elseif (b==nil) then
return false
end
-- Compare the attributes (assuming a and b are strings or numbers)
return a < b
end
function isempty(foo)
return (foo==nil) or (foo=='') or (foo==0)
end
function sortActivityLog(posts)
table.sort(posts, function(a, b) return
(compareDOWN(a.yearfrom,b.yearfrom)) or
(a.yearfrom == b.yearfrom and compareUP(a.yearto,b.yearto)) or
(a.yearfrom == b.yearfrom and a.yearto == b.yearto and compareDOWN(a.datefrom,b.datefrom)) or
(a.yearfrom == b.yearfrom and a.yearto == b.yearto and a.datefrom == b.datefrom and compareUP(a.dateto,b.dateto))
end)
return posts
end
function mergeTables(t1, t2)
local mergedTable = {}
for _,v in ipairs(t2) do
table.insert(mergedTable, v)
end
for _,v in ipairs(t1) do
table.insert(mergedTable, v)
end
return mergedTable
end
function tblAddLocation(frame,myArgs,iCounter,txtLocationLabel,entityid, iProperty)
--Place
entityPlace=mw.wikibase.getBestStatements(entityid, iProperty )
--Only show if set
if next(entityPlace) then
idPlace=read(entityPlace[1],'id')
txtCountry = readFirstStatement(idPlace,'P17')
txtPlace = txtWikilink(idPlace)
if txtCountry then
txtPlace = txtPlace .. ', ' .. '[[' .. txtCountry .. ']]' .. txtUnpackReference(frame,tblProcessAllRefsForItemWD(frame,entityPlace[1].references,entityid,iProperty)) .. txtEditPen(entityid,iProperty)
end
iCounter=iCounter+1
myArgs[txtLabel .. iCounter]=txtLocationLabel
myArgs[txtContent .. iCounter]=txtPlace
end
return myArgs,iCounter
end
function getHomeVenues (qid)
claimHomeVenue=mw.wikibase.getBestStatements(qid, 'P115' )
local venues={}
for key, value in pairs( claimHomeVenue ) do
local venue={}
venue.id=read(value,'id')
venue.txtWikilink=txtWikilink(venue.id)
venue.from,venue.to=readDates(value)
claimCapacity=mw.wikibase.getBestStatements(venue.id,'P1083')
venue.capacity=useStatement(venue.id,'P1083')
venue.bHasRef,venue.ref = processAllRefsForWDItem_model(value.references,qid,value.id)
venue.qid=qid
venue.pid=value.id
table.insert(venues,venue)
end
return venues
end
function showPlace(data)
local txt=''
local bDifferentName=data.name_atthetime and (not (data.name_atthetime==data.name))
local both = bDifferentName and (not (data.country_atthetime==data.country)) -- If both the name of the place and the country was different at the time compared to now
if not (data.id==data.countryid) then -- Only show place if it is not set to a country (that will be shown after anyway)
if (data.sitelink) then -- Add sitelink to place (i.e. use a wikilink)
txt='[[' .. data.sitelink .. '|'
end
if (bDifferentName) then -- If it had another name at the time use it, otherwise use its current name
txt=txt..data.name_atthetime
else
txt=txt..data.name
end
if (data.sitelink) then -- Finish the wikilink for the place
txt=txt..']]'
end
if (not (both) and bDifferentName) then -- Add current name for the place if it is not the same as the past name. Also, do not add it here if the country was different (then it will be added later)
txt=txt .. " (" .. localisation.txtCurrently .. " ''" .. data.name .. "'')"
end
txt=txt .. ', '
end
if (not (data.country_atthetime==data.country)) then -- If the country at the time was not the current country of the place add information
if (data.country_atthetime) then
txt=txt..data.country_atthetime
else
txt=txt .. '[[' .. localisation.txtCategory .. ':' .. localisation.txtLocationLackCountryForGivenDateCategory .. ']]' .. localisation.txtLocationLackCountryForGivenDate .. p.frame:extensionTag("ref", localisation.txtLocationLackCountryForGivenDateRef)
end
if (both) then -- If the place also had a different name include it
txt = txt .. " (" .. localisation.txtCurrently .. " ''" .. data.name .. ", " .. data.country .. "'')"
else
txt = txt .. " (" .. localisation.txtCurrently .. " ''" .. data.country .. "'')"
end
else
txt=txt..data.country
end
return txt
end
function getPlace (value,qid,pid,asofdate)
local place={}
place.id=read(value,'id')
place.sitelink=mw.wikibase.getSitelink(place.id)
place.date=asofdate
local isok,txtNameNow=readStatementAtDate(place.id,'P2561','text')
if (isok) then
place.name=txtNameNow
else
place.name=mw.wikibase.getLabel(place.id)
end
local isok,txtNameAtTheTime=readStatementAtDate(place.id,'P2561','text',asofdate)
if (isok) then
place.name_atthetime=txtNameAtTheTime
end
local isok,iCountryNow=readStatementAtDate(place.id,'P17','id')
if (isok) then
place.countryid=iCountryNow
place.country = txtWikilink(place.countryid)
else
place.country=mw.wikibase.getLabel(place.id)
end
local isok,iCountryAtTheTime=readStatementAtDate(place.id,'P17','id',asofdate)
if (isok) then
place.countryid_atthetime=iCountryAtTheTime
place.country_atthetime=txtWikilink(iCountryAtTheTime)
end
place.from,place.to=readDates(value)
place.bHasRef,place.ref = processAllRefsForWDItem_model(value.references,qid,pid)
place.qid=qid
place.pid=pid
return place
end
function getLocation (qid,pid,bAllowMultiple,asofdate)
local places={}
local claimPlace=mw.wikibase.getBestStatements(qid, pid)
if (bAllowMultiple) then
for key, value in pairs( claimPlace ) do
local place=getPlace(value,qid,pid,asofdate)
table.insert(places,place)
end
return places
else
if (claimPlace[1]) then
return getPlace(claimPlace[1],qid,pid,asofdate)
else
return
end
end
return places
end
-- Function to split a string by a delimiter (by chatgpt)
function split(inputStr, delimiter)
local result = {}
for match in (inputStr .. delimiter):gmatch("(.-)" .. delimiter) do
table.insert(result, match)
end
return result
end
-- Function to merge two tables
function merge(table1, table2)
local result = {}
-- Insert all key-value pairs from table1 into result
for key, value in pairs(table1) do
result[key] = value
end
-- Insert all key-value pairs from table2 into result
for key, value in pairs(table2) do
result[key] = value
end
return result
end
function useOneStatement(claim,qid,txtAlternative,arrayAllowedQualifiers,funcprocessing)
local objOutput={}
objOutput.id=read(claim,'id')
objOutput.from,objOutput.to=readDates(claim)
if ((not txtAlternative) or (txtAlternative=="formatValue")) then
objOutput.data=mw.wikibase.formatValue(claim.mainsnak)
end
if (txtAlternative=="time") then
tmpTable=claim.mainsnak.datavalue.value
objOutput.raw=tmpTable.time
objOutput.precision=tmpTable.precision
if (objOutput.raw) then
objOutput.year=string.sub(objOutput.raw,2,5)
end
objOutput.formatted=mw.wikibase.formatValue(claim.mainsnak)
end
if (txtAlternative=="wikilink") then
objOutput.data=txtWikilink(read(claim,'id'))
end
if arrayAllowedQualifiers then
for i=1,#arrayAllowedQualifiers do
local qfid=arrayAllowedQualifiers[i]
objOutput[qfid]=getQualifierId(claim,qfid)
end
end
if (txtAlternative=="function") then
objOutputProcessed=funcprocessing(objOutput,claim)
objOutput=merge(objOutputProcessed,objOutput)
end
objOutput.bHasRef,objOutput.ref=processAllRefsForWDItem_model(claim.references,qid)
objOutput.qid=qid
objOutput.pid=claim.id
return objOutput
end
function useStatement(qid,pid,txtAlternative,arrayAllowedQualifiers,funcprocessing,onlyallowone)
local claim=mw.wikibase.getBestStatements(qid, pid )
if #claim==0 then
return
end
if onlyallowone or (#claim==1) then
firstClaim=claim[1]
return useOneStatement(firstClaim,qid,txtAlternative,arrayAllowedQualifiers,funcprocessing)
end
if #claim>1 then
statements={}
for key,value in pairs(claim) do
table.insert(statements,useOneStatement(value,qid,txtAlternative,arrayAllowedQualifiers,funcprocessing))
end
return statements
end
end
--Artiklar som använder modul Sportdata och person/klubb deltar i tävling som saknar P3450
function competitionData_model(tbl,claimsIndividualCompetition)
--Get the id of the reoccuring sports event
tbl.iLeague=read(claimsIndividualCompetition[1],'id')
--Get name of the reoccuring sports event
tbl.txtLeague=txtWikilinkWOsitelink(tbl.iLeague)
tbl.txtLeague_plain=getLabelByEntity(tbl.iLeague)
--Get its rank (lower number = more status)
tbl.iCompetitionRank=CompetitionDb[tbl.iLeague]
--If the reoccuring sports event has no stored rank number give it a very high one (= low status)
if (tbl.iCompetitionRank==nil) then
tbl.iCompetitionRank=9999999
end
tbl.iArea=sd.competitionarea(tbl.iLeague)
tbl.iCompetitionClass,tbl.iGender=getGender(tbl.iLeague)
tbl.iSport=readFirstStatementId(tbl.iLeague,'P641' )
return tbl
end
function getGender(iLeague)
--Get competition class (i.e. women's football, men's basketball etc.)
local claimsType = mw.wikibase.getBestStatements(iLeague,'P2094' )
local iGender
if (next(claimsType)) then
iCompetitionClass=read(claimsType[1],'id')
claimsUnderclass = mw.wikibase.getAllStatements(iCompetitionClass,'P279' )
for key, value in pairs( claimsUnderclass ) do
local iObject=read(value,'id')
if (iObject=="Q35555522") then
return iCompetitionClass,1
end
if (iObject=="Q920057") then
return iCompetitionClass,2
end
end
end
return iCompetitionClass,0
end
function getOneCompetiton(qid,valueParticipitation)
local tbl={}
tbl.errors=''
tbl.iSeason=read(valueParticipitation,'id')
iTmpClass=getQualifierId(valueParticipitation,'P2094')
tmpCompetitionClass=rm.tblWikilink(iTmpClass,rm.now(),true)
if not next(tmpCompetitionClass) then
tmpCompetitionClass=rm.tblWikilink(readFirstStatementId(tbl.iSeason,'P2094'),rm.now(),true)
end
if next(tmpCompetitionClass) then
tbl.competitionClassThisEvent=tmpCompetitionClass
end
tbl.iStatus=1 -- Everything ok
--Default values if nothing found
tbl.iCompetitionType="Q0"
tbl.sitelink=mw.wikibase.getSitelink(tbl.iSeason)
-- Assume team if nothing else set
iThisParticipant=qid
txtPropertyForParticipation='P1923'
tbl.qid=qid
tbl.pid='P1344'
tbl.iCoached=getPropertyId(valueParticipitation,'P6087')
if (tbl.iCoached) then
tbl.bCoached=true
iThisParticipant=tbl.iCoached
end
tbl.iPlayed=getPropertyId(valueParticipitation,'P54')
if (tbl.iPlayed) then
tbl.bPlayed=true
iThisParticipant=tbl.iPlayed
end
if (tbl.bPlayed or tbl.bCoached) then
txtPropertyForParticipation='P1923' --teams
tbl.iParticipator=iThisParticipant
iCountry=readFirstStatementId(iThisParticipant,'P17')
if not (iCountry) then
iLocation=readFirstStatementId(iThisParticipant,'P159')
if (iLocation) then
iCountry=readFirstStatementId(iLocation,'P17')
end
end
tblTeam={id=iThisParticipant,country=iCountry}
tbl.team=tblTeam
end
tbl.bIsClub=isClub(iThisParticipant,'P31')
tbl.bIsNationalTeam=isNationalTeam(iThisParticipant,'P31')
iPartner=getQualifierId(valueParticipitation,'P1706')
bIndividual=not (tbl.bIsClub or tbl.bIsNationalTeam)
if (bIndividual) then
bIndividual=true
txtPropertyForParticipation='P710' --individuals
iThisParticipant=qid
end
--Check wether the object is an instance of a reoccuring sports event, a qualification event or not at all sports related
local claimsMainorQualifier = mw.wikibase.getBestStatements(tbl.iSeason, 'P31' )
tbl.bMainOrQualifier='-' -- Defaults to not being a competition-- Defaults to not being a competition (as P1344, that is usually used to call the function can cover a lot of things, not just sports events)
bFoundQualification=false -- Check if found qualification (will take priority of instance of both Q27020041 and Q2122052/Q51036091 )
--Loop through instances statements
for keyQualifier, valueQualifier in pairs( claimsMainorQualifier ) do
iInstanceOf=read(valueQualifier,'id')
--If a main competition
if (not(bFoundQualification) and ((iInstanceOf=='Q27020041') or (iInstanceOf=='Q114609228') or (iInstanceOf=='Q18536594') or (iInstanceOf=='Q51031626') or (iInstanceOf=='Q26132862'))) then
tbl.bMainOrQualifier='M' -- Main competition
end
--If a qualifier
if ((iInstanceOf=='Q2122052') or (iInstanceOf=='Q51036091')) then
--Set as qualifier in table
tbl.bMainOrQualifier='Q'
-- --Get references
-- tbl.bHasref,tbl.ref=processAllRefsForWDItem_model(valueQualifier['references'],entityid,'P1344')
--Look for statement for what it qualifies for and set that as the main competiton
claimsMainCompetition=mw.wikibase.getAllStatements(tbl.iSeason, 'P3085' )
iMainCompetition=read(claimsMainCompetition[1],'id')
-- If there is data on what it qualifies for set that as the sports event (so for example a qualification for a world championship will be shown in the same way as the world championship itself (but with qualitifcation rather than position as result)
if not isempty(iMainCompetition) then
tbl.iSeason=iMainCompetition
end
-- Set that a relevant reoccuring sports event has been found and stop looking for one
bFoundQualification=true
end
tbl.instanceof=read(claimsMainorQualifier[1],'id')
end
--Get the claim for the reoccuring sports event
local claimsCompetition = mw.wikibase.getBestStatements(tbl.iSeason, 'P3450' )
if (claimsCompetition[1]) then -- Has a link to leauge (from the individual season)
if (not (tbl.bMainOrQualifier=='Q')) then -- If not a qualification tournament then a main tournament
tbl.bMainOrQualifier='M'
end
--Fill tbl with data about the reoccuring sports event (rather than the individual season)
tbl=competitionData_model(tbl,claimsCompetition)
else
--If no claim found try for a season that it might be part of instead (for example if there is a joint entity for all competitions independent of gender)
bFoundCompetition=false --Start with setting that nothing has been found
local claimsCompetition2
local claimsCompetitionSeasonPartOf = mw.wikibase.getBestStatements(tbl.iSeason, 'P361' )
--If part of another reoccuring sports event
if (claimsCompetitionSeasonPartOf[1]) then
iCompetitionSeasonPartOf=read(claimsCompetitionSeasonPartOf[1],'id')
claimsCompetition2 = mw.wikibase.getBestStatements(iCompetitionSeasonPartOf, 'P3450' )
bFoundCompetition=true
end
if (bFoundCompetition and claimsCompetition2[1]) then -- Part of a reoccuring sports event (from the individual season)
tbl=competitionData_model(tbl,claimsCompetition2)
else
--If neither instance of Q27020041 nor has a statement for P3450 -> assume not a sports competiton at all
tbl.iCompetitionRank=9999999
--If bMainOrQualifier still is its default value ('-'), it is not considered a sports results (might be a person participating in anything)
if (tbl.bMainOrQualifier=='-') then
tbl.iStatus=99 -- Return with a status that makes sure it is not considered a sports result
tbl.txtLeague=''
tbl.edit=''
tbl.bHasRef=false
return tbl
else
-- Sportsevent, but not part of a reoccuring sports event -> fill with information about the error (assuming all sports events are reoccuring and not one-off events at the moment)
-- txtRefTmp=txtClickToAddCompetitionType .. ' [https://www.wikidata.org/wiki/' .. tbl.iSeason .. ' ' .. txtHere .. '].' .. txtaddWikiData(txtProperty3450,'tävlingstyp',txtExplanationProperty3450)
-- tbl.txtLeague=txtCompetitionTypeNotSet.. frame:extensionTag("ref", txtRefTmp) .. '[[' .. txtCategory .. ':' .. txtErrorCompetitionWithoutP3450 .. ']]'
-- tbl.iCompetitionType="Q1"
-- tbl.iStatus=2
end
end
end
bFounddates,tbl.txtDateFrom,tbl.txtDateTo=processDates_model(tbl.iSeason)
if not bFounddates then
--If no start year check for era
p2348=mw.wikibase.getAllStatements(tbl.iSeason, 'P2348' ) -- Om tidsperiod
if (next(p2348)) then
bFounddates,tbl.txtDateFrom,tbl.txtDateTo=processDates_model(read(p2348[1],'id') )
end
end
if not bFounddates then
p585=mw.wikibase.getAllStatements(tbl.iSeason,'P585' ) -- Om tidsperiod
if (next(p585)) then
tbl.txtDateFrom=read(p585[1],'time')
tbl.txtDateTo=tbl.txtDateFrom
else
-- If neither startyear nor era, do not try do display more detailed information, just display information about the season of the league
if not tbl.iStatus==2 then
-- If part of reoccuring sportsevent, but lack start/end info
tbl.iStatus=3
else
-- If not part of reoccuring sportsevent set error message
tbl.errors=tbl.errors .. txtDateMissing .. '[[' .. txtCategory .. ':' .. txtGeneralError .. ']]'
end
end
end
--Get name of the reoccuring sports event
tbl.competitiontype=rm.tblWikilink(tbl.iLeague,tbl.txtDateTo,true)
local iPositionDirect=getQualifier(valueParticipitation,'P1352')
if iPositionDirect then
tbl.iPosition=iPositionDirect
end
if (iPartner==nil) then
iPartner=getQualifierId(valueParticipitation,'P1706')
if (iPartner==nil) then
iPartner=getQualifierId(valueParticipitation,'P1327')
end
end
--If a main competition the position was not set directly in the statement using P1352
if ((tbl.bMainOrQualifier=='M') and iPositionDirect==nil or (bIndividual and iPartner==nil)) then
-- events
claimParticipants=mw.wikibase.getAllStatements(tbl.iSeason,txtPropertyForParticipation)
-- tbl.txtPropertyForParticipation=txtPropertyForParticipation
txtPos=''
tbl.bHasRef=0
--Loop through participants of the event until find the particpant for which this function was called
for keyParticipant, valueParticipant in pairs(claimParticipants ) do
--Read participant id
iParticipantLoop=read(valueParticipant,'id')
--Check if it is the same one as for which the function was called
if (iParticipantLoop==iThisParticipant) then
txtPos=getQualifier(valueParticipant,'P1352')
if (valueParticipant.qualifiers) then
-- --If individual look for any people that they played with (for example when people play in pairs)
if (bIndividual and valueParticipant.qualifiers.P1327) then
iPartner=readQualifier(valueParticipant.qualifiers.P1327[1],'id')
else
if (bIndividual and valueParticipant.qualifiers.P1706) then
iPartner=readQualifier(valueParticipant.qualifiers.P1706[1],'id')
end
end
end
tbl.bHasRef,tbl.ref=processAllRefsForWDItem_model(valueParticipant['references'],tbl.iSeason,txtPropertyForParticipation)
tbl.qid=tbl.iSeason
tbl.pid=txtPropertyForParticipation
break
end
end
if not (tbl.iPosition) then -- If not already set directly
tbl.iPosition=txtPos
end
-- tmphasref,tmpref=tblProcessAllRefsForItemWD(frame,valueParticipitation['references'],entityid,'P1344')
tmphasref=0
tmpref={}
if ((tbl.bHasRef==1) and (tmphasref==1)) then
tbl.ref=mergeTables(tbl.ref,tmpref)
end
if ((tbl.bHasRef==1) and (tmphasref==0)) then
--do nothing
end
if ((tbl.bHasRef==0) and (tmphasref==1)) then
tbl.bHasRef=1
tbl.ref=tmpref
end
if ((tbl.bHasRef==0) and (tmphasref==0)) then
tbl.bHasRef=0
tbl.ref=tmpref
end
else
tbl.bHasRef,tbl.ref=processAllRefsForWDItem_model(valueParticipitation['references'],qid,'P1344')
end
-- If qualifier
if (tbl.bMainOrQualifier=='Q') then
tbl.iPosition=999998
end
if (iPartner) then
local iCountry=readFirstStatementId(iPartner,'P1532')
if not iCountry then
iCountry=readFirstStatementId(iPartner,'P27')
end
if (arrayFlagCountries[iCountry]) then
iCountry=arrayFlagCountries[iCountry]
end
tblTeam={id=iPartner,country=iCountry}
tbl.team=tblTeam
end
if (bIndividual and iPartner) then
tbl.txtTeam=txtTogetherWith .. txtWikilink(iPartner,'id')
end
tbl.iCompetitor=qid
if (not tbl.iPosition) or (tbl.iPosition=='') then
tbl.iPosition='999999'
end
tbl.iPosition=tonumber(tbl.iPosition)
return tbl
end
function getResults (qid)
local allresults={}
local claimsCompetition = mw.wikibase.getBestStatements(qid, 'P1344' )
for key, value in pairs( claimsCompetition ) do
resultonecompetition=getOneCompetiton(qid,value)
table.insert(allresults,resultonecompetition)
end
return allresults
end
p.showdata = function(frame)
p.frame=frame
p=p.data()
return tprint(p)
end
p.showpartininfobox=function(txtThisLabel,propertyname,bCheckChildren,runfunc)
local obj=p[propertyname]
if (obj) then
if(obj[1]) then --Safety check to check if obj is an array rather than a structure (since Lua for some reason lacks any built-in functionality to test the difference test for 1 is a quick fix)
obj=nil
end
end
if (obj) then
local txt=obj.data
if (obj.unit) then
txt=txt .. ' ' .. obj.unit
end
p.iCounter=p.iCounter+1
myArgs[localisation.txtLabel .. p.iCounter]=txtThisLabel
myArgs[localisation.txtContent .. p.iCounter]=txt .. txtUnpackReference_model(p.frame,obj.ref,obj.qid,obj.pid)
if (runfunc) then
myArgs[localisation.txtContent .. p.iCounter]=myArgs[txtContent .. p.iCounter] .. runfunc()
end
end
if (bCheckChildren) then
for key,value in pairs(p.objectIds) do
obj=p[value][propertyname]
if (obj) then
local txt=obj.data
if (obj.unit) then
txt=txt .. ' ' .. obj.unit
end
p.iCounter=p.iCounter+1
myArgs[localisation.txtLabel .. p.iCounter]=' – ' .. p[value]['label']
myArgs[localisation.txtContent .. p.iCounter]=txt .. txtUnpackReference_model(p.frame,obj.ref,obj.qid,obj.pid)
if (runfunc) then
myArgs[txtContent .. p.iCounter]=myArgs[localisation.txtContent .. p.iCounter] .. runfunc()
end
end
end
end
end
--[=====[
--]=====]
-- Function: Loopitems
-- Purpose: To fill an infobox row with values based on the content of ,general property, that will contain an array that is looped through
-- Arguments:
-- label - Label for the infobox row
-- generalproperty - Property to read the data from.
-- specificproperties - Subproperties that are used to fill the content of the infobox row.
-- separator - Separator between the different items of the list (except the last one)
-- lastseparator - Separator between the second last and the last item of the list
p.processoneiteminlist=function(item,func,specificproperties,separator,bHideReferences)
local ret
if (item.from or item.to) then
txtYears=' (' .. datetotext (item.from,item.to) .. ')'
else
txtYears=''
end
if func then
ret = func(item)
else
if not (specificproperties==nil) then
local txtCurrent=item[specificproperties[1]]
for j=2,#specificproperties do
if (item[specificproperties[j]]) then
if not txtCurrent then
txtCurrent=''
end
txtCurrent=txtCurrent .. separator .. item[specificproperties[j]]
end
end
ret = txtCurrent
else
ret= item
end
end
if (bHideReferences) then
return ret .. txtYears
else
return ret .. txtYears .. txtUnpackReference_model(p.frame,item.ref,item.qid,item.pid)
end
end
p.loopitems=function(label,generalproperty,func,specificproperties,separator,lastseparator,bHideReferences)
local listDataitems=p[generalproperty]
local iItems=1
if listDataitems and next(listDataitems) then
iItems=#listDataitems
local txt
if (iItems>0) then
txt=''
for i=1,iItems do
if(i>1) then
if (i==iItems) then
txt=txt..lastseparator
else
txt=txt..separator
end
end
local txtCurrent=p.processoneiteminlist(listDataitems[i],func,specificproperties,", ",bHideReferences)
if (i==1) then
txt=txt..firstToUpper(txtCurrent)
else
txt=txt..txtCurrent
end
end
else
txt=p.processoneiteminlist(listDataitems,func,specificproperties,", ",bHideReferences)
end
p.iCounter=p.iCounter+1
if type(label) == "string" then
myArgs[localisation.txtLabel .. p.iCounter]=label
else
if (iItems>1) then
myArgs[localisation.txtLabel .. p.iCounter]=label[2]
else
myArgs[localisation.txtLabel .. p.iCounter]=label[1]
end
end
myArgs[localisation.txtContent .. p.iCounter]=txt
end
end
p.addHeader=function(label,style,descriptionlabel)
p.iCounter=p.iCounter+1
myArgs[localisation.txtHeader .. p.iCounter]=label
if style then
myArgs[localisation.txtHeader .. p.iCounter .. localisation.txtStyle]=style
end
if descriptionlabel then
p.iCounter=p.iCounter+1
myArgs[localisation.txtContent .. p.iCounter]='\'\''..descriptionlabel..'\'\''
end
end
p.addContent=function(label,content)
p.iCounter=p.iCounter+1
myArgs[localisation.txtLabel .. p.iCounter]=label
myArgs[localisation.txtContent .. p.iCounter]=content
end
standarddatesearch=function (a,b)
if (not (a)) and (not (b)) then return false end
if not (a) then return true end
if not (b) then return false end
a.isempty=(not a.from) and (not a.to)
b.isempty=(not b.from) and (not b.to)
if (a.isempty and b.isempty) then return false end
if (a.isempty) then return true end
if (b.isempty) then return false end
if (a.to) then
a.last=a.to.raw
if (a.from) then
a.first=a.from.raw
else
a.first=a.last
end
else
a.last=a.from.raw
a.first=a.last
end
if (b.to) then
b.last=b.to.raw
if (b.from) then
b.first=b.from.raw
else
b.first=b.last
end
else
b.last=b.from.raw
b.first=b.last
end
if (a.last==b.last) then
if (a.first==b.first) then
return false
else
return a.first < b.first
end
end
return a.last < b.last
end
p.showtemporalpartininfobox=function(txtMainHeaderLabel,txtMainHeaderDescriptionLabel,txtSubHeaderLabel,obj,objfunction,bCheckChildren,tblExtraColumns)
if (#obj>0) then
table.sort(obj, standarddatesearch) -- Sort based on date
p.addHeader(txtMainHeaderLabel,nil,txtMainHeaderDescriptionLabel) -- Add header
p.iCounter=p.iCounter+1 -- Start table that will show the data
local txt='<table style="class: biography vcard" width="100%"><tr><th width="70px">' .. localisation.txtSeasonHeader .. '</th><th>' ..txtSubHeaderLabel .. '</th>'
-- If extra columns create headers for them
if tblExtraColumns then
for j=1,#tblExtraColumns do
txt=txt..'<th style="width:' .. tblExtraColumns[j].width .. '">' .. tblExtraColumns[j].title .. '</td>'
end
end
txt=txt..'</tr>'
for i=1,#obj do
txtRow='<tr><td style="text-align:left">' .. datetotext (obj[i].from,obj[i].to) .. '</td>'
local txtData
if (objfunction==nil) then
txtData= obj[i].data
else
txtData= objfunction(p.frame,obj[i])
end
txtRow=txtRow..'<td style="text-align:left">' .. txtData .. txtUnpackReference_model(p.frame,obj[i].ref,obj[i].qid,obj[i].pid) .. '</td>'
if (tblExtraColumns) then
for j=1,#tblExtraColumns do
txtRow=txtRow..'<td>'.. tblExtraColumns[j].func(obj[i]) ..'</td>'
end
end
txt=txt..txtRow .. '</tr>'
end
myArgs[txtContent .. p.iCounter]=txt .. '</table>'
end
end
p.showovertime=function(txtTitleHeaderLabel,obj,objfunction,bCheckChildren,tblExtraColumns)
if (#obj>0) then
table.sort(obj, standarddatesearch) -- Sort based on date
p.iCounter=p.iCounter+1 -- Start table that will show the data
local txt='<table style="class: biography vcard" width="100%"><tr><th width="70px">' .. localisation.txtSeasonHeader .. '</th><th>' ..txtTitleHeaderLabel .. '</th>'
-- If extra columns create headers for them
if tblExtraColumns then
for j=1,#tblExtraColumns do
txt=txt..'<th style="width:' .. tblExtraColumns[j].width .. '">' .. tblExtraColumns[j].title .. '</td>'
end
end
txt=txt..'</tr>'
for i=1,#obj do
txtRow='<tr><td style="text-align:left">' .. datetotext (obj[i].from,obj[i].to) .. '</td>'
local txtData
if (objfunction==nil) then
txtData= obj[i].data
else
txtData= objfunction(p.frame,obj[i])
end
txtRow=txtRow..'<td style="text-align:left">' .. txtData .. txtUnpackReference_model(p.frame,obj[i].ref,obj[i].qid,obj[i].pid) .. '</td>'
if (tblExtraColumns) then
for j=1,#tblExtraColumns do
txtRow=txtRow..'<td>'.. tblExtraColumns[j].func(obj[i]) ..'</td>'
end
end
txt=txt..txtRow .. '</tr>'
end
myArgs[txtContent .. p.iCounter]=txt .. '</table>'
end
end
--[=====[
General format for the Sportdata (LUA) tables:
p.frame Current frame
p.objectMainId Qid for the article (in the usual case, sometimes it can be useful to use another id, for example for testing purposes or if another wikidata object might be a better fit)
p.qids Qids for other wikidata objects that should be counted together with the objectMainId. It might for example be a predecessor, whose data will be included in the resulting infobox.
p[qids] The sports data functions will fill a property with the same name as the qid with information for that qid. Usually it will be filled in the same way as the objectMainId fill information directly under p. Though some properties might be objectMainId-only (for example label).
--]=====]
-- Function: Filter advanced
-- Purpose: To filter a table based on multiple properties (rather than one, which is the case for the 'filter'-function. For every property it only takes one selected value [that it matches with])
-- Arguments:
-- tblIn - A (LUA) table containing structured information that will be used by any of the sports data modules.
-- txtProperty - Property that will be filtered (will typically have a quite generic name and contain an array of data [that is the information that will be filtered])
-- arrayVariable - Array of variables that the filter is based upon
-- arraySelectedvalue - Value to base the filter upon (items for which the value of txtVariable is selectedvalue will be chosen, i.e. the array has the same length as arrayVariable, with one match for each variable)
p.filter_advanced=function(tblIn,txtProperty,arrayVariables,arraySelectedvalue)
local tblProperty=tblIn[txtProperty] -- Get chosen property
local iItems=#tblProperty -- Count number of items
local tblOut={} -- Empty table that will be filled by the results of the filter query
local iQueryVariables=#arrayVariables
tblOut.variables=iQueryVariables
for i=1,iItems do -- Loop through all items
local match=true
for j=1,iQueryVariables do
local databasevalue=tblProperty[i][arrayVariables[j]]
if (type(databasevalue)=="table") then
match=false
for k=1,#databasevalue do
if (databasevalue[k]==arraySelectedvalue[j]) then match=true end -- If the data value for the chosen variable of this item is the same as the selected value (for the filter) ...
end
-- tblProperty[i].data=#databasevalue .. tprint(databasevalue) .. arraySelectedvalue[j] .. tostring(match)
-- match=true
else
if not (databasevalue==arraySelectedvalue[j]) then match=false end -- If the data value for the chosen variable of this item is the same as the selected value (for the filter) ...
end
end
if (match) then
table.insert(tblOut,tblProperty[i]) -- into the out table
end
end
if (tblIn.objectIds) then -- If any child objects
for key,value in pairs(tblIn.objectIds) do -- Loop through them
local obj=p[value] -- Set obj to the current child object (in the loop)
filteredobj=p.filter_advanced(obj,txtProperty,arrayVariables,arraySelectedvalue) -- Call the filter function (recursivelly) based on the child object
iItemsSub=#filteredobj -- Read the (LUA) tables returned by the filter
for j=1,iItemsSub do -- Loop through the returned table items
table.insert(tblOut,filteredobj[j]) -- Add them to the out table
end
end
end
return tblOut -- Return the out table
end
-- Function: Filter
-- Purpose: To filter a table based on property, variable and selected value to return a table of the same format as the one supplied
-- Arguments:
-- tblIn - A (LUA) table containing structured information that will be used by any of the sports data modules.
-- txtProperty - Property that will be filtered (will typically have a quite generic name and contain an array of data [that is the information that will be filtered])
-- arrayVariable - Array of variables that the filter is based upon
-- arraySelectedvalue - Value to base the filter upon (items for which the value of txtVariable is selectedvalue will be chosen, i.e. the array has the same length as arrayVariable, with one match for each variable)
p.filter=function(tblIn,txtProperty,txtVariable,selectedvalue)
local tblProperty=tblIn[txtProperty] -- Get chosen property
local iItems=#tblProperty -- Count number of items
local tblOut={} -- Empty table that will be filled by the results of the filter query
for i=1,iItems do -- Loop through all items
if (tblProperty[i][txtVariable]==selectedvalue) then -- If the data value for the chosen variable of this item is the same as the selected value (for the filter) ...
table.insert(tblOut,tblProperty[i]) -- into the out table
end
end
if (tblIn.objectIds) then -- If any child objects
for key,value in pairs(tblIn.objectIds) do -- Loop through them
local obj=p[value] -- Set obj to the current child object (in the loop)
filteredobj=p.filter(obj,txtProperty,txtVariable,selectedvalue) -- Call the filter function (recursivelly) based on the child object
iItemsSub=#filteredobj -- Read the (LUA) tables returned by the filter
for j=1,iItemsSub do -- Loop through the returned table items
table.insert(tblOut,filteredobj[j]) -- Add them to the out table
end
end
end
return tblOut -- Return the out table
end
-- The function produce a summary of top 3 positions for the person/club, followed by a more detailed description of their competition results
p.resulttable = function(tblAllQueryResults,headerstyle)
-- Create empty tables to be filled
local tblCompetitionTypes={} -- Will host all types of competition (World Championshipcs, Olympic Games, continental cup etc.) that the person/club has participated in
local tblAllPositions={} -- All positions (organised by competition type and position). It is a table of tables as every post in the table will be a table with the results of the person/club in that competition
local tblPodium={} -- All podium positions (organised by competition type)
local maxpositions={} -- "highest" position (as in the numerical value such as 32, not the best position)
table.sort(tblAllQueryResults, function(a, b) return a.txtDateFrom < b.txtDateFrom end) -- Sort in calendar order (so that, when relevant, the results are presented in the right order)
local iCompetitionTypes=0 -- Count of number of competition types
local bPodiumHasContent=false -- Check if the person/club has any podium positions at all (if none, the function will not return a podium table)
local bAllResultsHasContent=false -- Check if the person/club has any results at all
for i=1,#tblAllQueryResults do -- Loop through all results
if tblAllQueryResults[i].iPosition == nil or tblAllQueryResults[i].txtYears then -- temporary fix to avoid skript errors by skipping competitions where there is no valid value for iPosition or txtYears
mw.log('ERROR: iPosition or txtYears is missing')
mw.logObject(tblAllQueryResults[i])
else
-- Read league/competition type
local iCompetitionType=tblAllQueryResults[i].iLeague
-- If no result has been processed for that competition type
if not (tblAllPositions[iCompetitionType]) then
-- Create with relevant information about the competition type
local tblCompetitionType={id=iCompetitionType,title=tblAllQueryResults[i].txtLeague,icon='',rank=tblAllQueryResults[i].iCompetitionRank}
-- For coaching result write out the gender (not done for player results as those will usually all be for the same gender)
if (tblAllQueryResults[i].bCoached) then
tblCompetitionType.title=tblCompetitionType.title
tblCompetitionType.icon=txtGenderIcon(tblAllQueryResults[i].iGender)
-- tblCompetitionType.title_plain=tblCompetitionType.title_plain
end
table.insert(tblCompetitionTypes,tblCompetitionType) -- Add the post of the competition type to the table over competition types
tblAllPositions[iCompetitionType]={} -- Create an empty position table for the competition
tblPodium[iCompetitionType]={0,0,0} -- Create an empty podium
iCompetitionTypes=iCompetitionTypes+1 -- Increase the number of competition types
maxpositions[iCompetitionType]=0 -- Start highest position with zero (as no competitions added yet)
end
iPosition=tblAllQueryResults[i].iPosition -- Read position
if (iPosition<4) then -- If top three position - add to podium
tblPodium[iCompetitionType][iPosition]=tblPodium[iCompetitionType][iPosition]+1 -- Add to podium
bPodiumHasContent=true -- Has a podium position is now true
end
--Adding result to the tblCompetitionTypes table
local tblCompetition=tblAllPositions[iCompetitionType] -- Pick out the individual competition type (in order to add the result to it)
if not (tblCompetition[iPosition]) then -- If it doesn't already have any results where the club/person has ended up at position iPosition then..
tblCompetition[iPosition]={text='',pos=iPosition} -- Create an empty table post
if (iPosition>maxpositions[iCompetitionType]) then -- If position is higher than current max positions..
maxpositions[iCompetitionType]=iPosition -- .. set it as new max position
end
end
if not (tblCompetition[iPosition].text=='') then -- If it the position text (containing the times the club/person has ended up at that position) is not empty
tblCompetition[iPosition].text=tblCompetition[iPosition].text..', ' -- Add an ", " before adding anything else (i.e. between all elements, not before the first element)
end
-- If there is a linked wikipedia page, try to extract the years from its title based on regular expression (that way they years shown will match the title, rather than be based on the actual dates of the competition). This is prefereable for example for the 2020 Olympics (as they took place in 2021, due to the Covid 19 pandemic).
if(tblAllQueryResults[i].sitelink) then
-- Find all four-digit sequences
local iterator = string.gmatch(tblAllQueryResults[i].sitelink, "%d%d%d%d")
local iYear1 = iterator() -- First match
local iYear2 = iterator() -- Second match
local txtEventtitle
if (iYear1) then
txtEventtitle=iYear1
if (iYear2) then
txtEventtitle=txtEventtitle .. '/' .. iYear2
end
else
iYear1=string.sub(tblAllQueryResults[i].txtDateFrom,2,5)
iYear2=string.sub(tblAllQueryResults[i].txtDateTo,2,5)
if (iYear1==iYear2) then
txtEventtitle=iYear1
else
txtEventtitle=iYear1 .. '/' .. iYear2
end
end
tblCompetition[iPosition].text=tblCompetition[iPosition].text.. '[[' .. tblAllQueryResults[i].sitelink .. '|' .. txtEventtitle .. ']]' .. txtUnpackReference_model(p.frame,tblAllQueryResults[i].ref,tblAllQueryResults[i].qid,tblAllQueryResults[i].pid)
tblAllQueryResults[i].txtYears='[[' .. tblAllQueryResults[i].sitelink .. '|' .. txtEventtitle .. ']]'
else
iYear1=string.sub(tblAllQueryResults[i].txtDateFrom,2,5)
iYear2=string.sub(tblAllQueryResults[i].txtDateTo,2,5)
if (iYear1==iYear2) then
txtEventtitle=iYear1
else
txtEventtitle=iYear1 .. '/' .. iYear2
end
tblCompetition[iPosition].text=tblCompetition[iPosition].text.. txtEventtitle .. txtUnpackReference_model(p.frame,tblAllQueryResults[i].ref,tblAllQueryResults[i].qid,tblAllQueryResults[i].pid)
tblAllQueryResults[i].txtYears=txtEventtitle
end
tblAllPositions[iCompetitionType]=tblCompetition
bAllResultsHasContent=true
end -- temporary fix to avoid skript errors by skipping competitions where there is no valid value for iPosition or txtYears
end
table.sort(tblCompetitionTypes, function(a, b) return a.rank < b.rank end) -- Sort competitions based on their rank (as entered in module 'sportdata rankings') so that for exampel world championships are shown above national championships
if not (bAllResultsHasContent) then -- Only show header if there are any results
p.addContent("''" .. localisation.txtNoResult .. "''" .. "[[" .. localisation.txtCategory .. ":" .. localisation.txtNoResultsAtAll .. "]]" )
return -- If no content there is no need to do anything else
end
local txtPodium
if (bPodiumHasContent) then -- Only show podium if there are any podium positions
txtPodium='<table style="width:100%"><tr><td style="text-align:left">Tävling</td><td style="background:gold;width:50px">'..txtGoldHeader..'</td><td style="background:silver;width:50px">' .. txtSilverHeader .. '</td><td style="background:#CC9966;width:50px">'..txtBronzeHeader .. '</td>'
for i=1,iCompetitionTypes do
iTotalMedals=tblPodium[tblCompetitionTypes[i].id][1]+tblPodium[tblCompetitionTypes[i].id][2]+tblPodium[tblCompetitionTypes[i].id][3]
if (iTotalMedals>0) then -- Only show competition in medal list if the person/team has won a medal
txtRow='<tr><td style="text-align:left">'..tblCompetitionTypes[i].title..tblCompetitionTypes[i].icon..'</td>'
for j=1,3 do
local iPos=tblPodium[tblCompetitionTypes[i].id][j]
if (iPos==0) then
iPos='-'
end
txtRow=txtRow..'<td>'..iPos..'</td>'
end
txtPodium=txtPodium..txtRow..'</tr>'
end
end
txtPodium=txtPodium..'</table>'
else
txtPodium=''
end
local txtAll2
if (bPodiumHasContent) then -- Show all results in collapsed view if had podium positions, otherwised open
txtAll2='<table class="mw-collapsible mw-collapsed biography vcard" style="width:100%;margin: 2px 0;border: 1px solid #000;"><tr><th colspan="3" style="background:#ececec">'..localisation.txtCompleteResultsList..'</th></tr><tr><td style="width:50px;">'..localisation.txtPositionHeader..'</td><td>'..localisation.txtCompetitionHeader..'</td><td>'..localisation.txtSeasonHeader..'</td></tr>'
else
txtAll2='<table class="mw-collapsible biography vcard" style="width:100%;margin: 2px 0;border: 1px solid #000;"><tr><th colspan="3" style="background:#ececec">'..localisation.txtCompleteResultsList..'</th></tr><tr><td style="width:50px;">'..localisation.txtPositionHeader..'</td><td>'..localisation.txtCompetitionHeader..'</td><td>'..localisation.txtSeasonHeader..'</td></tr>'
end
table.sort(tblAllQueryResults, function(a, b)
return a.txtDateTo < b.txtDateTo
end)
iOldTeam=0;
for i=1,#tblAllQueryResults do
if tblAllQueryResults[i].iPosition == nil or tblAllQueryResults[i].txtYears == nil then -- temporary fix to avoid skript errors by skipping competitions where there is no valid value for iPosition or txtYears
mw.log('ERROR: iPosition or txtYears is missing')
mw.logObject(tblAllQueryResults[i])
else
if (tblAllQueryResults[i].team) then
if not (tblAllQueryResults[i].team.id==iOldTeam) then
local txtTeamname
if (tblAllQueryResults[i].bIsClub) then
local tblTeamname,bIsOk=rm.tblWikilink(tblAllQueryResults[i].team.id)
if (tblAllQueryResults[i].team and tblAllQueryResults[i].team.country) then
if (bIsOk) then
txtTeamname= p.frame:expandTemplate{ title = localisation.txtFlagIconTemplate , args={getLabelByEntity(tblAllQueryResults[i].team.country)}} .. ' ' .. tblTeamname.txtLabel
end
else
txtTeamname= tblTeamname.txtLabel
end
end
if (tblAllQueryResults[i].bIsNationalTeam) then
local tblTeaminfo=tblNationalTeamInfo(tblAllQueryResults[i].team.id)
local tbl={country=tblTeaminfo}
txtTeamname=showcountry(p.frame,tbl)
end
if (tblAllQueryResults[i].bCoached) then -- Only show ,gender when coaching
txtTeamname=txtTeamname .. txtGenderIcon(tblAllQueryResults[i].iGender)
end
if (not (tblAllQueryResults[i].bIsClub or tblAllQueryResults[i].bIsNationalTeam)) then
local iCountry=tblAllQueryResults[i].team.country
local txtFlag
if iCountry then
txtFlag=p.frame:expandTemplate{ title = localisation.txtTemplate .. ':' .. localisation.txtFlagIconTemplate , args={getLabelByEntity(iCountry)}}
else
txtFlag=''
end
local tblTeamname,bIsOk=rm.tblWikilink(tblAllQueryResults[i].team.id)
txtTeamname=txtTogetherWith .. txtFlag .. ' ' .. tblTeamname.txtLabel
end
txtAll2 = txtAll2.. '<tr style="background:#f0ecb0;border:1"><td colspan="3">' .. txtTeamname .. '</td></tr>'
iOldTeam=tblAllQueryResults[i].team.id
end
end
local txtPos=txtPosition(tblAllQueryResults[i].iPosition)
local txtLeague
if (tblAllQueryResults[i].competitiontype) then
txtLeague=txtShowLink(tblAllQueryResults[i].competitiontype)
if not (tblAllQueryResults[i].competitiontype.txtLabel==tblAllQueryResults[i].competitiontype.txtLabel_current) then
localrefitem={}
localrefitem['error']=false
localrefitem[localisation.txtTitle]=localisation.txtCurrently .. ' ' .. tblAllQueryResults[i].competitiontype.txtLabel_current
local reftbl={localrefitem}
txtLeague=txtLeague .. txtUnpackReference_model(p.frame,reftbl)
end
else
txtLeague=''
end
if (settings.tblSportWithManyDisciplines[tblAllQueryResults[i].iSport] and tblAllQueryResults[i].competitionClassThisEvent) then
txtLeague=txtLeague .. ' (' .. txtShowLink(tblAllQueryResults[i].competitionClassThisEvent) .. ')'
end
txtLeague = txtLeague.. txtUnpackReference_model(p.frame,tblAllQueryResults[i].ref,tblAllQueryResults[i].qid,tblAllQueryResults[i].pid)
local txtYears=tblAllQueryResults[i].txtYears
txtAll2 = txtAll2.. '<tr>'.. txtPos .. '<td style="text-align:left">' .. txtLeague .. '</td><td>' .. txtYears ..'</td></tr>'
end -- temporary fix to avoid script errors when there is no valid value for txtYears
end
txtAll2=txtAll2 .. '</table>'
p.iCounter=p.iCounter+1
myArgs[localisation.txtContent .. p.iCounter]=txtPodium .. txtAll2
end
function datetotext (from,to)
local txt =''
if not isempty(from) then
txt=from.year
end
if not (isempty(from) and isempty(to)) then
txt=txt..'–'
end
if not isempty(to) then
txt=txt..to.year
end
if from and to and (from.year==to.year) then
txt=from.year
end
return txt
end
-- Loop through a table and return unique elements
function listalluniques(tblItems,txtProperty)
local uniqueSet={}
local uniqueSubset={}
for i=1,#tblItems do
value=tblItems[i][txtProperty]
if value then
if not uniqueSet[value] then
uniqueSet[value] = true
table.insert(uniqueSubset, value)
end
end
end
return uniqueSubset
end
function txtGenderIcon(iGender)
if (iGender==1) then -- Is it men's sport?
return '[[' .. localisation.txtImage .. ':Male symbol (heavy blue).svg]]'
end
if (iGender==2) then -- Is it women's sport?
return '[[' .. localisation.txtImage .. ':Venus symbol (heavy pink).svg]]'
end
return '' -- Return empty string if neither is set
end
--Kopia av p.filter, men utan filtrerandet
p.all=function(tblIn,txtProperty)
local tblProperty=tblIn[txtProperty] -- Get chosen property
local iItems=#tblProperty -- Count number of items
local tblOut={} -- Empty table that will be filled by the results of the filter query
for i=1,iItems do -- Loop through all items
table.insert(tblOut,tblProperty[i]) -- into the out table
end
if (tblIn.objectIds) then -- If any child objects
for key,value in pairs(tblIn.objectIds) do -- Loop through them
local obj=p[value] -- Set obj to the current child object (in the loop)
daughterobj=p.all(obj,txtProperty) -- Call the function (recursivelly) based on the child object
iItemsSub=#daughterobj -- Read the (LUA) tables returned by the filter
for j=1,iItemsSub do -- Loop through the returned table items
table.insert(tblOut,daughterobj[j]) -- Add them to the out table
end
end
end
return tblOut -- Return the out table
end
p.tblInfobox_canvas=function()
local myArgs={}
myArgs[localisation.txtTitle]=p.label
myArgs[localisation.txtHeaderStyle] = settings.txtStyleMain
myArgs[localisation.txtBodyStyle]="width:"..settings.iWidth_px .. "px"
myArgs[localisation.txtLabelStyle]="width:" .. settings.iLabelWidth_pc .. "%"
myArgs[localisation.txtDataStyle]="width:" .. settings.iDataWidth_pc .. "%"
return myArgs
end
---------------------------------------------------- GENERIC SUPPORT FUNCTIONS -----------------------------------------------------------------------------------
--Remove?--
function processDates(entityid,txtSeparator)
txtDateFrom=''
txtDateTo=''
local p580=mw.wikibase.getAllStatements(entityid, 'P580' )
local hasstart=next(p580)
p582=mw.wikibase.getAllStatements(entityid, 'P582' )
local hasend=next(p582)
if hasstart then
txtDateFrom=read(p580[1],'time')
txtYearFrom=string.sub(txtDateFrom,2,5)
end
if hasend then
txtDateTo=read(p582[1],'time')
txtYearTo=string.sub(txtDateTo,2,5)
end
--For sorting purposes set date from and to date to the same if one of them is lacking
if hasend and not hasstart then
txtDateFrom=txtDateTo
txtYearFrom=txtYearTo
end
if hasstart and not hasend then
txtDateTo=txtDateFrom
txtYearTo=txtYearFrom
end
hasanydate=hasstart or hasend
if (hasanydate) then
txtSeason=txtYears(txtYearFrom,txtYearTo,txtSeparator)
end
return hasanydate,txtDateFrom,txtDateTo,txtYearFrom,txtSeason
end
sd.competitionarea=function(qidCompetition)
iArea=useStatement(qidCompetition, 'P131' ) -- located in the administrative territorial entity
if not (iArea) then
iArea=useStatement(qidCompetition, 'P17' ) -- country
end
if not (iArea) then
iArea=useStatement(qidCompetition, 'P30' ) -- continent
end
if not (iArea) then
iArea=useStatement(qidCompetition, 'P276' ) -- place
end
return iArea
end
return sd
--[=====[
--]=====]