Feat: player stats [WIP]
This commit is contained in:
		| @@ -86,3 +86,20 @@ CREATE TABLE journal( | ||||
|     FOREIGN KEY (username) REFERENCES players(username) ON DELETE CASCADE, | ||||
|     FOREIGN KEY (room_id) REFERENCES rooms(id) ON DELETE CASCADE | ||||
| ); | ||||
|  | ||||
| CREATE TABLE player_stats ( | ||||
|     id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||
|     player_username TEXT NOT NULL UNIQUE, | ||||
|     games_played INTEGER NOT NULL DEFAULT 0, | ||||
|     games_won INTEGER NOT NULL DEFAULT 0, | ||||
|     games_lost INTEGER NOT NULL DEFAULT 0, | ||||
|     opened_opposite_words INTEGER NOT NULL DEFAULT 0, | ||||
|     opened_white_words INTEGER NOT NULL DEFAULT 0, | ||||
|     opened_black_words INTEGER NOT NULL DEFAULT 0, | ||||
|     mime_winrate REAL NOT NULL DEFAULT 0.0, | ||||
|     guesser_winrate REAL NOT NULL DEFAULT 0.0, | ||||
|     played_as_mime INTEGER NOT NULL DEFAULT 0, | ||||
|     played_as_guesser INTEGER NOT NULL DEFAULT 0, | ||||
|     FOREIGN KEY (player_username) REFERENCES players(username) ON DELETE CASCADE | ||||
| ); | ||||
|  | ||||
|   | ||||
| @@ -138,6 +138,22 @@ type Journal struct { | ||||
| 	CreatedAt time.Time `db:"created_at"` | ||||
| } | ||||
|  | ||||
| type PlayerStats struct { | ||||
| 	ID                  uint32  `db:"id"` | ||||
| 	PlayerUsername      string  `db:"player_username"` | ||||
| 	GamesPlayed         int     `db:"games_played"` | ||||
| 	GamesWon            int     `db:"games_won"` | ||||
| 	GamesLost           int     `db:"games_lost"` | ||||
| 	OpenedOppositeWords int     `db:"opened_opposite_words"` | ||||
| 	OpenedWhiteWords    int     `db:"opened_white_words"` | ||||
| 	OpenedBlackWords    int     `db:"opened_black_words"` | ||||
| 	MimeWinrate         float64 `db:"mime_winrate"` | ||||
| 	GuesserWinrate      float64 `db:"guesser_winrate"` | ||||
| 	PlayedAsMime        int     `db:"played_as_mime"` | ||||
| 	PlayedAsGuesser     int     `db:"played_as_guesser"` | ||||
| } | ||||
|  | ||||
|  | ||||
| type Room struct { | ||||
| 	ID             string    `json:"id" db:"id"` | ||||
| 	CreatedAt      time.Time `json:"created_at" db:"created_at"` | ||||
|   | ||||
| @@ -2,7 +2,6 @@ package repos | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"gralias/config" | ||||
| 	"log/slog" | ||||
| 	"os" | ||||
| 	"sync" | ||||
| @@ -20,6 +19,7 @@ type AllRepos interface { | ||||
| 	WordCardsRepo | ||||
| 	SettingsRepo | ||||
| 	CardMarksRepo | ||||
| 	PlayerStatsRepo | ||||
| 	InitTx(ctx context.Context) (context.Context, *sqlx.Tx, error) | ||||
| 	Close() | ||||
| } | ||||
| @@ -32,12 +32,7 @@ type RepoProvider struct { | ||||
|  | ||||
| var RP AllRepos | ||||
|  | ||||
| func init() { | ||||
| 	cfg := config.LoadConfigOrDefault("") | ||||
| 	// sqlite3 has lock on write, so we need to have only one connection per whole app | ||||
| 	// https://github.com/mattn/go-sqlite3/issues/274#issuecomment-232942571 | ||||
| 	RP = NewRepoProvider(cfg.DBPath) | ||||
| } | ||||
|  | ||||
|  | ||||
| func NewRepoProvider(pathToDB string) *RepoProvider { | ||||
| 	db, err := sqlx.Connect("sqlite3", pathToDB) | ||||
|   | ||||
							
								
								
									
										42
									
								
								repos/player_stats.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								repos/player_stats.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| package repos | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"gralias/models" | ||||
|  | ||||
| 	"github.com/jmoiron/sqlx" | ||||
| ) | ||||
|  | ||||
| type PlayerStatsRepo interface { | ||||
| 	GetPlayerStats(ctx context.Context, username string) (*models.PlayerStats, error) | ||||
| 	UpdatePlayerStats(ctx context.Context, stats *models.PlayerStats) error | ||||
| 	CreatePlayerStats(ctx context.Context, username string) error | ||||
| } | ||||
|  | ||||
| func (p *RepoProvider) GetPlayerStats(ctx context.Context, username string) (*models.PlayerStats, error) { | ||||
| 	stats := &models.PlayerStats{} | ||||
| 	err := sqlx.GetContext(ctx, p.DB, stats, "SELECT * FROM player_stats WHERE player_username = ?", username) | ||||
| 	return stats, err | ||||
| } | ||||
|  | ||||
| func (p *RepoProvider) UpdatePlayerStats(ctx context.Context, stats *models.PlayerStats) error { | ||||
| 	_, err := p.DB.NamedExecContext(ctx, `UPDATE player_stats SET | ||||
| 		games_played = :games_played, | ||||
| 		games_won = :games_won, | ||||
| 		games_lost = :games_lost, | ||||
| 		opened_opposite_words = :opened_opposite_words, | ||||
| 		opened_white_words = :opened_white_words, | ||||
| 		opened_black_words = :opened_black_words, | ||||
| 		mime_winrate = :mime_winrate, | ||||
| 		guesser_winrate = :guesser_winrate, | ||||
| 		played_as_mime = :played_as_mime, | ||||
| 		played_as_guesser = :played_as_guesser | ||||
| 	WHERE player_username = :player_username`, stats) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (p *RepoProvider) CreatePlayerStats(ctx context.Context, username string) error { | ||||
| 	db := getDB(ctx, p.DB) | ||||
| 	_, err := db.ExecContext(ctx, "INSERT INTO player_stats (player_username) VALUES (?)", username) | ||||
| 	return err | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder