From 757586ea22defa261db8d96c3ae71a2e59fdae78 Mon Sep 17 00:00:00 2001 From: Grail Finder Date: Sat, 12 Jul 2025 21:02:10 +0300 Subject: [PATCH 1/5] Enha: avoid nil panics --- handlers/elements.go | 25 +++++++++++++++---------- handlers/game.go | 25 +++++++++++++++---------- handlers/handlers.go | 5 +++-- todos.md | 10 +++++----- 4 files changed, 38 insertions(+), 27 deletions(-) diff --git a/handlers/elements.go b/handlers/elements.go index 061edbf..d450e68 100644 --- a/handlers/elements.go +++ b/handlers/elements.go @@ -42,8 +42,9 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) { return } fi, err := getFullInfoByCtx(ctx) - if err != nil { - abortWithError(w, err.Error()) + if err != nil || fi == nil { + log.Error("failed to fetch fi", "error", err) + http.Redirect(w, r, "/", 302) return } if err := validateMove(fi, models.UserRoleGuesser); err != nil { @@ -206,8 +207,9 @@ func HandleMarkCard(w http.ResponseWriter, r *http.Request) { return } fi, err := getFullInfoByCtx(ctx) - if err != nil { - abortWithError(w, err.Error()) + if err != nil || fi == nil { + log.Error("failed to fetch fi", "error", err) + http.Redirect(w, r, "/", 302) return } if err := validateMove(fi, models.UserRoleGuesser); err != nil { @@ -274,8 +276,9 @@ func HandleMarkCard(w http.ResponseWriter, r *http.Request) { func HandleActionHistory(w http.ResponseWriter, r *http.Request) { fi, err := getFullInfoByCtx(r.Context()) - if err != nil { - abortWithError(w, err.Error()) + if err != nil || fi == nil { + log.Error("failed to fetch fi", "error", err) + http.Redirect(w, r, "/", 302) return } tmpl, err := template.ParseGlob("components/*.html") @@ -293,8 +296,9 @@ func HandleAddBot(w http.ResponseWriter, r *http.Request) { team := r.URL.Query().Get("team") role := r.URL.Query().Get("role") fi, err := getFullInfoByCtx(r.Context()) - if err != nil { - abortWithError(w, err.Error()) + if err != nil || fi == nil { + log.Error("failed to fetch fi", "error", err) + http.Redirect(w, r, "/", 302) return } var botname string @@ -319,8 +323,9 @@ func HandleRemoveBot(w http.ResponseWriter, r *http.Request) { botName := r.URL.Query().Get("bot") log.Debug("got remove-bot request", "bot_name", botName) fi, err := getFullInfoByCtx(r.Context()) - if err != nil { - abortWithError(w, err.Error()) + if err != nil || fi == nil { + log.Error("failed to fetch fi", "error", err) + http.Redirect(w, r, "/", 302) return } if err := llmapi.RemoveBot(botName, fi.Room); err != nil { diff --git a/handlers/game.go b/handlers/game.go index 11a286c..a34e657 100644 --- a/handlers/game.go +++ b/handlers/game.go @@ -72,8 +72,9 @@ func HandleJoinTeam(w http.ResponseWriter, r *http.Request) { } // get username fi, err := getFullInfoByCtx(r.Context()) - if err != nil { - abortWithError(w, err.Error()) + if err != nil || fi == nil { + log.Error("failed to fetch fi", "error", err) + http.Redirect(w, r, "/", 302) return } if fi.Room == nil { @@ -111,8 +112,9 @@ func HandleJoinTeam(w http.ResponseWriter, r *http.Request) { func HandleEndTurn(w http.ResponseWriter, r *http.Request) { // get username fi, err := getFullInfoByCtx(r.Context()) - if err != nil { - abortWithError(w, err.Error()) + if err != nil || fi == nil { + log.Error("failed to fetch fi", "error", err) + http.Redirect(w, r, "/", 302) return } // check if one who pressed it is from the team who has the turn @@ -143,8 +145,9 @@ func HandleEndTurn(w http.ResponseWriter, r *http.Request) { func HandleStartGame(w http.ResponseWriter, r *http.Request) { fi, err := getFullInfoByCtx(r.Context()) - if err != nil { - abortWithError(w, err.Error()) + if err != nil || fi == nil { + log.Error("failed to fetch fi", "error", err) + http.Redirect(w, r, "/", 302) return } // check if enough players @@ -293,8 +296,9 @@ func HandleGiveClue(w http.ResponseWriter, r *http.Request) { clue := r.PostFormValue("clue") num := r.PostFormValue("number") fi, err := getFullInfoByCtx(r.Context()) - if err != nil { - abortWithError(w, err.Error()) + if err != nil || fi == nil { + log.Error("failed to fetch fi", "error", err) + http.Redirect(w, r, "/", 302) return } guessLimitU64, err := strconv.ParseUint(num, 10, 8) @@ -360,8 +364,9 @@ func HandleGiveClue(w http.ResponseWriter, r *http.Request) { func HandleRenotifyBot(w http.ResponseWriter, r *http.Request) { fi, err := getFullInfoByCtx(r.Context()) - if err != nil { - abortWithError(w, err.Error()) + if err != nil || fi == nil { + log.Error("failed to fetch fi", "error", err) + http.Redirect(w, r, "/", 302) return } notifyBotIfNeeded(fi.Room) diff --git a/handlers/handlers.go b/handlers/handlers.go index 20b9398..f7b56c0 100644 --- a/handlers/handlers.go +++ b/handlers/handlers.go @@ -75,8 +75,9 @@ func HandleExit(w http.ResponseWriter, r *http.Request) { return } fi, err := getFullInfoByCtx(r.Context()) - if err != nil { - abortWithError(w, err.Error()) + if err != nil || fi == nil { + log.Error("failed to fetch fi", "error", err) + http.Redirect(w, r, "/", 302) return } if fi.Room.IsRunning { diff --git a/todos.md b/todos.md index 3f1fb02..e725224 100644 --- a/todos.md +++ b/todos.md @@ -21,8 +21,8 @@ - redo card .revealed use: it should mean that card is revealed for everybody, while mime should be able to see cards as is; + - better styles and fluff; - common auth system between sites; -- signup vs login; -- passwords (to room and to login); +- signup vs login; + +- passwords (to room and to login); + === - show in backlog (and with that in prompt to llm) how many cards are left to open, also additional comment: if guess was right; - gameover to backlog; @@ -33,7 +33,7 @@ - possibly turn markings into parts of names of users (first three letters?); + - at game creation list languages and support them at backend; + - sql ping goroutine with reconnect on fail; + -- player stats: played games, lost, won, rating elo, opened opposite words, opened white words, opened black words. +- player stats: played games, lost, won, rating elo, opened opposite words, opened white words, opened black words. + - at the end of the game, all colors should be revealed; - tracing; @@ -91,5 +91,5 @@ - mime sees the clue input out of turn; (eh) - there is a problem of two timers, they both could switch turn, but it is not easy to stop them from llmapi or handlers. + - journal still does not work; + -- lose/win game; then exit room (while being the creator), then press to stats -> cannot find session in db, although cookie in place and session in db; -- exit endpoints delets player from db; +- lose/win game; then exit room (while being the creator), then press to stats -> cannot find session in db, although cookie in place and session in db; + +- exit endpoints delets player from db; + From 155aa1b2cbdbdf75f520333901e9f028bdd6f78d Mon Sep 17 00:00:00 2001 From: Grail Finder Date: Sun, 13 Jul 2025 08:31:16 +0300 Subject: [PATCH 2/5] Feat: bot failed state to show/hide llm restart btn --- components/actionhistory.html | 2 +- components/room.html | 2 +- llmapi/main.go | 19 ++++++++----------- migrations/001_initial_schema.up.sql | 1 + models/main.go | 2 ++ repos/rooms.go | 14 ++++++++++++++ 6 files changed, 27 insertions(+), 13 deletions(-) diff --git a/components/actionhistory.html b/components/actionhistory.html index c914b59..8a3d6f9 100644 --- a/components/actionhistory.html +++ b/components/actionhistory.html @@ -18,7 +18,7 @@ if (!window.actionHistoryScrollSet) { htmx.onLoad(function(target) { if (target.id === 'actionHistoryContainer') { - target.scrollTop = target.scrollHeight; + target.scrollToBottom(); } }); window.actionHistoryScrollSet = true; diff --git a/components/room.html b/components/room.html index 47497b6..1caabbd 100644 --- a/components/room.html +++ b/components/room.html @@ -74,7 +74,7 @@ {{end}}
- {{if and (eq .State.Username .Room.CreatorName) (.Room.IsRunning)}} + {{if and (eq .State.Username .Room.CreatorName) (.Room.BotFailed)}} {{end}}
diff --git a/llmapi/main.go b/llmapi/main.go index 8d18853..8e6db0b 100644 --- a/llmapi/main.go +++ b/llmapi/main.go @@ -188,6 +188,11 @@ func (b *Bot) BotMove() { b.log.Error("bot loop", "error", err) return } + if room.BotFailed { + if err := repo.RoomUnSetBotFailed(context.Background(), room.ID); err != nil { + b.log.Error("failed to unset bot failed bool", "error", err) + } + } // eventName := models.NotifyBacklogPrefix + room.ID eventName := models.NotifyRoomUpdatePrefix + room.ID eventPayload := "" @@ -231,6 +236,9 @@ func (b *Bot) BotMove() { b.log.Warn("failed to write to journal", "entry", lj) } b.log.Error("bot loop", "error", err) + if err := repo.RoomSetBotFailed(context.Background(), room.ID); err != nil { + b.log.Error("failed to set bot failed bool", "error", err) + } return } tempMap, err := b.LLMParser.ParseBytes(llmResp) @@ -666,16 +674,5 @@ func (b *Bot) CallLLM(prompt string) ([]byte, error) { b.log.Debug("llm resp", "body", string(body), "url", b.cfg.LLMConfig.URL, "attempt", attempt) return body, nil } - entry := fmt.Sprintf("bot '%s' exceeded attempts to call llm;", b.BotName) - lj := models.Journal{ - Entry: entry, - Username: b.BotName, - RoomID: b.RoomID, - } - if err := repo.JournalCreate(context.Background(), &lj); err != nil { - b.log.Warn("failed to write to journal", "entry", lj) - } - // notify room - // This line should not be reached because each error path returns in the loop. return nil, errors.New("unknown error in retry loop") } diff --git a/migrations/001_initial_schema.up.sql b/migrations/001_initial_schema.up.sql index bae52bd..d5c696a 100644 --- a/migrations/001_initial_schema.up.sql +++ b/migrations/001_initial_schema.up.sql @@ -13,6 +13,7 @@ CREATE TABLE rooms ( mime_done BOOLEAN NOT NULL DEFAULT FALSE, is_running BOOLEAN NOT NULL DEFAULT FALSE, is_over BOOLEAN NOT NULL DEFAULT FALSE, + bot_failed BOOLEAN NOT NULL DEFAULT FALSE, team_won TEXT NOT NULL DEFAULT '', room_link TEXT NOT NULL DEFAULT '' ); diff --git a/models/main.go b/models/main.go index 8bab780..e53d395 100644 --- a/models/main.go +++ b/models/main.go @@ -178,6 +178,8 @@ type Room struct { BotMap map[string]BotPlayer `db:"-"` LogJournal []Journal `db:"-"` Settings GameSettings `db:"-"` + // + BotFailed bool `db:"bot_failed"` } func (r *Room) FindColor(word string) (WordColor, bool) { diff --git a/repos/rooms.go b/repos/rooms.go index 87b901a..343f984 100644 --- a/repos/rooms.go +++ b/repos/rooms.go @@ -15,6 +15,20 @@ type RoomsRepo interface { RoomCreate(ctx context.Context, room *models.Room) error RoomDeleteByID(ctx context.Context, id string) error RoomUpdate(ctx context.Context, room *models.Room) error + RoomSetBotFailed(ctx context.Context, roomID string) error + RoomUnSetBotFailed(ctx context.Context, roomID string) error +} + +func (p *RepoProvider) RoomSetBotFailed(ctx context.Context, roomID string) error { + db := getDB(ctx, p.DB) + _, err := db.ExecContext(ctx, "UPDATE rooms SET bot_failed = true WHERE id = ?", roomID) + return err +} + +func (p *RepoProvider) RoomUnSetBotFailed(ctx context.Context, roomID string) error { + db := getDB(ctx, p.DB) + _, err := db.ExecContext(ctx, "UPDATE rooms SET bot_failed = false WHERE id = ?", roomID) + return err } func (p *RepoProvider) RoomList(ctx context.Context) ([]*models.Room, error) { From ad44dc0642adde1a72f93085ee239c6fa2971434 Mon Sep 17 00:00:00 2001 From: Grail Finder Date: Sun, 13 Jul 2025 12:28:52 +0300 Subject: [PATCH 3/5] Chore: styles --- assets/style.css | 1 - assets/style.css.gz | Bin 461 -> 454 bytes broker/sse.go | 9 ++++++++- components/room.html | 16 +++++++++------- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/assets/style.css b/assets/style.css index 613e333..db799d7 100644 --- a/assets/style.css +++ b/assets/style.css @@ -1,7 +1,6 @@ body{ background-color: #0C1616FF; color: #8896b2; - max-width: 1000px; min-width: 0px; margin: 2em auto !important; margin-left: auto; diff --git a/assets/style.css.gz b/assets/style.css.gz index e4b3e9fbdd6da4b7d13ee5731620a8daa31153e8..5f04e9aa5ca808676f21c16eee78ca343f61b1dc 100644 GIT binary patch literal 454 zcmV;%0XhC3iwFp6TXSdt19NnFY-KKEb8`TVQo)MbFc7`_D^&KPxk*){l=56XA&7-+x@oyNnImmRqetUyGI7%@}Z}Z7uF_5HJQ3Z}i}Z1K9AKP#SDQ zJuwzA>#kqmMq4a<%y4!4A)_tXP9cZT7Wza%jbOu>SpL)?hLt;4YM4 zbQc9SXajP_mG;g+tdfSB%|mf00!V|&8cD2>lPLzAkMle_U^cL z{vAdzVxEjvV%zJ0(;%J$xK6nlJ@QG=xmv-a+$Y*CG(krTE)ca%Hj38Jwq&AZ68W&6 z#h&{7vM}IMn^sH}!7T#;yBkOR&b5PGv2TDyY9XrmqD90W*MrLA3yKCM^11YD= zH&+2~h{1M~d&Q>>?puz_c+rBwZ}ux~tw^0)ra|NplyVDE`)a-^vEH}DL!Ez3O#J8D wvSJ+GCB`AX@p7LPSN|(s&4n)|J&oaqyQ=6_O)sf=^(u$rFTcD?ISB*+0D@uJ1g@)97>9S>^ zr#+M&dMYDpY>UVmGm=TtlK)=Ga z{cAyPu<_NTSYXy|x8O!w%sWiDy#17DL)Pa`|Hi;p$E_#WK(Ecd63+u#@g1!D_`n)W zQh40?9E@&*!5XbcPF!g>7zkC;P`$a&4w(mOFa{=x6>^Nqz~I7u4hLZHcy_Q^=LV>? zZG)|l$n<$x3@|W9Mk}%Hw8v>9p2u=sax*&Qlc96Bf=9WJvRkOV4iQ`sY8zt|jiGJM zM9WE}#cDQt>hsG&k4tZsEXLBaz7Z|5*S15}{>0OuUeN)Rno>G;oNrMYdpI#N6HD4% z%SIZAbGm$=74U`_Y&)fwec9l?;cyry8c_Jnex!{_}laGWH*$;t<|&xzCEr{}mT=;lGxiNB?8E>gY{PFS&X1Q4ZN(^F3gG9|QmZ D1g7bP diff --git a/broker/sse.go b/broker/sse.go index 1946bb4..116c23f 100644 --- a/broker/sse.go +++ b/broker/sse.go @@ -91,7 +91,9 @@ func (broker *Broker) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Listen for new notifications and redistribute them to clients func (broker *Broker) Listen() { + slog.Info("Broker listener started") for { + slog.Info("Broker waiting for event") select { case s := <-broker.newClients: // A new client has connected. @@ -104,16 +106,21 @@ func (broker *Broker) Listen() { delete(broker.clients, s) slog.Info("Client removed", "clients listening", len(broker.clients)) case event := <-broker.Notifier: + slog.Info("Received new event", "event", event.EventName, "payload", event.Payload) // We got a new event from the outside! // Send event to all connected clients + slog.Info("Broadcasting event to clients", "client_count", len(broker.clients)) for clientMessageChan := range broker.clients { + slog.Info("Sending event to client", "client", clientMessageChan) select { case clientMessageChan <- event: + slog.Info("Successfully sent event to client", "client", clientMessageChan) case <-time.After(patience): delete(broker.clients, clientMessageChan) - slog.Info("Client was removed", "clients listening", len(broker.clients)) + slog.Warn("Client timed out, removed", "client", clientMessageChan, "clients listening", len(broker.clients)) } } + slog.Info("Finished broadcasting event") } } } diff --git a/components/room.html b/components/room.html index 1caabbd..e3dd763 100644 --- a/components/room.html +++ b/components/room.html @@ -49,6 +49,15 @@ {{template "teamlist" .Room.RedTeam}}
+
+
+ {{template "actionhistory" .Room.ActionHistory}} +
+
+ {{template "cardtable" .Room}} +
+ +
bot thought:
    @@ -57,13 +66,6 @@ {{end}}
-
- {{template "actionhistory" .Room.ActionHistory}} -
-
-
- {{template "cardtable" .Room}} -
{{if .Room.IsRunning}} {{if and (eq .State.Role "guesser") (eq .State.Team .Room.TeamTurn)}} From 6951ec0535658c3c7cf1a3fd51d4b2221f621159 Mon Sep 17 00:00:00 2001 From: Grail Finder Date: Sun, 13 Jul 2025 12:45:55 +0300 Subject: [PATCH 4/5] Chore: styles --- components/room.html | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/components/room.html b/components/room.html index e3dd763..9704937 100644 --- a/components/room.html +++ b/components/room.html @@ -1,6 +1,7 @@ {{define "room"}}
-
+
+

Hello {{.State.Username}};

Room created by {{.Room.CreatorName}};

Room link:

@@ -16,13 +17,13 @@ {{end}}

{{if eq .State.Team ""}} - join the team! + you don't have a role! join the team -> {{else}} you're on the team {{.State.Team}}! {{end}}

-
+
{{if .Room.IsRunning}}

Turn of the {{.Room.TeamTurn}} team

{{template "turntimer" .Room}} @@ -48,6 +49,8 @@ {{template "teamlist" .Room.RedTeam}}
+
+

From 123d6c240f1fb673baaae08cba3176f30c26b77b Mon Sep 17 00:00:00 2001 From: Grail Finder Date: Sun, 13 Jul 2025 09:00:05 +0300 Subject: [PATCH 5/5] Feat: ru prompts for llm --- llmapi/main.go | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/llmapi/main.go b/llmapi/main.go index 8e6db0b..0742069 100644 --- a/llmapi/main.go +++ b/llmapi/main.go @@ -25,10 +25,10 @@ var ( DoneChanMap = make(map[string]chan bool) mapMutex = &sync.RWMutex{} // got prompt: control character (\\u0000-\\u001F) found while parsing a string at line 4 column 0 - // MimePrompt = `we are playing alias;\nyou are a mime (player who gives a clue of one noun word and number of cards you expect them to open) of the %s team (people who would guess by your clue want open the %s cards);\nplease return your clue, number of cards to open and what words you mean them to find using that clue in json like:\n{\n\"clue\": \"one-word-noun\",\n\"number\": \"number-from-0-to-9\",\n\"words_I_mean_my_team_to_open\": [\"this\", \"that\", ...]\n}\nthe team who openes all their cards first wins.\nplease return json only.\nunopen Blue cards left: %d;\nunopen Red cards left: %d;\nhere is the game info in json:\n%s` - // GuesserPrompt = `we are playing alias;\nyou are to guess words of the %s team (you want open %s cards) by given clue and a number of meant guesses;\nplease return your guesses and words that could be meant by the clue, but you do not wish to open yet, in json like:\n{\n\"guesses\": [\"word1\", \"word2\", ...],\n\"could_be\": [\"this\", \"that\", ...]\n}\nthe team who openes all their cards first wins.\nplease return json only.\nunopen Blue cards left: %d;\nunopen Red cards left: %d;\nhere is the cards (and other info), you need to choose revealed==false words:\n%s` - GuesserSimplePrompt = `we are playing game of alias;\n you were given a clue: \"%s\";\nplease return your guess and words that could be meant by the clue, but you do not wish to open yet, in json like:\n{\n\"guess\": \"most_relevant_word_to_the_clue\",\n\"could_be\": [\"this\", \"that\", ...]\n}\nhere is the words that you can choose from:\n%v` - MimeSimplePrompt = `we are playing alias;\nyou are to give one word clue and a number of words you mean your team to open; your team words: %v;\nhere are the words of opposite team you want to avoid: %v;\nand here is a black word that is critical not to pick: %s;\nplease return your clue, number of cards to open and what words you mean them to find using that clue in json like:\n{\n\"clue\": \"one-word-noun\",\n\"number\": \"number-from-0-to-9-as-string\",\n\"words_I_mean_my_team_to_open\": [\"this\", \"that\", ...]\n}\nplease return json only.\nunopen Blue cards left: %d;\nunopen Red cards left: %d;` + GuesserSimplePrompt = `we are playing game of alias;\n you were given a clue: \"%s\";\nplease return your guess and words that could be meant by the clue, but you do not wish to open yet, in json like:\n{\n\"guess\": \"most_relevant_word_to_the_clue\",\n\"could_be\": [\"this\", \"that\", ...]\n}\nhere is the words that you can choose from:\n%v` + MimeSimplePrompt = `we are playing alias;\nyou are to give one word clue and a number of words you mean your team to open; your team words: %v;\nhere are the words of opposite team you want to avoid: %v;\nand here is a black word that is critical not to pick: %s;\nplease return your clue, number of cards to open and what words you mean them to find using that clue in json like:\n{\n\"clue\": \"one-word-noun\",\n\"number\": \"number-from-0-to-9-as-string\",\n\"words_I_mean_my_team_to_open\": [\"this\", \"that\", ...]\n}\nplease return json only.` + GuesserSimplePromptRU = `мы играем в alias;\n тебе дана подсказка (clue): \"%s\";\nпожалуйста, верни свою догадку (guess), а также слова, что тоже подходят к подсказке, но ты меньше в них уверен, в формате json; пример:\n{\n\"guess\": \"отгадка\",\n\"could_be\": [\"слово1\", \"слово2\", ...]\n}\nвот список слов из которых нужно выбрать:\n%v` + MimeSimplePromptRU = `мы играем в alias;\nтебе нужно дать подсказку одним словом и число слов, что ты подразумевал этой подсказкой; слова твоей комманды: %v;\nслова противоположной комманды, что ты хочешь избежать: %v;\nи вот ЧЕРНОЕ СЛОВО, открыв которое твоя комманда проиграет игру: %s;\nпожалуйста, верни подсказку (одним словом) и количество слов, что ты подразумеваешь в формате json; пример:\n{\n\"clue\": \"подсказка\",\n\"number\": \"число-от-0-до-9-as-string\",\n\"words_I_mean_my_team_to_open\": [\"слово1\", \"слово2\", ...]\n}\nпожалуйста верни только json.` ) func convertToSliceOfStrings(value any) ([]string, error) { @@ -553,6 +553,9 @@ func (b *Bot) BuildSimpleGuesserPrompt(room *models.Room) string { } words[i] = card.Word } + if strings.EqualFold(room.Settings.Language, "ru") { + return fmt.Sprintf(MimeSimplePromptRU, clueAction.Word, words) + } return fmt.Sprintf(GuesserSimplePrompt, clueAction.Word, words) } @@ -581,34 +584,20 @@ func (b *Bot) BuildSimpleMimePrompt(room *models.Room) string { theirwords = append(theirwords, card.Word) } } - return fmt.Sprintf(MimeSimplePrompt, ourwords, theirwords, blackWord, room.BlueCounter, room.RedCounter) + if strings.EqualFold(room.Settings.Language, "ru") { + return fmt.Sprintf(MimeSimplePromptRU, ourwords, theirwords, blackWord) + } + return fmt.Sprintf(MimeSimplePrompt, ourwords, theirwords, blackWord) } func (b *Bot) BuildPrompt(room *models.Room) string { if b.Role == "" { return "" } - // toText := make(map[string]any) - // toText["backlog"] = room.ActionHistory - // // mime sees all colors; - // // guesser sees only revealed ones - // if b.Role == models.UserRoleMime { - // toText["cards"] = room.Cards - // } - // data, err := json.Marshal(toText) - // if err != nil { - // b.log.Error("failed to marshal", "error", err) - // return "" - // } - // Escape the JSON string for inclusion in another JSON field - // escapedData := strings.ReplaceAll(string(data), `"`, `\\"`) if b.Role == models.UserRoleMime { - // return fmt.Sprintf(MimeSimplePrompt, b.Team, b.Team, room.BlueCounter, room.RedCounter, escapedData) - // return fmt.Sprintf(MimePrompt, b.Team, b.Team, room.BlueCounter, room.RedCounter, escapedData) return b.BuildSimpleMimePrompt(room) } if b.Role == models.UserRoleGuesser { - // return fmt.Sprintf(GuesserPrompt, b.Team, b.Team, room.BlueCounter, room.RedCounter, escapedData) return b.BuildSimpleGuesserPrompt(room) } return ""