Guide d'utilisateur GUI ; Recoverable statement/Persp Gemini generation

This commit is contained in:
sebastien committed 2026-10-05 09:04:01 +02:00
1 parent 2f8422f6d5
commit 94ca8b8256
9 files changed
+1333 -170

No files matched your search

+41
View File
@@ -21,6 +21,7 @@ from copienator.platform import (
validate_windows_labels,
)
from copienator.utils import LATEX_WARNING_MARKER
from copienator.rubrics import present_rubric_labels
from .diagnostics import collect_diagnostics
from .batch_monitor import BatchMonitor
@@ -821,6 +822,7 @@ class CopienatorApp(tk.Tk):
"plotting",
"manual_resolution",
"giving_names",
"statement_persp",
}
self.console.configure(height=8 if expanded_form else 14)
self.rowconfigure(1, weight=4 if expanded_form else 3)
@@ -877,6 +879,10 @@ class CopienatorApp(tk.Tk):
if spec.variants and variant.id not in spec.variants:
continue
value = values.get(spec.name, value_for_default(spec.default, evaluation_arg))
if step.id == 'statement_persp' and spec.name == 'delete_persp':
value = False # Deletion is a one-run choice, never a saved default.
if step.id == 'statement' and spec.name == 'restart':
value = False
choices = spec.choices
if spec.name == "annotation_dir" and step.id in {"export", "import"}:
choices, value = self._annotation_directory_choices(step.id)
@@ -910,6 +916,16 @@ class CopienatorApp(tk.Tk):
attach_tooltip(widget, spec.help)
row += 1
if step.id == 'statement_persp':
self.persp_inventory_label = ttk.Label(self.form, wraplength=680, justify='left')
self.persp_inventory_label.grid(row=row, column=0, columnspan=2, sticky='ew', pady=8)
row += 1
ttk.Button(self.form, text='Actualiser les barèmes présents',
command=self._refresh_persp_inventory).grid(row=row, column=1, sticky='w')
row += 1
self.arg_vars['target'].trace_add('write', lambda *_args: self._refresh_persp_inventory())
self._refresh_persp_inventory()
if step.id == "manual_resolution":
def manual_evaluation():
target = self.arg_vars.get("target")
@@ -947,6 +963,23 @@ class CopienatorApp(tk.Tk):
self._update_command_preview()
self._update_controls()
def _refresh_persp_inventory(self) -> None:
if not self.current_step or self.current_step.id != 'statement_persp':
return
target = self.arg_vars.get('target')
value = str(target.get()).strip() if target else ''
root = (self.repository / value).resolve() if value else self.evaluation
try:
labels = EvaluationWorkspace(root).read_labels() if root else []
present = present_rubric_labels(root, labels) if root else []
missing = [label for label in labels if label not in set(present)]
text = (f'Barèmes présents : {len(present)}/{len(labels)} — Manquants : {len(missing)}\n'
+ 'Présents : ' + (', '.join(present) or 'aucun') + '\n'
+ 'Manquants : ' + (', '.join(missing) or 'aucun'))
except (OSError, ValueError) as error:
text = f'Inventaire Persp indisponible : {error}'
self.persp_inventory_label.configure(text=text)
def _render_context_controls(self, step: StepDefinition, row: int) -> int:
if step.id == "annotation" and self.variant_var.get() == "grouped":
controls = ttk.Frame(self.form)
@@ -1589,6 +1622,12 @@ class CopienatorApp(tk.Tk):
self._append_console(f"\n$ {command_display(command)}\n")
try:
self.runner.start(command, self.repository, environment, log_path)
if step.id == 'statement_persp':
self.arg_vars['delete_persp'].set(False)
self._save_current_form()
if step.id == 'statement' and 'restart' in self.arg_vars:
self.arg_vars['restart'].set(False)
self._save_current_form()
if step.id == "correction" and variant.id in {"batch", "hybrid"}:
self.state_store.update_step("correction", batch_started=True)
except (OSError, RuntimeError) as exc:
@@ -1922,6 +1961,8 @@ class CopienatorApp(tk.Tk):
self.active_step_id = None
self._populate_tree()
self._update_controls()
if step_id == 'statement_persp':
self._refresh_persp_inventory()
if step_id == "statement" and self._latex_warning_paths:
self.after_idle(self._show_current_latex_warnings)
if step_id == "personal_read":
+11 -5
View File
@@ -152,10 +152,10 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
arg_target("le dossier de l’évaluation"),
ArgumentSpec(
"restart",
"Ignorer le cache (--restart)",
"Recommencer l’analyse (--restart)",
kind="bool",
flag="--restart",
help="Ignore les résultats Gemini mis en cache et recommence entièrement l’analyse de l’énoncé.",
help="Recommence entièrement l’analyse. Archive les checkpoints, les modifications des groupes et les sorties précédentes. Sans cette option, reprend le travail incomplet en conservant les résultats déjà enregistrés.",
variants=("gemini",),
),
),
@@ -172,10 +172,16 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
optional=True, personal=True, requires=("labels", "Text2", "Sol2"),
),
StepDefinition(
"statement_persp", "Prétraitement de l’énoncé", "Générer les barèmes par Gemini",
"Facultatif. Inutile après l'analyse de l'énoncé par Gemini, puisque les barèmes ont déjà été générés. ",
"statement_persp", "Prétraitement de l’énoncé", "Générer les barèmes manquants avec Gemini",
"Génère uniquement les barèmes manquants dans Persp et conserve ceux déjà présents. "
"Les fichiers vides ou contenant seulement le label sont considérés comme manquants. "
"Après un échec, relancez cette étape pour compléter les barèmes. "
"Cochez Delete current Persp pour supprimer les barèmes actuels au lancement et tous les régénérer.",
(python("default", "Barèmes Gemini", "statement", fixed_args=("--persp-only",)),),
arguments=(arg_target("le dossier de l’évaluation"),),
arguments=(arg_target("le dossier de l’évaluation"),
ArgumentSpec('delete_persp', 'Delete current Persp', kind='bool',
flag='--delete-persp', default=False,
help='Supprime tous les fichiers actuels de Persp au lancement, y compris les barèmes modifiés manuellement. Puis régénère tous les barèmes.')),
optional=True, personal=True, requires=("labels", "label_groups", "Text2", "Sol2"),
),
StepDefinition(