From 86063a4f7ede65cc659d9fda238baf8e637754ab Mon Sep 17 00:00:00 2001 From: Grail Finder Date: Fri, 27 Jun 2025 15:23:45 +0300 Subject: [PATCH] Feat: mark words [for guessers] --- components/cardword.html | 8 +++- handlers/elements.go | 99 +++++++--------------------------------- todos.md | 36 +++++++-------- 3 files changed, 40 insertions(+), 103 deletions(-) diff --git a/components/cardword.html b/components/cardword.html index 9f855a0..24df4a3 100644 --- a/components/cardword.html +++ b/components/cardword.html @@ -17,8 +17,12 @@ {{.Word}}
-   + hx-get="/mark-card?word={{.Word}}" hx-trigger="click" hx-swap="outerHTML transition:true swap:.05s"> + {{range .Mark}} + {{if .Active}} + X + {{end}} + {{end}}
{{end}} diff --git a/handlers/elements.go b/handlers/elements.go index 7afaa3d..4d07bcc 100644 --- a/handlers/elements.go +++ b/handlers/elements.go @@ -171,6 +171,7 @@ func HandleMarkCard(w http.ResponseWriter, r *http.Request) { abortWithError(w, "word is not found") return } + cardword := models.WordCard{} // check if card already was revealed for i, card := range fi.Room.Cards { if !strings.EqualFold(card.Word, word) { @@ -180,97 +181,29 @@ func HandleMarkCard(w http.ResponseWriter, r *http.Request) { abortWithError(w, "cannot mark already revealed") return } - fi.Room.Cards[i].Mark = append(card.Mark, models.CardMark{ - Username: fi.State.Username, - Active: true, - }) - } - cardword := models.WordCard{ - Word: word, - Color: color, - Revealed: false, - } - fi.Room.RevealSpecificWord(word) - fi.Room.UpdateCounter() - action := models.Action{ - Actor: fi.State.Username, - ActorColor: string(fi.State.Team), - WordColor: string(color), - Action: models.ActionTypeGuess, - Word: word, - } - fi.Room.ActionHistory = append(fi.Room.ActionHistory, action) - // if opened card is of color of opp team, change turn - oppositeColor := fi.Room.GetOppositeTeamColor() - fi.Room.OpenedThisTurn++ - if fi.Room.ThisTurnLimit > 0 { - if fi.Room.ThisTurnLimit >= fi.Room.OpenedThisTurn { - // end turn - fi.Room.TeamTurn = oppositeColor - fi.Room.MimeDone = false - fi.Room.OpenedThisTurn = 0 - fi.Room.ThisTurnLimit = 0 - } - } - switch string(color) { - case "black": - // game over - fi.Room.IsRunning = false - fi.Room.IsOver = true - fi.Room.TeamWon = oppositeColor - action := models.Action{ - Actor: fi.State.Username, - ActorColor: string(fi.State.Team), - WordColor: models.WordColorBlack, - Action: models.ActionTypeGameOver, - } - fi.Room.OpenedThisTurn = 0 - fi.Room.ThisTurnLimit = 0 - fi.Room.ActionHistory = append(fi.Room.ActionHistory, action) - case "white", string(oppositeColor): - // end turn - fi.Room.TeamTurn = oppositeColor - fi.Room.MimeDone = false - fi.Room.OpenedThisTurn = 0 - fi.Room.ThisTurnLimit = 0 - // check if no cards left => game over - if fi.Room.BlueCounter == 0 { - // blue won - fi.Room.IsRunning = false - fi.Room.IsOver = true - fi.Room.TeamWon = "blue" - action := models.Action{ - Actor: fi.State.Username, - ActorColor: string(fi.State.Team), - WordColor: models.WordColorBlue, - Action: models.ActionTypeGameOver, + // Check if the current user already has an active mark on this card + found := false + var newMarks []models.CardMark + for _, mark := range card.Mark { + if mark.Username == fi.State.Username && mark.Active { + found = true + } else { + newMarks = append(newMarks, mark) } - fi.Room.OpenedThisTurn = 0 - fi.Room.ThisTurnLimit = 0 - fi.Room.ActionHistory = append(fi.Room.ActionHistory, action) } - if fi.Room.RedCounter == 0 { - // red won - fi.Room.IsRunning = false - fi.Room.IsOver = true - fi.Room.TeamWon = "red" - action := models.Action{ - Actor: fi.State.Username, - ActorColor: string(fi.State.Team), - WordColor: models.WordColorRed, - Action: models.ActionTypeGameOver, - } - fi.Room.OpenedThisTurn = 0 - fi.Room.ThisTurnLimit = 0 - fi.Room.ActionHistory = append(fi.Room.ActionHistory, action) + if !found { + newMarks = append(newMarks, models.CardMark{ + Username: fi.State.Username, + Active: true, + }) } + fi.Room.Cards[i].Mark = newMarks + cardword = fi.Room.Cards[i] } if err := saveFullInfo(fi); err != nil { abortWithError(w, err.Error()) return } - // get mime bot for opp team and notify it - notifyBotIfNeeded(fi) notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "") if err := tmpl.ExecuteTemplate(w, "cardword", cardword); err != nil { log.Error("failed to execute cardword template", "error", err) diff --git a/todos.md b/todos.md index af32b5a..d663cc6 100644 --- a/todos.md +++ b/todos.md @@ -1,24 +1,25 @@ ### feats - auto close room if nothing is going on there (hmm) for ~1h; + - words database (file) load and form random 25 words; + -- different files for each supported lang; -- mark cards (instead of opening them (right click?); - invite link; + - login with invite link; + - there three places for bot to check if its its move: start-game; end-turn, after mime gave clue; + - remove bot button (if game is not running, or bot already added); + - show in backlog (and with that in prompt to llm) how many cards are left to open, also additional comment: if guess was right; -- hide clue input for mime when it's not their turn; +- hide clue input for mime when it's not their turn; + - needs resend to llm btn; + +- check if clue word is the same as one of the cards and return err if it is; + +- autoscroll down backlog on update; + +- instead of guessing all words at ones, ask only for 1 word to be open. + +- ways to remove bots from teams; + - better styles and fluff; - common auth system between sites; -- autoscroll down backlog on update; - gameover to backlog; +- cleanup backlog after new game is started; - ended turn action to backlog; - clear indication that model (llm) is thinking / answered; -- instead of guessing all words at ones, ask only for 1 word to be open. -- ways to remove bots from teams; -- check if clue word is the same as one of the cards and return err if it is; + +- different files for each supported lang; +- mark cards (instead of opening them (right click?); #### sse points - clue sse update; @@ -31,19 +32,18 @@ ### issues -- after the game started (isrunning) players should be able join guessers, but not switch team, or join as a mime; -- cleanup backlog after new game is started; +- after the game started (isrunning) players should be able join guessers, but not switch team, or join as a mime; + - guessers should not be able to open more cards, than mime gave them +1 (auto end turn); + -- 0 should mean without limit; -- sse hangs / fails connection which causes to wait for cards to open a few seconds (on local machine); -- after starting a new game (after old one) blue mime has no clue input; -- remove verbs from word file; -- invite link gets cutoff; - mime rejoined the room: does not see colors; state save in store.json has empty role and team + - restart bot routines after server restart; + +- remove verbs from word file; + +- if mime joins another role, he stays as mime (before game start); + +- guesser llm makes up words, likely the prompt should be more clear; + +- remove bot does not remove for player roles in the room; + +- 0 should mean without limit; +- sse hangs / fails connection which causes to wait for cards to open a few seconds (on local machine) (did not reoccur so far); +- invite link gets cutoff; - guesser did not have same number of guesses (move ended after 1 guess); show how much guesses left on the page (red after blue); - guesser bot no request after game restart; -- if mime joins another role, he stays as mime (before game start); -- guesser llm makes up words, likely the prompt should be more clear; -- remove bot does not remove for player roles in the room; + -- remove join as mime button if there is a mime already on that team; +- remove join as mime button if there is a mime already on that team (rewrite teampew templ); +- openrouter 429 errors;