Tournament queues, seems to work.

This commit is contained in:
marcins78@gmail.com
2012-07-03 21:46:08 +00:00
parent 5e5211e07d
commit 66d84b05e8
15 changed files with 215 additions and 51 deletions

View File

@@ -96,6 +96,34 @@ public class DbTournamentDAO implements TournamentDAO {
}
}
@Override
public List<TournamentInfo> getFinishedTournamentsSince(long time) {
try {
Connection connection = _dbAccess.getDataSource().getConnection();
try {
PreparedStatement statement = connection.prepareStatement("select tournament_id, class, parameters, start from tournament where finished=true and start>?");
try {
statement.setLong(1, time);
ResultSet rs = statement.executeQuery();
try {
List<TournamentInfo> result = new ArrayList<TournamentInfo>();
while (rs.next())
result.add(new TournamentInfo(rs.getString(1), rs.getString(2), rs.getString(3), new Date(rs.getLong(4))));
return result;
} finally {
rs.close();
}
} finally {
statement.close();
}
} finally {
connection.close();
}
} catch (SQLException exp) {
throw new RuntimeException(exp);
}
}
@Override
public void markTournamentFinished(String tournamentId) {
try {

View File

@@ -133,7 +133,7 @@ public class DbTournamentPlayerDAO implements TournamentPlayerDAO {
PreparedStatement statement = connection.prepareStatement("select deck_name, deck from tournament_player where tournament_id=? and player=?");
try {
statement.setString(1, tournamentId);
statement.setString(2, tournamentId);
statement.setString(2, playerName);
ResultSet rs = statement.executeQuery();
try {
if (rs.next())

View File

@@ -30,6 +30,7 @@ public class LotroGameMediator {
private int _maxSecondsForGamePerPlayer = 60 * 80; // 80 minutes
private boolean _noSpectators;
private boolean _cancellable;
// private final int _maxSecondsForGamePerPlayer = 60 * 40; // 40 minutes
private final int _channelInactivityTimeoutPeriod = 1000 * 60 * 5; // 5 minutes
private final int _playerDecisionTimeoutPeriod = 1000 * 60 * 10; // 10 minutes
@@ -40,9 +41,10 @@ public class LotroGameMediator {
private int _channelNextIndex = 0;
public LotroGameMediator(LotroFormat lotroFormat, LotroGameParticipant[] participants, LotroCardBlueprintLibrary library, int maxSecondsForGamePerPlayer,
boolean noSpectators) {
boolean noSpectators, boolean cancellable) {
_maxSecondsForGamePerPlayer = maxSecondsForGamePerPlayer;
_noSpectators = noSpectators;
_cancellable = cancellable;
if (participants.length < 1)
throw new IllegalArgumentException("Game can't have less than one participant");
@@ -271,6 +273,9 @@ public class LotroGameMediator {
}
public void cancel(Player player) {
if (!_cancellable)
_userFeedback.sendWarning(player.getName(), "You can't cancel this game");
String playerId = player.getName();
_writeLock.lock();
try {

View File

@@ -127,7 +127,8 @@ public class LotroServer extends AbstractServer {
throw new IllegalArgumentException("There has to be at least two players");
final String gameId = String.valueOf(_nextGameId);
boolean noSpectators = false;
boolean noSpectators = competetive;
boolean cancellable = !competetive;
if (noSpectators) {
Set<String> allowedUsers = new HashSet<String>();
@@ -138,7 +139,7 @@ public class LotroServer extends AbstractServer {
_chatServer.createChatRoom(getChatRoomName(gameId), 30);
LotroGameMediator lotroGameMediator = new LotroGameMediator(lotroFormat, participants, _lotroCardBlueprintLibrary,
competetive ? 60 * 40 : 60 * 80, noSpectators);
competetive ? 60 * 40 : 60 * 80, noSpectators, cancellable);
lotroGameMediator.addGameResultListener(
new GameResultListener() {
@Override

View File

@@ -62,7 +62,7 @@ public class HallServer extends AbstractServer {
_runningTournaments.addAll(tournamentService.getLiveTournaments());
_tournamentQueues.put("fotr_queue", new SingleEliminationRecurringQueue(0, _formatLibrary.getFormat("fotr_block"),
_tournamentQueues.put("fotr_queue", new SingleEliminationRecurringQueue(0, "fotr_block",
new CollectionType("default", "All cards"), "fotrQueue-", "Fellowship Block", 2,
tournamentService));
}
@@ -175,7 +175,7 @@ public class HallServer extends AbstractServer {
if (tournamentQueue.isPlayerSignedUp(player.getName()))
throw new HallException("You have already joined that queue");
LotroDeck lotroDeck = validateUserAndDeck(tournamentQueue.getLotroFormat(), player, deckName, tournamentQueue.getCollectionType());
LotroDeck lotroDeck = validateUserAndDeck(_formatLibrary.getFormat(tournamentQueue.getFormat()), player, deckName, tournamentQueue.getCollectionType());
tournamentQueue.joinPlayer(_collectionsManager, player, lotroDeck);
@@ -281,7 +281,7 @@ public class HallServer extends AbstractServer {
String tournamentQueueKey = tournamentQueueEntry.getKey();
TournamentQueue tournamentQueue = tournamentQueueEntry.getValue();
visitor.visitTournamentQueue(tournamentQueueKey, tournamentQueue.getCollectionType().getFullName(),
tournamentQueue.getLotroFormat().getName(), tournamentQueue.getTournamentQueueName(),
tournamentQueue.getFormat(), tournamentQueue.getTournamentQueueName(),
tournamentQueue.getPlayerCount(), tournamentQueue.isPlayerSignedUp(player.getName()));
}

View File

@@ -49,7 +49,7 @@ public abstract class AbstractTournament implements Tournament {
_playersInContention.removeAll(_tournamentService.getDroppedPlayers(tournamentId));
int round = 1;
while (!isFinished()) {
while (true) {
List<TournamentMatch> matches = _tournamentService.getMatches(tournamentId, round);
if (matches.size() > 0) {
Map<String, String> gamesToCreate = new HashMap<String, String>();
@@ -71,9 +71,16 @@ public abstract class AbstractTournament implements Tournament {
break;
}
} else {
_nextTask = new PairPlayers();
if (isFinished())
break;
if (round == 1)
_nextTask = new StartTournament();
else
_nextTask = new PairPlayers();
break;
}
round++;
}
}
@@ -209,6 +216,27 @@ public abstract class AbstractTournament implements Tournament {
new LotroGameParticipant(playerTwo, _playerDecks.get(playerTwo)));
}
private class StartTournament implements TournamentTask {
@Override
public void executeTask(TournamentCallback tournamentCallback) {
tournamentCallback.broadcastMessage("Tournament " + getTournamentName() + " is starting");
_playersInContention.removeAll(_droppedPlayers);
_droppedPlayers.clear();
if (isFinished()) {
finishTournament(tournamentCallback);
} else {
_currentRound++;
pairPlayers(tournamentCallback);
}
}
@Override
public long getExecuteAfter() {
return 0;
}
}
private class PairPlayers implements TournamentTask {
private long _taskStart = System.currentTimeMillis() + 1000 * 60 * 2;

View File

@@ -3,7 +3,6 @@ package com.gempukku.lotro.tournament;
import com.gempukku.lotro.DateUtils;
import com.gempukku.lotro.collection.CollectionsManager;
import com.gempukku.lotro.db.vo.CollectionType;
import com.gempukku.lotro.game.LotroFormat;
import com.gempukku.lotro.game.Player;
import com.gempukku.lotro.logic.vo.LotroDeck;
@@ -13,7 +12,7 @@ import java.util.Map;
public class SingleEliminationRecurringQueue implements TournamentQueue {
private int _cost;
private LotroFormat _lotroFormat;
private String _format;
private CollectionType _collectionType;
private String _tournamentQueueName;
private CollectionType _currencyCollection = new CollectionType("permanent", "My cards");
@@ -25,9 +24,9 @@ public class SingleEliminationRecurringQueue implements TournamentQueue {
private TournamentService _tournamentService;
private String _tournamentIdPrefix;
public SingleEliminationRecurringQueue(int cost, LotroFormat lotroFormat, CollectionType collectionType, String tournamentIdPrefix, String tournamentQueueName, int playerCap, TournamentService tournamentService) {
public SingleEliminationRecurringQueue(int cost, String format, CollectionType collectionType, String tournamentIdPrefix, String tournamentQueueName, int playerCap, TournamentService tournamentService) {
_cost = cost;
_lotroFormat = lotroFormat;
_format = format;
_collectionType = collectionType;
_tournamentQueueName = tournamentQueueName;
_playerCap = playerCap;
@@ -36,8 +35,8 @@ public class SingleEliminationRecurringQueue implements TournamentQueue {
}
@Override
public LotroFormat getLotroFormat() {
return _lotroFormat;
public String getFormat() {
return _format;
}
@Override
@@ -57,7 +56,7 @@ public class SingleEliminationRecurringQueue implements TournamentQueue {
String tournamentName = _tournamentQueueName + " - " + DateUtils.getStringDateWithHour();
String parameters = _lotroFormat.getName() + "," + _collectionType.getCode() + "," + _collectionType.getFullName() + "," + tournamentName;
String parameters = _format + "," + _collectionType.getCode() + "," + _collectionType.getFullName() + "," + tournamentName;
for (Map.Entry<String, LotroDeck> playerDeck : _playerDecks.entrySet())
_tournamentService.addPlayer(tournamentId, playerDeck.getKey(), playerDeck.getValue());

View File

@@ -10,5 +10,7 @@ public interface TournamentDAO {
public List<TournamentInfo> getUnfinishedTournaments();
public List<TournamentInfo> getFinishedTournamentsSince(long time);
public TournamentInfo getTournamentById(String tournamentId);
}

View File

@@ -2,12 +2,11 @@ package com.gempukku.lotro.tournament;
import com.gempukku.lotro.collection.CollectionsManager;
import com.gempukku.lotro.db.vo.CollectionType;
import com.gempukku.lotro.game.LotroFormat;
import com.gempukku.lotro.game.Player;
import com.gempukku.lotro.logic.vo.LotroDeck;
public interface TournamentQueue {
public LotroFormat getLotroFormat();
public String getFormat();
public CollectionType getCollectionType();

View File

@@ -63,12 +63,23 @@ public class TournamentService {
_tournamentDao.markTournamentFinished(tournamentId);
}
public List<Tournament> getOldTournaments(long since) {
List<Tournament> result = new ArrayList<Tournament>();
for (TournamentInfo tournamentInfo : _tournamentDao.getFinishedTournamentsSince(since)) {
Tournament tournament = _tournamentById.get(tournamentInfo.getTournamentId());
if (tournament == null)
tournament = createTournamentAndStoreInCache(tournamentInfo.getTournamentId(), tournamentInfo);
result.add(tournament);
}
return result;
}
public List<Tournament> getLiveTournaments() {
List<Tournament> result = new ArrayList<Tournament>();
for (TournamentInfo tournamentInfo : _tournamentDao.getUnfinishedTournaments()) {
Tournament tournament = _tournamentById.get(tournamentInfo.getTournamentId());
if (tournament == null)
tournament = createTournamentAndStoreInCache(tournament.getTournamentId(), tournamentInfo);
tournament = createTournamentAndStoreInCache(tournamentInfo.getTournamentId(), tournamentInfo);
result.add(tournament);
}
return result;

View File

@@ -53,6 +53,37 @@ public class TournamentResource extends AbstractResource {
for (Tournament tournament : _tournamentService.getLiveTournaments()) {
Element tournamentElem = doc.createElement("tournament");
tournamentElem.setAttribute("id", tournament.getTournamentId());
tournamentElem.setAttribute("name", tournament.getTournamentName());
tournamentElem.setAttribute("format", _lotroFormatLibrary.getFormat(tournament.getFormat()).getName());
tournamentElem.setAttribute("collection", tournament.getCollectionType().getFullName());
tournamentElem.setAttribute("round", String.valueOf(tournament.getCurrentRound()));
tournamentElem.setAttribute("finished", String.valueOf(tournament.isFinished()));
tournaments.appendChild(tournamentElem);
}
doc.appendChild(tournaments);
return doc;
}
@Path("/history")
@GET
public Document getHistoryTournaments(
@QueryParam("participantId") String participantId,
@Context HttpServletRequest request,
@Context HttpServletResponse response) throws ParserConfigurationException {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document doc = documentBuilder.newDocument();
Element tournaments = doc.createElement("tournaments");
for (Tournament tournament : _tournamentService.getOldTournaments(System.currentTimeMillis() - (1000 * 60 * 24 * 7))) {
Element tournamentElem = doc.createElement("tournament");
tournamentElem.setAttribute("id", tournament.getTournamentId());
tournamentElem.setAttribute("name", tournament.getTournamentName());
tournamentElem.setAttribute("format", _lotroFormatLibrary.getFormat(tournament.getFormat()).getName());
tournamentElem.setAttribute("collection", tournament.getCollectionType().getFullName());
@@ -86,6 +117,7 @@ public class TournamentResource extends AbstractResource {
Element tournamentElem = doc.createElement("tournament");
tournamentElem.setAttribute("id", tournament.getTournamentId());
tournamentElem.setAttribute("name", tournament.getTournamentName());
tournamentElem.setAttribute("format", _lotroFormatLibrary.getFormat(tournament.getFormat()).getName());
tournamentElem.setAttribute("collection", tournament.getCollectionType().getFullName());
@@ -118,7 +150,7 @@ public class TournamentResource extends AbstractResource {
if (tournament == null)
sendError(Response.Status.NOT_FOUND);
if (tournament.isFinished())
if (!tournament.isFinished())
sendError(Response.Status.FORBIDDEN);
LotroDeck deck = _tournamentService.getPlayerDeck(tournamentId, playerName);

View File

@@ -19,6 +19,11 @@
font-weight: bolder;
}
.tournamentName {
font-size: 200%;
font-weight: bolder;
}
.serieName {
font-size: 150%;
font-weight: bolder;
@@ -226,11 +231,11 @@
var infoDialog = $("<div></div>")
.dialog({
autoOpen:false,
closeOnEscape:true,
resizable:false,
title:"Card information"
});
autoOpen:false,
closeOnEscape:true,
resizable:false,
title:"Card information"
});
$("body").click(
function (event) {

View File

@@ -2,8 +2,14 @@
$(document).ready(
function () {
var ui = new TournamentResultsUI("/gemp-lotr-server");
$(".loadFinishedTournaments").button().click(
function() {
ui.loadHistoryTournaments();
});
});
</script>
All times are GMT based.
<div class="loadFinishedTournaments">Load finished tournaments</div>
<div id="tournamentResults"></div>

View File

@@ -81,6 +81,32 @@ var GempLotrCommunication = Class.extend({
});
},
getHistoryTournaments:function (callback, errorMap) {
$.ajax({
type:"GET",
url:this.url + "/tournament/history",
cache:false,
data:{
participanId:getUrlParam("participantId") },
success:this.deliveryCheck(callback),
error:this.errorCheck(errorMap),
dataType:"xml"
});
},
getTournament:function (tournamentId, callback, errorMap) {
$.ajax({
type:"GET",
url:this.url + "/tournament/" + tournamentId,
cache:false,
data:{
participanId:getUrlParam("participantId") },
success:this.deliveryCheck(callback),
error:this.errorCheck(errorMap),
dataType:"xml"
});
},
getLeagues:function (callback, errorMap) {
$.ajax({
type:"GET",

View File

@@ -4,17 +4,17 @@ var TournamentResultsUI = Class.extend({
init:function (url) {
this.communication = new GempLotrCommunication(url,
function (xhr, ajaxOptions, thrownError) {
});
function (xhr, ajaxOptions, thrownError) {
});
this.formatDialog = $("<div></div>")
.dialog({
autoOpen:false,
closeOnEscape:true,
resizable:false,
modal:true,
title:"Format description"
});
.dialog({
autoOpen:false,
closeOnEscape:true,
resizable:false,
modal:true,
title:"Format description"
});
this.loadLiveTournaments();
},
@@ -22,9 +22,17 @@ var TournamentResultsUI = Class.extend({
loadLiveTournaments:function () {
var that = this;
this.communication.getLiveTournaments(
function (xml) {
that.loadedLiveTournaments(xml);
});
function (xml) {
that.loadedTournaments(xml);
});
},
loadHistoryTournaments: function() {
var that = this;
this.communication.getHistoryTournaments(
function (xml) {
that.loadedTournaments(xml);
});
},
loadedTournament:function (xml) {
@@ -36,6 +44,7 @@ var TournamentResultsUI = Class.extend({
var tournament = root;
var tournamentId = tournament.getAttribute("id");
var tournamentName = tournament.getAttribute("name");
var tournamentFormat = tournament.getAttribute("format");
var tournamentCollection = tournament.getAttribute("collection");
@@ -50,11 +59,11 @@ var TournamentResultsUI = Class.extend({
var standings = tournament.getElementsByTagName("tournamentStanding");
if (standings.length > 0)
$("#tournamentExtraInfo").append(this.createStandingsTable(standings));
$("#tournamentExtraInfo").append(this.createStandingsTable(standings, tournamentId, tournamentFinished));
}
},
loadedLiveTournaments:function (xml) {
loadedTournaments:function (xml) {
var that = this;
log(xml);
var root = xml.documentElement;
@@ -64,6 +73,7 @@ var TournamentResultsUI = Class.extend({
var tournaments = root.getElementsByTagName("tournament");
for (var i = 0; i < tournaments.length; i++) {
var tournament = tournaments[i];
var tournamentId = tournament.getAttribute("id");
var tournamentName = tournament.getAttribute("name");
var tournamentFormat = tournament.getAttribute("format");
var tournamentCollection = tournament.getAttribute("collection");
@@ -71,18 +81,18 @@ var TournamentResultsUI = Class.extend({
var tournamentFinished = tournament.getAttribute("finished");
$("#tournamentResults").append("<div class='tournamentName'>" + tournamentName + "</div>");
$("#tournamentResults").append("<div class='tournamentRound'>" + tournamentRound + "</div>");
$("#tournamentResults").append("<div class='tournamentRound'><b>Round:</b> " + tournamentRound + "</div>");
var detailsBut = $("<button>See details</button>").button();
detailsBut.click(
(function (type) {
return function () {
that.communication.getTournament(type,
function (xml) {
that.loadedTournament(xml);
});
};
})(tournamentFormat));
(function (id) {
return function () {
that.communication.getTournament(id,
function (xml) {
that.loadedTournament(xml);
});
};
})(tournamentId));
$("#tournamentResults").append(detailsBut);
}
if (tournaments.length == 0)
@@ -93,7 +103,7 @@ var TournamentResultsUI = Class.extend({
}
},
createStandingsTable:function (standings) {
createStandingsTable:function (standings, tournamentId, tournamentFinished) {
var standingsTable = $("<table class='standings'></table>");
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>");
@@ -108,7 +118,13 @@ var TournamentResultsUI = Class.extend({
var gamesPlayed = parseInt(standing.getAttribute("gamesPlayed"));
var opponentWinPerc = standing.getAttribute("opponentWin");
standingsTable.append("<tr><td>" + currentStanding + "</td><td>" + player + "</td><td>" + points + "</td><td>" + gamesPlayed + "</td><td>" + opponentWinPerc + "</td></tr>");
var playerStr;
if (tournamentFinished == "true")
playerStr = "<a target='_blank' href='/gemp-lotr-server/tournament/" + tournamentId + "/deck/" + player + "/html'>" + player + "</a>";
else
playerStr = player;
standingsTable.append("<tr><td>" + currentStanding + "</td><td>" + playerStr + "</td><td>" + points + "</td><td>" + gamesPlayed + "</td><td>" + opponentWinPerc + "</td></tr>");
}
for (var k = secondColumnBaseIndex; k < standings.length; k++) {
@@ -119,7 +135,13 @@ var TournamentResultsUI = Class.extend({
var gamesPlayed = parseInt(standing.getAttribute("gamesPlayed"));
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><td>" + opponentWinPerc + "</td>");
var playerStr;
if (tournamentFinished == "true")
playerStr = "<a target='_blank' href='/gemp-lotr-server/tournament/" + tournamentId + "/deck/" + player + "/html'>" + player + "</a>";
else
playerStr = player;
$("tr:eq(" + (k - secondColumnBaseIndex + 1) + ")", standingsTable).append("<td></td><td>" + currentStanding + "</td><td>" + playerStr + "</td><td>" + points + "</td><td>" + gamesPlayed + "</td><td>" + opponentWinPerc + "</td>");
}
return standingsTable;