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

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:

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

Die Variablen-Werte werden später im html der Aufgabe ausgelesen (siehe unten). Zum Beispiel definiert
<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:

  1. 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>
  2. 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>
    
  3. Stammt aus Beispiel: Logische Operationen sind auch möglich:
    <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>
    
    Es wird sichergestellt, dass K negativ ist und D keine der Quadratzahlen, alternativ definiere die Variable D mit:
     <var id="D">randRangeExclude(2,24,[4,9,16])</var>
    
  4. 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>
    
  5. 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 und X2/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 und Y1 != X2, kann dennoch X1/Y1 == X2/Y2, z.B. ist 1/2 = 2/4.

    Eine Lösungsmöglichkeit ist eine sorgfältigere Programmierung mit data-ensure, z.B.:

    <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>
    
    oder wir lassen uns mehr als genug Antworten generieren und bereinigen dann diese Auswahl, wie im folgenden Beispiel

Question

In <div class="question">...</div> steht die Aufgabenstellung als html.

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.

  1. Antworttypen mit Textbox Eingabe sind z.B. text, number, rational oder decimal. Im einfachsten Fall wird die korrekte Lösung direkt im <div class="solution"> angegeben. Z.B.:
    <div class="solution"><var>X</var></div>
    Hier ist die korrekte Antwort in der Variable X gespeichert und als wahr (korrekt) nach Drücken des Prüfen-Knopfs validiert. Ein Beispiel:
    <div class="solution">
     <var>a*(B*B/2)</var>
    </div>
  2. Für Antworttypen mit Textbox gibt es auch eine erweiterte Syntax, welche individuelle Gestaltung der Textbox zulässt:
    <div class="solution">
        <span class="xlabel"><code>\displaystyle \int_\gamma K d\gamma=</span>
        <span class="value"><var>result</var></span>
    </div>
    Dabei enthält
    • <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.
  3. Für Single-Choice braucht es den Antworttyp radio. Folgendes Beispiel stammt aus:
  4. Der Antworttyp multiple erlaubt Aufgaben mit mehreren Antworten. Beispiel
    <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>
    
    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=sol data-type="..."> vorliegen, bei dem data-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>
    

  5. 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ür set muss wie für multiple ein Unter-Antworttyp gewählt werden. Im folgenden Beispiel ist dies expression:
    <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>
    
  6. Der Antworttyp expression fragt nach mathematischen Ausdrücken wie \sin(5x) oder im vorherigen Beispiel nach e^{<var>L1</var>*t}.

  7. Mit Antworttyp custom sind massgeschneiderte Aufgaben möglich, aber auch anspruchsvoller. Das Beispiel oben "Demo custom mit Geradengleichung" ginge sicher auch elementarer.

    1. Beispiel einer geometrischen Validierung:

    2. 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 &gt; a) && (X &lt; b);
          </div>
      </div>
      

      Hier wird X als korrekt gewertet, falls X > a und X < b, wobei a und b Variablen sind. Mit &gt;= und &lt;= 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:

      Beispiel:

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:

  1. 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>
    
  2. 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

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 &lt;, &gt;, &amp; geschrieben werden. Gib es z.B. in einem JavaScript-Abschnitt einen Grössenvergleich if (x > y), dann muss dort if (x &gt; y) stehen.

Direktes html

Es gibt Abschnitte, in denen das html der Aufgabe direkt als html interpretiert wird:

Ü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:

Es ist möglich, <var> innerhalb von <code> zu verwenden, siehe Beispiele oben.