diff options
Diffstat (limited to 'html/boss/ai-companion.html')
| -rw-r--r-- | html/boss/ai-companion.html | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/html/boss/ai-companion.html b/html/boss/ai-companion.html new file mode 100644 index 00000000..65923543 --- /dev/null +++ b/html/boss/ai-companion.html @@ -0,0 +1,184 @@ +<!doctype html> +<html> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> + <title>AI Companion</title> + + <script src="https://cdnjs.cloudflare.com/ajax/libs/eruda/3.4.1/eruda.js" integrity="sha512-3h7ROKDcr6JDuNeJM83xKEnx4cqMvii81NQ+9bSOwOTQL6AKhSmp5oVRL1R4rrM6H23CarCgDK3FIFl3ZnZEZA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> + <script>eruda.init();</script> + + <script src="../js/wasm_exec.js"></script> + + <style> +:root { + /* define applied colors */ + --bg: #fdfdfd; + --fg: #1a1a1a; +} + +@media (prefers-color-scheme: dark) { + /* change apllied colors to the dark gruvbox pallet + * https://github.com/morhetz/gruvbox + */ + :root { + --bg: #282828; /* dark bg */ + --fg: #ebdbb2; /* dark fg */ + } +} + +html { + line-height: 1.5; + font-family: Georgia, serif; + font-size: 20px; + color: var(--fg); + background-color: var(--bg); +} + +body { + margin: 0 auto; + max-width: 36em; + padding-left: 50px; + padding-right: 50px; + padding-top: 50px; + padding-bottom: 50px; + hyphens: auto; + word-wrap: break-word; + text-rendering: optimizeLegibility; + font-kerning: normal; +} + +@media (max-width: 600px) { + body { + font-size: 0.9em; + padding: 1em; + } +} +.card-remove-button { + margin: 5px; + border: solid; + border-radius: 1px; + background: gray; +} +</style> + + <datalist id="maps"> + <option value="the-kraken"></option> + <option value="the-tyrant"></option> + </datalist> + <datalist id="cards"> + %CARDS% + </datalist> + + <script> + if (!WebAssembly.instantiateStreaming) { // polyfill + WebAssembly.instantiateStreaming = async (resp, importObject) => { + const source = await (await resp).arrayBuffer(); + return await WebAssembly.instantiate(source, importObject); + }; + } + + const go = new Go(); + let mod, inst; + const wasm = "ai-companion.wasm" + + WebAssembly.instantiateStreaming(fetch(wasm), go.importObject).then((result) => { + mod = result.module; + inst = result.instance; + document.getElementById("runButton").disabled = false; + }).catch((err) => { + console.error(err); + }); + + var cards = {}; + for (const opt of document.getElementById("cards").options) { + cards[opt.value] = true; + } + + var players = {}; + + var ebitenArgs; + async function run() { + const map = document.getElementById("mapInput").value; + // global value retrieved by the go wasm + ebitenArgs = JSON.stringify({mapName: map, players: players.values}); + await go.run(inst); + inst = await WebAssembly.instantiate(mod, go.importObject); // reset instance + } + + function addCard(cardInput) { + const card = cardInput.value; + if (!cards[card]) return; + let playerDisplay = cardInput.parentNode; + const playerName = playerDisplay.id.slice(0, -4); + let player = players[playerName]; + let pcards = player.cards; + + console.log(playerName + " " + card); + pcards.push(card); + const cardIdx = pcards.length; + + let cardElem = document.createElement("div"); + cardElem.appendChild(document.createTextNode(card)); + let rmvBtn = document.createElement("span"); + rmvBtn.innerHTML = "x"; + rmvBtn.onclick = function() { + pcards.splice(cardIdx, 1); + playerDisplay.removeChild(cardElem); + }; + rmvBtn.classList.add("card-remove-button"); + cardElem.appendChild(rmvBtn); + playerDisplay.appendChild(cardElem); + } + + function addPlayer() { + let nameInput = document.getElementById("playerName"); + const name = nameInput.value; + players[name] = {name: name, cards: []} + + nameInput.value = ""; + + let player = document.createElement("div"); + player.id = name; + player.innerHTML = `${name} +<div id="${name}Deck"> +<input list="cards" oninput="addCard(this)"> +</input> +</div>`; + document.getElementById("players").appendChild(player); + } + + function prefillInputsFromUrl() { + const queryParams = window.location.search.substring(1).split("?"); + for (const param of queryParams) { + let parts = param.split("=") + let key = parts[0] + let value = parts[1] + + let input = document.getElementById(key); + if (input) { + input.value = value; + } + } + } +window.onload = function() { + prefillInputsFromUrl(); +} + </script> +</head> + +<body> + <h1>AI Companion</h1> + <label for="mapInput">Map:</label> + <input autocomplete="on" id="mapInput" list="maps"></input> + <br> + + <label for="playerName">Player name:</label> + <input id="playerName"></input> + <button onclick="addPlayer()">add</button> + + <div id="players"></div> + + <button onClick="run();" id="runButton" disabled>Run</button> +</body> +</html> |
