From ee0988c22e49222fcd5ae1ff9b4024eb4db5fcdb Mon Sep 17 00:00:00 2001 From: Topvennie Date: Tue, 26 Mar 2024 00:29:36 +0100 Subject: [PATCH 1/7] added simple positioner --- .../logic/positioners/CircularQueue.java | 30 +++++++++ .../logic/positioners/SimplePositioner.java | 66 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/main/java/telraam/logic/positioners/CircularQueue.java create mode 100644 src/main/java/telraam/logic/positioners/SimplePositioner.java diff --git a/src/main/java/telraam/logic/positioners/CircularQueue.java b/src/main/java/telraam/logic/positioners/CircularQueue.java new file mode 100644 index 0000000..eb0c403 --- /dev/null +++ b/src/main/java/telraam/logic/positioners/CircularQueue.java @@ -0,0 +1,30 @@ +package telraam.logic.positioners; + +import java.util.LinkedList; + +public class CircularQueue extends LinkedList { + + private final int maxSize; + private int size = 0; + + public CircularQueue(int maxSize) { + this.maxSize = maxSize; + } + + @Override + public boolean add(T e) { + if (this.size >= this.maxSize) { + super.removeFirst(); + this.size--; + } + + boolean result = super.add(e); + + if (result) { + this.size++; + } + + return result; + } + +} diff --git a/src/main/java/telraam/logic/positioners/SimplePositioner.java b/src/main/java/telraam/logic/positioners/SimplePositioner.java new file mode 100644 index 0000000..83d2872 --- /dev/null +++ b/src/main/java/telraam/logic/positioners/SimplePositioner.java @@ -0,0 +1,66 @@ +package telraam.logic.positioners; + +import org.jdbi.v3.core.Jdbi; +import telraam.database.daos.BatonSwitchoverDAO; +import telraam.database.daos.StationDAO; +import telraam.database.daos.TeamDAO; +import telraam.database.models.BatonSwitchover; +import telraam.database.models.Detection; +import telraam.database.models.Station; +import telraam.database.models.Team; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SimplePositioner { + private final int QUEUE_SIZE = 50; + private final int MIN_RSSI = -85; + private Map teamIdToTeam = new HashMap<>(); + private Map> teamDetections = new HashMap<>(); + private List stations; + + public SimplePositioner(Jdbi jdbi) { + TeamDAO teamDAO = jdbi.onDemand(TeamDAO.class); + List teams = teamDAO.getAll(); + for (Team team: teams) { + this.teamDetections.put(team, new CircularQueue<>(QUEUE_SIZE)); + } + List switchovers = jdbi.onDemand(BatonSwitchoverDAO.class).getAll(); + switchovers.sort(Comparator.comparing(BatonSwitchover::getTimestamp)); + + for (BatonSwitchover switchover: switchovers) { + this.teamIdToTeam.put(switchover.getNewBatonId(), teamDAO.getById(switchover.getTeamId()).get()); + } + + List stationList = jdbi.onDemand(StationDAO.class).getAll(); + stationList.sort(Comparator.comparing(Station::getDistanceFromStart)); + this.stations = stationList.stream().map(Station::getId).toList(); + } + + private void calculatePosition(Team team) { + List detections = this.teamDetections.get(team); + detections.sort(Comparator.comparing(Detection::getTimestamp)); + + int currentStationRssi = MIN_RSSI; + int currentStationPosition = 0; + for (Detection detection: detections) { + if (detection.getRssi() > currentStationRssi) { + currentStationRssi = detection.getRssi(); + currentStationPosition = detection.getStationId(); + } + } + + float progress = ((float) 100 / this.stations.size()) * this.stations.indexOf(currentStationPosition); + + System.out.printf("Team: %s | Progress: %f | Acceleration: %f%n", team.getName(), progress, 1.0); + } + + public void handle(Detection detection) { + Team team = this.teamIdToTeam.get(detection.getBatonId()); + this.teamDetections.get(team).add(detection); + this.calculatePosition(team); + } + +} From c4abdd9f1d65ff10f3247d640ab2a609bf2a0f0a Mon Sep 17 00:00:00 2001 From: Topvennie Date: Fri, 29 Mar 2024 11:17:40 +0100 Subject: [PATCH 2/7] refactor --- src/main/java/telraam/logic/{ => lapper}/Lapper.java | 0 .../telraam/logic/{ => lapper}/external/ExternalLapper.java | 0 .../logic/{ => lapper}/external/ExternalLapperResource.java | 0 .../logic/{ => lapper}/external/models/ExternalLapperLap.java | 0 .../{ => lapper}/external/models/ExternalLapperStats.java | 0 .../{ => lapper}/external/models/ExternalLapperTeamLaps.java | 0 .../java/telraam/logic/{ => lapper}/robust/RobustLapper.java | 0 .../java/telraam/logic/{ => lapper}/simple/SimpleLapper.java | 0 .../logic/{positioners => positioner}/CircularQueue.java | 0 src/main/java/telraam/logic/positioner/Position.java | 4 ++++ .../logic/{positioners => positioner}/SimplePositioner.java | 0 11 files changed, 4 insertions(+) rename src/main/java/telraam/logic/{ => lapper}/Lapper.java (100%) rename src/main/java/telraam/logic/{ => lapper}/external/ExternalLapper.java (100%) rename src/main/java/telraam/logic/{ => lapper}/external/ExternalLapperResource.java (100%) rename src/main/java/telraam/logic/{ => lapper}/external/models/ExternalLapperLap.java (100%) rename src/main/java/telraam/logic/{ => lapper}/external/models/ExternalLapperStats.java (100%) rename src/main/java/telraam/logic/{ => lapper}/external/models/ExternalLapperTeamLaps.java (100%) rename src/main/java/telraam/logic/{ => lapper}/robust/RobustLapper.java (100%) rename src/main/java/telraam/logic/{ => lapper}/simple/SimpleLapper.java (100%) rename src/main/java/telraam/logic/{positioners => positioner}/CircularQueue.java (100%) create mode 100644 src/main/java/telraam/logic/positioner/Position.java rename src/main/java/telraam/logic/{positioners => positioner}/SimplePositioner.java (100%) diff --git a/src/main/java/telraam/logic/Lapper.java b/src/main/java/telraam/logic/lapper/Lapper.java similarity index 100% rename from src/main/java/telraam/logic/Lapper.java rename to src/main/java/telraam/logic/lapper/Lapper.java diff --git a/src/main/java/telraam/logic/external/ExternalLapper.java b/src/main/java/telraam/logic/lapper/external/ExternalLapper.java similarity index 100% rename from src/main/java/telraam/logic/external/ExternalLapper.java rename to src/main/java/telraam/logic/lapper/external/ExternalLapper.java diff --git a/src/main/java/telraam/logic/external/ExternalLapperResource.java b/src/main/java/telraam/logic/lapper/external/ExternalLapperResource.java similarity index 100% rename from src/main/java/telraam/logic/external/ExternalLapperResource.java rename to src/main/java/telraam/logic/lapper/external/ExternalLapperResource.java diff --git a/src/main/java/telraam/logic/external/models/ExternalLapperLap.java b/src/main/java/telraam/logic/lapper/external/models/ExternalLapperLap.java similarity index 100% rename from src/main/java/telraam/logic/external/models/ExternalLapperLap.java rename to src/main/java/telraam/logic/lapper/external/models/ExternalLapperLap.java diff --git a/src/main/java/telraam/logic/external/models/ExternalLapperStats.java b/src/main/java/telraam/logic/lapper/external/models/ExternalLapperStats.java similarity index 100% rename from src/main/java/telraam/logic/external/models/ExternalLapperStats.java rename to src/main/java/telraam/logic/lapper/external/models/ExternalLapperStats.java diff --git a/src/main/java/telraam/logic/external/models/ExternalLapperTeamLaps.java b/src/main/java/telraam/logic/lapper/external/models/ExternalLapperTeamLaps.java similarity index 100% rename from src/main/java/telraam/logic/external/models/ExternalLapperTeamLaps.java rename to src/main/java/telraam/logic/lapper/external/models/ExternalLapperTeamLaps.java diff --git a/src/main/java/telraam/logic/robust/RobustLapper.java b/src/main/java/telraam/logic/lapper/robust/RobustLapper.java similarity index 100% rename from src/main/java/telraam/logic/robust/RobustLapper.java rename to src/main/java/telraam/logic/lapper/robust/RobustLapper.java diff --git a/src/main/java/telraam/logic/simple/SimpleLapper.java b/src/main/java/telraam/logic/lapper/simple/SimpleLapper.java similarity index 100% rename from src/main/java/telraam/logic/simple/SimpleLapper.java rename to src/main/java/telraam/logic/lapper/simple/SimpleLapper.java diff --git a/src/main/java/telraam/logic/positioners/CircularQueue.java b/src/main/java/telraam/logic/positioner/CircularQueue.java similarity index 100% rename from src/main/java/telraam/logic/positioners/CircularQueue.java rename to src/main/java/telraam/logic/positioner/CircularQueue.java diff --git a/src/main/java/telraam/logic/positioner/Position.java b/src/main/java/telraam/logic/positioner/Position.java new file mode 100644 index 0000000..988120c --- /dev/null +++ b/src/main/java/telraam/logic/positioner/Position.java @@ -0,0 +1,4 @@ +package telraam.logic.positioner; + +public class Position { +} diff --git a/src/main/java/telraam/logic/positioners/SimplePositioner.java b/src/main/java/telraam/logic/positioner/SimplePositioner.java similarity index 100% rename from src/main/java/telraam/logic/positioners/SimplePositioner.java rename to src/main/java/telraam/logic/positioner/SimplePositioner.java From 2a9cd403a2a961904ace8e0c0c6b4c35b76cbbe5 Mon Sep 17 00:00:00 2001 From: Topvennie Date: Fri, 29 Mar 2024 11:17:57 +0100 Subject: [PATCH 3/7] refactor --- src/main/java/telraam/App.java | 6 ++--- .../java/telraam/logic/lapper/Lapper.java | 2 +- .../logic/lapper/external/ExternalLapper.java | 6 ++--- .../external/ExternalLapperResource.java | 6 ++--- .../external/models/ExternalLapperLap.java | 2 +- .../external/models/ExternalLapperStats.java | 2 +- .../models/ExternalLapperTeamLaps.java | 2 +- .../logic/lapper/robust/RobustLapper.java | 4 +-- .../logic/lapper/simple/SimpleLapper.java | 4 +-- .../logic/positioner/CircularQueue.java | 2 +- .../telraam/logic/positioner/Position.java | 27 ++++++++++++++++++- .../logic/positioner/SimplePositioner.java | 2 +- src/main/java/telraam/station/Fetcher.java | 2 +- .../logic/simple/SimpleLapperTest.java | 4 +-- 14 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/main/java/telraam/App.java b/src/main/java/telraam/App.java index d7bfdba..5c93fe8 100644 --- a/src/main/java/telraam/App.java +++ b/src/main/java/telraam/App.java @@ -17,9 +17,9 @@ import telraam.database.daos.*; import telraam.database.models.Station; import telraam.healthchecks.TemplateHealthCheck; -import telraam.logic.Lapper; -import telraam.logic.external.ExternalLapper; -import telraam.logic.robust.RobustLapper; +import telraam.logic.lapper.Lapper; +import telraam.logic.lapper.external.ExternalLapper; +import telraam.logic.lapper.robust.RobustLapper; import telraam.station.Fetcher; import telraam.util.AcceptedLapsUtil; import telraam.websocket.WebSocketConnection; diff --git a/src/main/java/telraam/logic/lapper/Lapper.java b/src/main/java/telraam/logic/lapper/Lapper.java index c3dc674..d999307 100644 --- a/src/main/java/telraam/logic/lapper/Lapper.java +++ b/src/main/java/telraam/logic/lapper/Lapper.java @@ -1,4 +1,4 @@ -package telraam.logic; +package telraam.logic.lapper; import io.dropwizard.jersey.setup.JerseyEnvironment; import telraam.database.models.Detection; diff --git a/src/main/java/telraam/logic/lapper/external/ExternalLapper.java b/src/main/java/telraam/logic/lapper/external/ExternalLapper.java index 3aee9f2..510e28a 100644 --- a/src/main/java/telraam/logic/lapper/external/ExternalLapper.java +++ b/src/main/java/telraam/logic/lapper/external/ExternalLapper.java @@ -1,4 +1,4 @@ -package telraam.logic.external; +package telraam.logic.lapper.external; import io.dropwizard.jersey.setup.JerseyEnvironment; import org.jdbi.v3.core.Jdbi; @@ -7,8 +7,8 @@ import telraam.database.models.Detection; import telraam.database.models.Lap; import telraam.database.models.LapSource; -import telraam.logic.Lapper; -import telraam.logic.external.models.ExternalLapperTeamLaps; +import telraam.logic.lapper.Lapper; +import telraam.logic.lapper.external.models.ExternalLapperTeamLaps; import java.sql.Timestamp; import java.util.Comparator; diff --git a/src/main/java/telraam/logic/lapper/external/ExternalLapperResource.java b/src/main/java/telraam/logic/lapper/external/ExternalLapperResource.java index 37f8e58..55f6aa0 100644 --- a/src/main/java/telraam/logic/lapper/external/ExternalLapperResource.java +++ b/src/main/java/telraam/logic/lapper/external/ExternalLapperResource.java @@ -1,10 +1,10 @@ -package telraam.logic.external; +package telraam.logic.lapper.external; import io.swagger.v3.oas.annotations.Operation; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; -import telraam.logic.external.models.ExternalLapperStats; -import telraam.logic.external.models.ExternalLapperTeamLaps; +import telraam.logic.lapper.external.models.ExternalLapperStats; +import telraam.logic.lapper.external.models.ExternalLapperTeamLaps; import java.util.List; diff --git a/src/main/java/telraam/logic/lapper/external/models/ExternalLapperLap.java b/src/main/java/telraam/logic/lapper/external/models/ExternalLapperLap.java index f343ce1..3623891 100644 --- a/src/main/java/telraam/logic/lapper/external/models/ExternalLapperLap.java +++ b/src/main/java/telraam/logic/lapper/external/models/ExternalLapperLap.java @@ -1,4 +1,4 @@ -package telraam.logic.external.models; +package telraam.logic.lapper.external.models; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/telraam/logic/lapper/external/models/ExternalLapperStats.java b/src/main/java/telraam/logic/lapper/external/models/ExternalLapperStats.java index cc31a04..8c875bc 100644 --- a/src/main/java/telraam/logic/lapper/external/models/ExternalLapperStats.java +++ b/src/main/java/telraam/logic/lapper/external/models/ExternalLapperStats.java @@ -1,4 +1,4 @@ -package telraam.logic.external.models; +package telraam.logic.lapper.external.models; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/telraam/logic/lapper/external/models/ExternalLapperTeamLaps.java b/src/main/java/telraam/logic/lapper/external/models/ExternalLapperTeamLaps.java index c8e8170..fa37f63 100644 --- a/src/main/java/telraam/logic/lapper/external/models/ExternalLapperTeamLaps.java +++ b/src/main/java/telraam/logic/lapper/external/models/ExternalLapperTeamLaps.java @@ -1,4 +1,4 @@ -package telraam.logic.external.models; +package telraam.logic.lapper.external.models; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/telraam/logic/lapper/robust/RobustLapper.java b/src/main/java/telraam/logic/lapper/robust/RobustLapper.java index 2ad64c5..62ae807 100644 --- a/src/main/java/telraam/logic/lapper/robust/RobustLapper.java +++ b/src/main/java/telraam/logic/lapper/robust/RobustLapper.java @@ -1,4 +1,4 @@ -package telraam.logic.robust; +package telraam.logic.lapper.robust; import io.dropwizard.jersey.setup.JerseyEnvironment; import org.jdbi.v3.core.Jdbi; @@ -10,7 +10,7 @@ import telraam.database.models.Lap; import telraam.database.models.LapSource; import telraam.database.models.Station; -import telraam.logic.Lapper; +import telraam.logic.lapper.Lapper; import java.sql.Timestamp; import java.util.*; diff --git a/src/main/java/telraam/logic/lapper/simple/SimpleLapper.java b/src/main/java/telraam/logic/lapper/simple/SimpleLapper.java index 9b26f9b..608e724 100644 --- a/src/main/java/telraam/logic/lapper/simple/SimpleLapper.java +++ b/src/main/java/telraam/logic/lapper/simple/SimpleLapper.java @@ -1,11 +1,11 @@ -package telraam.logic.simple; +package telraam.logic.lapper.simple; import io.dropwizard.jersey.setup.JerseyEnvironment; import org.jdbi.v3.core.Jdbi; import telraam.database.daos.LapDAO; import telraam.database.daos.LapSourceDAO; import telraam.database.models.*; -import telraam.logic.Lapper; +import telraam.logic.lapper.Lapper; import java.util.ArrayList; import java.util.HashMap; diff --git a/src/main/java/telraam/logic/positioner/CircularQueue.java b/src/main/java/telraam/logic/positioner/CircularQueue.java index eb0c403..042ba79 100644 --- a/src/main/java/telraam/logic/positioner/CircularQueue.java +++ b/src/main/java/telraam/logic/positioner/CircularQueue.java @@ -1,4 +1,4 @@ -package telraam.logic.positioners; +package telraam.logic.positioner; import java.util.LinkedList; diff --git a/src/main/java/telraam/logic/positioner/Position.java b/src/main/java/telraam/logic/positioner/Position.java index 988120c..23bcf00 100644 --- a/src/main/java/telraam/logic/positioner/Position.java +++ b/src/main/java/telraam/logic/positioner/Position.java @@ -1,4 +1,29 @@ -package telraam.logic.positioner; +package telraam.logic.positioners; +import lombok.Getter; +import lombok.Setter; +import telraam.database.models.Team; +import telraam.websocket.WebSocketMessageSingleton; + +@Getter @Setter public class Position { + private Team team; + private float progress; // Progress of the lap. Between 0-1 + private float speed; // Current speed. Progress / second + + public Position(Team team) { + this.team = team; + this.progress = 0; + this.speed = 0; + } + + private String toWebsocketMessage() { + return String.format("{\"topic\": \"position\", \"data\": {\"team\": %d, \"progress\": %.4f, \"speed\": %.5f}}", team.getId(), this.progress, this.speed); + } + + public void send() { + WebSocketMessageSingleton.getInstance().sendToAll( + this.toWebsocketMessage() + ); + } } diff --git a/src/main/java/telraam/logic/positioner/SimplePositioner.java b/src/main/java/telraam/logic/positioner/SimplePositioner.java index 83d2872..794fa35 100644 --- a/src/main/java/telraam/logic/positioner/SimplePositioner.java +++ b/src/main/java/telraam/logic/positioner/SimplePositioner.java @@ -1,4 +1,4 @@ -package telraam.logic.positioners; +package telraam.logic.positioner; import org.jdbi.v3.core.Jdbi; import telraam.database.daos.BatonSwitchoverDAO; diff --git a/src/main/java/telraam/station/Fetcher.java b/src/main/java/telraam/station/Fetcher.java index 54e04db..d2cdce0 100644 --- a/src/main/java/telraam/station/Fetcher.java +++ b/src/main/java/telraam/station/Fetcher.java @@ -7,7 +7,7 @@ import telraam.database.models.Baton; import telraam.database.models.Detection; import telraam.database.models.Station; -import telraam.logic.Lapper; +import telraam.logic.lapper.Lapper; import telraam.station.models.RonnyDetection; import telraam.station.models.RonnyResponse; diff --git a/src/test/java/telraam/logic/simple/SimpleLapperTest.java b/src/test/java/telraam/logic/simple/SimpleLapperTest.java index 838397f..c50e810 100644 --- a/src/test/java/telraam/logic/simple/SimpleLapperTest.java +++ b/src/test/java/telraam/logic/simple/SimpleLapperTest.java @@ -8,8 +8,8 @@ import telraam.database.models.Detection; import telraam.database.models.Lap; import telraam.database.models.LapSource; -import telraam.logic.Lapper; -import telraam.logic.simple.SimpleLapper; +import telraam.logic.lapper.Lapper; +import telraam.logic.lapper.simple.SimpleLapper; import java.sql.Timestamp; import java.util.Optional; From 2262cbb09e7016158a6b9534b033dca6fa25e5be Mon Sep 17 00:00:00 2001 From: Topvennie Date: Fri, 29 Mar 2024 13:46:19 +0100 Subject: [PATCH 4/7] implementation of positioner --- src/main/java/telraam/App.java | 9 +- .../telraam/logic/positioner/Position.java | 18 +-- .../logic/positioner/PositionSender.java | 31 ++++++ .../telraam/logic/positioner/Positioner.java | 9 ++ .../logic/positioner/SimplePositioner.java | 66 ----------- .../positioner/simple/SimplePositioner.java | 104 ++++++++++++++++++ src/main/java/telraam/station/Fetcher.java | 10 +- .../telraam/websocket/WebSocketMessage.java | 10 ++ .../websocket/WebSocketMessageSingleton.java | 19 +++- 9 files changed, 190 insertions(+), 86 deletions(-) create mode 100644 src/main/java/telraam/logic/positioner/PositionSender.java create mode 100644 src/main/java/telraam/logic/positioner/Positioner.java delete mode 100644 src/main/java/telraam/logic/positioner/SimplePositioner.java create mode 100644 src/main/java/telraam/logic/positioner/simple/SimplePositioner.java create mode 100644 src/main/java/telraam/websocket/WebSocketMessage.java diff --git a/src/main/java/telraam/App.java b/src/main/java/telraam/App.java index 5c93fe8..4e6eb03 100644 --- a/src/main/java/telraam/App.java +++ b/src/main/java/telraam/App.java @@ -20,6 +20,8 @@ import telraam.logic.lapper.Lapper; import telraam.logic.lapper.external.ExternalLapper; import telraam.logic.lapper.robust.RobustLapper; +import telraam.logic.positioner.Positioner; +import telraam.logic.positioner.simple.SimplePositioner; import telraam.station.Fetcher; import telraam.util.AcceptedLapsUtil; import telraam.websocket.WebSocketConnection; @@ -131,10 +133,15 @@ public void run(AppConfiguration configuration, Environment environment) throws lapper.registerAPI(jersey); } + // Set up positioners + Set positioners = new HashSet<>(); + + positioners.add(new SimplePositioner(this.database)); + // Start fetch thread for each station StationDAO stationDAO = this.database.onDemand(StationDAO.class); for (Station station : stationDAO.getAll()) { - new Thread(() -> new Fetcher(this.database, station, lappers).fetch()).start(); + new Thread(() -> new Fetcher(this.database, station, lappers, positioners).fetch()).start(); } } diff --git a/src/main/java/telraam/logic/positioner/Position.java b/src/main/java/telraam/logic/positioner/Position.java index 23bcf00..3a4218e 100644 --- a/src/main/java/telraam/logic/positioner/Position.java +++ b/src/main/java/telraam/logic/positioner/Position.java @@ -1,4 +1,4 @@ -package telraam.logic.positioners; +package telraam.logic.positioner; import lombok.Getter; import lombok.Setter; @@ -7,23 +7,13 @@ @Getter @Setter public class Position { - private Team team; + private int teamId; private float progress; // Progress of the lap. Between 0-1 private float speed; // Current speed. Progress / second - public Position(Team team) { - this.team = team; + public Position(int teamId) { + this.teamId = teamId; this.progress = 0; this.speed = 0; } - - private String toWebsocketMessage() { - return String.format("{\"topic\": \"position\", \"data\": {\"team\": %d, \"progress\": %.4f, \"speed\": %.5f}}", team.getId(), this.progress, this.speed); - } - - public void send() { - WebSocketMessageSingleton.getInstance().sendToAll( - this.toWebsocketMessage() - ); - } } diff --git a/src/main/java/telraam/logic/positioner/PositionSender.java b/src/main/java/telraam/logic/positioner/PositionSender.java new file mode 100644 index 0000000..e6fe68d --- /dev/null +++ b/src/main/java/telraam/logic/positioner/PositionSender.java @@ -0,0 +1,31 @@ +package telraam.logic.positioner; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.NoArgsConstructor; +import telraam.websocket.WebSocketMessage; +import telraam.websocket.WebSocketMessageSingleton; + +import java.util.List; +import java.util.logging.Logger; + +public class PositionSender { + private static final Logger logger = Logger.getLogger(PositionSender.class.getName()); + private final ObjectMapper mapper = new ObjectMapper(); + private final WebSocketMessage message = new WebSocketMessage(); + + public PositionSender() { + this.message.setTopic("position"); + } + + public void send(List position) { + try { + String json = mapper.writeValueAsString(position); + this.message.setData(json); + WebSocketMessageSingleton.getInstance().sendToAll(this.message); + } catch (JsonProcessingException e) { + logger.severe("Json conversion error for \"%s\"".formatted(position.toString())); + } + } + +} diff --git a/src/main/java/telraam/logic/positioner/Positioner.java b/src/main/java/telraam/logic/positioner/Positioner.java new file mode 100644 index 0000000..b61cdbf --- /dev/null +++ b/src/main/java/telraam/logic/positioner/Positioner.java @@ -0,0 +1,9 @@ +package telraam.logic.positioner; + +import telraam.database.models.Detection; + +public interface Positioner { + void handle(Detection detection); + + void calculatePositions(); +} diff --git a/src/main/java/telraam/logic/positioner/SimplePositioner.java b/src/main/java/telraam/logic/positioner/SimplePositioner.java deleted file mode 100644 index 794fa35..0000000 --- a/src/main/java/telraam/logic/positioner/SimplePositioner.java +++ /dev/null @@ -1,66 +0,0 @@ -package telraam.logic.positioner; - -import org.jdbi.v3.core.Jdbi; -import telraam.database.daos.BatonSwitchoverDAO; -import telraam.database.daos.StationDAO; -import telraam.database.daos.TeamDAO; -import telraam.database.models.BatonSwitchover; -import telraam.database.models.Detection; -import telraam.database.models.Station; -import telraam.database.models.Team; - -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class SimplePositioner { - private final int QUEUE_SIZE = 50; - private final int MIN_RSSI = -85; - private Map teamIdToTeam = new HashMap<>(); - private Map> teamDetections = new HashMap<>(); - private List stations; - - public SimplePositioner(Jdbi jdbi) { - TeamDAO teamDAO = jdbi.onDemand(TeamDAO.class); - List teams = teamDAO.getAll(); - for (Team team: teams) { - this.teamDetections.put(team, new CircularQueue<>(QUEUE_SIZE)); - } - List switchovers = jdbi.onDemand(BatonSwitchoverDAO.class).getAll(); - switchovers.sort(Comparator.comparing(BatonSwitchover::getTimestamp)); - - for (BatonSwitchover switchover: switchovers) { - this.teamIdToTeam.put(switchover.getNewBatonId(), teamDAO.getById(switchover.getTeamId()).get()); - } - - List stationList = jdbi.onDemand(StationDAO.class).getAll(); - stationList.sort(Comparator.comparing(Station::getDistanceFromStart)); - this.stations = stationList.stream().map(Station::getId).toList(); - } - - private void calculatePosition(Team team) { - List detections = this.teamDetections.get(team); - detections.sort(Comparator.comparing(Detection::getTimestamp)); - - int currentStationRssi = MIN_RSSI; - int currentStationPosition = 0; - for (Detection detection: detections) { - if (detection.getRssi() > currentStationRssi) { - currentStationRssi = detection.getRssi(); - currentStationPosition = detection.getStationId(); - } - } - - float progress = ((float) 100 / this.stations.size()) * this.stations.indexOf(currentStationPosition); - - System.out.printf("Team: %s | Progress: %f | Acceleration: %f%n", team.getName(), progress, 1.0); - } - - public void handle(Detection detection) { - Team team = this.teamIdToTeam.get(detection.getBatonId()); - this.teamDetections.get(team).add(detection); - this.calculatePosition(team); - } - -} diff --git a/src/main/java/telraam/logic/positioner/simple/SimplePositioner.java b/src/main/java/telraam/logic/positioner/simple/SimplePositioner.java new file mode 100644 index 0000000..f8a9022 --- /dev/null +++ b/src/main/java/telraam/logic/positioner/simple/SimplePositioner.java @@ -0,0 +1,104 @@ +package telraam.logic.positioner.simple; + +import org.jdbi.v3.core.Jdbi; +import telraam.database.daos.BatonSwitchoverDAO; +import telraam.database.daos.StationDAO; +import telraam.database.daos.TeamDAO; +import telraam.database.models.BatonSwitchover; +import telraam.database.models.Detection; +import telraam.database.models.Station; +import telraam.database.models.Team; +import telraam.logic.positioner.CircularQueue; +import telraam.logic.positioner.Position; +import telraam.logic.positioner.PositionSender; +import telraam.logic.positioner.Positioner; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + +public class SimplePositioner implements Positioner { + private final int QUEUE_SIZE = 50; + private final int MIN_RSSI = -85; + private final int DEBOUNCE_TIMEOUT = 1; + private boolean debounceScheduled; + private final ScheduledExecutorService scheduler; + private static final Logger logger = Logger.getLogger(SimplePositioner.class.getName()); + private final PositionSender positionSender; + private final Map batonIdToTeam; + private final Map> teamDetections; + private final List stations; + private final Map teamPositions; + + public SimplePositioner(Jdbi jdbi) { + this.debounceScheduled = false; + this.scheduler = Executors.newScheduledThreadPool(1); + this.positionSender = new PositionSender(); + this.batonIdToTeam = new HashMap<>(); + this.teamDetections = new HashMap<>(); + this.teamPositions = new HashMap<>(); + + TeamDAO teamDAO = jdbi.onDemand(TeamDAO.class); + List teams = teamDAO.getAll(); + for (Team team: teams) { + teamDetections.put(team, new CircularQueue<>(QUEUE_SIZE)); + teamPositions.put(team, new Position(team.getId())); + } + List switchovers = jdbi.onDemand(BatonSwitchoverDAO.class).getAll(); + switchovers.sort(Comparator.comparing(BatonSwitchover::getTimestamp)); + + for (BatonSwitchover switchover: switchovers) { + batonIdToTeam.put(switchover.getNewBatonId(), teamDAO.getById(switchover.getTeamId()).get()); + } + + List stationList = jdbi.onDemand(StationDAO.class).getAll(); + stationList.sort(Comparator.comparing(Station::getDistanceFromStart)); + stations = stationList.stream().map(Station::getId).toList(); + } + + public void calculatePositions() { + logger.info("SimplePositioner: Calculating positions..."); + for (Map.Entry> entry: teamDetections.entrySet()) { + List detections = teamDetections.get(entry.getKey()); + detections.sort(Comparator.comparing(Detection::getTimestamp)); + + int currentStationRssi = MIN_RSSI; + int currentStationPosition = 0; + for (Detection detection: detections) { + if (detection.getRssi() > currentStationRssi) { + currentStationRssi = detection.getRssi(); + currentStationPosition = detection.getStationId(); + } + } + + float progress = ((float) 100 / stations.size()) * currentStationPosition; + teamPositions.get(entry.getKey()).setProgress(progress); + } + + positionSender.send(teamPositions.values().stream().toList()); + logger.info("SimplePositioner: Done calculating positions"); + } + + public void handle(Detection detection) { + Team team = batonIdToTeam.get(detection.getBatonId()); + teamDetections.get(team).add(detection); + + if (! debounceScheduled) { + debounceScheduled = true; + scheduler.schedule(() -> { + try { + calculatePositions(); + } catch (Exception e) { + logger.severe(e.getMessage()); + } + debounceScheduled = false; + }, DEBOUNCE_TIMEOUT, TimeUnit.SECONDS); + } + } + +} diff --git a/src/main/java/telraam/station/Fetcher.java b/src/main/java/telraam/station/Fetcher.java index d2cdce0..bb0ed5e 100644 --- a/src/main/java/telraam/station/Fetcher.java +++ b/src/main/java/telraam/station/Fetcher.java @@ -8,6 +8,7 @@ import telraam.database.models.Detection; import telraam.database.models.Station; import telraam.logic.lapper.Lapper; +import telraam.logic.positioner.Positioner; import telraam.station.models.RonnyDetection; import telraam.station.models.RonnyResponse; @@ -29,6 +30,7 @@ public class Fetcher { private final Set lappers; + private final Set positioners; private Station station; private final BatonDAO batonDAO; @@ -48,11 +50,12 @@ public class Fetcher { private final static int IDLE_TIMEOUT_MS = 4000; // Wait 4 seconds - public Fetcher(Jdbi database, Station station, Set lappers) { + public Fetcher(Jdbi database, Station station, Set lappers, Set positioners) { this.batonDAO = database.onDemand(BatonDAO.class); this.detectionDAO = database.onDemand(DetectionDAO.class); this.stationDAO = database.onDemand(StationDAO.class); this.lappers = lappers; + this.positioners = positioners; this.station = station; } @@ -158,7 +161,10 @@ public void fetch() { } if (!new_detections.isEmpty()) { detectionDAO.insertAll(new_detections); - new_detections.forEach((detection) -> lappers.forEach((lapper) -> lapper.handle(detection))); + new_detections.forEach((detection) -> { + lappers.forEach((lapper) -> lapper.handle(detection)); + positioners.forEach((positioner) -> positioner.handle(detection)); + }); } this.logger.finer("Fetched " + detections.size() + " detections from " + station.getName() + ", Saved " + new_detections.size()); diff --git a/src/main/java/telraam/websocket/WebSocketMessage.java b/src/main/java/telraam/websocket/WebSocketMessage.java new file mode 100644 index 0000000..67cf878 --- /dev/null +++ b/src/main/java/telraam/websocket/WebSocketMessage.java @@ -0,0 +1,10 @@ +package telraam.websocket; + +import lombok.Getter; +import lombok.Setter; + +@Getter @Setter +public class WebSocketMessage { + private String topic; + private String data; +} diff --git a/src/main/java/telraam/websocket/WebSocketMessageSingleton.java b/src/main/java/telraam/websocket/WebSocketMessageSingleton.java index de12115..598a901 100644 --- a/src/main/java/telraam/websocket/WebSocketMessageSingleton.java +++ b/src/main/java/telraam/websocket/WebSocketMessageSingleton.java @@ -1,20 +1,24 @@ package telraam.websocket; +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Getter; +import lombok.NoArgsConstructor; import java.util.HashSet; import java.util.Set; import java.util.logging.Logger; +@NoArgsConstructor public class WebSocketMessageSingleton { private static final Logger logger = Logger.getLogger(WebSocketMessageSingleton.class.getName()); @Getter private static final WebSocketMessageSingleton instance = new WebSocketMessageSingleton(); private static final Set registeredConnections = new HashSet<>(); - - private WebSocketMessageSingleton() { - } + private ObjectMapper mapper = new ObjectMapper(); public void registerConnection(WebSocketConnection conn) { boolean modified = registeredConnections.add(conn); @@ -34,4 +38,13 @@ public void sendToAll(String s) { logger.finest("Sending \"%s\" to all registered WebSocketConnection instances".formatted(s)); registeredConnections.forEach(conn -> conn.send(s)); } + + public void sendToAll(WebSocketMessage message) { + try { + String json = mapper.writeValueAsString(message); + this.sendToAll(json); + } catch (JsonProcessingException e) { + logger.severe("Json conversion error for \"%s\"".formatted(message.toString())); + } + } } From c173bebf295ac8f7e6eaf667142adb13046a3b15 Mon Sep 17 00:00:00 2001 From: Topvennie Date: Fri, 29 Mar 2024 14:01:57 +0100 Subject: [PATCH 5/7] cleanup --- src/main/java/telraam/logic/positioner/CircularQueue.java | 2 +- src/main/java/telraam/logic/positioner/Positioner.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/telraam/logic/positioner/CircularQueue.java b/src/main/java/telraam/logic/positioner/CircularQueue.java index 042ba79..94cadec 100644 --- a/src/main/java/telraam/logic/positioner/CircularQueue.java +++ b/src/main/java/telraam/logic/positioner/CircularQueue.java @@ -14,7 +14,7 @@ public CircularQueue(int maxSize) { @Override public boolean add(T e) { if (this.size >= this.maxSize) { - super.removeFirst(); + removeFirst(); this.size--; } diff --git a/src/main/java/telraam/logic/positioner/Positioner.java b/src/main/java/telraam/logic/positioner/Positioner.java index b61cdbf..4128b36 100644 --- a/src/main/java/telraam/logic/positioner/Positioner.java +++ b/src/main/java/telraam/logic/positioner/Positioner.java @@ -5,5 +5,4 @@ public interface Positioner { void handle(Detection detection); - void calculatePositions(); } From f6aab9f53f5badcdb9393865c2c47becad53cafa Mon Sep 17 00:00:00 2001 From: Topvennie Date: Fri, 29 Mar 2024 14:18:09 +0100 Subject: [PATCH 6/7] change WebSocketMessage data type --- .../logic/positioner/PositionSender.java | 19 ++++--------------- .../telraam/websocket/WebSocketMessage.java | 4 ++-- .../websocket/WebSocketMessageSingleton.java | 4 ++-- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/src/main/java/telraam/logic/positioner/PositionSender.java b/src/main/java/telraam/logic/positioner/PositionSender.java index e6fe68d..5e779dc 100644 --- a/src/main/java/telraam/logic/positioner/PositionSender.java +++ b/src/main/java/telraam/logic/positioner/PositionSender.java @@ -1,31 +1,20 @@ package telraam.logic.positioner; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.NoArgsConstructor; import telraam.websocket.WebSocketMessage; import telraam.websocket.WebSocketMessageSingleton; import java.util.List; -import java.util.logging.Logger; public class PositionSender { - private static final Logger logger = Logger.getLogger(PositionSender.class.getName()); - private final ObjectMapper mapper = new ObjectMapper(); - private final WebSocketMessage message = new WebSocketMessage(); + private final WebSocketMessage> message = new WebSocketMessage<>(); public PositionSender() { this.message.setTopic("position"); } - public void send(List position) { - try { - String json = mapper.writeValueAsString(position); - this.message.setData(json); - WebSocketMessageSingleton.getInstance().sendToAll(this.message); - } catch (JsonProcessingException e) { - logger.severe("Json conversion error for \"%s\"".formatted(position.toString())); - } + public void send(List positions) { + this.message.setData(positions); + WebSocketMessageSingleton.getInstance().sendToAll(this.message); } } diff --git a/src/main/java/telraam/websocket/WebSocketMessage.java b/src/main/java/telraam/websocket/WebSocketMessage.java index 67cf878..0b4200f 100644 --- a/src/main/java/telraam/websocket/WebSocketMessage.java +++ b/src/main/java/telraam/websocket/WebSocketMessage.java @@ -4,7 +4,7 @@ import lombok.Setter; @Getter @Setter -public class WebSocketMessage { +public class WebSocketMessage { private String topic; - private String data; + private T data; } diff --git a/src/main/java/telraam/websocket/WebSocketMessageSingleton.java b/src/main/java/telraam/websocket/WebSocketMessageSingleton.java index 598a901..d073217 100644 --- a/src/main/java/telraam/websocket/WebSocketMessageSingleton.java +++ b/src/main/java/telraam/websocket/WebSocketMessageSingleton.java @@ -18,7 +18,7 @@ public class WebSocketMessageSingleton { @Getter private static final WebSocketMessageSingleton instance = new WebSocketMessageSingleton(); private static final Set registeredConnections = new HashSet<>(); - private ObjectMapper mapper = new ObjectMapper(); + private final ObjectMapper mapper = new ObjectMapper(); public void registerConnection(WebSocketConnection conn) { boolean modified = registeredConnections.add(conn); @@ -39,7 +39,7 @@ public void sendToAll(String s) { registeredConnections.forEach(conn -> conn.send(s)); } - public void sendToAll(WebSocketMessage message) { + public void sendToAll(WebSocketMessage message) { try { String json = mapper.writeValueAsString(message); this.sendToAll(json); From f71ad1ba1f9e0c4791352ffbe09553693d8fcede Mon Sep 17 00:00:00 2001 From: Topvennie Date: Fri, 29 Mar 2024 14:21:09 +0100 Subject: [PATCH 7/7] use built in function --- .../telraam/logic/positioner/CircularQueue.java | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/main/java/telraam/logic/positioner/CircularQueue.java b/src/main/java/telraam/logic/positioner/CircularQueue.java index 94cadec..773c633 100644 --- a/src/main/java/telraam/logic/positioner/CircularQueue.java +++ b/src/main/java/telraam/logic/positioner/CircularQueue.java @@ -5,26 +5,17 @@ public class CircularQueue extends LinkedList { private final int maxSize; - private int size = 0; - public CircularQueue(int maxSize) { this.maxSize = maxSize; } @Override public boolean add(T e) { - if (this.size >= this.maxSize) { + if (size() >= this.maxSize) { removeFirst(); - this.size--; - } - - boolean result = super.add(e); - - if (result) { - this.size++; } - return result; + return super.add(e); } }