Follow the leader with help from a server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

309 lines
6.5KB

  1. // NGnius 2020-02-12
  2. package main
  3. import (
  4. "encoding/json"
  5. "strconv"
  6. // test
  7. //"fmt"
  8. )
  9. type Jsonable interface {
  10. Json() ([]byte, error)
  11. JsonPretty() ([]byte, error)
  12. Unjson([]byte) error
  13. JsonObject() (interface{}, error)
  14. }
  15. type Rower interface {
  16. Intake() []interface{}
  17. Output() []interface{}
  18. }
  19. type Board struct {
  20. ID int64
  21. Name string
  22. Description string
  23. }
  24. func LoadBoard(id int64) *Board {
  25. b := &Board{ID: id}
  26. loadErr := b.Load()
  27. if loadErr != nil {
  28. return nil
  29. }
  30. return b
  31. }
  32. func (b *Board) Load() error {
  33. return db.QueryRow("SELECT * FROM Boards WHERE id=?", b.ID).Scan(b.Intake()...)
  34. }
  35. func (b *Board) Commit() error {
  36. tx, _ := db.Begin()
  37. statement, _ := tx.Prepare("INSERT OR REPLACE INTO Boards(id, name, description) VALUES (?, ?, ?);")
  38. _, err := statement.Exec(b.Output()...)
  39. if err != nil {
  40. tx.Rollback()
  41. return err
  42. }
  43. return tx.Commit()
  44. }
  45. func (b *Board) Entries() ([]*Entry, error) {
  46. var entries []*Entry
  47. rows, err := db.Query("SELECT * FROM Entries WHERE board=?", b.ID)
  48. if err != nil {
  49. return entries, err
  50. }
  51. count := 0
  52. for rows.Next() {
  53. entries = append(entries, &Entry{})
  54. scanErr := rows.Scan(entries[count].Intake()...)
  55. if scanErr != nil {
  56. return entries, scanErr
  57. }
  58. count++
  59. }
  60. return entries, nil
  61. }
  62. func (b *Board) SomeEntries(start, end int64) ([]*Entry, error) {
  63. var entries []*Entry
  64. rows, err := db.Query("SELECT * FROM Entries WHERE board=? and rank >= ? and rank <= ? ORDER BY rank ASC;", b.ID, start, end)
  65. if err != nil {
  66. return entries, err
  67. }
  68. count := 0
  69. for rows.Next() {
  70. entries = append(entries, &Entry{})
  71. scanErr := rows.Scan(entries[count].Intake()...)
  72. if scanErr != nil {
  73. return entries, scanErr
  74. }
  75. count++
  76. }
  77. return entries, nil
  78. }
  79. func (b *Board) Url() string {
  80. return "/board?name=" + b.Name
  81. }
  82. // implementation of Jsonable
  83. func (b *Board) Json() ([]byte, error) {
  84. var data []byte
  85. jsonObj, err := b.JsonObject()
  86. if err != nil {
  87. return data, err
  88. }
  89. return json.Marshal(jsonObj)
  90. }
  91. func (b *Board) JsonPretty() ([]byte, error) {
  92. var data []byte
  93. jsonObj, err := b.JsonObject()
  94. if err != nil {
  95. return data, err
  96. }
  97. return json.MarshalIndent(jsonObj, "", " ")
  98. }
  99. func (b *Board) JsonObject() (interface{}, error) {
  100. jsonObj := BoardJSON{ID: b.ID, Name: b.Name, Description: b.Description, Url: b.Url()}
  101. return jsonObj, nil
  102. }
  103. // implementation of Rower
  104. func (b *Board) Intake() []interface{} {
  105. return []interface{}{&b.ID, &b.Name, &b.Description}
  106. }
  107. func (b *Board) Output() []interface{} {
  108. return []interface{}{b.ID, b.Name, b.Description}
  109. }
  110. type Player struct {
  111. ID int64
  112. Name string
  113. }
  114. func LoadPlayer(id int64) *Player {
  115. p := &Player{ID: id}
  116. loadErr := p.Load()
  117. if loadErr != nil {
  118. return nil
  119. }
  120. return p
  121. }
  122. func (p *Player) Load() error {
  123. return db.QueryRow("SELECT * FROM Players WHERE id=? LIMIT 1;", p.ID).Scan(p.Intake()...)
  124. }
  125. func (p *Player) Commit() error {
  126. tx, _ := db.Begin()
  127. statement, _ := tx.Prepare("INSERT OR REPLACE INTO Players(id, name) VALUES (?, ?);")
  128. _, err := statement.Exec(p.Output()...)
  129. if err != nil {
  130. tx.Rollback()
  131. return err
  132. }
  133. return tx.Commit()
  134. }
  135. func (p *Player) Entries() ([]*Entry, error) {
  136. var entries []*Entry
  137. rows, err := db.Query("SELECT * FROM Entries WHERE player=?", p.ID)
  138. if err != nil {
  139. return entries, err
  140. }
  141. count := 0
  142. for rows.Next() {
  143. entries = append(entries, &Entry{})
  144. scanErr := rows.Scan(entries[count].Intake()...)
  145. if scanErr != nil {
  146. return entries, scanErr
  147. }
  148. count++
  149. }
  150. return entries, nil
  151. }
  152. func (p *Player) SomeEntries(limit int64) ([]*Entry, error) {
  153. var entries []*Entry
  154. rows, err := db.Query("SELECT * FROM Entries WHERE player=? ORDER BY time DESC LIMIT ?;", p.ID, limit)
  155. if err != nil {
  156. return entries, err
  157. }
  158. count := 0
  159. for rows.Next() {
  160. entries = append(entries, &Entry{})
  161. scanErr := rows.Scan(entries[count].Intake()...)
  162. if scanErr != nil {
  163. return entries, scanErr
  164. }
  165. count++
  166. }
  167. return entries, nil
  168. }
  169. func (p *Player) Url() string {
  170. return "/player?id=" + strconv.Itoa(int(p.ID))
  171. }
  172. // implementation of Jsonable
  173. func (p *Player) Json() ([]byte, error) {
  174. var data []byte
  175. jsonObj, err := p.JsonObject()
  176. if err != nil {
  177. return data, err
  178. }
  179. return json.Marshal(jsonObj)
  180. }
  181. func (p *Player) JsonPretty() ([]byte, error) {
  182. var data []byte
  183. jsonObj, err := p.JsonObject()
  184. if err != nil {
  185. return data, err
  186. }
  187. return json.MarshalIndent(jsonObj, "", " ")
  188. }
  189. func (p *Player) JsonObject() (interface{}, error) {
  190. jsonObj := PlayerJSON{ID: p.ID, Name: p.Name, Url: p.Url()}
  191. return jsonObj, nil
  192. }
  193. // implementation of Rower
  194. func (p *Player) Intake() []interface{} {
  195. return []interface{}{&p.ID, &p.Name}
  196. }
  197. func (p *Player) Output() []interface{} {
  198. return []interface{}{p.ID, p.Name}
  199. }
  200. type Entry struct {
  201. ID int64
  202. Rank int64
  203. Score int64
  204. Player int64
  205. Board int64
  206. Time int64 // Created time (seconds since Unix epoch)
  207. Metadata []byte
  208. }
  209. func LoadEntry(id int64) *Entry {
  210. e := &Entry{ID: id}
  211. loadErr := e.Load()
  212. if loadErr != nil {
  213. return nil
  214. }
  215. return e
  216. }
  217. func (e *Entry) Load() error {
  218. return db.QueryRow("SELECT * FROM Entries WHERE id=? LIMIT 1;", e.ID).Scan(e.Intake()...)
  219. }
  220. func (e *Entry) Commit() error {
  221. tx, _ := db.Begin()
  222. statement, _ := tx.Prepare("INSERT OR REPLACE INTO Entries(id, rank, score, player, board, time, metadata) VALUES (?, ?, ?, ?, ?, ?, ?);")
  223. _, err := statement.Exec(e.Output()...)
  224. if err != nil {
  225. tx.Rollback()
  226. return err
  227. }
  228. return tx.Commit()
  229. }
  230. // implementation of Jsonable
  231. func (e *Entry) Json() ([]byte, error) {
  232. var data []byte
  233. jsonObj, err := e.JsonObject()
  234. if err != nil {
  235. return data, err
  236. }
  237. return json.Marshal(jsonObj)
  238. }
  239. func (e *Entry) JsonPretty() ([]byte, error) {
  240. var data []byte
  241. jsonObj, err := e.JsonObject()
  242. if err != nil {
  243. return data, err
  244. }
  245. return json.MarshalIndent(jsonObj, "", " ")
  246. }
  247. func (e *Entry) JsonObject() (interface{}, error) {
  248. jsonObj := EntryJSON{ID: e.ID, Rank: e.Rank, Score: e.Score, PlayerID: e.Player, BoardID: e.Board}
  249. ePlayer := &Player{ID: e.Player}
  250. err := ePlayer.Load()
  251. if err != nil {
  252. return jsonObj, err
  253. }
  254. jsonObj.PlayerName = ePlayer.Name
  255. jsonObj.PlayerURL = ePlayer.Url()
  256. eBoard := &Board{ID: e.Board}
  257. err = eBoard.Load()
  258. if err != nil {
  259. return jsonObj, err
  260. }
  261. jsonObj.BoardName = eBoard.Name
  262. jsonObj.BoardURL = eBoard.Url()
  263. return jsonObj, nil
  264. }
  265. // implementation of Rower
  266. func (e *Entry) Intake() []interface{} {
  267. return []interface{}{&e.ID, &e.Rank, &e.Score, &e.Player, &e.Board, &e.Time, &e.Metadata}
  268. }
  269. func (e *Entry) Output() []interface{} {
  270. return []interface{}{e.ID, e.Rank, e.Score, e.Player, e.Board, e.Time, e.Metadata}
  271. }