Added - queue configurator now has competitive settings; Modified - spawning of queue goes through hall, so it can be updated immediately; Tournaments can be spectated if there is 'casual' in their names

This commit is contained in:
jakub.salavec
2025-06-13 14:08:58 +02:00
parent 7991dc713e
commit a7057ee042
5 changed files with 65 additions and 18 deletions

View File

@@ -13,6 +13,7 @@ import com.gempukku.lotro.game.LotroCardBlueprintLibrary;
import com.gempukku.lotro.game.Player; import com.gempukku.lotro.game.Player;
import com.gempukku.lotro.game.SortAndFilterCards; import com.gempukku.lotro.game.SortAndFilterCards;
import com.gempukku.lotro.game.formats.LotroFormatLibrary; import com.gempukku.lotro.game.formats.LotroFormatLibrary;
import com.gempukku.lotro.hall.HallServer;
import com.gempukku.lotro.logic.vo.LotroDeck; import com.gempukku.lotro.logic.vo.LotroDeck;
import com.gempukku.lotro.packs.ProductLibrary; import com.gempukku.lotro.packs.ProductLibrary;
import com.gempukku.lotro.tournament.*; import com.gempukku.lotro.tournament.*;
@@ -51,6 +52,8 @@ public class TournamentRequestHandler extends LotroServerRequestHandler implemen
private final TableDraftDefinitions _tableDraftLibrary; private final TableDraftDefinitions _tableDraftLibrary;
private final ProductLibrary _productLibrary; private final ProductLibrary _productLibrary;
private final HallServer _hallServer;
private static final Logger _log = LogManager.getLogger(TournamentRequestHandler.class); private static final Logger _log = LogManager.getLogger(TournamentRequestHandler.class);
public TournamentRequestHandler(Map<Type, Object> context) { public TournamentRequestHandler(Map<Type, Object> context) {
@@ -66,6 +69,8 @@ public class TournamentRequestHandler extends LotroServerRequestHandler implemen
_productLibrary = extractObject(context, ProductLibrary.class); _productLibrary = extractObject(context, ProductLibrary.class);
_deckRenderer = new DeckRenderer(_library, _formatLibrary, _sortAndFilterCards); _deckRenderer = new DeckRenderer(_library, _formatLibrary, _sortAndFilterCards);
_hallServer = extractObject(context, HallServer.class);
} }
@Override @Override
@@ -130,6 +135,10 @@ public class TournamentRequestHandler extends LotroServerRequestHandler implemen
String playoff = getFormParameterSafely(postDecoder, "playoff"); String playoff = getFormParameterSafely(postDecoder, "playoff");
String maxPlayersStr = getFormParameterSafely(postDecoder, "maxPlayers"); String maxPlayersStr = getFormParameterSafely(postDecoder, "maxPlayers");
String competitiveStr = getFormParameterSafely(postDecoder, "competitive");
boolean competitive = Throw400IfNullOrNonBoolean("competitive", competitiveStr);
String sealedFormatCodeStr = getFormParameterSafely(postDecoder, "sealedFormatCode"); String sealedFormatCodeStr = getFormParameterSafely(postDecoder, "sealedFormatCode");
String soloDraftFormatCodeStr = getFormParameterSafely(postDecoder, "soloDraftFormatCode"); String soloDraftFormatCodeStr = getFormParameterSafely(postDecoder, "soloDraftFormatCode");
@@ -151,7 +160,11 @@ public class TournamentRequestHandler extends LotroServerRequestHandler implemen
var params = new TournamentParams(); var params = new TournamentParams();
String casual = "Casual "; String casualPrefix = "Casual ";
String competitivePrefix = "Competitive ";
String prefix = competitive ? competitivePrefix : casualPrefix;
//TODO ready check, ready check time, startable early
if(type == Tournament.TournamentType.SEALED) { if(type == Tournament.TournamentType.SEALED) {
var sealedParams = new SealedTournamentParams(); var sealedParams = new SealedTournamentParams();
@@ -165,7 +178,7 @@ public class TournamentRequestHandler extends LotroServerRequestHandler implemen
Throw400IfValidationFails("sealedFormatCode", sealedFormatCodeStr,sealedFormat != null); Throw400IfValidationFails("sealedFormatCode", sealedFormatCodeStr,sealedFormat != null);
sealedParams.sealedFormatCode = sealedFormatCodeStr; sealedParams.sealedFormatCode = sealedFormatCodeStr;
sealedParams.format = sealedFormat.GetFormat().getCode(); sealedParams.format = sealedFormat.GetFormat().getCode();
sealedParams.name = casual + sealedFormat.GetName(); sealedParams.name = prefix + sealedFormat.GetName().substring(3); // Strip the ordering number for sealed formats
params = sealedParams; params = sealedParams;
} }
else if (type == Tournament.TournamentType.SOLODRAFT) { else if (type == Tournament.TournamentType.SOLODRAFT) {
@@ -181,10 +194,10 @@ public class TournamentRequestHandler extends LotroServerRequestHandler implemen
soloDraftParams.soloDraftFormatCode = soloDraftFormatCodeStr; soloDraftParams.soloDraftFormatCode = soloDraftFormatCodeStr;
soloDraftParams.format = soloDraftFormat.getFormat(); soloDraftParams.format = soloDraftFormat.getFormat();
switch (soloDraftFormatCodeStr) { switch (soloDraftFormatCodeStr) {
case "fotr_draft" -> soloDraftParams.name = casual + "FotR Solo Draft"; case "fotr_draft" -> soloDraftParams.name = prefix + "FotR Solo Draft";
case "ttt_draft" -> soloDraftParams.name = casual + "TTT Solo Draft"; case "ttt_draft" -> soloDraftParams.name = prefix + "TTT Solo Draft";
case "hobbit_random_draft" -> soloDraftParams.name = casual + "Hobbit Solo Draft"; case "hobbit_random_draft" -> soloDraftParams.name = prefix + "Hobbit Solo Draft";
default -> soloDraftParams.name = casual + soloDraftFormatCodeStr; default -> soloDraftParams.name = prefix + soloDraftFormatCodeStr;
} }
params = soloDraftParams; params = soloDraftParams;
} }
@@ -200,7 +213,7 @@ public class TournamentRequestHandler extends LotroServerRequestHandler implemen
Throw400IfValidationFails("soloTableDraftFormatCode", soloTableDraftFormatCodeStr,tableDraftDefinition != null); Throw400IfValidationFails("soloTableDraftFormatCode", soloTableDraftFormatCodeStr,tableDraftDefinition != null);
soloTableDraftParams.soloTableDraftFormatCode = soloTableDraftFormatCodeStr; soloTableDraftParams.soloTableDraftFormatCode = soloTableDraftFormatCodeStr;
soloTableDraftParams.format = tableDraftDefinition.getFormat(); soloTableDraftParams.format = tableDraftDefinition.getFormat();
soloTableDraftParams.name = casual + tableDraftDefinition.getName(); soloTableDraftParams.name = prefix + tableDraftDefinition.getName();
params = soloTableDraftParams; params = soloTableDraftParams;
} }
else if (type == Tournament.TournamentType.TABLE_DRAFT) { else if (type == Tournament.TournamentType.TABLE_DRAFT) {
@@ -216,7 +229,7 @@ public class TournamentRequestHandler extends LotroServerRequestHandler implemen
tableDraftParams.tableDraftFormatCode = tableDraftFormatCodeStr; tableDraftParams.tableDraftFormatCode = tableDraftFormatCodeStr;
tableDraftParams.format = tableDraftDefinition.getFormat(); tableDraftParams.format = tableDraftDefinition.getFormat();
tableDraftParams.draftTimerType = DraftTimer.getTypeFromString(tableDraftTimer); tableDraftParams.draftTimerType = DraftTimer.getTypeFromString(tableDraftTimer);
tableDraftParams.name = casual + tableDraftDefinition.getName(); tableDraftParams.name = prefix + tableDraftDefinition.getName();
params = tableDraftParams; params = tableDraftParams;
} }
else { else {
@@ -251,7 +264,7 @@ public class TournamentRequestHandler extends LotroServerRequestHandler implemen
return; return;
} }
if (_tournamentService.addPlayerMadeLimitedQueue(info, resourceOwner, false, -1)) { if (_hallServer.addPlayerMadeLimitedQueue(info, resourceOwner, false, -1)) {
responseWriter.sendJsonOK(); responseWriter.sendJsonOK();
} else { } else {
Throw400IfValidationFails("Error", "Error", false, "Error while creating queue or joining"); Throw400IfValidationFails("Error", "Error", false, "Error while creating queue or joining");

View File

@@ -1445,7 +1445,7 @@ var GempLotrCommunication = Class.extend({
}); });
}, },
createTournament:function (type, maxPlayers, sealedFormatCode, soloDraftFormatCode, tableDraftFormatCode, tableDraftTimer, createTournament:function (type, maxPlayers, sealedFormatCode, soloDraftFormatCode, tableDraftFormatCode, tableDraftTimer,
playoff, deckbuildingDuration, callback, errorMap) { playoff, deckbuildingDuration, competitive, callback, errorMap) {
$.ajax({ $.ajax({
type:"POST", type:"POST",
url:this.url + "/tournament/create", url:this.url + "/tournament/create",
@@ -1459,6 +1459,7 @@ var GempLotrCommunication = Class.extend({
tableDraftTimer:tableDraftTimer, tableDraftTimer:tableDraftTimer,
playoff:playoff, playoff:playoff,
deckbuildingDuration:deckbuildingDuration, deckbuildingDuration:deckbuildingDuration,
competitive:competitive,
participantId:getUrlParam("participantId") participantId:getUrlParam("participantId")
}, },
success:this.deliveryCheck(callback), success:this.deliveryCheck(callback),

View File

@@ -209,6 +209,10 @@ var GempLotrHallUI = Class.extend({
$toggleAdvanced.off("click").on("click", function () { $toggleAdvanced.off("click").on("click", function () {
advancedVisible = !advancedVisible; advancedVisible = !advancedVisible;
$advanced.toggle(advancedVisible); $advanced.toggle(advancedVisible);
if (advancedVisible) {
// Scroll to bottom so that the new field can be seen
$("#limitedGameForm").get(0).scrollIntoView({ behavior: "smooth", block: "end" });
}
$(this).text(advancedVisible ? "Hide advanced settings" : "Show advanced settings"); $(this).text(advancedVisible ? "Hide advanced settings" : "Show advanced settings");
}); });
@@ -255,6 +259,13 @@ var GempLotrHallUI = Class.extend({
.append($("<option>").val("SWISS").text("Swiss")) .append($("<option>").val("SWISS").text("Swiss"))
.append($("<option>").val("SINGLE_ELIMINATION").text("Single elimination")); .append($("<option>").val("SINGLE_ELIMINATION").text("Single elimination"));
// Competitive
const $competitiveLabel = $("<label>").attr("for", "competitiveSelect").text("Competitive:");
const $competitiveSelect = $("<select>")
.attr({ id: "competitiveSelect", name: "competitive" })
.append($("<option>").val("false").text("Games can be spectated"))
.append($("<option>").val("true").text("No spectate; hidden names in queue"));
// Deck-building duration // Deck-building duration
const $durationLabel = $("<label>").attr("for", "deckDuration").text("Deck-building duration (minutes, minimum 5):"); const $durationLabel = $("<label>").attr("for", "deckDuration").text("Deck-building duration (minutes, minimum 5):");
const $durationInput = $("<input>") const $durationInput = $("<input>")
@@ -292,7 +303,9 @@ var GempLotrHallUI = Class.extend({
$("<div>").append($pairingLabel), $("<div>").append($pairingLabel),
$("<div>").append($pairingSelect), $("<div>").append($pairingSelect),
$("<div>").append($durationLabel), $("<div>").append($durationLabel),
$("<div>").append($durationInput) $("<div>").append($durationInput),
$("<div>").append($competitiveLabel),
$("<div>").append($competitiveSelect)
); );
// Add validating listeners // Add validating listeners
@@ -340,6 +353,9 @@ var GempLotrHallUI = Class.extend({
// Pairing // Pairing
const playoff = $("#pairingType").val(); const playoff = $("#pairingType").val();
const competitive = $("#competitiveSelect").val();
// Deck building duration (number input) // Deck building duration (number input)
const deckbuildingDuration = parseInt($("#deckDuration").val(), 10) || 15; const deckbuildingDuration = parseInt($("#deckDuration").val(), 10) || 15;
const maxPlayers = parseInt($("#numPlayers").val(), 10) || 4; const maxPlayers = parseInt($("#numPlayers").val(), 10) || 4;
@@ -354,6 +370,7 @@ var GempLotrHallUI = Class.extend({
tableDraftTimer, tableDraftTimer,
playoff, playoff,
deckbuildingDuration, deckbuildingDuration,
competitive,
function(json) { function(json) {
// Success callback — handle your response here // Success callback — handle your response here
console.log("Tournament created successfully:", json); console.log("Tournament created successfully:", json);

View File

@@ -21,10 +21,7 @@ import com.gempukku.lotro.logic.GameUtils;
import com.gempukku.lotro.logic.timing.GameResultListener; import com.gempukku.lotro.logic.timing.GameResultListener;
import com.gempukku.lotro.logic.vo.LotroDeck; import com.gempukku.lotro.logic.vo.LotroDeck;
import com.gempukku.lotro.service.AdminService; import com.gempukku.lotro.service.AdminService;
import com.gempukku.lotro.tournament.Tournament; import com.gempukku.lotro.tournament.*;
import com.gempukku.lotro.tournament.TournamentCallback;
import com.gempukku.lotro.tournament.TournamentQueue;
import com.gempukku.lotro.tournament.TournamentService;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -476,6 +473,21 @@ public class HallServer extends AbstractServer {
} }
} }
public boolean addPlayerMadeLimitedQueue(TournamentInfo info, Player player, boolean startableEarly, int readyCheckTimeSecs) throws SQLException, IOException {
_hallDataAccessLock.writeLock().lock();
try {
boolean success = _tournamentService.addPlayerMadeLimitedQueue(info, player, startableEarly, readyCheckTimeSecs);
if (success) {
hallChanged();
}
return success;
} finally {
_hallDataAccessLock.writeLock().unlock();
}
}
public void leaveQueue(String queueId, Player player) throws SQLException, IOException { public void leaveQueue(String queueId, Player player) throws SQLException, IOException {
_hallDataAccessLock.writeLock().lock(); _hallDataAccessLock.writeLock().lock();
try { try {
@@ -916,9 +928,9 @@ public class HallServer extends AbstractServer {
private HallTournamentCallback(Tournament tournament) { private HallTournamentCallback(Tournament tournament) {
tournamentId = tournament.getTournamentId(); tournamentId = tournament.getTournamentId();
tournamentName = tournament.getTournamentName(); tournamentName = tournament.getTournamentName();
// Tournaments with no prizes and no entry are not competitive // Tournaments with no prizes or with 'casual' in their names are not competitive
boolean casual = tournament.getInfo().Parameters().prizes == Tournament.PrizeType.NONE boolean casual = tournament.getInfo().Parameters().prizes == Tournament.PrizeType.NONE
&& tournament.getInfo().Parameters().cost == 0; || tournamentName.toLowerCase().contains("casual");
if (tournament.isWC()) { if (tournament.isWC()) {
gameSettings = new GameSettings(null, _formatLibrary.getFormat(tournament.getFormatCode()), gameSettings = new GameSettings(null, _formatLibrary.getFormat(tournament.getFormatCode()),

View File

@@ -283,7 +283,11 @@ public abstract class AbstractTournamentQueue implements TournamentQueue {
@Override @Override
public String getPlayerList() { public String getPlayerList() {
return _playerList; if (_tournamentQueueName.toLowerCase().contains("competitive")) {
return "Competitive, player count: " + _players.size();
} else {
return _playerList;
}
} }
@Override @Override