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
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: c865faf1b57fa5d059871913a9ffe259c5cfccc6f5e5c80819c2bcf7c7477ee9
4
- data.tar.gz: d34065214cd2129a7f433c201150afdaf88bbf845b7214c2c88ec095f1064a4c
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NzcyNTgxZjZiMzBlZGU2NTcyNzIzOGU1M2RiMTAxMDA0Y2ViOTRmMA==
5
+ data.tar.gz: !binary |-
6
+ YTVmNWNlNGJhYTcyYTVjYmE0OThjNDY1MWE0NmVhMjljMWYxOWQxOA==
5
7
  SHA512:
6
- metadata.gz: 1e20444a7feb901736b98135e27ac2f63d6d06e7f0cd0e594bbd5a2853a2e2586dad8338733d5f32c06265ddbc04eaf79ca3e672b08f2e3f495b350bca7d620d
7
- data.tar.gz: e2405ad249c55e3473b9999cf761373aab346b26d395417921865d6e7d9b44b9f7a26cebebc1aedae27a531feacc2d20f3be98df520458d739cd2d25f944887a
8
+ metadata.gz: !binary |-
9
+ YzdhOGFkODU2MjhjMTg2NGNkZDcwM2U3MzdkODQyYjE4MTVmYWI4Y2EwYzA3
10
+ OTdhNDMxOTUwOGI0M2ZmN2ZiZTc2M2VhMzk3YjRiNDY4MGU5NDg5YmRhNWI2
11
+ ZjI4N2RmZTVlYTk1Mjc5ZGQxZGUxNzA1NzEyYzNiNTM4ZTcyMGQ=
12
+ data.tar.gz: !binary |-
13
+ ZmQ2M2Y5ZTNjYThkY2ViNjRkN2FhMDI5Zjc3YTVjZmE4ZjI0MWE1YmJjMjBk
14
+ NTlkMmNjZmZiODVmZjVmNDNjNzM0YzY1MzliZGViNmU4YmM5MjYxZDhjYzYx
15
+ MWEzNGU3OWU0ZDRiNTAxMzkyN2U2NjY1MDA0MmI1ZmNmMjFlMGQ=
data/.travis.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.4
3
+ - 2.2.4
4
4
  before_install: gem install bundler -v 1.12.5
5
5
  deploy:
6
6
  skip_cleanup: true
@@ -12,7 +12,3 @@ deploy:
12
12
  repo: tygerbytes/runby-pace
13
13
  git:
14
14
  depth: 1024
15
- notifications:
16
- email:
17
- on_success: always
18
- on_failure: always
data/Gemfile CHANGED
@@ -1,9 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- group :development do
4
- gem 'rubocop', require: false
5
- end
6
-
7
3
  group :test do
8
4
  gem 'coveralls', require: false
9
5
  end
data/README.md CHANGED
@@ -6,7 +6,6 @@ RunbyPace contains the core logic for calculating the target "paces" used by run
6
6
  | | |
7
7
  | --- | --- |
8
8
  | **Build** | [![Build Status](https://travis-ci.org/tygerbytes/runby-pace.svg?branch=master)](https://travis-ci.org/tygerbytes/runby-pace) |
9
- | **Grade** | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/7c228c8601ff4eeb9dfe0f6c60867f25)](https://www.codacy.com/app/tygerbytes/runby-pace?utm_source=github.com&utm_medium=referral&utm_content=tygerbytes/runby-pace&utm_campaign=badger) |
10
9
  | **Coverage** | [![Coverage Status](https://coveralls.io/repos/github/tygerbytes/runby-pace/badge.svg?branch=master)](https://coveralls.io/github/tygerbytes/runby-pace?branch=master) |
11
10
  | **Gem** | [![gem](https://img.shields.io/gem/v/runby_pace.svg)](https://rubygems.org/gems/runby_pace) |
12
11
 
@@ -21,9 +20,7 @@ Any sort of running program will include runs at varying paces, easy runs, dista
21
20
  So this is great, but a little tedious. RunbyPace automates this whole process by calculating all of the paces for you.
22
21
  All you need is your current 5K time and some Ruby, and you're off running at just the right pace.
23
22
 
24
- RunbyPace also encapsulates the logic and math necessary for many running-related calculations based on time, pace, speed, unit coversions, etc. If you're tired of constantly converting minutes and seconds to decimal and back again, RunbyPace is for you.
25
-
26
- [![RunbyPace logo](misc/runbypace_logo.png)](https://runbypace.com)
23
+ Note that this project is currently being developed, so much of the functionality is pending.
27
24
 
28
25
  ## Installation
29
26
 
@@ -37,32 +34,24 @@ And then execute:
37
34
 
38
35
  $ bundle
39
36
 
40
- Or install it yourself:
37
+ Or install it yourself as:
41
38
 
42
39
  $ gem install runby_pace
43
40
 
44
41
  ## Usage
45
42
 
46
- I plan to craft better docs in the future, but for now the **specs** make for excellent class usage documentation: https://github.com/tygerbytes/runby-pace/tree/master/spec/runby_pace
47
-
48
- For a live front end written in **Rails**, see https://runbypace.com. It's code will be open-sourced as well, as soon as we can guarantee secure deployment.
49
-
50
- For an open-source example front end written in **Elm**, see https://github.com/tygerbytes/pacebyelm
51
-
52
- The CLI is still in its infancy, but the gem comes with a basic CLI/REPL (`bin/runbypace`)
43
+ TODO: Coming soon... When the class interfaces are fleshed out.
53
44
 
54
45
  ## Development
55
46
 
56
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` or `bin/runbypace` for an interactive prompt that will allow you to experiment.
47
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
57
48
 
58
- To install this gem onto your local machine, run `bundle exec rake install`.
49
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
59
50
 
60
51
  ## Contributing
61
52
 
62
53
  Bug reports and pull requests are welcome on GitHub at https://github.com/tygerbytes/runby-pace.
63
54
 
64
- Contribute front-end and CLI ideas at [@runbypace](https://twitter.com/runbypace).
65
-
66
55
  ## Acknowledgements
67
56
 
68
57
  Crafted with care, with the support of [JetBrains RubyMine](https://www.jetbrains.com/ruby/)
data/Rakefile CHANGED
@@ -1,17 +1,15 @@
1
- # frozen_string_literal: true
2
-
3
1
  require 'bundler/gem_tasks'
4
2
  require 'rspec/core/rake_task'
5
3
 
6
4
  RSpec::Core::RakeTask.new(:spec)
7
5
 
8
- task default: :build
6
+ task :default => :build
9
7
 
10
- task build: %i[gen_version_number gen_all_run_types spec]
8
+ task :build => [:gen_all_run_types,:spec]
11
9
 
12
10
  desc 'Generate the all_run_types.g.rb file'
13
11
  task :gen_all_run_types do
14
- puts "\e[32m__TEXT__\e[0m".gsub('__TEXT__', '> Generate all_run_types.g.rb')
12
+ puts "\e[32m__TEXT__\e[0m".gsub('__TEXT__', 'Generate all_run_types.g.rb')
15
13
  run_types_path = './lib/runby_pace/run_types'
16
14
 
17
15
  # Parse *_run.rb file names to generate array of the run type class names
@@ -21,48 +19,16 @@ task :gen_all_run_types do
21
19
  filename_sans_extension = filename[0, filename.length - 3]
22
20
  parts = filename_sans_extension.to_s.downcase.split(/_|\./)
23
21
  run_type = ''
24
- parts.each do |part|
22
+ parts.each { |part|
25
23
  run_type += part[0].upcase + part[-(part.length - 1), part.length - 1]
26
- end
24
+ }
27
25
  run_type
28
26
  end
29
27
  puts all_run_types.join(' ')
30
28
 
31
29
  # Write run types to the generated file, all_run_types.g.rb
32
30
  template = File.read(File.join(run_types_path, 'all_run_types.template'))
33
- template.gsub!('__RUN_TYPE_NAMES__', all_run_types.join(' '))
34
- template.gsub!('__RUN_TYPES__', all_run_types.join(', '))
31
+ template.gsub!('__RUN_TYPES__', all_run_types.join(' '))
35
32
  File.write(File.join(run_types_path, 'all_run_types.g.rb'), template)
36
33
  puts "\e[32mDone\e[0m\n\n"
37
34
  end
38
-
39
- desc 'Generate version number'
40
- task :gen_version_number do
41
- puts "\e[32m__TEXT__\e[0m".gsub('__TEXT__', '> Generate version number')
42
-
43
- # Generate "teeny" version number based on the number of commits since the last tagged major/minor release
44
- latest_tagged_release = `git describe --tags --abbrev=0 --match v*`.to_s.chomp
45
- puts "\e[32m__TEXT__\e[0m".gsub('__TEXT__', "Latest tagged release is #{latest_tagged_release}")
46
- version = "#{latest_tagged_release[1..-1]}.#{`git rev-list --count #{latest_tagged_release}..HEAD`}".chomp
47
-
48
- # Write version number to generated file
49
- path = './lib/runby_pace'
50
- template = File.read(File.join(path, 'version.seed'))
51
- template.gsub!('__VERSION__', version)
52
- version_file_path = File.join(path, 'version.g.rb')
53
- File.write(version_file_path, template)
54
- with_no_warnings do
55
- # Silencing warnings about redefining constants, since it's intentional
56
- load version_file_path
57
- Runby::VERSION = Runby::GENERATED_VERSION
58
- end
59
- puts "\e[32m__TEXT__\e[0m".gsub('__TEXT__', "Version: #{Runby::VERSION}")
60
- end
61
-
62
- def with_no_warnings
63
- warning_level = $VERBOSE
64
- $VERBOSE = nil
65
- result = yield
66
- $VERBOSE = warning_level
67
- result
68
- end
data/bin/_guard-core CHANGED
@@ -1,17 +1,16 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
- #
4
- # This file was generated by Bundler.
5
- #
6
- # The application '_guard-core' is installed as part of a gem, and
7
- # this file is here to facilitate running it.
8
- #
9
-
10
- require "pathname"
11
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
- Pathname.new(__FILE__).realpath)
13
-
14
- require "rubygems"
15
- require "bundler/setup"
16
-
17
- load Gem.bin_path("guard", "_guard-core")
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application '_guard-core' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require "pathname"
10
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require "rubygems"
14
+ require "bundler/setup"
15
+
16
+ load Gem.bin_path("guard", "_guard-core")
data/bin/guard CHANGED
@@ -1,17 +1,16 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
- #
4
- # This file was generated by Bundler.
5
- #
6
- # The application 'guard' is installed as part of a gem, and
7
- # this file is here to facilitate running it.
8
- #
9
-
10
- require "pathname"
11
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
- Pathname.new(__FILE__).realpath)
13
-
14
- require "rubygems"
15
- require "bundler/setup"
16
-
17
- load Gem.bin_path("guard", "guard")
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'guard' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require "pathname"
10
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require "rubygems"
14
+ require "bundler/setup"
15
+
16
+ load Gem.bin_path("guard", "guard")
data/lib/runby_pace.rb CHANGED
@@ -1,10 +1,7 @@
1
1
 
2
2
  require 'runby_pace/version'
3
3
  Dir[File.dirname(__FILE__) + '/runby_pace/*.rb'].each { |file| require file }
4
- Dir[File.dirname(__FILE__) + '/runby_pace/cli/*.rb'].each { |file| require file }
5
4
  Dir[File.dirname(__FILE__) + '/runby_pace/run_types/*.rb'].each { |file| require file }
6
- Dir[File.dirname(__FILE__) + '/runby_pace/utility/*.rb'].each { |file| require file }
7
5
 
8
- # The main module
9
- module Runby
6
+ module RunbyPace
10
7
  end
@@ -1,8 +1,7 @@
1
- # frozen_string_literal: true
1
+ module RunbyPace
2
+
3
+ class PaceData
2
4
 
3
- module Runby
4
- # Encapsulates the algorithms used to calculate target paces.
5
- class PaceCalculator
6
5
  # The number of data points plotted on our line of 5K times.
7
6
  # We take 5K times from 14:00 to 42:00 with a sample rate
8
7
  # of 30 seconds, and out pops 57.
@@ -27,41 +26,26 @@ module Runby
27
26
  # until it matches that of the data. (See #curve_minutes)
28
27
  attr_reader :midpoint_radius_divisor
29
28
 
30
- def initialize(golden_pace_set, midpoint_radius_divisor)
31
- @fastest_pace_km = golden_pace_set.fastest
32
- @slowest_pace_km = golden_pace_set.slowest
29
+ def initialize(fastest_pace_km, slowest_pace_km, midpoint_radius_divisor)
30
+ @fastest_pace_km = RunbyPace::PaceTime.new(fastest_pace_km)
31
+ @slowest_pace_km = RunbyPace::PaceTime.new(slowest_pace_km)
33
32
  @midpoint_radius_divisor = midpoint_radius_divisor
34
33
  end
35
34
 
36
35
  # Calculate the slope of the line between the fastest and slowest paces
37
36
  def slope
38
- (@slowest_pace_km.time.total_minutes - @fastest_pace_km.time.total_minutes) / (DATA_POINTS_COUNT - 1)
37
+ (@slowest_pace_km.total_minutes - @fastest_pace_km.total_minutes) / (DATA_POINTS_COUNT - 1)
39
38
  end
40
39
 
41
40
  # Calculate the prescribed pace for the given 5K time
42
- # @return [Pace]
43
- def calc(five_k_time, distance_units = :km)
44
- five_k_time = Runby.sanitize(five_k_time).as(RunbyTime)
45
- distance_units = Runby.sanitize(distance_units).as(DistanceUnit)
46
-
47
- minutes_per_unit = calculate_minutes_per_unit(distance_units, five_k_time)
48
- build_pace minutes_per_unit, distance_units
41
+ def calc(five_k_time)
42
+ five_k_time = RunbyPace::PaceTime.new(five_k_time)
43
+ x2 = ((five_k_time.total_minutes * 2) - (MIDPOINT_X - 1)) - 1
44
+ RunbyPace::PaceTime.from_minutes(slope * x2 + @fastest_pace_km.total_minutes + curve_minutes(x2))
49
45
  end
50
46
 
51
47
  private
52
48
 
53
- def build_pace(minutes_per_unit, distance_units)
54
- time = RunbyTime.from_minutes(minutes_per_unit)
55
- distance = Distance.new distance_units, 1
56
- Pace.new time, distance
57
- end
58
-
59
- def calculate_minutes_per_unit(distance_units, five_k_time)
60
- x2 = ((five_k_time.total_minutes * 2) - (MIDPOINT_X - 1)) - 1
61
- minutes_per_km = slope * x2 + @fastest_pace_km.time.total_minutes + curve_minutes(x2)
62
- minutes_per_km * distance_units.conversion_factor
63
- end
64
-
65
49
  # Since the paces for each 5K time do not progress in a straight line
66
50
  # when plotted on a graph, but rather a curve with its highest point near
67
51
  # the center, we must add some seconds to the calculated time depending on
@@ -71,12 +55,12 @@ module Runby
71
55
  # The default curve radius is the same as the midpoint of the X axis,
72
56
  # forming a circle. Use #midpoint_radius_divisor to reduce it's size.
73
57
  def curve_minutes(x_axis)
74
- return 0 if @midpoint_radius_divisor.zero?
58
+ return 0 if @midpoint_radius_divisor == 0
75
59
  midpoint_reduction = x_axis
76
60
  midpoint = MIDPOINT_X
77
61
  if midpoint_reduction > midpoint
78
62
  midpoint_reduction = midpoint - (midpoint_reduction - midpoint)
79
- midpoint_reduction = 0 if midpoint_reduction.negative?
63
+ midpoint_reduction = 0 if midpoint_reduction < 0
80
64
  end
81
65
  # TODO: Use an actual curve instead of a triangle to calculate the number of minutes to add.
82
66
  midpoint_reduction / @midpoint_radius_divisor / 60
@@ -1,33 +1,15 @@
1
- # frozen_string_literal: true
1
+ module RunbyPace
2
2
 
3
- require_relative 'runby_range'
3
+ class PaceRange
4
+ attr_reader :fast, :slow
4
5
 
5
- module Runby
6
- # Represents a range of paces, from fast to slow.
7
- class PaceRange < RunbyRange
8
- def initialize(fast, slow, distance_units = :km)
9
- if fast.is_a?(Pace) && slow.is_a?(Pace)
10
- @fast = fast
11
- @slow = slow
12
- else
13
- # Hopefully 'fast' and 'slow' are parseable as a RunbyTime
14
- distance = Distance.new distance_units, 1
15
- @fast = Pace.new(fast, distance)
16
- @slow = Pace.new(slow, distance)
17
- end
18
- freeze
6
+ def initialize(fast, slow)
7
+ @fast = RunbyPace::PaceTime.new(fast)
8
+ @slow = RunbyPace::PaceTime.new(slow)
19
9
  end
20
10
 
21
- def as_speed_range
22
- SpeedRange.new @fast.as_speed, @slow.as_speed
23
- end
24
-
25
- def to_s(format: :short)
26
- if @fast == @slow
27
- @fast.to_s(format: format)
28
- else
29
- @fast.to_s(format: format).sub(@fast.time.to_s, "#{@fast.time}-#{@slow.time}")
30
- end
11
+ def to_s
12
+ "#{@fast}-#{@slow}"
31
13
  end
32
14
  end
33
- end
15
+ end
@@ -0,0 +1,110 @@
1
+ module RunbyPace
2
+
3
+ class PaceTime
4
+ attr_reader :time_s, :minutes_part, :seconds_part
5
+
6
+ def initialize(time)
7
+ if time.is_a?(String) || time.is_a?(Symbol)
8
+ init_from_string(time)
9
+ elsif time.is_a?(PaceTime)
10
+ init_from_clone(time)
11
+ end
12
+ end
13
+
14
+ # @param [numeric] total_seconds
15
+ def self.from_seconds(total_seconds)
16
+ minutes = total_seconds.abs.to_i / 60
17
+ seconds = total_seconds.abs.to_i % 60
18
+ PaceTime.new("#{'%02d' % minutes}:#{'%02d' % seconds}")
19
+ end
20
+
21
+ # @param [numeric] total_minutes
22
+ def self.from_minutes(total_minutes)
23
+ self.from_seconds(total_minutes * 60.0)
24
+ end
25
+
26
+ def to_s
27
+ @time_s
28
+ end
29
+
30
+ def total_seconds
31
+ @minutes_part * 60 + @seconds_part
32
+ end
33
+
34
+ def total_minutes
35
+ @minutes_part + (@seconds_part / 60.0)
36
+ end
37
+
38
+ # @param [PaceTime] value
39
+ def -(value)
40
+ if value.is_a?(PaceTime)
41
+ PaceTime.from_seconds(total_seconds - value.total_seconds)
42
+ end
43
+ end
44
+
45
+ # @param [PaceTime] value
46
+ def +(value)
47
+ if value.is_a?(PaceTime)
48
+ PaceTime.from_seconds(total_seconds + value.total_seconds)
49
+ end
50
+ end
51
+
52
+ def ==(value)
53
+ if value.is_a?(PaceTime)
54
+ total_seconds == value.total_seconds
55
+ elsif value.is_a?(String)
56
+ @time_s == value
57
+ end
58
+ end
59
+
60
+ def almost_equals?(other_time, tolerance_time = '00:01')
61
+ if other_time.is_a?(String)
62
+ other_time = PaceTime.new(other_time)
63
+ end
64
+ tolerance = PaceTime.new(tolerance_time)
65
+ self >= (other_time - tolerance) && self <= (other_time + tolerance)
66
+ end
67
+
68
+ def >(value)
69
+ if value.is_a?(PaceTime)
70
+ total_seconds > value.total_seconds
71
+ end
72
+ end
73
+
74
+ def >=(value)
75
+ if value.is_a?(PaceTime)
76
+ total_seconds >= value.total_seconds
77
+ end
78
+ end
79
+
80
+ def <(value)
81
+ if value.is_a?(PaceTime)
82
+ total_seconds < value.total_seconds
83
+ end
84
+ end
85
+
86
+ def <=(value)
87
+ if value.is_a?(PaceTime)
88
+ total_seconds <= value.total_seconds
89
+ end
90
+ end
91
+
92
+ private
93
+
94
+ def init_from_string(time)
95
+ raise 'Invalid time format' if !time.match(/(-)?\d\d:\d\d/)
96
+ @time_s = time.to_s
97
+ parts = time.to_s.split(':')
98
+ @minutes_part = parts[0].to_i
99
+ @seconds_part = parts[1].to_i
100
+ raise 'Seconds must be less than 60' if @seconds_part.abs > 59
101
+ end
102
+
103
+ # @param [PaceTime] time
104
+ def init_from_clone(time)
105
+ @time_s = time.time_s
106
+ @minutes_part = time.minutes_part
107
+ @seconds_part = time.seconds_part
108
+ end
109
+ end
110
+ end