A collection of worker programs for server tasks
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
Ce dépôt est archivé. Vous pouvez voir les fichiers et le cloner, mais vous ne pouvez pas pousser ni ouvrir de ticket/demande d'ajout.

177 lignes
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. }