Enha: sse update on actions
This commit is contained in:
@ -41,7 +41,7 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id=ancestor>
|
<div id="ancestor" hx-ext="sse" sse-connect="/sub/sse">
|
||||||
{{template "main" .}}
|
{{template "main" .}}
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
color: white;
|
color: white;
|
||||||
text-shadow: 0 2px 4px rgba(0,0,0,0.8);
|
text-shadow: 0 2px 4px rgba(0,0,0,0.8);
|
||||||
cursor: pointer;"
|
cursor: pointer;"
|
||||||
hx-get="/word/show-color?word={{.Word}}" hx-trigger="click" hx-swap="outerHTML transition:true swap:.1s">
|
hx-get="/word/show-color?word={{.Word}}" hx-trigger="click" hx-swap="outerHTML transition:true swap:.05s">
|
||||||
{{.Word}}
|
{{.Word}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
{{define "main"}}
|
{{define "main"}}
|
||||||
<div hx-ext="sse" sse-connect="/sub/sse" sse-swap="test">
|
|
||||||
Contents of this box will be updated in real time
|
|
||||||
with every SSE message received from the chatroom.
|
|
||||||
</div>
|
|
||||||
<!-- user has no username -> login form -->
|
<!-- user has no username -> login form -->
|
||||||
{{ if not . }}
|
{{ if not . }}
|
||||||
{{template "login"}}
|
{{template "login"}}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
{{define "teamlist"}}
|
{{define "teamlist"}}
|
||||||
<div class="playerlist border border-gray-300 rounded mb-2">
|
<div class="playerlist border border-gray-300 text-{{.Color}}-500 rounded mb-2">
|
||||||
<p class=border>Guessers</p>
|
<p class=border>Guessers</p>
|
||||||
{{range .Guessers}}
|
{{range .Guessers}}
|
||||||
<p>{{.}}</p>
|
<p>{{.}}</p>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<div class="playerlist border border-gray-300 rounded mb-2">
|
<div class="playerlist border border-gray-300 rounded mb-2 text-{{.Color}}-700">
|
||||||
<p class=border>Mime</p>
|
<p class=border>Mime</p>
|
||||||
<p>{{.Mime}}</p>
|
<p>{{.Mime}}</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{{define "room"}}
|
{{define "room"}}
|
||||||
<div id="hello-user">
|
<div id="interier" hx-get="/" hx-trigger="sse:roomupdate_{{.State.RoomID}}">
|
||||||
|
<div id="meta">
|
||||||
<p>Hello {{.State.Username}};</p>
|
<p>Hello {{.State.Username}};</p>
|
||||||
<p>Room created by {{.Room.CreatorName}};</p>
|
<p>Room created by {{.Room.CreatorName}};</p>
|
||||||
<p>Game is running: {{.Room.IsRunning}}</p>
|
<p>Game is running: {{.Room.IsRunning}}</p>
|
||||||
@ -8,37 +9,38 @@
|
|||||||
<button hx-get="/start-game" hx-target="#room" class="bg-amber-100 text-black px-4 py-2 rounded">Start Game</button>
|
<button hx-get="/start-game" hx-target="#room" class="bg-amber-100 text-black px-4 py-2 rounded">Start Game</button>
|
||||||
{{end}}
|
{{end}}
|
||||||
</p>
|
</p>
|
||||||
<p>Turn of the {{.Room.TeamTurn}} team</p>
|
<p>Turn of the <span class="text-{{.Room.TeamTurn}}-500">{{.Room.TeamTurn}}</span> team</p>
|
||||||
<p>
|
<p>
|
||||||
{{if eq .State.Team ""}}
|
{{if eq .State.Team ""}}
|
||||||
join the team!
|
join the team!
|
||||||
{{else}}
|
{{else}}
|
||||||
you're on the team {{.State.Team}}!
|
you're on the team <span class="text-{{.State.Team}}-500">{{.State.Team}}</span>!
|
||||||
{{end}}
|
{{end}}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<!-- Left Panel -->
|
<!-- Left Panel -->
|
||||||
{{template "teamlist" .Room.BlueTeam}}
|
{{template "teamlist" .Room.BlueTeam}}
|
||||||
{{if ne .State.Team "blue"}}
|
{{if and (ne .State.Team "blue") (not .Room.IsRunning)}}
|
||||||
{{template "teampew" "blue"}}
|
{{template "teampew" "blue"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
<!-- Right Panel -->
|
<!-- Right Panel -->
|
||||||
{{if ne .State.Team "red"}}
|
{{if and (ne .State.Team "red") (not .Room.IsRunning)}}
|
||||||
{{template "teampew" "red"}}
|
{{template "teampew" "red"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{template "teamlist" .Room.RedTeam}}
|
{{template "teamlist" .Room.RedTeam}}
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<div id="cardtable">
|
<div id="cardtable">
|
||||||
{{template "cardtable" .Room}}
|
{{template "cardtable" .Room}}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{{if eq .State.Role "guesser"}}
|
{{if and (eq .State.Role "guesser") (eq .State.Team .Room.TeamTurn)}}
|
||||||
<button hx-get="/end-turn" hx-target="#room" class="bg-amber-100 text-black px-4 py-2 rounded">End Turn</button>
|
<button hx-get="/end-turn" hx-target="#room" class="bg-amber-100 text-black px-4 py-2 rounded">End Turn</button>
|
||||||
{{else if eq .State.Role "mime"}}
|
{{else if eq .State.Role "mime"}}
|
||||||
{{template "mimeclue"}}
|
{{template "mimeclue"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"golias/broker"
|
||||||
"golias/models"
|
"golias/models"
|
||||||
"golias/utils"
|
"golias/utils"
|
||||||
"strings"
|
"strings"
|
||||||
@ -168,6 +169,7 @@ func joinTeam(ctx context.Context, role, team string) (*models.FullInfo, error)
|
|||||||
return fi, err
|
return fi, err
|
||||||
}
|
}
|
||||||
fi.Room.BlueTeam.Mime = fi.State.Username
|
fi.Room.BlueTeam.Mime = fi.State.Username
|
||||||
|
fi.Room.BlueTeam.Color = "blue"
|
||||||
fi.State.Team = "blue"
|
fi.State.Team = "blue"
|
||||||
fi.State.Role = "mime"
|
fi.State.Role = "mime"
|
||||||
if fi.Room.RedTeam.Mime == fi.State.Username {
|
if fi.Room.RedTeam.Mime == fi.State.Username {
|
||||||
@ -180,6 +182,7 @@ func joinTeam(ctx context.Context, role, team string) (*models.FullInfo, error)
|
|||||||
return fi, err
|
return fi, err
|
||||||
}
|
}
|
||||||
fi.Room.RedTeam.Mime = fi.State.Username
|
fi.Room.RedTeam.Mime = fi.State.Username
|
||||||
|
fi.Room.RedTeam.Color = "red"
|
||||||
fi.State.Team = "red"
|
fi.State.Team = "red"
|
||||||
fi.State.Role = "mime"
|
fi.State.Role = "mime"
|
||||||
if fi.Room.BlueTeam.Mime == fi.State.Username {
|
if fi.Room.BlueTeam.Mime == fi.State.Username {
|
||||||
@ -192,10 +195,12 @@ func joinTeam(ctx context.Context, role, team string) (*models.FullInfo, error)
|
|||||||
} else if role == "guesser" {
|
} else if role == "guesser" {
|
||||||
if team == "blue" {
|
if team == "blue" {
|
||||||
fi.Room.BlueTeam.Guessers = append(fi.Room.BlueTeam.Guessers, fi.State.Username)
|
fi.Room.BlueTeam.Guessers = append(fi.Room.BlueTeam.Guessers, fi.State.Username)
|
||||||
|
fi.Room.BlueTeam.Color = "blue"
|
||||||
fi.State.Team = "blue"
|
fi.State.Team = "blue"
|
||||||
fi.State.Role = "guesser"
|
fi.State.Role = "guesser"
|
||||||
} else if team == "red" {
|
} else if team == "red" {
|
||||||
fi.Room.RedTeam.Guessers = append(fi.Room.RedTeam.Guessers, fi.State.Username)
|
fi.Room.RedTeam.Guessers = append(fi.Room.RedTeam.Guessers, fi.State.Username)
|
||||||
|
fi.Room.RedTeam.Color = "red"
|
||||||
fi.State.Team = "red"
|
fi.State.Team = "red"
|
||||||
fi.State.Role = "guesser"
|
fi.State.Role = "guesser"
|
||||||
} else {
|
} else {
|
||||||
@ -232,3 +237,10 @@ func listPublicRooms() []*models.Room {
|
|||||||
}
|
}
|
||||||
return publicRooms
|
return publicRooms
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func notify(event, msg string) {
|
||||||
|
Notifier.Notifier <- broker.NotificationEvent{
|
||||||
|
EventName: event,
|
||||||
|
Payload: msg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -35,24 +35,23 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) {
|
|||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
session, ok := ctx.Value(models.CtxSessionKey).(*models.Session)
|
fi, err := getFullInfoByCtx(ctx)
|
||||||
if !ok {
|
|
||||||
// trying to get color without a session -> error
|
|
||||||
http.Redirect(w, r, "/", 302)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
state, err := loadState(session.Username)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO: whos move it is?
|
if fi.State.Role != "guesser" {
|
||||||
if state.Role != "guesser" {
|
|
||||||
err = errors.New("need to guesser to open the card")
|
err = errors.New("need to guesser to open the card")
|
||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Debug("got state", "state", state)
|
// whos move it is?
|
||||||
|
if fi.State.Team != models.UserTeam(fi.Room.TeamTurn) {
|
||||||
|
err = errors.New("not your team's move")
|
||||||
|
abortWithError(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Debug("got state", "state", fi)
|
||||||
// TODO: update room score
|
// TODO: update room score
|
||||||
color, exists := roundWords[word]
|
color, exists := roundWords[word]
|
||||||
log.Debug("got show-color request", "word", word, "color", color)
|
log.Debug("got show-color request", "word", word, "color", color)
|
||||||
@ -65,5 +64,11 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) {
|
|||||||
Color: models.StrToWordColor(color),
|
Color: models.StrToWordColor(color),
|
||||||
Revealed: true,
|
Revealed: true,
|
||||||
}
|
}
|
||||||
|
fi.Room.RevealSpecificWord(word)
|
||||||
|
if err := saveFullInfo(fi); err != nil {
|
||||||
|
abortWithError(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
||||||
tmpl.ExecuteTemplate(w, "cardword", cardword)
|
tmpl.ExecuteTemplate(w, "cardword", cardword)
|
||||||
}
|
}
|
||||||
|
@ -149,6 +149,7 @@ func HandleJoinTeam(w http.ResponseWriter, r *http.Request) {
|
|||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
||||||
tmpl.ExecuteTemplate(w, "base", fi)
|
tmpl.ExecuteTemplate(w, "base", fi)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,6 +177,7 @@ func HandleEndTurn(w http.ResponseWriter, r *http.Request) {
|
|||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
||||||
tmpl.ExecuteTemplate(w, "base", fi)
|
tmpl.ExecuteTemplate(w, "base", fi)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,6 +206,8 @@ func HandleStartGame(w http.ResponseWriter, r *http.Request) {
|
|||||||
abortWithError(w, err.Error())
|
abortWithError(w, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// to update only the room that should be updated
|
||||||
|
notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "")
|
||||||
tmpl.ExecuteTemplate(w, "room", fi)
|
tmpl.ExecuteTemplate(w, "room", fi)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"golias/broker"
|
"golias/broker"
|
||||||
"golias/config"
|
"golias/config"
|
||||||
"golias/pkg/cache"
|
"golias/pkg/cache"
|
||||||
@ -9,7 +8,6 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -28,18 +26,6 @@ func init() {
|
|||||||
cfg = config.LoadConfigOrDefault("")
|
cfg = config.LoadConfigOrDefault("")
|
||||||
Notifier = broker.NewBroker()
|
Notifier = broker.NewBroker()
|
||||||
go Notifier.Listen()
|
go Notifier.Listen()
|
||||||
ticker := time.NewTicker(2 * time.Second)
|
|
||||||
go func() {
|
|
||||||
counter := 0
|
|
||||||
for {
|
|
||||||
<-ticker.C
|
|
||||||
Notifier.Notifier <- broker.NotificationEvent{
|
|
||||||
EventName: "test",
|
|
||||||
Payload: fmt.Sprintf("%v test call of notifier", counter),
|
|
||||||
}
|
|
||||||
counter++
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var roundWords = map[string]string{
|
var roundWords = map[string]string{
|
||||||
|
@ -7,4 +7,6 @@ var (
|
|||||||
// cache
|
// cache
|
||||||
CacheRoomPrefix = "room#"
|
CacheRoomPrefix = "room#"
|
||||||
CacheStatePrefix = "state-"
|
CacheStatePrefix = "state-"
|
||||||
|
// sse
|
||||||
|
NotifyRoomUpdatePrefix = "roomupdate_"
|
||||||
)
|
)
|
||||||
|
@ -34,6 +34,7 @@ func StrToWordColor(s string) WordColor {
|
|||||||
type Team struct {
|
type Team struct {
|
||||||
Guessers []string
|
Guessers []string
|
||||||
Mime string
|
Mime string
|
||||||
|
Color string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Room struct {
|
type Room struct {
|
||||||
@ -109,6 +110,14 @@ func (r *Room) RevealAllCards() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Room) RevealSpecificWord(word string) {
|
||||||
|
for i, card := range r.Cards {
|
||||||
|
if card.Word == word {
|
||||||
|
r.Cards[i].Revealed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type WordCard struct {
|
type WordCard struct {
|
||||||
Word string
|
Word string
|
||||||
Color WordColor
|
Color WordColor
|
||||||
|
@ -75,8 +75,8 @@ func MakeTestState(creatorName string) *FullInfo {
|
|||||||
{Word: "tomato", Color: "red"},
|
{Word: "tomato", Color: "red"},
|
||||||
{Word: "cloud", Color: "white"},
|
{Word: "cloud", Color: "white"},
|
||||||
}
|
}
|
||||||
redTeam := Team{Guessers: []string{"Adam", "Eve"}, Mime: "Serpent"}
|
redTeam := Team{Guessers: []string{"Adam", "Eve"}, Mime: "Serpent", Color: "red"}
|
||||||
blueTeam := Team{Guessers: []string{"Abel", "Kain"}}
|
blueTeam := Team{Guessers: []string{"Abel", "Kain"}, Color: "blue"}
|
||||||
room := &Room{
|
room := &Room{
|
||||||
ID: "test-id",
|
ID: "test-id",
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
|
Reference in New Issue
Block a user