ss13_se/charts.go
2017-07-15 18:08:17 +02:00

165 lines
3.2 KiB
Go

package ss13_se
import (
"bytes"
"fmt"
"io"
"net/http"
"time"
chart "github.com/wcharczuk/go-chart"
)
type renderableChart interface {
Render(chart.RendererProvider, io.Writer) error
}
func (a *App) renderChart(w http.ResponseWriter, c renderableChart) error {
buf := &bytes.Buffer{}
err := c.Render(chart.PNG, buf)
if err != nil {
//a.Log("Error while rendering chart: %s", err)
return HttpError{
Status: http.StatusInternalServerError,
Err: fmt.Errorf("error while rendering chart"),
}
}
w.Header().Add("Content-Type", "image/png")
_, err = io.Copy(w, buf)
if err != nil {
a.Log("Error while sending chart: %s", err)
return HttpError{
Status: http.StatusInternalServerError,
Err: fmt.Errorf("error while sending chart"),
}
}
return nil
}
func makeHistoryChart(title string, points []ServerPoint) chart.Chart {
var xVals []time.Time
var yVals []float64
for _, p := range points {
xVals = append(xVals, p.Time)
yVals = append(yVals, float64(p.Players))
}
series := chart.TimeSeries{
Name: "Players",
XValues: xVals,
YValues: yVals,
}
li := &chart.LinearRegressionSeries{
Name: "Linear regression",
InnerSeries: series,
}
sma := &chart.SMASeries{
Name: "Simple moving avg.",
InnerSeries: series,
}
c := chart.Chart{
Title: title,
TitleStyle: chart.Style{
Show: true,
},
Background: chart.Style{
Padding: chart.Box{
Left: 120,
},
},
XAxis: chart.XAxis{
Style: chart.Style{
Show: true,
},
},
YAxis: chart.YAxis{
Style: chart.Style{
Show: true,
},
},
Series: []chart.Series{
series,
li,
sma,
},
}
// Add a legend
c.Elements = []chart.Renderable{
chart.LegendLeft(&c),
}
return c
}
// NOTE: The chart won't be renderable unless we've got at least two days of history
func makeDayAverageChart(title string, points []ServerPoint) chart.BarChart {
days := make(map[time.Weekday][]int)
for _, p := range points {
day := p.Time.Weekday()
days[day] = append(days[day], p.Players)
}
avgDays := make(map[time.Weekday]float64)
for day, vals := range days {
sum := 0
for _, v := range vals {
sum += v
}
avg := sum / len(vals)
avgDays[day] = float64(avg)
}
prettyName := func(d time.Weekday) string {
return fmt.Sprintf("%s (%.0f)", d, avgDays[d])
}
return chart.BarChart{
Title: title,
TitleStyle: chart.Style{
Show: true,
},
BarWidth: 60,
XAxis: chart.Style{
Show: true,
},
YAxis: chart.YAxis{
Style: chart.Style{
Show: true,
},
},
Bars: []chart.Value{
chart.Value{
Label: prettyName(time.Monday),
Value: avgDays[time.Monday],
},
chart.Value{
Label: prettyName(time.Tuesday),
Value: avgDays[time.Tuesday],
},
chart.Value{
Label: prettyName(time.Wednesday),
Value: avgDays[time.Wednesday],
},
chart.Value{
Label: prettyName(time.Thursday),
Value: avgDays[time.Thursday],
},
chart.Value{
Label: prettyName(time.Friday),
Value: avgDays[time.Friday],
},
chart.Value{
Label: prettyName(time.Saturday),
Value: avgDays[time.Saturday],
},
chart.Value{
Label: prettyName(time.Sunday),
Value: avgDays[time.Sunday],
},
},
}
}