set colors
This commit is contained in:
		
							parent
							
								
									bd6a5422cb
								
							
						
					
					
						commit
						f21a8e5736
					
				
							
								
								
									
										922
									
								
								bot.go
									
									
									
									
									
								
							
							
						
						
									
										922
									
								
								bot.go
									
									
									
									
									
								
							| @ -5,16 +5,10 @@ import ( | ||||
| 	"encoding/hex" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"math" | ||||
| 	"regexp" | ||||
| 	"sort" | ||||
| 	"strconv" | ||||
| 	"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" | ||||
| ) | ||||
| 
 | ||||
| @ -938,922 +932,6 @@ func botRegister(m *tb.Message) { | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| 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 = plotutil.Color(i) | ||||
| 		l.Dashes = plotutil.Dashes(2) | ||||
| 		s.Color = plotutil.Color(i) | ||||
| 		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 = plotutil.Color(i) | ||||
| 		l.Dashes = plotutil.Dashes(2) | ||||
| 		s.Color = plotutil.Color(i) | ||||
| 		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 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 = plotutil.Color(i) | ||||
| 		l.Dashes = plotutil.Dashes(2) | ||||
| 		s.Color = plotutil.Color(i) | ||||
| 		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 = plotutil.Color(i) | ||||
| 		l.Dashes = plotutil.Dashes(2) | ||||
| 		s.Color = plotutil.Color(i) | ||||
| 		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 = plotutil.Color(i) | ||||
| 		l.Dashes = plotutil.Dashes(2) | ||||
| 		s.Color = plotutil.Color(i) | ||||
| 		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 = plotutil.Color(i) | ||||
| 		l.Dashes = plotutil.Dashes(2) | ||||
| 		s.Color = plotutil.Color(i) | ||||
| 		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 = plotutil.Color(i) | ||||
| 		l.Dashes = plotutil.Dashes(2) | ||||
| 		s.Color = plotutil.Color(i) | ||||
| 		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 = plotutil.Color(i) | ||||
| 		l.Dashes = plotutil.Dashes(2) | ||||
| 		s.Color = plotutil.Color(i) | ||||
| 		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 = plotutil.Color(i) | ||||
| 		l.Dashes = plotutil.Dashes(2) | ||||
| 		s.Color = plotutil.Color(i) | ||||
| 		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 = plotutil.Color(i) | ||||
| 		l.Dashes = plotutil.Dashes(2) | ||||
| 		s.Color = plotutil.Color(i) | ||||
| 		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 = plotutil.Color(i) | ||||
| 		l.Dashes = plotutil.Dashes(2) | ||||
| 		s.Color = plotutil.Color(i) | ||||
| 		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 | ||||
| } | ||||
| 
 | ||||
| func PrintText(m *tb.Message) { | ||||
| 	logInfoDebug("[%d] %s(%d) | %s(%d) : %s\n", m.ID, m.Chat.Title, m.Chat.ID, m.Sender.Username, m.Sender.ID, m.Text) | ||||
| 	return | ||||
|  | ||||
							
								
								
									
										930
									
								
								bot_graph.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										930
									
								
								bot_graph.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,930 @@ | ||||
| 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 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 | ||||
| } | ||||
							
								
								
									
										44
									
								
								config.go
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								config.go
									
									
									
									
									
								
							| @ -3,6 +3,7 @@ package main | ||||
| import ( | ||||
| 	_ "embed" | ||||
| 	"encoding/json" | ||||
| 	"image/color" | ||||
| 	"io/ioutil" | ||||
| 	"time" | ||||
| 
 | ||||
| @ -128,3 +129,46 @@ func (c *Config) GetCompanyClient(id uint8) *ClientConfig { | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (c *Config) GetClientColor(id int) color.Color { | ||||
| 	cc, ok := c.Clients[id] | ||||
| 	if !ok { | ||||
| 		return color.RGBA{0, 0, 0, 255} // Black | ||||
| 	} | ||||
| 	switch cc.Color { | ||||
| 	case "Dark Blue": | ||||
| 		return color.RGBA{28, 68, 140, 255} | ||||
| 	case "Pale Green": | ||||
| 		return color.RGBA{76, 116, 88, 255} | ||||
| 	case "Pink": | ||||
| 		return color.RGBA{188, 84, 108, 255} | ||||
| 	case "Yellow": | ||||
| 		return color.RGBA{212, 156, 32, 255} | ||||
| 	case "Red": | ||||
| 		return color.RGBA{196, 0, 0, 255} | ||||
| 	case "Light Blue": | ||||
| 		return color.RGBA{52, 112, 132, 255} | ||||
| 	case "Green": | ||||
| 		return color.RGBA{84, 132, 20, 255} | ||||
| 	case "Dark Green": | ||||
| 		return color.RGBA{80, 104, 60, 255} | ||||
| 	case "Blue": | ||||
| 		return color.RGBA{24, 120, 220, 255} | ||||
| 	case "Cream": | ||||
| 		return color.RGBA{184, 112, 80, 255} | ||||
| 	case "Mauve": | ||||
| 		return color.RGBA{80, 80, 116, 255} | ||||
| 	case "Purple": | ||||
| 		return color.RGBA{104, 76, 196, 255} | ||||
| 	case "Orange": | ||||
| 		return color.RGBA{252, 156, 0, 255} | ||||
| 	case "Brown": | ||||
| 		return color.RGBA{124, 104, 72, 255} | ||||
| 	case "Gray": | ||||
| 		return color.RGBA{116, 116, 116, 255} | ||||
| 	case "White": | ||||
| 		return color.RGBA{184, 184, 184, 255} | ||||
| 	default: | ||||
| 		return color.RGBA{0, 0, 0, 255} // Black | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -15,5 +15,6 @@ | ||||
|         "threshold":600000000000, | ||||
|         "start_date":"2021-11-01T17:22:28+02:00" | ||||
|     }, | ||||
|     "stats":null | ||||
|     "stats_monthly":null, | ||||
|     "stats_daily":null | ||||
| } | ||||
| @ -1,6 +1,6 @@ | ||||
| // Code generated by version.sh (@generated) DO NOT EDIT. | ||||
| package main | ||||
| var githash = "eec4d75" | ||||
| var buildstamp = "2021-12-11_02:53:36" | ||||
| var commits = "255" | ||||
| var version = "eec4d75-b255 - 2021-12-11_02:53:36" | ||||
| var githash = "bd6a542" | ||||
| var buildstamp = "2021-12-11_03:50:14" | ||||
| var commits = "256" | ||||
| var version = "bd6a542-b256 - 2021-12-11_03:50:14" | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user