diff --git a/frontend/prebuild/src/app/login/login.component.html b/frontend/prebuild/src/app/login/login.component.html index 1828ac8..f5bf640 100644 --- a/frontend/prebuild/src/app/login/login.component.html +++ b/frontend/prebuild/src/app/login/login.component.html @@ -3,18 +3,24 @@

Liberty Bikes

-
+
+
+
+ +
+
+
-
- +
+
diff --git a/frontend/prebuild/src/app/login/login.component.scss b/frontend/prebuild/src/app/login/login.component.scss index f6b66c8..26f77bb 100644 --- a/frontend/prebuild/src/app/login/login.component.scss +++ b/frontend/prebuild/src/app/login/login.component.scss @@ -42,7 +42,7 @@ padding-bottom: 50px; } -#login-form { +.login-form { width: 100%; margin-bottom: 15px; } @@ -85,7 +85,7 @@ text-transform: uppercase; } -#button-bar { +.button-bar { display: flex; flex-flow: column; width: 100%; @@ -93,7 +93,7 @@ padding-right: 10px; } -#button-bar button { +.button-bar button { width: 100%; margin-top: 6px; margin-bottom: 6px; diff --git a/frontend/prebuild/src/app/login/login.component.ts b/frontend/prebuild/src/app/login/login.component.ts index 1e41b4f..e58d32f 100644 --- a/frontend/prebuild/src/app/login/login.component.ts +++ b/frontend/prebuild/src/app/login/login.component.ts @@ -36,11 +36,23 @@ export class LoginComponent implements OnInit { } } + + async quickJoin() { + // First get an unstarted round ID + let roundID = await this.http.post(`${environment.API_URL_GAME_ROUND}/available`, "", { responseType: 'text' }).toPromise(); + + // Then join the round + this.joinRoundById(roundID); + } + + async joinRound() { + let roundID: string = $('#roundid').val(); + this.joinRoundById(roundID); + } -async joinRound() { +async joinRoundById(roundID: string) { let ngZone = this.ngZone; let router = this.router; - let roundID: string = $('#roundid').val(); let username: string = $('#username').val(); roundID = roundID.toUpperCase().replace(/[^A-Z]/g, ''); let gameBoard = true; diff --git a/game-service/src/main/java/org/libertybikes/game/core/GameRound.java b/game-service/src/main/java/org/libertybikes/game/core/GameRound.java index 91ec9bf..e30be7c 100644 --- a/game-service/src/main/java/org/libertybikes/game/core/GameRound.java +++ b/game-service/src/main/java/org/libertybikes/game/core/GameRound.java @@ -399,6 +399,9 @@ public class GameRound implements Runnable { // If there are any clients still connected to this game, keep sending heartbeats if (round.clients.size() == 0) { log("No clients remaining. Cancelling heartbeat."); + // Ensure that game state is closed off so that no other players can quick join while a round is marked for deletion + if (gameState == State.OPEN) + gameState = State.FINISHED; return null; } return Date.from(Instant.now().plusSeconds(HEARTBEAT_INTERVAL_SEC)); diff --git a/game-service/src/main/java/org/libertybikes/game/round/service/GameRoundService.java b/game-service/src/main/java/org/libertybikes/game/round/service/GameRoundService.java index 1a93c5d..549631c 100644 --- a/game-service/src/main/java/org/libertybikes/game/round/service/GameRoundService.java +++ b/game-service/src/main/java/org/libertybikes/game/round/service/GameRoundService.java @@ -2,6 +2,7 @@ package org.libertybikes.game.round.service; import java.util.Collection; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -16,6 +17,7 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import org.libertybikes.game.core.GameRound; +import org.libertybikes.game.core.GameRound.State; @Path("/") @ApplicationScoped @@ -44,6 +46,19 @@ public class GameRoundService { return p.id; } + @POST + @Path("/available") + public String getAvailableRound() { + Optional availableRound = allRounds.values() + .stream() + .filter(r -> r.gameState == GameRound.State.OPEN) + .findFirst(); + if (availableRound.isPresent()) + return availableRound.get().id; + else + return createRound(); + } + @GET @Path("/{roundId}") @Produces(MediaType.APPLICATION_JSON) @@ -71,7 +86,10 @@ public class GameRoundService { return nextRound; } - public void deleteRound(String roundId) { + public void deleteRound(GameRound round) { + String roundId = round.id; + if (round.gameState == State.OPEN) + round.gameState = State.FINISHED; System.out.println("Scheduling round id=" + roundId + " for deletion in 5 minutes"); // Do not immediately delete rounds in order to give players/spectators time to move along to the next game exec.schedule(() -> { diff --git a/game-service/src/main/java/org/libertybikes/game/round/service/GameRoundWebsocket.java b/game-service/src/main/java/org/libertybikes/game/round/service/GameRoundWebsocket.java index 288dc52..d43d669 100644 --- a/game-service/src/main/java/org/libertybikes/game/round/service/GameRoundWebsocket.java +++ b/game-service/src/main/java/org/libertybikes/game/round/service/GameRoundWebsocket.java @@ -51,7 +51,7 @@ public class GameRoundWebsocket { GameRound round = gameSvc.getRound(roundId); if (round != null) if (round.removeClient(session) == 0) - gameSvc.deleteRound(roundId); + gameSvc.deleteRound(round); } catch (Exception e) { e.printStackTrace(); }