todo last event is big one

main
bel 2024-12-14 23:25:08 -07:00
parent 306295ba1c
commit 0aefff5b82
1 changed files with 150 additions and 4 deletions

View File

@ -1,6 +1,13 @@
package main
import "context"
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"io"
"time"
)
type Games struct {
db DB
@ -10,20 +17,159 @@ func NewGames(ctx context.Context, db DB) (Games, error) {
err := db.Exec(ctx, `
CREATE TABLE IF NOT EXISTS users (
uuid TEXT,
updated DATETIME,
name TEXT
);
CREATE TABLE IF NOT EXISTS games (
uuid TEXT
uuid TEXT,
updated DATETIME,
name TEXT,
completed DATETIME
);
CREATE TABLE IF NOT EXISTS players (
user_uuid TEXT,
game_uuid TEXT
game_uuid TEXT,
updated DATETIME
);
CREATE TABLE IF NOT EXISTS events (
game_uuid TEXT,
timestamp DATETIME,
updated DATETIME,
payload TEXT
);
`)
return Games{db: db}, err
}
func (games Games) GamesForUser(ctx context.Context, id string) ([]string, error) {
result := []string{}
err := games.db.Query(ctx, func(rows *sql.Rows) error {
var game string
err := rows.Scan(&game)
result = append(result, game)
return err
}, `
SELECT players.game_uuid
FROM players
WHERE players.user_uuid=?
`, id)
return result, err
}
func (games Games) GameByName(ctx context.Context, name string) (string, error) {
return "", io.EOF
}
type (
GameState struct {
Completed time.Time
Players map[string]PlayerState
}
PlayerState struct {
Kills []Kill
KillWords KillWords
}
Kill struct {
Timestamp time.Time
Victim string
Public bool
}
KillWords struct {
Global string
Assigned time.Time
Assignee string
Assignment Assignment
}
Assignment struct {
Public []string
Private []string
}
EventType int
EventPlayerJoin struct {
ID string
}
EventPlayerLeave struct {
ID string
}
EventGameComplete struct{}
EventAssignmentRotation struct {
Killer string
Killed string
Assignments map[string]Assignment
}
)
const (
PlayerJoin EventType = iota + 1
PlayerLeave
GameComplete
AssignmentRotation
)
func (games Games) GameState(ctx context.Context, id string) (GameState, error) {
result := GameState{Players: map[string]PlayerState{}}
err := games.db.Query(ctx, func(rows *sql.Rows) error {
var timestamp time.Time
var payload []byte
if err := rows.Scan(&timestamp, &payload); err != nil {
return err
}
var peek struct {
Type EventType
}
if err := json.Unmarshal(payload, &peek); err != nil {
return err
}
switch peek.Type {
case PlayerJoin:
var playerJoin EventPlayerJoin
if err := json.Unmarshal(payload, &playerJoin); err != nil {
return err
}
result.Players[playerJoin.ID] = PlayerState{}
return nil
case PlayerLeave:
var playerLeave EventPlayerLeave
if err := json.Unmarshal(payload, &playerLeave); err != nil {
return err
}
delete(result.Players, playerLeave.ID)
return nil
case GameComplete:
var gameComplete EventGameComplete
if err := json.Unmarshal(payload, &gameComplete); err != nil {
return err
}
result.Completed = timestamp
return nil
case AssignmentRotation:
var assignmentRotation EventAssignmentRotation
if err := json.Unmarshal(payload, &assignmentRotation); err != nil {
return err
}
// TODO gather current assignees
// TODO get victim's target
// TODO assign victim's target to killer
// TODO randomize everyone else so not the same as before
return fmt.Errorf("not impl: assignment rotation: %+v", assignmentRotation)
default:
return fmt.Errorf("unknown event type %d: %s", peek.Type, payload)
}
return nil
}, `
SELECT timestamp, payload
FROM events
WHERE game_uuid=?
`, id)
return result, err
}