function restore_session_and_responses(&$question, &$state)
 {
     try {
         $lines = explode("\n", $state->responses['']);
         $vars = new question_variables(array());
         // the first line is the random variables of the session
         $vars->add_local_variables($lines[0]);
         // the $lines[0] is a simple (variable => value) pairs
         $state->randomvars = $vars->get_variables();
         $vars->add_local_variables($question->options->extra->varsglobal);
         $state->globalvars = $vars->get_variables();
         $submitinfo = explode(';', $lines[2]);
         // get the submission information of this state
         $grading = explode(';', $lines[3]);
         // get the grading information of the state
         $state->subanum = intval($submitinfo[0]);
         $state->trials = explode(",", $submitinfo[1]);
         $state->raw_grades = explode(",", $grading[0]);
         $state->fractions = explode(",", $grading[1]);
         $state->corrunits = explode(",", $grading[2]);
         // the remaining lines are responses of subquestions, put them in state responses
         $state->responses = array_merge($state->responses, array_slice($lines, 4, -1));
         return true;
         // success
     } catch (Exception $e) {
         return false;
         // fail
     }
 }
 /**
  * Validating the data returning from the client.
  * 
  * The check the basic error as well as the formula error by evaluating one instantiation.
  */
 function validation($data, $files)
 {
     $errors = parent::validation($data, $files);
     global $basic_unit_conversion_rules;
     global $QTYPES;
     $qt =& $QTYPES[$this->qtype()];
     $form = (object) $data;
     try {
         $tmpquestion->options->extra->retrymarkseq = $form->retrymarkseq;
         $qt->get_trial_mark_fraction(&$tmpquestion, 0);
     } catch (Exception $e) {
         $errors["retrymarkseq"] = $e->getMessage();
     }
     $validanswers = $qt->check_form_answers($form);
     if (isset($validanswers->error)) {
         $errors = $errors + $validanswers->errors;
         $validanswers = $validanswers->answers;
     }
     $res = $qt->get_subquestion_structure($form->questiontext, $validanswers);
     if (isset($res->errors)) {
         $errors = $errors + $res->errors;
     }
     try {
         $vars = new question_variables($form->varsrandom);
         // checking random variables by instantiating one set
     } catch (Exception $e) {
         $errors["varsrandom"] = $e->getMessage();
         return $errors;
     }
     try {
         $vars->add_local_variables($form->varsglobal);
     } catch (Exception $e) {
         $errors["varsglobal"] = $e->getMessage();
         return $errors;
     }
     $globalvars = $vars->get_variables();
     /// Attempt to compute the answer so that it can see whether it is wrong
     foreach ($validanswers as $idx => $ans) {
         $unitcheck = new answer_unit_conversion();
         if ($ans->unitpenalty < 0 || $ans->unitpenalty > 1) {
             $errors["unitpenalty[{$idx}]"] = get_string('error_unitpenalty', 'qtype_coordinates') . $e->getMessage();
         }
         try {
             $unitcheck->parse_targets($ans->postunit);
         } catch (Exception $e) {
             $errors["postunit[{$idx}]"] = get_string('error_validation_parse_rule', 'qtype_coordinates') . $e->getMessage();
         }
         try {
             $unitcheck->parse_targets($ans->preunit);
         } catch (Exception $e) {
             $errors["preunit[{$idx}]"] = get_string('error_validation_parse_rule', 'qtype_coordinates') . $e->getMessage();
         }
         try {
             $unitcheck->assign_additional_rules($ans->otherrule);
             $unitcheck->reparse_all_rules();
         } catch (Exception $e) {
             $errors["otherrule[{$idx}]"] = get_string('error_validation_parse_rule', 'qtype_coordinates') . $e->getMessage();
         }
         try {
             $entry = $basic_unit_conversion_rules[$ans->ruleid];
             if ($entry === null || $entry[1] === null) {
                 throw new Exception(get_string('error_validation_ruleid', 'qtype_coordinates'));
             }
             $unitcheck->assign_default_rules($ans->ruleid, $entry[1]);
             $unitcheck->reparse_all_rules();
         } catch (Exception $e) {
             $errors["ruleid[{$idx}]"] = $e->getMessage();
         }
         try {
             $vars->add_local_variables($ans->vars1);
         } catch (Exception $e) {
             $errors["vars1[{$idx}]"] = get_string('error_validation_eval', 'qtype_coordinates') . $e->getMessage();
             continue;
         }
         try {
             $input = $qt->evaluate_answer($ans, $globalvars);
         } catch (Exception $e) {
             $errors["answer[{$idx}]"] = get_string('error_validation_eval', 'qtype_coordinates') . $e->getMessage();
             continue;
         }
         try {
             $qt->add_special_correctness_variables($vars, $input, $input);
             $vars->add_local_variables($ans->vars2);
         } catch (Exception $e) {
             $errors["vars2[{$idx}]"] = get_string('error_validation_eval', 'qtype_coordinates') . $e->getMessage();
             continue;
         }
         try {
             $correctness = $qt->grade_response_correctness($ans, $globalvars, '(' . implode(',', $input->coordinates) . ')', $unitcheck);
         } catch (Exception $e) {
             $errors["correctness[{$idx}]"] = get_string('error_validation_eval', 'qtype_coordinates') . $e->getMessage();
             continue;
         }
     }
     return $errors;
 }