/**
  * Persist an AssessmentTestSession into binary data.
  *
  * @param \qtism\runtime\tests\AssessmentTestSession $assessmentTestSession
  * @throws \qtism\runtime\storage\common\StorageException
  */
 public function persist(AssessmentTestSession $assessmentTestSession)
 {
     try {
         $stream = new MemoryStream();
         $stream->open();
         $access = $this->createBinaryStreamAccess($stream);
         // -- Deal with intrinsic values of the Test Session.
         $access->writeTinyInt($assessmentTestSession->getState());
         // Write the current position in the route.
         $route = $assessmentTestSession->getRoute();
         $access->writeTinyInt($route->getPosition());
         // persist time reference.
         $timeReference = $assessmentTestSession->getTimeReference();
         if (is_null($timeReference) === true) {
             $access->writeBoolean(false);
         } else {
             $access->writeBoolean(true);
             $access->writeDateTime($timeReference);
         }
         // -- Persist the Route of the AssessmentTestSession and the related item sessions.
         $access->writeTinyInt($route->count());
         $itemSessionStore = $assessmentTestSession->getAssessmentItemSessionStore();
         $pendingResponseStore = $assessmentTestSession->getPendingResponseStore();
         $oldRoutePosition = $route->getPosition();
         foreach ($route as $routeItem) {
             $item = $routeItem->getAssessmentItemRef();
             $occurence = $routeItem->getOccurence();
             // Deal with RouteItem
             $access->writeRouteItem($this->getSeeker(), $routeItem);
             // Deal with ItemSession related to the previously written RouteItem.
             try {
                 $itemSession = $itemSessionStore->getAssessmentItemSession($item, $occurence);
                 $access->writeBoolean(true);
                 $access->writeAssessmentItemSession($this->getSeeker(), $itemSession);
                 // Deal with last occurence update.
                 $access->writeBoolean($assessmentTestSession->isLastOccurenceUpdate($item, $occurence));
                 // Deal with PendingResponses
                 if (($pendingResponses = $pendingResponseStore->getPendingResponses($item, $occurence)) !== false) {
                     $access->writeBoolean(true);
                     $access->writePendingResponses($this->getSeeker(), $pendingResponses);
                 } else {
                     $access->writeBoolean(false);
                 }
             } catch (OutOfBoundsException $e) {
                 $access->writeBoolean(false);
                 // No assessmentItemSession for this route item.
                 continue;
             }
         }
         $route->setPosition($oldRoutePosition);
         // Deal with test session configuration.
         // !!! AutoForward (not in use anymore, fake it).
         $access->writeBoolean(false);
         // Persist the test-level global scope.
         foreach ($assessmentTestSession->getKeys() as $outcomeIdentifier) {
             $outcomeVariable = $assessmentTestSession->getVariable($outcomeIdentifier);
             $access->writeVariableValue($outcomeVariable);
         }
         $durationStore = $assessmentTestSession->getDurationStore();
         $access->writeShort(count($durationStore));
         foreach ($durationStore->getKeys() as $k) {
             $access->writeString($k);
             $access->writeVariableValue($durationStore->getVariable($k));
         }
         $this->persistStream($assessmentTestSession, $stream);
         $stream->close();
     } catch (Exception $e) {
         $sessionId = $assessmentTestSession->getSessionId();
         $msg = "An error occured while persisting AssessmentTestSession with ID '{$sessionId}': " . $e->getMessage();
         throw new StorageException($msg, StorageException::PERSITANCE, $e);
     }
 }