Evaluation automatique de code Python (PDF Download Available)

2 downloads 5741 Views 379KB Size Report
Apr 17, 2016 - Official Full-Text Paper (PDF): Evaluation automatique de code Python. ... PuTTY http://www.chiark.greenend.org.uk/~sgtatham/putty/download. html .... After this my app in production started sending. emails. 8. [program:hello].
Évaluation de codes Python en ligne F. Kany. ISEN-Brest & La Croix-Rouge 17 avril 2016

Table des matières 1 Utilisation en local 1.1 Installation de Python 2.7 . . . . . . 1.2 Création d’un environnement virtuel 1.3 Installation . . . . . . . . . . . . . . 1.4 Utilisation en local . . . . . . . . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

2 2 2 3 3

2 Déploiement sur un VPS 2.1 Fournisseur d’accès Internet . . . . . . . . . . . . . . 2.2 Installation de Debian/Postgre/Python/Django . . . 2.2.1 Debian . . . . . . . . . . . . . . . . . . . . . . 2.2.2 Postgresql . . . . . . . . . . . . . . . . . . . . 2.2.3 User . . . . . . . . . . . . . . . . . . . . . . . 2.2.4 Python . . . . . . . . . . . . . . . . . . . . . 2.2.5 Gunicorn . . . . . . . . . . . . . . . . . . . . 2.3 Transfert de fichiers . . . . . . . . . . . . . . . . . . 2.4 Supervisor/Nginx . . . . . . . . . . . . . . . . . . . . 2.4.1 Test gunicorn . . . . . . . . . . . . . . . . . . 2.4.2 Supervisor . . . . . . . . . . . . . . . . . . . . 2.4.3 Nginx . . . . . . . . . . . . . . . . . . . . . . 2.5 Installation et chargement de la base de données . . 2.6 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . 2.7 Opérations de maintenance . . . . . . . . . . . . . . 2.7.1 Environnement virtuel . . . . . . . . . . . . . 2.7.2 Relancer l’application et le serveur . . . . . . 2.7.3 La base de données . . . . . . . . . . . . . . . 2.7.4 Super-utilisateur . . . . . . . . . . . . . . . . 2.7.5 Zipper l’ensemble du site . . . . . . . . . . . 2.7.6 Installer une nouvelle version de l’application 2.8 Modification du bandeau . . . . . . . . . . . . . . . . 2.9 Pour l’application Bomberman . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

4 4 4 4 5 5 5 6 7 8 8 8 9 10 10 11 11 11 11 12 12 13 13 13

3 Mode d’emploi 3.1 Soumission de code . . . . . . . . 3.2 Le suivi des élèves . . . . . . . . 3.3 Créer des exercices . . . . . . . . 3.3.1 Énoncé . . . . . . . . . . 3.3.2 Question/réponse . . . . . 3.4 S’échanger des énoncés d’exercice 3.5 Problèmes connus . . . . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

14 14 14 14 14 15 15 15

. . . .

. . . .

. . . .

. . . .

. . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . entre profs . . . . . . .

. . . .

. . . . . . .

. . . .

. . . . . . .

. . . .

. . . . . . .

. . . . . . .

4 Annexe : architecture et contenu de la base de données

1

17

Chapitre 1

Utilisation en local 1.1

Installation de Python 2.7

Installer une distribution Python 2.7 de son choix. Par exemple : https://sourceforge.net/projects/ winpython/files/WinPython_2.7/2.7.10.3/WinPython-64bit-2.7.10.3.exe/download N.B. Python 2.7 est obligatoire car PySandBox ne fonctionne pas sous Python 3.

1.2

Création d’un environnement virtuel

En ligne de commande (touche Windows+R : cmd) : cd c:\WinPython-64bit-2.7.10.3\python-2.7.10.amd64\Scripts pip install virtualenv cd c:\ mkdir venvdjango virtualenv --no-site-packages venvdjango cd venvdjango cd Scripts activate pip install Django==1.8.2 pip install django-appconf==1.0.1 pip install django-geoip==0.5.2 pip install django-user-sessions==1.2.0 pip install geoip2==2.2.0 #pip install ipaddr==2.1.11 #pip install maxminddb==1.2.0 pip install pygeoip==0.3.2 pip install pysandbox==1.5.1 pip install pytz==2015.7 #pip install requests==2.9.1 #pip install six==1.10.0 pip install wheel==0.24.0 deactivate N.B. Les lignes commençant par # n’ont pas besoin d’être tapées ; normalement les packages ont déjà été installés par les librairies précédentes. N.B. On peut, alternativement, copier-coller la liste des packages ci-dessous dans un fichier requirements.txt et faire pip install requirements.txt Django==1.8.2 2

django-appconf==1.0.1 django-geoip==0.5.2 django-user-sessions==1.2.0 geoip2==2.2.0 ipaddr==2.1.11 maxminddb==1.2.0 pygeoip==0.3.2 pysandbox==1.5.1 pytz==2015.7 requests==2.9.1 six==1.10.0 wheel==0.24.0

1.3

Installation

Télécharger hello.zip à l’adresse http://vps99063.ovh.net/static/fichiers-perso/hello.zip Décompacter à la racine c:\ Lorsqu’on utilise l’application en local, Django utilise une base de données SQLite pré-remplie. Il n’est pas nécessaire d’importer les fichiers du répertoire hello/BASE_DE_DONNES. cd c:\venvdjango\Scripts activate python c:\hello\manage.py createsuperuser Username: ... Email address: ... Password: ... Password (again): ... deactivate

1.4

Utilisation en local

cd c:\venvdjango\Scripts activate python c:\hello\manage.py runserver Dans la barre d’url d’un navigateur : 127.0.0.1:8000 Se logger identifiant: guest mot de passe: 1234 Page d’accueil guest est un compte élève. Pour administrer le site, aller dans la partie Backoffice : 127.0.0.1:8000/admin dans la barre d’url du navigateur, puis : — se logger avec le compte superuser défini dans la partie installation. — aller dans Userprofile/User profile — sélectionner l’utilisateur superuser, cocher est enseignant — enregistrer On peut maintenant utiliser ce compte comme professeur.

3

Chapitre 2

Déploiement sur un VPS 2.1

Fournisseur d’accès Internet

Choisir un fournisseur d’accès. Exemple : https://www.ovh.com/fr/vps/, choisir SSD à 3 euros HT/mois. VPS SSD 1 / Commander Catégorie: Virtual Private Server SSD Produit: VPS 2016 SSD1 (1vCore/2Go/10Go) Quantité: 1 Localisation: Gravelines Distribution: Linux Version: Debian 8 (Jessie) 64 bits Langue: Français Noter le mot de passe. Payer, aller dans sa boîte électronique pour récupérer l’identifiant : subject: Votre identifiant client Aller sur https://www.ovh.com/manager/ et entrer l’identifiant et le mot de passe. Au bout de quelques minutes, aller dans sa boîte électronique pour récupérer l’adresse du serveur et le mot de passe root. subject: installation de votre VPS

2.2

Installation de Debian/Postgre/Python/Django

Source : http://michal.karzynski.pl/blog/2013/06/09/django-nginx-gunicorn-virtualenv-supervisor/ Sur son PC, installer PuTTY http://www.chiark.greenend.org.uk/~sgtatham/putty/download. html Lancer PuTTY Host name: vpsxxxxxx.ovh.net; Port 22; Connection. Dans la fenêtre PuTTY : login as: root [email protected]’s password:

2.2.1

celui envoyé par courrier électronique

Debian

Dans la fenêtre PuTTY (ne pas taper les instructions après #) apt-get update apt-get upgrade

4

dpkg-reconfigure locales export LANG=fr_FR.UTF-8 export LANGUAGE=fr_FR.UTF-8 export LC_ALL=fr_FR.UTF-8 apt-get apt-get apt-get apt-get apt-get apt-get apt-get

install install install install install install install

nano apt-utils postgresql postgresql-contrib postgresql-client nginx git supervisor build-essential mysql-server mysql-client libmysqlclient-dev gcc #pour pouvoir compiler pysandbox libpq-dev #pour pouvoir installer psycopg2 python-dev #pour avoir "python.h"

wget https://bootstrap.pypa.io/get-pip.py --no-check-certificate wget https://pypi.python.org/packages/source/s/setuptools/setuptools-18.2.zip --no-check-certificate apt-get install unzip unzip setuptools-18.2.zip cd setuptools-18.2 python setup.py install cd .. python get-pip.py

2.2.2

Postgresql

Toujours dans la fenêtre PuTTY On crée un utilisateur et une base de données pour notre projet hello_django su - postgres postgres@xxx:~$ createuser --interactive -P Enter name of role to add: hello_django Enter password for new role: Enter it again: Shall the new role be a superuser? (y/n) n Shall the new role be allowed to create databases? (y/n) n Shall the new role be allowed to create more new roles? (y/n) n postgres@xxx:~$ postgres@django:~$ createdb --owner hello_django hello postgres@django:~$ logout Noter le mot de passe.

2.2.3

User

Toujours dans la fenêtre PuTTY On crée un utilisateur pour Django groupadd --system webapps useradd --system --gid webapps --shell /bin/bash --home /webapps/hello_django hello

2.2.4

Python

Toujours dans la fenêtre PuTTY On crée un environnement virtuel pour Python apt-get install python-virtualenv mkdir -p /webapps/hello_django/ chown hello /webapps/hello_django/ 5

su - hello hello@xxx:~$ cd /webapps/hello_django/ hello@xxx:~$ virtualenv . hello@xxx:~$ source bin/activate (hello_django)hello@xxx:~$ pip install Django==1.8.2 pip install Fabric==1.10.2 pip install MySQL-python==1.2.5 pip install PyYAML==3.11 pip install argparse==1.2.1 pip install django-appconf==1.0.1 pip install django-geoip==0.5.2 pip install django-user-sessions==1.2.0 pip install ecdsa==0.13 pip install email==4.0.2 pip install geoip2==2.2.0 pip install gunicorn==19.3.0 pip install ipaddr==2.1.11 pip install maxminddb==1.2.0 pip install ordereddict==1.1 pip install paramiko==1.15.2 pip install psycopg2==2.6.1 pip install pycrypto==2.6.1 pip install pygeoip==0.3.2 pip install pysandbox==1.5.1 pip install pytz==2015.7 pip install requests==2.9.1 pip install setproctitle==1.1.9 pip install six==1.10.0 pip install subprocess32==3.2.6 pip install wheel==0.24.0 pip install wsgiref==0.1.2 pip freeze Vérifier que pip freeze a bien installé tous les packages. (hello_django)hello@xxx:~$ exit chown -R hello:users /webapps/hello_django chmod -R g+w /webapps/hello_django

2.2.5

Gunicorn

Toujours dans la fenêtre PuTTY cd /webapps/hello_django/bin nano gunicorn_start Copier ce code : #!/bin/sh NAME="hello_app" DJANGODIR=/webapps/hello_django/hello SOCKFILE=/webapps/hello_django/run/gunicorn.sock 6

# Name of the application # Django project directory # we will communicte using this unix socket

USER=hello GROUP=webapps NUM_WORKERS=3 DJANGO_SETTINGS_MODULE=Projet.settings DJANGO_WSGI_MODULE=Projet.wsgi

# the user to run as # the group to run as # how many worker processes should Gunicorn spawn # which settings file should Django use # WSGI module name

echo "Starting $NAME as ‘whoami‘" # Activate the virtual environment cd $DJANGODIR source ../bin/activate export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE export PYTHONPATH=$DJANGODIR:$PYTHONPATH # Create the run directory if it doesn’t exist RUNDIR=$(dirname $SOCKFILE) test -d $RUNDIR || mkdir -p $RUNDIR # Start your Django Unicorn # Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon) exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \ --name $NAME \ --workers $NUM_WORKERS \ --user=$USER --group=$GROUP \ --bind=unix:$SOCKFILE \ --log-level=debug \ --log-file=Coller le dans gunicorn_start (clic droit) ; sauver (Ctrl-O) et quitter (Ctrl-X) Rendre le fichier exécutable chmod u+x gunicorn_start cd ..

2.3

Transfert de fichiers

Télécharger l’archive : hello.zip à l’adresse http://vps99063.ovh.net/static/fichiers-perso/ hello.zip Sur son PC, installer WinSCP https://winscp.net/ Nouveau site SFTP ; nom d’hôte : vpsxxxxx.ovh.net ; port 22 ; nom d’utilisateur : root ; mot de passe : celui envoyé par courrier électronique par OVH. Dans la partie droite (côté serveur), se déplacer dans l’arborescence /webapps/hello_django Dans la partie gauche (côté PC), se déplacer dans le répertoire où se trouve hello.zip Faire glisser hello.zip de la partie gauche à la partie droite (donc dans /webapps/hello_django). Dans la fenêtre PuTTY cd /webapps/hello_django unzip hello.zip mkdir static cd static ln -s /webapps/hello_django/lib/python2.7/site-packages/django/contrib/admin/static/admin admin ln -s /webapps/hello_django/hello/Projet/static/js js

7

ln -s /webapps/hello_django/hello/Projet/static/css css ln -s /webapps/hello_django/hello/Projet/static/media media ln -s /webapps/hello_django/hello/fort/static/fort fort ln -s /webapps/hello_django/hello/frog/static/frog frog ln -s /webapps/hello_django/hello/gomoku/static/gomoku gomoku ln -s /webapps/hello_django/hello/bomberman/static/bomberman bomberman ln -s /webapps/hello_django/hello/tron/static/tron tron cd /webapps/hello_django/hello/Projet/ nano settings.py Mettre DEBUG à False (ligne 27) et PRODUCTION à True (ligne 28). Modifier ALLOWED_HOST=[’vpsxxx.ovh.net’] (ligne 32) Modifier le mot de passe de DATABASES (ligne 123) en mettant celui du §2.2.2 Modifier l’adresse e-mail (se créer un compte Gmail spécifique) pour que le serveur puisse envoyer automatiquement des mails 1 à ceux qui ont oublié leur mot de passe (lignes 177 et 178). Ctrl-O (sauver) Ctrl-X (quitter) cd /

2.4 2.4.1

Supervisor/Nginx Test gunicorn

Dans la fenêtre PuTTY su - hello hello@xxx:~$ bin/gunicorn_start Le serveur doit démarrer ; exemple : [2016-03-29 [2016-03-29 [2016-03-29 [2016-03-29 [2016-03-29 [2016-03-29 [2016-03-29 [2016-03-29 [2016-03-29

23:28:57 23:28:57 23:28:57 23:28:57 23:28:57 23:28:58 23:28:58 23:28:58 23:28:59

+0000] +0000] +0000] +0000] +0000] +0000] +0000] +0000] +0000]

[23696] [23696] [23696] [23696] [23703] [23706] [23707] [23696] [23696]

[INFO] Starting gunicorn 19.3.0 [DEBUG] Arbiter booted [INFO] Listening at: unix:/webapps/hello_django/run/gunicorn.sock [INFO] Using worker: sync [INFO] Booting worker with pid: 23703 [INFO] Booting worker with pid: 23706 [INFO] Booting worker with pid: 23707 [DEBUG] 3 workers [DEBUG] 3 workers

On arrête avec : Ctrl-C exit

2.4.2

Supervisor

Dans la fenêtre PuTTY cd / cd /etc/supervisor/conf.d nano hello.conf Copier ce code : 1. Pour empêcher Gmail de bloquer le serveur : http://www.google.com/accounts/DisplayUnlockCaptcha and click continue (this will grant access for 10 minutes for registering new apps). After this my app in production started sending emails

8

[program:hello] command = /webapps/hello_django/bin/gunicorn_start user = hello stdout_logfile = /webapps/hello_django/logs/gunicorn_supervisor.log redirect_stderr = true environment=LANG=fr_FR.UTF-8,LC_ALL=fr_FR.UTF-8 Coller le dans hello.conf (clic droit) ; sauver (Ctrl-O) et quitter (Ctrl-X) Puis (sans les commentaires après #) cd / mkdir -p /webapps/hello_django/logs/ touch /webapps/hello_django/logs/gunicorn_supervisor.log supervisorctl reread #hello: available supervisorctl update #hello: added process group supervisorctl start hello #hello: started

2.4.3

Nginx

Dans la fenêtre PuTTY service nginx start cd /etc/nginx/sites-available mkdir hello cd hello nano nginx.conf Copier ce code : upstream hello_app_server { server unix:/webapps/hello_django/run/gunicorn.sock fail_timeout=0; } server { listen 80; server_name vpsxxxx.ovh.net; #mettre le nom du serveur client_max_body_size 4G; access_log /webapps/hello_django/logs/nginx-access.log; error_log /webapps/hello_django/logs/nginx-error.log; location /static/ { alias /webapps/hello_django/static/; } location /media/ { alias /webapps/hello_django/media/; } location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; 9

; ; ; ; ;

Command to start app User to run as Where to write log messages Save stderr in the same log Set UTF-8 as default encoding

proxy_redirect off; if (!-f $request_filename) { proxy_pass http://hello_app_server; break; } } # Error pages error_page 500 502 503 504 /500.html; location = /500.html { root /webapps/hello_django/static/; } } Coller le dans nginx.conf (clic droit) ; modifier server_name (ligne 8) ; sauver (Ctrl-O) et quitter (Ctrl-X) ln -s /etc/nginx/sites-available/hello/nginx.conf /etc/nginx/sites-enabled/hello service nginx restart Dans la barre d’url d’un navigateur vpsxxx.ovh.net. Ça y est !

2.5

Installation et chargement de la base de données

Lorsque l’on utilise l’application sur un serveur, Django utilise une base de données Postgresql, initialement vierge. Il faut la créer et, éventuellement, la remplir. su - hello source bin/activate cd /webapps/hello_django/hello python manage.py makemigrations python manage.py migrate python manage.py loaddata ./BASE_DE_DONNEES/dump_mini_auth_user_foreign_primary.json python manage.py loaddata ./BASE_DE_DONNEES/dump_mini_userprofile_foreign_primary.json python manage.py loaddata ./BASE_DE_DONNEES/dump_eval_code_td_foreign_primary_2016_04_07.json python manage.py loaddata ./BASE_DE_DONNEES/eval_code_exercice_foreign_primary_2016_04_07.json python manage.py loaddata ./BASE_DE_DONNEES/eval_code_question_foreign_primary_2016_04_07.json exit supervisorctl restart hello 3 profils sont créés : identifiant admin prof1 eleve1

mot de passe 1234 1234 1234

super-utilisateur oui oui non

est_enseignant non oui non

ainsi qu’une centaine d’exercices et environ 4 questions par exercice.

2.6

Utilisation

Dans la barre d’url d’un navigateur vpsxxxx.ovh.net ; puis : se logger identifiant: prof1 mot de passe: 1234 puis page d’accueil. 10

2.7 2.7.1

Opérations de maintenance Environnement virtuel

Pour accéder à l’environnement virtuel de Python su - hello source bin/activate puis, pour quitter : exit

2.7.2

Relancer l’application et le serveur

En cas de modifications sur le code source (en particulier settings.py), dans une console PuTTY : supervisorctl restart hello service nginx restart

2.7.3

La base de données

Pour sauver les bases de données : su - hello source bin/activate cd /webapps/hello_django/hello python manage.py dumpdata auth.user --natural-foreign --natural-primary --indent 4 > ./BASE_DE_DONNEES/auth_user.json python manage.py dumpdata userprofile --natural-foreign --natural-primary --indent 4 > ./BASE_DE_DONNEES/userprofile.json python manage.py dumpdata eval_code.td --natural-foreign --natural-primary --indent 4 > ./BASE_DE_DONNEES/eval_code_td.json python manage.py dumpdata eval_code.exercice --natural-foreign --natural-primary --indent 4 > ./BASE_DE_DONNEES/eval_code_exercice.json python manage.py dumpdata eval_code.question --natural-foreign --natural-primary --indent 4 > ./BASE_DE_DONNEES/eval_code_question.json python manage.py dumpdata eval_code.soumission_code --natural-foreign --natural-primary --indent 4 > ./BASE_DE_DONNEES/eval_code_soummission.json ou bien tout en même temps (si ça se passe bien) python manage.py dumpdata auth.user userprofile eval_code --natural-foreign --natural-primary --exclude auth.permission --exclude contenttypes --indent 4 > ./BASE_DE_DONNEES/all.json Pour charger les bases de données : su - hello source bin/activate cd /webapps/hello_django/hello python manage.py loaddata ./BASE_DE_DONNEES/auth_user.json python manage.py loaddata ./BASE_DE_DONNEES/userprofile.json python manage.py loaddata ./BASE_DE_DONNEES/eval_code_td.json python manage.py loaddata ./BASE_DE_DONNEES/eval_code_exercice.json python manage.py loaddata ./BASE_DE_DONNEES/eval_code_questionl.json python manage.py loaddata ./BASE_DE_DONNEES/eval_code_soummission.json ou bien tout en même temps python manage.py loaddata ./BASE_DE_DONNEES/all.json 11

En cas de problème pour charger l’une des tables de l’application app_name (où app_name=userprofile ou eval_code), il faut effacer les tables et les migrations (construction de la base) et retenter les dumps (remplissage de la base). su - hello source bin/activate cd /webapps/hello_django/hello cd app_name/migrations rm * touch __init__.py cd /webapps/hello_django/hello python manage.py sqlclear app_name | python manage.py dbshell python manage.py makemigrations python manage.py migrate Si ça ne suffit pas, il faut également effacer l’historique des migrations dans la base de données de django. su - hello source bin/activate cd /webapps/hello_django/hello python manage.py dbshell \d #all tables select * from django_migrations where app = ’app_name’; delete * from django_migrations where app = ’app_name’; \q #quit cd app_name/migrations rm * touch __init__.py cd /webapps/hello_django/hello python manage.py sqlclear app_name | python manage.py dbshell python manage.py makemigrations python manage.py migrate

2.7.4

Super-utilisateur

Pour créer un nouveau super-utilisateur : su - hello source bin/activate cd /webapps/hello_django/hello python manage.py createsuperuser Username: admin Password: ... Password again:... ou bien directement depuis l’interface administrateur.

2.7.5

Zipper l’ensemble du site

compresser: tar -zcvf archive.tar.gz directory/ decompresser: tar -zxvf archive.tar.gz

12

2.7.6

Installer une nouvelle version de l’application

Sauver la base de données (cf §2.7.3). Dans une fenêtre PuTTY cd /webapps/hello_django mv hello hello_old Refaire toutes les opérations du paragraphe “Transfert de fichiers” (cf §2.3), puis : chown -R hello:users /webapps/hello_django chmod -R g+w /webapps/hello_django supervisorctl restart hello service nginx restart Enfin, recharger la base de données (cf §2.7.3).

2.8

Modification du bandeau

Les images dans le bandeau en haut du site sont définies ici : hello\Projet\static\media. On peut soit insérer ses propres images en les renommant logo_croix_rouge.jpg et logo_isen.jpg, soit modifier le code hello\Projet\templates\Projet\base.html (lignes 6 et 7) pour changer le nom des images.

2.9

Pour l’application Bomberman

apt-get install ocaml cd /webapps/hello_django/hello/bomberman mv utils.py utils_windows.py mv utils_debian.py utils.py supervisorctl restart hello

13

Chapitre 3

Mode d’emploi 3.1

Soumission de code

Lorsqu’il soumet son code, l’utilisateur avec le statut est_enseignant voit les questions posées, les solutions attendues et les réponses calculées (ou les messages d’erreur). L’utilisateur qui n’a pas le statut est_enseignant voit seulement les messages d’erreurs.

3.2

Le suivi des élèves

Les comptes avec le statut est_enseignant permettent d’accéder à la partie réservée : — Appel — Bilans (par nom) — Bilans (par total) — Bilans (par date) — Backoffice (vpsxxx.ovh.net/admin)

3.3

Créer des exercices

Dans la partie backoffice vpsxxx.ovh.net/admin

3.3.1

Énoncé

Pour entrer un énoncé dans la base de données : — On peut insérer des balises HTML dans les énoncés. — Pour insérer des images ou des équations dans les énoncés, utiliser le format SVG ... et copier-coller le code généré par InkScape ou LaTeX Pour que l’insertion soit dans une ligne de texte, utiliser ... — Dans Exercice.bibliotheques_autorisees : Les bibliothèques doivent être séparées par des virgules. Exemple : math,future. Il est important d’autoriser future dans tous les exercices (à cause du problème de la division entière). On ne peut pas autoriser numpy et scipy. Dans le code, on ne peut pas écrire "from module import *" mais on peut écrire "from module import __all__" lorsque ’__all__’ est défini (N.B. ’__all__’ n’est pas défini dans le module : math) — Dans Exercice.enonce, s’il y a des fonctions à passer en argument de la fonction principale, celles-ci doivent être en premier argument. Exemple : fonction_principale(fonction_argument1,argument_2,argument3) et non fonction_principale(argument1,fonction_argument_2,argument3)

14

Si l’on ne veut pas qu’un exercice soit visible pour les élèves : créer une liste de TD, ne pas cocher est visible. À la création de l’exercice, affecter le numéro au TD précédent. Si, par la suite, on veut rendre cet exercice visible aux élèves, affecter le numéro à une liste de TD visible.

3.3.2

Question/réponse

Pour entrer une question dans la base de données : — Dans Question.question et Question.reponse : les chaines de caractères doivent être explicitement délimitées par des apostrophes ’...’ ou bien des guillemets "..." — Dans Question.question : il faut au minimum un argument ; lorsqu’il n’y a qu’un seul argument, terminer par une virgule "," — Dans Question.question : les fonctions à passer en arguments doivent : — être en premier argument (cf § précédent) — être des chaines de caractères séparées par des virgules — être des lambda fonctions — avoir un nom d’une seule lettre — donc de la forme : ’f=lambda x:x**2’,’g=lambda x:x**3’

3.4

S’échanger des énoncés d’exercice entre profs

Il est difficile de faire un dump partiel de la base de données pour exporter un seul exercice (on peut faire un dump total et faire un copier-coller de la partie du .json que l’on souhaite). Le plus simple est d’aller dans la partie administrateur et de sauver la page de l’exercice (et des questions) au format HTML. Il suffit alors au destinataire de faire un copier-coller dans sa propre partie administrateur.

3.5

Problèmes connus

1. Race condition Si on clique très rapidement plusieurs fois au moment où l’on entame un nouvel exercice, deux soumissions sont créées avec le même exercice et le même utilisateur. Le serveur ne sait pas quelle soumission afficher et renvoie une page 404. Le problème arrive très rarement (3 fois sur plus de 5 000 soumissions). Si c’est le cas, aller dans la partie backoffice, eval_code/soumission, rechercher le doublon (en triant par date) et supprimer les soumissions correspondantes. 2. Si un élève quitte le site VPS sans se délogger, sa session expire automatiquement au bout de 24 heures. Néanmoins, il reste des traces de sa session dans la base de données (ce qui l’encombre inutilement). Pour effacer les sessions qui ont expiré : aller dans le backoffice, sélectionner les sessions et les supprimer. Sinon python manage.py clearsessions. On peut faire un cron pour automatiser cette tache. 3. Dans Projet/settings.py, laisser USER_SESSION à False. En utilisation locale, cette option fonctionne ; elle permet, dans la partie backoffice, d’avoir des informations supplémentaires sur les sessions (OS de l’utilisateur, navigateur, adresse IP,...). [L’idée était de banir pendant 3 minutes les adresses IP des élèves qui soumettent des boucles infinies] Sur un serveur Nginx (avec la configuration actuelle), on ne peut pas récupérer l’adresse IP (IP=null) ce qui fait crasher le serveur. 4. Dans un dump de toutes les tables (cf. > dump_all), si un utilisateur ne s’est jamais logé, il y a un champ ’last_login’: null (à chercher par Ctrl-F) à remplacer par ’last_login’: "2000-01-01 00:00". Si on trouve ”null” dans les autres applications (bomberman,tron,...), on le remplace par 0.

15

5. Ne pas créer deux exercices avec le même numéro de TD et le même ordre dans le TD. (C’est possible, mais si on efface ensuite un des exercices, il y a des risques d’effacer le mauvais exercice [Bug non reproductible, probablement lié à une modification la structure de la base de données entre 2 dumps] ; de plus cela peut créer des conflits lorsqu’on exporte/importe les questions relatives à ces exercices [avec l’option natural-foreign]). 6. ...

16

Chapitre 4

Annexe : architecture et contenu de la base de données eval_code_question

auth_user id

int

password is_superuser username first_name email is_staff is_active date_joined last_login

varchar bool varchar varchar varchar bool bool datetime datetime

userprofile_userprofile id

int

est_enseignant user_id classe_principale_id

bool int int

id

int

question reponse exercice_id temps_max eval_code_submission_code id

classe

int

date_creation date_modification programme log note auteur_id exercice_id temps

datetime datetime text text int int int real

eval_code_exercice

userprofile_classe id

text text int real

int varchar

id

int

numero_TD ordre_dans_TD titre enonce nom_fonction nbre_fonct_en_papametre solution bibliotheques_autorisees

int int varchar text varchar int text text

eval_code_TD id

int

numero titre visible

int varchar bool

17

n◦ TD 110 120 130 140 150 210 220 230 240 310 320 330 404 410 420 490 500 510 520 530

Titre Première année : les variables Première année : les tests Première année : les boucles Première année : les listes Première année : les chaînes de caractères Deuxième année : révisions Deuxième année : algorithmes numériques Deuxième année : algorithmes récursifs Deuxième année : algorithmes de tri Arithmétique Probabilités Algèbre linéaire Liste cachée Electricité Mécanique Chimie Algorithmique : divers Algorithmique : rendu de la monnaie Algorithmique : labyrinthes et graphes Programmation objet

18

n◦ TD 110 110 110 110 110 110 120 120 120 120 120 120 120 130 130 130 130 130 130 130 130 130 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 150 150 150 150 150 150 150 150 150 150 150 150

n◦ ex 10 20 30 40 50 60 10 20 30 40 50 60 80 10 20 30 40 50 60 70 80 90 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 10 15 17 18 20 30 40 50 55 56 60 70

Exercice Marches TTC Rectangle Perimetre Equation second degre Augmentation des taxes Divisible par 7 Calcul remise Equation second degre (suite) Année bissextile Impots Intervalle - 1 Intersection Somme - 1 Produit Somme - 2 Nenuphar Somme carré Epidémie Euclide Syracuse Babylone Intervalle - 2 Multiples Table de multiplication Crible Conversion base 10 -> base b Perimetre rectangle Dans le rectangle Denivelé Liste de courses Variation de stocks Médian Retour à l’entrée d’un labyrinthe Les petits avec les grands Participants à une fête Allonger une liste Tournoi 1 Tournoi 2 Minuscule Compter les mots Nombre associé Palindrome Rectangle plein Rectangle creux Triangle rectangle Triangle isocèle Celsius-Farenheit Liste Labyrinthe Cible

19

Nbre ques 2 3 2 2 3 3 4 5 4 4 5 4 3 4 4 4 3 3 3 4 4 4 3 3 3 2 4 4 4 3 3 3 3 3 3 4 3 2 2 2 4 4 4 2 2 2 2 4 3 5 3

n◦ TD 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 230 230 230 230 230 230 240 240 240 240 240

n◦ ex 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 10 20 30 40 50 60 70 80 90 100 102 105 110 120 130 140 150 10 20 25 26 30 40 10 20 30 40 50

Exercice Hello World ! Recherche du maximum dans une liste de nombres Calcul de la moyenne et de la variance Compte à rebours multiple Somme de polynômes Recherche d’une sous-liste dans une liste de nombres Numération romaine Recherche par dichotomie dans une liste triée Recherche par dichotomie du zéro d’une fonction Addition binaire Évaluation d’une expression postfixée (version chaine) Évaluation d’une expression postfixée (version liste) Encodage Attaque par force brute Détermination des fréquences Recherche de la fréquence maximale Décodage par analyse fréquentielle Question subsidiaire Recherche de l’intersection de 2 fonctions Horner - 1 Horner - 2 Secante Newton Gauss - 1 Gauss - 2 Dérivée Lagrange - 1 Lagrange - 2 Régression linéaire Régression parabolique Plan Intégrale par la méthode des trapèzes Intégrale par la méthode de Simpson Euler Fourier FFT Zéros Hanoï Générateur avec répétition Générateur sans répétition Casse-tête Sudoku Tri par sélection Tri à bulles Tri par insertion Tri rapide Tri fusion

20

Nbre ques 3 4 7 11 10 11 18 23 5 8 4 4 9 2 4 5 3 1 2 5 3 4 5 4 6 4 4 4 5 3 3 3 3 3 3 3 5 3 3 3 3 4 4 4 4 4 5

n◦ TD 310 310 310 310 310 310 310 310 310 320 320 320 320 330 330 330 404 404 404 404 404 404 410 410 410 410 410 410 420 420 420 420 490 500 500 500 500 500 510 510 510 510 510 520 520 520 520 520 520 530 530

n◦ ex 10 20 25 30 40 50 60 70 80 10 20 30 40 10 20 30 0 0 10 100 120 130 10 20 30 40 50 100 10 20 30 40 10 10 20 30 40 50 10 20 30 40 50 10 20 30 40 50 60 10 20

Exercice Diophante Diviseurs Diviseurs premiers McNugget Partition - 1 Partition - 2 Décomposition en somme de carrés Fraction continue Fraction rationnelle Chasseurs Anniversaires Avion Jeu de dé Vecteur Matrice Gram-Schmidt Decomposition QR [OK, à passer en visible] Vecteur [à effacer] Rebond [OK, à passer en visible] Demineur (old) [à effacer] Atteindre la cible [OK, à passer en visible] Le compte est bon [OK, à passer en visible] Association série Association parallèle Signal sinusoidal Signal carré Signal triangle Bode Tir balistique Tir balistique (2) Cycloide Cycloide (2) Klechkowski 13/04/16 Puce Chapeaux Mastermind Démineur Rendu de la monnaie (force brute, avec itertools) Rendu de la monnaie (force brute, sans itertools) Rendu de la monnaie (glouton) Rendu de la monnaie (programmation dynamique) Nombre de rendus de la monnaie Pledge BFS (Breadth First Search) DFS (Depth First Search) Cavalier Dijkstra Vers la sortie Parcours d’un arbre Arbre de recherche

21

Nbre ques 5 4 4 4 4 5 4 4 4 4 4 3 4 4 4 4 4 0 4 0 5 4 3 3 4 4 4 5 4 4 4 4 5 5 4 1 7 4 5 5 5 5 6 5 3 3 4 5 5 4 4 613