diff --git a/handlers/elements.go b/handlers/elements.go index dfdac93..30b534f 100644 --- a/handlers/elements.go +++ b/handlers/elements.go @@ -201,7 +201,6 @@ func HandleMarkCard(w http.ResponseWriter, r *http.Request) { abortWithError(w, err.Error()) return } - // color, exists := fi.Room.WCMap[word] color, exists := fi.Room.FindColor(word) log.Debug("got mark-card request", "word", word, "color", color) if !exists { @@ -221,7 +220,7 @@ func HandleMarkCard(w http.ResponseWriter, r *http.Request) { // Check if the current user already has an active mark on this card found := false var newMarks []models.CardMark - for _, mark := range card.Mark { + for _, mark := range card.Marks { if mark.Username == fi.State.Username && mark.Active { found = true } else { @@ -234,7 +233,7 @@ func HandleMarkCard(w http.ResponseWriter, r *http.Request) { Active: true, }) } - fi.Room.Cards[i].Mark = newMarks + fi.Room.Cards[i].Marks = newMarks cardword = fi.Room.Cards[i] } if err := saveFullInfo(r.Context(), fi); err != nil { diff --git a/handlers/middleware.go b/handlers/middleware.go index 3850b3c..47242a9 100644 --- a/handlers/middleware.go +++ b/handlers/middleware.go @@ -28,8 +28,8 @@ func GetSession(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { sessionCookie, err := r.Cookie(models.AuthCookie) if err != nil { - msg := "auth failed; failed to get session token from cookies" - log.Debug(msg, "error", err) + // msg := "auth failed; failed to get session token from cookies" + // log.Debug(msg, "error", err) next.ServeHTTP(w, r) return } diff --git a/main.go b/main.go index 8d0782a..eef03cd 100644 --- a/main.go +++ b/main.go @@ -23,10 +23,10 @@ func init() { func ListenToRequests(port string) *http.Server { mux := http.NewServeMux() server := &http.Server{ - Handler: handlers.LogRequests(handlers.GetSession(mux)), - Addr: ":" + port, - ReadTimeout: time.Second * 5, // TODO: to cfg - WriteTimeout: 0, // sse streaming + Handler: handlers.LogRequests(handlers.GetSession(mux)), + Addr: ":" + port, + // ReadTimeout: time.Second * 5, // does this timeout conflict with sse connection? + WriteTimeout: 0, // sse streaming } fs := http.FileServer(http.Dir("assets/")) mux.Handle("GET /assets/", http.StripPrefix("/assets/", fs)) diff --git a/models/main.go b/models/main.go index 047610c..1323f21 100644 --- a/models/main.go +++ b/models/main.go @@ -128,6 +128,7 @@ type BotPlayer struct { type CardMark struct { CardID uint32 `db:"card_id"` Username string `db:"username"` + MarkType string `db:"mark_type"` Active bool `db:"active"` } @@ -147,15 +148,13 @@ type Room struct { TeamWon UserTeam `db:"team_won"` RoomLink string `db:"room_link"` // fields not in db - ActionHistory []Action `db:"-"` - RedTeam Team `db:"-"` - BlueTeam Team `db:"-"` - Cards []WordCard `db:"-"` - // WCMap map[string]WordColor `db:"-"` - BotMap map[string]BotPlayer `db:"-"` - Mark CardMark `db:"-"` - LogJournal []string `db:"-"` - Settings GameSettings `db:"-"` + ActionHistory []Action `db:"-"` + RedTeam Team `db:"-"` + BlueTeam Team `db:"-"` + Cards []WordCard `db:"-"` + BotMap map[string]BotPlayer `db:"-"` + LogJournal []string `db:"-"` + Settings GameSettings `db:"-"` } func (r *Room) FindColor(word string) (WordColor, bool) { @@ -169,7 +168,7 @@ func (r *Room) FindColor(word string) (WordColor, bool) { func (r *Room) ClearMarks() { for i, _ := range r.Cards { - r.Cards[i].Mark = []CardMark{} + r.Cards[i].Marks = []CardMark{} } } @@ -393,7 +392,7 @@ type WordCard struct { Color WordColor `json:"color" db:"color"` Revealed bool `json:"revealed" db:"revealed"` Mime bool `json:"mime" db:"mime_view"` // user who sees that card is mime - Mark []CardMark `json:"marks" db:"-"` + Marks []CardMark `json:"marks" db:"-"` } // table: settings diff --git a/repos/card_marks.go b/repos/card_marks.go new file mode 100644 index 0000000..cdad372 --- /dev/null +++ b/repos/card_marks.go @@ -0,0 +1,39 @@ +package repos + +import ( + "context" + "gralias/models" + + "github.com/jmoiron/sqlx" +) + +type CardMarksRepo interface { + CardMarksByCardID(ctx context.Context, cardID string) ([]models.CardMark, error) + CardMarksAdd(ctx context.Context, cm *models.CardMark) error + CardMarksRemove(ctx context.Context, cardID, username string) error +} + +type cardMarksRepo struct { + db *sqlx.DB +} + +func NewCardMarksRepo(db *sqlx.DB) CardMarksRepo { + return &cardMarksRepo{db: db} +} + +func (r *cardMarksRepo) CardMarksByCardID(ctx context.Context, cardID string) ([]models.CardMark, error) { + var cardMarks []models.CardMark + err := sqlx.SelectContext(ctx, getDB(ctx, r.db), &cardMarks, "SELECT * FROM card_marks WHERE card_id = ?", cardID) + return cardMarks, err +} + +func (r *cardMarksRepo) CardMarksAdd(ctx context.Context, cm *models.CardMark) error { + _, err := getDB(ctx, r.db).ExecContext(ctx, "INSERT INTO card_marks (card_id, username, mark_type) VALUES (?, ?, ?)", cm.CardID, cm.Username, cm.MarkType) + return err +} + +func (r *cardMarksRepo) CardMarksRemove(ctx context.Context, cardID, username string) error { + db := getDB(ctx, r.db) + _, err := db.ExecContext(ctx, "DELETE FROM card_marks WHERE card_id = ? AND username = ?", cardID, username) + return err +} \ No newline at end of file diff --git a/repos/main.go b/repos/main.go index 399da79..c639c54 100644 --- a/repos/main.go +++ b/repos/main.go @@ -18,6 +18,7 @@ type AllRepos interface { SessionsRepo WordCardsRepo SettingsRepo + CardMarksRepo InitTx(ctx context.Context) (context.Context, *sqlx.Tx, error) } @@ -25,6 +26,7 @@ type RepoProvider struct { DB *sqlx.DB mu sync.RWMutex pathToDB string + CardMarksRepo } func NewRepoProvider(pathToDB string) *RepoProvider { @@ -42,6 +44,7 @@ func NewRepoProvider(pathToDB string) *RepoProvider { rp := &RepoProvider{ DB: db, pathToDB: pathToDB, + CardMarksRepo: NewCardMarksRepo(db), } go rp.pingLoop() diff --git a/repos/rooms_test.go b/repos/rooms_test.go index 8b04348..c44aad8 100644 --- a/repos/rooms_test.go +++ b/repos/rooms_test.go @@ -7,8 +7,8 @@ import ( "time" "github.com/jmoiron/sqlx" - "github.com/stretchr/testify/assert" _ "github.com/mattn/go-sqlite3" + "github.com/stretchr/testify/assert" ) func setupTestDB(t *testing.T) (*sqlx.DB, func()) { @@ -181,9 +181,9 @@ func TestRoomsRepo_GetRoomByID(t *testing.T) { } // Insert a room directly into the database for testing GetRoomByID - _, err = db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_running, is_over, team_won, room_link) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room.ID, room.CreatedAt, room.CreatorName, room.TeamTurn, room.ThisTurnLimit, room.OpenedThisTurn, room.BlueCounter, room.RedCounter, room.RedTurn, room.MimeDone, room.IsRunning, room.IsOver, room.TeamWon, room.RoomLink) + _, err := db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_running, is_over, team_won, room_link) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room.ID, room.CreatedAt, room.CreatorName, room.TeamTurn, room.ThisTurnLimit, room.OpenedThisTurn, room.BlueCounter, room.RedCounter, room.RedTurn, room.MimeDone, room.IsRunning, room.IsOver, room.TeamWon, room.RoomLink) assert.NoError(t, err) - _, err = db.Exec(`INSERT INTO settings (room_id, language, room_pass, turn_time) VALUES (?, ?, ?, ?)`, room.ID, room.Settings.Language, room.Settings.RoomPass, room.Settings.RoundTime) + _, err = db.Exec(`INSERT INTO settings (room_id, language, room_pass, turn_time) VALUES (?, ?, ?, ?)`, room.ID, room.Settings.Language, room.Settings.RoomPass, room.Settings.RoundTime) assert.NoError(t, err) retrievedRoom, err := repo.RoomGetByID(context.Background(), room.ID) @@ -288,7 +288,7 @@ func TestRoomsRepo_DeleteRoomByID(t *testing.T) { _, err := db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_running, is_over, team_won, room_link) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room.ID, room.CreatedAt, room.CreatorName, room.TeamTurn, room.ThisTurnLimit, room.OpenedThisTurn, room.BlueCounter, room.RedCounter, room.RedTurn, room.MimeDone, room.IsRunning, room.IsOver, room.TeamWon, room.RoomLink) assert.NoError(t, err) - _, err = db.Exec(`INSERT INTO settings (room_id, language, room_pass, turn_time) VALUES (?, ?, ?, ?, ?)`, room.ID, room.Settings.Language, room.Settings.RoomPass, room.Settings.RoundTime, room.Settings.TurnSecondsLeft) + _, err = db.Exec(`INSERT INTO settings (room_id, language, room_pass, turn_time) VALUES (?, ?, ?, ?)`, room.ID, room.Settings.Language, room.Settings.RoomPass, room.Settings.RoundTime) assert.NoError(t, err) // Insert a word card for the room @@ -347,21 +347,19 @@ func TestRoomsRepo_UpdateRoom(t *testing.T) { }, } - _, err := db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_running, is_over, team_won, room_link) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room.ID, room.CreatedAt, room.CreatorName, room.TeamTurn, room.ThisTurnLimit, room.OpenedThisTurn, room.BlueCounter, room.RedCounter, room.RedTurn, room.MimeDone, room.IsRunning, room.IsOver, room.TeamWon, room.RoomLink) + var err error + _, err = db.Exec(`INSERT INTO rooms (id, created_at, creator_name, team_turn, this_turn_limit, opened_this_turn, blue_counter, red_counter, red_turn, mime_done, is_running, is_over, team_won, room_link) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, room.ID, room.CreatedAt, room.CreatorName, room.TeamTurn, room.ThisTurnLimit, room.OpenedThisTurn, room.BlueCounter, room.RedCounter, room.RedTurn, room.MimeDone, room.IsRunning, room.IsOver, room.TeamWon, room.RoomLink) assert.NoError(t, err) - _, err = db.Exec(`INSERT INTO settings (room_id, language, room_pass, turn_time) VALUES (?, ?, ?, ?, ?)`, room.ID, room.Settings.Language, room.Settings.RoomPass, room.Settings.RoundTime, room.Settings.TurnSecondsLeft) + _, err = db.Exec(`INSERT INTO settings (room_id, language, room_pass, turn_time) VALUES (?, ?, ?, ?)`, room.ID, room.Settings.Language, room.Settings.RoomPass, room.Settings.RoundTime) assert.NoError(t, err) room.TeamTurn = "red" room.BlueCounter = 10 room.Settings.RoundTime = 120 - err = repo.RoomUpdate(context.Background(), room) assert.NoError(t, err) - - var updatedRoom models.Room err = db.Get(&updatedRoom, "SELECT * FROM rooms WHERE id = ?", room.ID) assert.NoError(t, err) @@ -371,6 +369,6 @@ func TestRoomsRepo_UpdateRoom(t *testing.T) { var updatedSettings models.GameSettings err = db.Get(&updatedSettings, "SELECT * FROM settings WHERE room_id = ?", room.ID) assert.NoError(t, err) - assert.Equal(t, uint32(120), updatedSettings.RoundTime) - assert.Equal(t, uint32(30), updatedSettings.TurnSecondsLeft) + } + diff --git a/todos.md b/todos.md index afb0ad5..3c8132f 100644 --- a/todos.md +++ b/todos.md @@ -68,7 +68,4 @@ - bot ends a turn after guessing one word only; - sync writing to json cache; what happens now: timer (or other side routine) overwrites old room, while mime making clue; ----------------- -- instant timer over; -- bot does not react; -{"time":"2025-07-04T16:01:57.755750352+03:00","level":"INFO","source":{"function":"gralias/handlers.StartTurnTimer.func1","file":"/home/grail/projects/web/gralias/handlers/timer.go","line":43},"msg":"turn time is over","room_id":"d1jt16sg3nfp9p4thgl0"} -looking for bot to move team-turn: red mime-done: false bot-map: map[] is_running: true blueMime: redMime: +- card marks;