Skip to content

Commit

Permalink
Slapper
Browse files Browse the repository at this point in the history
  • Loading branch information
Topvennie committed Apr 2, 2024
1 parent a653a57 commit 779cb94
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/main/java/telraam/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import telraam.logic.lapper.Lapper;
import telraam.logic.lapper.external.ExternalLapper;
import telraam.logic.lapper.robust.RobustLapper;
import telraam.logic.lapper.slapper.Slapper;
import telraam.logic.positioner.Positioner;
import telraam.logic.positioner.simple.SimplePositioner;
import telraam.station.Fetcher;
Expand Down Expand Up @@ -130,6 +131,7 @@ public void run(AppConfiguration configuration, Environment environment) {

lappers.add(new ExternalLapper(this.database));
lappers.add(new RobustLapper(this.database));
lappers.add(new Slapper(this.database));

// Enable lapper APIs
for (Lapper lapper : lappers) {
Expand Down
139 changes: 139 additions & 0 deletions src/main/java/telraam/logic/lapper/slapper/Slapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package telraam.logic.lapper.slapper;

import io.dropwizard.jersey.setup.JerseyEnvironment;
import org.jdbi.v3.core.Jdbi;
import telraam.database.daos.LapSourceDAO;
import telraam.database.models.Detection;
import telraam.database.models.LapSource;
import telraam.logic.lapper.Lapper;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

// Lapper that only uses a single sql query
public class Slapper implements Lapper {
private final String SOURCE_NAME = "slapper";
private final int DEBOUNCE_TIMEOUT = 10;
private final ScheduledExecutorService scheduler;
private boolean debounceScheduled;
private final Logger logger;
private final Jdbi jdbi;

public Slapper(Jdbi jdbi) {
this.jdbi = jdbi;
this.scheduler = Executors.newScheduledThreadPool(1);
this.logger = Logger.getLogger(Slapper.class.getName());
this.debounceScheduled = false;

// Get the lapSourceId, create the source if needed
LapSourceDAO lapSourceDAO = jdbi.onDemand(LapSourceDAO.class);
if (lapSourceDAO.getByName(SOURCE_NAME).isEmpty()) {
lapSourceDAO.insert(new LapSource(SOURCE_NAME));
}
}

@Override
public void handle(Detection msg) {
if (!this.debounceScheduled) {
this.debounceScheduled = true;
this.scheduler.schedule(() -> {
try {
this.calculateLaps();
} catch (Exception e) {
logger.severe(e.getMessage());
}
this.debounceScheduled = false;
}, DEBOUNCE_TIMEOUT, TimeUnit.SECONDS);
}
}

private void calculateLaps() {
logger.info("Slapper: Calculating laps...");
this.jdbi.useHandle(handle -> handle.execute(
"""
WITH switchovers AS (
SELECT teamid AS team_id,
newbatonid,
timestamp AS start_timestamp,
COALESCE(
LEAD(timestamp) OVER (PARTITION BY teamid ORDER BY timestamp),
timestamp + INTERVAL '6 MONTHS'
) AS next_baton_switch
FROM batonswitchover
),
team_detections AS (
SELECT MIN(station_id) AS station_id,
MAX(rssi) as rssi,
date_trunc('second', timestamp) AS timestamp_seconds,
team_id
FROM detection d
LEFT JOIN switchovers s ON d.baton_id = s.newbatonid
AND d.timestamp BETWEEN s.start_timestamp AND s.next_baton_switch
WHERE station_id NOT BETWEEN 3 AND 5
AND rssi > -85
AND team_id IS NOT NULL
GROUP BY date_trunc('second', timestamp), team_id
),
no_duplicates AS (
SELECT team_id,
timestamp_seconds,
FIRST_VALUE(timestamp_seconds) OVER (
PARTITION BY team_id
ORDER BY timestamp_seconds
) AS first_timestamp_seconds
FROM (
SELECT *,
LAG(station_id) OVER (
PARTITION BY team_id
ORDER BY timestamp_seconds
) AS prev_station_id
FROM team_detections
) AS previous
WHERE station_id - prev_station_id <= -5
),
new_laps AS (
SELECT team_id,
timestamp_seconds
FROM no_duplicates n_d
WHERE timestamp_seconds > first_timestamp_seconds
),
cst_source_id AS (
SELECT COALESCE(id, -1) AS source_id
FROM lap_source
WHERE name ILIKE 'slapper'
),
deletions AS (
DELETE FROM lap l
WHERE lap_source_id = (SELECT source_id FROM cst_source_id)
AND NOT EXISTS (
SELECT 1
FROM new_laps n_l
WHERE l.team_id = n_l.team_id
AND l.timestamp = n_l.timestamp_seconds
)
)
INSERT INTO lap (team_id, timestamp, lap_source_id)
SELECT team_id,
timestamp_seconds,
source_id
FROM new_laps n_l, cst_source_id
WHERE NOT EXISTS (
SELECT 1
FROM lap l, cst_source_id
WHERE l.lap_source_id = source_id
AND l.team_id = n_l.team_id
AND l.timestamp = n_l.timestamp_seconds
)
"""
)
);
logger.info("Slapper: Done calculating laps");
}

@Override
public void registerAPI(JerseyEnvironment jersey) {

}
}

0 comments on commit 779cb94

Please sign in to comment.