Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
1 result

Target

Select target project
  • nthiery/wims-info
  • medimegh/wims-info
  • ventos/wims-info
  • bokaris/wims-info
4 results
Select Git revision
  • master
1 result
Show changes
Commits on Source (205)
Showing
with 1183 additions and 15 deletions
*.answer
test~coding~readingCppPrograms.fr/data/index
core
Modules:
- `<U2~coding~oefprogramC.fr/>`_: un dérivé du module éponyme déjà
existant dans WIMS, avec quelques menues améliorations.
- `Compréhension de programmes C++ <test~coding~readingCppPrograms.fr/>`_:
deviner l'entrée ou la sortie d'un programme
Le répertoire `<data/>`_ contient des programmes C++, qui peuvent être de deux types.
Pour les programmes du premier type, l'utilisateur doit deviner la sortie du programme.
Ces programmes sont nommés sous la forme ``<theme>_<nom>.cpp``.
Les programme du deuxième type doivent lire un entier entre 0 et 99 sur l'entrée standard, et l'utilisateur doit deviner lequel donne 42; pour l'instant cet entier doit être unique.
Ces programmes sont nommés ``<theme>_<nom>_input.cpp``
Pour les deux types de programme, le thème peut être constitué d'un thème principal et de sous-thèmes, séparés par des ``_`` (p. ex. ``loop_for``, ``loop_while``).
Les noms de fichiers ne doivent contenir que des caractères alphanumériques et le caractère ``_``.
* Liste des thèmes :
file
function
if
io
loop
procedure
struct
variable
vector1D
vector2D
* Sous-thèmes :
1. struct_simple : seulement un type de structure, dans un main (pas de fonction ou procédure)
2. struct_fonction : fonction manipulant et renvoyant des structures
3. struct_procedure : procédures manipulant des structures
4. struct_profond : structure contenant une structure (pas de fonction ou procédure)
5. struct_tableaux : structure contenant un tableau (pas de fonction ou procédure)
6. struct_tableau_struct : structure contenant un tableau contenant des structures (pas de fonction ou procédure)
7. struct_gros : structure contenant un tableau contenant des structures, avec fonctions
8. struct_hard : programmes difficiles manipulant des structures
* Liste et descriptif des programmes par thème :
Thème vector1D_recherche : recherche d'un élément dans un tableau. Les variations a, b, et c l'appliquent sur un tableau contenant 1, 2 ou 0 occurrences de l'élément.
recherche_1 : parcours du tableau de gauche à droite, avec return direct, correct.
recherche_2 : parcours du tableau de gauche à droite, avec return direct, non correct.
recherche_3 : parcours du tableau de gauche à droite, avec variable locale, correct.
recherche_4 : parcours du tableau de gauche à droite, avec variable locale, non correct.
recherche_5 : parcours du tableau de droite à gauche, avec variable locale, non correct.
recherche_6 : parcours du tableau de droite à gauche, avec return direct, correct.
recherche_7 : parcours du tableau de droite à gauche, avec variable locale, correct.
Thème vector1D_tri : teste si un tableau est trié. Les variations a, b, et c l'appliquent sur divers tableaux
tri_1 : avec return direct, correct (tri croissant). Tests sur 2358 8532 2538
tri_2 : avec return direct, non correct (tri croissant). Tests sur 2835 2583 5238
tri_3 : avec variable locale, correct (tri croissant). Tests sur 2358 8532 2538
tri_4 : avec variable locale, non correct (tri croissant). Tests sur 2835 2583 5238
tri_5 : avec return direct, correct (tri décroissant). Tests sur 2358 8532 8352
tri_6 : avec return direct, non correct (tri décroissant). Tests sur 5283 5328 5832
tri_7 : avec variable locale, correct (tri décroissant). Tests sur 2358 8532 8352
tri_8 : avec variable locale, non correct (tri décroissant). Tests sur 5283 5328 5832
Pour le moment, la plateforme d'exercices interactifs pour `WIMS
<http://wims.unice.fr/>`_ contient très peu de chose pour
l'enseignement de l'informatique. L'objectif de ce dépôt est de
développer collaborativement de nouveaux modules.
Modules:
- `<U2~coding~oefprogramC.fr/>`_: un dérivé du module éponyme déjà
existant dans WIMS, avec quelques menues améliorations.
- `Compréhension de programmes C++ <test~coding~readingCppPrograms.fr/>`_:
deviner l'entrée ou la sortie d'un programme
* Question logique
- [ ] pour ***que*** l'expression suivante ***retourne*** true.
- [ ]
* WIMS questions
- create temporary file
- pass data to input
- boolean arithmetic
* QCM Question logique
- [ ] pour ***que*** l'expression suivante ***retourne*** true.
- [ ]
* Collections de programmes + randomisation + résultat
** Features
- [X] Code colorization
- [X] Code area just of the proper height
- [X] Selection of topic based on file prefix
- [X] Output dans un textarea
- [ ] Why are empty lines on top and bottom of the text aread
- [ ] Why are there empty lines at the top and bottom of the text shown?
- [ ] Randomization of the variable names
- [ ] Randomization of the output by substitution (preprocessing)
- [ ] Implement more logic in WIMS
- [ ] Onsite compilation and production of the output
- [ ] Support for various programming languages, based on file extension
- [ ] Support for various programming languages, based on file extension (see below)
- [ ] Separate clearly the expected output from the rest of the text
- [ ] Allow for broken programs
** Programs
- variables-assign.cpp est un peu trop long
- ceux avec factorielle sont trop prévisibles sans lire le code
- obfuscated / misindented programs
- programes autour de la division entiere
** Substitution des variables?
- programes autour de la division entiere
** Substitution des variables et constantes?
\text{code=\wims(replace internal resultat par \resultat)}
- Mesure intermédiaire:
Définir sur la ligne de commande de G++ un certain nombre de macros
I1,I2,I3, C1,C2,C3, F1,F2,F3, et les utiliser dans les programmes.
Comme ça, le jour de l'examen, on peut facilement travailler sur
d'autres valeurs.
* Onsite compilation and production of the output
** DONE Utility to compile and execute a program in a sandbox (docker container)
See file:docker-compile-and-run/docker-compile-and-run.cpp for an
experimental program.
** DONE rewrite the module to use it.
** TODO [/] Improvements
- [ ] Randomisation
- [ ] Where to put compile-and-run.sh
- [ ] Avoid hardcoding the module data location
- [ ] Avoid hardcoding the location of compile-and-run.sh
- [ ] Afficher la question avant de calculer la réponse?
- [ ] Support for other programming languages
See file:docker-compile-and-run/compile-and-run.sh
** TODO Deployment
Discuss with Bernadette to include that script (or some
equivalent) in Orsay's WIMS server.
** TODO Kernel panic
https://github.com/docker/docker/issues/15057 ?
** References:
http://askubuntu.com/questions/477551/how-can-i-use-docker-without-sudo
* Choisir l'entrée pour que ...
* Exercice générique avec base de donnée de programmes à trous
WIMS affiche un programme dont certain bouts sont cachés (les
trous), ainsi que l'affichage dudit programme. L'étudiant doit alors
compléter les trous pour que le programme affiche exactement la même
chose que le programme d'origine.
Typiquement le programme contiendra une fonction avec sa
documentation et ses tests, mais dont le corps et caché.
Pour introduire un peu de variabilité, le programme pourra lire sur
son entrée standard un entier que WIMS choisira aléatoirement.
* Écrire un programme qui ... par exemple pour n=5 ... copier coller le résultat ici
(Comparatif de la sortie par rapport à un programme de référence caché)
* Exercices existant: U1 / algo
Non fonctionnels en l'état (requiers un chroot qui n'est plus fonctionnel)
* Notes techniques sur WIMS
** Créer ses propres utilitaires
** Créer ses propres utilitaires / plugins / programmes externes
Si un programme est présent dans public_html/bin, il est exécutable
depuis les oef avec:
\text(toto=wims(exec ccc parametres ...)}
public_html/bin/sigdigits
other/bin
Il doit suivre un protocole spécifique. Le plus simple est de
mettre un programme usuel dans other/bin, avec un wrapper. Voir par
exemple toascii.
Ces programmes sont exécutables sans restriction par n'importe quel
auteur de module OEF/... Donc doivent être parfaitement sûr
\text(toto=wims(exec ccc parametres ...)}
** Créer ses programmes exécutables seulement par module de confiance
** Créer un index et chercher des infos dedans:
......@@ -58,7 +112,7 @@ Mettre le module dans
** Compiler WIMS
sudo apt-get install libgd-dev
sudo apt-get install libgd-dev
./compile --mathjax
......@@ -78,3 +132,65 @@ You don't have permission to access /wims/ on this server.
Se créer un compte développeur
* A propos des modules WIMS existants exécutant du code
** Modules
Chercher sur programmation sur le serveur
*** U1/algo/progstring.fr
*** ... arithmetic
** Supporte: perl, c, pascal
cf. public_html/bin/c
** Infrastructure:
- Un type de réponse: wims/public_html/scripts/anstype/code
définit:
- comment l'utilisateur rentre la réponse
- comment traiter la réponse (ici exécuter le code dans un chroot)
- le retour: qu'est-ce qui est affiché, note, ...
Objectif: mettre à jour pour utiliser docker à la place du chroot / secure_execq
Voir aussi ~/wims.log/unsecure.
Passe par WIMS/src/Misc/wrap.c à un moment ou un autre
** Variante: public_html/modules/tool/directexec/ (en particulier var.proc)
Outil indépendant permettant à un utilisateur d'exécuter un
programme quelconque écrit dans un des systèmes suivant:
outil,software, language, pari, gp, maxima, octave, macaulay, yacas, gap, scilab, c, perl, sh, python, pascal, fortran,jmol, jsgraph, canvasdraw,graphviz
entrée: une chaîne de caractère contenant le programme
sortie: l'affichage du programme
À confirmer: nécessitait un patch sur le noyau.
Utilise _calc_exec de WIMS/src/calc.c.
Exécute une commande, dans un chroot s'il n'est pas de confiance.
TODO: mettre à jour pour utiliser docker
** Consommation de ressources jugées raisonnables
Cf. src/wimsdef.h
Cf. aussi wims/log/wims.conf: rlimit_cpu et
public_html/bases/sys/defaults.conf pour les valeurs par défaut
** Si on se connecte avec une certaine IP alors on est en mode debug / admin
Affiche en particulier des informations sur l'exécution
* Serveur WIMS de test
https://wimstest2.di.u-psud.fr/
3/11/2015:
Serveur Centos6 similaire à WIMS installé par WIMS
docker.io installé
WIMS svn 4.11 a installé dans ~wims
voir /etc/httpd/conf/httpd.conf
Mainteneur: Julien Nauroy
Compte dévelopeur: nthiery wcloiasdf
service httpd restart FAILS, with selinux message in /var/log/httpd/error.log
2015/12/02: NT disabled selinux: http://www.crypt.gen.nz/selinux/disable_selinux.html
CXXFLAGS=-g -Wall -std=c++0x
WIMSHOST=wimstest
#DOCKERHOST=134.158.75.87# wimsdocker
#DOCKERHOSTADMIN=debian
DOCKERHOST=sage-docker# sage-docker
DOCKERHOSTADMIN=ubuntu
SSH=ssh -x
docker-compile-and-run: docker-compile-and-run.cpp
docker-compile-and-run-remote: docker-compile-and-run-remote.cpp
tests: test-compile-and-run.sh test-docker-compile-and-run test-docker-compile-and-run-client
test-%:
@echo running tests for $*
@echo | $* prog.cpp > prog.out.obtained 2> /dev/null && diff prog.out prog.out.obtained
@echo coucou | $* prog-stdin.cpp > prog-stdin.out.obtained 2> /dev/null && diff prog-stdin.out prog-stdin.out.obtained
@rm prog.out.obtained prog-stdin.out.obtained
test-docker-compile-and-run-client: start-server
stop-server:
-killall docker-compile-and-run-server
start-server: #stop-server
docker-compile-and-run-server &
# ssh wims@$(WIMSHOST) "(echo Host wimsdockerhost; echo Hostname $(DOCKERHOST); echo IdentityFile ~/.ssh/id_rsa_docker) >> .ssh/config; chmod 600 .ssh/config"
dockerhost-preinstall:
scp dockerhost-setup.sh root@$(DOCKERHOST):
$(SSH) $(DOCKERHOSTADMIN)@$(DOCKERHOST) sudo bash dockerhost-setup.sh
dockerhost-clean: # TODO Add a test that DOCKERHOST <-> WIMSHOST
ssh root@$(DOCKERHOST) userdel -r wims
#scp wimstest2-developers-config wims@$(DOCKERHOST):log/.developers
#ssh root@wimstest service httpd restart
dockerhost-install:
$(SSH) wims@$(DOCKERHOST) mkdir -p other/bin
scp compile-and-run.sh docker-compile-and-run-server wims@$(DOCKERHOST):other/bin
$(SSH) wims@$(DOCKERHOST) chmod 755 other/bin/compile-and-run.sh other/bin/docker-compile-and-run-server
scp docker-compile-and-run.cpp wims@$(DOCKERHOST):
$(SSH) wims@$(DOCKERHOST) "g++ $(CXXFLAGS) docker-compile-and-run.cpp -o other/bin/docker-compile-and-run && rm docker-compile-and-run.cpp"
$(SSH) $(DOCKERHOSTADMIN)@$(DOCKERHOST) "sudo chown wims:docker ~wims/other/bin/docker-compile-and-run; sudo chmod 2755 ~wims/other/bin/docker-compile-and-run"
$(SSH) $(DOCKERHOSTADMIN)@$(DOCKERHOST) sudo service docker restart
dockerhost-run:
$(SSH) wims@$(DOCKERHOST) other/bin/docker-compile-and-run-server
dockerhost-test:
$(SSH) $(DOCKERHOSTADMIN)@$(DOCKERHOST) docker run hello-world
scp prog.cpp wims@$(DOCKERHOST):
$(SSH) wims@$(DOCKERHOST) ./other/bin/docker-compile-and-run prog.cpp < /dev/null
docker-compile-and-run-client prog.cpp < /dev/null
wimshost-install:
scp docker-compile-and-run-client wims@$(WIMSHOST):other/bin/docker-compile-and-run
scp docker-compile-and-run-wrapper.sh wims@$(WIMSHOST):public_html/bin/docker-compile-and-run
# $(SSH) root@$(WIMSHOST) service httpd restart
wimshost-test: # Needs to be updated
scp prog.cpp wims@$(WIMSHOST):
$(SSH) wims@$(WIMSHOST) ./other/bin/docker-compile-and-run prog.cpp < /dev/null
install-remote:
xxx
#!/bin/sh
CXXFLAGS="-std=c++11 -Wall -Wno-sign-compare -Wno-unused-value"
usage () {
echo compile-and-run [program.cpp]
echo
echo Compiles and executes a c++ program.
echo The standard input and output is passed down to the program.
echo The exit status is that of the compiler.
}
if [ x"$1" = "x" ]; then
usage
exit 0
fi
# -H does not seem to always work
#ulimit -H -t 100
ulimit -t 5
if g++ $CXXFLAGS $1; then
# ulimit -H -t 1 # Apparently -H -t takes a number >= 10 for hard limit
ulimit -t 1
./a.out
else
exit $?
fi
#!/bin/sh
#host=134.158.75.87 # wims-docker
host=134.158.75.207 # sage-docker
#host=localhost
port=8080
file=$1
curl --form "code=<$file" --form "input=<-" $host:$port/compile-and-run
#!/usr/bin/python
import tempfile
import popen2
import os
from flask import Flask, redirect, url_for, request
docker_compile_and_run="/home/wims/other/bin/docker-compile-and-run"
#docker_compile_and_run="docker-compile-and-run"
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Web service for compiling and running a c++ program in a remote sandbox.\nPost on /compile-and-run with the c++ program uploaded as form input `code` and input as form input `input`\n'
@app.route('/compile-and-run',methods=['POST'])
def compile_and_run():
input = request.form['input']
code = request.form['code']
fd = tempfile.NamedTemporaryFile(suffix=".cpp", prefix="docker-compile-and-run-")
fd.write(code)
fd.flush()
(child_out, child_in) = popen2.popen2(docker_compile_and_run+" "+fd.name)
child_in.write(input)
child_in.flush()
child_in.close()
result = child_out.read()
return result
if __name__ == '__main__':
#app.run(debug=True)
app.run(host="0.0.0.0", port=8080)
#include <vector>
#include <iostream>
#include <cstdlib>
#include <sstream>
using namespace std;
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
/**
* TODO:
* - [X] make this into a program rather than a shell script for a minimum of safety
* - [ ] set tight resources limits
* - [ ] check proper handling of all potential errors
* - [ ] make this into a plain C program to not add a dependency on C++
**/
string compile_and_run = "compile-and-run.sh";
string bin_dir = "/home/wims/other/bin/";
//string bin_dir = "";
string docker = "/usr/bin/docker";
bool verbose = false;
void usage () {
cerr << "docker-compile-and-run [program.cpp]" << endl;
cerr << endl;
cerr << "Compiles and executes a c++ program within a sandbox." << endl;
cerr << "The standard input and output is passed down to the program." << endl;
cerr << "The exit status is that of the compiler." << endl;
}
int my_exec(string cmd, const vector<string> args) {
if (verbose) {
cerr << "exec: " << cmd;
for (unsigned int i=0; i<args.size(); i++)
cerr << " " << args[i];
cerr << endl;
}
vector<const char*> argv;
argv.push_back(cmd.c_str());
for (unsigned int i=0; i<args.size(); i++)
argv.push_back(args[i].c_str());
argv.push_back((char *) 0);
const vector<const char *> argv2(argv.begin(), argv.end());
return execv(cmd.c_str(), (char * const*)argv.data());
}
int my_system(string cmd, const vector<string> args, const string in, const string out, const string err) {
// Taken from man waitpid
int status;
pid_t w;
pid_t cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Code executed by child */
if ( in != "" ) {
FILE* f = fopen(in.c_str(), "r");
dup2(fileno(f), STDIN_FILENO);
fclose(f);
}
if ( out != "" ) {
FILE* f = fopen(out.c_str(), "w");
dup2(fileno(f), STDOUT_FILENO);
fclose(f);
}
my_exec(cmd, args);
perror("exec");
exit(EXIT_FAILURE);
}
w = waitpid(cpid, &status, 0);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}
int my_system(string cmd, const vector<string> args) {
return my_system(cmd, args, "", "", "");
}
std::string my_popen(const string cmd, vector<string> args) {
int pipefd[2];
pid_t cpid;
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Child writes to pipe */
close(pipefd[0]); /* Close unused read end */
dup2(pipefd[1], STDOUT_FILENO);
my_exec(cmd, args);
perror("exec");
exit(EXIT_FAILURE);
}
close(pipefd[1]); /* Close unused write end */
char buffer[128];
std::string result = "";
int n;
while ((n = read(pipefd[0], buffer, sizeof(buffer))) > 0) {
buffer[n] = 0;
result += buffer;
}
wait(NULL); /* Wait for child */
return result;
}
string docker_run(string container, string cmd, vector<string> args) {
// See http://docs.docker.com/engine/reference/run/#runtime-constraints-on-resources
// for the resource limitations
vector<string> docker_args = {"run",
"--detach=true", // Run in background
// With 10M, the compilation and run is much slower
"--memory", "100M", "--memory-swap", "100M",
// Not available with docker 1.7?
// "--kernel-memory", "50M",
// "--cpu-quota" "50000", // Allow for using max 50% of the CPU
// Incompatible with detach
// "--rm=true", // Automatically delete container when done with the command
container, cmd};
for (unsigned int i=0; i<args.size(); i++)
docker_args.push_back(args[i]);
string ID = my_popen(docker, docker_args);
// see http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
ID.erase(ID.find_last_not_of(" \n\r\t")+1);
return ID;
}
void docker_exec(string docker_id, vector<string> args, bool interactive) {
vector<string> docker_args = {"exec"};
if (interactive) docker_args.push_back("-i");
docker_args.push_back(docker_id);
for (unsigned int i=0; i<args.size(); i++)
docker_args.push_back(args[i]);
my_system(docker, docker_args);
}
void docker_cp(string docker_id, string source, string target) {
// See http://stackoverflow.com/questions/22907231/copying-files-from-host-to-docker-container
// TODO: replace with 'docker cp' of docker 1.8 when possible
vector<string> docker_args = {"exec", "-i", docker_id, "/bin/bash", "-c", "cat > "+target};
my_system(docker, docker_args, source, "", "");
}
void docker_rm(string docker_id) {
vector<string> docker_args = {"rm", "-f", docker_id};
my_system(docker, docker_args, "", "/dev/null", "");
}
int main(int argc, char **argv) {
//cout << my_popen("/usr/bin/id", {}) << "|" << endl;
//printf("egid: %d\n", getegid());
//exec("/usr/bin/id", {});
//system("/usr/bin/id");
if (argc != 2) {
usage();
return 0;
}
string program=argv[1];
if (verbose)
cerr << "Compiling and running: " << program << endl;
string program_in_docker="prog.cpp";
string docker_id = docker_run("crosbymichael/build-essential", "sleep", vector<string>({"10"}));
if (verbose) {
cerr << "docker_id: " << docker_id << endl;
cerr << "Current directory: ";
my_system("/bin/pwd", {});
}
docker_cp(docker_id, bin_dir+compile_and_run, compile_and_run);
docker_cp(docker_id, program, program_in_docker);
docker_exec(docker_id, vector<string>({ "chmod", "700", compile_and_run }), false);
docker_exec(docker_id, vector<string>({ "./"+compile_and_run, program_in_docker}), true);
docker_rm(docker_id);
return 0;
}
#!/bin/sh
# TODO:
# - set tight resources limits
# - make this into a program rather than a shell script for a minimum of safety
usage () {
echo docker-compile-and-run [program.cpp]
echo
echo Compiles and executes a c++ program within a sandbox.
echo The standard input and output is passed down to the program.
echo The exit status is that of the compiler.
}
if [ x"$1" = "x" ]; then
usage
exit 0
fi
ID=`sudo docker run -d crosbymichael/build-essential sleep 1000`
sudo docker exec -i $ID sh -c "cat > prog.cpp" < $1
if sudo docker exec $ID g++ prog.cpp; then
sudo docker exec -i $ID ./a.out
else
exit $?
fi
sudo docker rm -f $ID > /dev/null 2>&1
#include<stdio.h>
main()
{
printf("Hello World");
}
#include <iostream>
#include <fstream>
using namespace std;
int main() {
int x = 1+2;
if ( x == 3 ); {
cout << "Bonjour!" << endl;
}
cerr << "Bonjour sur la sortie d'erreur" << endl;
cout << "Au revoir." << endl;
return 0;
}
print "coucou"
type=first
textarea="data explain"
:Remettre en bon ordre des objets donnés, glisser-déposer.
On présente une liste d'objets, et il faut les trier selon l'ordre précisé
en les tirant vers les cases prévues avec la souris.
<p>
Pour construire un exercice avec ce modèle, il suffit d'entrer la liste
d'objets à trier et changer le texte explicatif.
<p>
Avec une petite modification, une variante de ce modèle peut accepter des
images comme objets.
<p>
Auteur du modèle : Gang Xiao <qualite@wimsedu.info>
:%%%%%%%%%%%%%%%%% ATTENTION %%%%%%%%%%%%%%%%%%%%
Enlevez l'en-tête ci-dessus si vous détruisez les balises pour le modèle !
(Ce sont les lignes qui commencent par un ':'.)
Sinon l'exercice risque de ne pas pouvoir repasser sous Createxo.
:%%%%%%%% Paramètres d'exemples à redéfinir %%%%%%%%%%%%%%%%%
:\title{Complexité}
:\author{Viviane, Pons}
:\email{viviane.pons@lri.fr}
:\credits{}
:Nombre d'objets à trier par exercice. Jusqu'à 20.
Si ce nombre est plus petit que les objets disponibles, une partie tirée au
hasard des objets seront présentés. <p>
Si ce nombre est plus grand que les objets disponibles, il sera ramené au
nombre d'objets.
\integer{tot=4}
:La taille des objets à glisser, en pixels, x fois y.
Pensez aux gens qui augmentent la taille de polices de leurs navigateurs !
Ne mettez pas les cases trop petites.
\text{size=80x40}
:La liste d'objets à réordonner
Ecrivez les objets dans le bon ordre, séparés par des virgules.
\text{data=log(n),n,nlog(n),n^2,n^3,2^n}
:Le texte qui explique ce qu'il faut faire.
\text{explain=Ordonner ces complexités de la plus rapide (à gauche) à la plus lente (à droite) pour n grand.}
:Mise en aléatoire par des accolades emboitables
help
\text{accolade=item(1,1 oui, 2 non)}
:%%%%%%%%%%%%%% Rien à modifier avant l'énoncé %%%%%%%%%%%%%%%%
\text{accolade=wims(word 1 of \accolade)}
\text{data=\accolade=1 ? wims(embraced randitem \data)}
\integer{datacnt=items(\data)}
\integer{tot=min(20,min(\tot,\datacnt))}
\if{\tot<\datacnt}{
\text{sh=shuffle(\datacnt)}
\text{sh=wims(sort numeric items \sh[1..\tot])}
\text{data=item(\sh,\data)}
}
\text{st=wims(makelist r x for x=1 to \tot)}
\steps{\st}
:%%%%%%%%%%%%% Maintenant l'énoncé en code html. %%%%%%%%%%%%%%%%%%%%
::Vous n'avez pas besoin de modifier ceci en général.
\statement{\explain
<table class="wimsnoborder"><tr>
\for{k=1 to \tot}{<td>\embed{r\k,\size}</td>}
</tr></table>}
:%%%%%%%%%%%%% Rien à modifier ci-après. %%%%%%%%%%%%%%%%%5
\answer{1}{\data[1]}{type=dragfill}
\answer{2}{\data[2]}{type=dragfill}
\answer{3}{\data[3]}{type=dragfill}
\answer{4}{\data[4]}{type=dragfill}
\answer{5}{\data[5]}{type=dragfill}
\answer{6}{\data[6]}{type=dragfill}
\answer{7}{\data[7]}{type=dragfill}
\answer{8}{\data[8]}{type=dragfill}
\answer{9}{\data[9]}{type=dragfill}
\answer{10}{\data[10]}{type=dragfill}
\answer{11}{\data[11]}{type=dragfill}
\answer{12}{\data[12]}{type=dragfill}
\answer{13}{\data[13]}{type=dragfill}
\answer{14}{\data[14]}{type=dragfill}
\answer{15}{\data[15]}{type=dragfill}
\answer{16}{\data[16]}{type=dragfill}
\answer{17}{\data[17]}{type=dragfill}
\answer{18}{\data[18]}{type=dragfill}
\answer{19}{\data[19]}{type=dragfill}
\answer{20}{\data[20]}{type=dragfill}
type=first
textarea="datatrue datafalse explain"
:Une question choix multiples avec permutation alatoire des choix.
Voici un modle de question choix multiples. L'ordre des choix est alatoire,
ainsi que les choix s'il y en a suffisamment qui sont dfinis.
Quand il y a plusieurs bons choix, il suffit d'en choisir un, peu importe lequel.
<p>
Le texte n'est pas alatoire. Un autre modle <b>QCM la suite</b>
permet d'avoir aussi un texte alatoire.
<p>Auteur du modle : Gang Xiao <qualite@wimsedu.info></p>
:%%%%%%%%%%%%%%%%% ATTENTION %%%%%%%%%%%%%%%%%%%%
Enlevez l'en-tte ci-dessus si vous dtruisez les balises pour le modle !
(Ce sont les lignes qui commencent par un ':'.)
Sinon l'exercice risque de ne pas pouvoir repasser sous Createxo.
:%%%%%%%% Paramtres d'exemples redfinir %%%%%%%%%%%%%%%%%
:\title{Appel de fonctions}
:\author{Viviane Pons}
:\email{viviane.pons@upsud.fr}
:\credits{}
:Nombre de choix prsenter. Au plus 10.
Vous devez dfinir suffisamment de choix. Sinon l'exercice affichera seulement ce qui est disponible.
\integer{tot=4}
:Le nombre de bons choix dans chaque exercice. Ne doit pas depasser le total.
\integer{givetrue=1}
:Nombre de mauvais choix "obligatoires".
Par exemple si ce nombre est 2, les deux premiers mauvais choix dans la liste seront toujours prsents dans les exercices gnrs.
<p> Dans le doute, mettez 0.</p>
\integer{minfalse=0}
:Le texte qui explique ce qu'il faut faire.
help
\text{explain=Slectionner un appel correct pour la fonction dont la signature est
<pre>int max(int a, int b)</pre>}
:Le(s) bon(s) choix, un par ligne.
On peut en placer plusieurs (un par ligne) pour tirer au hasard.
Evitez les phrases trop longues ! Aucun point-virgule dans la phrase.
help
\matrix{datatrue=max(3,4)
max(-1,5)
max(6,2)
max(max(1,2),3)}
:Les mauvais choix, un par ligne.
Vous pouvez en donner plus que ce qu'il faut tirer au hasard.
Evitez les phrases trop longues ! Aucun point-virgule dans la phrase.
help
\matrix{datafalse=max(2.5,3)
max("abab","bcbc")
max(5)
max(8)
max(5,4,2,9)
max(1.2,5.3)
max(4,4,"hop")
min(2,5)
Max(3,3)}
:Mots d'option : <span class="tt wims_code_words">checkbox</span>, <span class="tt wims_code_words">split</span>.
Ajouter le mot <span class="tt wims_code_words">checkbox</span> s'il y a plusieurs bonnes rponses et si l'lve doit choisir toutes les bonnes rponses (au lieu d'une seule).
Dans ce cas, ajouter aussi le mot <span class="tt wims_code_words">split</span> si on autorise une note partielle quand seulement une partie des bonnes rponses sont choisies.
\text{option=}
:Feedback Gnral
Ce texte s'affichera aprs la rponse de l'apprenant, qu'elle soit juste ou fausse.
\text{feedback_general=}
:Feedback en cas de bonne rponse
Ce texte s'affichera aprs la rponse de l'apprenant, en cas de bonne reponse ou de reponse partielle.
\text{feedback_bon=}
:Feedback en cas de mauvaise rponse
Ce texte s'affichera aprs la rponse de l'apprenant, s'il a coch au moins une mauvaise rponse.
\text{feedback_mauvais=}
:Mise en alatoire par des accolades emboitables
help
\text{accolade=item(1,1 oui, 2 non)}
:%%%%%%%%%%%%%% Rien modifier avant l'nonc %%%%%%%%%%%%%%%%
\text{accolade=wims(word 1 of \accolade)}
\text{empty=}
\if{\feedback_general != \empty}{
\text{feedback_general=<p class="feedback">\feedback_general</p>}
}
\if{\feedback_bon != \empty}{
\text{feedback_bon=<p class="feedback good_answer">\feedback_bon</p>}
}
\if{\feedback_mauvais != \empty}{
\text{feedback_mauvais=<p class="feedback bad_answer">\feedback_mauvais</p>}
}
\text{datatrue=wims(nonempty rows \datatrue)}
\text{datafalse=wims(nonempty rows \datafalse)}
\integer{truecnt=rows(\datatrue)}
\integer{falsecnt=rows(\datafalse)}
\integer{givetrue=\givetrue<1?1}
\integer{givetrue=\givetrue>\truecnt?\truecnt}
\integer{tot=\tot > \falsecnt+\givetrue?\falsecnt+\givetrue}
\integer{givetrue=\givetrue>\tot-1?\tot-1}
\integer{minfalse=\minfalse>\tot-\givetrue?\tot-\givetrue}
\text{tsh=shuffle(\truecnt)}
\text{true=row(\tsh,\datatrue)}
\if{\minfalse>0}{
\text{false1=row(1..\minfalse,\datafalse);}
\text{false2=row(\minfalse+1..\falsecnt,\datafalse)}
}{
\integer{minfalse=0}
\text{false1=}
\text{false2=\datafalse}
}
\text{fsh=shuffle(\falsecnt)}
\text{false2=row(\fsh,\false2)}
\text{pick=row(1..\givetrue,\true);\false1 row(1..\tot-\givetrue-\minfalse,\false2)}
\text{ind=wims(makelist 1 for x=1 to \givetrue),wims(makelist 0 for x=1 to \tot-\givetrue)}
\text{sh=shuffle(\tot)}
\text{ind=item(\sh,\ind)}
\text{pick=row(\sh,\pick)}
\text{pick=\accolade=1 ? wims(embraced randitem \pick)}
\text{explain=\accolade=1 ? wims(embraced randitem \explain)}
\text{ans=positionof(1,\ind)}
\text{list=item(1..\tot,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)}
\text{anstype=checkbox iswordof \option?checkbox:radio}
:%%%%%%%%%%%%% Maintenant l'nonc en code html. %%%%%%%%%%%%%%%%%%%%
::Vous n'avez pas besoin de modifier ceci en gnral.
\statement{
\explain
\for{i=1 to \tot}{
<p class="oefreply"><label><strong>\embed{reply 1,\i}-</strong> \pick[\i;]</label></p>
}}
:%%%%%%%%%%%%% Rien modifier ci-aprs. %%%%%%%%%%%%%%%%%5
\answer{La rponse}{\ans;\list}{type=\anstype}{option=\option}
\feedback{1=1}{\feedback_general}
\feedback{\reply1 isitemof \list[\ans]}{\feedback_bon}
\feedback{\reply1 notitemof \list[\ans]}{\feedback_mauvais}
type=first
textarea="datatrue datafalse explain"
:Une question choix multiples avec permutation alatoire des choix.
Voici un modle de question choix multiples. L'ordre des choix est alatoire,
ainsi que les choix s'il y en a suffisamment qui sont dfinis.
Quand il y a plusieurs bons choix, il suffit d'en choisir un, peu importe lequel.
<p>
Le texte n'est pas alatoire. Un autre modle <b>QCM la suite</b>
permet d'avoir aussi un texte alatoire.
<p>Auteur du modle : Gang Xiao <qualite@wimsedu.info></p>
:%%%%%%%%%%%%%%%%% ATTENTION %%%%%%%%%%%%%%%%%%%%
Enlevez l'en-tte ci-dessus si vous dtruisez les balises pour le modle !
(Ce sont les lignes qui commencent par un ':'.)
Sinon l'exercice risque de ne pas pouvoir repasser sous Createxo.
:%%%%%%%% Paramtres d'exemples redfinir %%%%%%%%%%%%%%%%%
:\title{Cration de tableau}
:\author{Viviane, Pons}
:\email{viviane.pons@lri.fr}
:\credits{}
:Nombre de choix prsenter. Au plus 10.
Vous devez dfinir suffisamment de choix. Sinon l'exercice affichera seulement ce qui est disponible.
\integer{tot=4}
:Le nombre de bons choix dans chaque exercice. Ne doit pas depasser le total.
\integer{givetrue=1}
:Nombre de mauvais choix "obligatoires".
Par exemple si ce nombre est 2, les deux premiers mauvais choix dans la liste seront toujours prsents dans les exercices gnrs.
<p> Dans le doute, mettez 0.</p>
\integer{minfalse=0}
:Le texte qui explique ce qu'il faut faire.
help
\text{explain=Slectionner l'instruction correcte pour crer un tableau d'entier.}
:Le(s) bon(s) choix, un par ligne.
On peut en placer plusieurs (un par ligne) pour tirer au hasard.
Evitez les phrases trop longues ! Aucun point-virgule dans la phrase.
help
\matrix{datatrue=vector &lt;int&gt; tab = &#123;1,2,4,4,2,1&#125;;
vector &lt;int&gt; tab = vector &lt;int&gt; (3);
vector &lt;int&gt; a = &#123;3,3,4&#125;;}
:Les mauvais choix, un par ligne.
Vous pouvez en donner plus que ce qu'il faut tirer au hasard.
Evitez les phrases trop longues ! Aucun point-virgule dans la phrase.
help
\matrix{datafalse=vector tab = &#123;1,2,4,4,2,1&#125;;
int tab = vector &lt;int&gt; (3);
vector &lt;double&gt; tab = vector &lt;double&gt;(5);
vector&lt;int&gt; a = 5;
int a = &#123;3,3,4&#125;;}
:Mots d'option : <span class="tt wims_code_words">checkbox</span>, <span class="tt wims_code_words">split</span>.
Ajouter le mot <span class="tt wims_code_words">checkbox</span> s'il y a plusieurs bonnes rponses et si l'lve doit choisir toutes les bonnes rponses (au lieu d'une seule).
Dans ce cas, ajouter aussi le mot <span class="tt wims_code_words">split</span> si on autorise une note partielle quand seulement une partie des bonnes rponses sont choisies.
\text{option=}
:Feedback Gnral
Ce texte s'affichera aprs la rponse de l'apprenant, qu'elle soit juste ou fausse.
\text{feedback_general=}
:Feedback en cas de bonne rponse
Ce texte s'affichera aprs la rponse de l'apprenant, en cas de bonne reponse ou de reponse partielle.
\text{feedback_bon=}
:Feedback en cas de mauvaise rponse
Ce texte s'affichera aprs la rponse de l'apprenant, s'il a coch au moins une mauvaise rponse.
\text{feedback_mauvais=}
:Mise en alatoire par des accolades emboitables
help
\text{accolade=item(1,1 oui, 2 non)}
:%%%%%%%%%%%%%% Rien modifier avant l'nonc %%%%%%%%%%%%%%%%
\text{accolade=wims(word 1 of \accolade)}
\text{empty=}
\if{\feedback_general != \empty}{
\text{feedback_general=<p class="feedback">\feedback_general</p>}
}
\if{\feedback_bon != \empty}{
\text{feedback_bon=<p class="feedback good_answer">\feedback_bon</p>}
}
\if{\feedback_mauvais != \empty}{
\text{feedback_mauvais=<p class="feedback bad_answer">\feedback_mauvais</p>}
}
\text{datatrue=wims(nonempty rows \datatrue)}
\text{datafalse=wims(nonempty rows \datafalse)}
\integer{truecnt=rows(\datatrue)}
\integer{falsecnt=rows(\datafalse)}
\integer{givetrue=\givetrue<1?1}
\integer{givetrue=\givetrue>\truecnt?\truecnt}
\integer{tot=\tot > \falsecnt+\givetrue?\falsecnt+\givetrue}
\integer{givetrue=\givetrue>\tot-1?\tot-1}
\integer{minfalse=\minfalse>\tot-\givetrue?\tot-\givetrue}
\text{tsh=shuffle(\truecnt)}
\text{true=row(\tsh,\datatrue)}
\if{\minfalse>0}{
\text{false1=row(1..\minfalse,\datafalse);}
\text{false2=row(\minfalse+1..\falsecnt,\datafalse)}
}{
\integer{minfalse=0}
\text{false1=}
\text{false2=\datafalse}
}
\text{fsh=shuffle(\falsecnt)}
\text{false2=row(\fsh,\false2)}
\text{pick=row(1..\givetrue,\true);\false1 row(1..\tot-\givetrue-\minfalse,\false2)}
\text{ind=wims(makelist 1 for x=1 to \givetrue),wims(makelist 0 for x=1 to \tot-\givetrue)}
\text{sh=shuffle(\tot)}
\text{ind=item(\sh,\ind)}
\text{pick=row(\sh,\pick)}
\text{pick=\accolade=1 ? wims(embraced randitem \pick)}
\text{explain=\accolade=1 ? wims(embraced randitem \explain)}
\text{ans=positionof(1,\ind)}
\text{list=item(1..\tot,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)}
\text{anstype=checkbox iswordof \option?checkbox:radio}
:%%%%%%%%%%%%% Maintenant l'nonc en code html. %%%%%%%%%%%%%%%%%%%%
::Vous n'avez pas besoin de modifier ceci en gnral.
\statement{
\explain
\for{i=1 to \tot}{
<p class="oefreply"><label><strong>\embed{reply 1,\i}-</strong> \pick[\i;]</label></p>
}}
:%%%%%%%%%%%%% Rien modifier ci-aprs. %%%%%%%%%%%%%%%%%5
\answer{La rponse}{\ans;\list}{type=\anstype}{option=\option}
\feedback{1=1}{\feedback_general}
\feedback{\reply1 isitemof \list[\ans]}{\feedback_bon}
\feedback{\reply1 notitemof \list[\ans]}{\feedback_mauvais}
CXXFLAGS=-g -Wall -std=c++0x
WIMSHOST=wimstest
#DOCKERHOST=134.158.75.87# wimsdocker
DOCKERHOSTADMIN=debian
DOCKERHOST=134.158.75.92
SSH=ssh -x
tests: test-compile-and-run.sh test-docker-compile-and-run test-docker-compile-and-run-client
test-%:
@echo running tests for $*
@echo | $* prog.cpp > prog.out.obtained 2> /dev/null && diff prog.out prog.out.obtained
@echo coucou | $* prog-stdin.cpp > prog-stdin.out.obtained 2> /dev/null && diff prog-stdin.out prog-stdin.out.obtained
@rm prog.out.obtained prog-stdin.out.obtained
dockerhost-preinstall:
scp dockerhost_setup.sh secure_exec_local secure_exec_server $(DOCKERHOSTADMIN)@$(DOCKERHOST):
$(SSH) $(DOCKERHOSTADMIN)@$(DOCKERHOST) sudo bash dockerhost-setup.sh
dockerhost-update:
scp secure_exec_local secure_exec_server $(DOCKERHOSTADMIN)@$(DOCKERHOST):
$(SSH) $(DOCKERHOSTADMIN)@$(DOCKERHOST) sudo cp secure_exec_server secure_exec_local /usr/local/bin
dockerhost-clean: # TODO Add a test that DOCKERHOST <-> WIMSHOST
ssh root@$(DOCKERHOST) userdel -r www
dockerhost-run:
$(SSH) wims@$(DOCKERHOST) other/bin/docker-compile-and-run-server
dockerhost-test:
@echo == Testing docker ===============
$(SSH) $(DOCKERHOSTADMIN)@$(DOCKERHOST) sudo docker run hello-world
@echo == Testing secure_exec_local ====
tar czf - -C tests/dir . | $(SSH) $(DOCKERHOSTADMIN)@$(DOCKERHOST) sudo -u www super secure_exec_local ./monscript
@echo == Testing server ===============
tar czf archive.tgz -C tests/dir .
curl --form "archive=@archive.tgz" --form "cmd=./monscript" "http://$(DOCKERHOST):8080/secure_exec"
wimshost-install:
scp secure_exec wims@$(WIMSHOST):other/bin
scp secure_exec_wrapper.sh wims@$(WIMSHOST):public_html/bin/secure_exec
# $(SSH) root@$(WIMSHOST) service httpd restart
wimshost-test: # Needs to be updated
scp prog.cpp wims@$(WIMSHOST):
$(SSH) wims@$(WIMSHOST) ./other/bin/docker-compile-and-run prog.cpp < /dev/null
install-remote:
xxx
# Secure execution of a command in a sandbox
This implements a web service allowing to execute a command in a
docker sandbox with reasonable security.
## Usage of the client
This assumes that the webservice is running and its url is set in
[](secure_exec).
The following command uses the webservice to create a new sandbox,
initialize it with a copy of the content of `dir` in the sandbox, run
`cmd` in it, and print the output:
secure_exec <dir> <cmd>
## Installation of the webservice
This assumes that you have access to some remote machine running some
variant of debian, under a user with sudo permission.
- Edit the [](Makefile) to point DOCKERHOST to the ip address of the
server and DOCKERHOSTADMIN to the user
- Run:
make dockerhost-preinstall
make dockerhost-run
- (optional) Run
make dockerhost-test
## Updating the webservice
Run:
make dockerhost-update
## Tests
The directory `tests` contains a collection of tests scripts:
- Test 1 assumes that docker is installed.
- Tests 2 and 3 assume in addition that `secure_exec_local` has been
installed in `/usr/local/bin` and `/etc/super.tab` has been
configured locally as in `super.tab`.
- Test 4 assumes that the web service is running on some (remote)
server, and that its url is set in `secure_exec`.
In addition, the following command runs some tests on the webservice:
make dockerhost-test
## TODO
- More documentation
- Security review
- Truncation of output
- Authentication between client and server
A minima: firewall setup to restrict incoming connections from the client
- Resource limitations
- The created temporary archive should be in a temporary directory and cleaned up
Or could we avoid the temporary file?
#!/bin/bash
BASE_DOCKER_IMAGE=crosbymichael/build-essential
# Taken from https://docs.docker.com/engine/installation/linux/docker-ce/debian/#install-using-the-repository
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg2 \
software-properties-common \
super python3-flask
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/debian \
$(lsb_release -cs) \
stable"
sudo apt-get update
sudo apt-get install docker-ce
#sudo groupadd docker # aready exists
#sudo service docker restart
sudo docker pull $BASE_DOCKER_IMAGE
sudo useradd www
sudo cp secure_exec_local secure_exec_server /usr/local/bin
sudo sh -c 'echo "secure_exec_local /usr/local/bin/secure_exec_local u=nobody g=docker www" >> /etc/super.tab'
# At boot time run the server as www
sudo sh -c '#!/bin/sh echo "su -c /usr/local/bin/secure_exec_server www" >> /etc/rc.local'
# TODO
#! /bin/sh
#vm="$1"
url=http://134.158.75.92:8080/secure_exec
dir="$1"
cmd="$2"
tar czf archive.tgz -C "$dir" .
curl --form "archive=@archive.tgz" --form "cmd=$cmd" "$url"