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,11 +1,11 @@
package main
import (
"database/sql"
"encoding/json"
"fmt"
"net/http"
"os"
"sync"
"time"
)
@@ -16,104 +16,38 @@ type User struct {
CreatedAt time.Time `json:"created_at"`
}
type UserRegistry struct {
Users map[string]*User `json:"users"` // Map of FitbitUserID -> User
mu sync.RWMutex
}
var userRegistry *UserRegistry
// InitUserRegistry loads or creates the user registry
func InitUserRegistry() {
userRegistry = &UserRegistry{
Users: make(map[string]*User),
}
userRegistry.Load()
}
// Load reads the user registry from disk
func (ur *UserRegistry) Load() error {
ur.mu.Lock()
defer ur.mu.Unlock()
data, err := os.ReadFile("data/users.json")
// GetUser retrieves a user by Fitbit user ID from the database
func GetUser(fitbitUserID string) (*User, error) {
var user User
err := db.QueryRow("SELECT fitbit_user_id, display_name, avatar_url, created_at FROM users WHERE fitbit_user_id = ?", fitbitUserID).
Scan(&user.FitbitUserID, &user.DisplayName, &user.AvatarURL, &user.CreatedAt)
if err != nil {
if os.IsNotExist(err) {
return nil // First run, no users yet
if err == sql.ErrNoRows {
return nil, nil
}
return err
return nil, err
}
return json.Unmarshal(data, ur)
return &user, nil
}
// Save writes the user registry to disk
func (ur *UserRegistry) Save() error {
ur.mu.RLock()
defer ur.mu.RUnlock()
return ur.saveUnlocked()
}
// saveUnlocked writes the user registry to disk without locking (caller must hold lock)
func (ur *UserRegistry) saveUnlocked() error {
if err := os.MkdirAll("data", 0755); err != nil {
return err
}
data, err := json.MarshalIndent(ur, "", " ")
// CreateOrUpdateUser adds or updates a user in the database
func CreateOrUpdateUser(fitbitUserID, displayName, avatarURL string) (*User, error) {
_, err := db.Exec(`
INSERT INTO users (fitbit_user_id, display_name, avatar_url, created_at)
VALUES (?, ?, ?, NOW())
ON DUPLICATE KEY UPDATE display_name = ?, avatar_url = ?
`, fitbitUserID, displayName, avatarURL, displayName, avatarURL)
if err != nil {
return err
}
return os.WriteFile("data/users.json", data, 0644)
}
// GetUser retrieves a user by Fitbit user ID
func (ur *UserRegistry) GetUser(fitbitUserID string) (*User, bool) {
ur.mu.RLock()
defer ur.mu.RUnlock()
user, exists := ur.Users[fitbitUserID]
return user, exists
}
// CreateOrUpdateUser adds or updates a user in the registry
func (ur *UserRegistry) CreateOrUpdateUser(fitbitUserID, displayName, avatarURL string) (*User, error) {
ur.mu.Lock()
defer ur.mu.Unlock()
user, exists := ur.Users[fitbitUserID]
if exists {
// Update existing user
user.DisplayName = displayName
user.AvatarURL = avatarURL
} else {
// Create new user
user = &User{
FitbitUserID: fitbitUserID,
DisplayName: displayName,
AvatarURL: avatarURL,
CreatedAt: time.Now(),
}
ur.Users[fitbitUserID] = user
}
// Save without locking (we already have the lock)
if err := ur.saveUnlocked(); err != nil {
return nil, err
}
// Create user directory
userDir := fmt.Sprintf("data/users/%s", fitbitUserID)
// Create user directory for KML files
userDir := fmt.Sprintf("data/users/%s/kml", fitbitUserID)
if err := os.MkdirAll(userDir, 0755); err != nil {
return nil, err
}
kmlDir := fmt.Sprintf("data/users/%s/kml", fitbitUserID)
if err := os.MkdirAll(kmlDir, 0755); err != nil {
return nil, err
}
return user, nil
return GetUser(fitbitUserID)
}
// FetchFitbitUserProfile fetches the user's profile from Fitbit API