From 1ee47cf90e0ee8442bdaba2ed10bedabf39d0db5 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Tue, 15 Jun 2021 17:52:18 +0200 Subject: Add "Rematch" button for easier repeat match making. --- public/common/client.js | 60 +++++++++++++++++++++++++++++++++++-------------- public/common/grid.css | 2 +- public/images/cycle.svg | 1 + server.js | 36 ++++++++++++++++++++++++++++- views/about.ejs | 3 +++ views/join.ejs | 3 +++ 6 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 public/images/cycle.svg diff --git a/public/common/client.js b/public/common/client.js index 26f953e..5185da1 100644 --- a/public/common/client.js +++ b/public/common/client.js @@ -1,4 +1,7 @@ +let game = null; +let player = null; let socket = null; + let chat_is_visible = false; let chat_text = null; let chat_key = null; @@ -103,8 +106,8 @@ function add_chat_lines(log) { } } -function load_chat(game) { - chat_key = "chat/" + game; +function load_chat(game_id) { + chat_key = "chat/" + game_id; chat_text = document.querySelector(".chat_text"); chat_last_day = null; chat_log = []; @@ -137,9 +140,11 @@ function update_chat(log_start, log) { function init_client(roles) { let params = new URLSearchParams(window.location.search); let title = window.location.pathname.split("/")[1]; - let game = params.get("game"); + let game_id = params.get("game"); let role = params.get("role"); - let player = null; + + game = null; + player = null; const ROLE_SEL = [ ".role.one", @@ -161,13 +166,13 @@ function init_client(roles) { ".role.seven .role_user", ]; - load_chat(game); + load_chat(game_id); - console.log("JOINING game", game, "role", role); + console.log("JOINING game", game_id, "role", role); socket = io({ transports: ['websocket'], - query: { title: title, game: game, role: role }, + query: { title: title, game: game_id, role: role }, }); socket.on('connect', () => { @@ -205,11 +210,13 @@ function init_client(roles) { } }); - socket.on('state', (state) => { + socket.on('state', (state, game_over) => { console.log("STATE"); - on_update_log(state); - on_update_bar(state, player); - on_update(state, player); + game = state; + on_update_log(); + on_update_bar(); + on_update(); + on_game_over(game_over); }); socket.on('save', (msg) => { @@ -264,22 +271,22 @@ function init_client(roles) { drag_element_with_mouse(".chat_window", ".chat_header"); } -function on_update_bar(state, player) { - document.getElementById("prompt").textContent = state.prompt; - if (state.actions) +function on_update_bar() { + document.getElementById("prompt").textContent = game.prompt; + if (game.actions) document.querySelector(".grid_top").classList.add("your_turn"); else document.querySelector(".grid_top").classList.remove("your_turn"); } -function on_update_log(state) { +function on_update_log() { let parent = document.getElementById("log"); - let to_delete = parent.children.length - state.log_start; + let to_delete = parent.children.length - game.log_start; while (to_delete > 0) { parent.removeChild(parent.firstChild); --to_delete; } - for (let entry of state.log) { + for (let entry of game.log) { let p = document.createElement("div"); p.textContent = entry; parent.prepend(p); @@ -411,3 +418,22 @@ function send_restore() { function send_restart(scenario) { socket.emit('restart', scenario); } + +function on_game_over(game_over) { + if (player && player != "Observer") { + let rematch_button = document.querySelector("#rematch_button"); + if (rematch_button) + { + if (game_over) + rematch_button.classList.remove("hide"); + else + rematch_button.classList.add("hide"); + } + } +} + +function send_rematch() { + let params = new URLSearchParams(window.location.search); + let game = params.get("game"); + window.location = '/rematch/' + game; +} diff --git a/public/common/grid.css b/public/common/grid.css index 2e1b6b2..eb59357 100644 --- a/public/common/grid.css +++ b/public/common/grid.css @@ -175,7 +175,7 @@ html, body, div { .grid_top button { margin: 0 10px; } -.grid_top button.hide { +.grid_top .hide { display: none; } diff --git a/public/images/cycle.svg b/public/images/cycle.svg new file mode 100644 index 0000000..349da30 --- /dev/null +++ b/public/images/cycle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/server.js b/server.js index 9dedb26..e5ca446 100644 --- a/server.js +++ b/server.js @@ -501,6 +501,21 @@ const QUERY_IS_ACTIVE = db.prepare("SELECT COUNT(*) FROM players WHERE game_id = const QUERY_COUNT_OPEN_GAMES = db.prepare("SELECT COUNT(*) FROM games WHERE owner = ? AND status = 0").pluck(); const QUERY_DELETE_GAME = db.prepare("DELETE FROM games WHERE game_id = ?"); +const QUERY_REMATCH_FIND = db.prepare(` + SELECT game_id FROM games WHERE status=0 AND description=? +`).pluck(); + +const QUERY_REMATCH_CREATE = db.prepare(` + INSERT INTO games + (owner, title_id, scenario, private, random, ctime, mtime, description, status, state, chat) + SELECT + $user_id, title_id, scenario, private, random, datetime('now'), datetime('now'), $magic, 0, NULL, '[]' + FROM games + WHERE game_id = $game_id AND NOT EXISTS ( + SELECT * FROM games WHERE status=0 AND description=$magic + ) +`); + app.get('/', function (req, res) { res.render('index.ejs', { user: req.user, message: req.flash('message') }); }); @@ -630,6 +645,25 @@ app.get('/delete/:game_id', must_be_logged_in, function (req, res) { } }); +app.get('/rematch/:old_game_id', must_be_logged_in, function (req, res) { + LOG(req, "GET /rematch/" + req.params.old_game_id); + let old_game_id = req.params.old_game_id | 0; + try { + let magic = "\u{1F503} " + old_game_id; + let info = QUERY_REMATCH_CREATE.run({user_id: req.user.user_id, game_id: old_game_id, magic: magic}); + if (info.changes == 1) + return res.redirect('/join/'+info.lastInsertRowid); + let new_game_id = QUERY_REMATCH_FIND.get(magic); + if (new_game_id) + return res.redirect('/join/'+new_game_id); + req.flash('message', "Can't create or find rematch game!"); + return res.redirect('/join/'+old_game_id); + } catch (err) { + req.flash('message', err.toString()); + return res.redirect('/join/'+old_game_id); + } +}); + app.get('/join/:game_id', must_be_logged_in, function (req, res) { LOG(req, "GET /join/" + req.params.game_id); let game_id = req.params.game_id | 0; @@ -776,7 +810,7 @@ function send_state(socket, state) { view.log_start = view.log.length; socket.log_length = view.log.length; view.log = view.log.slice(view.log_start); - socket.emit('state', view); + socket.emit('state', view, state.state == 'game_over'); } catch (err) { console.log(err); return socket.emit('error', err.toString()); diff --git a/views/about.ejs b/views/about.ejs index 8478301..fca63e0 100644 --- a/views/about.ejs +++ b/views/about.ejs @@ -52,6 +52,9 @@ see more of the map.
  • The button lights up if you have unread chat messages. +
  • +The button appears when the game is over, and can be used to quickly start a rematch. +

    diff --git a/views/join.ejs b/views/join.ejs index 42feaaf..2da5f03 100644 --- a/views/join.ejs +++ b/views/join.ejs @@ -81,6 +81,9 @@ Description: <%= game.description || "No description." %> %>Waiting for players to join the game.<% } } + if (game.status == 2 && players.some(p => p.user_id == user.user_id)) { + %>
    <% + } if (game.owner_id == user.user_id && (game.status == 0 || solo)) { %>


    <% } -- cgit v1.2.3