280 lines
6.4 KiB
Go
Raw Normal View History

2025-02-02 15:11:35 +01:00
package repo
import (
"database/sql"
"fmt"
"time"
"git.kapelle.org/niklas/beerpong-elo/internal/model"
_ "github.com/go-sql-driver/mysql"
)
type SQLRepo struct {
db *sql.DB
}
func NewSQLRepo(host, username, password, dbName string) (Repo, error) {
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?parseTime=true", username, password, host, dbName))
if err != nil {
return nil, err
}
db.SetConnMaxLifetime(time.Minute * 3)
db.SetMaxOpenConns(10)
db.SetMaxIdleConns(10)
return &SQLRepo{
db: db,
}, nil
}
func (s *SQLRepo) AddGame(game model.Game) (model.GameID, error) {
stmt, err := s.db.Prepare("INSERT INTO Games(added,score,overtime,author,team0player0,team0player1,team1player0,team1player1) VALUES (?,?,?,?,?,?,?,?)")
if err != nil {
return "", err
}
res, err := stmt.Exec(game.Added, game.Score, game.Overtime, game.Author, game.Team0Player0, game.Team0Player1, game.Team1Player0, game.Team1Player1)
if err != nil {
return "", err
}
id, err := res.LastInsertId()
if err != nil {
return "", err
}
var gameID model.GameID
gameID.Scan(id)
return gameID, nil
}
func (s *SQLRepo) AddGameResult(gameResult model.GameResult) (model.GameResultID, error) {
stms, err := s.db.Prepare("INSERT INTO GameResults(game,player,startElo,endElo) VALUES (?,?,?,?)")
if err != nil {
return "", err
}
res, err := stms.Exec(gameResult.Game, gameResult.Player, gameResult.StartElo, gameResult.EndElo)
if err != nil {
return "", err
}
id, err := res.LastInsertId()
if err != nil {
return "", err
}
var gameResultID model.GameResultID
gameResultID.Scan(id)
return gameResultID, nil
}
func (s *SQLRepo) GetGame(id model.GameID) (*model.Game, error) {
rows := s.db.QueryRow("SELECT id,added, score,overtime,author,team0player0,team0player1,team1player0,team1player1 FROM Games WHERE id = ? ", id)
var game model.Game
if err := rows.Scan(&game.ID, &game.Added, &game.Score, &game.Overtime, &game.Author, &game.Team0Player0, &game.Team0Player1, &game.Team1Player0, &game.Team1Player1); err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
return &game, nil
}
func (s *SQLRepo) GetGameResult(id model.GameResultID) (*model.GameResult, error) {
rows := s.db.QueryRow("SELECT game,player,startElo,endElo FROM GameResults WHERE id = ? ", id)
var gameResult model.GameResult
gameResult.ID = id
if err := rows.Scan(&gameResult.Game, &gameResult.Player, &gameResult.StartElo, &gameResult.EndElo); err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
return &gameResult, nil
}
func (s *SQLRepo) playerWithNameExists(name string) (*model.PlayerID, error) {
rows := s.db.QueryRow("SELECT id FROM Players WHERE name = ?", name)
var id model.PlayerID
if err := rows.Scan(&id); err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
return &id, nil
}
func (s *SQLRepo) GetOrCreatePlayerID(name string) (model.PlayerID, error) {
foundID, err := s.playerWithNameExists(name)
if err != nil {
return "", err
}
if foundID != nil {
return *foundID, nil
}
stmt, err := s.db.Prepare("INSERT INTO Players(name,elo) VALUES (?,?)")
if err != nil {
return "", err
}
newPlayer := model.NewPlayer(name)
res, err := stmt.Exec(newPlayer.Name, newPlayer.Elo)
if err != nil {
return "", err
}
id, err := res.LastInsertId()
if err != nil {
return "", err
}
var playerID model.PlayerID
playerID.Scan(id)
return playerID, nil
}
func (s *SQLRepo) GetPlayer(id model.PlayerID) (*model.Player, error) {
rows := s.db.QueryRow("SELECT name,elo from Players WHERE id = ?", id)
var player model.Player
player.ID = id
if err := rows.Scan(&player.Name, &player.Elo); err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
return &player, nil
}
func (s *SQLRepo) GetGamesForPlayer(id model.PlayerID) ([]*model.Game, error) {
rows, err := s.db.Query(`
SELECT id,added, score,overtime,author,team0player0,team0player1,team1player0,team1player1
FROM Games
WHERE team0player0 = ? OR team0player1 = ? OR team1player0 = ? OR team1player1 = ?
`, id, id, id, id)
if err != nil {
return nil, err
}
defer rows.Close()
rtn := []*model.Game{}
for rows.Next() {
var game model.Game
err = rows.Scan(&game.ID, &game.Added, &game.Score, &game.Overtime, &game.Author, &game.Team0Player0, &game.Team0Player1, &game.Team1Player0, &game.Team1Player1)
if err != nil {
return nil, err
}
rtn = append(rtn, &game)
}
return rtn, nil
}
func (s *SQLRepo) GetGameResultForPlayerAndGame(gameID model.GameID, playerID model.PlayerID) (*model.GameResult, error) {
rows := s.db.QueryRow("SELECT id,game,player,startElo,endElo FROM GameResults WHERE game = ? AND player = ? ", gameID, playerID)
var gameResult model.GameResult
if err := rows.Scan(&gameResult.ID, &gameResult.Game, &gameResult.Player, &gameResult.StartElo, &gameResult.EndElo); err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, err
}
return &gameResult, nil
}
func (s *SQLRepo) GetGameResultsForPlayer(id model.PlayerID) ([]*model.GameResult, error) {
rows, err := s.db.Query("SELECT id,game,player,startElo,endElo FROM GameResults WHERE player = ? ", id)
if err != nil {
return nil, err
}
rtn := []*model.GameResult{}
for rows.Next() {
var gameResult model.GameResult
err = rows.Scan(&gameResult.ID, &gameResult.Game, &gameResult.Player, &gameResult.StartElo, &gameResult.EndElo)
if err != nil {
return nil, err
}
rtn = append(rtn, &gameResult)
}
return rtn, nil
}
func (s *SQLRepo) GetPlayers() ([]*model.Player, error) {
rows, err := s.db.Query("SELECT id, name, elo FROM Players")
if err != nil {
return nil, err
}
rtn := []*model.Player{}
for rows.Next() {
var player model.Player
err = rows.Scan(&player.ID, &player.Name, &player.Elo)
if err != nil {
return nil, err
}
rtn = append(rtn, &player)
}
return rtn, nil
}
func (s *SQLRepo) GetGames() ([]*model.Game, error) {
rows, err := s.db.Query("SELECT id,added, score,overtime,author,team0player0,team0player1,team1player0,team1player1 FROM Games")
if err != nil {
return nil, err
}
rtn := []*model.Game{}
for rows.Next() {
var game model.Game
err = rows.Scan(&game.ID, &game.Added, &game.Score, &game.Overtime, &game.Author, &game.Team0Player0, &game.Team0Player1, &game.Team1Player0, &game.Team1Player1)
if err != nil {
return nil, err
}
rtn = append(rtn, &game)
}
return rtn, nil
}