diff --git a/dashboard/pom.xml b/dashboard/pom.xml index 215093e..cddc3ad 100644 --- a/dashboard/pom.xml +++ b/dashboard/pom.xml @@ -168,6 +168,30 @@ + + org.apache.maven.plugins + maven-antrun-plugin + 3.1.0 + + + delete-mvnpm-deps + package + + run + + + + + + + + + + + + + + diff --git a/dashboard/src/main/java/rest/Dashboard.java b/dashboard/src/main/java/rest/Dashboard.java index f385c25..30cb9b4 100644 --- a/dashboard/src/main/java/rest/Dashboard.java +++ b/dashboard/src/main/java/rest/Dashboard.java @@ -76,11 +76,35 @@ public void reset() { @Produces(MediaType.SERVER_SENT_EVENTS) @RestStreamElementType(MediaType.TEXT_PLAIN) - public Multi events(@Context Sse sse) { + public Multi boardEvents(@Context Sse sse) { return gameService.events() + .filter(e -> e.type().sseEventName().equals("BoardUpdate") || e.type().sseEventName().equals("GameUpdate")) .group().intoLists() - .every(Duration.ofMillis(200)) - .map(g -> sse.newEvent(resolveSseEventName(g), "")); + .every(Duration.ofMillis(500)) + .map(g -> sse.newEvent("BoardUpdate", compactHtml(Templates.board().render()))); + } + + @Produces(MediaType.SERVER_SENT_EVENTS) + @RestStreamElementType(MediaType.TEXT_PLAIN) + public Multi controlsEvents(@Context Sse sse) { + return gameService.events() + .filter(e -> e.type().sseEventName().equals("ControlsUpdate") || e.type().sseEventName().equals("GameUpdate")) + .map(g -> sse.newEvent("ControlsUpdate", compactHtml(Templates.controls().render()))); + } + + private static String compactHtml(String html) { + return html.replaceAll("(\\s+|\\v)", " "); + } + + private String resolveEventData(String eventName) { + switch (eventName) { + case "BoardUpdate": + return Templates.board().render(); + case "ControlsUpdate": + return Templates.controls().render(); + default: + return Templates.index$game().render(); + } } private static String resolveSseEventName(List g) { diff --git a/dashboard/src/main/java/service/GameService.java b/dashboard/src/main/java/service/GameService.java index 8e32697..bd80a0f 100644 --- a/dashboard/src/main/java/service/GameService.java +++ b/dashboard/src/main/java/service/GameService.java @@ -120,7 +120,7 @@ public void stop() { rank.set(null); watching.set(null); watchStatus.set(OFF); - runners.replaceAll((r, v) -> v.runner().initialState()); + runners.replaceAll((r, v) -> v.active() ? v.runner().initialState() : v.runner().setInactive()); emitEvent(STOP); } @@ -129,7 +129,7 @@ public void reset() { watching.set(null); watchStatus.set(OFF); rank.set(null); - runners.replaceAll((r, v) -> v.runner().inactive()); + runners.replaceAll((r, v) -> v.runner().setInactive()); emitEvent(RESET); } @@ -177,6 +177,10 @@ public Collection runners() { return runners.values(); } + public Collection activeRunners() { + return runners.values().stream().filter(RunnerState::active).toList(); + } + public WatchStatus watchStatus() { return watchStatus.get(); } @@ -190,7 +194,7 @@ public Runner newRunner(String prevId) { if (prevId != null && runners.containsKey(prevId)) { final RunnerState state = runners.get(prevId); runner = state.runner(); - if (!state.isActive()) { + if (!state.active()) { runners.put(runner.id(), runner.initialState()); } } else { @@ -229,7 +233,7 @@ public void run(String runnerId, int distance, long time) { return null; } // inactive user becoming active - if (!state.isActive()) { + if (!state.active()) { emitEvent(NEW_RUNNER); return state.runner().initialState(); } @@ -296,7 +300,7 @@ public int getRank(String id) { } static Comparator rankComparator() { - return comparing(RunnerState::isActive).reversed() + return comparing(RunnerState::active).reversed() .thenComparing(comparing(RunnerState::saved).reversed()) .thenComparing(comparing(RunnerState::alive).reversed()) .thenComparing(comparing(RunnerState::distance).reversed()) @@ -339,14 +343,14 @@ public RunnerState initialState() { return new RunnerState(this, 0, 0, RunnerState.Status.alive); } - public RunnerState inactive() { + public RunnerState setInactive() { return new RunnerState(this, 0, 0, RunnerState.Status.inactive); } } - public int indexPercentage(int index) { - return (int) Math.floor((index + 0.5) * 100 / runners().size()); + public int indexPercentage(int index, int max) { + return (int) Math.floor((index + 0.5) * 100 / max); } public record RunnerState(Runner runner, int distance, long duration, Status status) { @@ -366,11 +370,15 @@ public boolean saved() { return status == Status.saved; } + public boolean inactive() { + return status == Status.inactive; + } + public boolean gameOver() { - return saved() || dead(); + return saved() || dead() || inactive(); } - public boolean isActive() { + public boolean active() { return status != Status.inactive; } diff --git a/dashboard/src/main/resources/application.properties b/dashboard/src/main/resources/application.properties index 0cd0f4c..8d531e3 100644 --- a/dashboard/src/main/resources/application.properties +++ b/dashboard/src/main/resources/application.properties @@ -11,7 +11,7 @@ mp.messaging.incoming.runners-in.topic=runners %dev.quarkus.http.cors=true %dev.quarkus.http.cors.origins=* - +quarkus.http.enable-compression=true quarkus.csrf-reactive.require-form-url-encoded=false game.target-distance=100 diff --git a/dashboard/src/main/resources/templates/Dashboard/board.html b/dashboard/src/main/resources/templates/Dashboard/board.html index 34441bf..bc435ec 100644 --- a/dashboard/src/main/resources/templates/Dashboard/board.html +++ b/dashboard/src/main/resources/templates/Dashboard/board.html @@ -1,7 +1,7 @@ -{#for item in cdi:game.runners} +{#let activeRunners = cdi:game.activeRunners} +{#for item in activeRunners} {#if item.active} - + {item.runner.name} {/if} diff --git a/dashboard/src/main/resources/templates/Dashboard/controls.html b/dashboard/src/main/resources/templates/Dashboard/controls.html index d5005d3..8cf475d 100644 --- a/dashboard/src/main/resources/templates/Dashboard/controls.html +++ b/dashboard/src/main/resources/templates/Dashboard/controls.html @@ -1,4 +1,4 @@ - + {#when cdi:game.watchStatus} {#is WATCHING} One-Two-Three @@ -11,13 +11,13 @@ {config:venue} {#is WARNING} - + {#is ROCKING} - + {#is GAME_OVER} + +> {#fragment id=game} - - {#include Dashboard/board /} - - - {#include Dashboard/controls /} - + {#include Dashboard/board /} + {#include Dashboard/controls /} {/fragment} \ No newline at end of file diff --git a/dashboard/src/main/resources/web/app/app.js b/dashboard/src/main/resources/web/app/app.js index 8a04337..feb983b 100644 --- a/dashboard/src/main/resources/web/app/app.js +++ b/dashboard/src/main/resources/web/app/app.js @@ -1,6 +1,9 @@ -import "htmx.org"; +import htmx from "htmx.org"; import "idiomorph"; import _hyperscript from "hyperscript.org"; import "bootstrap"; +window.htmx = htmx; + +require("htmx.org/dist/ext/sse"); _hyperscript.browserInit(); diff --git a/dashboard/src/main/resources/web/app/board.scss b/dashboard/src/main/resources/web/app/board.scss index 6d2b6ef..81627a6 100644 --- a/dashboard/src/main/resources/web/app/board.scss +++ b/dashboard/src/main/resources/web/app/board.scss @@ -11,15 +11,16 @@ bottom: 0; left: 0; border-radius: 50px; - height: 70px; - width: 70px; + height: 30px; + width: 30px; font-size: 30px; - border: 3px solid blue; + font-size: 12px; + border: 2px solid blue; display: flex; justify-content: center; align-items: center; font-weight: bold; - transition: bottom 200ms linear; + transition: all 1000ms linear; background-color: white; &.dead { diff --git a/pom.xml b/pom.xml index a50c043..ac813ef 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ true 3.1.2 3.0.4 - 1.2.0.alpha1 + 1.2.0.alpha2 0.0.1 diff --git a/runners/pom.xml b/runners/pom.xml index 76aa8cd..e88484e 100644 --- a/runners/pom.xml +++ b/runners/pom.xml @@ -205,6 +205,30 @@ + + org.apache.maven.plugins + maven-antrun-plugin + 3.1.0 + + + delete-mvnpm-deps + package + + run + + + + + + + + + + + + + + diff --git a/runners/src/main/resources/templates/pub/index.html b/runners/src/main/resources/web/index.html similarity index 100% rename from runners/src/main/resources/templates/pub/index.html rename to runners/src/main/resources/web/index.html diff --git a/scripts/GameLoader.java b/scripts/GameLoader.java index 8c6af4f..14e0f39 100755 --- a/scripts/GameLoader.java +++ b/scripts/GameLoader.java @@ -46,7 +46,7 @@ class GameLoader implements Callable { - @Option(names = {"-p", "--players"}, description = "The amount of players to assign", defaultValue = "1000") + @Option(names = {"-p", "--players"}, description = "The amount of players to assign", defaultValue = "100") private int players; @Option(names = {"-c", "--clicks"}, description = "How many click each player will trigger", defaultValue = "200") @@ -102,10 +102,11 @@ void load() throws InterruptedException { }); } latchLogin.await(); - Thread.sleep(5000); + Thread.sleep(1000); System.out.println(users.size() + "users created"); System.out.println(names.size() + " different names"); AtomicReference statusRef = new AtomicReference<>("OFF"); + Random random = new Random(); while (!Objects.equals(statusRef.get(), "GAME_OVER")) { client.request(HttpMethod.GET, portDashboard, urlDashboard.getHost(), "/api/game/status") @@ -123,13 +124,12 @@ void load() throws InterruptedException { }); for (JsonObject user : users) { - Thread.sleep(2); if(statusRef.get().equals("ROCKING")) { client.request(HttpMethod.POST, portRunners, urlRunners.getHost(), "/api/run") .expect(ResponsePredicate.SC_SUCCESS) .ssl(ssl) - .sendJsonObject(new JsonObject().put("distance", power).put("runner", user.getString("id"))) + .sendJsonObject(new JsonObject().put("distance", random.nextInt(power)).put("runner", user.getString("id"))) .onComplete((r) -> { if (r.failed()) { r.cause().printStackTrace(); @@ -137,6 +137,7 @@ void load() throws InterruptedException { }); } } + Thread.sleep(5); } System.out.println("game started");