diff options
Diffstat (limited to 'web/climb-backfill.go')
| -rw-r--r-- | web/climb-backfill.go | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/web/climb-backfill.go b/web/climb-backfill.go new file mode 100644 index 0000000..13a8c02 --- /dev/null +++ b/web/climb-backfill.go @@ -0,0 +1,81 @@ +package web + +import ( + "database/sql" + "log/slog" + + "github.com/martinlehoux/biking_home/config" + "github.com/martinlehoux/biking_home/mountain_pass" + "github.com/martinlehoux/biking_home/official_climb" + "github.com/martinlehoux/biking_home/ride" + "github.com/martinlehoux/biking_home/rideanalysis" + "github.com/martinlehoux/kagamigo/kcore" + "github.com/schollz/progressbar/v3" +) + +// BackfillOfficialClimbAttempts parses every route-bearing ride, matches its +// official climbs, and persists the resulting attempts. An optional reporter +// is invoked with progress for CLI rendering. +func BackfillOfficialClimbAttempts(db *sql.DB, configPath string, reporters ...func(current, total int)) (int, error) { + appConfig, err := config.Load(configPath) + if err != nil { + return 0, err + } + matchPolicy := official_climb.DefaultMatchPolicy() + matchPolicy.EndpointRadiusM = appConfig.OfficialClimb.MatchRadiusM + items, err := ride.List(db) + if err != nil { + return 0, err + } + officialClimbs, err := official_climb.List(db) + if err != nil { + return 0, err + } + var bar *progressbar.ProgressBar + report := func(int, int) {} + if len(reporters) > 0 { + report = reporters[0] + } + backfilled := 0 + for i, item := range items { + report(i+1, len(items)) + if item.FitPath == "" && item.GPXPath == "" { + continue + } + parsed, err := ride.ParseStoredRide(item) + if err != nil { + slog.Warn("Failed to parse ride for climb backfill", "ride_id", item.ID, "error", err) + continue + } + passes, err := mountain_pass.LoadMountainPassesAroundRide(db, parsed.Coords, rideDetailMountainPassMarginM) + if err != nil { + slog.Warn("Failed to load passes for climb backfill", "ride_id", item.ID, "error", err) + } + analysis := rideanalysis.Analyze(parsed, passes, officialClimbs, matchPolicy) + attempts := attemptsFromAnalysis(item.ID, analysis, parsed) + if err := official_climb.ReplaceRideAttempts(db, item.ID, attempts); err != nil { + slog.Warn("Failed to record climb attempts", "ride_id", item.ID, "error", err) + continue + } + backfilled++ + } + if bar != nil { + bar.Finish() + } + return backfilled, nil +} + +// BackfillOfficialClimbAttemptsCmd runs the climb attempt backfill from the CLI. +func BackfillOfficialClimbAttemptsCmd(db *sql.DB, configPath string) { + var bar *progressbar.ProgressBar + count, err := BackfillOfficialClimbAttempts(db, configPath, func(current, total int) { + if bar == nil && mountain_pass.ProgressBarEnabled() { + bar = progressbar.Default(int64(total), "Backfilling climb attempts") + } + if bar != nil { + bar.Set(current) + } + }) + kcore.Expect(err, "failed to backfill climb attempts") + slog.Info("Backfilled climb attempts", "rides", count) +} |
