Mercurial > hg > rlgwebd
comparison rlgwebd.js @ 42:8f6bc0df58fa
rlgwebd.js: add a player status interface.
Give information on a player's current status at "/pstatus/<name>".
Also fix some shift()/unshift() confusion in checkprogress().
author | John "Elwin" Edwards <elwin@sdf.org> |
---|---|
date | Sat, 09 Jun 2012 11:46:58 -0700 |
parents | f7116eb3f791 |
children | c4efc7522e7b |
comparison
equal
deleted
inserted
replaced
41:ea3b7775009d | 42:8f6bc0df58fa |
---|---|
24 /* Data on the games available. */ | 24 /* Data on the games available. */ |
25 var games = { | 25 var games = { |
26 "rogue3": { | 26 "rogue3": { |
27 "name": "Rogue V3", | 27 "name": "Rogue V3", |
28 "uname": "rogue3", | 28 "uname": "rogue3", |
29 "suffix": ".r3sav", | |
29 "path": "/bin/rogue3" | 30 "path": "/bin/rogue3" |
30 }, | 31 }, |
31 "rogue4": { | 32 "rogue4": { |
32 "name": "Rogue V4", | 33 "name": "Rogue V4", |
33 "uname": "rogue4", | 34 "uname": "rogue4", |
35 "suffix": ".r4sav", | |
34 "path": "/bin/rogue4" | 36 "path": "/bin/rogue4" |
35 }, | 37 }, |
36 "rogue5": { | 38 "rogue5": { |
37 "name": "Rogue V5", | 39 "name": "Rogue V5", |
38 "uname": "rogue5", | 40 "uname": "rogue5", |
41 "suffix": ".r5sav", | |
39 "path": "/bin/rogue5" | 42 "path": "/bin/rogue5" |
40 }, | 43 }, |
41 "srogue": { | 44 "srogue": { |
42 "name": "Super-Rogue", | 45 "name": "Super-Rogue", |
43 "uname": "srogue", | 46 "uname": "srogue", |
47 "suffix": ".srsav", | |
44 "path": "/bin/srogue" | 48 "path": "/bin/srogue" |
45 } | 49 } |
46 }; | 50 }; |
47 | 51 |
48 /* Global state */ | 52 /* Global state */ |
234 return; | 238 return; |
235 } | 239 } |
236 var fre = RegExp("^" + user + ":"); | 240 var fre = RegExp("^" + user + ":"); |
237 for (var i = 0; i < files.length; i++) { | 241 for (var i = 0; i < files.length; i++) { |
238 if (files[i].match(fre)) { | 242 if (files[i].match(fre)) { |
239 args.shift(null, files[i]); | 243 args.unshift(null, files[i]); |
240 callback.apply(null, args); | 244 callback.apply(null, args); |
241 return; | 245 return; |
242 } | 246 } |
243 } | 247 } |
244 args.shift(null, false); | 248 args.unshift(null, false); |
245 callback.apply(null, args); | 249 callback.apply(null, args); |
246 }); | 250 }); |
251 } | |
252 | |
253 function checksaved(user, game, callback, args) { | |
254 var savedirc = game.uname + "save"; | |
255 var basename = String(dropToUID) + "-" + user + game.suffix; | |
256 var savefile = path.join("/var/games/roguelike", savedirc, basename); | |
257 path.exists(savefile, function (exist) { | |
258 args.unshift(exist); | |
259 callback.apply(null, args); | |
260 }); | |
261 } | |
262 | |
263 function playerstatus(user, callback) { | |
264 var sdata = {}; | |
265 tslog("Starting (user %s)", user); | |
266 function finishp() { | |
267 for (var gname in games) { | |
268 if (!(gname in sdata)) | |
269 return; | |
270 } | |
271 tslog("Finished: %s", JSON.stringify(sdata)); | |
272 callback(sdata); | |
273 } | |
274 function regsaved(exists, game) { | |
275 if (exists) | |
276 sdata[game.uname] = "s"; | |
277 else | |
278 sdata[game.uname] = "0"; | |
279 finishp(); | |
280 } | |
281 function regactive(err, filename, game) { | |
282 if (!err && filename) { | |
283 sdata[game.uname] = "p"; | |
284 finishp(); | |
285 } | |
286 else | |
287 checksaved(user, game, regsaved, [game]); | |
288 } | |
289 for (var gname in games) { | |
290 checkprogress(user, games[gname], regactive, [games[gname]]); | |
291 } | |
247 } | 292 } |
248 | 293 |
249 /* A few utility functions */ | 294 /* A few utility functions */ |
250 function timestamp() { | 295 function timestamp() { |
251 dd = new Date(); | 296 dd = new Date(); |
607 if (req.method != 'HEAD') | 652 if (req.method != 'HEAD') |
608 res.write(JSON.stringify(reply)); | 653 res.write(JSON.stringify(reply)); |
609 res.end(); | 654 res.end(); |
610 } | 655 } |
611 | 656 |
657 function pstatusmsg(req, res) { | |
658 if (req.method == 'HEAD') { | |
659 res.writeHead(200, { "Content-Type": "application/json" }); | |
660 res.end(); | |
661 return; | |
662 } | |
663 var target = url.parse(req.url).pathname; | |
664 var pmatch = target.match(/^\/pstatus\/(.*)/); | |
665 if (pmatch && pmatch[1]) | |
666 var pname = pmatch[1]; | |
667 else { | |
668 sendError(res, 2, "No name given."); | |
669 return; | |
670 } | |
671 var reply = {"name": pname}; | |
672 playerstatus(pname, function (pdata) { | |
673 reply["stat"] = pdata; | |
674 res.writeHead(200, { "Content-Type": "application/json" }); | |
675 res.write(JSON.stringify(reply)); | |
676 res.end(); | |
677 }); | |
678 } | |
679 | |
612 var errorcodes = [ "Generic Error", "Not logged in", "Invalid data", | 680 var errorcodes = [ "Generic Error", "Not logged in", "Invalid data", |
613 "Login failed", "Already playing", "Game launch failed", | 681 "Login failed", "Already playing", "Game launch failed", |
614 "Server shutting down", "Game not in progress" ]; | 682 "Server shutting down", "Game not in progress" ]; |
615 | 683 |
616 function sendError(res, ecode, msg) { | 684 function sendError(res, ecode, msg) { |
696 readFeed(res, cterm); | 764 readFeed(res, cterm); |
697 } | 765 } |
698 else if (target == '/status') { | 766 else if (target == '/status') { |
699 statusmsg(req, res); | 767 statusmsg(req, res); |
700 } | 768 } |
769 else if (target.match(/^\/pstatus\//)) { | |
770 pstatusmsg(req, res); | |
771 } | |
701 else /* Go look for it in the filesystem */ | 772 else /* Go look for it in the filesystem */ |
702 serveStatic(req, res, target); | 773 serveStatic(req, res, target); |
703 } | 774 } |
704 else { /* Some other method */ | 775 else { /* Some other method */ |
705 res.writeHead(501, resheaders); | 776 res.writeHead(501, resheaders); |