From dd718dccd1f921466c44a15df379b0414a15ff2f Mon Sep 17 00:00:00 2001 From: Rikard Blixt Date: Thu, 28 Nov 2024 13:04:50 +0100 Subject: [PATCH] feat(match2): support for pubg (#5149) --- .../match2/wikis/pubg/brkts_wiki_specific.lua | 24 ++ components/match2/wikis/pubg/game_summary.lua | 254 ++++++++++++ .../pubg/get_match_group_copy_paste_wiki.lua | 68 ++++ .../wikis/pubg/match_group_input_custom.lua | 168 ++++++++ components/match2/wikis/pubg/match_legacy.lua | 44 +++ .../match2/wikis/pubg/match_summary.lua | 360 ++++++++++++++++++ .../wikis/pubgmobile/brkts_wiki_specific.lua | 2 +- standard/info/wikis/pubg/info.lua | 2 +- standard/info/wikis/pubgmobile/info.lua | 2 +- 9 files changed, 921 insertions(+), 3 deletions(-) create mode 100644 components/match2/wikis/pubg/brkts_wiki_specific.lua create mode 100644 components/match2/wikis/pubg/game_summary.lua create mode 100644 components/match2/wikis/pubg/get_match_group_copy_paste_wiki.lua create mode 100644 components/match2/wikis/pubg/match_group_input_custom.lua create mode 100644 components/match2/wikis/pubg/match_legacy.lua create mode 100644 components/match2/wikis/pubg/match_summary.lua diff --git a/components/match2/wikis/pubg/brkts_wiki_specific.lua b/components/match2/wikis/pubg/brkts_wiki_specific.lua new file mode 100644 index 00000000000..ffb991d3538 --- /dev/null +++ b/components/match2/wikis/pubg/brkts_wiki_specific.lua @@ -0,0 +1,24 @@ +--- +-- @Liquipedia +-- wiki=pubg +-- page=Module:Brkts/WikiSpecific +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local Lua = require('Module:Lua') +local Table = require('Module:Table') + +local BaseWikiSpecific = Lua.import('Module:Brkts/WikiSpecific/Base') + +---@class PubgBrktsWikiSpecific: BrktsWikiSpecific +local WikiSpecific = Table.copy(BaseWikiSpecific) + +---@param matchGroupType string +---@return function +function WikiSpecific.getMatchGroupContainer(matchGroupType) + local Horizontallist = Lua.import('Module:MatchGroup/Display/Horizontallist') + return Horizontallist.BracketContainer +end + +return WikiSpecific diff --git a/components/match2/wikis/pubg/game_summary.lua b/components/match2/wikis/pubg/game_summary.lua new file mode 100644 index 00000000000..c4094293d00 --- /dev/null +++ b/components/match2/wikis/pubg/game_summary.lua @@ -0,0 +1,254 @@ +--- +-- @Liquipedia +-- wiki=pubg +-- 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 OpponentLibraries = require('Module:OpponentLibraries') +local OpponentDisplay = OpponentLibraries.OpponentDisplay + +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 PubgMatchGroupUtilGame: MatchGroupUtilGame +---@field stream table + +local GAME_STANDINGS_COLUMNS = { + { + sortable = true, + sortType = 'rank', + class = 'cell--rank', + icon = 'rank', + header = { + value = 'Rank', + }, + sortVal = { + value = function (opponent, idx) + if opponent.placement == -1 or opponent.status ~= 'S' then + return idx + end + return opponent.placement + end, + }, + row = { + value = function (opponent, idx) + local place = opponent.placement ~= -1 and opponent.placement or idx + local placementDisplay + if opponent.status and opponent.status ~= 'S' then + placementDisplay = '-' + else + placementDisplay = tostring(MatchSummaryWidgets.RankRange{rankStart = place}) + end + return HtmlWidgets.Fragment{children = { + MatchSummaryWidgets.Trophy{place = place, additionalClasses = {'panel-table__cell-icon'}}, + HtmlWidgets.Span{children = placementDisplay}, + }} + end, + }, + }, + { + sortable = true, + sortType = 'team', + class = 'cell--team', + icon = 'team', + header = { + value = 'Team', + }, + sortVal = { + value = function (opponent, idx) + return opponent.name + end, + }, + row = { + value = function (opponent, idx) + return OpponentDisplay.BlockOpponent{ + opponent = opponent, + showLink = true, + overflow = 'ellipsis', + teamStyle = 'hybrid', + } + end, + }, + }, + { + sortable = true, + sortType = 'total-points', + class = 'cell--total-points', + icon = 'points', + header = { + value = 'Total Points', + mobileValue = 'Pts.', + }, + sortVal = { + value = function (opponent, idx) + return opponent.score + end, + }, + row = { + value = function (opponent, idx) + return opponent.score + end, + }, + }, + { + sortable = true, + sortType = 'placements', + class = 'cell--placements', + icon = 'placement', + header = { + value = 'Placement Points', + }, + sortVal = { + value = function (opponent, idx) + return opponent.scoreBreakdown.placePoints + end, + }, + row = { + value = function (opponent, idx) + return opponent.scoreBreakdown.placePoints + end, + }, + }, + { + sortable = true, + sortType = 'kills', + class = 'cell--kills', + icon = 'kills', + header = { + value = 'Kill Points', + }, + sortVal = { + value = function (opponent, idx) + return opponent.scoreBreakdown.killPoints + end, + }, + row = { + value = function (opponent, idx) + return opponent.scoreBreakdown.killPoints + end, + }, + }, +} +---@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(match) + local scoringData = SummaryHelper.createScoringData(match) + + return MatchSummaryWidgets.Tab{ + matchId = match.matchId, + idx = props.gameIdx, + children = { + CustomGameSummary._createGameDetails(game), + MatchSummaryWidgets.PointsDistribution{killScore = scoringData.kill, placementScore = scoringData.placement}, + CustomGameSummary._createGameStandings(game) + } + } +end + +---@param game table +---@return Widget +function CustomGameSummary._createGameDetails(game) + return MatchSummaryWidgets.ContentItemContainer{children = { + HtmlWidgets.Ul{ + classes = {'panel-content__game-schedule'}, + children = { + HtmlWidgets.Li{children = + HtmlWidgets.Div{ + classes = {'panel-content__game-schedule__container'}, + children = { + MatchSummaryWidgets.CountdownIcon{game = game, additionalClasses = {'panel-content__game-schedule__icon'}}, + SummaryHelper.gameCountdown(game), + }, + }, + }, + game.map and HtmlWidgets.Li{children = { + IconWidget{iconName = 'map', additionalClasses = {'panel-content__game-schedule__icon'}}, + HtmlWidgets.Span{children = Page.makeInternalLink(game.map)}, + }}} or nil, + } + } + } +end + +---@param game table +---@return Html +function CustomGameSummary._createGameStandings(game) + local rows = Array.map(game.opponents, function (opponent, index) + local children = Array.map(GAME_STANDINGS_COLUMNS, function(column) + if column.show and not column.show(game) then + return + end + return MatchSummaryWidgets.TableRowCell{ + class = column.class, + sortable = column.sortable, + sortType = column.sortType, + sortValue = column.sortVal and column.sortVal.value(opponent, index) or nil, + value = column.row.value(opponent, index), + } + end) + return MatchSummaryWidgets.TableRow{children = children} + end) + + return MatchSummaryWidgets.Table{children = { + MatchSummaryWidgets.TableHeader{children = Array.map(GAME_STANDINGS_COLUMNS, function(column) + if column.show and not column.show(game) then + return + end + return MatchSummaryWidgets.TableHeaderCell{ + class = column.class, + icon = column.icon, + mobileValue = column.header.mobileValue, + sortable = column.sortable, + sortType = column.sortType, + value = column.header.value, + } + end)}, + unpack(rows) + }} +end + +function CustomGameSummary._opponents(match) + -- Add match opponent data to game opponent + Array.forEach(match.games, function (game) + game.opponents = Array.map(game.opponents, + function(gameOpponent, opponentIdx) + local matchOpponent = match.opponents[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 + ) + end) + + -- Sort game level based on placement + Array.forEach(match.games, function (game) + Array.sortInPlaceBy(game.opponents, FnUtil.identity, SummaryHelper.placementSortFunction) + end) +end + +return CustomGameSummary diff --git a/components/match2/wikis/pubg/get_match_group_copy_paste_wiki.lua b/components/match2/wikis/pubg/get_match_group_copy_paste_wiki.lua new file mode 100644 index 00000000000..769c8110ca4 --- /dev/null +++ b/components/match2/wikis/pubg/get_match_group_copy_paste_wiki.lua @@ -0,0 +1,68 @@ +--- +-- @Liquipedia +-- wiki=pubg +-- 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 Lua = require('Module:Lua') + +local OpponentLibraries = require('Module:OpponentLibraries') +local Opponent = OpponentLibraries.Opponent + +local BaseCopyPaste = Lua.import('Module:GetMatchGroupCopyPaste/wiki/Base') + +---WikiSpecific Code for MatchList and Bracket Code Generators +---@class PubgMatchCopyPaste: 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 lines = Array.extend( + '{{Match|finished=', + INDENT .. '|p_kill=1 |p1=10 |p2=6 |p3=5 |p4=4 |p5=3 |p6=2 |p7=1 |p8=1', + {INDENT .. '|twitch=|youtube='}, + Array.map(Array.range(1, bestof), function(mapIndex) + return INDENT .. '|map' .. mapIndex .. '={{Map|date=|finished=|map=|vod=}}' + end), + Array.map(Array.range(1, opponents), function(opponentIndex) + return INDENT .. '|opponent' .. opponentIndex .. '=' .. WikiCopyPaste._getOpponent(mode, bestof) + end), + '}}' + ) + + return table.concat(lines, '\n') +end + +--subfunction used to generate the code for the Opponent template, depending on the type of opponent +---@param mode string +---@param mapCount integer +---@return string +function WikiCopyPaste._getOpponent(mode, mapCount) + local mapScores = table.concat(Array.map(Array.range(1, mapCount), function(idx) + return '|m' .. idx .. '={{MS||}}' + end)) + + if mode == Opponent.solo then + return '{{SoloOpponent||flag=' .. mapScores .. '}}' + elseif mode == Opponent.team then + return '{{TeamOpponent|' .. mapScores .. '}}' + elseif mode == Opponent.literal then + return '{{Literal|' .. mapScores .. '}}' + end + + return '' +end + +return WikiCopyPaste diff --git a/components/match2/wikis/pubg/match_group_input_custom.lua b/components/match2/wikis/pubg/match_group_input_custom.lua new file mode 100644 index 00000000000..aad9da970b9 --- /dev/null +++ b/components/match2/wikis/pubg/match_group_input_custom.lua @@ -0,0 +1,168 @@ +--- +-- @Liquipedia +-- wiki=pubg +-- page=Module:MatchGroup/Input/Custom +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local Array = require('Module:Array') +local Json = require('Module:Json') +local Lua = require('Module:Lua') +local Operator = require('Module:Operator') +local Table = require('Module:Table') + +local MatchGroupInputUtil = Lua.import('Module:MatchGroup/Input/Util') + +local MapFunctions = {} +local MatchFunctions = { + OPPONENT_CONFIG = { + resolveRedirect = true, + applyUnderScores = true, + maxNumPlayers = 3, + }, + DEFAULT_MODE = 'team' +} + +local CustomMatchGroupInput = {} + +---@param match table +---@param options table? +---@return table +function CustomMatchGroupInput.processMatch(match, options) + return MatchGroupInputUtil.standardProcessFfaMatch(match, MatchFunctions) +end + +-- +-- match related functions +-- +---@param match table +---@param opponents table[] +---@param scoreSettings table +---@return table[] +function MatchFunctions.extractMaps(match, opponents, scoreSettings) + local maps = {} + for key, map, mapIndex in Table.iter.pairsByPrefix(match, 'map', {requireIndex = true}) do + local finishedInput = map.finished --[[@as string?]] + local winnerInput = map.winner --[[@as string?]] + + Table.mergeInto(map, MatchGroupInputUtil.readDate(map.date)) + map.finished = MatchGroupInputUtil.mapIsFinished(map) + + map.opponents = Array.map(opponents, function(matchOpponent) + local opponentMapInput = Json.parseIfString(matchOpponent['m' .. mapIndex]) + return MapFunctions.makeMapOpponentDetails(opponentMapInput, scoreSettings) + end) + + map.scores = Array.map(map.opponents, Operator.property('score')) + if map.finished then + map.status = MatchGroupInputUtil.getMatchStatus(winnerInput, finishedInput) + map.winner = MatchGroupInputUtil.getWinner(map.status, winnerInput, map.opponents) + end + + map.extradata = MapFunctions.getExtraData(map) + + table.insert(maps, map) + match[key] = nil + end + + return maps +end + +---@param opponents table[] +---@param maps table[] +---@return fun(opponentIndex: integer): integer? +function MatchFunctions.calculateMatchScore(opponents, maps) + return function(opponentIndex) + return Array.reduce(Array.map(maps, function(map) + return map.scores[opponentIndex] or 0 + end), Operator.add, 0) + end +end + +---@param match table +---@return {score: table, status: table} +function MatchFunctions.parseSettings(match) + -- Score Settings + local scoreSettings = { + kill = tonumber(match.p_kill) or 1, + placement = Array.mapIndexes(function(idx) + return match['opponent' .. idx] and (tonumber(match['p' .. idx]) or 0) or nil + end) + } + + -- Up/Down colors + local statusSettings = Array.flatMap(Array.parseCommaSeparatedString(match.bg, ','), function (status) + local placements, color = unpack(Array.parseCommaSeparatedString(status, '=')) + local pStart, pEnd = unpack(Array.parseCommaSeparatedString(placements, '-')) + local pStartNumber = tonumber(pStart) --[[@as integer]] + local pEndNumber = tonumber(pEnd) or pStartNumber + return Array.map(Array.range(pStartNumber, pEndNumber), function() + return color + end) + end) + + return { + score = scoreSettings, + status = statusSettings, + } +end + +---@param match table +---@param games table[] +---@param opponents table[] +---@param settings table +---@return table +function MatchFunctions.getExtraData(match, games, opponents, settings) + return { + scoring = settings.score, + status = settings.status, + } +end + +-- +-- map related functions +-- + +---@param map table +---@return table +function MapFunctions.getExtraData(map) + return { + dateexact = map.dateexact, + comment = map.comment, + } +end + +---@param scoreDataInput table? +---@param scoreSettings table +---@return table +function MapFunctions.makeMapOpponentDetails(scoreDataInput, scoreSettings) + if not scoreDataInput then + return {} + end + + local scoreBreakdown = {} + + local placement, kills = tonumber(scoreDataInput[1]), tonumber(scoreDataInput[2]) + if placement and kills then + scoreBreakdown.placePoints = scoreSettings.placement[placement] or 0 + scoreBreakdown.killPoints = kills * scoreSettings.kill + scoreBreakdown.kills = kills + scoreBreakdown.totalPoints = scoreBreakdown.placePoints + scoreBreakdown.killPoints + end + local opponent = { + status = MatchGroupInputUtil.STATUS.SCORE, + scoreBreakdown = scoreBreakdown, + placement = placement, + score = scoreBreakdown.totalPoints, + } + + if scoreDataInput[1] == '-' then + opponent.status = MatchGroupInputUtil.STATUS.FORFEIT + opponent.score = 0 + end + + return opponent +end + +return CustomMatchGroupInput diff --git a/components/match2/wikis/pubg/match_legacy.lua b/components/match2/wikis/pubg/match_legacy.lua new file mode 100644 index 00000000000..9aeedcb101f --- /dev/null +++ b/components/match2/wikis/pubg/match_legacy.lua @@ -0,0 +1,44 @@ +--- +-- @Liquipedia +-- wiki=pubg +-- page=Module:Match/Legacy +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local MatchLegacy = {} + +local DisplayHelper = require('Module:MatchGroup/Display/Helper') +local Json = require('Module:Json') +local String = require('Module:StringUtils') +local Table = require('Module:Table') + + +function MatchLegacy.storeMatch(match2) + for gameIndex, game2 in ipairs(match2.match2games or {}) do + local match = Table.deepCopy(match2) + local g2extradata = Json.parseIfString(game2.extradata) or {} + + match.date = game2.date + match.vod = game2.vod + match.dateexact = g2extradata.dateexact + match.finished = String.isNotEmpty(game2.winner) + match.staticid = match2.match2id .. '_' .. gameIndex + + -- Handle extradata fields + local bracketData = Json.parseIfString(match2.match2bracketdata) + if type(bracketData) == 'table' and bracketData.inheritedheader then + match.header = (DisplayHelper.expandHeader(bracketData.inheritedheader) or {})[1] + end + local m1extradata = {} + + m1extradata.map = game2.map + m1extradata.round = tostring(gameIndex) + + match.extradata = mw.ext.LiquipediaDB.lpdb_create_json(m1extradata) + + mw.ext.LiquipediaDB.lpdb_match('legacymatch_' .. match2.match2id .. '_' .. gameIndex, match) + end +end + +return MatchLegacy diff --git a/components/match2/wikis/pubg/match_summary.lua b/components/match2/wikis/pubg/match_summary.lua new file mode 100644 index 00000000000..096ffd682d5 --- /dev/null +++ b/components/match2/wikis/pubg/match_summary.lua @@ -0,0 +1,360 @@ +--- +-- @Liquipedia +-- wiki=pubg +-- page=Module:MatchSummary +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local CustomMatchSummary = {} + +local Array = require('Module:Array') +local FnUtil = require('Module:FnUtil') +local Lua = require('Module:Lua') +local Table = require('Module:Table') + +local MatchGroupUtil = Lua.import('Module:MatchGroup/Util') +local SummaryHelper = Lua.import('Module:MatchSummary/Ffa') +local OpponentLibraries = require('Module:OpponentLibraries') +local OpponentDisplay = OpponentLibraries.OpponentDisplay + +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 PungMatchGroupUtilMatch: MatchGroupUtilMatch +---@field games ApexMatchGroupUtilGame[] + +local PLACEMENT_BG = { + 'cell--gold', + 'cell--silver', + 'cell--bronze', + 'cell--copper', +} + +local STATUS_ICONS = { + -- Normal Status + up = 'standings_up', + stayup = 'standings_stayup', + stay = 'standings_stay', + staydown = 'standings_staydown', + down = 'standings_down', +} + +local OVERVIEW_COLUMNS = { + { + class = 'cell--status', + show = function(match) + return Table.isNotEmpty(match.extradata.status) + end, + header = { + value = '', + }, + row = { + class = function (opponent) + return 'bg-' .. (opponent.advanceBg or '') + end, + value = function (opponent, idx) + if not STATUS_ICONS[opponent.placementStatus] then + return + end + return IconWidget{ + iconName = STATUS_ICONS[opponent.placementStatus], + } + end, + }, + }, + { + sortable = true, + sortType = 'rank', + class = 'cell--rank', + icon = 'rank', + header = { + value = 'Rank', + }, + sortVal = { + value = function (opponent, idx) + return opponent.placement ~= -1 and opponent.placement or idx + end, + }, + row = { + value = function (opponent, idx) + local place = opponent.placement ~= -1 and opponent.placement or idx + local placementDisplay = tostring(MatchSummaryWidgets.RankRange{rankStart = place}) + return HtmlWidgets.Fragment{children = { + MatchSummaryWidgets.Trophy{place = place, additionalClasses = {'panel-table__cell-icon'}}, + HtmlWidgets.Span{children = placementDisplay}, + }} + end, + }, + }, + { + sortable = true, + sortType = 'team', + class = 'cell--team', + icon = 'team', + header = { + value = 'Team', + }, + sortVal = { + value = function (opponent, idx) + return opponent.name + end, + }, + row = { + value = function (opponent, idx) + return OpponentDisplay.BlockOpponent{ + opponent = opponent, + showLink = true, + overflow = 'ellipsis', + teamStyle = 'hybrid', + } + end, + }, + }, + { + sortable = true, + sortType = 'total-points', + class = 'cell--total-points', + icon = 'points', + header = { + value = 'Total Points', + mobileValue = 'Pts.', + }, + sortVal = { + value = function (opponent, idx) + return OpponentDisplay.InlineScore(opponent) + end, + }, + row = { + value = function (opponent, idx) + return OpponentDisplay.InlineScore(opponent) + end, + }, + }, +} +local GAME_COLUMNS = { + { + class = 'panel-table__cell__game-placement', + icon = 'placement', + header = { + value = 'P', + }, + row = { + class = function (opponent) + return PLACEMENT_BG[opponent.placement] + end, + value = function (opponent) + local placementDisplay + if opponent.status and opponent.status ~= 'S' then + placementDisplay = '-' + else + placementDisplay = tostring(MatchSummaryWidgets.RankRange{rankStart = opponent.placement}) + end + return HtmlWidgets.Fragment{children = { + MatchSummaryWidgets.Trophy{place = opponent.placement, additionalClasses = {'panel-table__cell-icon'}}, + HtmlWidgets.Span{ + classes = {'panel-table__cell-game__text'}, + children = placementDisplay, + } + }} + end, + }, + }, + { + class = 'panel-table__cell__game-kills', + icon = 'kills', + header = { + value = 'K', + }, + row = { + value = function (opponent) + return opponent.scoreBreakdown.kills + end, + }, + }, +} + +---@param props {bracketId: string, matchId: string} +---@return Widget +function CustomMatchSummary.getByMatchId(props) + ---@class ApexMatchGroupUtilMatch + local match = MatchGroupUtil.fetchMatchForBracketDisplay(props.bracketId, props.matchId) + CustomMatchSummary._opponents(match) + local scoringData = SummaryHelper.createScoringData(match) + + return HtmlWidgets.Fragment{children = { + MatchSummaryWidgets.Header{matchId = match.matchId, games = match.games}, + MatchSummaryWidgets.Tab{ + matchId = match.matchId, + idx = 0, + children = { + CustomMatchSummary._createSchedule(match), + MatchSummaryWidgets.PointsDistribution{killScore = scoringData.kill, placementScore = scoringData.placement}, + CustomMatchSummary._createMatchStandings(match) + } + } + }} +end + +function CustomMatchSummary._opponents(match) + -- Add games opponent data to the match opponent + Array.forEach(match.opponents, function (opponent, idx) + opponent.games = Array.map(match.games, function (game) + return game.opponents[idx] + end) + end) + + -- Sort match level based on final placement & score + Array.sortInPlaceBy(match.opponents, FnUtil.identity, SummaryHelper.placementSortFunction) + + -- Set the status of the current placement + Array.forEach(match.opponents, function(opponent, idx) + opponent.placementStatus = match.extradata.status[idx] + end) +end + +---@param match table +---@return Widget +function CustomMatchSummary._createSchedule(match) + return MatchSummaryWidgets.ContentItemContainer{collapsed = true, collapsible = true, title = 'Schedule', children = { + HtmlWidgets.Ul{ + classes = {'panel-content__game-schedule'}, + children = Array.map(match.games, function (game, idx) + return HtmlWidgets.Li{ + children = { + HtmlWidgets.Span{ + children = MatchSummaryWidgets.CountdownIcon{ + game = game, + additionalClasses = {'panel-content__game-schedule__icon'} + }, + }, + HtmlWidgets.Span{ + classes = {'panel-content__game-schedule__title'}, + children = 'Game ' .. idx .. ':', + }, + HtmlWidgets.Div{ + classes = {'panel-content__game-schedule__container'}, + children = SummaryHelper.gameCountdown(game), + }, + }, + } + end) + } + }} +end + +---@param match table +---@return Html +function CustomMatchSummary._createMatchStandings(match) + local rows = Array.map(match.opponents, function (opponent, index) + local children = Array.map(OVERVIEW_COLUMNS, function(column) + if column.show and not column.show(match) then + return + end + return MatchSummaryWidgets.TableRowCell{ + class = (column.class or '') .. ' ' .. (column.row.class and column.row.class(opponent) or ''), + sortable = column.sortable, + sortType = column.sortType, + sortValue = column.sortVal and column.sortVal.value(opponent, index) or nil, + value = column.row.value(opponent, index), + } + end) + + local gameRowContainer = HtmlWidgets.Div{ + classes = {'panel-table__cell', 'cell--game-container'}, + attributes = { + ['data-js-battle-royale'] = 'game-container' + }, + children = Array.map(opponent.games, function(gameOpponent) + local gameRow = HtmlWidgets.Div{ + classes = {'panel-table__cell', 'cell--game'}, + children = Array.map(GAME_COLUMNS, function(column) + if column.show and not column.show(match) then + return + end + return MatchSummaryWidgets.TableRowCell{ + class = (column.class or '') .. ' ' .. (column.row.class and column.row.class(gameOpponent) or ''), + value = column.row.value(gameOpponent), + } + end) + } + return gameRow + end) + } + table.insert(children, gameRowContainer) + return MatchSummaryWidgets.TableRow{children = children} + end) + + local cells = Array.map(OVERVIEW_COLUMNS, function(column) + if column.show and not column.show(match) then + return + end + return MatchSummaryWidgets.TableHeaderCell{ + class = column.class, + icon = column.icon, + mobileValue = column.header.mobileValue, + show = column.show, + sortable = column.sortable, + sortType = column.sortType, + value = column.header.value, + } + end) + + table.insert(cells, HtmlWidgets.Div{ + classes = {'panel-table__cell', 'cell--game-container-nav-holder'}, + attributes = { + ['data-js-battle-royale'] = 'game-nav-holder' + }, + children = { + HtmlWidgets.Div{ + classes = {'panel-table__cell', 'cell--game-container'}, + attributes = { + ['data-js-battle-royale'] = 'game-container' + }, + children = Array.map(match.games, function(game, idx) + return HtmlWidgets.Div{ + classes = {'panel-table__cell', 'cell--game'}, + children = { + HtmlWidgets.Div{ + classes = {'panel-table__cell__game-head'}, + children = { + HtmlWidgets.Div{ + classes = {'panel-table__cell__game-title'}, + children = { + MatchSummaryWidgets.CountdownIcon{game = game, additionalClasses = {'panel-table__cell-icon'}}, + HtmlWidgets.Span{ + classes = {'panel-table__cell-text'}, + children = 'Game ' .. idx + } + } + }, + SummaryHelper.gameCountdown(game), + } + }, + HtmlWidgets.Div{ + classes = {'panel-table__cell__game-details'}, + children = Array.map(GAME_COLUMNS, function(column) + return MatchSummaryWidgets.TableHeaderCell{ + class = column.class, + icon = column.icon, + mobileValue = column.header.mobileValue, + show = column.show, + value = column.header.value, + } + end) + } + } + } + end) + } + } + }) + + return MatchSummaryWidgets.Table{children = { + MatchSummaryWidgets.TableHeader{children = cells}, + unpack(rows) + }} +end + +return CustomMatchSummary diff --git a/components/match2/wikis/pubgmobile/brkts_wiki_specific.lua b/components/match2/wikis/pubgmobile/brkts_wiki_specific.lua index de4c7887eb0..7ee89b54b48 100644 --- a/components/match2/wikis/pubgmobile/brkts_wiki_specific.lua +++ b/components/match2/wikis/pubgmobile/brkts_wiki_specific.lua @@ -11,7 +11,7 @@ local Table = require('Module:Table') local BaseWikiSpecific = Lua.import('Module:Brkts/WikiSpecific/Base') ----@class PubgmobileBrktsWikiSpecific: BrktsWikiSpecific +---@class PubgmBrktsWikiSpecific: BrktsWikiSpecific local WikiSpecific = Table.copy(BaseWikiSpecific) ---@param matchGroupType string diff --git a/standard/info/wikis/pubg/info.lua b/standard/info/wikis/pubg/info.lua index 93a6ce1a4ab..a9fcdc02a28 100644 --- a/standard/info/wikis/pubg/info.lua +++ b/standard/info/wikis/pubg/info.lua @@ -33,7 +33,7 @@ return { allowManual = true, }, match2 = { - status = 0, + status = 1, }, }, defaultRoundPrecision = 0, diff --git a/standard/info/wikis/pubgmobile/info.lua b/standard/info/wikis/pubgmobile/info.lua index 6ac2398645b..6fbdec6feda 100644 --- a/standard/info/wikis/pubgmobile/info.lua +++ b/standard/info/wikis/pubgmobile/info.lua @@ -72,7 +72,7 @@ return { allowManual = true, }, match2 = { - status = 0, + status = 1, }, transfers = { showTeamName = true,