summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2023-09-15 19:17:32 +0200
committerTor Andersson <tor@ccxvii.net>2023-09-20 20:29:16 +0200
commit5d5f3baa5ae2197fec783ace10d03952e669ed1e (patch)
tree1b22bf8d4f52873fdbee0aca5b2ffcf0803fd8e9
parent58530e70bbd741d29fbc7b7904c37dcbc3ec1648 (diff)
downloadserver-5d5f3baa5ae2197fec783ace10d03952e669ed1e.tar.gz
Add pace property to games.
Currently unenforced and only visual effect in game listings.- Future time control and user penalty features may make use of it.
-rw-r--r--schema.sql1
-rw-r--r--server.js27
-rw-r--r--views/create.pug22
-rw-r--r--views/head.pug12
-rw-r--r--views/join.pug8
5 files changed, 62 insertions, 8 deletions
diff --git a/schema.sql b/schema.sql
index 6d7fc13..d4cb397 100644
--- a/schema.sql
+++ b/schema.sql
@@ -352,6 +352,7 @@ create table if not exists games (
owner_id integer default 0,
notice text,
+ pace integer default 0,
is_private boolean default 0,
is_random boolean default 0,
diff --git a/server.js b/server.js
index 3e23a74..137a24d 100644
--- a/server.js
+++ b/server.js
@@ -164,11 +164,17 @@ function set_static_headers(res, path) {
}
let app = express()
+
app.locals.SITE_NAME = SITE_NAME
app.locals.SITE_URL = SITE_URL
app.locals.ENABLE_MAIL = !!mailer
app.locals.ENABLE_WEBHOOKS = !!WEBHOOKS
app.locals.ENABLE_FORUM = process.env.FORUM | 0
+
+app.locals.EMOJI_LIVE = "\u{1f465}"
+app.locals.EMOJI_FAST = "\u{1f3c1}"
+app.locals.EMOJI_SLOW = "\u{1f40c}"
+
app.set('x-powered-by', false)
app.set('etag', false)
app.set('view engine', 'pug')
@@ -1051,6 +1057,13 @@ const STATUS_ACTIVE = 1
const STATUS_FINISHED = 2
const STATUS_ARCHIVED = 3
+const PACE_ANY = 0
+const PACE_LIVE = 1
+const PACE_FAST = 2
+const PACE_SLOW = 3
+
+const PACE_NAME = [ "Any", "Live", "Fast", "Slow" ]
+
function load_rules() {
const SQL_SELECT_TITLES = SQL("SELECT * FROM titles")
for (let title of SQL_SELECT_TITLES.all()) {
@@ -1126,7 +1139,7 @@ function is_game_ready(player_count, players) {
load_rules()
-const SQL_INSERT_GAME = SQL("INSERT INTO games (owner_id,title_id,scenario,options,player_count,is_private,is_random,notice) VALUES (?,?,?,?,?,?,?,?)")
+const SQL_INSERT_GAME = SQL("INSERT INTO games (owner_id,title_id,scenario,options,player_count,pace,is_private,is_random,notice) VALUES (?,?,?,?,?,?,?,?,?)")
const SQL_DELETE_GAME = SQL("DELETE FROM games WHERE game_id=? AND owner_id=?")
const SQL_START_GAME = SQL(`
@@ -1229,9 +1242,9 @@ const SQL_COUNT_ACTIVE_GAMES = SQL(`
const SQL_SELECT_REMATCH = SQL(`SELECT game_id FROM games WHERE status < ${STATUS_FINISHED} AND notice=?`).pluck()
const SQL_INSERT_REMATCH = SQL(`
INSERT INTO games
- (owner_id, title_id, scenario, options, player_count, is_private, is_random, notice)
+ (owner_id, title_id, scenario, options, player_count, pace, is_private, is_random, notice)
SELECT
- $user_id, title_id, scenario, options, player_count, is_private, 0, $magic
+ $user_id, title_id, scenario, options, player_count, pace, is_private, 0, $magic
FROM games
WHERE game_id = $game_id AND NOT EXISTS (
SELECT * FROM games WHERE notice=$magic
@@ -1561,6 +1574,7 @@ app.get('/create/:title_id', must_be_logged_in, function (req, res) {
function options_json_replacer(key, value) {
if (key === 'scenario') return undefined
if (key === 'notice') return undefined
+ if (key === 'pace') return undefined
if (key === 'is_random') return undefined
if (key === 'is_private') return undefined
if (value === 'true') return true
@@ -1574,8 +1588,9 @@ function options_json_replacer(key, value) {
app.post("/create/:title_id", must_be_logged_in, function (req, res) {
let title_id = req.params.title_id
- let priv = req.body.is_private === "true"
- let rand = req.body.is_random === "true"
+ let priv = req.body.is_private === "true" ? 1 : 0
+ let rand = req.body.is_random === "true" ? 1 : 0
+ let pace = req.body.pace | 0
let user_id = req.user.user_id
let scenario = req.body.scenario
let options = JSON.stringify(req.body, options_json_replacer)
@@ -1592,7 +1607,7 @@ app.post("/create/:title_id", must_be_logged_in, function (req, res) {
let player_count = get_game_roles(title_id, scenario, parse_game_options(options)).length
- let info = SQL_INSERT_GAME.run(user_id, title_id, scenario, options, player_count, priv ? 1 : 0, rand ? 1 : 0, notice)
+ let info = SQL_INSERT_GAME.run(user_id, title_id, scenario, options, player_count, pace, priv, rand, notice)
res.redirect("/join/" + info.lastInsertRowid)
})
diff --git a/views/create.pug b/views/create.pug
index 32fa01b..95e0ea0 100644
--- a/views/create.pug
+++ b/views/create.pug
@@ -29,6 +29,27 @@ html
br
input(type="text" autocomplete="off" name="notice" size=50 placeholder="What are you looking for?")
+ p Pace:
+ br
+ label
+ input(type="radio" name="pace" value="0" checked)
+ | Any
+
+ br
+ label
+ input(type="radio" name="pace" value="1")
+ | #{EMOJI_LIVE} Live
+
+ br
+ label
+ input(type="radio" name="pace" value="2")
+ | #{EMOJI_FAST} Fast <i>&ndash; many moves per day</i>
+
+ br
+ label
+ input(type="radio" name="pace" value="3")
+ | #{EMOJI_SLOW} Slow <i>&ndash; one move per day</i>
+
p
label
input(type="checkbox" name="is_random" value="true")
@@ -38,6 +59,7 @@ html
label
input(type="checkbox" name="is_private" value="true")
| Private
+
if limit
p.error= limit
else
diff --git a/views/head.pug b/views/head.pug
index 0fc415b..d9a1364 100644
--- a/views/head.pug
+++ b/views/head.pug
@@ -43,6 +43,8 @@ mixin gamelist(list,hide_title=0)
div
-
let className = "game_item"
+ let pace_icon = ""
+ let pace_text = ""
let chat_icon = ""
if (item.your_turn) className += " your_turn"
if (item.status === 0 && item.join_count === 0) className += " open replacement"
@@ -53,15 +55,19 @@ mixin gamelist(list,hide_title=0)
else if (item.status === 2) className += " finished"
else if (item.status === 3) className += " archived"
if (item.is_unread) chat_icon = "\u{1f4dd}"
+ if (item.pace === 0) pace_icon = "", pace_text = ""
+ else if (item.pace === 1) pace_icon = EMOJI_LIVE, pace_text = "Live!"
+ else if (item.pace === 2) pace_icon = EMOJI_FAST, pace_text = "Fast - many moves per day"
+ else if (item.pace === 3) pace_icon = EMOJI_SLOW, pace_text = "Slow - one move per day"
div(class=className)
div.game_head
if item.scenario.length <= 2
div
- | <a href="/join/#{item.game_id}">#{item.game_id} &#x2013; #{item.title_name} (#{item.scenario})</a> #{chat_icon}
+ | #{pace_icon} <a href="/join/#{item.game_id}">#{item.game_id} &#x2013; #{item.title_name} (#{item.scenario})</a> #{chat_icon}
else
div
- | <a href="/join/#{item.game_id}">#{item.game_id} &#x2013; #{item.title_name}</a> #{chat_icon}
+ | #{pace_icon} <a href="/join/#{item.game_id}">#{item.game_id} &#x2013; #{item.title_name}</a> #{chat_icon}
case item.status
when 0
@@ -94,6 +100,8 @@ mixin gamelist(list,hide_title=0)
div.game_info
if item.notice
i= item.notice
+ else
+ i= pace_text
if item.scenario !== "Standard" && item.scenario !== "Historical" && item.scenario.length > 2
div Scenario: #{item.scenario}
unless item.human_options === "None"
diff --git a/views/join.pug b/views/join.pug
index 3110bd3..5c3c296 100644
--- a/views/join.pug
+++ b/views/join.pug
@@ -61,6 +61,14 @@ html
unless game.human_options === "None"
p Options: #{game.human_options}.
+ case game.pace
+ when 1
+ p #{EMOJI_LIVE} Live!
+ when 2
+ p #{EMOJI_FAST} Fast &ndash; many moves per day.
+ when 3
+ p #{EMOJI_SLOW} Slow &ndash; one move per day.
+
if game.notice
p
i= game.notice