diff --git a/pytron_run/ai_manager/__init__.py b/pytron_run/ai_manager/__init__.py
deleted file mode 100644
index d2dd5e3..0000000
--- a/pytron_run/ai_manager/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from os.path import dirname, basename, isfile
-import glob
-modules = glob.glob(dirname(__file__)+"/*/ai.py")
-__all__ = ['.'.join(f.split('.')[:-1]) for f in modules if isfile(f)]
diff --git a/pytron_run/ai_manager/dummy/ai.py b/pytron_run/ai_manager/dummy/ai.py
deleted file mode 100644
index 9cdba62..0000000
--- a/pytron_run/ai_manager/dummy/ai.py
+++ /dev/null
@@ -1,11 +0,0 @@
-"""An AI to try things"""
-
-from tron.player import Player, Direction
-
-class Ai(Player):
- """" A basic AI"""
- def __init__(self):
- super(Ai, self).__init__()
-
- def action(self, map, id):
- return Direction.RIGHT
diff --git a/server.js b/server.js
index 51b4b45..0ea9bb3 100644
--- a/server.js
+++ b/server.js
@@ -127,6 +127,21 @@ function startServer() {
});
app.post('/upload-target', (req, res) => {
+
+ if (!req.body.name) {
+ res.render('error', {message: "You have to enter a name in the form"});
+ return;
+ }
+
+ if (req.body.name.indexOf('.') !== -1) {
+ res.render('error', {message: "The name of your AI can't contain dots"});
+ }
+
+ if (!req.files.archive) {
+ res.render('error', {message: "You have to send a ZIP archive"});
+ return;
+ }
+
let path = pathtools.join(aisPath, req.body.name)
try {
@@ -158,6 +173,8 @@ function startServer() {
req.files.archive.mv(zipfile, (err) => {
if (err != null) {
console.log(err);
+ res.render('error', {message: 'Unable to save the ZIP archive to the server'});
+ return;
}
fs.createReadStream(zipfile)
.pipe(unzip.Extract({path}))
@@ -170,7 +187,7 @@ function startServer() {
});
})
.on('error', () => {
- res.send('an error occured while extracting the archive')
+ res.render('error', {message: 'Failed to unzip the archive'});
});
});
});
diff --git a/views/error.pug b/views/error.pug
new file mode 100644
index 0000000..0eaf81d
--- /dev/null
+++ b/views/error.pug
@@ -0,0 +1,8 @@
+extends base
+
+block content
+ section.section
+ .container
+ .message.is-danger
+ .message-header An error occured
+ .message-body= message
diff --git a/views/upload.pug b/views/upload.pug
index 3ba5ba1..9a2a90d 100644
--- a/views/upload.pug
+++ b/views/upload.pug
@@ -1,14 +1,42 @@
extends base
+
block content
section.section
.container
.columns.is-centered
- .column.is-narrow.is-desktop
+ .column.is-6.is-desktop
form(action="upload-target", method="POST", encType="multipart/form-data")
.field
label.label Name
+ p.content.has-text-justified
+ | This name will be the name you will see on
+ | the leaderboard. It also corresponds to the
+ | name of the module your AI will be on the
+ | server.
+ p.content.has-text-justified
+ | You can use an already exisiting name to
+ | replace it with a new version of your AI.
+ p.content.has-text-justified
+ | You could also erase other people's AI, but
+ | please, don't do it, because I would be sad
+ | 😢
input.input(type="text", name="name", placeholder="Name of your AI")
.field
+ label.label Archive
+ p.content.has-text-justified
+ | The archive to upload needs to contain a file
+ | named ai.py
which must contain a
+ | class named Ai
which must contain
+ | a constructor that takes no arguments (other
+ | than self or optional arguments).
+ p.content.has-text-justified
+ | It may also contain more files, such as
+ | binary files with neural network weights, or
+ | such as other python modules.
+ p.content.has-text-justified
+ | Please note that this archive must not
+ | contain a directory, it must only contain the
+ | files.
.file.has-name
label.file-label
input.file-input(type="file", name="archive")
@@ -17,6 +45,6 @@ block content
i.fas.fa-upload
span.file-label Choose a file…
span.file-name
- .control
- button.button.is-link Submit
+ .field
+ input.button.is-link(type="submit", value="Submit")