From c1d8482760895e85aa9e462038fb50ea87478980 Mon Sep 17 00:00:00 2001 From: FKD13 <44001949+FKD13@users.noreply.github.com> Date: Mon, 25 Mar 2024 20:27:51 +0100 Subject: [PATCH] quick cleanup --- .gitignore | 4 +- .idea/$PRODUCT_WORKSPACE_FILE$ | 18 -- .idea/.gitignore | 2 - .idea/.name | 1 - .idea/compiler.xml | 6 - .idea/dataSources.xml | 23 -- .idea/jarRepositories.xml | 25 -- .idea/jpa-buddy.xml | 6 - .idea/misc.xml | 8 - .idea/runConfigurations/Telraam__build_.xml | 23 -- .../Telraam__migrateDevelopmentDatabase_.xml | 21 -- .../Telraam__migrateProductionDatabase_.xml | 21 -- .../Telraam__migrateTestingDatabase_.xml | 21 -- .idea/runConfigurations/Telraam__runDev_.xml | 21 -- .idea/runConfigurations/Telraam__runProd_.xml | 21 -- .idea/runConfigurations/Telraam__test_.xml | 26 -- .../Telraam__test_force_.xml | 26 -- .idea/sonarlint-state.xml | 6 - .idea/sonarlint.xml | 8 - .idea/sqldialects.xml | 7 - .idea/vcs.xml | 6 - src/main/java/telraam/App.java | 2 +- src/main/java/telraam/database/models/Id.java | 19 -- .../RobustLapper.java | 2 +- .../logic/{ => simple}/SimpleLapper.java | 3 +- .../telraam/logic/viterbi/ViterbiLapper.java | 292 ------------------ .../viterbi/ViterbiLapperConfiguration.java | 42 --- .../logic/viterbi/ViterbiLapperResource.java | 61 ---- .../algorithm/InvalidParameterException.java | 7 - .../viterbi/algorithm/ViterbiAlgorithm.java | 127 -------- .../logic/viterbi/algorithm/ViterbiModel.java | 30 -- .../logic/viterbi/algorithm/ViterbiState.java | 25 -- src/main/java/telraam/station/Fetcher.java | 2 + .../station/{ => models}/RonnyDetection.java | 2 +- .../station/{ => models}/RonnyResponse.java | 2 +- src/main/resources/banner.txt | 9 +- .../java/telraam/logic/SimpleLapperTest.java | 1 + 37 files changed, 20 insertions(+), 906 deletions(-) delete mode 100644 .idea/$PRODUCT_WORKSPACE_FILE$ delete mode 100644 .idea/.gitignore delete mode 100644 .idea/.name delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/dataSources.xml delete mode 100644 .idea/jarRepositories.xml delete mode 100644 .idea/jpa-buddy.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/runConfigurations/Telraam__build_.xml delete mode 100644 .idea/runConfigurations/Telraam__migrateDevelopmentDatabase_.xml delete mode 100644 .idea/runConfigurations/Telraam__migrateProductionDatabase_.xml delete mode 100644 .idea/runConfigurations/Telraam__migrateTestingDatabase_.xml delete mode 100644 .idea/runConfigurations/Telraam__runDev_.xml delete mode 100644 .idea/runConfigurations/Telraam__runProd_.xml delete mode 100644 .idea/runConfigurations/Telraam__test_.xml delete mode 100644 .idea/runConfigurations/Telraam__test_force_.xml delete mode 100644 .idea/sonarlint-state.xml delete mode 100644 .idea/sonarlint.xml delete mode 100644 .idea/sqldialects.xml delete mode 100644 .idea/vcs.xml delete mode 100644 src/main/java/telraam/database/models/Id.java rename src/main/java/telraam/logic/{robustLapper => robust}/RobustLapper.java (99%) rename src/main/java/telraam/logic/{ => simple}/SimpleLapper.java (97%) delete mode 100644 src/main/java/telraam/logic/viterbi/ViterbiLapper.java delete mode 100644 src/main/java/telraam/logic/viterbi/ViterbiLapperConfiguration.java delete mode 100644 src/main/java/telraam/logic/viterbi/ViterbiLapperResource.java delete mode 100644 src/main/java/telraam/logic/viterbi/algorithm/InvalidParameterException.java delete mode 100644 src/main/java/telraam/logic/viterbi/algorithm/ViterbiAlgorithm.java delete mode 100644 src/main/java/telraam/logic/viterbi/algorithm/ViterbiModel.java delete mode 100644 src/main/java/telraam/logic/viterbi/algorithm/ViterbiState.java rename src/main/java/telraam/station/{ => models}/RonnyDetection.java (90%) rename src/main/java/telraam/station/{ => models}/RonnyResponse.java (87%) diff --git a/.gitignore b/.gitignore index b55c818..95ddd25 100644 --- a/.gitignore +++ b/.gitignore @@ -192,4 +192,6 @@ flycheck_*.el !gradle-wrapper.jar -node_modules/ \ No newline at end of file +node_modules/ + +.idea \ No newline at end of file diff --git a/.idea/$PRODUCT_WORKSPACE_FILE$ b/.idea/$PRODUCT_WORKSPACE_FILE$ deleted file mode 100644 index 96ce66b..0000000 --- a/.idea/$PRODUCT_WORKSPACE_FILE$ +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 5c98b42..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# Default ignored files -/workspace.xml \ No newline at end of file diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 780c8da..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -telraam \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 659bf43..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml deleted file mode 100644 index f37c315..0000000 --- a/.idea/dataSources.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - postgresql - true - org.postgresql.Driver - jdbc:postgresql://localhost:5432/telraam_dev - - - sqlite.xerial - true - org.sqlite.JDBC - jdbc:sqlite::memory: - - - postgresql - true - org.postgresql.Driver - jdbc:postgresql://localhost:5432/telraam_dev - - - \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml deleted file mode 100644 index b3e9cbd..0000000 --- a/.idea/jarRepositories.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/jpa-buddy.xml b/.idea/jpa-buddy.xml deleted file mode 100644 index d08f400..0000000 --- a/.idea/jpa-buddy.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 240ddf3..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations/Telraam__build_.xml b/.idea/runConfigurations/Telraam__build_.xml deleted file mode 100644 index 0d73339..0000000 --- a/.idea/runConfigurations/Telraam__build_.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - true - true - false - - - \ No newline at end of file diff --git a/.idea/runConfigurations/Telraam__migrateDevelopmentDatabase_.xml b/.idea/runConfigurations/Telraam__migrateDevelopmentDatabase_.xml deleted file mode 100644 index 202127f..0000000 --- a/.idea/runConfigurations/Telraam__migrateDevelopmentDatabase_.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - true - - - \ No newline at end of file diff --git a/.idea/runConfigurations/Telraam__migrateProductionDatabase_.xml b/.idea/runConfigurations/Telraam__migrateProductionDatabase_.xml deleted file mode 100644 index ffc82b4..0000000 --- a/.idea/runConfigurations/Telraam__migrateProductionDatabase_.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - true - - - \ No newline at end of file diff --git a/.idea/runConfigurations/Telraam__migrateTestingDatabase_.xml b/.idea/runConfigurations/Telraam__migrateTestingDatabase_.xml deleted file mode 100644 index b2859c2..0000000 --- a/.idea/runConfigurations/Telraam__migrateTestingDatabase_.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - true - - - \ No newline at end of file diff --git a/.idea/runConfigurations/Telraam__runDev_.xml b/.idea/runConfigurations/Telraam__runDev_.xml deleted file mode 100644 index c3766a2..0000000 --- a/.idea/runConfigurations/Telraam__runDev_.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - true - - - \ No newline at end of file diff --git a/.idea/runConfigurations/Telraam__runProd_.xml b/.idea/runConfigurations/Telraam__runProd_.xml deleted file mode 100644 index 0f6b693..0000000 --- a/.idea/runConfigurations/Telraam__runProd_.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - true - - - \ No newline at end of file diff --git a/.idea/runConfigurations/Telraam__test_.xml b/.idea/runConfigurations/Telraam__test_.xml deleted file mode 100644 index fdffce2..0000000 --- a/.idea/runConfigurations/Telraam__test_.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - true - - - \ No newline at end of file diff --git a/.idea/runConfigurations/Telraam__test_force_.xml b/.idea/runConfigurations/Telraam__test_force_.xml deleted file mode 100644 index f18cffe..0000000 --- a/.idea/runConfigurations/Telraam__test_force_.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - true - - - \ No newline at end of file diff --git a/.idea/sonarlint-state.xml b/.idea/sonarlint-state.xml deleted file mode 100644 index 0b9835d..0000000 --- a/.idea/sonarlint-state.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 1634050067000 - - \ No newline at end of file diff --git a/.idea/sonarlint.xml b/.idea/sonarlint.xml deleted file mode 100644 index 4b4f6a7..0000000 --- a/.idea/sonarlint.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml deleted file mode 100644 index 0840fc3..0000000 --- a/.idea/sqldialects.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/main/java/telraam/App.java b/src/main/java/telraam/App.java index a4ba783..243edc8 100644 --- a/src/main/java/telraam/App.java +++ b/src/main/java/telraam/App.java @@ -16,7 +16,7 @@ import telraam.healthchecks.TemplateHealthCheck; import telraam.logic.Lapper; import telraam.logic.external.ExternalLapper; -import telraam.logic.robustLapper.RobustLapper; +import telraam.logic.robust.RobustLapper; import telraam.station.Fetcher; import telraam.util.AcceptedLapsUtil; diff --git a/src/main/java/telraam/database/models/Id.java b/src/main/java/telraam/database/models/Id.java deleted file mode 100644 index 97132af..0000000 --- a/src/main/java/telraam/database/models/Id.java +++ /dev/null @@ -1,19 +0,0 @@ -package telraam.database.models; - -public class Id { - - private int id; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - @Override - public String toString() { - return String.format("Id: %d", id); - } -} \ No newline at end of file diff --git a/src/main/java/telraam/logic/robustLapper/RobustLapper.java b/src/main/java/telraam/logic/robust/RobustLapper.java similarity index 99% rename from src/main/java/telraam/logic/robustLapper/RobustLapper.java rename to src/main/java/telraam/logic/robust/RobustLapper.java index 0477875..07335c4 100644 --- a/src/main/java/telraam/logic/robustLapper/RobustLapper.java +++ b/src/main/java/telraam/logic/robust/RobustLapper.java @@ -1,4 +1,4 @@ -package telraam.logic.robustLapper; +package telraam.logic.robust; import io.dropwizard.jersey.setup.JerseyEnvironment; import org.jdbi.v3.core.Jdbi; diff --git a/src/main/java/telraam/logic/SimpleLapper.java b/src/main/java/telraam/logic/simple/SimpleLapper.java similarity index 97% rename from src/main/java/telraam/logic/SimpleLapper.java rename to src/main/java/telraam/logic/simple/SimpleLapper.java index 5ed367e..6acc326 100644 --- a/src/main/java/telraam/logic/SimpleLapper.java +++ b/src/main/java/telraam/logic/simple/SimpleLapper.java @@ -1,10 +1,11 @@ -package telraam.logic; +package telraam.logic.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 java.util.ArrayList; import java.util.HashMap; diff --git a/src/main/java/telraam/logic/viterbi/ViterbiLapper.java b/src/main/java/telraam/logic/viterbi/ViterbiLapper.java deleted file mode 100644 index 980d891..0000000 --- a/src/main/java/telraam/logic/viterbi/ViterbiLapper.java +++ /dev/null @@ -1,292 +0,0 @@ -package telraam.logic.viterbi; - -import io.dropwizard.jersey.setup.JerseyEnvironment; -import org.jdbi.v3.core.Jdbi; -import telraam.database.daos.*; -import telraam.database.models.*; -import telraam.logic.Lapper; -import telraam.logic.viterbi.algorithm.ViterbiAlgorithm; -import telraam.logic.viterbi.algorithm.ViterbiModel; -import telraam.logic.viterbi.algorithm.ViterbiState; - -import java.sql.Time; -import java.sql.Timestamp; -import java.time.Instant; -import java.util.*; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -public class ViterbiLapper implements Lapper { - static final String SOURCE_NAME = "viterbi-lapper"; - - private final ViterbiLapperConfiguration config; - private Map currentStates; - private final Jdbi jdbi; - private final int lapSourceId; - private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); - private boolean debounceScheduled; - private final Logger logger = Logger.getLogger(ViterbiLapper.class.getName()); - - public ViterbiLapper(Jdbi jdbi) { - this(jdbi, new ViterbiLapperConfiguration()); - } - - public ViterbiLapper(Jdbi jdbi, ViterbiLapperConfiguration configuration) { - this.jdbi = jdbi; - this.config = configuration; - this.currentStates = new HashMap<>(); - this.debounceScheduled = false; - - LapSourceDAO lapSourceDAO = jdbi.onDemand(LapSourceDAO.class); - - lapSourceDAO.getByName(ViterbiLapper.SOURCE_NAME).orElseThrow(); - - this.lapSourceId = lapSourceDAO.getByName(ViterbiLapper.SOURCE_NAME).get().getId(); - } - - - private ViterbiModel createViterbiModel() { - StationDAO stationDAO = jdbi.onDemand(StationDAO.class); - - // We will construct one segment for each station, which will represent its - // neighbourhood. - List stations = stationDAO.getAll(); - stations.sort(Comparator.comparing(Station::getDistanceFromStart)); - - - // *********************************** - // Build detection probability mapping - // *********************************** - Map> emissionProbabilities = new HashMap<>(); - for (int segmentNum = 0; segmentNum < stations.size(); segmentNum++) { - Map probas = new HashMap<>(); - for (int stationNum = 0; stationNum < stations.size(); stationNum++) { - int stationId = stations.get(stationNum).getId(); - if (segmentNum == stationNum) { - probas.put(stationId, this.config.SAME_STATION_DETECTION_CHANCE); - } else { - probas.put(stationId, this.config.BASE_DETECTION_CHANCE); - } - } - emissionProbabilities.put(segmentNum, probas); - } - - // ************************************ - // Build transition probability mapping - // ************************************ - Map> transitionProbabilities = new HashMap<>(); - for (int prevSegment = 0; prevSegment < stations.size(); prevSegment++) { - Map probas = new HashMap<>(); - - // a station is skipped when it is broken, or when all detections are missed - // TODO: this currently does not take into account detections by other stations - double skipStationProbability = this.config.BROKEN_STATION_PROBABILITY + Math.pow( - 1 - this.config.SAME_STATION_DETECTION_CHANCE, - this.config.EXPECTED_NUM_DETECTIONS - ); - - // calculate amount of steps this way so that backwards steps are rounded down - // and forward steps is rounded up (because we'd like to assume people run in the right direction) - int numStepsBackwards = (stations.size() - 1) / 2; - int numStepsForwards = stations.size() - 1 - numStepsBackwards; - - // This represents the odds (sameStationWeight against one) of staying on the same station - // "how much more likely is it to stay, compared to moving" - double sameStationWeight = (1 - this.config.BROKEN_STATION_PROBABILITY) * this.config.EXPECTED_NUM_DETECTIONS; - // add 2: one unit of weight for running forwards, one for running backwards - probas.put(prevSegment, sameStationWeight / (sameStationWeight + 2)); - - // transition probabilities for running forwards. - // To be precise: these probabilities should represent the probability that you will be at nextSegment - // when the next detection happens. So assuming that you cannot be detected when you are in segment 2, - // the transition probabilities towards segment 2 should always be 0. - // This is because the viterbi algorithm runs in discrete time-steps, where each step corresponds - // to a single detection (and is only vaguely related to the passage of time or distance). - double remainingProbabilityMass = 1 / (sameStationWeight + 2); - for (int i = 1; i <= numStepsForwards; i++) { - // compute next segment index - int nextSegment = Math.floorMod(prevSegment + i, stations.size()); - double proba = remainingProbabilityMass; - if (i < numStepsForwards) { - // multiply by the probability that this station was not skipped. - // When this is the final step, we do not consider the possibility of skipping anymore - // (so that probabilities add up to 1) - proba *= (1 - skipStationProbability); - } - probas.put(nextSegment, proba); - - // subtract the used amount of probability mass - remainingProbabilityMass -= proba; - } - - // transition probabilities for running backwards - // refer to above comments - remainingProbabilityMass = 1 / (sameStationWeight + 2); - for (int i = 1; i <= numStepsBackwards; i++) { - int nextSegment = Math.floorMod(prevSegment - i, stations.size()); - double proba = remainingProbabilityMass; - if (i < numStepsBackwards) { - proba *= (1 - skipStationProbability); - } - probas.put(nextSegment, proba); - remainingProbabilityMass -= proba; - } - - transitionProbabilities.put(prevSegment, probas); - } - - return new ViterbiModel<>( - stations.stream().map(Station::getId).collect(Collectors.toSet()), - IntStream.range(0, stations.size()).boxed().collect(Collectors.toSet()), - transitionProbabilities, - emissionProbabilities, - calculateStartProbabilities() - ); - } - - public Map> getProbabilities() { - Map> ret = new HashMap<>(); - for (Map.Entry entry : this.currentStates.entrySet()) { - ret.put(entry.getKey(), entry.getValue().probabilities()); - } - return ret; - } - - public Map>> getLapTimes() { - Map>> ret = new HashMap<>(); - for (Map.Entry entry : this.currentStates.entrySet()) { - ret.put(entry.getKey(), entry.getValue().lapTimestamps()); - } - return ret; - } - - private Map calculateStartProbabilities() { - StationDAO stationDAO = jdbi.onDemand(StationDAO.class); - List stations = stationDAO.getAll(); - int numStations = stations.size(); - - Map ret = new HashMap<>(); - - ret.put(0, 1.0 - (numStations - 1) * this.config.RESTART_PROBABILITY); - for (int i = 1; i < numStations; i++) { - ret.put(i, this.config.RESTART_PROBABILITY); - } - - return ret; - } - - @Override - public synchronized void handle(Detection msg) { - if (msg.getRssi() < -77) { - return; - } - if (!this.debounceScheduled) { - // TODO: this might be better as an atomic - this.debounceScheduled = true; - this.scheduler.schedule(() -> { - try { - this.calculateLaps(); - } catch (Exception e) { - logger.severe(e.getMessage()); - } - this.debounceScheduled = false; - }, this.config.DEBOUNCE_TIMEOUT, TimeUnit.SECONDS); - } - } - - public synchronized void calculateLaps() { - System.out.println("Calculating laps"); - - TeamDAO teamDAO = this.jdbi.onDemand(TeamDAO.class); - DetectionDAO detectionDAO = this.jdbi.onDemand(DetectionDAO.class); - LapDAO lapDAO = this.jdbi.onDemand(LapDAO.class); - BatonSwitchoverDAO batonSwitchoverDAO = this.jdbi.onDemand(BatonSwitchoverDAO.class); - LapSourceSwitchoverDAO lapSourceSwitchoverDAO = this.jdbi.onDemand(LapSourceSwitchoverDAO.class); - List teams = teamDAO.getAll(); - List switchovers = batonSwitchoverDAO.getAll(); - - Optional maybeFirstLapSourceSwitchover = lapSourceSwitchoverDAO.getAll().stream().filter((x) -> x.getNewLapSource() == 3).findFirst(); - Timestamp firstSwitchover = maybeFirstLapSourceSwitchover.map(LapSourceSwitchover::getTimestamp).orElse(new Timestamp(0)); - - // TODO: stream these from the database - List detections = detectionDAO.getAll(); - detections.removeIf((detection) -> detection.getRssi() < -77 || detection.getTimestamp().before(firstSwitchover)); - detections.sort(Comparator.comparing(Detection::getTimestamp)); - - // we create a viterbi model each time because the set of stations is not static - ViterbiModel viterbiModel = createViterbiModel(); - - Map> viterbis = teams.stream() - .collect(Collectors.toMap(Team::getId, _team -> new ViterbiAlgorithm<>(viterbiModel))); - - Map batonIdToTeamId = new HashMap<>(); - - int switchoverIndex = 0; - - for (Detection detection : detections) { - while (switchoverIndex < switchovers.size() && switchovers.get(switchoverIndex).getTimestamp().before(detection.getTimestamp())) { - BatonSwitchover switchover = switchovers.get(switchoverIndex); - batonIdToTeamId.put(switchover.getNewBatonId(), switchover.getTeamId()); - switchoverIndex += 1; - } - - if (batonIdToTeamId.containsKey(detection.getBatonId())) { - int teamId = batonIdToTeamId.get(detection.getBatonId()); - viterbis.get(teamId).observe(detection.getStationId(), detection.getTimestamp()); - } - } - - this.currentStates = viterbis.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getState())); - - // We made a new estimation of the lap count, now we can update the database state to match - - Map> lapsByTeam = teams.stream().collect(Collectors.toMap(Team::getId, x -> new TreeSet<>(Comparator.comparing(Lap::getTimestamp)))); - - for (Lap lap : lapDAO.getAllBySource(this.lapSourceId)) { - lapsByTeam.get(lap.getTeamId()).add(lap); - } - - for (Map.Entry entry : this.currentStates.entrySet()) { - int teamId = entry.getKey(); - TreeSet laps = lapsByTeam.get(teamId); - - ViterbiState state = entry.getValue(); - - Set currentLaps = laps.stream().map(Lap::getTimestamp).collect(Collectors.toSet()); - Set predictedLaps = state.lapTimestamps().get(state.mostLikelySegment()); - - Set toRemove = new TreeSet<>(currentLaps); - toRemove.removeAll(predictedLaps); - - Set toAdd = new TreeSet<>(predictedLaps); - toAdd.removeAll(currentLaps); - - for (Timestamp timestamp : toRemove) { - lapDAO.removeByTeamAndTimestamp(teamId, timestamp); - } - - for (Timestamp timestamp : toAdd) { - lapDAO.insert(new Lap(teamId, this.lapSourceId, timestamp)); - } - } - - System.out.println("Done calculating laps"); - } - - @Override - public void registerAPI(JerseyEnvironment jersey) { - jersey.register(new ViterbiLapperResource(this)); - } - - public ViterbiLapperConfiguration getConfig() { - return this.config; - } - - public ViterbiModel getModel() { - return this.createViterbiModel(); - } -} diff --git a/src/main/java/telraam/logic/viterbi/ViterbiLapperConfiguration.java b/src/main/java/telraam/logic/viterbi/ViterbiLapperConfiguration.java deleted file mode 100644 index 0c1c8ce..0000000 --- a/src/main/java/telraam/logic/viterbi/ViterbiLapperConfiguration.java +++ /dev/null @@ -1,42 +0,0 @@ -package telraam.logic.viterbi; - -public class ViterbiLapperConfiguration { - public double RESTART_PROBABILITY; // The probability that the runners will start the race in a different spot than the start/finish line (should only happen on complete restarts) - public int DEBOUNCE_TIMEOUT; // The amount of time detections are debounced for in seconds - - // probability that you will be for detection in the segment corresponding to a station - public double SAME_STATION_DETECTION_CHANCE; - - // the probability that you will be detected at a random station ("noise" detections) - public double BASE_DETECTION_CHANCE; - - // the probability that an individual station is down at any moment in time - // ~= downtime / total time. - // It is not that important that this parameter is estimated correctly (which would be very hard to do) - // it is better to interpret this as the system's eagerness to assume that a station was not working - // when trying to explain a series of detections. - public double BROKEN_STATION_PROBABILITY; - - // The amount of times we expect a runner to be detected when passing by a station, given that the station is alive. - // - // The higher this parameter, the more 'evidence' (= detections) the system will require - // in order to change the predicted location - so, the predictions will be less sensitive to noise detections - // at different stations. - // Consequently, it is better to under-estimate this parameter than to over-estimate it. - public double EXPECTED_NUM_DETECTIONS; - - public ViterbiLapperConfiguration() { - this.RESTART_PROBABILITY = 0.001; - this.DEBOUNCE_TIMEOUT = 10; - - // ballpark estimates extracted from test event data - // IMPORTANT: these numbers are only valid assuming that detection are filtered for rssi >=-70 - // (ask @iasoon for details) - this.SAME_STATION_DETECTION_CHANCE = 0.90; - this.BASE_DETECTION_CHANCE = 0.10; - this.EXPECTED_NUM_DETECTIONS = 3; - - - this.BROKEN_STATION_PROBABILITY = 0.01; - } -} diff --git a/src/main/java/telraam/logic/viterbi/ViterbiLapperResource.java b/src/main/java/telraam/logic/viterbi/ViterbiLapperResource.java deleted file mode 100644 index 3b1de23..0000000 --- a/src/main/java/telraam/logic/viterbi/ViterbiLapperResource.java +++ /dev/null @@ -1,61 +0,0 @@ -package telraam.logic.viterbi; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import telraam.logic.viterbi.algorithm.ViterbiModel; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import java.sql.Timestamp; -import java.util.List; -import java.util.Map; -import java.util.Set; - -@Path("/lappers/viterbi") -@Api("/lappers/viterbi") -@Produces(MediaType.APPLICATION_JSON) -public class ViterbiLapperResource { - private final ViterbiLapper lapper; - - public ViterbiLapperResource(ViterbiLapper lapper) { - this.lapper = lapper; - } - - @GET - @Path("/probabilities") - @ApiOperation(value = "Get lapper position probabilities") - public Map> getProbabilities() { - return this.lapper.getProbabilities(); - } - - @GET - @Path("/lap-times") - @ApiOperation(value = "Get lapper estimated laps") - public Map>> getLapTimes() { - return this.lapper.getLapTimes(); - } - - @GET - @Path("/configuration") - @ApiOperation(value = "Get lapper configuration") - public ViterbiLapperConfiguration getConfiguration() { - return this.lapper.getConfig(); - } - - @GET - @Path("/model") - @ApiOperation(value = "Get Viterbi model") - public ViterbiModel getModel() { - return this.lapper.getModel(); - } - - @GET - @Path("/recalculate") - @ApiOperation(value = "Recalculate Viterbi rounds") - public String recalculateRounds() { - this.lapper.calculateLaps(); - return "Recalculated rounds"; - } -} diff --git a/src/main/java/telraam/logic/viterbi/algorithm/InvalidParameterException.java b/src/main/java/telraam/logic/viterbi/algorithm/InvalidParameterException.java deleted file mode 100644 index 632bf2d..0000000 --- a/src/main/java/telraam/logic/viterbi/algorithm/InvalidParameterException.java +++ /dev/null @@ -1,7 +0,0 @@ -package telraam.logic.viterbi.algorithm; - -public class InvalidParameterException extends RuntimeException { - public InvalidParameterException(String s) { - super(s); - } -} diff --git a/src/main/java/telraam/logic/viterbi/algorithm/ViterbiAlgorithm.java b/src/main/java/telraam/logic/viterbi/algorithm/ViterbiAlgorithm.java deleted file mode 100644 index 2f4e82f..0000000 --- a/src/main/java/telraam/logic/viterbi/algorithm/ViterbiAlgorithm.java +++ /dev/null @@ -1,127 +0,0 @@ -package telraam.logic.viterbi.algorithm; - -import io.swagger.models.auth.In; - -import java.sql.Time; -import java.sql.Timestamp; -import java.util.*; - -/** - * The class performing the Viterbi algorithm. - * @param The type of the observations. - */ -public class ViterbiAlgorithm { - private final ViterbiModel model; - - private ViterbiState lastState; - - public ViterbiAlgorithm(ViterbiModel viterbiModel) { - this.model = viterbiModel; - - this.verifyProbabilities(); - - // Set up the initial probabilities - int numSegments = this.model.getHiddenStates().size(); - Map probabilities = new HashMap<>(); - Map previousSegments = new HashMap<>(); - Map> lapTimestamps = new HashMap<>(); - - for (Map.Entry entry : viterbiModel.getStartProbabilities().entrySet()) { - probabilities.put(entry.getKey(), entry.getValue()); - previousSegments.put(entry.getKey(), 0); - lapTimestamps.put(entry.getKey(), new TreeSet<>()); - } - - this.lastState = new ViterbiState(probabilities, previousSegments, lapTimestamps); - } - - /** - * Verify that the given probabilities are valid. - * @throws InvalidParameterException If the probabilities were not valid. - */ - private void verifyProbabilities() { - if (!this.model.getTransitionProbabilities().keySet().equals(this.model.getHiddenStates())) { - throw new InvalidParameterException("Invalid key set for transition probabilities"); - } - - for (Integer state : this.model.getHiddenStates()) { - if (!this.model.getTransitionProbabilities().get(state).keySet().equals(this.model.getHiddenStates())) { - throw new InvalidParameterException("Invalid key set for transition probabilities for state " + state); - } - } - - if (!this.model.getEmitProbabilities().keySet().equals(this.model.getHiddenStates())) { - throw new InvalidParameterException("Invalid key set for emission probabilities: " + this.model.getEmitProbabilities().keySet() + " != " + this.model.getHiddenStates()); - } - - for (Integer state : this.model.getHiddenStates()) { - if (!this.model.getTransitionProbabilities().get(state).keySet().equals(this.model.getHiddenStates())) { - throw new InvalidParameterException( - "Invalid key set for emission probabilities for state " + - state + - ": " + - this.model.getTransitionProbabilities().get(state).keySet() + - " != " + - this.model.getObservations() - ); - } - } - } - - /** - * Handle an observation. - * @param observation The observation to process. - * @param observationTimestamp The timestamp when this observation was made - */ - public void observe(O observation, Timestamp observationTimestamp) { - int numSegments = this.model.getHiddenStates().size(); - Map probabilities = new HashMap<>(); - Map previousSegments = new HashMap<>(); - Map> lapTimestamps = new HashMap<>(); - - for (int nextSegment = 0; nextSegment < numSegments; nextSegment++) { - probabilities.put(nextSegment, 0.0); - for (int previousSegment = 0; previousSegment < numSegments; previousSegment++) { - double probability = this.lastState.probabilities().get(previousSegment) * - this.model.getTransitionProbabilities().get(previousSegment).get(nextSegment) * - this.model.getEmitProbabilities().get(nextSegment).get(observation); - if (probabilities.get(nextSegment) < probability) { - probabilities.put(nextSegment, probability); - previousSegments.put(nextSegment, previousSegment); - - int half = numSegments / 2; - // Dit is het algoritme van De Voerstreek - int delta = half - (half - (nextSegment - previousSegment)) % numSegments; - - Set newTimestamps = new TreeSet<>(this.lastState.lapTimestamps().get(previousSegment)); - - if (delta > 0 && previousSegment > nextSegment) { - // forward wrap-around - newTimestamps.add(observationTimestamp); - } else if (delta < 0 && previousSegment < nextSegment) { - // backwards wrap-around - Optional highestTimestamp = newTimestamps.stream().max(Timestamp::compareTo); - highestTimestamp.ifPresent(newTimestamps::remove); - } - lapTimestamps.put(nextSegment, newTimestamps); - } - } - } - - // normalize probabilities - double sum = probabilities.values().stream().reduce(0.0, Double::sum); - for (int i = 0; i < numSegments; i++) { - probabilities.put(i, probabilities.get(i) / sum); - } - - this.lastState = new ViterbiState(probabilities, previousSegments, lapTimestamps); - } - - /** - * Get the current state of the Viterbi algorithm. - * @return The last Result. - */ - public ViterbiState getState() { - return this.lastState; - } -} diff --git a/src/main/java/telraam/logic/viterbi/algorithm/ViterbiModel.java b/src/main/java/telraam/logic/viterbi/algorithm/ViterbiModel.java deleted file mode 100644 index edda291..0000000 --- a/src/main/java/telraam/logic/viterbi/algorithm/ViterbiModel.java +++ /dev/null @@ -1,30 +0,0 @@ -package telraam.logic.viterbi.algorithm; - -import java.util.Map; -import java.util.Set; - -public record ViterbiModel(Set observations, Set hiddenStates, - Map> transitionProbabilities, - Map> emitProbabilities, - Map startProbabilities) { - - public Set getObservations() { - return observations; - } - - public Set getHiddenStates() { - return hiddenStates; - } - - public Map> getTransitionProbabilities() { - return transitionProbabilities; - } - - public Map> getEmitProbabilities() { - return emitProbabilities; - } - - public Map getStartProbabilities() { - return startProbabilities; - } -} diff --git a/src/main/java/telraam/logic/viterbi/algorithm/ViterbiState.java b/src/main/java/telraam/logic/viterbi/algorithm/ViterbiState.java deleted file mode 100644 index ada5d6b..0000000 --- a/src/main/java/telraam/logic/viterbi/algorithm/ViterbiState.java +++ /dev/null @@ -1,25 +0,0 @@ -package telraam.logic.viterbi.algorithm; - -import java.sql.Timestamp; -import java.util.Map; -import java.util.Set; - -/** - * Helper class to store steps in the Viterbi algorithm. - */ -public record ViterbiState(Map probabilities, Map previousStates, Map> lapTimestamps) { - /** - * Get the most likely state to be in, in this Result - * - * @return The state that is most likely. - */ - public Integer mostLikelySegment() { - int mostLikelySegment = 0; - for (int i : probabilities.keySet()) { - if (this.probabilities.get(i) > this.probabilities.get(mostLikelySegment)) { - mostLikelySegment = i; - } - } - return mostLikelySegment; - } -} diff --git a/src/main/java/telraam/station/Fetcher.java b/src/main/java/telraam/station/Fetcher.java index cf371f8..54e04db 100644 --- a/src/main/java/telraam/station/Fetcher.java +++ b/src/main/java/telraam/station/Fetcher.java @@ -8,6 +8,8 @@ import telraam.database.models.Detection; import telraam.database.models.Station; import telraam.logic.Lapper; +import telraam.station.models.RonnyDetection; +import telraam.station.models.RonnyResponse; import java.io.IOException; import java.net.ConnectException; diff --git a/src/main/java/telraam/station/RonnyDetection.java b/src/main/java/telraam/station/models/RonnyDetection.java similarity index 90% rename from src/main/java/telraam/station/RonnyDetection.java rename to src/main/java/telraam/station/models/RonnyDetection.java index 40689b8..234a50d 100644 --- a/src/main/java/telraam/station/RonnyDetection.java +++ b/src/main/java/telraam/station/models/RonnyDetection.java @@ -1,4 +1,4 @@ -package telraam.station; +package telraam.station.models; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/telraam/station/RonnyResponse.java b/src/main/java/telraam/station/models/RonnyResponse.java similarity index 87% rename from src/main/java/telraam/station/RonnyResponse.java rename to src/main/java/telraam/station/models/RonnyResponse.java index b2cf9ef..011f2c7 100644 --- a/src/main/java/telraam/station/RonnyResponse.java +++ b/src/main/java/telraam/station/models/RonnyResponse.java @@ -1,4 +1,4 @@ -package telraam.station; +package telraam.station.models; import java.util.List; diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt index f11cd06..46bfca7 100644 --- a/src/main/resources/banner.txt +++ b/src/main/resources/banner.txt @@ -1 +1,8 @@ -ZeusWPI - Telraam \ No newline at end of file + + + _____ __ ______ ___ _____ _ +|__ /___ _ _ ___ \ \ / / _ \_ _| |_ _|__| |_ __ __ _ __ _ _ __ ___ + / // _ \ | | / __| \ \ /\ / /| |_) | | _____ | |/ _ \ | '__/ _` |/ _` | '_ ` _ \ + / /| __/ |_| \__ \ \ V V / | __/| | |_____| | | __/ | | | (_| | (_| | | | | | | +/____\___|\__,_|___/ \_/\_/ |_| |___| |_|\___|_|_| \__,_|\__,_|_| |_| |_| + diff --git a/src/test/java/telraam/logic/SimpleLapperTest.java b/src/test/java/telraam/logic/SimpleLapperTest.java index 4214d13..7758c47 100644 --- a/src/test/java/telraam/logic/SimpleLapperTest.java +++ b/src/test/java/telraam/logic/SimpleLapperTest.java @@ -8,6 +8,7 @@ import telraam.database.models.Detection; import telraam.database.models.Lap; import telraam.database.models.LapSource; +import telraam.logic.simple.SimpleLapper; import java.sql.Timestamp; import java.util.Optional;