diff --git a/components/infobox/commons/infobox_league.lua b/components/infobox/commons/infobox_league.lua index cfc8ff50e64..2870b78b78f 100644 --- a/components/infobox/commons/infobox_league.lua +++ b/components/infobox/commons/infobox_league.lua @@ -23,6 +23,7 @@ local Variables = require('Module:Variables') local BasicInfobox = Lua.import('Module:Infobox/Basic') local Flags = Lua.import('Module:Flags') +local HighlightConditions = Lua.import('Module:HighlightConditions') local InfoboxPrizePool = Lua.import('Module:Infobox/Extensions/PrizePool') local LeagueIcon = Lua.import('Module:LeagueIcon') local Links = Lua.import('Module:Links') @@ -504,7 +505,7 @@ end ---@param args table ---@return boolean function League:liquipediaTierHighlighted(args) - return self.data.publishertier + return HighlightConditions.tournament(self.data) end --- Allows for overriding this functionality diff --git a/components/infobox/wikis/callofduty/infobox_league_custom.lua b/components/infobox/wikis/callofduty/infobox_league_custom.lua index d2821957652..6c7d5196450 100644 --- a/components/infobox/wikis/callofduty/infobox_league_custom.lua +++ b/components/infobox/wikis/callofduty/infobox_league_custom.lua @@ -85,12 +85,6 @@ function CustomLeague:defineCustomPageVariables(args) Variables.varDefine('tournament_edate', self.data.endDate) end ----@param args table ----@return boolean -function CustomLeague:liquipediaTierHighlighted(args) - return Logic.readBool(args['atvi-sponsored']) -end - ---@param content Html|string|number|nil ---@return Html function CustomLeague:_createNoWrappingSpan(content) diff --git a/components/infobox/wikis/leagueoflegends/infobox_league_custom.lua b/components/infobox/wikis/leagueoflegends/infobox_league_custom.lua index 5719b366556..1b076e09c84 100644 --- a/components/infobox/wikis/leagueoflegends/infobox_league_custom.lua +++ b/components/infobox/wikis/leagueoflegends/infobox_league_custom.lua @@ -56,18 +56,12 @@ end ---@param args table ---@return string function CustomLeague:appendLiquipediatierDisplay(args) - if Logic.readBool(args.riotpremier) then + if self.data.publishertier then return ' ' .. RIOT_ICON end return '' end ----@param args table ----@return boolean -function CustomLeague:liquipediaTierHighlighted(args) - return Logic.readBool(args.riotpremier) -end - ---@param lpdbData table ---@param args table ---@return table @@ -75,14 +69,14 @@ function CustomLeague:addToLpdb(lpdbData, args) lpdbData.extradata.individual = String.isNotEmpty(args.participants_number) or String.isNotEmpty(args.individual) and 'true' or '' - lpdbData.extradata['is riot premier'] = String.isNotEmpty(args.riotpremier) and 'true' or '' + lpdbData.extradata['is riot premier'] = lpdbData.publishertier and 'true' or '' return lpdbData end ---@param args table function CustomLeague:customParseArguments(args) - self.data.publishertier = Logic.readBool(args.riotpremier) and '1' or nil + self.data.publishertier = Logic.readBoolOrNil(args.riotpremier) or nil end ---@param args table diff --git a/components/infobox/wikis/tft/infobox_league_custom.lua b/components/infobox/wikis/tft/infobox_league_custom.lua index f9670b04044..8c8120c77fa 100644 --- a/components/infobox/wikis/tft/infobox_league_custom.lua +++ b/components/infobox/wikis/tft/infobox_league_custom.lua @@ -62,16 +62,10 @@ function CustomInjector:parse(id, widgets) return widgets end ----@param args table ----@return boolean -function CustomLeague:liquipediaTierHighlighted(args) - return Logic.readBool(args['riot-sponsored']) -end - ---@param args table ---@return string function CustomLeague:appendLiquipediatierDisplay(args) - if Logic.readBool(args['riot-sponsored']) then + if self.data.publishertier then return ' ' .. RIOT_ICON end return '' @@ -83,6 +77,7 @@ function CustomLeague:customParseArguments(args) args.mode = args.mode and GAME_MODES[string.lower(args.mode):gsub('s$', '')] or DEFAULT_MODE self.data.mode = string.lower(args.mode) + self.data.publishertier = Logic.readBool(args['riot-sponsored']) and 'sponsored' or nil end ---@param args table diff --git a/components/infobox/wikis/trackmania/infobox_league_custom.lua b/components/infobox/wikis/trackmania/infobox_league_custom.lua index a7f7bf8c8d6..590d0c4ce3a 100644 --- a/components/infobox/wikis/trackmania/infobox_league_custom.lua +++ b/components/infobox/wikis/trackmania/infobox_league_custom.lua @@ -92,15 +92,6 @@ function CustomInjector:parse(id, widgets) return widgets end ----@param args table ----@return boolean -function CustomLeague:liquipediaTierHighlighted(args) - return Array.any(self:getAllArgsForBase(args, 'organizer'), - function(organizer) - return organizer:find('Nadeo', 1, true) or organizer:find('Ubisoft', 1, true) - end) -end - ---@param args table function CustomLeague:customParseArguments(args) self.data.mode = Logic.emptyOr( @@ -108,6 +99,10 @@ function CustomLeague:customParseArguments(args) (String.isNotEmpty(args.team_number) and 'team' or nil), DEFAULT_MODE ) + self.data.publishertier = Array.any(self:getAllArgsForBase(args, 'organizer'), + function(organizer) + return organizer:find('Nadeo', 1, true) or organizer:find('Ubisoft', 1, true) + end) end ---@param args table @@ -133,7 +128,7 @@ function CustomLeague:getWikiCategories(args) return info and (info.link .. ' Competitions') or nil end) - return Array.append(categories, self:liquipediaTierHighlighted(args) and 'Ubisoft Tournaments' or nil) + return Array.append(categories, self.data.publishertier and 'Ubisoft Tournaments' or nil) end ---@param lpdbData table diff --git a/components/infobox/wikis/valorant/infobox_league_custom.lua b/components/infobox/wikis/valorant/infobox_league_custom.lua index 799666fe963..be27bc34925 100644 --- a/components/infobox/wikis/valorant/infobox_league_custom.lua +++ b/components/infobox/wikis/valorant/infobox_league_custom.lua @@ -110,16 +110,10 @@ function CustomLeague:addToLpdb(lpdbData, args) return lpdbData end ----@param args table ----@return boolean -function CustomLeague:liquipediaTierHighlighted(args) - return Logic.readBool(args['riot-highlighted']) -end - ---@param args table ---@return string function CustomLeague:appendLiquipediatierDisplay(args) - if Logic.readBool(args['riot-highlighted']) or Logic.readBool(args['riot-sponsored']) then + if self.data.publishertier then return ' ' .. RIOT_ICON end return '' diff --git a/components/match2/commons/match_group_input_util.lua b/components/match2/commons/match_group_input_util.lua index afe350825ee..e9b3dcfc163 100644 --- a/components/match2/commons/match_group_input_util.lua +++ b/components/match2/commons/match_group_input_util.lua @@ -1078,11 +1078,12 @@ function MatchGroupInputUtil.mergeStandaloneIntoMatch(match, standaloneMatch) end ---@class MatchParserInterface ----@field extractMaps fun(match: table, opponents: table[]): table[] +---@field extractMaps fun(match: table, opponents: table[], mapProps: any?): table[] ---@field getBestOf fun(bestOfInput: string|integer, maps: table[]): integer ----@field calculateMatchScore fun(maps: table[], opponents: table[]): fun(opponentIndex: integer): integer +---@field calculateMatchScore? fun(maps: table[], opponents: table[]): fun(opponentIndex: integer): integer ---@field removeUnsetMaps? fun(maps: table[]): table[] ---@field getExtraData? fun(match: table, games: table[], opponents: table[]): table +---@field getLinks? fun(match: table, games: table[]): table ---@field DEFAULT_MODE? string ---@field DATE_FALLBACKS? string[] ---@field OPPONENT_CONFIG? readOpponentOptions @@ -1090,13 +1091,14 @@ end --- The standard way to process a match input. --- --- The Parser injection must have the following functions: ---- - extractMaps(match, opponents): table[] +--- - extractMaps(match, opponents, mapProps): table[] --- - getBestOf(bestOfInput, maps): integer ---- - calculateMatchScore(maps, opponents): fun(opponentIndex): integer --- --- It may optionally have the following functions: +--- - calculateMatchScore(maps, opponents): fun(opponentIndex): integer --- - removeUnsetMaps(maps): table[] --- - getExtraData(match, games, opponents): table +--- - getLinks --- --- Additionally, the Parser may have the following properties: --- - DEFAULT_MODE: string @@ -1104,8 +1106,9 @@ end --- - OPPONENT_CONFIG: table ---@param match table ---@param Parser MatchParserInterface +---@param mapProps any? ---@return table -function MatchGroupInputUtil.standardProcessMatch(match, Parser) +function MatchGroupInputUtil.standardProcessMatch(match, Parser, mapProps) local finishedInput = match.finished --[[@as string?]] local winnerInput = match.winner --[[@as string?]] @@ -1115,13 +1118,13 @@ function MatchGroupInputUtil.standardProcessMatch(match, Parser) return MatchGroupInputUtil.readOpponent(match, opponentIndex, Parser.OPPONENT_CONFIG) end) - local games = Parser.extractMaps(match, opponents) + local games = Parser.extractMaps(match, opponents, mapProps) match.bestof = Parser.getBestOf(match.bestof, games) games = Parser.removeUnsetMaps and Parser.removeUnsetMaps(games) or games - match.links = MatchGroupInputUtil.getLinks(match) + match.links = Parser.getLinks and Parser.getLinks(match, games) or MatchGroupInputUtil.getLinks(match) - local autoScoreFunction = MatchGroupInputUtil.canUseAutoScore(match, games) + local autoScoreFunction = (Parser.calculateMatchScore and MatchGroupInputUtil.canUseAutoScore(match, games)) and Parser.calculateMatchScore(games, opponents) or nil Array.forEach(opponents, function(opponent, opponentIndex) diff --git a/components/match2/wikis/dota2/match_group_input_custom.lua b/components/match2/wikis/dota2/match_group_input_custom.lua index 6bb7c98e0f6..cb35a12d073 100644 --- a/components/match2/wikis/dota2/match_group_input_custom.lua +++ b/components/match2/wikis/dota2/match_group_input_custom.lua @@ -13,7 +13,6 @@ local Logic = require('Module:Logic') local Lua = require('Module:Lua') local Operator = require('Module:Operator') local String = require('Module:StringUtils') -local Streams = require('Module:Links/Stream') local Table = require('Module:Table') local Variables = require('Module:Variables') @@ -23,20 +22,20 @@ local MatchGroupUtil = Lua.import('Module:MatchGroup/Util') local OpponentLibraries = Lua.import('Module:OpponentLibraries') local Opponent = OpponentLibraries.Opponent -local OPPONENT_CONFIG = { +local CustomMatchGroupInput = {} +local MatchFunctions = {} +local MapFunctions = {} + +local DUMMY_MAP = 'default' +MatchFunctions.OPPONENT_CONFIG = { resolveRedirect = true, pagifyTeamNames = false, maxNumPlayers = 15, } -local DEFAULT_MODE = 'team' -local DUMMY_MAP = 'default' - -local MatchFunctions = {} -local MapFunctions = {} +MatchFunctions.DEFAULT_MODE = 'team' +MatchFunctions.getBestOf = MatchGroupInputUtil.getBestOf -local CustomMatchGroupInput = {} - ----@class Dota2MatchParserInterface +---@class Dota2MapParserInterface ---@field getMap fun(mapInput: table): table ---@field getLength fun(map: table): string? ---@field getSide fun(map: table, opponentIndex: integer): string? @@ -61,76 +60,33 @@ function CustomMatchGroupInput.processMatch(match, options) end end - local MatchParser + local MapParser if options.isMatchPage then - MatchParser = Lua.import('Module:MatchGroup/Input/Custom/MatchPage') + MapParser = Lua.import('Module:MatchGroup/Input/Custom/MatchPage') else - MatchParser = Lua.import('Module:MatchGroup/Input/Custom/Normal') + MapParser = Lua.import('Module:MatchGroup/Input/Custom/Normal') end - return CustomMatchGroupInput.processMatchWithoutStandalone(MatchParser, match) + return CustomMatchGroupInput.processMatchWithoutStandalone(MapParser, match) end ----@param MatchParser Dota2MatchParserInterface +---@param MapParser Dota2MapParserInterface ---@param match table ---@return table -function CustomMatchGroupInput.processMatchWithoutStandalone(MatchParser, match) - local finishedInput = match.finished --[[@as string?]] - local winnerInput = match.winner --[[@as string?]] - Table.mergeInto(match, MatchGroupInputUtil.readDate(match.date)) - - local opponents = Array.mapIndexes(function(opponentIndex) - return MatchGroupInputUtil.readOpponent(match, opponentIndex, OPPONENT_CONFIG) - end) - local games = MatchFunctions.extractMaps(MatchParser, match, opponents) - match.bestof = MatchGroupInputUtil.getBestOf(match.bestof, games) - match.links = MatchFunctions.getLinks(match, games, opponents) - - local autoScoreFunction = MatchGroupInputUtil.canUseAutoScore(match, games) - and MatchFunctions.calculateMatchScore(games) - or nil - - Array.forEach(opponents, function(opponent, opponentIndex) - opponent.score, opponent.status = MatchGroupInputUtil.computeOpponentScore({ - walkover = match.walkover, - winner = match.winner, - opponentIndex = opponentIndex, - score = opponent.score, - }, autoScoreFunction) - end) - - match.finished = MatchGroupInputUtil.matchIsFinished(match, opponents) - - if match.finished then - match.resulttype = MatchGroupInputUtil.getResultType(winnerInput, finishedInput, opponents) - match.walkover = MatchGroupInputUtil.getWalkover(match.resulttype, opponents) - match.winner = MatchGroupInputUtil.getWinner(match.resulttype, winnerInput, opponents) - Array.forEach(opponents, function(opponent, opponentIndex) - opponent.placement = MatchGroupInputUtil.placementFromWinner(match.resulttype, match.winner, opponentIndex) - end) - end - - match.mode = Logic.emptyOr(match.mode, Variables.varDefault('tournament_mode'), DEFAULT_MODE) - Table.mergeInto(match, MatchGroupInputUtil.getTournamentContext(match)) - - match.stream = Streams.processStreams(match) - - match.games = games - match.opponents = opponents - - match.extradata = MatchFunctions.getExtraData(match) - - return match +function CustomMatchGroupInput.processMatchWithoutStandalone(MapParser, match) + local parsedMatch = MatchGroupInputUtil.standardProcessMatch(match, MatchFunctions, MapParser) + parsedMatch.links.headtohead = MatchFunctions.getHeadToHeadLink(match, parsedMatch.opponents) + return parsedMatch end ----@param MatchParser Dota2MatchParserInterface ---@param match table ---@param opponents table[] +---@param MapParser Dota2MapParserInterface ---@return table[] -function MatchFunctions.extractMaps(MatchParser, match, opponents) +function MatchFunctions.extractMaps(match, opponents, MapParser) local maps = {} for key, mapInput, mapIndex in Table.iter.pairsByPrefix(match, 'map', {requireIndex = true}) do - local map = MatchParser.getMap(mapInput) + local map = MapParser.getMap(mapInput) local finishedInput = map.finished --[[@as string?]] local winnerInput = map.winner --[[@as string?]] @@ -138,11 +94,11 @@ function MatchFunctions.extractMaps(MatchParser, match, opponents) map.map = nil end - map.length = MatchParser.getLength(map) + map.length = MapParser.getLength(map) map.vod = map.vod or String.nilIfEmpty(match['vodgame' .. mapIndex]) map.publisherid = map.matchid or String.nilIfEmpty(match['matchid' .. mapIndex]) - map.participants = MapFunctions.getParticipants(MatchParser, map, opponents) - map.extradata = MapFunctions.getExtraData(MatchParser, map, #opponents) + map.participants = MapFunctions.getParticipants(MapParser, map, opponents) + map.extradata = MapFunctions.getExtraData(MapParser, map, #opponents) map.finished = MatchGroupInputUtil.mapIsFinished(map) local opponentInfo = Array.map(opponents, function(_, opponentIndex) @@ -179,9 +135,8 @@ end ---@param match table ---@param games table[] ----@param opponents table[] ---@return table -function MatchFunctions.getLinks(match, games, opponents) +function MatchFunctions.getLinks(match, games) ---@type table local links = MatchGroupInputUtil.getLinks(match) links.stratz = {} @@ -197,17 +152,22 @@ function MatchFunctions.getLinks(match, games, opponents) end ) + return links +end + +---@param match table +---@param opponents table[] +---@return string? +function MatchFunctions.getHeadToHeadLink(match, opponents) local isTeamGame = Array.all(opponents, function(opponent) return opponent.type == Opponent.team end) if Logic.readBool(Logic.emptyOr(match.headtohead, Variables.varDefault('headtohead'))) and isTeamGame then local team1, team2 = string.gsub(opponents[1].name, ' ', '_'), string.gsub(opponents[2].name, ' ', '_') - links.headtohead = tostring(mw.uri.fullUrl('Special:RunQuery/Match_history')) .. + return tostring(mw.uri.fullUrl('Special:RunQuery/Match_history')) .. '?pfRunQueryFormName=Match+history&Head_to_head_query%5Bplayer%5D=' .. team1 .. '&Head_to_head_query%5Bopponent%5D=' .. team2 .. '&wpRunQuery=Run+query' end - - return links end ---@param match table @@ -219,11 +179,11 @@ function MatchFunctions.getExtraData(match) } end ----@param MatchParser Dota2MatchParserInterface +---@param MapParser Dota2MapParserInterface ---@param map table ---@param opponentCount integer ---@return table -function MapFunctions.getExtraData(MatchParser, map, opponentCount) +function MapFunctions.getExtraData(MapParser, map, opponentCount) local extraData = { publisherid = tonumber(map.publisherid), comment = map.comment, @@ -236,14 +196,14 @@ function MapFunctions.getExtraData(MatchParser, map, opponentCount) for opponentIndex = 1, opponentCount do local opponentData = { - objectives = MatchParser.getObjectives(map, opponentIndex), - side = MatchParser.getSide(map, opponentIndex), + objectives = MapParser.getObjectives(map, opponentIndex), + side = MapParser.getSide(map, opponentIndex), } opponentData = Table.merge(opponentData, - Table.map(MatchParser.getHeroPicks(map, opponentIndex) or {}, function(idx, hero) + Table.map(MapParser.getHeroPicks(map, opponentIndex) or {}, function(idx, hero) return 'hero' .. idx, getCharacterName(hero) end), - Table.map(MatchParser.getHeroBans(map, opponentIndex) or {}, function(idx, hero) + Table.map(MapParser.getHeroBans(map, opponentIndex) or {}, function(idx, hero) return 'ban' .. idx, getCharacterName(hero) end) ) @@ -253,7 +213,7 @@ function MapFunctions.getExtraData(MatchParser, map, opponentCount) end)) end - extraData.vetophase = MatchParser.getVetoPhase(map) + extraData.vetophase = MapParser.getVetoPhase(map) Array.forEach(extraData.vetophase or {}, function(veto) veto.character = getCharacterName(veto.character) end) @@ -262,16 +222,16 @@ function MapFunctions.getExtraData(MatchParser, map, opponentCount) end -- Parse participant information ----@param MatchParser Dota2MatchParserInterface +---@param MapParser Dota2MapParserInterface ---@param map table ---@param opponents table[] ---@return table -function MapFunctions.getParticipants(MatchParser, map, opponents) +function MapFunctions.getParticipants(MapParser, map, opponents) local allParticipants = {} local getCharacterName = FnUtil.curry(MatchGroupInputUtil.getCharacterName, HeroNames) Array.forEach(opponents, function(opponent, opponentIndex) - local participantList = MatchParser.getParticipants(map, opponentIndex) or {} + local participantList = MapParser.getParticipants(map, opponentIndex) or {} local participants, unattachedParticipants = MatchGroupInputUtil.parseParticipants( opponent.match2players, participantList, diff --git a/components/match2/wikis/easportsfc/match_group_input_custom.lua b/components/match2/wikis/easportsfc/match_group_input_custom.lua index 94eef48d385..769947e03b0 100644 --- a/components/match2/wikis/easportsfc/match_group_input_custom.lua +++ b/components/match2/wikis/easportsfc/match_group_input_custom.lua @@ -12,72 +12,42 @@ local Lua = require('Module:Lua') local Ordinal = require('Module:Ordinal') local Operator = require('Module:Operator') local Table = require('Module:Table') -local Variables = require('Module:Variables') local MatchGroupInputUtil = Lua.import('Module:MatchGroup/Input/Util') -local Streams = Lua.import('Module:Links/Stream') local OpponentLibraries = Lua.import('Module:OpponentLibraries') local Opponent = OpponentLibraries.Opponent local CustomMatchGroupInput = {} +CustomMatchGroupInput.DEFAULT_MODE = 'solo' --- called from Module:MatchGroup ---@param match table ---@param options table? ---@return table function CustomMatchGroupInput.processMatch(match, options) - local winnerInput = match.winner --[[@as string?]] - local finishedInput = match.finished --[[@as string?]] - - Table.mergeInto(match, MatchGroupInputUtil.readDate(match.date)) - - local opponents = Array.mapIndexes(function(opponentIndex) - return MatchGroupInputUtil.readOpponent(match, opponentIndex, {}) - end) - - local games = CustomMatchGroupInput.extractMaps(match, opponents) - - local scoreType = 'mapScores' - if Logic.readBool(match.hasSubmatches) then - scoreType = 'mapWins' - elseif Array.any(Array.map(games, Operator.property('penalty')), Logic.readBool) then - scoreType = 'penalties' - end - local autoScoreFunction = MatchGroupInputUtil.canUseAutoScore(match, games) - and CustomMatchGroupInput.calculateMatchScore(games, scoreType) - or nil - - Array.forEach(opponents, function(opponent, opponentIndex) - opponent.score, opponent.status = MatchGroupInputUtil.computeOpponentScore({ - walkover = match.walkover, - winner = winnerInput, - opponentIndex = opponentIndex, - score = opponent.score, - }, autoScoreFunction) - end) - - match.bestof = tonumber(match.bestof) - match.finished = MatchGroupInputUtil.matchIsFinished(match, opponents) - - if match.finished then - match.resulttype = MatchGroupInputUtil.getResultType(winnerInput, finishedInput, opponents) - match.walkover = MatchGroupInputUtil.getWalkover(match.resulttype, opponents) - match.winner = MatchGroupInputUtil.getWinner(match.resulttype, winnerInput, opponents) - Array.forEach(opponents, function(opponent, opponentIndex) - opponent.placement = MatchGroupInputUtil.placementFromWinner(match.resulttype, match.winner, opponentIndex) - end) + --- TODO: Investigate if some parts of this should be a display rather than storage. + --- If penalties is supplied, than one map MUST have the penalty flag set to true. + ---@param maps table[] + ---@return fun(opponentIndex: integer): integer + CustomMatchGroupInput.calculateMatchScore = function(maps) + local calculateBy = CustomMatchGroupInput.getScoreType(match, maps) + return function(opponentIndex) + if calculateBy == 'mapWins' then + return MatchGroupInputUtil.computeMatchScoreFromMapWinners(maps, opponentIndex) + elseif calculateBy == 'mapScores' then + return Array.reduce(Array.map(maps, function(map) + return map.scores[opponentIndex] or 0 + end), Operator.add, 0) + elseif calculateBy == 'penalties' then + return Array.filter(maps, function(map) + return Logic.readBool(map.penalty) + end)[1].scores[opponentIndex] + else + error('Unknown calculateBy: ' .. tostring(calculateBy)) + end + end end - match.mode = Logic.emptyOr(match.mode, Variables.varDefault('tournament_mode', 'solo')) - Table.mergeInto(match, MatchGroupInputUtil.getTournamentContext(match)) - - match.stream = Streams.processStreams(match) - match.extradata = CustomMatchGroupInput.getExtraData(match, scoreType == 'mapWins') - - match.games = games - match.opponents = opponents - - return match + return MatchGroupInputUtil.standardProcessMatch(match, CustomMatchGroupInput) end ---@param match table @@ -131,33 +101,30 @@ function CustomMatchGroupInput.extractMaps(match, opponents) return maps end ---- TODO: Investigate if some parts of this should be a display rather than storage. ---- If penalties is supplied, than one map MUST have the penalty flag set to true. ----@param maps table[] ----@param calculateBy 'mapWins'|'mapScores'|'penalties' ----@return fun(opponentIndex: integer): integer -function CustomMatchGroupInput.calculateMatchScore(maps, calculateBy) - return function(opponentIndex) - if calculateBy == 'mapWins' then - return MatchGroupInputUtil.computeMatchScoreFromMapWinners(maps, opponentIndex) - elseif calculateBy == 'mapScores' then - return Array.reduce(Array.map(maps, function(map) - return map.scores[opponentIndex] or 0 - end), Operator.add, 0) - elseif calculateBy == 'penalties' then - return Array.filter(maps, function(map) - return Logic.readBool(map.penalty) - end)[1].scores[opponentIndex] - else - error('Unknown calculateBy: ' .. tostring(calculateBy)) - end +---@param bestOfInput string? +---@return integer? +function CustomMatchGroupInput.getBestOf(bestOfInput) + return tonumber(bestOfInput) +end + +---@param match table +---@param games table[] +---@return 'mapWins'|'mapScores'|'penalties' +function CustomMatchGroupInput.getScoreType(match, games) + if Logic.readBool(match.hasSubmatches) then + return 'mapWins' + elseif Array.any(Array.map(games, Operator.property('penalty')), Logic.readBool) then + return 'penalties' + else + return 'mapScores' end end ---@param match table ----@param hasSubmatches boolean +---@param maps table[] ---@return table -function CustomMatchGroupInput.getExtraData(match, hasSubmatches) +function CustomMatchGroupInput.getExtraData(match, maps) + local hasSubmatches = CustomMatchGroupInput.getScoreType(match, maps) == 'mapWins' return { casters = MatchGroupInputUtil.readCasters(match, {noSort = true}), hassubmatches = tostring(hasSubmatches), diff --git a/components/match2/wikis/goals/get_match_group_copy_paste_wiki.lua b/components/match2/wikis/goals/get_match_group_copy_paste_wiki.lua new file mode 100644 index 00000000000..e4006c797ec --- /dev/null +++ b/components/match2/wikis/goals/get_match_group_copy_paste_wiki.lua @@ -0,0 +1,48 @@ +--- +-- @Liquipedia +-- wiki=goals +-- page=Module:GetMatchGroupCopyPaste/wiki +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local Array = require('Module:Array') +local Class = require('Module:Class') +local Logic = require('Module:Logic') +local Lua = require('Module:Lua') + +local BaseCopyPaste = Lua.import('Module:GetMatchGroupCopyPaste/wiki/Base') + +---@class GoalsMatch2CopyPaste: Match2CopyPasteBase +local WikiCopyPaste = Class.new(BaseCopyPaste) + +local INDENT = WikiCopyPaste.Indent + +--returns the Code for a Match, depending on the input +---@param bestof integer +---@param mode string +---@param index integer +---@param opponents integer +---@param args table +---@return string +function WikiCopyPaste.getMatchCode(bestof, mode, index, opponents, args) + local showScore = Logic.readBool(args.score) + local streams = Logic.readBool(args.streams) + + local lines = Array.extend({}, + '{{Match', + Array.map(Array.range(1, opponents), function(opponentIndex) + return INDENT .. '|opponent' .. opponentIndex .. '=' .. WikiCopyPaste.getOpponent(mode, showScore) + end), + INDENT .. '|date= |finished=', + streams and (INDENT .. '|twitch=|vod=') or nil, + Array.map(Array.range(1, bestof), function(mapIndex) + return INDENT .. '|map' .. mapIndex .. '={{Map|score1=|score2=|finished=}}' + end), + '}}' + ) + + return table.concat(lines, '\n') +end + +return WikiCopyPaste diff --git a/components/match2/wikis/goals/match_group_input_custom.lua b/components/match2/wikis/goals/match_group_input_custom.lua new file mode 100644 index 00000000000..9f7c787040f --- /dev/null +++ b/components/match2/wikis/goals/match_group_input_custom.lua @@ -0,0 +1,72 @@ +--- +-- @Liquipedia +-- wiki=goals +-- page=Module:MatchGroup/Input/Custom +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local Array = require('Module:Array') +local Lua = require('Module:Lua') +local Operator = require('Module:Operator') +local Table = require('Module:Table') + +local MatchGroupInputUtil = Lua.import('Module:MatchGroup/Input/Util') + +local CustomMatchGroupInput = {} +CustomMatchGroupInput.DEFAULT_MODE = 'solo' +CustomMatchGroupInput.getBestOf = MatchGroupInputUtil.getBestOf + +-- called from Module:MatchGroup +---@param match table +---@param options table? +---@return table +function CustomMatchGroupInput.processMatch(match, options) + return MatchGroupInputUtil.standardProcessMatch(match, CustomMatchGroupInput) +end + +---@param match table +---@param opponents table[] +---@return table[] +function CustomMatchGroupInput.extractMaps(match, opponents) + local maps = {} + for mapKey, map in Table.iter.pairsByPrefix(match, 'map', {requireIndex = true}) do + if Table.isEmpty(map) then + break + end + local finishedInput = map.finished --[[@as string?]] + local winnerInput = map.winner --[[@as string?]] + + map.finished = MatchGroupInputUtil.mapIsFinished(map) + local opponentInfo = Array.map(opponents, function(_, opponentIndex) + local score, status = MatchGroupInputUtil.computeOpponentScore({ + walkover = map.walkover, + winner = map.winner, + opponentIndex = opponentIndex, + score = map['score' .. opponentIndex], + }) + return {score = score, status = status} + end) + + map.scores = Array.map(opponentInfo, Operator.property('score')) + if map.finished then + map.resulttype = MatchGroupInputUtil.getResultType(winnerInput, finishedInput, opponentInfo) + map.walkover = MatchGroupInputUtil.getWalkover(map.resulttype, opponentInfo) + map.winner = MatchGroupInputUtil.getWinner(map.resulttype, winnerInput, opponentInfo) + end + + table.insert(maps, map) + match[mapKey] = nil + end + + return maps +end + +---@return fun(opponentIndex: integer): integer +function CustomMatchGroupInput.calculateMatchScore(maps) + return function(opponentIndex) + return MatchGroupInputUtil.computeMatchScoreFromMapWinners(maps, opponentIndex) + end +end + +return CustomMatchGroupInput diff --git a/components/match2/wikis/goals/match_summary.lua b/components/match2/wikis/goals/match_summary.lua new file mode 100644 index 00000000000..abf594d3f46 --- /dev/null +++ b/components/match2/wikis/goals/match_summary.lua @@ -0,0 +1,40 @@ +--- +-- @Liquipedia +-- wiki=goals +-- page=Module:MatchSummary +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local CustomMatchSummary = {} + +local Lua = require('Module:Lua') + +local MatchSummary = Lua.import('Module:MatchSummary/Base') +local MatchSummaryWidgets = Lua.import('Module:Widget/Match/Summary/All') +local WidgetUtil = Lua.import('Module:Widget/Util') + +---@param args table +---@return Html +function CustomMatchSummary.getByMatchId(args) + return MatchSummary.defaultGetByMatchId(CustomMatchSummary, args) +end + +---@param date string +---@param game MatchGroupUtilGame +---@param gameIndex integer +---@return MatchSummaryRow +function CustomMatchSummary.createGame(date, game, gameIndex) + return MatchSummaryWidgets.Row{ + classes = {'brkts-popup-body-game'}, + css = {['font-size'] = '80%', padding = '4px'}, + children = WidgetUtil.collect( + MatchSummaryWidgets.GameWinLossIndicator{winner = game.winner, opponentIndex = 1}, + MatchSummaryWidgets.GameCenter{children = ('Game ' .. gameIndex)}, + MatchSummaryWidgets.GameWinLossIndicator{winner = game.winner, opponentIndex = 2}, + MatchSummaryWidgets.GameComment{children = game.comment} + ) + } +end + +return CustomMatchSummary diff --git a/components/match2/wikis/halo/match_group_input_custom.lua b/components/match2/wikis/halo/match_group_input_custom.lua index 996beff95f6..a7b777ed4b8 100644 --- a/components/match2/wikis/halo/match_group_input_custom.lua +++ b/components/match2/wikis/halo/match_group_input_custom.lua @@ -7,10 +7,8 @@ -- local Array = require('Module:Array') -local Logic = require('Module:Logic') local Lua = require('Module:Lua') local Operator = require('Module:Operator') -local Streams = require('Module:Links/Stream') local Table = require('Module:Table') local Variables = require('Module:Variables') @@ -18,69 +16,20 @@ local MatchGroupInputUtil = Lua.import('Module:MatchGroup/Input/Util') local OpponentLibrary = require('Module:OpponentLibraries') local Opponent = OpponentLibrary.Opponent -local DEFAULT_BESTOF = 3 -local DEFAULT_MODE = 'team' - --- containers for process helper functions +local CustomMatchGroupInput = {} local MatchFunctions = {} local MapFunctions = {} -local CustomMatchGroupInput = {} +local DEFAULT_BESTOF = 3 +MatchFunctions.DEFAULT_MODE = 'team' --- called from Module:MatchGroup ---@param match table ---@param options table? ---@return table function CustomMatchGroupInput.processMatch(match, options) - local finishedInput = match.finished --[[@as string?]] - local winnerInput = match.winner --[[@as string?]] - - Table.mergeInto(match, MatchGroupInputUtil.readDate(match.date)) - - local opponents = Array.mapIndexes(function(opponentIndex) - return MatchGroupInputUtil.readOpponent(match, opponentIndex, {}) - end) - - local games = MatchFunctions.extractMaps(match, #opponents) - match.links = MatchGroupInputUtil.getLinks(match) - match.links.headtohead = MatchFunctions.getHeadToHeadLink(match, opponents) - - match.bestof = MatchFunctions.getBestOf(match.bestof) - - local autoScoreFunction = MatchGroupInputUtil.canUseAutoScore(match, games) - and MatchFunctions.calculateMatchScore(games) - or nil - Array.forEach(opponents, function(opponent, opponentIndex) - opponent.score, opponent.status = MatchGroupInputUtil.computeOpponentScore({ - walkover = match.walkover, - winner = match.winner, - opponentIndex = opponentIndex, - score = opponent.score, - }, autoScoreFunction) - end) - - match.finished = MatchGroupInputUtil.matchIsFinished(match, opponents) - - if match.finished then - match.resulttype = MatchGroupInputUtil.getResultType(winnerInput, finishedInput, opponents) - match.walkover = MatchGroupInputUtil.getWalkover(match.resulttype, opponents) - match.winner = MatchGroupInputUtil.getWinner(match.resulttype, winnerInput, opponents) - Array.forEach(opponents, function(opponent, opponentIndex) - opponent.placement = MatchGroupInputUtil.placementFromWinner(match.resulttype, match.winner, opponentIndex) - end) - end - - match.mode = Logic.emptyOr(match.mode, Variables.varDefault('tournament_mode'), DEFAULT_MODE) - Table.mergeInto(match, MatchGroupInputUtil.getTournamentContext(match)) - - match.stream = Streams.processStreams(match) - - match.games = games - match.opponents = opponents - - match.extradata = MatchFunctions.getExtraData(match) - - return match + local parsedMatch = MatchGroupInputUtil.standardProcessMatch(match, MatchFunctions) + parsedMatch.links.headtohead = MatchFunctions.getHeadToHeadLink(match, parsedMatch.opponents) + return parsedMatch end -- @@ -88,9 +37,9 @@ end -- ---@param match table ----@param opponentCount integer +---@param opponents table[] ---@return table[] -function MatchFunctions.extractMaps(match, opponentCount) +function MatchFunctions.extractMaps(match, opponents) local maps = {} for key, map in Table.iter.pairsByPrefix(match, 'map', {requireIndex = true}) do if not map.map then @@ -99,10 +48,10 @@ function MatchFunctions.extractMaps(match, opponentCount) local finishedInput = map.finished --[[@as string?]] local winnerInput = map.winner --[[@as string?]] - map.extradata = MapFunctions.getExtraData(map, opponentCount) + map.extradata = MapFunctions.getExtraData(map) map.finished = MatchGroupInputUtil.mapIsFinished(map) - local opponentInfo = Array.map(Array.range(1, opponentCount), function(opponentIndex) + local opponentInfo = Array.map(opponents, function(_, opponentIndex) local score, status = MatchGroupInputUtil.computeOpponentScore({ walkover = map.walkover, winner = map.winner, @@ -195,9 +144,8 @@ end -- ---@param map table ----@param opponentCount integer ---@return table -function MapFunctions.getExtraData(map, opponentCount) +function MapFunctions.getExtraData(map) return { comment = map.comment, points1 = map.points1, diff --git a/components/match2/wikis/leagueoflegends/match_group_input_custom.lua b/components/match2/wikis/leagueoflegends/match_group_input_custom.lua index 1f4e864e85f..0349e735931 100644 --- a/components/match2/wikis/leagueoflegends/match_group_input_custom.lua +++ b/components/match2/wikis/leagueoflegends/match_group_input_custom.lua @@ -9,30 +9,27 @@ local Array = require('Module:Array') local FnUtil = require('Module:FnUtil') local HeroNames = mw.loadData('Module:ChampionNames') -local Logic = require('Module:Logic') local Lua = require('Module:Lua') local Operator = require('Module:Operator') local String = require('Module:StringUtils') -local Streams = require('Module:Links/Stream') local Table = require('Module:Table') -local Variables = require('Module:Variables') local MatchGroupInputUtil = Lua.import('Module:MatchGroup/Input/Util') local MatchGroupUtil = Lua.import('Module:MatchGroup/Util') -local OPPONENT_CONFIG = { +local CustomMatchGroupInput = {} +local MatchFunctions = {} +local MapFunctions = {} + +MatchFunctions.OPPONENT_CONFIG = { resolveRedirect = true, pagifyTeamNames = false, maxNumPlayers = 15, } -local DEFAULT_MODE = 'team' - -local MatchFunctions = {} -local MapFunctions = {} - -local CustomMatchGroupInput = {} +MatchFunctions.DEFAULT_MODE = 'team' +MatchFunctions.getBestOf = MatchGroupInputUtil.getBestOf ----@class LeagueOfLegendsMatchParserInterface +---@class LeagueOfLegendsMapParserInterface ---@field getMap fun(mapInput: table): table ---@field getLength fun(map: table): string? ---@field getSide fun(map: table, opponentIndex: integer): string? @@ -57,83 +54,38 @@ function CustomMatchGroupInput.processMatch(match, options) end end - local MatchParser + local MapParser if options.isMatchPage then - MatchParser = Lua.import('Module:MatchGroup/Input/Custom/MatchPage') + MapParser = Lua.import('Module:MatchGroup/Input/Custom/MatchPage') else - MatchParser = Lua.import('Module:MatchGroup/Input/Custom/Normal') + MapParser = Lua.import('Module:MatchGroup/Input/Custom/Normal') end - return CustomMatchGroupInput.processMatchWithoutStandalone(MatchParser, match) + return CustomMatchGroupInput.processMatchWithoutStandalone(MapParser, match) end ----@param MatchParser LeagueOfLegendsMatchParserInterface +---@param MapParser LeagueOfLegendsMapParserInterface ---@param match table ---@return table -function CustomMatchGroupInput.processMatchWithoutStandalone(MatchParser, match) - local finishedInput = match.finished --[[@as string?]] - local winnerInput = match.winner --[[@as string?]] - Table.mergeInto(match, MatchGroupInputUtil.readDate(match.date)) - - local opponents = Array.mapIndexes(function(opponentIndex) - return MatchGroupInputUtil.readOpponent(match, opponentIndex, OPPONENT_CONFIG) - end) - local games = MatchFunctions.extractMaps(MatchParser, match, opponents) - match.bestof = MatchGroupInputUtil.getBestOf(match.bestof, games) - match.links = MatchGroupInputUtil.getLinks(match) - - local autoScoreFunction = MatchGroupInputUtil.canUseAutoScore(match, games) - and MatchFunctions.calculateMatchScore(games) - or nil - - Array.forEach(opponents, function(opponent, opponentIndex) - opponent.score, opponent.status = MatchGroupInputUtil.computeOpponentScore({ - walkover = match.walkover, - winner = match.winner, - opponentIndex = opponentIndex, - score = opponent.score, - }, autoScoreFunction) - end) - - match.finished = MatchGroupInputUtil.matchIsFinished(match, opponents) - - if match.finished then - match.resulttype = MatchGroupInputUtil.getResultType(winnerInput, finishedInput, opponents) - match.walkover = MatchGroupInputUtil.getWalkover(match.resulttype, opponents) - match.winner = MatchGroupInputUtil.getWinner(match.resulttype, winnerInput, opponents) - Array.forEach(opponents, function(opponent, opponentIndex) - opponent.placement = MatchGroupInputUtil.placementFromWinner(match.resulttype, match.winner, opponentIndex) - end) - end - - match.mode = Logic.emptyOr(match.mode, Variables.varDefault('tournament_mode'), DEFAULT_MODE) - Table.mergeInto(match, MatchGroupInputUtil.getTournamentContext(match)) - - match.stream = Streams.processStreams(match) - - match.games = games - match.opponents = opponents - - match.extradata = MatchFunctions.getExtraData(match) - - return match +function CustomMatchGroupInput.processMatchWithoutStandalone(MapParser, match) + return MatchGroupInputUtil.standardProcessMatch(match, MatchFunctions, MapParser) end ----@param MatchParser LeagueOfLegendsMatchParserInterface ---@param match table ---@param opponents table[] +---@param MapParser LeagueOfLegendsMapParserInterface ---@return table[] -function MatchFunctions.extractMaps(MatchParser, match, opponents) +function MatchFunctions.extractMaps(match, opponents, MapParser) local maps = {} for key, mapInput, mapIndex in Table.iter.pairsByPrefix(match, 'map', {requireIndex = true}) do - local map = MatchParser.getMap(mapInput) + local map = MapParser.getMap(mapInput) local finishedInput = map.finished --[[@as string?]] local winnerInput = map.winner --[[@as string?]] - map.length = MatchParser.getLength(map) + map.length = MapParser.getLength(map) map.vod = map.vod or String.nilIfEmpty(match['vodgame' .. mapIndex]) - map.participants = MapFunctions.getParticipants(MatchParser, map, opponents) - map.extradata = MapFunctions.getExtraData(MatchParser, map, #opponents) + map.participants = MapFunctions.getParticipants(MapParser, map, opponents) + map.extradata = MapFunctions.getExtraData(MapParser, map, #opponents) map.finished = MatchGroupInputUtil.mapIsFinished(map) local opponentInfo = Array.map(opponents, function(_, opponentIndex) @@ -176,11 +128,11 @@ function MatchFunctions.getExtraData(match) } end ----@param MatchParser LeagueOfLegendsMatchParserInterface +---@param MapParser LeagueOfLegendsMapParserInterface ---@param map table ---@param opponentCount integer ---@return table -function MapFunctions.getExtraData(MatchParser, map, opponentCount) +function MapFunctions.getExtraData(MapParser, map, opponentCount) local extraData = { comment = map.comment, } @@ -192,14 +144,14 @@ function MapFunctions.getExtraData(MatchParser, map, opponentCount) for opponentIndex = 1, opponentCount do local opponentData = { - objectives = MatchParser.getObjectives(map, opponentIndex), - side = MatchParser.getSide(map, opponentIndex), + objectives = MapParser.getObjectives(map, opponentIndex), + side = MapParser.getSide(map, opponentIndex), } opponentData = Table.merge(opponentData, - Table.map(MatchParser.getHeroPicks(map, opponentIndex) or {}, function(idx, hero) + Table.map(MapParser.getHeroPicks(map, opponentIndex) or {}, function(idx, hero) return 'champion' .. idx, getCharacterName(hero) end), - Table.map(MatchParser.getHeroBans(map, opponentIndex) or {}, function(idx, hero) + Table.map(MapParser.getHeroBans(map, opponentIndex) or {}, function(idx, hero) return 'ban' .. idx, getCharacterName(hero) end) ) @@ -209,7 +161,7 @@ function MapFunctions.getExtraData(MatchParser, map, opponentCount) end)) end - extraData.vetophase = MatchParser.getVetoPhase(map) + extraData.vetophase = MapParser.getVetoPhase(map) Array.forEach(extraData.vetophase or {}, function(veto) veto.character = getCharacterName(veto.character) end) @@ -218,16 +170,16 @@ function MapFunctions.getExtraData(MatchParser, map, opponentCount) end -- Parse participant information ----@param MatchParser LeagueOfLegendsMatchParserInterface +---@param MapParser LeagueOfLegendsMapParserInterface ---@param map table ---@param opponents table[] ---@return table -function MapFunctions.getParticipants(MatchParser, map, opponents) +function MapFunctions.getParticipants(MapParser, map, opponents) local allParticipants = {} local getCharacterName = FnUtil.curry(MatchGroupInputUtil.getCharacterName, HeroNames) Array.forEach(opponents, function(opponent, opponentIndex) - local participantList = MatchParser.getParticipants(map, opponentIndex) or {} + local participantList = MapParser.getParticipants(map, opponentIndex) or {} local participants, unattachedParticipants = MatchGroupInputUtil.parseParticipants( opponent.match2players, participantList, diff --git a/spec/test_helper.lua b/spec/test_helper.lua index 6b4be1e9ba0..7c4700a1e6c 100644 --- a/spec/test_helper.lua +++ b/spec/test_helper.lua @@ -59,6 +59,7 @@ return function(busted, helper, options) table.insert(paths, 'components/standings/wikis/'.. wiki ..'/?.lua') table.insert(paths, 'components/transfer/wikis/'.. wiki ..'/?.lua') table.insert(paths, 'standard/info/wikis/'.. wiki ..'/?.lua') + table.insert(paths, 'standard/highlight_conditions/wikis/'.. wiki ..'/?.lua') table.insert(paths, 'standard/region/wikis/'.. wiki ..'/?.lua') table.insert(paths, 'standard/tier/wikis/'.. wiki ..'/?.lua') end @@ -78,6 +79,7 @@ return function(busted, helper, options) table.insert(paths, 'components/team_card/?.lua') table.insert(paths, 'components/transfer/commons/?.lua') table.insert(paths, 'standard/info/commons/?.lua') + table.insert(paths, 'standard/highlight_conditions/commons/?.lua') table.insert(paths, 'standard/region/commons/?.lua') table.insert(paths, 'standard/links/commons/?.lua') table.insert(paths, 'standard/tier/commons/?.lua') diff --git a/standard/highlight_conditions/wikis/counterstrike/highlight_conditions.lua b/standard/highlight_conditions/wikis/counterstrike/highlight_conditions.lua new file mode 100644 index 00000000000..15de437da8b --- /dev/null +++ b/standard/highlight_conditions/wikis/counterstrike/highlight_conditions.lua @@ -0,0 +1,38 @@ +--- +-- @Liquipedia +-- wiki=counterstrike +-- page=Module:HighlightConditions +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local String = require('Module:StringUtils') +local Table = require('Module:Table') + +local HighlightConditions = {} + +local DEFAULT_HIGHLIGHTABLE_VALUES = { + 'Major Championship', + 'Minor Championship', + 'Major Qualifier', + 'RMR Event' +} + +--- Check arguments or queryData if the tournament should be highlighted +---@param data table +---@param options table +---@return boolean +function HighlightConditions.tournament(data, options) + data.extradata = data.extradata or {} + options = options or {} + + if options.onlyHighlightOnValue then + return data.publishertier == options.onlyHighlightOnValue + elseif options.highlightOnAnyValue then + return String.isNotEmpty(data.publishertier) + end + + return String.isNotEmpty(data.publishertier) and Table.includes(DEFAULT_HIGHLIGHTABLE_VALUES, data.publishertier) +end + +return HighlightConditions diff --git a/standard/info/wikis/goals/info.lua b/standard/info/wikis/goals/info.lua index f4fdc545239..1024fa8ad9c 100644 --- a/standard/info/wikis/goals/info.lua +++ b/standard/info/wikis/goals/info.lua @@ -33,7 +33,8 @@ return { allowManual = true, }, match2 = { - status = 0, + status = 1, + gameScoresIfBo1 = true, }, }, }