diff --git a/cmd/chart/main.go b/cmd/chart/main.go index 216062a..8818663 100644 --- a/cmd/chart/main.go +++ b/cmd/chart/main.go @@ -11,11 +11,16 @@ import ( ) var ( - outputPath = flag.String("output", "", "The output file") - inputFormat = flag.String("format", "csv", "The input format, either 'csv' or 'tsv' (defaults to 'csv')") - inputPath = flag.String("f", "", "The input file") - disableLinreg = flag.Bool("disable-linreg", false, "If we should omit linear regressions") - disableLastValues = flag.Bool("disable-last-values", false, "If we should omit last values") + outputPath = flag.String("output", "", "The output file") + + inputFormat = flag.String("format", "csv", "The input format, either 'csv' or 'tsv' (defaults to 'csv')") + inputPath = flag.String("f", "", "The input file") + reverse = flag.Bool("reverse", false, "If we should reverse the inputs") + + hideLegend = flag.Bool("hide-legend", false, "If we should omit the chart legend") + hideSMA = flag.Bool("hide-sma", false, "If we should omit simple moving average") + hideLinreg = flag.Bool("hide-linreg", false, "If we should omit linear regressions") + hideLastValues = flag.Bool("hide-last-values", false, "If we should omit last values") ) func main() { @@ -58,6 +63,10 @@ func main() { log.FatalErr(err) } + if *reverse { + yvalues = chart.ValueSequence(yvalues...).Reverse().Values() + } + var series []chart.Series mainSeries := chart.ContinuousSeries{ Name: "Values", @@ -66,17 +75,57 @@ func main() { } series = append(series, mainSeries) - if !*disableLinreg { - linRegSeries := &chart.LinearRegressionSeries{ - InnerSeries: mainSeries, - } - series = append(series, linRegSeries) + smaSeries := &chart.SMASeries{ + Name: "SMA", + Style: chart.Style{ + Hidden: *hideSMA, + StrokeColor: chart.ColorRed, + StrokeDashArray: []float64{5.0, 5.0}, + }, + InnerSeries: mainSeries, } + series = append(series, smaSeries) + + linRegSeries := &chart.LinearRegressionSeries{ + Name: "Values - Lin. Reg.", + Style: chart.Style{ + Hidden: *hideLinreg, + }, + InnerSeries: mainSeries, + } + series = append(series, linRegSeries) + + mainLastValue := chart.LastValueAnnotationSeries(mainSeries) + mainLastValue.Style = chart.Style{ + Hidden: *hideLastValues, + } + series = append(series, mainLastValue) + + linregLastValue := chart.LastValueAnnotationSeries(linRegSeries) + linregLastValue.Style = chart.Style{ + Hidden: (*hideLastValues || *hideLinreg), + } + series = append(series, linregLastValue) + + smaLastValue := chart.LastValueAnnotationSeries(smaSeries) + smaLastValue.Style = chart.Style{ + Hidden: (*hideLastValues || *hideSMA), + } + series = append(series, smaLastValue) graph := chart.Chart{ + Background: chart.Style{ + Padding: chart.Box{ + Top: 50, + }, + }, Series: series, } + if !*hideLegend { + graph.Elements = []chart.Renderable{chart.LegendThin(&graph)} + } + var output *os.File if *outputPath != "" { output, err = os.Create(*outputPath) diff --git a/last_value_annotation.go b/last_value_annotation_series.go similarity index 81% rename from last_value_annotation.go rename to last_value_annotation_series.go index f3d4b46..550c367 100644 --- a/last_value_annotation.go +++ b/last_value_annotation_series.go @@ -2,8 +2,8 @@ package chart import "fmt" -// LastValueAnnotation returns an annotation series of just the last value of a value provider. -func LastValueAnnotation(innerSeries ValuesProvider, vfs ...ValueFormatter) AnnotationSeries { +// LastValueAnnotationSeries returns an annotation series of just the last value of a value provider. +func LastValueAnnotationSeries(innerSeries ValuesProvider, vfs ...ValueFormatter) AnnotationSeries { var vf ValueFormatter if len(vfs) > 0 { vf = vfs[0] diff --git a/last_value_annotation_test.go b/last_value_annotation_series_test.go similarity index 79% rename from last_value_annotation_test.go rename to last_value_annotation_series_test.go index 3d1931f..651105d 100644 --- a/last_value_annotation_test.go +++ b/last_value_annotation_series_test.go @@ -6,7 +6,7 @@ import ( "github.com/blend/go-sdk/assert" ) -func TestLastValueAnnotation(t *testing.T) { +func TestLastValueAnnotationSeries(t *testing.T) { assert := assert.New(t) series := ContinuousSeries{ @@ -14,7 +14,7 @@ func TestLastValueAnnotation(t *testing.T) { YValues: []float64{5.0, 3.0, 3.0, 2.0, 1.0}, } - lva := LastValueAnnotation(series) + lva := LastValueAnnotationSeries(series) assert.NotEmpty(lva.Annotations) lvaa := lva.Annotations[0] assert.Equal(5, lvaa.XValue) diff --git a/seq.go b/seq.go index aabdc99..76ac40d 100644 --- a/seq.go +++ b/seq.go @@ -148,6 +148,27 @@ func (s Seq) Sort() Seq { return Seq{Array(values)} } +// Reverse reverses the sequence +func (s Seq) Reverse() Seq { + if s.Len() == 0 { + return s + } + + values := s.Values() + valuesLen := len(values) + valuesLen1 := len(values) - 1 + valuesLen2 := valuesLen >> 1 + var i, j float64 + for index := 0; index < valuesLen2; index++ { + i = values[index] + j = values[valuesLen1-index] + values[index] = j + values[valuesLen1-index] = i + } + + return Seq{Array(values)} +} + // Median returns the median or middle value in the sorted seq. func (s Seq) Median() (median float64) { l := s.Len()