From 65b84ace41e7cb5de1d894f9facaca4b8a57909b Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Tue, 7 Jun 2022 01:42:05 +0200 Subject: Zap semicolons. --- public/common/play.js | 836 +++++++++++++++++++++++++------------------------- public/sort.js | 101 +++--- 2 files changed, 476 insertions(+), 461 deletions(-) (limited to 'public') diff --git a/public/common/play.js b/public/common/play.js index 80ead70..1df4708 100644 --- a/public/common/play.js +++ b/public/common/play.js @@ -1,18 +1,18 @@ -"use strict"; +"use strict" // TODO: Remove when CSS Images Module Level 4 is widely supported, -(function () { - let avif = new Image(); - avif.src = "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUEAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAABkAAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAEAAAABAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgSAAAAAAABNjb2xybmNseAABAA0ABoAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACFtZGF0EgAKBzgABhAQ0GkyDBZABhhhhAAAeUzRyg=="; - avif.onload = () => document.documentElement.className = "avif"; - avif.onerror = () => document.documentElement.className = "jpeg"; -})(); +;(function () { + let avif = new Image() + avif.src = "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUEAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAABkAAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAEAAAABAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgSAAAAAAABNjb2xybmNseAABAA0ABoAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACFtZGF0EgAKBzgABhAQ0GkyDBZABhhhhAAAeUzRyg==" + avif.onload = () => document.documentElement.className = "avif" + avif.onerror = () => document.documentElement.className = "jpeg" +})() /* URL: /$title_id/(re)play:$game_id:$role */ if (!/\/[\w-]+\/(re)?play:\d+(:[\w-]+)?/.test(window.location.pathname)) { - document.getElementById("prompt").textContent = "Invalid game ID."; - throw Error("Invalid game ID."); + document.getElementById("prompt").textContent = "Invalid game ID." + throw Error("Invalid game ID.") } let params = { @@ -22,129 +22,129 @@ let params = { role: decodeURIComponent(window.location.pathname.split("/")[2]).split(":")[2] || "Observer", } -let roles = Array.from(document.querySelectorAll(".role")).map(x=>({id:x.id,role:x.id.replace(/^role_/,"").replace(/_/g," ")})); +let roles = Array.from(document.querySelectorAll(".role")).map(x=>({id:x.id,role:x.id.replace(/^role_/,"").replace(/_/g," ")})) -let view = null; -let player = "Observer"; -let socket = null; -let chat = null; +let view = null +let player = "Observer" +let socket = null +let chat = null function scroll_with_middle_mouse(panel_sel, multiplier) { - let panel = document.querySelector(panel_sel); - let down_x, down_y, scroll_x, scroll_y; + let panel = document.querySelector(panel_sel) + let down_x, down_y, scroll_x, scroll_y if (!multiplier) - multiplier = 1; + multiplier = 1 function md(e) { if (e.button === 1) { - down_x = e.clientX; - down_y = e.clientY; - scroll_x = panel.scrollLeft; - scroll_y = panel.scrollTop; - window.addEventListener("mousemove", mm); - window.addEventListener("mouseup", mu); - e.preventDefault(); + down_x = e.clientX + down_y = e.clientY + scroll_x = panel.scrollLeft + scroll_y = panel.scrollTop + window.addEventListener("mousemove", mm) + window.addEventListener("mouseup", mu) + e.preventDefault() } } function mm(e) { - let dx = down_x - e.clientX; - let dy = down_y - e.clientY; - panel.scrollLeft = scroll_x + dx * multiplier; - panel.scrollTop = scroll_y + dy * multiplier; - e.preventDefault(); + let dx = down_x - e.clientX + let dy = down_y - e.clientY + panel.scrollLeft = scroll_x + dx * multiplier + panel.scrollTop = scroll_y + dy * multiplier + e.preventDefault() } function mu(e) { if (e.button === 1) { - window.removeEventListener("mousemove", mm); - window.removeEventListener("mouseup", mu); - e.preventDefault(); + window.removeEventListener("mousemove", mm) + window.removeEventListener("mouseup", mu) + e.preventDefault() } } - panel.addEventListener("mousedown", md); + panel.addEventListener("mousedown", md) } function drag_element_with_mouse(element_sel, grabber_sel) { - let element = document.querySelector(element_sel); - let grabber = document.querySelector(grabber_sel) || element; - let save_x, save_y; + let element = document.querySelector(element_sel) + let grabber = document.querySelector(grabber_sel) || element + let save_x, save_y function md(e) { if (e.button === 0) { - save_x = e.clientX; - save_y = e.clientY; - window.addEventListener("mousemove", mm); - window.addEventListener("mouseup", mu); - e.preventDefault(); + save_x = e.clientX + save_y = e.clientY + window.addEventListener("mousemove", mm) + window.addEventListener("mouseup", mu) + e.preventDefault() } } function mm(e) { - let dx = save_x - e.clientX; - let dy = save_y - e.clientY; - save_x = e.clientX; - save_y = e.clientY; - element.style.left = (element.offsetLeft - dx) + "px"; - element.style.top = (element.offsetTop - dy) + "px"; - e.preventDefault(); + let dx = save_x - e.clientX + let dy = save_y - e.clientY + save_x = e.clientX + save_y = e.clientY + element.style.left = (element.offsetLeft - dx) + "px" + element.style.top = (element.offsetTop - dy) + "px" + e.preventDefault() } function mu(e) { if (e.button === 0) { - window.removeEventListener("mousemove", mm); - window.removeEventListener("mouseup", mu); - e.preventDefault(); + window.removeEventListener("mousemove", mm) + window.removeEventListener("mouseup", mu) + e.preventDefault() } } - grabber.addEventListener("mousedown", md); + grabber.addEventListener("mousedown", md) } /* TITLE BLINKER */ -let blink_title = document.title; -let blink_timer = 0; +let blink_title = document.title +let blink_timer = 0 function start_blinker(message) { - let tick = false; + let tick = false if (blink_timer) - stop_blinker(); + stop_blinker() if (!document.hasFocus()) { - document.title = message; + document.title = message blink_timer = setInterval(function () { - document.title = tick ? message : blink_title; - tick = !tick; - }, 1000); + document.title = tick ? message : blink_title + tick = !tick + }, 1000) } } function stop_blinker() { - document.title = blink_title; - clearInterval(blink_timer); - blink_timer = 0; + document.title = blink_title + clearInterval(blink_timer) + blink_timer = 0 } -window.addEventListener("focus", stop_blinker); +window.addEventListener("focus", stop_blinker) /* CHAT */ function init_chat() { // only fetch new messages when we reconnect! if (chat !== null) { - send_message("getchat", chat.log); - return; + send_message("getchat", chat.log) + return } - let chat_window = document.createElement("div"); - chat_window.id = "chat_window"; + let chat_window = document.createElement("div") + chat_window.id = "chat_window" chat_window.innerHTML = `
\u274c
Chat
- `; - document.querySelector("body").appendChild(chat_window); + ` + document.querySelector("body").appendChild(chat_window) - let chat_button = document.createElement("div"); - chat_button.id = "chat_button"; - chat_button.className = "icon_button"; - chat_button.innerHTML = ''; - chat_button.addEventListener("click", toggle_chat); - document.querySelector("#toolbar").appendChild(chat_button); + let chat_button = document.createElement("div") + chat_button.id = "chat_button" + chat_button.className = "icon_button" + chat_button.innerHTML = '' + chat_button.addEventListener("click", toggle_chat) + document.querySelector("#toolbar").appendChild(chat_button) chat = { is_visible: false, @@ -154,737 +154,737 @@ function init_chat() { log: 0 } - chat.seen = window.localStorage.getItem(chat.key) | 0; + chat.seen = window.localStorage.getItem(chat.key) | 0 - drag_element_with_mouse("#chat_window", "#chat_header"); + drag_element_with_mouse("#chat_window", "#chat_header") document.getElementById("chat_form").addEventListener("submit", e => { - let input = document.getElementById("chat_input"); - e.preventDefault(); + let input = document.getElementById("chat_input") + e.preventDefault() if (input.value) { - send_message("chat", input.value); - input.value = ""; + send_message("chat", input.value) + input.value = "" } else { - hide_chat(); + hide_chat() } - }); + }) document.querySelector("body").addEventListener("keydown", e => { if (e.key === "Escape") { if (chat.is_visible) { - e.preventDefault(); - hide_chat(); + e.preventDefault() + hide_chat() } } if (e.key === "Enter") { - let input = document.getElementById("chat_input"); + let input = document.getElementById("chat_input") if (document.activeElement !== input) { - e.preventDefault(); - show_chat(); + e.preventDefault() + show_chat() } } - }); + }) - send_message("getchat", 0); + send_message("getchat", 0) } function save_chat() { - window.localStorage.setItem(chat.key, chat.log); + window.localStorage.setItem(chat.key, chat.log) } function update_chat(chat_id, utc_date, user, message) { function format_time(date) { - let mm = date.getMinutes(); - let hh = date.getHours(); - if (mm < 10) mm = "0" + mm; - if (hh < 10) hh = "0" + hh; - return hh + ":" + mm; + let mm = date.getMinutes() + let hh = date.getHours() + if (mm < 10) mm = "0" + mm + if (hh < 10) hh = "0" + hh + return hh + ":" + mm } function add_date_line(date) { - let line = document.createElement("div"); - line.className = "date"; - line.textContent = "~ " + date + " ~"; - chat.text_element.appendChild(line); + let line = document.createElement("div") + line.className = "date" + line.textContent = "~ " + date + " ~" + chat.text_element.appendChild(line) } function add_chat_line(time, user, message) { - let line = document.createElement("div"); - line.textContent = "[" + time + "] " + user + " \xbb " + message; - chat.text_element.appendChild(line); - chat.text_element.scrollTop = chat.text_element.scrollHeight; + let line = document.createElement("div") + line.textContent = "[" + time + "] " + user + " \xbb " + message + chat.text_element.appendChild(line) + chat.text_element.scrollTop = chat.text_element.scrollHeight } if (chat_id > chat.log) { - chat.log = chat_id; - let date = new Date(utc_date + "Z"); - let day = date.toDateString(); + chat.log = chat_id + let date = new Date(utc_date + "Z") + let day = date.toDateString() if (day !== chat.last_day) { - add_date_line(day); - chat.last_day = day; + add_date_line(day) + chat.last_day = day } - add_chat_line(format_time(date), user, message); + add_chat_line(format_time(date), user, message) } if (chat_id > chat.seen) { - let button = document.getElementById("chat_button"); - start_blinker("NEW MESSAGE"); + let button = document.getElementById("chat_button") + start_blinker("NEW MESSAGE") if (!chat.is_visible) - button.classList.add("new"); + button.classList.add("new") else - save_chat(); + save_chat() } } function show_chat() { if (!chat.is_visible) { - document.getElementById("chat_button").classList.remove("new"); - document.getElementById("chat_window").classList.add("show"); - document.getElementById("chat_input").focus(); - chat.is_visible = true; - save_chat(); + document.getElementById("chat_button").classList.remove("new") + document.getElementById("chat_window").classList.add("show") + document.getElementById("chat_input").focus() + chat.is_visible = true + save_chat() } } function hide_chat() { if (chat.is_visible) { - document.getElementById("chat_window").classList.remove("show"); - document.getElementById("chat_input").blur(); - chat.is_visible = false; + document.getElementById("chat_window").classList.remove("show") + document.getElementById("chat_input").blur() + chat.is_visible = false } } function toggle_chat() { if (chat.is_visible) - hide_chat(); + hide_chat() else - show_chat(); + show_chat() } /* REMATCH BUTTON */ function remove_resign_menu() { - document.querySelectorAll(".resign").forEach(x => x.remove()); + document.querySelectorAll(".resign").forEach(x => x.remove()) } function goto_rematch() { - window.location = "/rematch/" + params.game_id + "/" + params.role; + window.location = "/rematch/" + params.game_id + "/" + params.role } function goto_replay() { - window.location = "/" + params.title_id + "/replay:" + params.game_id; + window.location = "/" + params.title_id + "/replay:" + params.game_id } function on_game_over() { function icon_button(id, img, title, fn) { if (!document.getElementById(id)) { - let button = document.createElement("div"); - button.id = id; - button.title = title; - button.className = "icon_button"; - button.innerHTML = ''; - button.addEventListener("click", fn); - document.querySelector("header").appendChild(button); + let button = document.createElement("div") + button.id = id + button.title = title + button.className = "icon_button" + button.innerHTML = '' + button.addEventListener("click", fn) + document.querySelector("header").appendChild(button) } } - icon_button("replay_button", "sherlock-holmes-mirror", "Watch replay", goto_replay); + icon_button("replay_button", "sherlock-holmes-mirror", "Watch replay", goto_replay) if (player !== "Observer") - icon_button("rematch_button", "cycle", "Propose a rematch!", goto_rematch); - remove_resign_menu(); + icon_button("rematch_button", "cycle", "Propose a rematch!", goto_rematch) + remove_resign_menu() } /* CONNECT TO GAME SERVER */ function init_player_names(players) { for (let i = 0; i < roles.length; ++i) { - let sel = "#" + roles[i].id + " .role_user"; - let p = players.find(p => p.role === roles[i].role); - document.querySelector(sel).textContent = p ? p.name : "NONE"; + let sel = "#" + roles[i].id + " .role_user" + let p = players.find(p => p.role === roles[i].role) + document.querySelector(sel).textContent = p ? p.name : "NONE" } } function send_message(cmd, arg) { - let data = JSON.stringify([cmd, arg]); - console.log("SEND %s %s", cmd, arg); - socket.send(data); + let data = JSON.stringify([cmd, arg]) + console.log("SEND %s %s", cmd, arg) + socket.send(data) } -let reconnect_count = 0; -let reconnect_max = 10; +let reconnect_count = 0 +let reconnect_max = 10 function connect_play() { if (reconnect_count >= reconnect_max) { - document.title = "DISCONNECTED"; - document.getElementById("prompt").textContent = "Disconnected."; - return; + document.title = "DISCONNECTED" + document.getElementById("prompt").textContent = "Disconnected." + return } - let protocol = (window.location.protocol === "http:") ? "ws" : "wss"; - let seen = document.getElementById("log").children.length; - let url = `${protocol}://${window.location.host}/play-socket?title=${params.title_id}&game=${params.game_id}&role=${params.role}&seen=${seen}`; + let protocol = (window.location.protocol === "http:") ? "ws" : "wss" + let seen = document.getElementById("log").children.length + let url = `${protocol}://${window.location.host}/play-socket?title=${params.title_id}&game=${params.game_id}&role=${params.role}&seen=${seen}` - console.log("CONNECTING", url); - document.getElementById("prompt").textContent = "Connecting... "; + console.log("CONNECTING", url) + document.getElementById("prompt").textContent = "Connecting... " - socket = new WebSocket(url); + socket = new WebSocket(url) window.addEventListener('beforeunload', function () { - socket.close(1000); - }); + socket.close(1000) + }) socket.onopen = function (evt) { - console.log("OPEN"); - document.querySelector("header").classList.remove("disconnected"); - reconnect_count = 0; + console.log("OPEN") + document.querySelector("header").classList.remove("disconnected") + reconnect_count = 0 } socket.onclose = function (evt) { - console.log("CLOSE %d", evt.code); + console.log("CLOSE %d", evt.code) if (evt.code === 1000 && evt.reason !== "") { - document.getElementById("prompt").textContent = "Disconnected: " + evt.reason; - document.title = "DISCONNECTED"; + document.getElementById("prompt").textContent = "Disconnected: " + evt.reason + document.title = "DISCONNECTED" } if (evt.code !== 1000) { - document.querySelector("header").classList.add("disconnected"); - document.getElementById("prompt").textContent = `Reconnecting soon... (${reconnect_count+1}/${reconnect_max})`; - let wait = 1000 * (Math.random() + 0.5) * Math.pow(2, reconnect_count++); - console.log("WAITING %.1f TO RECONNECT", wait/1000); - setTimeout(connect_play, wait); + document.querySelector("header").classList.add("disconnected") + document.getElementById("prompt").textContent = `Reconnecting soon... (${reconnect_count+1}/${reconnect_max})` + let wait = 1000 * (Math.random() + 0.5) * Math.pow(2, reconnect_count++) + console.log("WAITING %.1f TO RECONNECT", wait/1000) + setTimeout(connect_play, wait) } } socket.onmessage = function (evt) { - let [ cmd, arg ] = JSON.parse(evt.data); - console.log("MESSAGE %s", cmd); + let [ cmd, arg ] = JSON.parse(evt.data) + console.log("MESSAGE %s", cmd) switch (cmd) { case 'error': - document.getElementById("prompt").textContent = arg; - break; + document.getElementById("prompt").textContent = arg + break case 'chat': - update_chat(arg[0], arg[1], arg[2], arg[3]); - break; + update_chat(arg[0], arg[1], arg[2], arg[3]) + break case 'players': - player = arg[0]; - document.querySelector("body").classList.add(player.replace(/ /g, "_")); + player = arg[0] + document.querySelector("body").classList.add(player.replace(/ /g, "_")) if (player !== "Observer") - init_chat(); + init_chat() else - remove_resign_menu(); - init_player_names(arg[1]); - break; + remove_resign_menu() + init_player_names(arg[1]) + break case 'presence': for (let i = 0; i < roles.length; ++i) { - let elt = document.getElementById(roles[i].id); + let elt = document.getElementById(roles[i].id) if (roles[i].role in arg) - elt.classList.add("present"); + elt.classList.add("present") else - elt.classList.remove("present"); + elt.classList.remove("present") } - break; + break case 'state': - view = arg; - on_update_header(); + view = arg + on_update_header() if (typeof on_update === 'function') - on_update(); - on_update_log(); + on_update() + on_update_log() if (view.game_over) - on_game_over(); - break; + on_game_over() + break case 'reply': if (typeof on_reply === 'function') - on_reply(arg[0], arg[1]); - break; + on_reply(arg[0], arg[1]) + break case 'save': - window.localStorage[params.title_id + "/save"] = arg; - break; + window.localStorage[params.title_id + "/save"] = arg + break } } } /* HEADER */ -let is_your_turn = false; -let old_active = null; +let is_your_turn = false +let old_active = null function on_update_header() { - document.getElementById("prompt").textContent = view.prompt; + document.getElementById("prompt").textContent = view.prompt if (params.mode === "replay") - return; + return if (view.actions) { - document.querySelector("header").classList.add("your_turn"); + document.querySelector("header").classList.add("your_turn") if (!is_your_turn || old_active !== view.active) - start_blinker("YOUR TURN"); - is_your_turn = true; + start_blinker("YOUR TURN") + is_your_turn = true } else { - document.querySelector("header").classList.remove("your_turn"); - is_your_turn = false; + document.querySelector("header").classList.remove("your_turn") + is_your_turn = false } - old_active = view.active; + old_active = view.active } /* LOG */ function on_update_log() { - let div = document.getElementById("log"); - let to_delete = div.children.length - view.log_start; + let div = document.getElementById("log") + let to_delete = div.children.length - view.log_start while (to_delete-- > 0) - div.removeChild(div.lastChild); + div.removeChild(div.lastChild) for (let text of view.log) { if (typeof on_log === 'function') { - div.appendChild(on_log(text)); + div.appendChild(on_log(text)) } else { - let entry = document.createElement("div"); - entry.textContent = text; - div.appendChild(entry); + let entry = document.createElement("div") + entry.textContent = text + div.appendChild(entry) } } - scroll_log_to_end(); + scroll_log_to_end() } function scroll_log_to_end() { - let div = document.getElementById("log"); - div.scrollTop = div.scrollHeight; + let div = document.getElementById("log") + div.scrollTop = div.scrollHeight } try { - new ResizeObserver(scroll_log_to_end).observe(document.getElementById("log")); + new ResizeObserver(scroll_log_to_end).observe(document.getElementById("log")) } catch (err) { - window.addEventListener("resize", scroll_log_to_end); + window.addEventListener("resize", scroll_log_to_end) } /* MAP ZOOM */ function toggle_log() { - document.querySelector("aside").classList.toggle("hide"); - zoom_map(); + document.querySelector("aside").classList.toggle("hide") + zoom_map() } function toggle_zoom() { - let mapwrap = document.getElementById("mapwrap"); + let mapwrap = document.getElementById("mapwrap") if (mapwrap) { - mapwrap.classList.toggle("fit"); - zoom_map(); + mapwrap.classList.toggle("fit") + zoom_map() } } function zoom_map() { - let mapwrap = document.getElementById("mapwrap"); + let mapwrap = document.getElementById("mapwrap") if (mapwrap) { - let main = document.querySelector("main"); - let map = document.getElementById("map"); - map.style.transform = null; - mapwrap.style.width = null; - mapwrap.style.height = null; + let main = document.querySelector("main") + let map = document.getElementById("map") + map.style.transform = null + mapwrap.style.width = null + mapwrap.style.height = null if (mapwrap.classList.contains("fit")) { - let { width: gw, height: gh } = main.getBoundingClientRect(); - let { width: ww, height: wh } = mapwrap.getBoundingClientRect(); - let { width: cw, height: ch } = map.getBoundingClientRect(); - let scale = Math.min(ww / cw, gh / ch); + let { width: gw, height: gh } = main.getBoundingClientRect() + let { width: ww, height: wh } = mapwrap.getBoundingClientRect() + let { width: cw, height: ch } = map.getBoundingClientRect() + let scale = Math.min(ww / cw, gh / ch) if (scale < 1) { - map.style.transform = "scale(" + scale + ")"; - mapwrap.style.width = (cw * scale) + "px"; - mapwrap.style.height = (ch * scale) + "px"; + map.style.transform = "scale(" + scale + ")" + mapwrap.style.width = (cw * scale) + "px" + mapwrap.style.height = (ch * scale) + "px" } } } } -window.addEventListener("resize", zoom_map); +window.addEventListener("resize", zoom_map) window.addEventListener("keydown", (evt) => { if (evt.key === "Shift") - document.querySelector("body").classList.add("shift"); -}); + document.querySelector("body").classList.add("shift") +}) window.addEventListener("keyup", (evt) => { if (evt.key === "Shift") - document.querySelector("body").classList.remove("shift"); -}); + document.querySelector("body").classList.remove("shift") +}) /* ACTIONS */ function action_button_imp(action, label, callback) { if (params.mode === "replay") - return; - let id = action + "_button"; - let button = document.getElementById(id); + return + let id = action + "_button" + let button = document.getElementById(id) if (!button) { - button = document.createElement("button"); - button.id = id; - button.textContent = label; - button.addEventListener("click", callback); - document.getElementById("actions").appendChild(button); + button = document.createElement("button") + button.id = id + button.textContent = label + button.addEventListener("click", callback) + document.getElementById("actions").appendChild(button) } if (view.actions && action in view.actions) { - button.classList.remove("hide"); + button.classList.remove("hide") if (view.actions[action]) { if (label === undefined) - button.textContent = view.actions[action]; - button.disabled = false; + button.textContent = view.actions[action] + button.disabled = false } else { - button.disabled = true; + button.disabled = true } } else { - button.classList.add("hide"); + button.classList.add("hide") } } function action_button(action, label) { - action_button_imp(action, label, evt => send_action(action)); + action_button_imp(action, label, evt => send_action(action)) } function confirm_action_button(action, label, message) { - action_button_imp(action, label, evt => confirm_action(message, action)); + action_button_imp(action, label, evt => confirm_action(message, action)) } function send_action(verb, noun) { if (params.mode === "replay") - return; + return // Reset action list here so we don't send more than one action per server prompt! if (noun !== undefined) { - let realnoun = Array.isArray(noun) ? noun[0] : noun; + let realnoun = Array.isArray(noun) ? noun[0] : noun if (view.actions && view.actions[verb] && view.actions[verb].includes(realnoun)) { - view.actions = null; - send_message("action", [verb, noun]); - return true; + view.actions = null + send_message("action", [verb, noun]) + return true } } else { if (view.actions && view.actions[verb]) { - view.actions = null; - send_message("action", [verb]); - return true; + view.actions = null + send_message("action", [verb]) + return true } } - return false; + return false } function confirm_action(message, verb, noun) { if (window.confirm(message)) - send_action(verb, noun); + send_action(verb, noun) } -let replay_query = null; +let replay_query = null function send_query(q, param) { - if (param !== undefined) + if (param !== undefined) { if (replay_query) - replay_query(q, param); + replay_query(q, param) else - send_message("query", [q, param]); - else + send_message("query", [q, param]) + } else { if (replay_query) - replay_query(q, undefined); + replay_query(q, undefined) else - send_message("query", q); + send_message("query", q) + } } function confirm_resign() { if (window.confirm("Are you sure that you want to resign?")) - send_message("resign"); + send_message("resign") } /* MOBILE PHONE LAYOUT */ -let mobile_scroll_header = document.querySelector("header"); -let mobile_scroll_last_y = 0; +let mobile_scroll_header = document.querySelector("header") +let mobile_scroll_last_y = 0 window.addEventListener("scroll", function scroll_mobile_fix (evt) { if (mobile_scroll_header.clientWidth <= 640) { if (window.scrollY > 40) { if (mobile_scroll_last_y <= 40) - mobile_scroll_header.classList.add("mobilefix"); + mobile_scroll_header.classList.add("mobilefix") } else { if (mobile_scroll_last_y > 40) - mobile_scroll_header.classList.remove("mobilefix"); + mobile_scroll_header.classList.remove("mobilefix") } - mobile_scroll_last_y = window.scrollY; + mobile_scroll_last_y = window.scrollY } -}); +}) /* DEBUGGING */ function send_save() { - send_message("save"); + send_message("save") } function send_restore() { - send_message("restore", window.localStorage[params.title_id + "/save"]); + send_message("restore", window.localStorage[params.title_id + "/save"]) } function send_restart(scenario) { - send_message("restart", scenario); + send_message("restart", scenario) } /* REPLAY */ function adler32(data) { - let a = 1, b = 0; + let a = 1, b = 0 for (let i = 0, n = data.length; i < n; ++i) { - a = (a + data.charCodeAt(i)) % 65521; - b = (b + a) % 65521; + a = (a + data.charCodeAt(i)) % 65521 + b = (b + a) % 65521 } - return (b << 16) | a; + return (b << 16) | a } async function require(path) { - let cache = {}; + let cache = {} if (!path.endsWith(".js")) - path = path + ".js"; + path = path + ".js" if (path.startsWith("./")) - path = path.substring(2); + path = path.substring(2) - console.log("REQUIRE", path); + console.log("REQUIRE", path) - let response = await fetch(path); - let source = await response.text(); + let response = await fetch(path) + let source = await response.text() for (let [_, subpath] of source.matchAll(/require\(['"]([^)]*)['"]\)/g)) if (cache[subpath] === undefined) - cache[subpath] = await require(subpath); + cache[subpath] = await require(subpath) - let module = { exports: {} }; - Function("module", "exports", "require", source) - (module, module.exports, path => cache[path]); - return module.exports; + let module = { exports: {} } + Function("module", "exports", "require", source)(module, module.exports, path => cache[path]) + return module.exports } -let replay = null; +let replay = null async function init_replay() { - remove_resign_menu(); + remove_resign_menu() - document.getElementById("prompt").textContent = "Loading replay..."; + document.getElementById("prompt").textContent = "Loading replay..." - console.log("LOADING RULES"); - let rules = await require("rules.js"); + console.log("LOADING RULES") + let rules = await require("rules.js") - console.log("LOADING REPLAY"); - let response = await fetch("/replay/" + params.game_id); - let body = await response.json(); - replay = body.replay; + console.log("LOADING REPLAY") + let response = await fetch("/replay/" + params.game_id) + let body = await response.json() + replay = body.replay - init_player_names(body.players); + init_player_names(body.players) - let viewpoint = "Observer"; - let log_length = 0; - let p = 0; - let s = {}; + let viewpoint = "Observer" + let log_length = 0 + let p = 0 + let s = {} function eval_action(item) { switch (item.action) { case "setup": - s = rules.setup(item.arguments[0], item.arguments[1], item.arguments[2]); - break; + s = rules.setup(item.arguments[0], item.arguments[1], item.arguments[2]) + break case "resign": - s = rules.resign(s, item.role); - break; + s = rules.resign(s, item.role) + break default: - s = rules.action(s, item.role, item.action, item.arguments); - break; + s = rules.action(s, item.role, item.action, item.arguments) + break } } replay_query = function (query, params) { - let reply = rules.query(s, player, query, params); - on_reply(query, reply); + let reply = rules.query(s, player, query, params) + on_reply(query, reply) } - let ss; + let ss for (p = 0; p < replay.length; ++p) { - replay[p].arguments = JSON.parse(replay[p].arguments); + replay[p].arguments = JSON.parse(replay[p].arguments) if (rules.is_checkpoint) { - replay[p].is_checkpoint = (p > 0 && rules.is_checkpoint(ss, s)); - ss = Object.assign({}, s); + replay[p].is_checkpoint = (p > 0 && rules.is_checkpoint(ss, s)) + ss = Object.assign({}, s) } try { - eval_action(replay[p]); + eval_action(replay[p]) } catch (err) { - console.log("ERROR IN REPLAY %d %s %s/%s/%s", p, s.state, replay[p].role, replay[p].action, replay[p].arguments); - console.log(err); - replay.length = 0; - break; + console.log("ERROR IN REPLAY %d %s %s/%s/%s", p, s.state, replay[p].role, replay[p].action, replay[p].arguments) + console.log(err) + replay.length = 0 + break } - replay[p].digest = adler32(JSON.stringify(s)); + replay[p].digest = adler32(JSON.stringify(s)) for (let k = p-1; k > 0; --k) { if (replay[k].digest === replay[p].digest && !replay[k].is_undone) { for (let a = k+1; a <= p; ++a) if (!replay[a].is_undone) - replay[a].is_undone = true; - break; + replay[a].is_undone = true + break } } } - replay = replay.filter(x => !x.is_undone); + replay = replay.filter(x => !x.is_undone) function set_hash(n) { - history.replaceState(null, "", window.location.pathname + "#" + n); + history.replaceState(null, "", window.location.pathname + "#" + n) } - let timer = 0; + let timer = 0 function play_pause_replay(evt) { if (timer === 0) { - evt.target.textContent = "Stop"; + evt.target.textContent = "Stop" timer = setInterval(() => { if (p < replay.length) - goto_replay(p+1); + goto_replay(p+1) else - play_pause_replay(evt); - }, 1000); + play_pause_replay(evt) + }, 1000) } else { - evt.target.textContent = "Run"; - clearInterval(timer); - timer = 0; + evt.target.textContent = "Run" + clearInterval(timer) + timer = 0 } } function prev() { for (let i = p - 1; i > 1; --i) if (replay[i].is_checkpoint) - return i; - return 1; + return i + return 1 } function next() { for (let i = p + 1; i < replay.length; ++i) if (replay[i].is_checkpoint) - return i; - return replay.length; + return i + return replay.length } function on_hash_change() { - goto_replay(parseInt(window.location.hash.slice(1)) || 1); + goto_replay(parseInt(window.location.hash.slice(1)) || 1) } function goto_replay(np) { if (np < 1) - np = 1; + np = 1 if (np > replay.length) - np = replay.length; - set_hash(np); + np = replay.length + set_hash(np) if (p > np) - p = 0, s = {}; + p = 0, s = {} while (p < np) - eval_action(replay[p++]); - update_replay_view(); + eval_action(replay[p++]) + update_replay_view() } function update_replay_view() { - player = viewpoint; + player = viewpoint if (viewpoint === "Active") { - player = s.active; + player = s.active if (player === "All" || player === "Both" || player === "None" || !player) - player = "Observer"; + player = "Observer" } - let body = document.querySelector("body"); - body.classList.remove("Observer"); + let body = document.querySelector("body") + body.classList.remove("Observer") for (let i = 0; i < roles.length; ++i) - body.classList.remove(roles[i].role.replace(/ /g, "_")); - body.classList.add(player.replace(/ /g, "_")); + body.classList.remove(roles[i].role.replace(/ /g, "_")) + body.classList.add(player.replace(/ /g, "_")) - view = rules.view(s, player); - view.actions = null; + view = rules.view(s, player) + view.actions = null if (viewpoint === "Observer") - view.game_over = 1; + view.game_over = 1 if (s.state === "game_over") - view.game_over = 1; + view.game_over = 1 if (replay.length > 0) { if (document.querySelector("body").classList.contains("shift")) { - view.prompt = `[${p}/${replay.length}] ${s.active} / ${s.state}`; + view.prompt = `[${p}/${replay.length}] ${s.active} / ${s.state}` if (p < replay.length) - view.prompt += ` / ${replay[p].action} ${replay[p].arguments}`; + view.prompt += ` / ${replay[p].action} ${replay[p].arguments}` } else { - view.prompt = "[" + p + "/" + replay.length + "] " + view.prompt; + view.prompt = "[" + p + "/" + replay.length + "] " + view.prompt } } if (log_length < view.log.length) - view.log_start = log_length; + view.log_start = log_length else - view.log_start = view.log.length; - log_length = view.log.length; - view.log = view.log.slice(view.log_start); + view.log_start = view.log.length + log_length = view.log.length + view.log = view.log.slice(view.log_start) - on_update_header(); - on_update(); - on_update_log(); + on_update_header() + on_update() + on_update_log() } function text_button(div, txt, fn) { - let button = document.createElement("button"); - button.addEventListener("click", fn); - button.textContent = txt; - div.appendChild(button); - return button; + let button = document.createElement("button") + button.addEventListener("click", fn) + button.textContent = txt + div.appendChild(button) + return button } function set_viewpoint(vp) { - viewpoint = vp; - update_replay_view(); + viewpoint = vp + update_replay_view() } - let div = document.createElement("div"); - div.className = "replay"; + let div = document.createElement("div") + div.className = "replay" if (replay.length > 0) - text_button(div, "Active", () => set_viewpoint("Active")); + text_button(div, "Active", () => set_viewpoint("Active")) for (let r of roles) - text_button(div, r.role, () => set_viewpoint(r.role)); - text_button(div, "Observer", () => set_viewpoint("Observer")); - document.querySelector("header").appendChild(div); + text_button(div, r.role, () => set_viewpoint(r.role)) + text_button(div, "Observer", () => set_viewpoint("Observer")) + document.querySelector("header").appendChild(div) if (replay.length > 0) { - console.log("REPLAY READY"); - - div = document.createElement("div"); - div.className = "replay"; - text_button(div, "<<<", () => goto_replay(1)); - text_button(div, "<<", () => goto_replay(prev())); - text_button(div, "<\xa0", () => goto_replay(p-1)); - text_button(div, "\xa0>", () => goto_replay(p+1)); - text_button(div, ">>", () => goto_replay(next())); - text_button(div, "Run", play_pause_replay).style.width = "65px"; - document.querySelector("header").appendChild(div); + console.log("REPLAY READY") + + div = document.createElement("div") + div.className = "replay" + text_button(div, "<<<", () => goto_replay(1)) + text_button(div, "<<", () => goto_replay(prev())) + text_button(div, "<\xa0", () => goto_replay(p-1)) + text_button(div, "\xa0>", () => goto_replay(p+1)) + text_button(div, ">>", () => goto_replay(next())) + text_button(div, "Run", play_pause_replay).style.width = "65px" + document.querySelector("header").appendChild(div) if (window.location.hash === "") - set_hash(replay.length); + set_hash(replay.length) - on_hash_change(); + on_hash_change() - window.addEventListener("hashchange", on_hash_change); + window.addEventListener("hashchange", on_hash_change) } else { - console.log("REPLAY NOT AVAILABLE"); - s = JSON.parse(body.state); - update_replay_view(); + console.log("REPLAY NOT AVAILABLE") + s = JSON.parse(body.state) + update_replay_view() } } window.addEventListener("load", function () { - zoom_map(); + zoom_map() if (params.mode === "replay") - init_replay(); + init_replay() if (params.mode === "play") - connect_play(); -}); + connect_play() +}) function init_home_menu(link, text) { - let popup = document.querySelector(".menu_popup"); - let sep = document.createElement("div"); - sep.className = "menu_separator"; - popup.insertBefore(sep, popup.firstChild); - let item = document.createElement("div"); - item.className = "menu_item"; - item.onclick = () => window.open(link, "_self"); - item.textContent = text; - popup.insertBefore(item, popup.firstChild); -} - -init_home_menu("/games/active", "Go Home"); + let popup = document.querySelector(".menu_popup") + let sep = document.createElement("div") + sep.className = "menu_separator" + popup.insertBefore(sep, popup.firstChild) + let item = document.createElement("div") + item.className = "menu_item" + item.onclick = () => window.open(link, "_self") + item.textContent = text + popup.insertBefore(item, popup.firstChild) +} + +init_home_menu("/games/active", "Go Home") diff --git a/public/sort.js b/public/sort.js index b98334d..ed243c2 100644 --- a/public/sort.js +++ b/public/sort.js @@ -1,67 +1,82 @@ -"use strict"; +"use strict" function sort_table_column(table, column) { - const minute = 60000; - const hour = 60 * minute; - const day = 24 * hour; - const week = 7 * day; + const minute = 60000 + const hour = 60 * minute + const day = 24 * hour + const week = 7 * day function is_date(s) { if (s.match(/^\d{4}-\d{2}-\d{2}$/)) - return true; + return true if (s.match(/^\d+ (minutes?|hours?|days|weeks) ago$/)) - return true; + return true if (s.match(/^(Yesterday|now)$/)) - return true; - return false; + return true + return false } function parse_date(s) { - if (s.match(/^\d{4}-\d{2}-\d{2}$/)) return new Date(s).valueOf(); - if (s === 'now') return Date.now(); - if (s === 'Yesterday') return Date.now() - day; - let [ _, value, unit ] = s.match(/^(\d+) (minutes?|hours?|days|weeks) ago$/); + if (s.match(/^\d{4}-\d{2}-\d{2}$/)) + return new Date(s).valueOf() + if (s === "now") + return Date.now() + if (s === "Yesterday") + return Date.now() - day + let [ _, value, unit ] = s.match(/^(\d+) (minutes?|hours?|days|weeks) ago$/) switch (unit) { - default: unit = 0; break; - case 'minute': case 'minutes': unit = minute; break; - case 'hours': case 'hours': unit = hour; break; - case 'days': unit = day; break; - case 'weeks': unit = week; break; + default: + unit = 0 + break + case "minute": + case "minutes": + unit = minute + break + case "hours": + case "hours": + unit = hour + break + case "days": + unit = day + break + case "weeks": + unit = week + break } - return Date.now() - Number(value) * unit; + return Date.now() - Number(value) * unit } - let tbody = table.querySelector("tbody"); - let rows = Array.from(tbody.querySelectorAll("tr")); + let tbody = table.querySelector("tbody") + let rows = Array.from(tbody.querySelectorAll("tr")) rows.sort((row_a, row_b) => { - let cell_a = row_a.querySelectorAll("td")[column].textContent; - let cell_b = row_b.querySelectorAll("td")[column].textContent; + let cell_a = row_a.querySelectorAll("td")[column].textContent + let cell_b = row_b.querySelectorAll("td")[column].textContent if (is_date(cell_a) && is_date(cell_b)) { - let age_a = parse_date(cell_a); - let age_b = parse_date(cell_b); - if (age_a > age_b) return -1; - if (age_a < age_b) return 1; - return 0; + let age_a = parse_date(cell_a) + let age_b = parse_date(cell_b) + if (age_a > age_b) return -1 + if (age_a < age_b) return 1 + return 0 } else if (cell_a.match(/^\d+$/) && cell_b.match(/^\d+$/)) { - cell_a = Number(cell_a); - cell_b = Number(cell_b); - if (cell_a > cell_b) return -1; - if (cell_a < cell_b) return 1; - return 0; + cell_a = Number(cell_a) + cell_b = Number(cell_b) + if (cell_a > cell_b) return -1 + if (cell_a < cell_b) return 1 + return 0 } else { - if (cell_a > cell_b) return 1; - if (cell_a < cell_b) return -1; - return 0; + if (cell_a > cell_b) return 1 + if (cell_a < cell_b) return -1 + return 0 } - }); - rows.forEach(row => tbody.appendChild(row)); + }) + rows.forEach((row) => tbody.appendChild(row)) } -document.querySelectorAll("table.sort").forEach(table => { +document.querySelectorAll("table.sort").forEach((table) => { table.querySelectorAll("th").forEach((th, column) => { if (th.textContent !== "") { - th.addEventListener("click", evt => sort_table_column(table, column)); - th.style.cursor = "pointer"; + th.addEventListener("click", (evt) => sort_table_column(table, column)) + th.style.cursor = "pointer" } - }); -}); + }) +}) -- cgit v1.2.3