Initial commit: smartrun MVP
Garmin run classification and progression tracker. Go backend (MCP client to mcp-garmin, SQLite store, deterministic rule engine, REST API) and React/TS frontend (Dashboard, Review Queue, Workout Kinds). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
109
backend/internal/store/migrations/0001_init.sql
Normal file
109
backend/internal/store/migrations/0001_init.sql
Normal file
@@ -0,0 +1,109 @@
|
||||
CREATE TABLE activities (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
garmin_activity_id INTEGER NOT NULL UNIQUE,
|
||||
activity_name TEXT NOT NULL DEFAULT '',
|
||||
activity_type TEXT NOT NULL,
|
||||
start_time_utc TEXT NOT NULL,
|
||||
begin_timestamp_ms INTEGER NOT NULL,
|
||||
duration_seconds REAL NOT NULL,
|
||||
distance_meters REAL NOT NULL,
|
||||
avg_hr REAL,
|
||||
max_hr REAL,
|
||||
avg_speed_mps REAL,
|
||||
max_speed_mps REAL,
|
||||
elevation_gain_m REAL,
|
||||
elevation_loss_m REAL,
|
||||
calories REAL,
|
||||
lap_count INTEGER NOT NULL DEFAULT 0,
|
||||
aerobic_training_effect REAL,
|
||||
anaerobic_training_effect REAL,
|
||||
training_effect_label TEXT NOT NULL DEFAULT '',
|
||||
vo2max_value REAL,
|
||||
hr_time_in_zone_1 REAL,
|
||||
hr_time_in_zone_2 REAL,
|
||||
hr_time_in_zone_3 REAL,
|
||||
hr_time_in_zone_4 REAL,
|
||||
hr_time_in_zone_5 REAL,
|
||||
raw_json TEXT NOT NULL,
|
||||
details_fetched_at TEXT,
|
||||
details_raw_json TEXT,
|
||||
splits_fetched_at TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
CREATE INDEX idx_activities_start_time ON activities(start_time_utc);
|
||||
CREATE INDEX idx_activities_activity_type ON activities(activity_type);
|
||||
|
||||
CREATE TABLE laps (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
activity_id INTEGER NOT NULL REFERENCES activities(id) ON DELETE CASCADE,
|
||||
lap_index INTEGER NOT NULL,
|
||||
start_time_utc TEXT NOT NULL,
|
||||
duration_seconds REAL NOT NULL,
|
||||
distance_meters REAL NOT NULL,
|
||||
avg_hr REAL,
|
||||
max_hr REAL,
|
||||
avg_speed_mps REAL,
|
||||
max_speed_mps REAL,
|
||||
elevation_gain_m REAL,
|
||||
elevation_loss_m REAL,
|
||||
intensity_type TEXT NOT NULL DEFAULT '',
|
||||
hr_drift_bpm_per_min REAL,
|
||||
hr_recovery_bpm_per_min REAL,
|
||||
raw_json TEXT NOT NULL,
|
||||
UNIQUE(activity_id, lap_index)
|
||||
);
|
||||
|
||||
CREATE TABLE activity_samples (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
activity_id INTEGER NOT NULL REFERENCES activities(id) ON DELETE CASCADE,
|
||||
elapsed_seconds REAL NOT NULL,
|
||||
timestamp_ms INTEGER NOT NULL,
|
||||
heart_rate REAL,
|
||||
speed_mps REAL,
|
||||
distance_m REAL,
|
||||
elevation_m REAL
|
||||
);
|
||||
CREATE INDEX idx_activity_samples_activity ON activity_samples(activity_id, elapsed_seconds);
|
||||
|
||||
CREATE TABLE workout_kinds (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
color TEXT NOT NULL DEFAULT '',
|
||||
rule_json TEXT NOT NULL,
|
||||
priority INTEGER NOT NULL DEFAULT 0,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE TABLE kind_assignments (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
activity_id INTEGER NOT NULL REFERENCES activities(id) ON DELETE CASCADE,
|
||||
workout_kind_id INTEGER REFERENCES workout_kinds(id),
|
||||
assignment_source TEXT NOT NULL CHECK(assignment_source IN ('rule_engine','manual')),
|
||||
status TEXT NOT NULL CHECK(status IN ('assigned','needs_review')),
|
||||
confidence REAL,
|
||||
candidate_kinds_json TEXT NOT NULL DEFAULT '[]',
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
CREATE INDEX idx_kind_assignments_activity ON kind_assignments(activity_id);
|
||||
CREATE INDEX idx_kind_assignments_status ON kind_assignments(status);
|
||||
|
||||
CREATE VIEW current_kind_assignment AS
|
||||
SELECT a.* FROM kind_assignments a
|
||||
JOIN (
|
||||
SELECT activity_id, MAX(id) AS max_id
|
||||
FROM kind_assignments GROUP BY activity_id
|
||||
) latest ON a.activity_id = latest.activity_id AND a.id = latest.max_id;
|
||||
|
||||
CREATE TABLE sync_runs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
kind TEXT NOT NULL CHECK(kind IN ('backfill','incremental')),
|
||||
started_at TEXT NOT NULL,
|
||||
finished_at TEXT,
|
||||
activities_fetched INTEGER NOT NULL DEFAULT 0,
|
||||
status TEXT NOT NULL CHECK(status IN ('running','success','error')),
|
||||
error_message TEXT
|
||||
);
|
||||
Reference in New Issue
Block a user