Updated both main.py and generate_math_exercises.py to use consistent double quotes for strings and improved code formatting with better line breaks for readability. Also added JSON import to main.py for bulk operations.
251 lines
8.7 KiB
Python
251 lines
8.7 KiB
Python
#!/usr/bin/env python3
|
|
import random
|
|
import sys
|
|
import subprocess
|
|
import os
|
|
from fpdf import FPDF
|
|
|
|
|
|
class MathExercisesPDF(FPDF):
|
|
def header(self):
|
|
self.set_font("Helvetica", "B", 16)
|
|
self.cell(
|
|
0,
|
|
10,
|
|
"Exercices de Multiplication et Division",
|
|
0,
|
|
1,
|
|
"C",
|
|
new_x="LMARGIN",
|
|
new_y="NEXT",
|
|
)
|
|
self.ln(10)
|
|
|
|
def footer(self):
|
|
self.set_y(-15)
|
|
self.set_font("Helvetica", "I", 8)
|
|
self.cell(
|
|
0, 10, f"Page {self.page_no()}", 0, 0, "C", new_x="RIGHT", new_y="TOP"
|
|
)
|
|
|
|
|
|
def generate_exercises(min_table, max_table, num_exercises=15):
|
|
"""Génère des exercices de multiplication et division aléatoires mélangés sans doublons"""
|
|
exercises = []
|
|
used_operations = set() # Pour éviter les doublons
|
|
|
|
# Générer le nombre exact d'exercices demandé
|
|
attempts = 0
|
|
max_attempts = num_exercises * 10 # Limite pour éviter une boucle infinie
|
|
|
|
while len(exercises) < num_exercises and attempts < max_attempts:
|
|
attempts += 1
|
|
|
|
# Choisir deux nombres aléatoires entre min_table et max_table
|
|
a = random.randint(min_table, max_table)
|
|
b = random.randint(min_table, max_table)
|
|
result = a * b
|
|
|
|
# Choisir aléatoirement le type d'exercice (seulement multiplication ou division)
|
|
exercise_type = random.choice(["multiplication", "division"])
|
|
|
|
if exercise_type == "multiplication":
|
|
# Exercice de multiplication
|
|
operation_key = f"mult_{a}_{b}" # Clé unique pour cette opération
|
|
if operation_key not in used_operations:
|
|
exercise = f"{a} · {b} = ____"
|
|
exercises.append(exercise)
|
|
used_operations.add(operation_key)
|
|
else: # division
|
|
# Exercice de division
|
|
divisor = random.choice([a, b])
|
|
operation_key = f"div_{result}_{divisor}" # Clé unique pour cette opération
|
|
if operation_key not in used_operations:
|
|
exercise = f"{result} : {divisor} = ____"
|
|
exercises.append(exercise)
|
|
used_operations.add(operation_key)
|
|
|
|
# Si nous n'avons pas pu générer suffisamment d'exercices uniques,
|
|
# compléter avec des variations
|
|
if len(exercises) < num_exercises:
|
|
remaining = num_exercises - len(exercises)
|
|
for _ in range(remaining):
|
|
# Générer des variations avec des nombres légèrement différents
|
|
a = random.randint(min_table, max_table)
|
|
b = random.randint(min_table, max_table)
|
|
result = a * b
|
|
|
|
# Choisir aléatoirement le type d'exercice
|
|
exercise_type = random.choice(["multiplication", "division"])
|
|
|
|
if exercise_type == "multiplication":
|
|
exercise = f"{a} · {b} = ____"
|
|
else: # division
|
|
divisor = random.choice([a, b])
|
|
exercise = f"{result} : {divisor} = ____"
|
|
|
|
exercises.append(exercise)
|
|
|
|
return exercises
|
|
|
|
|
|
def create_math_exercises_pdf(min_table, max_table, num_exercises=15):
|
|
"""Crée un fichier PDF avec des exercices de mathématiques mélangés en 3 colonnes"""
|
|
pdf = MathExercisesPDF()
|
|
pdf.add_page()
|
|
pdf.set_font("Helvetica", "", 12)
|
|
|
|
# Ajouter des informations sur la plage de tables
|
|
if min_table == max_table:
|
|
table_info = f"Tables de multiplication et division pour {min_table}"
|
|
else:
|
|
table_info = (
|
|
f"Tables de multiplication et division de {min_table} à {max_table}"
|
|
)
|
|
|
|
pdf.cell(0, 10, table_info, 0, 1, "C", new_x="LMARGIN", new_y="NEXT")
|
|
pdf.ln(5)
|
|
|
|
# Générer les exercices
|
|
exercises = generate_exercises(min_table, max_table, num_exercises)
|
|
|
|
# Pas d'en-têtes de colonnes
|
|
|
|
# Répartir les exercices en 3 colonnes
|
|
num_per_column = (num_exercises + 2) // 3 # Arrondi vers le haut
|
|
col1_exercises = exercises[:num_per_column]
|
|
col2_exercises = exercises[num_per_column : num_per_column * 2]
|
|
col3_exercises = exercises[num_per_column * 2 :]
|
|
|
|
# Ajouter les exercices numérotés de 1 à n dans les colonnes
|
|
max_rows = max(len(col1_exercises), len(col2_exercises), len(col3_exercises))
|
|
|
|
for i in range(max_rows):
|
|
# Colonne 1
|
|
if i < len(col1_exercises):
|
|
exercise_num = i + 1
|
|
col1_text = f"{exercise_num}. {col1_exercises[i]}"
|
|
else:
|
|
col1_text = ""
|
|
|
|
# Colonne 2
|
|
if i < len(col2_exercises):
|
|
exercise_num = i + 1 + len(col1_exercises)
|
|
col2_text = f"{exercise_num}. {col2_exercises[i]}"
|
|
else:
|
|
col2_text = ""
|
|
|
|
# Colonne 3
|
|
if i < len(col3_exercises):
|
|
exercise_num = i + 1 + len(col1_exercises) + len(col2_exercises)
|
|
col3_text = f"{exercise_num}. {col3_exercises[i]}"
|
|
else:
|
|
col3_text = ""
|
|
|
|
# Ajouter la ligne
|
|
pdf.cell(60, 10, col1_text, 0, 0, "L", new_x="RIGHT", new_y="TOP")
|
|
pdf.cell(60, 10, col2_text, 0, 0, "L", new_x="RIGHT", new_y="TOP")
|
|
pdf.cell(60, 10, col3_text, 0, 1, "L", new_x="LMARGIN", new_y="NEXT")
|
|
|
|
# Sauvegarder le PDF
|
|
if min_table == max_table:
|
|
filename = (
|
|
f"exercices_mathematiques_table_{min_table}_{num_exercises}_exercices.pdf"
|
|
)
|
|
else:
|
|
filename = f"exercices_mathematiques_tables_{min_table}_a_{max_table}_{num_exercises}_exercices.pdf"
|
|
pdf.output(filename)
|
|
return filename
|
|
|
|
|
|
def open_pdf(filename):
|
|
"""Ouvre le fichier PDF avec la commande système appropriée"""
|
|
try:
|
|
if sys.platform == "darwin": # macOS
|
|
subprocess.run(["open", filename], check=True)
|
|
elif sys.platform == "win32": # Windows
|
|
os.startfile(filename)
|
|
else: # Linux et autres
|
|
subprocess.run(["xdg-open", filename], check=True)
|
|
return True
|
|
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
|
return False
|
|
|
|
|
|
def main():
|
|
"""Fonction principale"""
|
|
# Vérifier les arguments de ligne de commande
|
|
if len(sys.argv) < 3:
|
|
print(
|
|
"Usage: python generate_math_exercises.py <min_table> <max_table> [num_exercises] [--open]"
|
|
)
|
|
print("Exemple: python generate_math_exercises.py 4 7 15")
|
|
print(
|
|
" python generate_math_exercises.py 4 7 15 --open (pour ouvrir automatiquement le PDF)"
|
|
)
|
|
print(
|
|
" python generate_math_exercises.py 5 5 10 (pour seulement la table de 5)"
|
|
)
|
|
sys.exit(1)
|
|
|
|
# Vérifier si l'option --open est présente
|
|
open_after_creation = "--open" in sys.argv
|
|
if open_after_creation:
|
|
sys.argv.remove("--open") # Retirer l'option de la liste des arguments
|
|
|
|
try:
|
|
min_table = int(sys.argv[1])
|
|
max_table = int(sys.argv[2])
|
|
if min_table < 1 or max_table < 1:
|
|
raise ValueError("Les tables doivent être supérieures à 0")
|
|
if min_table > max_table:
|
|
raise ValueError(
|
|
"La table minimale doit être inférieure ou égale à la table maximale"
|
|
)
|
|
except ValueError as e:
|
|
print(f"Erreur: {e}")
|
|
sys.exit(1)
|
|
|
|
# Nombre d'exercices (par défaut 15)
|
|
num_exercises = 15
|
|
if len(sys.argv) > 3:
|
|
try:
|
|
num_exercises = int(sys.argv[3])
|
|
if num_exercises < 1:
|
|
raise ValueError("Le nombre d'exercices doit être supérieur à 0")
|
|
except ValueError as e:
|
|
print(f"Erreur: {e}")
|
|
sys.exit(1)
|
|
|
|
# Créer le PDF
|
|
try:
|
|
filename = create_math_exercises_pdf(min_table, max_table, num_exercises)
|
|
print(f"Fichier PDF '{filename}' créé avec succès !")
|
|
if min_table == max_table:
|
|
print(f"- Exercices pour la table de {min_table}")
|
|
else:
|
|
print(f"- Exercices pour les tables de {min_table} à {max_table}")
|
|
print(
|
|
f"- {num_exercises} exercices MÉLANGÉS générés aléatoirement et numérotés de 1 à {num_exercises}"
|
|
)
|
|
print("- Types d'exercices : multiplications (·) et divisions (:) uniquement")
|
|
print("- Présentés en 3 colonnes pour économiser l'espace")
|
|
print("- Aucune opération en double (quand c'est possible)")
|
|
|
|
# Ouvrir le PDF si demandé
|
|
if open_after_creation:
|
|
if open_pdf(filename):
|
|
print("\nPDF ouvert automatiquement avec succès !")
|
|
else:
|
|
print(
|
|
"\nImpossible d'ouvrir automatiquement le PDF. Vous pouvez l'ouvrir manuellement."
|
|
)
|
|
|
|
except Exception as e:
|
|
print(f"Erreur lors de la création du PDF: {e}")
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|