Vorbereitung für Skript für gemischte Brüche
This commit is contained in:
		
							
								
								
									
										594
									
								
								aufgabengenerator_formulas_fraction_new_c.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										594
									
								
								aufgabengenerator_formulas_fraction_new_c.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,594 @@
 | 
			
		||||
import random
 | 
			
		||||
import operator
 | 
			
		||||
import re
 | 
			
		||||
from math import gcd, lcm
 | 
			
		||||
import xml.etree.ElementTree as ET
 | 
			
		||||
from collections import Counter
 | 
			
		||||
 | 
			
		||||
# Define operators and their corresponding functions
 | 
			
		||||
ops = {
 | 
			
		||||
    '+': operator.add,
 | 
			
		||||
    '-': operator.sub,
 | 
			
		||||
    '*': operator.mul,
 | 
			
		||||
    '/': operator.truediv
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Konstanten
 | 
			
		||||
# Anzahl der zu generierenden Fragen.
 | 
			
		||||
NUM_QUESTIONS = 5
 | 
			
		||||
# Algebraische Struktur der Aufgaben
 | 
			
		||||
STRUCTURE = "(+)-((+)-(+))"
 | 
			
		||||
# Gleiche Nenner erlauben
 | 
			
		||||
SAME_ALLOWED = True
 | 
			
		||||
# Größter Zähler
 | 
			
		||||
MAX_NUMERATOR = 10
 | 
			
		||||
# Größter Nenner
 | 
			
		||||
MAX_DENOMINATOR = 8
 | 
			
		||||
# Größter erlaubter gemeinsamer Nenner
 | 
			
		||||
MAX_COMMON_DENOMINATOR = 100
 | 
			
		||||
# Dateiname für Ausgabe
 | 
			
		||||
FILENAME = 'formulas_new_quiz.xml'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_expression(expression):
 | 
			
		||||
    """Parse an algebraic expression and determine the required number of numbers.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        expression (str): The algebraic expression to parse.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        int: The total number of numbers required for the expression.
 | 
			
		||||
    """
 | 
			
		||||
    op_count = 0
 | 
			
		||||
 | 
			
		||||
    # Count operators in parentheses
 | 
			
		||||
    paren_count = 1
 | 
			
		||||
    max_depth = 0
 | 
			
		||||
 | 
			
		||||
    for i, char in enumerate(expression):
 | 
			
		||||
        if char in ops.keys():
 | 
			
		||||
            op_count += 1
 | 
			
		||||
 | 
			
		||||
    return max_depth + op_count + 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Anzahl der benötigten Brüche
 | 
			
		||||
NUM_FRACTIONS = parse_expression(STRUCTURE)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def add_placeholders(expression):
 | 
			
		||||
    """Add placeholders to the expression for calculation.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        expression (str): The algebraic expression to modify.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        str: The modified expression with placeholders.
 | 
			
		||||
    """
 | 
			
		||||
    placeholder_counter = 0  # Zähler für die Platzhalter
 | 
			
		||||
 | 
			
		||||
    def placeholder_generator():
 | 
			
		||||
        nonlocal placeholder_counter
 | 
			
		||||
        placeholder = f'n{placeholder_counter}'
 | 
			
		||||
        placeholder_counter += 1
 | 
			
		||||
        return placeholder
 | 
			
		||||
 | 
			
		||||
    output = []  # Ausgabe als Liste zum späteren Zusammensetzen
 | 
			
		||||
    need_placeholder = True  # Flag, um zu tracken, ob ein Platzhalter hinzugefügt werden soll
 | 
			
		||||
 | 
			
		||||
    for char in expression:
 | 
			
		||||
        if char in '+-*/':  # Operator gefunden
 | 
			
		||||
            if need_placeholder:  # Wenn wir einen Platzhalter brauchen
 | 
			
		||||
                output.append(placeholder_generator())
 | 
			
		||||
            output.append(char)  # Fügen Sie den Operator hinzu
 | 
			
		||||
            need_placeholder = True  # Nach einem Operator müssen wir wieder einen Platzhalter hinzufügen
 | 
			
		||||
        elif char == '(':  # Eine neue Sub-Expression beginnt
 | 
			
		||||
            output.append(char)  # Fügen Sie die öffnende Klammer hinzu
 | 
			
		||||
            need_placeholder = True
 | 
			
		||||
        elif char == ')':  # Eine Sub-Expression endet
 | 
			
		||||
            if need_placeholder:  # Wenn wir einen Platzhalter brauchen
 | 
			
		||||
                output.append(placeholder_generator())
 | 
			
		||||
            output.append(char)  # Fügen Sie die schließende Klammer hinzu
 | 
			
		||||
            need_placeholder = False  # Nach einer schließenden Klammer erwarten wir keine Platzhalter mehr
 | 
			
		||||
        else:  # Bei anderen Zeichen
 | 
			
		||||
            if need_placeholder:  # Wenn wir einen Platzhalter brauchen
 | 
			
		||||
                output.append(placeholder_generator())
 | 
			
		||||
            output.append(char)  # Fügen Sie das Zeichen hinzu
 | 
			
		||||
            need_placeholder = False  # Nach einem Platzhalter sollten wir keinen weiteren setzen
 | 
			
		||||
 | 
			
		||||
    # Platzhalter am Beginn hinzufügen
 | 
			
		||||
    if output and not (output[0] == f'n{0}' or output[0] == '('):
 | 
			
		||||
        result = [placeholder_generator()] + output
 | 
			
		||||
    else:
 | 
			
		||||
        result = output
 | 
			
		||||
    # Platzhalter am Ende hinzufügen, wenn nötig
 | 
			
		||||
    if output[-1] in '+-*/':
 | 
			
		||||
        result = result + [placeholder_generator()]
 | 
			
		||||
    else:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    # Zusammensetzen des finalen Ausdrucks
 | 
			
		||||
    final_expression = ''.join(result).strip()
 | 
			
		||||
    print(final_expression)
 | 
			
		||||
    return final_expression
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Algebraische Struktur mit Platzhaltern
 | 
			
		||||
STRUCTURE_PH = add_placeholders(STRUCTURE)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def calculate(expression, numbers):
 | 
			
		||||
    """Calculate the result of the expression using provided numbers.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        expression (str): The algebraic expression with placeholders.
 | 
			
		||||
        numbers (list): A list of numbers to replace the placeholders.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        float: The calculated result of the expression.
 | 
			
		||||
    """
 | 
			
		||||
    print(numbers)
 | 
			
		||||
    # Replace placeholders with actual number values
 | 
			
		||||
    for i, num in enumerate(numbers):
 | 
			
		||||
        placeholder = f'n{i}'
 | 
			
		||||
        expression = re.sub(rf'\{placeholder}\s*([+-/*])', rf'{num} \1', expression)
 | 
			
		||||
        expression = re.sub(rf'({placeholder})\s*', rf'{num}', expression)
 | 
			
		||||
 | 
			
		||||
    print(expression)
 | 
			
		||||
    # Evaluate the result
 | 
			
		||||
    return eval(expression)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def gen_calculate_string(expression: str, liststring: str):
 | 
			
		||||
    """Generate a calculation string for the expression with actual number values.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        expression (str): The algebraic expression with placeholders.
 | 
			
		||||
        liststring (str): The list of values to replace the placeholders.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        str: The modified expression with the list values.
 | 
			
		||||
    """
 | 
			
		||||
    for i in range(NUM_FRACTIONS):
 | 
			
		||||
        placeholder = f'n{i}'
 | 
			
		||||
        expression = re.sub(rf'\{placeholder}\s*([+-/*])', rf'{liststring}[{i}] \1', expression)
 | 
			
		||||
        expression = re.sub(rf'({placeholder})\s*', rf'{liststring}[{i}]', expression)
 | 
			
		||||
 | 
			
		||||
    print(expression)
 | 
			
		||||
    return expression
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def gen_latex_calculate_string(expression: str, liststring: str):
 | 
			
		||||
    """Generate a LaTeX-compatible calculation string for the expression.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        expression (str): The algebraic expression with placeholders.
 | 
			
		||||
        liststring (str): A list of LaTeX strings to replace the placeholders.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        str: The modified expression formatted for LaTeX.
 | 
			
		||||
    """
 | 
			
		||||
    for i in range(NUM_FRACTIONS):
 | 
			
		||||
        placeholder = f'n{i}'
 | 
			
		||||
        replacement = liststring[i]
 | 
			
		||||
        print(replacement)
 | 
			
		||||
        expression = re.sub(rf'\{placeholder}\s*([+-/*])', replacement, expression)
 | 
			
		||||
        expression = re.sub(rf'({placeholder})\s*', replacement, expression)
 | 
			
		||||
 | 
			
		||||
    # Klammern anpassen
 | 
			
		||||
    expression = re.sub(rf'\(', u'\\\\left(', expression)
 | 
			
		||||
    expression = re.sub(rf'\)', u'\\\\right)', expression)
 | 
			
		||||
    return expression
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def create_html_table_for_fracture_input(rows: list):
 | 
			
		||||
    """Create an HTML table for displaying fraction inputs.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        rows (list): A list of rows to include in the table.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        str: The generated HTML table as a string.
 | 
			
		||||
    """
 | 
			
		||||
    table_rows = []
 | 
			
		||||
    for i, row in enumerate(rows):
 | 
			
		||||
        if (i % 2) == 0:
 | 
			
		||||
            table_row = "<tr style='border-bottom: 1px solid black;'>"
 | 
			
		||||
        else:
 | 
			
		||||
            table_row = "<tr>"
 | 
			
		||||
 | 
			
		||||
        for cell in row:
 | 
			
		||||
            table_row += f"<td style='padding: 5px;'>{cell}</td>"
 | 
			
		||||
 | 
			
		||||
        table_row += "</tr>"
 | 
			
		||||
        table_rows.append(table_row)
 | 
			
		||||
 | 
			
		||||
    # Tabelle zusammenbauen
 | 
			
		||||
    table_html = f"<table style='border-collapse: collapse; display: inline-table;'>\n" + "\n".join(table_rows) + "</table>"
 | 
			
		||||
 | 
			
		||||
    return table_html
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def create_formula_question(ex_number: int):
 | 
			
		||||
    """Create a formula question based on a random set of fractions.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        ex_number (int): The index number of the exercise being created.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        Element: The XML element representing the question.
 | 
			
		||||
    """
 | 
			
		||||
    numerators = []
 | 
			
		||||
    denominators = []
 | 
			
		||||
    for i in range(NUM_FRACTIONS):
 | 
			
		||||
        n = random.randint(1, MAX_NUMERATOR)
 | 
			
		||||
        d = random.randint(2, MAX_DENOMINATOR)
 | 
			
		||||
        numerators.append(n)
 | 
			
		||||
        denominators.append(d)
 | 
			
		||||
 | 
			
		||||
    # Müssen Nenner unterschiedlich sein?
 | 
			
		||||
    if not SAME_ALLOWED:
 | 
			
		||||
        # Sicherstellen, dass die Nenner unterschiedlich sind
 | 
			
		||||
        same_denominators = [k for k, v in Counter(denominators).items() if v > 1]
 | 
			
		||||
        while len(same_denominators) > 1:
 | 
			
		||||
            new_denom = random.randint(2, MAX_DENOMINATOR)
 | 
			
		||||
            try:
 | 
			
		||||
                index = denominators.index(same_denominators[0])
 | 
			
		||||
                denominators[index] = new_denom
 | 
			
		||||
            except ValueError:
 | 
			
		||||
                pass
 | 
			
		||||
            same_denominators = [k for k, v in Counter(denominators).items() if v > 1]
 | 
			
		||||
    else:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    # Hauptnenner bestimmen
 | 
			
		||||
    *denoms_integers, = denominators  # Entpacken der Liste
 | 
			
		||||
    common_denominator = lcm(*denoms_integers)
 | 
			
		||||
    cd = common_denominator
 | 
			
		||||
 | 
			
		||||
    fractions = []
 | 
			
		||||
    for i in range(NUM_FRACTIONS):
 | 
			
		||||
        fraction = {"n": numerators[i], "d": denominators[i]}
 | 
			
		||||
        fractions.append(fraction)
 | 
			
		||||
 | 
			
		||||
    expanded_numerators = [frac["n"] * cd // frac["d"] for frac in fractions]
 | 
			
		||||
 | 
			
		||||
    expanded_fractions = []
 | 
			
		||||
    for i in range(NUM_FRACTIONS):
 | 
			
		||||
        fraction = {"n": expanded_numerators[i], "d": cd}
 | 
			
		||||
        expanded_fractions.append(fraction)
 | 
			
		||||
 | 
			
		||||
    result_numerator = calculate(STRUCTURE_PH, expanded_numerators)
 | 
			
		||||
 | 
			
		||||
    gcd_result = gcd(result_numerator, cd)
 | 
			
		||||
    if gcd_result > 1:
 | 
			
		||||
        shortable = True
 | 
			
		||||
        shortened_numerator = result_numerator // gcd_result
 | 
			
		||||
        shortened_denominator = common_denominator // gcd_result
 | 
			
		||||
    else:
 | 
			
		||||
        shortable = False
 | 
			
		||||
 | 
			
		||||
    # Start der Aufgabe
 | 
			
		||||
    question = ET.Element('question', attrib={'type': 'formulas'})
 | 
			
		||||
 | 
			
		||||
    # Name der Aufgabe
 | 
			
		||||
    has_plus = '+' in STRUCTURE
 | 
			
		||||
    has_minus = '-' in STRUCTURE
 | 
			
		||||
    has_mult = '*' in STRUCTURE
 | 
			
		||||
    has_div = '/' in STRUCTURE
 | 
			
		||||
 | 
			
		||||
    if has_plus and has_minus:
 | 
			
		||||
        expression_type = "Addition/Subtraktion" + f" ({STRUCTURE})"
 | 
			
		||||
        exercise_text = "Berechne den Term"
 | 
			
		||||
    elif has_plus:
 | 
			
		||||
        expression_type = "Addition" + f" ({STRUCTURE})"
 | 
			
		||||
        exercise_text = "Addiere die Brüche"
 | 
			
		||||
    elif has_minus:
 | 
			
		||||
        expression_type = "Subtraktion" + f" ({STRUCTURE})"
 | 
			
		||||
        exercise_text = "Subtrahiere die Brüche"
 | 
			
		||||
    else:
 | 
			
		||||
        expression_type = "Rechnung" + f" ({STRUCTURE})"
 | 
			
		||||
        exercise_text = "Berechne den Term"
 | 
			
		||||
    name_elem = ET.SubElement(question, 'name')
 | 
			
		||||
    text_elem = ET.SubElement(name_elem, 'text')
 | 
			
		||||
    text_elem.text = f'{expression_type} von {NUM_FRACTIONS} ungleichnamigen Brüchen {ex_number}'
 | 
			
		||||
 | 
			
		||||
    # Allgemeiner Aufgabentext
 | 
			
		||||
    questiontext_elem = ET.SubElement(question, 'questiontext', attrib={'format': 'html'})
 | 
			
		||||
    text_elem = ET.SubElement(questiontext_elem, 'text')
 | 
			
		||||
    if shortable:
 | 
			
		||||
        text_elem.text = f"<![CDATA[ <p>{exercise_text} und kürze das Ergebnis so weit wie möglich.</p>" + "<p>{#A} </p> ]]>"
 | 
			
		||||
    else:
 | 
			
		||||
        text_elem.text = f"<![CDATA[ <p>{exercise_text}.</p>"+"<p>{#A} </p> ]]>"
 | 
			
		||||
 | 
			
		||||
    # Allgemeines Feedback
 | 
			
		||||
    generalfeedback_elem = ET.SubElement(question, 'generalfeedback', attrib={'format': 'html'})
 | 
			
		||||
    text_elem = ET.SubElement(generalfeedback_elem, 'text')
 | 
			
		||||
    text_elem.text = ' '
 | 
			
		||||
 | 
			
		||||
    # Grundlegende Bewertungsinformationen
 | 
			
		||||
    ET.SubElement(question, 'defaultgrade').text = '1.0000000'
 | 
			
		||||
    ET.SubElement(question, 'penalty').text = '0.3333333'
 | 
			
		||||
    ET.SubElement(question, 'hidden').text = '0'
 | 
			
		||||
    ET.SubElement(question, 'idnumber').text = ' '
 | 
			
		||||
 | 
			
		||||
    # Feedback für korrekte und inkorrekte Antworten
 | 
			
		||||
    correctfeedback_elem = ET.SubElement(question, 'correctfeedback', attrib={'format': 'html'})
 | 
			
		||||
    text_elem = ET.SubElement(correctfeedback_elem, 'text')
 | 
			
		||||
    text_elem.text = '''<![CDATA[ <p>Die Antwort ist richtig.</p> ]]> '''
 | 
			
		||||
 | 
			
		||||
    partiallycorrectfeedback_elem = ET.SubElement(question, 'partiallycorrectfeedback', attrib={'format': 'html'})
 | 
			
		||||
    text_elem = ET.SubElement(partiallycorrectfeedback_elem, 'text')
 | 
			
		||||
    text_elem.text = '''<![CDATA[ <p>Die Antwort ist teilweise richtig.</p> ]]> '''
 | 
			
		||||
 | 
			
		||||
    incorrectfeedback_elem = ET.SubElement(question, 'incorrectfeedback', attrib={'format': 'html'})
 | 
			
		||||
    text_elem = ET.SubElement(incorrectfeedback_elem, 'text')
 | 
			
		||||
    text_elem.text = '''<![CDATA[ <p>Die Antwort ist falsch.</p> ]]>'''
 | 
			
		||||
 | 
			
		||||
    ET.SubElement(question, 'shownumcorrect')
 | 
			
		||||
 | 
			
		||||
    varsrandom_elem = ET.SubElement(question, 'varsrandom')
 | 
			
		||||
    text_elem = ET.SubElement(varsrandom_elem, 'text')
 | 
			
		||||
    text_elem.text = f' '
 | 
			
		||||
 | 
			
		||||
    # Globale Variablen definieren
 | 
			
		||||
    varsglobal_elem = ET.SubElement(question, 'varsglobal')
 | 
			
		||||
    text_elem = ET.SubElement(varsglobal_elem, 'text')
 | 
			
		||||
    numerators_string = ",".join([str(n) for n in numerators])
 | 
			
		||||
    denominators_string = ",".join([str(d) for d in denominators])
 | 
			
		||||
    text_elem.text = f'n = [{numerators_string}];\n d = [{denominators_string}];'
 | 
			
		||||
 | 
			
		||||
    # Durchnummerierung der Antworten
 | 
			
		||||
    answernumbering_elem = ET.SubElement(question, 'answernumbering')
 | 
			
		||||
    text_elem = ET.SubElement(answernumbering_elem, 'text')
 | 
			
		||||
    text_elem.text = 'ABCD'
 | 
			
		||||
 | 
			
		||||
    # Antworten definieren
 | 
			
		||||
    answers_elem = ET.SubElement(question, 'answers')
 | 
			
		||||
 | 
			
		||||
    # Indizes für die Antworten
 | 
			
		||||
    partindex_elem = ET.SubElement(answers_elem, 'partindex')
 | 
			
		||||
    ET.SubElement(partindex_elem, 'text').text = '0'
 | 
			
		||||
    placeholder_elem = ET.SubElement(answers_elem, 'placeholder')
 | 
			
		||||
    ET.SubElement(placeholder_elem, 'text').text = '#A'
 | 
			
		||||
 | 
			
		||||
    # Punktzahl auf Teilaufgabe
 | 
			
		||||
    answermark_elem = ET.SubElement(answers_elem, 'answermark')
 | 
			
		||||
    if shortable:
 | 
			
		||||
        ET.SubElement(answermark_elem, 'text').text = '2'
 | 
			
		||||
    else:
 | 
			
		||||
        ET.SubElement(answermark_elem, 'text').text = '1'
 | 
			
		||||
 | 
			
		||||
    # Antworttyp
 | 
			
		||||
    answertype_elem = ET.SubElement(answers_elem, 'answertype')
 | 
			
		||||
    ET.SubElement(answertype_elem, 'text').text = '0'
 | 
			
		||||
    numbox_elem = ET.SubElement(answers_elem, 'numbox')
 | 
			
		||||
    ET.SubElement(numbox_elem, 'text').text = '2'
 | 
			
		||||
 | 
			
		||||
    # Berechnungsvariablen
 | 
			
		||||
    # common divisor
 | 
			
		||||
    cdtext = ""
 | 
			
		||||
    for i in range(NUM_FRACTIONS):
 | 
			
		||||
        if i == 0:
 | 
			
		||||
            pass
 | 
			
		||||
        elif i == 1:
 | 
			
		||||
            cdtext += f"cd{i} = lcm(d[{i}],d[{i-1}]);"
 | 
			
		||||
        else:
 | 
			
		||||
            cdtext += f"cd{i} = lcm(cd{i-1}, d[{i}]);"
 | 
			
		||||
    cdtext += f"cd = cd{NUM_FRACTIONS-1};"
 | 
			
		||||
 | 
			
		||||
    # expansions
 | 
			
		||||
    extext = "e = ["
 | 
			
		||||
    for i in range(NUM_FRACTIONS):
 | 
			
		||||
        extext += f"cd / d[{i}],"
 | 
			
		||||
    extext = extext[:-1]
 | 
			
		||||
    extext += "];"
 | 
			
		||||
 | 
			
		||||
    # expanded_numerators
 | 
			
		||||
    entext = "ens = ["
 | 
			
		||||
    for i in range(NUM_FRACTIONS):
 | 
			
		||||
        entext += f"n[{i}]*e[{i}],"
 | 
			
		||||
    entext = entext[:-1]
 | 
			
		||||
    entext += "];"
 | 
			
		||||
 | 
			
		||||
    # result numerator
 | 
			
		||||
    resnum = "resnum = " + gen_calculate_string(STRUCTURE_PH, "ens") + ";"
 | 
			
		||||
 | 
			
		||||
    # gcd of result numerator and result (common) denominator
 | 
			
		||||
    resgcd = "resgcd = gcd(resnum, cd);"
 | 
			
		||||
 | 
			
		||||
    # shortened result numerator
 | 
			
		||||
    sresnum = "sresnum = resnum / resgcd;"
 | 
			
		||||
 | 
			
		||||
    # shortened result denominator
 | 
			
		||||
    sresden = "sresden = cd / resgcd;"
 | 
			
		||||
 | 
			
		||||
    vars1_elem = ET.SubElement(answers_elem, 'vars1')
 | 
			
		||||
    if shortable:
 | 
			
		||||
        vars1_elem_text = f"<![CDATA[{cdtext}\n {extext}\n {entext}\n {resnum}\n {resgcd}\n {sresnum}\n {sresden}]]>"
 | 
			
		||||
    else:
 | 
			
		||||
        vars1_elem_text = f"<![CDATA[{cdtext}\n {extext}\n {entext}\n {resnum}]]>"
 | 
			
		||||
    ET.SubElement(vars1_elem, 'text').text = vars1_elem_text
 | 
			
		||||
 | 
			
		||||
    # Antwort
 | 
			
		||||
    answer_elem = ET.SubElement(answers_elem, 'answer')
 | 
			
		||||
    if shortable:
 | 
			
		||||
        answer_text = '[resnum, cd, sresnum, sresden]'
 | 
			
		||||
    else:
 | 
			
		||||
        answer_text = '[resnum, cd]'
 | 
			
		||||
    ET.SubElement(answer_elem, 'text').text = answer_text
 | 
			
		||||
 | 
			
		||||
    answernotunique_elem = ET.SubElement(answers_elem, 'answernotunique')
 | 
			
		||||
    ET.SubElement(answernotunique_elem, 'text').text = '0'
 | 
			
		||||
 | 
			
		||||
    vars2_elem = ET.SubElement(answers_elem, 'vars2')
 | 
			
		||||
    if shortable:
 | 
			
		||||
        vars2_elem_text = "<![CDATA[ ga = _0 == resnum && _1 == cd;\n gb = (_0 / _1) == (resnum / cd);\n gsa = _2 == sresnum && _3 == sresden;\n gsb = (_2 / _3) == (sresnum / sresden); ]]>"
 | 
			
		||||
    else:
 | 
			
		||||
        vars2_elem_text = "<![CDATA[ ga = _0 == resnum && _1 == cd; gb = (_0 / _1) == (resnum / cd); ]]>"
 | 
			
		||||
    ET.SubElement(vars2_elem, 'text').text = vars2_elem_text
 | 
			
		||||
 | 
			
		||||
    correctness_elem = ET.SubElement(answers_elem, 'correctness')
 | 
			
		||||
    if shortable:
 | 
			
		||||
        ET.SubElement(correctness_elem, 'text').text = '0.25*ga + 0.25*gb + 0.25*gsa + 0.25*gsb'
 | 
			
		||||
    else:
 | 
			
		||||
        ET.SubElement(correctness_elem, 'text').text = '0.5*ga + 0.5*gb'
 | 
			
		||||
 | 
			
		||||
    unitpenalty_elem = ET.SubElement(answers_elem, 'unitpenalty')
 | 
			
		||||
    ET.SubElement(unitpenalty_elem, 'text').text = '1'
 | 
			
		||||
 | 
			
		||||
    postunit_elem = ET.SubElement(answers_elem, 'postunit')
 | 
			
		||||
    ET.SubElement(postunit_elem, 'text').text = ' '
 | 
			
		||||
 | 
			
		||||
    ruleid_elem = ET.SubElement(answers_elem, 'ruleid')
 | 
			
		||||
    ET.SubElement(ruleid_elem, 'text').text = '1'
 | 
			
		||||
 | 
			
		||||
    otherrule_elem = ET.SubElement(answers_elem, 'otherrule')
 | 
			
		||||
    ET.SubElement(otherrule_elem, 'text').text = ' '
 | 
			
		||||
 | 
			
		||||
    # Unterfragen-Text
 | 
			
		||||
    subqtext_elem = ET.SubElement(answers_elem, 'subqtext', attrib={'format': 'html'})
 | 
			
		||||
 | 
			
		||||
    fractions_latex_strings = []
 | 
			
		||||
    for i in range(NUM_FRACTIONS):
 | 
			
		||||
        l_str = "\\\\frac{{"+ f"n[{i}]" +"}}{{"+ f"d[{i}]" +"}}"
 | 
			
		||||
        fractions_latex_strings.append(l_str)
 | 
			
		||||
    latex_calculation = gen_latex_calculate_string(STRUCTURE_PH, fractions_latex_strings)
 | 
			
		||||
 | 
			
		||||
    sub_q_t_begin = "<![CDATA[ <p>Berechne:</p>"
 | 
			
		||||
    sub_q_t_math = "<p>\$\\Large \\displaystyle " + f"{latex_calculation}" + "=\$</p>"
 | 
			
		||||
    rows_list = [
 | 
			
		||||
        ["Zähler:", "{_0}"],
 | 
			
		||||
        ["Nenner:", "{_1}"]
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    sub_q_t_input = '<div style="display: inline-table"> ='
 | 
			
		||||
    if shortable:
 | 
			
		||||
        sub_q_t_input += create_html_table_for_fracture_input(rows_list)
 | 
			
		||||
 | 
			
		||||
        rows_list_s = [["Gekürzter Zähler:", "{_2}"],
 | 
			
		||||
                       ["Gekürzter Nenner:", "{_3}"]]
 | 
			
		||||
        sub_q_t_input += " = "
 | 
			
		||||
        sub_q_t_input += create_html_table_for_fracture_input(rows_list_s)
 | 
			
		||||
 | 
			
		||||
    else:
 | 
			
		||||
        sub_q_t_input += create_html_table_for_fracture_input(rows_list)
 | 
			
		||||
    sub_q_t_input += '</div>'
 | 
			
		||||
    sub_q_t_end = "]]>"
 | 
			
		||||
 | 
			
		||||
    sub_question_text = sub_q_t_begin + sub_q_t_math + sub_q_t_input + sub_q_t_end
 | 
			
		||||
    ET.SubElement(subqtext_elem, 'text').text = sub_question_text
 | 
			
		||||
 | 
			
		||||
    expanded_fractions_latex_strings = []
 | 
			
		||||
    for i in range(NUM_FRACTIONS):
 | 
			
		||||
        l_str = "\\\\frac{{"+ f"ens[{i}]" +"}}{{"+ f"cd" +"}}"
 | 
			
		||||
        expanded_fractions_latex_strings.append(l_str)
 | 
			
		||||
    expanded_latex_calculation = gen_latex_calculate_string(STRUCTURE_PH, expanded_fractions_latex_strings)
 | 
			
		||||
 | 
			
		||||
    # Lösungshinweis
 | 
			
		||||
    feedback_elem = ET.SubElement(answers_elem, 'feedback', attrib={'format': 'html'})
 | 
			
		||||
    if shortable:
 | 
			
		||||
        feedback_text = '''<![CDATA[ <h4>Lösungshinweis</h4>
 | 
			
		||||
                           <p>Die korrekte Lösung ist:</p>
 | 
			
		||||
                           <p>\$\\displaystyle''' + f"{latex_calculation}" +" = " + f"{expanded_latex_calculation}" + ''' = \\frac{{resnum}}{{cd}} = \\frac{{sresnum}}{{sresden}} \$ </p> ]]>'''
 | 
			
		||||
    else:
 | 
			
		||||
        feedback_text = '''<![CDATA[ <h4>Lösungshinweis</h4>
 | 
			
		||||
                           <p>Die korrekte Lösung ist:</p>
 | 
			
		||||
                           <p>\$ \\displaystyle ''' + f"{latex_calculation}" +" = " + f"{expanded_latex_calculation}" + ''' = \\frac{{resnum}}{{cd}} \$ </p> ]]>'''
 | 
			
		||||
    ET.SubElement(feedback_elem, 'text').text = feedback_text
 | 
			
		||||
 | 
			
		||||
    # correctfeedback
 | 
			
		||||
    correctfeedback_elem = ET.SubElement(answers_elem, 'correctfeedback', attrib={'format': 'html'})
 | 
			
		||||
    correctfeedback_text = '''<![CDATA[ <p>Richtig!</p>]]>'''
 | 
			
		||||
    ET.SubElement(correctfeedback_elem, 'text').text = correctfeedback_text
 | 
			
		||||
 | 
			
		||||
    # partially correct feedback
 | 
			
		||||
    pcorrectfeedback_elem = ET.SubElement(answers_elem, 'partiallycorrectfeedback', attrib={'format': 'html'})
 | 
			
		||||
    pcorrectfeedback_text = '''<![CDATA[ <p>Teilweise richtig.</p>]]>'''
 | 
			
		||||
    ET.SubElement(pcorrectfeedback_elem, 'text').text = pcorrectfeedback_text
 | 
			
		||||
 | 
			
		||||
    # incorrect feedback
 | 
			
		||||
    incorrectfeedback_elem = ET.SubElement(answers_elem, 'incorrectfeedback', attrib={'format': 'html'})
 | 
			
		||||
    incorrectfeedback_text = '''<![CDATA[ <p>Leider nicht richtig.</p>]]>'''
 | 
			
		||||
    ET.SubElement(incorrectfeedback_elem, 'text').text = incorrectfeedback_text
 | 
			
		||||
 | 
			
		||||
    return question
 | 
			
		||||
 | 
			
		||||
def generate_questions(num_questions):
 | 
			
		||||
    """Generates a list of questions.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        num_questions (int): The number of questions to generate.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        list: A list of question elements.
 | 
			
		||||
    """
 | 
			
		||||
    questions = []
 | 
			
		||||
    for i in range(num_questions):
 | 
			
		||||
        questions.append(create_formula_question(i))
 | 
			
		||||
 | 
			
		||||
    return questions
 | 
			
		||||
 | 
			
		||||
def create_quiz(questions):
 | 
			
		||||
    """Creates the overall quiz element.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        questions (list): A list of question elements.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        Element: The complete quiz element.
 | 
			
		||||
    """
 | 
			
		||||
    quiz = ET.Element('quiz')
 | 
			
		||||
    for q in questions:
 | 
			
		||||
        quiz.append(q)
 | 
			
		||||
    return quiz
 | 
			
		||||
 | 
			
		||||
def save_to_file(xml_element, filename):
 | 
			
		||||
    """Saves the XML document to a file.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        xml_element (Element): The XML element to save.
 | 
			
		||||
        filename (str): The name of the target file.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        None
 | 
			
		||||
    """
 | 
			
		||||
    tree = ET.ElementTree(xml_element)
 | 
			
		||||
    ET.indent(tree, space="\t", level=0)
 | 
			
		||||
    with open(filename, 'wb') as f:
 | 
			
		||||
        tree.write(f, encoding='utf_8', xml_declaration=True)
 | 
			
		||||
 | 
			
		||||
    return 0
 | 
			
		||||
 | 
			
		||||
def replace_vars2(xml_file):
 | 
			
		||||
    """Replaces special characters in the XML file.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        xml_file (str): The name of the XML file to modify.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        None
 | 
			
		||||
    """
 | 
			
		||||
    # XML-Datei lesen
 | 
			
		||||
    with open(xml_file, 'r') as f:
 | 
			
		||||
        text = f.read()
 | 
			
		||||
 | 
			
		||||
    text = text.replace("&", "&")
 | 
			
		||||
    text = text.replace("<", "<")
 | 
			
		||||
    text = text.replace(">", ">")
 | 
			
		||||
 | 
			
		||||
    with open(xml_file, 'w') as f:
 | 
			
		||||
        f.write(text)
 | 
			
		||||
 | 
			
		||||
    print("Ersetzungen abgeschlossen.")
 | 
			
		||||
 | 
			
		||||
# Hauptprogramm
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    questions = generate_questions(NUM_QUESTIONS)
 | 
			
		||||
    quiz = create_quiz(questions)
 | 
			
		||||
 | 
			
		||||
    save_to_file(quiz, FILENAME)
 | 
			
		||||
    replace_vars2(FILENAME)
 | 
			
		||||
 | 
			
		||||
    print("Moodle-XMLDatei erfolgreich erstellt.")
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										252
									
								
								aufgabengenerator_formulas_gem_fraction_new.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								aufgabengenerator_formulas_gem_fraction_new.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,252 @@
 | 
			
		||||
import random
 | 
			
		||||
import operator
 | 
			
		||||
import re
 | 
			
		||||
from math import gcd, lcm
 | 
			
		||||
import xml.etree.ElementTree as ET
 | 
			
		||||
from collections import Counter
 | 
			
		||||
 | 
			
		||||
# Define operators and their corresponding functions
 | 
			
		||||
ops = {
 | 
			
		||||
    '+': operator.add,
 | 
			
		||||
    '-': operator.sub,
 | 
			
		||||
    '*': operator.mul,
 | 
			
		||||
    '/': operator.truediv
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Konstanten
 | 
			
		||||
NUM_QUESTIONS = 5
 | 
			
		||||
STRUCTURE = "(+)-((+)-(+))"
 | 
			
		||||
SAME_ALLOWED = True
 | 
			
		||||
MAX_WHOLE = 5  # Größte ganze Zahl für gemischte Brüche
 | 
			
		||||
MAX_NUMERATOR = 10  # Größter Zähler
 | 
			
		||||
MAX_DENOMINATOR = 8  # Größter Nenner
 | 
			
		||||
MAX_COMMON_DENOMINATOR = 100
 | 
			
		||||
FILENAME = 'formulas_new_quiz.xml'
 | 
			
		||||
 | 
			
		||||
def parse_expression(expression):
 | 
			
		||||
    op_count = 0
 | 
			
		||||
    for char in expression:
 | 
			
		||||
        if char in ops.keys():
 | 
			
		||||
            op_count += 1
 | 
			
		||||
    return op_count + 1
 | 
			
		||||
 | 
			
		||||
NUM_FRACTIONS = parse_expression(STRUCTURE)
 | 
			
		||||
 | 
			
		||||
def add_placeholders(expression):
 | 
			
		||||
    placeholder_counter = 0
 | 
			
		||||
    def placeholder_generator():
 | 
			
		||||
        nonlocal placeholder_counter
 | 
			
		||||
        placeholder = f'n{placeholder_counter}'
 | 
			
		||||
        placeholder_counter += 1
 | 
			
		||||
        return placeholder
 | 
			
		||||
 | 
			
		||||
    output = []
 | 
			
		||||
    need_placeholder = True
 | 
			
		||||
 | 
			
		||||
    for char in expression:
 | 
			
		||||
        if char in '+-*/':
 | 
			
		||||
            if need_placeholder:
 | 
			
		||||
                output.append(placeholder_generator())
 | 
			
		||||
            output.append(char)
 | 
			
		||||
            need_placeholder = True
 | 
			
		||||
        elif char == '(':
 | 
			
		||||
            output.append(char)
 | 
			
		||||
            need_placeholder = True
 | 
			
		||||
        elif char == ')':
 | 
			
		||||
            if need_placeholder:
 | 
			
		||||
                output.append(placeholder_generator())
 | 
			
		||||
            output.append(char)
 | 
			
		||||
            need_placeholder = False
 | 
			
		||||
        else:
 | 
			
		||||
            if need_placeholder:
 | 
			
		||||
                output.append(placeholder_generator())
 | 
			
		||||
            output.append(char)
 | 
			
		||||
            need_placeholder = False
 | 
			
		||||
 | 
			
		||||
    if output and not (output[0] == f'n{0}' or output[0] == '('):
 | 
			
		||||
        result = [placeholder_generator()] + output
 | 
			
		||||
    else:
 | 
			
		||||
        result = output
 | 
			
		||||
    if output[-1] in '+-*/':
 | 
			
		||||
        result = result + [placeholder_generator()]
 | 
			
		||||
 | 
			
		||||
    final_expression = ''.join(result).strip()
 | 
			
		||||
    return final_expression
 | 
			
		||||
 | 
			
		||||
STRUCTURE_PH = add_placeholders(STRUCTURE)
 | 
			
		||||
 | 
			
		||||
def calculate(expression, numbers):
 | 
			
		||||
    for i, num in enumerate(numbers):
 | 
			
		||||
        placeholder = f'n{i}'
 | 
			
		||||
        expression = re.sub(rf'\{placeholder}\s*([+-/*])', rf'{num} \1', expression)
 | 
			
		||||
        expression = re.sub(rf'({placeholder})\s*', rf'{num}', expression)
 | 
			
		||||
    return eval(expression)
 | 
			
		||||
 | 
			
		||||
def create_mixed_fraction():
 | 
			
		||||
    """Generates a random mixed fraction represented as a dictionary."""
 | 
			
		||||
    whole = random.randint(1, MAX_WHOLE)
 | 
			
		||||
    numerator = random.randint(1, MAX_NUMERATOR)
 | 
			
		||||
    denominator = random.randint(2, MAX_DENOMINATOR)
 | 
			
		||||
    return {
 | 
			
		||||
        "whole": whole,
 | 
			
		||||
        "numerator": numerator,
 | 
			
		||||
        "denominator": denominator
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
def create_formula_question(ex_number: int):
 | 
			
		||||
    numerators = []
 | 
			
		||||
    denominators = []
 | 
			
		||||
    mixed_fractions = []
 | 
			
		||||
 | 
			
		||||
    for i in range(NUM_FRACTIONS):
 | 
			
		||||
        mixed_fraction = create_mixed_fraction()
 | 
			
		||||
        mixed_fractions.append(mixed_fraction)
 | 
			
		||||
        # Convert mixed fraction to improper fraction for calculation
 | 
			
		||||
        improper_numerator = mixed_fraction["whole"] * mixed_fraction["denominator"] + mixed_fraction["numerator"]
 | 
			
		||||
        numerators.append(improper_numerator)
 | 
			
		||||
        denominators.append(mixed_fraction["denominator"])
 | 
			
		||||
 | 
			
		||||
    if not SAME_ALLOWED:
 | 
			
		||||
        same_denominators = [k for k, v in Counter(denominators).items() if v > 1]
 | 
			
		||||
        while len(same_denominators) > 1:
 | 
			
		||||
            new_denom = random.randint(2, MAX_DENOMINATOR)
 | 
			
		||||
            try:
 | 
			
		||||
                index = denominators.index(same_denominators[0])
 | 
			
		||||
                denominators[index] = new_denom
 | 
			
		||||
            except ValueError:
 | 
			
		||||
                pass
 | 
			
		||||
            same_denominators = [k for k, v in Counter(denominators).items() if v > 1]
 | 
			
		||||
 | 
			
		||||
    *denoms_integers, = denominators
 | 
			
		||||
    common_denominator = lcm(*denoms_integers)
 | 
			
		||||
    expanded_numerators = [(frac["whole"] * frac["denominator"] + frac["numerator"]) * common_denominator // frac["denominator"] for frac in mixed_fractions]
 | 
			
		||||
 | 
			
		||||
    result_numerator = calculate(STRUCTURE_PH, expanded_numerators)
 | 
			
		||||
 | 
			
		||||
    gcd_result = gcd(result_numerator, common_denominator)
 | 
			
		||||
    shortable = gcd_result > 1
 | 
			
		||||
    shortened_numerator = result_numerator // gcd_result if shortable else result_numerator
 | 
			
		||||
    shortened_denominator = common_denominator // gcd_result if shortable else common_denominator
 | 
			
		||||
 | 
			
		||||
    question = ET.Element('question', attrib={'type': 'formulas'})
 | 
			
		||||
    has_plus = '+' in STRUCTURE
 | 
			
		||||
    has_minus = '-' in STRUCTURE
 | 
			
		||||
 | 
			
		||||
    if has_plus and has_minus:
 | 
			
		||||
        expression_type = "Addition/Subtraktion"
 | 
			
		||||
        exercise_text = "Berechne den Term"
 | 
			
		||||
    elif has_plus:
 | 
			
		||||
        expression_type = "Addition"
 | 
			
		||||
        exercise_text = "Addiere die gemischten Brüche"
 | 
			
		||||
    elif has_minus:
 | 
			
		||||
        expression_type = "Subtraktion"
 | 
			
		||||
        exercise_text = "Subtrahiere die gemischten Brüche"
 | 
			
		||||
    else:
 | 
			
		||||
        expression_type = "Rechnung"
 | 
			
		||||
        exercise_text = "Berechne den Term"
 | 
			
		||||
 | 
			
		||||
    name_elem = ET.SubElement(question, 'name')
 | 
			
		||||
    text_elem = ET.SubElement(name_elem, 'text')
 | 
			
		||||
    text_elem.text = f'{expression_type} von {NUM_FRACTIONS} gemischten Brüchen {ex_number}'
 | 
			
		||||
 | 
			
		||||
    questiontext_elem = ET.SubElement(question, 'questiontext', attrib={'format': 'html'})
 | 
			
		||||
    text_elem = ET.SubElement(questiontext_elem, 'text')
 | 
			
		||||
    text_elem.text = f"<![CDATA[ <p>{exercise_text} und kürze das Ergebnis so weit wie möglich.</p>" + "<p>{#A} </p> ]]>"
 | 
			
		||||
 | 
			
		||||
    generalfeedback_elem = ET.SubElement(question, 'generalfeedback', attrib={'format': 'html'})
 | 
			
		||||
    text_elem = ET.SubElement(generalfeedback_elem, 'text')
 | 
			
		||||
    text_elem.text = ' '
 | 
			
		||||
 | 
			
		||||
    ET.SubElement(question, 'defaultgrade').text = '1.0000000'
 | 
			
		||||
    ET.SubElement(question, 'penalty').text = '0.3333333'
 | 
			
		||||
    ET.SubElement(question, 'hidden').text = '0'
 | 
			
		||||
 | 
			
		||||
    correctfeedback_elem = ET.SubElement(question, 'correctfeedback', attrib={'format': 'html'})
 | 
			
		||||
    text_elem = ET.SubElement(correctfeedback_elem, 'text')
 | 
			
		||||
    text_elem.text = '''<![CDATA[ <p>Die Antwort ist richtig.</p> ]]> '''
 | 
			
		||||
 | 
			
		||||
    partiallycorrectfeedback_elem = ET.SubElement(question, 'partiallycorrectfeedback', attrib={'format': 'html'})
 | 
			
		||||
    text_elem = ET.SubElement(partiallycorrectfeedback_elem, 'text')
 | 
			
		||||
    text_elem.text = '''<![CDATA[ <p>Die Antwort ist teilweise richtig.</p> ]]> '''
 | 
			
		||||
 | 
			
		||||
    incorrectfeedback_elem = ET.SubElement(question, 'incorrectfeedback', attrib={'format': 'html'})
 | 
			
		||||
    text_elem = ET.SubElement(incorrectfeedback_elem, 'text')
 | 
			
		||||
    text_elem.text = '''<![CDATA[ <p>Die Antwort ist falsch.</p> ]]>'''
 | 
			
		||||
 | 
			
		||||
    varsrandom_elem = ET.SubElement(question, 'varsrandom')
 | 
			
		||||
    text_elem = ET.SubElement(varsrandom_elem, 'text')
 | 
			
		||||
    text_elem.text = f' '
 | 
			
		||||
 | 
			
		||||
    varsglobal_elem = ET.SubElement(question, 'varsglobal')
 | 
			
		||||
    text_elem = ET.SubElement(varsglobal_elem, 'text')
 | 
			
		||||
    numerators_string = ",".join([str(n) for n in numerators])
 | 
			
		||||
    denominators_string = ",".join([str(d) for d in denominators])
 | 
			
		||||
    text_elem.text = f'n = [{numerators_string}];\n d = [{denominators_string}];'
 | 
			
		||||
 | 
			
		||||
    answers_elem = ET.SubElement(question, 'answers')
 | 
			
		||||
    partindex_elem = ET.SubElement(answers_elem, 'partindex')
 | 
			
		||||
    ET.SubElement(partindex_elem, 'text').text = '0'
 | 
			
		||||
    placeholder_elem = ET.SubElement(answers_elem, 'placeholder')
 | 
			
		||||
    ET.SubElement(placeholder_elem, 'text').text = '#A'
 | 
			
		||||
 | 
			
		||||
    answermark_elem = ET.SubElement(answers_elem, 'answermark')
 | 
			
		||||
    ET.SubElement(answermark_elem, 'text').text = '2' if shortable else '1'
 | 
			
		||||
 | 
			
		||||
    answer_elem = ET.SubElement(answers_elem, 'answer')
 | 
			
		||||
    answer_text = '[resnum, cd, sresnum, sresden]' if shortable else '[resnum, cd]'
 | 
			
		||||
    ET.SubElement(answer_elem, 'text').text = answer_text
 | 
			
		||||
 | 
			
		||||
    vars1_elem = ET.SubElement(answers_elem, 'vars1')
 | 
			
		||||
    vars1_elem_text = f"<![CDATA[resnum = {result_numerator}; cd = {common_denominator}; sresnum = {shortened_numerator}; sresden = {shortened_denominator};]]>"
 | 
			
		||||
    ET.SubElement(vars1_elem, 'text').text = vars1_elem_text
 | 
			
		||||
 | 
			
		||||
    vars2_elem = ET.SubElement(answers_elem, 'vars2')
 | 
			
		||||
    vars2_elem_text = "<![CDATA[ ga = _0 == resnum && _1 == cd; gb = (_0 / _1) == (resnum / cd); ]]>"
 | 
			
		||||
    ET.SubElement(vars2_elem, 'text').text = vars2_elem_text
 | 
			
		||||
 | 
			
		||||
    correctness_elem = ET.SubElement(answers_elem, 'correctness')
 | 
			
		||||
    ET.SubElement(correctness_elem, 'text').text = '0.5*ga + 0.5*gb'
 | 
			
		||||
 | 
			
		||||
    feedback_elem = ET.SubElement(answers_elem, 'feedback', attrib={'format': 'html'})
 | 
			
		||||
    feedback_text = '''<![CDATA[ <h4>Lösungshinweis</h4>
 | 
			
		||||
                       <p>Die korrekte Lösung ist:</p>
 | 
			
		||||
                       <p>\\(\\displaystyle''' + f"{result_numerator}/{common_denominator}" + '''\\)</p> ]]>'''
 | 
			
		||||
    ET.SubElement(feedback_elem, 'text').text = feedback_text
 | 
			
		||||
 | 
			
		||||
    return question
 | 
			
		||||
 | 
			
		||||
def generate_questions(num_questions):
 | 
			
		||||
    questions = []
 | 
			
		||||
    for i in range(num_questions):
 | 
			
		||||
        questions.append(create_formula_question(i))
 | 
			
		||||
    return questions
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
    ET.indent(tree, space="\t", level=0)
 | 
			
		||||
    with open(filename, 'wb') as f:
 | 
			
		||||
        tree.write(f, encoding='utf_8', xml_declaration=True)
 | 
			
		||||
    return 0
 | 
			
		||||
 | 
			
		||||
def replace_vars2(xml_file):
 | 
			
		||||
    with open(xml_file, 'r') as f:
 | 
			
		||||
        text = f.read()
 | 
			
		||||
    text = text.replace("&", "&")
 | 
			
		||||
    text = text.replace("<", "<")
 | 
			
		||||
    text = text.replace(">", ">")
 | 
			
		||||
    with open(xml_file, 'w') as f:
 | 
			
		||||
        f.write(text)
 | 
			
		||||
    print("Ersetzungen abgeschlossen.")
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    questions = generate_questions(NUM_QUESTIONS)
 | 
			
		||||
    quiz = create_quiz(questions)
 | 
			
		||||
    save_to_file(quiz, FILENAME)
 | 
			
		||||
    replace_vars2(FILENAME)
 | 
			
		||||
    print("Moodle-XMLDatei erfolgreich erstellt.")
 | 
			
		||||
		Reference in New Issue
	
	Block a user