fix trend calculation if days are missing by linear interpolation
This commit is contained in:
parent
79282317b1
commit
b1c5b729d1
76
hdiet.go
76
hdiet.go
|
@ -102,14 +102,21 @@ type yRange struct {
|
|||
max float64
|
||||
}
|
||||
|
||||
func process(file string) ([]point, error) {
|
||||
func readFile(file string) (map[time.Time]float64, time.Time, time.Time) {
|
||||
optPanic := func(err error) {
|
||||
if err != nil {
|
||||
panic("process:" + err.Error())
|
||||
}
|
||||
}
|
||||
weights, err := goutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, time.Time{}, time.Time{}
|
||||
}
|
||||
lines := strings.Split(weights, "\n")
|
||||
trend := 0.0
|
||||
s := []point{}
|
||||
var firstDay time.Time
|
||||
firstDayIsSet := false
|
||||
var lastDay time.Time
|
||||
dateToWeight := make(map[time.Time]float64)
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if len(line) == 0 {
|
||||
|
@ -117,18 +124,58 @@ func process(file string) ([]point, error) {
|
|||
}
|
||||
splitline := strings.Split(line, "\t")
|
||||
if len(splitline) < 2 {
|
||||
return nil, errors.New("process - invalid line in weight file: " + line)
|
||||
optPanic(errors.New("invalid line in weight file " + file + ": " + line))
|
||||
}
|
||||
date, err := time.Parse(dateLayout, splitline[0])
|
||||
optPanic(err)
|
||||
weight, err := strconv.ParseFloat(splitline[1], 64)
|
||||
optPanic(err)
|
||||
if !firstDayIsSet {
|
||||
firstDay = date
|
||||
firstDayIsSet = true
|
||||
}
|
||||
lastDay = date
|
||||
dateToWeight[date] = weight
|
||||
}
|
||||
return dateToWeight, firstDay, lastDay
|
||||
}
|
||||
|
||||
func process(file string) []point {
|
||||
dateToWeight, firstDay, lastDay := readFile(file)
|
||||
if dateToWeight == nil {
|
||||
return []point{}
|
||||
}
|
||||
trend := 0.0
|
||||
points := []point{}
|
||||
for d := firstDay; d.Before(lastDay) || d == lastDay; d = d.AddDate(0, 0, 1) {
|
||||
var weight float64
|
||||
if w, ok := dateToWeight[d]; ok {
|
||||
weight = w
|
||||
} else {
|
||||
prevPoint := points[len(points)-1]
|
||||
prevDay := prevPoint.date
|
||||
prevWeight := prevPoint.weight
|
||||
var nextWeight float64
|
||||
var nextDay time.Time
|
||||
for nextDay = d.AddDate(0, 0, 1); nextDay.Before(lastDay) || nextDay == lastDay; nextDay = nextDay.AddDate(0, 0, 1) {
|
||||
if w, ok := dateToWeight[nextDay]; ok {
|
||||
nextWeight = w
|
||||
break
|
||||
}
|
||||
}
|
||||
days := nextDay.Sub(prevDay).Hours() / 24
|
||||
changePerDay := (nextWeight - prevWeight) / days
|
||||
weight = prevWeight + changePerDay
|
||||
}
|
||||
date, _ := time.Parse(dateLayout, splitline[0])
|
||||
weight, _ := strconv.ParseFloat(splitline[1], 64)
|
||||
if trend == 0.0 {
|
||||
trend = weight
|
||||
} else {
|
||||
trend = math.Floor((trend+0.1*(weight-trend))*100) / 100
|
||||
}
|
||||
s = append(s, point{date, weight, trend})
|
||||
points = append(points, point{d, weight, trend})
|
||||
|
||||
}
|
||||
return s, nil
|
||||
return points
|
||||
}
|
||||
|
||||
type showFlags struct {
|
||||
|
@ -138,11 +185,8 @@ type showFlags struct {
|
|||
}
|
||||
|
||||
func show(args showFlags) error {
|
||||
points, err := process(logfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dietpoints, _ := process(dietfile)
|
||||
points := process(logfile)
|
||||
dietpoints := process(dietfile)
|
||||
var to time.Time
|
||||
var from time.Time
|
||||
if args.to.date != nil {
|
||||
|
@ -170,7 +214,7 @@ func show(args showFlags) error {
|
|||
YRange.min = math.Floor(YRange.min) - 1.0
|
||||
YRange.max = math.Ceil(YRange.max) + 1.0
|
||||
graph := graph(xticks(xRange), s1, s2, s3, YRange)
|
||||
err = writeGraphToFile(graph)
|
||||
err := writeGraphToFile(graph)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -194,7 +238,7 @@ func showCommand() (goutil.CommandFlagsInit, goutil.CommandFunc) {
|
|||
func writeDietFile(from time.Time, initial float64, goal float64, change float64) error {
|
||||
date := from
|
||||
weight := initial
|
||||
s := "#Date\tTarget\n"
|
||||
s := ""
|
||||
s += fmt.Sprintf("%s\t%.1f\n", date.Format(dateLayout), weight)
|
||||
for weight > goal {
|
||||
date = date.AddDate(0, 0, 1)
|
||||
|
|
Loading…
Reference in New Issue
Block a user