Let the rating repository accept integers rather than Names, and tweak the delegate accordingly. Hrm, does this handle guests correctly, actually?

git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@348 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
Par Winzell
2007-07-05 23:18:44 +00:00
parent a78c1a35d9
commit 3484e8cd1f
2 changed files with 46 additions and 51 deletions
@@ -98,9 +98,9 @@ public abstract class RatingManagerDelegate
int gameId = _gmgr.getGameConfig().getGameId(); int gameId = _gmgr.getGameConfig().getGameId();
// enumerate our players // enumerate our players
Name[] players = new Name[_gmgr.getPlayerCount()]; Integer[] players = new Integer[_gmgr.getPlayerCount()];
for (int ii = 0; ii < players.length; ii ++) { for (int ii = 0; ii < players.length; ii ++) {
players[ii] = _gmgr.getPlayerName(ii); players[ii] = _gmgr.getPlayerPersistentId(_gmgr.getPlayer(ii));
} }
try { try {
@@ -116,7 +116,7 @@ public abstract class RatingManagerDelegate
// now build the array we keep around until the end of the game // now build the array we keep around until the end of the game
_ratings = new Rating[_gmgr.getPlayerCount()]; _ratings = new Rating[_gmgr.getPlayerCount()];
for (int ii = 0; ii < _ratings.length; ii ++) { for (int ii = 0; ii < _ratings.length; ii ++) {
RatingRecord record = map.get(_repo.mapNameToId(_gmgr.getPlayerName(ii))); RatingRecord record = map.get(players[ii]);
// if the player had no previous record, initiate them at default values // if the player had no previous record, initiate them at default values
_ratings[ii] = record != null ? _ratings[ii] = record != null ?
new Rating(record.rating, record.experience) : new Rating(); new Rating(record.rating, record.experience) : new Rating();
@@ -167,12 +167,19 @@ public abstract class RatingManagerDelegate
_ratings[ii].experience ++; _ratings[ii].experience ++;
modified = true; modified = true;
} }
// bail if nothing changed
if (!modified) { if (!modified) {
return; return;
} }
// finally persist the result if necessary // else enumerate our players
final int[] players = new int[_gmgr.getPlayerCount()];
for (int ii = 0; ii < players.length; ii ++) {
players[ii] = _gmgr.getPlayerPersistentId(_gmgr.getPlayer(ii));
}
// and finally persist the result
final int gameId = _gmgr.getGameConfig().getGameId(); final int gameId = _gmgr.getGameConfig().getGameId();
CrowdServer.invoker.postUnit(new Invoker.Unit() { CrowdServer.invoker.postUnit(new Invoker.Unit() {
public boolean invoke () { public boolean invoke () {
@@ -180,9 +187,8 @@ public abstract class RatingManagerDelegate
for (int ii = 0; ii < _ratings.length; ii ++) { for (int ii = 0; ii < _ratings.length; ii ++) {
// for each player, update or create the rating record // for each player, update or create the rating record
// TODO: reorganize things so this can be a single db request? // TODO: reorganize things so this can be a single db request?
_repo.setRating( _repo.setRating(gameId, players[ii], _ratings[ii].rating,
gameId, _gmgr.getPlayerName(ii), _ratings[ii].experience);
_ratings[ii].rating, _ratings[ii].experience);
} }
return true; return true;
@@ -202,23 +208,6 @@ public abstract class RatingManagerDelegate
}); });
} }
/**
* Return the minimum time (in seconds) a game must've lasted for it to count towards rating.
*/
protected abstract int minimumRatedDuration ();
/**
* Return a reference to the {@link RatingRepository} instance we should use to persist.
*/
protected abstract RatingRepository getRatingRepository ();
/**
* Optionally store update ratings in memory e.g. in the user object.
*
* This method is called on the dobj thread.
*/
protected abstract void updateRatingInMemory (int gameId, Name playerName, Rating rating);
/** /**
* Computes a player's updated rating using a modified version of the FIDE/ELO system. * Computes a player's updated rating using a modified version of the FIDE/ELO system.
* The rating adjustment is computed for the player versus each opponent individually and * The rating adjustment is computed for the player versus each opponent individually and
@@ -317,6 +306,24 @@ public abstract class RatingManagerDelegate
} }
} }
/**
* Return the minimum time (in seconds) a game must've lasted for it to count towards rating.
*/
protected abstract int minimumRatedDuration ();
/**
* Return a reference to the {@link RatingRepository} instance we should use to persist.
*/
protected abstract RatingRepository getRatingRepository ();
/**
* Optionally store update ratings in memory e.g. in the user object.
*
* This method is called on the dobj thread.
*/
protected abstract void updateRatingInMemory (int gameId, Name playerName, Rating rating);
/** An appropriately casted reference to our GameManager. */ /** An appropriately casted reference to our GameManager. */
protected GameManager _gmgr; protected GameManager _gmgr;
@@ -31,30 +31,30 @@ import com.samskivert.jdbc.depot.clause.Where;
import com.samskivert.jdbc.depot.operator.Logic.*; import com.samskivert.jdbc.depot.operator.Logic.*;
import com.samskivert.jdbc.depot.operator.Conditionals.*; import com.samskivert.jdbc.depot.operator.Conditionals.*;
import com.threerings.util.Name;
/** /**
* Handles the persistent storage of per-user per-game ratings. * Handles the persistent storage of per-user per-game ratings.
*/ */
public abstract class RatingRepository extends DepotRepository public class RatingRepository extends DepotRepository
{ {
/** /**
* Users are indexed by integer. It is the responsibility of the subclasser to implement * Initialize the {@link RatingRepository}.
* an injective mapping of {@link Name} instance to integer here.
*/ */
public abstract int mapNameToId (Name player); public RatingRepository(ConnectionProvider conprov)
{
super(conprov);
}
/** /**
* Loads the rating for the given player for the given game and returns it as a * Loads the rating for the given player for the given game and returns it as a
* {@link RatingRecord} object, or null if the player has no previous rating for the game. * {@link RatingRecord} object, or null if the player has no previous rating for the game.
*/ */
public RatingRecord getRating (int gameId, Name player) public RatingRecord getRating (int gameId, int playerId)
throws PersistenceException throws PersistenceException
{ {
return load( return load(
RatingRecord.class, RatingRecord.class,
RatingRecord.GAME_ID, gameId, RatingRecord.GAME_ID, gameId,
RatingRecord.PLAYER_ID, mapNameToId(player)); RatingRecord.PLAYER_ID, playerId);
} }
/** /**
@@ -62,44 +62,32 @@ public abstract class RatingRepository extends DepotRepository
* them as a list of {@link RatingRecord} objects. The size of this list is no less than zero * them as a list of {@link RatingRecord} objects. The size of this list is no less than zero
* and no greater than the number of given players. * and no greater than the number of given players.
*/ */
public List<RatingRecord> getRatings (int gameId, Name... players) public List<RatingRecord> getRatings (int gameId, Integer... players)
throws PersistenceException throws PersistenceException
{ {
Comparable[] idArr = new Comparable[players.length];
for (int ii = 0; ii < idArr.length; ii ++) {
idArr[ii] = mapNameToId(players[ii]);
}
return findAll( return findAll(
RatingRecord.class, RatingRecord.class,
new Where(new And( new Where(new And(
new Equals(RatingRecord.GAME_ID, gameId), new Equals(RatingRecord.GAME_ID, gameId),
new In(RatingRecord.PLAYER_ID, idArr)))); new In(RatingRecord.PLAYER_ID, players))));
} }
/** /**
* Fetch and return all the registered {@link RatingRecord} rows for the given player. * Fetch and return all the registered {@link RatingRecord} rows for the given player.
*/ */
public List<RatingRecord> getRatings (Name player) public List<RatingRecord> getRatings (int playerId)
throws PersistenceException throws PersistenceException
{ {
return findAll(RatingRecord.class, new Where(RatingRecord.PLAYER_ID, mapNameToId(player))); return findAll(RatingRecord.class, new Where(RatingRecord.PLAYER_ID, playerId));
} }
/** /**
* Set the rating and experience for a given player and game. This method will either update * Set the rating and experience for a given player and game. This method will either update
* or create a row. * or create a row.
*/ */
public void setRating (int gameId, Name player, int rating, int experience) public void setRating (int gameId, int playerId, int rating, int experience)
throws PersistenceException throws PersistenceException
{ {
store(new RatingRecord(gameId, mapNameToId(player), rating, experience)); store(new RatingRecord(gameId, playerId, rating, experience));
}
/**
* Initialize the {@link RatingRepository}.
*/
protected RatingRepository(ConnectionProvider conprov)
{
super(conprov);
} }
} }