lion-turtle/leadercraft-ranker/main.go

177 lines
4.3 KiB
Go
Raw Normal View History

2020-08-11 09:54:42 -04:00
// NGnius 2020-01-30
package main // leadercraft-server
import (
"flag"
2020-08-11 09:54:42 -04:00
"fmt"
"os"
"os/signal"
)
const (
// Version the current version
Version = "0.1"
// Name the program name
Name = "leadercraft-s"
)
var (
isClosing bool
2020-08-11 09:54:42 -04:00
printVersionAndExit bool
)
func init() {
initArgs()
}
func main() {
parseArgs()
sqlInitErr := sqlInit()
if sqlInitErr != nil {
fmt.Printf("Failed to initialise SQL connection: %s\n", sqlInitErr)
os.Exit(1)
}
// handle interrupt (terminate) signal
signalChan := make(chan os.Signal)
signal.Notify(signalChan, os.Interrupt)
go func() {
s := <-signalChan
fmt.Println("Received terminate signal " + s.String())
isClosing = true
sqlClose()
}()
// get new rankings
rows, err := db.Query("SELECT * FROM Entries WHERE rank=-1 ORDER BY time ASC;")
var players []int64
2020-08-11 09:54:42 -04:00
if err == nil {
// update rank for boards
var entries []*Entry
2020-08-11 09:54:42 -04:00
count := 0
for rows.Next() {
entries = append(entries, &Entry{})
scanErr := rows.Scan(entries[count].Intake()...)
if scanErr == nil {
//fmt.Printf("Updating rank for entry %d in board %d from player %d\n", entries[count].ID, entries[count].Board, entries[count].Player)
if entries[count].Board > 2 { // ignore special boards
players = append(players, entries[count].Player)
}
updateBoardEntries(entries[count])
count++
} else {
fmt.Println(scanErr)
}
}
// update special boards
for _, elem := range players {
p := &Player{ID: elem}
err := p.Load()
if err == nil {
//fmt.Printf("Updating high score for player %d\n", p.ID)
updateMainRank(p)
} else {
fmt.Println(err)
}
}
2020-08-11 09:54:42 -04:00
} else {
fmt.Println(err)
}
2020-08-11 09:54:42 -04:00
}
func initArgs() {
flag.BoolVar(&printVersionAndExit, "version", false, "Print version and exit")
flag.StringVar(&sqlConnection, "conn", sqlConnectionDefault, "Database connection string")
flag.StringVar(&sqlServer, "sql", sqlServerDefault, "SQL Database type")
}
func parseArgs() {
flag.Parse()
if printVersionAndExit {
fmt.Println(Name + " v" + Version)
os.Exit(0)
}
}
func updateBoardEntries(entry *Entry) {
// get nearest entry that's lower and steal it's rank
nearestEntry := &Entry{}
scanErr := db.QueryRow("SELECT * FROM Entries WHERE score < $1 AND rank!= -1 AND board=$2 ORDER BY score DESC LIMIT 1;", entry.Score, entry.Board).Scan(nearestEntry.Intake()...)
if scanErr == nil {
entry.Rank = nearestEntry.Rank
entry.Commit()
// update all ranks lower than itself
tx, _ := db.Begin()
stmt, _ := tx.Prepare("UPDATE Entries SET rank=rank+1 WHERE rank >=$1 AND id!=$2 AND board=$3;")
_, err := stmt.Exec(entry.Rank, entry.ID, entry.Board)
if err != nil {
tx.Rollback()
fmt.Println(err)
} else {
tx.Commit()
}
} else {
// nothing to beat
scanErr = db.QueryRow("SELECT * FROM Entries WHERE score >= $1 AND rank!= -1 AND board=$2 ORDER BY score ASC LIMIT 1;", entry.Score, entry.Board).Scan(nearestEntry.Intake()...)
if scanErr == nil {
entry.Rank = nearestEntry.Rank + 1
entry.Commit()
} else {
// no other entries
entry.Rank = 1
entry.Commit()
}
}
}
func updateMainRank(p *Player) {
rows, err := db.Query("SELECT * FROM Entries WHERE player = $1 AND board > 2 ORDER BY score DESC LIMIT $2;", p.ID, 100)
var count int64 = 0
var sum int64 = 0
if err == nil {
for rows.Next() {
entry := &Entry{}
scanErr := rows.Scan(entry.Intake()...)
if scanErr == nil {
count++
sum += entry.Score
} else {
fmt.Println(scanErr)
return
}
}
if count > 0 && sum > 0 {
mainEntry := &Entry{
Player: p.ID,
Board: 1,
}
average := sum / count
//fmt.Printf("Average of %d/%d is %d\n", sum, count, average)
dne := db.QueryRow("SELECT * FROM Entries WHERE board=$1 AND player=$2", 1, p.ID).Scan(mainEntry.Intake()...)
if dne == nil {
tx, _ := db.Begin()
stmt, _ := tx.Prepare("UPDATE Entries SET rank=rank-1 WHERE rank >$1 AND id!=$2 AND board=$3;")
_, err := stmt.Exec(mainEntry.Rank, mainEntry.ID, 1)
if err != nil {
tx.Rollback()
fmt.Println(err)
return // abort
} else {
tx.Commit()
}
mainEntry.Score = average
mainEntry.Rank = -1
mainEntry.Commit()
} else {
createErr := newEntrySql(average, p.ID, 1)
if createErr == nil {
fmt.Println(createErr)
return
}
}
}
} else {
fmt.Println(err)
return
}
2020-08-11 09:54:42 -04:00
}