Added - timers for deck-building stage, registration stage and pairing delay in playing stage

This commit is contained in:
jakub.salavec
2025-04-14 16:49:20 +02:00
parent 5dbd81dfc3
commit 88fe7cdd95
10 changed files with 102 additions and 11 deletions

View File

@@ -813,9 +813,13 @@ var GempLotrHallUI = Class.extend({
}
rowhtml += "<td>" + tournament.getAttribute("name") + "</td>" +
"<td>" + tournament.getAttribute("system") + "</td>" +
"<td>" + tournament.getAttribute("stage") + "</td>" +
"<td>" + tournament.getAttribute("round") + "</td>" +
"<td>" + tournament.getAttribute("system") + "</td>";
if (tournament.hasAttribute("timeRemaining")) {
rowhtml += "<td>" + tournament.getAttribute("stage") + " - " + tournament.getAttribute("timeRemaining") + "</td>";
} else {
rowhtml += "<td>" + tournament.getAttribute("stage") + "</td>";
}
rowhtml += "<td>" + tournament.getAttribute("round") + "</td>" +
"<td><div class='prizeHint' title='Competing Players' value='" + tournament.getAttribute("playerList") + "<br><br>* = abandoned'>" + tournament.getAttribute("playerCount") + "</div></td>" +
"</tr>";
@@ -843,7 +847,11 @@ var GempLotrHallUI = Class.extend({
var tablesRow = $("<tr class='table" + id + "'></tr>");
tablesRow.append("<td>" + tournament.getAttribute("format") + "</td>");
tablesRow.append("<td> Tournament - " + displayType + " - " + tournament.getAttribute("name") + "</td>");
tablesRow.append("<td>" + tournament.getAttribute("stage") + "</td>");
if (tournament.hasAttribute("timeRemaining")) {
tablesRow.append("<td>" + tournament.getAttribute("stage") + " - " + tournament.getAttribute("timeRemaining") + "</td>");
} else {
tablesRow.append("<td>" + tournament.getAttribute("stage") + "</td>");
}
tablesRow.append("<td>" + tournament.getAttribute("playerList") + "</td>");
var actionsFieldClone = actionsField.clone(true);
tablesRow.append(actionsFieldClone);

View File

@@ -1,11 +1,13 @@
package com.gempukku.lotro.hall;
import com.gempukku.lotro.common.DateUtils;
import com.gempukku.lotro.game.Player;
import com.gempukku.polling.LongPollableResource;
import com.gempukku.polling.WaitingRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.mutable.MutableObject;
import java.time.Duration;
import java.util.*;
public class HallCommunicationChannel implements LongPollableResource {
@@ -128,7 +130,8 @@ public class HallCommunicationChannel implements LongPollableResource {
@Override
public void visitTournament(String tournamentKey, String collectionName, String formatName, String tournamentName, String type, String pairingDescription,
String tournamentStage, int round, int playerCount, String playerList, boolean playerInCompetition, boolean abandoned, boolean joinable) {
String tournamentStage, int round, int playerCount, String playerList, boolean playerInCompetition, boolean abandoned, boolean joinable,
long secsRemaining) {
Map<String, String> props = new HashMap<>();
props.put("collection", collectionName);
props.put("format", formatName);
@@ -142,6 +145,9 @@ public class HallCommunicationChannel implements LongPollableResource {
props.put("signedUp", String.valueOf(playerInCompetition));
props.put("abandoned", String.valueOf(abandoned));
props.put("joinable", String.valueOf(joinable));
if (secsRemaining >= 0) {
props.put("timeRemaining", DateUtils.HumanDuration(Duration.ofSeconds(secsRemaining)));
}
tournamentsOnServer.put(tournamentKey, props);
}

View File

@@ -18,7 +18,8 @@ public interface HallInfoVisitor {
int readyCheckSecsRemaining, boolean confirmedReadyCheck);
public void visitTournament(String tournamentKey, String collectionName, String formatName, String tournamentName, String type,
String pairingDescription, String tournamentStage, int round, int playerCount, String playerList, boolean playerInCompetition, boolean abandoned, boolean joinable);
String pairingDescription, String tournamentStage, int round, int playerCount, String playerList, boolean playerInCompetition, boolean abandoned, boolean joinable,
long secsRemaining);
public void runningPlayerGame(String gameId);
}

View File

@@ -7,25 +7,21 @@ import com.gempukku.lotro.common.DateUtils;
import com.gempukku.lotro.competitive.ModifiedMedianStandingsProducer;
import com.gempukku.lotro.competitive.PlayerStanding;
import com.gempukku.lotro.db.vo.CollectionType;
import com.gempukku.lotro.draft.Draft;
import com.gempukku.lotro.draft2.SoloDraftDefinitions;
import com.gempukku.lotro.draft3.TableDraftDefinitions;
import com.gempukku.lotro.game.CardCollection;
import com.gempukku.lotro.game.CardNotFoundException;
import com.gempukku.lotro.game.formats.LotroFormatLibrary;
import com.gempukku.lotro.hall.TableHolder;
import com.gempukku.lotro.logic.actions.AbstractCostToEffectAction;
import com.gempukku.lotro.logic.vo.LotroDeck;
import com.gempukku.lotro.packs.ProductLibrary;
import com.gempukku.lotro.tournament.action.BroadcastAction;
import com.gempukku.lotro.tournament.action.CreateGameAction;
import com.gempukku.lotro.tournament.action.TournamentProcessAction;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DurationFormatUtils;
import org.apache.commons.text.StringEscapeUtils;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
@@ -519,4 +515,9 @@ public abstract class BaseTournament implements Tournament {
}
return _tournamentReport;
}
@Override
public long getSecondsRemaining() throws IllegalStateException{
throw new IllegalStateException();
}
}

View File

@@ -16,11 +16,14 @@ import com.gempukku.lotro.tournament.action.BroadcastAction;
import com.gempukku.lotro.tournament.action.TournamentProcessAction;
import org.apache.commons.lang3.StringUtils;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.*;
public class SealedTournament extends BaseTournament implements Tournament {
private SealedTournamentInfo _sealedInfo;
private ZonedDateTime nextRoundStart = null;
public SealedTournament(TournamentService tournamentService, CollectionsManager collectionsManager, ProductLibrary productLibrary,
LotroFormatLibrary formatLibrary, SoloDraftDefinitions soloDraftDefinitions, TableDraftDefinitions tableDraftDefinitions, TableHolder tables, String tournamentId) {
@@ -201,6 +204,7 @@ public class SealedTournament extends BaseTournament implements Tournament {
if (_tournamentInfo.PairingMechanism.isFinished(getCurrentRound(), _players, _droppedPlayers)) {
result.add(finishTournament(collectionsManager));
} else {
nextRoundStart = DateUtils.Now().plus(PairingDelayTime);
if(getCurrentRound() == 0) {
result.add(new BroadcastAction("Deck registration for tournament <b>" + getTournamentName()
+ "</b> has closed. Round "
@@ -247,4 +251,17 @@ public class SealedTournament extends BaseTournament implements Tournament {
getTournamentStage() == Tournament.Stage.PAUSED || getTournamentStage() == Tournament.Stage.AWAITING_KICKOFF)
&& (maximumPlayers > activePlayers.size() || maximumPlayers < 0);
}
@Override
public long getSecondsRemaining() throws IllegalStateException {
if (getTournamentStage() == Stage.DECK_BUILDING) {
return Duration.between(DateUtils.Now(), _sealedInfo.DeckbuildingDeadline).getSeconds();
} else if (getTournamentStage() == Stage.DECK_REGISTRATION) {
return Duration.between(DateUtils.Now(), _sealedInfo.RegistrationDeadline).getSeconds();
} else if (getTournamentStage() == Stage.PLAYING_GAMES && nextRoundStart != null && DateUtils.Now().isBefore(nextRoundStart)) {
return Duration.between(DateUtils.Now(), nextRoundStart).getSeconds();
} else {
throw new IllegalStateException();
}
}
}

View File

@@ -18,12 +18,15 @@ import com.gempukku.lotro.tournament.action.BroadcastAction;
import com.gempukku.lotro.tournament.action.TournamentProcessAction;
import org.apache.commons.lang3.StringUtils;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.*;
public class SoloDraftTournament extends BaseTournament implements Tournament {
private static final int HIGH_ENOUGH_PRIME_NUMBER = 8963;
private SoloDraftTournamentInfo _soloDraftInfo;
private ZonedDateTime nextRoundStart = null;
public SoloDraftTournament(TournamentService tournamentService, CollectionsManager collectionsManager, ProductLibrary productLibrary,
LotroFormatLibrary formatLibrary, SoloDraftDefinitions soloDraftDefinitions, TableDraftDefinitions tableDraftDefinitions, TableHolder tables, String tournamentId) {
@@ -196,6 +199,7 @@ public class SoloDraftTournament extends BaseTournament implements Tournament {
if (_tournamentInfo.PairingMechanism.isFinished(getCurrentRound(), _players, _droppedPlayers)) {
result.add(finishTournament(collectionsManager));
} else {
nextRoundStart = DateUtils.Now().plus(PairingDelayTime);
if(getCurrentRound() == 0) {
result.add(new BroadcastAction("Deck registration for tournament <b>" + getTournamentName()
+ "</b> has closed. Round "
@@ -262,4 +266,17 @@ public class SoloDraftTournament extends BaseTournament implements Tournament {
getTournamentStage() == Tournament.Stage.PAUSED || getTournamentStage() == Tournament.Stage.AWAITING_KICKOFF)
&& (maximumPlayers > activePlayers.size() || maximumPlayers < 0);
}
@Override
public long getSecondsRemaining() throws IllegalStateException {
if (getTournamentStage() == Stage.DECK_BUILDING) {
return Duration.between(DateUtils.Now(), _soloDraftInfo.DeckbuildingDeadline).getSeconds();
} else if (getTournamentStage() == Stage.DECK_REGISTRATION) {
return Duration.between(DateUtils.Now(), _soloDraftInfo.RegistrationDeadline).getSeconds();
} else if (getTournamentStage() == Stage.PLAYING_GAMES && nextRoundStart != null && DateUtils.Now().isBefore(nextRoundStart)) {
return Duration.between(DateUtils.Now(), nextRoundStart).getSeconds();
} else {
throw new IllegalStateException();
}
}
}

View File

@@ -16,12 +16,15 @@ import com.gempukku.lotro.tournament.action.BroadcastAction;
import com.gempukku.lotro.tournament.action.TournamentProcessAction;
import org.apache.commons.lang3.StringUtils;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.*;
public class SoloTableDraftTournament extends BaseTournament implements Tournament {
private SoloTableDraftTournamentInfo soloTableDraftInfo;
private Map<String, TableDraft> tables = null;
private ZonedDateTime nextRoundStart = null;
public SoloTableDraftTournament(TournamentService tournamentService, CollectionsManager collectionsManager, ProductLibrary productLibrary,
LotroFormatLibrary formatLibrary, SoloDraftDefinitions soloDraftDefinitions, TableDraftDefinitions tableDraftDefinitions,
@@ -176,6 +179,7 @@ public class SoloTableDraftTournament extends BaseTournament implements Tourname
if (_tournamentInfo.PairingMechanism.isFinished(getCurrentRound(), _players, _droppedPlayers)) {
result.add(finishTournament(collectionsManager));
} else {
nextRoundStart = DateUtils.Now().plus(PairingDelayTime);
if(getCurrentRound() == 0) {
result.add(new BroadcastAction("Deck registration for tournament <b>" + getTournamentName()
+ "</b> has closed. Round "
@@ -245,4 +249,17 @@ public class SoloTableDraftTournament extends BaseTournament implements Tourname
getTournamentStage() == Tournament.Stage.PAUSED || getTournamentStage() == Tournament.Stage.AWAITING_KICKOFF)
&& (maximumPlayers > activePlayers.size() || maximumPlayers < 0);
}
@Override
public long getSecondsRemaining() throws IllegalStateException {
if (getTournamentStage() == Stage.DECK_BUILDING) {
return Duration.between(DateUtils.Now(), soloTableDraftInfo.deckbuildingDeadline).getSeconds();
} else if (getTournamentStage() == Stage.DECK_REGISTRATION) {
return Duration.between(DateUtils.Now(), soloTableDraftInfo.registrationDeadline).getSeconds();
} else if (getTournamentStage() == Stage.PLAYING_GAMES && nextRoundStart != null && DateUtils.Now().isBefore(nextRoundStart)) {
return Duration.between(DateUtils.Now(), nextRoundStart).getSeconds();
} else {
throw new IllegalStateException();
}
}
}

View File

@@ -18,6 +18,8 @@ import com.gempukku.lotro.tournament.action.BroadcastAction;
import com.gempukku.lotro.tournament.action.TournamentProcessAction;
import org.apache.commons.lang3.StringUtils;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.*;
public class TableDraftTournament extends BaseTournament implements Tournament {
@@ -25,6 +27,7 @@ public class TableDraftTournament extends BaseTournament implements Tournament {
private TableDraftTournamentInfo tableDraftInfo;
private TableDraft table = null;
private final ChatServer chatServer;
private ZonedDateTime nextRoundStart = null;
public TableDraftTournament(TournamentService tournamentService, CollectionsManager collectionsManager, ProductLibrary productLibrary,
LotroFormatLibrary formatLibrary, SoloDraftDefinitions soloDraftDefinitions, TableDraftDefinitions tableDraftDefinitions,
@@ -201,6 +204,7 @@ public class TableDraftTournament extends BaseTournament implements Tournament {
if (_tournamentInfo.PairingMechanism.isFinished(getCurrentRound(), _players, _droppedPlayers)) {
result.add(finishTournament(collectionsManager));
} else {
nextRoundStart = DateUtils.Now().plus(PairingDelayTime);
if(getCurrentRound() == 0) {
result.add(new BroadcastAction("Deck registration for tournament <b>" + getTournamentName()
+ "</b> has closed. Round "
@@ -262,4 +266,17 @@ public class TableDraftTournament extends BaseTournament implements Tournament {
public boolean isJoinable() {
return false; // cannot join draft in progress
}
@Override
public long getSecondsRemaining() throws IllegalStateException {
if (getTournamentStage() == Stage.DECK_BUILDING) {
return Duration.between(DateUtils.Now(), tableDraftInfo.deckbuildingDeadline).getSeconds();
} else if (getTournamentStage() == Stage.DECK_REGISTRATION) {
return Duration.between(DateUtils.Now(), tableDraftInfo.registrationDeadline).getSeconds();
} else if (getTournamentStage() == Stage.PLAYING_GAMES && nextRoundStart != null && DateUtils.Now().isBefore(nextRoundStart)) {
return Duration.between(DateUtils.Now(), nextRoundStart).getSeconds();
} else {
throw new IllegalStateException();
}
}
}

View File

@@ -206,4 +206,5 @@ public interface Tournament {
TournamentInfo getInfo();
boolean isJoinable();
long getSecondsRemaining() throws IllegalStateException;
}

View File

@@ -264,11 +264,17 @@ public class TournamentService {
for (var entry : _activeTournaments.entrySet()) {
var tourneyID = entry.getKey();
var tournament = entry.getValue();
long secsRemaining = -1;
try {
secsRemaining = tournament.getSecondsRemaining();
} catch (IllegalStateException ignore) {
}
visitor.visitTournament(tourneyID, tournament.getCollectionType().getFullName(),
formatLibrary.getFormat(tournament.getFormatCode()).getName(), tournament.getTournamentName(), tournament.getInfo().Parameters().type.toString(), tournament.getPlayOffSystem(),
tournament.getTournamentStage().getHumanReadable(),
tournament.getCurrentRound(), tournament.getPlayersInCompetitionCount(), tournament.getPlayerList(), tournament.isPlayerInCompetition(player.getName()), tournament.isPlayerAbandoned(player.getName()),
tournament.isJoinable());
tournament.isJoinable(), secsRemaining);
}
}