Add history command

This commit is contained in:
Trevor Slocum 2023-12-19 16:26:05 -08:00
parent aef7db8309
commit 54a5c228c1
9 changed files with 86 additions and 3 deletions

View file

@ -54,6 +54,9 @@ formatted responses are more easily parsed by computers.
- `replay <id>`
- Retrieve replay of the specified game.
- `history <username>`
- Retrieve match history of the specified player.
- `json <on/off>`
- Turn JSON formatted messages on or off. JSON messages are not sent by default.

View file

@ -11,6 +11,7 @@ const (
CommandPassword = "password" // Change password.
CommandSet = "set" // Change account setting.
CommandReplay = "replay" // Retrieve replay.
CommandHistory = "history" // Retrieve match history.
CommandHelp = "help" // Print help information.
CommandJSON = "json" // Enable or disable JSON formatted messages.
CommandSay = "say" // Send chat message.
@ -52,4 +53,5 @@ const (
EventTypeWin = "win"
EventTypeSettings = "settings"
EventTypeReplay = "replay"
EventTypeHistory = "history"
)

View file

@ -123,6 +123,19 @@ type EventReplay struct {
Content []byte
}
type HistoryMatch struct {
ID int
Timestamp int64
Points int
Opponent string
Winner int
}
type EventHistory struct {
Event
Matches []*HistoryMatch
}
func DecodeEvent(message []byte) (interface{}, error) {
e := &Event{}
err := json.Unmarshal(message, e)
@ -170,6 +183,8 @@ func DecodeEvent(message []byte) (interface{}, error) {
ev = &EventSettings{}
case EventTypeReplay:
ev = &EventReplay{}
case EventTypeHistory:
ev = &EventHistory{}
default:
return nil, fmt.Errorf("failed to decode event: unknown event type: %s", e.Type)
}

2
go.mod
View file

@ -34,7 +34,7 @@ require (
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/vanng822/css v1.0.1 // indirect
github.com/vanng822/go-premailer v1.20.2 // indirect
golang.org/x/crypto v0.16.0 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect

4
go.sum
View file

@ -100,8 +100,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=

View file

@ -67,6 +67,8 @@ func (c *serverClient) sendEvent(e interface{}) {
ev.Type = bgammon.EventTypeSettings
case *bgammon.EventReplay:
ev.Type = bgammon.EventTypeReplay
case *bgammon.EventHistory:
ev.Type = bgammon.EventTypeHistory
default:
log.Panicf("unknown event type %+v", ev)
}

View file

@ -461,6 +461,47 @@ func replayByID(id int) ([]byte, error) {
return replay, nil
}
func matchHistory(username string) ([]*bgammon.HistoryMatch, error) {
dbLock.Lock()
defer dbLock.Unlock()
tx, err := begin()
if err != nil {
return nil, err
}
defer tx.Commit(context.Background())
username = strings.ToLower(username)
var matches []*bgammon.HistoryMatch
var player1, player2 string
var winner int
rows, err := tx.Query(context.Background(), "SELECT id, started, player1, player2, points, winner FROM game WHERE (LOWER(player1) = $1 OR LOWER(player2) = $2) AND replay != '' ORDER BY id DESC", username, username)
if err != nil {
return nil, err
}
for rows.Next() {
if err != nil {
continue
}
match := &bgammon.HistoryMatch{}
err = rows.Scan(&match.ID, &match.Timestamp, &player1, &player2, &match.Points, &winner)
if err != nil {
continue
}
if strings.ToLower(player1) == username {
match.Winner, match.Opponent = winner, player2
} else {
match.Winner, match.Opponent = 1+(2-winner), player1
}
matches = append(matches, match)
}
if err != nil {
return nil, err
}
return matches, nil
}
func dailyStats(tz *time.Location) (*serverStatsResult, error) {
dbLock.Lock()
defer dbLock.Unlock()

View file

@ -51,6 +51,10 @@ func recordGameResult(g *bgammon.Game, winType int, account1 int, account2 int,
return nil
}
func matchHistory(username string) ([]*bgammon.HistoryMatch, error) {
return nil, nil
}
func dailyStats(tz *time.Location) (*serverStatsResult, error) {
return &serverStatsResult{}, nil
}

View file

@ -1685,6 +1685,22 @@ COMMANDS:
ID: id,
Content: replay,
})
case bgammon.CommandHistory:
if len(params) == 0 {
cmd.client.sendNotice("Please specify the player as follows: history <username>")
continue
}
matches, err := matchHistory(string(params[0]))
if err != nil {
cmd.client.sendNotice("Invalid replay ID provided.")
continue
}
ev := &bgammon.EventHistory{
Matches: matches,
}
ev.Player = string(params[0])
cmd.client.sendEvent(ev)
case bgammon.CommandDisconnect:
if clientGame != nil {
clientGame.removeClient(cmd.client)