feat(hunt): track walking distance via GPS, show live locations on map
Docker Image CI / test (push) Failing after 41s
Docker Image CI / deploy (push) Skipped
Tests / unit (push) Failing after 36s
Tests / integration (push) Successful in 1m34s

Add foreground-only GPS distance tracking for hunts
This commit is contained in:
2026-09-27 20:55:58 +02:00
parent a0fc836c05
commit 61cc516f47
43 changed files with 2313 additions and 24 deletions
+45
View File
@@ -33,6 +33,9 @@ model User {
reviews Review[]
uploadedFiles File[]
trackPoints TrackPoint[]
userTracks UserTrack[]
}
enum UserRole {
@@ -80,6 +83,7 @@ model Hunt {
revealQuests Boolean @default(false)
revealAnswers Boolean @default(false)
public Boolean @default(true)
trackDistance Boolean @default(false)
creator User @relation(fields: [creatorId], references: [id], onUpdate: Cascade, onDelete: Cascade)
creatorId Int
@@ -98,6 +102,9 @@ model Hunt {
oldFiles File[] @relation("OldHuntFiles")
trackPoints TrackPoint[]
userTracks UserTrack[]
@@index([creatorId])
}
@@ -255,3 +262,41 @@ model Review {
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
}
/// A single raw GPS fix streamed by the client while tracking is active.
/// All points are retained (for future map features); distance is derived
/// server-side and stored on UserTrack.
model TrackPoint {
id Int @id @default(autoincrement())
lat Decimal @db.Decimal(10, 8)
lon Decimal @db.Decimal(10, 8)
/// Reported accuracy in meters, if the device provided one.
accuracy Float?
recordedAt DateTime @db.Timestamptz(3)
createdAt DateTime @default(now()) @db.Timestamptz(3)
user User @relation(fields: [userId], references: [id], onUpdate: Cascade, onDelete: Cascade)
userId Int
hunt Hunt @relation(fields: [huntId], references: [id], onUpdate: Cascade, onDelete: Cascade)
huntId Int
@@index([userId, huntId, recordedAt])
}
/// Per-user, per-hunt aggregate of the derived walking distance.
/// Recomputed idempotently from all of the user's TrackPoints on each batch.
model UserTrack {
id Int @id @default(autoincrement())
distanceMeters Int @default(0)
lastFixAt DateTime? @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
user User @relation(fields: [userId], references: [id], onUpdate: Cascade, onDelete: Cascade)
userId Int
hunt Hunt @relation(fields: [huntId], references: [id], onUpdate: Cascade, onDelete: Cascade)
huntId Int
@@unique([userId, huntId])
}