~quanrong/calories

c57c3201824b0046389cc8d6577a084e6446ef58 — quanrong 3 years ago
Initial commit
4 files changed, 162 insertions(+), 0 deletions(-)

A README.md
A calories.go
A go.mod
A go.sum
A  => README.md +1 -0
@@ 1,1 @@
Calculate your calories burned hiking

A  => calories.go +154 -0
@@ 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
}

A  => go.mod +5 -0
@@ 1,5 @@
module sr.ht/~quanrong/calories

go 1.14

require github.com/jessevdk/go-flags v1.4.0

A  => go.sum +2 -0
@@ 1,2 @@
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=