diff --git a/chart_type.go b/chart_type.go index 333ada7..89c31d1 100644 --- a/chart_type.go +++ b/chart_type.go @@ -6,9 +6,9 @@ import ( "github.com/marianogappa/chart/format" ) -func resolveChartType(ct chartType, lf format.LineFormat) (chartType, error) { +func resolveChartType(ct chartType, lf format.LineFormat, datasetLength int) (chartType, error) { ct = _resolveChartType(ct, lf) - return ct, assertChartable(ct, lf) + return ct, assertChartable(ct, lf, datasetLength) } func _resolveChartType(ct chartType, f format.LineFormat) chartType { @@ -27,7 +27,10 @@ func _resolveChartType(ct chartType, f format.LineFormat) chartType { } } -func assertChartable(ct chartType, f format.LineFormat) error { +func assertChartable(ct chartType, f format.LineFormat, datasetLength int) error { + if datasetLength == 0 { + return fmt.Errorf("empty dataset; nothing to plot here") + } var errIncompatibleFormat = fmt.Errorf("I don't know how to plot a dataset with this line format") switch ct { case pie, bar: diff --git a/chart_type_test.go b/chart_type_test.go index c006ae3..45f80f1 100644 --- a/chart_type_test.go +++ b/chart_type_test.go @@ -47,7 +47,7 @@ func TestResolveChartType(t *testing.T) { for _, ts := range tests { lf, _ := format.NewLineFormat(ts.lf, ' ', "") // ignoring errors as we're not testing the format package here - result, err := resolveChartType(ts.t, lf) + result, err := resolveChartType(ts.t, lf, 123) if err != nil { // TODO test cases where there's an error t.Errorf("%v: there was an error resolving the chart type", ts.name) } diff --git a/cheatsheet_test.go b/cheatsheet_test.go index e5e1942..4f48361 100644 --- a/cheatsheet_test.go +++ b/cheatsheet_test.go @@ -62,10 +62,13 @@ func TestCheatsheet(t *testing.T) { var rdr io.Reader rdr, o.lineFormat = format.Parse(rd, o.separator, o.dateFormat) - d := mustNewDataset(rdr, o) - o.chartType, err = resolveChartType(o.chartType, d.lineFormat) + d := mustNewDataset(rdr, o.lineFormat) + if !o.lineFormat.HasFloats && !o.lineFormat.HasDateTimes && o.lineFormat.HasStrings { + d.fss, d.sss, o.lineFormat = preprocessFreq(d.sss, o.lineFormat) + } + o.chartType, err = resolveChartType(o.chartType, o.lineFormat, d.Len()) if err != nil { - t.Errorf("[%v] error resolving chart type when o.chartType=%v and d.lineFormat=%v: [%v]", f, o.chartType, d.lineFormat, err) + t.Errorf("[%v] error resolving chart type when o.chartType=%v and d.lineFormat=%v: [%v]", f, o.chartType, o.lineFormat, err) t.FailNow() } b, err := chartjs.New( diff --git a/dataset.go b/dataset.go index d361603..159ebd2 100644 --- a/dataset.go +++ b/dataset.go @@ -2,7 +2,6 @@ package main import ( "bufio" - "fmt" "io" "time" @@ -11,13 +10,12 @@ import ( ) type dataset struct { - fss [][]float64 - sss [][]string - tss [][]time.Time - minFSS []float64 - maxFSS []float64 - lineFormat format.LineFormat - stdinLen int + fss [][]float64 + sss [][]string + tss [][]time.Time + minFSS []float64 + maxFSS []float64 + stdinLen int } func (d dataset) Len() int { @@ -27,15 +25,15 @@ func (d dataset) Len() int { return len(d.fss) } -func mustNewDataset(r io.Reader, o options) *dataset { - d, err := newDataset(r, o) +func mustNewDataset(r io.Reader, f format.LineFormat) *dataset { + d, err := newDataset(r, f) if err != nil { log.WithError(err).Fatal("Could not build dataset.") } return d } -func newDataset(r io.Reader, o options) (*dataset, error) { +func newDataset(r io.Reader, f format.LineFormat) (*dataset, error) { d := &dataset{ fss: make([][]float64, 0, 500), sss: make([][]string, 0, 500), @@ -43,20 +41,18 @@ func newDataset(r io.Reader, o options) (*dataset, error) { minFSS: make([]float64, 0, 500), maxFSS: make([]float64, 0, 500), } - return d, d.read(r, o) + return d, d.read(r, f) } -func (d *dataset) read(r io.Reader, o options) error { +func (d *dataset) read(r io.Reader, f format.LineFormat) error { var ( nilSSS, nilFSS, nilTSS = true, true, true scanner = bufio.NewScanner(r) stdinLen = 0 ) - d.lineFormat = o.lineFormat - for scanner.Scan() { stdinLen++ - fs, ss, ts, err := d.lineFormat.ParseLine(scanner.Text()) + fs, ss, ts, err := f.ParseLine(scanner.Text()) if err != nil { continue } @@ -104,15 +100,6 @@ func (d *dataset) read(r io.Reader, o options) error { if nilTSS { d.tss = nil } - if !d.lineFormat.HasFloats && len(d.sss) > 0 { - d.fss, d.sss = preprocessFreq(d.sss) - d.lineFormat.ColTypes = append(d.lineFormat.ColTypes, format.Float) - d.lineFormat.FloatCount++ - d.lineFormat.HasFloats = true - } - if d.Len() == 0 { - return fmt.Errorf("empty dataset; nothing to plot here") - } return nil } diff --git a/dataset_test.go b/dataset_test.go index a48d5fd..5733a66 100644 --- a/dataset_test.go +++ b/dataset_test.go @@ -60,11 +60,8 @@ func TestDataset(t *testing.T) { c a `, - o: options{separator: '\t', scaleType: linear, chartType: pie}, - fss: [][]float64{ - {2}, {1}, {1}, - }, - sss: [][]string{{"a"}, {"b"}, {"c"}}, + o: options{separator: '\t', scaleType: linear, chartType: pie}, + sss: [][]string{{"a"}, {"b"}, {"c"}, {"a"}}, tss: nil, minFSS: nil, maxFSS: nil, @@ -91,8 +88,7 @@ func TestDataset(t *testing.T) { for _, ts := range tests { rd, lf := format.Parse(strings.NewReader(ts.i), ts.o.separator, ts.o.dateFormat) - ts.o.lineFormat = lf - d, err := newDataset(rd, ts.o) + d, err := newDataset(rd, lf) if err != nil { t.Errorf("'%v' failed: error reading dataset %v", ts.name, err) diff --git a/debug.go b/debug.go index cf48ce0..9b37d28 100644 --- a/debug.go +++ b/debug.go @@ -24,7 +24,7 @@ func renderDebug(d dataset, o options, err error) string { tcn = len(d.tss[0]) } buffer.WriteString(fmt.Sprintf("Lines read\t%v\n", d.stdinLen)) - buffer.WriteString(fmt.Sprintf("Line format inferred\t%v\n", d.lineFormat.String())) + buffer.WriteString(fmt.Sprintf("Line format inferred\t%v\n", o.lineFormat.String())) buffer.WriteString(fmt.Sprintf("Lines used\t%v\n", rn)) buffer.WriteString(fmt.Sprintf("Float column count\t%v\n", fcn)) buffer.WriteString(fmt.Sprintf("String column count\t%v\n", scn)) diff --git a/freq.go b/freq.go index 87d2784..bf967c0 100644 --- a/freq.go +++ b/freq.go @@ -2,9 +2,11 @@ package main import ( "sort" + + "github.com/marianogappa/chart/format" ) -func preprocessFreq(isss [][]string) ([][]float64, [][]string) { +func preprocessFreq(isss [][]string, lineFormat format.LineFormat) ([][]float64, [][]string, format.LineFormat) { fss := [][]float64{} sss := [][]string{} @@ -44,7 +46,12 @@ func preprocessFreq(isss [][]string) ([][]float64, [][]string) { sss = append(sss, []string{fqs.fs[9].s}) } - return fss, sss + // Updates lineFormat + lineFormat.ColTypes = append(lineFormat.ColTypes, format.Float) + lineFormat.FloatCount++ + lineFormat.HasFloats = true + + return fss, sss, lineFormat } type freq struct { diff --git a/freq_test.go b/freq_test.go index f02e394..e9041b2 100644 --- a/freq_test.go +++ b/freq_test.go @@ -1,6 +1,10 @@ package main -import "testing" +import ( + "testing" + + "github.com/marianogappa/chart/format" +) func TestFreq(t *testing.T) { tests := []struct { @@ -119,7 +123,7 @@ func TestFreq(t *testing.T) { } for _, ts := range tests { - fss, sss := preprocessFreq(ts.isss) + fss, sss, _ := preprocessFreq(ts.isss, format.LineFormat{}) if !equalMap(fss, ts.expectedFSS, sss, ts.expectedSSS) { t.Errorf("[%v] case failed: %v, %v were not equal to %v, %v", ts.name, fss, sss, ts.expectedFSS, ts.expectedSSS) diff --git a/main.go b/main.go index b148ca3..574ab5d 100644 --- a/main.go +++ b/main.go @@ -20,8 +20,11 @@ func main() { if opts.rawLineFormat == "" { rd, opts.lineFormat = format.Parse(rd, opts.separator, opts.dateFormat) } - dataset := mustNewDataset(rd, opts) - if opts.chartType, err = resolveChartType(opts.chartType, dataset.lineFormat); opts.debug || err != nil { + dataset := mustNewDataset(rd, opts.lineFormat) + if !opts.lineFormat.HasFloats && !opts.lineFormat.HasDateTimes && opts.lineFormat.HasStrings { + dataset.fss, dataset.sss, opts.lineFormat = preprocessFreq(dataset.sss, opts.lineFormat) + } + if opts.chartType, err = resolveChartType(opts.chartType, opts.lineFormat, dataset.Len()); opts.debug || err != nil { fmt.Println(renderDebug(*dataset, opts, err)) os.Exit(0) }