MLTutorBeispielerstellung: Unterschied zwischen den Versionen

Aus Physik
Zur Navigation springen Zur Suche springen
 
(44 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
  +
[[Category:MLTutor]]
==Allgemeine Fragen und Antworten zum Adaptieren der Übungsbeispiele==
 
  +
== Allgemeines ==
  +
=== MLTutor-Projekte ===
  +
Für jede Aufgabe die im Laufe des Kurses zu absolvieren ist, muss ein
  +
MLTutor-Projekt angelegt werden.
   
  +
Dieses ist eine Sammlung von Dateien, die für den Ablauf notwendig
=== Soll jedes Beispiel einer Übung ein eigenes Projekt sein? Wenn nicht sollen wir die Benennung so wie auf Angabe für Referenzprogramm übernehmen? ===
 
  +
sind:
* <span style="color:green"> JA, jedes Beispiel als eigenes Projekt; Referenzprogramm heißt immer '''main.m'''. Das gilt nur für ein eventuell notwendiges Script. Funktionen werden gleich benannt wie in der Angabe, und ein Projekt kann mehr als eine Funktion enthalten. </span>
 
  +
* Ein XML-File (.mlt)
**<span style="color:red"> ÄNDERUNG: Sogar jede Funktion soll ein eigenes Projekt werden. Eine Übung besteht dann aus der Aufgabe mehrere Projekte zu programmieren! Deshalb bitte merken, welche Projekte zu welcher Übung gehören!</span>
 
  +
* Ein before- und after-script (manipulieren die Umgebung in der der Test
***<span style="color:blue">Wenn in der Übung gefordert wird, eine Funktion und ein Script zu schreiben wobei in diesem Script die Funktion aufgerufen wird, da sollte ein Projekt reichen? Wenn die Funktion in einem anderen Projekt sein sollte, dann ist sie auch in einem anderen Verzeichniss. Das Script könnte dann die Funktion nur mit dem entsprechenden Pfad aufrufen...</span>
 
  +
abläuft)
****<span style="color:green"> Die Funktion soll trotzdem ein eigenes Projekt sein. Es wird dann im XML-File möglich sein die Abhängigkeiten zu definieren. Damit wird die Funktion, obwohl sie in einem anderen Verzeichnis ist, automatisch gefunden </span>
 
  +
* Eine Referenzlösung
  +
* Eventuell benötigte Datenfiles
   
=== Wie werden Funktionen getestet? ===
+
=== Der XML-File ===
  +
Diese Datei dient zur allgemeinen Steuerung des Testvorgangs.
<span style="color:green"> Es wird eine Referenzfunktion geschrieben und beide Funktionen werden aufgerufen. Danach werden die Variablen verglichen.
 
  +
Welche Einstellungen hierin vorgenommen werden können ist im Anschluss zu finden.
   
  +
==== Anlegen eines neuen XML-Files ====
=== Ist Laden von Übungsdaten noch notwendig? ===
 
  +
In der Matlab-Workbench in der Projektbaumstruktur Rechtsklick auf den Namen eines MLTutor-Projektes.
<span style="color:green">NEIN</span>
 
  +
Im ersheinenden Menü
  +
New -> Other -> MLTutor File
  +
Jetzt sollte ein example.mlt angelegt worden sein.
   
  +
==== Einstellungen im XML-File ====
Die Datenfiles sollen einfach im gleichen Verzeichnis wie der Matlab-File liegen. Sie werden dann automatisch an die entsprechende Stelle kopiert damit der Test funktioniert.
 
  +
Diese Liste bezieht sich auf die Tabs, die im XML-Editor (nach Doppelklick auf .mlt) unten eingeblendet werden.
   
  +
* '''Overview''': Name und Art des Beispiels sind anzugeben
=== Wie werden Variablen gesetzt? ===
 
  +
** Der Name wird im entsprechenden Textfeld eingetragen
*<span style="color:green">ENTWEDER es wird ganz klar gefordert welche Werte den Variablen zugewiesen werden müssen,</span>
 
  +
** Die Art des Beispiels wird im entsprechenden Dropdown Menü eingestellt. Hier gilt folgende Zuordnung
*<span style="color:green">ODER es werden Variablen im Praescript definiert und in der Angabe wird mitgeteilt, dass diese Variablen existieren.</span>
 
  +
*** Standard -> Einführungsbeispiel
  +
*** Übungsbeispiel -> Pflichtbeispiel
  +
*** Zusatzbeispiel -> Freiwilliger Zusatz
  +
* '''Dependencies'''
   
  +
POSTPONED UNTIL NEW EDITOR
   
  +
=== before- und after-script ===
  +
Mit diesen MATLAB-Skripten wird die
  +
Umgebung, in der der Test ausgeführt wird manipuliert. Ein Großteil
  +
der Eigenschaften eines Tests wird hierin festgelegt.
   
  +
=== Referenzlösung ===
=== Kann man beim Ausführen eines Skriptes <tt>input</tt> umgehen bzw. Werte vordefinieren, die dann verwendet werden? ===
 
  +
Die Referenzlösung ist ein MATLAB-Script (-Funktion), das die
<span style="color:green"> JA; Die Lösung existiert auch schon. Es wird im before-script die Variable MLTutor_INPUT_ANSWERS gesetzt. Dies ist eine Zelle, die Strings der zu setzenden Werte enthält. Es muss allerdings die Reihenfolge der Abfrage vorgegeben sein. Will man tatsächlich einen String setzen so ist dieser in dreifache single-quotes einzuschließen. </span>
 
  +
gestellte Aufgabe löst. Im Test wird dieses Skript ausgeführt, und die
  +
Werte bestimmter Variablen werden gespeichert. Anschließend wird das
  +
äquivalente Skript der KursteilnehmerInnen ausgeführt, und die Werte
  +
der fraglichen Variablen verglichen.
   
  +
=== Datenfiles ===
Beispiel:
 
  +
... werden im Projektverzeichnis abgelegt und im XML-File eingetragen.
MLTutor_INPUT_ANSWERS={'[1:5]','''Kegel''','[]'};
 
  +
Zum Zeitpunkt des Tests wird dann sichergestellt, dass die Datenfiles
Bitte beachtet, wie ein leerer Input einzugeben ist (<nowiki>'[]'</nowiki>). Bei Zeichenketten braucht man jeweils drei Hochkommas am Anfang und am Ende, was bei obigem Beispiel dann <nowiki>'Kegel'</nowiki> als Input liefert.
 
  +
gefunden werden.
   
==== Input - Fragen ====
+
== Allgemeines zu Tests ==
  +
Prinzipieller Ablauf von Tests sollte woanders beschrieben werden.
Die Fragen, die mit dem Befehl <tt>input</tt> gestellt werden, können auch überprüft werden. Beim Beispiel
 
x = input('Bitte geben Sie x ein: ');
 
könnte man angeben
 
MLTutor_INPUT_REGEXP = { ...
 
{'[B,b][I,i][T,t][T,t][E,e]','geben','x'} ...
 
};
 
was folgendes bedeutet (in beliebiger Reihenfolge):
 
das Wort Bitte in beliebiger Schreibweise BItte, BITTE, ...
 
das Wort geben
 
das Zeichen x
 
Eine andere Möglichkeit
 
MLTutor_INPUT_REGEXP = { ...
 
{'\<Bitte\>.+\<geben\>.+y.*:'} ...
 
};
 
Was in richtiger Reihenfolge bedeutet:
 
das Wort Bitte
 
zumindest ein beliebiges Zeichen dazwischen .+
 
das Wort bitte
 
zumindest ein beliebiges Zeichen dazwischen .+
 
der Buchstabe y
 
beliebig viele Zeichen .* (auch null)
 
der Doppelpunkt
 
   
  +
=== Wie werden Variablen gesetzt? ===
Näheres zum Thema unter:
 
  +
Im Allgemeinen werden in der Aufgabenstellung einzuhaltende
[[#Regular Expressions bei Fehlern]] oder [http://itp.tugraz.at/matlab/techdoc/matlab_prog/ch_com15.html Regular Expressions]
 
  +
Variablennamen vorgegeben.
  +
  +
Es ist auch möglich bestimmte Variablen im before-script zu setzen,
  +
und in der Aufgabenstellung auf die Existenz dieser Variablen
  +
hinzuweisen.
   
  +
Beim Testen von Funktionen ist es in der Regel nicht notwendig
Wie [[#Regular Expressions bei disp |disp]] bei stehen die Ergebnisse dann in
 
  +
Variablennamen zu fordern.
MLTutor_INPUT_REGEXP_CORRECT
 
  +
MLTutor_INPUT_REGEXP_ALL_CORRECT
 
  +
=== Test von Funktionen ===
MLTutor_INPUT_REGEXP_REALALL_CORRECT
 
  +
Referenz- und Studierendenfunktion werden im before- oder after-script
wobei <tt>MLTutor_INPUT_REGEXP_ALL_CORRECT</tt> für jedes input 0 oder 1 enthält und das Gesamtergebnis in
 
  +
aufgerufen. Dabei hat man volle Kontrolle über Ein- und
<tt>MLTutor_INPUT_REGEXP_REALALL_CORRECT</tt> steht.
 
  +
Ausgabeparameter. Die Überprüfung erfolgt anhand der Rückgabewerte.
  +
  +
=== Umgang mit <tt>input</tt> ===
  +
Es wird im before-script die Variable
  +
MLTutor_INPUT_ANSWERS gesetzt. Dies ist eine Zelle, die Strings der zu
  +
setzenden Werte enthält. Es muss allerdings die Reihenfolge der
  +
Abfrage vorgegeben sein. Will man tatsächlich einen String setzen so
  +
ist dieser in dreifache single-quotes einzuschließen.
  +
  +
Beispiel:
  +
MLTutor_INPUT_ANSWERS={'[1:5]',<nowiki>'''Kegel'''</nowiki>,'[]'};
  +
Bitte beachtet, wie ein leerer Input einzugeben ist
  +
(<nowiki>'[]'</nowiki>). Bei Zeichenketten braucht man jeweils drei
  +
Hochkommas am Anfang und am Ende, was bei obigem Beispiel dann
  +
<nowiki>'Kegel'</nowiki> als Input liefert. <br>
   
  +
<b> Zählen von Input-Aufrufen </b> <br>
=== Können wir die korrekte Handhabung von <tt>rand</tt> überprüfen? ===
 
  +
Der Zähler für die Aufrufe von input ist
<span style="color:green"> JA, vor dem Ausführen muss der SEED des Zufallszahlengenerators gesetzt werden. Dazu existiert die Variable <tt> MLTutor_RANDOM_SEED </tt>. Das Setzen des SEEDS erfolgt im before-Skript durch den Aufruf von <tt> rand('state',MLTutor_RANDOM_SEED) </tt>. Wichtig ist, dass danach die Reihenfolge in der Variablen erzeugt werden vorgegeben wird und AUF ALLE FÄLLE einzuhalten ist. </span>
 
  +
MLTutor_INPUT_COUNT
  +
Damit kann man feststellen, wie oft die Funktion input aufgerufen wurde.
   
  +
=== Umgang mit <tt>rand</tt> ===
=== Was passiert wenn jemand "clear all" in seinem Script stehen hat? Ist ja ansich lobenswert wenn man es verwendet, nur wird dann die Initialisierung durch ml_test1_before Beispiele: .m gelöscht. ===
 
  +
Die Testumgebung setzt vor dem Ausführen der Skripte den Seed des
<span style="color:green"> Naja, ich sehe das als Fehler des Benutzers, da er ja weiß dass Variablen vorgegeben werden. <br> Eine andere Möglichkeit wäre das aufmerksam machen des Benutzers auf seinen Fehler. Muss man noch entscheiden..</span>
 
  +
Zufallszahlengenerators. Wichtig ist, dass danach die Reihenfolge in
  +
der Variablen erzeugt werden vorgegeben wird. Wird diese Reihenfolge
  +
nicht eingehalten wird ein positiver Test fehlschlagen.
   
  +
=== Was passiert wenn jemand "clear all" in einem Script stehen hat?===
Kein Problem. Alle kritischen Aktionen des Benutzers (Studenten) werden abgefangen.
 
  +
clear wird von der Testumgebung abgefangen,
  +
wenn etwas von den Studenten laufen kann. Damit werden vor allem die
  +
MLTutor-Variablen beschützt.
  +
Damit läuft aber u.U. einProgramm im Testbetieb, das ausserhalb nicht
  +
laufen würde.
   
Na ja, das Problem ist Folgendes: Ich habe jetzt clear abgefangen, wenn etwas von den Studenten laufen kann. Damit beschütze ich auch meine Infrastruktur von MLTutor-Variablen. Damit läuft aber u.U. ein Programm im Testbetieb, das ausserhalb nicht laufen würde. Ich sehe dafür aber jetzt keine bessere Lösung.
 
   
In der Variablen
+
Mit der Variablen
 
MLTutor_CLEAR_COUNT
 
MLTutor_CLEAR_COUNT
  +
existiert eine Möglichkeit zu prüfen ob <tt> clear </tt> aufgerufen
wird mitgezählt wie oft clear aufgerufen wird. Man kann es in den Test aufnehmen, dann bekommt man einen Fehler, wenn clear verwendet wird, weil MLTutor_CLEAR_COUNT dann nicht Null ist.
 
  +
wird.Man kann es in den Test aufnehmen, dann bekommt man einen Fehler,
  +
wenn clear verwendet wird, weil MLTutor_CLEAR_COUNT dann nicht Null
  +
ist.
   
  +
=== Verbotene Funktionen (z.B. <tt> for </tt>). ===
=== Soll die Abgabe generel mit Regulären Ausdrücken überprüft werden? Etwa wenn etwas ohne for Schleifen programmiert werden sollte. ===
 
  +
Es gibt einen Punkt in der XML-Datei, die zum Test gehört, wo man
<span style="color:green"> Nein, es gibt einen Punkt in der XML-Datei, die zum Test gehört, wo man einfach angibt, welche Funktionen der Benutzer nicht verwenden darf. Wenn du kompliziertere Tests des Script schreiben willst, könnte man natürlich in ml_test?_after.m eine Variable ausrechnen und diese mit ml_test?_check.m überprüfen </span>
 
  +
einfach angibt, welche Funktionen der Benutzer nicht verwenden darf.
   
=== Wie wird das mit der [[LaTeX]]-Angabe geregelt? (Referenzen, Kurzbefehle die für das Skriptum definiert wurden...)===
+
=== [[LaTeX]]-Angabe? (Referenzen, Kurzbefehle) ===
 
<span style="color:green"> Es existiert ein Projekt <tt> kernbich.testbeispiele.shorts.de </tt> in dem hilfreiche Kurzbefehle definiert sind. Dieses kann am Beginn eines Dokuments folgendermaßen eingebunden werden: </span>
 
<span style="color:green"> Es existiert ein Projekt <tt> kernbich.testbeispiele.shorts.de </tt> in dem hilfreiche Kurzbefehle definiert sind. Dieses kann am Beginn eines Dokuments folgendermaßen eingebunden werden: </span>
   
Zeile 87: Zeile 124:
 
<span style="color:green"> Wobei der Pfad zum Projekt (hier ..) jeweils angepasst werden muss. Diese Angabe hier sollte aber funktionieren, wenn sich alle Projekte im gleichen Workspace befinden. </span>
 
<span style="color:green"> Wobei der Pfad zum Projekt (hier ..) jeweils angepasst werden muss. Diese Angabe hier sollte aber funktionieren, wenn sich alle Projekte im gleichen Workspace befinden. </span>
   
  +
In <tt> kernbich.testbeispiele.shorts.de </tt> existieren einige Kürzel, deren Bedeutung selbserklärend sein sollte:
=== Überprüfung ob eine Funktion eine Fehlermitteilung produziert. ===
 
  +
\matrefe{sqrt}
<span style="color:green"> Im before- oder after-Skript wird definiert ob die gesamte Fehlermitteilung einer Vorgabe entsprechen soll, oder ob es genügt, dass sie eine gewisse Zeichenfolge enthält. Im after-script wird anschließend die Variable MLTutor_ERROR_CORRECT abgefragt. Diese ist 1 wenn die Fehlermitteilungen die gewünschten Kriterien erfüllt.</span>
 
  +
\matrefe{Wurzel}{sqrt}
  +
\matref{arithmetische Operatoren}{arithmeticoperators}
  +
Bei den Kapiteln bitte unbedingt die neuen [[Applikationssoftware - Dokumente|Kapitelnummern]] verwenden.
  +
\appsoftskriptum
  +
\appsoftkapitel{n} % Kapitelnummer n von 1 bis 20
   
  +
\MatlabLearning
Weitere Möglichkeiten gibt es auch unter [[#Regular Expressions bei Fehlern]].
 
  +
\MatlabReference
  +
\MatlabMathematics
  +
\MatlabCreatingPlots
  +
\MatlabPrograming
  +
\MatlabDataAnalysis
  +
\MatlabEnvironment
  +
\MatlabVisualize
  +
\MatlabCreatingGUIs
  +
\MatlabExternalInterfacesReference
  +
\MatlabExternalInterfaces
   
  +
\MatlabReferenceFunctionsCategoricalList
% func.m
 
  +
\MatlabReferenceMathematics
 
  +
\MatlabReferenceMathematicsArraysAndMatrices
function [x,y] = func(t)
 
  +
\MatlabReferenceMathematicsLinearAlgebra
if nargin < 1; error('time vector is undefined'); end
 
  +
\MatlabReferenceMathematicsElementaryMath
x = t;
 
  +
\MatlabReferenceMathematicsPolynomials
y = t.^2;
 
  +
\MatlabReferenceMathematicsInterporlationAndComputationalGeometry
  +
\MatlabReferenceMathematicsCoordinateSystemConversion
  +
\MatlabReferenceMathematicsNonlinearNumericalMethods
  +
\MatlabReferenceMathematicsSpecializedMath
  +
\MatlabReferenceMathematicsSparseMatrices
  +
\MatlabReferenceMathematicsMathConstants
   
  +
Es gibt jetzt auch noch ein Kürzel für die [[MLTutor - Hints]]
% ml_test1_before.m
 
  +
\mltutorhint{Strichpunkt}{MLTutor Hinweisen}
  +
Dies führt auf [[MLTutor - Hints#Strichpunkt]].
  +
  +
=== Zählen von disp-Aufrufen ===
  +
Der Zähler für die Aufrufe von disp ist
  +
MLTutor_DISP_COUNT
  +
Damit kann man feststellen, wie oft die Funktion disp oder fprintf (mit fid 1 oder 2) aufgerufen wurde.
  +
  +
=== Anzeige des Testaufrufs von Funktionen für den Benutzer ===
  +
Alles was in einem before- oder after-script von %### eingeschlossen ist, ist dem
  +
Benutzer zugänglich.
  +
  +
<pre>
  +
%ml_test1_after.m
  +
%###
  +
t = linspace(0,10,100);
  +
[x,y] = foo(t,[],4);
  +
%###
  +
  +
test_size = size(x);
  +
</pre>
  +
  +
Hier sieht der Benutzer also, welche Werte
  +
<tt> t </tt> zugewiesen werden, und wie die Funktion <tt> foo </tt>
  +
aufgerufen wird. Er sieht allerdings nicht, dass anschließend auch
  +
noch eine Variable <tt> test_size </tt> erzeugt wird.</span>
  +
  +
Bei Skripts braucht man das nur, wenn im before-Skript Variablen
  +
gesetzt werden. Dann sollten diese auch zwischen
  +
%###
  +
a = 3; b = 5;
  +
%###
  +
gesetzt werden.
  +
  +
In den Skripts und Funktionen UNBEDINGT Strichpunkte am Ende von
  +
Zeilen verwenden, die eine Ausgabe haben!
  +
  +
==== Verbesserung ====
  +
Möglich wäre obiges Beispiel auch in dieser Form:
  +
%ml_test1_after.m
  +
%###
  +
t = linspace(0,10,100);
  +
%###
 
 
  +
mltutor_function_switch(1);
% request an exact error message
 
  +
%###
MLTutor_ERROR_REQUEST.message = 'time vector is undefined';
 
  +
[x,y] = foo(t,[],4);
MLTutor_ERROR_REQUEST.type = 'e';
 
  +
%###
  +
mltutor_function_switch(0);
 
 
  +
test_size = size(x);
% alternative 'n' means - not exact
 
  +
Der Aufruf <tt>mltutor_function_switch(1);</tt> teilt der Testroutine
%MLTutor_ERROR_REQUEST.message = 'time vector';
 
  +
mit, dass jetzt wirklich die Funktion des Studenten bearbeitet wird.
%MLTutor_ERROR_REQUEST.type = 'n';
 
  +
Mit <tt>mltutor_function_switch(0);</tt> schaltet man das wieder aus.
  +
Wenn man das nicht macht, läuft das gesamte after-Skript in diesem
  +
Modus, was normalerweise keine Problem ist, da es nur Auswirkungen auf
  +
MLTutor_DISPLAY_COUNT % Anzahl vergessener Strichpunkte
  +
MLTutor_CPU_TIME % cpu-Time während der Abarbeitung
  +
Verwendet man das Feature nicht, wird das gesamte after-Skript in
  +
diesem Modus betrieben. Dann ist es eben noch wichtiger, dass man
  +
ordnungsgemäß Strichpunkte am Ende der Zeile macht!
   
  +
=== CPU Time ===
% ml_test1_check.m
 
  +
Die CPU Time, die von jenem Teil des Programms verbraucht wird, die
 
  +
vom Studenten stammt, findet sich in
MLTutor_ERROR_CORRECT
 
  +
MLTutor_CPU_TIME % cpu-Time während der Abarbeitung
  +
(siehe dazu auch [[#Verbesserung]]).
   
  +
=== Anzahl der vergessenen Strichpunkte ===
% ml_test1_after.m
 
  +
Gute Skripts und Funktionen sollten keinen Output am Schirm
 
  +
produzieren, der nur durch Weglassen des Strichpunktes am Ende einer
func()
 
  +
Anweisung entsteht. Das sollte man auch in den before- und
  +
after-Skripts beherzigen. Wenn man in einem Test zählen will, wie oft
  +
der Student den Strichpunkt vergessen hat, dan kann man folgende
  +
Variable verwenden
  +
MLTutor_DISPLAY_COUNT
  +
  +
== Überprüfung von Textausgaben ==
  +
  +
  +
Es ist mögliche Textausgaben mit Hilfe von
  +
[http://itp.tugraz.at/matlab/techdoc/matlab_prog/ch_com15.html Regular Expressions]
  +
zu testen.
  +
Dabei wird im before- oder after-Skript die Zelle
  +
MLTutor_<type>_REGEXP.message = {}
  +
gesetzt. <tt> <type> </tt> wird dabei je nach der zu überprüfenden
  +
Ausgabe (ERROR, DISP, ...) ersetzt. Die Elemente der Zelle sind
  +
wieder Zellen mit Strings von regulären Ausdrücken.
  +
Dabei prüft die erste Zelle die erste Zeile die vom entsprechenden
  +
Befehl (z.B. disp) ausgegeben wird, die zweite die zweite Zeile usw.
  +
  +
Zur Überprüfung stehen dann die Variablen
  +
MLTutor_<type>_REGEXP_CORRECT
  +
MLTutor_<type>_REGEXP_ALL_CORRECT
  +
zur Verfügung. Diese Variablen sind Vektoren vom Typ logical. An den
  +
Stellen an denen die Überprüfung korrekt war enthalten sie 1 ansonsten 0.
  +
  +
Der endgültige Test findet wieder durch Vergleich dieser Variablen
  +
statt. Es ist also unbedingt darauf zu achten, dass diese Tests in
  +
Bezug auf das Referenzskript überall eine 1 liefern.
  +
  +
Sind in den zu überprüfenden Textmeldungen in Strings umgewandelte
  +
Variablen(werte) enthalten, so sollte die REGEXP.request im
  +
after-Skript definiert werden, und die zu überprüfende Variable zur
  +
Definition des Ausdruckes verwenden. Siehe Beispiele bei [[#Regular Expressions bei disp]]
   
  +
Aus "historischen" Gründen existiert auch noch eine zweite Art der
Das Gleiche funktioniert nicht nur für message sondern auch für identifier:
 
  +
Testmöglichkeit. Dabei wird ein gesamter String vorgegeben. Es kann
MLTutor_ERROR_REQUEST.message
 
  +
dann gewählt werden, ob dieser String die gesamte (exakte)
MLTutor_ERROR_REQUEST.type
 
  +
Fehlermitteilung darstellt, oder ob dieser String lediglich in der
mit der Antwort in
 
  +
Fehlermitteilung enthalten sein muss. Tests dieser Art sollten nicht
MLTutor_ERRORID_CORRECT
 
  +
mehr verwendet werden. Der Überprüfung mit Regular Expressions ist wesentlich flexibler und
  +
verhindert, dass Tests aufgrund von unwichtigen Tippfehlern (z.B.
  +
unterschiedliche Anzahl an Leerräumen) fehlschlagen.
   
 
==== Regular Expressions bei Fehlern ====
 
==== Regular Expressions bei Fehlern ====
  +
Hier stehen die Variablen:
  +
MLTutor_ERROR_REGEXP.message
   
Darüberhinaus gibt es auch noch eine bessere Variante, die sich bei der Überprüfung der sogenannten "Regular Expressions" bedient. Man hat im simplen Fall die Möglihkeit zu schreiben
 
MLTutor_ERROR_REGEXP.message = 'time vector is undefined';
 
und die Variablen
 
 
MLTutor_ERROR_REGEXP_CORRECT
 
MLTutor_ERROR_REGEXP_CORRECT
 
MLTutor_ERROR_REGEXP_ALL_CORRECT
 
MLTutor_ERROR_REGEXP_ALL_CORRECT
  +
zur Verfügung.
wären dann entweder 1 (richtig) oder 0 (falsch). Ein Unterschied zur ersten Methode besteht aber, da man jetzt die Antwort 1 bekommt, wenn die Zeichenfolge 'time vector is undefined' genau so in der Fehlermitteilung vor kommt, auch wenn vorher oder nachher etwas anderes steht (eigentlich wie <tt>type 'n'</tt>). Um den <tt>type 'e'</tt> zu simulieren, müsste man eigentlich
 
MLTutor_ERROR_REGEXP.message = '^time vector is undefined$';
 
schreiben. Das Zeichen <tt>^</tt> steht für Anfang und <tt>$</tt> steht für Ende.
 
   
  +
Einige Möglichkeiten die Fehlermitteilung
Details zu [http://itp.tugraz.at/matlab/techdoc/matlab_prog/ch_com15.html Regular Expressions] in Matlab geben weitere Hinweise.
 
  +
Time vector is undefined
Einige Möglichkeiten wären
 
  +
zu testen wären:
MLTutor_ERROR_REGEXP.message = '^[T|t]ime'; % Time oder time am Anfang
 
MLTutor_ERROR_REGEXP.message = {'^[T|t]ime'}; % gleich wie vorige Zeile
+
MLTutor_ERROR_REGEXP.message = '^[Tt]ime'; % Time oder time am Anfang
  +
MLTutor_ERROR_REGEXP.message = {'^[Tt]ime'}; % gleich wie vorige Zeile
 
MLTutor_ERROR_REGEXP.message = {'time', 'vector', 'undefined'}; % beliebige Reihenfolge der drei Worte
 
MLTutor_ERROR_REGEXP.message = {'time', 'vector', 'undefined'}; % beliebige Reihenfolge der drei Worte
 
MLTutor_ERROR_REGEXP.message = {'time.+vector.+undefined'}; % die drei Worte mit zumindest einem Zeichen dazwischen
 
MLTutor_ERROR_REGEXP.message = {'time.+vector.+undefined'}; % die drei Worte mit zumindest einem Zeichen dazwischen
Zeile 152: Zeile 300:
 
MLTutor_ERRORID_REGEXP_CORRECT
 
MLTutor_ERRORID_REGEXP_CORRECT
 
MLTutor_ERRORID_REGEXP_ALL_CORRECT
 
MLTutor_ERRORID_REGEXP_ALL_CORRECT
 
=== Überprüfung von Warnungen ===
 
Funktioniert "gleich" wie bei Fehlermitteilungen. <br>
 
Request:<br>
 
MLTutor_WARNING_REQUEST.message
 
MLTutor_WARNING_REQUEST.type
 
Überprüfung:<br>
 
MLTutor_WARNING_CORRECT
 
Interessiert man sich (auch) für den Idetifier der Warnung, dann kann man das gleiche mit
 
MLTutor_WARNING_REQUEST.identifier
 
MLTutor_WARNING_REQUEST.type
 
mit der Antwort in
 
MLTutor_WARNINGID_CORRECT
 
machen.
 
   
 
==== Regular Expressions bei Warnungen ====
 
==== Regular Expressions bei Warnungen ====
  +
Die Definitions-Variablen sind jetzt
 
Wie bei den Fehlern gibt es auch noch eine bessere Variante, die sich bei der Überprüfung der sogenannten "Regular Expressions" bedient (siehe [[#Regular Expressions bei Fehlern]], [http://itp.tugraz.at/matlab/techdoc/matlab_prog/ch_com15.html Regular Expressions]).
 
 
Die Definitions-Variablen sind jetzt einfach
 
 
MLTutor_WARNING_REGEXP.message
 
MLTutor_WARNING_REGEXP.message
 
MLTutor_WARNING_REGEXP.identifier
 
MLTutor_WARNING_REGEXP.identifier
Zeile 177: Zeile 308:
 
MLTutor_WARNING_REGEXP_CORRECT
 
MLTutor_WARNING_REGEXP_CORRECT
 
MLTutor_WARNING_REGEXP_ALL_CORRECT
 
MLTutor_WARNING_REGEXP_ALL_CORRECT
  +
 
MLTutor_WARNINGID_REGEXP_CORRECT
 
MLTutor_WARNINGID_REGEXP_CORRECT
 
MLTutor_WARNINGID_REGEXP_ALL_CORRECT
 
MLTutor_WARNINGID_REGEXP_ALL_CORRECT
 
=== Überprüfung von Ausgaben von disp ===
 
Funktioniert ebenfalls wie bei Fehlermitteilungen. <br>
 
MLTutor_DISP_REQUEST.message
 
MLTutor_DISP_REQUEST.type
 
Überprüfung:<br>
 
MLTutor_DISP_CORRECT
 
 
Beispiel:<br>
 
a = pi;
 
b = [1:4];
 
 
disp(['Variable a: ',num2str(a)])
 
disp(['Variable b: ',mat2str(b)])
 
disp(a)
 
disp(b)
 
 
MLTutor_DISP_REQUEST.message = { ...
 
['Variable a: ',num2str(a)], ...
 
['Variable b: ',mat2str(b)], ...
 
a, ...
 
b ...
 
};
 
MLTutor_DISP_REQUEST.type = {'e','e','e','e'};
 
 
Die Anweisung für <tt>MLTutor_DISP_REQUEST.message</tt> und <tt>MLTutor_DISP_REQUEST.type</tt> können in <tt>test_before</tt> oder <tt>test_after</tt> stehen. Das Problem besteht aber darin, dass man u.U. die Variablennamen nicht kennt. Wenn man z.B. den Studenten nicht anweist, dass der Variablenname <tt>a</tt> ist, dann kann man im <tt>test_after</tt> nicht <tt>num2str(a)</tt> verwenden. Ausserdem geht es bei Funktionen auch nicht, da alle internen Variablen der Funktion im <tt>test_after</tt> nicht sichtbar sind.
 
 
Insgesamt empfiehlt es sich immer Strings wie <tt>['a = ',num2str(a)]</tt> zu verwenden und nicht einfach <tt>a</tt>. Bei Zahlen funktioniert, die nichtexakte Überprüfung nämlich nicht.
 
 
Was immer möglich ist, ist <tt>MLTutor_DISP_RESULTS</tt>. Diese Größe enthält, das Ergebnis der Ausgabe, wobei noch keine Überprüfung durchgeführt wird. Die Überprüfung liegt dann wie bei allen anderen Variablen in den Händen von David. Damit müssen die Strings aber exakt übereinstimmen. Eine nichtexakte Überprüfung ist da nicht möglich.
 
   
 
==== Regular Expressions bei disp ====
 
==== Regular Expressions bei disp ====
  +
Hier steht im Gegensatz zu den vorherigen Beispielen auch die Variable
  +
MLTutor_DISP_REGEXP_REALALL_CORRECT
  +
zum Testen zur Verfügung. Ihre Funktion geht aus dem folgenden
  +
Beispiel hervor.
   
  +
Hier ist vorausgesetzt, dass man die Variablen <tt>a</tt> und <tt>b</tt> im after-Skript kennt:
Auch bei disp (oder fprintf) kann man jetzt [http://itp.tugraz.at/matlab/techdoc/matlab_prog/ch_com15.html Regular Expressions] (siehe auch [[#Regular Expressions bei Fehlern]]) verwenden.
 
 
Auch hier ist vorausgesetzt, dass man die Variablen <tt>a</tt> und <tt>b</tt> im after-Skript kennt:
 
 
astr = num2str(a);
 
astr = num2str(a);
 
astr = strrep(astr(1:5),'.','\.');
 
astr = strrep(astr(1:5),'.','\.');
Zeile 221: Zeile 325:
 
bstr=strrep(bstr,']','\]');
 
bstr=strrep(bstr,']','\]');
 
MLTutor_DISP_REGEXP = { ...
 
MLTutor_DISP_REGEXP = { ...
{'Variable\s+a\s*[:|-]',astr}, ...
+
{'Variable\s+a\s*[:-]',astr}, ...
 
{'Variable','b:',bstr}, ...
 
{'Variable','b:',bstr}, ...
 
{astr}, ...
 
{astr}, ...
Zeile 231: Zeile 335:
 
dem Buchstaben a
 
dem Buchstaben a
 
beliebig vielen Whitespace-Characters (auch Null) \s*
 
beliebig vielen Whitespace-Characters (auch Null) \s*
einem Doppelpunkt oder einem Bindestrich [:|-]
+
einem Doppelpunkt oder einem Bindestrich [:-]
 
und dann, ob das Ergebnis von a vorkommt, und zwar
 
und dann, ob das Ergebnis von a vorkommt, und zwar
 
die ersten fünf Zeichen, wobei . durch \. ersetzt wurde
 
die ersten fünf Zeichen, wobei . durch \. ersetzt wurde
Zeile 254: Zeile 358:
 
<tt>MLTutor_DISP_REGEXP_REALALL_CORRECT</tt> steht.
 
<tt>MLTutor_DISP_REGEXP_REALALL_CORRECT</tt> steht.
   
==== Zählen von disp-Aufrufen ====
+
==== Input - Fragen ====
  +
Die Fragen, die mit dem Befehl <tt>input</tt> gestellt werden, können auch überprüft werden. Beim Beispiel
Der Zähler für die Aufrufe von disp ist
 
  +
x = input('Bitte geben Sie x ein: ');
MLTutor_DISP_COUNT
 
  +
könnte man angeben
Damit kann man feststellen, wie oft die Funktion disp oder fprintf (mit fid 1 oder 2) aufgerufen wurde.
 
  +
MLTutor_INPUT_REGEXP = { ...
  +
{'[Bb][Ii][Tt][Tt][Ee]','geben','x'} ...
  +
};
  +
was folgendes bedeutet (in beliebiger Reihenfolge):
  +
das Wort Bitte in beliebiger Schreibweise BItte, BITTE, ...
  +
das Wort geben
  +
das Zeichen x
  +
Es wäre noch möglich
  +
[Tt][Tt] -> [Tt]{2} zu ersetzen.
  +
Im Allgemeinen bedeutet die
  +
Konstruktionen <tt> {n,m} </tt> das der vorhergehende Ausdruck
  +
mindestens n-, und maximal m-Mal auftreten soll.
   
=== Haben wir eine Möglichkeit Plots zu vergleichen? ===
+
Eine andere Möglichkeit
  +
MLTutor_INPUT_REGEXP = { ...
<span style="color:green">JA; Es funktioniert ähnlich wie das Testen von Fehlermeldungen. Im before-script wird mit Hilfe von MLTutor_GRAPHICS_REQUEST festgelegt, welche Eigenschaften des Plots überprüft werden sollen. Darin kann jedes Element das im [http://itp.tugraz.at/matlab/techdoc/infotool/hgprop/doc_frame.html Handle Graphics Property Browser] zu finden ist überprüft werden. Die Numerierung (siehe Beispiel) in der Anforderung der Ergebnisse ergibt sich aus der Reihenfolge in der die Objekte im Plot erzeugt werden. Somit muss diese in der Angabe zu einem Projekt fix vorgegeben sein. Beispiele: </span>
 
  +
{'\<Bitte\>.+\<geben\>.+y.*:'} ...
* <span style="color:green"> siehe unten </span>
 
  +
};
* <span style="color:green"> kernbich.testbeispiele.sgraph* </span>
 
  +
Was in richtiger Reihenfolge bedeutet:
  +
das Wort Bitte
  +
zumindest ein beliebiges Zeichen dazwischen .+
  +
das Wort bitte
  +
zumindest ein beliebiges Zeichen dazwischen .+
  +
der Buchstabe y
  +
beliebig viele Zeichen .* (auch null)
  +
der Doppelpunkt
   
  +
Wie bei [[#Regular Expressions bei disp |disp]] stehen die Ergebnisse dann in
<pre>
 
  +
MLTutor_INPUT_REGEXP_CORRECT
% main.m
 
  +
MLTutor_INPUT_REGEXP_ALL_CORRECT
  +
MLTutor_INPUT_REGEXP_REALALL_CORRECT
  +
wobei <tt>MLTutor_INPUT_REGEXP_ALL_CORRECT</tt> für jedes input 0 oder 1 enthält und das Gesamtergebnis in
  +
<tt>MLTutor_INPUT_REGEXP_REALALL_CORRECT</tt> steht.
   
  +
==== Überprüfung des Hilfetextes ====
x = -2:0.1:3;
 
  +
Ebenfalls mit
  +
[http://itp.tugraz.at/matlab/techdoc/matlab_prog/ch_com15.html Regular Expressions].
  +
Als Variable stehen zur Verfügung für die Definition
  +
MLTutor_HELP_REGEXP = {'regexp1','regexp2','regexp3','usw'};
  +
bzw. die Überprüfung
  +
MLTutor_HELP_REGEXP_CORRECT
  +
MLTutor_HELP_REGEXP_ALL_CORRECT
  +
Näheres zum Thema unter:
  +
[[#Regular Expressions bei Fehlern]], [[#Regular Expressions bei Warnungen]],
  +
[[#Regular Expressions bei disp]], [[#Regular Expressions bei input]]
   
  +
== Überprüfung von Plots ==
g1 = normpdf(x,0,1);
 
  +
Funktioniert ähnlich wie das Testen von Textausgaben. Im
g2 = normpdf(x,1,0.5);
 
  +
before-script wird mit Hilfe von
  +
MLTutor_GRAPHICS_REQUEST
  +
festgelegt, welche Eigenschaften des Plots überprüft werden sollen. Darin kann
  +
jedes Element das im
  +
[http://itp.tugraz.at/matlab/techdoc/infotool/hgprop/doc_frame.html
  +
Handle Graphics Property Browser] zu finden ist überprüft werden. Die
  +
Numerierung (siehe Beispiel) in der Anforderung der Ergebnisse ergibt
  +
sich aus der Reihenfolge in der die Objekte im Plot erzeugt werden.
  +
Somit muss diese in der Angabe zu einem Projekt fix vorgegeben sein.
   
  +
Beispiel:
plot(x,g1,x,g2,'r'); %line1 & line2
 
  +
% main.m
  +
  +
x = -2:0.1:3;
  +
  +
g1 = normpdf(x,0,1);
  +
g2 = normpdf(x,1,0.5);
  +
  +
plot(x,g1,x,g2,'r'); %line1 & line2
  +
  +
hold on
  +
plot(x,g1+g2,'k'); %line 3
  +
hold off
  +
  +
line(x,g1-g2,'color','green'); %draw line in current axes without the use of hold on .... hold off
  +
  +
xlabel('x');
  +
ylabel('y');
  +
title('Just an example')
   
  +
% end main.m
hold on
 
plot(x,g1+g2,'k'); %line 3
 
hold off
 
   
  +
% test_before.m
line(x,g1-g2,'color','green'); %draw line in current axes without the use of hold on .... hold off
 
  +
  +
% check properties of axes
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.request = {'xlabel','ylabel','title'};
  +
  +
% check data of line 1 (g1)
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_1.request = {'xdata','ydata'};
  +
  +
% check data and color of line 2 (g2)
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_2.request = {'xdata','ydata','color'};
  +
  +
% check data and color of line 3 (g1 + g2)
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_3.request = {'xdata','ydata','color'};
  +
  +
% check data and color of line 4 (g1 - g2)
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_4.request = {'xdata','ydata','color'};
   
  +
Um beim Test der Variablenwerte keinen Plot angezeigt zu bekommen ist
xlabel('x');
 
  +
im folgendes ins before script einzutragen.
ylabel('y');
 
title('Just an example')
 
   
% end main.m
+
% test_before.m
  +
MLTutor_FIGURE_HIDE = 1;
</pre>
 
   
  +
Beispiel für Legende:
<pre>
 
% ml_test1_before.m
 
   
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_2.text_1.request = {{'string',{'\<Gauss\>|\<gauss\>|\<GAUSS\>'}}};
% check properties of axes
 
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.request = {'xlabel','ylabel','title'};
 
   
  +
Als Testvariable ist
% check data of line 1 (g1)
 
  +
MLTutor_GRAPHICS_RESULTS
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_1.request = {'xdata','ydata'};
 
  +
einzutragen.
   
  +
=== Regular Expressions ===
% check data and color of line 2 (g2)
 
  +
Auch hier kann man nun
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_2.request = {'xdata','ydata','color'};
 
  +
[http://itp.tugraz.at/matlab/techdoc/matlab_prog/ch_com15.html Regular Expressions]
  +
verwenden, und zwar geht das bei allen Größen die
  +
Zeichenketten als Resultat haben. Obiges Beispiel könnte also so
  +
modifiziert werden:
   
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.request = { ...
% check data and color of line 3 (g1 + g2)
 
  +
{ 'xlabel', '^x$' }, ...
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_3.request = {'xdata','ydata','color'};
 
  +
{ 'ylabel', '^y$' }, ...
  +
{ 'title', {'[Jj]ust', '[Ee]xample'} } ...
  +
};
  +
Die Beispiele funktionieren wie bei [[#Regular Expressions bei disp |disp]],
  +
[[#Regular Expressions bei Fehlern |Fehlern]], [[#Regular Expressions bei Warnungen |Warnungen]]
  +
und [[#Input - Fragen |input]].
   
  +
Im Unterschied zur Verwendung ohne
% check data and color of line 4 (g1 - g2)
 
  +
[http://itp.tugraz.at/matlab/techdoc/matlab_prog/ch_com15.html Regular Expressions]
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_4.request = {'xdata','ydata','color'};
 
  +
steht dann im Ergebnis z.B. bei <tt>xlabel</tt> nicht
</pre>
 
  +
<tt>x</tt> sondern 1 (richtig) oder 0 (falsch). Die Outputvariable ist
  +
aber die selbe Struktur:
   
  +
MLTutor_GRAPHICS_RESULTS
<pre>
 
% ml_test1_check.m
 
   
  +
=== Eigenheiten bei <nowiki>errorbar</nowiki> ===
MLTutor_GRAPHICS_RESULTS
 
  +
Bei <nowiki>errorbar</nowiki> und bei anderen Befehlen, welche die
</pre>
 
  +
neuen Gruppierungsfeatures von Matlab verwenden, gibt es das Problem,
<pre>
 
  +
dass die Reihenfolge der Linien nicht so ist wie erwartet.
% ml_test1_after.m
 
% nothing to do
 
</pre>
 
   
  +
x = linspace(0,pi,100)
==== Eigenheiten bei <nowiki>errorbar</nowiki> ====
 
  +
y = sin(x);
Bei <nowiki>errorbar</nowiki> und bei anderen Befehlen, welche die neuen Gruppierungsfeatures von Matlab verwenden, gibt es das Problem, dass die Reihenfolge der Linien nicht so ist wie erwartet.
 
  +
xd = x(1:5:end);
<pre>
 
  +
yd = sin(xd);
x = linspace(0,pi,100)
 
y = sin(x);
+
y1 = cos(x);
xd = x(1:5:end);
+
yd1 = cos(xd);
  +
yd = sin(xd);
 
y1 = cos(x);
+
sig = 0.2;
yd1 = cos(xd);
+
rd = rand(size(xd))*sig
  +
  +
figure
  +
plot(x,y,'r-')
  +
  +
hold on
  +
errorbar(xd,yd,rd,'ob')
  +
plot(x,y1,'k-')
  +
errorbar(xd,yd1,rd,'og')
  +
hold off
   
  +
legend({'Fit1','Data1','Fit2','Data2'},'Location','sw')
sig = 0.2;
 
rd = rand(size(xd))*sig
 
   
  +
Normalerweise würde man erwarten, dass
figure
 
plot(x,y,'r-')
 
   
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_1.request = {'xdata','ydata','color'}; % sin(x)
hold on
 
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_2.request = {'xdata','ydata','color'}; % sin(xd)
errorbar(xd,yd,rd,'ob')
 
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_3.request = {'xdata','ydata','color'}; % Fehler zu sin(xd)
plot(x,y1,'k-')
 
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_4.request = {'xdata','ydata','color'}; % cos(x)
errorbar(xd,yd1,rd,'og')
 
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_5.request = {'xdata','ydata','color'}; % cos(xd)
hold off
 
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_6.request = {'xdata','ydata','color'}; % Fehler zu cos(xd)
 
legend({'Fit1','Data1','Fit2','Data2'},'Location','sw')
 
</pre>
 
Normalerweise würde man erwarten, dass
 
<pre>
 
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_1.request = {'xdata','ydata','color'}; % sin(x)
 
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_2.request = {'xdata','ydata','color'}; % sin(xd)
 
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_3.request = {'xdata','ydata','color'}; % Fehler zu sin(xd)
 
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_4.request = {'xdata','ydata','color'}; % cos(x)
 
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_5.request = {'xdata','ydata','color'}; % cos(xd)
 
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_6.request = {'xdata','ydata','color'}; % Fehler zu cos(xd)
 
</pre>
 
 
liefert. In der Realität ist die Reihenfolge aber
 
liefert. In der Realität ist die Reihenfolge aber
<pre>
 
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_1.request = {'xdata','ydata','color'}; % Fehler zu sin(xd) - Erste hggroup
 
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_2.request = {'xdata','ydata','color'}; % sin(xd) - Erste hggroup
 
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_3.request = {'xdata','ydata','color'}; % Fehler zu cos(xd) - Zweite hggroup
 
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_4.request = {'xdata','ydata','color'}; % cos(xd) - Zweite hggroup
 
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_5.request = {'xdata','ydata','color'}; % sin(x) - Erster Plotbefehl
 
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_6.request = {'xdata','ydata','color'}; % cos(x) - Zeiter Plotbefehl
 
</pre>
 
Seid also bitte vorsichtig, welche Linien ihr überprüft. Ich habe keine Möglichkeit, dass zu korrigieren, jedenfalls nicht mit vertretbarem Aufwand.
 
   
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_1.request = {'xdata','ydata','color'}; % Fehler zu sin(xd) - Erste hggroup
==== Legende ====
 
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_2.request = {'xdata','ydata','color'}; % sin(xd) - Erste hggroup
Beim Befehl [http://itp.tugraz.at/matlab/techdoc/ref/legend.html legend] gibt es eine neue Syntax:
 
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_3.request = {'xdata','ydata','color'}; % Fehler zu cos(xd) - Zweite hggroup
<pre>
 
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_4.request = {'xdata','ydata','color'}; % cos(xd) - Zweite hggroup
legend({'Fit1','Data1','Fit2','Data2'},'Location','nw')
 
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_5.request = {'xdata','ydata','color'}; % sin(x) - Erster Plotbefehl
</pre>
 
  +
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_6.request = {'xdata','ydata','color'}; % cos(x) - Zeiter Plotbefehl
Es ist gut wenn man die Liste der Beschriftung jetzt in einer Zelle {} schreibt und dann den Ort in der neuen Syntax.
 
Siehe dazu [http://itp.tugraz.at/matlab/techdoc/ref/legend.html legend].
 
   
  +
Seid also bitte vorsichtig, welche Linien ihr überprüft. Ich habe
Will man auch Fehler in der Legende ehen, dann muss man obiges Beispiel so ändern:
 
  +
keine Möglichkeit, dass zu korrigieren, jedenfalls nicht mit
<pre>
 
  +
vertretbarem Aufwand.
figure
 
lh1 = plot(x,y,'r-')
 
   
  +
=== Legende ===
hold on
 
  +
Beim Befehl [http://itp.tugraz.at/matlab/techdoc/ref/legend.html legend] gibt es eine neue Syntax:
ebh1 = errorbar(xd,yd,rd,'ob') % hggroup
 
ebh1_ch = get(ebh1,'children');
 
lh2 = plot(x,y1,'k-')
 
ebh2 = errorbar(xd,yd1,rd,'og') % hggroup
 
ebh2_ch = get(ebh2,'children');
 
hold off
 
   
legend([lh1;ebh1_ch;lh2;ebh2_ch],{'Fit1','Data1','Fehler1','Fit2','Data2','Fehler2'},'Location','sw')
+
legend({'Fit1','Data1','Fit2','Data2'},'Location','nw')
</pre>
 
Dazu muss man die Handles auf alle gewünschten Graphikobjekte verwenden und daraus einen Vektor formen. Die Handles ebh1 und ebh2 sind Handles auf hggroup und man muss daher zuerst auch noch ihre Kinder (children) abfragen.
 
   
  +
Es ist gut wenn man die Liste der Beschriftung jetzt in einer Zelle {}
==== Polarplot ====
 
  +
schreibt und dann den Ort in der neuen Syntax. Siehe dazu
Der Befehl [http://itp.tugraz.at/matlab/techdoc/ref/polar.html polar]
 
  +
[http://itp.tugraz.at/matlab/techdoc/ref/legend.html legend].
funktioniert wie erwartet. De extra Linien, die den Polarplot schmücken (Kreise, radiale Linien) sind alle versteckt (hidden) und machen daher keine Probleme.
 
Die Abfrage nach den Linien geht daher wunderbar und es gibt auch kein Problem mir der Reihenfolge.
 
   
  +
Will man auch Fehler in der Legende sehen, dann muss man obiges Beispiel so ändern:
==== Figure ====
 
Während der Tests werden für [http://itp.tugraz.at/matlab/techdoc/ref/figure.html figure] noninteger-Handles verwendet. Daher sieht man, auch wenn man es z.B. mit figure(1) versucht keine Zeichnung mit dem Handle 1 sondern mit einem anderen Handle. Daher funktioniert auf keinen Fall:
 
<pre>
 
figure(1);
 
set(1,'Color','red')
 
</pre>
 
Will man so etwas, muss man schreiben
 
<pre>
 
fh=figure;
 
set(fh,'Color','red')
 
</pre>
 
Ein anfänglicher Fehler sollte mit einem Update behoben sein.
 
   
  +
figure
=== Wie wird dem Benutzer der Testaufruf der Funktion mitgeteilt? ===
 
  +
lh1 = plot(x,y,'r-')
<span style="color:green"> Alles was in einem Script von %### eingeschlossen ist, ist dem Benutzer zugänglich.</span>
 
  +
  +
hold on
  +
ebh1 = errorbar(xd,yd,rd,'ob') % hggroup
  +
ebh1_ch = get(ebh1,'children');
  +
lh2 = plot(x,y1,'k-')
  +
ebh2 = errorbar(xd,yd1,rd,'og') % hggroup
  +
ebh2_ch = get(ebh2,'children');
  +
hold off
   
  +
legend([lh1;ebh1_ch;lh2;ebh2_ch],{'Fit1','Data1','Fehler1','Fit2','Data2','Fehler2'},'Location','sw')
<pre>
 
%ml_test1_after.m
 
%###
 
t = linspace(0,10,100)
 
[x,y] = foo(t,[],4)
 
%###
 
   
  +
Dazu muss man die Handles auf alle gewünschten Graphikobjekte
test_size = size(x);
 
  +
verwenden und daraus einen Vektor formen. Die Handles ebh1 und ebh2
</pre>
 
  +
sind Handles auf hggroup und man muss daher zuerst auch noch ihre
  +
Kinder (children) abfragen.
   
  +
==== ACHTUNG ====
<span style="color:green"> Hier sieht der Benutzer also, welche Werte <tt> t </tt> zugewiesen werden, und wie die Funktion <tt> foo </tt> aufgerufen wird. Er sieht allerdings nicht, dass anschließend auch ncoh eine Variable <tt> test_size </tt> erzeugt wird.</span>
 
  +
Werden Legenden verwendet so stellen diese Achsen dar. Dies muss beim Testen von Daten in z.B. einem subplot berücksichtigt werden.\\
  +
Hat man zum Beispiel:
   
  +
subplot(2,1,1)
== Beispiel2 ==
 
  +
plot(1,2,'o')
Projektverzeichnissname:
 
  +
legend('testlegende')
<b>andrej.sommer2005.aufgabe2a</b><br>
 
  +
Weis nicht ob es so gedacht war, aber jedenfalls die erste aufgabe mit Testscript:
 
  +
subplot(2,1,2)
  +
plot(3,4,'o')
  +
legend('testlegende2')
   
  +
Hier '''müssen''' zum Testen der xdata und ydata die Linien der Achsen 1 und 3 abgefragt werden!
Nur eine Anmerkung: Das Überprüfen des Ergebnisses vom Studenten übernimmt das MLTutor-Programm, aber im Prinzip läuft es genau so ab, wie du es geschrieben hast. Wenn du selber die Überprüfung übernehmen willst, dann kannst du natürlich gerne deine eigene Routine schreiben, aber im ml_test1_check.m würde bei diesem Test nur
 
V2,F2,R2,r2
 
drinnenstehen, damit das Programm weiß, welche Variablen überprüft werden sollten. Im XML-File, dass man dazu erstellt, kann man dann definieren, mit welcher Genauigkeit der Check abläuft und ähnliches.
 
--[[User:Camhy|Camhy]] 15:39, 3 Nov 2005 (CET)
 
   
  +
=== Polarplot ===
Ich bin total dagegen, dass jemand eigene Überprüfungsroutinen schreibt. Das gehört total zum mlTutor und hat überhaupt nichts mit den Beispielen selbst zu tun. Bitte unbedingt nur die Syntax von David verwenden. Wenn irgendetaws für den gewünschten Test nicht ausreicht, dann unbedingt als Anregung an David und mich leiten. Dann müssen wir uns auf Seite des mlTutor darum kümmern.
 
  +
Der Befehl [http://itp.tugraz.at/matlab/techdoc/ref/polar.html polar]
--[[User:Winny|Winny]] 16:40, 8 Nov 2005 (CET)
 
  +
funktioniert wie erwartet.
  +
De extra Linien, die den Polarplot schmücken (Kreise, radiale Linien)
  +
sind alle versteckt (hidden) und machen daher keine Probleme. Die
  +
Abfrage nach den Linien geht daher wunderbar und es gibt auch kein
  +
Problem mir der Reihenfolge.
   
  +
=== Figure ===
Die Variablen würden dann beim Scriptausführen als Text ausgegeben werden um vom ml_tutor weiterverarbeitet zu werden? Habe das Beispiel jatzt umgeschrieben: --Golubkov 13:03, 10 November 2005 (CET)
 
  +
Während der Tests werden für
  +
[http://itp.tugraz.at/matlab/techdoc/ref/figure.html figure]
  +
noninteger-Handles verwendet. Daher sieht man, auch wenn man es z.B.
  +
mit figure(1) versucht keine Zeichnung mit dem Handle 1 sondern mit
  +
einem anderen Handle. Daher funktioniert auf keinen Fall:
   
  +
figure(1);
Nein, der MLTutor muss nur wissen, welche Variablen überprüft werden sollen. Dh. es soll wirklich wie oben nur z.B.
 
  +
set(1,'Color','red')
V2,F2,R2,r2
 
drinnenstehen, od. ähnliches. z.B. würde ich in diesem Fall aus dieser for Schleife mit typ einfach mehrere Tests machen, da ja unterschiedliche Eigenschaften der vom Studenten geschriebenen Funktion überprüft werden. Die StudentIn soll ja wissen, bei welchem Typ es funktioniert und bei welchem nicht. Diese Syntax wurde nur deswegen gleich gewählt wie eine Ausgabe, um das Testen ohne fertigen MLTutor leichter zu machen. In den Beispielen camhy.testbeispiele.* ist es eh vorgeführt. Siehe auch [[Erstellen eines MLTutor Beispiels mit Eclipse]]. Von der technischen Seite läuft es dann so ab, dass der MLTutor aus dieser Datei herausliest, welche Variablen überprüft werden sollen, dann die Variablen als XML aus Matlab ausgibt, dieses XML von der MLTutor Oberfläche geparst wird und mit dem Ergebnis der StudentIn verglichen wird. Mit einer Ausgabe als Text wäre das Parsen komplexerer Datentypen wie Structures od. Cells, die aus verschachtelten Matrizen bestehen nicht möglich. --[[User:Camhy|Camhy]] 13:19, 11 November 2005 (CET)
 
   
  +
Will man so etwas, muss man schreiben
<br>
 
=== main.m ===
 
<pre>
 
function [V,F,R,r]=main(typ,a)
 
   
  +
fh=figure;
switch lower(typ(1))
 
  +
set(fh,'Color','red')
case 't'
 
V=a^3/12*sqrt(2);
 
F=a^2*sqrt(3);
 
R=a/4*sqrt(6);
 
r=a/12*sqrt(6);
 
case 'w'
 
V=a^3;
 
F=6*a^2;
 
R=a/2*sqrt(3);
 
r=a/2;
 
case 'o'
 
V=a^3/3*sqrt(2);
 
F=2*a^2*sqrt(3);
 
R=a/2*sqrt(2);
 
r=a/6*sqrt(6);
 
case 'd'
 
V=a^3/4*(15+7*sqrt(5));
 
F=3*a^2*sqrt(5*(5+2*sqrt(5)));
 
R=a/4*(1+sqrt(5))*sqrt(3);
 
r=a/4*sqrt((50+22*sqrt(5))/5);
 
case 'i'
 
V=5*a^3/12*(3+sqrt(5));
 
F=5*a^2*sqrt(3);
 
R=a/4*sqrt(2*(5+sqrt(5)));
 
r=a/2*sqrt((7+3*sqrt(5))/6);
 
end
 
</pre>
 
 
=== ml_test1_after.m ===
 
<pre>
 
typ = {'t','w','o','d','i'};
 
a=2;
 
[V,F,R,r] = regpol(typ(1),a);
 
</pre>
 
 
=== ml_test2_after.m ===
 
 
<pre>
 
ptyp = {'t','w','o','d','i'};
 
a=[1:10];
 
[V,F,R,r] = regpol(typ(2),a);
 
</pre>
 
 
=== ml_test3_after.m ===
 
 
<pre>
 
typ = {'t','w','o','d','i'};
 
a=4;
 
[V,F,R,r] = regpol(typ(3),a);
 
</pre>
 
 
=== ml_test4_after.m ===
 
 
<pre>
 
typ = {'t','w','o','d','i'};
 
a=2;
 
[V,F,R,r] = regpol(typ(4),a);
 
</pre>
 
 
=== ml_test5_after.m ===
 
 
<pre>
 
typ = {'T','w','O','d','I'};
 
a=3;
 
[V,F,R,r] = regpol(typ(5),a);
 
</pre>
 
 
Als Referenz müsste nun ml_tutor hier statt '''regpol''' auch mal '''main''' einsetzen. War das so gedacht?
 
 
Nein, du kannst die Funktion nennen, wie du willst, nur bei Skriptbeispielen muss das Hauptskript main.m heißen, damit das
 
Programm weiß, welches das Hauptskript ist. Generell muss der Student alle *.m Dateien schreiben, die nicht mit ml_ beginnen.
 
Siehe [[Erstellen eines MLTutor Beispiels mit Eclipse]]. Dort gibt es auch ein Funktionsbeispiel. camhy.testbeispiele.function1
 
In der MLTutor-Oberfläche gibt es mittlerweile auch einen Menüpunkt, der das richtige "Layout" eines Beispiels überprüft. Macht zwar noch ein paar Schwierigkeiten, aber diese sind mittlerweile behoben und stehen am Montag allen zur Verfügung. --[[User:Camhy|Camhy]] 16:39, 17 November 2005 (CET)
 
 
 
=== ml_test1_check.m ===
 
<pre>
 
V,F,R,r
 
</pre>
 
Mit ml_test1_check.m bis ml_test5_check.m sind identisch.
 
 
== Dokumentation ==
 
'''document.tex''':
 
Entsprechendes [http://itp.tugraz.at/~golubk_a/download/ml_tutor/document.pdf pdf] <br>
 
Statt \matref habe ich vorerst einfach matref stehen gelassen, bis sich eine Lösung für die definierten Kurzbefehle findet.
 
<pre>
 
\documentclass[12pt,a4paper]{article}
 
\usepackage[german,english]{babel}
 
\usepackage[latin1]{inputenc}
 
\usepackage{palatino}
 
\usepackage{verbatim}
 
\usepackage{typearea}
 
\usepackage{graphicx}
 
\usepackage[usenames]{color}
 
\usepackage{ifthen}
 
\usepackage{longtable}
 
\usepackage{makeidx}
 
\usepackage{float}
 
\usepackage{alltt}
 
\usepackage{amsmath,amssymb,amsthm}
 
\usepackage[colorlinks,breaklinks,backref,pdfstartview=FitH]{hyperref}
 
\setlength{\parindent}{0pt}
 
\setlength{\parskip}{6pt}
 
\usepackage[top=1mm,left=5mm,right=0mm,bottom=5mm]{geometry}
 
\pagestyle{empty}
 
\newcommand{\bsp}{\vspace{1em}\hrulefill\\[1em]\underline{Anschauungsbeispiel:}\\[0.5em]}
 
\newcommand{\zus}{\vspace{1em}\hrulefill\\[1em]\underline{Zusammenfassung:}\\[0.5em]}
 
\newcommand{\hw}{\vspace{1em}\underline{Hinweis:}\\[0.5em]}
 
\newcommand{\geg}{Gegeben: }
 
\newcommand{\ges}{Gesucht: }
 
\newcommand{\ii}{\textrm{i}}
 
\newcommand{\define}{\stackrel{\textrm{\tiny def}}{=}}
 
\newcommand{\field}[1]{\mathbb{#1}}
 
\newcommand{\R}{\field{R}}
 
\newcommand{\corrs}{\stackrel{\textrm{\tiny $\wedge$}}{=}}
 
 
\begin{document}
 
\section{Aufgabe}
 
Schreiben Sie eine \verb°regpol.m°, die folgende Aufgaben
 
erfüllt:
 
\begin{enumerate}
 
\item Für eine vorgegebene Kantenlänge $a$ soll das Volumen $V$, die
 
Oberfläche $F$, der Radius der umbeschriebenen Kugel $R$ und der Radius der
 
einbeschriebenen Kugel $r$ wahlweise für einen der 5 regulären konvexen
 
Polyeder (Tetraeder, Würfel, Oktaeder, Dodekaeder, Ikosaeder) berechnet werden.
 
\item Mit der String-Variablen {\tt typ} soll der Typ des regulären Polyeders
 
übergeben werden. Verwenden sie die Buchstaben 't','w','o','d' bzw. 'i' um einen der Polyeder auszuwählen.
 
\item Das Programm soll für einen Vektor von $a$-Werten funktionieren und
 
gleichlange Vektoren mit den Resultaten für $V$, $F$, $R$ und $r$
 
zurückgeben.
 
\item Im Programm soll zur Unterscheidung der Fälle die
 
matref{switch}{switch}-Konstruktion verwendet werden:
 
\begin{verbatim}
 
switch lower(typ(1))
 
case 't'
 
...
 
case 'w'
 
...
 
...
 
end
 
\end{verbatim}
 
Überlegen Sie, welche Zeichenkette man als {\tt typ} eingeben kann, was {\tt
 
typ(1)} bewirkt, und was
 
der Befehl matref{lower}{lower} dabei bewirkt.
 
\item
 
Stellen Sie auch den Unterschied zwischen folgenden Aufrufen der
 
Funktion fest und versuchen Sie das Verhalten zu verstehen.
 
\begin{verbatim}
 
regpol(typ,a)
 
V = regpol(typ,a)
 
[V,F] = regpol(typ,a)
 
[V,F,R] = regpol(typ,a)
 
[V,F,R,r] = regpol(typ,a)
 
\end{verbatim}
 
\end{enumerate}
 
 
 
\section{Mathematische Grundlagen}
 
\begin{enumerate}
 
\item Tetraeder
 
\begin{align*}
 
&V = \frac{a^3}{12} \sqrt{2}
 
&F = a^2 \sqrt{3} \\
 
&R = \frac{a}{4} \sqrt{6}
 
&r = \frac{a}{12} \sqrt{6}
 
\end{align*}
 
\item Würfel
 
\begin{align*}
 
&V = a^3
 
&F = 6a^2 \\
 
&R = \frac{a}{2} \sqrt{3}
 
&r = \frac{a}{2}
 
\end{align*}
 
\item Oktaeder
 
\begin{align*}
 
&V = \frac{a^3}{3} \sqrt{2}
 
&F = 2a^2 \sqrt{3} \\
 
&R = \frac{a}{2} \sqrt{2}
 
&r = \frac{a}{6} \sqrt{6}
 
\end{align*}
 
\item Dodekaeder
 
\begin{align*}
 
&V = \frac{a^3}{4} \left(15 + 7\sqrt{5}\right)
 
&F = 3a^2 \sqrt{5\left(5 + 2\sqrt{5}\right) } \\
 
&R = \frac{a}{4} \left( 1 + \sqrt{5} \right) \sqrt{3}
 
&r = \frac{a}{4} \sqrt{ \frac{50 + 22\sqrt{5}}{5} }
 
\end{align*}
 
\item Ikosaeder
 
\begin{align*}
 
&V = \frac{5a^3}{12} \left(3 + \sqrt{5}\right)
 
&F = 5a^2 \sqrt{3} \\
 
&R = \frac{a}{4} \sqrt{ 2 \left( 5 + \sqrt{5} \right) }
 
&r = \frac{a}{2} \sqrt{ \frac{7 + 3\sqrt{5}}{6} }
 
\end{align*}
 
\end{enumerate}
 
 
 
\ges Funktion \verb°regpol.m° mit Inputparametern: Polyeder-typ \verb°typ° und Polyeder-kantenlänge \verb°a°.
 
Rückgabewerte: Kantenlänge \verb°a°, Volumen \verb°V°, Oberfläche \verb°F°,
 
Radius der umbeschriebenen Kugel \verb°R°, Radius der einbeschriebenen Kugel \verb°r°
 
 
\bsp
 
\begin{verbatim}
 
[V,F,R,r] = regpol('w',3)
 
V = 27
 
F = 54
 
R = 2.5981
 
r = 1.5000
 
 
\end{verbatim}
 
 
\end{document}
 
</pre>
 

Aktuelle Version vom 19. November 2007, 16:58 Uhr

Allgemeines

MLTutor-Projekte

Für jede Aufgabe die im Laufe des Kurses zu absolvieren ist, muss ein MLTutor-Projekt angelegt werden.

Dieses ist eine Sammlung von Dateien, die für den Ablauf notwendig sind:

  • Ein XML-File (.mlt)
  • Ein before- und after-script (manipulieren die Umgebung in der der Test

abläuft)

  • Eine Referenzlösung
  • Eventuell benötigte Datenfiles

Der XML-File

Diese Datei dient zur allgemeinen Steuerung des Testvorgangs. Welche Einstellungen hierin vorgenommen werden können ist im Anschluss zu finden.

Anlegen eines neuen XML-Files

In der Matlab-Workbench in der Projektbaumstruktur Rechtsklick auf den Namen eines MLTutor-Projektes. Im ersheinenden Menü

New -> Other -> MLTutor File

Jetzt sollte ein example.mlt angelegt worden sein.

Einstellungen im XML-File

Diese Liste bezieht sich auf die Tabs, die im XML-Editor (nach Doppelklick auf .mlt) unten eingeblendet werden.

  • Overview: Name und Art des Beispiels sind anzugeben
    • Der Name wird im entsprechenden Textfeld eingetragen
    • Die Art des Beispiels wird im entsprechenden Dropdown Menü eingestellt. Hier gilt folgende Zuordnung
      • Standard -> Einführungsbeispiel
      • Übungsbeispiel -> Pflichtbeispiel
      • Zusatzbeispiel -> Freiwilliger Zusatz
  • Dependencies

POSTPONED UNTIL NEW EDITOR

before- und after-script

Mit diesen MATLAB-Skripten wird die Umgebung, in der der Test ausgeführt wird manipuliert. Ein Großteil der Eigenschaften eines Tests wird hierin festgelegt.

Referenzlösung

Die Referenzlösung ist ein MATLAB-Script (-Funktion), das die gestellte Aufgabe löst. Im Test wird dieses Skript ausgeführt, und die Werte bestimmter Variablen werden gespeichert. Anschließend wird das äquivalente Skript der KursteilnehmerInnen ausgeführt, und die Werte der fraglichen Variablen verglichen.

Datenfiles

... werden im Projektverzeichnis abgelegt und im XML-File eingetragen. Zum Zeitpunkt des Tests wird dann sichergestellt, dass die Datenfiles gefunden werden.

Allgemeines zu Tests

Prinzipieller Ablauf von Tests sollte woanders beschrieben werden.

Wie werden Variablen gesetzt?

Im Allgemeinen werden in der Aufgabenstellung einzuhaltende Variablennamen vorgegeben.

Es ist auch möglich bestimmte Variablen im before-script zu setzen, und in der Aufgabenstellung auf die Existenz dieser Variablen hinzuweisen.

Beim Testen von Funktionen ist es in der Regel nicht notwendig Variablennamen zu fordern.

Test von Funktionen

Referenz- und Studierendenfunktion werden im before- oder after-script aufgerufen. Dabei hat man volle Kontrolle über Ein- und Ausgabeparameter. Die Überprüfung erfolgt anhand der Rückgabewerte.

Umgang mit input

Es wird im before-script die Variable MLTutor_INPUT_ANSWERS gesetzt. Dies ist eine Zelle, die Strings der zu setzenden Werte enthält. Es muss allerdings die Reihenfolge der Abfrage vorgegeben sein. Will man tatsächlich einen String setzen so ist dieser in dreifache single-quotes einzuschließen.

Beispiel:

MLTutor_INPUT_ANSWERS={'[1:5]','''Kegel''','[]'};

Bitte beachtet, wie ein leerer Input einzugeben ist ('[]'). Bei Zeichenketten braucht man jeweils drei Hochkommas am Anfang und am Ende, was bei obigem Beispiel dann 'Kegel' als Input liefert.

Zählen von Input-Aufrufen
Der Zähler für die Aufrufe von input ist

MLTutor_INPUT_COUNT

Damit kann man feststellen, wie oft die Funktion input aufgerufen wurde.

Umgang mit rand

Die Testumgebung setzt vor dem Ausführen der Skripte den Seed des Zufallszahlengenerators. Wichtig ist, dass danach die Reihenfolge in der Variablen erzeugt werden vorgegeben wird. Wird diese Reihenfolge nicht eingehalten wird ein positiver Test fehlschlagen.

Was passiert wenn jemand "clear all" in einem Script stehen hat?

clear wird von der Testumgebung abgefangen, wenn etwas von den Studenten laufen kann. Damit werden vor allem die MLTutor-Variablen beschützt. Damit läuft aber u.U. einProgramm im Testbetieb, das ausserhalb nicht laufen würde.


Mit der Variablen

MLTutor_CLEAR_COUNT

existiert eine Möglichkeit zu prüfen ob clear aufgerufen wird.Man kann es in den Test aufnehmen, dann bekommt man einen Fehler, wenn clear verwendet wird, weil MLTutor_CLEAR_COUNT dann nicht Null ist.

Verbotene Funktionen (z.B. for ).

Es gibt einen Punkt in der XML-Datei, die zum Test gehört, wo man einfach angibt, welche Funktionen der Benutzer nicht verwenden darf.

LaTeX-Angabe? (Referenzen, Kurzbefehle)

Es existiert ein Projekt kernbich.testbeispiele.shorts.de in dem hilfreiche Kurzbefehle definiert sind. Dieses kann am Beginn eines Dokuments folgendermaßen eingebunden werden:

\documentclass[12pt,a4paper]{article}
\input{../kernbich.testbeispiele.shorts.de/shorts}

Wobei der Pfad zum Projekt (hier ..) jeweils angepasst werden muss. Diese Angabe hier sollte aber funktionieren, wenn sich alle Projekte im gleichen Workspace befinden.

In kernbich.testbeispiele.shorts.de existieren einige Kürzel, deren Bedeutung selbserklärend sein sollte:

\matrefe{sqrt}
\matrefe{Wurzel}{sqrt}
\matref{arithmetische Operatoren}{arithmeticoperators}

Bei den Kapiteln bitte unbedingt die neuen Kapitelnummern verwenden.

\appsoftskriptum
\appsoftkapitel{n} % Kapitelnummer n von 1 bis 20
\MatlabLearning
\MatlabReference
\MatlabMathematics
\MatlabCreatingPlots
\MatlabPrograming
\MatlabDataAnalysis
\MatlabEnvironment
\MatlabVisualize
\MatlabCreatingGUIs
\MatlabExternalInterfacesReference
\MatlabExternalInterfaces
\MatlabReferenceFunctionsCategoricalList
\MatlabReferenceMathematics
\MatlabReferenceMathematicsArraysAndMatrices
\MatlabReferenceMathematicsLinearAlgebra
\MatlabReferenceMathematicsElementaryMath
\MatlabReferenceMathematicsPolynomials
\MatlabReferenceMathematicsInterporlationAndComputationalGeometry
\MatlabReferenceMathematicsCoordinateSystemConversion
\MatlabReferenceMathematicsNonlinearNumericalMethods
\MatlabReferenceMathematicsSpecializedMath
\MatlabReferenceMathematicsSparseMatrices
\MatlabReferenceMathematicsMathConstants

Es gibt jetzt auch noch ein Kürzel für die MLTutor - Hints

\mltutorhint{Strichpunkt}{MLTutor Hinweisen}

Dies führt auf MLTutor - Hints#Strichpunkt.

Zählen von disp-Aufrufen

Der Zähler für die Aufrufe von disp ist

MLTutor_DISP_COUNT

Damit kann man feststellen, wie oft die Funktion disp oder fprintf (mit fid 1 oder 2) aufgerufen wurde.

Anzeige des Testaufrufs von Funktionen für den Benutzer

Alles was in einem before- oder after-script von %### eingeschlossen ist, ist dem Benutzer zugänglich.

 %ml_test1_after.m
 %###
 t = linspace(0,10,100);
 [x,y] = foo(t,[],4);
 %###

 test_size = size(x);

Hier sieht der Benutzer also, welche Werte t zugewiesen werden, und wie die Funktion foo aufgerufen wird. Er sieht allerdings nicht, dass anschließend auch noch eine Variable test_size erzeugt wird.

Bei Skripts braucht man das nur, wenn im before-Skript Variablen gesetzt werden. Dann sollten diese auch zwischen

%###
a = 3; b = 5;
%###

gesetzt werden.

In den Skripts und Funktionen UNBEDINGT Strichpunkte am Ende von Zeilen verwenden, die eine Ausgabe haben!

Verbesserung

Möglich wäre obiges Beispiel auch in dieser Form:

%ml_test1_after.m
%###
t = linspace(0,10,100);
%###

mltutor_function_switch(1);
%###
[x,y] = foo(t,[],4);
%###
mltutor_function_switch(0);

test_size = size(x);

Der Aufruf mltutor_function_switch(1); teilt der Testroutine mit, dass jetzt wirklich die Funktion des Studenten bearbeitet wird. Mit mltutor_function_switch(0); schaltet man das wieder aus. Wenn man das nicht macht, läuft das gesamte after-Skript in diesem Modus, was normalerweise keine Problem ist, da es nur Auswirkungen auf

MLTutor_DISPLAY_COUNT % Anzahl vergessener Strichpunkte
MLTutor_CPU_TIME % cpu-Time während der Abarbeitung

Verwendet man das Feature nicht, wird das gesamte after-Skript in diesem Modus betrieben. Dann ist es eben noch wichtiger, dass man ordnungsgemäß Strichpunkte am Ende der Zeile macht!

CPU Time

Die CPU Time, die von jenem Teil des Programms verbraucht wird, die vom Studenten stammt, findet sich in

MLTutor_CPU_TIME % cpu-Time während der Abarbeitung

(siehe dazu auch #Verbesserung).

Anzahl der vergessenen Strichpunkte

Gute Skripts und Funktionen sollten keinen Output am Schirm produzieren, der nur durch Weglassen des Strichpunktes am Ende einer Anweisung entsteht. Das sollte man auch in den before- und after-Skripts beherzigen. Wenn man in einem Test zählen will, wie oft der Student den Strichpunkt vergessen hat, dan kann man folgende Variable verwenden

MLTutor_DISPLAY_COUNT

Überprüfung von Textausgaben

Es ist mögliche Textausgaben mit Hilfe von Regular Expressions zu testen. Dabei wird im before- oder after-Skript die Zelle

MLTutor_<type>_REGEXP.message = {}

gesetzt. <type> wird dabei je nach der zu überprüfenden Ausgabe (ERROR, DISP, ...) ersetzt. Die Elemente der Zelle sind wieder Zellen mit Strings von regulären Ausdrücken. Dabei prüft die erste Zelle die erste Zeile die vom entsprechenden Befehl (z.B. disp) ausgegeben wird, die zweite die zweite Zeile usw.

Zur Überprüfung stehen dann die Variablen

MLTutor_<type>_REGEXP_CORRECT
MLTutor_<type>_REGEXP_ALL_CORRECT

zur Verfügung. Diese Variablen sind Vektoren vom Typ logical. An den Stellen an denen die Überprüfung korrekt war enthalten sie 1 ansonsten 0.

Der endgültige Test findet wieder durch Vergleich dieser Variablen statt. Es ist also unbedingt darauf zu achten, dass diese Tests in Bezug auf das Referenzskript überall eine 1 liefern.

Sind in den zu überprüfenden Textmeldungen in Strings umgewandelte Variablen(werte) enthalten, so sollte die REGEXP.request im after-Skript definiert werden, und die zu überprüfende Variable zur Definition des Ausdruckes verwenden. Siehe Beispiele bei #Regular Expressions bei disp

Aus "historischen" Gründen existiert auch noch eine zweite Art der Testmöglichkeit. Dabei wird ein gesamter String vorgegeben. Es kann dann gewählt werden, ob dieser String die gesamte (exakte) Fehlermitteilung darstellt, oder ob dieser String lediglich in der Fehlermitteilung enthalten sein muss. Tests dieser Art sollten nicht mehr verwendet werden. Der Überprüfung mit Regular Expressions ist wesentlich flexibler und verhindert, dass Tests aufgrund von unwichtigen Tippfehlern (z.B. unterschiedliche Anzahl an Leerräumen) fehlschlagen.

Regular Expressions bei Fehlern

Hier stehen die Variablen:

MLTutor_ERROR_REGEXP.message
MLTutor_ERROR_REGEXP_CORRECT
MLTutor_ERROR_REGEXP_ALL_CORRECT

zur Verfügung.

Einige Möglichkeiten die Fehlermitteilung

Time vector is undefined

zu testen wären:

MLTutor_ERROR_REGEXP.message = '^[Tt]ime'; % Time oder time am Anfang
MLTutor_ERROR_REGEXP.message = {'^[Tt]ime'}; % gleich wie vorige Zeile
MLTutor_ERROR_REGEXP.message = {'time', 'vector', 'undefined'}; % beliebige Reihenfolge der drei Worte
MLTutor_ERROR_REGEXP.message = {'time.+vector.+undefined'}; % die drei Worte mit zumindest einem Zeichen dazwischen

Bei der dritten Zeile würde, wenn alles richtig ist,

MLTutor_ERROR_REGEXP_CORRECT = 1 1 1
MLTutor_ERROR_REGEXP_ALL_CORRECT = 1

sein. Wäre vector falsch oder fehlend, dann hätte man

MLTutor_ERROR_REGEXP_CORRECT = 1 0 1
MLTutor_ERROR_REGEXP_ALL_CORRECT = 0

als Resultat. Die Variable MLTutor_ERROR_REGEXP_ALL_CORRECT ist somit eine endgültige Antwort, ob etwas falsch oder richtig ist.

Das Ganze funktioniert auch für Error Identifier, die Variablen heissen dann

MLTutor_ERROR_REGEXP.identifier
MLTutor_ERRORID_REGEXP_CORRECT
MLTutor_ERRORID_REGEXP_ALL_CORRECT

Regular Expressions bei Warnungen

Die Definitions-Variablen sind jetzt

MLTutor_WARNING_REGEXP.message
MLTutor_WARNING_REGEXP.identifier

und die Lösung der Überprüfung steht in

MLTutor_WARNING_REGEXP_CORRECT
MLTutor_WARNING_REGEXP_ALL_CORRECT
MLTutor_WARNINGID_REGEXP_CORRECT
MLTutor_WARNINGID_REGEXP_ALL_CORRECT

Regular Expressions bei disp

Hier steht im Gegensatz zu den vorherigen Beispielen auch die Variable

MLTutor_DISP_REGEXP_REALALL_CORRECT

zum Testen zur Verfügung. Ihre Funktion geht aus dem folgenden Beispiel hervor.

Hier ist vorausgesetzt, dass man die Variablen a und b im after-Skript kennt:

astr = num2str(a);
astr = strrep(astr(1:5),'.','\.');
bstr = mat2str(b);
bstr=strrep(bstr,'[','\[');
bstr=strrep(bstr,']','\]');
MLTutor_DISP_REGEXP = { ...
    {'Variable\s+a\s*[:-]',astr}, ...
    {'Variable','b:',bstr}, ...
    {astr}, ...
    {b}, ...
    };

Beim ersten Ergebnis wird überprüft, ob die Antwort besteht aus

dem Wort Variable
zumindest einem Whitespace-Character (z.B. Leerzeichen) \s+
dem Buchstaben a
beliebig vielen Whitespace-Characters (auch Null) \s*
einem Doppelpunkt oder einem Bindestrich [:-]

und dann, ob das Ergebnis von a vorkommt, und zwar

die ersten fünf Zeichen, wobei . durch \. ersetzt wurde

Bei der zweiten Zeile wird überprüft, ob die Antwort besteht aus

dem Wort Variable
der Kombination b:
dem Ergebnis von mat2str(b), wobei [ durch \[ und ] durch \] ersetzt wurde

Bei der dritten Zeile wieder

astr aus num2str mit dem Dezimalpunkt ersetzt

Bei der vierten Zeile

b

hier erfolgt automatisch eine Umwandlung mit num2str(b). Dies funktioniert klaglos aber nur, weil b ein Zeilenvektor aus Integerzahlen ist. Im Prinzip ist das keine gute Idee, viel besser ist die Überprüfung, wenn die Variablen schon vorher in Strings umgewandelt wurden.

Die Ergebnisse stehen dann in

MLTutor_DISP_REGEXP_CORRECT
MLTutor_DISP_REGEXP_ALL_CORRECT
MLTutor_DISP_REGEXP_REALALL_CORRECT

wobei MLTutor_DISP_REGEXP_ALL_CORRECT für jedes disp 0 oder 1 enthält und das Gesamtergebnis in MLTutor_DISP_REGEXP_REALALL_CORRECT steht.

Input - Fragen

Die Fragen, die mit dem Befehl input gestellt werden, können auch überprüft werden. Beim Beispiel

x = input('Bitte geben Sie x ein: ');

könnte man angeben

MLTutor_INPUT_REGEXP = { ...
   {'[Bb][Ii][Tt][Tt][Ee]','geben','x'} ...
   };

was folgendes bedeutet (in beliebiger Reihenfolge):

das Wort Bitte in beliebiger Schreibweise BItte, BITTE, ...
das Wort geben
das Zeichen x 

Es wäre noch möglich

[Tt][Tt] -> [Tt]{2} zu ersetzen. 

Im Allgemeinen bedeutet die Konstruktionen {n,m} das der vorhergehende Ausdruck mindestens n-, und maximal m-Mal auftreten soll.

Eine andere Möglichkeit

MLTutor_INPUT_REGEXP = { ...
   {'\<Bitte\>.+\<geben\>.+y.*:'} ...
   };

Was in richtiger Reihenfolge bedeutet:

das Wort Bitte
zumindest ein beliebiges Zeichen dazwischen .+
das Wort bitte
zumindest ein beliebiges Zeichen dazwischen .+
der Buchstabe y
beliebig viele Zeichen .* (auch null)
der Doppelpunkt

Wie bei disp stehen die Ergebnisse dann in

MLTutor_INPUT_REGEXP_CORRECT
MLTutor_INPUT_REGEXP_ALL_CORRECT
MLTutor_INPUT_REGEXP_REALALL_CORRECT

wobei MLTutor_INPUT_REGEXP_ALL_CORRECT für jedes input 0 oder 1 enthält und das Gesamtergebnis in MLTutor_INPUT_REGEXP_REALALL_CORRECT steht.

Überprüfung des Hilfetextes

Ebenfalls mit Regular Expressions. Als Variable stehen zur Verfügung für die Definition

MLTutor_HELP_REGEXP = {'regexp1','regexp2','regexp3','usw'};

bzw. die Überprüfung

MLTutor_HELP_REGEXP_CORRECT
MLTutor_HELP_REGEXP_ALL_CORRECT

Näheres zum Thema unter: #Regular Expressions bei Fehlern, #Regular Expressions bei Warnungen, #Regular Expressions bei disp, #Regular Expressions bei input

Überprüfung von Plots

Funktioniert ähnlich wie das Testen von Textausgaben. Im before-script wird mit Hilfe von

MLTutor_GRAPHICS_REQUEST 

festgelegt, welche Eigenschaften des Plots überprüft werden sollen. Darin kann jedes Element das im [http://itp.tugraz.at/matlab/techdoc/infotool/hgprop/doc_frame.html Handle Graphics Property Browser] zu finden ist überprüft werden. Die Numerierung (siehe Beispiel) in der Anforderung der Ergebnisse ergibt sich aus der Reihenfolge in der die Objekte im Plot erzeugt werden. Somit muss diese in der Angabe zu einem Projekt fix vorgegeben sein.

Beispiel:

% main.m

x = -2:0.1:3;

g1 = normpdf(x,0,1);
g2 = normpdf(x,1,0.5);

plot(x,g1,x,g2,'r');  %line1 & line2

hold on
plot(x,g1+g2,'k'); %line 3
hold off

line(x,g1-g2,'color','green'); %draw line in current axes without the use of hold on .... hold off

xlabel('x');
ylabel('y');
title('Just an example')
% end main.m
% test_before.m

% check properties of axes
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.request = {'xlabel','ylabel','title'};

% check data of line 1 (g1)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_1.request = {'xdata','ydata'};

% check data and color of line 2 (g2)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_2.request = {'xdata','ydata','color'};

% check data and color of line 3 (g1 + g2)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_3.request = {'xdata','ydata','color'};

% check data and color of line 4 (g1 - g2)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_4.request = {'xdata','ydata','color'};

Um beim Test der Variablenwerte keinen Plot angezeigt zu bekommen ist im folgendes ins before script einzutragen.

% test_before.m
MLTutor_FIGURE_HIDE = 1;

Beispiel für Legende:

MLTutor_GRAPHICS_REQUEST.figure_1.axes_2.text_1.request = {{'string',{'\<Gauss\>|\<gauss\>|\<GAUSS\>'}}};

Als Testvariable ist

MLTutor_GRAPHICS_RESULTS

einzutragen.

Regular Expressions

Auch hier kann man nun Regular Expressions verwenden, und zwar geht das bei allen Größen die Zeichenketten als Resultat haben. Obiges Beispiel könnte also so modifiziert werden:

MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.request = { ...
 { 'xlabel', '^x$' }, ...
 { 'ylabel', '^y$' }, ...
 { 'title', {'[Jj]ust', '[Ee]xample'} } ...
};

Die Beispiele funktionieren wie bei disp, Fehlern, Warnungen und input.

Im Unterschied zur Verwendung ohne Regular Expressions steht dann im Ergebnis z.B. bei xlabel nicht x sondern 1 (richtig) oder 0 (falsch). Die Outputvariable ist aber die selbe Struktur:

MLTutor_GRAPHICS_RESULTS

Eigenheiten bei errorbar

Bei errorbar und bei anderen Befehlen, welche die neuen Gruppierungsfeatures von Matlab verwenden, gibt es das Problem, dass die Reihenfolge der Linien nicht so ist wie erwartet.

x = linspace(0,pi,100)
y = sin(x);
xd = x(1:5:end);
yd = sin(xd);
y1 = cos(x);
yd1 = cos(xd);

sig = 0.2;
rd = rand(size(xd))*sig

figure
plot(x,y,'r-')

hold on
errorbar(xd,yd,rd,'ob')
plot(x,y1,'k-')
errorbar(xd,yd1,rd,'og')
hold off
legend({'Fit1','Data1','Fit2','Data2'},'Location','sw')

Normalerweise würde man erwarten, dass

MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_1.request = {'xdata','ydata','color'};   % sin(x)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_2.request = {'xdata','ydata','color'};   % sin(xd)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_3.request = {'xdata','ydata','color'};   % Fehler zu sin(xd)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_4.request = {'xdata','ydata','color'};   % cos(x)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_5.request = {'xdata','ydata','color'};   % cos(xd)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_6.request = {'xdata','ydata','color'};   % Fehler zu cos(xd)

liefert. In der Realität ist die Reihenfolge aber

MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_1.request = {'xdata','ydata','color'};   % Fehler zu sin(xd) - Erste hggroup
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_2.request = {'xdata','ydata','color'};   % sin(xd) - Erste hggroup
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_3.request = {'xdata','ydata','color'};   % Fehler zu cos(xd) - Zweite hggroup
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_4.request = {'xdata','ydata','color'};   % cos(xd) - Zweite hggroup
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_5.request = {'xdata','ydata','color'};   % sin(x) - Erster Plotbefehl
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_6.request = {'xdata','ydata','color'};   % cos(x) - Zeiter Plotbefehl

Seid also bitte vorsichtig, welche Linien ihr überprüft. Ich habe keine Möglichkeit, dass zu korrigieren, jedenfalls nicht mit vertretbarem Aufwand.

Legende

Beim Befehl legend gibt es eine neue Syntax:

legend({'Fit1','Data1','Fit2','Data2'},'Location','nw')

Es ist gut wenn man die Liste der Beschriftung jetzt in einer Zelle {} schreibt und dann den Ort in der neuen Syntax. Siehe dazu legend.

Will man auch Fehler in der Legende sehen, dann muss man obiges Beispiel so ändern:

figure
lh1 = plot(x,y,'r-')

hold on
ebh1 = errorbar(xd,yd,rd,'ob') % hggroup
ebh1_ch = get(ebh1,'children');
lh2 = plot(x,y1,'k-')
ebh2 = errorbar(xd,yd1,rd,'og') % hggroup
ebh2_ch = get(ebh2,'children');
hold off
legend([lh1;ebh1_ch;lh2;ebh2_ch],{'Fit1','Data1','Fehler1','Fit2','Data2','Fehler2'},'Location','sw')

Dazu muss man die Handles auf alle gewünschten Graphikobjekte verwenden und daraus einen Vektor formen. Die Handles ebh1 und ebh2 sind Handles auf hggroup und man muss daher zuerst auch noch ihre Kinder (children) abfragen.

ACHTUNG

Werden Legenden verwendet so stellen diese Achsen dar. Dies muss beim Testen von Daten in z.B. einem subplot berücksichtigt werden.\\ Hat man zum Beispiel:

subplot(2,1,1)
plot(1,2,'o')
legend('testlegende')

subplot(2,1,2)
plot(3,4,'o')
legend('testlegende2')

Hier müssen zum Testen der xdata und ydata die Linien der Achsen 1 und 3 abgefragt werden!

Polarplot

Der Befehl polar funktioniert wie erwartet. De extra Linien, die den Polarplot schmücken (Kreise, radiale Linien) sind alle versteckt (hidden) und machen daher keine Probleme. Die Abfrage nach den Linien geht daher wunderbar und es gibt auch kein Problem mir der Reihenfolge.

Figure

Während der Tests werden für figure noninteger-Handles verwendet. Daher sieht man, auch wenn man es z.B. mit figure(1) versucht keine Zeichnung mit dem Handle 1 sondern mit einem anderen Handle. Daher funktioniert auf keinen Fall:

figure(1);
set(1,'Color','red')

Will man so etwas, muss man schreiben

fh=figure;
set(fh,'Color','red')