diff --git a/lua/wikis/commons/StageWinningsCalculation.lua b/lua/wikis/commons/StageWinningsCalculation.lua index b6c6f02dcb8..90d209542a9 100644 --- a/lua/wikis/commons/StageWinningsCalculation.lua +++ b/lua/wikis/commons/StageWinningsCalculation.lua @@ -22,9 +22,11 @@ local ColumnName = Condition.ColumnName local StageWinningsCalculation = {} ---@param props {matchGroupsSpecProps: table, startDate: integer?, endDate: integer?, mode: string, ----startValue: number, valuePerWin: number, valueByScore: table?} +---startValue: number, valuePerWin: number, valueByScore: table?, +---pointsStart: number, pointsPerWin: number, pointsByScore: table?, +---points2Start: number, points2PerWin: number, points2ByScore: table?, hideWinnings: boolean} ---@return {opponent: standardOpponent, matchWins: integer, matchLosses: integer, gameWins: integer, ----gameLosses: integer, winnings: number, scoreDetails: table}[] +---gameLosses: integer, winnings: number, scoreDetails: table, points: number, points2: number}[] function StageWinningsCalculation.run(props) local matches = mw.ext.LiquipediaDB.lpdb('match2', { conditions = StageWinningsCalculation._buildConditions(props), @@ -52,6 +54,8 @@ function StageWinningsCalculation.run(props) gameWins = 0, gameLosses = 0, winnings = 0, + points = 0, + points2 = 0, } end) @@ -85,22 +89,38 @@ function StageWinningsCalculation.run(props) Array.forEach(opponents, function(opponent) if props.mode == 'matchWins' then opponent.winnings = props.startValue + opponent.matchWins * props.valuePerWin + opponent.points = props.pointsStart + opponent.matchWins * props.pointsPerWin + opponent.points2 = props.points2Start + opponent.matchWins * props.points2PerWin return elseif props.mode == 'gameWins' then opponent.winnings = props.startValue + opponent.gameWins * props.valuePerWin + opponent.points = props.pointsStart + opponent.gameWins * props.pointsPerWin + opponent.points2 = props.points2Start + opponent.gameWins * props.points2PerWin return end -- case: props.mode == 'scores' local winnings = props.startValue + local points = props.pointsStart + local points2 = props.points2Start for score, count in pairs(opponent.scoreDetails) do winnings = winnings + (props.valueByScore[score] or 0) * count + points = points + (props.pointsByScore[score] or 0) * count + points2 = points2 + (props.points2ByScore[score] or 0) * count end opponent.winnings = winnings + opponent.points = points + opponent.points2 = points2 end) - Array.sortInPlaceBy(opponents, function(opponent) - return {- opponent.winnings, - opponent.matchWins, - opponent.gameWins, Opponent.toName(opponent)} - end) + if props.hideWinnings then + Array.sortInPlaceBy(opponents, function(opponent) + return {- opponent.points, - opponent.points, - opponent.matchWins, - opponent.gameWins, Opponent.toName(opponent)} + end) + else + Array.sortInPlaceBy(opponents, function(opponent) + return {- opponent.winnings, - opponent.matchWins, - opponent.gameWins, Opponent.toName(opponent)} + end) + end return opponents diff --git a/lua/wikis/commons/Widget/StageWinnings.lua b/lua/wikis/commons/Widget/StageWinnings.lua index 6fa90f04ee5..e352f913468 100644 --- a/lua/wikis/commons/Widget/StageWinnings.lua +++ b/lua/wikis/commons/Widget/StageWinnings.lua @@ -12,47 +12,62 @@ local Class = Lua.import('Module:Class') local Currency = Lua.import('Module:Currency') local DateExt = Lua.import('Module:Date/Ext') local FnUtil = Lua.import('Module:FnUtil') +local LeagueIcon = Lua.import('Module:LeagueIcon') local Logic = Lua.import('Module:Logic') local MatchGroupInputUtil = Lua.import('Module:MatchGroup/Input/Util') local OpponentDisplay = Lua.import('Module:OpponentDisplay/Custom') +local Points = Lua.import('Module:Points/data', {loadData = true}) local StageWinningsCalculation = Lua.import('Module:StageWinningsCalculation') local String = Lua.import('Module:StringUtils') local Table = Lua.import('Module:Table') -local Variables = Lua.import('Module:Variables') +local Link = Lua.import('Module:Widget/Basic/Link') local HtmlWidgets = Lua.import('Module:Widget/Html/All') local TableWidgets = Lua.import('Module:Widget/Table2/All') local Widget = Lua.import('Module:Widget') local WidgetUtil = Lua.import('Module:Widget/Util') local BASE_CURRENCY = 'USD' +local NON_BREAKING_SPACE = ' ' ---@class StageWinningProps ----@field tournaments string ----@field ids string? +---@field tournament1 string? +---@field tournament2 string? +---@field tournament3 string? +---@field matchGroupId1 string? +---@field matchGroupId2 string? +---@field matchGroupId3 string? ---@field sdate string|number|osdate|osdateparam? ---@field edate string|number|osdate|osdateparam? ---@field prizeMode 'matchWins'|'gameWins'|'scores' +---@field points string? +---@field points2 string? ---@field valueStart number? ---@field valuePerWin number? +---@field pointsStart number? +---@field pointsPerWin number? +---@field points2Start number? +---@field points2PerWin number? ---@field n-m number? # n amd m integers +---@field n-m_points number? # n amd m integers +---@field n-m_points2 number? # n amd m integers ---@field localcurrency string? ----@field width integer? ---@field cutafter integer? ---@field title string? ---@field precision integer? ---@field autoexchange boolean ----@field showMatchWL boolean ----@field showGameWL boolean ----@field showScore boolean +---@field showMatchWL boolean? +---@field showGameWL boolean? +---@field showScore boolean? +---@field hideWinnings boolean? ---@class StageWinnings: Widget ---@operator call(table): StageWinnings ---@field props StageWinningProps +---@field points {title: string, icon: string?, iconDark: string?, link: string?, titleLong: string?}? +---@field points2 {title: string, icon: string?, iconDark: string?, link: string?, titleLong: string?}? local StageWinnings = Class.new(Widget) StageWinnings.defaultProps = { - tournaments = mw.title.getCurrentTitle().text, - delimiter = ',', autoexchange = true, prizeMode = 'matchWins', title = 'Group Stage Winnings' @@ -65,21 +80,27 @@ function StageWinnings:render() local startDate = DateExt.readTimestamp(props.sdate) local endDate = DateExt.readTimestamp(props.edate) - local valueByScore = Table.filterByKey(props, function(key) - if key:match('^%d+%-%d+$') ~= nil then - return true - end - local keyParts = Array.parseCommaSeparatedString(key, '-') - return #keyParts == 2 and - Array.all(keyParts, function(keyPart) return Table.includes(MatchGroupInputUtil.STATUS, keyPart) end) - end) - valueByScore = Table.map(valueByScore, function(key, value) - return key, tonumber(value) - end) + local getValuesByScore = function(postFix) + local valueByScore = Table.filterByKey(props, function(key) + if key:match('^%d+%-%d+' .. postFix .. '$') ~= nil then + return true + end + local keyParts = Array.parseCommaSeparatedString((key:gsub(postFix, '')), '-') + return #keyParts == 2 and + Array.all(keyParts, function(keyPart) return Table.includes(MatchGroupInputUtil.STATUS, keyPart) end) + end) + return Table.map(valueByScore, function(key, value) + return key, tonumber(value) + end) + end + + local valueByScore = getValuesByScore('') + local pointsByScore = getValuesByScore('_points') + local points2ByScore = getValuesByScore('_points2') assert(props.prizeMode == 'matchWins' or props.prizeMode == 'gameWins' or props.prizeMode == 'scores', 'Invalid prizeMode input') - assert(props.prizeMode ~= 'scores' or Logic.isNotEmpty(valueByScore), + assert(props.prizeMode ~= 'scores' or Logic.isNotEmpty(valueByScore) or Logic.isNotEmpty(pointsByScore), 'No values per scores defined') local opponentList = StageWinningsCalculation.run{ @@ -90,20 +111,41 @@ function StageWinnings:render() endDate = endDate, mode = props.prizeMode, valueByScore = valueByScore, + pointsByScore = pointsByScore, + points2ByScore = points2ByScore, startValue = tonumber(props.valueStart) or 0, + pointsStart = tonumber(props.pointsStart) or 0, + points2Start = tonumber(props.points2Start) or 0, valuePerWin = tonumber(props.valuePerWin) or 0, + pointsPerWin = tonumber(props.pointsPerWin) or 0, + points2PerWin = tonumber(props.points2PerWin) or 0, + hideWinnings = Logic.readBool(props.hideWinnings), } if Logic.isNotEmpty(props.localcurrency) and Logic.readBool(props.autoexchange) then - Currency.display(props.localcurrency, nil, {setVariables = true}) self.currencyRate = Currency.getExchangeRate{ currency = props.localcurrency, - currencyRate = Variables.varDefault('exchangerate_' .. props.localcurrency:upper()), date = DateExt.toYmdInUtc(endDate or DateExt.getContextualDateOrNow()), setVariables = false } end + ---@param prefix string + ---@return {title: string, icon: string?, iconDark: string?, link: string?, titleLong: string?}? + local parsePoints = function(prefix) + if Logic.isEmpty(props[prefix]) then + return + end + + local pointsData = Table.copy(Points[props[prefix]] or {}) + pointsData.title = pointsData.title or props[prefix] + pointsData.link = props[prefix .. 'link'] + + return pointsData + end + self.points = parsePoints('points') + self.points2 = parsePoints('points2') + return TableWidgets.Table{ caption = props.title, tableClasses = {'prizepooltable', 'collapsed'}, @@ -118,7 +160,11 @@ function StageWinnings:render() (Logic.readBool(props.showGameWL) or props.prizeMode == 'gameWins') and {align = 'center'} or nil, Logic.readBool(props.showScore) and {align = 'left'} or nil, Logic.isNotEmpty(props.localcurrency) and {align = 'right'} or nil, - (Logic.readBool(props.autoexchange) or Logic.isEmpty(props.localcurrency)) and {align = 'right'} or nil + (Logic.readBool(props.autoexchange) or Logic.isEmpty(props.localcurrency)) + and (not Logic.readBool(props.hideWinnings)) and {align = 'right'} + or nil, + Logic.isNotEmpty(self.points) and {align = 'right'} or nil, + Logic.isNotEmpty(self.points2) and {align = 'right'} or nil ), children = { self:_headerRow(), @@ -143,14 +189,17 @@ function StageWinnings:_headerRow() Logic.isNotEmpty(props.localcurrency) and TableWidgets.CellHeader{children = Currency.display(props.localcurrency)} or nil, (Logic.readBool(props.autoexchange) or Logic.isEmpty(props.localcurrency)) - and TableWidgets.CellHeader{children = Currency.display(BASE_CURRENCY)} or nil + and (not Logic.readBool(props.hideWinnings)) + and TableWidgets.CellHeader{children = Currency.display(BASE_CURRENCY)} or nil, + self:_pointsHeader(self.points), + self:_pointsHeader(self.points2) )} }} end ---@private ---@param data {opponent: standardOpponent, matchWins: integer, matchLosses: integer, gameWins: integer, ----gameLosses: integer, winnings: number, scoreDetails: table} +---gameLosses: integer, winnings: number, points: number, points2: number, scoreDetails: table} ---@return Widget function StageWinnings:_row(data) local props = self.props @@ -189,12 +238,19 @@ function StageWinnings:_row(data) currencyDisplayConfig ), } or nil, - (Logic.readBool(props.autoexchange) or Logic.isEmpty(props.localcurrency)) and TableWidgets.Cell{ - children = Currency.display( + (Logic.readBool(props.autoexchange) or Logic.isEmpty(props.localcurrency)) + and (not Logic.readBool(props.hideWinnings)) and TableWidgets.Cell{children = Currency.display( BASE_CURRENCY, data.winnings * (self.currencyRate or 1), currencyDisplayConfig - ), + )} or nil, + Logic.isNotEmpty(self.points) and TableWidgets.Cell{ + children = Currency.formatMoney(data.points, 2, false, true), + ['data-sort-value'] = data.points, + } or nil, + Logic.isNotEmpty(self.points2) and TableWidgets.Cell{ + children = Currency.formatMoney(data.points2, 2, false, true), + ['data-sort-value'] = data.points2, } or nil ), } @@ -225,4 +281,25 @@ function StageWinnings._detailedScores(scoresTable) ) end +---@private +---@param data {title: string, icon: string?, iconDark: string?, link: string?, titleLong: string?}? +---@return Widget? +function StageWinnings:_pointsHeader(data) + if not data then + return + end + + local titleText = Logic.isNotEmpty(data.titleLong) and HtmlWidgets.Abbr{ + children = data.title, title = data.titleLong + } or data.title + + return TableWidgets.CellHeader{children = WidgetUtil.collect( + Logic.isNotEmpty(data.icon) and { + LeagueIcon.display{link = data.link, icon = data.icon, iconDark = data.iconDark, name = data.title}, + NON_BREAKING_SPACE, + } or nil, + Logic.isNotEmpty(data.link) and Link{link = data.link, children = titleText} or titleText + )} +end + return StageWinnings