package main import ( "fmt" "os" ) type OTS_DataPoint struct { TimeStamp float64 Rate float64 } type OTS_Data struct { TSData []OTS_DataPoint } /* Functions for the sort interface. */ func (obj *OTS_Data) Len () int { return (len (obj.TSData)) } func (obj *OTS_Data) Less (i, j int) bool { if obj.TSData[i].TimeStamp < obj.TSData[j].TimeStamp { return true } return false } func (obj *OTS_Data) Swap (i, j int) { tmp := obj.TSData[i] obj.TSData[i] = obj.TSData[j] obj.TSData[j] = tmp } func Fmod64 (a float64, b float64) float64 { tmp := int (a / b) return b * float64 (tmp) } func (obj *OTS_Data) Write (name string) os.Error { fd, err := os.OpenFile(name, os.O_WRONLY, 0666) if err != nil { return err } for i := 0; i < len (obj.TSData); i++ { data_point := obj.TSData[i] str := fmt.Sprintf ("%.3f,%g\n", data_point.TimeStamp, data_point.Rate) fd.WriteString (str) } fd.Close () return nil } func ReadFile (name string) (obj *OTS_Data, err os.Error) { } func (raw_data *OTS_Data) Consolidate (interval float64) *OTS_Data { if interval <= 0.0 { return nil } ts_raw_first := raw_data.TSData[0].TimeStamp ts_raw_last := ts_raw_first /* Determine the first and last data point. * XXX: In the future, this should be a sorted list! */ for i := 1; i < len (raw_data.TSData); i++ { data_point := raw_data.TSData[i] if ts_raw_first > data_point.TimeStamp { ts_raw_first = data_point.TimeStamp } if ts_raw_last < data_point.TimeStamp { ts_raw_last = data_point.TimeStamp } } fmt.Printf ("ts_raw_first = %g; ts_raw_last = %g;\n", ts_raw_first, ts_raw_last) /* Determine the timespan the consolidated data will span. */ ts_csl_first := Fmod64 (ts_raw_first, interval) ts_csl_last := Fmod64 (ts_raw_last, interval) if ts_csl_last < ts_raw_last { ts_csl_last += interval } fmt.Printf ("ts_csl_first = %g; ts_csl_last = %g;\n", ts_csl_first, ts_csl_last) intervals_num := int ((ts_csl_last - ts_csl_first) / interval) fmt.Printf ("Got a %gs timespan (%d intervals).\n", ts_csl_last - ts_csl_first, intervals_num) /* Allocate return structure */ ret_data := new (OTS_Data) ret_data.TSData = make ([]OTS_DataPoint, intervals_num) /* FIXME: This is currently a O(n^2) algorithm. It should instead be a O(n) * algorithm. This is possible if raw_data is sorted (which, obviously, is a * O(n log(n)) task). */ for i := 0; i < intervals_num; i++ { ts := ts_csl_first + (float64 (i) * interval) sum := 0.0 num := 0.0 fmt.Printf ("Building data for interval %g.\n", ts) ret_data.TSData[i].TimeStamp = ts for j := 0; j < len (raw_data.TSData); j++ { data_point := raw_data.TSData[j] if ((data_point.TimeStamp < ts) || (data_point.TimeStamp >= (ts + interval))) { continue } sum += data_point.Rate num += 1.0 } /* TODO: Be more clever about how this consolidated rate is computed. */ if num > 0.0 { ret_data.TSData[i].Rate = sum / num } } return ret_data } func (obj *OTS_Data) Print () { for i := 0; i < len (obj.TSData); i++ { data_point := obj.TSData[i] fmt.Printf ("[%g] %g\n", data_point.TimeStamp, data_point.Rate) } } /* Print () */ func main () { var data_points []OTS_DataPoint var raw_data *OTS_Data var new_data *OTS_Data data_points = []OTS_DataPoint { {0.0, 1.0}, {1.0, 2.0}, {2.0, 5.0}, {3.0, 8.0}, {4.0, 0.0}, {5.0, 3.0}} raw_data = new (OTS_Data) raw_data.TSData = data_points new_data = raw_data.Consolidate (2.0) new_data.Print() }