runby_pace 0.2.50.111 → 0.2.55

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +13 -5
  2. data/.travis.yml +1 -5
  3. data/Gemfile +0 -4
  4. data/README.md +5 -16
  5. data/Rakefile +6 -40
  6. data/bin/_guard-core +16 -17
  7. data/bin/guard +16 -17
  8. data/lib/runby_pace.rb +1 -4
  9. data/lib/runby_pace/{pace_calculator.rb → pace_data.rb} +13 -29
  10. data/lib/runby_pace/pace_range.rb +9 -27
  11. data/lib/runby_pace/pace_time.rb +110 -0
  12. data/lib/runby_pace/run_type.rb +4 -12
  13. data/lib/runby_pace/run_types/all_run_types.template +4 -6
  14. data/lib/runby_pace/run_types/easy_run.rb +10 -31
  15. data/lib/runby_pace/run_types/find_divisor.rb +17 -13
  16. data/lib/runby_pace/run_types/long_run.rb +10 -32
  17. data/lib/runby_pace/version.rb +2 -17
  18. data/runby_pace.gemspec +5 -4
  19. metadata +18 -41
  20. data/.rubocop.yml +0 -10
  21. data/bin/runbypace +0 -15
  22. data/lib/runby_pace/cli/cli.rb +0 -127
  23. data/lib/runby_pace/cli/config.rb +0 -82
  24. data/lib/runby_pace/distance.rb +0 -135
  25. data/lib/runby_pace/distance_unit.rb +0 -89
  26. data/lib/runby_pace/golden_pace_set.rb +0 -50
  27. data/lib/runby_pace/pace.rb +0 -152
  28. data/lib/runby_pace/run_math.rb +0 -14
  29. data/lib/runby_pace/run_types/distance_run.rb +0 -55
  30. data/lib/runby_pace/run_types/fast_tempo_run.rb +0 -23
  31. data/lib/runby_pace/run_types/five_kilometer_race_run.rb +0 -22
  32. data/lib/runby_pace/run_types/mile_race_run.rb +0 -24
  33. data/lib/runby_pace/run_types/slow_tempo_run.rb +0 -22
  34. data/lib/runby_pace/run_types/tempo_run.rb +0 -54
  35. data/lib/runby_pace/run_types/ten_kilometer_race_run.rb +0 -23
  36. data/lib/runby_pace/runby_range.rb +0 -22
  37. data/lib/runby_pace/runby_time.rb +0 -138
  38. data/lib/runby_pace/runby_time_parser.rb +0 -80
  39. data/lib/runby_pace/speed.rb +0 -97
  40. data/lib/runby_pace/speed_range.rb +0 -30
  41. data/lib/runby_pace/utility/parameter_sanitizer.rb +0 -29
  42. data/lib/runby_pace/version.seed +0 -5
  43. data/misc/runbypace_logo.png +0 -0
data/bin/runbypace DELETED
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- begin
4
- require "bundler/setup"
5
- rescue LoadError
6
- end
7
-
8
- begin
9
- require 'runby_pace'
10
- rescue LoadError
11
- require_relative '../lib/runby_pace'
12
- end
13
-
14
- cli = Runby::Cli::Cli.new(ARGV)
15
- cli.run
@@ -1,127 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'readline'
4
- require 'optparse'
5
- require_relative 'config'
6
-
7
- module Runby
8
- module Cli
9
- # Command line interface and REPL for RunbyPace
10
- class Cli
11
- def initialize(args = ARGV)
12
- @args = args
13
- @config = Config.new
14
- @options = parse_options args
15
- end
16
-
17
- def run
18
- puts 'Runby Pace REPL!'
19
- bnd = binding
20
- while (input = Readline.readline('🏃 ', true))
21
- begin
22
- result = bnd.eval input
23
- rescue StandardError => e
24
- puts "#{e.class}: #{e.message}"
25
- else
26
- puts result
27
- end
28
- end
29
- end
30
-
31
- def print_targets(five_k_time, distance_units = :mi)
32
- five_k_time = @config['five_k_time'] if five_k_time.nil?
33
-
34
- five_k_time = Runby.sanitize(five_k_time).as(RunbyTime)
35
- puts "\nIf you can run a 5K in #{five_k_time}, your training paces should be:"
36
- paces = []
37
- RunTypes.all_classes.each do |run_type|
38
- run = run_type.new
39
- paces.push(description: run.description, pace: run.lookup_pace(five_k_time, distance_units))
40
- end
41
- paces.sort_by { |p| p[:pace].fast }.reverse_each { |p| puts " #{p[:description]}: #{p[:pace]}" }
42
- nil
43
- end
44
-
45
- # -- Shortcuts for the REPL
46
- def di(*args)
47
- Distance.new(*args)
48
- end
49
-
50
- def du(*args)
51
- DistanceUnit.new(*args)
52
- end
53
-
54
- def pc(*args)
55
- Pace.new(*args)
56
- end
57
-
58
- def sp(*args)
59
- Speed.new(*args)
60
- end
61
-
62
- def tm(*args)
63
- RunbyTime.new(*args)
64
- end
65
-
66
- private
67
-
68
- def parse_options(options)
69
- args = { targets: nil }
70
-
71
- OptionParser.new do |opts|
72
- opts.banner = 'Usage: runbypace.rb [options]'
73
-
74
- opts.on('-h', '--help', 'Display this help message') do
75
- puts opts
76
- exit
77
- end
78
-
79
- opts.on('-c', '--config [SETTING][=NEW_VALUE]', 'Get or set a configuration value') do |config|
80
- manage_config config
81
- exit
82
- end
83
-
84
- opts.on('-t', '--targets [5K race time]', 'Show target paces') do |targets|
85
- args[:targets] = targets
86
- print_targets targets
87
- exit
88
- end
89
- end.parse!(options)
90
- args
91
- end
92
-
93
- def manage_config(config)
94
- c = parse_config_setting config
95
- unless c.key
96
- # No key specified. Print all settings.
97
- @config.pretty_print
98
- return
99
- end
100
- if c.value
101
- # Set setting "key" to new "value"
102
- @config[c.key] = c.value
103
- return
104
- end
105
- if c.clear_setting
106
- @config[c.key] = nil
107
- else
108
- # Print the value of setting "key"
109
- p @config[c.key]
110
- end
111
- end
112
-
113
- def parse_config_setting(setting)
114
- setting = '' if setting.nil?
115
- Class.new do
116
- attr_reader :key, :value, :clear_setting
117
- def initialize(setting)
118
- tokens = setting.split('=')
119
- @key = tokens[0]
120
- @value = tokens[1]
121
- @clear_setting = (@value.nil? && setting.include?('='))
122
- end
123
- end.new(setting)
124
- end
125
- end
126
- end
127
- end
@@ -1,82 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'yaml'
4
- require 'pp'
5
-
6
- module Runby
7
- #
8
- module Cli
9
- class Config
10
- USER_CONFIG_PATH = File.expand_path('~/.runbypace').freeze
11
-
12
- VALID_OPTIONS = {
13
- five_k_time: { validate_as: RunbyTime }
14
- }.freeze
15
-
16
- def initialize
17
- @settings = load_user_settings
18
- end
19
-
20
- def load_user_settings
21
- if File.exist? USER_CONFIG_PATH
22
- YAML.load_file USER_CONFIG_PATH
23
- else
24
- {}
25
- end
26
- end
27
-
28
- def store_user_settings
29
- File.open(USER_CONFIG_PATH, 'w') { |file| file.write @settings.to_yaml }
30
- end
31
-
32
- def [](key)
33
- return unless known_setting?(key)
34
- return unless option_configured?(key)
35
- "#{key} => #{@settings[key]}"
36
- end
37
-
38
- def []=(key, value)
39
- return unless known_setting?(key)
40
- if value
41
- value = sanitize_value key, value
42
- return unless value
43
- @settings[key] = value.to_s
44
- else
45
- @settings.delete(key)
46
- end
47
- store_user_settings
48
- end
49
-
50
- def pretty_print
51
- pp @settings
52
- end
53
-
54
- def known_setting?(key)
55
- unless VALID_OPTIONS.key?(key.to_sym)
56
- puts "Unknown setting #{key}"
57
- return false
58
- end
59
- true
60
- end
61
-
62
- def sanitize_value(key, value)
63
- cls = VALID_OPTIONS[key.to_sym][:validate_as]
64
- begin
65
- value = Runby.sanitize(value).as(cls)
66
- rescue StandardError => ex
67
- value = nil
68
- p ex.message
69
- end
70
- value
71
- end
72
-
73
- def option_configured?(key)
74
- unless @settings.key? key
75
- puts "#{key} not configured. Set with:\n\trunbypace --config #{key} VALUE"
76
- false
77
- end
78
- true
79
- end
80
- end
81
- end
82
- end
@@ -1,135 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Runby
4
- # Represents a distance (distance UOM and multiplier)
5
- class Distance
6
- include Comparable
7
-
8
- attr_reader :uom, :multiplier
9
-
10
- def self.new(uom = :km, multiplier = 1)
11
- return uom if uom.is_a? Distance
12
- return Distance.parse uom if uom.is_a? String
13
- super
14
- end
15
-
16
- def initialize(uom = :km, multiplier = 1)
17
- case uom
18
- when DistanceUnit
19
- init_from_distance_unit uom, multiplier
20
- when Symbol
21
- init_from_symbol uom, multiplier
22
- else
23
- raise 'Invalid distance unit of measure'
24
- end
25
- freeze
26
- end
27
-
28
- def convert_to(target_uom)
29
- target_uom = DistanceUnit.new target_uom unless target_uom.is_a?(DistanceUnit)
30
- return self if @uom == target_uom
31
- target_multiplier = kilometers / (target_uom.conversion_factor * 1.0)
32
- Distance.new target_uom, target_multiplier
33
- end
34
-
35
- def meters
36
- kilometers * 1000.0
37
- end
38
-
39
- def kilometers
40
- @multiplier * @uom.conversion_factor
41
- end
42
-
43
- def self.parse(str)
44
- str = str.strip.chomp.downcase
45
- multiplier = str.scan(/[\d,.]+/).first
46
- multiplier = multiplier.nil? ? 1 : multiplier.to_f
47
- uom = str.scan(/[-_a-z ]+$/).first
48
- raise "Unable to find distance unit in '#{str}'" if uom.nil?
49
-
50
- parsed_uom = Runby::DistanceUnit.parse uom
51
- raise "'#{uom.strip}' is not recognized as a distance unit" if parsed_uom.nil?
52
-
53
- new parsed_uom, multiplier
54
- end
55
-
56
- def self.try_parse(str)
57
- distance, error_message = nil
58
- begin
59
- distance = parse str
60
- rescue StandardError => ex
61
- error_message = ex.message.to_s
62
- end
63
- { distance: distance, error: error_message }
64
- end
65
-
66
- def to_s(format: :short)
67
- formatted_multiplier = format('%g', @multiplier.round(2))
68
- case format
69
- when :short then "#{formatted_multiplier} #{@uom.to_s(format: format)}"
70
- when :long then "#{formatted_multiplier} #{@uom.to_s(format: format, pluralize: (@multiplier > 1))}"
71
- else raise "Invalid string format #{format}"
72
- end
73
- end
74
-
75
- # @param [Distance, String] other
76
- def <=>(other)
77
- raise "Unable to compare Runby::Distance to #{other.class}(#{other})" unless [Distance, String].include? other.class
78
- if other.is_a?(String)
79
- return 0 if to_s == other || to_s(format: :long) == other
80
- return self <=> Distance.try_parse(other)[:distance]
81
- end
82
- kilometers <=> other.kilometers
83
- end
84
-
85
- # @param [Distance] other
86
- # @return [Distance]
87
- def +(other)
88
- raise "Cannot add Runby::Distance to #{other.class}" unless other.is_a?(Distance)
89
- sum_in_km = Distance.new(:km, kilometers + other.kilometers)
90
- sum_in_km.convert_to(@uom)
91
- end
92
-
93
- # @param [Distance] other
94
- # @return [Distance]
95
- def -(other)
96
- raise "Cannot add Runby::Distance to #{other.class}" unless other.is_a?(Distance)
97
- sum_in_km = Distance.new(:km, kilometers - other.kilometers)
98
- sum_in_km.convert_to(@uom)
99
- end
100
-
101
- # @param [Numeric] other
102
- # @return [Distance]
103
- def *(other)
104
- raise "Cannot multiply Runby::Distance by #{other.class}" unless other.is_a?(Numeric)
105
- product_in_km = Distance.new(:km, kilometers * other)
106
- product_in_km.convert_to(@uom)
107
- end
108
-
109
- # @param [Numeric, Distance] other
110
- # @return [Distance, Numeric]
111
- def /(other)
112
- raise "Cannot divide Runby::Distance by #{other.class}" unless other.is_a?(Numeric) || other.is_a?(Distance)
113
- if other.is_a?(Numeric)
114
- quotient_in_km = Distance.new(:km, kilometers / other)
115
- return quotient_in_km.convert_to(@uom)
116
- elsif other.is_a?(Distance)
117
- return kilometers / other.kilometers
118
- end
119
- end
120
-
121
- private
122
-
123
- def init_from_distance_unit(uom, multiplier)
124
- @uom = uom
125
- @multiplier = multiplier
126
- end
127
-
128
- def init_from_symbol(distance_uom_symbol, multiplier)
129
- raise "Unknown unit of measure #{distance_uom_symbol}" unless Runby::DistanceUnit.known_uom? distance_uom_symbol
130
- raise 'Invalid multiplier' unless multiplier.is_a?(Numeric)
131
- @uom = DistanceUnit.new distance_uom_symbol
132
- @multiplier = multiplier * 1.0
133
- end
134
- end
135
- end
@@ -1,89 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Runby
4
- # Represents the distance units (e.g. kilometers, miles) used in paces
5
- # including the human-readable description of each unit
6
- # and the factor used to convert it to kilometers.
7
- class DistanceUnit
8
- attr_reader :symbol, :description, :conversion_factor
9
-
10
- def self.new(unit_of_measure)
11
- return unit_of_measure if unit_of_measure.is_a? DistanceUnit
12
- return DistanceUnit.parse(unit_of_measure) if unit_of_measure.is_a? String
13
- super
14
- end
15
-
16
- def initialize(unit_of_measure)
17
- raise "':#{unit_of_measure}' is an unknown unit of measure" unless DistanceUnit.known_uom? unit_of_measure
18
- @symbol = unit_of_measure
19
- @conversion_factor = UOM_DEFINITIONS[@symbol][:conversion_factor]
20
- @description = UOM_DEFINITIONS[@symbol][:description]
21
- freeze
22
- end
23
-
24
- def to_s(format: :long, pluralize: false)
25
- case format
26
- when :short then @symbol.to_s
27
- when :long then pluralize ? description_plural : @description
28
- else raise "Invalid string format #{format}"
29
- end
30
- end
31
-
32
- def description_plural
33
- UOM_DEFINITIONS[@symbol][:description_plural]
34
- end
35
-
36
- def self.parse(description)
37
- return new description if description.is_a? Symbol
38
- description = description.strip.chomp.downcase
39
- found_uom = nil
40
- UOM_DEFINITIONS.each do |uom, details|
41
- if details[:synonyms].include? description
42
- found_uom = uom
43
- break
44
- end
45
- end
46
- raise "Error parsing distance unit '#{description}'" unless found_uom
47
- DistanceUnit.new found_uom
48
- end
49
-
50
- def self.try_parse(str)
51
- uom, error_message = nil
52
- begin
53
- uom = parse str
54
- rescue StandardError => ex
55
- error_message = ex.message
56
- end
57
- { uom: uom, error: error_message }
58
- end
59
-
60
- def self.known_uom?(symbol)
61
- UOM_DEFINITIONS.key?(symbol)
62
- end
63
-
64
- def ==(other)
65
- if other.is_a? DistanceUnit
66
- @symbol == other.symbol
67
- elsif other.is_a? String
68
- self == DistanceUnit.parse(other)
69
- else
70
- raise "Unable to compare DistanceUnit to #{other.class}(#{other})"
71
- end
72
- end
73
-
74
- UOM_DEFINITIONS =
75
- { km: { description: 'kilometer', description_plural: 'kilometers', conversion_factor: 1.0,
76
- synonyms: %w[k km kms kilometer kilometers] },
77
- m: { description: 'meter', description_plural: 'meters', conversion_factor: 0.001,
78
- synonyms: %w[m meter meters] },
79
- mi: { description: 'mile', description_plural: 'miles', conversion_factor: 1.609344,
80
- synonyms: %w[mi mile miles] },
81
- ft: { description: 'foot', description_plural: 'feet', conversion_factor: 0.0003048,
82
- synonyms: %w[ft foot feet] },
83
- yd: { description: 'yard', description_plural: 'yards', conversion_factor: 1093.61,
84
- synonyms: %w[y yd yds yard yards] },
85
- # Fun distance unit of measures
86
- marathon: { description: 'marathon', description_plural: 'marathons', conversion_factor: 42.1648128,
87
- synonyms: %w[marathon] } }.freeze
88
- end
89
- end