198 lines
4.4 KiB
Go
198 lines
4.4 KiB
Go
package main
|
|
|
|
import (
|
|
"database/sql"
|
|
|
|
_ "github.com/mattn/go-sqlite3"
|
|
)
|
|
|
|
var migrations = []string{
|
|
"ALTER TABLE Games ADD count INT DEFAULT 0;",
|
|
}
|
|
|
|
func connectDB() (*sql.DB, error) {
|
|
db, err := sql.Open("sqlite3", "./game.db")
|
|
if err != nil {
|
|
return db, err
|
|
}
|
|
|
|
err = checkPreinstall(db)
|
|
if err != nil {
|
|
return db, err
|
|
}
|
|
|
|
return db, nil
|
|
}
|
|
|
|
func checkPreinstall(db *sql.DB) error {
|
|
sqlStmt := `
|
|
CREATE TABLE IF NOT EXISTS Games (id INTEGER NOT NULL PRIMARY KEY, game_flow TEXT NOT NULL, first_won BOOL);
|
|
CREATE UNIQUE INDEX IF NOT EXISTS game_flow_idx ON Games (game_flow);
|
|
|
|
CREATE TABLE IF NOT EXISTS Stats (id INTEGER NOT NULL PRIMARY KEY, name TEXT NOT NULL, count INT, comment TEXT);
|
|
CREATE UNIQUE INDEX IF NOT EXISTS stats_idx ON Stats (name);
|
|
INSERT OR IGNORE INTO Stats (name, count) VALUES ('total', 0);
|
|
INSERT OR IGNORE INTO Stats (name, count) VALUES ('ai_won', 0);
|
|
INSERT OR IGNORE INTO Stats (name, count) VALUES ('draw', 0);
|
|
INSERT OR IGNORE INTO Stats (name, comment) VALUES ('last_ai_lost', NULL);
|
|
INSERT OR IGNORE INTO Stats (name, count) VALUES ('last_migration', 0);
|
|
`
|
|
_, err := db.Exec(sqlStmt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = runMigrations(db)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func runMigrations(db *sql.DB) error {
|
|
lastMigration, err := getStatsCounter(db, "last_migration")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for i := lastMigration; i < len(migrations); i++ {
|
|
sqlStmt := migrations[i]
|
|
_, err := db.Exec(sqlStmt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
db.Exec("UPDATE Stats SET count=count+1 WHERE name='last_migration';")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func getStatsCounter(db *sql.DB, name string) (int, error) {
|
|
stmt, err := db.Prepare("SELECT count FROM Stats WHERE name = ?")
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer stmt.Close()
|
|
|
|
var count int
|
|
err = stmt.QueryRow(name).Scan(&count)
|
|
if err != nil {
|
|
return 0, nil
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
func getStatsComment(db *sql.DB, name string) (string, error) {
|
|
stmt, err := db.Prepare("SELECT comment FROM Stats WHERE name = ?")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer stmt.Close()
|
|
|
|
var comment string
|
|
err = stmt.QueryRow(name).Scan(&comment)
|
|
if err != nil {
|
|
return "", nil
|
|
}
|
|
|
|
return comment, nil
|
|
}
|
|
|
|
func saveGameLog(db *sql.DB, game *Game) {
|
|
db.Exec("UPDATE Stats SET count=count+1 WHERE name='total';")
|
|
if game.hasWinner() {
|
|
db.Exec(
|
|
"INSERT OR IGNORE INTO Games (game_flow, first_won) VALUES (?, ?);",
|
|
game.gameFlow,
|
|
game.isFirstWon(),
|
|
)
|
|
db.Exec(
|
|
"UPDATE Games SET count=count+1 WHERE game_flow=? AND first_won=?;",
|
|
game.gameFlow,
|
|
game.isFirstWon(),
|
|
)
|
|
|
|
if game.isAiWon() {
|
|
db.Exec("UPDATE Stats SET count=count+1 WHERE name='ai_won';")
|
|
} else {
|
|
db.Exec("UPDATE Stats SET comment=datetime() WHERE name='last_ai_lost';")
|
|
}
|
|
} else {
|
|
db.Exec("UPDATE Stats SET count=count+1 WHERE name='draw';")
|
|
}
|
|
}
|
|
|
|
func getWinnerNextStep(db *sql.DB, game *Game) string {
|
|
stmt, err := db.Prepare(
|
|
"SELECT game_flow FROM Games WHERE game_flow LIKE ? AND first_won = ? ORDER BY count DESC",
|
|
)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
defer stmt.Close()
|
|
|
|
var gameFlow string
|
|
err = stmt.QueryRow(game.gameFlow+"%", !game.aiSecond).Scan(&gameFlow)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
return gameFlow[len(game.gameFlow) : len(game.gameFlow)+1]
|
|
}
|
|
|
|
func getStatsTable(db *sql.DB) [][]string {
|
|
result := make([][]string, 0)
|
|
rows, err := db.Query("SELECT id, name, IFNULL(count, ''), IFNULL(comment, '') FROM Stats")
|
|
if err != nil {
|
|
return result
|
|
}
|
|
|
|
defer rows.Close()
|
|
for rows.Next() {
|
|
var (
|
|
id string
|
|
name string
|
|
count string
|
|
comment string
|
|
)
|
|
if err := rows.Scan(&id, &name, &count, &comment); err != nil {
|
|
return result
|
|
}
|
|
result = append(result, []string{id, name, count, comment})
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return result
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func getGamesTable(db *sql.DB) [][]string {
|
|
result := make([][]string, 0)
|
|
rows, err := db.Query("SELECT * FROM Games ORDER BY count DESC")
|
|
if err != nil {
|
|
return result
|
|
}
|
|
|
|
defer rows.Close()
|
|
for rows.Next() {
|
|
var (
|
|
id string
|
|
gameFlow string
|
|
firstWon string
|
|
count string
|
|
)
|
|
if err := rows.Scan(&id, &gameFlow, &firstWon, &count); err != nil {
|
|
return result
|
|
}
|
|
result = append(result, []string{id, gameFlow, firstWon, count})
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return result
|
|
}
|
|
|
|
return result
|
|
}
|