calcpace 1.9.4 → 1.9.5
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/CHANGELOG.md +21 -1
- data/Gemfile.lock +1 -1
- data/README.md +39 -1
- data/lib/calcpace/age_grading.rb +198 -0
- data/lib/calcpace/data/wma_2023_open_standards.yml +30 -0
- data/lib/calcpace/data/wma_2023_road.yml +16 -0
- data/lib/calcpace/version.rb +1 -1
- data/lib/calcpace.rb +2 -0
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: db7effb21592146022bf3df34ecdb8a8688fb4d79d618c43c5b99a9912ac967a
|
|
4
|
+
data.tar.gz: 2e009f5c0fa7856f65c3f8a447fa9a4de2e51e5057bf1606810d3bc38e3d9a02
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 129467189d43ea17a4ac31f371e813b08a12d7d0482a3f4717414087db3ffa0f5134478e5134cb512c5c6f242f7eab57b2172bf40b61107ed7a204f2043bf78e
|
|
7
|
+
data.tar.gz: c716d04864bdf92ab64259c938a05d1cce552a9c35738f1b7b76848b4c32d36119ed71c9ddcd8c0725b4002c660eee8cb51e5a020fdf9ac7d29d062ea3801002
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [1.9.5] - 2026-05-02
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Age-grading module (`AgeGrading`) with:
|
|
14
|
+
- `age_grade(distance_km, time, age:, sex:)`
|
|
15
|
+
- `age_grade_percent(distance_km, time, age:, sex:)`
|
|
16
|
+
- `age_grade_label(percent)`
|
|
17
|
+
- Versioned data file loader using YAML + `YAML.safe_load` from
|
|
18
|
+
`lib/calcpace/data/wma_2023_road.yml`
|
|
19
|
+
- Interpolation support for in-between ages (e.g., 57 between 55 and 60)
|
|
20
|
+
- Initial road-race support: 5K, 10K, half marathon, marathon
|
|
21
|
+
- WMA 2023 one-year age factors integrated for `M`/`F` road distances in meters
|
|
22
|
+
- Source: World Masters Athletics (WMA) competition rules documents
|
|
23
|
+
https://world-masters-athletics.org/documents/competition-rules/
|
|
24
|
+
- Race-style age-factored time rounding up to the next hundredth
|
|
25
|
+
- Test suite for validation, interpolation, and error handling
|
|
26
|
+
|
|
8
27
|
## [1.9.4] - 2026-04-18
|
|
9
28
|
|
|
10
29
|
### Added
|
|
@@ -145,5 +164,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
145
164
|
|
|
146
165
|
See git history for changes in earlier versions.
|
|
147
166
|
|
|
148
|
-
[Unreleased]: https://github.com/0jonjo/calcpace/compare/v1.
|
|
167
|
+
[Unreleased]: https://github.com/0jonjo/calcpace/compare/v1.9.5...HEAD
|
|
168
|
+
[1.9.5]: https://github.com/0jonjo/calcpace/compare/v1.9.4...v1.9.5
|
|
149
169
|
[1.6.0]: https://github.com/0jonjo/calcpace/releases/tag/v1.6.0
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Calcpace [](https://badge.fury.io/rb/calcpace)
|
|
2
2
|
|
|
3
3
|
A Ruby gem for running and cycling calculations: pace, time, distance, unit conversions, race predictions, GPS track analysis, and VO2max estimation.
|
|
4
4
|
|
|
@@ -124,6 +124,44 @@ calc.track_splits(points, 1.0) # => [{ km: 1, elapsed: 312, pace: "05:12" }, ...
|
|
|
124
124
|
|
|
125
125
|
---
|
|
126
126
|
|
|
127
|
+
### Age Grading (Road Races)
|
|
128
|
+
|
|
129
|
+
Age grading compares race results across different ages and sexes by using
|
|
130
|
+
age factors and open standards.
|
|
131
|
+
|
|
132
|
+
```ruby
|
|
133
|
+
result = calc.age_grade(10.0, '00:45:00', age: 55, sex: :male)
|
|
134
|
+
# => {
|
|
135
|
+
# age_grade_percent: 64.6,
|
|
136
|
+
# category: "Local Class",
|
|
137
|
+
# age_graded_time_seconds: 2376.0,
|
|
138
|
+
# age_graded_time_clock: "00:39:36",
|
|
139
|
+
# open_standard_seconds: 1571.0,
|
|
140
|
+
# open_standard_clock: "00:26:11",
|
|
141
|
+
# factor: 0.88,
|
|
142
|
+
# table_version: "WMA_2023_ONE_YEAR_FACTORS_V1"
|
|
143
|
+
# }
|
|
144
|
+
|
|
145
|
+
calc.age_grade_percent(5.0, '00:22:30', age: 40, sex: :female) # => 74.1
|
|
146
|
+
calc.age_grade_label(74.1) # => "Regional Class"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Supported distances: 5K, 10K, half marathon, marathon.
|
|
150
|
+
|
|
151
|
+
Age factors are based on WMA 2023 one-year age grading tables:
|
|
152
|
+
https://world-masters-athletics.org/documents/competition-rules/
|
|
153
|
+
|
|
154
|
+
Open standards used in `open_standard_seconds` / `open_standard_clock` are loaded
|
|
155
|
+
from the bundled WMA 2023 open standards dataset
|
|
156
|
+
(`lib/calcpace/data/wma_2023_open_standards.yml`).
|
|
157
|
+
|
|
158
|
+
Field meanings:
|
|
159
|
+
- `age_graded_time_clock`: your result after applying the WMA age factor (normalized performance time).
|
|
160
|
+
- `open_standard_clock`: the open standard reference time used to compute the percentage for that distance/sex.
|
|
161
|
+
- `age_grade_percent`: `(open_standard_seconds / age_graded_time_seconds) * 100`.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
127
165
|
### VO2max Estimation
|
|
128
166
|
|
|
129
167
|
Estimate aerobic fitness from a race result using the **Daniels & Gilbert formula** (1979):
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
|
|
5
|
+
# Module for age-grading race performances with a versioned table
|
|
6
|
+
#
|
|
7
|
+
# Age grading allows fairer comparison across ages by applying an age factor
|
|
8
|
+
# to the raw performance time.
|
|
9
|
+
#
|
|
10
|
+
# Current scope:
|
|
11
|
+
# - Common road distances: 5K, 10K, half marathon, marathon
|
|
12
|
+
# - Sex: male/female
|
|
13
|
+
# - Age: 18+
|
|
14
|
+
# - Data file is versioned and replaceable (`lib/calcpace/data/wma_2023_road.yml`)
|
|
15
|
+
#
|
|
16
|
+
# Returned values include:
|
|
17
|
+
# - age grade percentage
|
|
18
|
+
# - age-graded time
|
|
19
|
+
# - open standard time for the selected distance/sex
|
|
20
|
+
# - performance category
|
|
21
|
+
# rubocop:disable Metrics/ModuleLength
|
|
22
|
+
module AgeGrading
|
|
23
|
+
DATA_PATH = File.expand_path('data/wma_2023_road.yml', __dir__).freeze
|
|
24
|
+
OPEN_STANDARDS_DATA_PATH = File.expand_path('data/wma_2023_open_standards.yml', __dir__).freeze
|
|
25
|
+
WMA_DATA = YAML.safe_load_file(DATA_PATH, permitted_classes: [],
|
|
26
|
+
aliases: false).freeze
|
|
27
|
+
OPEN_STANDARDS_DATA = YAML.safe_load_file(OPEN_STANDARDS_DATA_PATH, permitted_classes: [],
|
|
28
|
+
aliases: false).freeze
|
|
29
|
+
TABLE_VERSION = OPEN_STANDARDS_DATA.fetch('meta').fetch('table_version').freeze
|
|
30
|
+
|
|
31
|
+
AGE_GRADE_LABELS = OPEN_STANDARDS_DATA.fetch('age_grade_classifications').map do |entry|
|
|
32
|
+
{ min: entry.fetch('min').to_f, label: entry.fetch('label') }
|
|
33
|
+
end.freeze
|
|
34
|
+
|
|
35
|
+
DISTANCE_TO_METERS = {
|
|
36
|
+
5.0 => '5000',
|
|
37
|
+
10.0 => '10000',
|
|
38
|
+
21.0975 => '21097',
|
|
39
|
+
42.195 => '42195'
|
|
40
|
+
}.freeze
|
|
41
|
+
RACE_TO_METERS = {
|
|
42
|
+
'5k' => '5000',
|
|
43
|
+
'10k' => '10000',
|
|
44
|
+
'half_marathon' => '21097',
|
|
45
|
+
'marathon' => '42195'
|
|
46
|
+
}.freeze
|
|
47
|
+
|
|
48
|
+
SUPPORTED_DISTANCES_KM = DISTANCE_TO_METERS.keys.freeze
|
|
49
|
+
|
|
50
|
+
# Returns a full age-grading report for a race performance
|
|
51
|
+
#
|
|
52
|
+
# @param distance_km [Numeric, String, Symbol] race distance in kilometres
|
|
53
|
+
# (5.0, 10.0, 21.0975, 42.195) or race key (:5k, :10k, :half_marathon, :marathon)
|
|
54
|
+
# @param time [String, Numeric] performance time as HH:MM:SS / MM:SS, or total seconds
|
|
55
|
+
# @param age [Integer] athlete age (must be >= 18)
|
|
56
|
+
# @param sex [String, Symbol] male or female
|
|
57
|
+
# @return [Hash] age-grading result details
|
|
58
|
+
def age_grade(distance_km, time, age:, sex:)
|
|
59
|
+
distance_m = normalize_distance(distance_km)
|
|
60
|
+
seconds = parse_time_seconds(time)
|
|
61
|
+
age_value = normalize_age(age)
|
|
62
|
+
sex_value = normalize_sex(sex)
|
|
63
|
+
|
|
64
|
+
check_positive(seconds, 'Time')
|
|
65
|
+
|
|
66
|
+
factor = interpolated_factor(sex_value, age_value, distance_m)
|
|
67
|
+
age_graded_time = round_up_hundredth(seconds * factor)
|
|
68
|
+
open_standard = open_standard_seconds(sex_value, distance_m)
|
|
69
|
+
grade_percent = (open_standard / age_graded_time) * 100.0
|
|
70
|
+
rounded_percent = grade_percent.round(1)
|
|
71
|
+
|
|
72
|
+
{
|
|
73
|
+
age_grade_percent: rounded_percent,
|
|
74
|
+
category: age_grade_label(rounded_percent),
|
|
75
|
+
age_graded_time_seconds: age_graded_time,
|
|
76
|
+
age_graded_time_clock: convert_to_clocktime(age_graded_time),
|
|
77
|
+
open_standard_seconds: open_standard,
|
|
78
|
+
open_standard_clock: convert_to_clocktime(open_standard),
|
|
79
|
+
factor: factor.round(4),
|
|
80
|
+
table_version: TABLE_VERSION
|
|
81
|
+
}
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Returns only the age-grade percentage
|
|
85
|
+
#
|
|
86
|
+
# @param distance_km [Numeric] race distance in kilometres
|
|
87
|
+
# @param time [String, Numeric] performance time
|
|
88
|
+
# @param age [Integer] athlete age
|
|
89
|
+
# @param sex [String, Symbol] male or female
|
|
90
|
+
# @return [Float] age-grade percentage
|
|
91
|
+
def age_grade_percent(distance_km, time, age:, sex:)
|
|
92
|
+
age_grade(distance_km, time, age: age, sex: sex)[:age_grade_percent]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Returns a descriptive label for an age-grade percentage
|
|
96
|
+
#
|
|
97
|
+
# @param percent [Numeric] age-grade percentage
|
|
98
|
+
# @return [String] category label
|
|
99
|
+
def age_grade_label(percent)
|
|
100
|
+
percent_value = begin
|
|
101
|
+
Float(percent)
|
|
102
|
+
rescue ArgumentError, TypeError
|
|
103
|
+
raise ArgumentError, 'Age-grade percent must be a numeric value greater than or equal to 0'
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
raise ArgumentError, 'Age-grade percent must be greater than or equal to 0' if percent_value.negative?
|
|
107
|
+
|
|
108
|
+
AGE_GRADE_LABELS.find { |entry| percent_value >= entry[:min] }[:label]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
|
|
113
|
+
def normalize_distance(distance_km)
|
|
114
|
+
if distance_km.is_a?(String) || distance_km.is_a?(Symbol)
|
|
115
|
+
key = distance_km.to_s.strip.downcase
|
|
116
|
+
return RACE_TO_METERS.fetch(key) if RACE_TO_METERS.key?(key)
|
|
117
|
+
|
|
118
|
+
raise ArgumentError,
|
|
119
|
+
"Unsupported race '#{distance_km}'. Supported: #{RACE_TO_METERS.keys.join(', ')}"
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
distance = distance_km.to_f
|
|
123
|
+
check_positive(distance, 'Distance')
|
|
124
|
+
|
|
125
|
+
match = SUPPORTED_DISTANCES_KM.find { |value| (distance - value).abs <= 0.001 }
|
|
126
|
+
return DISTANCE_TO_METERS.fetch(match) if match
|
|
127
|
+
|
|
128
|
+
raise ArgumentError,
|
|
129
|
+
"Unsupported distance #{distance_km}km. Supported: #{SUPPORTED_DISTANCES_KM.join(', ')}"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def parse_time_seconds(time)
|
|
133
|
+
return time.to_f if time.is_a?(Numeric)
|
|
134
|
+
|
|
135
|
+
check_time(time.to_s)
|
|
136
|
+
convert_to_seconds(time.to_s)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def normalize_age(age)
|
|
140
|
+
age_value = Integer(age)
|
|
141
|
+
rescue ArgumentError, TypeError
|
|
142
|
+
raise ArgumentError, 'Age must be an integer greater than or equal to 18'
|
|
143
|
+
else
|
|
144
|
+
raise ArgumentError, 'Age must be at least 18' if age_value < 18
|
|
145
|
+
|
|
146
|
+
age_value
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def normalize_sex(sex)
|
|
150
|
+
normalized = sex.to_s.strip.downcase.to_sym
|
|
151
|
+
return normalized if %i[male female].include?(normalized)
|
|
152
|
+
|
|
153
|
+
raise ArgumentError, "Sex must be 'male' or 'female'"
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def interpolated_factor(sex, age, distance_m)
|
|
157
|
+
table = factor_table(sex, distance_m)
|
|
158
|
+
ages = table.keys.map(&:to_i).sort
|
|
159
|
+
|
|
160
|
+
return table.fetch(ages.first).to_f if age <= ages.first
|
|
161
|
+
return table.fetch(ages.last).to_f if age >= ages.last
|
|
162
|
+
|
|
163
|
+
lower_age, upper_age = neighboring_ages(ages, age)
|
|
164
|
+
return table.fetch(lower_age).to_f if lower_age == upper_age
|
|
165
|
+
|
|
166
|
+
interpolated_value(table, lower_age, upper_age, age)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def factor_table(sex, distance_m)
|
|
170
|
+
WMA_DATA.fetch(sex_key(sex)).fetch(distance_m)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def sex_key(sex)
|
|
174
|
+
sex == :male ? 'M' : 'F'
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def open_standard_seconds(sex, distance_m)
|
|
178
|
+
OPEN_STANDARDS_DATA.fetch('open_standards_seconds').fetch(sex_key(sex)).fetch(distance_m).to_f
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def round_up_hundredth(value)
|
|
182
|
+
(value * 100.0).ceil / 100.0
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def neighboring_ages(ages, age)
|
|
186
|
+
lower_age = ages.select { |value| value <= age }.max
|
|
187
|
+
upper_age = ages.select { |value| value >= age }.min
|
|
188
|
+
[lower_age, upper_age]
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def interpolated_value(table, lower_age, upper_age, age)
|
|
192
|
+
lower_factor = table.fetch(lower_age).to_f
|
|
193
|
+
upper_factor = table.fetch(upper_age).to_f
|
|
194
|
+
ratio = (age - lower_age).to_f / (upper_age - lower_age)
|
|
195
|
+
lower_factor + ((upper_factor - lower_factor) * ratio)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
# rubocop:enable Metrics/ModuleLength
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
meta:
|
|
2
|
+
source: "WMA/Masters Rankings age grading tables (2023)"
|
|
3
|
+
url: "https://howardgrubb.co.uk/athletics/wmatnf23.html"
|
|
4
|
+
table_version: "WMA_2023_ONE_YEAR_FACTORS_V1"
|
|
5
|
+
|
|
6
|
+
age_grade_classifications:
|
|
7
|
+
- min: 100.0
|
|
8
|
+
label: "Approximate World Record Level"
|
|
9
|
+
- min: 90.0
|
|
10
|
+
label: "World Class"
|
|
11
|
+
- min: 80.0
|
|
12
|
+
label: "National Class"
|
|
13
|
+
- min: 70.0
|
|
14
|
+
label: "Regional Class"
|
|
15
|
+
- min: 60.0
|
|
16
|
+
label: "Local Class"
|
|
17
|
+
- min: 0.0
|
|
18
|
+
label: "Developing"
|
|
19
|
+
|
|
20
|
+
open_standards_seconds:
|
|
21
|
+
M:
|
|
22
|
+
"5000": 755.0
|
|
23
|
+
"10000": 1571.0
|
|
24
|
+
"21097": 3451.0
|
|
25
|
+
"42195": 7269.0
|
|
26
|
+
F:
|
|
27
|
+
"5000": 846.0
|
|
28
|
+
"10000": 1741.0
|
|
29
|
+
"21097": 3772.0
|
|
30
|
+
"42195": 8044.0
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
F:
|
|
3
|
+
"1500": { 30: 1.0000, 31: 1.0000, 32: 1.0000, 33: 0.9960, 34: 0.9886, 35: 0.9812, 36: 0.9738, 37: 0.9664, 38: 0.9590, 39: 0.9515, 40: 0.9441, 41: 0.9367, 42: 0.9293, 43: 0.9218, 44: 0.9144, 45: 0.9069, 46: 0.8995, 47: 0.8921, 48: 0.8846, 49: 0.8772, 50: 0.8697, 51: 0.8623, 52: 0.8548, 53: 0.8473, 54: 0.8399, 55: 0.8324, 56: 0.8249, 57: 0.8175, 58: 0.8100, 59: 0.8025, 60: 0.7951, 61: 0.7876, 62: 0.7801, 63: 0.7726, 64: 0.7651, 65: 0.7576, 66: 0.7501, 67: 0.7427, 68: 0.7352, 69: 0.7277, 70: 0.7202, 71: 0.7127, 72: 0.7052, 73: 0.6976, 74: 0.6897, 75: 0.6812, 76: 0.6722, 77: 0.6628, 78: 0.6529, 79: 0.6425, 80: 0.6316, 81: 0.6202, 82: 0.6083, 83: 0.5960, 84: 0.5832, 85: 0.5698, 86: 0.5561, 87: 0.5418, 88: 0.5270, 89: 0.5118, 90: 0.4960, 91: 0.4798, 92: 0.4631, 93: 0.4460, 94: 0.4283, 95: 0.4102, 96: 0.3915, 97: 0.3724, 98: 0.3528, 99: 0.3327, 100: 0.3122, 101: 0.2911, 102: 0.2696, 103: 0.2476, 104: 0.2251, 105: 0.2021, 106: 0.1787, 107: 0.1547, 108: 0.1303, 109: 0.1054, 110: 0.0800 }
|
|
4
|
+
"3000": { 30: 1.0000, 31: 1.0000, 32: 1.0000, 33: 1.0000, 34: 1.0000, 35: 1.0000, 36: 1.0000, 37: 1.0000, 38: 0.9930, 39: 0.9849, 40: 0.9767, 41: 0.9685, 42: 0.9603, 43: 0.9521, 44: 0.9438, 45: 0.9355, 46: 0.9271, 47: 0.9188, 48: 0.9104, 49: 0.9019, 50: 0.8935, 51: 0.8850, 52: 0.8765, 53: 0.8680, 54: 0.8594, 55: 0.8509, 56: 0.8423, 57: 0.8336, 58: 0.8250, 59: 0.8163, 60: 0.8076, 61: 0.7989, 62: 0.7901, 63: 0.7813, 64: 0.7725, 65: 0.7637, 66: 0.7549, 67: 0.7460, 68: 0.7371, 69: 0.7282, 70: 0.7193, 71: 0.7103, 72: 0.7013, 73: 0.6923, 74: 0.6833, 75: 0.6743, 76: 0.6652, 77: 0.6561, 78: 0.6470, 79: 0.6379, 80: 0.6288, 81: 0.6196, 82: 0.6098, 83: 0.5993, 84: 0.5881, 85: 0.5762, 86: 0.5637, 87: 0.5505, 88: 0.5366, 89: 0.5220, 90: 0.5067, 91: 0.4908, 92: 0.4742, 93: 0.4569, 94: 0.4390, 95: 0.4204, 96: 0.4010, 97: 0.3811, 98: 0.3604, 99: 0.3391, 100: 0.3171, 101: 0.2944, 102: 0.2711, 103: 0.2470, 104: 0.2223, 105: 0.1970, 106: 0.1709, 107: 0.1442, 108: 0.1168, 109: 0.0887, 110: 0.0600 }
|
|
5
|
+
"5000": { 30: 1.0000, 31: 1.0000, 32: 1.0000, 33: 1.0000, 34: 1.0000, 35: 0.9974, 36: 0.9904, 37: 0.9833, 38: 0.9761, 39: 0.9689, 40: 0.9615, 41: 0.9541, 42: 0.9467, 43: 0.9392, 44: 0.9316, 45: 0.9239, 46: 0.9162, 47: 0.9084, 48: 0.9006, 49: 0.8926, 50: 0.8847, 51: 0.8766, 52: 0.8685, 53: 0.8603, 54: 0.8521, 55: 0.8438, 56: 0.8355, 57: 0.8271, 58: 0.8186, 59: 0.8101, 60: 0.8015, 61: 0.7929, 62: 0.7842, 63: 0.7755, 64: 0.7667, 65: 0.7578, 66: 0.7489, 67: 0.7399, 68: 0.7309, 69: 0.7219, 70: 0.7128, 71: 0.7036, 72: 0.6944, 73: 0.6851, 74: 0.6758, 75: 0.6665, 76: 0.6571, 77: 0.6476, 78: 0.6381, 79: 0.6286, 80: 0.6190, 81: 0.6094, 82: 0.5997, 83: 0.5893, 84: 0.5783, 85: 0.5665, 86: 0.5541, 87: 0.5410, 88: 0.5272, 89: 0.5127, 90: 0.4975, 91: 0.4816, 92: 0.4650, 93: 0.4478, 94: 0.4299, 95: 0.4112, 96: 0.3919, 97: 0.3719, 98: 0.3513, 99: 0.3299, 100: 0.3079, 101: 0.2852, 102: 0.2618, 103: 0.2377, 104: 0.2129, 105: 0.1875, 106: 0.1613, 107: 0.1345, 108: 0.1070, 109: 0.0788, 110: 0.0500 }
|
|
6
|
+
"10000": { 30: 1.0000, 31: 1.0000, 32: 1.0000, 33: 1.0000, 34: 0.9937, 35: 0.9869, 36: 0.9801, 37: 0.9731, 38: 0.9661, 39: 0.9591, 40: 0.9519, 41: 0.9447, 42: 0.9374, 43: 0.9301, 44: 0.9227, 45: 0.9152, 46: 0.9077, 47: 0.9001, 48: 0.8925, 49: 0.8848, 50: 0.8770, 51: 0.8692, 52: 0.8613, 53: 0.8533, 54: 0.8453, 55: 0.8373, 56: 0.8291, 57: 0.8210, 58: 0.8127, 59: 0.8045, 60: 0.7961, 61: 0.7877, 62: 0.7793, 63: 0.7708, 64: 0.7623, 65: 0.7537, 66: 0.7450, 67: 0.7363, 68: 0.7276, 69: 0.7188, 70: 0.7100, 71: 0.7011, 72: 0.6922, 73: 0.6832, 74: 0.6742, 75: 0.6651, 76: 0.6560, 77: 0.6468, 78: 0.6376, 79: 0.6284, 80: 0.6191, 81: 0.6098, 82: 0.6004, 83: 0.5903, 84: 0.5795, 85: 0.5679, 86: 0.5556, 87: 0.5425, 88: 0.5287, 89: 0.5142, 90: 0.4990, 91: 0.4830, 92: 0.4662, 93: 0.4488, 94: 0.4306, 95: 0.4116, 96: 0.3920, 97: 0.3716, 98: 0.3505, 99: 0.3286, 100: 0.3060, 101: 0.2827, 102: 0.2586, 103: 0.2339, 104: 0.2084, 105: 0.1821, 106: 0.1551, 107: 0.1275, 108: 0.0990, 109: 0.0699, 110: 0.0400 }
|
|
7
|
+
"21097": { 30: 1.0000, 31: 1.0000, 32: 1.0000, 33: 0.9935, 34: 0.9869, 35: 0.9802, 36: 0.9734, 37: 0.9666, 38: 0.9596, 39: 0.9526, 40: 0.9455, 41: 0.9384, 42: 0.9311, 43: 0.9238, 44: 0.9164, 45: 0.9090, 46: 0.9014, 47: 0.8938, 48: 0.8862, 49: 0.8784, 50: 0.8706, 51: 0.8627, 52: 0.8548, 53: 0.8468, 54: 0.8387, 55: 0.8306, 56: 0.8224, 57: 0.8141, 58: 0.8058, 59: 0.7974, 60: 0.7889, 61: 0.7804, 62: 0.7718, 63: 0.7632, 64: 0.7545, 65: 0.7457, 66: 0.7369, 67: 0.7280, 68: 0.7191, 69: 0.7101, 70: 0.7011, 71: 0.6920, 72: 0.6828, 73: 0.6736, 74: 0.6644, 75: 0.6551, 76: 0.6457, 77: 0.6363, 78: 0.6268, 79: 0.6173, 80: 0.6078, 81: 0.5982, 82: 0.5879, 83: 0.5769, 84: 0.5653, 85: 0.5530, 86: 0.5401, 87: 0.5265, 88: 0.5122, 89: 0.4972, 90: 0.4816, 91: 0.4653, 92: 0.4484, 93: 0.4307, 94: 0.4125, 95: 0.3935, 96: 0.3739, 97: 0.3536, 98: 0.3327, 99: 0.3111, 100: 0.2888, 101: 0.2659, 102: 0.2424, 103: 0.2181, 104: 0.1932, 105: 0.1677, 106: 0.1414, 107: 0.1146, 108: 0.0870, 109: 0.0588, 110: 0.0300 }
|
|
8
|
+
"42195": { 30: 1.0000, 31: 1.0000, 32: 1.0000, 33: 1.0000, 34: 1.0000, 35: 0.9982, 36: 0.9918, 37: 0.9854, 38: 0.9789, 39: 0.9722, 40: 0.9654, 41: 0.9585, 42: 0.9515, 43: 0.9444, 44: 0.9371, 45: 0.9298, 46: 0.9223, 47: 0.9148, 48: 0.9071, 49: 0.8993, 50: 0.8915, 51: 0.8835, 52: 0.8754, 53: 0.8672, 54: 0.8590, 55: 0.8506, 56: 0.8421, 57: 0.8336, 58: 0.8249, 59: 0.8162, 60: 0.8073, 61: 0.7984, 62: 0.7894, 63: 0.7803, 64: 0.7711, 65: 0.7618, 66: 0.7524, 67: 0.7430, 68: 0.7335, 69: 0.7239, 70: 0.7142, 71: 0.7044, 72: 0.6946, 73: 0.6846, 74: 0.6746, 75: 0.6646, 76: 0.6544, 77: 0.6442, 78: 0.6339, 79: 0.6235, 80: 0.6131, 81: 0.6025, 82: 0.5914, 83: 0.5795, 84: 0.5670, 85: 0.5538, 86: 0.5400, 87: 0.5254, 88: 0.5103, 89: 0.4944, 90: 0.4779, 91: 0.4608, 92: 0.4429, 93: 0.4245, 94: 0.4053, 95: 0.3855, 96: 0.3651, 97: 0.3439, 98: 0.3222, 99: 0.2997, 100: 0.2767, 101: 0.2529, 102: 0.2285, 103: 0.2035, 104: 0.1778, 105: 0.1515, 106: 0.1245, 107: 0.0968, 108: 0.0685, 109: 0.0396, 110: 0.0100 }
|
|
9
|
+
|
|
10
|
+
M:
|
|
11
|
+
"1500": { 30: 1.0000, 31: 1.0000, 32: 1.0000, 33: 0.9973, 34: 0.9911, 35: 0.9849, 36: 0.9786, 37: 0.9723, 38: 0.9660, 39: 0.9596, 40: 0.9532, 41: 0.9468, 42: 0.9403, 43: 0.9338, 44: 0.9272, 45: 0.9206, 46: 0.9140, 47: 0.9073, 48: 0.9006, 49: 0.8939, 50: 0.8871, 51: 0.8803, 52: 0.8734, 53: 0.8666, 54: 0.8596, 55: 0.8527, 56: 0.8457, 57: 0.8387, 58: 0.8316, 59: 0.8246, 60: 0.8174, 61: 0.8103, 62: 0.8031, 63: 0.7959, 64: 0.7887, 65: 0.7814, 66: 0.7741, 67: 0.7668, 68: 0.7594, 69: 0.7520, 70: 0.7446, 71: 0.7371, 72: 0.7296, 73: 0.7221, 74: 0.7146, 75: 0.7070, 76: 0.6994, 77: 0.6918, 78: 0.6835, 79: 0.6746, 80: 0.6651, 81: 0.6549, 82: 0.6440, 83: 0.6325, 84: 0.6204, 85: 0.6076, 86: 0.5942, 87: 0.5801, 88: 0.5654, 89: 0.5501, 90: 0.5341, 91: 0.5175, 92: 0.5002, 93: 0.4823, 94: 0.4638, 95: 0.4446, 96: 0.4248, 97: 0.4043, 98: 0.3832, 99: 0.3614, 100: 0.3390, 101: 0.3160, 102: 0.2923, 103: 0.2680, 104: 0.2431, 105: 0.2175, 106: 0.1913, 107: 0.1644, 108: 0.1369, 109: 0.1088, 110: 0.0800 }
|
|
12
|
+
"3000": { 30: 1.0000, 31: 1.0000, 32: 1.0000, 33: 1.0000, 34: 1.0000, 35: 0.9993, 36: 0.9922, 37: 0.9851, 38: 0.9780, 39: 0.9708, 40: 0.9636, 41: 0.9564, 42: 0.9491, 43: 0.9419, 44: 0.9345, 45: 0.9272, 46: 0.9199, 47: 0.9125, 48: 0.9051, 49: 0.8976, 50: 0.8901, 51: 0.8827, 52: 0.8751, 53: 0.8676, 54: 0.8600, 55: 0.8524, 56: 0.8448, 57: 0.8372, 58: 0.8295, 59: 0.8218, 60: 0.8141, 61: 0.8064, 62: 0.7986, 63: 0.7908, 64: 0.7830, 65: 0.7752, 66: 0.7674, 67: 0.7595, 68: 0.7516, 69: 0.7437, 70: 0.7357, 71: 0.7278, 72: 0.7198, 73: 0.7118, 74: 0.7038, 75: 0.6957, 76: 0.6877, 77: 0.6796, 78: 0.6715, 79: 0.6634, 80: 0.6552, 81: 0.6464, 82: 0.6367, 83: 0.6263, 84: 0.6151, 85: 0.6032, 86: 0.5905, 87: 0.5771, 88: 0.5629, 89: 0.5480, 90: 0.5323, 91: 0.5158, 92: 0.4986, 93: 0.4806, 94: 0.4619, 95: 0.4425, 96: 0.4222, 97: 0.4013, 98: 0.3795, 99: 0.3570, 100: 0.3338, 101: 0.3098, 102: 0.2851, 103: 0.2596, 104: 0.2333, 105: 0.2063, 106: 0.1785, 107: 0.1500, 108: 0.1208, 109: 0.0908, 110: 0.0600 }
|
|
13
|
+
"5000": { 30: 1.0000, 31: 1.0000, 32: 1.0000, 33: 1.0000, 34: 1.0000, 35: 1.0000, 36: 1.0000, 37: 0.9943, 38: 0.9863, 39: 0.9782, 40: 0.9701, 41: 0.9621, 42: 0.9540, 43: 0.9460, 44: 0.9380, 45: 0.9299, 46: 0.9219, 47: 0.9139, 48: 0.9059, 49: 0.8980, 50: 0.8900, 51: 0.8820, 52: 0.8740, 53: 0.8661, 54: 0.8582, 55: 0.8502, 56: 0.8423, 57: 0.8344, 58: 0.8265, 59: 0.8185, 60: 0.8106, 61: 0.8028, 62: 0.7949, 63: 0.7870, 64: 0.7791, 65: 0.7713, 66: 0.7634, 67: 0.7556, 68: 0.7477, 69: 0.7399, 70: 0.7321, 71: 0.7242, 72: 0.7164, 73: 0.7086, 74: 0.7008, 75: 0.6930, 76: 0.6852, 77: 0.6775, 78: 0.6697, 79: 0.6619, 80: 0.6541, 81: 0.6464, 82: 0.6367, 83: 0.6263, 84: 0.6151, 85: 0.6032, 86: 0.5905, 87: 0.5771, 88: 0.5629, 89: 0.5480, 90: 0.5323, 91: 0.5158, 92: 0.4986, 93: 0.4806, 94: 0.4619, 95: 0.4425, 96: 0.4222, 97: 0.4013, 98: 0.3795, 99: 0.3570, 100: 0.3338, 101: 0.3098, 102: 0.2851, 103: 0.2596, 104: 0.2333, 105: 0.2063, 106: 0.1785, 107: 0.1500, 108: 0.1208, 109: 0.0908, 110: 0.0600 }
|
|
14
|
+
"10000": { 30: 1.0000, 31: 1.0000, 32: 1.0000, 33: 1.0000, 34: 0.9973, 35: 0.9897, 36: 0.9822, 37: 0.9747, 38: 0.9672, 39: 0.9597, 40: 0.9523, 41: 0.9449, 42: 0.9375, 43: 0.9301, 44: 0.9228, 45: 0.9155, 46: 0.9082, 47: 0.9009, 48: 0.8937, 49: 0.8865, 50: 0.8793, 51: 0.8722, 52: 0.8650, 53: 0.8579, 54: 0.8509, 55: 0.8438, 56: 0.8368, 57: 0.8298, 58: 0.8228, 59: 0.8158, 60: 0.8089, 61: 0.8019, 62: 0.7950, 63: 0.7882, 64: 0.7813, 65: 0.7745, 66: 0.7677, 67: 0.7609, 68: 0.7541, 69: 0.7474, 70: 0.7407, 71: 0.7340, 72: 0.7273, 73: 0.7206, 74: 0.7140, 75: 0.7073, 76: 0.7007, 77: 0.6942, 78: 0.6868, 79: 0.6787, 80: 0.6698, 81: 0.6601, 82: 0.6496, 83: 0.6383, 84: 0.6263, 85: 0.6135, 86: 0.5999, 87: 0.5856, 88: 0.5704, 89: 0.5545, 90: 0.5378, 91: 0.5203, 92: 0.5021, 93: 0.4830, 94: 0.4632, 95: 0.4426, 96: 0.4213, 97: 0.3991, 98: 0.3762, 99: 0.3524, 100: 0.3279, 101: 0.3027, 102: 0.2766, 103: 0.2498, 104: 0.2221, 105: 0.1937, 106: 0.1646, 107: 0.1346, 108: 0.1038, 109: 0.0723, 110: 0.0400 }
|
|
15
|
+
"21097": { 30: 1.0000, 31: 1.0000, 32: 1.0000, 33: 1.0000, 34: 1.0000, 35: 0.9953, 36: 0.9885, 37: 0.9816, 38: 0.9748, 39: 0.9680, 40: 0.9612, 41: 0.9544, 42: 0.9476, 43: 0.9408, 44: 0.9340, 45: 0.9272, 46: 0.9204, 47: 0.9137, 48: 0.9069, 49: 0.9002, 50: 0.8934, 51: 0.8867, 52: 0.8799, 53: 0.8732, 54: 0.8665, 55: 0.8598, 56: 0.8531, 57: 0.8464, 58: 0.8397, 59: 0.8331, 60: 0.8264, 61: 0.8197, 62: 0.8131, 63: 0.8064, 64: 0.7998, 65: 0.7931, 66: 0.7865, 67: 0.7799, 68: 0.7733, 69: 0.7666, 70: 0.7600, 71: 0.7534, 72: 0.7468, 73: 0.7396, 74: 0.7318, 75: 0.7233, 76: 0.7142, 77: 0.7044, 78: 0.6941, 79: 0.6831, 80: 0.6715, 81: 0.6592, 82: 0.6463, 83: 0.6328, 84: 0.6187, 85: 0.6039, 86: 0.5885, 87: 0.5725, 88: 0.5558, 89: 0.5385, 90: 0.5206, 91: 0.5021, 92: 0.4829, 93: 0.4631, 94: 0.4426, 95: 0.4216, 96: 0.3999, 97: 0.3776, 98: 0.3546, 99: 0.3310, 100: 0.3068, 101: 0.2820, 102: 0.2565, 103: 0.2304, 104: 0.2036, 105: 0.1763, 106: 0.1483, 107: 0.1197, 108: 0.0904, 109: 0.0605, 110: 0.0300 }
|
|
16
|
+
"42195": { 30: 1.0000, 31: 1.0000, 32: 1.0000, 33: 1.0000, 34: 1.0000, 35: 1.0000, 36: 1.0000, 37: 1.0000, 38: 0.9947, 39: 0.9876, 40: 0.9804, 41: 0.9733, 42: 0.9661, 43: 0.9589, 44: 0.9517, 45: 0.9445, 46: 0.9372, 47: 0.9299, 48: 0.9226, 49: 0.9153, 50: 0.9079, 51: 0.9005, 52: 0.8931, 53: 0.8857, 54: 0.8783, 55: 0.8708, 56: 0.8633, 57: 0.8558, 58: 0.8483, 59: 0.8407, 60: 0.8331, 61: 0.8255, 62: 0.8179, 63: 0.8103, 64: 0.8026, 65: 0.7950, 66: 0.7873, 67: 0.7796, 68: 0.7718, 69: 0.7641, 70: 0.7563, 71: 0.7485, 72: 0.7407, 73: 0.7329, 74: 0.7250, 75: 0.7165, 76: 0.7074, 77: 0.6976, 78: 0.6871, 79: 0.6760, 80: 0.6643, 81: 0.6519, 82: 0.6388, 83: 0.6251, 84: 0.6108, 85: 0.5958, 86: 0.5801, 87: 0.5638, 88: 0.5469, 89: 0.5293, 90: 0.5110, 91: 0.4921, 92: 0.4726, 93: 0.4524, 94: 0.4316, 95: 0.4101, 96: 0.3879, 97: 0.3651, 98: 0.3417, 99: 0.3176, 100: 0.2929, 101: 0.2675, 102: 0.2415, 103: 0.2148, 104: 0.1875, 105: 0.1595, 106: 0.1309, 107: 0.1017, 108: 0.0718, 109: 0.0412, 110: 0.0100 }
|
data/lib/calcpace/version.rb
CHANGED
data/lib/calcpace.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'calcpace/calculator'
|
|
4
4
|
require_relative 'calcpace/cameron_predictor'
|
|
5
|
+
require_relative 'calcpace/age_grading'
|
|
5
6
|
require_relative 'calcpace/checker'
|
|
6
7
|
require_relative 'calcpace/converter'
|
|
7
8
|
require_relative 'calcpace/converter_chain'
|
|
@@ -35,6 +36,7 @@ require_relative 'calcpace/vo2max_estimator'
|
|
|
35
36
|
#
|
|
36
37
|
# @see https://github.com/0jonjo/calcpace
|
|
37
38
|
class Calcpace
|
|
39
|
+
include AgeGrading
|
|
38
40
|
include Calculator
|
|
39
41
|
include CameronPredictor
|
|
40
42
|
include Checker
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: calcpace
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.9.
|
|
4
|
+
version: 1.9.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- João Gilberto Saraiva
|
|
@@ -31,11 +31,14 @@ files:
|
|
|
31
31
|
- Rakefile
|
|
32
32
|
- calcpace.gemspec
|
|
33
33
|
- lib/calcpace.rb
|
|
34
|
+
- lib/calcpace/age_grading.rb
|
|
34
35
|
- lib/calcpace/calculator.rb
|
|
35
36
|
- lib/calcpace/cameron_predictor.rb
|
|
36
37
|
- lib/calcpace/checker.rb
|
|
37
38
|
- lib/calcpace/converter.rb
|
|
38
39
|
- lib/calcpace/converter_chain.rb
|
|
40
|
+
- lib/calcpace/data/wma_2023_open_standards.yml
|
|
41
|
+
- lib/calcpace/data/wma_2023_road.yml
|
|
39
42
|
- lib/calcpace/errors.rb
|
|
40
43
|
- lib/calcpace/pace_calculator.rb
|
|
41
44
|
- lib/calcpace/pace_converter.rb
|