gobm65.go
changeset 28 3f39d3cd68ce
parent 27 e882f78c302e
child 30 0df0950f4c21
equal deleted inserted replaced
27:e882f78c302e 28:3f39d3cd68ce
    23 // ... display more statistics:
    23 // ... display more statistics:
    24 // % gobm65 --stats
    24 // % gobm65 --stats
    25 // ... also display World Health Organization classification:
    25 // ... also display World Health Organization classification:
    26 // % gobm65 --stats --class
    26 // % gobm65 --stats --class
    27 //
    27 //
       
    28 // Display all records but reduce the list so that close records are replaced
       
    29 // with their average:
       
    30 // % gobm65 --reduce
    28 // Display the latest 3 records with the average:
    31 // Display the latest 3 records with the average:
    29 // % gobm65 -l 3 --average
    32 // % gobm65 -l 3 --average
    30 // Display all records since a specific date:
    33 // Display all records since a specific date:
    31 // % gobm65 --since "2016-06-01"
    34 // % gobm65 --since "2016-06-01"
    32 // Display all records before a specific date:
    35 // Display all records before a specific date:
   344 func parseTime(timeStr string) (t simpleTime, err error) {
   347 func parseTime(timeStr string) (t simpleTime, err error) {
   345 	_, err = fmt.Sscanf(timeStr, "%d:%d", &t.hour, &t.minute)
   348 	_, err = fmt.Sscanf(timeStr, "%d:%d", &t.hour, &t.minute)
   346 	return
   349 	return
   347 }
   350 }
   348 
   351 
       
   352 // diffTime returns the duration between two (decreasing) sorted measurements
       
   353 func diffTime(a, b measurement) time.Duration {
       
   354 	dateA := time.Date(a.Year, time.Month(a.Month), a.Day, a.Hour, a.Minute, 0, 0, time.Local)
       
   355 	dateB := time.Date(b.Year, time.Month(b.Month), b.Day, b.Hour, b.Minute, 0, 0, time.Local)
       
   356 	return dateA.Sub(dateB)
       
   357 }
       
   358 
   349 func average(items []measurement) (measurement, error) {
   359 func average(items []measurement) (measurement, error) {
   350 	var avgMeasure measurement
   360 	var avgMeasure measurement
   351 	var avgCount int
   361 	var avgCount int
   352 
   362 
   353 	for _, data := range items {
   363 	for _, data := range items {
   455 	dev.Systolic = int(sumSys / float64(len(items)))
   465 	dev.Systolic = int(sumSys / float64(len(items)))
   456 	dev.Diastolic = int(sumDia / float64(len(items)))
   466 	dev.Diastolic = int(sumDia / float64(len(items)))
   457 	dev.Pulse = int(sumPul / float64(len(items)))
   467 	dev.Pulse = int(sumPul / float64(len(items)))
   458 
   468 
   459 	return dev, nil
   469 	return dev, nil
       
   470 }
       
   471 
       
   472 // reduceList reduces the measurement list by regrouping close measurements;
       
   473 // if the time difference between several measurements is less than the given
       
   474 // threshold, they are replaced with their average.
       
   475 func reduceList(list []measurement, threshold time.Duration) []measurement {
       
   476 	var newList, acc []measurement
       
   477 
       
   478 	// flushAcc flushes the accumulator and adds an average measurement to
       
   479 	// the new list.
       
   480 	flushAcc := func() {
       
   481 		// setAvgTime computes the average date of the list and sets
       
   482 		// the measurement date to this average.
       
   483 		setAvgTime := func(m *measurement, l []measurement) {
       
   484 			var timestamp int64 = 0
       
   485 			for _, i := range l {
       
   486 				iDate := time.Date(i.Year, time.Month(i.Month), i.Day,
       
   487 					i.Hour, i.Minute, 0, 0, time.Local)
       
   488 				timestamp += iDate.Unix()
       
   489 			}
       
   490 			timestamp /= int64(len(l))
       
   491 			avgTime := time.Unix(timestamp, 0)
       
   492 			m.Year = avgTime.Year()
       
   493 			m.Month = int(avgTime.Month())
       
   494 			m.Day = avgTime.Day()
       
   495 			m.Hour = avgTime.Hour()
       
   496 			m.Minute = avgTime.Minute()
       
   497 		}
       
   498 		avg, _ := average(acc)
       
   499 		avg.Header = acc[0].Header // Arbitrary…
       
   500 		setAvgTime(&avg, acc)
       
   501 		newList = append(newList, avg)
       
   502 		acc = acc[:0]
       
   503 	}
       
   504 
       
   505 	for _, item := range list {
       
   506 		if len(acc) > 0 && diffTime(acc[len(acc)-1], item) > threshold {
       
   507 			flushAcc()
       
   508 		}
       
   509 		acc = append(acc, item)
       
   510 	}
       
   511 	flushAcc()
       
   512 	return newList
   460 }
   513 }
   461 
   514 
   462 func (m measurement) WHOClass() (int, int) {
   515 func (m measurement) WHOClass() (int, int) {
   463 	flag := 0
   516 	flag := 0
   464 
   517 
   525 	whoClass := flag.BoolP("class", "c", false, "Display WHO classification")
   578 	whoClass := flag.BoolP("class", "c", false, "Display WHO classification")
   526 	merge := flag.BoolP("merge", "m", false, "Try to merge input JSON file with fetched data")
   579 	merge := flag.BoolP("merge", "m", false, "Try to merge input JSON file with fetched data")
   527 	device := flag.StringP("device", "d", "/dev/ttyUSB0", "Serial device")
   580 	device := flag.StringP("device", "d", "/dev/ttyUSB0", "Serial device")
   528 	fromTime := flag.String("from-time", "", "Select records after time (HH:MM)")
   581 	fromTime := flag.String("from-time", "", "Select records after time (HH:MM)")
   529 	toTime := flag.String("to-time", "", "Select records bofore time (HH:MM)")
   582 	toTime := flag.String("to-time", "", "Select records bofore time (HH:MM)")
       
   583 	reduce := flag.BoolP("reduce", "r", false, "Reduce number of measurements (regroup measurements)")
   530 
   584 
   531 	flag.StringVar(fromDate, "since", "", "Same as --from-date")
   585 	flag.StringVar(fromDate, "since", "", "Same as --from-date")
   532 
   586 
   533 	var startTime, endTime simpleTime
   587 	var startTime, endTime simpleTime
   534 
   588 
   659 				continue
   713 				continue
   660 			}
   714 			}
   661 			newItems = append(newItems, data)
   715 			newItems = append(newItems, data)
   662 		}
   716 		}
   663 		items = newItems
   717 		items = newItems
       
   718 	}
       
   719 
       
   720 	if *reduce {
       
   721 		items = reduceList(items, time.Hour)
   664 	}
   722 	}
   665 
   723 
   666 	if *limit > 0 && len(items) > int(*limit) {
   724 	if *limit > 0 && len(items) > int(*limit) {
   667 		items = items[0:*limit]
   725 		items = items[0:*limit]
   668 	}
   726 	}