====== Multi-Level Struktur ======

Eine Multi-Level Struktur liegt dann vor, wenn innerhalb eines Fragebogens die gleichen Fragen mehrfach beantwortet werden sollen, und zwar für unterschiedliche Personen oder Objekte. Beispiele sind:

  * Ein Netzwerkfragebogen (Namensgenerator), bei dem der Teilnehmer mehrere Namen eingeben soll und zu jeder Person eine Reihe von Fragen beantworten muss.
  * Ein Code-Sheet im Rahmen einer Inhaltsanalyse, wo etwa für jeden Zeitungsartikel mehrere Akteure kodiert werden sollen.

**Hinweis:** Zur Verwendung von SoSci Survey im Rahmen mehrwelliger Erhebungen (welche ebenfalls Multi-Level-Daten erzeugen) siehe [[:de:create:waves]].


===== Einfache Lösung =====

Wenn zu jedem genannten Element (Namen, Artikel, Objekt, ...) nur eine oder wenige Eigenschaften abgefragt werden sollen, kann ein ganz "normaler" Fragebogen ausreichend sein. In diesem Fragebogen sieht man eine bestimmte (maximale) Anzahl an Nennungen vor und legt eine entsprechende Anzahl Fragen oder Items an.

**Wichtig:** Bei dieser Variante werden die Daten für alle Elemente in einer einzigen Datenzeile in unterschiedlichen Variablen gespeichert.

**Beispiel:** Der Teilnehmer soll Namen seiner Kollegen eintragen und für jeden Kollegen bewerten, wie viel er mit diesem zusammenarbeitet und ob er ihn auch außerhalb der Arbeit privat trifft.

  * Die Abfrage der Namen lässt sich z.B. über eine Frage vom Typ //Offene Nennungen// umsetzen (als Kennung für diese Frage wird unten exemplarisch "NG01" verwendet). Standardmäßig erlaubt diese Frage bis zu 20 Nennungen -- der Wert kann nach Bedarf erhöht werden.
  * Die Intensität der Zusammearbeit wird z.B. mit einer Frage vom Typ //Skala (mit Zwischenwerten)// abgefragt ("FR01"). Hier werden so viele Items angelegt, wie der Namensgenerator "NG01" (die oben genannte Frage) maximal erlaubt. Als Item-Texte werden hier Platzhalter verwendet, z.B. ''%name1%'' bis ''%name20%''.
  * Ob man die Kollegen auch privat trifft, wird z.B. mit einer Frage vom Typ //Mehrfachauswahl// erfragt ("FR02"). Auch hier benötigt man entsprechend viele Items. Am einfachsten kopiert man die Skala {{:button.copy.gif?nolink|Frage duplizieren}} und ändert anschließen den Fragetyp.

Mit einem Filter wird ermittelt, welche der Eingabefelder ausgefüllt wurden. Außerdem werden die Namen in die [[:de:create:placeholders|Platzhalter]] gespeichert ...

<code php>
$items = getItems('NG01', 'valid');
foreach ($items as $item) {
  $varID = id('NG01', $item);
  $value = value($varID);
  replace('%name'.$item.'%', $value);
}
registerVariable($items);
</code>

... und anschließend (ggf. auch über mehrere Seiten verteilt) nur jene Items der folgenden Fragen angezeigt, zu denen auch ein Element eingetragen wurde.

<code php>
question('FR01', $items);
question('FR02', $items);
</code>

**Tipp:** Wenn man die Fragen zu den Elementen auf einzelnen Seiten abfragen möchte, bietet sich die Funktion ''[[:de:create:functions:looppage]]'' an. Auf deren Basis kann man (a) jeweils ein einzelnes Item aus einer Frage anzeigen, (b) jeweils eine Frage aus einer Rubrik anzeigen (z.B. "RB01" bis "RB20") oder %%(c)%% jeweils aus einer eigenen Rubrik (z.B. "R0" bis "R9") bestimmte Fragen anzeigen (z.B. "R001, R002" bis "R901, R902").

**Hinweis:** Diese Variante setzt immer eine definierte Obergrenze für die Anzahl an Elementen voraus. Diese Obergrenze wird -- je nach Anwendungsfall -- zwischen 5 und 99 liegen, denn mehr als 99 Elemente sind mit dieser Lösung nur aufwändig zu realisieren. Theoretisch gibt es natürlich auch Fälle, wo diese Obergrenze nicht ausrecht. Umgekehrt darf man fragen, ob man wirklich jeden statistischen Ausreißer in den Daten abbilden muss. Meistens ist das nicht notwendig, um aussagekräftige Ergebnisse zu erhalten. Und praktisch ist es auch so, dass es den meisten Teilnehmer auch an Motivation mangelt, dieselben Fragen für mehr als eine Hand voll Elemente zu beantworten.


===== Echtes Multi-Level Design =====

Möchte man die Daten für eine Multi-Level Analyse tatsächlich in unterschiedlichen Datenzeilen speichern, unterstützt SoSci Survey dies mit den folgenden PHP-Befehlen:

  * ''[[:de:create:functions:multileveldown]]'' -- Startet innerhalb des Hauptfragebogens (Level 2) einen Teilfragebogen (Level 1) für das einzelne Element.
  * ''[[:de:create:functions:multileveldata]]'' -- Liefert im Teilfragebogen die Daten, die evtl. mittels ''multiLevelDown()'' übermittelt wurden.
  * ''[[:de:create:functions:multilevelreturn]]'' -- Leitet den Teilnehmer vom Teilfragebogen zurück zum Hauptfragebogen und übergibt dabei (optional) Daten, z.B. einer Auswahlfrage, ob noch weitere Elemente folgen. Falls der Befehl nicht verwendet wird, springt der Teilfragebogen beim Erreichen der "letzten Seite" automatisch zurück zum Hauptfragebogen (dabei werden keine Daten übermittelt).
  * ''[[:de:create:functions:multilevelresponse]]'' -- Liefert im Hauptfragebogen die Daten, die evtl. von ''multiLevelReturn()'' übermittelt wurden.

Der Teilfragebogen speichert die Fallnummer (CASE) des Hauptfragebogens als Referenz (REF), sodass eine eindeutige Zuordnung von Teil- zu Hauptfragebögen möglich ist.


==== Beispiel 1 ====

Im ersten Anwendungsfall sollen die Elemente im Teilfragebogen (Kennung "sub01") abgefragt werden. Dafür wird als erste Frage im Teilfragebogen eine //offene Texteingabe// ("NT01") mit Ausweichoption "kein weiteres Element" verwendet.

Der Hauptfragebogen hat zwei Aufgaben: Zum einen muss er den Teilnehmer an geeigneter Stelle zum Teilfragebogen schicken. Diese Seite benötigt eine Kennung, z.B. "subStart".

<code php>
multiLevelDown('sub01');
</code>

Zum anderen muss er auf der nächsten Seite überprüfen, ob der Teilfragebogen erneut vorgelegt werden soll (das wird erreicht, indem der Fragebogen zur Seite "subStart" zurück springt). Dafür gibt der Teilfragebogen mittels ''multiLevelReturn()'' entweder den Wert ''true'' zurück (s. unten), falls ein Element eingetragen wurde oder ''false'', wenn die Ausweichoption "kein weiteres Element" angegeben wurde. Diese Antwort wird mittels ''multiLevelResponse()'' abgefragt und in einem Filter verwertet.

<code php>
$rsp = multiLevelResponse();
// Falls $rsp den Wert true hat...
if ($rsp) {
  // ... springt der Fragebogen zurück zur vorigen Seite "subStart"
  goToPage('subStart');
}
</code>

Der Teilfragebogen muss lediglich dafür sorgen, dem Hauptfragebogen den korrekten Wert (''true'' oder ''false'') mitzuteilen. Dafür wird vor der "letzten Seite" eine zusätzliche Seite eingefügt, welche mittels überprüft, ob die Ausweichoption (nicht) angekreuzt wurde (Variable "NT01_01a").

<code php>
$gotName = (value('NT01_01a') != 2);
multiLevelReturn($gotName);
</code>

Im obigen Beispiel wurde die Vergleichsbedingung direkt als Variable ''$gotName'' gespeichert. Man kann es stattdessen auch als IF-Filter formulieren:

<code php>
if (value('NT01_01a') != 2) {
  multiLevelReturn(true);
} else {
  multiLevelReturn(false);
}
</code>


==== Beispiel 2 ====

Alternativ kann der Hauptfragebogen zunächst alle Element abfragen und dann den Teilfragebogen entsprechend oft starten. Dieses Beispiel geht davon aus, dass in einer Frage vom Typ //Offene Nennungen// (Kennung z.B. "NG01") zunächst Elemente abgefragt wurden.

Im Hauptfragebogen wird zunächst eine Liste der genannten Elemente erstellt und die Seite, welche den Teilfragebogen mittels ''multiLevelDown()'' aufruft entsprechend oft wiederholt. Die Nennung wird dabei an den Teilfragebogen übergeben.

<code php>
// Eine Liste der ausgefüllten Textfelder im Namensgenerator ermitteln
$items = getItems('NG01', 'valid');

if (count($items) > 0) {
  $item = loopPage($items);
  // Text der Nennung abrugen
  $element = value(id('NG01', $item));
  // Teilfragebogen starten und Text der Nennung übergeben
  multiLevelDown('sub', $element);
}
</code>

Im Hauptfragebogen sind dann keine weitere Anpassungen mehr erforderlich. Im Teilfragebogen sollte das Element mittels ''[[:de:create:function:put]]'' in einer [[:de:create:questions:internal|internen Variable]] gespeichert werden. Es kann darüber hinaus sinnvoll sein, einen Platzhalter für die Nennung mittels ''[[:de:create:function:replace]]'' zu definieren.

<code php>
$element = multiLevelData();
// Element im Teildatensatz speichern
put('IV01_01', $element);
// Platzhalter %element% definieren
replace('%element%', $element);
</code>

Ein Rückgabewert vom Teilfragebogen an den Hauptfragebogen ist bei diesem Design in alle Regel nicht erforderlich.


==== Beispiel 3 ====

Die Anleitung zu [[:de:create:functions:randomuse#anwendungsbeispiel|randomUse()]] zeigt den vollständigen PHP-Code für den Anwendungsfall, dass Teilnehmer 20 zufällig aus einem Pool ausgewählte Items bewerten müssen, diese aber auch auslassen können.


===== Hinweise =====

  * Es ist empfehlenswert im untergeordeneten Fragebogen die Nummerierung der Fragen abzuschalten (**Fragebogen zusammenstellen** -> Karteireiter //Einstellungen//). Derzeit ist die Nummerierung der Fragen in jedem untergeordneten Fragebogen noch unabhängig von der Nummerierung im Hauptfragebogen.
  * Platzhalter gelten nur jeweils innerhalb eines Datensatzes -- daher können Platzhalter aus dem Hauptfragebogen nicht im Teilfragebogen verwendet werden. Falls ein Platzhalter auch im Teilfragebogen erforderlich ist, muss der entsprechende Wert mittels ''multiLevelDown()'' an den Teilfragebogen übergeben und dort ein Platzhalter definiert werden.

**Tipp:** Legen sie für den Teilfragebogen unter **Fragebogen zusammenstellen** -> Karteireiter //Einstellungen// den Zugriffsmodus "Intern/gesperrt" fest, damit der Fragebogen tatsächlich nur als Teilfragebogen und nicht direkt aufgerufen werden kann.