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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5d4addd08029f44a569bf1e7caebc7f890f6ef31a2acc4a0a4de7c9ff74dff4c
4
- data.tar.gz: 3eedd8d3727f7e9bea165f347fcd30ac430b37518a1c3b36ce7a91d14d2dc15c
3
+ metadata.gz: 5922b46e00a21d66f591fb8d0e43b9a5e35dbb2fef4f5118aa7c689e62fa0118
4
+ data.tar.gz: 103cb559cef56006024fb838982410a47c49485c9a104ee6bd29a33cc05179f2
5
5
  SHA512:
6
- metadata.gz: 416c3f458713d03a648d723d05b48af609f5165d9d09ae3f22646089825a2fc058974c34210f5553fe9e28ee52f108932d20a69b1bf8b8aee3fa682e45cc18ad
7
- data.tar.gz: 6fce4b173ae5d10000a2b3e0035cb81e6c2c1c656357f4373d5532a51977acdae5610d8ecba42888fddf3f846094b6653c96ebdc438e72b23422300ec2e7592e
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: summary['avgCadence']&.to_f,
505
- max_cadence: summary['maxCadence']&.to_f,
506
- average_power: summary['avgPower']&.to_f,
507
- max_power: summary['maxPower']&.to_f,
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: summary['avgTemperature']&.to_f,
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?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GitFit
4
- VERSION = '0.14.1'
4
+ VERSION = '0.14.3'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git-fit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.1
4
+ version: 0.14.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lax