diff --git a/build b/build new file mode 100755 index 0000000..7bfb546 --- /dev/null +++ b/build @@ -0,0 +1 @@ +./mvnw spring-boot:build-image && docker push simonharrer/mob-timer && ssh root@timer.mob.sh 'bash -s' < deploy \ No newline at end of file diff --git a/deploy b/deploy new file mode 100644 index 0000000..adf245e --- /dev/null +++ b/deploy @@ -0,0 +1,3 @@ +docker stop mobtimer +docker rm mobtimer +docker run -d -e VIRTUAL_HOST=timer.mob.sh -e LETSENCRYPT_HOST=timer.mob.sh -e LETSENCRYPT_EMAIL=simon.harrer@gmail.com -e PORT=80 --expose 80 --network=proxy --pull always --name mobtimer simonharrer/mob-timer:latest \ No newline at end of file diff --git a/pom.xml b/pom.xml index 022a54c..3d4d8b1 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ timer timer - 17 + 11 @@ -58,8 +58,8 @@ maven-compiler-plugin org.apache.maven.plugins - 17 - 17 + ${java.version} + ${java.version} diff --git a/src/main/java/sh/mob/timer/web/IndexController.java b/src/main/java/sh/mob/timer/web/IndexController.java index c958dbd..fa2056e 100644 --- a/src/main/java/sh/mob/timer/web/IndexController.java +++ b/src/main/java/sh/mob/timer/web/IndexController.java @@ -1,5 +1,6 @@ package sh.mob.timer.web; +import java.util.Objects; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @@ -28,8 +29,40 @@ public String index(Model model) { @PostMapping public String post(@ModelAttribute Form form) { - return "redirect:/%s".formatted(form.room()); + return String.format("redirect:/%s", form.room()); } - public record Form (String room) {} + public static final class Form { + + private final String room; + + public Form(String room) { + this.room = room; + } + + public String room() { + return room; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) + return true; + if (obj == null || obj.getClass() != this.getClass()) + return false; + var that = (Form) obj; + return Objects.equals(this.room, that.room); + } + + @Override + public int hashCode() { + return Objects.hash(room); + } + + @Override + public String toString() { + return "Form[" + + "room=" + room + ']'; + } + } } diff --git a/src/main/java/sh/mob/timer/web/Room.java b/src/main/java/sh/mob/timer/web/Room.java index b85f05b..a9a6b79 100644 --- a/src/main/java/sh/mob/timer/web/Room.java +++ b/src/main/java/sh/mob/timer/web/Room.java @@ -5,7 +5,9 @@ import java.time.temporal.ChronoUnit; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.stream.Collectors; final class Room { @@ -40,10 +42,66 @@ public TimeLeft timeLeft() { return new TimeLeft(result, timer, lastTimerRequestedTimestamp, lastTimerRequest.user()); } - public record TimeLeft(Duration duration, Long timer, Instant requested, String name) {} + public static final class TimeLeft { + + private final Duration duration; + private final Long timer; + private final Instant requested; + private final String name; + + public TimeLeft(Duration duration, Long timer, Instant requested, String name) { + this.duration = duration; + this.timer = timer; + this.requested = requested; + this.name = name; + } + + public Duration duration() { + return duration; + } + + public Long timer() { + return timer; + } + + public Instant requested() { + return requested; + } + + public String name() { + return name; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) + return true; + if (obj == null || obj.getClass() != this.getClass()) + return false; + var that = (TimeLeft) obj; + return Objects.equals(this.duration, that.duration) && + Objects.equals(this.timer, that.timer) && + Objects.equals(this.requested, that.requested) && + Objects.equals(this.name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(duration, timer, requested, name); + } + + @Override + public String toString() { + return "TimeLeft[" + + "duration=" + duration + ", " + + "timer=" + timer + ", " + + "requested=" + requested + ", " + + "name=" + name + ']'; + } + } public List team() { - return timerRequests().stream().map(TimerRequest::user).distinct().sorted().toList(); + return timerRequests().stream().map(TimerRequest::user).distinct().sorted().collect(Collectors.toList()); } public String name() { @@ -54,5 +112,53 @@ public List timerRequests() { return Collections.unmodifiableList(timerRequests); } - record TimerRequest(Long timer, Instant requested, String user) {} + static final class TimerRequest { + + private final Long timer; + private final Instant requested; + private final String user; + + TimerRequest(Long timer, Instant requested, String user) { + this.timer = timer; + this.requested = requested; + this.user = user; + } + + public Long timer() { + return timer; + } + + public Instant requested() { + return requested; + } + + public String user() { + return user; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) + return true; + if (obj == null || obj.getClass() != this.getClass()) + return false; + var that = (TimerRequest) obj; + return Objects.equals(this.timer, that.timer) && + Objects.equals(this.requested, that.requested) && + Objects.equals(this.user, that.user); + } + + @Override + public int hashCode() { + return Objects.hash(timer, requested, user); + } + + @Override + public String toString() { + return "TimerRequest[" + + "timer=" + timer + ", " + + "requested=" + requested + ", " + + "user=" + user + ']'; + } + } } diff --git a/src/main/java/sh/mob/timer/web/RoomApiController.java b/src/main/java/sh/mob/timer/web/RoomApiController.java index 41dda6a..b408091 100644 --- a/src/main/java/sh/mob/timer/web/RoomApiController.java +++ b/src/main/java/sh/mob/timer/web/RoomApiController.java @@ -1,6 +1,7 @@ package sh.mob.timer.web; import java.time.Duration; +import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; import org.springframework.http.HttpStatus; @@ -67,13 +68,10 @@ private static ServerSentEvent timerUpdate(Long sequence, TimeLeft timeL String data = timeLeft.timer() == null ? "00:00" - : "%d:%d (%d min timer started by %s at %s)" - .formatted( - timeLeft.duration().toMinutesPart(), - timeLeft.duration().toSecondsPart(), - timeLeft.timer(), - timeLeft.name(), - timeLeft.requested().toString()); + : String.format( + "%02d:%02d", + timeLeft.duration().toMinutesPart(), + timeLeft.duration().toSecondsPart()); return ServerSentEvent.builder() .id(String.valueOf(sequence)) .event("TIMER_UPDATE") @@ -97,5 +95,40 @@ public void publishEvent(@PathVariable String roomId, @RequestBody TimerRequest System.out.println("timerRequest = " + timerRequest); } - record TimerRequest(Long timer, String user) {} + static final class TimerRequest { + + private final Long timer; + private final String user; + + TimerRequest(Long timer, String user) { + this.timer = timer; + this.user = user; + } + + public Long timer() { + return timer; + } + + public String user() { + return user; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (TimerRequest) obj; + return Objects.equals(this.timer, that.timer) && Objects.equals(this.user, that.user); + } + + @Override + public int hashCode() { + return Objects.hash(timer, user); + } + + @Override + public String toString() { + return "TimerRequest[" + "timer=" + timer + ", " + "user=" + user + ']'; + } + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e69de29..71a2e05 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.main.banner-mode=off +server.port=${PORT:8080} diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 1a5da6b..af6ea10 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -2,21 +2,42 @@ + + + Mob Timer - Mob Timer - - Rooms: [[${numberOfRooms}]] - Users: [[${numberOfUsers}]] - Connections: [[${numberOfConnections}]] + + + + Mob Timer + + + + + Mob Timer + + + Rooms [[${numberOfRooms}]] + Users [[${numberOfUsers}]] + Connections [[${numberOfConnections}]] - - Room - Join - + + + https://timer.mob.sh/ + + Join + + + + + + - \ No newline at end of file +