|
- // NGnius 2020-01-30
-
- package main // leadercraft-server
-
- import (
- "flag"
- "fmt"
- "os"
- "os/signal"
- )
-
- const (
- // Version the current version
- Version = "0.1"
- // Name the program name
- Name = "leadercraft-s"
- )
-
- var (
- isClosing bool
- 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
- if err == nil {
- // update rank for boards
- var entries []*Entry
- 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)
- }
- }
- } else {
- fmt.Println(err)
- }
- }
-
- 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
- }
- }
|