====== Multi-Level Structure ======

A Multi-Level Structure exists when the same questions should be answered more than once within a questionnaire for different persons or objects. Examples are:

  * Network-based questionnaire (name generator), where the participant should enter several names and answer a series of questions for each person
  * A Code-Sheet as a part of Content analysis, where several actors (participants) should be coded for each newspaper article
 
**Note:** See [[:en:create:waves]] for the use of SoSci Survey in multi-wave surveys (which also generate multi-level data). 



===== Simple Solution =====


A "normal" questionnaire can be sufficient, if only one or a few properties should be identified for each element (name, article, object,...). In this type of questionnaire, a certain (maximum) number of namings is provided and a corresponding number of questions or items is created.

**Important:** In this case, the data for all elements are stored in a single data row in different variables.

**Example:** The participant should enter the names of his colleagues and rate for each colleague how much he/she cooperates with them and whether he/she meets them privately outside work.

  * The query of the names can be implemented e.g. by a question of the type //responses to open questions// (as identifier for this question "NG01" is used below as an example). By default, this question allows up to 20 entries -- the value can be increased if needed.
  * The intensity of the collaboration is rated e.g. by a question of the type //scale (with intermediate values)// ("FR01"). In this case, as many items are created as the name generator "NG01" (the above mentioned question) allows. Placeholders are used here as item texts, e.g. ''%name1%'' to ''%name20%''.
  * If one meets colleagues privately as well, is asked e.g. by a question of the type //multiple selection// ("FR02"). Here, too,  a corresponding number of items is needed. The easiest way is to copy the scale {{:button.copy.gif?nolink|Duplicate question}} and then change the question type.

A filter is used to determine which of the input fields have been selected. In addition, the names are stored in the [[:en:create:placeholders|Placeholders]]] ... 

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

... and then only those items of the following questions will be displayed (possibly distributed over several pages) for which an element has been entered.

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

**Tip:** If you want to ask questions about the elements on individual pages, the function ''[[:de:create:functions:looppage]]'' could be used. Based on this, you can (a) display a single item from a question, (b) display a question from a section (e.g. "RB01" to "RB20") or %%(c)%% display specific questions (e.g. "R001, R002" to "R901, R902") from a separate section (e.g. "R0" to "R9").


**Note:** This alternative always requires a defined upper limit for the number of elements. Depending on the application, this upper limit will be between 5 and 99, as more than 99 elements are difficult to implement with this solution. Theoretically, there are also cases where this upper limit is not adequate. Conversely, one may ask whether one really has to map every statistical outlier in the data. In most cases, this is not necessary in order to obtain meaningful results. And in practice, most participants lack the motivation to answer the same questions for more than a handful of elements.


===== Real Multi-Level Design =====

If one really wants to store the data for a multi-level analysis in different data rows, SoSci Survey facilitates this with the following PHP commands:

  * ''[[:en:create:functions:multileveldown]]'' -- Starts a sub-questionnaire (Level 1) within the main questionnaire (Level 2) for the single element.
  * ''[[:en:create:functions:multileveldata]]'' -- Provides the data, which were possibly transmitted using ''multiLevelDown()'', in sub-questionnaires.
  * ''[[:en:create:functions:multilevelreturn]]'' -- Redirects the participant from the sub-questionnaire back to the main questionnaire and passes (optionally) data, e.g. a multiple-choice question, whether further elements follow. If the command is not used, the sub-questionnaire automatically jumps back to the main questionnaire when reaching the "last page" (in the course of this, no data is transmitted). 
   
The sub-questionnaire stores the case number (CASE) of the main questionnaire as a reference (REF), so that a clear allocation of sub-questionnaires to the main questionnaires is possible. 

==== Example 1 ====


In the first application, the elements in the sub-questionnaire (naming "sub01") are queried. For this purpose, a //open question// ("NT01") with alternative option "no further element" will be used.

The main questionnaire has two functions: Firstly, it has to redirect the respondents to the sub-questionnaire at the right place. This page requires an identifier, e.g. "subStart". 

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


Secondly, on the next page it has to check, if the sub-questionnaire has to be presented again (this is achieved by jumping back to the page "subStart"). For this purpose, the sub-questionnaire either returns the value ''true'' using ''multiLevelReturn()'' (see below) if an element was registered, or ''false'' if the alternative option "no further element" was chosen. This answer is queried using ''multiLevelResponse()'' and utilized in a filter.

<code php>
$rsp = multiLevelResponse();
// If $rsp has the value true...
if ($rsp) {
  // ... the questionnaire jumps back to the previous page "subStart"
  goToPage('subStart');
}
</code>

The sub-questionnaire only has to communicate the right value (''true'' or ''false'') to the main questionnaire. For this purpose, an additional page will be inserted before the "last page", to check if the alternative option has (not) been selected (variable "NT01_01a").


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

In the example above, the comparison condition was directly stored as variable ''$gotName''. Instead, one can also formulate it as IF-filter:

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


==== Example 2 ====

Alternatively, the main questionnaire can first query all elements and then start the sub-questionnaire a corresponding number of times. This example assumes that elements were first queried in a question of the type //Open namings// (identifier e.g. "NG01").

In the main questionnaire, a list of the mentioned elements will be created first and the page, which the sub-questionnaire by ''multiLevelDown()'' retrieves, will be repeated correspondingly often. The naming will be transferred to the sub-questionnaire.  

<code php>
// Determine a list of the completed text fields in name generator
$items = getItems('NG01', 'valid');

if (count($items) > 0) {
  $item = loopPage($items);
  // Retrieve text of the naming
  $element = value(id('NG01', $item));
  // Start sub-questionnaire and transfer text of naming
  multiLevelDown('sub', $element);
}
</code>

No further adaptations are needed in the main questionnaire. In the sub-questionnaire, the element should be stored by ''[[:en:create:function:put]]'' in a [[:en:create:questions:internal|internal variable]]. Moreover, it could be useful to define a placeholder for the naming by ''[[:en:create:function:replace]]''.

<code php>
$element = multiLevelData();
// Store element in sub-data set 
put('IV01_01', $element);
// Define placeholder %element% 
replace('%element%', $element);
</code>

A return value from the sub-questionnaire to the main questionnaire is usually not required for this design.


==== Example 3 ====

The instruction on [[:en:create:functions:randomuse#anwendungsbeispiel|randomUse()]] shows the complete PHP-Code for the case where participant has to rate 20 items randomly selected from a pool, but can also skip them. 


===== Notes =====

  * It is recommended to switch off the numbering of the questions in the subordinate questionnaire (**Compose questionnaire** -> Tab //Settings//). At present, the numbering of the questions in each subordinate questionnaire is still independent of the numbering in the main questionnaire.
  * Placeholders are only valid within one data set -- therefore, placeholders from the main questionnaire cannot be used in the sub-questionnaire. If a placeholder is also required in the sub-questionnaire, the corresponding value must be transferred to the sub-questionnaire using ''multiLevelDown()'' and a placeholder must be defined there.

**Tip:** Set the access mode for the sub-questionnaire under **Compose questionnaire** -> tab //Settings// "Internal/locked", so that the questionnaire can indeed only be retrieved as a sub-questionnaire and not directly.