@@ 1,154 @@
+package main
+
+import (
+ "fmt"
+ "github.com/jessevdk/go-flags"
+ "math"
+ "os"
+)
+
+var opts struct {
+ Factor float64 `short:"f" long:"factor" default:"1.3" description:"Terrain factor"`
+ Load float64 `short:"l" long:"load" default:"0.0" description:"Load carried, Kg"`
+ Elevation float64 `short:"e" long:"elevation" default:"0.0" description:"Elevation gain, m"`
+ Equation string `short:"q" long:"equation" default:"lcda" description:"Equation used to calculate energy expenditure" choice:"lcda" choice:"pandolf" choice:"minetti"`
+ InJoul bool `long:"joul" description:"Output energy in Joul"`
+ InHours bool `long:"hours" description:"Input time in hours instead of minutes"`
+ USCUnits bool `long:"us-units" description:"Use U.S. Customary Units"`
+ All bool `short:"a" long:"all" description:"Print all data"`
+ Args struct {
+ Weight float64
+ Distance float64
+ Time float64
+ } `positional-args:"yes" required:"yes"`
+}
+
+var parser = flags.NewParser(&opts, flags.Default)
+
+func main() {
+
+ _, err := parser.Parse()
+ if err != nil {
+ if flagsErr, ok := err.(*flags.Error); ok && flagsErr.Type == flags.ErrHelp {
+ os.Exit(0)
+ } else {
+ os.Exit(1)
+ }
+ }
+
+ t := opts.Args.Time
+
+ if opts.USCUnits == true {
+ uscToIntern(&opts.Elevation, &opts.Args.Weight, &opts.Args.Distance)
+ }
+ if opts.InHours == false {
+ t = t * 60
+ } else {
+ t = t * 60 * 60
+ }
+
+ d := opts.Args.Distance * 1000 // km to m
+ s := avgSpeed(d, t) // speed of walking in m / s
+ g := opts.Elevation * 100 / (d / 2) // average grade
+
+ waU, waD := applyEq(s, g, opts.Args.Weight,
+ opts.Load, d, opts.Factor, t, opts.Equation)
+ enU, enD := wattToJ(waU, (t/2)), wattToJ(waD, (t/2))
+
+ var uE string
+ if opts.InJoul == false {
+ jToKcal(&enU)
+ jToKcal(&enD)
+ uE = "Kcal"
+ } else {
+ uE = "J"
+ }
+
+ enT := enU + enD
+
+ if opts.All == false {
+ printResult(enT, uE)
+ } else {
+ printAll(enT, enU, enD, g, uE)
+ }
+
+}
+
+func printAll(r, up, dn, g float64, un string) {
+ fmt.Printf("%f\t%s\n%f\t%s (uphill)\n%f\t%s (downhill)\n"+
+ "%f\tgrade(%%)\n", r, un, up, un, dn, un, g)
+}
+
+func printResult(r float64, u string) {
+ fmt.Printf("%d %s\n", int(math.Round(r)), u)
+}
+
+func applyEq(s, g, w, l, d, f, t float64, eq string) (float64, float64) {
+ switch eq {
+ case "minetti":
+ return apminetti(w, g, d, f, t)
+ case "pandolf":
+ return appandolf(s, g, w, l, f)
+ default:
+ return aplcda(s, g, w, l, f)
+ }
+
+}
+
+func jToKcal(j *float64) {
+ *j = *j / 4184
+}
+
+
+func santee(s, g, w, l, f float64) float64 {
+ return f * (((s * g * (w + l)) / 3.5) -
+ (((w + l) * math.Pow((g+6), 2)) / w) +
+ 25*math.Pow(s, 2))
+}
+
+func apminetti(w, g, d, f, t float64) (float64, float64) {
+ i, d, t := g/100, d/2, t/2
+ return minetti(i) * f * d * w / t, minetti(-i) * f * d * w / t
+}
+
+func minetti(i float64) float64 {
+ i = i
+ return 380.5*math.Pow(i, 5) - 58.7*math.Pow(i, 4) -
+ 76.8*math.Pow(i, 3) + 51.9*math.Pow(i, 2) +
+ 19.6*i + 2.5
+}
+
+func aplcda(s, g, w, l, f float64) (float64, float64) {
+ return lcda(s, g) * f * w, lcda(s, -g) * f * w
+}
+
+func appandolf(s, g, w, l, f float64) (float64, float64) {
+ return pandolf(s, g, w, l, f), pandolfdn(s, -g, w, l, f)
+}
+
+func lcda(s, g float64) float64 {
+ return 1.44 + math.Pow((1.44*s), 0.43) +
+ math.Pow((0.24*s), 4) +
+ 0.34*s*g*(1-math.Pow(1.05, (1-math.Pow(1.1, (g+32)))))
+}
+
+func pandolf(s, g, w, l, f float64) float64 {
+ return 1.5*w + 2*(w+l)*math.Pow((l/w), 2) +
+ f*(w+l)*(math.Pow((1.5*s), 2)+0.35*s*g)
+
+}
+
+func pandolfdn(s, g, w, l, f float64) float64 {
+ return pandolf(s, g, w, l, f) - santee(s, g, w, l, f)
+}
+
+func avgSpeed(d, t float64) float64 {
+ return d / t
+}
+
+func wattToJ(w, t float64) float64 { return w * t }
+func uscToIntern(e, w, d *float64) {
+ *e = *e / 3.2808
+ *w = *w * 0.45359237
+ *d = *d * 1.609344
+}