git-fit 0.25.0 → 0.25.1

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: 0b5ac295fe113517b660831a4cdaf826ac0905781ccdc591174117e0ec91973b
4
- data.tar.gz: ecafcdedbdb2469570e946bd2b885d2605d92bf43a65fed7668f0074709a9a09
3
+ metadata.gz: e7cac4c94c7c256f2385670c9b386a73edf9d25c54cd0a2b4def3e69e93be273
4
+ data.tar.gz: dcf8048d51b7249ec2dd8097058cf4cbc1b592c19d71bb75eb1d283eaf22f6b1
5
5
  SHA512:
6
- metadata.gz: a588657ec9decf802ec4b2dc68bce7eb9e3c149282fd67e10a8e80a07c69c22cb418aef44513ba62e4de59c153475ba37dbf66da596b330d88d64601ea89f5a1
7
- data.tar.gz: 2f1cdbe55b0f3ddd59406bb3b01c8d43ea09d491ec9a47a3fb316356e35cf6834633a1aa0315e495f5f26e623b214052b6934bd025a3c620d6f869c50d707a1e
6
+ metadata.gz: 2e5dbe464f60f71675e256e639a0515acec48b69e1a92d9b64170b8de22d90a6727a2cc6692f273f8742a5164ae279dc94dacce5ea4d6c30ed71a82311c4f597
7
+ data.tar.gz: f6af70eda9113085f911f2126eef03e112b578994327ef9f825239be36e91ac329eb4f4c03bc49dee21b2445c6a671b1f33e00a81731560972f9ed4a40bdcf25
@@ -44,13 +44,11 @@ module GitFit
44
44
  def normalize_as_of(as_of)
45
45
  return nil if as_of.nil? || as_of.to_s.empty?
46
46
 
47
- valid = as_of.to_s.match?(/\A\d{4}-\d{2}-\d{2}\z/)
48
- unless valid
49
- raise ArgumentError, "Ability: invalid --as-of '#{as_of}' (expected YYYY-MM-DD)\n" \
50
- ' Fix: git fit ability compute --as-of 2025-03-15'
51
- end
52
-
47
+ Date.iso8601(as_of.to_s)
53
48
  as_of
49
+ rescue Date::Error
50
+ raise ArgumentError, "Ability: invalid --as-of '#{as_of}' (expected YYYY-MM-DD)\n" \
51
+ ' Fix: git fit ability compute --as-of 2025-03-15'
54
52
  end
55
53
 
56
54
  def load_rows
@@ -99,21 +97,19 @@ module GitFit
99
97
  # --- fitness layer ---
100
98
 
101
99
  def fitness_snapshots(rows)
102
- base = {}
103
- Snapshot::PERIOD_TYPES.each do |type|
104
- buckets = bucketize(rows, type)
105
- buckets.each { |key, period_rows| base[[type, key]] = fitness_fields(type, key, period_rows) }
106
- end
107
- out = []
108
- Snapshot::PERIOD_TYPES.each do |type|
109
- bucketize(rows, type).keys.sort.each do |key|
100
+ buckets = Snapshot::PERIOD_TYPES.to_h { |type| [type, bucketize(rows, type)] }
101
+ base = buckets.flat_map do |type, per|
102
+ per.map do |key, period_rows|
103
+ [[type, key], fitness_fields(type, key, period_rows)]
104
+ end
105
+ end.to_h
106
+ Snapshot::PERIOD_TYPES.flat_map do |type|
107
+ buckets[type].keys.sort.map do |key|
110
108
  fields = base[[type, key]]
111
- prev_key = Snapshot.previous_key(type, key)
112
- prev = prev_key && base[[type, prev_key]]
113
- out << fields.merge('trend_vs_prev' => prev ? trend_fields(fields, prev) : nil)
109
+ prev = Snapshot.previous_key(type, key)&.then { |pk| base[[type, pk]] }
110
+ fields.merge('trend_vs_prev' => prev ? trend_fields(fields, prev) : nil)
114
111
  end
115
112
  end
116
- out
117
113
  end
118
114
 
119
115
  def bucketize(rows, type)
@@ -84,21 +84,18 @@ module GitFit
84
84
  format('%<year>04d-W%<week>02d', year: date.cwyear, week: date.cweek)
85
85
  end
86
86
 
87
- # Distinct ISO weeks overlapping [start, end].
87
+ # Distinct ISO weeks overlapping [start, end] (cwyear*53+cweek is monotonic;
88
+ # cweek never exceeds 53).
88
89
  def week_count(start_date, end_date)
89
- keys = {}
90
- (start_date..end_date).each { |d| keys[week_key_of_date(d)] = true }
91
- keys.size
90
+ (end_date.cwyear * 53 + end_date.cweek) - (start_date.cwyear * 53 + start_date.cweek) + 1
92
91
  end
93
92
 
94
93
  # Sample-count confidence: <3 low (prompt-excluded), 3-9 medium, >=10 high.
95
94
  def confidence_for(count)
96
95
  if count < 3
97
96
  'low'
98
- elsif count < 10
99
- 'medium'
100
97
  else
101
- 'high'
98
+ count < 10 ? 'medium' : 'high'
102
99
  end
103
100
  end
104
101
 
@@ -29,33 +29,5 @@ module GitFit
29
29
  rescue StandardError => e
30
30
  say_status :error, "Ability compute failed: #{e.message}", :red
31
31
  end
32
-
33
- desc 'show', 'Print a single ability snapshot by period key'
34
- option :period, type: :string, required: true, desc: 'Period key, e.g. 2025-03 / 2025-Q1 / 2025-W12 / 2025 / all'
35
- option :output, type: :string, aliases: '-o', desc: 'ability.json path to read'
36
-
37
- def show
38
- path = options[:output] || git_fit_config.export_config.dig('ability', 'path') || 'site/ability.json'
39
- doc = JSON.parse(File.read(path))
40
- snapshot = find_snapshot(doc, options[:period])
41
- if snapshot
42
- puts JSON.pretty_generate(snapshot)
43
- else
44
- say_status :warn, "Ability: no snapshot for period '#{options[:period]}' in #{path}", :yellow
45
- end
46
- rescue StandardError => e
47
- say_status :error, "Ability show failed: #{e.message}", :red
48
- end
49
-
50
- private
51
-
52
- def find_snapshot(doc, period_key)
53
- candidates = (doc.dig('fitness', 'snapshots') || []) +
54
- (doc['sports'] || {}).values.flat_map { |s| s['snapshots'] || [] }
55
- matches = candidates.select { |s| s['period_key'] == period_key }
56
- return matches.first if matches.one?
57
-
58
- matches # both fitness and sport layers may carry the key — print all
59
- end
60
32
  end
61
33
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GitFit
4
- VERSION = '0.25.0'
4
+ VERSION = '0.25.1'
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.25.0
4
+ version: 0.25.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lax