Skip to content
Snippets Groups Projects
Commit 0f7a6513 authored by Rob Swindell's avatar Rob Swindell :speech_balloon:
Browse files

Export high scores to message base with "export" command-line option

A periodic (e.g. weekly) digest of high scores posted to SYNCDATA
will allow BBSes to have an accurate list of global high scores
without requiring the retention of several years of SYNCDATA messages.

Also, made the necessary changes to allow:
'jsexec minesweeper.js export' (for testing, primarily)

When posting an exception report, post from sysop if user.alias is undefined.

Incremented revision to 2.15 (though there were no game-play changes).
parent ca9a691f
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
// $Id: minesweeper.js,v 2.14 2020/08/04 05:11:26 rswindell Exp $
// Minesweeper, the game // Minesweeper, the game
// See readme.txt for instructions on installation, configuration, and use // See readme.txt for instructions on installation, configuration, and use
...@@ -8,7 +6,7 @@ ...@@ -8,7 +6,7 @@
const title = "Synchronet Minesweeper"; const title = "Synchronet Minesweeper";
const ini_section = "minesweeper"; const ini_section = "minesweeper";
const REVISION = "$Revision: 2.14 $".split(' ')[1]; const REVISION = "$Revision: 2.15 $".split(' ')[1];
const author = "Digital Man"; const author = "Digital Man";
const header_height = 4; const header_height = 4;
const winners_list = js.exec_dir + "winners.jsonl"; const winners_list = js.exec_dir + "winners.jsonl";
...@@ -32,6 +30,8 @@ const char_mine = '\x01r\x01h\xEB'; ...@@ -32,6 +30,8 @@ const char_mine = '\x01r\x01h\xEB';
const char_detonated_mine = '\x01r\x01h\x01i\*'; const char_detonated_mine = '\x01r\x01h\x01i\*';
const attr_count = "\x01c"; const attr_count = "\x01c";
const winner_subject = "Winner"; const winner_subject = "Winner";
const highscores_subject = "High Scores";
const tear_line = "\r\n--- " + js.exec_file + " " + REVISION + "\r\n";
const selectors = ["()", "[]", "<>", "{}", "--", " "]; const selectors = ["()", "[]", "<>", "{}", "--", " "];
require("sbbsdefs.js", "K_NONE"); require("sbbsdefs.js", "K_NONE");
...@@ -61,13 +61,22 @@ if(!options.splash_delay) ...@@ -61,13 +61,22 @@ if(!options.splash_delay)
options.splash_delay = 500; options.splash_delay = 500;
if(!options.sub) if(!options.sub)
options.sub = load({}, "syncdata.js").find(); options.sub = load({}, "syncdata.js").find();
if(js.global.bbs === undefined)
json_lines = load({}, "json_lines.js");
else {
var userprops = bbs.mods.userprops; var userprops = bbs.mods.userprops;
if(!userprops) if(!userprops)
userprops = load(bbs.mods.userprops = {}, "userprops.js"); userprops = load(bbs.mods.userprops = {}, "userprops.js");
var json_lines = bbs.mods.json_lines; var json_lines = bbs.mods.json_lines;
if(!json_lines) if(!json_lines)
json_lines = load(bbs.mods.json_lines = {}, "json_lines.js"); json_lines = load(bbs.mods.json_lines = {}, "json_lines.js");
var selector = userprops.get(ini_section, "selector", options.selector);
var highlight = userprops.get(ini_section, "highlight", options.highlight);
var difficulty = userprops.get(ini_section, "difficulty", options.difficulty);
var ansiterm = bbs.mods.ansiterm_lib;
if(!ansiterm)
ansiterm = bbs.mods.ansiterm_lib = load({}, "ansiterm_lib.js");
}
var game = {}; var game = {};
var board = []; var board = [];
var selected = {x:0, y:0}; var selected = {x:0, y:0};
...@@ -77,17 +86,10 @@ var new_best = false; ...@@ -77,17 +86,10 @@ var new_best = false;
var win_rank = false; var win_rank = false;
var view_details = false; var view_details = false;
var cell_width; // either 3 or 2 var cell_width; // either 3 or 2
var selector = userprops.get(ini_section, "selector", options.selector);
var highlight = userprops.get(ini_section, "highlight", options.highlight);
var difficulty = userprops.get(ini_section, "difficulty", options.difficulty);
var best = null; var best = null;
log(LOG_DEBUG, title + " options: " + JSON.stringify(options)); log(LOG_DEBUG, title + " options: " + JSON.stringify(options));
var ansiterm = bbs.mods.ansiterm_lib;
if(!ansiterm)
ansiterm = bbs.mods.ansiterm_lib = load({}, "ansiterm_lib.js");
function mouse_enable(enable) function mouse_enable(enable)
{ {
const mouse_passthru = (CON_MOUSE_CLK_PASSTHRU | CON_MOUSE_REL_PASSTHRU); const mouse_passthru = (CON_MOUSE_CLK_PASSTHRU | CON_MOUSE_REL_PASSTHRU);
...@@ -183,7 +185,7 @@ function isgamewon() ...@@ -183,7 +185,7 @@ function isgamewon()
game.md5 = md5_calc(JSON.stringify(game)); game.md5 = md5_calc(JSON.stringify(game));
game.name = undefined; game.name = undefined;
var body = lfexpand(JSON.stringify(game, null, 1)); var body = lfexpand(JSON.stringify(game, null, 1));
body += "\r\n--- " + js.exec_file + " " + REVISION + "\r\n"; body += tear_line;
if(!msgbase.save_msg(hdr, body)) if(!msgbase.save_msg(hdr, body))
alert("Error saving message to: " + options.sub); alert("Error saving message to: " + options.sub);
msgbase.close(); msgbase.close();
...@@ -266,6 +268,21 @@ function secondstr(t, frac) ...@@ -266,6 +268,21 @@ function secondstr(t, frac)
return format("%2u:%02u", Math.floor(t/60), Math.floor(t%60)); return format("%2u:%02u", Math.floor(t/60), Math.floor(t%60));
} }
function list_contains(list, obj)
{
var match = false;
for(var i = 0; i < list.length && !match; i++) {
match = true;
for(var p in obj) {
if(list[i][p] != obj[p]) {
match = false;
break;
}
}
}
return match;
}
function get_winners(level) function get_winners(level)
{ {
var list = json_lines.get(winners_list); var list = json_lines.get(winners_list);
...@@ -276,17 +293,21 @@ function get_winners(level) ...@@ -276,17 +293,21 @@ function get_winners(level)
var msgbase = new MsgBase(options.sub); var msgbase = new MsgBase(options.sub);
if(msgbase.get_index !== undefined && msgbase.open()) { if(msgbase.get_index !== undefined && msgbase.open()) {
var to_crc = crc16_calc(title.toLowerCase()); var to_crc = crc16_calc(title.toLowerCase());
var subj_crc = crc16_calc(winner_subject.toLowerCase()); var winner_crc = crc16_calc(winner_subject.toLowerCase());
var highscores_crc = crc16_calc(highscores_subject.toLowerCase());
var index = msgbase.get_index(); var index = msgbase.get_index();
for(var i = 0; index && i < index.length; i++) { for(var i = 0; index && i < index.length; i++) {
var idx = index[i]; var idx = index[i];
if((idx.attr&MSG_DELETE) if((idx.attr&MSG_DELETE) || idx.to != to_crc)
|| idx.to != to_crc || idx.subject != subj_crc) continue;
if(idx.subject != winner_crc && idx.subject != highscores_crc)
continue; continue;
var hdr = msgbase.get_msg_header(true, idx.offset); var hdr = msgbase.get_msg_header(true, idx.offset);
if(!hdr) if(!hdr)
continue; continue;
if(!hdr.from_net_type || hdr.to != title || hdr.subject != winner_subject) if(!hdr.from_net_type || hdr.to != title)
continue;
if(hdr.subject != winner_subject && hdr.subject != highscores_subject)
continue; continue;
var body = msgbase.get_msg_body(hdr, false, false, false); var body = msgbase.get_msg_body(hdr, false, false, false);
if(!body) if(!body)
...@@ -302,13 +323,25 @@ function get_winners(level) ...@@ -302,13 +323,25 @@ function get_winners(level)
} }
if(!obj.md5) // Ignore old test messages if(!obj.md5) // Ignore old test messages
continue; continue;
if(idx.subject == highscores_crc && !obj.game)
continue;
obj.name = hdr.from; obj.name = hdr.from;
var md5 = obj.md5; var md5 = obj.md5;
obj.md5 = undefined; obj.md5 = undefined;
var calced = md5_calc(JSON.stringify(obj)); var calced = md5_calc(JSON.stringify(idx.subject == winner_crc ? obj : obj.game));
if(calced == md5) { if(calced == md5) {
if(idx.subject == winner_crc) {
obj.net_addr = hdr.from_net_addr; // Not included in MD5 sum obj.net_addr = hdr.from_net_addr; // Not included in MD5 sum
if(!list_contains(obj))
list.push(obj); list.push(obj);
} else {
for(var j = 0; j < obj.game.length; j++) {
var game = obj.game[j];
game.net_addr = hdr.from_net_addr;
if(!list_contains(game))
list.push(game);
}
}
} else { } else {
log(LOG_INFO, title + log(LOG_INFO, title +
" MD5 not " + calced + " MD5 not " + calced +
...@@ -1214,11 +1247,12 @@ try { ...@@ -1214,11 +1247,12 @@ try {
break; break;
} }
if(js.global.console) {
if(argv.indexOf("nocls") < 0) if(argv.indexOf("nocls") < 0)
js.on_exit("console.clear()"); js.on_exit("console.clear()");
js.on_exit("console.attributes = LIGHTGRAY"); js.on_exit("console.attributes = LIGHTGRAY");
}
if(argv.indexOf("winners") >= 0) { if(argv.indexOf("winners") >= 0) {
if(!isNaN(numval) && numval > 0) if(!isNaN(numval) && numval > 0)
options.winners = numval; options.winners = numval;
...@@ -1226,11 +1260,46 @@ try { ...@@ -1226,11 +1260,46 @@ try {
exit(); exit();
} }
if(argv.indexOf("export") >= 0) {
if(!options.sub) {
alert("Sub-board not defined");
exit(1);
}
var count = 20;
if(!isNaN(numval) && numval > 0)
count = numval;
var list = json_lines.get(winners_list);
if(typeof list != 'object') {
alert("No winners yet: " + list);
exit(0);
}
list.sort(compare_won_game);
var obj = { date: Date(), game: [] };
for(var i = 0; i < list.length && i < count; i++)
obj.game.push(list[i]);
obj.md5 = md5_calc(JSON.stringify(obj.game));
var msgbase = new MsgBase(options.sub);
var hdr = {
to: title,
from: system.operator,
subject: highscores_subject
};
var body = lfexpand(JSON.stringify(obj, null, 1));
body += tear_line;
if(!msgbase.save_msg(hdr, body)) {
alert("Error saving message to: " + options.sub);
exit(2);
}
msgbase.close();
exit(0);
}
if(js.global.console) {
js.on_exit("console.line_counter = 0"); js.on_exit("console.line_counter = 0");
js.on_exit("console.status = " + console.status); js.on_exit("console.status = " + console.status);
js.on_exit("console.ctrlkey_passthru = " + console.ctrlkey_passthru); js.on_exit("console.ctrlkey_passthru = " + console.ctrlkey_passthru);
console.ctrlkey_passthru = "KOPTUZ"; console.ctrlkey_passthru = "KOPTUZ";
}
if(!isNaN(numval) && numval > 0 && numval < max_difficulty) if(!isNaN(numval) && numval > 0 && numval < max_difficulty)
difficulty = numval; difficulty = numval;
...@@ -1247,16 +1316,17 @@ try { ...@@ -1247,16 +1316,17 @@ try {
var msg = file_getname(e.fileName) + var msg = file_getname(e.fileName) +
" line " + e.lineNumber + " line " + e.lineNumber +
": " + e.message; ": " + e.message;
if(js.global.console)
console.crlf(); console.crlf();
alert(msg); alert(msg);
if(options.sub && user.alias != author) { if(options.sub && user.alias != author) {
var msgbase = new MsgBase(options.sub); var msgbase = new MsgBase(options.sub);
var hdr = { var hdr = {
to: author, to: author,
from: user.alias, from: user.alias || system.operator,
subject: title subject: title
}; };
msg += "\r\n--- " + js.exec_file + " " + REVISION + "\r\n"; msg += tear_line;
if(!msgbase.save_msg(hdr, msg)) if(!msgbase.save_msg(hdr, msg))
alert("Error saving exception-message to: " + options.sub); alert("Error saving exception-message to: " + options.sub);
msgbase.close(); msgbase.close();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment