summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--schema.sql2
-rw-r--r--server.js67
-rwxr-xr-xtools/patchgame.js36
-rw-r--r--views/tm_pool.pug30
4 files changed, 109 insertions, 26 deletions
diff --git a/schema.sql b/schema.sql
index 5fd189e..041761b 100644
--- a/schema.sql
+++ b/schema.sql
@@ -173,6 +173,7 @@ create view rated_games_view as
and moves >= player_count * 3
and user_count = player_count
and player_count > 1
+ and result != 'None'
and not exists (
select 1 from players where players.game_id = games.game_id and user_id = 0
)
@@ -720,6 +721,7 @@ begin
set score = (
case
when new.result is null then null
+ when new.result = 'None' then null
when new.result = role then 2
when new.result = 'Draw' then 1
when instr(new.result, role) then 1
diff --git a/server.js b/server.js
index 8b5c0b6..8dc1c8d 100644
--- a/server.js
+++ b/server.js
@@ -1277,10 +1277,11 @@ function format_options(options_json) {
function get_game_roles(title_id, scenario, options) {
let roles = RULES[title_id].roles
- if (typeof options === "string")
- options = parse_game_options(options)
- if (typeof roles === "function")
+ if (typeof roles === "function") {
+ if (typeof options === "string")
+ options = parse_game_options(options)
return roles(scenario, options)
+ }
return roles
}
@@ -2719,7 +2720,7 @@ function time_control_ticker() {
for (let item of SQL_SELECT_TIME_CONTROL.all()) {
if (item.is_opposed) {
console.log("TIMED OUT GAME:", item.game_id, item.role)
- do_resign(item.game_id, item.role, "timed out")
+ do_timeout(item.game_id, item.role, item.role + " timed out.")
if (item.is_match) {
console.log("BANNED FROM TOURNAMENTS:", item.user_id)
TM_INSERT_TIMEOUT.run(item.user_id, item.game_id)
@@ -2903,6 +2904,7 @@ const TM_SELECT_GAMES = SQL(`
tm_rounds.*,
games.status,
games.moves,
+ games.status > 1 and games.result = 'None' as is_abandoned,
json_group_object(role, coalesce(name, 'null')) as role_names,
json_group_object(role, score) as role_scores
from
@@ -3116,7 +3118,7 @@ app.get("/tm/pool/:pool_name", function (req, res) {
players = TM_SELECT_PLAYERS_MP.all(pool_id)
let games = TM_SELECT_GAMES.all(pool_id)
let games_by_round = object_group_by(games, "round")
- res.render("tm_pool.pug", { user: req.user, seed, pool, roles, players, games_by_round })
+ res.render("tm_pool.pug", { user: req.user, seed, pool, roles, players, games, games_by_round })
})
app.post("/api/tm/register/:seed_id", must_be_logged_in, function (req, res) {
@@ -3647,20 +3649,45 @@ function on_action(socket, action, args, cookie) {
function on_resign(socket) {
SLOG(socket, "RESIGN")
try {
- do_resign(socket.game_id, socket.role, "resigned")
+ do_resign(socket.game_id, socket.role)
+ } catch (err) {
+ console.log(err)
+ return send_message(socket, "error", err.toString())
+ }
+}
+
+function on_abondon(socket) {
+ SLOG(socket, "ABANDON")
+ try {
+ do_abandon(socket.game_id, socket.role)
} catch (err) {
console.log(err)
return send_message(socket, "error", err.toString())
}
}
-function do_resign(game_id, role, how) {
+function do_abandon(game_id, role) {
let game = SQL_SELECT_GAME.get(game_id)
let state = get_game_state(game_id)
let old_active = state.active
+ state = finish_game_state(game.title_id, state, "None", role + " abandoned the game.")
+ put_new_state(game.title_id, game_id, state, old_active, role, ".abandon", null)
+}
- let result = "None"
+function do_timeout(game_id, role) {
+ let game = SQL_SELECT_GAME.get(game_id)
+ let state = get_game_state(game_id)
+ let old_active = state.active
+ state = finish_game_state(game.title_id, state, "None", role + " timed out.")
+ put_new_state(game.title_id, game_id, state, old_active, role, ".timeout", null)
+}
+
+function do_resign(game_id, role) {
+ let game = SQL_SELECT_GAME.get(game_id)
+ let state = get_game_state(game_id)
+ let old_active = state.active
+ let result = "None"
let roles = get_game_roles(game.title_id, game.scenario, game.options)
if (game.player_count === 2) {
for (let r of roles)
@@ -3670,15 +3697,23 @@ function do_resign(game_id, role, how) {
result = roles.filter(r => r !== role).join(", ")
}
- // TODO: clean up
- state.state = "game_over"
- state.active = "None"
- state.result = result
- state.victory = role + " " + how + "."
- state.log.push("")
- state.log.push(state.victory)
+ state = finish_game_state(game.title_id, state, result, role + " resigned.")
+
+ put_new_state(game.title_id, game_id, state, old_active, role, ".resign", result)
+}
- put_new_state(game.title_id, game_id, state, old_active, role, ".resign", null)
+function finish_game_state(title_id, state, result, message) {
+ if (typeof RULES[title_id].finish === "function") {
+ state = RULES[title_id].finish(state, result, message)
+ } else {
+ state.state = "game_over"
+ state.active = "None"
+ state.result = result
+ state.victory = message
+ state.log.push("")
+ state.log.push(message)
+ }
+ return state
}
function on_query(socket, q, params) {
diff --git a/tools/patchgame.js b/tools/patchgame.js
index fef07a0..a28ce1f 100755
--- a/tools/patchgame.js
+++ b/tools/patchgame.js
@@ -97,6 +97,34 @@ function dont_snap(rules, state, old_active) {
return false
}
+function get_game_roles(rules, scenario, options) {
+ let roles = rules.roles
+ if (typeof roles === "function") {
+ if (typeof options === "string")
+ options = JSON.parse(options)
+ return roles(scenario, options)
+ }
+ return roles
+}
+
+function get_resign_result(roles, role) {
+ return roles.filter(r => r !== role).join(", ")
+}
+
+function finish_game(rules, state, result, message) {
+ if (typeof rules.finish === "function") {
+ state = RULES[title_id].finish(state, result, message)
+ } else {
+ state.state = "game_over"
+ state.active = "None"
+ state.result = result
+ state.victory = message
+ state.log.push("")
+ state.log.push(message)
+ }
+ return state
+}
+
function patch_game(game_id, {validate_actions=true, save_snaps=true, delete_undo=false, delete_invalid=false}, verbose) {
let game = select_game.get(game_id)
if (!game) {
@@ -106,6 +134,7 @@ function patch_game(game_id, {validate_actions=true, save_snaps=true, delete_und
let title_id = game.title_id
let rules = require("../public/" + title_id + "/rules.js")
+ let roles = get_game_roles(rules, game.scenario, game.options)
let replay = select_replay.all(game_id)
if (replay.length === 0)
@@ -129,8 +158,13 @@ function patch_game(game_id, {validate_actions=true, save_snaps=true, delete_und
case ".setup":
state = rules.setup(...args)
break
+ case ".timeout":
+ finish_game(rules, state, "None", item.role + " timed out.")
+ break
+ case ".abandon":
+ finish_game(rules, state, "None", item.role + " abandoned the game.")
case ".resign":
- state = rules.resign(state, item.role)
+ finish_game(rules, state, get_resign_result(roles, item.role), item.role + " resigned.")
break
default:
if (validate_actions) {
diff --git a/views/tm_pool.pug b/views/tm_pool.pug
index 1690535..e6c7715 100644
--- a/views/tm_pool.pug
+++ b/views/tm_pool.pug
@@ -49,9 +49,9 @@ html
tr
td Started
td= human_date(pool.start_date)
- tr
- td Finished
- if pool.finish_date
+ if pool.finish_date
+ tr
+ td Finished
td= human_date(pool.finish_date)
if seed.player_count === 2
@@ -84,7 +84,10 @@ html
if ix > 0
|  
if gs[1] === null
- a.black(href="/join/" + gs[0]) −
+ if games.find(game => game.game_id === gs[0]).is_abandoned
+ a.black(href="/join/" + gs[0]) ×
+ else
+ a.black(href="/join/" + gs[0]) −
else
a.black(href="/join/" + gs[0])= gs[1]
td.r= row.points
@@ -116,7 +119,10 @@ html
each gs in result
td.c
if gs[1] === null
- a.black(href="/join/" + gs[0]) −
+ if games.find(game => game.game_id === gs[0]).is_abandoned
+ a.black(href="/join/" + gs[0]) ×
+ else
+ a.black(href="/join/" + gs[0]) −
else
a.black(href="/join/" + gs[0])= gs[1]
td.r= row.points
@@ -150,10 +156,16 @@ html
if game.status > 1
td.w.r
- each role, ix in roles
- if ix > 0
- |  : 
- | #{role_scores[role]}
+ if game.is_abandoned
+ | None
+ else
+ each role, ix in roles
+ if ix > 0
+ |  : 
+ if role_scores[role] === null
+ | ×
+ else
+ | #{role_scores[role]}
else
td.r
if game.status > 0