Files
Copies/Script.org
T
2026-09-06 19:20:51 +02:00

482 lines
23 KiB
Org Mode

#+title: Référence des étapes et des scripts
#+author: Sébastien Miquel
#+date: 22-08-2026
#+OPTIONS:
Ce document décrit le workflow détaillé, les commandes disponibles et
les parcours alternatifs.
- [[file:Readme.org][Guide de démarrage]]
- [[file:Architecture.org][Architecture et conventions de développement]]
* Étapes
Utiliser `python -m copienator gui` ou `python -m copienator gui Interro` pour lancer un GUI
qui suit automatiquement les étapes décrites ci-dessous.
** Prétraitement de l'énoncé
Dans le dossier de l'évaluation, mettre les fichiers suivants de l'évaluation :
`enonce.pdf`, `enonce.tex`, `correction.tex`.
- `python -m copienator statement Interro` or
`python -m copienator statement Interro --restart`
À partir des trois fichiers précédents, se charge de détecter les
labels des questions et leur contenu.
Les questions vont également être regroupées. Par la suite, quand
des requêtes de corrections seront effectuées sur une question,
seulement les énoncés des questions du groupe seront envoyés (et le
corrigé de la question). Il faut donc que chaque groupe contienne
si possible le contexte nécessaire pour comprendre la question.
Une fenêtre s'ouvre pour permettre d'éditer le résultat. Ne pas
hésiter à faire des groupes plus gros que les groupes par défaut.
Après relecture le script génère :
+ un fichier `labels` avec les labels des questions
+ Un dossier `Text` avec le contenu textuel des questions,
regroupées.
+ Un dossier `Sol` avec le contenu textuel du corrigé, question par
question.
+ Un dossier `Text2`, qui compile un fichier `.tex` pour chaque
question (utilisé pour compiler un rendu pdf du corrigé pour
chaque question)
+ Un dossier `Sol2`, qui compile un fichier `.tex` pour chaque
correction de chaque question.
+ Un dossier `Persp` avec des instruction de barème pour chaque
question.
Éventuellement : vérifier et modifier les barèmes dans `Persp`.
- Alternative personnelle : `python -m copienator statement-personal Interro`
Ces deux commandes suivent la convention des scripts standardisés.
Leur import ne lance aucun traitement et les erreurs partielles sont
distinguées des échecs. Les réponses d'extraction mises en cache par
=copienator statement= et le fichier =labels= sont publiés
atomiquement.
** Prétraitement des copies
Mettre les copies scannées au format pdf dans =Interro=.
1. =python -m copienator copies rotate Interro= (facultatif)
Retourne tous les pdf de 180°, si la photocopie a été faite à
l'envers.
2. =python -m copienator copies rename Interro=
change le nom des copies en =Copie{id}.pdf=
3. =python -m copienator page-split Interro=
Découpe des copies A3 en pages A4, en retirant les pages vides.
Pour chaque page double il est possible
+ de garder les deux pages
+ de ne garder qu'une des deux pages.
+ de jeter les deux pages
+ de déplacer la délimitation à droite/gauche
Fix issues with =python -m copienator page-split Interro14/Copies/Copie01.pdf=
Le PDF transformé est construit dans un dossier temporaire. La
copie produite et la sauvegarde dans =Copies Originales= sont
ensuite installées avec rollback : une erreur conserve les deux
versions précédentes. Une relance ciblée lit directement la
sauvegarde originale sans la déplacer au préalable.
4. =python -m copienator crop-labels Interro=
Découpe la partie gauche des copies, là où il devrait y avoir les
labels des exercices/questions.
=python -m copienator crop-labels Interro --fullpage= to use the full page always.
Rerun on a single file with =python -m copienator crop-labels Interro/Copies/Copie01.pdf=
Les images et le fichier =_schema.json= d'une copie sont remplacés
ensemble. Fermer l'outil juste après la dernière validation ne peut
donc plus interrompre un thread de sauvegarde en arrière-plan.
** Labelisation et regroupement
Optional : Set proxy with ~export HTTPS_PROXY="http://10.0.0.1:3128"~
1. =python -m copienator labels Interro=, avec éventuellement =--overwrite=
Fait des requêtes à Gemini pour identifier les labels des
questions dans images générées à partir des parties gauches des copies.
Une copie PDF ou une image précise de =Cutleft= peut également être
ciblée. Plusieurs cibles de la même évaluation sont acceptées. Les
parties d'une copie restent traitées séquentiellement afin de
conserver les labels précédents comme contexte, tandis que les
copies différentes sont traitées en parallèle. Chaque réponse JSON
validée est écrite atomiquement. Une cible sans image correspondante
produit le code de sortie 4.
2. =python -m copienator review-labels Interro=
Permet de vérifier visuellement les labels trouvés.
+ Sous Linux et macOS, on peut faire =e= pour ouvrir le fichier .json et
l'éditer a la main.
+ Quand un label est manquant, il est possible de cliquer sur
l'image, ce qui copie les coordonnées dans le presse papier
puis on peut l'ajouter à la main.
+ Utilisation de `_`, `|…` et `…|` :
+ `|…` n'est pas arrêté verticalement par son type opposé.
+ `…|` est stoppé horizontalement par le `|…` le plus proche.
Pour modifier une seule copie :
=python -m copienator review-labels Interro/Copies/Copie01.pdf=
Les coordonnées agrégées sont écrites atomiquement dans le JSON de
la copie. Fermer la fenêtre avant la fin d'une copie ne remplace pas
son JSON par un résultat incomplet.
It also generates les =Copie01.json=, à partir des =Copie01_01.json=
En cas de soucis, (par exemple les pages ne sont pas dans le bon ordre)
- Réordonner les pages du fichier pdf
- Rerun =python -m copienator crop-labels Interro/Copie{id}=
- Rerun =python -m copienator labels Interro/Copie{id}=
3. =python -m copienator split-answers Interro=
Découpe les copies suivant les exercices
Peut-être appelé avec une seule copie.
Les réponses d'une copie sont préparées dans un dossier temporaire,
puis remplacent ensemble le dossier précédent. En cas d'erreur,
l'ancienne version est conservée. Les réponses devenues obsolètes
restent archivées dans le sous-dossier =Missing=.
4. =python -m copienator group-answers Interro=
Regroupe les mêmes questions de différentes copies en groupes de
tailles raisonnables.
5. Facultatif : =python -m copienator verify-groups Interro=
Vérifie que chaque réponse PDF apparaît bien dans les métadonnées
des groupes. La commande renvoie un code non nul si une réponse est
absente ou si la vérification est incomplète.
** Correction et annotation
Optional : Set proxy with ~export HTTPS_PROXY="http://10.0.0.1:3128"~
1. Il faut créer des persp, pour indication de comment corriger, et
relancer =copienator statement-personal=
2. =python -m copienator correct Interro --limit 240= OU
=python -m copienator correct Interro/Par\ label/Ex\ 2/Group_1.jpg= OU
=python -m copienator correct Interro --overwrite=
Fais les requêtes de correction à Gemini.
=copienator correct= peut être relancé sans supprimer son état. Les
fichiers =correction.json= et =correction_progress.json= sont mis à
jour atomiquement. Avec =--overwrite=, leur version précédente reste
en place jusqu'à la première écriture réussie de la nouvelle
exécution. =--reset= est la seule option qui supprime explicitement
cet état et restaure les fichiers =*_old.pdf=.
L'argument =limit= limite le nombre de requêtes à Gemini Pro
(chères), pour une version low cost, passer =--limit 0=, toutes
les requêtes seront sur Gemini Flash.
Pour diminuer le coût, il est possible de batch les requêtes, qui
seront alors traitées sous au plus 24h.
+ =python -m copienator correct Interro --batch=
+ OU =python -m copienator correct Interro --batch-from 'Ex 4'=
+ =python -m copienator batch-submit Interro=
+ =python -m copienator batch-status=
+ =python -m copienator batch-fetch Interro=
+ =python -m copienator correct Interro --deal-with-batched=
Les quatre commandes de ce flux suivent la convention des scripts
standardisés. Les fichiers de requêtes et le résultat JSONL combiné
sont publiés atomiquement : une interruption ne laisse pas de fichier
final partiellement écrit. =copienator batch-submit= conserve aussi les
identifiants distants dans =batch_jobs.json= ; la récupération les
utilise en priorité et garde la recherche par nom pour les anciens
batchs. =python -m copienator batch-status --download JOB --output
resultat.jsonl= permet aussi de télécharger atomiquement le résultat
d'un job particulier.
3. =python -m copienator post-correction Interro=
- Essaye de corriger des erreurs d'encodage/d'accents dans
=correction.json=.
- aussi échappe les `_` en dehors du mode math, pour LaTeX.
4. Résolution manuel de conflits, s'il y en a.
Edit `manual_resolutions.txt`. Use :
+ `->` or `x>` : Here set a pipe `|` before or after the new_label name
+ `-x` : replace the goal
+ `ss` : do nothing
+ `sx` : stay, and remove goal.
+ `xx` : move to goal.
+ `xs` : remove old, keep goal.
Then call `python -m copienator resolve-manual Interro`
5. Call `python -m copienator correct Interro --refaire`.
** Génération des copies annotées
1. =python -m copienator annotate-simple Interro= (facultatif)
Ajoute les annotations Gemini aux copies, enregistrées dans le dossier =Anot=.
On peut passer l'argument =--overwrite=.
OU
2. =python -m copienator annotate-checks Interro=
Ajoute les annotations Gemini, et des checkboxes à cocher.
Enregistrées dans le dossier =Bnot=,
=--overwrite=
Une seule copie peut être ciblée avec, par exemple,
=python -m copienator annotate-checks Interro/Copies/Copie01.pdf=.
Le mode =--refaire= exige un fichier =refaire.json= et écrit dans
=BRnot=.
OU
2. =python -m copienator annotate-grouped Interro= dans =BGnot=
Ajoute les annotations Gemini, et des checkboxes, et regroupe les
réponses par question.
Enregistrées dans =BGnot=
_Needs_ : label_groups file (made automatically by this function),
qui dit quelles questions regrouper.
3. =python -m copienator export Interro BGnot= (gestion perso)
Cela déplace les groupes dans le dossier configuré par =EXPORT_DIR=
(par défaut =Export=).
Le second argument peut être =BGnot=, =Bnot= ou =Anot= et reste
facultatif (=BGnot= par défaut). =Anot= exporte =Concat.jpg= ; les
deux autres modes exportent =Concat.pdf=. Dans le GUI, seuls les
dossiers présents sont proposés et le mode de la dernière génération
d'annotations est présélectionné.
Il faut ensuite annoter les fichiers dans `EXPORT_DIR` avec une
tablette graphique.
** Lecture de la correction manuscrite
_Before_ : vider le dossier configuré par =IMPORT_DIR= (par défaut
=Import=), puis y copier ou synchroniser les fichiers depuis la tablette.
1. =python -m copienator import Interro BGnot=
Une fois les corrections manuelles appliquées aux fichiers
=Concat.pdf=, il faut enregistrer le fichier annoté au même endroit,
sous le nom =Concat_annotated.pdf=.
Comme pour l'export, le second argument accepte =BGnot=, =Bnot= ou
=Anot=. Le GUI présélectionne le dossier utilisé lors du dernier
export. Pour =Anot=, l'image est importée sous le nom
=Concat_annotated.jpg=.
2. =python -m copienator read-annotations Interro=
Lit les =Concat_annotated= dans =Bnot=, regénère les copies avec
les modifications. Les fichiers générés (=score.json=,
=Concat.jpg=, etc.) sont préparés séparément puis installés
ensemble. Les entrées du dossier =Bnot= restent en place et une
erreur de génération conserve les anciennes sorties.
OU
2. =python -m copienator read-grouped Interro=
Idem, mais pour =BGnot=. Les tâches parallèles remontent leurs
erreurs au processus principal au lieu de les ignorer.
3. =python -m copienator giving-names Interro BGnot=
Crée un dossier =A Rendre= avec des liens symboliques vers
+ La copie à rendre
+ un fichier =score.json= qui contient les notes par question
Si un nom est =Unknown= : renommer à la main le dossier et le fichier dedans.
4. Éventuellement, faire des modifications manuelles aux =score.json=.
Puis
- `python -m copienator read-annotations --update-score Interro`
- `python -m copienator read-grouped --update-score Interro`
pour mettre à jour les scores dans les images.
4. (gestion perso)
+ =gestion_classe ne= pour créer l'interro puis
+ =gestion_classe we= (set barème here)
+ =python -m copienator update-ods Interro=
ou =python -m copienator update-ods Interro --sum= (en l'absence de barème)
+ =gestion_classe re=
+ =gestion_classe wsent=
+ =python -m copienator add-final-score Interro21=
(this makes files in =Server/copies=)
5. (gestion perso)
+ Deploy =miqmacs-copies-assets=, and
+ update the copies from =miqmacs.fr/admin=.
6. (gestion perso) Impression d'une copie. Via Evince » print to pdf.
** Archivage et nettoyage
Une fois l'évaluation terminée, =python -m copienator clean Interro=
supprime les fichiers intermédiaires et régénérables. La commande ne
conserve que :
+ les PDF =Copies/*.pdf= produits après le découpage des pages ;
+ les sources et sorties textuelles du prétraitement de l'énoncé :
=enonce.tex=, =correction.tex=, =labels=, =label_groups=, =Text=,
=Sol=, =Persp=, les fichiers TeX de =Text2= et =Sol2=, =Cache= et
=Tmp= ;
+ le résultat final =correction.json= ;
+ les journaux de =.copienator/logs= et les journaux placés à la
racine, comme =correction_log= ;
+ les images et fichiers =score.json= présents dans =A Rendre=.
Les liens symboliques conservés dans =A Rendre= sont remplacés par de
véritables fichiers avant la suppression de leurs cibles. La commande
refuse de démarrer si les copies traitées, =correction.json= ou une
image/un score d'élève sont absents. Elle affiche d'abord un résumé et
demande de saisir le nom de l'évaluation pour confirmer.
Dans le GUI, cette commande apparaît comme dernière étape facultative
dans la section =Archivage=. Un avertissement rappelle que la
progression du GUI et les données binaires permettant de reprendre les
étapes seront définitivement perdues.
Utiliser =python -m copienator clean Interro --dry-run= pour afficher
le plan sans rien supprimer, et =--yes= pour omettre la confirmation
interactive.
* Autres
** Recorrection d'une copie ou de quelques questions
Dans le GUI, ouvrir la section =Refaire des copies (facultatif)=,
repliée par défaut. Ajouter les copies et leurs questions depuis les
listes déroulantes, ou choisir =Toute la copie=, puis enregistrer la
sélection. Le dossier du passage principal est présélectionné d'après
le dernier mode utilisé et les dossiers présents ; vérifier ce choix.
Pour reprendre une même question dans toute la classe, choisir
=Toutes les copies=, sélectionner la question, puis =+ Ajouter=.
Seules les copies ayant un PDF de réponse pour cette question (normal
ou =_new=) sont ajoutées ; le nombre de copies sans réponse est affiché.
Une copie déjà sélectionnée entièrement reste sélectionnée entièrement.
Les boutons =Corrigés (Sol)= et =Consignes de notation (Persp)= ouvrent
les dossiers des textes utilisés par la correction. Modifier et enregistrer
les fichiers des questions concernées avant de relancer =Refaire la correction=.
Ces boutons sont aussi disponibles dans le parcours principal.
Le choix =PDF à vérifier= propose =Automatique=, =Par question (groupé)=
ou =Par copie=. En automatique, une question présente dans plusieurs
copies déclenche le regroupement ; sinon les PDF sont produits par copie.
Les groupes sont limités en hauteur : une question pour toute la classe
peut donc produire quelques PDF plutôt qu'un fichier par élève.
Le GUI écrit =refaire.json= et guide ensuite le parcours ci-dessous.
La vérification du découpage, le redécoupage et la recorrection peuvent
être ignorés. Pour plusieurs copies, les vérifications et découpages
s'exécutent successivement ; un échec ou une interruption arrête la suite.
Ce parcours a sa propre progression : les boutons de navigation du
passage principal ne l'ouvrent pas automatiquement. Après la fusion,
les étapes de restitution déjà terminées sont marquées à revalider.
Pour enchaîner les reprises, deux boutons sont disponibles dans ce parcours :
- =Nouvelle reprise= vide la sélection et remet les étapes de reprise à zéro.
- =Refaire la même sélection= conserve les copies et les questions du dernier
enregistrement, mais remet également les étapes de reprise à zéro.
Les choix du passage principal et de présentation des PDF sont conservés.
Enregistrer ensuite la sélection avant de poursuivre.
Attention : appeler =Nouvelle reprise= seulement après avoir importé les
résultats et exécuté =Mettre à jour les copies finales=. La même précaution
s'applique à =Refaire la même sélection=. Un avertissement est affiché avant
les deux actions, avec une mention supplémentaire si la fusion n'est pas
marquée réussie. Annuler conserve la reprise actuelle. Après une fusion
réussie, utiliser ces boutons pour recommencer, plutôt que modifier la
sélection du passage terminé.
Chaque nouveau passage utilise =Reprises/reprise-DATE-HEURE-ID/BRnot=.
Le passage précédent garde ses PDF, ses retours manuscrits, sa sélection
et une copie de la progression du GUI. Au premier changement de passage,
l'ancien =BRnot= à la racine est également copié dans =Reprises=.
Ces archives concernent les fichiers de vérification, pas un mécanisme
permettant d'annuler les modifications des copies finales.
Le fichier =refaire-session.json= désigne le passage actif ; les commandes
habituelles =--refaire= le suivent automatiquement. Sans ce fichier, le
fonctionnement historique dans =BRnot= à la racine reste disponible.
Dans la suite, =BRnot= désigne le dossier de la reprise active.
L'export d'un passage identifié utilise son propre sous-dossier dans
=EXPORT_DIR/Évaluation= et préfixe les noms des PDF par son identifiant.
Conserver les noms complets au retour et placer les PDF directement dans
=IMPORT_DIR=. L'import ignore les retours des autres passages ; aucun retour
du passage actif donne un résultat partiel. Ainsi, deux reprises de la même
question ne partagent pas les mêmes noms de fichiers exportés.
Ce flux fonctionne après =annotate-grouped= (=BGnot=),
=annotate-checks= (=Bnot=) ou =annotate-simple= (=Anot=).
Terminer d'abord la lecture des annotations du passage principal
(=read-grouped= ou =read-annotations= pour les modes à cases).
Conserver les dossiers d'annotation et leurs fichiers de référence.
1. Si nécessaire, reprendre le découpage :
+ =python -m copienator review-labels Interro/Copies/Copie01.pdf=
+ =python -m copienator split-answers Interro/Copies/Copie01.pdf=
Vérifier les réponses découpées avant de relancer la correction,
notamment les fichiers =_new= et =_old= issus de résolutions manuelles.
2. Créer =Interro/refaire.json= :
: [["Copie02", []],
: ["Copie01", ["Ex 1 : 1)"]]]
Une liste vide sélectionne toute la copie ; sinon donner les labels
exacts des questions (pas seulement le nom de l'exercice).
3. =python -m copienator correct Interro --refaire=
Crée des groupes individuels et remplace les corrections sélectionnées.
Les anciennes corrections sont conservées dans =overwritten_correction.json=.
Cette étape peut être omise si les corrections sont modifiées à la main.
4. Générer les PDF de vérification, selon la présentation souhaitée :
+ Par question : =python -m copienator annotate-grouped Interro --refaire --overwrite=
+ Par copie : =python -m copienator annotate-checks Interro --refaire --overwrite=
Les deux commandes produisent uniquement les réponses sélectionnées
dans =BRnot=, avec des cases à cocher, quel que soit le mode du passage
principal. Le mode groupé garde les identifiants des élèves et regroupe
les réponses par label sans demander de modifier =label_groups=.
Cela ne nécessite pas d'avoir généré =Bnot= ou =BGnot= auparavant.
Attention : =--overwrite= remplace le contenu du =BRnot= actif,
y compris ses annotations manuscrites, mais pas les autres reprises. Une génération incomplète
conserve l'ancien =BRnot=. Sans =--overwrite=, un =BRnot= existant est refusé.
5. Vider les dossiers personnels d'export/import des anciens fichiers,
puis =python -m copienator export Interro --refaire=.
Annoter les PDF sur la tablette, puis placer les PDF retournés dans
=IMPORT_DIR= en conservant leur nom exporté (nom de groupe ou =Copie01.pdf=).
Même sans modification manuscrite, retourner le PDF pour valider ce passage.
6. =python -m copienator import Interro --refaire=
7. Fusionner dans le dossier du passage principal :
+ Groupé : =python -m copienator read-grouped Interro --refaire=
+ Cases : =python -m copienator read-grouped Interro --refaire --annotation-dir Bnot=
+ Simple : =python -m copienator read-grouped Interro --refaire --annotation-dir Anot=
Le lecteur reconnaît les retours par question comme les retours par
copie grâce aux métadonnées et réattribue les cases et notes à chaque
élève. Un groupe manquant laisse intactes les copies qui en dépendent.
Il reconstruit la copie complète, conserve les réponses non
sélectionnées et leurs scores, et remplace les réponses sélectionnées
par celles de =BRnot=. Dans la compilation filtrée, les images déjà
enregistrées des questions non sélectionnées sont conservées par
prudence, même si leur score est parfait, pour ne pas perdre de notes.
Les anciennes cases et notes manuscrites des
questions refaites sont remplacées. Les autres copies restent intactes.
En mode simple, une image =Concat_annotated.jpg= ou =.jpeg= importée
doit conserver les dimensions de l'image exportée ; les parties non
sélectionnées sont conservées. Le fichier =refaire_simple_layout.json=
mémorise le découpage de cette image pour les passages suivants.
Les sorties finales (=Concat.jpg=, images par question, =score.json=
et compilation filtrée) sont mises à jour dans =BGnot=, =Bnot= ou
=Anot= ; les PDF et références du passage principal restent ceux de
ce passage. Pour une nouvelle retouche, reprendre ce flux =--refaire=,
sans relire ensuite les anciennes annotations avec le lecteur normal.
Relancer ensuite les étapes habituelles de calcul des notes et de diffusion.
=refaire.json=, =BRnot= et le dossier du passage principal sont
obligatoires (code de sortie 3 s'ils manquent). Une copie dont les
fichiers de retour sont incomplets est laissée intacte (code 4).
Ne pas ajouter =--update-score= sauf pour imposer volontairement les
anciens scores, y compris ceux des questions refaites.