Feat: update stats
This commit is contained in:
@ -71,6 +71,7 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) {
|
|||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
updateStatsOnCardReveal(r.Context(), fi.State, color)
|
||||||
fi.Room.UpdateCounter()
|
fi.Room.UpdateCounter()
|
||||||
action := models.Action{
|
action := models.Action{
|
||||||
Actor: fi.State.Username,
|
Actor: fi.State.Username,
|
||||||
@ -121,6 +122,7 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) {
|
|||||||
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
||||||
clearMarks = true
|
clearMarks = true
|
||||||
StopTurnTimer(fi.Room.ID)
|
StopTurnTimer(fi.Room.ID)
|
||||||
|
updateStatsOnGameOver(r.Context(), fi.Room)
|
||||||
case string(models.WordColorWhite), string(oppositeColor):
|
case string(models.WordColorWhite), string(oppositeColor):
|
||||||
log.Debug("opened white or opposite color word", "word", word, "opposite-color", oppositeColor)
|
log.Debug("opened white or opposite color word", "word", word, "opposite-color", oppositeColor)
|
||||||
// end turn
|
// end turn
|
||||||
@ -144,6 +146,7 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) {
|
|||||||
Action: models.ActionTypeGameOver,
|
Action: models.ActionTypeGameOver,
|
||||||
}
|
}
|
||||||
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
||||||
|
updateStatsOnGameOver(r.Context(), fi.Room)
|
||||||
}
|
}
|
||||||
if fi.Room.RedCounter == 0 {
|
if fi.Room.RedCounter == 0 {
|
||||||
// red won
|
// red won
|
||||||
@ -158,6 +161,7 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) {
|
|||||||
Action: models.ActionTypeGameOver,
|
Action: models.ActionTypeGameOver,
|
||||||
}
|
}
|
||||||
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
||||||
|
updateStatsOnGameOver(r.Context(), fi.Room)
|
||||||
}
|
}
|
||||||
default: // same color as the team
|
default: // same color as the team
|
||||||
// check if game over
|
// check if game over
|
||||||
@ -173,6 +177,7 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) {
|
|||||||
Action: models.ActionTypeGameOver,
|
Action: models.ActionTypeGameOver,
|
||||||
}
|
}
|
||||||
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
||||||
|
updateStatsOnGameOver(r.Context(), fi.Room)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if clearMarks {
|
if clearMarks {
|
||||||
|
80
handlers/stats.go
Normal file
80
handlers/stats.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"gralias/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// updateStatsOnCardReveal updates player stats when a card is revealed.
|
||||||
|
func updateStatsOnCardReveal(ctx context.Context, player *models.Player, cardColor models.WordColor) {
|
||||||
|
if player.IsBot {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stats, err := repo.GetPlayerStats(ctx, player.Username)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("failed to get player stats for card reveal update", "username", player.Username, "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
playerTeamColorStr := string(player.Team)
|
||||||
|
switch cardColor {
|
||||||
|
case models.WordColorBlack:
|
||||||
|
stats.OpenedBlackWords++
|
||||||
|
case models.WordColorWhite:
|
||||||
|
stats.OpenedWhiteWords++
|
||||||
|
default:
|
||||||
|
if string(cardColor) != playerTeamColorStr {
|
||||||
|
stats.OpenedOppositeWords++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := repo.UpdatePlayerStats(ctx, stats); err != nil {
|
||||||
|
log.Error("failed to update player stats on card reveal", "username", player.Username, "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateStatsOnGameOver updates stats for all players in a room when a game ends.
|
||||||
|
func updateStatsOnGameOver(ctx context.Context, room *models.Room) {
|
||||||
|
// Get all players in the room
|
||||||
|
players, err := repo.PlayerListByRoom(ctx, room.ID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("failed to list players by room for stats update", "room_id", room.ID, "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, player := range players {
|
||||||
|
if player.IsBot {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
stats, err := repo.GetPlayerStats(ctx, player.Username)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("failed to get player stats for game over update", "username", player.Username, "error", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
stats.GamesPlayed++
|
||||||
|
if player.Team == room.TeamWon {
|
||||||
|
stats.GamesWon++
|
||||||
|
} else {
|
||||||
|
stats.GamesLost++
|
||||||
|
}
|
||||||
|
if player.Role == models.UserRoleMime {
|
||||||
|
stats.PlayedAsMime++
|
||||||
|
if stats.PlayedAsMime > 0 {
|
||||||
|
gamesWonAsMime := stats.MimeWinrate * float64(stats.PlayedAsMime-1)
|
||||||
|
if player.Team == room.TeamWon {
|
||||||
|
gamesWonAsMime++
|
||||||
|
}
|
||||||
|
stats.MimeWinrate = gamesWonAsMime / float64(stats.PlayedAsMime)
|
||||||
|
}
|
||||||
|
} else if player.Role == models.UserRoleGuesser {
|
||||||
|
stats.PlayedAsGuesser++
|
||||||
|
if stats.PlayedAsGuesser > 0 {
|
||||||
|
gamesWonAsGuesser := stats.GuesserWinrate * float64(stats.PlayedAsGuesser-1)
|
||||||
|
if player.Team == room.TeamWon {
|
||||||
|
gamesWonAsGuesser++
|
||||||
|
}
|
||||||
|
stats.GuesserWinrate = gamesWonAsGuesser / float64(stats.PlayedAsGuesser)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := repo.UpdatePlayerStats(ctx, stats); err != nil {
|
||||||
|
log.Error("failed to update player stats on game over", "username", player.Username, "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -47,7 +47,13 @@ func (p *RepoProvider) PlayerAdd(ctx context.Context, player *models.Player) err
|
|||||||
db := getDB(ctx, p.DB)
|
db := getDB(ctx, p.DB)
|
||||||
_, err := db.ExecContext(ctx, "INSERT INTO players (room_id, username, team, role, is_bot, password) VALUES (?, ?, ?, ?, ?, ?)",
|
_, err := db.ExecContext(ctx, "INSERT INTO players (room_id, username, team, role, is_bot, password) VALUES (?, ?, ?, ?, ?, ?)",
|
||||||
player.RoomID, player.Username, player.Team, player.Role, player.IsBot, player.Password)
|
player.RoomID, player.Username, player.Team, player.Role, player.IsBot, player.Password)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
if !player.IsBot {
|
||||||
|
return p.CreatePlayerStats(ctx, player.Username)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RepoProvider) PlayerUpdate(ctx context.Context, player *models.Player) error {
|
func (p *RepoProvider) PlayerUpdate(ctx context.Context, player *models.Player) error {
|
||||||
|
Reference in New Issue
Block a user