feat: add configurable max_first_operand for multiplication exercises with randomized operand order

This commit is contained in:
2025-10-07 08:23:34 +02:00
parent d9dd1281c3
commit 3d720ff426
2 changed files with 53 additions and 28 deletions
+38 -25
View File
@@ -70,6 +70,7 @@ class ExerciseRequest(BaseModel):
max_table: int
num_exercises: int = 15
multiplication_only: bool = False
max_first_operand: int = 12 # New parameter for the maximum value of the first operand
class OperationExerciseRequest(BaseModel):
@@ -81,6 +82,7 @@ def generate_exercises(
max_table: int,
num_exercises: int = 15,
multiplication_only: bool = False,
max_first_operand: int = 12, # New parameter for the maximum value of the first operand
) -> List[str]:
"""Génère des exercices de multiplication et division aléatoires mélangés sans doublons"""
exercises: List[str] = []
@@ -93,27 +95,28 @@ def generate_exercises(
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
# Déterminer le type d'exercice
if multiplication_only:
exercise_type = "multiplication"
else:
# Choisir aléatoirement le type d'exercice (seulement multiplication ou division)
exercise_type = random.choice(["multiplication", "division"])
if exercise_type == "multiplication":
# Pour les multiplications, un des opérandes est entre 1 et max_first_operand
# et l'autre est entre min_table et max_table
if multiplication_only or random.choice([True, False]):
# Exercice de multiplication
operation_key = f"mult_{a}_{b}" # Clé unique pour cette opération
a = random.randint(1, max_first_operand) # Premier opérande entre 1 et max_first_operand
b = random.randint(min_table, max_table) # Second opérande entre min_table et max_table
# Randomize the order of operands
if random.choice([True, False]):
a, b = b, a
result = a * b
operation_key = f"mult_{min(a,b)}_{max(a,b)}" # Clé unique pour cette opération (order-independent)
if operation_key not in used_operations:
exercise = f"{a} · {b} = ____"
exercises.append(exercise)
used_operations.add(operation_key)
elif not multiplication_only: # division
# Exercice de division
a = random.randint(min_table, max_table)
b = random.randint(min_table, max_table)
result = a * b
divisor = random.choice([a, b])
operation_key = f"div_{result}_{divisor}" # Clé unique pour cette opération
if operation_key not in used_operations:
@@ -127,24 +130,32 @@ def generate_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
# Pour les multiplications, un des opérandes est entre 1 et max_first_operand
# et l'autre est entre min_table et max_table
if multiplication_only or random.choice([True, False]):
# Exercice de multiplication
a = random.randint(1, max_first_operand) # Premier opérande entre 1 et max_first_operand
b = random.randint(min_table, max_table) # Second opérande entre min_table et max_table
# Déterminer le type d'exercice
if multiplication_only:
exercise_type = "multiplication"
else:
# Choisir aléatoirement le type d'exercice
exercise_type = random.choice(["multiplication", "division"])
# Randomize the order of operands
if random.choice([True, False]):
a, b = b, a
if exercise_type == "multiplication":
result = a * b
exercise = f"{a} · {b} = ____"
elif not multiplication_only: # division
a = random.randint(min_table, max_table)
b = random.randint(min_table, max_table)
result = a * b
divisor = random.choice([a, b])
exercise = f"{result} : {divisor} = ____"
else:
# Fallback to multiplication if multiplication_only is True
a = random.randint(1, max_first_operand)
b = random.randint(min_table, max_table)
# Randomize the order of operands
if random.choice([True, False]):
a, b = b, a
exercise = f"{a} · {b} = ____"
exercises.append(exercise)
@@ -157,6 +168,7 @@ def create_math_exercises_pdf(
max_table: int,
num_exercises: int = 15,
multiplication_only: bool = False,
max_first_operand: int = 12, # New parameter for the maximum value of the first operand
) -> str:
"""Crée un fichier PDF avec des exercices de mathématiques mélangés en 3 colonnes et l'upload sur S3"""
import datetime
@@ -193,7 +205,7 @@ def create_math_exercises_pdf(
# Générer les exercices
exercises = generate_exercises(
min_table, max_table, num_exercises, multiplication_only
min_table, max_table, num_exercises, multiplication_only, max_first_operand
)
# Pas d'en-têtes de colonnes
@@ -290,6 +302,7 @@ async def generate_exercises_endpoint(request: ExerciseRequest):
request.max_table,
request.num_exercises,
request.multiplication_only,
request.max_first_operand, # Pass the new parameter
)
# Return redirect to automatically download the file
+13 -1
View File
@@ -66,6 +66,16 @@
<label class="form-check-label" for="multiplicationOnly">Générer uniquement des multiplications</label>
</div>
<div class="mb-3">
<label for="maxFirstOperand" class="form-label">Maximum du premier opérande</label>
<select class="form-select" id="maxFirstOperand">
<option value="9">9 (Tables jusqu'à 9)</option>
<option value="10" selected>10 (Tables jusqu'à 10)</option>
<option value="12">12 (Tables jusqu'à 12)</option>
</select>
<div class="form-text">La valeur maximale pour le premier opérande dans les multiplications</div>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary btn-lg" id="generateBtn">
<span id="buttonText">Générer le PDF (Mult/Div)</span>
@@ -517,6 +527,7 @@
const maxTable = parseInt(document.getElementById('maxTable').value);
const numExercises = parseInt(document.getElementById('numExercises').value);
const multiplicationOnly = document.getElementById('multiplicationOnly').checked;
const maxFirstOperand = parseInt(document.getElementById('maxFirstOperand').value);
const generateBtn = document.getElementById('generateBtn');
const buttonText = document.getElementById('buttonText');
@@ -537,7 +548,8 @@
min_table: minTable,
max_table: maxTable,
num_exercises: numExercises,
multiplication_only: multiplicationOnly
multiplication_only: multiplicationOnly,
max_first_operand: maxFirstOperand
})
});