use antigravity to rewrite all your code to migrate from flat files to relational database. YOLO
All checks were successful
pedestrian-simulator / build (push) Successful in 58s

This commit is contained in:
2026-01-11 20:24:50 -07:00
parent df1ee20994
commit 512b36b10e
10 changed files with 364 additions and 459 deletions

View File

@@ -1,9 +1,8 @@
package main
import (
"encoding/json"
"database/sql"
"fmt"
"os"
"sync"
"time"
)
@@ -29,70 +28,80 @@ type StepManager struct {
}
func NewStepManager(userID string) *StepManager {
now := time.Now()
interval := 15 * time.Minute
// Default state (will be used if load fails or file missing)
defaultState := TripState{
StartDate: now.Format("2006-01-02"),
StartTime: now,
DailyCache: make(map[string]int),
}
sm := &StepManager{
userID: userID,
tripState: defaultState,
syncInterval: interval,
lastSyncTime: now.Add(-interval),
nextSyncTime: now,
syncInterval: 15 * time.Minute,
}
if err := sm.LoadTripState(); err != nil {
fmt.Printf("Warning: Failed to load trip state: %v. Using new trip defaults.\n", err)
} else {
// Initialize total steps from the loaded state to avoid interpolating from 0
initialTotal := sm.RecalculateTotalFromState()
sm.previousTotalSteps = initialTotal
sm.targetTotalSteps = initialTotal
fmt.Printf("Initialized step counts from cache: %d\n", initialTotal)
}
sm.LoadTripState()
return sm
}
func (sm *StepManager) LoadTripState() error {
tripPath := fmt.Sprintf("data/users/%s/trip.json", sm.userID)
data, err := os.ReadFile(tripPath)
var startTime time.Time
err := db.QueryRow(`
SELECT start_date, start_time, start_day_initial_steps, previous_total_steps, target_total_steps, last_sync_time, next_sync_time
FROM trips WHERE user_id = ?
`, sm.userID).Scan(
&sm.tripState.StartDate, &startTime, &sm.tripState.StartDayInitialSteps,
&sm.previousTotalSteps, &sm.targetTotalSteps, &sm.lastSyncTime, &sm.nextSyncTime,
)
if err != nil {
if os.IsNotExist(err) {
if err == sql.ErrNoRows {
return nil // Normal for first run
}
return err
}
sm.tripState.StartTime = startTime
var loadedState TripState
if err := json.Unmarshal(data, &loadedState); err != nil {
return fmt.Errorf("failed to parse trip.json: %w", err)
// Load daily cache from DB
rows, err := db.Query("SELECT date, steps FROM daily_steps WHERE user_id = ?", sm.userID)
if err != nil {
return err
}
defer rows.Close()
sm.tripState.DailyCache = make(map[string]int)
for rows.Next() {
var date string
var steps int
if err := rows.Scan(&date, &steps); err != nil {
return err
}
sm.tripState.DailyCache[date] = steps
}
// Only update if valid
sm.tripState = loadedState
if sm.tripState.DailyCache == nil {
sm.tripState.DailyCache = make(map[string]int)
}
fmt.Printf("Loaded trip state: StartDate=%s, InitialSteps=%d\n", sm.tripState.StartDate, sm.tripState.StartDayInitialSteps)
return nil
}
func (sm *StepManager) SaveTripState() {
userDir := fmt.Sprintf("data/users/%s", sm.userID)
if err := os.MkdirAll(userDir, 0755); err != nil {
fmt.Printf("Error creating user directory: %v\n", err)
return
_, err := db.Exec(`
INSERT INTO trips (user_id, start_date, start_time, start_day_initial_steps, previous_total_steps, target_total_steps, last_sync_time, next_sync_time)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
start_date = VALUES(start_date),
start_time = VALUES(start_time),
start_day_initial_steps = VALUES(start_day_initial_steps),
previous_total_steps = VALUES(previous_total_steps),
target_total_steps = VALUES(target_total_steps),
last_sync_time = VALUES(last_sync_time),
next_sync_time = VALUES(next_sync_time)
`, sm.userID, sm.tripState.StartDate, sm.tripState.StartTime, sm.tripState.StartDayInitialSteps,
sm.previousTotalSteps, sm.targetTotalSteps, sm.lastSyncTime, sm.nextSyncTime)
if err != nil {
fmt.Printf("Error saving trip state: %v\n", err)
}
// Save daily cache
for date, steps := range sm.tripState.DailyCache {
_, err := db.Exec(`
INSERT INTO daily_steps (user_id, date, steps)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE steps = VALUES(steps)
`, sm.userID, date, steps)
if err != nil {
fmt.Printf("Error saving daily steps for %s: %v\n", date, err)
}
}
tripPath := fmt.Sprintf("%s/trip.json", userDir)
data, _ := json.MarshalIndent(sm.tripState, "", " ")
os.WriteFile(tripPath, data, 0644)
}
func (sm *StepManager) StartNewTrip() {
@@ -233,9 +242,12 @@ func (sm *StepManager) GetStatus() map[string]interface{} {
sm.mu.Lock()
defer sm.mu.Unlock()
// Reload from DB to get latest sync results from other instances
sm.LoadTripState()
// Auto-trigger sync if needed
if time.Now().After(sm.nextSyncTime) {
go sm.Sync() // Async sync
sm.Sync() // Sync and save to DB
}
currentSmoothed := sm.calculateSmoothedTokenAt(time.Now())