Skip to content

Commit

Permalink
feat(match2): standard processMatch on dota2 and lol (#5032)
Browse files Browse the repository at this point in the history
* feat(match2): standard processMatch on dota2 and lol

* lint
  • Loading branch information
Rathoz authored Nov 6, 2024
1 parent 7d9a7b2 commit 2328370
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 167 deletions.
13 changes: 8 additions & 5 deletions components/match2/commons/match_group_input_util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1078,34 +1078,37 @@ 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[]): 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

--- 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): fun(opponentIndex): integer
---
--- It may optionally have the following functions:
--- - removeUnsetMaps(maps): table[]
--- - getExtraData(match, games, opponents): table
--- - getLinks
---
--- Additionally, the Parser may have the following properties:
--- - DEFAULT_MODE: string
--- - DATE_FALLBACKS: string[]
--- - 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?]]

Expand All @@ -1115,11 +1118,11 @@ 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)
and Parser.calculateMatchScore(games)
Expand Down
126 changes: 43 additions & 83 deletions components/match2/wikis/dota2/match_group_input_custom.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand All @@ -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?
Expand All @@ -61,88 +60,45 @@ 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?]]

if map.map == DUMMY_MAP then
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)
Expand Down Expand Up @@ -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<string, string|table|nil>
local links = MatchGroupInputUtil.getLinks(match)
links.stratz = {}
Expand All @@ -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
Expand All @@ -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,
Expand All @@ -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)
)
Expand All @@ -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)
Expand All @@ -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,
Expand Down
Loading

0 comments on commit 2328370

Please sign in to comment.