From 765b6ff18cbdf2eb7dbb0a9e8655a71724be4a8a Mon Sep 17 00:00:00 2001 From: Rikard Blixt Date: Wed, 6 Nov 2024 14:49:29 +0100 Subject: [PATCH] feat(match2): replace `walkover` and `resulttype` with `status` on match level on standardized wikis (#5041) * feat(match2): replace `walkover` and `resulttype` with `status` on match level * fix walkover backwards * fix resulttype value for walkovers --- components/match2/commons/match.lua | 40 +++++++++++++++-- .../match2/commons/match_group_input_util.lua | 45 +++++++++++++------ .../match2/commons/match_group_util.lua | 5 +++ 3 files changed, 73 insertions(+), 17 deletions(-) diff --git a/components/match2/commons/match.lua b/components/match2/commons/match.lua index efdc52ef1b5..f3785fd2e25 100644 --- a/components/match2/commons/match.lua +++ b/components/match2/commons/match.lua @@ -308,7 +308,7 @@ end ---Final processing of records before being stored to LPDB. ---@param records table function Match._prepareRecordsForStore(records) - Match._prepareMatchRecordForStore(records.matchRecord) + Match._prepareMatchRecordForStore(records.matchRecord, records.opponentRecords) for opponentIndex, opponentRecord in ipairs(records.opponentRecords) do Match.clampFields(opponentRecord, Match.opponentFields) for _, playerRecord in ipairs(records.playerRecords[opponentIndex]) do @@ -321,7 +321,10 @@ function Match._prepareRecordsForStore(records) end ---@param match table -function Match._prepareMatchRecordForStore(match) +---@param opponents table[]? +function Match._prepareMatchRecordForStore(match, opponents) + Match._commonBackwardsCompatabilityForV3API(match, opponents) + match.dateexact = Logic.readBool(match.dateexact) and 1 or 0 match.finished = Logic.readBool(match.finished) and 1 or 0 match.match2bracketdata = match.match2bracketdata or match.bracketdata @@ -379,6 +382,35 @@ function Match._prepareGameRecordForStore(matchRecord, gameRecord) Match.clampFields(gameRecord, Match.gameFields) end +---Adds fields needed for backwards compatibility with API v3. +---walkover and resulttype are added to record. +---@param record table #game or match record +---@param opponents table[]? #opponents of the record +function Match._commonBackwardsCompatabilityForV3API(record, opponents) + if record.finished then + if not record.walkover then + local function calculateWalkover() + local walkoverOpponent = Array.find(opponents or {}, function(opponent) + return opponent.status == 'FF' or opponent.status == 'DQ' or opponent.status == 'L' + end) + return walkoverOpponent and walkoverOpponent.status:lower() or '' + end + record.walkover = calculateWalkover() + end + + if not record.resulttype then + if record.status == 'notplayed' then + record.resulttype = 'np' + elseif record.winner == 0 then + record.resulttype = 'draw' + elseif record.walkover ~= '' then + record.resulttype = 'default' + else + record.resulttype = '' + end + end + end +end Match.matchFields = Table.map({ 'bestof', @@ -400,7 +432,7 @@ Match.matchFields = Table.map({ 'parentname', 'patch', 'publishertier', - 'resulttype', + 'resulttype', -- LPDB API v3: backwards compatibility 'series', 'shortname', 'status', @@ -409,7 +441,7 @@ Match.matchFields = Table.map({ 'tournament', 'type', 'vod', - 'walkover', + 'walkover', -- LPDB API v3: backwards compatibility 'winner', 'section', }, function(_, field) return field, true end) diff --git a/components/match2/commons/match_group_input_util.lua b/components/match2/commons/match_group_input_util.lua index 9332ccd1fa4..453b22e4899 100644 --- a/components/match2/commons/match_group_input_util.lua +++ b/components/match2/commons/match_group_input_util.lua @@ -82,6 +82,11 @@ MatchGroupInputUtil.RESULT_TYPE = { NOT_PLAYED = 'np', DRAW = 'draw', } + +MatchGroupInputUtil.MATCH_STATUS = { + NOT_PLAYED = 'notplayed', +} + MatchGroupInputUtil.WALKOVER = { FORFEIT = 'ff', DISQUALIFIED = 'dq', @@ -608,7 +613,17 @@ function MatchGroupInputUtil.isNotPlayed(winnerInput, finishedInput) or (type(finishedInput) == 'string' and MatchGroupInputUtil.isNotPlayedInput(finishedInput)) end +---@param winnerInput integer|string|nil +---@param finishedInput string? +---@return string? #Match Status +function MatchGroupInputUtil.getMatchStatus(winnerInput, finishedInput) + if MatchGroupInputUtil.isNotPlayed(winnerInput, finishedInput) then + return MatchGroupInputUtil.MATCH_STATUS.NOT_PLAYED + end +end + ---Should only be called on finished matches or maps +---@deprecated ---@param winnerInput integer|string|nil ---@param finishedInput string? ---@param opponents {score: number?, status: string}[] @@ -627,18 +642,18 @@ function MatchGroupInputUtil.getResultType(winnerInput, finishedInput, opponents end end ----@param resultType string? +---@param status string ---@param winnerInput integer|string|nil ---@param opponents {score: number, status: string, placement: integer?}[] ---@return integer? # Winner -function MatchGroupInputUtil.getWinner(resultType, winnerInput, opponents) - if resultType == MatchGroupInputUtil.RESULT_TYPE.NOT_PLAYED then +function MatchGroupInputUtil.getWinner(status, winnerInput, opponents) + if status == MatchGroupInputUtil.RESULT_TYPE.NOT_PLAYED or status == MatchGroupInputUtil.MATCH_STATUS.NOT_PLAYED then return nil elseif Logic.isNumeric(winnerInput) then return tonumber(winnerInput) - elseif resultType == MatchGroupInputUtil.RESULT_TYPE.DRAW then + elseif MatchGroupInputUtil.isDraw(opponents, winnerInput) then return MatchGroupInputUtil.WINNER_DRAW - elseif resultType == MatchGroupInputUtil.RESULT_TYPE.DEFAULT then + elseif MatchGroupInputUtil.hasSpecialStatus(opponents) then return MatchGroupInputUtil.getDefaultWinner(opponents) elseif MatchGroupInputUtil.findOpponentWithFirstPlace(opponents) then return MatchGroupInputUtil.findOpponentWithFirstPlace(opponents) @@ -670,6 +685,7 @@ function MatchGroupInputUtil.getHighestScoringOpponent(opponents) return Array.indexOf(scores, FnUtil.curry(Operator.eq, maxScore)) end +---@deprecated ---@param resultType string? ---@param opponents {status: string}[] ---@return string? # Walkover Type @@ -679,6 +695,7 @@ function MatchGroupInputUtil.getWalkover(resultType, opponents) end end +---@deprecated ---@param opponents {status: string}[] ---@return string? function MatchGroupInputUtil.getWalkoverType(opponents) @@ -805,6 +822,7 @@ function MatchGroupInputUtil._opponentWithStatus(opponents, status) return Array.indexOf(opponents, function (opponent) return opponent.status == status end) end +---@deprecated -- function to check for forfeits ---@param opponents {status: string?}[] ---@return boolean @@ -812,6 +830,7 @@ function MatchGroupInputUtil.hasForfeit(opponents) return MatchGroupInputUtil._opponentWithStatus(opponents, MatchGroupInputUtil.STATUS.FORFEIT) ~= 0 end +---@deprecated -- function to check for DQ's ---@param opponents {status: string?}[] ---@return boolean @@ -819,6 +838,7 @@ function MatchGroupInputUtil.hasDisqualified(opponents) return MatchGroupInputUtil._opponentWithStatus(opponents, MatchGroupInputUtil.STATUS.DISQUALIFIED) ~= 0 end +---@deprecated -- function to check for W/L ---@param opponents {status: string?}[] ---@return boolean @@ -833,7 +853,7 @@ function MatchGroupInputUtil.hasScore(opponents) return MatchGroupInputUtil._opponentWithStatus(opponents, MatchGroupInputUtil.STATUS.SCORE) ~= 0 end --- Get the winner when resulttype=default +-- Get the winner when letter results (W/L etc) ---@param opponents {status: string?}[] ---@return integer function MatchGroupInputUtil.getDefaultWinner(opponents) @@ -848,12 +868,12 @@ end --- If Winner = 0, means it was a draw, return 1 --- If Winner = -1, means that mean no team won, returns 2 --- Otherwise return 2 ----@param resultType string? +---@param status string? ---@param winner integer? ---@param opponentIndex integer ---@return integer? -function MatchGroupInputUtil.placementFromWinner(resultType, winner, opponentIndex) - if resultType == MatchGroupInputUtil.RESULT_TYPE.NOT_PLAYED then +function MatchGroupInputUtil.placementFromWinner(status, winner, opponentIndex) + if status == MatchGroupInputUtil.RESULT_TYPE.NOT_PLAYED or status == MatchGroupInputUtil.MATCH_STATUS.NOT_PLAYED then return nil end if winner == 0 or winner == opponentIndex then @@ -1145,11 +1165,10 @@ function MatchGroupInputUtil.standardProcessMatch(match, Parser, mapProps) 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) + match.status = MatchGroupInputUtil.getMatchStatus(winnerInput, finishedInput) + match.winner = MatchGroupInputUtil.getWinner(match.status, winnerInput, opponents) Array.forEach(opponents, function(opponent, opponentIndex) - opponent.placement = MatchGroupInputUtil.placementFromWinner(match.resulttype, match.winner, opponentIndex) + opponent.placement = MatchGroupInputUtil.placementFromWinner(match.status, match.winner, opponentIndex) end) end diff --git a/components/match2/commons/match_group_util.lua b/components/match2/commons/match_group_util.lua index 39ffb965d7a..e64605f93f9 100644 --- a/components/match2/commons/match_group_util.lua +++ b/components/match2/commons/match_group_util.lua @@ -192,6 +192,8 @@ MatchGroupUtil.types.GameOpponent = TypeUtil.struct({ type = 'string', }) +---@alias MatchStatus 'notplayed'|''|nil +MatchGroupUtil.types.Status = TypeUtil.optional(TypeUtil.literalUnion('notplayed', '')) ---@alias ResultType 'default'|'draw'|'np' MatchGroupUtil.types.ResultType = TypeUtil.literalUnion('default', 'draw', 'np') ---@alias WalkoverType 'l'|'ff'|'dq' @@ -249,6 +251,7 @@ MatchGroupUtil.types.Game = TypeUtil.struct({ ---@field mode string? ---@field opponents standardOpponent[] ---@field resultType ResultType? +---@field status MatchStatus ---@field stream table ---@field tickername string? ---@field tournament string? @@ -272,6 +275,7 @@ MatchGroupUtil.types.Match = TypeUtil.struct({ mode = 'string', opponents = TypeUtil.array(MatchGroupUtil.types.Opponent), resultType = 'string?', + status = MatchGroupUtil.types.Status, stream = 'table', tickername = 'string?', tournament = 'string?', @@ -530,6 +534,7 @@ function MatchGroupUtil.matchFromRecord(record) parent = record.parent, patch = record.patch, resultType = nilIfEmpty(record.resulttype), + status = nilIfEmpty(record.status), stream = Json.parseIfString(record.stream) or {}, tickername = record.tickername, timestamp = tonumber(Table.extract(extradata, 'timestamp')),