2009-09-22 05:37:08 UTC
I just checked in an update that does this. (It was somewhat easier than I thought it would be.)
It's basically what I wrote above, except for step 4. Since the ratings system for a game should be static, there's no reason to keep calling getRatingSystem() each time a game ends. So, instead I've added a constructor for the ServerController that takes a parameter which is the rating system to use for the game. The old constructor without the new parameter will create a standard ELO rating system, so games that don't need this functionality don't change at all.
There are three ways to use this:
a) In the server directory for your game, create a new file xxxRatingSystem.java that implements IRatingSystem. Then, in your xxxServerController constructor, do this:
public xxxServerController (String gameKey) {
super (gameKey, new xxxRatingSystem());
}
or b) Make the xxxServerController itself implement the IRatingSystem interface, and then in the constructor do this:
public xxxServerController (String gameKey) {
super (gameKey);
gameRatingSystem = this;
}
or c) create a private class within the xxxServerController that implements the IRatingSystem, and change the constructor to be:
public xxxServerController (String gameKey) {
super (gameKey);
gameRatingSystem = new customRatingSystem();
}
For cases b & c, you can't use the new constructor because you're not allowed to use "this" or private classes in the call to super(). So, in those cases, you need to set the gameRatingSystem field directly.
In any case, to use the new rating system, whenever any of the gameOver() methods is called by the server controller, the getNewRatings() of your custom rating system will be called with the array of current ratings and the array of WIN/LOSE statuses. You then need to return the new ratings.
For example, a simple custom rating system for a two player game might be:
public int[] getNewRatings(int[] currentRatings, int[] results, Object customData) {
int [] newRatings = new int [2];
newRatings[0] = currentRatings[0];
newRatings[1] = currentRatings[1];
if (results[0] == IGameOver.WIN) {
// Player 0 wins
newRatings[0] += 10;
newRatings[1] -= 5;
} else if (results[0] == IGameOver.LOSE) {
// Player 1 wins
newRatings[1] += 10;
newRatings[0] -= 5;
}
return newRatings;
}
This will add 10 points to the rating of the winner and subtract 5 points from the rating of the loser.
The initial rating to give to new users is still defined in the server.xml file within the game using the <elo startRating="x"> field, regardless of rating system. I'm thinking of changing the tag from "elo" to "rating" because it's now a generic rating system, but haven't decided whether to do that or not.
The customData field of getNewRatings allows a game to provide more data to the rating system than just the results, if you need such functionality.
I hope this is clear. Let me know if you need any more help with explanations.
-Richard