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 (username) REFERENCES players(username) ON DELETE CASCADE, | ||||||
|     FOREIGN KEY (room_id) REFERENCES rooms(id) 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"` | 	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 { | type Room struct { | ||||||
| 	ID             string    `json:"id" db:"id"` | 	ID             string    `json:"id" db:"id"` | ||||||
| 	CreatedAt      time.Time `json:"created_at" db:"created_at"` | 	CreatedAt      time.Time `json:"created_at" db:"created_at"` | ||||||
|   | |||||||
| @@ -2,7 +2,6 @@ package repos | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"gralias/config" |  | ||||||
| 	"log/slog" | 	"log/slog" | ||||||
| 	"os" | 	"os" | ||||||
| 	"sync" | 	"sync" | ||||||
| @@ -20,6 +19,7 @@ type AllRepos interface { | |||||||
| 	WordCardsRepo | 	WordCardsRepo | ||||||
| 	SettingsRepo | 	SettingsRepo | ||||||
| 	CardMarksRepo | 	CardMarksRepo | ||||||
|  | 	PlayerStatsRepo | ||||||
| 	InitTx(ctx context.Context) (context.Context, *sqlx.Tx, error) | 	InitTx(ctx context.Context) (context.Context, *sqlx.Tx, error) | ||||||
| 	Close() | 	Close() | ||||||
| } | } | ||||||
| @@ -32,12 +32,7 @@ type RepoProvider struct { | |||||||
|  |  | ||||||
| var RP AllRepos | 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 { | func NewRepoProvider(pathToDB string) *RepoProvider { | ||||||
| 	db, err := sqlx.Connect("sqlite3", pathToDB) | 	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