summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorEwy <ewy@ewy.one>2026-09-18 15:06:59 +0200
committerEwy <ewy@ewy.one>2026-09-18 15:06:59 +0200
commit1f8364b145dbd0ff9ff7583f50aeb7498967b0f9 (patch)
treecf09f5b2151f1d37327831c00148f8431b527e70 /server
parentb82e6069c9dc93eff6e539a8cccd73e69ecde38e (diff)
add more stuff
Diffstat (limited to 'server')
-rw-r--r--server/server.go21
-rw-r--r--server/web/game/game.js39
-rw-r--r--server/web/game/index.html40
-rw-r--r--server/web/game/style.css3
-rw-r--r--server/web/home.js18
-rw-r--r--server/web/index.gohtml26
-rw-r--r--server/web/index.html19
-rw-r--r--server/web/style.css16
8 files changed, 143 insertions, 39 deletions
diff --git a/server/server.go b/server/server.go
index 798bab6..af8393d 100644
--- a/server/server.go
+++ b/server/server.go
@@ -3,28 +3,30 @@ package server
import (
"embed"
"fmt"
- "github.com/spf13/pflag"
- "html/template"
+ "io/fs"
"net"
"net/http"
"sakura/cfg"
"sakura/server/api"
"strconv"
+
+ "github.com/spf13/pflag"
)
//go:embed web
var web embed.FS
-var tmpl *template.Template
-
func Start() {
pflag.Parse()
fmt.Println("Server started")
addr := net.JoinHostPort(*cfg.Host, strconv.Itoa(*cfg.Port))
fmt.Printf("Listening on %s\n", addr)
var err error
- tmpl, err = template.ParseFS(web, "web/**.gohtml")
- http.HandleFunc("/{$}", serveHome)
+ if err != nil {
+ panic(err)
+ }
+ sub, err := fs.Sub(web, "web")
+ http.Handle("/", http.FileServer(http.FS(sub)))
http.HandleFunc(cfg.CreateMethod+" "+cfg.CreatePath, api.GameCreate)
http.HandleFunc(cfg.ConnectMethod+" "+cfg.ConnectPath, api.GameConnect)
err = http.ListenAndServe(addr, nil)
@@ -32,10 +34,3 @@ func Start() {
panic(err)
}
}
-
-func serveHome(w http.ResponseWriter, r *http.Request) {
- err := tmpl.ExecuteTemplate(w, "index.gohtml", nil)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- }
-}
diff --git a/server/web/game/game.js b/server/web/game/game.js
new file mode 100644
index 0000000..5e71786
--- /dev/null
+++ b/server/web/game/game.js
@@ -0,0 +1,39 @@
+"use strict"
+const showGame = (g) => {
+ const tmpl = document.querySelector("template#tmpl")
+ const disp = document.querySelector("#game")
+ const clone = document.importNode(tmpl.content, true)
+ doDistance(clone, g.Distance.Value)
+ disp.replaceChildren(clone)
+};
+
+const doDistance = (clone, value) => {
+ clone.querySelector(".distance").setAttribute("data-value", value);
+ [...clone.querySelectorAll(".distance .sakura")].map((n, i) => {
+ if (i < value) {
+ n.checked = true
+ } else {
+ n.checked = false
+ }
+ })
+
+}
+
+const connect = (gameId) => {
+ const connection = new WebSocket(`/api/game/${gameId}/connect`);
+ window.socket = connection;
+ connection.addEventListener("message", (ev) => {
+ const game = JSON.parse(ev.data);
+ console.debug(game);
+ showGame(game);
+ document.querySelector("#game-json").innerText =
+ JSON.stringify(ev.data, null, 2);
+ });
+}
+
+const init = () => {
+ const id = window.location.hash.slice(1)
+ connect(id)
+}
+
+init()
diff --git a/server/web/game/index.html b/server/web/game/index.html
new file mode 100644
index 0000000..414ff5c
--- /dev/null
+++ b/server/web/game/index.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta
+ name="viewport"
+ content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
+ />
+ <meta http-equiv="X-UA-Compatible" content="ie=edge" />
+ <title>sakura | game</title>
+ <link rel="stylesheet" type="text/css" href="/style.css" />
+ <link rel="stylesheet" type="text/css" href="/game/style.css" />
+ </head>
+ <body>
+ <header>
+ <details>
+ <summary>Game state</summary>
+ <pre id="game-json"></pre>
+ </details>
+ </header>
+ <main id="game"></main>
+
+ <template id="tmpl">
+ <div class="distance">
+ <input type="checkbox" class="sakura" />
+ <input type="checkbox" class="sakura" />
+ <input type="checkbox" class="sakura" />
+ <input type="checkbox" class="sakura" />
+ <input type="checkbox" class="sakura" />
+ <input type="checkbox" class="sakura" />
+ <input type="checkbox" class="sakura" />
+ <input type="checkbox" class="sakura" />
+ <input type="checkbox" class="sakura" />
+ <input type="checkbox" class="sakura" />
+ </div>
+ </template>
+
+ <script src="/game/game.js"></script>
+ </body>
+</html>
diff --git a/server/web/game/style.css b/server/web/game/style.css
new file mode 100644
index 0000000..dd0e421
--- /dev/null
+++ b/server/web/game/style.css
@@ -0,0 +1,3 @@
+.hidden {
+ display: none;
+}
diff --git a/server/web/home.js b/server/web/home.js
new file mode 100644
index 0000000..766f246
--- /dev/null
+++ b/server/web/home.js
@@ -0,0 +1,18 @@
+"use strict"
+
+const createGameFromUi = async () => {
+ const g = await newGame()
+ redirect(g)
+}
+
+const newGame = async () => {
+ const game = await fetch("/api/game/create", {
+ method: "POST",
+ });
+ const gameId = await game.text();
+ return gameId
+};
+
+const redirect = (id) => {
+ window.location.assign(`/game/#${id}`)
+}
diff --git a/server/web/index.gohtml b/server/web/index.gohtml
deleted file mode 100644
index d7a90b4..0000000
--- a/server/web/index.gohtml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!doctype html>
-<html lang="en">
-<head>
- <meta charset="UTF-8">
- <meta name="viewport"
- content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>Document</title>
-</head>
-<body>
-
-<script>
- const start = async () => {
- const game = await fetch("/api/game/create", {
- method: "POST",
- })
- const gameId = await game.text()
- const connection = new WebSocket(`/api/game/${gameId}/connect`)
- connection.addEventListener("message", (ev) => {
- console.debug(JSON.parse(ev.data))
- })
- }
- start()
-</script>
-</body>
-</html> \ No newline at end of file
diff --git a/server/web/index.html b/server/web/index.html
new file mode 100644
index 0000000..fda0309
--- /dev/null
+++ b/server/web/index.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta
+ name="viewport"
+ content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
+ />
+ <meta http-equiv="X-UA-Compatible" content="ie=edge" />
+ <title>sakura | home</title>
+ <link rel="stylesheet" type="text/css" href="/style.css" />
+ <script src="/home.js"></script>
+ </head>
+ <body>
+ <main>
+ <button type="button" onclick="createGameFromUi()" action="#game-created">Create and join new game</button>
+ </main>
+ </body>
+</html>
diff --git a/server/web/style.css b/server/web/style.css
new file mode 100644
index 0000000..0053142
--- /dev/null
+++ b/server/web/style.css
@@ -0,0 +1,16 @@
+@import "https://ewy.one/terminal.css";
+
+.sakura {
+ min-width: 32px;
+ min-height: 32px;
+ background-color: slategray;
+ pointer-events: none;
+
+ &:not(:disabled) {
+ background-color: lightpink;
+ }
+}
+
+.distance {
+ display: flex;
+}