git-fit 0.14.1 → 0.14.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/git_fit/export/calculator.rb +18 -2
- data/lib/git_fit/sync/garmin_base.rb +71 -7
- data/lib/git_fit/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5922b46e00a21d66f591fb8d0e43b9a5e35dbb2fef4f5118aa7c689e62fa0118
|
|
4
|
+
data.tar.gz: 103cb559cef56006024fb838982410a47c49485c9a104ee6bd29a33cc05179f2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d7de2f67f3c9d549cfa1f1117acb3d0843b15cf3543508a9e588e4d8a9e1b3e3ca06f1e6feb403204df9f17bc480b758b95586ef5ab55085e59795773890a545
|
|
7
|
+
data.tar.gz: 5e252339935260098d9d8811ba9a4229dabf58c86c861afad78e6a2d17096aaed24dc2500f2144a5982e2157a2d343cf35b1269e0098f32675153afda2583640
|
|
@@ -61,6 +61,7 @@ module GitFit
|
|
|
61
61
|
|
|
62
62
|
cadences = rows.map { |r| r[:average_cadence] }.compact
|
|
63
63
|
powers = rows.map { |r| r[:average_power] }.compact
|
|
64
|
+
max_powers = rows.map { |r| r[:max_power] }.compact
|
|
64
65
|
|
|
65
66
|
grouped_run_ids = if @db.table_exists?(:dedup_group_members)
|
|
66
67
|
@db[:dedup_group_members].select_map(:run_id)
|
|
@@ -80,6 +81,8 @@ module GitFit
|
|
|
80
81
|
total_steps: total_steps,
|
|
81
82
|
avg_cadence: cadences.any? ? (cadences.sum / cadences.size).round(1) : nil,
|
|
82
83
|
avg_power: powers.any? ? (powers.sum / powers.size).round(1) : nil,
|
|
84
|
+
max_power: max_powers.any? ? max_powers.max.round(1) : nil,
|
|
85
|
+
avg_max_power: max_powers.any? ? (max_powers.sum / max_powers.size).round(1) : nil,
|
|
83
86
|
sport_breakdown: breakdown.sort_by { |_, v| -v[:count] }.map do |cat, v|
|
|
84
87
|
{ category: cat, count: v[:count], distance_km: v[:distance_km].round(1),
|
|
85
88
|
moving_time_h: v[:moving_time_h].round(1) }
|
|
@@ -93,7 +96,8 @@ module GitFit
|
|
|
93
96
|
total_hr: 0.0, hr_count: 0, total_elev: 0.0,
|
|
94
97
|
total_loss: 0.0, total_steps: 0,
|
|
95
98
|
total_cadence: 0.0, cadence_count: 0,
|
|
96
|
-
total_power: 0.0, power_count: 0
|
|
99
|
+
total_power: 0.0, power_count: 0,
|
|
100
|
+
max_power_peak: 0.0, total_max_power: 0.0, max_power_count: 0 }
|
|
97
101
|
end
|
|
98
102
|
|
|
99
103
|
rows.each do |r|
|
|
@@ -127,6 +131,12 @@ module GitFit
|
|
|
127
131
|
monthly[ym][:total_power] += pow
|
|
128
132
|
monthly[ym][:power_count] += 1
|
|
129
133
|
end
|
|
134
|
+
max_pow = r[:max_power]
|
|
135
|
+
if max_pow && max_pow > 0
|
|
136
|
+
monthly[ym][:max_power_peak] = max_pow if max_pow > monthly[ym][:max_power_peak]
|
|
137
|
+
monthly[ym][:total_max_power] += max_pow
|
|
138
|
+
monthly[ym][:max_power_count] += 1
|
|
139
|
+
end
|
|
130
140
|
end
|
|
131
141
|
|
|
132
142
|
monthly.sort.map do |ym, v|
|
|
@@ -143,6 +153,8 @@ module GitFit
|
|
|
143
153
|
avg_hr: v[:hr_count] > 0 ? (v[:total_hr] / v[:hr_count]).round(0) : nil,
|
|
144
154
|
avg_cadence: v[:cadence_count] > 0 ? (v[:total_cadence] / v[:cadence_count]).round(0) : nil,
|
|
145
155
|
avg_power: v[:power_count] > 0 ? (v[:total_power] / v[:power_count]).round(0) : nil,
|
|
156
|
+
max_power: v[:max_power_count] > 0 ? v[:max_power_peak].round(0) : nil,
|
|
157
|
+
avg_max_power: v[:max_power_count] > 0 ? (v[:total_max_power] / v[:max_power_count]).round(0) : nil,
|
|
146
158
|
elevation_gain_m: v[:total_elev].round(0),
|
|
147
159
|
elevation_loss_m: v[:total_loss].round(0),
|
|
148
160
|
steps: v[:total_steps],
|
|
@@ -167,11 +179,15 @@ module GitFit
|
|
|
167
179
|
|
|
168
180
|
streak = calculate_streak(acts)
|
|
169
181
|
|
|
182
|
+
year_max_powers = acts.map { |r| r[:max_power] }.compact
|
|
183
|
+
|
|
170
184
|
{ year: year, count: acts.size, distance_km: total_dist.round(1),
|
|
171
185
|
moving_time_h: (total_time / 3600.0).round(1),
|
|
172
186
|
longest_km: longest.round(1), streak: streak,
|
|
173
187
|
elevation_gain_m: total_elev.round(0), elevation_loss_m: total_loss.round(0),
|
|
174
|
-
steps: total_steps
|
|
188
|
+
steps: total_steps,
|
|
189
|
+
max_power: year_max_powers.any? ? year_max_powers.max.round(0) : nil,
|
|
190
|
+
avg_max_power: year_max_powers.any? ? (year_max_powers.sum / year_max_powers.size).round(0) : nil }
|
|
175
191
|
end
|
|
176
192
|
end
|
|
177
193
|
|
|
@@ -138,7 +138,7 @@ module GitFit
|
|
|
138
138
|
write_standardized_json(l2, act_id) if l2
|
|
139
139
|
end
|
|
140
140
|
|
|
141
|
-
attrs = build_attrs(details, act_id, type, polyline)
|
|
141
|
+
attrs = build_attrs(details, act_id, type, polyline, l2_data: l2)
|
|
142
142
|
|
|
143
143
|
if (start_t = parse_garmin_time(details.dig('summaryDTO', 'startTimeGMT')))
|
|
144
144
|
local_t = resolve_local_time(start_t, act_id, polyline)
|
|
@@ -480,13 +480,28 @@ module GitFit
|
|
|
480
480
|
"Re-auth: set sync.#{source_prefix}.secret in #{GitFit::Config.default_path}"
|
|
481
481
|
end
|
|
482
482
|
|
|
483
|
-
def build_attrs(detail, activity_id, type, polyline = nil)
|
|
483
|
+
def build_attrs(detail, activity_id, type, polyline = nil, l2_data: nil)
|
|
484
484
|
summary = detail['summaryDTO'] || {}
|
|
485
485
|
|
|
486
486
|
start_t = parse_garmin_time(summary['startTimeGMT'])
|
|
487
487
|
moving_time = summary['movingDuration']&.to_i || summary['duration']&.to_i
|
|
488
488
|
elapsed_time = summary['elapsedDuration']&.to_i || summary['duration']&.to_i
|
|
489
489
|
|
|
490
|
+
average_power = summary['avgPower']&.to_f
|
|
491
|
+
average_power ||= fallback_avg_power(activity_id, l2_data)
|
|
492
|
+
|
|
493
|
+
max_power = summary['maxPower']&.to_f
|
|
494
|
+
|
|
495
|
+
average_cadence = summary['avgCadence']&.to_f
|
|
496
|
+
average_cadence ||= sport_cadence(summary, type)&.to_f
|
|
497
|
+
average_cadence ||= fallback_avg_cadence(activity_id, l2_data)
|
|
498
|
+
|
|
499
|
+
max_cadence = summary['maxCadence']&.to_f
|
|
500
|
+
max_cadence ||= sport_max_cadence(summary, type)&.to_f
|
|
501
|
+
|
|
502
|
+
average_temperature = summary['avgTemperature']&.to_f
|
|
503
|
+
average_temperature ||= fallback_avg_temperature(activity_id, l2_data)
|
|
504
|
+
|
|
490
505
|
{
|
|
491
506
|
run_id: "#{source_prefix}_#{activity_id}",
|
|
492
507
|
name: detail['activityName'] || 'Garmin Activity',
|
|
@@ -501,12 +516,12 @@ module GitFit
|
|
|
501
516
|
summary_polyline: polyline,
|
|
502
517
|
average_heartrate: summary['averageHR']&.to_f,
|
|
503
518
|
max_heartrate: summary['maxHR']&.to_f,
|
|
504
|
-
average_cadence:
|
|
505
|
-
max_cadence:
|
|
506
|
-
average_power:
|
|
507
|
-
max_power:
|
|
519
|
+
average_cadence: average_cadence,
|
|
520
|
+
max_cadence: max_cadence,
|
|
521
|
+
average_power: average_power,
|
|
522
|
+
max_power: max_power,
|
|
508
523
|
calories: summary['calories']&.to_i,
|
|
509
|
-
average_temperature:
|
|
524
|
+
average_temperature: average_temperature,
|
|
510
525
|
average_speed: summary['averageSpeed']&.to_f,
|
|
511
526
|
elevation_gain: summary['elevationGain']&.to_f,
|
|
512
527
|
elevation_loss: summary['elevationLoss']&.to_f,
|
|
@@ -530,6 +545,55 @@ module GitFit
|
|
|
530
545
|
val.is_a?(Hash) ? (val['typeKey'] || '').downcase : val.to_s.downcase
|
|
531
546
|
end
|
|
532
547
|
|
|
548
|
+
def fallback_avg_power(activity_id, l2_data)
|
|
549
|
+
records = l2_data || load_l2_from_disk(activity_id)
|
|
550
|
+
return nil unless records.is_a?(Array) && records.any?
|
|
551
|
+
|
|
552
|
+
power_values = records.filter_map { |r| r['power']&.to_f }
|
|
553
|
+
power_values.select! { |p| p > 0 }
|
|
554
|
+
return nil if power_values.empty?
|
|
555
|
+
|
|
556
|
+
(power_values.sum.to_f / power_values.size).round(1)
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
def sport_cadence(summary, type)
|
|
560
|
+
type == 'ride' ? summary['avgBikingCadence'] : summary['avgRunningCadence']
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
def sport_max_cadence(summary, type)
|
|
564
|
+
type == 'ride' ? summary['maxBikingCadence'] : summary['maxRunningCadence']
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
def fallback_avg_cadence(activity_id, l2_data)
|
|
568
|
+
records = l2_data || load_l2_from_disk(activity_id)
|
|
569
|
+
return nil unless records.is_a?(Array) && records.any?
|
|
570
|
+
|
|
571
|
+
cadence_values = records.filter_map { |r| r['cadence']&.to_f }
|
|
572
|
+
cadence_values.select! { |c| c > 0 }
|
|
573
|
+
return nil if cadence_values.empty?
|
|
574
|
+
|
|
575
|
+
(cadence_values.sum.to_f / cadence_values.size).round(1)
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
def fallback_avg_temperature(activity_id, l2_data)
|
|
579
|
+
records = l2_data || load_l2_from_disk(activity_id)
|
|
580
|
+
return nil unless records.is_a?(Array) && records.any?
|
|
581
|
+
|
|
582
|
+
temp_values = records.filter_map { |r| r['temperature']&.to_f }
|
|
583
|
+
return nil if temp_values.empty?
|
|
584
|
+
|
|
585
|
+
(temp_values.sum.to_f / temp_values.size).round(1)
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
def load_l2_from_disk(activity_id)
|
|
589
|
+
l2_path = std_path(activity_id)
|
|
590
|
+
return nil unless File.exist?(l2_path)
|
|
591
|
+
|
|
592
|
+
JSON.parse(File.read(l2_path))
|
|
593
|
+
rescue StandardError
|
|
594
|
+
nil
|
|
595
|
+
end
|
|
596
|
+
|
|
533
597
|
def map_type(activity_type)
|
|
534
598
|
ts = type_str(activity_type)
|
|
535
599
|
return 'other' if ts.empty?
|
data/lib/git_fit/version.rb
CHANGED