From 9dd661ecd0ec4b099536de06d54311f963639ff8 Mon Sep 17 00:00:00 2001 From: Bel LaPointe <153096461+breel-render@users.noreply.github.com> Date: Sun, 15 Dec 2024 01:41:22 -0700 Subject: [PATCH] naisu test --- cmd/server/games.go | 130 ++++++++++++++++++++++++++++++++------- cmd/server/games_test.go | 2 +- 2 files changed, 109 insertions(+), 23 deletions(-) diff --git a/cmd/server/games.go b/cmd/server/games.go index 8851968..05f3fc5 100644 --- a/cmd/server/games.go +++ b/cmd/server/games.go @@ -5,7 +5,8 @@ import ( "database/sql" "encoding/json" "fmt" - "io" + "maps" + "math/rand" "slices" "time" @@ -89,7 +90,7 @@ type ( Kill struct { Timestamp time.Time Victim string - Public bool + KillWord KillWord } KillWords struct { @@ -102,23 +103,33 @@ type ( } Assignment struct { - Public []string - Private []string + Public []KillWord + Private []KillWord + } + + KillWord struct { + Word string + Points int } EventType int EventPlayerJoin struct { - ID string + Type EventType + ID string } EventPlayerLeave struct { - ID string + Type EventType + ID string + } + EventGameComplete struct { + Type EventType } - EventGameComplete struct{} EventAssignmentRotation struct { + Type EventType Killer string - Killed string - KillWord string + Victim string + KillWord KillWord KillWords map[string]KillWords } ) @@ -176,12 +187,12 @@ func (games Games) GameState(ctx context.Context, id string) (GameState, error) } if killer, ok := result.Players[assignmentRotation.Killer]; !ok { - } else if victim, ok := result.Players[assignmentRotation.Killed]; !ok { + } else if _, ok := result.Players[assignmentRotation.Victim]; !ok { } else { killer.Kills = append(killer.Kills, Kill{ Timestamp: timestamp, - Victim: assignmentRotation.Killed, - Public: slices.Contains(victim.KillWords.Assignment.Public, assignmentRotation.KillWord), + Victim: assignmentRotation.Victim, + KillWord: assignmentRotation.KillWord, }) result.Players[assignmentRotation.Killer] = killer } @@ -238,24 +249,99 @@ func (games Games) CreateGame(ctx context.Context, name string) (string, error) } func (games Games) CreateEventPlayerJoin(ctx context.Context, id string, player string) error { - return games.createEvent(ctx, id, EventPlayerJoin{ID: player}) + if err := games.db.Exec(ctx, ` + INSERT INTO players ( + game_uuid, + user_uuid + ) VALUES (?, ?) + `, id, player); err != nil { + return err + } + return games.createEvent(ctx, id, EventPlayerJoin{Type: PlayerJoin, ID: player}) } func (games Games) CreateEventPlayerLeave(ctx context.Context, id string, player string) error { - return games.createEvent(ctx, id, EventPlayerLeave{ID: player}) + return games.createEvent(ctx, id, EventPlayerLeave{Type: PlayerLeave, ID: player}) } -func (games Games) CreateEventAssignmentRotation(ctx context.Context, id string, killer, killed, killWord string) error { - // 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 AND not self - return io.EOF - //return games.createEvent(ctx, id, v) +func (games Games) CreateEventAssignmentRotation(ctx context.Context, id string, killer, victim, word string, points int) error { + state, err := games.GameState(ctx, id) + if err != nil { + return err + } + now := time.Now() + + event := EventAssignmentRotation{ + Type: AssignmentRotation, + Killer: killer, + Victim: victim, + KillWord: KillWord{ + Word: word, + Points: points, + }, + KillWords: map[string]KillWords{}, + } + + toAssign := []string{} + doNotAssign := map[string]string{} + + for k, v := range state.Players { + v := v.KillWords + toAssign = append(toAssign, k) + doNotAssign[k] = v.Assignee + + event.KillWords[k] = KillWords{ + Global: v.Global, + Assigned: now, + Assignee: "", + Assignment: v.Assignment, + } + } + + if killerState, ok := state.Players[killer]; !ok { + } else if victimState, ok := state.Players[victim]; !ok { + } else { + event.KillWords[killer] = KillWords{ + Global: killerState.KillWords.Global, + Assigned: now, + Assignee: victimState.KillWords.Assignee, + Assignment: killerState.KillWords.Assignment, + } + toAssign = slices.DeleteFunc(toAssign, func(s string) bool { return s == event.KillWords[killer].Assignee }) + } + + for !func() bool { + toAssign := slices.Clone(toAssign) + doNotAssign := maps.Clone(doNotAssign) + eventKillWords := maps.Clone(event.KillWords) + + for i := range toAssign { + j := rand.Intn(i + 1) + toAssign[i], toAssign[j] = toAssign[j], toAssign[i] + } + for k, v := range eventKillWords { + if k == toAssign[0] || doNotAssign[k] == toAssign[0] { + return false + } + eventKillWords[k] = KillWords{ + Global: v.Global, + Assigned: now, + Assignee: toAssign[0], + Assignment: v.Assignment, + } + toAssign = toAssign[1:] + } + + event.KillWords = eventKillWords + return true + }() { + } + + return games.createEvent(ctx, id, event) } func (games Games) CreateEventGameComplete(ctx context.Context, id string) error { - return games.createEvent(ctx, id, EventGameComplete{}) + return games.createEvent(ctx, id, EventGameComplete{Type: GameComplete}) } func (games Games) createEvent(ctx context.Context, id string, v any) error { diff --git a/cmd/server/games_test.go b/cmd/server/games_test.go index 9d55e0b..93d8c6d 100644 --- a/cmd/server/games_test.go +++ b/cmd/server/games_test.go @@ -66,7 +66,7 @@ func TestGames(t *testing.T) { } } - if err := games.CreateEventAssignmentRotation(ctx, id, "", "", ""); err != nil { + if err := games.CreateEventAssignmentRotation(ctx, id, "", "", "", 1); err != nil { t.Fatal("err creating rotation:", err) }