calcpace 1.18.1 → 2.1.0

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.
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require_relative 'errors'
5
+ require_relative 'checker'
6
+
7
+ # Module for reading a VO2max against people of the same age and sex
8
+ #
9
+ # Uses the FRIEND registry (Fitness Registry and the Importance of Exercise
10
+ # National Database) percentiles of VO2max measured by cardiopulmonary
11
+ # exercise testing in 7,783 treadmill tests on US adults free of known
12
+ # cardiovascular disease:
13
+ #
14
+ # Kaminsky, L. A., Arena, R., & Myers, J. (2015). Reference Standards for
15
+ # Cardiorespiratory Fitness Measured With Cardiopulmonary Exercise Testing:
16
+ # Data From the Fitness Registry and the Importance of Exercise National
17
+ # Database. Mayo Clinic Proceedings, 90(11), 1515–1523, Table 3.
18
+ # https://doi.org/10.1016/j.mayocp.2015.07.026
19
+ #
20
+ # The table is stored, with its provenance, in
21
+ # `lib/calcpace/data/friend_2015_vo2max_percentiles.yml`.
22
+ # Vo2maxEstimator#vo2max_label uses it when given age and sex.
23
+ module Vo2maxNorms
24
+ # check_positive, normalize_age and normalize_sex: the same rules as AgeGrading
25
+ include Checker
26
+
27
+ # Percentile norms by age and sex: FRIEND registry, measured treadmill VO2max
28
+ # (Kaminsky, Arena & Myers, Mayo Clin Proc 2015;90(11):1515–1523, Table 3).
29
+ # See the data file for the full provenance.
30
+ NORMS_DATA_PATH = File.expand_path('data/friend_2015_vo2max_percentiles.yml', __dir__).freeze
31
+ norms_data = YAML.safe_load_file(NORMS_DATA_PATH, permitted_classes: [], aliases: false)
32
+ VO2MAX_NORMS_VERSION = norms_data.fetch('meta').fetch('table_version').freeze
33
+ VO2MAX_NORM_PERCENTILES = norms_data.fetch('percentiles').map(&:to_f).freeze
34
+ VO2MAX_NORMS = %w[M F].to_h do |sex|
35
+ bands = norms_data.fetch(sex).to_h { |age, row| [Integer(age), row.map(&:to_f).freeze] }
36
+ [sex.freeze, bands.freeze]
37
+ end.freeze
38
+
39
+ VO2MAX_NORMS.each do |sex, bands|
40
+ bands.each do |age, row|
41
+ next if row.size == VO2MAX_NORM_PERCENTILES.size && row.each_cons(2).all? { |low, high| high > low }
42
+
43
+ raise Calcpace::InvalidDataError,
44
+ "VO2max norms #{sex} #{age}: expected #{VO2MAX_NORM_PERCENTILES.size} rising values, got #{row.inspect}"
45
+ end
46
+ end
47
+
48
+ # Percentile cut for each label when vo2max_label is given age and sex. The
49
+ # cuts sit on percentiles the table publishes, so a label never depends on
50
+ # interpolation: at or above the 95th percentile is Elite, the 90th
51
+ # Excellent, the 75th Very Good, the median Good, the 25th Fair, and below
52
+ # the 25th Beginner. These cuts are calcpace's choice — FRIEND publishes
53
+ # percentiles, not labels.
54
+ VO2MAX_PERCENTILE_LABELS = [
55
+ { min: 95, label: 'Elite' },
56
+ { min: 90, label: 'Excellent' },
57
+ { min: 75, label: 'Very Good' },
58
+ { min: 50, label: 'Good' },
59
+ { min: 25, label: 'Fair' },
60
+ { min: 0, label: 'Beginner' }
61
+ ].freeze
62
+
63
+ # Approximate percentile of a VO2max among people of the same sex and age
64
+ #
65
+ # Reads the FRIEND registry percentiles (Kaminsky, Arena & Myers, 2015,
66
+ # Table 3: 5th, 10th, 25th, 50th, 75th, 90th and 95th, by decade from 20–29 to
67
+ # 70–79) and interpolates linearly between the two published percentiles
68
+ # around the value. The registry measured VO2max in a lab; an estimate from a
69
+ # race time carries its own ±3–5 ml/kg/min on top.
70
+ #
71
+ # - Age decades are used as published, without blending across them, so a
72
+ # 29- and a 30-year-old read different rows. Ages 18–19 use the 20–29 row and
73
+ # 80 or over the 70–79 row; under 18 is rejected (adult norms do not apply).
74
+ # - The result is bounded to the table: 5.0 means at or below the 5th
75
+ # percentile, 95.0 at or above the 95th.
76
+ #
77
+ # @param value [Numeric] VO2max in ml/kg/min
78
+ # @param age [Integer] age in years (18 or over; a fractional age is
79
+ # truncated, as in AgeGrading)
80
+ # @param sex [String, Symbol] male or female
81
+ # @return [Float] percentile between 5.0 and 95.0, rounded to one decimal
82
+ # @raise [Calcpace::NonPositiveInputError] if value is not positive
83
+ # @raise [ArgumentError] if age is under 18 or not a number, or sex is not male/female
84
+ #
85
+ # @example
86
+ # calc.vo2max_percentile(48.0, age: 25, sex: :male) #=> 50.0
87
+ # calc.vo2max_percentile(45, age: 25, sex: :male) #=> 40.5
88
+ # calc.vo2max_percentile(45, age: 25, sex: :female) #=> 75.7
89
+ # calc.vo2max_percentile(45, age: 60, sex: :male) #=> 95.0
90
+ def vo2max_percentile(value, age:, sex:)
91
+ check_positive(value.to_f, 'VO2max value')
92
+
93
+ raw_vo2max_percentile(value.to_f, age, sex).round(1)
94
+ end
95
+
96
+ private
97
+
98
+ # Unrounded percentile, so a label is decided against the published values
99
+ # themselves rather than a rounded reading of them. normalize_age and
100
+ # normalize_sex come from Checker — one rule for age and sex gem-wide.
101
+ def raw_vo2max_percentile(value, age, sex)
102
+ row = vo2max_norm_row(normalize_age(age), normalize_sex(sex))
103
+ return VO2MAX_NORM_PERCENTILES.first if value <= row.first
104
+ return VO2MAX_NORM_PERCENTILES.last if value >= row.last
105
+
106
+ upper = row.index { |norm| norm > value }
107
+ interpolate_percentile(row, upper, value)
108
+ end
109
+
110
+ def vo2max_norm_row(age, sex)
111
+ bands = VO2MAX_NORMS.fetch(sex == :male ? 'M' : 'F')
112
+ band = bands.keys.select { |lower| lower <= age }.max || bands.keys.min
113
+ bands.fetch(band)
114
+ end
115
+
116
+ def interpolate_percentile(row, upper, value)
117
+ low_norm, high_norm = row.values_at(upper - 1, upper)
118
+ low_pct, high_pct = VO2MAX_NORM_PERCENTILES.values_at(upper - 1, upper)
119
+ low_pct + ((high_pct - low_pct) * (value - low_norm) / (high_norm - low_norm))
120
+ end
121
+ end
data/lib/calcpace.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'calcpace/version'
3
4
  require_relative 'calcpace/errors'
4
5
  require_relative 'calcpace/calculator'
5
6
  require_relative 'calcpace/cameron_predictor'
@@ -9,15 +10,19 @@ require_relative 'calcpace/checker'
9
10
  require_relative 'calcpace/converter'
10
11
  require_relative 'calcpace/converter_chain'
11
12
  require_relative 'calcpace/fitness_predictor'
13
+ require_relative 'calcpace/grade_adjusted_pace'
12
14
  require_relative 'calcpace/lap_analyzer'
13
15
  require_relative 'calcpace/pace_calculator'
14
16
  require_relative 'calcpace/pace_converter'
17
+ require_relative 'calcpace/personalized_predictor'
15
18
  require_relative 'calcpace/race_predictor'
16
19
  require_relative 'calcpace/race_splits'
17
20
  require_relative 'calcpace/stride_calculator'
18
21
  require_relative 'calcpace/track_calculator'
19
22
  require_relative 'calcpace/training_zones'
23
+ require_relative 'calcpace/vo2max_effort'
20
24
  require_relative 'calcpace/vo2max_estimator'
25
+ require_relative 'calcpace/vo2max_norms'
21
26
 
22
27
  # Calcpace - A Ruby gem for pace, distance, and time calculations
23
28
  #
@@ -49,15 +54,18 @@ class Calcpace
49
54
  include Converter
50
55
  include ConverterChain
51
56
  include FitnessPredictor
57
+ include GradeAdjustedPace
52
58
  include LapAnalyzer
53
59
  include PaceCalculator
54
60
  include PaceConverter
61
+ include PersonalizedPredictor
55
62
  include RacePredictor
56
63
  include RaceSplits
57
64
  include StrideCalculator
58
65
  include TrackCalculator
59
66
  include TrainingZones
60
67
  include Vo2maxEstimator
68
+ include Vo2maxNorms
61
69
 
62
70
  # Creates a new Calcpace instance
63
71
  #
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.18.1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - João Gilberto Saraiva
@@ -10,9 +10,11 @@ cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: 'Ruby gem for runners: pace, time, and distance calculations, unit conversions
13
- (30+ units), race time predictions (Riegel & Cameron), GPS track analysis (Haversine,
14
- elevation gain, per-km splits), age grading (WMA 2023), VO2max estimation (Daniels
15
- & Gilbert), and personalized training zones (Daniels paces & Karvonen heart-rate
13
+ (30+ units), race time predictions (Riegel, Cameron, personal Riegel exponent, and
14
+ Tanda marathon from training volume), GPS track analysis (Haversine, elevation gain,
15
+ per-km splits, Minetti grade-adjusted pace), heat, humidity, and altitude adjustments,
16
+ age grading (2025 road tables), VO2max estimation (Daniels & Gilbert) with FRIEND
17
+ age/sex norms, and personalized training zones (Daniels paces & Karvonen heart-rate
16
18
  zones).'
17
19
  email:
18
20
  - joaogilberto@tuta.io
@@ -40,21 +42,27 @@ files:
40
42
  - lib/calcpace/converter.rb
41
43
  - lib/calcpace/converter_chain.rb
42
44
  - lib/calcpace/data/environmental_factors.yml
43
- - lib/calcpace/data/wma_2023_open_standards.yml
44
- - lib/calcpace/data/wma_2023_road.yml
45
+ - lib/calcpace/data/friend_2015_vo2max_percentiles.yml
46
+ - lib/calcpace/data/mldr_2025_road.yml
47
+ - lib/calcpace/data/mldr_2025_road_open_standards.yml
45
48
  - lib/calcpace/environmental_adjuster.rb
46
49
  - lib/calcpace/errors.rb
47
50
  - lib/calcpace/fitness_predictor.rb
51
+ - lib/calcpace/grade_adjusted_pace.rb
52
+ - lib/calcpace/humidity.rb
48
53
  - lib/calcpace/lap_analyzer.rb
49
54
  - lib/calcpace/pace_calculator.rb
50
55
  - lib/calcpace/pace_converter.rb
56
+ - lib/calcpace/personalized_predictor.rb
51
57
  - lib/calcpace/race_predictor.rb
52
58
  - lib/calcpace/race_splits.rb
53
59
  - lib/calcpace/stride_calculator.rb
54
60
  - lib/calcpace/track_calculator.rb
55
61
  - lib/calcpace/training_zones.rb
56
62
  - lib/calcpace/version.rb
63
+ - lib/calcpace/vo2max_effort.rb
57
64
  - lib/calcpace/vo2max_estimator.rb
65
+ - lib/calcpace/vo2max_norms.rb
58
66
  homepage: https://github.com/0jonjo/calcpace
59
67
  licenses:
60
68
  - MIT
@@ -76,8 +84,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
84
  - !ruby/object:Gem::Version
77
85
  version: '0'
78
86
  requirements: []
79
- rubygems_version: 4.0.16
87
+ rubygems_version: 4.0.20
80
88
  specification_version: 4
81
- summary: 'Running calculations: pace, race predictions, GPS track analysis, VO2max,
82
- and training zones.'
89
+ summary: 'Running calculations: pace, race predictions, GPS track analysis, heat and
90
+ altitude adjustments, age grading, VO2max, and training zones.'
83
91
  test_files: []
@@ -1,40 +0,0 @@
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
- # The WMA / Alan Jones (Howard Grubb) tables are numeric age factors and open
7
- # standards only — they define no categories at all. The bands from Local
8
- # Class (60%) upward follow the USATF Masters / National Masters News
9
- # convention; the three bands under 60% are Calcpace's own extension, added
10
- # to give recreational runners a meaningful label instead of a single
11
- # catch-all.
12
- age_grade_classifications:
13
- - min: 100.0
14
- label: "Approximate World Record Level"
15
- - min: 90.0
16
- label: "World Class"
17
- - min: 80.0
18
- label: "National Class"
19
- - min: 70.0
20
- label: "Regional Class"
21
- - min: 60.0
22
- label: "Local Class"
23
- - min: 50.0
24
- label: "Intermediate"
25
- - min: 40.0
26
- label: "Recreational"
27
- - min: 0.0
28
- label: "Active Beginner"
29
-
30
- open_standards_seconds:
31
- M:
32
- "5000": 755.0
33
- "10000": 1571.0
34
- "21097": 3451.0
35
- "42195": 7269.0
36
- F:
37
- "5000": 846.0
38
- "10000": 1741.0
39
- "21097": 3772.0
40
- "42195": 8044.0
@@ -1,16 +0,0 @@
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 }