import xml.etree.ElementTree as ET import random from math import gcd import re def create_html_table_for_fracture_input(rows: list): table_rows = [] # Tabellenzeilen festlegen for i, row in enumerate(rows): if (i % 2) == 0: table_row = "" else: table_row = "" for cell in row: table_row += f"{cell}" table_row += "" table_rows.append(table_row) # Tabelle zusammenbauen table_html = ( f"\n" + "\n".join(table_rows) + "
" ) return re.sub("\\s+", " ", table_html) def create_cloze_question(name, questiontext, question_math, calcstep_math, correct_answers, wrong_answers, feedback, tags): question = ET.Element('question', attrib={'type': 'cloze'}) name_elem = ET.SubElement(question, 'name') text_elem = ET.SubElement(name_elem, 'text') text_elem.text = name questiontext_elem = ET.SubElement(question, 'questiontext', attrib={'format': 'html'}) text_elem = ET.SubElement(questiontext_elem, 'text') # Erstelle die Tabelle für die Lücken rows_list = [ ["Zähler:", f"{{1:SHORTANSWER:={correct_answers[0]}~%0%{wrong_answers[0][0]}#{wrong_answers[0][1]}}}"], ["Nenner:", f"{{1:SHORTANSWER:={correct_answers[1]}~%0%{wrong_answers[1][0]}#{wrong_answers[1][1]}}}"] ] # Prüfe, ob der Bruch gekürzt werden kann if gcd(correct_answers[0], correct_answers[1]) > 1: common_divisor = gcd(correct_answers[0], correct_answers[1]) reduced_numerator = correct_answers[0] // common_divisor reduced_denominator = correct_answers[1] // common_divisor rows_list.append(["Gekürzter Zähler:",f"{{1:SHORTANSWER:={reduced_numerator}~%0%{wrong_answers[2][0]}#{wrong_answers[2][1]}}}"]) rows_list.append(["Gekürzter Nenner:",f"{{1:SHORTANSWER:={reduced_denominator}~%0%{wrong_answers[3][0]}#{wrong_answers[3][1]}}}"]) cloze_text = create_html_table_for_fracture_input(rows_list) # Füge die Frage hinzu text_elem.text = questiontext + " " + cloze_text generalfeedback_elem = ET.SubElement(question, 'generalfeedback', attrib={'format': 'html'}) text_elem = ET.SubElement(generalfeedback_elem, 'text') solution = f"

Lösungshinweise:

" solution += "

" # Musterlösung im LaTeX-Format if gcd(correct_answers[0], correct_answers[1]) > 1: solution += f"\\( {question_math} {calcstep_math} = \\frac{{{correct_answers[0]}}}{{{correct_answers[1]}}} = \\frac{{{reduced_numerator}}}{{{reduced_denominator}}} \\)." else: solution += f"\\( {question_math} {calcstep_math} = \\frac{{{correct_answers[0]}}}{{{correct_answers[1]}}} \\)" solution += "

" text_elem.text = solution defaultgrade_elem = ET.SubElement(question, 'defaultgrade') defaultgrade_elem.text = '1.0000000' penalty_elem = ET.SubElement(question, 'penalty') penalty_elem.text = '0.3333333' hidden_elem = ET.SubElement(question, 'hidden') hidden_elem.text = '0' # Tags hinzufügen tags_elem = ET.SubElement(question, 'tags') for tag in tags: tag_elem = ET.SubElement(tags_elem, 'tag') text_elem = ET.SubElement(tag_elem, 'text') text_elem.text = tag return question def lcm(a, b): return abs(a * b) // gcd(a, b) def create_quiz(questions): quiz = ET.Element('quiz') for q in questions: quiz.append(q) return quiz def save_to_file(xml_element, filename): tree = ET.ElementTree(xml_element) with open(filename, 'wb') as f: tree.write(f, encoding='utf-8', xml_declaration=True) questions = [] # Generiere n Aufgaben zur Addition und Subtraktion von Brüchen mit verschiedenen Nennern n = 20 for i in range(1, (n+1)): # Zähler und Nenner generieren numerator1 = random.randint(1, 20) # Zähler zwischen 1 und 20 numerator2 = random.randint(1, 20) # Zähler zwischen 1 und 20 numerator3 = random.randint(1, 20) # Zähler zwischen 1 und 20 denominator1 = random.randint(2, 10) # Nenner zwischen 2 und 10 denominator2 = random.randint(2, 10) # Nenner zwischen 2 und 10 denominator3 = random.randint(2, 10) # Nenner zwischen 2 und 10 # Berechne den gemeinsamen Nenner, der kleiner als 30 sein muss common_denominator = lcm(denominator1, lcm(denominator2, denominator3)) while common_denominator >= 50: denominator1 = random.randint(2, 10) denominator2 = random.randint(2, 10) denominator3 = random.randint(2, 10) common_denominator = lcm(denominator1, lcm(denominator2, denominator3)) # Berechne die äquivalenten Zähler equivalent_numerator1 = numerator1 * (common_denominator // denominator1) equivalent_numerator2 = numerator2 * (common_denominator // denominator2) equivalent_numerator3 = numerator3 * (common_denominator // denominator3) operations = random.choice(["+ +", "+ -", "- +", "- -"]) # Zufällige Operationen if operations == "+ +": result_numerator = equivalent_numerator1 + (equivalent_numerator2 + equivalent_numerator3) elif operations == "+ -": result_numerator = equivalent_numerator1 + (equivalent_numerator2 - equivalent_numerator3) elif operations == "- +": result_numerator = equivalent_numerator1 - (equivalent_numerator2 + equivalent_numerator3) else: result_numerator = equivalent_numerator1 - (equivalent_numerator2 - equivalent_numerator3) # Prüfe, ob der Bruch gekürzt werden kann needs_reduction = gcd(result_numerator, common_denominator) > 1 question_puremath = f"\\Large \\displaystyle \\frac{{{numerator1}}}{{{denominator1}}} {operations[0]} \\left(\\frac{{{numerator2}}}{{{denominator2}}} {operations[2]} \\frac{{{numerator3}}}{{{denominator3}}}\\right) =" # Frage im LaTeX-Format questiontext = (f"

Berechne und kürze das Ergebnis, wenn möglich:

" f"

\\( {question_puremath} \\)

") # Feedback-Ausgabe für notwendigen Zwischenschritt calculation_step_math = f"\\frac{{{equivalent_numerator1}}}{{{common_denominator}}} {operations[0]} \\left(\\frac{{{equivalent_numerator2}}}{{{common_denominator}}} {operations[2]} \\frac{{{equivalent_numerator3}}}{{{common_denominator}}}\\right)" # Antworten correct_answers = [result_numerator, common_denominator] if needs_reduction: common_divisor = gcd(result_numerator, common_denominator) reduced_numerator = result_numerator // common_divisor reduced_denominator = common_denominator // common_divisor correct_answers.extend([reduced_numerator, reduced_denominator]) # Füge gekürzte Antworten hinzu wrong_answers = [ (result_numerator + random.randint(1, 5), "Dieser Zähler ist zu hoch."), # Falscher Zähler (result_numerator - random.randint(1, 5), "Dieser Zähler ist zu niedrig."), # Falscher Zähler (reduced_numerator + random.randint(1, 3), "Dieser gekürzte Zähler ist nicht korrekt."), # Falscher gekürzter Zähler (reduced_denominator - random.randint(1, 3), "Dieser gekürzte Nenner ist nicht korrekt.") # Falscher gekürzter Nenner ] else: wrong_answers = [ (result_numerator + random.randint(1, 5), "Dieser Zähler ist zu hoch."), # Falscher Zähler (result_numerator - random.randint(1, 5), "Dieser Zähler ist zu niedrig.") # Falscher Zähler ] feedback = "Richtig! Die Lösung ist korrekt." # Frage erstellen und hinzufügen questions.append(create_cloze_question( f"Addition/Subtraktion von 3 ungleichnamigen Brüchen {i}", questiontext, question_puremath, calculation_step_math, correct_answers, wrong_answers, feedback, ["Mathematik", "Brüche", "Addition", "Subtraktion"] )) # Erstelle das Quiz quiz = create_quiz(questions) # Speichere die XML-Datei save_to_file(quiz, 'cloze_fraction_addition_subtraction_quiz.xml') print("Moodle-XML-Datei 'cloze_fraction_addition_subtraction_quiz.xml' erfolgreich erstellt.")