ActivitySummary

This commit is contained in:
2026-05-15 10:29:53 +02:00
parent feae6fc1bc
commit dd09c8dbcd
3 changed files with 51537 additions and 59 deletions

View File

@@ -16,7 +16,7 @@ import java.util.List;
import java.util.Objects;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@QuarkusTest
@TestProfile(PostgresWithDataTestProfile.class)
@@ -41,7 +41,7 @@ class ActivityTest extends AbstractPeakUpTest {
for (final IntervalsActivity activity : activities) {
final long activityId = Objects.requireNonNull(activity.getId());
assertFalse(activityStreamDAO.hasStreams(activityId), "activity " + activityId + " (" + activity.getName() + ") must not have stream points");
assertTrue(activityStreamDAO.hasStreams(activityId), "activity " + activityId + " (" + activity.getName() + ") must have stream points");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -65,7 +65,7 @@ public class TestDataDumper {
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.build();
public static void main(String[] args) throws Exception {
public static void main(final String[] args) throws Exception {
long athleteId = 90L;
LocalDate from = LocalDate.of(2026, 1, 1);
LocalDate to = LocalDate.of(2026, 2, 28);
@@ -76,16 +76,16 @@ public class TestDataDumper {
to = LocalDate.parse(args[2]);
}
Path output = Paths.get(System.getProperty("user.dir")).resolve(OUTPUT_PATH);
final Path output = Paths.get(System.getProperty("user.dir")).resolve(OUTPUT_PATH);
System.out.println("Dumping: athlete=" + athleteId + " from=" + from + " to=" + to);
System.out.println("Output: " + output.toAbsolutePath());
try (Connection conn = DriverManager.getConnection(JDBC_URL, DB_USER, DB_PASSWORD);
BufferedWriter writer = Files.newBufferedWriter(output, StandardCharsets.UTF_8)) {
try (final Connection conn = DriverManager.getConnection(JDBC_URL, DB_USER, DB_PASSWORD);
final BufferedWriter writer = Files.newBufferedWriter(output, StandardCharsets.UTF_8)) {
writeMeta(writer, athleteId, from, to);
List<Long> activityIds = dumpActivities(writer, conn, athleteId, from, to);
final List<Long> activityIds = dumpActivities(writer, conn, athleteId, from, to);
System.out.println(" intervals_activity: " + activityIds.size() + " rows");
if (activityIds.isEmpty()) {
@@ -93,10 +93,10 @@ public class TestDataDumper {
return;
}
int streamRows = dumpStreamTable(writer, conn, "activity_stream_point", activityIds);
final int streamRows = dumpStreamTable(writer, conn, "activity_stream_point", activityIds);
System.out.println(" activity_stream_point: " + streamRows + " rows");
int mapRows = dumpStreamTable(writer, conn, "activity_map_stream_point", activityIds);
final int mapRows = dumpStreamTable(writer, conn, "activity_map_stream_point", activityIds);
System.out.println(" activity_map_stream_point: " + mapRows + " rows");
}
@@ -107,25 +107,25 @@ public class TestDataDumper {
// Table dumpers
// -----------------------------------------------------------------------
private static List<Long> dumpActivities(BufferedWriter writer, Connection conn,
long athleteId, LocalDate from, LocalDate to) throws Exception {
private static List<Long> dumpActivities(final BufferedWriter writer, final Connection conn,
final long athleteId, final LocalDate from, final LocalDate to) throws Exception {
String query = "SELECT DISTINCT ON (sport_type) * FROM intervals_activity"
final String query = "SELECT DISTINCT ON (sport_type) * FROM intervals_activity"
+ " WHERE athlete_id = ?"
+ " AND start_time >= ?"
+ " AND start_time < ?"
+ " ORDER BY sport_type, start_time DESC";
List<Long> ids = new ArrayList<>();
final List<Long> ids = new ArrayList<>();
try (PreparedStatement ps = conn.prepareStatement(query)) {
try (final PreparedStatement ps = conn.prepareStatement(query)) {
ps.setLong(1, athleteId);
ps.setTimestamp(2, Timestamp.from(from.atStartOfDay(ZoneOffset.UTC).toInstant()));
ps.setTimestamp(3, Timestamp.from(to.plusDays(1).atStartOfDay(ZoneOffset.UTC).toInstant()));
try (ResultSet rs = ps.executeQuery()) {
try (final ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
ObjectNode node = rowToNode(rs, "intervals_activity");
final ObjectNode node = rowToNode(rs, "intervals_activity");
if (node.has("id")) {
ids.add(node.get("id").asLong());
}
@@ -137,19 +137,19 @@ public class TestDataDumper {
return ids;
}
private static int dumpStreamTable(BufferedWriter writer, Connection conn,
String table, List<Long> activityIds) throws Exception {
private static int dumpStreamTable(final BufferedWriter writer, final Connection conn,
final String table, final List<Long> activityIds) throws Exception {
String inClause = activityIds.stream()
final String inClause = activityIds.stream()
.map(String::valueOf)
.collect(Collectors.joining(","));
String query = "SELECT * FROM " + table
final String query = "SELECT * FROM " + table
+ " WHERE activity_id IN (" + inClause + ")"
+ " ORDER BY activity_id, time";
int count = 0;
try (var stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query)) {
try (final var stmt = conn.createStatement();
final ResultSet rs = stmt.executeQuery(query)) {
while (rs.next()) {
writeLine(writer, MAPPER.writeValueAsString(rowToNode(rs, table)));
count++;
@@ -162,14 +162,14 @@ public class TestDataDumper {
// Raw ResultSet → JSON
// -----------------------------------------------------------------------
private static ObjectNode rowToNode(ResultSet rs, String tableName) throws Exception {
ObjectNode node = MAPPER.createObjectNode();
private static ObjectNode rowToNode(final ResultSet rs, final String tableName) throws Exception {
final ObjectNode node = MAPPER.createObjectNode();
node.put("_type", tableName);
ResultSetMetaData meta = rs.getMetaData();
int n = meta.getColumnCount();
final ResultSetMetaData meta = rs.getMetaData();
final int n = meta.getColumnCount();
for (int i = 1; i <= n; i++) {
String col = meta.getColumnName(i).toLowerCase();
Object val = rs.getObject(i);
final String col = meta.getColumnName(i).toLowerCase();
final Object val = rs.getObject(i);
if (val != null) {
putValue(node, col, val);
}
@@ -177,42 +177,42 @@ public class TestDataDumper {
return node;
}
private static void putValue(ObjectNode node, String col, Object val) throws Exception {
if (val instanceof Boolean b) {
private static void putValue(final ObjectNode node, final String col, final Object val) throws Exception {
if (val instanceof final Boolean b) {
node.put(col, b);
} else if (val instanceof Integer i) {
} else if (val instanceof final Integer i) {
node.put(col, i);
} else if (val instanceof Long l) {
} else if (val instanceof final Long l) {
node.put(col, l);
} else if (val instanceof Float f) {
} else if (val instanceof final Float f) {
node.put(col, f);
} else if (val instanceof Double d) {
} else if (val instanceof final Double d) {
node.put(col, d);
} else if (val instanceof BigDecimal bd) {
} else if (val instanceof final BigDecimal bd) {
node.put(col, bd.doubleValue());
} else if (val instanceof Number num) {
} else if (val instanceof final Number num) {
node.put(col, num.longValue());
} else if (val instanceof Timestamp ts) {
} else if (val instanceof final Timestamp ts) {
node.put(col, ts.toInstant().toString());
} else if (val instanceof byte[] bytes) {
} else if (val instanceof final byte[] bytes) {
node.put(col, Base64.getEncoder().encodeToString(bytes));
} else if (val instanceof Array arr) {
ArrayNode arrNode = node.putArray(col);
Object javaArr = arr.getArray();
if (javaArr instanceof Integer[] ints) {
for (int v : ints) {
} else if (val instanceof final Array arr) {
final ArrayNode arrNode = node.putArray(col);
final Object javaArr = arr.getArray();
if (javaArr instanceof final Integer[] ints) {
for (final int v : ints) {
arrNode.add(v);
}
} else if (javaArr instanceof Long[] longs) {
for (long v : longs) {
} else if (javaArr instanceof final Long[] longs) {
for (final long v : longs) {
arrNode.add(v);
}
} else if (javaArr instanceof String[] strs) {
for (String s : strs) {
} else if (javaArr instanceof final String[] strs) {
for (final String s : strs) {
arrNode.add(s);
}
} else if (javaArr instanceof Object[] objs) {
for (Object o : objs) {
} else if (javaArr instanceof final Object[] objs) {
for (final Object o : objs) {
arrNode.add(o == null ? null : o.toString());
}
}
@@ -225,11 +225,11 @@ public class TestDataDumper {
// JSONL helpers
// -----------------------------------------------------------------------
private static void writeMeta(BufferedWriter writer, long athleteId,
LocalDate from, LocalDate to) throws Exception {
String dumpedAt = ZonedDateTime.now(ZoneOffset.UTC)
private static void writeMeta(final BufferedWriter writer, final long athleteId,
final LocalDate from, final LocalDate to) throws Exception {
final String dumpedAt = ZonedDateTime.now(ZoneOffset.UTC)
.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
ObjectNode meta = MAPPER.createObjectNode();
final ObjectNode meta = MAPPER.createObjectNode();
meta.put("_type", "_meta");
meta.put("athleteId", athleteId);
meta.put("from", from.toString());
@@ -238,7 +238,7 @@ public class TestDataDumper {
writeLine(writer, MAPPER.writeValueAsString(meta));
}
private static void writeLine(BufferedWriter writer, String line) throws Exception {
private static void writeLine(final BufferedWriter writer, final String line) throws Exception {
writer.write(line);
writer.newLine();
}