diff --git a/components/match2/wikis/brawlstars/legacy/match_group_legacy_default.lua b/components/match2/wikis/brawlstars/legacy/match_group_legacy_default.lua new file mode 100644 index 00000000000..aaf3769bdca --- /dev/null +++ b/components/match2/wikis/brawlstars/legacy/match_group_legacy_default.lua @@ -0,0 +1,196 @@ +--- +-- @Liquipedia +-- wiki=brawlstars +-- page=Module:MatchGroup/Legacy/Default +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local MatchGroupLegacyDefault = {} + +local String = require('Module:StringUtils') +local Logic = require('Module:Logic') + +local MAX_NUMBER_OF_OPPONENTS = 2 +local MAX_NUM_MAPS = 9 + +local roundData +---@param templateid string +---@param bracketType string +---@return table +function MatchGroupLegacyDefault.get(templateid, bracketType) + local lowerHeader = {} + local matches = mw.ext.Brackets.getCommonsBracketTemplate(templateid) + + assert(type(matches) == 'table') + local bracketData = {} + roundData = roundData or {} + local lastRound = 0 + for _, match in ipairs(matches) do + bracketData, lastRound, lowerHeader = MatchGroupLegacyDefault._getMatchMapping(match, bracketData, + bracketType, lowerHeader) + end + + for round = 1, lastRound do + bracketData['R' .. round .. 'M1header'] = 'R' .. round + if lowerHeader[round] then + bracketData['R' .. round .. 'M' .. lowerHeader[round] .. 'header'] = 'L' .. round + end + end + + -- add reference for map mappings + bracketData['$$map'] = { + ['$notEmpty$'] = 'map$1$', + map = 'map$1$', + winner = 'map$1$winner', + maptype = 'map$1$maptype', + score1 = 'map$1$score1', + score2 = 'map$1$score2' + } + + return bracketData +end + +---@param prefix string +---@param scoreKey string +---@param bracketType string +---@return table +function MatchGroupLegacyDefault._readOpponent(prefix, scoreKey, bracketType) + return { + ['type'] = 'type', + template = prefix .. 'team', + score = prefix .. scoreKey, + name = prefix, + displayname = prefix .. 'display', + flag = prefix .. 'flag', + win = prefix .. 'win', + ['$notEmpty$'] = bracketType == 'team' and (prefix .. 'team') or prefix + } +end + +--the following variable gets mutaded by each p._getMatchMapping +--it is needed as a basis for the next call +local _lastRound +---@param match table +---@param bracketData table +---@param bracketType string +---@param lowerHeader table +---@return table +---@return number +---@return table +function MatchGroupLegacyDefault._getMatchMapping(match, bracketData, bracketType, lowerHeader) + local id = String.split(match.match2id, '_')[2] or match.match2id + --remove 0's and dashes from the match param + --e.g. R01-M001 --> R1M1 + id = id:gsub('0*([1-9])', '%1'):gsub('%-', '') + local bd = match.match2bracketdata + + local roundNum + local round + local reset = false + if id == 'RxMTP' then + round = _lastRound + elseif id == 'RxMBR' then + round = _lastRound + round.G = round.G - 2 + round.W = round.W - 2 + round.D = round.D - 2 + reset = true + else + roundNum = id:match('R%d*'):gsub('R', '') + roundNum = tonumber(roundNum) + round = roundData[roundNum] or { R = roundNum, G = 0, D = 1, W = 1 } + end + round.G = round.G + 1 + + --if bd.header starts with '!l' + if string.match(bd.header or '', '^!l') then + lowerHeader[roundNum or ''] = round.G + end + + local opponents = {} + local finished = {} + local scoreKey = (reset and 'score2' or 'score') + for opponentIndex = 1, MAX_NUMBER_OF_OPPONENTS do + local prefix + if not reset and + (Logic.isEmpty(bd.toupper) and opponentIndex == 1 or + Logic.isEmpty(bd.tolower) and opponentIndex == 2) then + + prefix = 'R' .. round.R .. 'D' .. round.D + round.D = round.D + 1 + else + prefix = 'R' .. round.R .. 'W' .. round.W + round.W = round.W + 1 + end + + opponents[opponentIndex] = MatchGroupLegacyDefault._readOpponent(prefix, scoreKey, bracketType) + finished[opponentIndex] = prefix .. 'win' + end + + match = { + opponent1 = opponents[1], + opponent2 = opponents[2], + finished = finished[1] .. '|' .. finished[2], + -- reference to variables that shall be flattened + ['$flatten$'] = { 'R' .. round.R .. 'G' .. round.G .. 'details' } + } + + bracketData[id] = MatchGroupLegacyDefault.addMaps(match) + _lastRound = round + roundData[round.R] = round + + return bracketData, round.R, lowerHeader +end + +--[[ +custom mappings are used to overwrite the default mappings +in the cases where the default mappings do not fit the +parameter format of the old bracket +]]-- + +--this can be used for custom mappings too +---@param match table +---@return table +function MatchGroupLegacyDefault.addMaps(match) + for mapIndex = 1, MAX_NUM_MAPS do + match['map' .. mapIndex] = { + ['$ref$'] = 'map', + ['$1$'] = mapIndex + } + end + return match +end + +--this is for custom mappings +---@param data {opp1: string, opp2: string, details: string} +---@param bracketType string +---@return table +function MatchGroupLegacyDefault.matchMappingFromCustom(data, bracketType) + bracketType = bracketType or 'team' + + local mapping = { + ['$flatten$'] = {data.details .. 'details'}, + ['finished'] = data.opp1 .. 'win|' .. data.opp2 .. 'win', + opponent1 = MatchGroupLegacyDefault._readOpponent(data.opp1, 'score', bracketType), + opponent2 = MatchGroupLegacyDefault._readOpponent(data.opp2, 'score', bracketType), + } + mapping = MatchGroupLegacyDefault.addMaps(mapping) + + return mapping +end + +--this is for custom mappings for Reset finals matches +--it switches score2 into the place of score +--and sets flatten to nil +---@param mapping table +---@return table +function MatchGroupLegacyDefault.matchResetMappingFromCustom(mapping) + local mappingReset = mw.clone(mapping) + mappingReset.opponent1.score = mapping.opponent1.score .. '2' + mappingReset.opponent2.score = mapping.opponent2.score .. '2' + mappingReset['$flatten$'] = nil + return mappingReset +end + +return MatchGroupLegacyDefault diff --git a/components/match2/wikis/brawlstars/legacy/match_maps_legacy.lua b/components/match2/wikis/brawlstars/legacy/match_maps_legacy.lua new file mode 100644 index 00000000000..5ab1caa03b2 --- /dev/null +++ b/components/match2/wikis/brawlstars/legacy/match_maps_legacy.lua @@ -0,0 +1,329 @@ +--- +-- @Liquipedia +-- wiki=brawlstars +-- page=Module:MatchMaps/Legacy +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local CharacterIcon = require('Module:CharacterIcon') +local Arguments = require('Module:Arguments') +local Array = require('Module:Array') +local Logic = require('Module:Logic') +local Lua = require('Module:Lua') +local Json = require('Module:Json') +local MatchGroup = require('Module:MatchGroup') +local PageVariableNamespace = require('Module:PageVariableNamespace') +local Table = require('Module:Table') +local Template = require('Module:Template') + +local CharacterNames = mw.loadData('Module:BrawlerNames') + +local MatchGroupBase = Lua.import('Module:MatchGroup/Base') +local MatchSubobjects = Lua.import('Module:Match/Subobjects') + +local globalVars = PageVariableNamespace() +local matchlistVars = PageVariableNamespace('LegacyMatchlist') + +local MAX_NUMBER_OF_OPPONENTS = 2 +local DEFAULT_WIN = 'W' +local DEFAULT_LOSS = 'L' +local FORFEIT = 'FF' +local TBD = 'tbd' + +local MatchMapsLegacy = {} + +---@param args table +---@return table +function MatchMapsLegacy._handleMaps(args) + Array.mapIndexes(function (index) + local prefix = 'map' .. index + local map = args[prefix] + local winner = Table.extract(args, prefix .. 'win') + if Logic.isEmpty(map) then + return false + end + local score = Table.extract(args, prefix .. 'score') + local score1 + local score2 + if Logic.isNotEmpty(score) then + local splitedScore = mw.text.split(score, '-') + score1 = splitedScore[1] + score2 = splitedScore[2] + end + + args[prefix .. 'score1'] = mw.text.trim(score1 or '') + args[prefix .. 'score2'] = mw.text.trim(score2 or '') + args[prefix .. 'winner'] = winner + args[prefix .. 'maptype'] = Table.extract(args, prefix ..'type') + + return true + end) + + return args +end + +---@param args table +---@return table +function MatchMapsLegacy._handleBans(args) + local bans = {} + Array.mapIndexes(function (index) + local ban = Table.extract(args, 'ban' .. (index == 1 and '' or index)) + if Logic.isEmpty(ban) then + return false + end + table.insert(bans, CharacterIcon.Icon({ + character = CharacterNames[ban:lower()], + size = '30px' + })) + return true + end) + + if #bans == 0 then + return args + end + + local bansComment = '\'\'\'Bans\'\'\':' .. table.concat(bans, ' ') + args.comment = args.comment and (args.comment .. '
' .. bansComment) or bansComment + return args +end + +-- invoked by Template:BracketMatchSummary +---@param frame Frame +---@return string +function MatchMapsLegacy.convertBracketMatchSummary(frame) + local args = Arguments.getArgs(frame) + args = MatchMapsLegacy._handleMaps(args) + args = MatchMapsLegacy._handleBans(args) + return Json.stringify(args) +end + +---@param args table +---@param details table +---@return table, table +function MatchMapsLegacy._handleDetails(args, details) + Array.mapIndexes(function (index) + local prefix = 'map' .. index + if not details[prefix] then + return false + end + local map = { + map = Table.extract(details, prefix), + winner = Table.extract(details, prefix .. 'winner'), + maptype = Table.extract(details, prefix .. 'maptype'), + score1 = Table.extract(details, prefix .. 'score1'), + score2 = Table.extract(details, prefix .. 'score2') + } + args[prefix] = MatchSubobjects.luaGetMap(map) + + if map and map.winner then + args.mapWinnersSet = true + end + + return true + end) + + return args, details +end + +---@param args table +---@return table +function MatchMapsLegacy._getScoresFromMapWinners(args) + local scores = {} + local hasScores = false + Array.mapIndexes(function (index) + local winner = tonumber(Table.extract(args, 'map' .. index .. 'win')) + if winner and winner > 0 and winner <= MAX_NUMBER_OF_OPPONENTS then + scores[winner] = (scores[winner] or 0) + 1 + hasScores = true + return true + end + return false + end) + if hasScores then + scores[1] = scores[1] or 0 + scores[2] = scores[2] or 0 + end + return scores +end + +---@param args table +---@return table +function MatchMapsLegacy._handleOpponents(args) + args.winner = args.winner or Table.extract(args, 'win') + local walkover = tonumber(Table.extract(args, 'walkover')) + local scores = MatchMapsLegacy._getScoresFromMapWinners(args) + + Array.forEach(Array.range(1, MAX_NUMBER_OF_OPPONENTS), function(opponentIndex) + args['score' .. opponentIndex] = args['score' .. opponentIndex] or + Table.extract(args, 'games' .. opponentIndex) + local template = Table.extract(args, 'team' .. opponentIndex) + + if (not template) or template == ' ' then + template = TBD + else + template = string.lower(template) + end + + local score + local winner = tonumber(args.winner) + if walkover and walkover ~= 0 then + score = walkover == opponentIndex and DEFAULT_WIN or FORFEIT + elseif args['score' .. opponentIndex] then + score = Table.extract(args, 'score' .. opponentIndex) + elseif not args.mapWinnersSet and winner then + if Logic.isNotEmpty(scores[opponentIndex]) then + score = scores[opponentIndex] + else + score = winner == opponentIndex and DEFAULT_WIN or DEFAULT_LOSS + end + end + + local opponent + if template ~= TBD then + opponent = { + ['type'] = 'team', + score = score, + template = template, + } + end + if Logic.isEmpty(opponent) then + opponent = { + ['type'] = 'literal', + template = TBD, + } + end + args['opponent' .. opponentIndex] = opponent + end) + args.mapWinnersSet = nil + + return args +end + +---@param args table +---@param details table +---@return table +function MatchMapsLegacy._setHeaderIfEmpty(args, details) + args.header = args.header or args.date + args.date = details.date or args.date + return args +end + +---@param args table +---@param details table +---@return table +function MatchMapsLegacy._copyDetailsToArgs(args, details) + for key, value in pairs(details) do + if Logic.isEmpty(args[key]) then + args[key] = value + end + end + args.details = nil + return args +end + +-- invoked by Template:MatchMaps +---@param frame Frame +---@return Html +function MatchMapsLegacy.convertMatch(frame) + local args = Arguments.getArgs(frame) + local details = Json.parseIfString(args.details or '{}') + + args, details = MatchMapsLegacy._handleDetails(args, details) + args = MatchMapsLegacy._handleOpponents(args) + args = MatchMapsLegacy._setHeaderIfEmpty(args, details) + args = MatchMapsLegacy._copyDetailsToArgs(args, details) + + Template.stashReturnValue(args, 'LegacyMatchlist') + return mw.html.create('div'):css('display', 'none') +end + +-- invoked by Template:LegacySingleMatch +---@param frame Frame +---@return Html +function MatchMapsLegacy.showmatch(frame) + local args = Arguments.getArgs(frame) + assert(args.id, 'Missing id') + + local store = Logic.nilOr( + Logic.readBoolOrNil(args.store), + not Logic.readBool(globalVars:get('disable_LPDB_storage')) + ) + + local matches = Template.retrieveReturnValues('LegacyMatchlist') + + MatchGroup.Bracket({ + 'Bracket/2', + isLegacy = true, + id = args.id, + hide = true, + store = store, + noDuplicateCheck = not store, + R1M1 = matches[1] + }) + + return MatchGroup.MatchByMatchId({ + id = MatchGroupBase.getBracketIdPrefix() .. args.id, + matchid = 'R1M1', + }) +end + +-- invoked by Template:MatchListStart +---@param frame Frame +function MatchMapsLegacy.matchListStart(frame) + local args = Arguments.getArgs(frame) + + local store = Logic.nilOr( + Logic.readBoolOrNil(args.store), + not Logic.readBool(globalVars:get('disable_LPDB_storage')) + ) + + matchlistVars:set('store', tostring(store)) + matchlistVars:set('bracketid', args.id) + matchlistVars:set('hide', args.hide or 'true') + matchlistVars:set('matchListTitle', args.title or args[1] or 'Match List') + matchlistVars:set('width', args.width or '300px') + matchlistVars:set('matchsection', args.matchsection) + globalVars:set('islegacy', 'true') +end + +-- invoked by MatchListEnd +---@return string +function MatchMapsLegacy.matchListEnd() + local bracketId = matchlistVars:get('bracketid') + assert(bracketId, 'Missing id') + + local store = Logic.readBool(matchlistVars:get('store')) + local hide = Logic.readBool(matchlistVars:get('hide')) + + local args = { + isLegacy = true, + id = bracketId, + store = store, + noDuplicateCheck = not store, + collapsed = hide, + attached = hide, + title = matchlistVars:get('matchListTitle'), + width = matchlistVars:get('width'), + matchsection = matchlistVars:get('matchsection'), + } + + local matches = Template.retrieveReturnValues('LegacyMatchlist') + + Array.forEach(matches, function(match, matchIndex) + args['M' .. matchIndex .. 'header'] = Table.extract(match, 'header') + args['M' .. matchIndex] = Json.stringify(match) + end) + + matchlistVars:delete('store') + matchlistVars:delete('bracketid') + matchlistVars:delete('matchListTitle') + matchlistVars:delete('width') + matchlistVars:delete('hide') + matchlistVars:delete('matchsection') + globalVars:delete('islegacy') + + return MatchGroup.MatchList(args) +end + +return MatchMapsLegacy