diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/cache/ExpireObjectCache.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/cache/ExpireObjectCache.java new file mode 100644 index 000000000..c03f5290d --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/cache/ExpireObjectCache.java @@ -0,0 +1,34 @@ +package com.gempukku.lotro.cache; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Guarantees that only one instance of the object will exists, via a synchronized double-check. + * + * @param + * @param + */ +public class ExpireObjectCache { + private Map _cachedObjects = new ConcurrentHashMap(); + + public U getCachedObject(T key, Producable producable) { + U result = _cachedObjects.get(key); + if (result != null) + return result; + + synchronized (this) { + result = _cachedObjects.get(key); + if (result != null) + return result; + + result = producable.produce(key); + _cachedObjects.put(key, result); + return result; + } + } + + public synchronized void clearCache() { + _cachedObjects.clear(); + } +} diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/cache/Producable.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/cache/Producable.java new file mode 100644 index 000000000..ba8d8ead3 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/cache/Producable.java @@ -0,0 +1,5 @@ +package com.gempukku.lotro.cache; + +public interface Producable { + public U produce(T key); +} diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/LeagueDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/LeagueDAO.java index 9dfc69d40..690b2a2fa 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/LeagueDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/LeagueDAO.java @@ -41,21 +41,20 @@ public class LeagueDAO { public List loadActiveLeagues(int currentTime) throws SQLException, IOException { Connection conn = _dbAccess.getDataSource().getConnection(); try { - PreparedStatement statement = conn.prepareStatement("select id, name, type, class, parameters, status, cost from league where end>=? order by start desc"); + PreparedStatement statement = conn.prepareStatement("select name, type, class, parameters, status, cost from league where end>=? order by start desc"); try { statement.setInt(1, currentTime); ResultSet rs = statement.executeQuery(); try { List activeLeagues = new ArrayList(); while (rs.next()) { - int id = rs.getInt(1); - String name = rs.getString(2); - String type = rs.getString(3); - String clazz = rs.getString(4); - String parameters = rs.getString(5); - int status = rs.getInt(6); - int cost = rs.getInt(7); - activeLeagues.add(new League(id, cost, name, type, clazz, parameters, status)); + String name = rs.getString(1); + String type = rs.getString(2); + String clazz = rs.getString(3); + String parameters = rs.getString(4); + int status = rs.getInt(5); + int cost = rs.getInt(6); + activeLeagues.add(new League(cost, name, type, clazz, parameters, status)); } return activeLeagues; } finally { @@ -73,12 +72,12 @@ public class LeagueDAO { try { Connection connection = _dbAccess.getDataSource().getConnection(); try { - String sql = "update league set status=? where id=?"; + String sql = "update league set status=? where type=?"; PreparedStatement statement = connection.prepareStatement(sql); try { statement.setInt(1, newStatus); - statement.setInt(2, league.getId()); + statement.setString(2, league.getType()); statement.execute(); } finally { statement.close(); diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/LeagueMatchDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/LeagueMatchDAO.java index 2bde7428d..7faecd639 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/LeagueMatchDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/LeagueMatchDAO.java @@ -8,7 +8,9 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.*; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; public class LeagueMatchDAO { private DbAccess _dbAccess; @@ -80,41 +82,7 @@ public class LeagueMatchDAO { } } - public Collection getPlayerMatchesPlayedOn(League league, LeagueSerieData leagueSeason, String player) { - try { - Connection conn = _dbAccess.getDataSource().getConnection(); - try { - PreparedStatement statement = conn.prepareStatement("select winner, loser from league_match where league_type=? and season_type=? and (winner=? or loser=?)"); - try { - statement.setString(1, league.getType()); - statement.setString(2, leagueSeason.getName()); - statement.setString(3, player); - statement.setString(4, player); - ResultSet rs = statement.executeQuery(); - try { - Set result = new HashSet(); - 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 void addPlayedMatch(League league, LeagueSerieData leagueSeason, String winner, String loser) { + public void addPlayedMatch(League league, LeagueSerieData leagueSeason, LeagueMatch match) { try { Connection conn = _dbAccess.getDataSource().getConnection(); try { @@ -122,8 +90,8 @@ public class LeagueMatchDAO { try { statement.setString(1, league.getType()); statement.setString(2, leagueSeason.getName()); - statement.setString(3, winner); - statement.setString(4, loser); + statement.setString(3, match.getWinner()); + statement.setString(4, match.getLoser()); statement.execute(); } finally { statement.close(); @@ -135,9 +103,4 @@ public class LeagueMatchDAO { throw new RuntimeException(exp); } } - - private int getCurrentDate() { - Calendar date = new GregorianCalendar(TimeZone.getTimeZone("GMT")); - return date.get(Calendar.YEAR) * 10000 + (date.get(Calendar.MONTH) + 1) * 100 + date.get(Calendar.DAY_OF_MONTH); - } } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/vo/League.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/vo/League.java index cf6889328..64b985901 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/vo/League.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/vo/League.java @@ -5,7 +5,6 @@ import com.gempukku.lotro.league.LeagueData; import java.lang.reflect.Constructor; public class League { - private int _id; private int _cost; private String _name; private String _type; @@ -13,8 +12,7 @@ public class League { private String _parameters; private int _status; - public League(int id, int cost, String name, String type, String clazz, String parameters, int status) { - _id = id; + public League(int cost, String name, String type, String clazz, String parameters, int status) { _cost = cost; _name = name; _type = type; @@ -23,10 +21,6 @@ public class League { _status = status; } - public int getId() { - return _id; - } - public int getCost() { return _cost; } @@ -60,13 +54,13 @@ public class League { League league = (League) o; - if (_id != league._id) return false; + if (_type != null ? !_type.equals(league._type) : league._type != null) return false; return true; } @Override public int hashCode() { - return _id; + return _type != null ? _type.hashCode() : 0; } } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/league/LeagueService.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/league/LeagueService.java index 43594fd80..83501fdc1 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/league/LeagueService.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/league/LeagueService.java @@ -1,6 +1,8 @@ package com.gempukku.lotro.league; import com.gempukku.lotro.DateUtils; +import com.gempukku.lotro.cache.ExpireObjectCache; +import com.gempukku.lotro.cache.Producable; import com.gempukku.lotro.collection.CollectionsManager; import com.gempukku.lotro.db.LeagueDAO; import com.gempukku.lotro.db.LeagueMatchDAO; @@ -18,6 +20,7 @@ import java.io.IOException; import java.sql.SQLException; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArraySet; public class LeagueService { private Comparator LEAGUE_STANDING_COMPARATOR = @@ -38,6 +41,9 @@ public class LeagueService { private Map> _playersParticipating = new ConcurrentHashMap>(); private Map> _playersNotParticipating = new ConcurrentHashMap>(); + private ExpireObjectCache> _cachedLeagueMatches = new ExpireObjectCache>(); + private ExpireObjectCache> _cachedSerieMatches = new ExpireObjectCache>(); + private int _activeLeaguesLoadedDate; private List _activeLeagues; @@ -59,6 +65,8 @@ public class LeagueService { private synchronized void ensureLoadedCurrentLeagues() { int currentDate = DateUtils.getCurrentDate(); if (currentDate != _activeLeaguesLoadedDate) { + _cachedLeagueMatches.clearCache(); + try { _activeLeagues = _leagueDao.loadActiveLeagues(currentDate); _activeLeaguesLoadedDate = currentDate; @@ -71,6 +79,26 @@ public class LeagueService { } } + private Collection getLeagueMatches(final League league) { + return _cachedLeagueMatches.getCachedObject(league, + new Producable>() { + @Override + public Collection produce(League key) { + return new CopyOnWriteArraySet(_leagueMatchDao.getLeagueMatches(league)); + } + }); + } + + private Collection getLeagueSerieMatches(final League league, final LeagueSerieData serie) { + return _cachedSerieMatches.getCachedObject(serie, + new Producable>() { + @Override + public Collection produce(LeagueSerieData key) { + return new CopyOnWriteArraySet(_leagueMatchDao.getLeagueSerieMatches(league, serie)); + } + }); + } + public List getActiveLeagues() { if (DateUtils.getCurrentDate() == _activeLeaguesLoadedDate) return Collections.unmodifiableList(_activeLeagues); @@ -174,7 +202,8 @@ public class LeagueService { } public void reportLeagueGameResult(League league, LeagueSerieData serie, String winner, String loser) { - _leagueMatchDao.addPlayedMatch(league, serie, winner, loser); + addMatch(league, serie, winner, loser); + _leaguePointsDao.addPoints(league, serie, winner, 2); _leaguePointsDao.addPoints(league, serie, loser, 1); _leagueStandings.remove(league); @@ -184,9 +213,16 @@ public class LeagueService { awardPrizesToPlayer(league, serie, loser, false); } + private void addMatch(League league, LeagueSerieData serie, String winner, String loser) { + LeagueMatch match = new LeagueMatch(winner, loser); + _leagueMatchDao.addPlayedMatch(league, serie, match); + getLeagueMatches(league).add(match); + getLeagueSerieMatches(league, serie).add(match); + } + private void awardPrizesToPlayer(League league, LeagueSerieData serie, String player, boolean winner) { int count = 0; - Collection playerMatchesPlayedOn = _leagueMatchDao.getPlayerMatchesPlayedOn(league, serie, player); + Collection playerMatchesPlayedOn = getPlayerMatchesInSerie(league, serie, player); for (LeagueMatch leagueMatch : playerMatchesPlayedOn) { if (leagueMatch.getWinner().equals(player)) count++; @@ -201,6 +237,16 @@ public class LeagueService { _collectionsManager.addItemsToPlayerCollection(player, new CollectionType("permanent", "My cards"), prize.getAll()); } + private Collection getPlayerMatchesInSerie(League league, LeagueSerieData serie, String player) { + final Collection allMatches = getLeagueSerieMatches(league, serie); + Set result = new HashSet(); + for (LeagueMatch match : allMatches) { + if (match.getWinner().equals(player) || match.getLoser().equals(player)) + result.add(match); + } + return result; + } + public List getLeagueStandings(League league) { List leagueStandings = _leagueStandings.get(league); if (leagueStandings == null) { @@ -225,14 +271,14 @@ public class LeagueService { private List createLeagueSerieStandings(League league, LeagueSerieData leagueSerie) { final Map points = _leaguePointsDao.getLeagueSeriePoints(league, leagueSerie); - final Collection matches = _leagueMatchDao.getLeagueSerieMatches(league, leagueSerie); + final Collection matches = getLeagueSerieMatches(league, leagueSerie); return createStandingsForMatchesAndPoints(points, matches); } private List createLeagueStandings(League league) { final Map points = _leaguePointsDao.getLeaguePoints(league); - final Collection matches = _leagueMatchDao.getLeagueMatches(league); + final Collection matches = getLeagueMatches(league); return createStandingsForMatchesAndPoints(points, matches); } @@ -304,14 +350,14 @@ public class LeagueService { public boolean canPlayRankedGame(League league, LeagueSerieData season, String player) { int maxMatches = season.getMaxMatches(); - Collection playedInSeason = _leagueMatchDao.getPlayerMatchesPlayedOn(league, season, player); + Collection playedInSeason = getPlayerMatchesInSerie(league, season, player); if (playedInSeason.size() >= maxMatches) return false; return true; } public boolean canPlayRankedGame(League league, LeagueSerieData season, String playerOne, String playerTwo) { - Collection playedInSeason = _leagueMatchDao.getPlayerMatchesPlayedOn(league, season, playerOne); + Collection playedInSeason = getPlayerMatchesInSerie(league, season, playerOne); for (LeagueMatch leagueMatch : playedInSeason) { if (playerTwo.equals(leagueMatch.getWinner()) || playerTwo.equals(leagueMatch.getLoser())) return false;