X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=index.js;h=9b7270b7673e03e1ae78c803b68c6af054551b9f;hb=f49cdc229d3db14bb00667c9e6d105c1d67274a8;hp=cb46c203bb3f63e28f1c292bbee6726321c62398;hpb=8443e4c644efeb5a3d8e21cf5502bc46381270cb;p=zombocom-ai diff --git a/index.js b/index.js index cb46c20..9b7270b 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,8 @@ const fs = require('fs'); const util = require('util'); -const execFile = util.promisify(require('child_process').execFile); - +const child_process = require('child_process'); +const execFile = util.promisify(child_process.execFile); const express = require('express'); const app = express(); const session = require('express-session'); @@ -15,6 +15,7 @@ const port = 2122; const python_path = '/usr/bin/python3' const generate_image_script = '/home/cworth/src/zombocom-ai/generate-image.py' +const run_turtle_script = '/home/cworth/src/zombocom-ai/run-turtle.py' const state_file = 'zombocom-state.json' const targets_dir = '/srv/cworth.org/zombocom/targets' const images_dir = '/srv/cworth.org/zombocom/images' @@ -132,6 +133,106 @@ app.get('/index.html', (req, res) => { res.sendFile(__dirname + '/index.html'); }); +function bus_app(req, res) { + res.sendFile(__dirname + '/bus.html'); +} + +app.get('/bus', bus_app); +app.get('/bus/', bus_app); + +const io_bus = io.of("/bus"); + +io_bus.use(wrap(session_middleware)); + +var bus_interval = 0; + +function start_bus() { + const bus = state.bus; + + bus.state = "program"; + + // Let all companions know the state of the game + io_bus.emit("state", bus.state); +} + +function emit_bus_timer() { + const bus = state.bus; + io_bus.emit('timer', bus.timer); + bus.timer = bus.timer - 1; + if (bus.timer < 0) { + clearInterval(bus_interval); + bus.timer = 30; + setTimeout(start_bus, 3000); + } +} + +function start_bus_timer() { + const bus = state.bus; + bus.timer = 3; // XXX: 30 in production + emit_bus_timer(); + bus_interval = setInterval(emit_bus_timer, 1000); +} + +io_bus.on("connection", (socket) => { + if (! socket.request.session.name) { + console.log("Error: Someone showed up at the Magic School Bus without a name."); + return; + } + + const name = socket.request.session.name; + const bus = state.bus; + + // Let the new user know the state of the bus + socket.emit("state", bus.state); + + if (bus.students.count === 0) { + start_bus_timer(); + } + + if (! bus.students.names.includes(name)) { + bus.students.count = bus.students.count + 1; + io_bus.emit('students', bus.students.count); + } + bus.students.names.push(name); + + socket.on('run', code => { + try { + output = child_process.execFileSync(python_path, [run_turtle_script, code], { input: code }); + // Grab just first line of output + const nl = output.indexOf("\n"); + if (nl === -1) + nl = undefined; + const filename = output.toString().substring(0, nl); + + // Give all clients the new image + io_bus.emit('output', filename); + } catch (e) { + console.log("Error executing turtle script: " + e); + } + }); + + socket.on('jumpstart', () => { + const bus = state.bus; + + bus.state = "welcome"; + io_bus.emit("state", bus.state); + io_bus.emit('students', bus.students.count); + + start_bus_timer(); + }); + + socket.on('disconnect', () => { + const names = bus.students.names; + + names.splice(names.indexOf(name), 1); + + if (! names.includes(name)) { + bus.students.count = bus.students.count - 1; + io_bus.emit('students', bus.students.count); + } + }); +}); + function tardis_app(req, res) { if (! req.session.name) { res.sendFile(__dirname + '/tardis-error.html');