Files
CosmicClash/server/store/ranked_profile_sql.go
2026-09-01 21:49:48 +01:00

49 lines
2.1 KiB
Go

package store
import (
"context"
"database/sql"
"fmt"
"github.com/cosmic-clash/cosmic-clash/server/domain"
)
const RankedProfileSelectSQL = `SELECT rating, deviation, volatility, ranked_games, updated_at,
COALESCE((SELECT season_id FROM seasons
WHERE playlist = 'ranked' AND starts_at <= CURRENT_TIMESTAMP AND ends_at > CURRENT_TIMESTAMP
ORDER BY starts_at DESC, season_id DESC LIMIT 1), ''),
COALESCE((SELECT ends_at FROM seasons
WHERE playlist = 'ranked' AND starts_at <= CURRENT_TIMESTAMP AND ends_at > CURRENT_TIMESTAMP
ORDER BY starts_at DESC, season_id DESC LIMIT 1), TIMESTAMP 'epoch')
FROM ratings
WHERE player_id = $1`
// PostgresRankedProfiles reads the durable rating row api.Service's
// RankedProfileProvider needs. A missing row means "this player has no
// ranked profile yet" (never queued ranked, or their identity predates any
// result) -- that's a real, expected state, not an error, and is reported
// the same way the in-memory RankedProfiles map api.Service still falls
// back to already did: (zero value, false, nil).
//
// LastSeasonID and SeasonHistory remain zero-valued because they describe
// rollover history, while CurrentSeasonID is derived from the active ranked
// season row. Keeping those concepts separate prevents the profile endpoint
// from making a current season look already rolled over to maintenance.
type PostgresRankedProfiles struct{ DB *sql.DB }
func (p PostgresRankedProfiles) Get(ctx context.Context, playerID string) (domain.RankedProfile, bool, error) {
if p.DB == nil || playerID == "" {
return domain.RankedProfile{}, false, fmt.Errorf("invalid ranked profile lookup")
}
var profile domain.RankedProfile
err := p.DB.QueryRowContext(ctx, RankedProfileSelectSQL, playerID).
Scan(&profile.Value, &profile.RD, &profile.Volatility, &profile.RankedGames, &profile.LastRatedAt, &profile.CurrentSeasonID, &profile.CurrentSeasonEndsAt)
if err == sql.ErrNoRows {
return domain.RankedProfile{}, false, nil
}
if err != nil {
return domain.RankedProfile{}, false, err
}
return profile, true, nil
}