Skip to content

Commit

Permalink
feat(match2): deadlock setup (#4652)
Browse files Browse the repository at this point in the history
* feat(match2): deadlock setup

* from review

* shortern down the copy paste

* update m2 status

* hero icon tweaks

* remove side colors
  • Loading branch information
Rathoz authored Aug 28, 2024
1 parent be7cf9d commit 429f64c
Show file tree
Hide file tree
Showing 4 changed files with 396 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
-- @Liquipedia
-- wiki=deadlock
-- 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 Logic = require('Module:Logic')
local Lua = require('Module:Lua')

local BaseCopyPaste = Lua.import('Module:GetMatchGroupCopyPaste/wiki/Base')

---@class DeadlockMatch2CopyPaste: Match2CopyPasteBase
local WikiCopyPaste = Class.new(BaseCopyPaste)

local INDENT = WikiCopyPaste.Indent

function WikiCopyPaste.getMatchCode(bestof, mode, index, opponents, args)
local showScore = Logic.nilOr(Logic.readBoolOrNil, bestof == 0)

local lines = Array.extend(
'{{Match|bestof=' .. (bestof ~= 0 and bestof or ''),
Array.map(Array.range(1, opponents), function(opponentIndex)
return INDENT .. '|opponent' .. opponentIndex .. '=' .. WikiCopyPaste.getOpponent(mode, showScore)
end),
INDENT .. '|date=|finished=',
INDENT .. '|twitch=|youtube=|vod=',
Array.map(Array.range(1, bestof), WikiCopyPaste._getMapCode),
'}}'
)

return table.concat(lines, '\n')
end

---@param mapIndex integer
---@return string
function WikiCopyPaste._getMapCode(mapIndex)
return table.concat(Array.extend(
INDENT .. '|map' .. mapIndex .. '={{Map|length=|winner=|vod=',
INDENT .. INDENT .. '|team1side=|team2side=',
INDENT .. INDENT .. '|t1h1=|t1h2=|t1h3=|t1h4=|t1h5=|t1h6=',
INDENT .. INDENT .. '|t2h1=|t2h2=|t2h3=|t2h4=|t2h5=|t2h6=',
INDENT .. '}}'
), '\n')
end

return WikiCopyPaste
181 changes: 181 additions & 0 deletions components/match2/wikis/deadlock/match_group_input_custom.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
---
-- @Liquipedia
-- wiki=deadlock
-- page=Module:MatchGroup/Input/Custom
--
-- Please see https://github.com/Liquipedia/Lua-Modules to contribute
--

local Array = require('Module:Array')
local FnUtil = require('Module:FnUtil')
local HeroNames = mw.loadData('Module:HeroNames')
local Lua = require('Module:Lua')
local Operator = require('Module:Operator')
local Streams = require('Module:Links/Stream')
local Table = require('Module:Table')

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

local OPPONENT_CONFIG = {
resolveRedirect = true,
pagifyTeamNames = true,
pagifyPlayerNames = true,
maxNumPlayers = 10,
}

local MatchFunctions = {}
local MapFunctions = {}

local CustomMatchGroupInput = {}

---@param match table
---@param options? {isMatchPage: boolean?}
---@return table
function CustomMatchGroupInput.processMatch(match, options)
local finishedInput = match.finished --[[@as string?]]
local winnerInput = match.winner --[[@as string?]]
Table.mergeInto(match, MatchGroupInputUtil.readDate(match.date))

local opponents = Array.mapIndexes(function(opponentIndex)
return MatchGroupInputUtil.readOpponent(match, opponentIndex, OPPONENT_CONFIG)
end)
local games = MatchFunctions.extractMaps(match, opponents)
match.bestof = MatchGroupInputUtil.getBestOf(match.bestof, games)

local autoScoreFunction = MatchGroupInputUtil.canUseAutoScore(match, games)
and MatchFunctions.calculateMatchScore(games)
or nil

Array.forEach(opponents, function(opponent, opponentIndex)
opponent.score, opponent.status = MatchGroupInputUtil.computeOpponentScore({
walkover = match.walkover,
winner = match.winner,
opponentIndex = opponentIndex,
score = opponent.score,
}, autoScoreFunction)
end)

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)
MatchGroupInputUtil.setPlacement(opponents, match.winner, 1, 2)
elseif MatchGroupInputUtil.isNotPlayed(winnerInput, finishedInput) then
match.resulttype = MatchGroupInputUtil.getResultType(winnerInput, finishedInput, opponents)
match.winner = nil
end

MatchGroupInputUtil.getCommonTournamentVars(match)

match.stream = Streams.processStreams(match)
match.extradata = MatchFunctions.getExtraData(match)

match.games = games
match.opponents = opponents

return match
end

---@param match table
---@param opponents table[]
---@return table[]
function MatchFunctions.extractMaps(match, opponents)
local maps = {}
for key, map in Table.iter.pairsByPrefix(match, 'map', {requireIndex = true}) do
local finishedInput = map.finished --[[@as string?]]
local winnerInput = map.winner --[[@as string?]]

map.map = nil
map.participants = MapFunctions.getParticipants(map, opponents)
map.extradata = MapFunctions.getExtraData(map)

map.finished = MatchGroupInputUtil.mapIsFinished(map)
local opponentInfo = Array.map(opponents, function(_, opponentIndex)
local score, status = MatchGroupInputUtil.computeOpponentScore({
walkover = map.walkover,
winner = map.winner,
opponentIndex = opponentIndex,
score = map['score' .. opponentIndex],
}, MapFunctions.calculateMapScore(map.winner, map.finished))
return {score = score, status = status}
end)

map.scores = Array.map(opponentInfo, Operator.property('score'))
if map.finished or MatchGroupInputUtil.isNotPlayed(map.winner, finishedInput) then
map.resulttype = MatchGroupInputUtil.getResultType(winnerInput, finishedInput, opponentInfo)
map.walkover = MatchGroupInputUtil.getWalkover(map.resulttype, opponentInfo)
map.winner = MatchGroupInputUtil.getWinner(map.resulttype, winnerInput, opponentInfo)
end

table.insert(maps, map)
match[key] = nil
end

return maps
end

CustomMatchGroupInput.processMap = FnUtil.identity

---@param maps table[]
---@return fun(opponentIndex: integer): integer
function MatchFunctions.calculateMatchScore(maps)
return function(opponentIndex)
return MatchGroupInputUtil.computeMatchScoreFromMapWinners(maps, opponentIndex)
end
end

---@param match table
---@return table
function MatchFunctions.getExtraData(match)
return {
comment = match.comment,
}
end

---@param map table
---@return table
function MapFunctions.getExtraData(map)
local extraData = {
comment = map.comment,
team1side = map.team1side,
team2side = map.team2side,
}

return extraData
end

---@param map table
---@param opponents table[]
---@return table
function MapFunctions.getParticipants(map, opponents)
local participants = {}
local getCharacterName = FnUtil.curry(MatchGroupInputUtil.getCharacterName, HeroNames)

for opponentIndex in ipairs(opponents) do
for _, hero, playerIndex in Table.iter.pairsByPrefix(map, 't' .. opponentIndex .. 'h', {requireIndex = true}) do
participants[opponentIndex .. '_' .. playerIndex] = {
character = getCharacterName(hero),
}
end
end

return participants
end

---@param winnerInput string|integer|nil
---@param finished boolean
---@return fun(opponentIndex: integer): integer?
function MapFunctions.calculateMapScore(winnerInput, finished)
local winner = tonumber(winnerInput)
return function(opponentIndex)
-- TODO Better to check if map has started, rather than finished, for a more correct handling
if not winner and not finished then
return
end
return winner == opponentIndex and 1 or 0
end
end

return CustomMatchGroupInput
164 changes: 164 additions & 0 deletions components/match2/wikis/deadlock/match_summary.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
---
-- @Liquipedia
-- wiki=deadlock
-- page=Module:MatchSummary
--
-- Please see https://github.com/Liquipedia/Lua-Modules to contribute
--

local Abbreviation = require('Module:Abbreviation')
local Array = require('Module:Array')
local CharacterIcon = require('Module:CharacterIcon')
local FnUtil = require('Module:FnUtil')
local DateExt = require('Module:Date/Ext')
local Icon = require('Module:Icon')
local Logic = require('Module:Logic')
local Lua = require('Module:Lua')
local Table = require('Module:Table')

local DisplayHelper = Lua.import('Module:MatchGroup/Display/Helper')
local MatchSummary = Lua.import('Module:MatchSummary/Base')

local SIZE_HERO = '48x48px'
local ICONS = {
winner = Icon.makeIcon{iconName = 'winner', color = 'forest-green-text', size = 'initial'},
loss = Icon.makeIcon{iconName = 'loss', color = 'cinnabar-text', size = 'initial'},
empty = '[[File:NoCheck.png|link=|16px]]',
}

local CustomMatchSummary = {}

---@param args table
---@return Html
function CustomMatchSummary.getByMatchId(args)
return MatchSummary.defaultGetByMatchId(CustomMatchSummary, args, {width = '400px', teamStyle = 'bracket'})
end

---@param match MatchGroupUtilMatch
---@return MatchSummaryBody
function CustomMatchSummary.createBody(match)
local body = MatchSummary.Body()

if match.dateIsExact or match.timestamp ~= DateExt.defaultTimestamp then
body:addRow(MatchSummary.Row():addElement(
DisplayHelper.MatchCountdownBlock(match)
))
end

Array.forEach(Array.map(match.games, CustomMatchSummary._createGame), FnUtil.curry(body.addRow, body))

return body
end

---@param participants table
---@param opponentIndex integer
---@return table
function CustomMatchSummary._getHeroesForOpponent(participants, opponentIndex)
local characters = {}
for _, participant in Table.iter.pairsByPrefix(participants, opponentIndex .. '_') do
table.insert(characters, participant.character)
end
return characters
end

---@param game MatchGroupUtilGame
---@param gameIndex integer
---@return MatchSummaryRow
function CustomMatchSummary._createGame(game, gameIndex)
local row = MatchSummary.Row()
local extradata = game.extradata or {}

row:addClass('brkts-popup-body-game')
:css('font-size', '80%')
:css('padding', '4px')

local function makeCharacterDisplay(opponentIndex)
return CustomMatchSummary._createCharacterDisplay(
CustomMatchSummary._getHeroesForOpponent(game.participants, opponentIndex),
extradata['team' .. opponentIndex .. 'side'],
opponentIndex == 2
)
end

row:addElement(makeCharacterDisplay(1))
row:addElement(CustomMatchSummary._createCheckMark(game.winner, 1))
row:addElement(mw.html.create('div')
:addClass('brkts-popup-body-element-vertical-centered')
:wikitext(Abbreviation.make(
Logic.isEmpty(game.length) and ('Game ' .. gameIndex) or game.length,
Logic.isEmpty(game.length) and ('Game ' .. gameIndex .. ' picks') or 'Match Length'
))
)
row:addElement(CustomMatchSummary._createCheckMark(game.winner, 2))
row:addElement(makeCharacterDisplay(2))

if Logic.isNotEmpty(game.comment) then
row:addElement(MatchSummary.Break():create())
row:addElement(mw.html.create('div'):css('margin', 'auto'):wikitext(game.comment))
end

return row
end

---@param winner integer|string
---@param opponentIndex integer
---@return Html
function CustomMatchSummary._createCheckMark(winner, opponentIndex)
return mw.html.create('div')
:addClass('brkts-popup-spaced')
:css('line-height', '17px')
:css('margin-left', '1%')
:css('margin-right', '1%')
:wikitext(
winner == opponentIndex and ICONS.winner
or winner == 0 and ICONS.draw
or Logic.isNotEmpty(winner) and ICONS.loss
or ICONS.empty
)
end

---@param characters {name: string, active: boolean}[]?
---@param side string?
---@param reverse boolean?
---@return Html
function CustomMatchSummary._createCharacterDisplay(characters, side, reverse)
local wrapper = mw.html.create('div')
:addClass('brkts-popup-body-element-thumbs')
:addClass('brkts-popup-body-element-thumbs-' .. (reverse and 'right' or 'left'))
:addClass('brkts-champion-icon')

local function makeCharacterIcon(character)
return CharacterIcon.Icon{
character = character,
size = SIZE_HERO,
}
end

local function characterDisplay(character, showName)
local display = mw.html.create('div')
if not showName then
display:node(makeCharacterIcon(character))
return display
end
if reverse then
display:wikitext(character):wikitext(' '):wikitext(makeCharacterIcon(character))
else
display:node(makeCharacterIcon(character)):wikitext(' '):wikitext(character)
end
return display
end

local characterDisplays = Array.map(characters or {}, function (character)
return characterDisplay(character, #characters == 1)
end)

if reverse then
characterDisplays = Array.reverse(characterDisplays)
end

Array.forEach(characterDisplays, FnUtil.curry(wrapper.node, wrapper))

return wrapper
end

return CustomMatchSummary
Loading

0 comments on commit 429f64c

Please sign in to comment.