From 893ef932af6fe4b63d1a785a8fe688e12631e35d Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Sat, 12 Aug 2023 00:40:13 -0500 Subject: [PATCH] WC Tournament Queues - Added new WC-specific queues to the front page. Any scheduled tournament with 'wc' in the name will use this UI section instead of the main one. - Added pop-up information on joining, leaving, and abandoning a tournament. - Fixed some xml parsing bugs in the comm object for tournament queues - Added new Championship Timer which grants both players 20 minutes and a 10 minute timeout - Altered the scheduled tournament table creation to use the Championship Timer --- .../src/main/web/css/gemp-001/hall.css | 8 + .../gemp-lotr-async/src/main/web/hall.html | 28 +++ .../src/main/web/js/gemp-022/communication.js | 7 +- .../src/main/web/js/gemp-022/hallUi.js | 205 +++++++++++++++--- .../com/gempukku/lotro/hall/GameTimer.java | 1 + .../com/gempukku/lotro/hall/HallServer.java | 13 +- .../tournament/ScheduledTournamentQueue.java | 8 +- 7 files changed, 233 insertions(+), 37 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/hall.css b/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/hall.css index f1a50f149..e53d0bbda 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/hall.css +++ b/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/hall.css @@ -280,6 +280,14 @@ table.tables tr.privateForPlayer { border-radius: 3px; } +.wc-queues { + background-color: #FF5555; +} + +.wc-events { + background-color: #FFFF55; +} + .tableFormatName { text-align: center; font-weight: bold; diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/hall.html b/gemp-lotr/gemp-lotr-async/src/main/web/hall.html index cdf3b8146..e7c966778 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/hall.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/hall.html @@ -175,6 +175,34 @@ +
World Championship Queues(0)
+
+ + + + + + + + + +
FormatEventStartsSystemPlayersActions
+
+ +
World Championship Events(0)
+
+ + + + + + + + + +
FormatEventStartsSystemPlayersActions
+
+
Tournament Queues(0)
diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/communication.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/communication.js index 0314320d0..4178c41b3 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/communication.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/communication.js @@ -603,18 +603,19 @@ var GempLotrCommunication = Class.extend({ participantId:getUrlParam("participantId")}, success:this.deliveryCheck(callback), error:this.errorCheck(errorMap), - dataType:"xml" + dataType:"text" }); }, - leaveQueue:function (queueId, errorMap) { + leaveQueue:function (queueId, callback, errorMap) { $.ajax({ type:"POST", url:this.url + "/hall/queue/" + queueId + "/leave", cache:false, data:{ participantId:getUrlParam("participantId")}, + success:this.deliveryCheck(callback), error:this.errorCheck(errorMap), - dataType:"xml" + dataType:"text" }); }, dropFromTournament:function(tournamentId, callback, errorMap) { diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/hallUi.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/hallUi.js index c03bc5d5d..1ae778f16 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/hallUi.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/hallUi.js @@ -77,9 +77,9 @@ var GempLotrHallUI = Class.extend({ this.adminTab.hide(); this.comm.getPlayerInfo(function(json) - { - that.userInfo = json; - if(that.userInfo.type.includes("a") || that.userInfo.type.includes("l")) + { + that.userInfo = json; + if(that.userInfo.type.includes("a") || that.userInfo.type.includes("l")) { that.adminTab.show(); } @@ -87,12 +87,12 @@ var GempLotrHallUI = Class.extend({ { that.adminTab.hide(); } - }); + }); var hallSettingsStr = $.cookie("hallSettings"); if (hallSettingsStr == null) - hallSettingsStr = "1|1|0|0|0"; + hallSettingsStr = "1|1|0|0|0|0|0"; var hallSettings = hallSettingsStr.split("|"); this.initTable(hallSettings[0] == "1", "waitingTablesHeader", "waitingTablesContent"); @@ -100,6 +100,13 @@ var GempLotrHallUI = Class.extend({ this.initTable(hallSettings[2] == "1", "finishedTablesHeader", "finishedTablesContent"); this.initTable(hallSettings[3] == "1", "tournamentQueuesHeader", "tournamentQueuesContent"); this.initTable(hallSettings[4] == "1", "activeTournamentsHeader", "activeTournamentsContent"); + this.initTable(hallSettings[5] == "1", "wcQueuesHeader", "wcQueuesContent"); + this.initTable(hallSettings[6] == "1", "wcEventsHeader", "wcEventsContent"); + + $('#wcQueuesHeader').hide(); + $('#wcQueuesContent').hide(); + $('#wcEventsHeader').hide(); + $('#wcEventsContent').hide(); $("#deckbuilder-button").button(); $("#bug-button").button(); @@ -230,6 +237,27 @@ var GempLotrHallUI = Class.extend({ closeText: '' }).text(text); }, + + showDialog:function(title, text, height) { + if(height == null) + height = 200 + var dialog = $("
").dialog({ + title: title, + resizable: true, + height: height, + modal: true, + closeOnEscape: true, + buttons: [ + { + text: "OK", + click: function() { + $( this ).dialog( "close" ); + } + } + ], + closeText: '' + }).html(text); + }, updateDecks:function () { var that = this; @@ -250,14 +278,18 @@ var GempLotrHallUI = Class.extend({ }, processResponse:function (xml) { - if (xml != null) { + if (xml != null && xml != "OK") { + var root = xml.documentElement; if (root.tagName == "error") { var message = root.getAttribute("message"); this.chat.appendMessage(message, "warningMessage"); - alert(message); + + this.showDialog("Error", message); + return false; } } + return true; }, processDecks:function (xml) { @@ -335,6 +367,7 @@ var GempLotrHallUI = Class.extend({ for (var i = 0; i < queues.length; i++) { var queue = queues[i]; var id = queue.getAttribute("id"); + var isWC = id.toLowerCase().includes("wc"); var action = queue.getAttribute("action"); if (action == "add" || action == "update") { var actionsField = $(""); @@ -343,59 +376,123 @@ var GempLotrHallUI = Class.extend({ if (joined != "true" && queue.getAttribute("joinable") == "true") { var but = $(""); $(but).button().click(( - function(queueId) { + function(queueInfo) { return function () { var deck = that.decksSelect.val(); - if (deck != null) - that.comm.joinQueue(queueId, deck, function (xml) { - that.processResponse(xml); - }); + + if (deck == null) + return; + + var queueId = queueInfo.getAttribute("id"); + var queueName = queueInfo.getAttribute("queue"); + var queueStart = queueInfo.getAttribute("start"); + that.comm.joinQueue(queueId, deck, function (xml) { + var result = that.processResponse(xml); + if(result) { + that.showDialog("Joined Tournament", "You have signed up to participate in the " + queueName + + " tournament.

You will use a snapshot of your '" + deck +"' deck as it is right now. " + + "If you need to change or update your deck, you will need to leave the queue and rejoin.

" + + "The first game begins at " + queueStart + ". Good luck!", 320); + } + }, that.hallErrorMap()); }; } - )(id)); + )(queue)); actionsField.append(but); } else if (joined == "true") { var but = $(""); $(but).button().click(( - function(queueId) { + function(queueInfo) { return function() { + var queueId = queueInfo.getAttribute("id"); + var queueName = queueInfo.getAttribute("queue"); + var queueStart = queueInfo.getAttribute("start"); that.comm.leaveQueue(queueId, function (xml) { - that.processResponse(xml); + var result = that.processResponse(xml); + + if(result) { + that.showDialog("Left Tournament", "You have been removed from the " + queueName + + " tournament.

If you wish to rejoin, you will need to requeue before it starts at " + queueStart + ".", 230); + } }); } - })(id)); + })(queue)); actionsField.append(but); } - var row = $("" + - "" + + var rowstr = ""; + if(isWC) { + rowstr = "" + + "" + + "" + + "" + + "" + + ""; + } + else { + rowstr += "" + "" + "" + "" + "" + "" + "" + - ""); - + ""; + } + + var row = $(rowstr); row.append(actionsField); if (action == "add") { - $("table.queues", this.tablesDiv) + if(isWC) { + $("table.wc-queues", this.tablesDiv) .append(row); + } + else { + $("table.queues", this.tablesDiv) + .append(row); + } } else if (action == "update") { - $(".queue" + id, this.tablesDiv).replaceWith(row); + if(isWC) { + $(".wc-queue" + id, this.tablesDiv).replaceWith(row); + } + else { + $(".queue" + id, this.tablesDiv).replaceWith(row); + } + } - this.animateRowUpdate(".queue" + id); + if(isWC) { + this.animateRowUpdate(".wc-queue" + id); + } + else { + this.animateRowUpdate(".queue" + id); + } + } else if (action == "remove") { - $(".queue" + id, this.tablesDiv).remove(); + if(isWC) { + $(".wc-queue" + id, this.tablesDiv).remove(); + } + else { + $(".queue" + id, this.tablesDiv).remove(); + } + } } + + if($('.wc-queues tr').length <= 1) { + $('#wcQueuesHeader').hide(); + $('#wcQueuesContent').hide(); + } else { + $('#wcQueuesHeader').show(); + $('#wcQueuesContent').show(); + } var tournaments = root.getElementsByTagName("tournament"); for (var i = 0; i < tournaments.length; i++) { var tournament = tournaments[i]; var id = tournament.getAttribute("id"); + var isWC = id.includes("wc"); var action = tournament.getAttribute("action"); if (action == "add" || action == "update") { var actionsField = $(""); @@ -404,18 +501,36 @@ var GempLotrHallUI = Class.extend({ if (joined == "true") { var but = $(""); $(but).button().click(( - function(tournamentId) { + function(tourneyInfo) { + var tourneyId = tournament.getAttribute("id"); + var tourneyName = tournament.getAttribute("queue"); + let isExecuted = confirm("Are you sure you want to resign from the " + tourneyName + " tournament? This cannot be undone."); + return function () { - that.comm.dropFromTournament(tournamentId, function (xml) { + if(isExecuted) { + that.comm.dropFromTournament(tournamentId, function (xml) { that.processResponse(xml); }); + } }; } - )(id)); + )(tournament)); actionsField.append(but); } - var row = $("" + + var rowstr = ""; + + if(isWC) { + rowstr = $("" + + "" + + "" + + "" + + "" + + "" + + ""); + } + else { + rowstr = $("" + "" + "" + "" + @@ -423,21 +538,49 @@ var GempLotrHallUI = Class.extend({ "" + "" + ""); + } + var row = $(rowstr); row.append(actionsField); if (action == "add") { - $("table.tournaments", this.tablesDiv) + if(isWC) { + $("table.wc-tournaments", this.tablesDiv) .append(row); + } + else { + $("table.tournaments", this.tablesDiv) + .append(row); + } + } else if (action == "update") { - $(".tournament" + id, this.tablesDiv).replaceWith(row); + if(isWC) { + $(".wc-tournament" + id, this.tablesDiv).replaceWith(row); + } + else { + $(".tournament" + id, this.tablesDiv).replaceWith(row); + } + } this.animateRowUpdate(".tournament" + id); } else if (action == "remove") { - $(".tournament" + id, this.tablesDiv).remove(); + if(isWC) { + $(".wc-tournament" + id, this.tablesDiv).remove(); + } + else { + $(".tournament" + id, this.tablesDiv).remove(); + } } } + + if($('.wc-events tr').length <= 1) { + $('#wcEventsHeader').hide(); + $('#wcEventsContent').hide(); + } else { + $('#wcEventsHeader').show(); + $('#wcEventsContent').show(); + } var tables = root.getElementsByTagName("table"); for (var i = 0; i < tables.length; i++) { diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/GameTimer.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/GameTimer.java index 39b7e47fd..f96915e44 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/GameTimer.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/GameTimer.java @@ -8,6 +8,7 @@ public record GameTimer(boolean longGame, String name, int maxSecondsPerPlayer, public static final GameTimer GLACIAL_TIMER = new GameTimer(true, "Glacial", 60 * 60 * 24 * 3, 60 * 60 * 24); // 5 minutes timeout, 40 minutes per game per player public static final GameTimer COMPETITIVE_TIMER = new GameTimer(false, "Competitive", 60 * 40, 60 * 5); + public static final GameTimer CHAMPIONSHIP_TIMER = new GameTimer(false, "WC", 60 * 20, 60 * 10); public static final GameTimer TOURNAMENT_TIMER = new GameTimer(false, "Tournament", 60 * 40, 60 * 5); public static GameTimer ResolveTimer(String timer) { diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java index 32dd0ceed..95b3065ca 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/hall/HallServer.java @@ -877,10 +877,15 @@ public class HallServer extends AbstractServer { private final Tournament _tournament; private final GameSettings tournamentGameSettings; + private final GameSettings wcGameSettings; + private HallTournamentCallback(Tournament tournament) { _tournament = tournament; tournamentGameSettings = new GameSettings(null, _formatLibrary.getFormat(_tournament.getFormat()), null, null, true, false, false, false, GameTimer.TOURNAMENT_TIMER, null); + + wcGameSettings = new GameSettings(null, _formatLibrary.getFormat(_tournament.getFormat()), + null, null, true, false, false, false, GameTimer.CHAMPIONSHIP_TIMER, null); } @Override @@ -895,7 +900,11 @@ public class HallServer extends AbstractServer { _hallDataAccessLock.writeLock().lock(); try { if (!_shutdown) { - final GameTable gameTable = tableHolder.setupTournamentTable(tournamentGameSettings, participants); + var settings = tournamentGameSettings; + if(_tournament.getTournamentId().toLowerCase().contains("wc")) { + settings = wcGameSettings; + } + final GameTable gameTable = tableHolder.setupTournamentTable(settings, participants); final LotroGameMediator mediator = createGameMediator(participants, new GameResultListener() { @Override @@ -907,7 +916,7 @@ public class HallServer extends AbstractServer { public void gameCancelled() { createGameInternal(participants); } - }, _tournament.getTournamentName(), tournamentGameSettings); + }, _tournament.getTournamentName(), settings); gameTable.startGame(mediator); } } finally { diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/ScheduledTournamentQueue.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/ScheduledTournamentQueue.java index 4215f8af7..d846afac5 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/ScheduledTournamentQueue.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/ScheduledTournamentQueue.java @@ -10,6 +10,8 @@ import java.util.Date; public class ScheduledTournamentQueue extends AbstractTournamentQueue implements TournamentQueue { private static final long _signupTimeBeforeStart = 1000 * 60 * 60; // 60 minutes before start + + private static final long _wcSignupTimeBeforeStart = 1000 * 60 * 60 * 24; // 24 hours before start private final long _startTime; private final int _minimumPlayers; private final String _startCondition; @@ -72,6 +74,10 @@ public class ScheduledTournamentQueue extends AbstractTournamentQueue implements @Override public boolean isJoinable() { - return System.currentTimeMillis() >= _startTime - _signupTimeBeforeStart; + long window = _signupTimeBeforeStart; + if(_scheduledTournamentId.toLowerCase().contains("wc")) { + window = _wcSignupTimeBeforeStart; + } + return System.currentTimeMillis() >= _startTime - window; } }
" + queue.getAttribute("format") + "" + queue.getAttribute("collection") + "
" + queue.getAttribute("format") + "
" + queue.getAttribute("format") + "" + queue.getAttribute("queue") + "" + queue.getAttribute("start") + "" + queue.getAttribute("system") + "" + queue.getAttribute("playerCount") + "
" + queue.getAttribute("collection") + "" + queue.getAttribute("queue") + "" + queue.getAttribute("start") + "" + queue.getAttribute("system") + "" + queue.getAttribute("playerCount") + "" + formatPrice(queue.getAttribute("cost")) + "" + queue.getAttribute("prizes") + "
" + tournament.getAttribute("format") + "
" + tournament.getAttribute("format") + "" + tournament.getAttribute("name") + "" + tournament.getAttribute("system") + "" + tournament.getAttribute("stage") + "" + tournament.getAttribute("round") + "" + tournament.getAttribute("playerCount") + "
" + tournament.getAttribute("format") + "" + tournament.getAttribute("collection") + "" + tournament.getAttribute("name") + "" + tournament.getAttribute("system") + "" + tournament.getAttribute("round") + "" + tournament.getAttribute("playerCount") + "