Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(match2): support underlords #5187

Merged
merged 11 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 27 additions & 28 deletions components/match2/commons/match_group_input_util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1283,7 +1283,6 @@ function MatchGroupInputUtil.standardProcessFfaMatch(match, Parser, mapProps)
local finishedInput = match.finished --[[@as string?]]
local winnerInput = match.winner --[[@as string?]]


local dateProps = Parser.readDate and Parser.readDate(match)
or MatchGroupInputUtil.readDate(match.date, Parser.DATE_FALLBACKS)
Table.mergeInto(match, dateProps)
Expand All @@ -1299,7 +1298,7 @@ function MatchGroupInputUtil.standardProcessFfaMatch(match, Parser, mapProps)
local settings = Parser.parseSettings and Parser.parseSettings(match, #opponents)
or MatchGroupInputUtil.parseSettings(match, #opponents)

local games = Parser.extractMaps(match, opponents, settings.score)
local games = Parser.extractMaps(match, opponents, settings.placementInfo)

local autoScoreFunction = Parser.calculateMatchScore and Parser.calculateMatchScore(opponents, games) or nil
Array.forEach(opponents, function(opponent, opponentIndex)
Expand All @@ -1324,7 +1323,7 @@ function MatchGroupInputUtil.standardProcessFfaMatch(match, Parser, mapProps)
local placementOfOpponents = MatchGroupInputUtil.calculatePlacementOfOpponents(opponents)
Array.forEach(opponents, function(opponent, opponentIndex)
opponent.placement = placementOfOpponents[opponentIndex]
opponent.extradata.bg = settings.status[opponent.placement]
opponent.extradata.bg = ((settings.placementInfo or {})[opponent.placement] or {}).status
end)

match.winner = Parser.getMatchWinner and Parser.getMatchWinner(match.status, winnerInput, opponents)
Expand Down Expand Up @@ -1458,19 +1457,9 @@ function MatchGroupInputUtil.calculatePlacementOfOpponents(opponents)
end

---@param match table
---@return {score: table, status: table, settings: table}
---@return {placementInfo: table[], settings: table}
function MatchGroupInputUtil.parseSettings(match, opponentCount)
-- Score Settings
local scoreSettings = {
kill = Array.map(Array.range(1, opponentCount), function(index)
return tonumber(match['p' .. index .. '_kill']) or tonumber(match.p_kill) or 1
end),
placement = Array.map(Array.range(1, opponentCount), function(index)
return tonumber(match['p' .. index]) or 0
end)
}

-- Status colors (up/down etc)
-- Pre-parse Status colors (up/down etc)
local statusParsed = {}
Array.forEach(Array.parseCommaSeparatedString(match.bg, ','), function (status)
local placements, color = unpack(Array.parseCommaSeparatedString(status, '='))
Expand All @@ -1482,13 +1471,18 @@ function MatchGroupInputUtil.parseSettings(match, opponentCount)
end)
end)

local statusSettings = Array.map(Array.range(1, opponentCount), function(index)
return statusParsed[index] or ''
-- Info per Placement
local placementInfo = Array.map(Array.range(1, opponentCount), function(index)
return {
placement = index,
killPoints = tonumber(match['p' .. index .. '_kill']) or tonumber(match.p_kill),
placementPoints = tonumber(match['p' .. index]) or 0,
status = statusParsed[index],
}
end)

return {
score = scoreSettings,
status = statusSettings,
placementInfo = placementInfo,
settings = {
showGameDetails = Logic.nilOr(Logic.readBoolOrNil(match.showgamedetails), true),
matchPointThreshold = tonumber(match.matchpoint),
Expand All @@ -1497,9 +1491,9 @@ function MatchGroupInputUtil.parseSettings(match, opponentCount)
end

---@param scoreDataInput table?
---@param scoreSettings {kill: integer[], placement: integer[]}
---@param placementsInfo {killPoints: number, placement: integer, placementPoints: number}[]
---@return table
function MatchGroupInputUtil.makeBattleRoyaleMapOpponentDetails(scoreDataInput, scoreSettings)
function MatchGroupInputUtil.makeBattleRoyaleMapOpponentDetails(scoreDataInput, placementsInfo)
if not scoreDataInput then
return {}
end
Expand All @@ -1509,13 +1503,18 @@ function MatchGroupInputUtil.makeBattleRoyaleMapOpponentDetails(scoreDataInput,
local placement, kills = tonumber(scoreDataInput[1]), tonumber(scoreDataInput[2])
local manualPoints = tonumber(scoreDataInput.p)
if placement or kills then
local minimumKillPoints = Array.reduce(scoreSettings.kill, math.min, math.huge)
if placement then
scoreBreakdown.placePoints = scoreSettings.placement[placement] or 0
end
if kills then
scoreBreakdown.killPoints = kills * (scoreSettings.kill[placement] or minimumKillPoints)
scoreBreakdown.kills = kills
local minimumKillPoints = Array.reduce(
Array.map(placementsInfo, Operator.property('killPoints')),
math.min,
math.huge
)
local placementInfo = placementsInfo[placement] or {}
scoreBreakdown.placePoints = placementInfo.placementPoints or 0
scoreBreakdown.kills = kills

local pointsPerKill = placementInfo.killPoints or minimumKillPoints
if kills and pointsPerKill ~= math.huge then
scoreBreakdown.killPoints = scoreBreakdown.kills * pointsPerKill
end
scoreBreakdown.totalPoints = (scoreBreakdown.placePoints or 0) + (scoreBreakdown.killPoints or 0)
end
Expand Down
42 changes: 20 additions & 22 deletions components/match2/commons/match_summary_ffa.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

local Array = require('Module:Array')
local FnUtil = require('Module:FnUtil')
local Logic = require('Module:Logic')
local Lua = require('Module:Lua')
local Table = require('Module:Table')

Expand Down Expand Up @@ -45,8 +44,8 @@ local MATCH_OVERVIEW_COLUMNS = {
{
class = 'cell--status',
show = function(match)
return Table.any(match.extradata.status or {}, function(_, value)
return Logic.isNotEmpty(value)
return Table.any(match.extradata.placementinfo or {}, function(_, value)
return value.status ~= nil
end)
end,
header = {
Expand All @@ -57,11 +56,11 @@ local MATCH_OVERVIEW_COLUMNS = {
return 'bg-' .. (opponent.advanceBg or '')
end,
value = function (opponent, idx)
if not STATUS_ICONS[opponent.placementStatus] then
if not STATUS_ICONS[opponent.advanceBg] then
return
end
return IconWidget{
iconName = STATUS_ICONS[opponent.placementStatus],
iconName = STATUS_ICONS[opponent.advanceBg],
}
end,
},
Expand Down Expand Up @@ -192,7 +191,12 @@ local GAME_OVERVIEW_COLUMNS = {
},
{
show = function(match)
return match.extradata.settings.showGameDetails
if match.extradata.settings.showGameDetails == false then
return false
end
return Table.any(match.extradata.placementinfo or {}, function(_, value)
return value.killPoints ~= nil
end)
end,
class = 'panel-table__cell__game-kills',
icon = 'kills',
Expand Down Expand Up @@ -361,26 +365,26 @@ end
---@param match table
---@return {kill: number, placement: {rangeStart: integer, rangeEnd: integer, score:number}[]}
function MatchSummaryFfa.createScoringData(match)
local scoreSettings = match.extradata.scoring

local scores = Array.map(scoreSettings.placement or {}, function(placementScore, placement)
return {placementPoints = placementScore, killPoints = (scoreSettings.kill or {})[placement]}
end)
local scoreSettings = match.extradata.placementinfo

local newScores = {}
local lastData = {}
for placement, score in ipairs(scores) do
if Table.deepEquals(lastData, score) then
for placement, placementData in ipairs(scoreSettings or {}) do
local currentData = {
killPoints = placementData.killPoints,
placementPoints = placementData.placementPoints,
}
if Table.deepEquals(lastData, currentData) then
newScores[#newScores].rangeEnd = newScores[#newScores].rangeEnd + 1
else
table.insert(newScores, {
rangeStart = placement,
rangeEnd = placement,
killScore = score.killPoints,
placementScore = score.placementPoints,
killScore = currentData.killPoints,
placementScore = currentData.placementPoints,
})
end
lastData = score
lastData = currentData
end
return newScores
end
Expand Down Expand Up @@ -565,12 +569,6 @@ function MatchSummaryFfa.updateMatchOpponents(match)

-- Sort match level based on final placement & score
Array.sortInPlaceBy(match.opponents, FnUtil.identity, MatchSummaryFfa.placementSortFunction)

-- Set the status of the current placement
Array.forEach(match.opponents, function(opponent, idx)
opponent.placementStatus = match.extradata.status[idx]
end)

end

return MatchSummaryFfa
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,7 @@ end
---@param match table
---@return table
function MatchFunctions.parseSettings(match)
return {
status = {},
scores = {},
}
return {}
end

---@param opponent table
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ end
---@return table
function MatchFunctions.getExtraData(match, games, opponents, settings)
return {
scoring = settings.score,
status = settings.status,
placementinfo = settings.placementInfo,
settings = settings.settings,
}
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ end
---@return table
function MatchFunctions.getExtraData(match, games, opponents, settings)
return {
scoring = settings.score,
status = settings.status,
placementinfo = settings.placementInfo,
settings = settings.settings,
}
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ end
---@return table
function MatchFunctions.getExtraData(match, games, opponents, settings)
return {
scoring = settings.score,
status = settings.status,
placementinfo = settings.placementInfo,
settings = settings.settings,
}
end
Expand Down
3 changes: 1 addition & 2 deletions components/match2/wikis/naraka/match_group_input_custom.lua
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ end
---@return table
function MatchFunctions.getExtraData(match, games, opponents, settings)
return {
scoring = settings.score,
status = settings.status,
placementinfo = settings.placementInfo,
settings = settings.settings,
}
end
Expand Down
3 changes: 1 addition & 2 deletions components/match2/wikis/pubg/match_group_input_custom.lua
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ end
---@return table
function MatchFunctions.getExtraData(match, games, opponents, settings)
return {
scoring = settings.score,
status = settings.status,
placementinfo = settings.placementInfo,
settings = settings.settings,
}
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ end
---@return table
function MatchFunctions.getExtraData(match, games, opponents, settings)
return {
scoring = settings.score,
status = settings.status,
placementinfo = settings.placementInfo,
settings = settings.settings,
}
end
Expand Down
89 changes: 89 additions & 0 deletions components/match2/wikis/underlords/game_summary.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
-- @Liquipedia
-- wiki=underlords
-- page=Module:GameSummary
--
-- Please see https://github.com/Liquipedia/Lua-Modules to contribute
--

local CustomGameSummary = {}

local Array = require('Module:Array')
local FnUtil = require('Module:FnUtil')
local Lua = require('Module:Lua')
local Page = require('Module:Page')
local Table = require('Module:Table')

local MatchGroupUtil = Lua.import('Module:MatchGroup/Util')

local SummaryHelper = Lua.import('Module:MatchSummary/Ffa')
local MatchSummaryWidgets = Lua.import('Module:Widget/Match/Summary/Ffa/All')
local HtmlWidgets = Lua.import('Module:Widget/Html/All')
local IconWidget = Lua.import('Module:Widget/Image/Icon/Fontawesome')

---@class UnderlordsMatchGroupUtilGame: MatchGroupUtilGame
---@field stream table

---@param props {bracketId: string, matchId: string, gameIdx: integer}
---@return Html
function CustomGameSummary.getGameByMatchId(props)
---@class ApexMatchGroupUtilMatch
local match = MatchGroupUtil.fetchMatchForBracketDisplay(props.bracketId, props.matchId)

local game = match.games[props.gameIdx]
assert(game, 'Error Game ID ' .. tostring(props.gameIdx) .. ' not found')

game.stream = match.stream

CustomGameSummary._opponents(game, match.opponents)
local scoringData = SummaryHelper.createScoringData(match)

return MatchSummaryWidgets.Tab{
matchId = match.matchId,
idx = props.gameIdx,
children = {
CustomGameSummary._createGameDetails(game),
MatchSummaryWidgets.PointsDistribution{scores = scoringData},
SummaryHelper.standardGame(game)
}
}
end

---@param game table
---@return Widget
function CustomGameSummary._createGameDetails(game)
return MatchSummaryWidgets.ContentItemContainer{contentClass = 'panel-content__game-schedule',
items = {
{
icon = MatchSummaryWidgets.CountdownIcon{game = game},
content = MatchSummaryWidgets.GameCountdown{game = game},
},
game.map and {
icon = IconWidget{iconName = 'map'},
content = HtmlWidgets.Span{children = Page.makeInternalLink(game.map)},
} or nil,
}
}
end

---@param game table
---@param matchOpponents table[]
function CustomGameSummary._opponents(game, matchOpponents)
-- Add match opponent data to game opponent
game.opponents = Array.map(game.opponents,
function(gameOpponent, opponentIdx)
local matchOpponent = matchOpponents[opponentIdx]
local newGameOpponent = Table.merge(matchOpponent, gameOpponent)
-- These values are only allowed to come from Game and not Match
newGameOpponent.placement = gameOpponent.placement
newGameOpponent.score = gameOpponent.score
newGameOpponent.status = gameOpponent.status
return newGameOpponent
end
)

-- Sort game level based on placement
Array.sortInPlaceBy(game.opponents, FnUtil.identity, SummaryHelper.placementSortFunction)
end

return CustomGameSummary
Loading
Loading