A collection of worker programs for server tasks
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
Este repositorio está archivado. Puede ver los archivos y clonarlo, pero no puede subir cambios o reportar incidencias ni pedir Pull Requests.

177 líneas
4.3KB

  1. // NGnius 2020-01-30
  2. package main // leadercraft-server
  3. import (
  4. "flag"
  5. "fmt"
  6. "os"
  7. "os/signal"
  8. )
  9. const (
  10. // Version the current version
  11. Version = "0.1"
  12. // Name the program name
  13. Name = "leadercraft-s"
  14. )
  15. var (
  16. isClosing bool
  17. printVersionAndExit bool
  18. )
  19. func init() {
  20. initArgs()
  21. }
  22. func main() {
  23. parseArgs()
  24. sqlInitErr := sqlInit()
  25. if sqlInitErr != nil {
  26. fmt.Printf("Failed to initialise SQL connection: %s\n", sqlInitErr)
  27. os.Exit(1)
  28. }
  29. // handle interrupt (terminate) signal
  30. signalChan := make(chan os.Signal)
  31. signal.Notify(signalChan, os.Interrupt)
  32. go func() {
  33. s := <-signalChan
  34. fmt.Println("Received terminate signal " + s.String())
  35. isClosing = true
  36. sqlClose()
  37. }()
  38. // get new rankings
  39. rows, err := db.Query("SELECT * FROM Entries WHERE rank=-1 ORDER BY time ASC;")
  40. var players []int64
  41. if err == nil {
  42. // update rank for boards
  43. var entries []*Entry
  44. count := 0
  45. for rows.Next() {
  46. entries = append(entries, &Entry{})
  47. scanErr := rows.Scan(entries[count].Intake()...)
  48. if scanErr == nil {
  49. //fmt.Printf("Updating rank for entry %d in board %d from player %d\n", entries[count].ID, entries[count].Board, entries[count].Player)
  50. if entries[count].Board > 2 { // ignore special boards
  51. players = append(players, entries[count].Player)
  52. }
  53. updateBoardEntries(entries[count])
  54. count++
  55. } else {
  56. fmt.Println(scanErr)
  57. }
  58. }
  59. // update special boards
  60. for _, elem := range players {
  61. p := &Player{ID: elem}
  62. err := p.Load()
  63. if err == nil {
  64. //fmt.Printf("Updating high score for player %d\n", p.ID)
  65. updateMainRank(p)
  66. } else {
  67. fmt.Println(err)
  68. }
  69. }
  70. } else {
  71. fmt.Println(err)
  72. }
  73. }
  74. func initArgs() {
  75. flag.BoolVar(&printVersionAndExit, "version", false, "Print version and exit")
  76. flag.StringVar(&sqlConnection, "conn", sqlConnectionDefault, "Database connection string")
  77. flag.StringVar(&sqlServer, "sql", sqlServerDefault, "SQL Database type")
  78. }
  79. func parseArgs() {
  80. flag.Parse()
  81. if printVersionAndExit {
  82. fmt.Println(Name + " v" + Version)
  83. os.Exit(0)
  84. }
  85. }
  86. func updateBoardEntries(entry *Entry) {
  87. // get nearest entry that's lower and steal it's rank
  88. nearestEntry := &Entry{}
  89. 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()...)
  90. if scanErr == nil {
  91. entry.Rank = nearestEntry.Rank
  92. entry.Commit()
  93. // update all ranks lower than itself
  94. tx, _ := db.Begin()
  95. stmt, _ := tx.Prepare("UPDATE Entries SET rank=rank+1 WHERE rank >=$1 AND id!=$2 AND board=$3;")
  96. _, err := stmt.Exec(entry.Rank, entry.ID, entry.Board)
  97. if err != nil {
  98. tx.Rollback()
  99. fmt.Println(err)
  100. } else {
  101. tx.Commit()
  102. }
  103. } else {
  104. // nothing to beat
  105. 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()...)
  106. if scanErr == nil {
  107. entry.Rank = nearestEntry.Rank + 1
  108. entry.Commit()
  109. } else {
  110. // no other entries
  111. entry.Rank = 1
  112. entry.Commit()
  113. }
  114. }
  115. }
  116. func updateMainRank(p *Player) {
  117. rows, err := db.Query("SELECT * FROM Entries WHERE player = $1 AND board > 2 ORDER BY score DESC LIMIT $2;", p.ID, 100)
  118. var count int64 = 0
  119. var sum int64 = 0
  120. if err == nil {
  121. for rows.Next() {
  122. entry := &Entry{}
  123. scanErr := rows.Scan(entry.Intake()...)
  124. if scanErr == nil {
  125. count++
  126. sum += entry.Score
  127. } else {
  128. fmt.Println(scanErr)
  129. return
  130. }
  131. }
  132. if count > 0 && sum > 0 {
  133. mainEntry := &Entry{
  134. Player: p.ID,
  135. Board: 1,
  136. }
  137. average := sum / count
  138. //fmt.Printf("Average of %d/%d is %d\n", sum, count, average)
  139. dne := db.QueryRow("SELECT * FROM Entries WHERE board=$1 AND player=$2", 1, p.ID).Scan(mainEntry.Intake()...)
  140. if dne == nil {
  141. tx, _ := db.Begin()
  142. stmt, _ := tx.Prepare("UPDATE Entries SET rank=rank-1 WHERE rank >$1 AND id!=$2 AND board=$3;")
  143. _, err := stmt.Exec(mainEntry.Rank, mainEntry.ID, 1)
  144. if err != nil {
  145. tx.Rollback()
  146. fmt.Println(err)
  147. return // abort
  148. } else {
  149. tx.Commit()
  150. }
  151. mainEntry.Score = average
  152. mainEntry.Rank = -1
  153. mainEntry.Commit()
  154. } else {
  155. createErr := newEntrySql(average, p.ID, 1)
  156. if createErr == nil {
  157. fmt.Println(createErr)
  158. return
  159. }
  160. }
  161. }
  162. } else {
  163. fmt.Println(err)
  164. return
  165. }
  166. }