More accurate league results calculation.

This commit is contained in:
marcins78@gmail.com
2012-01-25 15:47:43 +00:00
parent 1e9ac0c24e
commit b0e94bd4cd
6 changed files with 298 additions and 84 deletions

View File

@@ -17,6 +17,69 @@ public class LeagueMatchDAO {
_dbAccess = dbAccess;
}
public Collection<LeagueMatch> getLeagueMatches(League league) {
try {
Connection conn = _dbAccess.getDataSource().getConnection();
try {
PreparedStatement statement = conn.prepareStatement("select winner, loser from league_match where league_type=?");
try {
statement.setString(1, league.getType());
ResultSet rs = statement.executeQuery();
try {
Set<LeagueMatch> result = new HashSet<LeagueMatch>();
while (rs.next()) {
String winner = rs.getString(1);
String loser = rs.getString(2);
result.add(new LeagueMatch(winner, loser));
}
return result;
} finally {
rs.close();
}
} finally {
statement.close();
}
} finally {
conn.close();
}
} catch (SQLException exp) {
throw new RuntimeException(exp);
}
}
public Collection<LeagueMatch> getLeagueSerieMatches(League league, LeagueSerie leagueSerie) {
try {
Connection conn = _dbAccess.getDataSource().getConnection();
try {
PreparedStatement statement = conn.prepareStatement("select winner, loser from league_match where league_type=? and season_type=?");
try {
statement.setString(1, league.getType());
statement.setString(2, leagueSerie.getType());
ResultSet rs = statement.executeQuery();
try {
Set<LeagueMatch> result = new HashSet<LeagueMatch>();
while (rs.next()) {
String winner = rs.getString(1);
String loser = rs.getString(2);
result.add(new LeagueMatch(winner, loser));
}
return result;
} finally {
rs.close();
}
} finally {
statement.close();
}
} finally {
conn.close();
}
} catch (SQLException exp) {
throw new RuntimeException(exp);
}
}
public Collection<LeagueMatch> getPlayerMatchesPlayedOn(League league, LeagueSerie leagueSeason, String player) {
try {
Connection conn = _dbAccess.getDataSource().getConnection();

View File

@@ -7,17 +7,12 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class LeaguePointsDAO {
private DbAccess _dbAccess;
private Map<League, List<Standing>> _leagueStandings = new ConcurrentHashMap<League, List<Standing>>();
private Map<LeagueSerie, List<Standing>> _serieStandings = new ConcurrentHashMap<LeagueSerie, List<Standing>>();
public LeaguePointsDAO(DbAccess dbAccess) {
_dbAccess = dbAccess;
}
@@ -42,23 +37,9 @@ public class LeaguePointsDAO {
} catch (SQLException exp) {
throw new RuntimeException(exp);
}
_leagueStandings.remove(league);
_serieStandings.remove(serie);
}
public List<Standing> getLeagueStandings(League league) {
List<Standing> standings = _leagueStandings.get(league);
if (standings == null) {
synchronized (this) {
standings = loadLeagueStandings(league);
_leagueStandings.put(league, standings);
}
}
return standings;
}
private List<Standing> loadLeagueStandings(League league) {
public Map<String, Points> getLeaguePoints(League league) {
try {
Connection conn = _dbAccess.getDataSource().getConnection();
try {
@@ -67,14 +48,7 @@ public class LeaguePointsDAO {
statement.setString(1, league.getType());
ResultSet rs = statement.executeQuery();
try {
List<Standing> result = new LinkedList<Standing>();
while (rs.next()) {
String playerName = rs.getString(1);
int sumPoints = rs.getInt(2);
int gamesPlayed = rs.getInt(3);
result.add(new Standing(playerName, sumPoints, gamesPlayed));
}
return result;
return createPoints(rs);
} finally {
rs.close();
}
@@ -89,18 +63,18 @@ public class LeaguePointsDAO {
}
}
public List<Standing> getSerieStandings(League league, LeagueSerie serie) {
List<Standing> standings = _serieStandings.get(serie);
if (standings == null) {
synchronized (this) {
standings = loadSerieStandings(league, serie);
_serieStandings.put(serie, standings);
}
private Map<String, Points> createPoints(ResultSet rs) throws SQLException {
Map<String, Points> result = new HashMap<String, Points>();
while (rs.next()) {
String playerName = rs.getString(1);
int sumPoints = rs.getInt(2);
int gamesPlayed = rs.getInt(3);
result.put(playerName, new Points(sumPoints, gamesPlayed));
}
return standings;
return result;
}
private List<Standing> loadSerieStandings(League league, LeagueSerie serie) {
public Map<String, Points> getLeagueSeriePoints(League league, LeagueSerie serie) {
try {
Connection conn = _dbAccess.getDataSource().getConnection();
try {
@@ -110,14 +84,7 @@ public class LeaguePointsDAO {
statement.setString(2, serie.getType());
ResultSet rs = statement.executeQuery();
try {
List<Standing> result = new LinkedList<Standing>();
while (rs.next()) {
String playerName = rs.getString(1);
int sumPoints = rs.getInt(2);
int gamesPlayed = rs.getInt(3);
result.add(new Standing(playerName, sumPoints, gamesPlayed));
}
return result;
return createPoints(rs);
} finally {
rs.close();
}
@@ -132,13 +99,11 @@ public class LeaguePointsDAO {
}
}
public static class Standing {
private String _player;
public static class Points {
private int _points;
private int _gamesPlayed;
public Standing(String player, int points, int gamesPlayed) {
_player = player;
public Points(int points, int gamesPlayed) {
_points = points;
_gamesPlayed = gamesPlayed;
}
@@ -147,10 +112,6 @@ public class LeaguePointsDAO {
return _gamesPlayed;
}
public String getPlayer() {
return _player;
}
public int getPoints() {
return _points;
}

View File

@@ -11,13 +11,23 @@ import com.gempukku.lotro.game.LotroGameMediator;
import com.gempukku.lotro.logic.timing.GameResultListener;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class LeagueService {
private Comparator<LeagueStanding> LEAGUE_STANDING_COMPARATOR =
new MultipleComparator<LeagueStanding>(
new DescComparator<LeagueStanding>(new PointsComparator()),
new GamesPlayedComparator(),
new DescComparator<LeagueStanding>(new OpponentsWinComparator()));
private LeagueDAO _leagueDao;
private LeagueSerieDAO _leagueSeasonDao;
private LeaguePointsDAO _leaguePointsDao;
private LeagueMatchDAO _leagueMatchDao;
private Map<League, List<LeagueStanding>> _leagueStandings = new ConcurrentHashMap<League, List<LeagueStanding>>();
private Map<LeagueSerie, List<LeagueStanding>> _leagueSerieStandings = new ConcurrentHashMap<LeagueSerie, List<LeagueStanding>>();
public LeagueService(LeagueDAO leagueDao, LeagueSerieDAO leagueSeasonDao, LeaguePointsDAO leaguePointsDao, LeagueMatchDAO leagueMatchDao) {
_leagueDao = leagueDao;
_leagueSeasonDao = leagueSeasonDao;
@@ -53,6 +63,7 @@ public class LeagueService {
_leagueMatchDao.addPlayedMatch(league, serie, winnerPlayerId, loser);
_leaguePointsDao.addPoints(league, serie, winnerPlayerId, 2);
_leaguePointsDao.addPoints(league, serie, loser, 1);
_leagueStandings.remove(league);
}
});
gameMediator.sendMessageToPlayers("This is a ranked game in " + league.getName());
@@ -61,6 +72,88 @@ public class LeagueService {
}
}
public List<LeagueStanding> getLeagueStandings(League league) {
List<LeagueStanding> leagueStandings = _leagueStandings.get(league);
if (leagueStandings == null) {
synchronized (this) {
leagueStandings = createLeagueStandings(league);
_leagueStandings.put(league, leagueStandings);
}
}
return leagueStandings;
}
public List<LeagueStanding> getLeagueSerieStandings(League league, LeagueSerie leagueSerie) {
List<LeagueStanding> serieStandings = _leagueSerieStandings.get(leagueSerie);
if (serieStandings == null) {
synchronized (this) {
serieStandings = createLeagueStandings(league);
_leagueSerieStandings.put(leagueSerie, serieStandings);
}
}
return serieStandings;
}
private List<LeagueStanding> createLeagueSerieStandings(League league, LeagueSerie leagueSerie) {
final Map<String, LeaguePointsDAO.Points> points = _leaguePointsDao.getLeagueSeriePoints(league, leagueSerie);
final Collection<LeagueMatch> matches = _leagueMatchDao.getLeagueSerieMatches(league, leagueSerie);
return createStandingsForMatchesAndPoints(points, matches);
}
private List<LeagueStanding> createLeagueStandings(League league) {
final Map<String, LeaguePointsDAO.Points> points = _leaguePointsDao.getLeaguePoints(league);
final Collection<LeagueMatch> matches = _leagueMatchDao.getLeagueMatches(league);
return createStandingsForMatchesAndPoints(points, matches);
}
private List<LeagueStanding> createStandingsForMatchesAndPoints(Map<String, LeaguePointsDAO.Points> points, Collection<LeagueMatch> matches) {
Map<String, List<String>> playerOpponents = new HashMap<String, List<String>>();
for (LeagueMatch leagueMatch : matches) {
appendPlayer(playerOpponents, leagueMatch.getWinner(), leagueMatch.getLoser());
appendPlayer(playerOpponents, leagueMatch.getLoser(), leagueMatch.getWinner());
}
List<LeagueStanding> leagueStandings = new LinkedList<LeagueStanding>();
for (Map.Entry<String, LeaguePointsDAO.Points> playerPoints : points.entrySet()) {
LeagueStanding standing = new LeagueStanding(playerPoints.getKey(), playerPoints.getValue().getPoints(), playerPoints.getValue().getGamesPlayed());
List<String> opponents = playerOpponents.get(playerPoints.getKey());
int opponentWins = 0;
int opponentGames = 0;
for (String opponent : opponents) {
final LeaguePointsDAO.Points opponentPoints = points.get(opponent);
opponentWins += opponentPoints.getPoints() - opponentPoints.getGamesPlayed();
opponentGames += opponentPoints.getGamesPlayed();
}
standing.setOpponentWin(opponentWins * 1f / opponentGames);
leagueStandings.add(standing);
}
Collections.sort(leagueStandings, LEAGUE_STANDING_COMPARATOR);
int standing = 0;
int position = 1;
LeagueStanding lastStanding = null;
for (LeagueStanding leagueStanding : leagueStandings) {
if (lastStanding == null || LEAGUE_STANDING_COMPARATOR.compare(lastStanding, lastStanding) != 0)
standing = position;
leagueStanding.setStanding(standing);
position++;
lastStanding = leagueStanding;
}
return leagueStandings;
}
private void appendPlayer(Map<String, List<String>> playerOpponents, String player, String opponent) {
List<String> opponents = playerOpponents.get(player);
if (opponents == null) {
opponents = new LinkedList<String>();
playerOpponents.put(player, opponents);
}
opponents.add(opponent);
}
public boolean canPlayRankedGame(League league, LeagueSerie season, String player) {
int maxMatches = season.getMaxMatches();
Collection<LeagueMatch> playedInSeason = _leagueMatchDao.getPlayerMatchesPlayedOn(league, season, player);
@@ -97,4 +190,61 @@ public class LeagueService {
}
return true;
}
private class MultipleComparator<T> implements Comparator<T> {
private Comparator<T>[] _comparators;
public MultipleComparator(Comparator<T>... comparators) {
_comparators = comparators;
}
@Override
public int compare(T o1, T o2) {
for (Comparator<T> comparator : _comparators) {
int result = comparator.compare(o1, o2);
if (result != 0)
return result;
}
return 0;
}
}
private class DescComparator<T> implements Comparator<T> {
private Comparator<T> _comparator;
private DescComparator(Comparator<T> comparator) {
_comparator = comparator;
}
@Override
public int compare(T o1, T o2) {
return _comparator.compare(o2, o1);
}
}
private class PointsComparator implements Comparator<LeagueStanding> {
@Override
public int compare(LeagueStanding o1, LeagueStanding o2) {
return o1.getPoints() - o2.getPoints();
}
}
private class GamesPlayedComparator implements Comparator<LeagueStanding> {
@Override
public int compare(LeagueStanding o1, LeagueStanding o2) {
return o1.getGamesPlayed() - o2.getGamesPlayed();
}
}
private class OpponentsWinComparator implements Comparator<LeagueStanding> {
@Override
public int compare(LeagueStanding o1, LeagueStanding o2) {
final float diff = o1.getOpponentWin() - o2.getOpponentWin();
if (diff < 0)
return -1;
if (diff > 0)
return 1;
return 0;
}
}
}

View File

@@ -0,0 +1,43 @@
package com.gempukku.lotro.league;
public class LeagueStanding {
private String _playerName;
private int _points;
private int _gamesPlayed;
private float _opponentWin;
private int _standing;
public LeagueStanding(String playerName, int points, int gamesPlayed) {
_playerName = playerName;
_points = points;
_gamesPlayed = gamesPlayed;
}
public int getGamesPlayed() {
return _gamesPlayed;
}
public float getOpponentWin() {
return _opponentWin;
}
public String getPlayerName() {
return _playerName;
}
public int getPoints() {
return _points;
}
public int getStanding() {
return _standing;
}
public void setOpponentWin(float opponentWin) {
_opponentWin = opponentWin;
}
public void setStanding(int standing) {
_standing = standing;
}
}

View File

@@ -1,10 +1,11 @@
package com.gempukku.lotro.server;
import com.gempukku.lotro.db.LeagueDAO;
import com.gempukku.lotro.db.LeaguePointsDAO;
import com.gempukku.lotro.db.LeagueSerieDAO;
import com.gempukku.lotro.db.vo.League;
import com.gempukku.lotro.db.vo.LeagueSerie;
import com.gempukku.lotro.league.LeagueService;
import com.gempukku.lotro.league.LeagueStanding;
import com.sun.jersey.spi.resource.Singleton;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -15,6 +16,7 @@ import javax.ws.rs.core.Context;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.text.DecimalFormat;
import java.util.List;
@Singleton
@@ -23,9 +25,9 @@ public class LeagueResource extends AbstractResource {
@Context
private LeagueDAO _leagueDao;
@Context
private LeagueSerieDAO _leagueSerieDao;
private LeagueService _leagueService;
@Context
private LeaguePointsDAO _leaguePointsDao;
private LeagueSerieDAO _leagueSerieDao;
@GET
public Document getLeagueInformation() throws ParserConfigurationException {
@@ -50,24 +52,20 @@ public class LeagueResource extends AbstractResource {
serieElem.setAttribute("start", String.valueOf(serie.getStart()));
serieElem.setAttribute("end", String.valueOf(serie.getEnd()));
final List<LeaguePointsDAO.Standing> standings = _leaguePointsDao.getSerieStandings(league, serie);
for (LeaguePointsDAO.Standing standing : standings) {
final List<LeagueStanding> standings = _leagueService.getLeagueSerieStandings(league, serie);
for (LeagueStanding standing : standings) {
Element standingElem = doc.createElement("standing");
standingElem.setAttribute("player", standing.getPlayer());
standingElem.setAttribute("points", String.valueOf(standing.getPoints()));
standingElem.setAttribute("gamesPlayed", String.valueOf(standing.getGamesPlayed()));
setStandingAttributes(standing, standingElem);
serieElem.appendChild(standingElem);
}
leagueElem.appendChild(serieElem);
}
List<LeaguePointsDAO.Standing> leagueStandings = _leaguePointsDao.getLeagueStandings(league);
for (LeaguePointsDAO.Standing standing : leagueStandings) {
List<LeagueStanding> leagueStandings = _leagueService.getLeagueStandings(league);
for (LeagueStanding standing : leagueStandings) {
Element standingElem = doc.createElement("leagueStanding");
standingElem.setAttribute("player", standing.getPlayer());
standingElem.setAttribute("points", String.valueOf(standing.getPoints()));
standingElem.setAttribute("gamesPlayed", String.valueOf(standing.getGamesPlayed()));
setStandingAttributes(standing, standingElem);
leagueElem.appendChild(standingElem);
}
@@ -78,4 +76,13 @@ public class LeagueResource extends AbstractResource {
return doc;
}
private void setStandingAttributes(LeagueStanding standing, Element standingElem) {
standingElem.setAttribute("player", standing.getPlayerName());
standingElem.setAttribute("standing", String.valueOf(standing.getStanding()));
standingElem.setAttribute("points", String.valueOf(standing.getPoints()));
standingElem.setAttribute("gamesPlayed", String.valueOf(standing.getGamesPlayed()));
DecimalFormat format = new DecimalFormat("##0.00%");
standingElem.setAttribute("opponentWin", format.format(standing.getOpponentWin()));
}
}

View File

@@ -83,40 +83,30 @@ var LeagueResultsUI = Class.extend({
createStandingsTable: function(standings) {
var standingsTable = $("<table class='standings'></table>");
standingsTable.append("<tr><th>Standing</th><th>Player</th><th>Points</th><th>Games played</th><th></th><th>Standing</th><th>Player</th><th>Points</th><th>Games played</th></tr>");
var lastPoints = -1;
var lastGamesPlayed = -1;
var currentStanding = -1;
standingsTable.append("<tr><th>Standing</th><th>Player</th><th>Points</th><th>Games played</th><th>Opp. Win %</th><th></th><th>Standing</th><th>Player</th><th>Points</th><th>Games played</th><th>Opp. Win %</th></tr>");
var secondColumnBaseIndex = Math.ceil(standings.length / 2);
for (var k = 0; k < secondColumnBaseIndex; k++) {
var standing = standings[k];
var currentStanding = standing.getAttribute("standing");
var player = standing.getAttribute("player");
var points = parseInt(standing.getAttribute("points"));
var gamesPlayed = parseInt(standing.getAttribute("gamesPlayed"));
if (points != lastPoints || gamesPlayed != lastGamesPlayed) {
lastPoints = points;
lastGamesPlayed = gamesPlayed;
currentStanding = k + 1;
}
var opponentWinPerc = standing.getAttribute("opponentWin");
standingsTable.append("<tr><td>" + currentStanding + "</td><td>" + player + "</td><td>" + points + "</td><td>" + gamesPlayed + "</td></tr>");
standingsTable.append("<tr><td>" + currentStanding + "</td><td>" + player + "</td><td>" + points + "</td><td>" + gamesPlayed + "</td><td>" + opponentWinPerc + "</td></tr>");
}
for (var k = secondColumnBaseIndex; k < standings.length; k++) {
var standing = standings[k];
var currentStanding = standing.getAttribute("standing");
var player = standing.getAttribute("player");
var points = parseInt(standing.getAttribute("points"));
var gamesPlayed = parseInt(standing.getAttribute("gamesPlayed"));
if (points != lastPoints || gamesPlayed != lastGamesPlayed) {
lastPoints = points;
lastGamesPlayed = gamesPlayed;
currentStanding = k + 1;
}
var opponentWinPerc = standing.getAttribute("opponentWin");
$("tr:eq(" + (k - secondColumnBaseIndex + 1) + ")", standingsTable).append("<td></td><td>" + currentStanding + "</td><td>" + player + "</td><td>" + points + "</td><td>" + gamesPlayed + "</td>");
$("tr:eq(" + (k - secondColumnBaseIndex + 1) + ")", standingsTable).append("<td></td><td>" + currentStanding + "</td><td>" + player + "</td><td>" + points + "</td><td>" + gamesPlayed + "</td><td>" + opponentWinPerc + "</td>");
}
return standingsTable;