Fix: notify bot
This commit is contained in:
@ -33,8 +33,7 @@ func saveRoom(room *models.Room) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
memcache.Set(models.CacheRoomPrefix+room.ID, data)
|
memcache.Set(key, data)
|
||||||
log.Debug("saved room", "room", room, "key", key)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +83,21 @@ func saveFullInfo(fi *models.FullInfo) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func notifyBotIfNeeded(fi *models.FullInfo) {
|
||||||
|
if botName := fi.Room.WhichBotToMove(); botName != "" {
|
||||||
|
// // get bot from memcache
|
||||||
|
// bot, err := loadBot(botName, fi.Room.ID)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Error("failed to load bot", "bot_name", botName, "room_id", fi.Room.ID)
|
||||||
|
// // abortWithError(w, err.Error())
|
||||||
|
// // return
|
||||||
|
// }
|
||||||
|
// send signal to bot
|
||||||
|
llmapi.SignalChanMap[botName] <- true
|
||||||
|
}
|
||||||
|
log.Debug("no bot", "room_id", fi.Room.ID)
|
||||||
|
}
|
||||||
|
|
||||||
// cache
|
// cache
|
||||||
|
|
||||||
func saveState(username string, state *models.UserState) error {
|
func saveState(username string, state *models.UserState) error {
|
||||||
@ -110,7 +124,16 @@ func loadState(username string) (*models.UserState, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadBot(botName, roomID string) (*llmapi.Bot, error) {
|
func loadBot(botName, roomID string) (*llmapi.Bot, error) {
|
||||||
return nil, nil
|
key := "botkey_" + roomID + botName
|
||||||
|
data, err := memcache.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp := &llmapi.Bot{}
|
||||||
|
if err := json.Unmarshal(data, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllNames() []string {
|
func getAllNames() []string {
|
||||||
|
@ -92,6 +92,7 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) {
|
|||||||
case "white", string(oppositeColor):
|
case "white", string(oppositeColor):
|
||||||
// end turn
|
// end turn
|
||||||
fi.Room.TeamTurn = oppositeColor
|
fi.Room.TeamTurn = oppositeColor
|
||||||
|
fi.Room.MimeDone = false
|
||||||
}
|
}
|
||||||
// check if no cards left => game over
|
// check if no cards left => game over
|
||||||
if fi.Room.BlueCounter == 0 {
|
if fi.Room.BlueCounter == 0 {
|
||||||
@ -110,6 +111,8 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) {
|
|||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// get mime bot for opp team and notify it
|
||||||
|
notifyBotIfNeeded(fi)
|
||||||
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
||||||
if err := tmpl.ExecuteTemplate(w, "cardword", cardword); err != nil {
|
if err := tmpl.ExecuteTemplate(w, "cardword", cardword); err != nil {
|
||||||
log.Error("failed to execute cardword template", "error", err)
|
log.Error("failed to execute cardword template", "error", err)
|
||||||
@ -136,16 +139,19 @@ func HandleAddBot(w http.ResponseWriter, r *http.Request) {
|
|||||||
// get team; // get role; make up a name
|
// get team; // get role; make up a name
|
||||||
team := r.URL.Query().Get("team")
|
team := r.URL.Query().Get("team")
|
||||||
role := r.URL.Query().Get("role")
|
role := r.URL.Query().Get("role")
|
||||||
|
log.Debug("got add-bot request", "team", team, "role", role)
|
||||||
fi, err := getFullInfoByCtx(r.Context())
|
fi, err := getFullInfoByCtx(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// TODO: what if bot exists already?
|
||||||
|
// control number and names of bots
|
||||||
bot, err := llmapi.NewBot(role, team, "bot1", fi.Room.ID, cfg)
|
bot, err := llmapi.NewBot(role, team, "bot1", fi.Room.ID, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bot.StartBot()
|
go bot.StartBot()
|
||||||
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
||||||
}
|
}
|
||||||
|
@ -51,53 +51,6 @@ func HandleCreateRoom(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEPRACATED: duplication of HandleJoinRoom
|
|
||||||
// func HandleRoomEnter(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// // parse payload
|
|
||||||
// roomID := r.URL.Query().Get("id")
|
|
||||||
// if roomID == "" {
|
|
||||||
// msg := "room id not provided"
|
|
||||||
// log.Error(msg)
|
|
||||||
// abortWithError(w, msg)
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// tmpl, err := template.ParseGlob("components/*.html")
|
|
||||||
// if err != nil {
|
|
||||||
// abortWithError(w, err.Error())
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// // create a room
|
|
||||||
// room, err := getRoomByID(roomID)
|
|
||||||
// if err != nil {
|
|
||||||
// msg := "failed to find the room"
|
|
||||||
// log.Error(msg, "error", err, "room_id", roomID)
|
|
||||||
// abortWithError(w, msg)
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// state, err := getStateByCtx(r.Context())
|
|
||||||
// // INFO: if non-loggined user join: prompt to login
|
|
||||||
// if err != nil {
|
|
||||||
// log.Error("failed to get state", "error", err)
|
|
||||||
// // abortWithError(w, err.Error())
|
|
||||||
// tmpl.ExecuteTemplate(w, "login", nil)
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// state.RoomID = room.ID
|
|
||||||
// // update state
|
|
||||||
// if err := saveStateByCtx(r.Context(), state); err != nil {
|
|
||||||
// log.Error("failed to update state", "error", err)
|
|
||||||
// abortWithError(w, err.Error())
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// // send msg of created room
|
|
||||||
// // h.Broker.Notifier <- broker.NotificationEvent{
|
|
||||||
// // EventName: models.MsgRoomListUpdate,
|
|
||||||
// // Payload: fmt.Sprintf("%s created a room named %s", r.CreatorName, r.RoomName),
|
|
||||||
// // }
|
|
||||||
// // return html
|
|
||||||
// tmpl.ExecuteTemplate(w, "base", room)
|
|
||||||
// }
|
|
||||||
|
|
||||||
func HandleJoinTeam(w http.ResponseWriter, r *http.Request) {
|
func HandleJoinTeam(w http.ResponseWriter, r *http.Request) {
|
||||||
if err := r.ParseForm(); err != nil {
|
if err := r.ParseForm(); err != nil {
|
||||||
log.Error("failed to parse form", "error", err)
|
log.Error("failed to parse form", "error", err)
|
||||||
@ -158,6 +111,7 @@ func HandleEndTurn(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
fi.Room.ChangeTurn()
|
fi.Room.ChangeTurn()
|
||||||
|
fi.Room.MimeDone = false
|
||||||
if err := saveFullInfo(fi); err != nil {
|
if err := saveFullInfo(fi); err != nil {
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
@ -168,17 +122,7 @@ func HandleEndTurn(w http.ResponseWriter, r *http.Request) {
|
|||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if botName := fi.Room.WhichBotToMove(); botName != "" {
|
notifyBotIfNeeded(fi)
|
||||||
// get bot from memcache
|
|
||||||
bot, err := loadBot(botName, fi.Room.ID)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("failed to load bot", "bot_name", botName, "room_id", fi.Room.ID)
|
|
||||||
abortWithError(w, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// send signal to bot
|
|
||||||
bot.SignalsCh <- true
|
|
||||||
}
|
|
||||||
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
||||||
if err := tmpl.ExecuteTemplate(w, "base", fi); err != nil {
|
if err := tmpl.ExecuteTemplate(w, "base", fi); err != nil {
|
||||||
log.Error("failed to execute base template", "error", err)
|
log.Error("failed to execute base template", "error", err)
|
||||||
@ -222,17 +166,7 @@ func HandleStartGame(w http.ResponseWriter, r *http.Request) {
|
|||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if botName := fi.Room.WhichBotToMove(); botName != "" {
|
notifyBotIfNeeded(fi)
|
||||||
// get bot from memcache
|
|
||||||
bot, err := loadBot(botName, fi.Room.ID)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("failed to load bot", "bot_name", botName, "room_id", fi.Room.ID)
|
|
||||||
abortWithError(w, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// send signal to bot
|
|
||||||
bot.SignalsCh <- true
|
|
||||||
}
|
|
||||||
// to update only the room that should be updated
|
// to update only the room that should be updated
|
||||||
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
||||||
// notify(models.NotifyBacklogPrefix+fi.Room.ID, "game started")
|
// notify(models.NotifyBacklogPrefix+fi.Room.ID, "game started")
|
||||||
|
@ -5,24 +5,22 @@ import (
|
|||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
|
||||||
"golias/models"
|
"golias/models"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// LogRequests logs all HTTP requests with method, path and duration
|
// LogRequests logs all HTTP requests with method, path and duration
|
||||||
func LogRequests(next http.Handler) http.Handler {
|
func LogRequests(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
start := time.Now()
|
// start := time.Now()
|
||||||
// Wrap response writer to capture status code
|
// Wrap response writer to capture status code
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
duration := time.Since(start)
|
// duration := time.Since(start)
|
||||||
log.Debug("request completed",
|
// log.Debug("request completed",
|
||||||
"method", r.Method,
|
// "method", r.Method,
|
||||||
"path", r.URL.RequestURI(),
|
// "path", r.URL.RequestURI(),
|
||||||
"duration", duration.String(),
|
// "duration", duration.String(),
|
||||||
)
|
// )
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,11 +63,11 @@ func GetSession(next http.Handler) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
userSession, err := cacheGetSession(sessionToken)
|
userSession, err := cacheGetSession(sessionToken)
|
||||||
log.Debug("userSession from cache", "us", userSession)
|
// log.Debug("userSession from cache", "us", userSession)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "auth failed; session does not exists"
|
// msg := "auth failed; session does not exists"
|
||||||
err = errors.New(msg)
|
// err = errors.New(msg)
|
||||||
log.Debug(msg, "error", err)
|
// log.Debug(msg, "error", err)
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,6 +19,14 @@ import (
|
|||||||
// MIME: llm needs to know all the cards, colors and previous actions
|
// MIME: llm needs to know all the cards, colors and previous actions
|
||||||
// GUESSER: llm needs to know all the cards and previous actions
|
// GUESSER: llm needs to know all the cards and previous actions
|
||||||
|
|
||||||
|
// channels are not serializable
|
||||||
|
|
||||||
|
var (
|
||||||
|
// botname -> channel
|
||||||
|
SignalChanMap = make(map[string]chan bool)
|
||||||
|
DoneChanMap = make(map[string]chan bool)
|
||||||
|
)
|
||||||
|
|
||||||
type Bot struct {
|
type Bot struct {
|
||||||
Role string // gueeser | mime
|
Role string // gueeser | mime
|
||||||
Team string
|
Team string
|
||||||
@ -26,15 +35,17 @@ type Bot struct {
|
|||||||
BotName string
|
BotName string
|
||||||
log *slog.Logger
|
log *slog.Logger
|
||||||
// channels for communicaton
|
// channels for communicaton
|
||||||
SignalsCh chan bool
|
// channels are not serializable
|
||||||
DoneCh chan bool
|
// SignalsCh chan bool
|
||||||
|
// DoneCh chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartBot
|
// StartBot
|
||||||
func (b *Bot) StartBot() {
|
func (b *Bot) StartBot() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-b.SignalsCh:
|
case <-SignalChanMap[b.BotName]:
|
||||||
|
b.log.Debug("got signal", "bot-team", b.Team, "bot-role", b.Role)
|
||||||
// get room cards and actions
|
// get room cards and actions
|
||||||
room, err := getRoomByID(b.RoomID)
|
room, err := getRoomByID(b.RoomID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -53,7 +64,7 @@ func (b *Bot) StartBot() {
|
|||||||
// if mime -> give clue
|
// if mime -> give clue
|
||||||
// if guesser -> open card (does opening one card prompting new loop?)
|
// if guesser -> open card (does opening one card prompting new loop?)
|
||||||
// send notification to sse broker
|
// send notification to sse broker
|
||||||
case <-b.DoneCh:
|
case <-DoneChanMap[b.BotName]:
|
||||||
b.log.Debug("got done signal", "bot-name", b.BotName)
|
b.log.Debug("got done signal", "bot-name", b.BotName)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -69,6 +80,10 @@ func NewBot(role, team, name, roomID string, cfg *config.Config) (*Bot, error) {
|
|||||||
BotName: name,
|
BotName: name,
|
||||||
Team: team,
|
Team: team,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
|
log: slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
|
||||||
|
Level: slog.LevelDebug,
|
||||||
|
AddSource: true,
|
||||||
|
})),
|
||||||
}
|
}
|
||||||
// add to room
|
// add to room
|
||||||
room, err := getRoomByID(bot.RoomID)
|
room, err := getRoomByID(bot.RoomID)
|
||||||
@ -108,10 +123,25 @@ func NewBot(role, team, name, roomID string, cfg *config.Config) (*Bot, error) {
|
|||||||
if err := saveRoom(room); err != nil {
|
if err := saveRoom(room); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if err := saveBot(bot); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
SignalChanMap[bot.BotName] = make(chan bool)
|
||||||
|
DoneChanMap[bot.BotName] = make(chan bool)
|
||||||
go bot.StartBot() // run bot routine
|
go bot.StartBot() // run bot routine
|
||||||
return bot, nil
|
return bot, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func saveBot(bot *Bot) error {
|
||||||
|
key := "botkey_" + bot.RoomID + bot.BotName
|
||||||
|
data, err := json.Marshal(bot)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cache.MemCache.Set(key, data)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func getRoomByID(roomID string) (*models.Room, error) {
|
func getRoomByID(roomID string) (*models.Room, error) {
|
||||||
roomBytes, err := cache.MemCache.Get(models.CacheRoomPrefix + roomID)
|
roomBytes, err := cache.MemCache.Get(models.CacheRoomPrefix + roomID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"golias/utils"
|
"golias/utils"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -84,6 +85,7 @@ type Room struct {
|
|||||||
|
|
||||||
// WhichBotToMove returns bot name that have to move or empty string
|
// WhichBotToMove returns bot name that have to move or empty string
|
||||||
func (r *Room) WhichBotToMove() string {
|
func (r *Room) WhichBotToMove() string {
|
||||||
|
fmt.Println("looking for bot to move", "team-turn", r.TeamTurn, "mime-done", r.MimeDone, "bot-map", r.BotMap, "is_running", r.IsRunning)
|
||||||
if !r.IsRunning {
|
if !r.IsRunning {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
1
todos.md
1
todos.md
@ -7,6 +7,7 @@
|
|||||||
- login with invite link;
|
- login with invite link;
|
||||||
- add html icons of whos turn it is (like an image of big ? when mime is thinking);
|
- add html icons of whos turn it is (like an image of big ? when mime is thinking);
|
||||||
- there two places for bot to check if its its move: start-game; end-turn;
|
- there two places for bot to check if its its move: start-game; end-turn;
|
||||||
|
- remove bot button (if game is not running);
|
||||||
|
|
||||||
#### sse points
|
#### sse points
|
||||||
- clue sse update;
|
- clue sse update;
|
||||||
|
Reference in New Issue
Block a user