package main import ( "fmt" "math" "sort" "time" "gonum.org/v1/plot" "gonum.org/v1/plot/plotter" "gonum.org/v1/plot/plotutil" "gonum.org/v1/plot/vg" tb "gopkg.in/tucnak/telebot.v2" ) func botGraphValue(m *tb.Message) { var ( maxVal float64 unitFactor float64 unitName string ) for _, dStats := range cfg.StatsMonthly { for _, stat := range dStats { valueFloat := float64(stat.CompanyValueLastQuarter) if math.Abs(valueFloat) > maxVal { maxVal = math.Abs(valueFloat) } } } if maxVal > 1000000000 { unitFactor = 1000000000 unitName = "billion" } else if maxVal > 1000000 { unitFactor = 1000000 unitName = "million" } else { unitFactor = 1 unitName = "" } var vals map[int]plotter.XYs vals = make(map[int]plotter.XYs) for ccID, dStats := range cfg.StatsMonthly { vals[ccID] = make(plotter.XYs, 0) for dStr, stat := range dStats { d, err := time.Parse("20060102", dStr) logErrorDebug(err, "botGraphValue : time.Parse") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("time.Parse : %s", err)) return } dateFloat := float64(d.Year()) + float64(d.Month()-1)/12 valueFloat := float64(stat.CompanyValueLastQuarter) pt := plotter.XY{ X: dateFloat, Y: valueFloat / unitFactor, } vals[ccID] = append(vals[ccID], pt) } sort.Slice(vals[ccID], func(i, j int) bool { return vals[ccID][i].X < vals[ccID][j].X }) } p := plot.New() p.Title.Text = "Company Values" p.X.Label.Text = "Year" if unitName != "" { p.Y.Label.Text = fmt.Sprintf("Value (%s)", unitName) } else { p.Y.Label.Text = "Value" } i := 0 for ccID, xys := range vals { cc := cfg.Clients[ccID] l, s, err := plotter.NewLinePoints(xys) logErrorDebug(err, "botGraphValue : plotter.NewLinePoints") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plotter.NewLinePoints : %s", err)) return } l.Color = cfg.GetClientColor(ccID) l.Dashes = plotutil.Dashes(2) s.Color = cfg.GetClientColor(ccID) s.Shape = plotutil.Shape(0) p.Add(l) p.Add(s) p.Legend.Add(cc.Username, l, s) i++ } err := p.Save(12*vg.Inch, 8*vg.Inch, "/app/data/points.png") logErrorDebug(err, "botGraphValue : plot.Save") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plot.Save : %s", err)) return } bot.SendChatImage(m.Chat.ID, "/app/data/points.png") return } func botGraphValueDelta(m *tb.Message) { var ( maxVal float64 unitFactor float64 unitName string ) var vals map[int]plotter.XYs vals = make(map[int]plotter.XYs) for ccID, dStats := range cfg.StatsMonthly { vals[ccID] = make(plotter.XYs, 0) for dStr, stat := range dStats { d, err := time.Parse("20060102", dStr) logErrorDebug(err, "botGraphValueDelta : time.Parse") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("time.Parse : %s", err)) return } pt := plotter.XY{ X: float64(d.Year()) + float64(d.Month()-1)/12, Y: float64(stat.CompanyValuePreviousQuarter), } vals[ccID] = append(vals[ccID], pt) } sort.Slice(vals[ccID], func(i, j int) bool { return vals[ccID][i].X < vals[ccID][j].X }) } for ccID, v := range vals { v2 := make(plotter.XYs, 0) for i := 0; i < len(v); i = i + 3 { v2 = append(v2, v[i]) } vals[ccID] = v2 } for ccID, v := range vals { v0 := v[0].Y for i := 1; i < len(v); i++ { v[i].Y, v0 = v[i].Y-v0, v[i].Y if math.Abs(v[i].Y) > maxVal { maxVal = math.Abs(v[i].Y) } } vals[ccID] = v[1:] } if maxVal > 1000000000 { unitFactor = 1000000000 unitName = "billion" } else if maxVal > 1000000 { unitFactor = 1000000 unitName = "million" } else { unitFactor = 1 unitName = "" } for ccID, v := range vals { for i := 0; i < len(v); i++ { v[i].Y = v[i].Y / unitFactor if math.IsNaN(v[i].Y) { logInfoDebug("botGraphValueDelta : NaN : %d / %f", ccID, v[i].X) } } vals[ccID] = v } p := plot.New() p.Title.Text = "Company Values (delta)" p.X.Label.Text = "Year" if unitName != "" { p.Y.Label.Text = fmt.Sprintf("Variation (%s)", unitName) } else { p.Y.Label.Text = "Variation" } i := 0 for ccID, xys := range vals { cc := cfg.Clients[ccID] l, s, err := plotter.NewLinePoints(xys) logErrorDebug(err, "botGraphValueDelta : plotter.NewLinePoints") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plotter.NewLinePoints : %s", err)) return } l.Color = cfg.GetClientColor(ccID) l.Dashes = plotutil.Dashes(2) s.Color = cfg.GetClientColor(ccID) s.Shape = plotutil.Shape(0) p.Add(l) p.Add(s) p.Legend.Add(cc.Username, l, s) i++ } err := p.Save(12*vg.Inch, 8*vg.Inch, "/app/data/points.png") logErrorDebug(err, "botGraphValueDelta : plot.Save") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plot.Save : %s", err)) return } bot.SendChatImage(m.Chat.ID, "/app/data/points.png") return } func botGraphDeliveries(m *tb.Message) { var ( maxVal float64 unitFactor float64 unitName string ) for _, dStats := range cfg.StatsMonthly { for _, stat := range dStats { valueFloat := float64(stat.DeliveredCargoLastQuarter) if math.Abs(valueFloat) > maxVal { maxVal = math.Abs(valueFloat) } } } if maxVal > 1000000000 { unitFactor = 1000000000 unitName = "billion" } else if maxVal > 1000000 { unitFactor = 1000000 unitName = "million" } else { unitFactor = 1 unitName = "" } var vals map[int]plotter.XYs vals = make(map[int]plotter.XYs) for ccID, dStats := range cfg.StatsMonthly { vals[ccID] = make(plotter.XYs, 0) for dStr, stat := range dStats { d, err := time.Parse("20060102", dStr) logErrorDebug(err, "botGraphDeliveries : time.Parse") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("time.Parse : %s", err)) return } dateFloat := float64(d.Year()) + float64(d.Month()-1)/12 valueFloat := float64(stat.DeliveredCargoLastQuarter) pt := plotter.XY{ X: dateFloat, Y: valueFloat / unitFactor, } vals[ccID] = append(vals[ccID], pt) } sort.Slice(vals[ccID], func(i, j int) bool { return vals[ccID][i].X < vals[ccID][j].X }) } p := plot.New() p.Title.Text = "Company Deliveries" p.X.Label.Text = "Year" if unitName != "" { p.Y.Label.Text = fmt.Sprintf("Deliveries (%s)", unitName) } else { p.Y.Label.Text = "Deliveries" } i := 0 for ccID, xys := range vals { cc := cfg.Clients[ccID] l, s, err := plotter.NewLinePoints(xys) logErrorDebug(err, "botGraphDeliveries : plotter.NewLinePoints") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plotter.NewLinePoints : %s", err)) return } l.Color = cfg.GetClientColor(ccID) l.Dashes = plotutil.Dashes(2) s.Color = cfg.GetClientColor(ccID) s.Shape = plotutil.Shape(0) p.Add(l) p.Add(s) p.Legend.Add(cc.Username, l, s) i++ } err := p.Save(12*vg.Inch, 8*vg.Inch, "/app/data/points.png") logErrorDebug(err, "botGraphDeliveries : plot.Save") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plot.Save : %s", err)) return } bot.SendChatImage(m.Chat.ID, "/app/data/points.png") return } func botGraphMoney(m *tb.Message) { var ( maxVal float64 unitFactor float64 unitName string ) for _, dStats := range cfg.StatsMonthly { for _, stat := range dStats { valueFloat := float64(stat.Money) if math.Abs(valueFloat) > maxVal { maxVal = math.Abs(valueFloat) } } } if maxVal > 1000000000 { unitFactor = 1000000000 unitName = "billion" } else if maxVal > 1000000 { unitFactor = 1000000 unitName = "million" } else { unitFactor = 1 unitName = "" } var vals map[int]plotter.XYs vals = make(map[int]plotter.XYs) for ccID, dStats := range cfg.StatsMonthly { vals[ccID] = make(plotter.XYs, 0) for dStr, stat := range dStats { d, err := time.Parse("20060102", dStr) logErrorDebug(err, "botGraphMoney : time.Parse") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("time.Parse : %s", err)) return } dateFloat := float64(d.Year()) + float64(d.Month()-1)/12 valueFloat := float64(stat.Money) pt := plotter.XY{ X: dateFloat, Y: valueFloat / unitFactor, } vals[ccID] = append(vals[ccID], pt) } sort.Slice(vals[ccID], func(i, j int) bool { return vals[ccID][i].X < vals[ccID][j].X }) } p := plot.New() p.Title.Text = "Company Money" p.X.Label.Text = "Year" if unitName != "" { p.Y.Label.Text = fmt.Sprintf("Money (%s)", unitName) } else { p.Y.Label.Text = "Money" } i := 0 for ccID, xys := range vals { cc := cfg.Clients[ccID] l, s, err := plotter.NewLinePoints(xys) logErrorDebug(err, "botGraphMoney : plotter.NewLinePoints") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plotter.NewLinePoints : %s", err)) return } l.Color = cfg.GetClientColor(ccID) l.Dashes = plotutil.Dashes(2) s.Color = cfg.GetClientColor(ccID) s.Shape = plotutil.Shape(0) p.Add(l) p.Add(s) p.Legend.Add(cc.Username, l, s) i++ } err := p.Save(12*vg.Inch, 8*vg.Inch, "/app/data/points.png") logErrorDebug(err, "botGraphMoney : plot.Save") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plot.Save : %s", err)) return } bot.SendChatImage(m.Chat.ID, "/app/data/points.png") return } func botGraphIncome(m *tb.Message) { var ( maxVal float64 unitFactor float64 unitName string ) for _, dStats := range cfg.StatsMonthly { for _, stat := range dStats { valueFloat := float64(stat.Income) if math.Abs(valueFloat) > maxVal { maxVal = math.Abs(valueFloat) } } } if maxVal > 1000000000 { unitFactor = 1000000000 unitName = "billion" } else if maxVal > 1000000 { unitFactor = 1000000 unitName = "million" } else { unitFactor = 1 unitName = "" } var vals map[int]plotter.XYs vals = make(map[int]plotter.XYs) for ccID, dStats := range cfg.StatsMonthly { vals[ccID] = make(plotter.XYs, 0) for dStr, stat := range dStats { d, err := time.Parse("20060102", dStr) logErrorDebug(err, "botGraphIncome : time.Parse") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("time.Parse : %s", err)) return } dateFloat := float64(d.Year()) + float64(d.Month()-1)/12 valueFloat := float64(stat.Income) pt := plotter.XY{ X: dateFloat, Y: valueFloat / unitFactor, } vals[ccID] = append(vals[ccID], pt) } sort.Slice(vals[ccID], func(i, j int) bool { return vals[ccID][i].X < vals[ccID][j].X }) } p := plot.New() p.Title.Text = "Company Income" p.X.Label.Text = "Year" if unitName != "" { p.Y.Label.Text = fmt.Sprintf("Income (%s)", unitName) } else { p.Y.Label.Text = "Income" } i := 0 for ccID, xys := range vals { cc := cfg.Clients[ccID] l, s, err := plotter.NewLinePoints(xys) logErrorDebug(err, "botGraphIncome : plotter.NewLinePoints") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plotter.NewLinePoints : %s", err)) return } l.Color = cfg.GetClientColor(ccID) l.Dashes = plotutil.Dashes(2) s.Color = cfg.GetClientColor(ccID) s.Shape = plotutil.Shape(0) p.Add(l) p.Add(s) p.Legend.Add(cc.Username, l, s) i++ } err := p.Save(12*vg.Inch, 8*vg.Inch, "/app/data/points.png") logErrorDebug(err, "botGraphIncome : plot.Save") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plot.Save : %s", err)) return } bot.SendChatImage(m.Chat.ID, "/app/data/points.png") return } func botGraphLoan(m *tb.Message) { var ( maxVal float64 unitFactor float64 unitName string ) for _, dStats := range cfg.StatsMonthly { for _, stat := range dStats { valueFloat := float64(stat.Loan) if math.Abs(valueFloat) > maxVal { maxVal = math.Abs(valueFloat) } } } if maxVal > 1000000000 { unitFactor = 1000000000 unitName = "billion" } else if maxVal > 1000000 { unitFactor = 1000000 unitName = "million" } else { unitFactor = 1 unitName = "" } var vals map[int]plotter.XYs vals = make(map[int]plotter.XYs) for ccID, dStats := range cfg.StatsMonthly { vals[ccID] = make(plotter.XYs, 0) for dStr, stat := range dStats { d, err := time.Parse("20060102", dStr) logErrorDebug(err, "botGraphLoan : time.Parse") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("time.Parse : %s", err)) return } dateFloat := float64(d.Year()) + float64(d.Month()-1)/12 valueFloat := float64(stat.Loan) pt := plotter.XY{ X: dateFloat, Y: valueFloat / unitFactor, } vals[ccID] = append(vals[ccID], pt) } sort.Slice(vals[ccID], func(i, j int) bool { return vals[ccID][i].X < vals[ccID][j].X }) } p := plot.New() p.Title.Text = "Company Loan" p.X.Label.Text = "Year" if unitName != "" { p.Y.Label.Text = fmt.Sprintf("Loan (%s)", unitName) } else { p.Y.Label.Text = "Loan" } i := 0 for ccID, xys := range vals { cc := cfg.Clients[ccID] l, s, err := plotter.NewLinePoints(xys) logErrorDebug(err, "botGraphLoan : plotter.NewLinePoints") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plotter.NewLinePoints : %s", err)) return } l.Color = cfg.GetClientColor(ccID) l.Dashes = plotutil.Dashes(2) s.Color = cfg.GetClientColor(ccID) s.Shape = plotutil.Shape(0) p.Add(l) p.Add(s) p.Legend.Add(cc.Username, l, s) i++ } err := p.Save(12*vg.Inch, 8*vg.Inch, "/app/data/points.png") logErrorDebug(err, "botGraphLoan : plot.Save") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plot.Save : %s", err)) return } bot.SendChatImage(m.Chat.ID, "/app/data/points.png") return } func botGraphPerf(m *tb.Message) { var ( maxVal float64 unitFactor float64 unitName string ) for _, dStats := range cfg.StatsMonthly { for _, stat := range dStats { valueFloat := float64(stat.PerformancePreviousQuarter) if math.Abs(valueFloat) > maxVal { maxVal = math.Abs(valueFloat) } } } if maxVal > 1000000000 { unitFactor = 1000000000 unitName = "billion" } else if maxVal > 1000000 { unitFactor = 1000000 unitName = "million" } else { unitFactor = 1 unitName = "" } var vals map[int]plotter.XYs vals = make(map[int]plotter.XYs) for ccID, dStats := range cfg.StatsMonthly { vals[ccID] = make(plotter.XYs, 0) for dStr, stat := range dStats { d, err := time.Parse("20060102", dStr) logErrorDebug(err, "botGraphPerf : time.Parse") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("time.Parse : %s", err)) return } dateFloat := float64(d.Year()) + float64(d.Month()-1)/12 valueFloat := float64(stat.PerformancePreviousQuarter) pt := plotter.XY{ X: dateFloat, Y: valueFloat / unitFactor, } vals[ccID] = append(vals[ccID], pt) } sort.Slice(vals[ccID], func(i, j int) bool { return vals[ccID][i].X < vals[ccID][j].X }) } p := plot.New() p.Title.Text = "Company Perf" p.X.Label.Text = "Year" if unitName != "" { p.Y.Label.Text = fmt.Sprintf("Perf (%s)", unitName) } else { p.Y.Label.Text = "Perf" } i := 0 for ccID, xys := range vals { cc := cfg.Clients[ccID] l, s, err := plotter.NewLinePoints(xys) logErrorDebug(err, "botGraphPerf : plotter.NewLinePoints") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plotter.NewLinePoints : %s", err)) return } l.Color = cfg.GetClientColor(ccID) l.Dashes = plotutil.Dashes(2) s.Color = cfg.GetClientColor(ccID) s.Shape = plotutil.Shape(0) p.Add(l) p.Add(s) p.Legend.Add(cc.Username, l, s) i++ } err := p.Save(12*vg.Inch, 8*vg.Inch, "/app/data/points.png") logErrorDebug(err, "botGraphPerf : plot.Save") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plot.Save : %s", err)) return } bot.SendChatImage(m.Chat.ID, "/app/data/points.png") return } func botGraphPlanes(m *tb.Message) { var planes, airports map[int]plotter.XYs planes = make(map[int]plotter.XYs) airports = make(map[int]plotter.XYs) for ccID, dStats := range cfg.StatsMonthly { planes[ccID] = make(plotter.XYs, 0) for dStr, stat := range dStats { d, err := time.Parse("20060102", dStr) logErrorDebug(err, "botGraphPlanes : time.Parse") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("time.Parse : %s", err)) return } dateFloat := float64(d.Year()) + float64(d.Month()-1)/12 pt := plotter.XY{ X: dateFloat, Y: float64(stat.Planes), } planes[ccID] = append(planes[ccID], pt) pt = plotter.XY{ X: dateFloat, Y: float64(stat.Airports), } airports[ccID] = append(airports[ccID], pt) } sort.Slice(planes[ccID], func(i, j int) bool { return planes[ccID][i].X < planes[ccID][j].X }) sort.Slice(airports[ccID], func(i, j int) bool { return airports[ccID][i].X < airports[ccID][j].X }) } p := plot.New() p.Title.Text = "Planes summary" p.X.Label.Text = "Year" p.Y.Label.Text = "Planes" p.Y.Min = 0 i := 0 for ccID, xys := range planes { cc := cfg.Clients[ccID] l, s, err := plotter.NewLinePoints(xys) logErrorDebug(err, "botGraphPlanes : plotter.NewLinePoints") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plotter.NewLinePoints : %s", err)) return } l.Color = cfg.GetClientColor(ccID) l.Dashes = plotutil.Dashes(2) s.Color = cfg.GetClientColor(ccID) s.Shape = plotutil.Shape(0) p.Add(l) p.Add(s) p.Legend.Add(cc.Username, l, s) i++ } err := p.Save(12*vg.Inch, 8*vg.Inch, "/app/data/points.png") logErrorDebug(err, "botGraphPlanes : plot.Save") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plot.Save : %s", err)) return } bot.SendChatImage(m.Chat.ID, "/app/data/points.png") return } func botGraphBusses(m *tb.Message) { var busses, busStops map[int]plotter.XYs busses = make(map[int]plotter.XYs) busStops = make(map[int]plotter.XYs) for ccID, dStats := range cfg.StatsMonthly { busses[ccID] = make(plotter.XYs, 0) for dStr, stat := range dStats { d, err := time.Parse("20060102", dStr) logErrorDebug(err, "botGraphBusses : time.Parse") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("time.Parse : %s", err)) return } dateFloat := float64(d.Year()) + float64(d.Month()-1)/12 pt := plotter.XY{ X: dateFloat, Y: float64(stat.Busses), } busses[ccID] = append(busses[ccID], pt) pt = plotter.XY{ X: dateFloat, Y: float64(stat.BusStops), } busStops[ccID] = append(busStops[ccID], pt) } sort.Slice(busses[ccID], func(i, j int) bool { return busses[ccID][i].X < busses[ccID][j].X }) sort.Slice(busStops[ccID], func(i, j int) bool { return busStops[ccID][i].X < busStops[ccID][j].X }) } p := plot.New() p.Title.Text = "Busses summary" p.X.Label.Text = "Year" p.Y.Label.Text = "Busses" p.Y.Min = 0 i := 0 for ccID, xys := range busses { cc := cfg.Clients[ccID] l, s, err := plotter.NewLinePoints(xys) logErrorDebug(err, "botGraphBusses : plotter.NewLinePoints") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plotter.NewLinePoints : %s", err)) return } l.Color = cfg.GetClientColor(ccID) l.Dashes = plotutil.Dashes(2) s.Color = cfg.GetClientColor(ccID) s.Shape = plotutil.Shape(0) p.Add(l) p.Add(s) p.Legend.Add(cc.Username, l, s) i++ } err := p.Save(12*vg.Inch, 8*vg.Inch, "/app/data/points.png") logErrorDebug(err, "botGraphBusses : plot.Save") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plot.Save : %s", err)) return } bot.SendChatImage(m.Chat.ID, "/app/data/points.png") return } func botGraphTrains(m *tb.Message) { var trains, trainStations map[int]plotter.XYs trains = make(map[int]plotter.XYs) trainStations = make(map[int]plotter.XYs) for ccID, dStats := range cfg.StatsMonthly { trains[ccID] = make(plotter.XYs, 0) for dStr, stat := range dStats { d, err := time.Parse("20060102", dStr) logErrorDebug(err, "botGraphTrains : time.Parse") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("time.Parse : %s", err)) return } dateFloat := float64(d.Year()) + float64(d.Month()-1)/12 pt := plotter.XY{ X: dateFloat, Y: float64(stat.Trains), } trains[ccID] = append(trains[ccID], pt) pt = plotter.XY{ X: dateFloat, Y: float64(stat.TrainStations), } trainStations[ccID] = append(trainStations[ccID], pt) } sort.Slice(trains[ccID], func(i, j int) bool { return trains[ccID][i].X < trains[ccID][j].X }) sort.Slice(trainStations[ccID], func(i, j int) bool { return trainStations[ccID][i].X < trainStations[ccID][j].X }) } p := plot.New() p.Title.Text = "Trains summary" p.X.Label.Text = "Year" p.Y.Label.Text = "Trains" p.Y.Min = 0 i := 0 for ccID, xys := range trains { cc := cfg.Clients[ccID] l, s, err := plotter.NewLinePoints(xys) logErrorDebug(err, "botGraphTrains : plotter.NewLinePoints") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plotter.NewLinePoints : %s", err)) return } l.Color = cfg.GetClientColor(ccID) l.Dashes = plotutil.Dashes(2) s.Color = cfg.GetClientColor(ccID) s.Shape = plotutil.Shape(0) p.Add(l) p.Add(s) p.Legend.Add(cc.Username, l, s) i++ } err := p.Save(12*vg.Inch, 8*vg.Inch, "/app/data/points.png") logErrorDebug(err, "botGraphTrains : plot.Save") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plot.Save : %s", err)) return } bot.SendChatImage(m.Chat.ID, "/app/data/points.png") return } func botGraphLorries(m *tb.Message) { var lorries, lorriesStations map[int]plotter.XYs lorries = make(map[int]plotter.XYs) lorriesStations = make(map[int]plotter.XYs) for ccID, dStats := range cfg.StatsMonthly { lorries[ccID] = make(plotter.XYs, 0) for dStr, stat := range dStats { d, err := time.Parse("20060102", dStr) logErrorDebug(err, "botGraphLorries : time.Parse") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("time.Parse : %s", err)) return } dateFloat := float64(d.Year()) + float64(d.Month()-1)/12 pt := plotter.XY{ X: dateFloat, Y: float64(stat.Lorries), } lorries[ccID] = append(lorries[ccID], pt) pt = plotter.XY{ X: dateFloat, Y: float64(stat.LorryStations), } lorriesStations[ccID] = append(lorriesStations[ccID], pt) } sort.Slice(lorries[ccID], func(i, j int) bool { return lorries[ccID][i].X < lorries[ccID][j].X }) sort.Slice(lorriesStations[ccID], func(i, j int) bool { return lorriesStations[ccID][i].X < lorriesStations[ccID][j].X }) } p := plot.New() p.Title.Text = "Lorries summary" p.X.Label.Text = "Year" p.Y.Label.Text = "Lorries" p.Y.Min = 0 i := 0 for ccID, xys := range lorries { cc := cfg.Clients[ccID] l, s, err := plotter.NewLinePoints(xys) logErrorDebug(err, "botGraphLorries : plotter.NewLinePoints") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plotter.NewLinePoints : %s", err)) return } l.Color = cfg.GetClientColor(ccID) l.Dashes = plotutil.Dashes(2) s.Color = cfg.GetClientColor(ccID) s.Shape = plotutil.Shape(0) p.Add(l) p.Add(s) p.Legend.Add(cc.Username, l, s) i++ } err := p.Save(12*vg.Inch, 8*vg.Inch, "/app/data/points.png") logErrorDebug(err, "botGraphLorries : plot.Save") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plot.Save : %s", err)) return } bot.SendChatImage(m.Chat.ID, "/app/data/points.png") return } func botGraphShips(m *tb.Message) { var ships, harbours map[int]plotter.XYs ships = make(map[int]plotter.XYs) harbours = make(map[int]plotter.XYs) for ccID, dStats := range cfg.StatsMonthly { ships[ccID] = make(plotter.XYs, 0) for dStr, stat := range dStats { d, err := time.Parse("20060102", dStr) logErrorDebug(err, "botGraphShips : time.Parse") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("time.Parse : %s", err)) return } dateFloat := float64(d.Year()) + float64(d.Month()-1)/12 pt := plotter.XY{ X: dateFloat, Y: float64(stat.Ships), } ships[ccID] = append(ships[ccID], pt) pt = plotter.XY{ X: dateFloat, Y: float64(stat.Harbours), } harbours[ccID] = append(harbours[ccID], pt) } sort.Slice(ships[ccID], func(i, j int) bool { return ships[ccID][i].X < ships[ccID][j].X }) sort.Slice(harbours[ccID], func(i, j int) bool { return harbours[ccID][i].X < harbours[ccID][j].X }) } p := plot.New() p.Title.Text = "Ships summary" p.X.Label.Text = "Year" p.Y.Label.Text = "Ships" p.Y.Min = 0 i := 0 for ccID, xys := range ships { cc := cfg.Clients[ccID] l, s, err := plotter.NewLinePoints(xys) logErrorDebug(err, "botGraphShips : plotter.NewLinePoints") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plotter.NewLinePoints : %s", err)) return } l.Color = cfg.GetClientColor(ccID) l.Dashes = plotutil.Dashes(2) s.Color = cfg.GetClientColor(ccID) s.Shape = plotutil.Shape(0) p.Add(l) p.Add(s) p.Legend.Add(cc.Username, l, s) i++ } err := p.Save(12*vg.Inch, 8*vg.Inch, "/app/data/points.png") logErrorDebug(err, "botGraphShips : plot.Save") if err != nil { bot.SendChat(m.Chat.ID, fmt.Sprintf("plot.Save : %s", err)) return } bot.SendChatImage(m.Chat.ID, "/app/data/points.png") return }