db.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. package main
  2. import (
  3. "database/sql"
  4. "log"
  5. "os"
  6. "strconv"
  7. _ "github.com/mattn/go-sqlite3"
  8. )
  9. // Make sure the go-sqlite3 is here. Keep the db related things together.
  10. type DBData struct {
  11. DB *sql.DB
  12. User string
  13. }
  14. func (db *DBData) Open(filename string) {
  15. var err error
  16. db.DB, err = sql.Open("sqlite3", filename)
  17. if err != nil {
  18. log.Panicln("Error Opening Sqlite3:", err)
  19. }
  20. // Create the tables (if needed)
  21. db.Create()
  22. }
  23. func (db *DBData) Close() {
  24. db.DB.Close()
  25. }
  26. const LOCK_USERNAME = ""
  27. const LOCK_SETTING = "LOCK"
  28. const LOCK_CLEAR = "0"
  29. func (db *DBData) Create() {
  30. _, err := db.DB.Exec(
  31. "CREATE TABLE IF NOT EXISTS settings(username TEXT, setting TEXT, value TEXT, PRIMARY KEY(username, setting));")
  32. if err != nil {
  33. log.Panicln(err)
  34. }
  35. _, err = db.DB.Exec(
  36. "CREATE TABLE IF NOT EXISTS scores ( username TEXT, `when` INTEGER, date INTEGER, hand INTEGER, won INTEGER, score INTEGER, PRIMARY KEY(username, date, hand));")
  37. if err != nil {
  38. log.Panicln(err)
  39. }
  40. _, err = db.DB.Exec(
  41. "CREATE TABLE IF NOT EXISTS monthly ( month INTEGER, username TEXT, days INTEGER, hands_won INTEGER, score INTEGER, PRIMARY KEY(month, username) );")
  42. if err != nil {
  43. log.Panicln(err)
  44. }
  45. // Make sure our settings LOCK value exists
  46. db.DB.Exec(
  47. "INSERT INTO settings(username, setting, value) VALUES(?,?,?);",
  48. LOCK_USERNAME, LOCK_SETTING, LOCK_CLEAR)
  49. // An error here is OK. It means the setting already exists.
  50. /*
  51. if err != nil {
  52. log.Printf("LOCK %#v\n", err)
  53. }
  54. */
  55. }
  56. func (db *DBData) Lock(value string) string {
  57. _, err := db.DB.Exec("UPDATE settings SET value=? WHERE username=? AND setting=? AND value=?;",
  58. value, LOCK_USERNAME, LOCK_SETTING, LOCK_CLEAR)
  59. if err != nil {
  60. log.Printf("Lock(%s) : %s\n", value, err)
  61. }
  62. row := db.DB.QueryRow("SELECT value FROM settings WHERE username=? AND setting=?;",
  63. LOCK_USERNAME, LOCK_SETTING)
  64. var result string
  65. err = row.Scan(&result)
  66. if err != nil {
  67. log.Println("Lock Scan", err)
  68. }
  69. log.Printf("Lock(%s) = %s\n", value, result)
  70. return result
  71. }
  72. func (db *DBData) Unlock(value string) bool {
  73. _, err := db.DB.Exec("UPDATE settings SET value=? WHERE username=? AND setting=? AND value=?;",
  74. LOCK_CLEAR, LOCK_USERNAME, LOCK_SETTING, value)
  75. if err != nil {
  76. log.Printf("Unlock(%s) : %s\n", value, err)
  77. }
  78. row := db.DB.QueryRow("SELECT value FROM settings WHERE username=? AND setting=?;",
  79. LOCK_USERNAME, LOCK_SETTING)
  80. var result string
  81. err = row.Scan(&result)
  82. if err != nil {
  83. log.Println("Unlock Scan", err)
  84. }
  85. log.Printf("Unlock(%s) = %s\n", value, result)
  86. return result == LOCK_CLEAR
  87. }
  88. func (db *DBData) GetSetting(setting string, ifMissing string) string {
  89. row := db.DB.QueryRow("SELECT value FROM settings WHERE username=? AND setting=?;",
  90. db.User, setting)
  91. var value string
  92. // log.Printf("row: %#v\n", row)
  93. err := row.Scan(&value)
  94. if err != nil {
  95. return ifMissing
  96. }
  97. return value
  98. }
  99. func (db *DBData) SetSetting(setting string, value string) {
  100. _, err := db.DB.Exec("REPLACE INTO settings(username, setting, value) VALUES(?,?,?);",
  101. db.User, setting, value)
  102. if err != nil {
  103. log.Panicln("Query SetSetting", err)
  104. }
  105. // log.Printf("SetSetting %s %s = %s\n", db.User, setting, value)
  106. }
  107. func (db *DBData) SaveScore(when int64, date int64, hand int, won int, score int) {
  108. _, err := db.DB.Exec("INSERT INTO scores(username, `when`, date, hand, won, score) VALUES(?,?,?,?,?,?);",
  109. db.User, when, date, hand, won, score)
  110. if err != nil {
  111. log.Panicln("SaveScore", err)
  112. }
  113. }
  114. func (db *DBData) HandsPlayedOnDay(day int64) int {
  115. row := db.DB.QueryRow("SELECT COUNT(*) FROM scores WHERE username=? AND date=?;")
  116. var value int
  117. err := row.Scan(&value)
  118. if err != nil {
  119. return 0
  120. }
  121. return value
  122. }
  123. /*
  124. WhenPlayed = GetPlayed (as far as I can tell...)
  125. */
  126. func (db *DBData) WhenPlayed() map[int64]int {
  127. var result map[int64]int = make(map[int64]int)
  128. rows, err := db.DB.Query("SELECT date, COUNT(hand) FROM scores WHERE username=? GROUP BY date;",
  129. db.User)
  130. if err != nil {
  131. log.Println("GetPlayed", err)
  132. return result
  133. }
  134. defer rows.Close()
  135. for rows.Next() {
  136. var date int64
  137. var hands int
  138. if err := rows.Scan(&date, &hands); err != nil {
  139. log.Println("GetPlayed Scan", err)
  140. return result
  141. }
  142. result[date] = hands
  143. }
  144. if err = rows.Err(); err != nil {
  145. log.Println("GetPlayed rows.Err", err)
  146. }
  147. return result
  148. }
  149. type MonthUser struct {
  150. Date int64
  151. Username string
  152. }
  153. type MonthStats struct {
  154. Days int
  155. Hands_Won int
  156. Score int
  157. }
  158. func (db *DBData) ExpireScores(month_first_t int64) {
  159. // step 1: acquire lock
  160. // ... step 0: find working lock strategy in go. :(
  161. // lockfile := lockedfile.Create("db.lock")
  162. // defer lockfile.Close()
  163. var pid string = strconv.Itoa(os.Getpid())
  164. l := db.Lock(pid)
  165. if l == pid {
  166. log.Printf("Lock worked!\n")
  167. defer db.Unlock(pid)
  168. } else {
  169. log.Printf("Lock failed [%s]\n", l)
  170. }
  171. // var Monthly map[MonthUser]MonthStats = make(map[MonthUser]MonthStats)
  172. }
  173. type ScoresDetails struct {
  174. User string
  175. Date int64
  176. Hand int
  177. Won int
  178. Score int
  179. }
  180. func (db *DBData) GetScoresOnDay(date int64) []ScoresDetails {
  181. var result []ScoresDetails
  182. rows, err := db.DB.Query("SELECT username, date, hand, won, score FROM SCORES WHERE date=? ORDER BY username, hand;",
  183. date)
  184. if err != nil {
  185. log.Println("GetScoresOnDay", date, err)
  186. return result
  187. }
  188. defer rows.Close()
  189. for rows.Next() {
  190. var sd ScoresDetails
  191. if err := rows.Scan(&sd.User, &sd.Date, &sd.Hand, &sd.Won, &sd.Score); err != nil {
  192. log.Println("GetScoresOnDay Scan", err)
  193. return result
  194. }
  195. result = append(result, sd)
  196. }
  197. if err = rows.Err(); err != nil {
  198. log.Println("GetScoresOnDay rows.Err", err)
  199. }
  200. return result
  201. }
  202. type ScoresData struct {
  203. Date int64
  204. User string
  205. Score int
  206. Won int
  207. }
  208. func (db *DBData) GetScores(limit int) []ScoresData {
  209. var result []ScoresData
  210. rows, err := db.DB.Query("SELECT date, username, SUM(score), SUM(won) FROM SCORES GROUP BY date, username ORDER BY SUM(score) DESC LIMIT ?;",
  211. limit)
  212. if err != nil {
  213. log.Println("GetScores", err)
  214. return result
  215. }
  216. defer rows.Close()
  217. for rows.Next() {
  218. var sd ScoresData
  219. if err := rows.Scan(&sd.Date, &sd.User, &sd.Score, &sd.Won); err != nil {
  220. log.Println("GetScores Scan", err)
  221. return result
  222. }
  223. result = append(result, sd)
  224. }
  225. if err = rows.Err(); err != nil {
  226. log.Println("GetScores rows.Err", err)
  227. }
  228. return result
  229. }
  230. type MonthlyData struct {
  231. Date int64
  232. User string
  233. Days int
  234. Hands_Won int
  235. Score int
  236. }
  237. func (db *DBData) GetMonthlyScores(limit int) []MonthlyData {
  238. var result []MonthlyData
  239. rows, err := db.DB.Query("SELECT month, username, days, hands_won, score FROM monthly ORDER BY score DESC LIMIT ?;",
  240. limit)
  241. if err != nil {
  242. log.Println("GetMonthlyScores", err)
  243. return result
  244. }
  245. defer rows.Close()
  246. for rows.Next() {
  247. var md MonthlyData
  248. if err := rows.Scan(&md.Date, &md.User, &md.Days, &md.Hands_Won, &md.Score); err != nil {
  249. log.Println("GetMonthlyScores Scan", err)
  250. return result
  251. }
  252. result = append(result, md)
  253. }
  254. if err = rows.Err(); err != nil {
  255. log.Println("GetMonthlyScores rows.Err", err)
  256. }
  257. return result
  258. }