Class: Runby::Pace
- Inherits:
-
Object
- Object
- Runby::Pace
- Includes:
- Comparable
- Defined in:
- lib/runby_pace/pace.rb
Overview
Represents a pace consisting of a distance and a time in which that distance was covered
Instance Attribute Summary collapse
-
#distance ⇒ Object
readonly
Returns the value of attribute distance.
-
#time ⇒ Object
readonly
Returns the value of attribute time.
Class Method Summary collapse
Instance Method Summary collapse
- #+(other) ⇒ Object
- #-(other) ⇒ Object
- #<=>(other) ⇒ Object
- #almost_equals?(other_pace, tolerance_time = '00:01') ⇒ Boolean
- #as_speed ⇒ Object
- #convert_to(target_distance) ⇒ Object
- #distance_covered_over_time(time) ⇒ Object
-
#initialize(time_or_pace, distance = '1K') ⇒ Pace
constructor
A new instance of Pace.
- #meters_per_minute ⇒ Object
- #to_s(format: :short) ⇒ Object
Constructor Details
#initialize(time_or_pace, distance = '1K') ⇒ Pace
Returns a new instance of Pace.
15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/runby_pace/pace.rb', line 15 def initialize(time_or_pace, distance = '1K') case time_or_pace when RunbyTime init_from_time time_or_pace, distance when String init_from_string time_or_pace, distance else raise 'Invalid Time or Pace' end freeze end |
Instance Attribute Details
#distance ⇒ Object (readonly)
Returns the value of attribute distance.
8 9 10 |
# File 'lib/runby_pace/pace.rb', line 8 def distance @distance end |
#time ⇒ Object (readonly)
Returns the value of attribute time.
8 9 10 |
# File 'lib/runby_pace/pace.rb', line 8 def time @time end |
Class Method Details
.new(time_or_pace, distance = '1K') ⇒ Object
10 11 12 13 |
# File 'lib/runby_pace/pace.rb', line 10 def self.new(time_or_pace, distance = '1K') return time_or_pace if time_or_pace.is_a? Pace super end |
.parse(str) ⇒ Object
58 59 60 61 62 63 64 65 |
# File 'lib/runby_pace/pace.rb', line 58 def self.parse(str) str = str.to_s.strip.chomp match = str.match %r{^(?<time>[:\d]*) ?(?: per |p\/)(?<distance>(?:[\d.]+ ?)?\w+)$} raise "Invalid pace format (#{str})" unless match time = Runby::RunbyTime.new(match[:time]) distance = Runby::Distance.new(match[:distance]) Pace.new time, distance end |
Instance Method Details
#+(other) ⇒ Object
116 117 118 119 120 121 122 |
# File 'lib/runby_pace/pace.rb', line 116 def +(other) if other.is_a?(Pace) Pace.new(@time + other.convert_to(@distance).time, @distance) elsif other.is_a?(RunbyTime) Pace.new(@time + other, @distance) end end |
#-(other) ⇒ Object
107 108 109 110 111 112 113 |
# File 'lib/runby_pace/pace.rb', line 107 def -(other) if other.is_a?(Pace) Pace.new(@time - other.convert_to(@distance).time, @distance) elsif other.is_a?(RunbyTime) Pace.new(@time - other, @distance) end end |
#<=>(other) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/runby_pace/pace.rb', line 79 def <=>(other) raise "Unable to compare Runby::Pace to #{other.class}(#{other})" unless [Pace, RunbyTime, String].include? other.class if other.is_a? Pace meters_per_minute.round(2) <=> other.meters_per_minute.round(2) elsif other.is_a? RunbyTime @time <=> other elsif other.is_a? String return 0 if to_s == other || to_s(format: :long) == other return 0 if @time == other self <=> try_parse(other)[:pace] end end |
#almost_equals?(other_pace, tolerance_time = '00:01') ⇒ Boolean
92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/runby_pace/pace.rb', line 92 def almost_equals?(other_pace, tolerance_time = '00:01') if other_pace.is_a?(RunbyTime) return almost_equals?(Pace.new(other_pace, @distance), tolerance_time) end if other_pace.is_a?(String) return almost_equals?(Pace.new(other_pace, @distance), tolerance_time) if other_pace.match?(/^\d?\d:\d\d$/) other_pace = Pace.parse(other_pace) end tolerance = RunbyTime.new(tolerance_time) fast_end = (self - tolerance) slow_end = (self + tolerance) slow_end <= other_pace && other_pace <= fast_end end |
#as_speed ⇒ Object
44 45 46 47 48 49 |
# File 'lib/runby_pace/pace.rb', line 44 def as_speed total_minutes = @time.total_minutes multiplier = total_minutes.positive? ? (60 / total_minutes).round(2) : 0 distance = Runby::Distance.new(@distance.uom, multiplier) Runby::Speed.new distance end |
#convert_to(target_distance) ⇒ Object
27 28 29 30 31 32 |
# File 'lib/runby_pace/pace.rb', line 27 def convert_to(target_distance) target_distance = Distance.new(target_distance) unless target_distance.is_a?(Distance) return self if @distance == target_distance conversion_factor = target_distance / @distance Pace.new @time * conversion_factor, target_distance end |
#distance_covered_over_time(time) ⇒ Object
124 125 126 127 128 129 130 131 132 |
# File 'lib/runby_pace/pace.rb', line 124 def distance_covered_over_time(time) time = Runby.sanitize(time).as(RunbyTime) if time.total_minutes.zero? || @distance.multiplier.zero? return Runby::Distance.new(@distance.uom, 0) end divisor = @time.total_minutes / time.total_minutes / @distance.multiplier distance_covered = Runby::Distance.new(@distance.uom, 1 / divisor) distance_covered end |
#meters_per_minute ⇒ Object
51 52 53 54 55 |
# File 'lib/runby_pace/pace.rb', line 51 def meters_per_minute total_minutes = @time.total_minutes return 0 unless total_minutes.positive? @distance.meters / total_minutes end |
#to_s(format: :short) ⇒ Object
34 35 36 37 38 39 40 41 42 |
# File 'lib/runby_pace/pace.rb', line 34 def to_s(format: :short) leading_one_regex = /^1 ?/ distance_s = @distance.to_s(format: format).gsub(leading_one_regex, '') case format when :short then "#{time} p/#{distance_s}" when :long then "#{time} per #{distance_s}" else raise "Invalid string format #{format}" end end |