Skip to content
Open
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
107 changes: 97 additions & 10 deletions lua/spec/prize_pool_spec.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
--- Triple Comment to Enable our LLS Plugin
local TeamTemplateMock = require('wikis.commons.Mock.TeamTemplate')
describe('prize pool', function()
local PrizePool = require('Module:PrizePool')
local InfoboxLeague = require('Module:Infobox/League/Custom')
Expand All @@ -13,16 +14,18 @@ describe('prize pool', function()
stub(mw.ext.LiquipediaDB, "lpdb_tournament")
LpdbPlacementStub = stub(mw.ext.LiquipediaDB, "lpdb_placement")
InfoboxLeague.run(tournamentData)
TeamTemplateMock.setUp()
end)

after_each(function ()
LpdbPlacementStub:revert()
---@diagnostic disable-next-line: undefined-field
mw.ext.LiquipediaDB.lpdb:revert()
mw.ext.LiquipediaDB.lpdb_tournament:revert()
TeamTemplateMock.tearDown()
end)

local prizePoolArgs = {
local prizePool1Args = {
type = {type = 'solo'},
currencyroundprecision = 3,
lpdb_prefix = 'abc',
Expand All @@ -39,8 +42,19 @@ describe('prize pool', function()
[2] = {qualified1 = true, [1] = {'Salt'}},
}

local prizePool2Args = {
type = {type = 'team'},
currencyroundprecision = 2,
lpdb_prefix = 'abc',
import = false,
playershare = true,
[1] = {usdprize = '400000', playershare = '200000', [1] = {'mouz'}},
[2] = {usdprize = '1,000', [1] = {'t1'}},
}

it('parameters are correctly parsed', function()
local ppt = PrizePool(prizePoolArgs):create()
local ppt = PrizePool(prizePool1Args):create()
local ppt2 = PrizePool(prizePool2Args):create()

assert.are_same(
{
Expand Down Expand Up @@ -73,6 +87,14 @@ describe('prize pool', function()
},
ppt.prizes
)
assert.are_same(
{
{id = 'BASE_CURRENCY1', type = 'BASE_CURRENCY', index = 1, data = {roundPrecision = 2}},
{id = 'PLAYER_SHARE1', type = 'PLAYER_SHARE', index = 1, data = {title = 'Player Share'}},
{id = 'CLUB_SHARE1', type = 'CLUB_SHARE', index = 1, data = {title = 'Club Share', roundPrecision = 2}},
},
ppt2.prizes
)

assert.are_same(
{
Expand All @@ -96,11 +118,12 @@ describe('prize pool', function()

describe('prize pool is correct', function()
it('display', function()
GoldenTest('prize_pool', tostring(PrizePool(prizePoolArgs):create():build()))
GoldenTest('prize_pool', tostring(PrizePool(prizePool1Args):create():build()))
GoldenTest('prize_pool_player_share', tostring(PrizePool(prizePool2Args):create():build()))
end)

it('lpdb storage', function()
PrizePool(prizePoolArgs):create():build()
PrizePool(prizePool1Args):create():build()
assert.stub(LpdbPlacementStub).was.called_with('ranking_abc1_Rathoz', {
date = '2022-10-15',
extradata = '{"prizepoints":"","prizepoints2":""}',
Expand Down Expand Up @@ -157,42 +180,106 @@ describe('prize pool', function()
type = 'Offline',
qualified = 1,
})

PrizePool(prizePool2Args):create():build()
assert.stub(LpdbPlacementStub).was.called_with('ranking_abc_mouz', {
date = '2022-10-15',
extradata = '{"playershare":200000,"prizepoints":"","prizepoints2":""}',
game = 'commons',
icon = 'test.png',
icondark = 'test dark.png',
image = 'MOUZ allmode.png',
imagedark = 'MOUZ allmode.png',
individualprizemoney = 0,
lastvsdata = '[]',
liquipediatier = '1',
liquipediatiertype = 'Qualifier',
opponentname = 'MOUZ',
opponentplayers = '[]',
opponenttype = 'team',
opponenttemplate = 'mouz 2021',
parent = 'FakePage',
participant = 'MOUZ', -- Legacy
participantlink = 'MOUZ', -- Legacy
participanttemplate = 'mouz 2021',
placement = 1,
players = '[]', -- Legacy
prizemoney = 400000,
prizepoolindex = 2,
series = 'Test Series',
shortname = 'Test Tourney',
startdate = '2022-10-13',
tournament = 'Test Tournament',
type = 'Offline',
qualified = 0,
})
assert.stub(LpdbPlacementStub).was.called_with('ranking_abc_t1', {
date = '2022-10-15',
extradata = '{"prizepoints":"","prizepoints2":""}',
game = 'commons',
icon = 'test.png',
icondark = 'test dark.png',
image = 'T1 2019 allmode.png',
imagedark = 'T1 2019 allmode.png',
individualprizemoney = 0,
lastvsdata = '[]',
liquipediatier = '1',
liquipediatiertype = 'Qualifier',
opponentname = 'T1',
opponentplayers = '[]',
opponenttype = 'team',
opponenttemplate = 't1 2019',
parent = 'FakePage',
participant = 'T1', -- Legacy
participantlink = 'T1', -- Legacy
participanttemplate = 't1 2019',
placement = 2,
players = '[]', -- Legacy
prizemoney = 1000,
prizepoolindex = 2,
series = 'Test Series',
shortname = 'Test Tourney',
startdate = '2022-10-13',
tournament = 'Test Tournament',
type = 'Offline',
qualified = 0,
})
end)
end)

describe('enabling/disabling lpdb storage', function()
it('normal behavior', function()
PrizePool(prizePoolArgs):create():build()
PrizePool(prizePool1Args):create():build()
assert.stub(LpdbPlacementStub).called(2)
end)

it('disabled', function()
PrizePool(Table.merge(prizePoolArgs, {storelpdb = false})):create():build()
PrizePool(Table.merge(prizePool1Args, {storelpdb = false})):create():build()
assert.stub(LpdbPlacementStub).called(0)
end)

it('wiki-var enabled', function()
Variables.varDefine('disable_LPDB_storage', 'false')
PrizePool(prizePoolArgs):create():build()
PrizePool(prizePool1Args):create():build()
assert.stub(LpdbPlacementStub).called(2)
end)

it('wiki-var enabled with override', function()
Variables.varDefine('disable_LPDB_storage', 'false')
PrizePool(Table.merge(prizePoolArgs, {storelpdb = false})):create():build()
PrizePool(Table.merge(prizePool1Args, {storelpdb = false})):create():build()
assert.stub(LpdbPlacementStub).called(0)
end)


it('wiki-var disable with override', function()
Variables.varDefine('disable_LPDB_storage', 'true')
PrizePool(Table.merge(prizePoolArgs, {storelpdb = true})):create():build()
PrizePool(Table.merge(prizePool1Args, {storelpdb = true})):create():build()
assert.stub(LpdbPlacementStub).called(2)
end)

it('wiki-var disable without override', function()
Variables.varDefine('disable_LPDB_storage', 'true')
PrizePool(prizePoolArgs):create():build()
PrizePool(prizePool1Args):create():build()
assert.stub(LpdbPlacementStub).called(0)
end)
end)
Expand Down
Binary file added lua/spec/snapshots/prize_pool_player_share.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
86 changes: 85 additions & 1 deletion lua/wikis/commons/PrizePool/Base.lua
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ local PRIZE_TYPE_QUALIFIES = 'QUALIFIES'
local PRIZE_TYPE_POINTS = 'POINTS'
local PRIZE_TYPE_PERCENTAGE = 'PERCENT'
local PRIZE_TYPE_FREETEXT = 'FREETEXT'
local PRIZE_TYPE_PLAYER_SHARE = 'PLAYER_SHARE'
local PRIZE_TYPE_CLUB_SHARE = 'CLUB_SHARE'

BasePrizePool.config = {
showBaseCurrency = {
Expand Down Expand Up @@ -357,9 +359,55 @@ BasePrizePool.prizeTypes = {
end
end,
},
[PRIZE_TYPE_FREETEXT] = {
[PRIZE_TYPE_PLAYER_SHARE] = {
sortOrder = 60,

header = 'playershare',
headerParse = function (prizePool, input, context, index)
return {title = 'Player Share'}
end,
headerDisplay = function (data)
return TableCell{children = {data.title}}
end,

row = 'playershare',
rowParse = function (placement, input, context, index)
return BasePrizePool._parseInteger(input)
end,
rowDisplay = function (headerData, data)
if data > 0 then
return TableCell{children = {
Currency.display(BASE_CURRENCY, data,
{formatValue = true, formatPrecision = headerData.roundPrecision, displayCurrencyCode = false})
}}
end
end,
},
[PRIZE_TYPE_CLUB_SHARE] = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know valve calls it club share, but this is for all wikis, so we should consider whether there's a better name for it.
There's no other place where we refer to teams as clubs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dota2 is still Valve :D

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its not a term from Valve though.

Originally it was ESL https://www.hltv.org/news/40576/club-financial-incentives-introduced-as-esl-reveals-more-ept-details and then other TO's followed suit.

Maybe an arg to rename the header? but in current context all applciations of a club / team share are called club share across dota, cs.

Its also the term used for Esports World Cup (still ESL eotd) for all titles, not just Valve

sortOrder = 70,
header = 'clubshare',
headerParse = function(prizePool, input, context, index)
return {title = String.isNotEmpty(input) and input or 'Club Share'}
end,
headerDisplay = function(data)
return TableCell{children = {data.title}}
end,
row = 'clubshare',
rowParse = function(placement, input, context, index)
return input
end,
rowDisplay = function(headerData, data)
if data and tonumber(data) > 0 then
return TableCell{children = {
Currency.display(BASE_CURRENCY, data,
{formatValue = true, formatPrecision = headerData.roundPrecision, displayCurrencyCode = false})
}}
end
end,
},
[PRIZE_TYPE_FREETEXT] = {
sortOrder = 80,

header = 'freetext',
headerParse = function (prizePool, input, context, index)
return {title = input}
Expand Down Expand Up @@ -423,6 +471,22 @@ function BasePrizePool:create()
self:setConfig('showBaseCurrency', true)
self:addPrize(PRIZE_TYPE_BASE_CURRENCY, 1, {roundPrecision = self.options.currencyRoundPrecision})

local hasPlayerShare = Array.any(self.prizes, function(prize)
return prize.type == PRIZE_TYPE_PLAYER_SHARE
end)
if hasPlayerShare then
local alreadyHasClubShare = Array.any(self.prizes, function(prize)
return prize.type == PRIZE_TYPE_CLUB_SHARE
end)
if not alreadyHasClubShare then
local clubShareTitle = self.args.clubshare
self:addPrize(PRIZE_TYPE_CLUB_SHARE, 1, {
title = String.isNotEmpty(clubShareTitle) and clubShareTitle or 'Club Share',
roundPrecision = self.options.currencyRoundPrecision
})
end
end

if self.options.autoExchange then
local canConvertCurrency = function(prize)
return prize.type == PRIZE_TYPE_LOCAL_CURRENCY
Expand Down Expand Up @@ -642,6 +706,26 @@ function BasePrizePool:_buildRows()

self:applyToggleExpand(previousPlacement, placement, rows)

-- Calculate club share for the placement
Array.forEach(placement.opponents, function(opponent)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems out of place here. Probably move somewhere into PrizePool/Placement/Base.lua

As an alternative, can require that via input as well. Not sure whether there could be an instance where player+club != total money (e.g. cause there are extras were no split is known)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldnt movement there not allow it to be visually displayed?

Copy link
Collaborator Author

@MischiefCS MischiefCS Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and player+club would always = total (from a Liquipedia stance)

theoretically not all player may go to player, but thats how the rest of the wiki works

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldnt movement there not allow it to be visually displayed?

Don't think so, iirc placements are parsed already

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and player+club would always = total (from a Liquipedia stance)

theoretically not all player may go to player, but thats how the rest of the wiki works

Currently in CS that is the case, but again, this implementation affects all wikis, so I'm considering other (potential) cases as well.

local basePrize
local playerShare
Array.forEach(self.prizes, function(prize)
if prize.type == PRIZE_TYPE_BASE_CURRENCY then
basePrize = opponent.prizeRewards[prize.id] or placement.prizeRewards[prize.id]
return
end
if prize.type == PRIZE_TYPE_PLAYER_SHARE then
playerShare = opponent.prizeRewards[prize.id] or placement.prizeRewards[prize.id]
end
end)
if basePrize and playerShare then
local clubShare = tonumber(basePrize) - tonumber(playerShare)
if not opponent.prizeRewards then opponent.prizeRewards = {} end
opponent.prizeRewards[PRIZE_TYPE_CLUB_SHARE .. '1'] = clubShare
end
end)

local cells = {}
table.insert(cells, self:placeOrAwardCell(placement))

Expand Down
3 changes: 3 additions & 0 deletions lua/wikis/commons/PrizePool/Placement.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ local DASH = '-'
local PRIZE_TYPE_BASE_CURRENCY = 'BASE_CURRENCY'
local PRIZE_TYPE_POINTS = 'POINTS'
local PRIZE_TYPE_QUALIFIES = 'QUALIFIES'
local PRIZE_TYPE_PLAYER_SHARE = 'PLAYER_SHARE'

-- Allowed none-numeric score values.
local SPECIAL_SCORES = {'W', 'FF' , 'L', 'DQ', 'D'}
Expand Down Expand Up @@ -235,6 +236,7 @@ function Placement:_getLpdbData(...)
local pointsReward = self:getPrizeRewardForOpponent(opponent, PRIZE_TYPE_POINTS .. 1)
local pointsReward2 = self:getPrizeRewardForOpponent(opponent, PRIZE_TYPE_POINTS .. 2)
local isQualified = self:getPrizeRewardForOpponent(opponent, PRIZE_TYPE_QUALIFIES .. '1')
local playerShare = tonumber(self:getPrizeRewardForOpponent(opponent, PRIZE_TYPE_PLAYER_SHARE .. 1))

local lpdbData = {
image = image,
Expand Down Expand Up @@ -262,6 +264,7 @@ function Placement:_getLpdbData(...)
participantteam = (opponentType == Opponent.solo and players.p1team)
and Opponent.toName{template = players.p1team, type = 'team', extradata = {}}
or nil,
playershare = playerShare,
},
qualified = isQualified and 1 or 0
-- TODO: We need to create additional LPDB Fields
Expand Down
6 changes: 4 additions & 2 deletions lua/wikis/commons/TeamParticipants/Repository.lua
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,14 @@ function TeamParticipantsRepository.save(participant)
lpdbData.players = lpdbData.opponentplayers

-- Calculate individual prize money (prize money per player on team)
if lpdbData.prizemoney then
-- Opt to use playerShare over prizepool if available
local prizevalue = lpdbData.extradata and lpdbData.extradata.playershare or lpdbData.prizemoney
if prizevalue then
local filteredPlayers = Array.filter(activeOpponent.players, function(player)
return player.extradata.type ~= 'staff'
end)
local numberOfPlayersOnTeam = math.max(#(filteredPlayers), 1)
lpdbData.individualprizemoney = lpdbData.prizemoney / numberOfPlayersOnTeam
lpdbData.individualprizemoney = prizevalue / numberOfPlayersOnTeam
end

mw.ext.LiquipediaDB.lpdb_placement(lpdbData.objectName, Json.stringifySubTables(lpdbData))
Expand Down