Compare commits

..

No commits in common. "26d02b098774ff43f080b2bee05323d83dcd45a7" and "81be54b5f7f7aeb102da184b6570769816ac6cbd" have entirely different histories.

7 changed files with 16 additions and 83 deletions

View File

@ -1,7 +1,7 @@
#+title: Script
#+author: Sébastien Miquel
#+date: 14-03-2026
# Time-stamp: <07-05-26 11:33>
# Time-stamp: <01-05-26 22:35>
#+OPTIONS:
* Quézaco
@ -205,8 +205,7 @@ OU
1. =python from_tablette.py Interro= (gestion perso)
_Before_ : delete =~/SyncCopies/Annotées=, copy or sync from the
tablette to here.
_Before_ : delete =~/SyncCopies/Annotées=, copy from the tablette to here.
Une fois les corrections manuelles appliquées aux fichiers
=Concat.pdf=, il faut enregistrer le fichier annoté au même endroit,
@ -243,13 +242,9 @@ OU
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.
* Recorrection d'une seule copie (peu testé)
!! Attention, refaire ne marchera pas si tu fais une annotation non
groupée into refaire !!
@ -257,8 +252,8 @@ groupée into refaire !!
+ =python plotting.py InterroTest/Copie01.pdf=
+ =python splitting_int.py InterroTest/Copie20.pdf=
2. Créer =refaire.json=, avec un contenu comme
: [["Copie01", []],
: ["Copie01", ["Ex 1 : 1)"]]]
[["Copie01", []],
["Copie01", ["Ex 1 : 1)"]]]
3. Appeler =correction= avec --refaire. Il doit créer des groupes
individuels, faire des requêtes, et remplacer les corrections
précédentes (à sauver ailleurs).

View File

@ -582,7 +582,7 @@ Here is a list of all possible labels. You need to answer with a list one of the
height = grouping.get_pdf_height(str(new_pdf_path))
grouping.create_jpg(add_label, idx, [(pid, str(new_pdf_path), height)], INPUT_DIR)
new_tasks.append((str(Path(INPUT_DIR) / add_label / f"Group_{idx+1}.jpg"),
add_label, False, f"{label}(->)"))
add_label, False))
error += f"(->){add_label}"
keep_error = True
else:
@ -603,7 +603,6 @@ def process_single_task(task_tuple, precomputed_response=None):
file_path = task_tuple[0]
label = task_tuple[1]
can_spawn_tasks = task_tuple[2] if len(task_tuple) > 2 else True
injected_error = task_tuple[3] if len(task_tuple) > 3 else ""
group_name = os.path.splitext(file_path)[0]
json_path = group_name + '.json'
@ -649,15 +648,6 @@ def process_single_task(task_tuple, precomputed_response=None):
for p in json_data:
pid = p["id"]
res = p["result"]
# Inject additional error if present
if injected_error:
if res["error"]:
res["error"] = f"{injected_error} {res['error']}"
else:
res["error"] = injected_error
yming, ymaxg, width_r = d_data[pid]
pdf_path = Path(INPUT_DIR) / f"Copie{pid}" / f"{label}.pdf"
@ -720,8 +710,6 @@ def process_single_task(task_tuple, precomputed_response=None):
tprint(f"Error decoding JSON for {file_path}", file=sys.stderr)
except Exception as e:
error_msg = f"Exception processing {file_path}: {e}"
import traceback
traceback.print_exc() # <--- Add this line to see the real crash
print(error_msg, file=sys.stderr)
with io_lock:
errors_summary.append((error_msg, file_path))

View File

@ -55,10 +55,7 @@ def compile_to_pdf(text, output_pdf_path): # 21 cm + 3.8 (dimension de la marge
def fetch_and_save_sub_text(ex_id, indices, label, text_path):
"""Fetches text for a specific sub-question and saves it to Text/{label}.tex"""
qinds = ",".join(map(str, indices))
if qinds:
url = f"http://localhost:8080/exercices/exo_q_text/{ex_id}/{qinds}"
else:
url = f"http://localhost:8080/exercices/exo_q_text/{ex_id}"
try:
with urllib.request.urlopen(url) as response:
content = response.read().decode('utf-8')
@ -74,10 +71,7 @@ def fetch_and_save_sub_text(ex_id, indices, label, text_path):
def fetch_and_save_sub_sol(ex_id, indices, label, sol_path):
"""Fetches text for a specific sub-question and saves it to Text/{label}.tex"""
qinds = ",".join(map(str, indices))
if qinds:
url = f"http://localhost:8080/exercices/exo_q_sol/{ex_id}/{qinds}"
else:
url = f"http://localhost:8080/exercices/exo_q_sol/{ex_id}"
try:
with urllib.request.urlopen(url) as response:
content = response.read().decode('utf-8')
@ -174,11 +168,11 @@ def process_directory(directory):
if not tex_files:
print(f"No .tex file found in {directory}. Looking in /Staging/Interro/")
int_name = directory[:-1] if directory.endswith("/") else directory
tex_path = os.path.join(os.path.expanduser("~"), "Prépa/Staging/Interro", f"{int_name}.tex")
tex_path = os.path.join(os.path.expanduser("~"), "Prépa/Staging/Interro/", int_name, ".tex")
if os.path.exists(tex_path):
tex_file = tex_path
else:
print("Not found in ", tex_path)
print("Not found.")
return
else:
tex_file = tex_files[0]

View File

@ -314,7 +314,7 @@ def process_copy_group(group_key, files):
# Run ThreadPool on GROUPS (Copies), not individual files
# Each thread handles one student's full exam copy sequentially
with ThreadPoolExecutor(max_workers=16) as executor:
with ThreadPoolExecutor(max_workers=12) as executor:
# Convert dict items to arguments for map
# executor.map expects a function and an iterable.
# We use a lambda or separate function to unpack the tuple if needed,

View File

@ -4358,8 +4358,6 @@ conjoncture
conjugaison
conjugal
conjuguer
conjugué
conjugués
conjuration
conjuré
conjurer
@ -6099,7 +6097,6 @@ détenus
détérioration
détériorer
déterminant
déterminants
déterminante
détermination
détermine
@ -10282,7 +10279,6 @@ inacceptable
inacceptables
inaccessible
inaccoutumé
inachevé
inactif
inaction
inadmissible

View File

@ -9,7 +9,7 @@ from tkinter import messagebox
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont, ImageTk
print("o to open pdf, O original pdf, e to emacs part, p to go back, i to interro, click for coordinates")
print("o to open pdf, O original pdf, e to emacs part, i to interro, click for coordinates")
# --- Configuration & Globals ---
padding = 60
@ -79,8 +79,6 @@ def prepare_image(image_path: str, bounding_boxes, all_labels, nb_pages, last_la
current_index = all_labels.index(label)
if current_index < last_label_index or (last_label_index == -1 and current_index != 0):
color = "red"
elif current_index > last_label_index + 1:
color = "orange"
last_label_index = current_index
draw.rectangle(((abs_x_min, abs_y_min), (abs_x_max, abs_y_max)), outline=color, width=4)
@ -172,15 +170,8 @@ class ImageViewer:
self.active_copie_name = None
self.accumulated_results = None # Dict with "name" and "list"
# To go back
self.history = []
self.forward_stack = []
self.current_pil_image = None
# Bindings
self.root.bind('<Return>', self.on_enter)
self.root.bind('p', self.on_previous)
self.root.bind('e', self.on_edit)
self.root.bind('o', self.on_open_pdf)
self.root.bind('i', self.on_open_interro)
@ -193,10 +184,6 @@ class ImageViewer:
def poll_queue(self):
if not self.is_viewing:
try:
# pil_image, json_path, metadata = image_queue.get_nowait()
if self.forward_stack:
pil_image, json_path, metadata = self.forward_stack.pop()
else:
pil_image, json_path, metadata = image_queue.get_nowait()
# Handle End of Stream
@ -212,7 +199,6 @@ class ImageViewer:
# Start new batch
self.active_copie_name = metadata["copie"]
self.accumulated_results = {"name": metadata["name"], "list": []}
self.history.clear()
self.display_image(pil_image, json_path, metadata)
except queue.Empty:
@ -228,24 +214,7 @@ class ImageViewer:
json.dump(self.accumulated_results, f)
self.accumulated_results = None
def on_previous(self, event):
if self.is_viewing and self.history:
print("Going back to previous image...")
prev_pil, prev_json, prev_meta, num_added = self.history.pop()
# Undo the accumulation to prevent duplicates when we hit Enter again
if self.accumulated_results and num_added > 0:
self.accumulated_results["list"] = self.accumulated_results["list"][:-num_added]
# Push current image to the forward stack so we don't lose it
self.forward_stack.append((self.current_pil_image,
self.current_json_path, self.current_meta))
# Display the previous image immediately
self.display_image(prev_pil, prev_json, prev_meta)
def display_image(self, pil_image, json_path, metadata):
self.current_pil_image = pil_image # ADD THIS LINE
self.orig_size = pil_image.size
self.scale_factor = 1.0
screen_h = self.root.winfo_screenheight() - 100
@ -264,7 +233,6 @@ class ImageViewer:
def on_enter(self, event):
if self.is_viewing:
print(f"Committing data for {self.current_json_path.name}...")
num_added = 0 # ADD THIS LINE
try:
with open(self.current_json_path, 'r') as f:
@ -277,8 +245,6 @@ class ImageViewer:
self.current_meta["schema"]
)
num_added = len(converted_items)
# Add to accumulator
if self.accumulated_results:
self.accumulated_results["list"].extend(converted_items)
@ -293,9 +259,6 @@ class ImageViewer:
messagebox.showerror("JSON Error", msg)
return # Abort advancement
self.history.append((self.current_pil_image, self.current_json_path,
self.current_meta, num_added))
# Advance UI
self.is_viewing = False
self.label.config(image="", text="Loading next...")
@ -307,13 +270,13 @@ class ImageViewer:
print(f"Opening {pdf_path}")
subprocess.Popen(['xdg-open', str(pdf_path.absolute())])
def on_open_interro(self, event):
def on_open_ori_pdf(self, event):
if self.is_viewing and self.current_json_path:
pdf_path = "/home/sebastien/Prépa/Staging/Interro/" + str(base_dir) + ".pdf"
pdf_path = "/home/sebastien/Staging/Interro/" + str(base_dir) + "pdf"
print(f"Opening {pdf_path}")
subprocess.Popen(['xdg-open', pdf_path])
def on_open_ori_pdf(self, event):
def on_open_interro(self, event):
if self.is_viewing and self.current_json_path:
new_filename = self.current_json_path.stem.split('_')[0] + ".pdf"
pdf_path = self.current_json_path.parent / "Copies Originales" / new_filename

View File

@ -14,10 +14,7 @@ def enonce_total(base_dir):
if not text_dir.is_dir():
return ""
# Exclude .tex and .pdf files
files = [f for f in text_dir.iterdir()
if f.is_file() and f.suffix.lower() not in ('.tex', '.pdf')]
files = [f for f in text_dir.iterdir() if f.is_file()]
files.sort(key=lambda f: natural_key(f.name))
output = []