====== Punkte für Antworten zählen ======

In den meisten sozialwissenschaftlichen Befragungen ist man an der Meinung der Teilnehmer interessiert -- nicht so, wenn man Feedback zu einem Wissenstest geben möchte. Hier gibt es richtige und falsche Antworten und man kann einen Punktwert ermitteln. Auch bei live-Auswertungen (z.B. einer Thurstone- oder Likert-Skala) darf man mitunter Punkte zählen. So lässt sich als Incentive etwa eine Auswertung des Persönlichkeitstests am Ende des Fragebogens bauen.

**Tipp:** Die PHP-Code Beispiele auf dieser Seite sehen sehr lang aus -- das liegt daran, dass jeder Schritt einzeln ausgeführt und kommentiert wurde. Lassen Sie sich von der Länge nicht erschrecken.

**Tipp:** Lesen Sie zum Verständnis der Code-Beispiele die Kapitel [[:de:create:php|Einführung in PHP-Code]] und [[:de:create:array|Einführung in Arrays]].

**Tipp:** Wenn Sie für eine Auswertung lediglich [[:de:general:indices|Skalenindizes]] berechnen möchten, stehen dafür die Funktionen ''[[:de:create:functions:valuesum|valueSum()]]'' und ''[[:de:create:functions:valuemean|valueMean()]]'' zur Verfügung.


===== Richtige und falsche Antworten =====

Die einfachste Anwendung, bei der man Punkte zählt ist ein Quiz bzw. Wissentest. Hier gibt es eine Reihe von Auswahl-Fragen und es ist jeweils eine der Auswahloptionen richtig.

Der folgende PHP-Code definiert zunächst, welche Fragen ausgewertet werden und wie die richtige Antwort lautet. Dafür wird ein [[:de:create:array|assoziatives Array]] verwendet: Als Schlüssel für jeden Eintrag im Array wird die Kennung der Variable (bei Auswahlfragen entsprechend der Frage-Kennung) verwendet. Als Wert wird jener Antwortcode zugewiesen, der als "richtig" gezählt werden soll.

Anschließend werden alle Fragen in einer FOR-Schleife geprüft -- das ist wesentlich kompakter als dutzende IF-Konstruktionen.

<code php>
// Definition der Fragen und der korrekten Antworten
$fragen = array(
  'AB01' => 3,  // In Frage AB01 ist die richtige Antwort die 3
  'AB02' => 1,  // In AB02 hat die richtige Antwort den Code 1
  'AB03' => 4,  // Bei AB03 versteckt sich die richtige Antwort hinter dem Code 4
  'AB04' => 2,
  'AB05' => 1
  // u.s.w.
);

// Initialisierung einer Zähler-Variable
$points = 0;

// Prüfung aller Fragen in einer Schleife
foreach ($fragen as $variable=>$correct) {
  // Die Antwort des Teilnehmers abrufen
  $answer = value($variable);
  // Überprüfen und ggf. einen Punkt zählen
  if ($answer == $correct) {
    $points++;  // Gleichbedeutend mit $points = $points + 1
  }
}

// Das Ergebnis anzeigen ...
html('<p>Sie haben '.$points.' Punkte erzielt.</p>');
// ... oder in einer internen Variable speichern
put('IV01_01', $points);
</code>

Eine kompaktere Programmierung des Zähl-Teils sieht wie folgt aus:

<code php>
// ...

// Prüfung aller Fragen in einer Schleife
foreach ($fragen as $variable=>$correct) {
  if (value($variable) == $correct) {
    $points++;
  }
}

// Das Ergebnis anzeigen oder anderweitig verarbeiten
// ...
</code>


===== Verschiedene Punktwerte =====

Bei einer Skala nach Thurstone hat jede Antwort einen anderen Wert -- auch dies lässt sich in einer Array-Struktur gut abbilden. Dabei wird zu jeder Frage ein Array mit Antwort-Werten gespeichert. 

<code php>
// Definition der Fragen und der Werte möglicher Antworten
$fragen = array(
  'AB01' => array(1 => 2, 2 => 5, 3 => 3),  // In Frage AB01 hat die Antwort 1 den Wert 2, 2 hat den Wert 5, 3 den Wert 3
  'AB02' => array(1 => 5, 2 => 4, 3 => 1),  // Für AB02 werden die Werte 5 (Antwort 1), 4 (2) und 1 (3) vergeben
  'AB03' => array(1 => 0, 2 => 0, 3 => 5),
  'AB04' => array(1 => 4, 2 => 0, 3 => 3)
  'AB05' => array(1 => 2, 2 => 2, 3 => 5)
  // u.s.w.
);

// Zähl-Variable initialisieren
$points = 0;

// Mittels foreach kann man einfach die Schlüssel-Wert-Paare durchlaufen
foreach ($fragen as $variable => $values) {
  // Antwort des Teilnehmers abrufen
  $answer = value($variable);
  // Prüfen, ob für diese Antwort ein Wert vorliegt (sonst keinen Punkt vergeben)
  if (isset($values[$answer])) {
    // Zählen des Wertes
    $points += $values[$answer];
  }
}

// Das Ergebnis anzeigen oder anderweitig verarbeiten
html('<p>Sie haben '.$points.' Punkte erzielt.</p>');
</code>


===== Skalen mit gedrehten Items =====

Auch für Likert-Skalen bzw. Teilskalen benötigt man hin und wieder einen Punktwert. Das Aufaddieren aller Items einer Skala ist trivial:

<code php>
$points = valueSum('AB01');

// Das Ergebnis anzeigen oder anderweitig verarbeiten
html('<p>Sie haben '.$points.' Punkte erzielt.</p>');
</code>

Man kann die Items natürlich auch einzeln abfragen, wie folgendes Beispiel zeigt:

<code php>
// Liste aller Items abrufen
$items = getItems('AB01');

// Summenvariable initialieren
$points = 0;

// Alle Items durchgehen
foreach ($items as $item) {
  // Die Frage-Kennung muss man noch zusammenbauen
  $kennung = 'AB01_'.sprintf('%02d', $item);
  // Antwort des Teilnehmers abrufen
  $antwort = value($kennung);
  // Es kann sein, dass ein Fehlercode (z.B. -1 für "keine Antwort") gespeichert wurde,
  // sonst die Antwort zählen
  if ($antwort > 0) {
    $points += $antwort;
  }
}

// Das Ergebnis anzeigen oder anderweitig verarbeiten
html('<p>Sie haben '.$points.' Punkte erzielt.</p>');
</code>

Die Codes reichen in SoSci Survey jeweils von 1 bis zum Skalenniveau. Falls man statt des Wertebereichs 1-5 lieber 0-4 aufaddieren möchte, muss man lediglich bei jeder Antwort 1 subtrahieren:

<code php>
    $points += $antwort - 1;
</code>

Nur minimal komplizierter wird es, wenn man eine Teilskala aufsummieren will oder die Items "gedreht" sind, also einige negativ, andere positiv formuliert. Hier legt man wieder in einem Array fest, welche Items und mit welcher Richtung man sie zählen will.

**Tipp:** Definieren Sie gedrehte Items gleich als solche (Item im **Fragenkatalog** auswählen -> //Antwortcodes für dieses Item invertieren//). Dann ersparen Sie sich den zusätzlichen Aufwand.

<code php>
// Liste der Items - jeweils mit Angabe der Polung
$items = array(
  '01' => +1,
  '02' => -1,
  '03' => +1,
  '04' => +1,
  '05' => -1
  // u.s.w.
);

// Initialisierung der Summenvariable
$points = 0;

// Alle Items durchlaufen
foreach ($items as $item => $polung) {
  // Auch hier baut man sich aus Frage- und Item-Kennung die Variablen-Kennung
  $kennung = 'AB01_'.$item;
  // Antwort des Befragten anrufen
  $antwort = value($kennung);
  // Ignorieren, falls es keine gültige Antwort ist
  if ($antwort < 1) {
    // Damit wird der Rest in der FOR-/FOREACH-Schleife ignoriert
    continue;
  }
  // Antworte "drehen"
  if ($polung < 0) {
    // Bei einer 5er-Skala erhält man den gedrehten Wert als 6-Antwortcode,
    // für andre Skalenniveaus muss die Konstante angepasst werden.
    $antwort = 6 - $antwort;
  }
  // Aufaddieren
  $points += $antwort;
}

// Das Ergebnis anzeigen oder anderweitig verarbeiten
html('<p>Sie haben '.$points.' Punkte erzielt.</p>');
</code>


===== Multiple Choice Antwortmuster =====

Mitunter müssen für die Überprüfung einer Antwort mehrere Bedingungen kombiniert werden. Hat man zum Beispiel eine Mehrfachauswahl mit 4 Antwortvorgaben und will prüfen, ob die ersten beiden Optionen ausgewählt wurden, die letzten beiden aber nicht, so könnte man das mittels IF-Konstruktion wie folgt lösen.

<code php>
if (
  (value('AB01_01') == 2) and
  (value('AB01_02') == 2) and
  (value('AB01_03') == 1) and
  (value('AB01_04') == 1)
) {
  // Punkt zählen, an eine andere Stelle springen oder einfach eine Meldung anzeigen
  html('<p>Korrekt</p>');
} else {
  html('<p>Falsch</p>');
}
</code>

Die Verwendung Bool'scher Operatoren (UND bzw. ODER) wird im Kapitel [[filter-boolean|Mehrere Bedingungen verknüpfen]] genauer beschrieben. Falls man aber mehrere Fragen dieses Typs hat und jeweils unterschiedliche Antwortmuster überprüfen will, kann man auch dies mit einem Array und einer Schleife eleganter lösen. Folgender Code zählt für Multiple Choice-Fragen á 4 Antwortvorgaben jeweils einen Punkt für jede vollkommen korrekt beantwortete Frage.

<code php>
// Definition der Fragen und der korrekten Antworten
// Es werden nur jene Items definiert, die auch überprüft werden sollen
$fragen = array(
  // In der Frage AB01 müssen 1 und 2 angekreuzt sein, 3 und 4 dürfen nicht angekreuzt sein
  'AB01' => array(1 => 2, 2 => 2, 3 => 1, 4 => 1),
  // In der Frage AB02 müssen 2 und 3 angekreuzt sein, 4 darf nicht und der Wert für 1 ist irrelevant
  'AB02' => array(        2 => 2, 3 => 2, 4 => 1),
  // In AB03 müssen alle 4 Kreuzchen gesetzt sein
  'AB03' => array(1 => 2, 2 => 2, 3 => 2, 4 => 2),
  // u.s.w.
  'AB04' => array(1 => 1, 2 => 2, 3 => 1, 4 => 2),
  'AB05' => array(1 => 2, 2 => 1, 3 => 2        )
);

// Punktezähler initialisieren
$points = 0;

// Alle Fragen durchlaufen
foreach ($fragen as $frageKenn => $antworten) {
  // Für diese Frage den Fehlerzähler auf 0 setzen
  $fehler = 0;
  foreach ($antworten as $itemKenn => $vorgabe) {
    // Kennung des Items zusammenbauen
    $kennung = $frageKenn.'_'.$itemKenn;
    // Antwort des Teilnehmers abfragen
    $antwort = value($kennung);
    // Antwort auf Richtigkeit (eigentlich: Falschheit) prüfen
    if ($antwort != $vorgabe) {
      // Bei Abweichung einen Fehler zählen
      $fehler++;
    }
  }
  // Prüfen, ob die Frage fehlerfrei beantwortet wurde
  if ($fehler == 0) {
    // Einen Punkt vergeben
    $points++;
  }
}

// Das Ergebnis anzeigen oder anderweitig verarbeiten
html('<p>Sie haben '.$points.' Punkte erzielt.</p>');
</code>


===== Bewertungstexte anzeigen =====

In Abhängigkeit vom erreichten Punktwert können Sie auch unterschiedliches Feedback geben. Folgender Code zeigt im Bereich von 0 bis 9 Punkten den Textbautein "feedback1", für 10-19 Punkte den Textbaustein "feedback2" und darüber "feedback3".

<code php>
if ($points < 10) {
  text('feedback1');
} elseif ($points < 20) {
  text('feedback2');
} else {
  text('feedback3');
}
</code>

Natürlich lässt sich so auch mehrdimensionales Feedback erstellen. Im folgenden Beispiel werden für die beiden Skalen ''AB01'' und ''AB02'' zwei getrennte Punktwerte berechnet und entsprechend Textbausteine angezeigt.

<code php>
$typ = valueMean('AB01');
$use = valueMean('AB02');

if ($typ < 1.5) {
  text('typA');
} elseif ($typ <= 4.5) {
  text('typB');
} else {
  text('typC');
}
if ($use < 2.0) {
  text('useA');
} elseif ($use < 4.0) {
  text('useB');
} else {
  text('useC');
}
</code>