Vademecum Khan-Aufgaben
Eine Khan-Aufgabe ermöglicht, sich interaktiv, individuell und wiederholt mit einem mathematischen Thema auseinanderzusetzen. Dies erfolgt numerisch, graphisch oder semantisch. Weitere Eigenschaften sind
- Bei jedem Aufruf wird die Aufgabe mit neuen Parametern (z.B. Zahlen oder Abbildungen) gestellt und muss erneut gelöst werden.
- Die Lösung kann durch Eingabe von Zahlen oder anderen mathematischen Ausdrücken erfolgen, daneben kann diese durch Lokalisieren im Browser, durch Multiple-Choice oder graphische Elemente erfolgen.
- Es gibt eine direkte Rückmeldung auf die Eingabe.
- Zuvor oder danach können schrittweise Hilfestellungen aufgerufen werden. Die Erläuterungen arbeiten mit den individuellen Parametern. Diese können auch graphisch sein.
- Die Darstellung der mathematischen Ausdrücke basiert auf KaTeX.
- Mit GenAI lassen sich neue Aufgaben erstellen.
Wir geben hier einen möglichst schnellen Einstieg, siehe auch FAQ.
Fragen der Programmiereleganz oder der Performance stehen dabei nicht im Mittelpunkt. Diese spielen bei dem kleinen Parameterraum in der Regel auch keine Rolle.
Beispiele aus Khan+
Einsatz
Der Einsatz erfordert keine Einbindung. Eine Aufgabe läuft im Browser, auch mobil. Direktes Verlinken, z.B. für oder in Übungsserien, erfolgt
mit href
oder verwandten Befehlen. Elementare Anpassungen (z.B. Notationen) erfolgen in einer html-Datei.
Die anonymen Daten zu Interaktionen mit einer Aufgabe (Eingabe, neue Parameter, Hinweise) werden erfasst und können dann ausgewertet werden.
Aufbau
Eine Khan-Aufgabe ist eine html-Datei
. Basis bildet das Khan-Exercise Framework, weiterentwickelt zu kekse
,
unserer Version von Khan.
Im Kopf der Aufgabe wird der Dokumententyp, die (globale) Sprache und die Kodierung definiert. Es werden die Pfade für die CSS-Stylesheets sowie der im Browser Tab angezeigte Titel spezifiziert. Es genügt für gewöhnlich, der Aufgabe einen Titel zu geben.
<head>
. . .
<title>Steht im Browser-Tab</title>
</head>
Interessant wird es nach <body>
.
Im Body wird das eigentliche Framework der gesamten Aufgabe inklusive Validation definiert. Ganz am Schluss des <body>
-Elements wird der Pfad zum JavaScript-Bündel angegeben. Dieser kann direkt übernommen werden.
<script src="../blob/dist/kexe.bundle.js"></script>
.
Das Bündel kekse
ist unsere Weiterentwicklung des Khan-Exercise Frameworks.
Meta
In <div class="meta">...</div>
werden neben lokaler Sprache und Kodierung noch definiert:
-
title
: Ist der Titel, der zuoberst in der Aufgabe steht. -
atype
: Ist der Antworttyp:- Für eine offene Aufgabe ist es, je nach Format
text, number, rational
oderdecimal
. Wir die Lösung als mathematischer Ausdruck erwartet, ist der Typexpression
. Hier gibt es zusätzlich eine Vorschau der Eingabe. - Für eine geschlossene Aufgabe sind es
radio
bei Single-Choice odercheckbox
bei Multiple-Choice. - Weitergehende Möglichkeiten sind in der Referenz zu finden.
- Für eine offene Aufgabe ist es, je nach Format
-
size
: Diese Grösse gibt an, wie oft neue, einzigartige Zahlen generiert werden können, bevor die Aufgabe komplett neu geladen werden muss. Dabei solltesize
nicht grösser (und im Idealfall gleich gross) sein wie die Zahl der Möglichkeiten des unten definierten Zufallsraumes der Variablen.
Vars
In der Umgebung <div class="vars">...</div>
werden die in der Aufgabe verwendeten Variablen definiert, mit <var id="name">wert</var>
pro Variable. Dabei sind
-
name
der Name der Variable und -
wert
ihr Wert. Es wirdwert
als JavaScript-Ausdruck interpretiert, wobei vorher definierte Variablen als JavaScript-Variablen mit ihrem jeweiligen Namen zur Verfügung stehen, und JavaScript-Mathematik-Funktionen in JSMathobject sowie einige Funktionen aus den Khan-Modulen verwendet werden können. - Siehe auch Liste mit Khan-Funktionen.
<var id="A">10</var>
<var id="B">A / 2</var>
zwei Variablen A
und B
mit Werten 10
und 5
.
Interessanter sind Variablen mit einem zufälligen Wert. Zum Beispiel
(siehe auch Khans in Teilen nicht aktuelles Manual):
<var id="A">randRangeExclude(-12,12,[-1,0,1])</var>
.
Hier kann die Variable A
ganzzahlige Werte zwischen -12
und 12
(inklusive Grenzen) annehmen, die aber ungleich -1
, 0
oder 1
sind.
Mit randRange(N,M)
werden zufällige Zahlen zwischen N
und M
erzeugt.
Statt randRangeExclude(N,M,[0])
geht auch einfach randRangeNonZero(N,M)
.
Mit <var id="L">randFromArray([L1,L2,...])</var>
wird zufällig eine der Variablen L1
, L2
, etc. ausgewählt und deren Wert der Variablen L
zugewiesen. Dabei sind L1
, L2
, etc. vorher definierte Variablen.
Die Ergänzung <div data-ensure="...">
schränkt die Auswahl weiter ein:
<div data-ensure="A > B">
<var id="A">randRange(1, 10)</var>
<var id="B">randRange(1, 10)</var>
Siehe auch Test-Funktionen auf der Liste mit Khan-Funktionen.
Weitere Beispiele sind:
- Stammt aus Beispiel:
Um sicherzustellen, dass die Vektoren
\(\left(\begin{smallmatrix} A \\ B \\ C \end{smallmatrix}\right)\)
und
\( \left(\begin{smallmatrix} D \\ E \\ F \end{smallmatrix}\right)\)
orthogonal sind, schreibe (zum Beispiel)
<div data-ensure="kvector.dot([A,B,C],[D,E,F]) == 0"> <var id="A">randRange(-4,4)</var> <var id="B">randRangeExclude(-4,4,[A])</var> <var id="C">randRange(-4,4)</var> <var id="D">randRange(-4,4)</var> <var id="E">randRangeExclude(-4,4,[D])</var> <var id="F">randRange(-4,4)</var> </div>
- Stammt aus Beispiel:
Für eine \( 2 \times 2\) - Matrix
\(\left(\begin{smallmatrix} A & B \\ C & D \end{smallmatrix} \right)\)
mit Determinante ungleich Null schreibe (zum Beispiel)
<div data-ensure="A*D-B*C !== 0"> <var id="A">randRangeNonZero(-8,8)</var> <var id="B">randRangeNonZero(-8,8)</var> <var id="D">randRangeNonZero(-8,8)</var> <var id="C">randRangeNonZero(-8,8)</var> </div>
- Stammt aus Beispiel:
Logische Operationen sind auch möglich:
Es wird sichergestellt, dass<div data-ensure="K<0 && -K!=4 && -K!= 9 && -K!=16"> <var id="N">randRangeExclude(-4,4,[-1,0])</var> <var id="T">2*N+1</var> <var id="D">randRange(2,24)</var> <var id="K">T*T - 4*D</var> </div>
K
negativ ist undD
keine der Quadratzahlen, alternativ definiere die VariableD
mit:<var id="D">randRangeExclude(2,24,[4,9,16])</var>
- Stammt aus Beispiel: Es können auch Felder definiert werden:
<var id="functionBank">[ <!-- [f, g, f', g', f*g', f'*g, g*f - \int f'*g, skp, UG,OG] --> ["x", "\\sin(x)", "1", "\\cos(x)", "x\\cos(x)", "\\sin(x)", "x\\sin(x) + \\cos(x)","0","-\\pi","\\pi"], ["x", "\\sin(x)", "1", "\\cos(x)", "x\\cos(x)", "\\sin(x)", "x\\sin(x) + \\cos(x)","0","-\\frac{\\pi}{2}","\\frac{\\pi}{2}"], ... ] </var> <var id="fNum">randRange(0,functionBank.length-1)</var> <var id="f">functionBank[fNum]</var>
- Wenn Single-Choice-Antworten aus mehreren zufälligen Variablen zusammengebaut werden, kann es passieren, dass zwei Antworten gleich ausfallen, obwohl die ursprünglichen Variablen ungleich waren. Z.B., wenn zwei mögliche Antworten Brüche
X1/Y1
undX2/Y2
sind:<div class="vars"> <var id="X1">randRange(-10,10)</var> <var id="X2">randRangeExclude(-10,10,X1)</var> <var id="Y1">randRange(-10,10)</var> <var id="Y2">randRangeExclude(-10,10,Y1)</var> </div>
Obwohl
X1 != X2
undY1 != X2
, kann dennochX1/Y1 == X2/Y2
, z.B. ist 1/2 = 2/4.Eine Lösungsmöglichkeit ist eine sorgfältigere Programmierung mit
data-ensure
, z.B.:
oder wir lassen uns mehr als genug Antworten generieren und bereinigen dann diese Auswahl, wie im folgenden Beispiel<div class="vars" data-ensure="X1/Y1!=X2/Y2"> <var id="X1">randRange(-10,10)</var> <var id="X2">randRange(-10,10)</var> <var id="Y1">randRange(-10,10)</var> <var id="Y2">randRange(-10,10)</var> </div>
Question
In <div class="question">...</div>
steht die Aufgabenstellung als html.
- LaTeX-Ausdrücke sind mittels KaTeX innerhalb von
<code>
-tags möglich: Siehe auch die unterstützten Funktionen in der KaTeX-Syntax. - Die
<var>
-tags erhalten ausserhalb von<div class="var">
eine neue Bedeutung: Ihr Inhalt wird als JavaScript ausgewertet und ausgegeben. So gibt z.B.<var>A</var>
den Wert der VariableA
aus, und<var>A+B</var>
die Summe vonA
undB
. Nützlich für eine saubere Darstellung von Werten sind folgende Khan-Funktionen, die in<var>...</var>
verwendet werden können:negParens(A)
: FallsA
negativ ist, wird(A)
dargestellt:negParens(-2)
zeigt dann(-2)
undnegParens(2)
einfach2
.fractionReduce(A,B)
: Stellt einen gekürzten Bruch da, auch ganzzahlig, zum Beispiel wirdfractionReduce(40,8)
zu5
undfractionReduce(40,80)
zu \( \dfrac 12 \). Taucht der Bruch zum Beispiel als Index auf, bietet sichfractionReduce(A,B,small=true)
an.formattedSquareRootOf(A)
: Schreibt eine möglichst reduzierte Wurzel, also wird mitformattedSquareRootOf(27)
dann \(3\sqrt{3}\) angezeigt.- Siehe auch Liste mit Print-Funktionen.
- Ein Element
<div data-if="bedingung">...</div>
wird nur angezeigt, falls die JavaScript-Bedingungbedingung
wahr ist. So können z.B. abhängig von Zufallsvariablen Weichen gestellt werden (siehe Beispiel unten). Nützlich sind hier auch die die Liste mit Test-Funktionen.
Auch in den Teilen "Solution" und "Hints" der Aufgabe (siehe nächste zwei Abschnitte) können diese drei Werkzeuge (KaTeX, Variablen, data-if) eingesetzt werden. Siehe auch die Liste mit Khan-Funktionen.
Solution
In <div class="solution">...</div>
wird bestimmt, wie die Lösung der Aufgabe eingegeben werden kann, und welche Eingabe(n) als korrekt gewertet werden.
Die Syntax für diesen Teil der Aufgabe ist massgeblich durch den Antworttyp bestimmt, der in <div class="meta">...</div>
angegeben wurde (siehe oben).
Antworttypen und deren Syntax sind in einem ergänzenden Manual beschrieben. Wir geben hier nur eine kurze Übersicht anhand von Beispielen.
- Antworttypen mit Textbox Eingabe sind z.B.
text
,number
,rational
oderdecimal
. Im einfachsten Fall wird die korrekte Lösung direkt im<div class="solution">
angegeben. Z.B.:
Hier ist die korrekte Antwort in der Variable<div class="solution"><var>X</var></div>
X
gespeichert und als wahr (korrekt) nach Drücken desPrüfen
-Knopfs validiert. Ein Beispiel:<div class="solution"> <var>a*(B*B/2)</var> </div>
- Für Antworttypen mit Textbox gibt es auch eine erweiterte Syntax, welche individuelle Gestaltung der Textbox zulässt:
Dabei enthält<div class="solution"> <span class="xlabel"><code>\displaystyle \int_\gamma K d\gamma=</span> <span class="value"><var>result</var></span> </div>
<span class="value">
nun den Wert der Lösung und ist das einzige notwendige Element in<div class="solution">
;<span class="xlabel">
eine Beschriftung (auch mit KaTeX) auf der linken Seite der Textbox.
- Für Single-Choice braucht es den Antworttyp
radio
. Folgendes Beispiel stammt aus: - Der Antworttyp
multiple
erlaubt Aufgaben mit mehreren Antworten. Beispiel
Es werden zwei Zahleneingaben erwartet: "untere Grenze" und "obere Grenze". Dafür gibt es automatisch zwei Eingabefelder. Allgemein muss für jede verlangte Teilantwort ein Element<div class="solution"> <div class="sol" data-type="number"> <span class="label">untere Grenze:</span> <span class="xlabel"><span style="width: 7em">untere Grenze:</span></span> <span id="sol_c" class="value"> <var>RANGE[0]</var> </span> </div> <div class="sol" data-type="number"> <span class="label">obere Grenze:</span> <span class="xlabel"><span style="width: 7em">obere Grenze:</span></span> <span id="sol_a" class="value"> <var>RANGE[1]</var> </span> </div> </div>
<div class=sol data-type="...">
vorliegen, bei demdata-type
den Antworttyp der Teilantwort spezifiziert.Für
multiple
existiert eine alte Syntax, die nur noch aus Kompatibilitätsgründen funktioniert. Obiges Beispiel wäre<div class="solution"> <div> <span class="label">untere Grenze:</span> <span class="xlabel">untere Grenze:</span> <span id="sol_c" class="sol" data-type="number"><var>RANGE[0]</var></span> </div> <div> <span class="label">obere Grenze:</span> <span class="xlabel">obere Grenze:</span> <span id="sol_a" class="sol" data-type="number"><var>RANGE[1]</var></span> </div> </div>
Viele bereits bestehende Aufgaben in Khan+ verwenden noch die alte
multiple
- Syntax, auch wenn nur eine Teilantwort verlangt ist.Beispiel einer
multiple
-Aufgabe im alten Format. Hier ist es möglich, mit<data-if>
Weichen in Abhängigkeit der Zufallsparameter einzubauen:<span data-if="L3 == L2" id="sol_c" class="sol" data-type="number">0</span> <span data-if="L3 == L1" id="sol_d" class="sol" data-type="number">1</span>
- Stammt aus Beispiel:
Gibt es keine eindeutige Lösung, oder ist die Lösung abhängig von
den aktuellen Variablen oder die Eingabe unabhängig von der Reihenfolge
der Eingabe, bietet sich der Antworttyp
set
an. Fürset
muss wie fürmultiple
ein Unter-Antworttyp gewählt werden. Im folgenden Beispiel ist diesexpression
:<div class="solution"> <div data-if="K == 0" class="set-sol" data-type="expression"> <div class="sol" data-type="expression">(A+B*t)e^{<var>L1</var>*t} </div> </div> <div data-if="K == 0" class="set-sol" data-type="expression"> <div class="sol" data-type="expression">(A*t+B)e^{<var>L1</var>*t} </div> </div> <div data-if="K > 0" class="set-sol" data-type="expression"> <div class="sol" data-type="expression"> Ae^{<var>L1</var>*t} + Be^{<var>L2</var>*t} </div> </div> <div data-if="K > 0" class="set-sol" data-type="expression"> <div class="sol" data-type="expression"> Ae^{<var>L2</var>*t} + Be^{<var>L1</var>*t} </div> </div> <div class="input-format"> <div class="entry" data-type="expression"> <span class="xlabel"><code>y(t) =</code></span> <span class="value"></span> </div> </div> </div>
Der Antworttyp
expression
fragt nach mathematischen Ausdrücken wie\sin(5x)
oder im vorherigen Beispiel nache^{<var>L1</var>*t}
.Mit Antworttyp
custom
sind massgeschneiderte Aufgaben möglich, aber auch anspruchsvoller. Das Beispiel oben "Demo custom mit Geradengleichung" ginge sicher auch elementarer.-
Mit
custom
kann ich auch Zahlen in einem Intervall als korrekt werten: Die validator-Funktion muss dann Grössenvergleiche implementieren:<div class="solution"> <div class="instruction"> <form class="needs-validation" autocomplete="off" novalidate=""> <label for="custom_input" class="control-label visually-hidden">B=</label> <div class="input-group"> <span class="input-group-text bk-input-group-addon"> <code>{\color{red}X=}</code> </span> <input id="custom_input" type="text" class="form-control" autocapitalize="off" /> </div> </form> </div> <div class="guess">[document.getElementById("custom_input").value]</div> <div class="validator-function"> return (X > a) && (X < b); </div> </div>
Hier wird
X
als korrekt gewertet, fallsX > a
undX < b
, wobeia
undb
Variablen sind. Mit>=
und<=
können Zahlen in abgeschlossenen Intervalle abgefragt werden. Das html in<div class="instruction">
bestimmt das Aussehen des Eingabefelds. Dies wird z.B. hier verwendet:
Hints
Die Hinweise (ver-)stecken (sich) im <div class="hints"> ... </div>
-Block.
Mit einer Serie von <div>
werden schrittweise Hinweise angezeigt, jeweils durch Drücken des Knopfes Hinweis
. Auch hier können KaTeX und Variablen verwendet werden.
Nützliche Punkte zeigen wir wieder an Beispielen:
- Stammt aus Beispiel:
Auch hier lassen sich mit
<data-if>
Weichen in Abhängigkeit der Zufallsparameter einbauen:<div data-if="V == W"> <p>Hier wird <code>\gamma</code> <b>positiv</b> durchlaufen.</p> </div> <div data-if="V !== W"> <p>Hier wird <code>\gamma</code> <b>negativ</b> durchlaufen.</p> </div>
- Stammt aus Beispiel:
Graphische Elemente können im Hinweis aktualisiert werden:
Sei <div class="graphie" id="rennen"> ... </div> gegeben. Dann wird durch <div class="graphie" data-update="rennen"> ... </div> im bestehenden Graphen eine Komponente hinzugefügt.
Graphie and Friends
Der Einsatz graphischer Elemente ist ein Sprung, der am besten durch Copy & Paste gemeistert wird.
In Khan+ gibt es neben den Beispielen oben noch
- Matrix-Abbildung
- Punkt in komplexer Ebene
- Komplexe Zahlen: more sophisticated
- Gradlinige Parametrisierung
- Integral via Symmetrie
- Mittelwert
- Gebietsintegral
KaTeX vs. JS vs. html
Als html-Datei wird eine Khan-Aufgabe vom Browser in erster Linie als html interpretiert.
Erst wenn die Aufgabe mit kekse, unserer Version von Khan, abschliesst
<script src="blob/dist/kexe.bundle.js"></script>
wird das html der Aufgabe speziell interpretiert
und daraus die einsatzbereite Khan-Aufgabe gebaut. Daher sieht eine Khan-Aufgabe u.U. "kaputt" aus, wenn kekse
nicht richtig (langsam) geladen wird.
Im Gegensatz zu üblichem html haben die Inhalte von bestimmten html-Elementen der Aufgabe dementsprechend spezielle Bedeutungen. So gibt es Elemente, die JavaScript-Code oder LaTeX-Code enthalten können/sollen, auch wenn das in html überlicherweise nicht möglich ist.
html-Escape
Werden umgekehrt in solchen Inhalten die html-Sonderzeichen <
, >
, &
benötigt,
müssen sie mit html-Escape-Sequenzen <
, >
, &
geschrieben werden.
Gib es z.B. in einem JavaScript-Abschnitt einen Grössenvergleich
if (x > y)
, dann muss dort if (x > y)
stehen.
Direktes html
Es gibt Abschnitte, in denen das html der Aufgabe direkt als html interpretiert wird:
<div class="question">...</div>
,<div class="hints">...</div>
: Das hier enthaltene html wird als Aufgabenstellung angezeigt bzw. als Hinweise angezeigt.- Verschiedenste Orte innerhalb von
<div class="solution">
, je nach Antworttyp: html wird hier je nach Antworttyp verwendet, um das/die Eingabefeld/er zu gestalten.
Überall, wo html direkt als solches interpretiert wird, kann mittels
<code>...</code>
LaTeX-Code eingefügt werden, welcher dann dementsprechend als Formel dargestellt wird. Dies geschieht mit KaTeX, also ist der Befehlssatz von KaTeX ausschlaggebend, siehe Beispiele oben.
JavaScript
JavaScript wird an folgenden Orten erwartet:
<var>...</var>
: Einerseits bei Variabeldefinitionen (z.B.<var id="A">2</var>
oder<var id="B">sqrt(A)</var>
). Anderseits bei Verwendung der Variable in der Aufgabe (z.B.<var>A</var>
oder<var>A*B</var>
); hier wird der Inhalt des Tags ausgewertet, zu Text umgewandelt und anstelle des<var>
-Tags eingefügt. Sobald eine Variable definiert wurde, ist sie als JavaScript-Variable überall verfügbar, wo JavaScript-Code erwartet wird.data-if="..."
unddata-ensure="..."
: Erwartet werden JavaScript-Ausdrücke, die entweder wahr oder falsch ergeben.<div class="graphie">...</div>
: Anweisungen an graphie werden hier als JavaScript-Code gegeben.- Antworttyp
custom
: Mit dem JavaScript-Code in<div class="guess">...</div>
,<div class="validator-function">...</div>
und<div class="show-guess">...</div>
wird dercustom
-Antworttyp konfiguriert, siehe Manual.
Es ist möglich, <var>
innerhalb von <code>
zu verwenden, siehe Beispiele oben.