class Runby::Pace
Represents a pace consisting of a distance and a time in which that distance was covered
Attributes
distance[R]
time[R]
Public Class Methods
new(time_or_pace, distance = '1K')
click to toggle source
Calls superclass method
# 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
new(time_or_pace, distance = '1K')
click to toggle source
# 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
parse(str)
click to toggle source
@param [String] str is either a long-form pace such as “10:00 per mile” or a short-form pace like “10:00 p/mi”
# 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
try_parse(str)
click to toggle source
# File lib/runby_pace/pace.rb, line 67 def self.try_parse(str) pace = nil error_message = nil warning_message = nil begin pace = Pace.parse str rescue StandardError => ex error_message = ex.message end { pace: pace, error: error_message, warning: warning_message } end
Public Instance Methods
+(other)
click to toggle source
@param [Pace, RunbyTime] other
# 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)
click to toggle source
@param [Pace, RunbyTime] other
# 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)
click to toggle source
# 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')
click to toggle source
# 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()
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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()
click to toggle source
# 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)
click to toggle source
# 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
Private Instance Methods
init_from_string(string, distance = '1K')
click to toggle source
# File lib/runby_pace/pace.rb, line 136 def init_from_string(string, distance = '1K') pace = Pace.try_parse(string) if pace[:pace] @time = pace[:pace].time @distance = pace[:pace].distance return end @time = Runby::RunbyTime.new string @distance = Runby::Distance.new distance end
init_from_time(time, distance)
click to toggle source
# File lib/runby_pace/pace.rb, line 147 def init_from_time(time, distance) @time = time @distance = Runby::Distance.new distance end