Add separate ratings for acey-deucey games

This commit is contained in:
Trevor Slocum 2024-01-02 18:38:14 -08:00
parent 4af5394f26
commit 1146b1c5c3
3 changed files with 148 additions and 76 deletions

View file

@ -27,21 +27,25 @@ import (
const databaseSchema = `
CREATE TABLE account (
id serial PRIMARY KEY,
created bigint NOT NULL,
confirmed bigint NOT NULL DEFAULT 0,
active bigint NOT NULL,
reset bigint NOT NULL DEFAULT 0,
email text NOT NULL,
username text NOT NULL,
password text NOT NULL,
casualsingle integer NOT NULL DEFAULT 150000,
casualmulti integer NOT NULL DEFAULT 150000,
ratedsingle integer NOT NULL DEFAULT 150000,
ratedmulti integer NOT NULL DEFAULT 150000,
highlight smallint NOT NULL DEFAULT 1,
pips smallint NOT NULL DEFAULT 1,
moves smallint NOT NULL DEFAULT 0
id serial PRIMARY KEY,
created bigint NOT NULL,
confirmed bigint NOT NULL DEFAULT 0,
active bigint NOT NULL,
reset bigint NOT NULL DEFAULT 0,
email text NOT NULL,
username text NOT NULL,
password text NOT NULL,
casual_backgammon_single integer NOT NULL DEFAULT 150000,
casual_backgammon_multi integer NOT NULL DEFAULT 150000,
casual_acey_single integer NOT NULL DEFAULT 150000,
casual_acey_multi integer NOT NULL DEFAULT 150000,
rated_backgammon_single integer NOT NULL DEFAULT 150000,
rated_backgammon_multi integer NOT NULL DEFAULT 150000,
rated_acey_single integer NOT NULL DEFAULT 150000,
rated_acey_multi integer NOT NULL DEFAULT 150000,
highlight smallint NOT NULL DEFAULT 1,
pips smallint NOT NULL DEFAULT 1,
moves smallint NOT NULL DEFAULT 0
);
CREATE TABLE game (
id serial PRIMARY KEY,
@ -459,16 +463,32 @@ func recordMatchResult(g *bgammon.Game, matchType int, account1 int, account2 in
var columnName string
switch matchType {
case matchTypeCasual:
if g.Points == 1 {
columnName = "casualsingle"
if !g.Acey {
if g.Points == 1 {
columnName = "casual_backgammon_single"
} else {
columnName = "casual_backgammon_multi"
}
} else {
columnName = "casualmulti"
if g.Points == 1 {
columnName = "casual_acey_single"
} else {
columnName = "casual_acey_multi"
}
}
case matchTypeRated:
if g.Points == 1 {
columnName = "ratedsingle"
if !g.Acey {
if g.Points == 1 {
columnName = "rated_backgammon_single"
} else {
columnName = "rated_backgammon_multi"
}
} else {
columnName = "ratedmulti"
if g.Points == 1 {
columnName = "rated_acey_single"
} else {
columnName = "rated_acey_multi"
}
}
default:
log.Panicf("unknown match type: %d", matchType)
@ -592,7 +612,7 @@ func matchHistory(username string) ([]*bgammon.HistoryMatch, error) {
return matches, nil
}
func getLeaderboard(matchType int, multiPoint bool) (*leaderboardResult, error) {
func getLeaderboard(matchType int, acey bool, multiPoint bool) (*leaderboardResult, error) {
dbLock.Lock()
defer dbLock.Unlock()
@ -605,16 +625,32 @@ func getLeaderboard(matchType int, multiPoint bool) (*leaderboardResult, error)
var columnName string
switch matchType {
case matchTypeCasual:
if !multiPoint {
columnName = "casualsingle"
if !acey {
if !multiPoint {
columnName = "casual_backgammon_single"
} else {
columnName = "casual_backgammon_multi"
}
} else {
columnName = "casualmulti"
if !multiPoint {
columnName = "casual_acey_single"
} else {
columnName = "casual_acey_multi"
}
}
case matchTypeRated:
if !multiPoint {
columnName = "ratedsingle"
if !acey {
if !multiPoint {
columnName = "rated_backgammon_single"
} else {
columnName = "rated_backgammon_multi"
}
} else {
columnName = "ratedmulti"
if !multiPoint {
columnName = "rated_acey_single"
} else {
columnName = "rated_acey_multi"
}
}
default:
log.Panicf("unknown match type: %d", matchType)

View file

@ -63,7 +63,7 @@ func matchHistory(username string) ([]*bgammon.HistoryMatch, error) {
return nil, nil
}
func getLeaderboard(matchType int, multiPoint bool) (*leaderboardResult, error) {
func getLeaderboard(matchType int, acey bool, multiPoint bool) (*leaderboardResult, error) {
return nil, nil
}

View file

@ -54,7 +54,7 @@ type server struct {
gamesCacheTime time.Time
gamesCacheLock sync.Mutex
leaderboardCache [4][]byte
leaderboardCache [8][]byte
leaderboardCacheTime time.Time
leaderboardCacheLock sync.Mutex
@ -150,7 +150,7 @@ func (s *server) cachedMatches() []byte {
return s.gamesCache
}
func (s *server) cachedLeaderboard(matchType int, multiPoint bool) []byte {
func (s *server) cachedLeaderboard(matchType int, acey bool, multiPoint bool) []byte {
s.leaderboardCacheLock.Lock()
defer s.leaderboardCacheLock.Unlock()
@ -167,47 +167,59 @@ func (s *server) cachedLeaderboard(matchType int, multiPoint bool) []byte {
i = 3
}
}
if acey {
i += 4
}
if time.Since(s.leaderboardCacheTime) < 5*time.Minute {
return s.leaderboardCache[i]
}
s.leaderboardCacheTime = time.Now()
result, err := getLeaderboard(matchTypeCasual, false)
if err != nil {
log.Fatalf("failed to get leaderboard: %s", err)
}
s.leaderboardCache[0], err = json.Marshal(result)
if err != nil {
log.Fatalf("failed to marshal %+v: %s", result, err)
for j := 0; j < 2; j++ {
i := 0
var acey bool
if j == 1 {
i += 4
acey = true
}
result, err := getLeaderboard(matchTypeCasual, acey, false)
if err != nil {
log.Fatalf("failed to get leaderboard: %s", err)
}
s.leaderboardCache[i], err = json.Marshal(result)
if err != nil {
log.Fatalf("failed to marshal %+v: %s", result, err)
}
result, err = getLeaderboard(matchTypeCasual, acey, true)
if err != nil {
log.Fatalf("failed to get leaderboard: %s", err)
}
s.leaderboardCache[i+1], err = json.Marshal(result)
if err != nil {
log.Fatalf("failed to marshal %+v: %s", result, err)
}
result, err = getLeaderboard(matchTypeRated, acey, false)
if err != nil {
log.Fatalf("failed to get leaderboard: %s", err)
}
s.leaderboardCache[i+2], err = json.Marshal(result)
if err != nil {
log.Fatalf("failed to marshal %+v: %s", result, err)
}
result, err = getLeaderboard(matchTypeRated, acey, true)
if err != nil {
log.Fatalf("failed to get leaderboard: %s", err)
}
s.leaderboardCache[i+3], err = json.Marshal(result)
if err != nil {
log.Fatalf("failed to marshal %+v: %s", result, err)
}
}
result, err = getLeaderboard(matchTypeCasual, true)
if err != nil {
log.Fatalf("failed to get leaderboard: %s", err)
}
s.leaderboardCache[1], err = json.Marshal(result)
if err != nil {
log.Fatalf("failed to marshal %+v: %s", result, err)
}
result, err = getLeaderboard(matchTypeRated, false)
if err != nil {
log.Fatalf("failed to get leaderboard: %s", err)
}
s.leaderboardCache[2], err = json.Marshal(result)
if err != nil {
log.Fatalf("failed to marshal %+v: %s", result, err)
}
result, err = getLeaderboard(matchTypeRated, true)
if err != nil {
log.Fatalf("failed to get leaderboard: %s", err)
}
s.leaderboardCache[3], err = json.Marshal(result)
if err != nil {
log.Fatalf("failed to marshal %+v: %s", result, err)
}
return s.leaderboardCache[i]
}
@ -255,24 +267,44 @@ func (s *server) handleListMatches(w http.ResponseWriter, r *http.Request) {
w.Write(s.cachedMatches())
}
func (s *server) handleLeaderboardCasualSingle(w http.ResponseWriter, r *http.Request) {
func (s *server) handleLeaderboardCasualBackgammonSingle(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write(s.cachedLeaderboard(matchTypeCasual, false))
w.Write(s.cachedLeaderboard(matchTypeCasual, false, false))
}
func (s *server) handleLeaderboardCasualMulti(w http.ResponseWriter, r *http.Request) {
func (s *server) handleLeaderboardCasualBackgammonMulti(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write(s.cachedLeaderboard(matchTypeCasual, true))
w.Write(s.cachedLeaderboard(matchTypeCasual, false, true))
}
func (s *server) handleLeaderboardRatedSingle(w http.ResponseWriter, r *http.Request) {
func (s *server) handleLeaderboardCasualAceySingle(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write(s.cachedLeaderboard(matchTypeRated, false))
w.Write(s.cachedLeaderboard(matchTypeCasual, true, false))
}
func (s *server) handleLeaderboardRatedMulti(w http.ResponseWriter, r *http.Request) {
func (s *server) handleLeaderboardCasualAceyMulti(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write(s.cachedLeaderboard(matchTypeRated, true))
w.Write(s.cachedLeaderboard(matchTypeCasual, true, true))
}
func (s *server) handleLeaderboardRatedBackgammonSingle(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write(s.cachedLeaderboard(matchTypeRated, false, false))
}
func (s *server) handleLeaderboardRatedBackgammonMulti(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write(s.cachedLeaderboard(matchTypeRated, false, true))
}
func (s *server) handleLeaderboardRatedAceySingle(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write(s.cachedLeaderboard(matchTypeRated, true, false))
}
func (s *server) handleLeaderboardRatedAceyMulti(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write(s.cachedLeaderboard(matchTypeRated, true, true))
}
func (s *server) handlePrintDailyStats(w http.ResponseWriter, r *http.Request) {
@ -361,10 +393,14 @@ func (s *server) listenWebSocket(address string) {
m.HandleFunc("/reset/{id:[0-9]+}/{key:[A-Za-z0-9]+}", s.handleResetPassword)
m.HandleFunc("/match/{id:[0-9]+}", s.handleMatch)
m.HandleFunc("/matches", s.handleListMatches)
m.HandleFunc("/leaderboard-casual-single", s.handleLeaderboardCasualSingle)
m.HandleFunc("/leaderboard-casual-multi", s.handleLeaderboardCasualMulti)
m.HandleFunc("/leaderboard-rated-single", s.handleLeaderboardRatedSingle)
m.HandleFunc("/leaderboard-rated-multi", s.handleLeaderboardRatedMulti)
m.HandleFunc("/leaderboard-casual-backgammon-single", s.handleLeaderboardCasualBackgammonSingle)
m.HandleFunc("/leaderboard-casual-backgammon-multi", s.handleLeaderboardCasualBackgammonMulti)
m.HandleFunc("/leaderboard-casual-acey-single", s.handleLeaderboardCasualAceySingle)
m.HandleFunc("/leaderboard-casual-acey-multi", s.handleLeaderboardCasualAceyMulti)
m.HandleFunc("/leaderboard-rated-backgammon-single", s.handleLeaderboardRatedBackgammonSingle)
m.HandleFunc("/leaderboard-rated-backgammon-multi", s.handleLeaderboardRatedBackgammonMulti)
m.HandleFunc("/leaderboard-rated-acey-single", s.handleLeaderboardRatedAceySingle)
m.HandleFunc("/leaderboard-rated-acey-multi", s.handleLeaderboardRatedAceyMulti)
m.HandleFunc("/stats", s.handlePrintDailyStats)
m.HandleFunc("/stats-total", s.handlePrintCumulativeStats)
m.HandleFunc("/stats-tabula", s.handlePrintTabulaStats)