diff --git a/EXOS/Examen.tex b/EXOS/Examen.tex new file mode 100644 index 0000000..d1941a9 --- /dev/null +++ b/EXOS/Examen.tex @@ -0,0 +1,135 @@ +% -*- coding: utf-8; -*- +\documentclass[a4paper,12pt]{article} + +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage[french,british]{babel} + + +%%%%%%%%% Gestion de la correction + +\usepackage{ifthen} +\usepackage{framed} +\usepackage{environ} +\usepackage{xcolor} +\colorlet{shadecolor}{gray!10!red!5} + +\ifdefined\iscorrec % Définition depuis le script d'appel +\else + \def\iscorrec{1} % 0=> sujet, 1=>corrigé +\fi + +%%% \begin{correction}....\end{correction} +% le contenu ne s'affiche que si \iscorrec=1 + +\NewEnviron{correction}{\ifthenelse{\iscorrec=1}{% + \medskip\medskip\par\begin{shaded}\noindent{\bf Solution:} \BODY \end{shaded} +}{}} + + +%%%%%%%%% Paramètres individuels du sujet + +%%% Valeurs par défaut (pour une compilation isolée) + +\ifdefined\assignedparameters\else + \def\assignedparameters{1,1,1,1} % dans cet exemple, 4 paramètres requis +\fi + +%%% Liste permettant d'accéder aux assignedparameters: \ListAP[1], \ListAP[2], etc. + +\usepackage{listofitems} +\ifx\assignedparameters\empty % (erreur de \readlist dans ce cas) +\else + \readlist*\ListAP{\assignedparameters} +\fi + +%%% Switch de versions, définie ici "à vide" pour mettre du renewcommand plus tard + +\newcommand{\switch}{} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\begin{document} + +\noindent BUT, 1ère année \hfill 2021-22 + +\begin{center} \Large Examen de math \end{center} + + +%%%%%%%%%%%%%% + +\subsection*{Exercice 1} + + +\def\versionExo{\ListAP[1]} + +\ifnum\versionExo=1 +MF1 +\fi +\ifnum\versionExo=2 +PB1 +\fi +\ifnum\versionExo=3 +FG1 +\fi +\ifnum\versionExo=4 +PL1 +\fi + +\subsection*{Exercice 2} + +\def\versionExo{\ListAP[2]} + +\ifnum\versionExo=1 +MF2 +\fi +\ifnum\versionExo=2 +PB2 +\fi +\ifnum\versionExo=3 +FG2 +\fi +\ifnum\versionExo=4 +PL2 +\fi + +\subsection*{Exercice 3} + +\def\versionExo{\ListAP[3]} +\ifnum\versionExo=1 +MF3 +\fi +\ifnum\versionExo=2 +PB3 +\fi +\ifnum\versionExo=3 +FG3 +\fi +\ifnum\versionExo=4 +PL3 +\fi + +\subsection*{Exercice 4} + +\def\versionExo{\ListAP[4]} + +\ifnum\versionExo=1 +MF4 +\fi +\ifnum\versionExo=2 +PB4 +\fi +\ifnum\versionExo=3 +FG4 +\fi +\ifnum\versionExo=4 +PL4 +\fi + +\end{document} + + diff --git a/EXOS/MODE_D_EMPLOI b/EXOS/MODE_D_EMPLOI new file mode 100644 index 0000000..20567ec --- /dev/null +++ b/EXOS/MODE_D_EMPLOI @@ -0,0 +1,49 @@ +======================================================================================= +Exemple 2 : idem + génération de sujets individualisés avec latex +======================================================================================= + + +assignation.ods : coordonnées et assignation des sujets pour chaque étudiant + +Examen.tex : sources du sujet d'examen (incluant différentes versions possibles + corrections) + + +GÉNÉRATION DES SUJETS +====================== + + - Ouvrir un terminal dans ce répertoire, taper 'ruby genere_sujets.rb' + + - Lit "assignation.ods", récupère les paramètres de chaque étudiant, et génère son sujet individuel en conséquence, avec pdflatex. + + - Les emplacements des sujets, nom de fichier d'assignation, etc, se configurent : ouvrir le fichier genere_sujets.rb avec un éditeur de texte + + - Lire les sources dans 'Examen.tex' afin de comprendre le lien entre "assignation.ods" et les variables latex correspondantes + + +ENVOI DES SUJETS +================ + + - Ouvrir un terminal dans ce répertoire, taper 'ruby envoie_sujets.rb' + + - Fonctionne exactement comme dans l'exemple 1 + + +AIDE À LA CORRECTION +==================== + + - Fonctionne exactement comme dans l'exemple 1 (les RENDUS ne sont pas remis ici, voir l'exemple 1) + + +Exécutables requis: +================== + +Pour tous les scripts: + - ruby (avec les quelques "gem" requis installés -- a priori ils sont plutôt standard) + - unoconv (version ligne de commande de libreoffice) + +Pour la génération basique de sujets: + - pdflatex + +Pour l'aide à la correction: + - un navigateur de fichier, lecteur de photos, lecteur de pdf, etc. + - wmctrl (manipulation des fenêtres x11 en ligne de commande) -- optionnel diff --git a/EXOS/envoie_sujets.rb b/EXOS/envoie_sujets.rb new file mode 100644 index 0000000..edde5c7 --- /dev/null +++ b/EXOS/envoie_sujets.rb @@ -0,0 +1,197 @@ +#!/usr/bin/ruby +# -*- coding: utf-8 -*- +# encoding: utf-8 + +# Envoi individuel des sujets d'interro + consignes + +# Lancement : +# ruby envoie_sujets.rb + +# Exécutables nécessaires à installer : +# * unoconv : version 'ligne de commande' de libreoffice. + +# Problèmes connus : +# * Classe ou gem ruby manquant : installer le gem correspondant +# --> exemple pour installer le gem 'highline' : sudo gem install highline +# * Erreur de unoconv : "Error: Unable to connect or start own listener. Aborting." +# --> Survient parfois si un fichier .ods est déjà ouvert. Simplement relancer le script. + + +# Classes et gems ruby nécessaires +##################################### + +# pour installer un gem manquant, par exemple le gem 'highline' : +# sudo gem install highline + +require 'net/smtp' +require 'mail' # gère tous types de serveurs d'envoi et permet de joindre facilement des fichiers (contrairement à net/smtp où j'ai eu des problèmes). +# https://www.rubydoc.info/github/mikel/mail + + +# Configuration +##################################### + +FileEtud = "assignation.ods" +SujetDir = "Sujets" # emplacement des sujets +NomEnvoi = "Examen.pdf" # nom générique de la pièce jointe à envoyer + +ReallySend = true # passer à true pour vraiment procéder à l'envoi + +### Paramètres du mail +Who='Pascal Lafourcade' +From='pascal.lafourcade@uca.fr' +MTA='smtp.uca.fr' +Subject="BD P3 -- Sujet Partiel" + +InteractivePwd = true +# true -> demande le MDP de la boîte mail lors l'exécution. Plus sécure. Nécessite le gem highline. +# false -> entrer le MDP de la boîte mail en dur, en argument de l'appel. Moins sécure. Ne nécessite pas le gem highline. +# - usage basique dans ce cas : ruby envoie_sujets.rb monmotdepasse +# - permet aussi le scheduling : echo "ruby envoie_sujets.rb monmotdepasse" | at 13h25 + +require 'highline/import' if InteractivePwd + + +# Demande de mot de passe pour le serveur mail (fonction) +##################################### + +$mail_initialized = false +def initMail + if not $mail_initialized + # récupération du mot de passe + pwd = InteractivePwd ? + ask("Enter your password for connection to the smtp server: ") { |q| q.echo = "*" } : + ARGV[0] + + # https://medium.com/derek-gc/sending-emails-in-ruby-with-smtp-3d40bed6c437 + Mail.defaults do + delivery_method :smtp, address: MTA, port: 587, password: pwd, authentication: :login, user_name: From + end + + $mail_initialized = true + end +end + + +# Contenu du mail (fonction) +##################################### + +def sendMail(adresse,nom,prenom,sujet_pdf) + + corps = < NomEnvoi, :content => File.read(sujet_pdf) + end + else + # simple affichage + puts From + puts adresse + puts Subject + puts corps + end +end + + +# Lecture du fichier étudiant et envoi des mails +##################################### + +### Conversion automatique du fichier ODS (ou XLS) en un fichier CSV +# Options du filtre: voir +# https://wiki.openoffice.org/wiki/Documentation/DevGuide/Spreadsheets/Filter_Options + +ods2csv_command = "unoconv -f csv -e FilterOptions=58,34,76,3,,2060,true,true" + +ext = File.extname(FileEtud) +if ext != ".ods" and ext != ".xls" + puts "ERROR. Wrong file format. Only .ods or .xls accepted" + exit(1) +end +csvfile = ".#{File.basename(FileEtud, ext)}.csv" +if not system(ods2csv_command+" -o #{csvfile} #{FileEtud}") + warn "Unoconv conversion error (arrive souvent, relancer simplement le script)" + exit(1) +end + + +### Lecture des lignes du CSV et envoi + +IO.readlines(csvfile).each_with_index { |l, id| + begin # (permet de récupérer la ligne d'un éventuel problème) + + data = l.chomp.split(":"); # chomp vire le \n final + # 5 premières colonnes (toujours les mêmes) + grnum = Integer(data.shift()) rescue nil + next unless grnum && grnum >= 0 # Continue uniquement pour les "vraies" lignes, caractérisées par un "vrai" numéro de groupe en 1ère colonne (entir poitif). + nom = data.shift().tr('"', '') + prenom = data.shift().tr('"', '') + adresse = data.shift().tr('"', '') + pdfname = data.shift().tr('"', '') + + sujet_pdf = "#{SujetDir}/#{pdfname}.pdf" + puts "Envoi à #{nom} #{prenom}" + sendMail(adresse, nom, prenom, sujet_pdf) + + rescue Exception => e + puts "ERREUR, pendant le traitement de la ligne #{id+1}, du fichier de notes #{csvfile} :" + puts e.message + print "\n"+e.backtrace.join("\n")+"\n" + exit(1) + end +} + +puts "Passer ReallySend à true pour vraiment procéder à l'envoi" unless ReallySend + + + diff --git a/EXOS/genere_sujets.rb b/EXOS/genere_sujets.rb new file mode 100644 index 0000000..f8db0d9 --- /dev/null +++ b/EXOS/genere_sujets.rb @@ -0,0 +1,104 @@ +#!/usr/bin/ruby +# -*- coding: utf-8 -*- + +# Génération individuelle des sujets avec pdflatex + +# Lancement : +# ruby genere_sujets.rb + +# Exécutables nécessaires à installer : +# * unoconv : version 'ligne de commande' de libreoffice. + +# Problèmes connus : +# * Classe ou gem ruby manquant : installer le gem correspondant +# --> exemple pour installer le gem 'highline' : sudo gem install highline +# * Erreur de unoconv : "Error: Unable to connect or start own listener. Aborting." +# --> Survient parfois si un fichier .ods est déjà ouvert. Simplement relancer le script. + + +# Classes et gems ruby nécessaires +##################################### + +# pour installer un gem manquant, par exemple le gem 'machin' : +# sudo gem install machin + +require 'fileutils' + +# Configuration +##################################### + +$file = "assignation.ods" # format ods (ou xls) +$source = "Examen.tex" +$sujetdir = "Sujets" # destination des sujets +$correcdir = "Corrigés" # destination des corrigés +$builddir = "build" # destination des fichiers auxiliaires + +#$a_generer = [:sujet] +#$a_generer = [:corrige] +$a_generer = [:sujet, :corrige] + + +# Conversion automatique du fichier ODS (ou XLS) en un fichier (caché) CSV +###################################### + +# nécesite d'avoir installé unoconv +# Options du filtre: voir +# https://wiki.openoffice.org/wiki/Documentation/DevGuide/Spreadsheets/Filter_Options + +ods2csv_command = "unoconv -f csv -e FilterOptions=58,34,76,3,,2060,true,true" + +ext = File.extname($file) +if ext != ".ods" and ext != ".xls" + puts "ERROR. Wrong file format. Only .ods or .xls accepted" + exit(1) +end +csvfile = ".#{File.basename($file, ext)}.csv" +if not system(ods2csv_command+" -o #{csvfile} #{$file}") + warn "Unoconv conversion error (arrive souvent, relancer simplement le script)" + exit(1) +end + +# Génération des sujets +###################################### + +puts "Génération des sujets avec PDFLATEX" + +IO.readlines(csvfile).each do |l| + data = l.chomp.split(":"); # chomp vire le \n final + # 5 premières colonnes (toujours les mêmes) + grnum = Integer(data.shift()) rescue nil + next unless grnum && grnum >= 0 # Continue uniquement pour les "vraies" lignes, caractérisées par un "vrai" numéro de groupe en 1ère colonne (entier poitif). + nom = data.shift().tr('"', '') + prenom = data.shift().tr('"', '') + adresse = data.shift().tr('"', '') + pdfname = data.shift().tr('"', '') + # Colonnes restantes -> assignedparameters + assignedparameters=data.map{|d| d.tr('"', '')}.join(",") + + $a_generer.each do |sujcorr| + + case sujcorr + when :sujet + pdfdir = $sujetdir + iscorrec = 0 + when :corrige + pdfdir = $correcdir + iscorrec = 1 + end + + FileUtils.mkdir "#{pdfdir}" if not Dir.exists? "#{pdfdir}" + FileUtils.mkdir "#{$builddir}" if not Dir.exists? "#{$builddir}" + + pdflatex_command = "pdflatex -jobname=\"#{pdfname}\" -output-directory #{$builddir} \"\\def\\iscorrec{#{iscorrec}} \\def\\assignedparameters{#{assignedparameters}} \\input{#{$source}}\"" + + if not system(pdflatex_command) + warn "pdflatex error" + exit(1) + end + FileUtils.mv("#{$builddir}/#{pdfname}.pdf",pdfdir) + FileUtils.rm_r Dir.glob("#{$builddir}/*") + end + +end + +