diff --git a/cmd/server/usergameserver.go b/cmd/server/usergameserver.go index 9c3c955..60966f1 100644 --- a/cmd/server/usergameserver.go +++ b/cmd/server/usergameserver.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "io" "log" "time" ) @@ -98,6 +99,36 @@ func (ugs *UserGameServer) listen(ctx context.Context, reader func(context.Conte return ctx.Err() } -func (ugs *UserGameServer) State(ctx context.Context) (GameState, error) { - return ugs.games.GameState(ctx, ugs.ID) +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 + } + + for k, v := range gameState.Players { + if isSelf := k == ugs.Session.ID; isSelf { + self.KillWords.Assignment = Assignment{} + } else { + v.KillWords.Assignee = "" + } + + if assignedToSomeoneElse := self.KillWords.Assignee != k; assignedToSomeoneElse { + v.KillWords.Assignment.Private = v.KillWords.Assignment.Private[:0] + } + + gameState.Players[k] = v + } + + return UserGameState(gameState), io.EOF } diff --git a/cmd/server/ws.go b/cmd/server/ws.go index c032c41..6ab59a7 100644 --- a/cmd/server/ws.go +++ b/cmd/server/ws.go @@ -68,7 +68,7 @@ func (ws WS) Push(ctx context.Context, ugs *UserGameServer) error { var msg map[string]any if unstarted := !gameState.Started; unstarted { - msg, err = ws.unstartedMsg(ctx, gameState) + msg, err = ws.unstartedMsg(ctx, ugs, gameState) } else if complete := !gameState.Completed.IsZero(); complete { msg, err = ws.completeMsg(ctx, gameState) } else { @@ -92,23 +92,27 @@ func (ws WS) Push(ctx context.Context, ugs *UserGameServer) error { return ws.c.Write(ctx, 1, msgB) } -func (ws WS) unstartedMsg(ctx context.Context, gameState GameState) (msg map[string]any, _ error) { +func (ws WS) unstartedMsg(ctx context.Context, ugs *UserGameServer, gameState UserGameState) (msg map[string]any, _ error) { msg["page"] = "A" items := []map[string]any{} for k := range gameState.Players { + if k == ugs.Session.ID { + continue + } + name, err := ws.games.UserName(ctx, k) if err != nil { return nil, err } - items = append(items, map[string]any{"name": name}) + items = append(items, map[string]any{"id": k, "name": name}) } msg["items"] = items return msg, nil } -func (ws WS) completeMsg(ctx context.Context, gameState GameState) (msg map[string]any, _ error) { +func (ws WS) completeMsg(ctx context.Context, gameState UserGameState) (msg map[string]any, _ error) { msg["page"] = "B" msg["event"] = "B" @@ -135,7 +139,7 @@ func (ws WS) completeMsg(ctx context.Context, gameState GameState) (msg map[stri return msg, nil } -func (ws WS) inProgressMsg(ctx context.Context, ugs *UserGameServer, gameState GameState) (msg map[string]any, _ error) { +func (ws WS) inProgressMsg(ctx context.Context, ugs *UserGameServer, gameState UserGameState) (msg map[string]any, _ error) { msg["page"] = "B" msg["event"] = "A" @@ -159,7 +163,7 @@ type inProgressMsgItemTag struct { V int `json:"v,string"` } -func (ws WS) inProgressMsgItems(ctx context.Context, ugs *UserGameServer, gameState GameState) ([]inProgressMsgItem, error) { +func (ws WS) inProgressMsgItems(ctx context.Context, ugs *UserGameServer, gameState UserGameState) ([]inProgressMsgItem, error) { items := []inProgressMsgItem{} for k := range gameState.Players { item, err := ws.inProgressMsgItem(ctx, ugs, gameState, k) @@ -179,39 +183,26 @@ func (ws WS) inProgressMsgItems(ctx context.Context, ugs *UserGameServer, gameSt return items, nil } -func (ws WS) inProgressMsgItem(ctx context.Context, ugs *UserGameServer, gameState GameState, uid string) (*inProgressMsgItem, error) { +func (ws WS) inProgressMsgItem(ctx context.Context, ugs *UserGameServer, gameState UserGameState, uid string) (*inProgressMsgItem, error) { if isSelf := uid == ugs.Session.ID; isSelf { return nil, nil } - - v := gameState.Players[uid] self := gameState.Players[ugs.Session.ID] + v := gameState.Players[uid] tags := []inProgressMsgItemTag{} if hasBeenKilledWithGlobal := slices.ContainsFunc(self.Kills, func(a Kill) bool { - return a.KillWord.Word == self.KillWords.Global.Word && a.Victim == uid + return a.Victim == uid && a.KillWord.Word == self.KillWords.Global.Word }); !hasBeenKilledWithGlobal { - tags = append(tags, inProgressMsgItemTag{ - K: self.KillWords.Global.Word, - V: self.KillWords.Global.Points, - }) + tags = append(tags, newInProgressMsgItemTag(self.KillWords.Global)) } - for _, public := range v.KillWords.Publics() { - tags = append(tags, inProgressMsgItemTag{ - K: public.Word, - V: public.Points, - }) - } - - if isAssigned := self.KillWords.Assignee == uid; isAssigned { - for _, private := range v.KillWords.Privates() { - tags = append(tags, inProgressMsgItemTag{ - K: private.Word, - V: private.Points, - }) - } + for _, killWord := range append( + v.KillWords.Publics(), + v.KillWords.Privates()..., + ) { + tags = append(tags, newInProgressMsgItemTag(killWord)) } name, err := ws.games.UserName(ctx, uid) @@ -221,3 +212,10 @@ func (ws WS) inProgressMsgItem(ctx context.Context, ugs *UserGameServer, gameSta Tags: tags, }, err } + +func newInProgressMsgItemTag(kw KillWord) inProgressMsgItemTag { + return inProgressMsgItemTag{ + K: kw.Word, + V: kw.Points, + } +}