function wrsqz_assemble($text, $vars=array()){
    global $CFG;

    if(!isset($text[0])) return $text;
    

    $W = WIRISQUIZZESEXTENSION;//This char should be always 'W'
    $T = 'T';
    $M = 'M';

    mb_internal_encoding("UTF-8");
    mb_regex_encoding("UTF-8");
    
    //Transform #x into ##Wx
    $start=0;
    while(($char = strpos($text,'#',$start))!==false){
        if(($char == 0 || substr($text,$char-1,1)!='#') && $char+1<strlen($text)){
            $char1 = substr($text, $char+1,1);
            if(('a'<=$char1 && $char1<='z') || ('A'<=$char1 && $char1<='Z')){
                $text = substr($text,0,$char) . '##W' . substr($text,$char+1);
                $start = $char + 3;
            }else{
                $start = $char+1;
            }
        }else{
            $start = $char + 1;
        }
    }
    
    //Transform ##Wx into ##Wx## in order to avoid conflicts between 2 variables
    //such that the name of the first is a prefix of the name of the second
    $text  = mb_ereg_replace('##(['.$W.$M.$T.']'.WRSQZ_ONLYLETTERS . WRSQZ_ONLYLETTERSANDNUMBERS . '*)', '##\1##', $text);

    //classify vars depending on their nature (##M, ##W and ##T)
    $mathmlvars = array();
    $encodedvars = array();
    $textvars = array();
    $imagevars = array();

    foreach ($vars as $name=>$value){
        if(!empty($name)){
            $prefix = substr($name,0,3);
            $name = $name . '##';
            if($prefix=='##'.$M){
                $mathmlvars[$name]=$value;
            }else if($prefix == '##'.$W){
                if (mb_substr($value,0,7)==='<image>') {
                    $imagevars[$name] = wrsqz_imgHTMLTag($value);
                }else{
                    $encodedvars[$name]=wrsqz_mathmlEncode($value);
                }
            }else if($prefix == '##'.$T){
                $textvars[$name]=$value;
            }
        }
    }

    //find MathML formulas & replace ##Mx variables inside.
    //We are using not-multibyte functions very carefully due to performance reasons.
    $start=0;
    while (($start = strpos($text,'<math',$start))!==false){
        $length = strpos($text, '</math>',$start)  - $start + strlen('</math>');
        $formula = substr($text, $start, $length);
        $formula = wrsqz_assembleInsideFormula($formula, $mathmlvars, false);
        
        $text = substr($text,0,$start) . $formula . substr($text, $start+$length);
        $start = $start+strlen($formula);
    }

    //find encoded MathML formulas & replace ##Wx variables inside them.
    //We are not using multibyte functions.
    $start=0;
    while (($start = strpos($text,'«math',$start))!==false){
        $length = strpos($text, '«/math»',$start)  - $start + strlen('«/math»');
        $formula = substr($text, $start, $length);

        $formula = wrsqz_assembleInsideFormula($formula, $encodedvars, true);
        $formula = wrsqz_extractTextFromMathML($formula);
        
        $text = substr($text,0,$start) . $formula . substr($text, $start+$length);
        $start = $start+strlen($formula);
    }

    //Replace variables outside formulas

    //MathML ones
    foreach($mathmlvars as $name=>$value){
        $text = str_replace($name, '<math xmlns="http://www.w3.org/1998/Math/MathML">' . $value . '</math>', $text);
    }
    //Encoded MathML Ones
    foreach ($encodedvars as $name=>$value){
        $value = wrsqz_extractTextFromMathML('«math xmlns=¨http://www.w3.org/1998/Math/MathML¨»'.$value.'«/math»');
        $value = wrsqz_extractNumbersfromMathML($value);
        $text = str_replace($name, $value, $text);
    }
    //Text Ones
    foreach ($textvars as $name=>$value){
        $text=str_replace($name, $value, $text);
    }
    //Image Ones
    foreach ($imagevars as $name=>$value){
        $text = str_replace($name, $value, $text);
    }

    return $text;
   }
            '<math><mrow><msqrt><mrow><mn>2</mn><msqrt><mn>3</mn></msqrt></mrow></msqrt><mi>#a</mi></mrow></math>',
          '<math><mrow><msub><mi>#</mi><mi>a</mi></msub></mrow></math>' => '<math><mrow><msub><mi>#</mi><mi>a</mi></msub></mrow></math>',
          '<math><mrow><mi>#</mi><msub><mi>a</mi><mi>c</mi></msub></mrow></math>'=>'<math><mrow><msub><mi>#a</mi><mi>c</mi></msub></mrow></math>',
          
        );
        foreach($tests as $test=>$correct){
          $resp = wrsqz_prepareVariablesInsideFormulas($test, FALSE);
          echo '<tr><td>';
          echo $resp == $correct ? 'OK' : 'KO';
          echo '</td>';
          echo '<td>'.htmlentities($test, ENT_COMPAT, 'UTF-8').'</td>';
          echo '<td>'.htmlentities($resp, ENT_COMPAT, 'UTF-8').'</td>';
          echo '</tr>';
        }
        foreach($tests as $test=>$correct){
          $correct = wrsqz_mathmlEncode($correct);
          $test    = wrsqz_mathmlEncode($test);
          $resp    = wrsqz_prepareVariablesInsideFormulas($test, TRUE);
          echo '<tr><td>';
          echo $resp == $correct ? 'OK' : 'KO';
          echo '</td>';
          echo '<td>'.htmlentities($test, ENT_COMPAT, 'UTF-8').'</td>';
          echo '<td>'.htmlentities($resp, ENT_COMPAT, 'UTF-8').'</td>';
          echo '</tr>';
        }
        ?>
        </tr>
      </table>
    </body>
</html>
function wrsqz_response_summary($questionType, $dbType, $question, $state, $length=80){
    if($questionType == 'match'){
        //assemble Questiontexts and answers.
        $subquestions = &$state->options->subquestions;
        $responses    = &$state->responses;
        $table = new stdClass();
        $table->data = array();
        $table->width = '100%';
        foreach ($subquestions as $key => $sub) {
            foreach ($responses as $ind => $code) {
               if (isset($sub->options->answers[$code])) {
                   //assemble $text in encoded MathML.
                   $text = format_text(wrsqz_assemble($subquestions[$ind]->questiontext,$state->vars),$question->questiontextformat);
                   //assemble $answer in text mode.
                   $answer = wrsqz_assemble(wrsqz_variablesToText($sub->options->answers[$code]->answer),$state->vars);
                   $table->data[] =  array($text ,$answer);
               }
           }
       }
       $summary = print_table($table, true);

    }else if($questionType == 'shortanswer'){
        if(isset($state->responses[''])){
            mb_parse_str($question->options->wiris->eqoption, $eqoptionArray);
            if(isset($eqoptionArray['editor']) && $eqoptionArray['editor'] == 'true'){
                $summary = format_text(wrsqz_mathmlEncode(stripslashes($state->responses[''])),FORMAT_HTML);
            }else{
                $summary = stripslashes($state->responses['']);
            }
        }else{
            $summary='';
        }
    }else if($questionType == 'truefalse'){
        if(isset($state->responses['']) && isset($question->options->answers[$state->responses['']])){
            $summary = $question->options->answers[$state->responses['']]->answer;
        }else{
            $summary = '';
        }
    }else if($questionType == 'multianswer'){
        global $QTYPES;
        
        $table = new stdClass();
        $table->data = array();
        $table->data[0] = array();
        $table->width = '100%';
        $numquestions = count($question->options->questions);
        $table->size=array_fill(0,$numquestions,100/$numquestions . '%');
        foreach ($question->options->questions as $key=>$wrapped) {
            $wrappedstate = clone($state);
            $wrappedstate->responses = array(''=>$state->responses[$key]);
            $table->data[0][] = $QTYPES[$wrapped->qtype]->response_summary($wrapped,$wrappedstate);
        }
        $summary = print_table($table, true);
    }
    return $summary;
}