Compare commits

..

2 Commits

Author SHA1 Message Date
Grail Finder
3cb43d5129 Fix: exit from room deletes player 2025-07-11 13:02:44 +03:00
Grail Finder
566d645230 Enha: avoid replacing div that connects to sse 2025-07-11 12:43:04 +03:00
10 changed files with 41 additions and 27 deletions

View File

@@ -13,7 +13,9 @@
</head> </head>
<body> <body>
<div id="ancestor" hx-ext="sse" sse-connect="/sub/sse"> <div id="ancestor" hx-ext="sse" sse-connect="/sub/sse">
<div id="main-content">
{{template "main" .}} {{template "main" .}}
</div>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -4,7 +4,7 @@
Create a room <br/> Create a room <br/>
or<br/> or<br/>
<button button class="justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" hx-get="/room/hideform" hx-target=".create-room-div" >Hide Form</button> <button button class="justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" hx-get="/room/hideform" hx-target=".create-room-div" >Hide Form</button>
<form hx-post="/room-create" hx-target="#ancestor"> <form hx-post="/room-create" hx-target="#main-content">
<label For="game_time">Turn Seconds:</label><br/> <label For="game_time">Turn Seconds:</label><br/>
<input type="number" id="game_time" name="game_time" class="text-center text-white" value="300"/><br/> <input type="number" id="game_time" name="game_time" class="text-center text-white" value="300"/><br/>
<label For="language">Language:</label><br/> <label For="language">Language:</label><br/>
@@ -14,7 +14,7 @@
<option value="ru">Russian</option> <option value="ru">Russian</option>
</select> </select>
</div> </div>
<label For="password">Password:</label><br/> <label For="room_pass">Password:</label><br/>
<input type="text" id="password" name="room_pass" class="text-center text-white" value="" placeholder="Leave empty for open room"/><br/> <input type="text" id="password" name="room_pass" class="text-center text-white" value="" placeholder="Leave empty for open room"/><br/>
<button button class="justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" type="submit" >Create Room</button> <button button class="justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" type="submit" >Create Room</button>
</form> </form>

View File

@@ -1,7 +1,7 @@
{{define "linklogin"}} {{define "linklogin"}}
<div id="logindiv"> <div id="logindiv">
You're about to join room#{{.}}; but first! You're about to join room#{{.}}; but first!
<form class="space-y-6" hx-post="/login" hx-target="#ancestor"> <form class="space-y-6" hx-post="/login" hx-target="#main-content">
<label For="username" class="block text-sm font-medium leading-6 text-white-900">tell us your username</label> <label For="username" class="block text-sm font-medium leading-6 text-white-900">tell us your username</label>
<div class="mt-2"> <div class="mt-2">
<input id="username" name="username" hx-target="#login_notice" hx-swap="outerHTML" hx-post="/check/name" hx-trigger="input changed delay:400ms" autocomplete="username" required class="block w-full rounded-md border-0 bg-white py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6 text-center"/> <input id="username" name="username" hx-target="#login_notice" hx-swap="outerHTML" hx-post="/check/name" hx-trigger="input changed delay:400ms" autocomplete="username" required class="block w-full rounded-md border-0 bg-white py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6 text-center"/>

View File

@@ -1,6 +1,6 @@
{{define "login"}} {{define "login"}}
<div id="logindiv"> <div id="logindiv">
<form class="space-y-6" hx-post="/login" hx-target="#ancestor"> <form class="space-y-6" hx-post="/login" hx-target="#main-content">
<div> <div>
<label For="username" class="block text-sm font-medium leading-6 text-white-900">tell us your username (signup|login)</label> <label For="username" class="block text-sm font-medium leading-6 text-white-900">tell us your username (signup|login)</label>
<div class="mt-2"> <div class="mt-2">

View File

@@ -80,7 +80,7 @@
</div> </div>
{{if not .Room.IsRunning}} {{if not .Room.IsRunning}}
<div id="exitbtn"> <div id="exitbtn">
<button button id="exit-room-btn" type="submit" class="justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" hx-get="/room/exit" hx-target="#ancestor">Exit Room</button> <button button id="exit-room-btn" type="submit" class="justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" hx-get="/room/exit" hx-target="#main-content">Exit Room</button>
</div> </div>
{{end}} {{end}}
</div> </div>

View File

@@ -1,7 +1,7 @@
{{define "roomlist"}} {{define "roomlist"}}
<div id="roomlist" hx-get="/" hx-trigger="sse:roomlistupdate" hx-target="#ancestor"> <div id="roomlist" hx-get="/" hx-trigger="sse:roomlistupdate" hx-target="#main-content">
{{range .}} {{range .}}
<div hx-get="/room-join?id={{.ID}}" hx-target="#ancestor" class="room-item mb-3 p-4 border rounded-lg hover:bg-gray-50 transition-colors"> <div hx-get="/room-join?id={{.ID}}" hx-target="#main-content" class="room-item mb-3 p-4 border rounded-lg hover:bg-gray-50 transition-colors">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<div class="room-info"> <div class="room-info">
<div class="text-sm text-gray-500"> <div class="text-sm text-gray-500">

View File

@@ -12,7 +12,7 @@
<link rel="icon" sizes="64x64" href="/assets/favicon/wolfhead_negated.ico"/> <link rel="icon" sizes="64x64" href="/assets/favicon/wolfhead_negated.ico"/>
</head> </head>
<body> <body>
<div id="ancestor"> <div id="main-content">
<div class="container mx-auto p-4"> <div class="container mx-auto p-4">
<h1 class="text-2xl font-bold mb-4">Player Leaderboard</h1> <h1 class="text-2xl font-bold mb-4">Player Leaderboard</h1>
<div class="mb-4"> <div class="mb-4">

View File

@@ -2,7 +2,7 @@
<div class="space-y-4"> <div class="space-y-4">
<div> <div>
<h2 class="text-xl mb-4">Join Blue Team</h2> <h2 class="text-xl mb-4">Join Blue Team</h2>
<form hx-post="/join-team" hx-target="#ancestor"> <form hx-post="/join-team" hx-target="#main-content">
<input type="hidden" name="team" value="blue"> <input type="hidden" name="team" value="blue">
<div class="mb-1"> <div class="mb-1">
{{if and (eq .State.Role "guesser") (eq .State.Team "blue")}} {{if and (eq .State.Role "guesser") (eq .State.Team "blue")}}
@@ -23,7 +23,7 @@
</div> </div>
<div> <div>
<h2 class="text-xl mb-4">Join Red Team</h2> <h2 class="text-xl mb-4">Join Red Team</h2>
<form hx-post="/join-team" hx-target="#ancestor"> <form hx-post="/join-team" hx-target="#main-content">
<input type="hidden" name="team" value="red"> <input type="hidden" name="team" value="red">
<div class="mb-1"> <div class="mb-1">
{{if and (eq .State.Role "guesser") (eq .State.Team "red")}} {{if and (eq .State.Role "guesser") (eq .State.Team "red")}}

View File

@@ -83,27 +83,39 @@ func HandleExit(w http.ResponseWriter, r *http.Request) {
abortWithError(w, "cannot leave when game is running") abortWithError(w, "cannot leave when game is running")
return return
} }
var creatorLeft bool // if creator leaves, remove all players from room and delete room
if fi.Room.CreatorName == fi.State.Username { if fi.Room.CreatorName == fi.State.Username {
creatorLeft = true players, err := repo.PlayerListByRoom(r.Context(), fi.Room.ID)
} if err != nil {
exitedRoom := fi.ExitRoom() log.Error("failed to list players in room", "error", err)
if creatorLeft { abortWithError(w, err.Error())
if err := repo.RoomDeleteByID(r.Context(), exitedRoom.ID); err != nil { return
}
for _, p := range players {
if p.IsBot {
if err := repo.PlayerDelete(r.Context(), p.Username); err != nil {
log.Error("failed to delete bot", "error", err)
}
continue
}
if err := repo.PlayerExitRoom(r.Context(), p.Username); err != nil {
log.Error("failed to exit room", "error", err)
}
}
if err := repo.RoomDeleteByID(r.Context(), fi.Room.ID); err != nil {
log.Error("failed to remove room", "error", err) log.Error("failed to remove room", "error", err)
} }
notify(models.NotifyRoomListUpdate, "") notify(models.NotifyRoomListUpdate, "")
} else {
// if regular player leaves, just exit room
if err := repo.PlayerExitRoom(r.Context(), fi.State.Username); err != nil {
log.Error("failed to exit room", "error", err)
abortWithError(w, err.Error())
return
}
} }
if err := repo.PlayerExitRoom(r.Context(), fi.State.Username); err != nil { fi.Room = nil
log.Error("failed to exit room", "error", err) fi.State.RoomID = nil
abortWithError(w, err.Error())
return
}
if err := repo.RoomUpdate(r.Context(), exitedRoom); err != nil {
log.Error("failed to update room", "error", err)
abortWithError(w, err.Error())
return
}
fi.List, err = repo.RoomList(r.Context()) fi.List, err = repo.RoomList(r.Context())
if err != nil { if err != nil {
abortWithError(w, err.Error()) abortWithError(w, err.Error())

View File

@@ -90,4 +90,4 @@
- there is a problem of two timers, they both could switch turn, but it is not easy to stop them from llmapi or handlers. + - there is a problem of two timers, they both could switch turn, but it is not easy to stop them from llmapi or handlers. +
- journal still does not work; + - journal still does not work; +
- lose/win game; then exit room (while being the creator), then press to stats -> cannot find session in db, although cookie in place and session in db; - lose/win game; then exit room (while being the creator), then press to stats -> cannot find session in db, although cookie in place and session in db;
- player got deleted from db; - exit endpoints delets player from db;