124 lines
2.7 KiB
Go
124 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
|
|
"github.com/go-echarts/go-echarts/v2/charts"
|
|
"github.com/go-echarts/go-echarts/v2/opts"
|
|
)
|
|
|
|
func main() {
|
|
ctx, can := signal.NotifyContext(context.Background())
|
|
defer can()
|
|
if err := run(ctx); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func run(ctx context.Context) error {
|
|
config, err := newConfig()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
log.Printf("%+v", config)
|
|
|
|
x, y, data, err := config.Data.AsScatterData()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
log.Printf("%s: (%s, %s) = %v", config.Data.Title, x, y, data)
|
|
|
|
minX, maxX := data[0][0].Value.([]float64)[0], data[0][0].Value.([]float64)[0]
|
|
minY, maxY := data[0][0].Value.([]float64)[1], data[0][0].Value.([]float64)[1]
|
|
for _, series := range data {
|
|
for _, datum := range series {
|
|
x := datum.Value.([]float64)[0]
|
|
if x < minX {
|
|
minX = x
|
|
} else if x > maxX {
|
|
maxX = x
|
|
}
|
|
y := datum.Value.([]float64)[1]
|
|
if y < minY {
|
|
minY = y
|
|
} else if y > maxY {
|
|
maxY = y
|
|
}
|
|
}
|
|
}
|
|
|
|
if 0 <= minX && minX <= 1 {
|
|
minX = 0
|
|
} else if 1 <= minX {
|
|
minX -= 1
|
|
maxX += 1
|
|
}
|
|
if 0 <= minY && minY <= 1 {
|
|
minY = 0
|
|
} else if 1 <= minY {
|
|
minY -= 1
|
|
maxY += 1
|
|
}
|
|
log.Printf("x=[%v, %v] y=[%v, %v]", minX, maxX, minY, maxY)
|
|
|
|
globalOpts := []charts.GlobalOpts{
|
|
charts.WithTitleOpts(opts.Title{
|
|
Title: config.Data.Title,
|
|
Subtitle: config.Data.Subtitle,
|
|
}),
|
|
charts.WithTooltipOpts(opts.Tooltip{
|
|
Show: true,
|
|
Formatter: `{c}`,
|
|
}),
|
|
charts.WithLegendOpts(opts.Legend{Show: true}),
|
|
charts.WithXAxisOpts(opts.XAxis{
|
|
Name: x,
|
|
NameLocation: "middle",
|
|
NameGap: config.Data.Weight.Floor + config.Data.Weight.Range,
|
|
Min: minX,
|
|
Max: maxX,
|
|
}),
|
|
charts.WithYAxisOpts(opts.YAxis{
|
|
Name: y,
|
|
NameLocation: "middle",
|
|
NameGap: config.Data.Weight.Floor + config.Data.Weight.Range,
|
|
Min: minY,
|
|
Max: maxY,
|
|
}),
|
|
}
|
|
|
|
buff := bytes.NewBuffer(nil)
|
|
|
|
switch config.Graph.Type {
|
|
case "line":
|
|
line := charts.NewLine()
|
|
line.SetGlobalOptions(globalOpts...)
|
|
for i, series := range scatterAsLineData(data) {
|
|
line.AddSeries(fmt.Sprintf("%s[%d]", y, i), series)
|
|
}
|
|
if err := line.Render(buff); err != nil {
|
|
return err
|
|
}
|
|
case "scatter":
|
|
scatter := charts.NewScatter()
|
|
scatter.SetGlobalOptions(globalOpts...)
|
|
for i, series := range data {
|
|
scatter.AddSeries(fmt.Sprintf("%s[%d]", y, i), series)
|
|
}
|
|
if err := scatter.Render(buff); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
switch config.Output.Scheme {
|
|
case "file":
|
|
return os.WriteFile(config.Output.Path, buff.Bytes(), os.ModePerm)
|
|
}
|
|
return fmt.Errorf("not impl output scheme: %s", config.Output.Scheme)
|
|
}
|