Skip to content

Commit

Permalink
feat(match2): add support for team opponents on AoE (#4043)
Browse files Browse the repository at this point in the history
* feat(match2): add support for team opponents on AoE

* .

* bigger width for non-solo game

* refactor a bit

* teams should now be working as intended

* linter

* match legacy

* add todo

* increase width + fix opponent fetching

* update copypasta

* code tyle in summary

* aoe bestof typo

* refactor game and match player merge

* full team support to match legacy

* fix typo

* m2 info status update

* code style
  • Loading branch information
Rathoz authored Mar 4, 2024
1 parent 253b522 commit ebdc1ef
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 81 deletions.
14 changes: 10 additions & 4 deletions components/match2/commons/match_summary_base.lua
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@ function Match:create()
end

---@class MatchSummary
---@operator call(string?):MatchSummary
---@field Header MatchSummaryHeader
---@field Body MatchSummaryBody
---@field Comment MatchSummaryComment
Expand Down Expand Up @@ -536,7 +537,7 @@ end

---Default header function
---@param match table
---@param options {teamStyle: teamStyle?, width: string?, noScore:boolean?}?
---@param options {teamStyle: teamStyle?, noScore:boolean?}?
---@return MatchSummaryHeader
function MatchSummary.createDefaultHeader(match, options)
options = options or {}
Expand Down Expand Up @@ -634,7 +635,7 @@ end
---Default createMatch function for usage in Custom MatchSummary
---@param matchData table?
---@param CustomMatchSummary table
---@param options {teamStyle: teamStyle?, width: string?, noScore: boolean?}?
---@param options {teamStyle: teamStyle?, noScore: boolean?}?
---@return MatchSummaryMatch?
function MatchSummary.createMatch(matchData, CustomMatchSummary, options)
if not matchData then
Expand Down Expand Up @@ -663,7 +664,7 @@ end
---Default getByMatchId function for usage in Custom MatchSummary
---@param CustomMatchSummary table
---@param args table
---@param options {teamStyle: teamStyle?, width: string?, noScore:boolean?}?
---@param options {teamStyle: teamStyle?, width: fun(MatchGroupUtilMatch):string?|string?, noScore:boolean?}?
---@return Html
function MatchSummary.defaultGetByMatchId(CustomMatchSummary, args, options)
assert(type(CustomMatchSummary.createBody) == 'function', 'Function "createBody" missing in "Module:MatchSummary"')
Expand All @@ -673,7 +674,12 @@ function MatchSummary.defaultGetByMatchId(CustomMatchSummary, args, options)
local match, bracketResetMatch = MatchGroupUtil.fetchMatchForBracketDisplay(
args.bracketId, args.matchId)

local matchSummary = MatchSummary():init(options.width)
local width = options.width
if type(width) == 'function' then
width = width(match)
end

local matchSummary = MatchSummary():init(width)

--additional header for when martin adds the the css and buttons for switching between match and reset match
--if bracketResetMatch then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ local INDENT = WikiCopyPaste.Indent
---@param args table
---@return string
function WikiCopyPaste.getMatchCode(bestof, mode, index, opponents, args)
local maps
if mode == Opponent.solo then
maps = Array.map(Array.range(1, bestof), function(mapIndex)
return INDENT .. '|map' .. mapIndex .. '={{Map|map=|winner=|civs1=|civs2=}}'
end)
else
maps = Array.map(Array.range(1, bestof), function(mapIndex)
return INDENT .. '|map' .. mapIndex .. '={{Map|map=|winner=|players1=|civs1=|players2=|civs2=}}'
end)
end

local lines = Array.extend(
'{{Match',
INDENT .. '|date=',
Expand All @@ -38,9 +49,7 @@ function WikiCopyPaste.getMatchCode(bestof, mode, index, opponents, args)
Array.map(Array.range(1, opponents), function(opponentIndex)
return INDENT .. '|opponent' .. opponentIndex .. '=' .. WikiCopyPaste._getOpponent(mode)
end),
Array.map(Array.range(1, bestof), function(mapIndex)
return INDENT .. '|map' .. mapIndex .. '={{Map|map=|winner=|civs1=|civs2=}}'
end),
maps,
'}}'
)

Expand Down
83 changes: 46 additions & 37 deletions components/match2/wikis/ageofempires/match_group_input_custom.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ local ALLOWED_STATUSES = {'W', 'FF', 'DQ', 'L'}
local CONVERT_STATUS_INPUT = {W = 'W', FF = 'FF', L = 'L', DQ = 'DQ', ['-'] = 'L'}
local DEFAULT_LOSS_STATUSES = {'FF', 'L', 'DQ'}
local MAX_NUM_OPPONENTS = 2
local MAX_NUM_PLAYERS = 10
local DEFAULT_BESTOF = 99

local CustomMatchGroupInput = {}
Expand Down Expand Up @@ -253,19 +254,23 @@ end
---@return table
function CustomMatchGroupInput._getOpponents(match)
-- read opponents and ignore empty ones
local opponents = {}
for opponentIndex = 1, MAX_NUM_OPPONENTS do
-- read opponent
local opponent = match['opponent' .. opponentIndex]
if not Logic.isEmpty(opponent) then
if Logic.isNotEmpty(opponent) then
CustomMatchGroupInput.processOpponent(opponent, match.timestamp)
end
end

-- Update all opponents with new values
for opponentIndex, opponent in pairs(opponents) do
match['opponent' .. opponentIndex] = opponent

if opponent.type == Opponent.team and Logic.isNotEmpty(opponent.name) then
MatchGroupInput.readPlayersOfTeam(match, opponentIndex, opponent.name, {
resolveRedirect = true,
applyUnderScores = true,
maxNumPlayers = MAX_NUM_PLAYERS,
})
end
end

return match
end

Expand Down Expand Up @@ -321,7 +326,7 @@ function CustomMatchGroupInput._mapInput(match, mapIndex)

-- get participants data for the map + get map mode + winnerfaction and loserfaction
--(w/l faction stuff only for 1v1 maps)
CustomMatchGroupInput.ProcessPlayerMapData(map, match, 2)
CustomMatchGroupInput.processPlayerMapData(map, match, 2)

match['map' .. mapIndex] = map
end
Expand Down Expand Up @@ -396,62 +401,66 @@ end
---@param map table
---@param match table
---@param numberOfOpponents integer
function CustomMatchGroupInput.ProcessPlayerMapData(map, match, numberOfOpponents)
function CustomMatchGroupInput.processPlayerMapData(map, match, numberOfOpponents)
local participants = {}
for opponentIndex = 1, numberOfOpponents do
local opponent = match['opponent' .. opponentIndex]
local players = opponent.match2players
if opponent.type == Opponent.solo then
CustomMatchGroupInput._processPartyPlayerMapData(players, map, opponentIndex, participants)
if Opponent.typeIsParty(opponent.type) then
CustomMatchGroupInput._processPartyMapData(opponent.match2players, map, opponentIndex, participants)
elseif opponent.type == Opponent.team then
error('Team opponents are not yet supported')
CustomMatchGroupInput._processTeamMapData(opponent.match2players, map, opponentIndex, participants)
end
end

map.participants = participants

if numberOfOpponents ~= MAX_NUM_OPPONENTS or map.mode ~= '1v1' then
return
end

local playerNameArray = CustomMatchGroupInput._fetchOpponentMapParticipantData(participants)

map.extradata.opponent1 = playerNameArray[1]
map.extradata.opponent2 = playerNameArray[2]
end

---@param players table[]
---@param map table
---@param opponentIndex integer
---@param participants table<string, table>
---@return table<integer, string>
function CustomMatchGroupInput._fetchOpponentMapParticipantData(participants)
local playerNameArray = {}
for participantKey, participantData in pairs(participants) do
local opponentIndex = tonumber(string.sub(participantKey, 1, 1))
-- opponentIndex can not be nil due to the format of the participants keys
---@cast opponentIndex -nil
playerNameArray[opponentIndex] = participantData.player
---@return table<string, table>
function CustomMatchGroupInput._processPartyMapData(players, map, opponentIndex, participants)
local civs = Array.parseCommaSeparatedString(map['civs' .. opponentIndex])

for playerIndex, player in pairs(players) do
local civ = Logic.emptyOr(civs[playerIndex], Faction.defaultFaction)
civ = Faction.read(civ, {game = Game.abbreviation{game = map.game}:lower()})

participants[opponentIndex .. '_' .. playerIndex] = {
civ = civ,
player = player.name,
}
end

return playerNameArray
return participants
end

---@param players table[]
---@param opponentPlayers table[]
---@param map table
---@param opponentIndex integer
---@param participants table<string, table>
---@return table<string, table>
function CustomMatchGroupInput._processPartyPlayerMapData(players, map, opponentIndex, participants)
function CustomMatchGroupInput._processTeamMapData(opponentPlayers, map, opponentIndex, participants)
local players = Array.parseCommaSeparatedString(map['players' .. opponentIndex])
local civs = Array.parseCommaSeparatedString(map['civs' .. opponentIndex])

local function findPlayer(name)
return Table.filter(opponentPlayers or {}, function(player)
return player.displayName == name or player.pageName == name
end)[1] or {pageName = name, displayName = name}
end

for playerIndex, player in pairs(players) do
local civ = Logic.emptyOr(
civs[playerIndex],
Faction.defaultFaction
)
local civ = Logic.emptyOr(civs[playerIndex], Faction.defaultFaction)
civ = Faction.read(civ, {game = Game.abbreviation{game = map.game}:lower()})
local playerData = findPlayer(player)

participants[opponentIndex .. '_' .. playerIndex] = {
civ = civ,
player = player.name,
displayName = playerData.displayname,
pageName = playerData.name,
flag = playerData.flag,
}
end

Expand Down
55 changes: 40 additions & 15 deletions components/match2/wikis/ageofempires/match_legacy.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,41 @@ function MatchLegacy.storeGames(match, match2)
for gameIndex, game2 in ipairs(match2.match2games or {}) do
local game = Table.deepCopy(game2)
local participants = Json.parseIfString(game2.participants) or {}
local player1 = participants['1_1'] or {}
local player2 = participants['2_1'] or {}

-- Extradata
game.extradata = {}
game.extradata.gamenumber = gameIndex
game.extradata.mapmode = game2.extradata.mapmode
game.extradata.tournament = match.tournament
game.extradata.vodmatch = match.vod
game.extradata.opponent1civ = player1.civ
game.extradata.opponent2civ = player2.civ
game.extradata.winnerciv =
(tonumber(game.winner) == 1 and game.extradata.opponent1civ) or
(tonumber(game.winner) == 2 and game.extradata.opponent2civ) or
''
game.extradata.loserciv =
(tonumber(game.winner) == 2 and game.extradata.opponent1civ) or
(tonumber(game.winner) == 1 and game.extradata.opponent2civ) or
''
game.extradata.opponent1name = player1.player
game.extradata.opponent2name = player2.player
if game.mode == 'team' then
local function processOpponent(opponentIndex)
for _, player, playerId in Table.iter.pairsByPrefix(participants, opponentIndex .. '_') do
local prefix = 'o' .. opponentIndex .. 'p' .. playerId
game.extradata[prefix] = player.pageName
game.extradata[prefix .. 'faction'] = player.civ
game.extradata[prefix .. 'name'] = player.displayname
game.extradata[prefix .. 'flag'] = player.flag
end
end
processOpponent(1)
processOpponent(2)
elseif game.mode == '1v1' then
local player1 = participants['1_1'] or {}
local player2 = participants['2_1'] or {}
game.extradata.opponent1civ = player1.civ
game.extradata.opponent2civ = player2.civ
game.extradata.winnerciv =
(tonumber(game.winner) == 1 and game.extradata.opponent1civ) or
(tonumber(game.winner) == 2 and game.extradata.opponent2civ) or
''
game.extradata.loserciv =
(tonumber(game.winner) == 2 and game.extradata.opponent1civ) or
(tonumber(game.winner) == 1 and game.extradata.opponent2civ) or
''
game.extradata.opponent1name = player1.player
game.extradata.opponent2name = player2.player
end
-- Other stuff
game.opponent1 = match.opponent1
game.opponent2 = match.opponent2
Expand Down Expand Up @@ -91,7 +106,7 @@ function MatchLegacy._convertParameters(match2)
-- Handle extradata fields
match.extradata = {}

match.extradata.bestofx = match2.bestof ~= 0 and tostring(match2.bestof) or ''
match.extradata.bestof = match2.bestof ~= 0 and tostring(match2.bestof) or ''
local bracketData = Json.parseIfString(match2.match2bracketdata)
if type(bracketData) == 'table' and bracketData.type == 'bracket' and bracketData.inheritedheader then
match.header = (DisplayHelper.expandHeader(bracketData.inheritedheader) or {})[1]
Expand All @@ -109,6 +124,16 @@ function MatchLegacy._convertParameters(match2)
match[prefix .. 'score'] = (tonumber(opponent.score) or 0) > 0 and opponent.score or 0
match[prefix .. 'flag'] = player.flag
match.extradata[prefix .. 'name'] = player.displayname
elseif opponent.type == Opponent.team then
match[prefix] = opponent.name
match[prefix..'score'] = (tonumber(opponent.score) or 0) > 0 and opponent.score or 0
local opponentplayers = {}
for i, player in pairs(opponentmatch2players) do
opponentplayers['p' .. i] = player.name or ''
opponentplayers['p' .. i .. 'flag'] = player.flag or ''
opponentplayers['p' .. i .. 'dn'] = player.displayname or ''
end
match[prefix..'players'] = mw.ext.LiquipediaDB.lpdb_create_json(opponentplayers)
elseif opponent.type == Opponent.literal then
match[prefix] = 'TBD'
end
Expand Down
Loading

0 comments on commit ebdc1ef

Please sign in to comment.