com2014-server/server.js

318 lines
10 KiB
JavaScript

const fs = require('fs')
var express = require('express')
var app = express()
var router = express.Router()
var upload = require('./app/config/multer.config.js')
const {Docker} = require('node-docker-api')
const { time } = require('console')
const lineReader = require('line-reader');
const docker = new Docker({ socketPath: '/var/run/docker.sock' })
const stripAnsi = require('strip-ansi');
global.__basedir = __dirname
app.use(express.static('resources'))
var http = require('http').createServer(app)
var io = require('socket.io')(http)
var readlineSync = require('readline-sync');
const path = require('path');
current_path = process.cwd()
var leaderboard = {}
leaderboard.ulysses16 = []
leaderboard.att48 = []
leaderboard.st70 = []
leaderboard.a280 = []
leaderboard.pcb442 = []
leaderboard.dsj1000 = []
var update_leaderboard = (obj) => {
if(obj.name === 'ulysses16') {
leaderboard.ulysses16.push(obj.data)
}
else if (obj.name === 'att48') {
leaderboard.att48.push(obj.data)
}
else if (obj.name === 'st70') {
leaderboard.st70.push(obj.data)
}
else if (obj.name === 'a280') {
leaderboard.a280.push(obj.data)
}
else if (obj.name === 'pcb442') {
leaderboard.pcb442.push(obj.data)
}
else if (obj.name === 'dsj1000') {
leaderboard.dsj1000.push(obj.data)
}
leaderboard.ulysses16.sort(function(a, b){return a.fitness - b.fitness})
leaderboard.ulysses16 = leaderboard.ulysses16.slice(0,10)
leaderboard.att48.sort(function(a, b){return a.fitness - b.fitness}).slice(0,10)
leaderboard.att48 = leaderboard.att48.slice(0,10)
leaderboard.st70.sort(function(a, b){return a.fitness - b.fitness}).slice(0,10)
leaderboard.st70 = leaderboard.st70.slice(0,10)
leaderboard.a280.sort(function(a, b){return a.fitness - b.fitness})
leaderboard.a280 = leaderboard.a280.slice(0,10)
leaderboard.pcb442.sort(function(a, b){return a.fitness - b.fitness})
leaderboard.pcb442 = leaderboard.pcb442.slice(0,10)
leaderboard.dsj1000.sort(function(a, b){return a.fitness - b.fitness})
leaderboard.dsj1000 = leaderboard.dsj1000.slice(0,10)
write_leaderboard()
}
var write_leaderboard = () => {
fs.writeFile('leaderboard.json', JSON.stringify(leaderboard), (err) => {
if (err) throw err;
console.log('Data written to file');
});
}
try {
if (fs.existsSync('leaderboard.json')) {
//file exists
leaderboard = require('./leaderboard.json');
console.log(leaderboard);
}
else {
write_leaderboard();
}
}
catch(err) {
console.error(err)
}
var res = [];
var update_submission = (socket, sessionID) => {
console.log('check result')
var output_dir = current_path.toString() + '/output/' + sessionID + '/'
console.log(output_dir)
if (output_dir.length != 0)
{
res = []
socket.emit('update', 'Got output')
fs.readdir(output_dir, (err, files) => {
if (err) {
console.log(err);
return;
}
console.log('iterate')
files.forEach(file => {
console.log(file)
console.log(path.extname(file))
if (path.extname(file) === '.txt') {
var i = 0
var obj = {}
obj.name = file
console.log(output_dir + file)
try {
// read contents of the file
const data = fs.readFileSync(output_dir + file, 'UTF-8');
// split the contents by new line
const lines = data.split(/\r?\n/);
// print all lines
lines.forEach((line) => {
console.log(line)
i = i + 1
// console.log(line)
if(i == 1) {
var fitness = parseFloat(line)
if(fitness < 0) {
obj.fitness = parseInt(line)
}
else {
obj.fitness = fitness
}
}
else if (i == 2) {
if(obj.fitness > 0) {
solution_array = line.split(",");
for(var j = 0; j < solution_array.length; j++) {
solution_array[i] = parseInt(solution_array[i], 10);
}
obj.solution = solution_array
}
else {
obj.solution = []
}
}
});
} catch (err) {
console.error(err);
}
res.push(obj)
}
});
// console.log(res)
socket.emit('result', JSON.stringify(res))
});
}
else {
console.log('no result')
}
};
var docker_build = (socket, sessionID) => {
console.log('[server][start]', sessionID)
socket.emit('start')
fs.mkdir(current_path + '/output/' + sessionID.toString(), () => {
socket.emit('update', 'Output directort created.')
socket.emit('update', 'Test started, this may take a while.')
})
{
if (fs.existsSync(current_path.toString() + '/uploads/' + sessionID.toString() + '/requirements.txt'))
{
//file exists
docker.container.create({
Image: 'com2014-tsp',
HostConfig: {
Binds: [
current_path.toString() + '/uploads/' + sessionID.toString() + '/requirements.txt:/tsp/requirements.txt',
current_path.toString() + "/output/" + sessionID.toString() + ":/output"
]
}
})
.then( (container) => {
container_id = container.data.Id
socket.emit('update','Container Id: ' + container_id)
return container.start()
})
.then(container => container.logs({
follow: true,
stdout: true,
stderr: true
}))
.then(stream => {
stream.on('data', info => socket.emit('update', new Buffer.from(info).toString('ascii')))
stream.on('error', err => console.log(err))
})
.catch(error => console.log(error))
}
else
{
docker.container.create({
Image: 'com2014-tsp',
HostConfig: {
Binds: [
current_path.toString() + "/output/" + sessionID.toString() + ":/output"
]
}
})
.then( (container) => {
container_id = container.data.Id
socket.emit('update','Container Id: ' + container_id)
return container.start()
})
.then(container => container.logs({
follow: true,
stdout: true,
stderr: true
}))
.then(stream => {
stream.on('data', (info) => {
console.log(stripAnsi(new Buffer.from(info).toString()))
socket.emit('update', stripAnsi(new Buffer.from(info).toString('ascii')))
}),
stream.on('error', err => console.log(err))
})
.catch(error => console.log(error))
}
var intervalObj;
var timeoutObj;
intervalObj = setInterval(() => {
if(!finished)
{
docker.container.list({all:true})
// Inspect
.then((containers) => {
containers.forEach(container => {
if(container.data.Id == container_id) {
socket.emit('update', 'Container Status: ' + container.data.State)
if(container.data.State === 'exited')
{
finished = true;
clearInterval(intervalObj);
clearTimeout(timeoutObj);
socket.emit('update', 'Test end')
update_submission(socket, sessionID);
}
}
});
})
.catch(error => console.log(error))
}
}, 2000);
var finished = false
// call the rest of the code and have it execute after 3 seconds
timeoutObj = setTimeout(() => {
console.log('end')
if(!finished)
{
clearInterval(intervalObj);
socket.emit('update', 'timeout')
}
}, 20000)
}
}
var clients = 0
io.on('connection', (socket) => {
const sessionID = socket.id
console.log('[client][connection]', sessionID)
clients = clients + 1
io.sockets.emit('users_count', clients)
console.log(leaderboard)
socket.emit('leaderboard', leaderboard)
socket.on('disconnect', () => {
clients = clients - 1
console.log('[client][disconnect]', sessionID)
io.sockets.emit('users_count', clients)
})
socket.on('build', () => {
console.log('[client][build]', sessionID)
docker_build(socket, sessionID)
})
socket.on('submit', (obj) => {
console.log('[client][submit]', sessionID)
update_leaderboard(obj)
io.emit('leaderboard', leaderboard)
})
})
require('./app/routers/file.router.js')(app, router, upload)
// Create a Server
var server = http.listen(8081, () => {
var host = server.address().address
var port = server.address().port
console.log("App listening at http://%s:%s", host, port)
})