ekzhang / setwithfriends

🎮 A frictionless multiplayer web app that lets you play Set with friends
https://setwithfriends.com
MIT License
558 stars 60 forks source link

Game Leaderboards #40

Open ekzhang opened 4 years ago

ekzhang commented 4 years ago

Global leaderboards for various metrics - fastest game played, fastest solo games, best average speed, matchmaking / TrueSkill rating algorithm.

Implementation

HiddeKoerts commented 3 years ago

My thoughts on the issue of dealing with bots: I don't think it is feasible to completely get rid of bots. Of course the really fast bots could easily be ignored, but slower ones would be incredibly difficult to detect. Therefore, I think that tactics should focus on circumventing the problem and deterring the use of bots in public games. Some concrete suggestions:

  1. Limit rankings to users who have played at least some number of games, say 300 (or even behind a paywall).
  2. Introduce an additional gamemode identical to the standard game, except that bots are encouraged. The idea would be that it'd discourage people from using bots in normal games. I'm not sure whether this will backfire and just result in the development of more bots to be used in both though.
  3. Let moderators ban people who use obvious bots in public games (of course a dangerous balancing act). The current number of moderators may not be sufficient for that to be an effective approach.

All in all, it is a very difficult problem. I'd say none of the suggestions I made are ideal, nor would they be sufficient to solve the issue.

ekzhang commented 3 years ago

Related: #96

ekzhang commented 3 years ago

Update: We can implement game leaderboards now using the finishGame() function. Seems like most players are interested in time leaderboards and rating leaderboards.

HiddeKoerts commented 3 years ago

My thoughts as I was working on the issue:

There are likely too many player accounts to re-sort all the accounts based on their rating / best time every time the leaderboards are requested. So one would have to store the leaderboards somehow and efficiently updating. For best times, this wouldn't be all that difficult. In finishGame() we could check whether a player has beaten their best and then update their entry in the leaderboard (likely in something like a linked list), accordingly. The idea would be that this wouldn't change all that often, as personal records are quite stable. For ratings, this wouldn't hold, as they're extremely volatile. Updating the leaderboards atomically (in the chosen datastructure), would be required after basically every game. I'm not sure how problematic this would be. Moreover, to be able to indicate the position on the leaderboard for an individual player, one would need to store a reference to the position in the player's account, and efficiently be able to find the index of an entry in the leaderboard datastructure. It is not logical to do this clientside, as that would mean a lot of data to transmit.

One could also choose to only store a limited leaderboard (say the top 100). For the best times this would be pretty simple, as they can only improve for a given account. For ratings, this would be a lot more difficult, as someone could also drop out of the top 100 if they lose a few games (and thus someone else should enter the top 100).

Another option, that I find quite enticing, is to not update the leaderboards directly after games at all. Instead, one could run a cronjob once a day or something similar, which would compute the position on the leaderboard of every player and store it on the player object (as well as the top 100 for separate displaying for example). The enticing option here is that you could include more heavy computations, such as generating distribution graphs.

In the end these are probably more in the direction of design choices, rather than one option being clearly superior.