Store match start and end time as int64

This commit is contained in:
Trevor Slocum 2024-08-30 00:06:09 -07:00
parent d2daf0da0b
commit dc5e2bfea5
6 changed files with 96 additions and 16 deletions

12
game.go
View file

@ -24,8 +24,8 @@ const (
)
type Game struct {
Started time.Time
Ended time.Time
Started int64
Ended int64
Player1 Player
Player2 Player
@ -124,7 +124,7 @@ func (g *Game) PartialTurn() int8 {
func (g *Game) PartialTime() int {
var delta time.Duration
if g.partialTime.IsZero() {
delta = time.Since(g.Started)
delta = since(g.Started)
} else {
delta = time.Since(g.partialTime)
}
@ -143,7 +143,7 @@ func (g *Game) SetPartialHandled(handled bool) {
}
func (g *Game) NextPartialTurn(player int8) {
if g.Started.IsZero() || g.Winner != 0 {
if g.Started == 0 || g.Winner != 0 {
return
}
@ -1073,3 +1073,7 @@ func (g *Game) TabulaBoard() (tabula.Board, bool) {
}
return tb, true
}
func since(timestamp int64) time.Duration {
return time.Since(time.Unix(timestamp, 0))
}

View file

@ -81,6 +81,7 @@ type serverClient struct {
commands chan []byte
autoplay bool
playerNumber int8
legacy bool
terminating bool
bgammon.Client
}
@ -116,7 +117,24 @@ func (c *serverClient) sendEvent(e interface{}) {
case *bgammon.EventFailedLeave:
ev.Type = bgammon.EventTypeFailedLeave
case *bgammon.EventBoard:
ev.Type = bgammon.EventTypeBoard
if !c.legacy {
ev.Type = bgammon.EventTypeBoard
} else {
v := &eventBoardCompat{}
v.Type = bgammon.EventTypeBoard
v.gameStateCompat = gameStateCompat{
gameCompat: &gameCompat{
Game: *ev.Game,
Started: timestamp(ev.Game.Started),
Ended: timestamp(ev.Game.Ended),
},
PlayerNumber: ev.PlayerNumber,
Available: ev.Available,
Forced: ev.Forced,
Spectating: ev.Spectating,
}
e = v
}
case *bgammon.EventRolled:
ev.Type = bgammon.EventTypeRolled
case *bgammon.EventFailedRoll:
@ -327,3 +345,38 @@ func logClientRead(msg []byte) {
log.Printf("<- %s", msg)
}
}
func legacyClient(clientName []byte) bool {
split := bytes.Split(clientName, []byte("-"))
if len(split) == 0 {
return true
} else if !bytes.Equal(split[0], []byte("boxcars")) {
return false
}
last := split[len(split)-1]
lastSplit := bytes.Split(last, []byte("."))
if len(lastSplit) != 3 {
return true
}
major, minor := parseInt(lastSplit[0]), parseInt(lastSplit[1])
return major < 1 || (major == 1 && minor < 4)
}
func parseInt(buf []byte) int {
matches := anyNumbers.FindAll(buf, -1)
if len(matches) == 0 {
return 0
}
v, err := strconv.Atoi(string(matches[0]))
if err != nil {
v = 0
}
return v
}
func timestamp(ts int64) time.Time {
if ts == 0 {
return time.Time{}
}
return time.Unix(ts, 0)
}

View file

@ -585,13 +585,13 @@ func recordGameResult(g *serverGame, winType int8, replay [][]byte) error {
dbLock.Lock()
defer dbLock.Unlock()
if db == nil || g.Started.IsZero() || g.Winner == 0 || len(g.replay) == 0 {
if db == nil || g.Started == 0 || g.Winner == 0 || len(g.replay) == 0 {
return nil
}
ended := g.Ended
if ended.IsZero() {
ended = time.Now()
if ended == 0 {
ended = time.Now().Unix()
}
tx, err := begin()
@ -600,7 +600,7 @@ func recordGameResult(g *serverGame, winType int8, replay [][]byte) error {
}
defer tx.Commit(context.Background())
_, err = tx.Exec(context.Background(), "INSERT INTO game (variant, started, ended, player1, account1, player2, account2, points, winner, wintype, replay) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", g.Variant, g.Started.Unix(), ended.Unix(), g.allowed1, g.account1, g.allowed2, g.account2, g.Points, g.Winner, winType, bytes.Join(replay, []byte("\n")))
_, err = tx.Exec(context.Background(), "INSERT INTO game (variant, started, ended, player1, account1, player2, account2, points, winner, wintype, replay) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", g.Variant, g.Started, ended, g.allowed1, g.account1, g.allowed2, g.account2, g.Points, g.Winner, winType, bytes.Join(replay, []byte("\n")))
if err != nil {
return err
}
@ -624,7 +624,7 @@ func recordMatchResult(g *serverGame, matchType int) error {
dbLock.Lock()
defer dbLock.Unlock()
if db == nil || g.Started.IsZero() || g.Winner == 0 || g.account1 == 0 || g.account2 == 0 || g.account1 == g.account2 {
if db == nil || g.Started == 0 || g.Winner == 0 || g.account1 == 0 || g.account2 == 0 || g.account1 == g.account2 {
return nil
}

View file

@ -157,8 +157,8 @@ func (g *serverGame) roll(player int8) bool {
}
// Store account IDs.
if g.Started.IsZero() && g.Roll1 != 0 && g.Roll2 != 0 {
g.Started = time.Now()
if g.Started == 0 && g.Roll1 != 0 && g.Roll2 != 0 {
g.Started = time.Now().Unix()
if g.client1.account != nil {
g.account1 = g.client1.account.id
}
@ -596,7 +596,7 @@ func (g *serverGame) nextTurn(reroll bool) {
}
func (g *serverGame) addReplayHeader() {
g.replay = append([][]byte{[]byte(fmt.Sprintf("i %d %s %s %d %d %d %d %d %d", g.Started.Unix(), g.allowed1, g.allowed2, g.Points, g.Player1.Points, g.Player2.Points, g.Winner, g.DoubleValue, g.Variant))}, g.replay...)
g.replay = append([][]byte{[]byte(fmt.Sprintf("i %d %s %s %d %d %d %d %d %d", g.Started, g.allowed1, g.allowed2, g.Points, g.Player1.Points, g.Player2.Points, g.Winner, g.DoubleValue, g.Variant))}, g.replay...)
}
func (g *serverGame) handleWin() bool {
@ -681,7 +681,7 @@ func (g *serverGame) handleWin() bool {
if g.Player1.Points < g.Points {
reset = true
} else {
g.Ended = time.Now()
g.Ended = time.Now().Unix()
}
} else {
winEvent.Player = g.Player2.Name
@ -689,7 +689,7 @@ func (g *serverGame) handleWin() bool {
if g.Player2.Points < g.Points {
reset = true
} else {
g.Ended = time.Now()
g.Ended = time.Now().Unix()
}
}

View file

@ -33,6 +33,7 @@ const maxUsernameLength = 18
const inactiveLimit = 600 // 10 minutes.
var (
anyNumbers = regexp.MustCompile(`[0-9]+`)
onlyNumbers = regexp.MustCompile(`^[0-9]+$`)
guestName = regexp.MustCompile(`^guest[0-9]+$`)
alphaNumericUnderscore = regexp.MustCompile(`^[A-Za-z0-9_]+$`)
@ -721,3 +722,23 @@ func (p ratingPlayer) Sigma() float64 {
func (p ratingPlayer) SJ() float64 {
return p.outcome
}
type gameCompat struct {
bgammon.Game
Started time.Time
Ended time.Time
}
type gameStateCompat struct {
*gameCompat
PlayerNumber int8
Available [][]int8 // Legal moves.
Forced bool // A forced move is being played automatically.
Spectating bool
}
type eventBoardCompat struct {
bgammon.Event
gameStateCompat
}

View file

@ -49,6 +49,7 @@ func (s *server) handleFirstCommand(cmd serverCommand, keyword string, params []
sendUsage()
return
}
cmd.client.legacy = legacyClient(params[0])
slashIndex := bytes.IndexRune(params[0], '/')
if slashIndex != -1 {
cmd.client.language = "bgammon-" + string(s.matchLanguage(params[0][slashIndex+1:]))
@ -91,6 +92,7 @@ func (s *server) handleFirstCommand(cmd serverCommand, keyword string, params []
readUsername := func() bool {
if cmd.client.json {
if len(params) > 0 {
cmd.client.legacy = legacyClient(params[0])
slashIndex := bytes.IndexRune(params[0], '/')
if slashIndex != -1 {
cmd.client.language = "bgammon-" + string(s.matchLanguage(params[0][slashIndex+1:]))
@ -705,7 +707,7 @@ COMMANDS:
clientGame.replay = append(clientGame.replay, []byte(fmt.Sprintf("%d t", cmd.client.playerNumber)))
}
clientGame.Ended = time.Now()
clientGame.Ended = time.Now().Unix()
var reset bool
if clientGame.Winner == 1 {