gobm65.go
changeset 8 366f991716a9
parent 7 17a1a3f4fb86
child 9 588f7779b0b5
equal deleted inserted replaced
7:17a1a3f4fb86 8:366f991716a9
    43 	"encoding/json"
    43 	"encoding/json"
    44 	"fmt"
    44 	"fmt"
    45 	"io"
    45 	"io"
    46 	"io/ioutil"
    46 	"io/ioutil"
    47 	"log"
    47 	"log"
       
    48 	"math"
       
    49 	"sort"
    48 	"time"
    50 	"time"
    49 
    51 
    50 	flag "github.com/docker/docker/pkg/mflag"
    52 	flag "github.com/docker/docker/pkg/mflag"
    51 	"github.com/tarm/serial"
    53 	"github.com/tarm/serial"
    52 )
    54 )
   215 	}
   217 	}
   216 	date = time.Date(yy, time.Month(mm), dd, h, m, s, 0, time.Local)
   218 	date = time.Date(yy, time.Month(mm), dd, h, m, s, 0, time.Local)
   217 	return
   219 	return
   218 }
   220 }
   219 
   221 
       
   222 func average(items []measurement) (measurement, error) {
       
   223 	var avgMeasure measurement
       
   224 	var avgCount int
       
   225 
       
   226 	for _, data := range items {
       
   227 		avgMeasure.Systolic += data.Systolic
       
   228 		avgMeasure.Diastolic += data.Diastolic
       
   229 		avgMeasure.Pulse += data.Pulse
       
   230 		avgCount++
       
   231 	}
       
   232 
       
   233 	roundDivision := func(a, b int) int {
       
   234 		return int(0.5 + float64(a)/float64(b))
       
   235 	}
       
   236 
       
   237 	if avgCount == 0 {
       
   238 		return avgMeasure, fmt.Errorf("cannot compute average: empty set")
       
   239 	}
       
   240 
       
   241 	avgMeasure.Systolic = roundDivision(avgMeasure.Systolic, avgCount)
       
   242 	avgMeasure.Diastolic = roundDivision(avgMeasure.Diastolic, avgCount)
       
   243 	avgMeasure.Pulse = roundDivision(avgMeasure.Pulse, avgCount)
       
   244 
       
   245 	return avgMeasure, nil
       
   246 }
       
   247 
       
   248 func intMedian(numbers []int) int {
       
   249 	middle := len(numbers) / 2
       
   250 	med := numbers[middle]
       
   251 	if len(numbers)%2 == 0 {
       
   252 		med = (med + numbers[middle-1]) / 2
       
   253 	}
       
   254 	return med
       
   255 }
       
   256 
       
   257 func median(items []measurement) (measurement, error) {
       
   258 	var med measurement
       
   259 	if len(items) == 0 {
       
   260 		return med, fmt.Errorf("cannot compute average: empty set")
       
   261 	}
       
   262 
       
   263 	var sys, dia, pul []int
       
   264 	for _, data := range items {
       
   265 		sys = append(sys, data.Systolic)
       
   266 		dia = append(dia, data.Diastolic)
       
   267 		pul = append(pul, data.Pulse)
       
   268 	}
       
   269 
       
   270 	sort.Ints(sys)
       
   271 	sort.Ints(dia)
       
   272 	sort.Ints(pul)
       
   273 
       
   274 	med.Systolic = intMedian(sys)
       
   275 	med.Diastolic = intMedian(dia)
       
   276 	med.Pulse = intMedian(pul)
       
   277 
       
   278 	return med, nil
       
   279 }
       
   280 
       
   281 func stdDeviation(items []measurement) (measurement, error) {
       
   282 	var sDev measurement
       
   283 
       
   284 	if len(items) <= 1 {
       
   285 		return sDev, fmt.Errorf("cannot compute deviation: set too small")
       
   286 	}
       
   287 
       
   288 	var sumSys, sumDia, sumPul float64
       
   289 	avg, err := average(items)
       
   290 	if err != nil {
       
   291 		return sDev, err
       
   292 	}
       
   293 
       
   294 	for _, data := range items {
       
   295 		sumSys += math.Pow(float64(data.Systolic-avg.Systolic), 2)
       
   296 		sumDia += math.Pow(float64(data.Diastolic-avg.Diastolic), 2)
       
   297 		sumPul += math.Pow(float64(data.Pulse-avg.Pulse), 2)
       
   298 	}
       
   299 
       
   300 	sDev.Systolic = int(math.Sqrt(sumSys / float64(len(items)-1)))
       
   301 	sDev.Diastolic = int(math.Sqrt(sumDia / float64(len(items)-1)))
       
   302 	sDev.Pulse = int(math.Sqrt(sumPul / float64(len(items)-1)))
       
   303 
       
   304 	return sDev, nil
       
   305 }
       
   306 
   220 func main() {
   307 func main() {
   221 	inFile := flag.String([]string{"-input-file", "i"}, "", "Input JSON file")
   308 	inFile := flag.String([]string{"-input-file", "i"}, "", "Input JSON file")
   222 	outFile := flag.String([]string{"-output-file", "o"}, "", "Output JSON file")
   309 	outFile := flag.String([]string{"-output-file", "o"}, "", "Output JSON file")
   223 	limit := flag.Uint([]string{"-limit", "l"}, 0, "Limit number of items to N first")
   310 	limit := flag.Uint([]string{"-limit", "l"}, 0, "Limit number of items to N first")
   224 	since := flag.String([]string{"-since"}, "",
   311 	since := flag.String([]string{"-since"}, "",
   225 		"Filter records from date (YYYY-mm-dd HH:MM:SS)")
   312 		"Filter records from date (YYYY-mm-dd HH:MM:SS)")
   226 	format := flag.String([]string{"-format", "f"}, "", "Output format (csv, json)")
   313 	format := flag.String([]string{"-format", "f"}, "", "Output format (csv, json)")
   227 	avg := flag.Bool([]string{"-average", "a"}, false, "Compute average")
   314 	avg := flag.Bool([]string{"-average", "a"}, false, "Compute average")
       
   315 	stats := flag.Bool([]string{"-stats"}, false, "Compute statistics")
   228 	merge := flag.Bool([]string{"-merge", "m"}, false,
   316 	merge := flag.Bool([]string{"-merge", "m"}, false,
   229 		"Try to merge input JSON file with fetched data")
   317 		"Try to merge input JSON file with fetched data")
   230 	device := flag.String([]string{"-device", "d"}, "/dev/ttyUSB0", "Serial device")
   318 	device := flag.String([]string{"-device", "d"}, "/dev/ttyUSB0", "Serial device")
   231 
   319 
   232 	flag.Parse()
   320 	flag.Parse()
   286 
   374 
   287 	if *limit > 0 && len(items) > int(*limit) {
   375 	if *limit > 0 && len(items) > int(*limit) {
   288 		items = items[0:*limit]
   376 		items = items[0:*limit]
   289 	}
   377 	}
   290 
   378 
   291 	var avgMeasure measurement
   379 	if *format == "csv" {
   292 	var avgCount int
   380 		for i, data := range items {
   293 
       
   294 	for i, data := range items {
       
   295 		if *format == "csv" {
       
   296 			fmt.Printf("%d;%x;%d-%02d-%02d %02d:%02d;%d;%d;%d\n",
   381 			fmt.Printf("%d;%x;%d-%02d-%02d %02d:%02d;%d;%d;%d\n",
   297 				i+1, data.Header,
   382 				i+1, data.Header,
   298 				data.Year, data.Month, data.Day,
   383 				data.Year, data.Month, data.Day,
   299 				data.Hour, data.Minute,
   384 				data.Hour, data.Minute,
   300 				data.Systolic, data.Diastolic, data.Pulse)
   385 				data.Systolic, data.Diastolic, data.Pulse)
   301 		}
   386 		}
   302 
   387 	}
   303 		avgMeasure.Systolic += data.Systolic
   388 
   304 		avgMeasure.Diastolic += data.Diastolic
   389 	if *stats {
   305 		avgMeasure.Pulse += data.Pulse
   390 		*avg = true
   306 		avgCount++
   391 	}
   307 	}
   392 
   308 
   393 	if *avg && len(items) > 0 {
   309 	if *avg && avgCount > 0 {
   394 		avgMeasure, err := average(items)
   310 		roundDivision := func(a, b int) int {
   395 		if err != nil {
   311 			return int(0.5 + float64(a)/float64(b))
   396 			log.Println("Error:", err)
   312 		}
   397 		} else {
   313 		avgMeasure.Systolic = roundDivision(avgMeasure.Systolic, avgCount)
   398 			fmt.Printf("Average: %d;%d;%d\n", avgMeasure.Systolic,
   314 		avgMeasure.Diastolic = roundDivision(avgMeasure.Diastolic, avgCount)
   399 				avgMeasure.Diastolic, avgMeasure.Pulse)
   315 		avgMeasure.Pulse = roundDivision(avgMeasure.Pulse, avgCount)
   400 		}
   316 
   401 	}
   317 		fmt.Printf("Average: %d;%d;%d\n", avgMeasure.Systolic,
   402 
   318 			avgMeasure.Diastolic, avgMeasure.Pulse)
   403 	if *stats && len(items) > 1 {
       
   404 		d, err := stdDeviation(items)
       
   405 		if err != nil {
       
   406 			log.Println("Error:", err)
       
   407 		} else {
       
   408 			fmt.Printf("Standard deviation: %d;%d;%d\n",
       
   409 				d.Systolic, d.Diastolic, d.Pulse)
       
   410 		}
       
   411 	}
       
   412 	if *stats && len(items) > 0 {
       
   413 		m, err := median(items)
       
   414 		if err != nil {
       
   415 			log.Println("Error:", err)
       
   416 		} else {
       
   417 			fmt.Printf("Median values: %d;%d;%d\n",
       
   418 				m.Systolic, m.Diastolic, m.Pulse)
       
   419 		}
   319 	}
   420 	}
   320 
   421 
   321 	if *format == "json" || *outFile != "" {
   422 	if *format == "json" || *outFile != "" {
   322 		rawJSON, err := json.MarshalIndent(items, "", "  ")
   423 		rawJSON, err := json.MarshalIndent(items, "", "  ")
   323 		if err != nil {
   424 		if err != nil {