Last active
March 1, 2019 14:59
-
-
Save aldipower/4d649c10ca2ec90510bc7181419fff15 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"math" | |
"os" | |
"strconv" | |
"strings" | |
) | |
func printHelp() { | |
fmt.Print(`Running cadence calculator - Written by Felix Gertz | |
Calculates optimal cadence (steps per minute) | |
for specfic pace and body height relations to gain optimal hip extension. | |
Just put in your body height and optionally a specific pace | |
and you will get the optimal cadence for a natural movement of your legs | |
assumed they land underneath your body. | |
Usage: | |
cadence bodyHeightInCm [paceMinKm] | |
Example: | |
cadence 177 | |
cadence 177 4:00 | |
`) | |
} | |
// Calculates the optimal running cadence for given speed and body height | |
func calcCadence(speedKmh float64, bodyHeightCm int) (int) { | |
cadenceSpm := | |
math.Ceil(160 + (speedKmh - 6) * 2.5 - (float64(bodyHeightCm) - 170) / 2) | |
return int(cadenceSpm) | |
} | |
func speedToPace(speedKmh float64) (string) { | |
paceMinkm := 60 / speedKmh | |
minutes := math.Floor(paceMinkm) | |
seconds := math.Floor((paceMinkm - minutes) * 60) | |
return fmt.Sprintf("%02d:%02d", int(minutes), int(seconds)) | |
} | |
// Converts min/km to km/h | |
func paceToSpeed(pace *string) (float64, error) { | |
var segments []string = strings.Split(*pace, ":") | |
if len(segments) != 2 { | |
return 0, fmt.Errorf("Cannot parse pace string: %s", *pace) | |
} | |
minutes, parseErr := strconv.Atoi(segments[0]); | |
if parseErr != nil { | |
return 0, | |
fmt.Errorf("Cannot parse minutes portion of pace string: %s", *pace) | |
} | |
seconds, parseErr := strconv.Atoi(segments[1]); | |
if parseErr != nil { | |
return 0, | |
fmt.Errorf("Cannot parse seconds portion of pace string: %s", *pace) | |
} | |
return 60 / (float64(minutes) + float64(seconds) / 60), nil | |
} | |
func parseArguments() (int, string, error) { | |
var bodyHeight int | |
var pace string | |
var parseErr error | |
switch len(os.Args[1:]) { | |
case 2: | |
pace = os.Args[2] | |
fallthrough | |
case 1: | |
bodyHeight, parseErr = strconv.Atoi(os.Args[1]) | |
if parseErr != nil { | |
return 0, "", | |
fmt.Errorf("Could not parse body height argument: %s", os.Args[1]) | |
} | |
default: | |
return 0, "", fmt.Errorf("Wrong number of arguments") | |
} | |
return bodyHeight, pace, nil | |
} | |
func main() { | |
onError := func(err error) { | |
if err != nil { | |
printHelp() | |
fmt.Fprintf(os.Stderr, "\nError: %s\n", err) | |
os.Exit(1) | |
} | |
} | |
printResultline := func(speed float64, bodyHeight int) { | |
fmt.Printf("%s %d\n", speedToPace(speed), calcCadence(speed, bodyHeight)) | |
} | |
bodyHeight, pace, err := parseArguments() | |
onError(err) | |
fmt.Printf("Pace (min/km) and cadence (spm) for %dcm body height\n", bodyHeight) | |
if len(pace) > 0 { | |
speed, err := paceToSpeed(&pace) | |
onError(err) | |
printResultline(speed, bodyHeight) | |
} else { | |
for speed := 7.0; speed <= 26.0; speed += 0.4 { | |
printResultline(speed, bodyHeight) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment