Modul:FootballMatch
Documentația acestui modul poate fi creată la Modul:FootballMatch/doc
local StringUtils = require('Modul:StringUtils')
local getArgs = require('Modul:Arguments').getArgs
local wikidata = require('Modul:Wikidata')
local illWd = require('Modul:Ill-wd').fromArgs
local DateUtils = require('Modul:DateUtils')
local TableTools = require('Modul:TableTools')
local WDF_U = require('Modul:WikidataUtils/Football')
local NameAndImage = require('Modul:NameAndImage')
local FC = require('Modul:FootballClub')
local _br_ = tostring(mw.html.create('br'))
local EXTRATIME = "([[Prelungiri după timpul regulamentar 90 de minute|d.p.]])"
local ATTENDANCE = "Spectatori: "
local REFEREE = "Arbitru: "
local eventschema = "http://schema.org/SportsEvent"
local teamschema = "http://schema.org/SportsTeam"
local placeschema = "http://schema.org/Place"
local emptyToNil = StringUtils._emptyToNil
local p = {}
local SCORING_METHOD_INDEX = { Q18533 = 'aut.', Q279532 = 'pen.' }
local function fmtlist(s)
s = mw.ustring.gsub(s or '', '%[%[ *([%?-]) *%]%]', '%1')
s = mw.ustring.gsub(s, '%[%[ *[%?-] *| *(.-) *%]%]', '%1')
if mw.ustring.sub(s, 1, 1) == '*' then
return tostring(mw.html.create('div'):addClass('plainlist'):newline():wikitext(s))
end
return s
end
local function makelink(s,t)
if s:match('^http') then
return '[' .. s .. ' ' .. t .. ']'
end
return s
end
function p.fromArgs(match, aspect)
local tbl
if aspect.bg ~= '' then
tbl = mw.html.create('table')
:attr('cellspacing', '0')
:addClass('collapsible'):addClass('collapsed'):addClass('vevent')
--:addClass('mw-collapsible'):addClass('mw-made-collapsible')
:addClass(aspect.class)
:css('width', aspect.width or '100%')
:css('background-color', aspect.bg)
:css('border-top', '1px solid #999')
:css('border-bottom', '1px solid #999')
:css('margin-bottom', '-1px')
else
tbl = mw.html.create('table')
:attr('cellspacing', '0')
:addClass('collapsible'):addClass('collapsed'):addClass('vevent')
--:addClass('mw-collapsible'):addClass('mw-made-collapsible')
:addClass(aspect.class)
:css('width', aspect.width or '100%')
:css('border-top', '1px solid #999')
:css('border-bottom', '1px solid #999')
:css('margin-bottom', '-1px')
end
if not aspect.nobars then
tbl:css('border-top', '1px solid #999999')
if not aspect.stack then
tbl:css('border-bottom', '1px solid #999999')
end
end
local headRow = tbl:tag('tr'):css('vertical-align', 'top')
local dateAndCompetitionCell = headRow:tag('td'):css('width', '28%')
if match.date or match.round then
dateAndCompetitionCell:tag('span')
:css('float', 'right')
:css('white-space', 'nowrap')
:css('margin-left', '0.5em')
:wikitext(match.date)
if match.round then
dateAndCompetitionCell:tag('small'):wikitext(match.round)
end
end
local team1cell = headRow:tag('td')
:addClass('vcard'):addClass('attendee')
:css('width', '23%')
:css('text-align', 'right')
:tag('span')
:addClass('fn'):addClass('org')
:css('white-space', 'nowrap')
:wikitext(StringUtils._encloseString({match.teams[1], "''' ", " '''"}))
local scorecell = headRow:tag('td')
:css('width', '12%')
:css('text-align', 'center')
local scorespan = scorecell:tag('span')
:css('white-space', 'nowrap')
:css('display', 'inline')
scorespan:wikitext("''' " .. (match.score or 'v') .. " '''")
if match.aet then
scorespan:tag('span')
:css('font-size', '85%')
:wikitext(EXTRATIME)
end
if match.aggregatescore then
scorecell:tag('br'):done()
:tag('div')
:css('font-size', '85%')
:wikitext("('''", match.aggregatescore, "''' [[Scorul la general|gen.]])")
end
if match.penaltyscore then
scorecell:tag('br'):done()
:tag('div')
:css('font-size', '85%')
:wikitext("('''", match.penaltyscore, "''' [[Fotbal#Reprizele_de_prelungiri_.C8.99i_loviturile_de_departajare|d.l.d.]])")
end
local team2cell = headRow:tag('td')
:addClass('vcard'):addClass('attendee')
:css('width', '23%')
:tag('span')
:addClass('fn'):addClass('org')
:css('white-space', 'nowrap')
:wikitext(StringUtils._encloseString({match.teams[2], "''' ", " '''"}))
local venuecell = headRow:tag('td')
:css('width', '23%')
:css('font-size', '85%')
:addClass('location')
:wikitext(match.location)
headRow:tag('th')
:attr('width', '4%')
:attr('valign', 'top')
:attr('rowspan', '2')
:wikitext('')
local scorersRow = tbl:tag('tr')
:css('vertical-align', 'top')
:css('font-size', '85%')
local timeCell = scorersRow:tag('td')
:css('text-align', 'right')
:wikitext(match.time)
local hostsGoalsTd = scorersRow:tag('td')
:css('text-align', 'right')
:wikitext(match.goalslists[1])
local reportTd = scorersRow:tag('td')
:css('text-align', 'center')
reportTd:wikitext(makelink(match.report or '', 'Raport'))
if match.qid then
reportTd:wikitext(_br_ .. '[[:d:' .. match.qid .. '|Wikidata]]')
end
local guestsGoalsTd = scorersRow:tag('td')
:css('text-align', 'left')
:wikitext(match.goalslists[2])
local detailsTd = scorersRow:tag('td')
if match.stadium then
detailsTd:wikitext('Stadion: '):wikitext(match.stadium):wikitext(_br_)
end
if match.attendance then
detailsTd:wikitext(ATTENDANCE):wikitext(match.attendance):wikitext(_br_)
end
if match.referee then
detailsTd:wikitext(REFEREE):wikitext(match.referee):wikitext(_br_)
end
if match.assistantreferees then
detailsTd:wikitext('Arbitri asistenți: '):wikitext(match.assistantreferees):wikitext(_br_)
end
if match.goallineassistants then
detailsTd:wikitext('Arbitri de linia porții: '):wikitext(match.goallineassistants):wikitext(_br_)
end
if match.fourthofficial then
detailsTd:wikitext('Arbitru de rezervă: '):wikitext(match.fourthofficial):wikitext(_br_)
end
if match.motm then
detailsTd:wikitext('Omul meciului: '):wikitext(match.motm):wikitext(_br_)
end
if match.penaltyLists and #(match.penaltyLists) > 1 then
local penaltiesTitleRow = tbl:tag('tr')
penaltiesTitleRow:tag('td'):attr('rowspan', '2')
penaltiesTitleRow:tag('td'):attr('colspan', '3'):css('text-align', 'center'):wikitext(illWd('Q2691960', 'Penalty-uri de departajare', nil, true))
penaltiesTitleRow:tag('td'):attr('rowspan', '2')
local penaltiesRow = tbl:tag('tr')
penaltiesRow:tag('td'):css('text-align', 'right'):wikitext(match.penaltyLists[1])
penaltiesRow:tag('td')
penaltiesRow:tag('td'):wikitext(match.penaltyLists[2])
end
return tostring(tbl)
end
local function grabFirstQual(quals)
local theQual
if quals then for _,eachQual in ipairs(quals) do
if 'value' == eachQual.snaktype then
theQual = eachQual
break
end
end end
return theQual
end
local function grabFirstStatement(entityId, propId)
local statementClaim = nil
local statementClaimsList = wikidata.findBestClaimsForProperty(entityId, propId)
if statementClaimsList then for _,eachStatementClaim in ipairs(statementClaimsList) do
if 'statement' == eachStatementClaim.type and 'value' == eachStatementClaim.mainsnak.snaktype then
statementClaim = eachStatementClaim
break
end
end end
return statementClaim
end
local function extractDataFromArray(array)
local entityId = array.q or mw.wikibase.getEntityIdForCurrentPage()
local aspect = {}
aspect.class = array.class
aspect.bars = nil == array.nobars
aspect.stack = nil ~= array.stack
aspect.width = array.width or '100%'
aspect.bg = array.bg or ''
local match = {}
match.qid = array.q
match.id = array.id or array.q
match.round = array.round
match.event = array.event or array.eveniment or wikidata.findOneValue('P361', array.q) or wikidata.findOneValue('P179', array.q)
match.date = array.date or array['dată'] or ''
local wdDateClaim = nil
local matchDate = nil
if not match.date then
wdDateClaim = grabFirstStatement(entityId, 'P585')
if wdDateClaim then
matchDate = DateUtils.parseWikidataDate(wdDateClaim.mainsnak.datavalue.value.time, wdDateClaim.mainsnak.datavalue.value.precision)
match.date = DateUtils.formatDate(matchDate, true, false)
end
end
match.time = array.time
match.teams = {}
for _,eachTeamArg in ipairs({array.team1 or array.echipa1, array.team2 or array.echipa2}) do
if eachTeamArg then table.insert(match.teams, eachTeamArg) end
end
local scoreElements = {}
local teamIds = {}
if 2 > #(match.teams) then
local wdTeamClaims = wikidata.findBestClaimsForProperty(array.q, 'P1923')
local thisIsFirstTeam = true
if wdTeamClaims then for _,eachTeamClaim in ipairs(wdTeamClaims) do
table.insert(teamIds, eachTeamClaim.mainsnak.datavalue.value.id)
local isoTS = DateUtils.toISO8601(matchDate)
local thisTeamLabel
local thisTeamFlag
if WDF_U.isNationalTeam(eachTeamClaim.mainsnak.datavalue.value.id) then
thisTeamLabel = WDF_U.getNationalTeamName(eachTeamClaim.mainsnak.datavalue.value.id)
thisTeamFlag = NameAndImage._imageFromOneOfProps(eachTeamClaim.mainsnak.datavalue.value.id, {'P41'}, matchDate)
else
thisTeamLabel = FC.labelFromArgs(eachTeamClaim.mainsnak.datavalue.value.id, isoTS)
thisTeamFlag = FC.flagLinkFromArgs(eachTeamClaim.mainsnak.datavalue.value.id, isoTS)
end
local thisTeamLink = illWd(eachTeamClaim.mainsnak.datavalue.value.id, thisTeamLabel, nil, true)
table.insert(match.teams, thisIsFirstTeam and (thisTeamLink .. ' ' .. thisTeamFlag) or (thisTeamFlag .. ' ' .. thisTeamLink))
if eachTeamClaim.qualifiers and eachTeamClaim.qualifiers['P1351'] and eachTeamClaim.qualifiers['P1351'][1] and eachTeamClaim.qualifiers['P1351'][1].snaktype == 'value' then
table.insert(scoreElements, math.abs(eachTeamClaim.qualifiers['P1351'][1].datavalue.value.amount))
end
thisIsFirstTeam = false
end end
end
match.score = array.score or array.scor or emptyToNil({table.concat(scoreElements, mw.text.decode('–'))})
match.aet = (nil ~= array.aet)
match.aggregate = array.aggregatescore
match.penaltyscore = array.penaltyscore
match.referee = array.referee or array.arbitru or wikidata.findOneValue('P1652', array.q)
match.report = array.report or array.raport or wikidata.findOneValueNoRef('P856', array.q)
match.assistantreferees = array.assistantreferees
match.goallineassistants = array.goallineassistants
match.fourthofficial = array.fourthofficial
match.attendance = array.attendance or array.spectatori or wikidata.findOneValue('P1110', array.q)
match.location = array.location or array.loc
match.stadium = array.stadium or array.stadion
match.motm = array.motm or array.mvp
match.notes = array.note or array.notes
if array.penalties1 and array.penalties2 then
match.penaltyLists = { array.penalties1, array.penalties2 }
end
if not match.stadium then
local venueStatement = grabFirstStatement(array.q, 'P276')
if venueStatement then
match.stadium = wikidata.printSnak(venueStatement.mainsnak)
local townSnak
if venueStatement.qualifiers and venueStatement.qualifiers['P131'] then
townSnak = grabFirstQual(venueStatement.qualifiers['P131'])
if townSnak then
match.location = wikidata.printSnak(townSnak)
end
end
if not townSnak then
match.location = wikidata.findOneValue('P131', venueStatement.mainsnak.datavalue.value.id)
end
end
end
match.goalslists = {}
if array.goals1 or array.goluri1 then match.goalslists[1] = array.goals1 or array.goluri1 end
if array.goals2 or array.goluri2 then match.goalslists[2] = array.goals2 or array.goluri2 end
if 1 > table.maxn(match.goalslists) and array.q then
local wdGoalsClaims = wikidata.findBestClaimsForProperty(array.q, 'P1363')
local goalsTables = { {}, {} }
if wdGoalsClaims and #wdGoalsClaims > 0 then
wdDateClaim = wdDateClaim or grabFirstStatement(entityId, 'P585')
local matchDate = wdDateClaim and DateUtils.extractDateFromWikidataSnak(wdDateClaim.mainsnak) or matchDate
local goalScorers = {}
local goalScorersOrder = {}
for _,eachGoalClaim in ipairs(wdGoalsClaims) do if 'statement' == eachGoalClaim.type and 'value' == eachGoalClaim.mainsnak.snaktype then
local minute, addedTime, matchIntervalId, authorId, fromTeamId, scoringMethodId
if eachGoalClaim.qualifiers then
authorId = eachGoalClaim.mainsnak.datavalue.value.id
if eachGoalClaim.qualifiers['P1390'] then
local minuteSnak = grabFirstQual(eachGoalClaim.qualifiers['P1390'])
if minuteSnak.snaktype == 'value' then
minute = minuteSnak.datavalue.value.amount
end
end
if eachGoalClaim.qualifiers['P6887'] then
local matchIntervalSnak = grabFirstQual(eachGoalClaim.qualifiers['P6887'])
if matchIntervalSnak.snaktype == 'value' then
matchIntervalId = matchIntervalSnak.datavalue.value.id
end
end
if eachGoalClaim.qualifiers['P54'] then
local fromTeamSnak = grabFirstQual(eachGoalClaim.qualifiers['P54'])
if fromTeamSnak then
fromTeamId = fromTeamSnak.datavalue.value.id
end
end
if eachGoalClaim.qualifiers['P1443'] then
local scoringMethod = grabFirstQual(eachGoalClaim.qualifiers['P1443'])
if scoringMethod then
scoringMethodId = scoringMethod.datavalue.value.id
end
end
end
if matchIntervalId then
local minuteNo = tonumber(minute)
if matchIntervalId == 'Q62521848' and minuteNo > 45 then
addedTime = minuteNo - 45
minute = 45
elseif matchIntervalId == 'Q62521875' and minuteNo > 90 then
addedTime = minuteNo - 90
minute = 90
elseif matchIntervalId == 'Q186982' and minuteNo > 120 then
addedTime = minuteNo - 120
minute = 120
end
end
local goalDirection = scoringMethodId == 'Q18533' and -1 or 1
local goalScorerIndex = mw.text.jsonEncode({ scorerId = authorId, direction = goalDirection, teamId = fromTeamId})
local crtScorerGoals
if goalScorers[goalScorerIndex] then
crtScorerGoals = goalScorers[goalScorerIndex]
else
table.insert(goalScorersOrder, goalScorerIndex)
crtScorerGoals = {}
end
crtScorerGoals.scorerId = crtScorerGoals.scorerId or authorId
crtScorerGoals.teamId = crtScorerGoals.teamId or fromTeamId
crtScorerGoals.direction = crtScorerGoals.direction or goalDirection
crtScorerGoals.goals = crtScorerGoals.goals or {}
table.insert(crtScorerGoals.goals, {goalTime = minute, addedTime = addedTime, goalMethod = scoringMethodId })
goalScorers[goalScorerIndex] = crtScorerGoals
end end
table.sort(goalScorersOrder, function(scorerIndex1, scorerIndex2)
local scorer1 = goalScorers[scorerIndex1]
local scorer2 = goalScorers[scorerIndex2]
if not scorer1 or not scorer1.goals or #scorer1.goals == 0 then return -1 end
if not scorer2 or not scorer2.goals or #scorer2.goals == 0 then return 1 end
local minGoal1 = tonumber(scorer1.goals[1].goalTime)
for _,eachGoal in ipairs(scorer1.goals) do
local thisGoalTime = tonumber(eachGoal.goalTime)
if thisGoalTime < minGoal1 then minGoal1 = thisGoalTime end
end
local minGoal2 = tonumber(scorer2.goals[1].goalTime)
for _,eachGoal in ipairs(scorer2.goals) do
local thisGoalTime = tonumber(eachGoal.goalTime)
if thisGoalTime < minGoal2 then minGoal2 = thisGoalTime end
end
if minGoal1 < minGoal2 then return true end
return false
end)
for _,scorerIndex in pairs(goalScorersOrder) do
local scorerGoals = goalScorers[scorerIndex]
local goalText = illWd(scorerGoals.scorerId, nil, nil, true)
local goalTemplateParams = {}
for _,eachGoalData in ipairs(scorerGoals.goals) do
table.insert(goalTemplateParams, StringUtils._removeStart({tostring(eachGoalData.goalTime), '+'}) .. (eachGoalData.addedTime and ('+' .. tostring(eachGoalData.addedTime)) or ''))
table.insert(goalTemplateParams, SCORING_METHOD_INDEX[eachGoalData.goalMethod or ''] or '')
end
goalText = goalText .. ' ' .. mw.getCurrentFrame():expandTemplate{title = 'Gol', args = goalTemplateParams}
if scorerGoals.teamId == teamIds[1] and scorerGoals.direction == 1
or scorerGoals.teamId == teamIds[2] and scorerGoals.direction == -1 then
table.insert(goalsTables[1], goalText)
else
table.insert(goalsTables[2], goalText)
end
end
for eachGoalsTableIdx,eachGoalsTable in ipairs(goalsTables) do
match.goalslists[eachGoalsTableIdx] = table.concat(eachGoalsTable, _br_)
end
end
end
return match, aspect
end
function p.fromArray(array)
local match, aspect = extractDataFromArray(array)
return p.fromArgs(match, aspect)
end
function p.fromFrame(frame)
return p.fromArray(getArgs(frame))
end
function p.uncollapsibleFromArgs(match, aspect)
-- Start box
local root = nil
if aspect.bg ~= '' then
root =
mw.html.create('div')
:attr('itemscope', '')
:attr('itemtype', eventschema)
:addClass('footballbox')
:css('width', aspect.width)
:css('background-color', aspect.bg)
:attr('id', match.id)
else
root =
mw.html.create('div')
:attr('itemscope', '')
:attr('itemtype', eventschema)
:addClass('footballbox')
:css('width', aspect.width)
:attr('id', match.id)
end
root:newline()
if match.round then
root:tag('div')
:addClass('ftitle')
:wikitext(match.round)
end
-- Start left block
block = root:tag('div')
:addClass('mobile-float-reset')
:addClass('fleft')
local timetag = block:tag('time')
:attr('itemprop', d and 'startDate' or nil)
:attr('datetime', d)
timetag:tag('div')
:addClass('mobile-float-reset')
:addClass('fdate')
:wikitext(match.date)
if match.time then
timetag:tag('div')
:addClass('mobile-float-reset')
:addClass('ftime')
:wikitext(match.time)
end
if match.round then
block:tag('div')
:addClass('mobile-float-reset')
:addClass('frnd')
:wikitext(match.round)
end
-- End block
-- Start table
local rtable = root:tag('table')
:addClass('fevent')
local row = rtable:tag('tr')
:attr('itemprop', 'name')
row:newline()
row:tag('th')
:addClass('fhome')
:attr('itemprop', 'homeTeam')
:attr('itemscope', '')
:attr('itemtype', teamschema)
:tag('span')
:attr('itemprop', 'name')
:wikitext(match.teams[1])
row:tag('th')
:addClass('fscore')
:wikitext(StringUtils._appendToString(match.score, StringUtils._prependIfMissing((match.aet or match.penaltyscore) and EXTRATIME or nil, ' ')))
row:tag('th')
:addClass('faway')
:attr('itemprop', 'awayTeam')
:attr('itemscope', '')
:attr('itemtype', teamschema)
:tag('span')
:attr('itemprop', 'name')
:wikitext(match.teams[2])
row = rtable:tag('tr')
:addClass('fgoals')
:newline()
row:tag('td')
:addClass('fhgoal')
:wikitext(fmtlist(match.goalslists[1]))
row:newline()
row:tag('td')
:wikitext(makelink(match.report or '', 'Raport'))
:wikitext(match.qid and (_br_ .. '[[:d:' .. match.qid .. '|Wikidata]]') or '')
row:newline()
row:tag('td')
:addClass('fagoal')
:wikitext(fmtlist(match.goalslists[2]))
row:newline()
if match.penaltyscore then
row = rtable:tag('tr')
:addClass('fgoals')
row:newline()
row:tag('td')
:addClass('fhgoal')
:wikitext(match.penaltyLists and fmtlist(match.penaltyLists[1]) or '')
row:newline()
row:tag('th')
:wikitext(match.penaltyscore)
row:newline()
row:tag('td')
:addClass('fagoal')
:wikitext(match.penaltyLists and fmtlist(match.penaltyLists[2]) or '')
row:newline()
end
-- End table
-- Start right block
block = root:tag('div')
:addClass('mobile-float-reset')
:addClass('fright')
if match.stadium then
local sdiv = block:tag('div')
:attr('itemprop', 'location')
:attr('itemscope', '')
:attr('itemtype', placeschema)
if match.location then
sdiv:tag('span')
:attr('itemprop', 'name')
:wikitext(match.stadium)
sdiv:wikitext(', ')
sdiv:tag('span')
:attr('itemprop', 'address')
:wikitext(match.location)
else
sdiv:tag('span')
:attr('itemprop', 'name address')
:wikitext(match.stadium)
end
end
if match.attendance then
block:tag('div'):wikitext(ATTENDANCE ..' ' .. match.attendance)
end
if match.referee then
block:tag('div'):wikitext(REFEREE .. ' ' .. match.referee)
end
return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Football box/styles.css'} } .. tostring(root)
end
function p.uncollapsibleFromArray(array)
local match, aspect = extractDataFromArray(array)
return p.uncollapsibleFromArgs(match, aspect)
end
function p.uncollapsibleFromFrame(frame)
return p.uncollapsibleFromArray(getArgs(frame))
end
return p