diff --git a/go.mod b/go.mod index ef7f9d3..4386c64 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,10 @@ go 1.22.6 require github.com/alexflint/go-arg v1.5.1 require ( + filippo.io/edwards25519 v1.1.0 // indirect github.com/alexflint/go-scalar v1.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/graphql-go/graphql v0.8.1 // indirect github.com/graphql-go/handler v0.2.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/go.sum b/go.sum index 1eecb00..f9891db 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,13 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/alexflint/go-arg v1.5.1 h1:nBuWUCpuRy0snAG+uIJ6N0UvYxpxA0/ghA/AaHxlT8Y= github.com/alexflint/go-arg v1.5.1/go.mod h1:A7vTJzvjoaSTypg4biM5uYNTkJ27SkNTArtYXnlqVO8= github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw= github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/graphql-go/graphql v0.8.1 h1:p7/Ou/WpmulocJeEx7wjQy611rtXGQaAcXGqanuMMgc= github.com/graphql-go/graphql v0.8.1/go.mod h1:nKiHzRM0qopJEwCITUuIsxk9PlVlwIiiI8pnJEhordQ= github.com/graphql-go/handler v0.2.4 h1:gz9q11TUHPNUpqzV8LMa+rkqM5NUuH/nkE3oF2LS3rI= diff --git a/internal/repo/sqlRepo.go b/internal/repo/sqlRepo.go new file mode 100644 index 0000000..22501ab --- /dev/null +++ b/internal/repo/sqlRepo.go @@ -0,0 +1,161 @@ +package repo + +import ( + "database/sql" + "strconv" + + "git.kapelle.org/niklas/beerpong-elo/internal/model" + _ "github.com/go-sql-driver/mysql" +) + +type SQLRepo struct { + db *sql.DB +} + +func NewSQLRepo() (Repo, error) { + db, err := sql.Open("mysql", "root:hunter2@/beer") + if err != nil { + return nil, err + } + + 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 "0", 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 "0", err + } + + id, err := res.LastInsertId() + if err != nil { + return "0", err + } + + return model.GameID(strconv.Itoa(int(id))), nil +} + +func (s *SQLRepo) AddGameResult(model.GameResult) (model.GameResultID, error) { + panic("unimplemented") +} + +func (s *SQLRepo) GetAllPlayers() ([]model.Player, error) { + panic("unimplemented") +} + +func (s *SQLRepo) GetGame(id model.GameID) (*model.Game, error) { + rows := s.db.QueryRow("SELECT id,score,overtime,author,team0player0,team0player1,team1player0,team1player1 FROM Games WHERE id = ? ", id) + + var foundID int64 + // var foundAdded time.Time + var foundScore int64 + var foundOvertime bool + var foundAuthor int64 + + var foundT0P0 int64 + var foundT0P1 int64 + var foundT1P0 int64 + var foundT1P1 int64 + + if err := rows.Scan(&foundID,&foundScore,&foundOvertime,&foundAuthor,&foundT0P0,&foundT0P1,&foundT1P0,&foundT1P1); err != nil { + if err == sql.ErrNoRows { + return nil, nil + } + return nil, err + } + + game := model.Game{ + ID: model.GameID(int64ToString(foundID)), + // Added: foundAdded, + Score: int(foundScore), + Overtime: foundOvertime, + Author: model.PlayerID(int64ToString(foundAuthor)), + + Team0Player0: model.PlayerID(int64ToString(foundT0P0)), + Team0Player1: model.PlayerID(int64ToString(foundT0P1)), + Team1Player0: model.PlayerID(int64ToString(foundT1P0)), + Team1Player1: model.PlayerID(int64ToString(foundT1P1)), + } + + return &game, nil +} + +func (s *SQLRepo) GetGameResult(model.GameResultID) (*model.GameResult, error) { + panic("unimplemented") +} + +func (s *SQLRepo) PlayerWithNameExists(name string) (*model.PlayerID, error) { + rows := s.db.QueryRow("SELECT id FROM Players WHERE name = ?", name) + + var id int64 + + if err := rows.Scan(&id); err != nil { + if err == sql.ErrNoRows { + return nil, nil + } + return nil, err + } + + sID := int64ToString(id) + + return (*model.PlayerID)(&sID), 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) VALUES (?)") + if err != nil { + return "", err + } + + res, err := stmt.Exec(name) + if err != nil { + return "", err + } + + id, err := res.LastInsertId() + if err != nil { + return "", err + } + + return model.PlayerID(strconv.Itoa(int(id))), nil +} + +func (s *SQLRepo) GetPlayer(id model.PlayerID) (*model.Player, error) { + rows := s.db.QueryRow("SELECT id,name from Players WHERE id = ?", id) + + var playerID int64 + var playerName string + + if err := rows.Scan(&playerID, &playerName); err != nil { + if err == sql.ErrNoRows { + return nil, nil + } + return nil, err + } + + return &model.Player{ + ID: model.PlayerID(strconv.Itoa(int(playerID))), + }, nil +} + +func int64ToString(i int64) string { + return strconv.Itoa(int(i)) +} diff --git a/internal/repo/sqlSchema.sql b/internal/repo/sqlSchema.sql new file mode 100644 index 0000000..5caae19 --- /dev/null +++ b/internal/repo/sqlSchema.sql @@ -0,0 +1,31 @@ +CREATE TABLE Players ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL +); + +CREATE TABLE Games ( + id INT AUTO_INCREMENT PRIMARY KEY, + added DATETIME NOT NULL, + score INT NOT NULL, + overtime BOOL NOT NULL, + author INT, + team0player0 INT, + team0player1 INT, + team1player0 INT, + team1player1 INT, + FOREIGN KEY (author) REFERENCES Players(id) on DELETE SET NULL, + FOREIGN KEY (team0player0) REFERENCES Players(id) ON DELETE SET NULL, + FOREIGN KEY (team0player1) REFERENCES Players(id) ON DELETE SET NULL, + FOREIGN KEY (team1player0) REFERENCES Players(id) ON DELETE SET NULL, + FOREIGN KEY (team1player1) REFERENCES Players(id) ON DELETE SET NULL +); + +CREATE TABLE GameResults ( + id INT AUTO_INCREMENT PRIMARY KEY, + game INT, + player INT, + startElo INT, + endElo INT, + FOREIGN KEY (game) REFERENCES Games(id) on DELETE SET NULL, + FOREIGN KEY (player) REFERENCES Players(id) on DELETE SET NULL +)