class Runby::PaceCalculator
Encapsulates the algorithms used to calculate target paces.
Constants
- DATA_POINTS_COUNT
The number of data points plotted on our line of 5K times.
We take 5K times from 14:00 to 42:00 with a sample rate of 30 seconds, and out pops 57.
- MIDPOINT_X
The midpoint along the X axis of our pace data “graph”
Attributes
fastest_pace_km[R]
The fastest pace within the run type data set.
Given a personal record of 14 minutes for a 5K race, this is the prescribed pace for this run type.
midpoint_radius_divisor[R]
For maximum flexibility, we assume the radius of the curve
of the pace data to be equal to the X axis midpoint, a perfect circle. Use the midpoint_radius_divisor to reduce the height of the curve until it matches that of the data. (See #curve_minutes)
slowest_pace_km[R]
The slowest pace for the run type data set.
Given a personal record of 42 minutes for a 5K race, this is the prescribed pace for this run type.
Public Class Methods
new(golden_pace_set, midpoint_radius_divisor)
click to toggle source
# File lib/runby_pace/pace_calculator.rb, line 30 def initialize(golden_pace_set, midpoint_radius_divisor) @fastest_pace_km = golden_pace_set.fastest @slowest_pace_km = golden_pace_set.slowest @midpoint_radius_divisor = midpoint_radius_divisor end
Public Instance Methods
calc(five_k_time, distance_units = :km)
click to toggle source
Calculate the prescribed pace for the given 5K time @return [Pace]
# File lib/runby_pace/pace_calculator.rb, line 43 def calc(five_k_time, distance_units = :km) five_k_time = Runby.sanitize(five_k_time).as(RunbyTime) distance_units = Runby.sanitize(distance_units).as(DistanceUnit) minutes_per_unit = calculate_minutes_per_unit(distance_units, five_k_time) build_pace minutes_per_unit, distance_units end
slope()
click to toggle source
Calculate the slope of the line between the fastest and slowest paces
# File lib/runby_pace/pace_calculator.rb, line 37 def slope (@slowest_pace_km.time.total_minutes - @fastest_pace_km.time.total_minutes) / (DATA_POINTS_COUNT - 1) end
Private Instance Methods
build_pace(minutes_per_unit, distance_units)
click to toggle source
# File lib/runby_pace/pace_calculator.rb, line 53 def build_pace(minutes_per_unit, distance_units) time = RunbyTime.from_minutes(minutes_per_unit) distance = Distance.new distance_units, 1 Pace.new time, distance end
calculate_minutes_per_unit(distance_units, five_k_time)
click to toggle source
# File lib/runby_pace/pace_calculator.rb, line 59 def calculate_minutes_per_unit(distance_units, five_k_time) x2 = ((five_k_time.total_minutes * 2) - (MIDPOINT_X - 1)) - 1 minutes_per_km = slope * x2 + @fastest_pace_km.time.total_minutes + curve_minutes(x2) minutes_per_km * distance_units.conversion_factor end
curve_minutes(x_axis)
click to toggle source
Since the paces for each 5K time do not progress in a straight line
when plotted on a graph, but rather a curve with its highest point near the center, we must add some seconds to the calculated time depending on where we are on the line.
Paces near the start and end of the line need little to no time added,
whereas paces near the middle need the most time added.
The default curve radius is the same as the midpoint of the X axis,
forming a circle. Use #midpoint_radius_divisor to reduce it's size.
# File lib/runby_pace/pace_calculator.rb, line 73 def curve_minutes(x_axis) return 0 if @midpoint_radius_divisor.zero? midpoint_reduction = x_axis midpoint = MIDPOINT_X if midpoint_reduction > midpoint midpoint_reduction = midpoint - (midpoint_reduction - midpoint) midpoint_reduction = 0 if midpoint_reduction.negative? end # TODO: Use an actual curve instead of a triangle to calculate the number of minutes to add. midpoint_reduction / @midpoint_radius_divisor / 60 end