deepy / glicko2

glicko2 implementation in python
Other
33 stars 14 forks source link

Documentation available? #1

Open Crypto-Spartan opened 4 years ago

Crypto-Spartan commented 4 years ago

Hi!

This is a really cool project. I am looking to implement this in some portions of code that I have. Is there any sort of documentation to show how to use it?

Thanks!

deepy commented 4 years ago

Hi @Crypto-Spartan I guess the tests would be the best place to start, they're pretty short! But I'll try to remember to add some examples to the readme tonight.

deepy commented 4 years ago

Looking at the interesting part from the tests we have a player being created, rating deviation being set to 200 and 3 matches being registered:

If you're implementing a ranked board you don't need to worry about most of these and after a match just p1.update_rating(p2.rating, p2.rd, 1) (although make sure to store p1s rating and rd before update player to apply to p2)

import glicko2
P1 = glicko2.Player()
P1.setRd(200)
P1.update_player([1400, 1550, 1700], [30, 100, 300], [1, 0, 0])
print(P1.rating)
Crypto-Spartan commented 4 years ago

Perfect!

Can this also be used to create balanced teams as well, or is this only for keeping track of player's glicko ratings?

deepy commented 4 years ago

I haven't personally used it in any way for non-static teams (only static teams where each team was represented as a player) and unfortunately I don't even know of a free/open or public domain rating system with support for teams. But if you should find one, please let me know!

deepy commented 4 years ago

Although if you're in charge of matchmaking between teams and got a large pool of players there's a bunch of ideas I can think of and if your teams are small or there's 1v1 matches there's some other things you can make use of

Crypto-Spartan commented 4 years ago

Looking to implement it for 5v5 matches. So far the player pool is small, most I've had is 50 players

shubhank008 commented 4 years ago

Having a improved Readme and documentation with some examples would be really great to have, specially for newbies to glicko as this seems to be the only python repo upto date and being maintained.

In the example, the RD is being set to 200 manually. But if I am not wrong, at end of player rating updation/evaluation (P1.rating), do we also get a updated RD (P1.rd) ?
And if so, should we be saving it in a DB or somewhere and use this updated/stored value instead of passing a fixed RD value of 200 for next match ?

I am trying to understand this in terms of a 1v1 game (chess)

Looking at the interesting part from the tests we have a player being created, rating deviation being set to 200 and 3 matches being registered:

  • a win against a 1400 player with 30 rating deviation
  • a loss against 1550 with 100 rd
  • a loss against 1700 with 300 rd

If you're implementing a ranked board you don't need to worry about most of these and after a match just p1.update_rating(p2.rating, p2.rd, 1) (although make sure to store p1s rating and rd before update player to apply to p2)

import glicko2
P1 = glicko2.Player()
P1.setRd(200)
P1.update_player([1400, 1550, 1700], [30, 100, 300], [1, 0, 0])
print(P1.rating)
deepy commented 4 years ago

I guess the example isn't great as you'd usually pass initial values to glicko2.Player() https://github.com/deepy/glicko2/blob/master/glicko2/glicko2.py#L50 if you want a custom initial value (e.g. Player(rd=200))

But yes, update_player() changes rating, rating deviation, and volatility. If you are storing a representation of the player then you need to store all 3 of these.

You'd also need to register a loss on the other side with the values from P1 before doing update_player()

shubhank008 commented 4 years ago

I guess the example isn't great as you'd usually pass initial values to glicko2.Player() https://github.com/deepy/glicko2/blob/master/glicko2/glicko2.py#L50 if you want a custom initial value (e.g. Player(rd=200))

But yes, update_player() changes rating, rating deviation, and volatility. If you are storing a representation of the player then you need to store all 3 of these.

You'd also need to register a loss on the other side with the values from P1 before doing update_player()

  1. Yes, the initial values would be provisional rating/rd if new player or player's last generated stats right ?
  2. Yes, wanted to confirm it.
  3. "You'd also need to register a loss on the other side with the values from P1 before doing update_player()" Did not understand this, what do you mean ? Do you mean register a loss in my game logic or register a loss in glicko2 (your repo) ?

If I am not wrong, actual boilerplate code should look like this ?

import glicko2
P1 = glicko2.Player()     ##this should be run empty for first match and then glicko2.Player(currentRating, currentRD, currentVol)
## This code I believe is run after a match ends and the PAST_MATCHES will include data for this current ended match too ?
P1.update_player([ALL_PAST_MATCHES_P1_RATING], [ALL_PAST_MATCHES_P1_RD], [ALL_PAST_MATCHES_P1_WIN_LOSS])
print(P1.rating)             ##We store this in our DB or somewhere to be next for next computation in P1_Rating and P1_RD ?  

^^The same is run for P2 as well

However, if I run above code after current match ends, how or where do I provide win/loss data from this recent match to recompute ?

deepy commented 4 years ago

This module really only gives you the glicko2 part, you're going to have to handle wins/losses and history yourself. I guess there might be a case for adding a method like win/lose to the Player object that takes another Player and updates both of them, but I'm not sure that'd be overly useful for the average user (since you're likely going to do that already, and also be interested in the change in values).

The way I'm using it is that I'm storing the history and the players in my database, when there's a new result I retrieve both players and update them accordingly, then I update the database with the new values for the players and store the new history entry.

shubhank008 commented 4 years ago

This module really only gives you the glicko2 part, you're going to have to handle wins/losses and history yourself. I guess there might be a case for adding a method like win/lose to the Player object that takes another Player and updates both of them, but I'm not sure that'd be overly useful for the average user (since you're likely going to do that already, and also be interested in the change in values).

The way I'm using it is that I'm storing the history and the players in my database, when there's a new result I retrieve both players and update them accordingly, then I update the database with the new values for the players and store the new history entry.

No no, obviously the win/loss and history logic is user/app side and not by this repo, I meant if I am managing them as a example of chess game.
What I meant to ask was, when a match chess ends and we store that match data and win status, we call the above code after saving the game status right ? So that ended match is also counted towards calculating the rating.
However, for this recent match we only know win status (1 or 0). So won't using this match data also mean we will have non-uniform count of ratings, rd and win/loss stats.
Example: Currently history has record of 9 matches, their win/loss status and how the rating/rd changed after that match.
Now when the 10th match ends, we will have win/loss record for 10 matches but rating/rd for still 9 matches (as 10th match needs to be calculated now), so how does that work. Basically, what I am asking is, when passing rating/rd/win-loss data, do their count need to be same ?

How is your history or records structured ?
And do we use same code template as P1 but for P2 for this ? "You'd also need to register a loss on the other side with the values from P1 before doing update_player()"

deepy commented 4 years ago

If you got 2 players playing against each other you're going to need to call update_player() twice and you're going to need to use the rating and rd from before calling update_player()

My personal usage is real-time so I only ever have one game to update, my history is id, winner_id, loser_id with the latter two being foreignkey'd to the player table

mrkvicka22 commented 1 year ago

Hi @Crypto-Spartan I guess the tests would be the best place to start, they're pretty short! But I'll try to remember to add some examples to the readme tonight.

he in fact did not remember...