diff --git a/cmd/server/games.go b/cmd/server/games.go index 378d871..f12b800 100644 --- a/cmd/server/games.go +++ b/cmd/server/games.go @@ -216,7 +216,7 @@ type ( Trial struct { Prosecutor string - Killer string + Defendant string Word string } @@ -253,7 +253,7 @@ type ( Type EventType Timestamp time.Time Prosecutor string - Killer string + Defendant string Word string } EventCodenameTrial struct { @@ -261,6 +261,12 @@ type ( Timestamp time.Time Guilty bool } + EventNotification struct { + Type EventType + Timestamp time.Time + Recipient string + Message string + } AllKillWords map[string]KillWords ) @@ -272,6 +278,7 @@ const ( GameReset CodenameAccusal CodenameTrial + Notification ) type Event interface{ event() } @@ -283,6 +290,7 @@ func (EventAssignmentRotation) event() {} func (EventGameReset) event() {} func (EventCodenameAccusal) event() {} func (EventCodenameTrial) event() {} +func (EventNotification) event() {} func EventWithTime(event Event, t time.Time) Event { switch e := event.(type) { @@ -307,6 +315,9 @@ func EventWithTime(event Event, t time.Time) Event { case EventCodenameTrial: e.Timestamp = t event = e + case EventNotification: + e.Timestamp = t + event = e } return event } @@ -369,6 +380,10 @@ func parseEvent(b []byte, timestamp time.Time) (Event, error) { var v EventCodenameTrial err := json.Unmarshal(b, &v) return EventWithTime(v, timestamp), err + case Notification: + var v EventNotification + err := json.Unmarshal(b, &v) + return EventWithTime(v, timestamp), err } return nil, fmt.Errorf("unknown event type %d: %s", peek.Type, b) } @@ -415,27 +430,29 @@ func (games Games) GameState(ctx context.Context, id string) (GameState, error) result.Players[k] = player } case EventCodenameAccusal: - if actual := result.Players[e.Killer].KillWords.Codename; !actual.Consumed { + if actual := result.Players[e.Defendant].KillWords.Codename; !actual.Consumed { result.Trial.Prosecutor = e.Prosecutor - result.Trial.Killer = e.Killer + result.Trial.Defendant = e.Defendant result.Trial.Word = e.Word - guessed := e.Word - if !basicallyTheSame(actual, guessed) { - } else if err := games.CreateEventCodenameTrial(ctx, true); err != nil { - return err + if !basicallyTheSame(actual.KillWord.Word, e.Word) { + } else if err := games.CreateEventCodenameTrial(ctx, id, true); err != nil { // TODO cannot be in State loop + return GameState{}, err } } case EventCodenameTrial: if result.Trial == (Trial{}) { } else if e.Guilty { + if err := games.CreateEventNotification(ctx, id, fmt.Sprintf(`%s revealed %s is %s and collected %s's bounty.`, result.Trial.Prosecutor, result.Trial.Defendant, result.Trial.Word, result.Trial.Defendant)); err != nil { // TODO not in this loop + return GameState{}, err + } return GameState{}, fmt.Errorf("not impl: trial: guilty: %+v", e) } else { v := result.Players[result.Trial.Prosecutor] - v.Killwords.Codename.Consumed = true + v.KillWords.Codename.Consumed = true v.Kills = append(v.Kills, Kill{ Timestamp: e.Timestamp, - Victim: result.Trial.Killer, + Victim: result.Trial.Defendant, KillWord: KillWord{ Word: result.Trial.Word, Points: -200, @@ -443,12 +460,12 @@ func (games Games) GameState(ctx context.Context, id string) (GameState, error) }) result.Players[result.Trial.Prosecutor] = v - v = result.Players[result.Trial.Killer] - v.KillWords.Codename.KillWord.Word = TODO + v = result.Players[result.Trial.Defendant] + v.KillWords.Codename.KillWord.Word = "" // TODO - return fmt.Errorf("creating state CANNOT create events because it will eval every loop") - if err := games.CreateEventNotification(ctx, fmt.Sprintf(`%s accused the innocent %s of being %s. %s will get a new codename.`, prosecutorName, killerName, result.Trial.Word, killerName)); err != nil { - return err + return GameState{}, fmt.Errorf("creating state CANNOT create events because it will eval every loop") + if err := games.CreateEventNotification(ctx, id, fmt.Sprintf(`%s accused the innocent %s of being %s. %s will get a new codename.`, result.Trial.Prosecutor, result.Trial.Defendant, result.Trial.Word, result.Trial.Defendant)); err != nil { + return GameState{}, err } } result.Trial = Trial{} @@ -537,7 +554,7 @@ func (games Games) CreateEventAssignmentRotation(ctx context.Context, id string, }, } - prevAllKillWords := games.AllKillWords() + prevAllKillWords := state.AllKillWords() event.AllKillWords = prevAllKillWords.ShuffleAssignees(killer, victim, word) event.AllKillWords = event.AllKillWords.FillKillWords() @@ -545,12 +562,12 @@ func (games Games) CreateEventAssignmentRotation(ctx context.Context, id string, return games.createEvent(ctx, id, event) } -func (playerState PlayerState) AllKillWords() AllKillWords { +func (state GameState) AllKillWords() AllKillWords { m := make(AllKillWords) for k, v := range state.Players { m[k] = v.KillWords } - return m + return m } func (games Games) CreateEventGameReset(ctx context.Context, gid string) error { @@ -794,6 +811,23 @@ func (games Games) CreateEventGameComplete(ctx context.Context, id string) error return games.createEvent(ctx, id, EventGameComplete{Type: GameComplete}) } +func (games Games) CreateEventCodenameAccusal(ctx context.Context, gid, prosecutor, defendant, codename string) error { + return fmt.Errorf("not impl: x accused y") + return fmt.Errorf("not impl: x caught by y") +} + +func (games Games) CreateEventCodenameTrial(ctx context.Context, gid string, guilty bool) error { + return fmt.Errorf("not impl: x found guilty/notguilty") +} + +func (games Games) CreateEventNotification(ctx context.Context, gid, msg string) error { + return games.CreateEventNotificationTo(ctx, gid, "", msg) +} + +func (games Games) CreateEventNotificationTo(ctx context.Context, gid, uid, msg string) error { + return fmt.Errorf("not impl: simple") +} + func (games Games) createEvent(ctx context.Context, id string, v any) error { payload, err := json.Marshal(v) if err != nil {