[clean] clean code
|
|
@ -1 +1,3 @@
|
||||||
|
sudo ln -s /mnt/f/COM2014/server/uploads /uploads
|
||||||
|
|
||||||
docker container run -d -p 80:8080 -v /var/run/docker.sock:/var/run/docker.sock -v /uploads/:/app/uploads/ -v /output/:/app/output/ com2014-server
|
docker container run -d -p 80:8080 -v /var/run/docker.sock:/var/run/docker.sock -v /uploads/:/app/uploads/ -v /output/:/app/output/ com2014-server
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,22 @@
|
||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
com2014:
|
tsp:
|
||||||
image: com2014-server
|
image: com2014-server
|
||||||
networks:
|
networks:
|
||||||
- traefik-public
|
- traefik-public
|
||||||
deploy:
|
deploy:
|
||||||
labels:
|
labels:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.com2014.rule=Host(`com2014.trustai.uk`)"
|
- "traefik.http.routers.tsp.rule=Host(`tsp.trustai.uk`)"
|
||||||
- "traefik.http.routers.com2014.entrypoints=web"
|
- "traefik.http.routers.tsp.entrypoints=web"
|
||||||
- "traefik.http.services.com2014.loadbalancer.server.port=80"
|
- "traefik.http.services.tsp.loadbalancer.server.port=8080"
|
||||||
# TLS
|
# TLS
|
||||||
- "traefik.http.routers.com2014s.rule=Host(`com2014.trustai.uk`)"
|
- "traefik.http.routers.tsps.rule=Host(`tsp.trustai.uk`)"
|
||||||
- "traefik.http.routers.com2014s.entrypoints=websecure"
|
- "traefik.http.routers.tsps.entrypoints=websecure"
|
||||||
- "traefik.http.routers.com2014s.tls.certresolver=myhttpchallenge"
|
- "traefik.http.routers.tsps.tls.certresolver=myhttpchallenge"
|
||||||
# Redirect
|
# Redirect
|
||||||
- "traefik.http.routers.com2014.middlewares=https_redirect"
|
- "traefik.http.routers.tsp.middlewares=https_redirect"
|
||||||
- "traefik.http.middlewares.https_redirect.redirectscheme.scheme=https"
|
- "traefik.http.middlewares.https_redirect.redirectscheme.scheme=https"
|
||||||
placement:
|
|
||||||
constraints:
|
|
||||||
- node.role == worker
|
|
||||||
networks:
|
networks:
|
||||||
traefik-public:
|
traefik-public:
|
||||||
external: true
|
external: true
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"ulysses16":[],"att48":[],"st70":[],"a280":[],"pcb442":[],"dsj1000":[]}
|
||||||
|
|
@ -1,8 +1,4 @@
|
||||||
# .gitignore sample
|
# Ignore everything in this directory
|
||||||
###################
|
|
||||||
|
|
||||||
# Ignore all files in this dir...
|
|
||||||
*
|
*
|
||||||
|
# Except this file
|
||||||
# ... except for this one.
|
|
||||||
!.gitignore
|
!.gitignore
|
||||||
|
|
@ -17,10 +17,8 @@
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.16.3",
|
"express": "^4.16.3",
|
||||||
"line-reader": "^0.4.0",
|
|
||||||
"multer": "^1.3.0",
|
"multer": "^1.3.0",
|
||||||
"node-docker-api": "^1.1.22",
|
"node-docker-api": "^1.1.22",
|
||||||
"readline-sync": "^1.4.10",
|
|
||||||
"socket.io": "^3.0.4",
|
"socket.io": "^3.0.4",
|
||||||
"strip-ansi": "^6.0.0"
|
"strip-ansi": "^6.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,14 +143,14 @@ body::after {
|
||||||
margin-top: 10%;
|
margin-top: 10%;
|
||||||
margin-left: 40%;
|
margin-left: 40%;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
content:url("/static/img/exeter.png");
|
content:url("/img/exeter.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.russell {
|
.russell {
|
||||||
margin-top: 5%;
|
margin-top: 5%;
|
||||||
margin-left: 40%;
|
margin-left: 40%;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
content:url("/static/img/russell.png");
|
content:url("/img/russell.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
#main-footer {
|
#main-footer {
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
|
@ -26,15 +26,15 @@
|
||||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/5.1.3/css/fileinput.min.css" media="all" rel="stylesheet" type="text/css" />
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/5.1.3/css/fileinput.min.css" media="all" rel="stylesheet" type="text/css" />
|
||||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" crossorigin="anonymous">
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/5.1.3/js/fileinput.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/5.1.3/js/fileinput.min.js"></script>
|
||||||
<script src="/static/themes/fas/theme.js" type="text/javascript"></script>
|
<script src="/themes/fas/theme.js" type="text/javascript"></script>
|
||||||
<script src="/static/themes/explorer-fas/theme.js" type="text/javascript"></script>
|
<script src="/themes/explorer-fas/theme.js" type="text/javascript"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Ubuntu+Mono" />
|
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Ubuntu+Mono" />
|
||||||
|
|
||||||
<!-- My Script -->
|
<!-- My Script -->
|
||||||
<link rel="stylesheet" href="/static/css/style.css">
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
<script src="/static/js/postrequest.js"></script>
|
<script src="/js/script.js"></script>
|
||||||
<script src="/static/js/getrequest.js"></script>
|
<script src="/js/socket_script.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@
|
||||||
<div class="row mb-5">
|
<div class="row mb-5">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="embed-responsive embed-responsive-16by9 box-shadow">
|
<div class="embed-responsive embed-responsive-16by9 box-shadow">
|
||||||
<iframe class="embed-responsive-item" src="/static/preview.html" allowfullscreen></iframe>
|
<iframe class="embed-responsive-item" src="/preview.html" allowfullscreen></iframe>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -0,0 +1,236 @@
|
||||||
|
$( document ).ready( () => {
|
||||||
|
// warn the user when leaving
|
||||||
|
window.onbeforeunload = function(){
|
||||||
|
return "Make sure to save your graph locally before leaving";
|
||||||
|
};
|
||||||
|
|
||||||
|
$('body').scrollspy({ target: '#main-nav', offset: 130 })
|
||||||
|
|
||||||
|
$('#fullpage').fullpage({
|
||||||
|
// anchors: ['underPage', 'gradPage', 'phdPage'],
|
||||||
|
sectionsColor: ['#ffffff', '#f8f8f8'],
|
||||||
|
autoScrolling: false,
|
||||||
|
css3: true,
|
||||||
|
fitToSection: false,
|
||||||
|
afterLoad: function(anchorLink, index) {
|
||||||
|
// history.pushState(null, null, "");
|
||||||
|
// console.log(anchorLink);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize Console
|
||||||
|
ConsoleLogHTML.connect(document.getElementById("console")); // Redirect log messages
|
||||||
|
// ConsoleLogHTML.disconnect(); // Stop redirecting
|
||||||
|
|
||||||
|
// Navbar click scroll
|
||||||
|
$(".navbar a").on('click', function(event) {
|
||||||
|
// Make sure this.hash has a value before overriding default behavior
|
||||||
|
if (this.hash !== "") {
|
||||||
|
// Prevent default anchor click behavior
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
// Store hash
|
||||||
|
var hash = this.hash;
|
||||||
|
|
||||||
|
// Using jQuery's animate() method to add smooth page scroll
|
||||||
|
// The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
|
||||||
|
var offset = 0;
|
||||||
|
if (hash === "#home")
|
||||||
|
{
|
||||||
|
offset = -100;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
offset = -60;
|
||||||
|
}
|
||||||
|
$('html, body').animate({
|
||||||
|
scrollTop: ($(hash).offset().top + offset)
|
||||||
|
}, 1000, function(){
|
||||||
|
// Add hash (#) to URL when done scrolling (default click behavior)
|
||||||
|
// window.location.hash = hash;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#submission_info').hide();
|
||||||
|
|
||||||
|
$('#ulysses16_submit').hide();
|
||||||
|
$('#att48_submit').hide();
|
||||||
|
$('#st70_submit').hide();
|
||||||
|
$('#a280_submit').hide();
|
||||||
|
$('#pcb442_submit').hide();
|
||||||
|
$('#dsj1000_submit').hide();
|
||||||
|
|
||||||
|
$( "#ulysses16_submit" ).click(function() {
|
||||||
|
upload_leaderboard('ulysses16');
|
||||||
|
$('#ulysses16_submit').removeClass('btn-primary');
|
||||||
|
$('#ulysses16_submit').text('Submitted');
|
||||||
|
$('#ulysses16_submit').prop('disabled', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
$( "#att48_submit" ).click(function() {
|
||||||
|
upload_leaderboard('att48');
|
||||||
|
$('#att48_submit').removeClass('btn-primary');
|
||||||
|
$('#att48_submit').text('Submitted');
|
||||||
|
$('#att48_submit').prop('disabled', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
$( "#st70_submit" ).click(function() {
|
||||||
|
upload_leaderboard('st70');
|
||||||
|
$('#st70_submit').removeClass('btn-primary');
|
||||||
|
$('#st70_submit').text('Submitted');
|
||||||
|
$('#st70_submit').prop('disabled', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
$( "#a280_submit" ).click(function() {
|
||||||
|
upload_leaderboard('a280');
|
||||||
|
$('#a280_submit').removeClass('btn-primary');
|
||||||
|
$('#a280_submit').text('Submitted');
|
||||||
|
$('#a280_submit').prop('disabled', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
$( "#pcb442_submit" ).click(function() {
|
||||||
|
upload_leaderboard('pcb442');
|
||||||
|
$('#pcb442_submit').removeClass('btn-primary');
|
||||||
|
$('#pcb442_submit').text('Submitted');
|
||||||
|
$('#pcb442_submit').prop('disabled', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
$( "#dsj1000_submit" ).click(function() {
|
||||||
|
upload_leaderboard('dsj1000');
|
||||||
|
$('#dsj1000_submit').removeClass('btn-primary');
|
||||||
|
$('#dsj1000_submit').text('Submitted');
|
||||||
|
$('#dsj1000_submit').prop('disabled', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize file uploader
|
||||||
|
// initialize with defaults
|
||||||
|
// $("#uploadfile").fileinput();
|
||||||
|
|
||||||
|
// with plugin options
|
||||||
|
$("#uploadfile").fileinput({
|
||||||
|
// theme: "fa",
|
||||||
|
'theme': 'fas',
|
||||||
|
showUpload:false,
|
||||||
|
previewFileType:'py',
|
||||||
|
maxFileCount: 1,
|
||||||
|
allowedFileExtensions: ["py"]
|
||||||
|
});
|
||||||
|
|
||||||
|
var url = window.location;
|
||||||
|
|
||||||
|
// GET REQUEST
|
||||||
|
$("#btnGetFiles").click( (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
ajaxGet();
|
||||||
|
});
|
||||||
|
|
||||||
|
// DO GET
|
||||||
|
function ajaxGet(){
|
||||||
|
$.ajax({
|
||||||
|
type : "GET",
|
||||||
|
url : "/api/files/getall",
|
||||||
|
success: (data) => {
|
||||||
|
// clear old data
|
||||||
|
$("#listFiles").html("");
|
||||||
|
// render list of files
|
||||||
|
$("#listFiles").append('<ul>');
|
||||||
|
$.each(data, (index, filename) => {
|
||||||
|
$("#listFiles").append('<li><a href=' + url + 'api/files/' + filename +'>' + filename + '</a></li>');
|
||||||
|
});
|
||||||
|
$("#listFiles").append('</ul>');
|
||||||
|
},
|
||||||
|
error : (err) => {
|
||||||
|
$("#listFiles").html(err.responseText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload File
|
||||||
|
$('#uploadfile').change(function(e){
|
||||||
|
if(e.target.files[0])
|
||||||
|
{
|
||||||
|
var fileName = e.target.files[0].name;
|
||||||
|
if(fileName !== "my_model.py")
|
||||||
|
{
|
||||||
|
alert('Please upload my_model.py');
|
||||||
|
$('#btnSubmit').prop('disabled', true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$('#btnSubmit').prop('disabled', false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Submit results
|
||||||
|
$("#btnSubmit").click((event) => {
|
||||||
|
// stop submit the form, we will post it manually.
|
||||||
|
event.preventDefault();
|
||||||
|
doAjax();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
function upload_leaderboard(name) {
|
||||||
|
obj = {}
|
||||||
|
obj.name = name;
|
||||||
|
data = {}
|
||||||
|
if(name === 'ulysses16') {
|
||||||
|
data.fitness = my_res.ulysses16.fitness;
|
||||||
|
}
|
||||||
|
else if (name === 'att48') {
|
||||||
|
data.fitness = my_res.att48.fitness;
|
||||||
|
}
|
||||||
|
else if (name === 'st70') {
|
||||||
|
data.fitness = my_res.st70.fitness;
|
||||||
|
}
|
||||||
|
else if (name === 'a280') {
|
||||||
|
data.fitness = my_res.a280.fitness;
|
||||||
|
}
|
||||||
|
else if (name === 'pcb442') {
|
||||||
|
data.fitness = my_res.pcb442.fitness;
|
||||||
|
}
|
||||||
|
else if (name === 'dsj1000') {
|
||||||
|
data.fitness = my_res.dsj1000.fitness;
|
||||||
|
}
|
||||||
|
data.name = $('#submit_name').val();
|
||||||
|
data.desc = $('#submit_desc').val()
|
||||||
|
data.time = Date.now()
|
||||||
|
obj.data = data;
|
||||||
|
socket.emit('submit', obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
function doAjax() {
|
||||||
|
// Get form
|
||||||
|
var form = $('#fileUploadForm')[0];
|
||||||
|
|
||||||
|
var data = new FormData(form);
|
||||||
|
var file = data.get('uploadfile');
|
||||||
|
|
||||||
|
var renameFile =new File([file], window.id + '.py' ,{type:file.type});
|
||||||
|
var formdata = new FormData();
|
||||||
|
|
||||||
|
formdata.append('uploadfile', renameFile);
|
||||||
|
|
||||||
|
if(window.id) {
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
enctype: 'multipart/form-data',
|
||||||
|
url: "/api/files/upload",
|
||||||
|
data: formdata,
|
||||||
|
processData: false, //prevent jQuery from automatically transforming the data into a query string
|
||||||
|
contentType: false,
|
||||||
|
cache: false,
|
||||||
|
success: (data) => {
|
||||||
|
console.log('Emit build request')
|
||||||
|
socket.emit('build', {});
|
||||||
|
},
|
||||||
|
error: (e) => {
|
||||||
|
$("#listFiles").text(e.responseText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alert('Failed to connect to server');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,3 @@
|
||||||
// warn the user when leaving
|
|
||||||
window.onbeforeunload = function(){
|
|
||||||
return "Make sure to save your graph locally before leaving";
|
|
||||||
};
|
|
||||||
|
|
||||||
var my_res = {};
|
var my_res = {};
|
||||||
my_res.ulysses16 = {}
|
my_res.ulysses16 = {}
|
||||||
|
|
@ -20,28 +16,32 @@ my_res.dsj1000.fitness = -1;
|
||||||
|
|
||||||
var socket = io();
|
var socket = io();
|
||||||
|
|
||||||
|
// User connected
|
||||||
socket.on('connect', () => {
|
socket.on('connect', () => {
|
||||||
$("#status").removeClass('badge-secondary');
|
$("#status").removeClass('badge-secondary');
|
||||||
$("#status").addClass('badge-primary');
|
$("#status").addClass('badge-primary');
|
||||||
window.id = socket.id
|
window.id = socket.id
|
||||||
console.log('Session Id: ', socket.id); // an alphanumeric id...
|
console.log('Session Id: ', socket.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// User disconnected
|
||||||
socket.on('disconnect', () => {
|
socket.on('disconnect', () => {
|
||||||
$("#status").removeClass('badge-primary');
|
$("#status").removeClass('badge-primary');
|
||||||
$("#status").addClass('badge-secondary');
|
$("#status").addClass('badge-secondary');
|
||||||
$("#status").text('offline');
|
$("#status").text('offline');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update online users
|
||||||
socket.on('users_count', (clients) => {
|
socket.on('users_count', (clients) => {
|
||||||
$("#status").text(clients + ' online');
|
$("#status").text(clients + ' online');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Server running algorithms
|
||||||
socket.on('start', () => {
|
socket.on('start', () => {
|
||||||
console.log('Building start');
|
console.log('Building start');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update Leaderboard Table
|
||||||
socket.on('leaderboard', (obj) => {
|
socket.on('leaderboard', (obj) => {
|
||||||
console.log(obj);
|
console.log(obj);
|
||||||
$(".leaderboard-table").find("tr:not(:first):not(:last)").remove();
|
$(".leaderboard-table").find("tr:not(:first):not(:last)").remove();
|
||||||
|
|
@ -88,7 +88,8 @@ socket.on('leaderboard', (obj) => {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('update', (msg) => {
|
// Log info in console
|
||||||
|
socket.on('info', (msg) => {
|
||||||
// var msg = msg.replace(/\x1b[[0-9;]*[a-zA-Z]/g, '');
|
// var msg = msg.replace(/\x1b[[0-9;]*[a-zA-Z]/g, '');
|
||||||
msg = msg.replace(/[^\x20-\x7E]/g, '')
|
msg = msg.replace(/[^\x20-\x7E]/g, '')
|
||||||
if(msg[1] == '[') {
|
if(msg[1] == '[') {
|
||||||
|
|
@ -97,130 +98,52 @@ socket.on('update', (msg) => {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update personal result
|
||||||
socket.on('result', (res) => {
|
socket.on('result', (res) => {
|
||||||
// console.log(res)
|
|
||||||
res = JSON.parse(res);
|
res = JSON.parse(res);
|
||||||
$('#submission_info').show();
|
$('#submission_info').show();
|
||||||
res.forEach(e => {
|
res.forEach(e => {
|
||||||
if(e.name === "ulysses16.txt") {
|
if(e.name === "ulysses16.txt") {
|
||||||
my_res.ulysses16.fitness = e.fitness
|
my_res.ulysses16.fitness = e.fitness
|
||||||
$("#ulysses16_your").text(e.fitness);
|
$("#ulysses16_your").text(e.fitness);
|
||||||
|
if(e.fitness > 0) {
|
||||||
$('#ulysses16_submit').show();
|
$('#ulysses16_submit').show();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(e.name === "att48.txt") {
|
if(e.name === "att48.txt") {
|
||||||
my_res.att48.fitness = e.fitness
|
my_res.att48.fitness = e.fitness
|
||||||
$("#att48_your").text(e.fitness);
|
$("#att48_your").text(e.fitness);
|
||||||
|
if(e.fitness > 0) {
|
||||||
$('#att48_submit').show();
|
$('#att48_submit').show();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(e.name === "st70.txt") {
|
if(e.name === "st70.txt") {
|
||||||
my_res.st70.fitness = e.fitness
|
my_res.st70.fitness = e.fitness
|
||||||
$("#st70_your").text(e.fitness)
|
$("#st70_your").text(e.fitness)
|
||||||
|
if(e.fitness > 0) {
|
||||||
$('#st70_submit').show();
|
$('#st70_submit').show();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(e.name === "a280.txt") {
|
if(e.name === "a280.txt") {
|
||||||
my_res.a280.fitness = e.fitness
|
my_res.a280.fitness = e.fitness
|
||||||
$("#a280_your").text(e.fitness)
|
$("#a280_your").text(e.fitness)
|
||||||
|
if(e.fitness > 0) {
|
||||||
$('#a280_submit').show();
|
$('#a280_submit').show();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(e.name === "pcb442.txt") {
|
if(e.name === "pcb442.txt") {
|
||||||
my_res.pcb442.fitness = e.fitness
|
my_res.pcb442.fitness = e.fitness
|
||||||
$("#pcb442_your").text(e.fitness)
|
$("#pcb442_your").text(e.fitness)
|
||||||
|
if(e.fitness > 0) {
|
||||||
$('#pcb442_submit').show();
|
$('#pcb442_submit').show();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(e.name === "dsj1000.txt") {
|
if(e.name === "dsj1000.txt") {
|
||||||
my_res.dsj1000.fitness = e.fitness
|
my_res.dsj1000.fitness = e.fitness
|
||||||
$("#dsj1000_your").text(e.fitness)
|
$("#dsj1000_your").text(e.fitness)
|
||||||
|
if(e.fitness > 0) {
|
||||||
$('#dsj1000_submit').show();
|
$('#dsj1000_submit').show();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).ready( () => {
|
|
||||||
$("#btnSubmit").click((event) => {
|
|
||||||
//stop submit the form, we will post it manually.
|
|
||||||
event.preventDefault();
|
|
||||||
doAjax();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#uploadfile').change(function(e){
|
|
||||||
if(e.target.files[0])
|
|
||||||
{
|
|
||||||
var fileName = e.target.files[0].name;
|
|
||||||
if(fileName !== "my_model.py")
|
|
||||||
{
|
|
||||||
alert('Please upload my_model.py');
|
|
||||||
$('#btnSubmit').prop('disabled', true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$('#btnSubmit').prop('disabled', false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function upload_loaderboard(name) {
|
|
||||||
obj = {}
|
|
||||||
obj.name = name;
|
|
||||||
data = {}
|
|
||||||
if(name === 'ulysses16') {
|
|
||||||
data.fitness = my_res.ulysses16.fitness;
|
|
||||||
}
|
|
||||||
else if (name === 'att48') {
|
|
||||||
data.fitness = my_res.att48.fitness;
|
|
||||||
}
|
|
||||||
else if (name === 'st70') {
|
|
||||||
data.fitness = my_res.st70.fitness;
|
|
||||||
}
|
|
||||||
else if (name === 'a280') {
|
|
||||||
data.fitness = my_res.a280.fitness;
|
|
||||||
}
|
|
||||||
else if (name === 'pcb442') {
|
|
||||||
data.fitness = my_res.pcb442.fitness;
|
|
||||||
}
|
|
||||||
else if (name === 'dsj1000') {
|
|
||||||
data.fitness = my_res.dsj1000.fitness;
|
|
||||||
}
|
|
||||||
data.name = $('#submit_name').val();
|
|
||||||
data.desc = $('#submit_desc').val()
|
|
||||||
data.time = Date.now()
|
|
||||||
obj.data = data;
|
|
||||||
socket.emit('submit', obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
function doAjax() {
|
|
||||||
|
|
||||||
// Get form
|
|
||||||
var form = $('#fileUploadForm')[0];
|
|
||||||
|
|
||||||
var data = new FormData(form);
|
|
||||||
var file = data.get('uploadfile');
|
|
||||||
|
|
||||||
var renameFile =new File([file], window.id + '.py' ,{type:file.type});
|
|
||||||
var formdata = new FormData();
|
|
||||||
formdata.append('uploadfile', renameFile);
|
|
||||||
// console.log(formdata.get('uploadfile'))
|
|
||||||
if(window.id) {
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
enctype: 'multipart/form-data',
|
|
||||||
url: "/api/files/upload",
|
|
||||||
data: formdata,
|
|
||||||
processData: false, //prevent jQuery from automatically transforming the data into a query string
|
|
||||||
contentType: false,
|
|
||||||
cache: false,
|
|
||||||
success: (data) => {
|
|
||||||
// $("#listFiles").text(data);
|
|
||||||
console.log('Emit build request')
|
|
||||||
socket.emit('build', {});
|
|
||||||
},
|
|
||||||
error: (e) => {
|
|
||||||
$("#listFiles").text(e.responseText);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
alert('Failed to connect to server');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
|
|
||||||
<title>Document</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<h1>Hello</h1>
|
|
||||||
<div class="ratio ratio-16x9">
|
|
||||||
<iframe src="preview.html" title="YouTube video" allowfullscreen></iframe>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<section>
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<h1>Leader</h1>
|
|
||||||
<label for="formFileLg" class="form-label">Large file input example</label>
|
|
||||||
<input class="form-control form-control-lg" id="formFileLg" type="file" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,142 +0,0 @@
|
||||||
$( document ).ready( () => {
|
|
||||||
|
|
||||||
$('body').scrollspy({ target: '#main-nav', offset: 130 })
|
|
||||||
|
|
||||||
$('#fullpage').fullpage({
|
|
||||||
// anchors: ['underPage', 'gradPage', 'phdPage'],
|
|
||||||
sectionsColor: ['#ffffff', '#f8f8f8'],
|
|
||||||
autoScrolling: false,
|
|
||||||
css3: true,
|
|
||||||
fitToSection: false,
|
|
||||||
afterLoad: function(anchorLink, index) {
|
|
||||||
// history.pushState(null, null, "");
|
|
||||||
// console.log(anchorLink);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$(".navbar a").on('click', function(event) {
|
|
||||||
// Make sure this.hash has a value before overriding default behavior
|
|
||||||
if (this.hash !== "") {
|
|
||||||
// Prevent default anchor click behavior
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
// Store hash
|
|
||||||
var hash = this.hash;
|
|
||||||
|
|
||||||
// Using jQuery's animate() method to add smooth page scroll
|
|
||||||
// The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
|
|
||||||
var offset = 0;
|
|
||||||
if (hash === "#home")
|
|
||||||
{
|
|
||||||
offset = -100;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
offset = -60;
|
|
||||||
}
|
|
||||||
$('html, body').animate({
|
|
||||||
scrollTop: ($(hash).offset().top + offset)
|
|
||||||
}, 1000, function(){
|
|
||||||
// Add hash (#) to URL when done scrolling (default click behavior)
|
|
||||||
// window.location.hash = hash;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#submission_info').hide();
|
|
||||||
$('#ulysses16_submit').hide();
|
|
||||||
$('#att48_submit').hide();
|
|
||||||
$('#st70_submit').hide();
|
|
||||||
$('#a280_submit').hide();
|
|
||||||
$('#pcb442_submit').hide();
|
|
||||||
$('#dsj1000_submit').hide();
|
|
||||||
|
|
||||||
$( "#ulysses16_submit" ).click(function() {
|
|
||||||
upload_loaderboard('ulysses16');
|
|
||||||
$('#ulysses16_submit').removeClass('btn-primary');
|
|
||||||
$('#ulysses16_submit').text('Submitted');
|
|
||||||
$('#ulysses16_submit').prop('disabled', true);
|
|
||||||
});
|
|
||||||
|
|
||||||
$( "#att48_submit" ).click(function() {
|
|
||||||
upload_loaderboard('att48');
|
|
||||||
$('#att48_submit').removeClass('btn-primary');
|
|
||||||
$('#att48_submit').text('Submitted');
|
|
||||||
$('#att48_submit').prop('disabled', true);
|
|
||||||
});
|
|
||||||
|
|
||||||
$( "#st70_submit" ).click(function() {
|
|
||||||
upload_loaderboard('st70');
|
|
||||||
$('#st70_submit').removeClass('btn-primary');
|
|
||||||
$('#st70_submit').text('Submitted');
|
|
||||||
$('#st70_submit').prop('disabled', true);
|
|
||||||
});
|
|
||||||
|
|
||||||
$( "#a280_submit" ).click(function() {
|
|
||||||
upload_loaderboard('a280');
|
|
||||||
$('#a280_submit').removeClass('btn-primary');
|
|
||||||
$('#a280_submit').text('Submitted');
|
|
||||||
$('#a280_submit').prop('disabled', true);
|
|
||||||
});
|
|
||||||
|
|
||||||
$( "#pcb442_submit" ).click(function() {
|
|
||||||
upload_loaderboard('pcb442');
|
|
||||||
$('#pcb442_submit').removeClass('btn-primary');
|
|
||||||
$('#pcb442_submit').text('Submitted');
|
|
||||||
$('#pcb442_submit').prop('disabled', true);
|
|
||||||
});
|
|
||||||
|
|
||||||
$( "#dsj1000_submit" ).click(function() {
|
|
||||||
upload_loaderboard('dsj1000');
|
|
||||||
$('#dsj1000_submit').removeClass('btn-primary');
|
|
||||||
$('#dsj1000_submit').text('Submitted');
|
|
||||||
$('#dsj1000_submit').prop('disabled', true);
|
|
||||||
});
|
|
||||||
|
|
||||||
// initialize with defaults
|
|
||||||
// $("#uploadfile").fileinput();
|
|
||||||
|
|
||||||
// with plugin options
|
|
||||||
$("#uploadfile").fileinput({
|
|
||||||
// theme: "fa",
|
|
||||||
'theme': 'fas',
|
|
||||||
showUpload:false,
|
|
||||||
previewFileType:'py',
|
|
||||||
maxFileCount: 1,
|
|
||||||
allowedFileExtensions: ["py"]
|
|
||||||
});
|
|
||||||
|
|
||||||
ConsoleLogHTML.connect(document.getElementById("console")); // Redirect log messages
|
|
||||||
// ConsoleLogHTML.disconnect(); // Stop redirecting
|
|
||||||
|
|
||||||
var url = window.location;
|
|
||||||
|
|
||||||
// GET REQUEST
|
|
||||||
$("#btnGetFiles").click( (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
ajaxGet();
|
|
||||||
});
|
|
||||||
|
|
||||||
// DO GET
|
|
||||||
function ajaxGet(){
|
|
||||||
$.ajax({
|
|
||||||
type : "GET",
|
|
||||||
url : "/api/files/getall",
|
|
||||||
success: (data) => {
|
|
||||||
//clear old data
|
|
||||||
$("#listFiles").html("");
|
|
||||||
|
|
||||||
/*
|
|
||||||
render list of files
|
|
||||||
*/
|
|
||||||
$("#listFiles").append('<ul>');
|
|
||||||
$.each(data, (index, filename) => {
|
|
||||||
$("#listFiles").append('<li><a href=' + url + 'api/files/' + filename +'>' + filename + '</a></li>');
|
|
||||||
});
|
|
||||||
$("#listFiles").append('</ul>');
|
|
||||||
},
|
|
||||||
error : (err) => {
|
|
||||||
$("#listFiles").html(err.responseText);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
219
server.js
|
|
@ -1,28 +1,32 @@
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
|
|
||||||
|
// Web Server
|
||||||
var express = require('express')
|
var express = require('express')
|
||||||
var app = express()
|
var app = express()
|
||||||
var router = express.Router()
|
var router = express.Router()
|
||||||
|
|
||||||
|
// Upload Files
|
||||||
var upload = require('./app/config/multer.config.js')
|
var upload = require('./app/config/multer.config.js')
|
||||||
|
|
||||||
const {Docker} = require('node-docker-api')
|
// Static Website
|
||||||
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'))
|
app.use(express.static('resources'))
|
||||||
|
|
||||||
var http = require('http').createServer(app)
|
var http = require('http').createServer(app)
|
||||||
var io = require('socket.io')(http)
|
var io = require('socket.io')(http)
|
||||||
|
|
||||||
var readlineSync = require('readline-sync');
|
// Docker Container
|
||||||
|
const {Docker} = require('node-docker-api')
|
||||||
|
const docker = new Docker({ socketPath: '/var/run/docker.sock' })
|
||||||
|
|
||||||
const path = require('path');
|
// Console Log
|
||||||
|
const stripAnsi = require('strip-ansi')
|
||||||
|
|
||||||
|
// Set up directories
|
||||||
|
global.__basedir = __dirname
|
||||||
|
const path = require('path')
|
||||||
current_path = process.cwd()
|
current_path = process.cwd()
|
||||||
|
|
||||||
|
// Initialize Leaderboard
|
||||||
var leaderboard = {}
|
var leaderboard = {}
|
||||||
leaderboard.ulysses16 = []
|
leaderboard.ulysses16 = []
|
||||||
leaderboard.att48 = []
|
leaderboard.att48 = []
|
||||||
|
|
@ -31,7 +35,31 @@ leaderboard.a280 = []
|
||||||
leaderboard.pcb442 = []
|
leaderboard.pcb442 = []
|
||||||
leaderboard.dsj1000 = []
|
leaderboard.dsj1000 = []
|
||||||
|
|
||||||
|
var write_leaderboard = () => {
|
||||||
|
fs.writeFile('leaderboard.json', JSON.stringify(leaderboard), (err) => {
|
||||||
|
if (err) throw err
|
||||||
|
console.log('Data written to file')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read from JSON file first if exists
|
||||||
|
try {
|
||||||
|
if (fs.existsSync('leaderboard.json')) {
|
||||||
|
//file exists
|
||||||
|
console.log("Existed leaderboard")
|
||||||
|
leaderboard = require('./leaderboard.json')
|
||||||
|
console.log(leaderboard)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
write_leaderboard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
|
||||||
var update_leaderboard = (obj) => {
|
var update_leaderboard = (obj) => {
|
||||||
|
// Update each TSP entry
|
||||||
if(obj.name === 'ulysses16') {
|
if(obj.name === 'ulysses16') {
|
||||||
leaderboard.ulysses16.push(obj.data)
|
leaderboard.ulysses16.push(obj.data)
|
||||||
}
|
}
|
||||||
|
|
@ -50,6 +78,8 @@ var update_leaderboard = (obj) => {
|
||||||
else if (obj.name === 'dsj1000') {
|
else if (obj.name === 'dsj1000') {
|
||||||
leaderboard.dsj1000.push(obj.data)
|
leaderboard.dsj1000.push(obj.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only accept top 10 results
|
||||||
leaderboard.ulysses16.sort(function(a, b){return a.fitness - b.fitness})
|
leaderboard.ulysses16.sort(function(a, b){return a.fitness - b.fitness})
|
||||||
leaderboard.ulysses16 = leaderboard.ulysses16.slice(0,10)
|
leaderboard.ulysses16 = leaderboard.ulysses16.slice(0,10)
|
||||||
|
|
||||||
|
|
@ -68,69 +98,45 @@ var update_leaderboard = (obj) => {
|
||||||
leaderboard.dsj1000.sort(function(a, b){return a.fitness - b.fitness})
|
leaderboard.dsj1000.sort(function(a, b){return a.fitness - b.fitness})
|
||||||
leaderboard.dsj1000 = leaderboard.dsj1000.slice(0,10)
|
leaderboard.dsj1000 = leaderboard.dsj1000.slice(0,10)
|
||||||
|
|
||||||
|
// Write to json file
|
||||||
write_leaderboard()
|
write_leaderboard()
|
||||||
}
|
}
|
||||||
|
|
||||||
var write_leaderboard = () => {
|
// Get submission results
|
||||||
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) => {
|
var update_submission = (socket, sessionID) => {
|
||||||
console.log('check result')
|
|
||||||
var output_dir = current_path.toString() + '/output/' + sessionID + '/'
|
var output_dir = current_path.toString() + '/output/' + sessionID + '/'
|
||||||
console.log(output_dir)
|
console.log(output_dir)
|
||||||
if (output_dir.length != 0)
|
if (output_dir.length != 0)
|
||||||
{
|
{
|
||||||
res = []
|
var res = []
|
||||||
socket.emit('update', 'Got output')
|
socket.emit('info', 'Got output')
|
||||||
|
|
||||||
|
// Read output dir
|
||||||
fs.readdir(output_dir, (err, files) => {
|
fs.readdir(output_dir, (err, files) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log(err);
|
console.log(err)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
console.log('iterate')
|
|
||||||
|
|
||||||
|
// Read each result in txt file
|
||||||
files.forEach(file => {
|
files.forEach(file => {
|
||||||
console.log(file)
|
|
||||||
console.log(path.extname(file))
|
|
||||||
if (path.extname(file) === '.txt') {
|
if (path.extname(file) === '.txt') {
|
||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
|
|
||||||
|
// Result object
|
||||||
var obj = {}
|
var obj = {}
|
||||||
obj.name = file
|
obj.name = file
|
||||||
console.log(output_dir + file)
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// read contents of the file
|
// read contents of the file
|
||||||
const data = fs.readFileSync(output_dir + file, 'UTF-8');
|
const data = fs.readFileSync(output_dir + file, 'UTF-8')
|
||||||
|
|
||||||
// split the contents by new line
|
// split the contents by new line
|
||||||
const lines = data.split(/\r?\n/);
|
const lines = data.split(/\r?\n/)
|
||||||
|
|
||||||
// print all lines
|
|
||||||
lines.forEach((line) => {
|
lines.forEach((line) => {
|
||||||
console.log(line)
|
|
||||||
i = i + 1
|
i = i + 1
|
||||||
// console.log(line)
|
// The first line is the fitness
|
||||||
if(i == 1) {
|
if(i == 1) {
|
||||||
var fitness = parseFloat(line)
|
var fitness = parseFloat(line)
|
||||||
if(fitness < 0) {
|
if(fitness < 0) {
|
||||||
|
|
@ -140,11 +146,13 @@ var update_submission = (socket, sessionID) => {
|
||||||
obj.fitness = fitness
|
obj.fitness = fitness
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// The second line is the path
|
||||||
else if (i == 2) {
|
else if (i == 2) {
|
||||||
|
// Only read when there is no error
|
||||||
if(obj.fitness > 0) {
|
if(obj.fitness > 0) {
|
||||||
solution_array = line.split(",");
|
solution_array = line.split(",")
|
||||||
for(var j = 0; j < solution_array.length; j++) {
|
for(var j = 0; j < solution_array.length; j++) {
|
||||||
solution_array[i] = parseInt(solution_array[i], 10);
|
solution_array[i] = parseInt(solution_array[i], 10)
|
||||||
}
|
}
|
||||||
obj.solution = solution_array
|
obj.solution = solution_array
|
||||||
}
|
}
|
||||||
|
|
@ -152,21 +160,20 @@ var update_submission = (socket, sessionID) => {
|
||||||
obj.solution = []
|
obj.solution = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err)
|
||||||
}
|
}
|
||||||
res.push(obj)
|
res.push(obj)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
// console.log(res)
|
|
||||||
socket.emit('result', JSON.stringify(res))
|
socket.emit('result', JSON.stringify(res))
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log('no result')
|
console.log('no result')
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
var docker_build = (socket, sessionID) => {
|
var docker_build = (socket, sessionID) => {
|
||||||
|
|
@ -174,41 +181,10 @@ var docker_build = (socket, sessionID) => {
|
||||||
socket.emit('start')
|
socket.emit('start')
|
||||||
|
|
||||||
fs.mkdir(current_path + '/output/' + sessionID.toString(), () => {
|
fs.mkdir(current_path + '/output/' + sessionID.toString(), () => {
|
||||||
socket.emit('update', 'Output directort created.')
|
socket.emit('info', 'Output directort created.')
|
||||||
socket.emit('update', 'Test started, this may take a while.')
|
socket.emit('info', '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: [
|
|
||||||
'/uploads/' + sessionID.toString() + '/requirements.txt:/tsp/requirements.txt',
|
|
||||||
'/uploads/' + sessionID.toString() + '/my_model.py:/tsp/model/my_model.py',
|
|
||||||
"/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({
|
docker.container.create({
|
||||||
Image: 'com2014-tsp',
|
Image: 'com2014-tsp',
|
||||||
HostConfig: {
|
HostConfig: {
|
||||||
|
|
@ -219,8 +195,9 @@ var docker_build = (socket, sessionID) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then( (container) => {
|
.then( (container) => {
|
||||||
|
// Start container
|
||||||
container_id = container.data.Id
|
container_id = container.data.Id
|
||||||
socket.emit('update','Container Id: ' + container_id)
|
socket.emit('info','Container Id: ' + container_id)
|
||||||
return container.start()
|
return container.start()
|
||||||
})
|
})
|
||||||
.then(container => container.logs({
|
.then(container => container.logs({
|
||||||
|
|
@ -229,76 +206,92 @@ var docker_build = (socket, sessionID) => {
|
||||||
stderr: true
|
stderr: true
|
||||||
}))
|
}))
|
||||||
.then(stream => {
|
.then(stream => {
|
||||||
|
// Write container logs to client
|
||||||
stream.on('data', (info) => {
|
stream.on('data', (info) => {
|
||||||
console.log(stripAnsi(new Buffer.from(info).toString()))
|
console.log(stripAnsi(new Buffer.from(info).toString()))
|
||||||
socket.emit('update', stripAnsi(new Buffer.from(info).toString('ascii')))
|
socket.emit('info', stripAnsi(new Buffer.from(info).toString('ascii')))
|
||||||
}),
|
}),
|
||||||
stream.on('error', err => console.log(err))
|
stream.on('error', (err) => {
|
||||||
|
console.log(err)
|
||||||
|
socket.emit('info', stripAnsi(new Buffer.from(err).toString('ascii')))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.catch(error => console.log(error))
|
.catch(error => console.log(error))
|
||||||
}
|
|
||||||
|
|
||||||
var intervalObj;
|
// Check if container is still running
|
||||||
var timeoutObj;
|
var intervalObj
|
||||||
|
|
||||||
|
// Timeout (each container runs only for 60s at most)
|
||||||
|
var timeoutObj
|
||||||
|
|
||||||
|
var finished = false
|
||||||
|
|
||||||
|
// Check if container is still running
|
||||||
intervalObj = setInterval(() => {
|
intervalObj = setInterval(() => {
|
||||||
if(!finished)
|
if(!finished)
|
||||||
{
|
{
|
||||||
docker.container.list({all:true})
|
docker.container.list({all:true})
|
||||||
// Inspect
|
|
||||||
.then((containers) => {
|
.then((containers) => {
|
||||||
containers.forEach(container => {
|
containers.forEach(container => {
|
||||||
if(container.data.Id == container_id) {
|
if(container.data.Id == container_id) {
|
||||||
socket.emit('update', 'Container Status: ' + container.data.State)
|
socket.emit('info', 'Container Status: ' + container.data.State)
|
||||||
if(container.data.State === 'exited')
|
if(container.data.State === 'exited')
|
||||||
{
|
{
|
||||||
finished = true;
|
// Finished Running
|
||||||
clearInterval(intervalObj);
|
finished = true
|
||||||
clearTimeout(timeoutObj);
|
clearInterval(intervalObj)
|
||||||
socket.emit('update', 'Test end')
|
clearTimeout(timeoutObj)
|
||||||
update_submission(socket, sessionID);
|
socket.emit('info', 'Container exited')
|
||||||
|
// Get submission results
|
||||||
|
update_submission(socket, sessionID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
})
|
})
|
||||||
.catch(error => console.log(error))
|
.catch(error => console.log(error))
|
||||||
}
|
}
|
||||||
}, 2000);
|
}, 2000)
|
||||||
|
|
||||||
var finished = false
|
// Timeout (each container runs only for 60s at most)
|
||||||
// call the rest of the code and have it execute after 3 seconds
|
|
||||||
timeoutObj = setTimeout(() => {
|
timeoutObj = setTimeout(() => {
|
||||||
console.log('end')
|
console.log('end')
|
||||||
if(!finished)
|
if(!finished)
|
||||||
{
|
{
|
||||||
clearInterval(intervalObj);
|
clearInterval(intervalObj)
|
||||||
socket.emit('update', 'timeout')
|
socket.emit('info', 'timeout')
|
||||||
}
|
|
||||||
}, 20000)
|
|
||||||
}
|
}
|
||||||
|
}, 60000)
|
||||||
}
|
}
|
||||||
|
|
||||||
var clients = 0
|
var clients = 0
|
||||||
|
|
||||||
io.on('connection', (socket) => {
|
io.on('connection', (socket) => {
|
||||||
|
// New client connected
|
||||||
const sessionID = socket.id
|
const sessionID = socket.id
|
||||||
console.log('[client][connection]', sessionID)
|
console.log('[client][connection]', sessionID)
|
||||||
|
|
||||||
|
// Update client number
|
||||||
clients = clients + 1
|
clients = clients + 1
|
||||||
io.sockets.emit('users_count', clients)
|
io.sockets.emit('users_count', clients)
|
||||||
console.log(leaderboard)
|
|
||||||
|
// Inform new client the leaderboard
|
||||||
|
// console.log(leaderboard)
|
||||||
socket.emit('leaderboard', leaderboard)
|
socket.emit('leaderboard', leaderboard)
|
||||||
|
|
||||||
|
// Client disconnected
|
||||||
socket.on('disconnect', () => {
|
socket.on('disconnect', () => {
|
||||||
clients = clients - 1
|
clients = clients - 1
|
||||||
console.log('[client][disconnect]', sessionID)
|
console.log('[client][disconnect]', sessionID)
|
||||||
io.sockets.emit('users_count', clients)
|
io.sockets.emit('users_count', clients)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Client request a build
|
||||||
socket.on('build', () => {
|
socket.on('build', () => {
|
||||||
console.log('[client][build]', sessionID)
|
console.log('[client][build]', sessionID)
|
||||||
docker_build(socket, sessionID)
|
docker_build(socket, sessionID)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Client submited a new result
|
||||||
socket.on('submit', (obj) => {
|
socket.on('submit', (obj) => {
|
||||||
console.log('[client][submit]', sessionID)
|
console.log('[client][submit]', sessionID)
|
||||||
update_leaderboard(obj)
|
update_leaderboard(obj)
|
||||||
|
|
|
||||||