240 lines
5.4 KiB
Go
240 lines
5.4 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"database/sql"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
_ "github.com/mattn/go-sqlite3"
|
|
)
|
|
|
|
// TODO: change these to be cmd args instead!
|
|
const DB_FIL = "/home/lmas/projects/ss13_se/src/db.sqlite3"
|
|
|
|
// Dir to save new graphs in
|
|
const SAVE_DIR = "/home/lmas/projects/ss13_se/src/static/graphs"
|
|
|
|
// How far back in time the graphs will go
|
|
var LAST_WEEK = time.Now().AddDate(0, 0, -7)
|
|
var LAST_MONTH = time.Now().AddDate(0, -1, 0)
|
|
|
|
var WEEK_DAYS = [7]string{
|
|
"Sunday",
|
|
"Monday",
|
|
"Tuesday",
|
|
"Wednesday",
|
|
"Thursday",
|
|
"Friday",
|
|
"Saturday",
|
|
}
|
|
|
|
func main() {
|
|
// open a db connection
|
|
db, err := sql.Open("sqlite3", DB_FIL)
|
|
checkerror(err)
|
|
defer db.Close()
|
|
|
|
// loop over each server in db
|
|
rows, err := db.Query("select id, title from gameservers_server")
|
|
checkerror(err)
|
|
defer rows.Close()
|
|
|
|
var (
|
|
id int
|
|
title string
|
|
group sync.WaitGroup
|
|
)
|
|
for rows.Next() {
|
|
err := rows.Scan(&id, &title)
|
|
checkerror(err)
|
|
|
|
// Make a new dumb goroutine
|
|
group.Add(1)
|
|
go updategraphs(db, &group, id, title)
|
|
}
|
|
err = rows.Err()
|
|
checkerror(err)
|
|
|
|
// Wait for all goroutines to finish
|
|
group.Wait()
|
|
}
|
|
|
|
func updategraphs(db *sql.DB, group *sync.WaitGroup, id int, title string) {
|
|
defer group.Done()
|
|
weeklyhistorygraph(db, id, title)
|
|
monthlyhistorygraph(db, id, title)
|
|
monthlyaveragedaygraph(db, id, title)
|
|
}
|
|
|
|
func checkerror(err error) {
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func setuptemppaths(prefix string, title string) (f *os.File, name string, path string) {
|
|
// create a tmp file
|
|
file, err := ioutil.TempFile("", prefix)
|
|
checkerror(err)
|
|
|
|
// Make sure we have somewhere to save the stored graphs in
|
|
err = os.MkdirAll(SAVE_DIR, 0777)
|
|
checkerror(err)
|
|
hash := fmt.Sprintf("%x", sha256.Sum256([]byte(title)))
|
|
path = filepath.Join(SAVE_DIR, fmt.Sprintf("%s%s", prefix, hash))
|
|
|
|
return file, file.Name(), path
|
|
}
|
|
|
|
func runcommand(cmd string, title string, args ...string) {
|
|
out, err := exec.Command(cmd, args...).CombinedOutput()
|
|
if err != nil && len(out) > 0 {
|
|
log.Printf("ERROR running '%s' for '%s': \n%s\n", cmd, title, out)
|
|
}
|
|
checkerror(err)
|
|
}
|
|
func weeklyhistorygraph(db *sql.DB, id int, title string) {
|
|
// Get the rows for the server, newer then LAST_WEEK and only on the hour
|
|
rows, err := db.Query("select created,players "+
|
|
"from gameservers_serverhistory "+
|
|
"where server_id = ? and created >= ? and strftime('%M', created) = '00' "+
|
|
"order by created asc",
|
|
id, LAST_WEEK)
|
|
checkerror(err)
|
|
defer rows.Close()
|
|
|
|
var (
|
|
created time.Time
|
|
players int
|
|
data []string
|
|
)
|
|
// Scan in each row and store it in mem
|
|
for rows.Next() {
|
|
err := rows.Scan(&created, &players)
|
|
checkerror(err)
|
|
data = append(data, fmt.Sprintf("%d, %d\n", created.Unix(), players))
|
|
checkerror(err)
|
|
}
|
|
err = rows.Err()
|
|
checkerror(err)
|
|
|
|
// No need to continue running if there's no data to work with
|
|
if len(data) < 1 {
|
|
return
|
|
}
|
|
|
|
// Create a new temp file, get it's filepath and get the final storage path
|
|
ifile, ifilename, ofilename := setuptemppaths("week-time-", title)
|
|
defer func() {
|
|
ifile.Close()
|
|
os.Remove(ifilename)
|
|
}()
|
|
|
|
// Write the server data to the tmp file
|
|
for _, line := range data {
|
|
_, err = ifile.WriteString(line)
|
|
checkerror(err)
|
|
}
|
|
|
|
// And finally run the plotter against the file
|
|
runcommand("./plot_time.sh", title, ifilename, ofilename)
|
|
}
|
|
|
|
func monthlyhistorygraph(db *sql.DB, id int, title string) {
|
|
// Rows for server, newer then LAST_WEEK and only every 6th hour
|
|
rows, err := db.Query("select created,players "+
|
|
"from gameservers_serverhistory "+
|
|
"where server_id = ? and created >= ? and strftime('%M', created) = '00' "+
|
|
"and strftime('%H', created) in ('00', '06', '12', '18') "+
|
|
"order by created asc",
|
|
id, LAST_MONTH)
|
|
checkerror(err)
|
|
defer rows.Close()
|
|
|
|
var (
|
|
created time.Time
|
|
players int
|
|
data []string
|
|
)
|
|
for rows.Next() {
|
|
err := rows.Scan(&created, &players)
|
|
checkerror(err)
|
|
data = append(data, fmt.Sprintf("%d, %d\n", created.Unix(), players))
|
|
checkerror(err)
|
|
}
|
|
err = rows.Err()
|
|
checkerror(err)
|
|
|
|
if len(data) < 1 {
|
|
return
|
|
}
|
|
|
|
ifile, ifilename, ofilename := setuptemppaths("month-time-", title)
|
|
defer func() {
|
|
ifile.Close()
|
|
os.Remove(ifilename)
|
|
}()
|
|
|
|
for _, line := range data {
|
|
_, err = ifile.WriteString(line)
|
|
checkerror(err)
|
|
}
|
|
|
|
runcommand("./plot_time.sh", title, ifilename, ofilename)
|
|
}
|
|
|
|
func monthlyaveragedaygraph(db *sql.DB, id int, title string) {
|
|
rows, err := db.Query("select "+
|
|
"strftime('%w', created) as weekday, avg(players) "+
|
|
"from gameservers_serverhistory "+
|
|
"where server_id = ? and created >= ? "+
|
|
"group by weekday;", id, LAST_MONTH)
|
|
checkerror(err)
|
|
defer rows.Close()
|
|
|
|
var (
|
|
day int
|
|
players float64
|
|
data []string
|
|
)
|
|
|
|
for rows.Next() {
|
|
err := rows.Scan(&day, &players)
|
|
checkerror(err)
|
|
data = append(data, fmt.Sprintf("%s, %f\n", WEEK_DAYS[day], players))
|
|
}
|
|
err = rows.Err()
|
|
checkerror(err)
|
|
|
|
if len(data) < 1 {
|
|
return
|
|
}
|
|
|
|
// If Sunday (WEEK_DAYS[0]) is the first day in the list, we have to
|
|
// move it to the end. Fucking wankers and their weird start of week shit...
|
|
if strings.HasPrefix(data[0], WEEK_DAYS[0]) {
|
|
data = append(data[1:len(data)], data[0])
|
|
}
|
|
|
|
ifile, ifilename, ofilename := setuptemppaths("month-avg_day-", title)
|
|
defer func() {
|
|
ifile.Close()
|
|
os.Remove(ifilename)
|
|
}()
|
|
|
|
for _, line := range data {
|
|
_, err = ifile.WriteString(line)
|
|
checkerror(err)
|
|
}
|
|
|
|
runcommand("./plot_bar.sh", title, ifilename, ofilename)
|
|
}
|