out/cmd/server/usergameserver.go

142 lines
3.3 KiB
Go

package main
import (
"context"
"encoding/json"
"fmt"
"log"
"time"
)
type UserGameServer struct {
ID string
Session Session
games Games
lastPoll time.Time
}
func NewUserGameServer(ctx context.Context, session Session, games Games) (*UserGameServer, error) {
ids, err := games.GamesForUser(ctx, session.ID)
if err != nil {
return nil, err
}
if len(ids) == 0 {
return nil, fmt.Errorf("user %s is in zero games", session.ID)
}
return &UserGameServer{
ID: ids[0],
Session: session,
games: games,
}, nil
}
func (ugs *UserGameServer) More(ctx context.Context) error {
defer func() {
ugs.lastPoll = time.Now()
}()
for {
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(time.Second * 1):
}
if events, err := ugs.games.GameEvents(ctx, ugs.ID, ugs.lastPoll); err != nil {
return err
} else if len(events) == 0 {
continue
}
return nil
}
}
func (ugs *UserGameServer) Listen(ctx context.Context, can context.CancelFunc, reader func(context.Context) ([]byte, error)) {
defer can()
if err := ugs.listen(ctx, reader); err != nil && ctx.Err() == nil {
log.Println(err)
}
}
func (ugs *UserGameServer) listen(ctx context.Context, reader func(context.Context) ([]byte, error)) error {
for ctx.Err() == nil {
b, err := reader(ctx)
if err != nil {
return err
}
var m map[string]string
if err := json.Unmarshal(b, &m); err != nil {
return err
}
if m["party"] == "start" {
if gameState, err := ugs.games.GameState(ctx, ugs.ID); err != nil {
return err
} else if gameState.Started {
} else if err := ugs.games.CreateEventAssignmentRotation(ctx, ugs.ID, "", "", "", 0); err != nil {
return err
}
} else if m["k"] != "" {
return fmt.Errorf("not impl: a kill occurred: %+v", m)
} else if name := m["name"]; name != "" {
if err := ugs.games.UpdateUserName(ctx, ugs.Session.ID, name); err != nil {
return err
}
} else if m["again"] == "true" {
if gameState, err := ugs.games.GameState(ctx, ugs.ID); err != nil {
return err
} else if gameState.Completed.IsZero() {
} else {
return fmt.Errorf("not impl: new game: %+v", m)
}
} else {
return fmt.Errorf("UNKNOWN: %+v", m)
}
}
return ctx.Err()
}
type UserGameState GameState
func (ugs *UserGameServer) State(ctx context.Context) (UserGameState, error) {
gameState, err := ugs.games.GameState(ctx, ugs.ID)
if err != nil {
return UserGameState{}, err
}
if complete := !gameState.Completed.IsZero(); complete {
return UserGameState(gameState), nil
}
self := gameState.Players[ugs.Session.ID]
for i := range self.Kills {
self.Kills[i].KillWord.Points = 0
}
self.KillWords.Assignment.Public = nil
self.KillWords.Assignment.Private = nil
gameState.Players[ugs.Session.ID] = self
for k, v := range gameState.Players {
if isSelf := k == ugs.Session.ID; isSelf {
v.KillWords.Assignment = Assignment{}
} else {
v.KillWords.Global = KillWord{}
v.KillWords.Assignee = ""
for i := range v.Kills {
v.Kills[i].Victim = ""
v.Kills[i].KillWord.Word = ""
}
}
if assignedToSomeoneElse := self.KillWords.Assignee != k; assignedToSomeoneElse {
v.KillWords.Assignment.Private = v.KillWords.Assignment.Private[:0]
}
gameState.Players[k] = v
}
return UserGameState(gameState), nil
}