vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


Tag 19

Komplexe Techniken: Lehren und Prüfen - online

Eines der am hitzigsten diskutierten Themen an den Schulen auf dem Land ist das Fernstudium - wo es Klassen gibt, in denen Kinder und Erwachsene unterrichtet werden, ohne in einem gemeinsamen Klassenzimmer sitzen zu müssen. Das World Wide Web ist ein ausgezeichnetes Medium, dieses Fernstudium möglichst vielen Benutzern zur Verfügung zu stellen.

Dieses Kapitel beschreibt die Entwicklung eines Online-Prüfungsforums, das ganz einfach auf viele Einsatzgebiete in akademischen und nicht-akademischen Einrichtungen ausgelegt werden kann. Heute geht es um die folgenden Themen:

19.1 Umfrage- und Prüfungssysteme

Ich habe Stunden damit verbracht, Online-Prüfungssysteme für die Ohio State University einzurichten. Dabei werden normalerweise nur ein paar HTML-Formulare angelegt, die die Antworten der Studenten per E-Mail an den Professor schicken, oder die Ergebnisse speichern, sodass der Professor sie später bewerten kann. Diese HTML-Formulare immer wieder anzulegen, kann müßig sein und irgendwie auch sinnlos. Besser erledigt man diese Aufgabe, indem man ein erweiterbares System einrichtet, in dem das HTML von den gestellten Fragen getrennt angelegt wird.

Das System, das Sie heute entwickeln werden, übernimmt genau diese Aufgabe - es zeichnet mehrere Fragen und die Antworten auf und gibt die Fragen an die Studenten weiter. Um auf die Site zuzugreifen, melden sich die Studenten am System an und bearbeiten die Fragen. Wenn sie fertig sind, kann der Administrator statistische Werte für die verschiedenen Studenten anzeigen.

Die Sitemap

Die Entwicklung dieses Systems bedarf verschiedener Vorüberlegungen. Anders als bei einigen der bisher entwickelten Applikationen ist ein Teil der Kommunikation nicht auf den ersten Blick erkennbar. Auch hier listen wir die verschiedenen Funktionsmerkmale auf, die für das System realisiert werden müssen:

Betrachten wir die Sitemap. Offensichtlich brauchen wir Bildschirme für die Anmeldung und für die Fragen, ebenso wie einen Bildschirm für die Administration, um nach einem Benutzer suchen und seine Ergebnisdaten anzeigen zu können. Wir brauchen also fünf oder sechs Bildschirme, aber ein Großteil der Funktionalität dieses Programms konzentriert sich auf den Bildschirm mit den Fragen.

Interessant wird das Ganze durch die Bereitstellung mehrerer Fragen und mehrerer Antworten. Das bedeutet, es kann eine beliebige Anzahl von Fragen geben, und jede Frage kann beliebig viele Antworten haben. Diese Informationen werden auf einem einzigen Bildschirm angezeigt. Viele der mir bekannten Online-Prüfungssysteme haben für einzelne Fragen separate Seiten entwickelt - keine Angst, das wird für unser System nicht nötig sein!

Abbildung 19.1 zeigt die Sitemap für das hier entwickelte Prüfungssystem.

Abbildung 19.1:  Die Sitemap für die Prüfung besteht aus vier Abschnitten.

Das SQL

Das SQL, das wir für diesen Abschnitt brauchen, umfasst nur ein paar Formulare, aber Sie müssen sicherstellen, dass die Tabellen so entwickelt werden, dass keine Beschränkungen entstehen.

Als Erstes brauchen wir eine Tabelle für den Benutzernamen und das Kennwort - sie ist für die Anmeldungen am System zuständig. Wir werden uns hier nicht mit der Entwicklung eines Anmeldebildschirms aufhalten, weil wir voraussetzen, dass der Administrator die Benutzer einträgt, die Zugriff auf das System haben sollen. Jetzt betrachten wir diese Tabelle - weil wir uns hier ganz auf das Authentifizierungssystem von UltraDev verlassen, wird sie etwas anders aussehen als frühere Benutzertabellen. Außerdem können wir Zugriffsebenen für die administrative Steuerung einführen.

create table user (
username varchar(50) not null,
password varchar(50),
userlevel varchar(50),
primary key (username)
);

Wie bereits erwähnt, trifft das Authentifizierungssystem von UltraDev keine Vorkehrungen für die Verwendung eines beliebigen Feldes (wie beispielsweise die Benutzer-ID) zur Identifizierung eines Benutzers. Durch die Implementierung von Benutzernamen müssen wir manuell auf Duplikate prüfen (oder die UltraDev-Verhalten verwenden). Zuvor haben wir automatisch inkrementierte Benutzer-IDs verwendet, sodass wir uns keine Gedanken über Duplikate machen mussten.

Jetzt legen wir die Tabelle mit den Fragen an - sie enthält alle Fragen, die der Administrator stellen will. Leider müssen für jede Frage mehrere Antworten bereitgestellt werden. Nach dem ersten Blick sind Sie vielleicht versucht, ein Tabellenlayout wie das folgende zu erstellen, aber tun Sie es nicht!

create table question (
questionID int not null auto_increment,
questionTitle varchar(50),
questionText varchar(250),
answer1 varchar(50),
answer2 varchar(50),
answer3 varchar(50),
etc...

Das funktioniert offensichtlich nicht. Statt einer einzigen Tabelle braucht man zwei Tabellen für die Fragen. Eine Tabelle enthält die eigentliche Frage, die andere enthält die Antworten auf Frage.

Um die beiden Tabellen zu verknüpfen, enthält die Antwortentabelle eine Frage-ID für jede der Antworten. Weil wir eine Online-Bewertung implementieren wollen, muss das System auch wissen, wann eine Antwort korrekt ist. Um dieses Funktionsmerkmal zu implementieren, tragen Sie die ID der korrekten Antwort in das Fragefeld ein.

Wir können die Fragentabelle wie folgt definieren, aber auch das funktioniert noch nicht wirklich.

create table question (
questionID int not null auto_increment,
questionTitle varchar(50),
questionText varchar(250),
answerID int,
primary key (questionID)
)

Diese Tabelle enthält alle Fragen und ihre IDs. Die Antworten können in einer Tabelle wie der folgenden abgelegt werden:

create table answer (
answerID int not null auto_increment,
questionID int,
answerText varchar(80),
primary key (answerID)
)

Betrachten wir die beiden Tabellen noch einmal - vielleicht haben Sie bemerkt, dass es problematisch sein könnte, die Daten in die Tabellen einzugeben. Weil Sie die Frage-ID nicht kennen, wenn Sie eine Antwort eingeben, und die Antwort-ID nicht, wenn Sie die Frage eingeben, ist es schwierig, alles synchron zu halten.

Um dieses Problem zu umgehen, machen Sie aus der Frage-ID ein Feld, das nicht automatisch inkrementiert wird. Sie müssen die Frage-IDs manuell verwalten, aber auf diese Weise können Sie zuerst die Fragen und dann die Antworten eingeben. Weil es weniger Fragen als Antworten gibt, ist es einfacher, die Frage-ID mit einem manuell erzeugten Wert zu definieren.

Die endgültige Fragentabelle könnte also wie folgt aussehen:

create table question (
questionID int not null,
questionTitle varchar(50),
questionText varchar(250),
answerID int,
primary key (questionID)
)

Wenn Sie eine Tabellendefinition eingegeben haben und diese später ändern wollen, verwenden Sie dazu die SQL-Funktion ALTER TABLE. Es ist jedoch nicht möglich, den Primärschlüssel zu ändern, ohne die gesamte Tabelle zu verwerfen.

Jetzt tragen wir einige Beispieldaten ein. Wir werden zuerst die Antworten eintragen, damit wir eine Antwort-ID haben, die wir in die Fragentabelle eintragen können.

Hier einige einfache Antwortdaten, die in die Datenbank eingetragen werden können:

insert into answer values ('',1,'G4 Cube');
insert into answer values ('',1,'G4 MP Tower');
insert into answer values ('',1,'Ruby iMac');
insert into answer values ('',1,'Pentium III');
insert into answer values ('',2,'Äpfel');
insert into answer values ('',2,'Birnen');
insert into answer values ('',2,'Weintrauben');
insert into answer values ('',2,'Zitronen');
insert into answer values ('',3,'Playstation 2');
insert into answer values ('',3,'Nintendo 64');
insert into answer values ('',3,'Dreamcast');
insert into answer values ('',3,'X-Box');

Die Fragentabelle kann mit einigen Beispielfragen gefüllt werden:

insert into question values (1,'Der beste Computer',
'Es gibt nur einen Computer, der 2000 herauskam und sein Geld wirklich wert war.
Welcher Computer ist das?',1);
insert into question values (2,'Eine saure Frucht',
'Wenn Sie eine Party haben und frisches Obst anbieten wollen,
welches Obst würden Sie dann nicht bereitstellen?',8);
insert into question values (3,'Videospielkonsolen',
'Welche Videokonsole ist nicht auf dem Videospielmarkt 2000-2001 zu finden?',12);

Beachten Sie in den Beispieldaten, dass es nur drei Fragen und vier verschiedene Antworten pro Frage gibt. Das System kann beliebig viele Fragen und Antworten verarbeiten. Für jede der Fragen können beliebig viele Antworten bereitgestellt werden. Und Sie können ganz einfach von Multiple-Choice-Fragen auf Richtig/Falsch-Fragen umsteigen.

Außerdem basieren die Fragen und Antworten auf Ihren Einstellungen.

Jetzt ein paar Benutzer. Wir tragen Benutzer in die Benutzerdatenbank ein, die sich am System anmelden und an dem Quiz teilnehmen können:

insert into user values ('jray','johnpass','schüler');
insert into user values ('vuj','snaffle','schüler');
insert into user values ('doorknob','thedoor','lehrer');

Damit haben wir alles, was wir für das Programm brauchen! Wir haben die Datenbank eingerichtet, sodass der Benutzer sich anmelden kann, und das Programm listet Fragen sowie mögliche Antworten auf. Das ist alles. Anmeldung... Fragen... Antworten...

Fehlt irgend etwas? Ja! Überlegen Sie doch selbst! Die Applikation kann Anmeldungen überprüfen und Fragen stellen, aber was passiert mit den vom Benutzer gegebenen Antworten?

Wir haben eine der wichtigsten Komponenten des Programms vergessen - das Speichern der Benutzerantworten. Ohne diese Information wird es sehr schwierig sein zu beurteilen, wie die Benutzer das Quiz bearbeitet haben. Die Tabelle für die Antworten des Benutzers ist ganz einfach - wir brauchen nur den Benutzernamen und die ID der Antwort, die der Benutzer für eine bestimmte Frage ausgewählt hat, aufzuzeichnen.

create table response (
username varchar(50) not null,
answerID int not null,
questionID int not null,
primary key (username,questionID)
)

Eine der schwierigsten Aufgaben in diesem Projekt ist, die Anzahl der korrekten Antworten eines Benutzers zu berechnen. Bevor wir die eigentlichen Seiten anlegen, wollen wir genau überlegen, wie dieser Prozess realisiert werden kann. Sie sollten vor der Implementierung Ihrer Seiten immer ganz genau verstehen, was auf der Site passieren soll. Wir tragen jetzt Informationen in die Antwortentabelle ein:

insert into response values ('jray',1,1);
insert into response values ('jray',2,7);
insert into response values ('jray',3,12);

Diese Beispieldaten setzen voraus, dass der Benutzer mit der ID 1 alle drei Fragen beantwortet hat - zwei davon richtig und eine falsch.

Wie können wir feststellen, wie viele der vom Benutzer gegebenen Antworten korrekt sind?

Dazu verwenden wir ein bisschen intelligentes SQL, das ist alles:

select * from response,question where response.username='jray' 
AND response.answerID=question.answerID AND
response.questionID=question.questionID;

Diese Anweisung gibt bei der Ausführung mehrere Datensätze zurück, die alle korrekten Antworten des Benutzers enthalten.

Ein Beispiel:

mysql> select * from response,question where response.username='jray' AND
response.answerID=question.answerID AND
response.questionID=question.questionID \ G
*************************** 1. row ***************************
username: jray
answerID: 1
questionID: 1
questionID: 1
questionTitle: Der beste Computer
questionText: Es gibt nur einen Computer, der 2000 herauskam und sein Geld =>;wirklich wert war.
Welcher Computer ist das?
answerID: 1
*************************** 2. row ***************************
username: jray
answerID: 12
questionID: 3
questionID: 3
questionTitle: Videospielkonsolen
questionText: Welche Videokonsole ist nicht auf dem Videospielmarkt 2000-2001 zu =>;finden?
answerID: 12
2 rows in set (0.04 sec)

Um die fehlerhaften Antworten in der Datenbank nachzuschlagen, kehren Sie die Testbedingung "response.answerID=question.answerID" einfach um. Die neue Abfrage für falsche Antworten sieht also wie folgt aus:

mysql> select * from response,question where response.username='jray' 
AND response.answerID!=question.answerID AND
=>;response.questionID=question.questionID \ G
*************************** 1. row ***************************
username: jray
answerID: 7
questionID: 2
questionID: 2
questionTitle: Eine saure Frucht
questionText: Wenn Sie eine Party haben und frisches Obst anbieten wollen, welches =>;Obst würden Sie dann nicht bereitstellen?
answerID: 8
1 row in set (0.00 sec)

Diese beiden SQL-Abschnitte bieten in Kombination mit dem UltraDev-Parameter [total records] die Möglichkeit, die Gesamtzahl der richtigen Antworten anzuzeigen, und worum es sich dabei gehandelt hat. Dasselbe ist für die falschen Antworten möglich.

Damit haben wir alles, um anfangen zu können. Der restliche Prozess wird innerhalb der UltraDev-Applikation realisiert. Abbildung 19.2 zeigt den endgültigen Entwurf unserer UltraDev-Datenbank.

Abbildung 19.2:  Wir brauchen für diese Applikation  Antworten, Ergebnisse und Fragen.

Jetzt können wir mit der Entwicklung beginnen! Richten Sie die erforderlichen Datenbank- und Serververbindungen ein.

19.2 Der Anmeldebildschirm

Wie bereits erwähnt, ist der Prüfungsbildschirm der erste Bildschirm für die Kommunikation mit dem Benutzer. Es handelt sich dabei aber nicht um den ersten Bildschirm, den wir entwickeln müssen. Um die Information speichern zu können, die der Benutzer auf der Website eingibt, muss das System wissen, um wen es sich bei dem Benutzer handelt. Dieses System muss abgesichert werden, deshalb erstellen wir das Anmeldesystem mithilfe der Authentifizierungs-Routinen von Macromedia und der Sitzungsvariablen MM_Username, die Sie aus früheren Kapiteln kennen.

An diesem Anmeldebildschirm ist nichts Besonderes. Wir müssen nur nach dem Benutzernamen und dem Kennwort fragen. Entwickeln Sie einen grundlegenden Anmeldebildschirm. Geben Sie dabei den Feldern für den Benutzernamen und das Kennwort geeignete Namen, ebenso wie dem Formular, in dem sie enthalten sind.

Weil es sich um die erste Seite handelt, die der Benutzer besuchen muss, werde ich mein Dokument unter dem Namen index.asp ablegen. Abbildung 19.3 zeigt ein Beispiel für einen solchen Anmeldebildschirm.

Abbildung 19.3:  Der Anmeldebildschirm braucht keine besonderen Eigenschaften aufzuweisen.

Die eigentliche Leistung der Authentifizierung kommt zutage, wenn Sie das Serververhalten Benutzer anmelden einfügen, um ein Benutzerkonto zu überprüfen. Damit wird überprüft, ob die eingegebene Benutzername/Kennwort-Kombination gültig ist. Abhängig von dem Ergebnis wird der Browser auf eine andere Seite weitergeleitet:

  1. Öffnen Sie die Palette Serververhalten.
  2. Klicken Sie auf das Plussymbol (+), und wählen Sie im Untermenü Benutzerauthentifizierung den Eintrag Benutzer anmelden.
  3. Wählen Sie das Formular sowie die Felder für den Benutzernamen und das Kennwort.
  4. Wählen Sie Ihre Datenbankverbindung und die Tabelle sowie die darin enthaltenen Felder, die mit den Feldern in Ihrem Formular verglichen werden sollen.
  5. Falls die Anmeldung erfolgreich ist, leiten Sie den Benutzer auf quiz.asp weiter. Andernfalls soll er auf einen Fehler-Bildschirm gelangen, wie beispielsweise badlogin.asp.
  6. Schränken Sie den Zugriff abhängig von Benutzername, Kennwort und Zugriffsebene ein.
  7. Wählen Sie das Feld userlevel als das Datenbankfeld, aus dem Sie die Zugriffsebene des Benutzers abrufen. Die endgültige Konfiguration sollte aussehen wie in Abbildung 19.4 gezeigt.

Nachdem Sie das Serververhalten wie in Abbildung 19.4 gezeigt definiert haben, können wir die Seite badlogin.asp anlegen, um Fehlermeldungen anzuzeigen, falls der Benutzername oder das Kennwort fehlerhaft eingegeben wurden.

Abbildung 19.4:  Vergleichen Sie die Felder mit dem Benutzernamen und dem Kennwort von Ihrem Anmeldeformular mit den Datenbankfeldern, um ein funktionierendes Authentifizierungssystem aufzubauen.

Die Seite badlogin.asp muss nichts Besonderes enthalten - einzig eine Meldung mit einem Link zurück zum Anmeldebildschirm, sodass der Benutzer einen erneuten Versuch unternehmen kann. Abhängig von Ihrer Applikation könnten Sie beispielsweise auch eine Warnmeldung für unberechtigte Benutzer ausgeben. Ein Beispiel für diesen Bildschirm sehen Sie in Abbildung 19.5.

Abbildung 19.5:  Zeigen Sie dem Benutzer eine Fehlermeldung an und stellen Sie ihm einen Link zurück zum Anmeldebildschirm bereit.

Das ist alles, was wir für die Anmeldeseiten brauchen. Bevor wir weiterarbeiten, müssen wir die Sitzungsvariable in die Datenbindungen aufnehmen, sodass wir von jeder Position auf der Site aus auf den aktuellen Benutzernamen zugreifen können:

  1. Öffnen Sie die Palette Datenbindungen.
  2. Klicken Sie auf das Plussymbol (+), und wählen Sie Sitzungsvariable.
  3. Geben Sie den Namen der Sitzungsvariablen für die Macromedia-Authentifizierung ein, MM_Username, wie in Abbildung 19.6 gezeigt.
  4. Klicken Sie auf OK.

    Abbildung 19.6:  Geben Sie den Namen der Sitzungsvariablen ein, die verfolgt werden soll.

Sie können eine Sitzungsvariable überall auf einer Site definieren und von überall aus darauf zugreifen. Die Sitzungsvariable bleibt aktiv, bis der Benutzer eine neue Browser-Sitzung initiiert (wobei der Browser beendet und neu gestartet wird).

Natürlich muss der Benutzer Cookies zulassen, damit diese Site funktioniert - andernfalls kann die Site nicht feststellen, wer sich angemeldet hat.

19.3 Das Quiz-Formular

Das Quiz-Formular für das Programm ist am schwierigsten zu implementieren - und offensichtlich die wichtigste Komponente. Bevor wir damit anfangen, wollen wir darüber nachdenken, was wir eigentlich brauchen und wie wir es realisieren wollen. Diese Seite ist einigen der zuvor erstellten Seiten ganz ähnlich. Was also muss die Seite quiz.asp können? Sie muss die folgenden Funktionsmerkmale aufweisen:

Wie können wir diese Anforderungen bewältigen? Überlegen wir, wie die Quiz-Seite arbeiten soll, bevor wir sie implementieren. Der wichtigste Teil des Quiz ist, die Fragen zu stellen - wie machen wir das? Wir legen ein grundlegendes Katalogsystem an, das anstelle von Produkten Fragen enthält. Sie erinnern sich an die bereits entwickelten Katalogsysteme - aber hier werden wir erzwingen, dass der Katalog in einer bestimmten Reihenfolge betrachtet werden muss.

Das Fragesystem ist sozusagen eine abgespeckte Version des Katalogsystems - keine Suchen, kein Browsing usw. Die Fragen für jede Seite werden abhängig von der angezeigten Frage-ID erzeugt. Dafür verwenden wir einfach ein datenbankgestütztes Popup-Menü. Die Navigation durch die Fragen ist erlaubt, aber nur in einer Richtung.

Es gibt noch einen Aspekt, der vielleicht nicht ganz so offensichtlich ist: die Beantwortung der Fragen. Auf den meisten Seiten wurde die Information als statische Daten angezeigt. Die Site hat absolut nichts dynamisches.

Im Fall des Quiz werden die Daten, die für jede der Fragen angezeigt werden, als Teil eines dynamischen Formulars erzeugt. Das Formular besteht aus dem Popup-Menü, das die Antworten zu der Frage enthält, und einer Senden-Schaltfläche. Wenn ein Formular gesendet wird, muss das System die Antwort für die Auswertung durch den Administrator in einer Datenbank ablegen.

Schließlich verwenden wir verborgene Bereiche (letztlich ein manuell erstelltes »Bereich verstecken«-Verhalten), um einige Funktionsmerkmale des Quiz-Bildschirms zu implementieren. Beispielsweise wird der Benutzer am Ende des Quiz durch einen verborgenen Bereich benachrichtigt (der verborgen bleibt, bis der Benutzer den letzten Datensatz erreicht hat). Gleichzeitig muss die ganze Seite verborgen bleiben, wenn sich der Benutzer nicht korrekt am System angemeldet hat. Jetzt wollen wir den Quiz- Bildschirm anlegen.

Wir werden nicht die gesamte Funktionalität in einem Durchgang realisieren - hier legen wir zunächst einen grundlegenden Bildschirmentwurf an. Abbildung 19.7 zeigt meinen ersten Bildschirm für quiz.asp.

Abbildung 19.7:  Jetzt richten Sie die Grundlage für Ihren Quiz-Bildschirm ein.

Der erste Schritt zur Verankerung des Quiz-Bildschirms ist, ihn mit der Datenbank zu verbinden. Wir müssen eine Datensatzgruppe für die Seite entwickeln. Und das ist hier ganz einfach, weil es sich um eine simple Abfrage handelt: "SELECT * FROM question". Richten Sie Ihre Datensatzgruppe als einfache Abfrage ein, wie in Abbildung 19.8 gezeigt.

Abbildung 19.8:  Die Fragen-Datensatzgruppe  ist eine einfache Abfrage aller Fragen-Datensätze.

Ziehen Sie den Fragen-Titel in einen allgemeinen Überschriftsbereich (er soll den Namen der Frage enthalten - Sie könnten dieses Feld später auch nutzen, um abgewandelte Quizaufgaben zu einem bestimmten Thema zu stellen, statt alle Fragen in der Datenbank zu durchlaufen). Anschließend fügen Sie auch den Fragetext in das Dokument ein.

Dies ist einer der wenigen Fälle, in denen wir keinen wiederholten Bereich verwenden, um die verschiedenen Fragen aus der Datenbank anzuzeigen. Wenn die Datensatzgruppe definiert wurde und die Datensatzfelder in das Dokument eingefügt sind, verweisen sie auf den aktuellen Datensatz in der Datenbank. Weil nur jeweils eine Frage auf dem Bildschirm angezeigt werden kann, ist das alles, was wir brauchen.

Fragen überspringen

Wir brauchen jedoch das Verhalten Zum nächsten Datensatz verschieben. Auf diese Weise kann ein Benutzer Fragen überspringen, die er nicht beantworten will. Statt eine übersprungene Antwort in der Datenbank abzulegen, können wir dem Benutzer die Möglichkeit bieten, auf eine Frage keine Antwort zu geben. Um diese Funktionalität zu realisieren, gehen Sie wie folgt vor:

  1. Legen Sie den Link Frage überspringen in Ihrem Dokument an.
  2. Markieren Sie den Link.
  3. Öffnen Sie die Palette Serververhalten.
  4. Klicken Sie auf das Plussymbol (+), und fügen Sie das Verhalten Zum nächsten Datensatz verschieben in das Dokument ein.
  5. Wählen Sie den Link und die entsprechende Datensatzgruppe, wie in Abbildung 19.9 gezeigt.

Ich habe es schon ein paar Mal erwähnt, aber für den Fall, dass Sie es vergessen haben: Sie müssen dem Dokument ein Formular hinzufügen. Legen Sie das Formular an, um die Senden-Schaltfläche für die Antworten und die Popup-Menüs, ebenfalls für die Antworten, verwalten zu können. Ich habe mein Formular unter dem Namen saveResponse abgelegt, weil das seine Aufgabe sein wird - die Antworten zu speichern.

Abbildung 19.9:  Sehen Sie die Möglichkeit vor, eine Frage zu überspringen.

Dynamische Antworten

Im nächsten Schritt beim Einrichten des Quiz-Bildschirms legen Sie das Popup-Menü mit den Antworten an. Dazu müssen Sie eine erweiterte Abfrage erstellen, die auf der Antworttabelle der Datenbank basiert. Leider müssen Sie einen Teil davon manuell erledigen. Das SQL für die Antwort, die wir benötigen, könnte wie folgt aussehen:

SELECT * FROM answer WHERE 
questionID=<irgendeine frage, die wir gerade anzeigen>

Um diese Funktionalität einzurichten, gehen Sie wie folgt vor:

  1. Ziehen Sie die Frage-ID (questionID) aus Ihrer existierenden Frage-Datensatzgruppe (question) in die Entwurfsansicht. Damit erhalten Sie den ASP-Code für den Verweis auf die Frage-ID der aktuell angezeigten Frage.
  2. Fügen Sie dem Dokument eine neue Datensatzgruppe hinzu. Dazu arbeiten Sie im einfachen Modus.
  3. Richten Sie die Datensatzgruppe mit einer einfachen Abfrage der Antworttabelle ein - "SELECT * FROM answer".

Nachdem Sie die Datensatzgruppe angelegt haben, richten Sie ein Popup-Menü ein, das von dieser Datensatzgruppe abgeleitet ist. Es ist sehr wichtig, dass Sie das jetzt tun, sodass Sie die Datensatzgruppe später nicht verändern müssen:

  1. Fügen Sie an beliebiger Stelle ein Popup-Formularelement (Sprungmenü) in das Dokument ein. Dieses Element nimmt alle Antworten aus der Antwortentabelle auf.
  2. Öffnen Sie die Palette Serververhalten.
  3. Klicken Sie auf das Plussymbol (+), und wählen Sie im Menü Dynamische Elemente den Eintrag Dynamische Liste/Menü.
  4. Setzen Sie die Datensatzgruppe auf die Antwort-Datensatzgruppe, die momentan alle Antworten aus der Datenbank enthält.
  5. Dem Menüfeld sollte das Popup-Menü des Formulars zugeordnet werden, das Sie dem System hinzugefügt haben.
  6. Die Beschriftungen sollen aus dem Feld answerText geladen werden.
  7. Die Werte für die Elemente im Popup-Feld sollten auf das Feld answerID gesetzt werden.

Klicken Sie auf OK, nachdem Sie das Verhalten vollständig konfiguriert haben, wie in Abbildung 19.10 gezeigt.

Abbildung 19.10:  Konfigurieren Sie das Popup-Menü so, dass es dynamisch aus der Antworten-Datensatzgruppe erzeugt wird.

Jetzt müssen Sie wieder manuell eingreifen. Öffnen Sie den Quellcode und suchen Sie nach diesem Codeabschnitt:

<%
set rsQuestion = Server.CreateObject("ADODB.Recordset")
rsQuestion.ActiveConnection = MM_connChapter19_STRING
rsAnswer.Source = "SELECT * FROM answer"
rsAnswer.CursorType = 0
rsAnswer.CursorLocation = 2
rsAnswer.LockType = 3
rsAnswer.Open
rsAnswer_numRows = 0
%>

Damit wird die Datensatzgruppe erstellt, die wir brauchen, um das Popup-Menü zu erstellen. Wir müssen das SQL so abändern, dass es die Bedingung beinhaltet, nach der Frage-ID (questionID) der aktuell angezeigten Frage zu suchen. Wenn Sie das Feld questionID von der Haupt-Frage-Datensatzgruppe in die Entwurfsansicht ziehen, finden Sie den Code, der die questionID auf Ihrer Seite darstellt. Für meine Webseite sieht das wie folgt aus:

<%= rsQuestion.Fields.Item("questionID").Value %>

Wir suchen genau den Wert rsQuestion.Fields.Item ("questionID").Value. Kopieren Sie diesen Wert und entfernen Sie das APS-Tag, aus dem Sie ihn erhalten haben. Bearbeiten Sie den Code der Datensatzgruppe wie folgt:

<%
set rsQuestion = Server.CreateObject("ADODB.Recordset")
rsQuestion.ActiveConnection = MM_connChapter19_STRING
rsAnswer.Source = "SELECT * FROM answer WHERE
questionID='" & rsQuestion.Fields.Item("questionID").Value &
"'"
rsAnswer.CursorType = 0
rsAnswer.CursorLocation = 2
rsAnswer.LockType = 3
rsAnswer.Open
rsAnswer_numRows = 0
%>

Mit der zusätzlichen Bedingung im Code wählt die Datensatzgruppe jetzt nur die Antworten aus, die für die vorliegende Frage zutreffen. Leider gibt es mit dieser Datensatzgruppe immer noch ein Problem - sie wird erstellt, bevor der Wert questionID zur Verfügung steht. Wenn Sie diesen Codeblock in dem Programm lassen, wo er sich gegenwärtig befindet, wird er nicht korrekt funktionieren. Statt dessen müssen Sie ihn im ASP-Code ganz nach unten verschieben - unmittelbar oberhalb des HTML. Wenn der Code an das Ende der anderen ASP-Prozeduren verschoben wird, steht der Wert von questionID zur Verfügung und kann genutzt werden.

Bei der Bearbeitung des serverseitig eingebetteten Codes kann nichts Schlimmes passieren, aber manchmal gibt es Nebeneffekte. Nachdem Sie den Code manuell bearbeitet haben, sollten Sie nicht erwarten, dass es weiterhin möglich sein wird, ihn über die Standarddialoge für die Konfiguration der Serververhalten bearbeiten zu können. Wenn Sie darüber hinaus eine geänderte Datensatzgruppe (oder ein anderes Verhalten) öffnen, ist es sehr wahrscheinlich, dass Sie den hinzugefügten Code zerstören.

Außerdem kann zusätzlicher Code verhindern, dass Serververhalten korrekt entfernt werden. Als Vorsichtsmaßnahme sollten Sie Ihre Webseite sichern, bevor Sie eines der Verhalten manuell ändern. Gut, dass ich es gesagt habe, nicht wahr?

Damit ist die Seite so weit, dass wir schon einmal ihre Funktionalität prüfen können. Momentan sollten drei Funktionen möglich sein:

Testen Sie diese Funktionen, bevor Sie weiterarbeiten. Falls irgend etwas nicht funktioniert, überprüfen Sie die bisher vorgenommenen Entwicklungsschritte und stellen Sie sicher, dass Sie alles korrekt nachvollzogen haben. Wenn Sie eine zusätzliche Funktionalität einfügen, bevor Sie etwaige Fehler korrigiert haben, kann das beim Debugging des Systems später zu Problemen führen.

Speichern der Antwort

Der wichtigste Teil des Quiz-Systems ist, die Antwort des Benutzers wieder in der Datenbank zu speichern. Damit beschäftigen wir uns als Nächstes. Nachdem wir es geschafft haben, entwickeln wir die Bildschirme für den Administrator, was etwas lockerer ist, weil sie nicht so »kritisch« für die Applikation sind. Wie also speichern wir die Antwort? Das Formular ist bereits eingerichtet, aber die Daten stehen noch nicht komplett zur Verfügung.

Um Ihre Erinnerung aufzufrischen, hier die Struktur der Antwortentabelle:

create table response (
username varchar(50) not null,
answerID int not null,
questionID int not null,
primary key (username,questionID)
)

Bevor Werte in die Tabelle eingetragen werden können, muss sie als Datensatzgruppe definiert werden. Machen Sie das jetzt. Richten Sie einen einfache Abfrage ein, rsResponse, die alle Felder in der Antwortentabelle abruft, wie in Abbildung 19.11 gezeigt. Wir werden diese Datensatzgruppe jetzt nicht abfragen, aber wir brauchen es für das Einfügen-Verhalten.

Abbildung 19.11:  Die Antwort-Datensatzgruppe muss definiert werden, damit die Einfügen-Aktion genutzt werden kann.

Das Formular, das wir hier angelegt haben, enthält die Frage-ID (questionID), aber was ist mit dem Benutzernamen (username) und der Antwort-ID (answerID)? Es gibt zwei Möglichkeiten, der Antwort diese Werte hinzuzufügen - entweder durch einen Zugriff auf die Antwort-ID (answerID), wie Sie es bereits kennen, und direktes Hinzufügen zur Einfügen-Anweisung, oder mithilfe eines verborgenen Feldes. Analog könnte die Sitzungsvariable, die den Benutzernamen (username) enthält, der Einfügen-Anweisung direkt hinzugefügt werden. Weil Sie bereits wissen, wie das geht, überlassen wir Ihnen dies als Übung. Damit es in unserem Projekt weitergeht, wollen wir diese Werte jetzt im existierenden Formular in verborgenen Feldern ablegen.

Fügen Sie Ihrem Dokument zwei verborgene Felder hinzu, questionID und username. Anschließend stellen Sie die Werte für diese Felder bereit. Dazu bearbeiten Sie die Feldattribute so, wie wir es bisher immer gemacht haben, oder Sie fügen die Felder direkt in das HTML ein:

<input type="hidden" name="questionID" 
value="<%=rsQuestion.Fields.Item("questionID").Value%>">
<input type="hidden" name="username" value="<%=Session("MM_Username")%>">

Damit werden alle Feldvariablen gefüllt, die wir für das Antwortformular brauchen. Jetzt können wir das Serververhalten Datensatz einfügen anlegen:

  1. Öffnen Sie den Dialog Serververhalten.
  2. Klicken Sie auf das Plussymbol (+), und wählen Sie Datensatz einfügen.
  3. Wählen Sie die Datensatzgruppe Response und ordnen Sie die einzelnen Formularfelder den Tabellenfeldern zu, wie in Abbildung 19.12 gezeigt. Das Feld Nach dem Einfügen hierher gehen lassen Sie einfach leer.

    Abbildung 19.12:  Legen Sie das Verhalten an, das der Datenbank die Antwort hinzufügt.

Jetzt kommt der Trick. Das Verhalten Datensatz einfügen hat ein Funktionsmerkmal, das wir in unseren Code nicht übernehmen wollen. Indem wir das Feld Nach dem Einfügen hierher gehen beim Einfügen eines Datensatzes nicht ausfüllen, teilen wir UltraDev mit, den Benutzer auf die Quiz-Seite zurück zu bringen. Leider gelangt man damit auch zurück zum ersten Datensatz - die aktuelle Datensatznummer wird nicht beibehalten.

Um dieses Problem zu umgehen, muss der eingebettete Quellcode bearbeitet werden, um diese Funktionalität zu deaktivieren.

Das Problem ist, nicht zum neuen Datensatz zu gehen, wenn das Formular gesendet wird. Die Lösung für dieses Dilemma liegt in der Betrachtung des Links Frage überspringen, der bereits im Dokument enthalten ist:

<A HREF="<%=MM_moveNext%>">FRAGE ÜBERSPRINGEN</A>

Wenn wir anstelle der aktuellen Formularaktion den Code <%=MM_moveNext%> verwenden, geht die Seite zum nächsten Datensatz weiter, ähnlich wie der Link Frage überspringen. Bearbeiten Sie den Anfang Ihres Formulars wie hier gezeigt:

<form name="saveResponse" method="post" action="<%=MM_moveNext%>">
<table width="100%" border="0" cellspacing="0" cellpadding="2">
<tr align="center" bgcolor="#CCCCFF">
<td>&nbsp;</td>

Falls Sie das HTML nicht manuell bearbeiten wollen, markieren Sie das Formular, öffnen die Eigenschaftenpalette und ändern die Aktion des Formulars auf <%=MM_moveNext%>.

Testen Sie die Seite erneut; jetzt sollte sich das Programm verhalten wie erwartet.

Frühere UltraDev-Versionen hätten versucht, den Browser umzuleiten, wenn das Feld Nach dem Einfügen hierher gehen nicht ausgefüllt wird. - was normalerweise in einer Fehlermeldung resultiert. Um das in UltraDev 1.0 zu umgehen, musste der Code manuell bearbeitet und die von UltraDev eingefügten Umleitungsanweisungen entfernt werden.

Korrekte Antworten bewerten (optional)

Während der Benutzer den Test bearbeitet, wird eine Tabelle mit Informationen zu seinen Antworten angelegt. Diese Antworten könnten jederzeit ausgewertet werden, um festzustellen, wie viele richtige Antworten der Benutzer gegeben hat. Für den Benutzer kann diese Bewertung ganz informativ sein - abhängig davon, wie Sie die Online- Prüfungen betrachten. Wenn Sie Ihrer Prüfungsseite diese Information hinzufügen wollen, dann sollten Sie diesen Abschnitt lesen. Andernfalls blättern Sie weiter zum nächsten Kapitel.

Das in diesem Kapitel entwickelte SQL zeigt eine Liste der korrekten Antworten des Benutzers an:

select * from response,question where response.username='jray'
AND response.answerID=question.answerID AND
response.questionID=question.questionID;

Diesen Code haben wir bereits. Mithilfe dieses SQL und der Sitzungsvariablen MM_Username können wir auf der Seite quiz.asp eine Echtzeit-Bewertung anzeigen:

Fügen Sie dem System eine neue Datensatzgruppe hinzu, um das Ganze anzukurbeln:

  1. Öffnen Sie die Palette Serververhalten, und legen Sie eine neue Datensatzgruppe an.
  2. Gehen Sie in den erweiterten Abfragemodus.
  3. Definieren Sie die neue Datensatzgruppe rsCorrect, die alle gültigen Benutzerantworten enthält.
  4. Geben Sie den folgenden Code in die SQL-Definition ein: select * from response,question where response.username='varUsername' AND response.answerID=question.answerID AND response.
    questionID=question.questionID
  5. Fügen Sie die neue UltraDev-Variable varUsername ein und geben Sie ihr den Laufzeitwert Session("MM_Username").
  6. Klicken Sie auf OK.

Abbildung 19.13 zeigt die vollständige Datensatzgruppe.

Abbildung 19.13:  Definieren Sie diese erweiterte Abfrage, um die Anzahl der korrekten Antworten für den aktuellen Benutzer zu berechnen.

In einer perfekten Welt wären wir fertig, sobald wir das Feld [total records] aus der neuen Datensatzgruppe in die Entwurfsansicht verschoben hätten, aber wir leben leider nicht in einer perfekten Welt. Wie wir aus Erfahrungen der Vergangenheit wissen, ist UltraDev nicht perfekt. Es ist ziemlich gut - aber eben nicht perfekt.

Als wir den Code in UltraDev manuell an eine andere Position verschoben haben, haben wir es damit richtig verwirrt. Die neue Datensatzgruppe, die wir hinzugefügt haben, wurde unten in dem eingebetteten Code definiert, während es Funktionen unterstützt, die in der Mitte definiert werden. Wir müssen nur noch den problematischen Codeblock finden und ihn an die richtige Position verschieben.

Öffnen Sie den Quellcode für Ihr Dokument und suchen Sie nach dem folgenden Block:

1 %
2 Dim rsCorrect__varUsername
3 rsCorrect__varUsername = "jray"
4 if (Session("MM_Username") <> "") then
5 rsCorrect__varUsername = Session("MM_Username")
6 %>
7 <%
8 set rsCorrect = Server.CreateObject("ADODB.Recordset")
9 rsCorrect.ActiveConnection = MM_connChapter19_STRING
10 rsCorrect.Source = "SELECT * FROM response,question
11 WHERE response.username='" + Replace(rsCorrect__varUsername, "'", "''")
=>;+ "'
12 AND response.answerID=question.answerID
13 AND response.questionID=question.questionID"
14 rsCorrect.CursorType = 0
15 rsCorrect.CursorLocation = 2
16 rsCorrect.LockType = 3
17 rsCorrect.Open()
18 rsCorrect_numRows = 0
19 %>

Diesen Code finden Sie in der Nähe des Anfangs des HTML-Rumpfs für Ihre Seite. Er definiert die Datensatzgruppe rsCorrect, die Sie zuvor erstellt haben.

1 <%
2 set rsQuestion = Server.CreateObject("ADODB.Recordset")
3 rsQuestion.ActiveConnection = MM_connChapter19_STRING
4 rsQuestion.Source = "SELECT * FROM question"
5 rsQuestion.CursorType = 0
6 rsQuestion.CursorLocation = 2
7 rsQuestion.LockType = 3
8 rsQuestion.Open()
9 rsQuestion_numRows = 0
10 %>
11 <%
12 set rsResponse = Server.CreateObject("ADODB.Recordset")
13 rsResponse.ActiveConnection = MM_connChapter19_STRING
14 rsResponse.Source = "SELECT * FROM response"
15 rsResponse.CursorType = 0
16 rsResponse.CursorLocation = 2
17 rsResponse.LockType = 3
18 rsResponse.Open()
19 rsResponse_numRows = 0
20 %> <%
21 Dim rsCorrect__varUsername
22 rsCorrect__varUsername = "jray"
23 if (Session("MM_Username") <> "") then
24 rsCorrect__varUsername = Session("MM_Username")
25 %>
26 <%
27 set rsCorrect = Server.CreateObject("ADODB.Recordset")
28 rsCorrect.ActiveConnection = MM_connChapter19_STRING
29 rsCorrect.Source = "SELECT * FROM response,question
30 WHERE response.username='" + Replace(rsCorrect__varUsername, "'", "''")
=>;+ "'
31 AND response.answerID=question.answerID
32 AND response.questionID=question.questionID"
33 rsCorrect.CursorType = 0
34 rsCorrect.CursorLocation = 2
35 rsCorrect.LockType = 3
36 rsCorrect.Open()
37 rsCorrect_numRows = 0
38 %>

Die hier gezeigten Datensatzmengen sind question (1-10), response (12-20) und die neu erstellte Datensatzgruppen correct response (20-38). Wenn Sie in dem Kapitel Dinge übersprungen haben, befinden sich Ihre Definitionen vielleicht nicht an derselben Stelle, aber Sie sollten sie dennoch finden.

Damit sind wir fertig. Fügen Sie ein [Total Records]-Feld in Ihre Entwurfsansicht ein - das ist der Zähler der vom Benutzer richtig eingegebenen Antworten. Glückwunsch! Damit haben Sie eine der verzwicktesten Komponenten des Systems implementiert.

Das Quiz beenden

Das System ist jetzt so weit implementiert, dass der Benutzer den Test bis zur letzten Frage bearbeiten kann. Leider bleibt ihm nach der Beantwortung der letzten Frage keine andere Möglichkeit, als sie zu beantworten (was nicht möglich ist, weil er bereits eine Antwort auf diese Frage eingegeben hat).

Um das Quiz zu beenden, brauchen wir ein leicht abgeändertes Bereich verbergen- Verhalten. Außerdem müssen wir dem Dokument eine weitere Datensatzgruppe hinzufügen. Diese Datensatzgruppe enthält alle vom Benutzer gegebenen Antworten - wenn wir diese Zahl mit der Gesamtzahl der Datensätze vergleichen, können wir feststellen, ob der Benutzer alle Fragen beantwortet hat. Jetzt fügen wir dem Dokument diese Datensatzgruppe hinzu. Ich verspreche Ihnen, dass dies die letzte Datensatzgruppe für diese Seite ist!

Fügen Sie die Datensatzgruppe wie folgt ein:

  1. Fügen Sie ein neues Datensatzgruppe-Serververhalten ein.
  2. Gehen Sie gegebenenfalls in den einfachen Modus.
  3. Legen Sie die neue Datensatzgruppe unter dem Namen rsResponseAll ab, weil es alle Antworten aufnimmt.
  4. Konfigurieren Sie die Abfrage so, dass in der Antwortentabelle der Datenbank alles ausgewählt wird.
  5. Filtern Sie die Abfrage abhängig von der Spalte für den Benutzernamen, der gleich der Sitzungsvariable MM_Username ist.
  6. Klicken Sie auf OK.

Diese Datensatzgruppen-Definition sehen Sie in Abbildung 19.14. Ihre Definition sollte vergleichbar aussehen.

Abbildung 19.14:  Definieren Sie Ihre Datensatzgruppe wie hier gezeigt.

Auch hier hat UltraDev dieses Serververhalten im Dokument an der falschen Stelle angeordnet. Wenn Sie den letzten optionalen Abschnitt gelesen haben, wissen Sie, dass dies passiert ist, weil wir den Code manuell bearbeitet und damit UltraDev verwirrt haben - falls Sie es nicht gelesen haben, wissen Sie es jetzt.

Suchen Sie in Ihrem HTML-Quellcode nach dem Bereich, der Ihre neue Datensatzgruppe definiert:

1 <%
2 Dim rsResponseAll__MMColParam
3 rsResponseAll__MMColParam = "0"
4 if (Session("MM_Username") <> "") then
5 rsResponseAll__MMColParam = Session("MM_Username")
6 %> <%
7 set rsResponseAll = Server.CreateObject("ADODB.Recordset")
8 rsResponseAll.ActiveConnection = MM_connChapter19_STRING
9 rsResponseAll.Source = "SELECT * FROM response
10 WHERE username = '" + Replace(rsResponseAll__MMColParam, "'", "''") + "'"
11 rsResponseAll.CursorType = 0
12 rsResponseAll.CursorLocation = 2
13 rsResponseAll.LockType = 3
14 rsResponseAll.Open()
15 rsResponseAll_numRows = 0
16 %>

Sehr wahrscheinlich befindet sich dieser Code relativ weit am Anfang Ihres HTML. Markieren Sie diesen Codeabschnitt (inklusive der öffnenden und schließenden Tags) und verschieben Sie ihn an den Anfang Ihres Dokuments - zu den anderen Datensatzgruppen- Definitionen. Ihr Code sollte anschließend wie folgt aussehen:

1 <%
2 set rsQuestion = Server.CreateObject("ADODB.Recordset")
3 rsQuestion.ActiveConnection = MM_connChapter19_STRING
4 rsQuestion.Source = "SELECT * FROM question"
5 rsQuestion.CursorType = 0
6 rsQuestion.CursorLocation = 2
7 rsQuestion.LockType = 3
8 rsQuestion.Open()
9 rsQuestion_numRows = 0
10 %>
11 <%
12 set rsResponse = Server.CreateObject("ADODB.Recordset")
13 rsResponse.ActiveConnection = MM_connChapter19_STRING
14 rsResponse.Source = "SELECT * FROM response"
15 rsResponse.CursorType = 0
16 rsResponse.CursorLocation = 2
17 rsResponse.LockType = 3
18 rsResponse.Open()
19 rsResponse_numRows = 0
20 %> <%
21 Dim rsCorrect__varUsername
22 rsCorrect__varUsername = "jray"
23 if (Session("MM_Username") <> "") then
24 rsCorrect__varUsername = Session("MM_Username")
25 %>
26 <%
27 set rsCorrect = Server.CreateObject("ADODB.Recordset")
28 rsCorrect.ActiveConnection = MM_connChapter19_STRING
29 rsCorrect.Source = "SELECT * FROM response,question
30 WHERE response.username='" + Replace(rsCorrect__varUsername, "'", "''")
=>;+ "'
31 AND response.answerID=question.answerID
32 AND response.questionID=question.questionID"
33 rsCorrect.CursorType = 0
34 rsCorrect.CursorLocation = 2
35 rsCorrect.LockType = 3
36 rsCorrect.Open()
37 rsCorrect_numRows = 0
38 %>
39 <%
40 Dim rsResponseAll__MMColParam
41 rsResponseAll__MMColParam = "0"
42 if (Session("MM_Username") <> "") then
43 rsResponseAll__MMColParam = Session("MM_Username")
44 %> <%
45 set rsResponseAll = Server.CreateObject("ADODB.Recordset")
46 rsResponseAll.ActiveConnection = MM_connChapter19_STRING
47 rsResponseAll.Source = "SELECT * FROM response
48 WHERE username = '" + Replace(rsResponseAll__MMColParam, "'", "''") + "'"
49 rsResponseAll.CursorType = 0
50 rsResponseAll.CursorLocation = 2
51 rsResponseAll.LockType = 3
52 rsResponseAll.Open()
53 rsResponseAll_numRows = 0
54 %>

Darin ist die optionale Datensatzgruppe enthalten, die die Anzahl der richtigen Antworten im Dokument anzeigt. In Ihrem Quellcode fehlt möglicherweise diese letzte Datensatzgruppen-Definition, wenn Sie den Abschnitt übersprungen haben, in dem die Ausgabe der Anzahl korrekter Antworten implementiert wurde.

Bevor wir den verborgenen Bereich für das Beenden des Quiz fertig stellen können, sind zwei weitere Schritte erforderlich. Öffnen Sie die Frage-Datensatzgruppe in der Palette Datenbindungen, und ziehen Sie das Feld [Total Records] in Ihr Dokument. Genau so gehen Sie für dasselbe Feld in Ihrer neuen Datensatzgruppe vor. Testen Sie die Applikation, um sicherzustellen, dass die beiden Zahlen korrekt ermittelt werden - die eine sollte die Gesamtzahl der Fragen darstellen, während die andere die Gesamtzahl der eingegebenen Antworten repräsentiert.

UltraDev fügt einen speziellen Code ein, um die Gesamtzahl der Datensätze in der Datensatzgruppe zu berechnen. Wenn Sie diese Elemente in Ihrem Dokument verwenden, ist sichergestellt, dass der unterstützende Code erstellt wird. Wenn im Testlauf alles korrekt zu sein scheint, fügen Sie einen letzten verborgenen Bereich ein.

Weil es kein Serververhalten gibt, das die von uns benötigte Aktion realisiert, fügen Sie dieses Verhalten manuell ein. Wir wollen die Variablen vergleichen, die die Gesamtzahl der Datensätze in der Datensatzgruppe Question und in der Datensatzgruppe All Responses vergleichen: rsQuestion_total bzw. rsResponseAll_total.

Möglicherweise müssen Sie variable IDs anpassen, wenn Sie Ihre Datensatzgruppe unter einem anderen Namen abgelegt haben. Mithilfe der dynamischen Total Record-Elemente, die Sie dem Dokument hinzugefügt haben, sollten Sie in der Lage sein herauszufinden, wie diese Namen aussehen sollten.

Sind diese beiden Werte nicht gleich, sollte das Quiz angezeigt werden. Sind sie gleich, sollte das Dokument dem Benutzer die Meldung »Ihr Test ist beendet« anzeigen. Dazu stellen Sie einfach eine If-Then-Anweisung um den Code, den Sie verbergen wollen:

<% If rsResponseAll_total <> rsQuestion_total Then %>
<table width="100%" border="0" cellspacing="0" cellpadding="2">
<tr align="center" bgcolor="#CCCCFF">
... <hier steht das HTML für das Quiz>
</tr>
</table>
<% End If %>

Damit wird geprüft, ob die Anzahl der Antworten gleich der Anzahl der Fragen ist. Sind sie ungleich, wird das Quiz angezeigt. Sind sie gleich, ist das Quiz abgeschlossen und das HTML zwischen den If- und den End If-Anweisungen wird verborgen.

Analog könnte der Code für die Meldung an den Benutzer die folgende Bedingung verwenden:

<% If rsResponseAll_total = rsQuestion_total Then %>
Glückwunsch! Sie haben das Quiz abgeschlossen!
<% End If %>

Offensichtlich können Sie in diese Bereiche beliebige Dinge einsetzen. Stellen Sie den HTML-Code für diesen Abschnitt des Quiz fertig und Sie sind fertig! Das ist ein komplizierter Bildschirm, aber Sie haben es geschafft!

Bei der Realisierung dieser letzten Funktionalität haben wir dem Quellcode eine recht praktische Funktion hinzugefügt. Weil das Quiz nicht abgeschlossen ist, bis die Anzahl der Antworten gleich der Anzahl der Fragen ist, kann der Benutzer immer auf die Seite zurückgehen und die Fragen vervollständigen, die er zuvor übersprungen hat.

Er kann jedoch nicht eine neue Antwort auf eine Frage übergeben, die er bereits beantwortet hat. Durch die Verwendung von questionID und username als Primärschlüssel wird sichergestellt, dass für jeden Benutzer im System jeweils nur eine Antwort vorhanden sein kann.

Das Quiz schützen

Um den Quiz-Bildschirm zu schützen, wenden Sie das Serververhalten Zugriff auf Seite beschränken an. Öffnen Sie die Palette Serververhalten, und gehen Sie wie folgt vor, um den Zugriff auf Ihre Seite zu beschränken:

  1. Klicken Sie auf der Palette Serververhalten auf das Plussymbol (+), und wählen Sie im Menü Benutzerauthentifizierung den Eintrag Zugriff auf Seite beschränken.
  2. Schränken Sie den Zugriff abhängig von Benutzername, Kennwort und Zugriffsebene ein.
  3. Definieren Sie zwei Zugriffsebenen, Schüler und Lehrer, indem Sie auf die Schaltfläche Definieren klicken und mit dem Plussymbol (+) neue Ebenen einfügen.
  4. Beschränken Sie den Zugriff auf die Ebenen Schüler und Lehrer - d.h. jeder kann an dem Quiz teilnehmen, auch jemand mit Lehrer-Zugriff.
  5. Falls der Zugriff verweigert wird, soll der Benutzer zurück auf die Anmeldeseite gelangen. Das ist in diesem Fall index.asp.
  6. Nachdem wir fertig sind, sollte das Verhalten wie in Abbildung 19.15 gezeigt konfiguriert sein. Klicken Sie auf OK, um die Definition abzuschließen.

    Abbildung 19.15:  Beschränken Sie den Zugriff auf die Seite abhängig von dem Benutzernamen, dem Kennwort und der Zugriffsebene.

Um einen einfachen Zugriff auf den Administrationsabschnitt zu bieten, könnten Sie einen Admin-Link im Dokument quiz.asp anlegen, der zu dem administrativen Abschnitt führt, den Sie gleich anlegen werden (admin1.asp) - andernfalls müssten die Administratoren die URL manuell eingeben.

19.4 Administrativer Zugriff

Wir schließen das Kapitel mit der Implementierung einer Administrationsoberfläche ab, die dem Prüfungs-Administrator ermöglichen soll, die Ergebnisse der Prüfungsteilnehmer einfach einzusehen. Das dauert nur eine Sekunde (oder eine Stunde, abhängig von der Genauigkeit Ihrer Uhr).

Als erstes entwickeln Sie einen Bildschirm mit einem einfachen Formular, in das Sie den Namen des Benutzers eingeben, dessen Ergebnisse eingesehen werden sollen. Sie brauchen dazu nur ein einziges Feld, username, und eine Senden-Schaltfläche, das ist alles. Diese Seite verwendet keine Serververhalten. Abbildung 19.16 zeigt einen Beispiel- Bildschirm für die Realisierung dieser Funktion.

Abbildung 19.16:  Der erste Bildschirm der Administratoroberfläche ist relativ einfach.

Ich habe das Feld für den Benutzernamen in meiner Version als username bezeichnet - wenn Sie das Beispiel genau nachvollziehen wollen, sollten Sie das auch tun. Die Aktion des Formulars wird auf die zweite administrative Seite gesetzt, admin2.asp.

Der Ergebnis-Bildschirm

Nachdem Sie die erste administrative Seite fertiggestellt haben, legen Sie die zweite Seite an. Verwenden Sie dafür unbedingt den Namen, auf den Sie in der Aktion der ersten Seite verwiesen haben.

Bevor Sie diesen Bildschirm entwerfen können, müssen Sie zwei Datensatzgruppen anlegen. Diese Abfragen erzeugen Listen der richtigen Benutzerantworten und der falschen Benutzerantworten. Wir haben bereits eine Abfrage, die diese Aufgabe erledigt:

select * from response,question where response.username='varUsername' 
AND response.answerID=question.answerID
AND response.questionID=question.questionID;

Das SQL für falsche Antworten ist ganz ähnlich; nur der Vergleich zwischen response.answerID und question.answerID muss abgeändert werden:

select * from response,question where response.username='varUsername' 
AND response.answered!=question.answerID
AND response.questionID=question.questionID;

Entwerfen Sie jetzt die Datensatzgruppen rsCorrect und rsIncorrect:

  1. Öffnen Sie die Palette Serververhalten.
  2. Klicken Sie auf das Plussymbol (+) und wählen Sie das Verhalten Datensatzgruppe (Abfrage).
  3. Gehen Sie gegebenenfalls in den erweiterten Abfragemodus.
  4. Fügen Sie den Datensatzgruppennamen und die Abfrage für die erste Datensatzgruppe ein, rsCorrect.
  5. Definieren Sie die UltraDev-Variable varUsername mit dem Laufzeitwert Request("username") - vorausgesetzt, username ist der Name des Felds, das Sie von dem ersten administrativen Formular aus übergeben haben.
  6. Klicken Sie auf OK.
  7. Wiederholen Sie diesen Prozess für die Datensatzgruppe rsIncorrect.

Abbildung 19.17 zeigt die Abfragedefinition für die Datensatzgruppe mit den korrekten Antworten.

Abbildung 19.17:  Definieren Sie beide Datensatzgruppen für diese Seite dieser Vorgabe entsprechend.

Jetzt können Sie unter Verwendung der beiden definierten Datensatzgruppen Ihre Ergebnisseite entwerfen. Das Feld [Total Records] kann genutzt werden, um die Gesamtzahl der richtigen Antworten anzuzeigen, oder die Gesamtzahl der falschen Antworten (abhängig davon, ob Sie sie aus der Datensatzgruppe rsCorrect oder rsIncorrect eingefügt haben).

Es wäre sinnvoll, die Titel der Fragen anzuzeigen, die der Benutzer richtig oder falsch beantwortet hat. Diese Funktion fügen Sie Ihrer Seite hinzu, indem Sie die entsprechenden Felder in Ihre Dokumententwurfsansicht verschieben und dann das Serververhalten Bereich wiederholen auf die Felder anwenden. Mein Bildschirm für den administrativen Überblick sieht wie in Abbildung 19.18 gezeigt aus.

Abbildung 19.18:  Fügen Sie die gewünschten Funktionen und Informationen in den Bildschirm für den administrativen Überblick ein.

Im letzten Schritt schützen Sie die administrativen Bildschirme admin1.asp und admin2.asp so, wie Sie die Datei quiz.asp geschützt haben:

  1. Öffnen Sie die Palette Serververhalten.
  2. Klicken Sie auf das Plussymbol (+), und wählen Sie im Menü Benutzerauthentifizierung den Eintrag Zugriff auf Seite beschränken.
  3. Schränken Sie den Zugriff abhängig von Benutzername, Kennwort und Zugriffsebene ein.
  4. Beschränken Sie den Zugriff auf die Ebene Lehrer. Damit wird verhindert, dass Studenten die Ergebnisse und Antworten einsehen können.
  5. Falls der Zugriff verweigert wird, soll der Benutzer zurück auf die Anmeldeseite gelangen. Das ist in diesem Fall index.asp.
  6. Nachdem Sie fertig sind, klicken Sie auf OK.

Das ist alles. Das Projekt für dieses Kapitel ist fertig. Sie haben ausreichend viel Erfahrung, um aus diesem Beispiel ein vollfunktionales Prüfungssystem zu machen - oder es so zu belassen, wie es ist.

19.5 Zusammenfassung

In dem heutigen Projekt haben wir eine Applikation mit Funktionsmerkmalen angelegt, die Sie zuvor noch nie in UltraDev-Applikationen gesehen haben. Beispielsweise wurde das Verhalten Nach dem Einfügen hierher gehen umgangen, nachdem Daten eingefügt wurden. Dies ist nur eine der vielen Änderungen, die wir an dem heute vorgestellten Code vorgenommen haben.

Leider hatten diese Änderungen auch ihren Preis. Durch das Hinzufügen von benutzerdefiniertem Code und die Abänderung des automatisch erzeugten Codes haben wir UltraDev verwirrt und es konnte die Seite nicht mehr korrekt verwalten. Nachdem wir den Code manuell geändert hatten, fügte UltraDev Verhalten an der falschen Position ein und wir mussten die Dinge immer wieder an die richtige Stelle schieben. Schließlich kann UltraDev nicht Gedanken lesen und hat sein Bestes getan. Selbst mit den heute aufgetretenen Problemen ist es seinen Konkurrenten immer noch um Lichtjahre voraus.

Zuletzt möchte ich noch anmerken, dass das heutige Projekt zwar ein funktionierendes System darstellt, aber dennoch beliebig erweiterbar ist. Eine vollständige Prüfungs-Site könnte vor der Prüfung Lehrmaterial anzeigen usw. Erweitern Sie das Projekt nach Ihren Vorstellungen.

19.6 Fragen und Antworten

Frage:
Die Sicherheit des Quiz... wie sicher ist es?

Antwort:
In Hinblick auf die korrekte Verarbeitung der Fragen ist es sicher, aber es hat das Problem, dass ein Benutzer seine Identität vortäuschen kann, indem er den Benutzernamen im Formular ändert. Wenn die Sicherheit für Sie wichtig ist, sollten Sie das verborgene Feld, das mit diesem Wert übergeben wird, ersetzen, sodass er ausschließlich über die Sitzungsvariable MM_Username verwaltet wird.

Frage:
Was ist der Unterschied zwischen der Funktion Nach dem Einfügen hierher gehen und dem Überspringen der Seitenumleitung?

Antwort:
Wenn wir nur auf die Seite umleiten, auf der wir uns beim Einfügen-Verhalten befanden, würden wir zurück zum Anfang der Fragen gelangen. Durch Umleitung zu einer URL wird der aktuelle Datensatzgruppen-Offset nicht mit übergeben und das Quiz würde von vorne beginnen.

Frage:
Was passiert, wenn der Benutzer eine Frage beantwortet, die er bereits beantwortet hat?

Antwort:
Das System erzeugt einen Fehler, weil für jeden Benutzer nur ein einziger Datensatz existieren kann. Im Abschnitt »Übungen« finden Sie einen Hinweis, wie dieses Problem behoben werden könnte.

Frage:
Können in einer einzigen Datenbank mehrere Prüfungen aufbewahrt werden?

Antwort:
Ja, natürlich. Wenn Sie das Fragenthema als Attribut der Hauptabfrage für die Fragen verwendet haben, könnten Sie die Themen des Quiz beschränken. Sie könnten die Datenbank auch erweitern, sodass ein zusätzliches Kategoriefeld als Attribut zur Auswahl von Fragen verwendet werden kann.

19.7 Workshop

Der Workshop dient dazu, den gelesenen Stoff mithilfe von gezielten Fragen und Übungen zu vertiefen. Die Antworten finden Sie in Anhang A, »Quiz-Antworten«.

Quiz

  1. Warum haben wir das Verhalten Nach dem Einfügen hierher gehen umgangen, das in dem Verhalten Datensatz einfügen enthalten ist?
  2. Wie wird die Sicherheit des Administrationsabschnitts realisiert?
  3. Warum mussten Sie in diesem Kapitel Code manuell verschieben?
  4. Wie haben wir einen Bereich ohne das Verhalten Bereich verbergen verborgen?
  5. Es gibt kein Serververhalten, um einen Bereich zu verbergen, wenn das Quiz beendet ist - wie haben wir es dann geschafft?

Übungen

  1. Das Programm schlägt in seinem aktuellen Zustand fehl, wenn der Benutzer versucht, eine Antwort mehrmals zu beantworten. Optimal bearbeitet man diese Situation, indem man nur Fragen anzeigt, zu denen es keine entsprechenden Benutzerantworten gibt. Ändern Sie Ihr SQL so ab, dass es auf diese Weise funktioniert.
  2. Fügen Sie dem Frage- und Antwortabschnitt ein administratives Frontend hinzu. Dazu legen Sie ein paar einfache Eingabeseiten an und verknüpfen sie - was ein benutzerfreundlicheres System für die Leute darstellt, die die Tests durchführen.
  3. Korrigieren Sie das Sicherheitsproblem dahingehend, dass der Benutzername von dem Quiz-Formular aus geändert werden kann. Dazu verwenden Sie die Sitzungsvariable Session("MM_username") direkt, wenn die Daten für eine bestimmte Frage gespeichert werden.



vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbackKapitelanfangnächstes Kapitel


© Markt+Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH