pytron-web/server.js

164 lines
4.6 KiB
JavaScript

const fs = require('fs');
const process = require('process');
const pathtools = require('path');
const express = require('express');
const fileUpload = require("express-fileupload");
const { spawn } = require('child_process');
const pug = require('pug');
const unzip = require('unzip');
const app = express();
const port = 8000;
const aisPath = "pytron_run/ai_manager/"
const aisPathOld = "pytron_run/ai_manager_old"
// Create the directories to store the files
try { fs.mkdirSync('pytron_run/ai_manager'); } catch { }
try { fs.mkdirSync('pytron_run/ai_manager_old'); } catch { }
let pythonRunning = false;
let pythonShouldRun = false;
function runPython() {
process.stdout.write('Requested to run python');
if (pythonRunning) {
process.stdout.write(' buy python is already running');
pythonShouldRun = true;
} else {
pythonRunning = true;
}
process.stdout.write('\n');
let p = spawn('python', ['pytron_run/run.py']);
p.stdout.on('data', (data) => {
let content = data.toString().split('\n');
for (let line of content) {
console.log("run.py: " + line);
}
});
p.stderr.on('data', (data) => {
let content = data.toString().split('\n');
for (let line of content) {
console.log("run.py: " + line);
}
});
p.on('close', (code) => {
process.stdout.write("Python finished executing");
if (pythonShouldRun) {
process.stdout.write(' but another request arrive, so we will relaunch it\n');
pythonShouldRun = false;
runPython();
} else {
process.stdout.write('\n');
pythonRunning = false;
}
});
}
function parse(data) {
let content = JSON.parse(data);
let parsed = {ais: [], battles: {}};
for (let ai of content.ais) {
parsed.ais.push({
name: ai,
victories: 0,
defeats: 0,
});
}
for (let key in content.battles) {
let battlers = key.split('/');
let ai1 = battlers[0];
let ai2 = battlers[1];
parsed.battles[ai1 + '/' + ai2] = Math.floor(100 * content.battles[key]);
parsed.battles[ai2 + '/' + ai1] = 100 - parsed.battles[ai1 + '/' + ai2];
}
parsed.sortedAis = parsed.ais.slice(0);
parsed.sortedAis.sort((a, b) => {
if (a.victories < b.victories) {
return -1;
} else if (a.victories > b.victories) {
return 1;
} else {
if (a.defeats > b.defeats) {
return -1;
} else if (a.defeats < b.defeats) {
return 1;
} else {
return 0;
}
}
});
return parsed;
}
app.set('view engine', 'pug');
app.use(fileUpload());
app.get('/', (req, res) => {
fs.readFile('assets/data.json', 'utf-8', (err, data) => {
if (err != null) {
console.log(err);
}
let parsed = parse(data);
res.render('index', parsed);
});
});
app.get('/upload', (req, res) => {
res.render('upload', {});
});
app.post('/upload-target', (req, res) => {
let path = pathtools.join(aisPath, req.body.name)
try {
if (fs.statSync(path).isDirectory()) {
// Move it to old
let version = 0;
for(;;) {
let movePath = pathtools.join(aisPathOld, req.body.name + '.' + version);
try {
fs.statSync(movePath);
// If the sync succeded, it means that the directory already exists
version++;
} catch {
// If we're here, it means that we found the right path. We
// will move the old one to the old directories, and save
// the new one
fs.renameSync(path, movePath);
break;
}
}
}
} catch {
// Nothing to do here
}
fs.mkdirSync(path);
let zipfile = pathtools.join(path, "archive.zip");
req.files.archive.mv(zipfile, (err) => {
console.log(err);
fs.createReadStream(zipfile)
.pipe(unzip.Extract({path}))
.on('close', () => {
// Trigger python_run
runPython();
res.send('yo');
})
.on('error', () => {
res.send('an error occured while extracting the archive')
});
});
});
app.use('/static', express.static('static'));
app.listen(port, () => {
console.log(`Server listening on port ${port}!`)
})