Feat: remove bot
This commit is contained in:
@ -1,18 +1,31 @@
|
|||||||
{{ define "addbot" }}
|
{{ define "addbot" }}
|
||||||
|
{{$botName := ""}}
|
||||||
<div>
|
<div>
|
||||||
|
{{$botName = .Room.FindBotByTeamRole "blue" "mime"}}
|
||||||
{{ if eq .Room.BlueTeam.Mime "" }}
|
{{ if eq .Room.BlueTeam.Mime "" }}
|
||||||
<button hx-get="/add-bot?team=blue&role=mime" hx-target="#addbot" class="bg-blue-400 text-black px-4 py-2 rounded">Add Bot Mime</button>
|
<button hx-get="/add-bot?team=blue&role=mime" hx-target="#addbot" class="bg-blue-400 text-black px-4 py-2 rounded">Add Bot Mime</button>
|
||||||
|
{{ else if ne $botName "" }}
|
||||||
|
<button hx-get="/remove-bot?bot={{$botName}}" hx-target="#addbot" class="bg-blue-400 text-black px-4 py-2 rounded">Remove {{$botName}}</button>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
{{$botName = .Room.FindBotByTeamRole "red" "mime"}}
|
||||||
{{ if eq .Room.RedTeam.Mime "" }}
|
{{ if eq .Room.RedTeam.Mime "" }}
|
||||||
<button hx-get="/add-bot?team=red&role=mime" hx-target="#addbot" class="bg-red-400 text-black px-4 py-2 rounded">Add Bot Mime</button>
|
<button hx-get="/add-bot?team=red&role=mime" hx-target="#addbot" class="bg-red-400 text-black px-4 py-2 rounded">Add Bot Mime</button>
|
||||||
|
{{ else if ne $botName "" }}
|
||||||
|
<button hx-get="/remove-bot?bot={{$botName}}" hx-target="#addbot" class="bg-red-400 text-black px-4 py-2 rounded">Remove {{$botName}}</button>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
|
{{$botName = .Room.FindBotByTeamRole "blue" "guesser"}}
|
||||||
<div>
|
<div>
|
||||||
{{ if not .Room.BlueTeam.Guessers }}
|
{{ if not .Room.BlueTeam.Guessers }}
|
||||||
<button hx-get="/add-bot?team=blue&role=guesser" hx-target="#addbot" class="bg-blue-300 text-black px-4 py-2 rounded">Add Bot Guesser</button>
|
<button hx-get="/add-bot?team=blue&role=guesser" hx-target="#addbot" class="bg-blue-300 text-black px-4 py-2 rounded">Add Bot Guesser</button>
|
||||||
|
{{ else if ne $botName "" }}
|
||||||
|
<button hx-get="/remove-bot?bot={{$botName}}" hx-target="#addbot" class="bg-blue-300 text-black px-4 py-2 rounded">Remove {{$botName}}</button>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
{{$botName = .Room.FindBotByTeamRole "red" "guesser"}}
|
||||||
{{ if not .Room.RedTeam.Guessers }}
|
{{ if not .Room.RedTeam.Guessers }}
|
||||||
<button hx-get="/add-bot?team=red&role=guesser" hx-target="#addbot" class="bg-red-300 text-black px-4 py-2 rounded">Add Bot Guesser</button>
|
<button hx-get="/add-bot?team=red&role=guesser" hx-target="#addbot" class="bg-red-300 text-black px-4 py-2 rounded">Add Bot Guesser</button>
|
||||||
|
{{ else if ne $botName "" }}
|
||||||
|
<button hx-get="/remove-bot?bot={{$botName}}" hx-target="#addbot" class="bg-red-300 text-black px-4 py-2 rounded">Remove {{$botName}}</button>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
{{define "cardword"}}
|
{{define "cardword"}}
|
||||||
{{if .Revealed}}
|
{{if .Revealed}}
|
||||||
{{if eq .Color "amber"}}
|
{{if eq .Color "amber"}}
|
||||||
<div id="card-{{.Word}}" class="bg-{{.Color}}-100 p-4 rounded-lg min-w-[100px] text-center text-white cursor-pointer"
|
<div id="card-{{.Word}}" class="bg-{{.Color}}-100 border border-gray-500 p-4 rounded-lg min-w-[100px] text-center text-white cursor-pointer"
|
||||||
style="text-shadow: 0 2px 4px rgba(0,0,0,0.9);"> {{.Word}}
|
style="text-shadow: 0 2px 4px rgba(0,0,0,0.9);"> {{.Word}}
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div id="card-{{.Word}}" class="bg-{{.Color}}-600 p-4 rounded-lg min-w-[100px] text-center text-white cursor-pointer"
|
<div id="card-{{.Word}}" class="bg-{{.Color}}-600 border border-gray-500 p-4 rounded-lg min-w-[100px] text-center text-white cursor-pointer"
|
||||||
style="text-shadow: 0 2px 4px rgba(0,0,0,0.9);"> {{.Word}}
|
style="text-shadow: 0 2px 4px rgba(0,0,0,0.9);"> {{.Word}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<div id="card-{{.Word}}" class="bg-stone-600 p-4 rounded-lg min-w-[100px] text-center text-white cursor-pointer"
|
<div id="card-{{.Word}}" class="bg-stone-600 border border-gray-500 p-4 rounded-lg min-w-[100px] text-center text-white cursor-pointer"
|
||||||
style="text-shadow: 0 2px 4px rgba(0,0,0,0.8);"
|
style="text-shadow: 0 2px 4px rgba(0,0,0,0.8);"
|
||||||
hx-get="/word/show-color?word={{.Word}}" hx-trigger="click" hx-swap="outerHTML transition:true swap:.05s">
|
hx-get="/word/show-color?word={{.Word}}" hx-trigger="click" hx-swap="outerHTML transition:true swap:.05s">
|
||||||
{{.Word}}
|
{{.Word}}
|
||||||
|
@ -194,3 +194,18 @@ func HandleAddBot(w http.ResponseWriter, r *http.Request) {
|
|||||||
// go bot.StartBot()
|
// go bot.StartBot()
|
||||||
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := llmapi.RemoveBot(botName, fi.Room); err != nil {
|
||||||
|
abortWithError(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleCreateRoom(w http.ResponseWriter, r *http.Request) {
|
func HandleCreateRoom(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -248,12 +249,20 @@ func HandleGiveClue(w http.ResponseWriter, r *http.Request) {
|
|||||||
abortWithError(w, "your team already has a clue")
|
abortWithError(w, "your team already has a clue")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// check if the clue is the same as one of the existing words
|
||||||
|
for _, card := range fi.Room.Cards {
|
||||||
|
if strings.EqualFold(card.Word, clue) {
|
||||||
|
msg := fmt.Sprintf("cannot use existing word (%s) as a clue", clue)
|
||||||
|
abortWithError(w, msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
// ===
|
// ===
|
||||||
action := models.Action{
|
action := models.Action{
|
||||||
Actor: fi.State.Username,
|
Actor: fi.State.Username,
|
||||||
ActorColor: string(fi.State.Team),
|
ActorColor: string(fi.State.Team),
|
||||||
WordColor: string(fi.State.Team),
|
WordColor: string(fi.State.Team),
|
||||||
Action: "gave clue",
|
Action: models.ActionTypeClue,
|
||||||
Word: clue,
|
Word: clue,
|
||||||
Number: num,
|
Number: num,
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ func (b *Bot) checkGuess(word string, room *models.Room) error {
|
|||||||
Actor: b.BotName,
|
Actor: b.BotName,
|
||||||
ActorColor: b.Team,
|
ActorColor: b.Team,
|
||||||
WordColor: string(color),
|
WordColor: string(color),
|
||||||
Action: "guessed",
|
Action: models.ActionTypeGuess,
|
||||||
Word: word,
|
Word: word,
|
||||||
}
|
}
|
||||||
room.ActionHistory = append(room.ActionHistory, action)
|
room.ActionHistory = append(room.ActionHistory, action)
|
||||||
@ -115,12 +115,7 @@ func (b *Bot) checkGuess(word string, room *models.Room) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartBot
|
func (b *Bot) BotMove() {
|
||||||
func (b *Bot) StartBot() {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-SignalChanMap[b.BotName]:
|
|
||||||
func() {
|
|
||||||
// botJournalName := models.NotifyJournalPrefix + b.RoomID
|
// botJournalName := models.NotifyJournalPrefix + b.RoomID
|
||||||
b.log.Debug("got signal", "bot-team", b.Team, "bot-role", b.Role)
|
b.log.Debug("got signal", "bot-team", b.Team, "bot-role", b.Role)
|
||||||
// get room cards and actions
|
// get room cards and actions
|
||||||
@ -168,7 +163,7 @@ func (b *Bot) StartBot() {
|
|||||||
Actor: b.BotName,
|
Actor: b.BotName,
|
||||||
ActorColor: b.Team,
|
ActorColor: b.Team,
|
||||||
WordColor: b.Team,
|
WordColor: b.Team,
|
||||||
Action: "gave clue",
|
Action: models.ActionTypeClue,
|
||||||
Word: mimeResp.Clue,
|
Word: mimeResp.Clue,
|
||||||
Number: mimeResp.Number,
|
Number: mimeResp.Number,
|
||||||
}
|
}
|
||||||
@ -213,7 +208,14 @@ func (b *Bot) StartBot() {
|
|||||||
b.log.Debug("notifying bot", "name", botName)
|
b.log.Debug("notifying bot", "name", botName)
|
||||||
SignalChanMap[botName] <- true
|
SignalChanMap[botName] <- true
|
||||||
}
|
}
|
||||||
}()
|
}
|
||||||
|
|
||||||
|
// StartBot
|
||||||
|
func (b *Bot) StartBot() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-SignalChanMap[b.BotName]:
|
||||||
|
b.BotMove()
|
||||||
case <-DoneChanMap[b.BotName]:
|
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
|
||||||
@ -221,6 +223,18 @@ func (b *Bot) StartBot() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RemoveBot(botName string, room *models.Room) error {
|
||||||
|
// channels
|
||||||
|
DoneChanMap[botName] <- true
|
||||||
|
close(DoneChanMap[botName])
|
||||||
|
close(SignalChanMap[botName])
|
||||||
|
// maps
|
||||||
|
delete(room.BotMap, botName)
|
||||||
|
delete(DoneChanMap, botName)
|
||||||
|
delete(SignalChanMap, botName)
|
||||||
|
return saveRoom(room)
|
||||||
|
}
|
||||||
|
|
||||||
// EndBot
|
// EndBot
|
||||||
|
|
||||||
func NewBot(role, team, name, roomID string, cfg *config.Config, recovery bool) (*Bot, error) {
|
func NewBot(role, team, name, roomID string, cfg *config.Config, recovery bool) (*Bot, error) {
|
||||||
|
@ -160,8 +160,10 @@ func (p *openRouterParser) ParseBytes(body []byte) (map[string]any, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *openRouterParser) MakePayload(prompt string) io.Reader {
|
func (p *openRouterParser) MakePayload(prompt string) io.Reader {
|
||||||
|
// "model": "deepseek/deepseek-chat-v3-0324:free",
|
||||||
|
// TODO: set list of models an option to pick on the frontend
|
||||||
strPayload := fmt.Sprintf(`{
|
strPayload := fmt.Sprintf(`{
|
||||||
"model": "deepseek/deepseek-chat-v3-0324:free",
|
"model": "google/gemini-2.0-flash-exp:free",
|
||||||
"messages": [
|
"messages": [
|
||||||
{
|
{
|
||||||
"role": "user",
|
"role": "user",
|
||||||
|
1
main.go
1
main.go
@ -47,6 +47,7 @@ func ListenToRequests(port string) *http.Server {
|
|||||||
mux.HandleFunc("GET /word/show-color", handlers.HandleShowColor)
|
mux.HandleFunc("GET /word/show-color", handlers.HandleShowColor)
|
||||||
mux.HandleFunc("POST /check/name", handlers.HandleNameCheck)
|
mux.HandleFunc("POST /check/name", handlers.HandleNameCheck)
|
||||||
mux.HandleFunc("GET /add-bot", handlers.HandleAddBot)
|
mux.HandleFunc("GET /add-bot", handlers.HandleAddBot)
|
||||||
|
mux.HandleFunc("GET /remove-bot", handlers.HandleRemoveBot)
|
||||||
// special
|
// special
|
||||||
mux.HandleFunc("GET /renotify-bot", handlers.HandleRenotifyBot)
|
mux.HandleFunc("GET /renotify-bot", handlers.HandleRenotifyBot)
|
||||||
// sse
|
// sse
|
||||||
|
@ -97,6 +97,16 @@ type Room struct {
|
|||||||
LogJournal []string
|
LogJournal []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindBotByTeamRole returns bot name if found; otherwise empty string
|
||||||
|
func (r *Room) FindBotByTeamRole(team, role string) string {
|
||||||
|
for bn, b := range r.BotMap {
|
||||||
|
if b.Role == StrToUserRole(role) && b.Team == StrToUserTeam(team) {
|
||||||
|
return bn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Room) FetchLastClue() (*Action, error) {
|
func (r *Room) FetchLastClue() (*Action, error) {
|
||||||
for i := len(r.ActionHistory) - 1; i >= 0; i-- {
|
for i := len(r.ActionHistory) - 1; i >= 0; i-- {
|
||||||
if r.ActionHistory[i].Action == string(ActionTypeClue) {
|
if r.ActionHistory[i].Action == string(ActionTypeClue) {
|
||||||
|
1
todos.md
1
todos.md
@ -18,6 +18,7 @@
|
|||||||
- clear indication that model (llm) is thinking / answered;
|
- clear indication that model (llm) is thinking / answered;
|
||||||
- instead of guessing all words at ones, ask only for 1 word to be open.
|
- instead of guessing all words at ones, ask only for 1 word to be open.
|
||||||
- ways to remove bots from teams;
|
- ways to remove bots from teams;
|
||||||
|
- check if clue word is the same as one of the cards and return err if it is; +
|
||||||
|
|
||||||
#### sse points
|
#### sse points
|
||||||
- clue sse update;
|
- clue sse update;
|
||||||
|
Reference in New Issue
Block a user