i have a plan but also realize event state computation CANNOT create events because itll evalulate many times

main
bel 2024-12-15 22:28:26 -07:00
parent c6ffa12354
commit 421331eb71
1 changed files with 67 additions and 15 deletions

View File

@ -11,6 +11,7 @@ import (
"slices" "slices"
"strings" "strings"
"time" "time"
"unicode"
"github.com/google/uuid" "github.com/google/uuid"
) )
@ -172,7 +173,10 @@ type (
ID string ID string
Started bool Started bool
Completed time.Time Completed time.Time
Players map[string]PlayerState Players map[string]PlayerState
Trial Trial
} }
PlayerState struct { PlayerState struct {
@ -210,6 +214,12 @@ type (
Points int Points int
} }
Trial struct {
Prosecutor string
Killer string
Word string
}
EventType int EventType int
EventPlayerJoin struct { EventPlayerJoin struct {
@ -249,6 +259,7 @@ type (
EventCodenameTrial struct { EventCodenameTrial struct {
Type EventType Type EventType
Timestamp time.Time Timestamp time.Time
Guilty bool
} }
AllKillWords map[string]KillWords AllKillWords map[string]KillWords
) )
@ -370,8 +381,6 @@ func (games Games) GameState(ctx context.Context, id string) (GameState, error)
return result, err return result, err
} }
var stateBeforeAccusal *GameState
for _, event := range events { for _, event := range events {
switch e := event.(type) { switch e := event.(type) {
case EventPlayerJoin: case EventPlayerJoin:
@ -406,19 +415,43 @@ func (games Games) GameState(ctx context.Context, id string) (GameState, error)
result.Players[k] = player result.Players[k] = player
} }
case EventCodenameAccusal: case EventCodenameAccusal:
if stateBeforeAccusal == nil { if actual := result.Players[e.Killer].KillWords.Codename; !actual.Consumed {
stateBeforeAccusal = &result result.Trial.Prosecutor = e.Prosecutor
result = *stateBeforeAccusal result.Trial.Killer = e.Killer
result.Trial.Word = e.Word
return GameState{}, fmt.Errorf("not impl: accusal: %+v", e) guessed := e.Word
if !basicallyTheSame(actual, guessed) {
} else if err := games.CreateEventCodenameTrial(ctx, true); err != nil {
return err
}
} }
case EventCodenameTrial: case EventCodenameTrial:
if stateBeforeAccusal != nil { if result.Trial == (Trial{}) {
result = *stateBeforeAccusal } else if e.Guilty {
stateBeforeAccusal = nil return GameState{}, fmt.Errorf("not impl: trial: guilty: %+v", e)
} else {
v := result.Players[result.Trial.Prosecutor]
v.Killwords.Codename.Consumed = true
v.Kills = append(v.Kills, Kill{
Timestamp: e.Timestamp,
Victim: result.Trial.Killer,
KillWord: KillWord{
Word: result.Trial.Word,
Points: -200,
},
})
result.Players[result.Trial.Prosecutor] = v
return GameState{}, fmt.Errorf("not impl: trial: %+v", e) v = result.Players[result.Trial.Killer]
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
} }
}
result.Trial = Trial{}
case EventGameReset: case EventGameReset:
return games.GameState(ctx, e.ID) return games.GameState(ctx, e.ID)
default: default:
@ -429,6 +462,20 @@ func (games Games) GameState(ctx context.Context, id string) (GameState, error)
return result, err return result, err
} }
func basicallyTheSame(a, b string) bool {
simplify := func(s string) string {
s = strings.TrimSpace(strings.ToLower(s))
s2 := ""
for _, c := range s {
if unicode.IsLetter(c) {
s2 = fmt.Sprintf("%s%c", s2, c)
}
}
return s2
}
return simplify(a) == simplify(b)
}
func (games Games) CreateGame(ctx context.Context, name string) (string, error) { func (games Games) CreateGame(ctx context.Context, name string) (string, error) {
var exists string var exists string
if err := games.db.Query(ctx, if err := games.db.Query(ctx,
@ -490,10 +537,7 @@ func (games Games) CreateEventAssignmentRotation(ctx context.Context, id string,
}, },
} }
prevAllKillWords := make(AllKillWords) prevAllKillWords := games.AllKillWords()
for k, v := range state.Players {
prevAllKillWords[k] = v.KillWords
}
event.AllKillWords = prevAllKillWords.ShuffleAssignees(killer, victim, word) event.AllKillWords = prevAllKillWords.ShuffleAssignees(killer, victim, word)
event.AllKillWords = event.AllKillWords.FillKillWords() event.AllKillWords = event.AllKillWords.FillKillWords()
@ -501,6 +545,14 @@ func (games Games) CreateEventAssignmentRotation(ctx context.Context, id string,
return games.createEvent(ctx, id, event) return games.createEvent(ctx, id, event)
} }
func (playerState PlayerState) AllKillWords() AllKillWords {
m := make(AllKillWords)
for k, v := range state.Players {
m[k] = v.KillWords
}
return m
}
func (games Games) CreateEventGameReset(ctx context.Context, gid string) error { func (games Games) CreateEventGameReset(ctx context.Context, gid string) error {
state, err := games.GameState(ctx, gid) state, err := games.GameState(ctx, gid)
if err != nil { if err != nil {