git-fit 0.14.0 → 0.14.2
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 +21 -1
- data/lib/git_fit/sync/garmin_base.rb +29 -4
- 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: 4aa9561c8dd3c3f589c8c0680f96b779a1d07b415cde954ed4f6787a4a5d3d28
|
|
4
|
+
data.tar.gz: 263aa4c476ab2b8a656d6a8aefcf6c6df7046042a42b362ccaf653a8201a6e0a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cffae3928c4efa2f3a1be2d329fbf74b23808ccd3baa0e6fb9524c029c3b8a261eff0fc1c9f26c742eb6bd2f1b053ba38d9b8a806c20085ddbca54c52c21c689
|
|
7
|
+
data.tar.gz: cef76be1158588e238686c931329613db7bde3a8ffe5453b61d1e3415aa53532ac10a5133c6e831e1b5ac7f3a04f9a194f0f18abfa522d3fcde459885850e93f
|
|
@@ -36,6 +36,8 @@ module GitFit
|
|
|
36
36
|
total_dist = 0.0
|
|
37
37
|
total_time = 0
|
|
38
38
|
total_elev = 0.0
|
|
39
|
+
total_loss = 0.0
|
|
40
|
+
total_steps = 0
|
|
39
41
|
breakdown = Hash.new { |h, k| h[k] = { count: 0, distance_km: 0.0, moving_time_h: 0.0 } }
|
|
40
42
|
|
|
41
43
|
rows.each do |r|
|
|
@@ -43,10 +45,14 @@ module GitFit
|
|
|
43
45
|
d = r[:distance] || 0
|
|
44
46
|
t = r[:moving_time] || 0
|
|
45
47
|
e = r[:elevation_gain] || 0
|
|
48
|
+
l = r[:elevation_loss] || 0
|
|
49
|
+
s = r[:steps] || 0
|
|
46
50
|
|
|
47
51
|
total_dist += d
|
|
48
52
|
total_time += t
|
|
49
53
|
total_elev += e
|
|
54
|
+
total_loss += l
|
|
55
|
+
total_steps += s
|
|
50
56
|
|
|
51
57
|
breakdown[cat][:count] += 1
|
|
52
58
|
breakdown[cat][:distance_km] += d / 1000.0
|
|
@@ -70,6 +76,8 @@ module GitFit
|
|
|
70
76
|
total_distance_km: total_dist / 1000.0,
|
|
71
77
|
total_moving_time_h: total_time / 3600.0,
|
|
72
78
|
total_elevation_gain_m: total_elev,
|
|
79
|
+
total_elevation_loss_m: total_loss,
|
|
80
|
+
total_steps: total_steps,
|
|
73
81
|
avg_cadence: cadences.any? ? (cadences.sum / cadences.size).round(1) : nil,
|
|
74
82
|
avg_power: powers.any? ? (powers.sum / powers.size).round(1) : nil,
|
|
75
83
|
sport_breakdown: breakdown.sort_by { |_, v| -v[:count] }.map do |cat, v|
|
|
@@ -83,6 +91,7 @@ module GitFit
|
|
|
83
91
|
monthly = Hash.new do |h, k|
|
|
84
92
|
h[k] = { count: 0, distance_km: 0.0, moving_time_h: 0.0,
|
|
85
93
|
total_hr: 0.0, hr_count: 0, total_elev: 0.0,
|
|
94
|
+
total_loss: 0.0, total_steps: 0,
|
|
86
95
|
total_cadence: 0.0, cadence_count: 0,
|
|
87
96
|
total_power: 0.0, power_count: 0 }
|
|
88
97
|
end
|
|
@@ -95,11 +104,15 @@ module GitFit
|
|
|
95
104
|
t = r[:moving_time] || 0
|
|
96
105
|
hr = r[:average_heartrate]
|
|
97
106
|
e = r[:elevation_gain] || 0
|
|
107
|
+
l = r[:elevation_loss] || 0
|
|
108
|
+
s = r[:steps] || 0
|
|
98
109
|
|
|
99
110
|
monthly[ym][:count] += 1
|
|
100
111
|
monthly[ym][:distance_km] += d / 1000.0
|
|
101
112
|
monthly[ym][:moving_time_h] += t / 3600.0
|
|
102
113
|
monthly[ym][:total_elev] += e
|
|
114
|
+
monthly[ym][:total_loss] += l
|
|
115
|
+
monthly[ym][:total_steps] += s
|
|
103
116
|
if hr && hr > 0
|
|
104
117
|
monthly[ym][:total_hr] += hr
|
|
105
118
|
monthly[ym][:hr_count] += 1
|
|
@@ -131,6 +144,8 @@ module GitFit
|
|
|
131
144
|
avg_cadence: v[:cadence_count] > 0 ? (v[:total_cadence] / v[:cadence_count]).round(0) : nil,
|
|
132
145
|
avg_power: v[:power_count] > 0 ? (v[:total_power] / v[:power_count]).round(0) : nil,
|
|
133
146
|
elevation_gain_m: v[:total_elev].round(0),
|
|
147
|
+
elevation_loss_m: v[:total_loss].round(0),
|
|
148
|
+
steps: v[:total_steps],
|
|
134
149
|
}
|
|
135
150
|
end
|
|
136
151
|
end
|
|
@@ -145,13 +160,18 @@ module GitFit
|
|
|
145
160
|
by_year.sort.map do |year, acts|
|
|
146
161
|
total_dist = acts.sum { |r| r[:distance] || 0 } / 1000.0
|
|
147
162
|
total_time = acts.sum { |r| r[:moving_time] || 0 }
|
|
163
|
+
total_elev = acts.sum { |r| r[:elevation_gain] || 0 }
|
|
164
|
+
total_loss = acts.sum { |r| r[:elevation_loss] || 0 }
|
|
165
|
+
total_steps = acts.sum { |r| r[:steps] || 0 }
|
|
148
166
|
longest = acts.map { |r| r[:distance] || 0 }.max / 1000.0
|
|
149
167
|
|
|
150
168
|
streak = calculate_streak(acts)
|
|
151
169
|
|
|
152
170
|
{ year: year, count: acts.size, distance_km: total_dist.round(1),
|
|
153
171
|
moving_time_h: (total_time / 3600.0).round(1),
|
|
154
|
-
longest_km: longest.round(1), streak: streak
|
|
172
|
+
longest_km: longest.round(1), streak: streak,
|
|
173
|
+
elevation_gain_m: total_elev.round(0), elevation_loss_m: total_loss.round(0),
|
|
174
|
+
steps: total_steps }
|
|
155
175
|
end
|
|
156
176
|
end
|
|
157
177
|
|
|
@@ -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,18 @@ 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
|
+
|
|
490
495
|
{
|
|
491
496
|
run_id: "#{source_prefix}_#{activity_id}",
|
|
492
497
|
name: detail['activityName'] || 'Garmin Activity',
|
|
@@ -503,8 +508,8 @@ module GitFit
|
|
|
503
508
|
max_heartrate: summary['maxHR']&.to_f,
|
|
504
509
|
average_cadence: summary['avgCadence']&.to_f,
|
|
505
510
|
max_cadence: summary['maxCadence']&.to_f,
|
|
506
|
-
average_power:
|
|
507
|
-
max_power:
|
|
511
|
+
average_power: average_power,
|
|
512
|
+
max_power: max_power,
|
|
508
513
|
calories: summary['calories']&.to_i,
|
|
509
514
|
average_temperature: summary['avgTemperature']&.to_f,
|
|
510
515
|
average_speed: summary['averageSpeed']&.to_f,
|
|
@@ -530,6 +535,26 @@ module GitFit
|
|
|
530
535
|
val.is_a?(Hash) ? (val['typeKey'] || '').downcase : val.to_s.downcase
|
|
531
536
|
end
|
|
532
537
|
|
|
538
|
+
def fallback_avg_power(activity_id, l2_data)
|
|
539
|
+
records = l2_data || load_l2_from_disk(activity_id)
|
|
540
|
+
return nil unless records.is_a?(Array) && records.any?
|
|
541
|
+
|
|
542
|
+
power_values = records.filter_map { |r| r['power']&.to_f }
|
|
543
|
+
power_values.select! { |p| p > 0 }
|
|
544
|
+
return nil if power_values.empty?
|
|
545
|
+
|
|
546
|
+
(power_values.sum.to_f / power_values.size).round(1)
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
def load_l2_from_disk(activity_id)
|
|
550
|
+
l2_path = std_path(activity_id)
|
|
551
|
+
return nil unless File.exist?(l2_path)
|
|
552
|
+
|
|
553
|
+
JSON.parse(File.read(l2_path))
|
|
554
|
+
rescue StandardError
|
|
555
|
+
nil
|
|
556
|
+
end
|
|
557
|
+
|
|
533
558
|
def map_type(activity_type)
|
|
534
559
|
ts = type_str(activity_type)
|
|
535
560
|
return 'other' if ts.empty?
|
data/lib/git_fit/version.rb
CHANGED