diff --git a/pytron_run/refresh.py b/pytron_run/refresh.py index 621d6c1..33cbc01 100755 --- a/pytron_run/refresh.py +++ b/pytron_run/refresh.py @@ -13,6 +13,9 @@ from tron.player import Direction, ConstantPlayer import ai_manager from utils import run_battle +import time +time.sleep(5) + ASSETS_PATH = "assets/data.json" LAST_REFRESH_PATH = "assets/refresh.dat" diff --git a/server.js b/server.js index 091a0eb..23402d2 100644 --- a/server.js +++ b/server.js @@ -56,9 +56,7 @@ function runPython() { } }); } - // parsed.ais.push({ - // }); function parse(data) { let content = JSON.parse(data); let parsed = {ais: [], battles: {}}; @@ -118,6 +116,18 @@ function parse(data) { return parsed; } +function readData(req, res, callback) { + fs.readFile('pytron_run/assets/data.json', 'utf-8', (err, data) => { + if (err != null) { + console.log(err); + res.render('error', {message: 'It seems like the site is broken :\'('}); + return; + } + let parsed = parse(data); + callback(parsed); + }); +} + function saveArchiveAndRun(req, res) { let path = pathtools.join(aisPath, req.body.name); @@ -152,11 +162,7 @@ function startServer() { app.use(fileUpload()); app.get('/', (req, res) => { - fs.readFile('pytron_run/assets/data.json', 'utf-8', (err, data) => { - if (err != null) { - console.log(err); - } - let parsed = parse(data); + readData(req, res, (parsed) => { res.render('index', { data: parsed, running: pythonRunning, @@ -164,6 +170,32 @@ function startServer() { }); }); + app.get('/is-running', (req, res) => { + if (pythonRunning) { + res.send('yes'); + } else { + res.send('no'); + } + }); + + app.get('/leaderboard', (req, res) => { + readData(req, res, (parsed) => { + res.render('leaderboard', { + data: parsed, + running: pythonRunning, + }); + }); + }); + + app.get('/battles', (req, res) => { + readData(req, res, (parsed) => { + res.render('battles', { + data: parsed, + running: pythonRunning, + }); + }); + }); + app.get('/upload', (req, res) => { res.render('upload', {}); }); diff --git a/static/main.js b/static/main.js new file mode 100644 index 0000000..6c2212f --- /dev/null +++ b/static/main.js @@ -0,0 +1,60 @@ +function request(url, callback) { + let xhr = new XMLHttpRequest(); + xhr.onreadystatechange = () => { + if (xhr.readyState === XMLHttpRequest.DONE) { + if (xhr.status === 200) { + callback(xhr.responseText); + } + } + }; + + xhr.open('GET', url, true); + xhr.send(null); +} + +function refreshElement(element, url) { + request(url, (response) => { element.innerHTML = response }); +} + +function isRunning(callback) { + request('is-running', (response) => { + callback(response === 'yes'); + }); +} + +function refresh() { + refreshElement(document.getElementById('leaderboard'), 'leaderboard'); + refreshElement(document.getElementById('battles'), 'battles'); +} + + +function watch() { + isRunning((running) => { + if (running) { + setTimeout(watch, 1000); + } else { + isCurrentlyRunning = false; + refresh(); + runningElement.style.display = "None"; + } + }); +} + +function updateDots() { + dotsElement.innerHTML += "."; + if (dotsElement.innerHTML === "....") { + dotsElement.innerHTML = "."; + } + if (isCurrentlyRunning) { + setTimeout(updateDots, 500); + } +} + +let runningElement = document.getElementById('running'); +let dotsElement = document.getElementById('dots'); +let isCurrentlyRunning = runningElement.style.display === ''; + +if (isCurrentlyRunning) { + watch(); + updateDots(); +} diff --git a/views/base.pug b/views/base.pug index 228fc3e..e7b0494 100644 --- a/views/base.pug +++ b/views/base.pug @@ -35,3 +35,4 @@ html(lang='en') }); } }); + block extrajs diff --git a/views/battles.pug b/views/battles.pug new file mode 100644 index 0000000..99a7710 --- /dev/null +++ b/views/battles.pug @@ -0,0 +1,22 @@ +table.table.is-bordered.is-striped.is-narrow.is-hoverable + tr + th + for ai in data.ais + th.has-text-centered= ai.name + for ai1 in data.ais + tr + th.has-text-centered= ai1.name + for ai2 in data.ais + if ai1.name == ai2.name + td + else if data.battles[ai1.name + "/" + ai2.name] > data.battles[ai2.name + "/" + ai1.name] + td.has-text-centered.has-text-success= data.battles[ai1.name + "/" + ai2.name] + else if data.battles[ai1.name + "/" + ai2.name] < data.battles[ai2.name + "/" + ai1.name] + td.has-text-centered.has-text-danger= data.battles[ai1.name + "/" + ai2.name] + else + td.has-text-centered= data.battles[ai1.name + "/" + ai2.name] + +.columns.is-centered + .column.is-narrow + caption + strong All battles diff --git a/views/index.pug b/views/index.pug index 399090b..e65783f 100644 --- a/views/index.pug +++ b/views/index.pug @@ -7,64 +7,27 @@ block content section.section .container if running - .columns.is-centered - .column.is-narrow.is-desktop - h5.title.is-5 Some battles are running... + #running + .columns.is-centered + .column.is-3.is-desktop + h5.title.is-5 Some battles are running + span#dots ... + else + #running(style="display:none") + .columns.is-centered + .column.is-3.is-desktop + h5.title.is-5 Some battles are running + span#dots ... .columns.is-centered .column.is-narrow.is-desktop - table.table.is-bordered.is-striped.is-hoverable - tr - th.has-text-centered AI - th.has-text-centered Victories - th.has-text-centered Nulls - th.has-text-centered Defeats - th.has-text-centered Score - for ai in data.sortedAis - tr - td.has-text-centered - if ai.rank === 1 - span.icon - i.fas.fa-trophy(style="color:#FFD700") - else if ai.rank === 2 - span.icon - i.fas.fa-trophy(style="color:#C0C0C0") - else if ai.rank === 3 - span.icon - i.fas.fa-trophy(style="color:#CD7F32") - strong= ai.name - td.has-text-centered= ai.victories - td.has-text-centered= ai.nulls - td.has-text-centered= ai.defeats - td.has-text-centered - strong= ai.score - .columns.is-centered - .column.is-narrow - caption - strong Leaderboard + #leaderboard + include leaderboard .columns.is-centered .column.is-narrow.is-desktop - table.table.is-bordered.is-striped.is-narrow.is-hoverable - tr - th - for ai in data.ais - th.has-text-centered= ai.name - for ai1 in data.ais - tr - th.has-text-centered= ai1.name - for ai2 in data.ais - if ai1.name == ai2.name - td - else if data.battles[ai1.name + "/" + ai2.name] > data.battles[ai2.name + "/" + ai1.name] - td.has-text-centered.has-text-success= data.battles[ai1.name + "/" + ai2.name] - else if data.battles[ai1.name + "/" + ai2.name] < data.battles[ai2.name + "/" + ai1.name] - td.has-text-centered.has-text-danger= data.battles[ai1.name + "/" + ai2.name] - else - td.has-text-centered= data.battles[ai1.name + "/" + ai2.name] - .columns.is-centered - .column.is-narrow - caption - strong All battles - + #battles + include battles +block extrajs + script(src="static/main.js") diff --git a/views/leaderboard.pug b/views/leaderboard.pug new file mode 100644 index 0000000..1ec577f --- /dev/null +++ b/views/leaderboard.pug @@ -0,0 +1,30 @@ +table.table.is-bordered.is-striped.is-hoverable + tr + th.has-text-centered AI + th.has-text-centered Victories + th.has-text-centered Nulls + th.has-text-centered Defeats + th.has-text-centered Score + for ai in data.sortedAis + tr + td.has-text-centered + if ai.rank === 1 + span.icon + i.fas.fa-trophy(style="color:#FFD700") + else if ai.rank === 2 + span.icon + i.fas.fa-trophy(style="color:#C0C0C0") + else if ai.rank === 3 + span.icon + i.fas.fa-trophy(style="color:#CD7F32") + strong= ai.name + td.has-text-centered= ai.victories + td.has-text-centered= ai.nulls + td.has-text-centered= ai.defeats + td.has-text-centered + strong= ai.score +.columns.is-centered + .column.is-narrow + caption + strong Leaderboard +