"A Round"
A round isn't a standard thing in Freon, even more than in TAM. A round could be over in seconds with everyone frozen, or go on for a long time with people being thawed over and over again in overtime. Sure, overtime starts at 120 seconds...but the round can just go on and on and on and on. A good player's contribution to a short round might be extreme. They might kill all 3 players on the ennemy team and score...what?...5 points?...and have a PPR of 5. A bad player could score more than that on a long round after dying 30 times just by spamming in the general direction of the enemy and get a higher PPR.
Average PPR
This is shown in the last column of the scoreboard. This is simple and easy to understand. You think. It's the average PPR over a number of games you've played on the server.
However it's not that easy. It doesn't take into account the map or the number of players in the game at the time. To remove the worst excesses of this I introduced a setting which can tell the server to not store stats for any match where there were not more than "n" players. We have this set to 5. Any match with fewer than 6 players is not counted.
If I only played Contrast or Goose, where you can thaw a lot my PPR would be about 15. If I only played open hitscan maps then it would be about 3. It sort of evens out over time....
The PPR that is stored is the Current PPR at the time the game ends or you leave. That value is not calculated very well at all:
Current PPR
This is shown in the first column of the scoreboard. It's supposed to show how well you're doing in this game so far. This is what the code currently has (up to today):
if("number of whole rounds played" > 0)
"What is shown" = "your Score" / "number of whole rounds played"
else
"What is shown" = "your Score"
The first problem is that it doesn't give a sensible number. For example:
If in the first 20 seconds of the first round of 120 seconds you score 5 points, it will show PPR = 5. By the time you hit overtime (after 120 seconds), if you continue scoring at that rate, then it will show PPR of 30 - even though your rate of scoring has not changed at any point in that round.
Ignore overtime for now. Assume the round ends after 120 seconds.
In the subsequent rounds the calculation uses the number of whole rounds played in the calculation of PPR. So, in the first second of the 2nd round, before you score your PPR is still 30. If you keep scoring at 5 points per 20 seconds in the second round then by overtime in that second round you've scored 60 points. The calculation for PPR says that you are scoring at a rate of "your Score / number of whole rounds played" = 60/1: you are shown as having 60 PPR.
We've become used to that in-game. As we've played a lot we sort of take that into account as we look at the scoreboard.
Here's the big problem: The balancer uses a combination of "Current PPR" (which is rubbish towards the start of a game) and "Average PPR" (which evens out from a combination of rubbish and good values). This combination gives rise to some of the strange balancing decisions you may have seen on the server. It doesn't matter how good the balancing logic is if the numbers it's using are bad.
PPR used in balancing.
As I mentioned, the balancer uses a combination of "Current PPR" and "Average PPR". We currently use 10% of the "Current PPR" and 90% of the "Average PPR" in the calculations. The idea behind this is that if you are having a bad day or a great day the balancer takes that into account as 10% of the PPR is uses when assigning teams.
From what I have said before, the Current PPR is really bad at certain points that the balancer may make calculations - and this leads to some poor moves to "balance". If your average PPR is 6, but at the moment it does calculation of PPR you are in round 2 with a Current PPR of 60 due to the calcuation I show above then the balancer uses a value of (10% of 60)+(90% of 6) = 11.4.
Thoughts I had to make current PPR "better" tactically.
I know rounds can be over quickly, however many good games have rounds which go into overtime. If we assume that a round "is 120 seconds" (configurable) then we could calculate current PPR like this. The 0.2 is to prevent PPR looking really silly in the first 24 seconds of the map. One good spam into a group of enemies could be multiplied up to a really silly number PPR:
"proportion of current round played" = "round time so far" / 120
If "in overtime" then "proportion of current round played" = 1
if("number of whole rounds played" > 0 or "proportion of current round played" > 0.2)
"What is shown" = "your Score" / ("number of whole rounds played" + "proportion of current round played" )
else
"What is shown" = "your Score"
Thoughts I had to make the PPR value that the balancer uses better:
At the start of the game the current PPR value isn't helpful. There isn't enough information yet to use it. In the same way that I've used 0.2 to ignore the first 24 seconds of the first round for calculating current PPR (showing points instead), for balancing I would propose to use average PPR only for the first 0.2 of a game (24 seconds), and not to take any notice of current PPR.
So - for the first 0.2 of a round you're there, the balancer would use Average PPR to balance you.
After that time it would use the proportion of Current PPR (using the new method of calculation) and Average PPR configured.
I have a version of the code ready to test - now playing on Freon 1 - which shows the new Current PPR using that calculation method, as well as Average PPR and the PPR the balancer is using for you at any point in time. I think it does what I've explained above. If it doesn't work at all, use one of the other freon server (ictf/Freon) and let me know what you see as problematic. Screenshots and helpful information would be apprecoated.
My initial observations.
1. The assumption for PPR purposes is that a round is 120 seconds means that for shorter rounds the current PPR is inflated - it assumes that you will score at your current rate for 120 seconds. It corrects at start of next round.
2. The assumption for PPR purposes is that a round is 120 seconds means that at 120 seconds when overtime starts it stops "predicting" your PPR, and effectively uses your current score in the round as the round total. As the overtime continues your PPR reflects the points you actually scored in rounds. It has no idea how long overtime could be so it can't predict it any longer.
If the definition of PPR is changed to Score per 120 seconds, then it should no longer be called points per round, but points per unit of time.
Regular deathmatch already has this and it's called PPH, but there you respawn instantly.
Most rounds dont last 120seconds or reach overtime, but usually it's 1 minute and 10-20 seconds
Let's test this.
Player1 has avg ppr of 10, Player2 has avg ppr of 5.
Player1 gets 10 score in 30 seconds and dies right after thawing Player2.
Player2 gets 5 score in 20 seconds and dies, gets thawed, doesnt thaw Player1, then another 5 next 40 seconds and dies.
The round lasts for 120 seconds.
Player1 has a PP2M or PPR of 11.
Player2 has a PP2M or PPR of 10.
Next round begins and Player1 gets 10 score in 30 seconds, Player2 gets score of 1.
They both die at 30 seconds.
Round ends.
Player1 has 21 score. Player1 has 16.8 PP2M or 10.5PPR
Player2 has 12 score. Player2 has 9.6 PP2M or 5.5 PPR
hmmmmmm
P.U.?
or
Poo P.U.?
How is average PPR (from previous games) calculated? Does it average all the rounds you played and all the points you scored in those rounds? Or the average PPR per game, averaged over the number of games? How long a history?
One thing I've often noticed is how easily the value drops (if for instance you join for last round and don't score, you lose a whole point from AvePPR), whereas it takes a long time to increase. I lost 2 points early this week because I joined in last round, someone ressed me seconds before end of game, and next game my phone went off and had to be answered around the end of first round. A big reduction for 2 rounds of partial play..
Hi Jozz,
The back end code appears to select the average of the last 20 maps in which you played for at least one round:
SELECT AVG('score'/'rounds') AS ppr FROM (SELECT 'score','rounds' FROM gamestats WHERE server_id=us AND player_id=you AND rounds>0 ORDER BY timestamp DESC LIMIT 20 AS t1");
That "rounds > 0" looks bad to me. If you just joined for a very short time at the end of the round and then left when the next round started it would give a low number
I might increase that number of rounds to include only when you've played more rounds....perhaps 3 or 4? More?
Edit: let's try with 4 or more rounds needed to count towards average PPR
Excellent, I knew there was something fishy there, that will fix a lot!
Kops will have a higher PPR in future for instance :D
I get scared if my ppr >3
If the distrubution of the appr over different maps is not normally distributed the median value could result in better results... It would "remove" extremeties from both the low and high end of ppr.
Are you any good with stats?
Here's an extract of score, number of rounds, and player ID across every recorded entry where the player has played at least 4 rounds:
https://hax.miasma.rocks/data.csv
If you can work out a better indicative PPR method than averaging the last 20, please let me know.
..and yes, we've had a 45 round game of freon....
Quote from: Piglet on August 07, 2020, 12:50
..
The first problem is that it doesn't give a sensible number. For example:
If in the first 20 seconds of the first round of 120 seconds you score 5 points, it will show PPR = 5. By the time you hit overtime (after 120 seconds), if you continue scoring at that rate, then it will show PPR of 30 - even though your rate of scoring has not changed at any point in that round.
Ignore overtime for now. Assume the round ends after 120 seconds.
..
120 is just the standard round time - after which overtime starts
so the 'round' may take 30 seconds or 300 seconds,. but it's still a round?
I think it's not perfect,. and I may be persuaded to some other method but I don't see what advantage there is to points per time unit,. or whatever,.
some games I meet the same shooter, die and spend a lot of time froze,. other games I meet different players and alive,. so if we extend it further we could count the points made in the time whilst alive (am not actually suggesting that)
PPR has advantage,. it's easy to understand and it mostly works for balancing
the balancer at 10% current seems pretty good mostly,. restricting the ability to call 'teams' actually had made games fun,. rather than someone keep typing teams every time one side is a couple of rounds ahead
imagine if the balancer was 'perfect' and each side had same chance if everyone played at their standard,. - well that's not how it works,. sometimes you have a good game and other times not so much,. but overcoming an imbalance are actually the most fun and rewarding games,. like "we kicked a$$ and their team was stacked"
will see what it does I guess :)
Quote from: Piglet on August 07, 2020, 17:12
That "rounds > 0" looks bad to me. If you just joined for a very short time at the end of the round and then left when the next round started it would give a low number
I might increase that number of rounds to include only when you've played more rounds....perhaps 3 or 4? More?
Edit: let's try with 4 or more rounds needed to count towards average PPR
Ah - that kind of change I can get behind,. I think TR's 3psn has a similar function,... PPR is only recorded at the end when you played 4 rounds and that makes sense (it's easy to come in near the end of the game kick a$$ for 2 rounds and end up with lot higher than normal PPR)
It was easier to add into the back-end than the game. I might retro-fit it into the game
ah - I say TR 3psn - but they did something likely in what was the backend - they ditched the standalone PHP and made the PPR stuff run within the game server (at least that's how it was explained to me)
but adding it in the php stuff is just as good / could be configurable from the php / mysql side
actually,. I mentioned before somewhere but I do see an area where the current/avg ppr mix doesn't really work,.
so the idea of adding in current PPR to the mix is to deal with case where player is under or over performing to a significant degree
and that's cool - we can fiddle with the percentage of each PPR type and see what happens (10% is ok I think)
but.. where current PPR is not useful is when a player joins mid-match,. ideally we would apply simply avg PPR for players who recently joined (e.g. within 2 rounds)
current PPR doesn't need to be mixed in for players just joined (if that makes sense)
That's certainly doable, and makes a lot of sense. It takes me a few rounds to get up to speed. If it used my initial PPR rather than something closer to my average to assign teams that wouldn't be right for long.
I'll have a think... Maybe make it configurable
I upped the percentage to 30% yesterday to see how it worked... I'll find a screenshot showing how it worked last night when holy spam and wife were both playing really well
Like i said it makes no sense to have the PPR shown be anything other than (your_points/rounds_played), visually PPR should remain as is.
Now it's just weird, first few rounds i get 10 points with 15 ppr, then round 10+ i get 100 points and 8 ppr
The balancer does need a change. Average PPR is useful for the initial balance, but someone might play much better or worse depending on a lot of factors. A static percentage doesnt help, when you're under/overperforming.
The downside with using more of current PPR is that anyone over/underperforming will probably be switched or swapped.
Forcing everyone to play near their average by bringing good players down and bad players up, making the game much more competitive for all players.
Using a dynamic weight for current_PPR based on Played_rounds is much better.
First round/Initial balance will always use (1 x AVG_PPR) for balancing.
The 3SPN formula is
BALANCER_PPR = (A x AVG_PPR + B x CUR_PPR)
Where A + B always equals 1, for every player, round and game.
Using this instead:
Lerp( FClamp( Played_Rounds / RToBal , 0, AutoBalanceCurPPRWeightMax/100 ), PRI.AvgPPR, PPR )
we can ensure that teams will be balanced depending on each player's current PPR up to AutoBalanceCurPPRWeightMax %, after "RToBal" rounds passed
Now you get perfectly balanced teams (as all things should be, let's call this Thanos!!)
In your example, you only get 15ppr showing if you get those 10 points in early in the round, the round doesn't go to overtime and you don't score any points towards the end of round.
Look again at the problem I posed with the old current PPR:
a) if you scored 10 points in the first round and another 10 points to the point of overtime in the second round then the old calculation would show you a PPR of 20, while my calculation would show a PPR of 10
b) if you scored 10 points in the first round and another 5 points at 60 seconds into the second round then the old calculation could show you with a PPR of 15, while my new calculation would show a PPR of 10
Of course, my calculation assumes that the current round will go to overtime: if the second round ended at 60 seconds in then my calculation would immediately drop your PPR from 10 to 15/2 = 7.5 at the start of the next round - and if you didn't score any points over the round your PPR would start to slowly drop as the round went on, until at the end of the round you would have a PPR of 15/3 = 5. The old calculation could leave you at 7.5 all the way through to the start of the 4th round....and at the that point would reset you to 5 PPR. You'd be balanced by the old balancer logic as if you were playing at 20 when you were actually playing at 10, or 7.5 when you were actually playing at 5 PPR. My version uses the more accurate numbers.
The assumption that rounds last until overtime affects all players equally.
In practice most rounds reach overtime or close to overtime so the calculations are pretty sensible. This is a snapshot part way through a high scoring map. The bot is playing badly - and has reduced PPR. The players are playing above their average PPR (due to the map) the ones who are doing particularly well are showing that the balancer considers them to be the better players. The better they are playing "now" the more the average PPR is raised:
(https://miasma.rocks/images/ppr.jpg)
Quote from: holyspam on August 08, 2020, 15:33
The downside with using more of current PPR is that anyone over/underperforming will probably be switched or swapped.
The balancer aims to swap players to get as close to the same average team PPR as it can. The times I saw it swap yesterday it picked exactly the right player to fill the gap. Once it was you! I don't think there is any correlation between playing better or worse and being picked for the swap. It doesn't know whether you're playing better or worse at the point of choosing. It's just working with the numbers in the last column (well - not exactly as it doesn't take current PPR into account until you've played at least 24 seconds).
PPR = points per round
New_PPR = points per 120seconds
Quote from: holyspam on August 08, 2020, 16:33
PPR = points per round
New_PPR = points per 120seconds
No. It the new calculation assumes only that the
current round will last 120 seconds.
Old PPR is:a. "Points scored so far", when in round 1
b. "The total of (all points scored in round 1 and all points scored so far in round 2)", when in round 2
c. In round 3 onwards "(The total of all points scored, including the ones scored so far in this round) divided by (one less than the round number you're in).
(Yes, I know b and c are the same calculation - but the impact is greater in round 2).
New PPR is:Your total points in the game / (number of rounds played + "the proportion (up to a whole round) of this round played assuming that the current round will last 120 seconds")
Quote from: Piglet on August 08, 2020, 16:51
Quote from: holyspam on August 08, 2020, 16:33
PPR = points per round
New_PPR = points per 120seconds
No. It the new calculation assumes only that the current round will last 120 seconds.
Old PPR is:
a. "Points scored so far", when in round 1
b. "The total of (all points scored in round 1 and all points scored so far in round 2)", when in round 2
c. In round 3 onwards "(The total of all points scored, including the ones scored so far in this round) divided by (one less than the round number you're in).
(Yes, I know b and c are the same calculation - but the impact is greater in round 2).
New PPR is:
Your total points in the game / (number of rounds played + "the proportion (up to a whole round) of this round played assuming that the current round will last 120 seconds")
So if i get 70 score in round 1 but the round lasts 240 seconds, my PPR is still 70 right?
it changes nothing for twice the duration just for partial rounds.
So it's points per 120 seconds with an asterisk, where overtime is not included.
My ppr after a 30 second first round becomes 10 score divided by 30/120 = 10/0.25 = 25 New_PPR
So when we have overtime it should drop but it doesnt.
So it's not Points per round, it's not points per 120 seconds, it's something arbitrary that has no meaning
I think you need to read my posts above a little more carefully.
there is another area in balancer that is flawed (or could be better)
Quote from: Piglet on August 08, 2020, 16:28
The balancer aims to swap players to get as close to the same average team PPR as it can.
yeah and for match starts - especially on a full server it works fairly well
where it breaks and is very noticeable is mid or late joining "A" players, say match is 7 players Vs 8 players,. new A player joins in the slot available (balancer is called automatically for players over avgPPR 6)
what happens is it doesn't do the same balancing as it would at match start,. the team the A player joined they typically aren't switched - so you can end up with multiple A players on that same side
I added in some randomness on the balancer option to help shake things up when clearly things aren't right
need to look at the balancing code again because it has an idea of 'sticky players'
what it should do (it might already do some of this but I'm not sure)
increase likelihood for switching players who joined - so the more round you played the less chance of being switched (I mean the reason the call the balancer mid-game after player joins is because they are on the wrong side)
the other thing,.. the balancer doesn't care about the score,. it's trying to make the PPRs equal,. however - the reason you call the balancer mid game is generally because either an A or B player joined on the wrong side or it's very obvious one side is like 5 rounds ahead
How about make the balancer care about the score in some situations,.,
example idea (perhaps this is overly complicated!)
step 1 - if the PPR difference between teams is less then 1 PPR (if PPRs are more than 1 do the normal balance for PPR/avgPPR)
step 2 - look at the scoreline - if the scoreline is more than 3 different then switch a midPPR / C player on leading side with a lowPPR / C player on trailing side
(if the scoreline is within 3 difference just do the normal PPR balance stuff)
Quote from: Piglet on August 08, 2020, 17:14
I think you need to read my posts above a little more carefully.
I think you need to join ingame and see what's displayed.
Quote from: holyspam on August 08, 2020, 17:21
Quote from: Piglet on August 08, 2020, 17:14
I think you need to read my posts above a little more carefully.
I think you need to join ingame and see what's displayed.
I have done - and not seen anything odd, except for where the numbers are inflated (for everyone) where the first round ends before 120 seconds.
Other than the example above, detail another example of where you see a problem worse than the old code which reported up to double the actual PPR and was only updated once a round.
You said "The downside with using more of current PPR is that anyone over/underperforming will probably be switched or swapped." - which isn't true, so I'm genuinely interested in the issue you see that actually exists.
Quote from: hagis on August 08, 2020, 17:20
there is another area in balancer that is flawed (or could be better)
Yeah - I've not made changes to the balancer itself in this revision. What I've done is make the values it use more accurate when current PPR is included in the mix. Rather than using current PPR which includes all of this round's score, but not the fact that this round is being played I've included this round's score estimated to what you would get if you carried on scoring at that rate to overtime.
Hmmm...while I was typing that I had a thought. We could get round Holyspam's concerns by totally ignoring all points from the current round:
In round 1, show score as PPR (and use AVE PPR in balancing in place of current PPR as there isn't enough data to say what PPR people will be playing at)
In round 2 onwards show PPR = average score in all completed rounds so far. (Start to use that in balancer after n rounds...where n>0)
That might be better, and removes the need to make any assumptions about how long a round would go on.
Quote from: hagis on August 08, 2020, 17:20
need to look at the balancing code again because it has an idea of 'sticky players'
Sticky player code isn't actually used. It's there in the code. It's meant to work - but it doesn't. I fixed the bug in it a while back and it was rubbish. It meant that players weren't swapped more than once in a game - leading to the wrong player being picked to balance. I backed out the fix and left it how it was!
I'm going to try the stategy in orange above.
That removes the problem in trying to work out how far through the round you are. Instead, just ignore the current round.
Old code includes the score from the current round, but still divides by the number of whole rounds which have been completed.
This orange strategy updates current PPR once a round, but based on whole rounds and only on points that have been scored in those rounds.
Yeah. That works. I'm happier with that. Removes the old problem without introducing a new one.
Quote from: hagis on August 08, 2020, 17:20
need to look at the balancing code again because it has an idea of 'sticky players'
The code I think you're talking about is in Team_GameBase->FindBestAutoBalanceCandidate():
// move player that closest matches the required PPR gap / number of players needed
for(C=Level.ControllerList; C!=None; C=C.NextController)
{
// Skip players who are on the don't switch list.
//Note: (Piglet) This is the code as I found it. Surely the "continue" on this iterator has no effect!
for(i=0; i<DontAutoBalanceList.Length; ++i) {
if(DontAutoBalanceList[i] == C)
continue;
}
....more stuff around checking the player and seeing if they are the "right one" to move...
}
The problem with that code is that it's pointless. It doesn't work. The "continue" just tells the code to skip to the next item in the DontAutoBalanceList and not the next controller in the ControllerList.
To make it work as intended this is the code I tried and then commented back out as it meant that a worse player was selected for swapping:
...same stuff...
// Skip players who are on the don't switch list. Note:(Piglet) Made this change to make the code work, but the players hated it. The 'wrong' player was swapped leaving the teams unbalanced. Reverting to investigate further some time.
for(i=0; i<DontAutoBalanceList.Length; ++i) {
if(DontAutoBalanceList[i] == C)
break;
}
if(i<DontAutoBalanceList.Length)
continue;
...same stuff...
Players are sorted by their PPR for balancing, not sure about dontautobalancelist, so if you do for i=3 it will skip the 3 highest pprs, in the balancelist
I think it would be better to remove all the balance code from 3spn and split that on a standalone mutator, but i have no idea how mutators hook with each other, maybe a standalone class.
No. The DontAutoBalanceList has no effect whatsoever. The code is bugging and results in it doing nothing.
If the code related to DontAutoBalanceList wasn't in there at all the game would play no differently in any way