assessmentResult = $assessmentResult; return $this; } /** * Get a formatted array of AssessmentContext object * * @return array * @throws LogicException If AssessmentResult is not loaded */ public function getContext() { $this->assertIsLoaded(); $context = $this->assessmentResult->getContext(); $sessionIdentifiers = []; if ($context->hasSessionIdentifiers()) { $contextSessionIdentifiers = iterator_to_array($context->getSessionIdentifiers()); /** @var SessionIdentifier $sessionIdentifier */ foreach ($contextSessionIdentifiers as $sessionIdentifier) { $sessionIdentifiers[$sessionIdentifier->getIdentifier()->getValue()] = $sessionIdentifier->getSourceID()->getValue(); } } $sourcedId = ''; if ($context->hasSourcedId()) { $sourcedId = $context->getSourcedId()->getValue(); } return [ 'sourcedId' => $sourcedId, 'sessionIdentifiers' => $sessionIdentifiers ]; } /** * Get test variables of result * - Loop on all test itemVariables * - Build tao outcome/response variables from qti sk variables * * @return array * @throws common_exception_NotImplemented * @throws common_exception_InvalidArgumentType * @throws LogicException If AssessmentResult is not loaded */ public function getTestVariables() { $this->assertIsLoaded(); if (!$this->assessmentResult->hasTestResult()) { return []; } $testResult = $this->assessmentResult->getTestResult(); if (!$testResult->hasItemVariables()) { return []; } return [ $testResult->getIdentifier()->getValue() => $this->createVariables($testResult->getItemVariables(), $testResult->getDatestamp()) ]; } /** * Get item variables of result * - Loop on all itemResult itemVariables * - Build tao outcome/response variables from qti sk variables * * @return array * @throws common_exception_NotImplemented * @throws common_exception_InvalidArgumentType * @throws LogicException If AssessmentResult is not loaded */ public function getItemVariables() { $this->assertIsLoaded(); if (!$this->assessmentResult->hasItemResults()) { return []; } $itemResults = $this->assessmentResult->getItemResults(); $itemVariables = []; /** @var ItemResult $itemResult */ foreach ($itemResults as $itemResult) { if (!$itemResult->hasItemVariables()) { continue; } $itemVariables[$itemResult->getIdentifier()->getValue()] = $this->createVariables($itemResult->getItemVariables(), $itemResult->getDatestamp()); } return $itemVariables; } /** * Create tao variables from ItemVariableCollection * - Based on itemVariable class, create associated tao variable * - Set variable epoch with itemResult datetime * * @param ItemVariableCollection $itemVariables * @param DateTime $datetime * @return taoResultServer_models_classes_Variable[] * @throws common_exception_NotImplemented If itemVariable is not outcome|response (e.g. template) * @throws common_exception_InvalidArgumentType */ protected function createVariables(ItemVariableCollection $itemVariables, DateTime $datetime) { $variables = []; $i = 0; foreach ($itemVariables as $itemVariable) { $i++; switch (get_class($itemVariable)) { case ResultOutcomeVariable::class: $variable = $this->createOutcomeVariable($itemVariable); break; case ResultResponseVariable::class: $variable = $this->createResponseVariable($itemVariable); break; case ResultTemplateVariable::class: default: throw new common_exception_NotImplemented('Qti Result parser cannot deals with "' . get_class($itemVariable) . '".'); break; } $datetime->modify('+' . $i . ' microsecond'); $variable->setEpoch(number_format($datetime->getMicroseconds(true), 8) . ' ' . $datetime->format('U')); $variables[] = $variable; } return $variables; } /** * Initialize a taoResultServer_models_classes_Variable based on ItemVariable * - including identifier, cardinality, baseType * * @param ItemVariable $itemVariable * @param taoResultServer_models_classes_Variable $variable * @return taoResultServer_models_classes_Variable * @throws common_exception_InvalidArgumentType */ protected function createVariableFromItemVariable(ItemVariable $itemVariable, taoResultServer_models_classes_Variable $variable) { $variable->setIdentifier((string) $itemVariable->getIdentifier()); $variable->setCardinality(Cardinality::getNameByConstant($itemVariable->getCardinality())); if (null !== $itemVariable->getBaseType()) { $variable->setBaseType(BaseType::getNameByConstant($itemVariable->getBaseType())); } return $variable; } /** * Transfer all attributes of a ResultOutcomeVariable to taoResultServer_models_classes_OutcomeVariable * * @param ResultOutcomeVariable $itemVariable * @return taoResultServer_models_classes_OutcomeVariable * @throws common_exception_InvalidArgumentType * @todo Implements Long Interpretation * @todo Implements Mastery Value * @todo Implements multiple Values * @todo Implements View * @todo Implements Interpretation */ protected function createOutcomeVariable(ResultOutcomeVariable $itemVariable) { /** @var taoResultServer_models_classes_OutcomeVariable $variable */ $variable = $this->createVariableFromItemVariable( $itemVariable, new taoResultServer_models_classes_OutcomeVariable() ); if ($itemVariable->hasValues()) { $variable->setValue($this->serializeValueCollection($itemVariable->getValues())); } if ($itemVariable->hasNormalMaximum()) { $variable->setNormalMaximum((string) $itemVariable->getNormalMaximum()->getValue()); } if ($itemVariable->hasNormalMinimum()) { $variable->setNormalMinimum((string) $itemVariable->getNormalMinimum()->getValue()); } if ($itemVariable->hasView()) { $this->logInfo('Qti Result Parser does not handle Outcome View'); } if ($itemVariable->hasInterpretation()) { $this->logInfo('Qti Result Parser does not handle Outcome Interpretation'); } if ($itemVariable->hasLongInterpretation()) { $this->logInfo('Qti Result Parser does not handle Outcome Long Interpretation'); } if ($itemVariable->hasMasteryValue()) { $this->logInfo('Qti Result Parser does not handle Outcome Mastery Value'); } return $variable; } /** * Transfer all attributes of a ResultResponseVariable to taoResultServer_models_classes_ResponseVariable * * @param ResultResponseVariable $itemVariable * @return taoResultServer_models_classes_ResponseVariable * @throws common_exception_InvalidArgumentType * @todo Deals with multiple CandidateResponse Values * @todo Deals with multiple CorrectResponse Values * @todo Implements Choice Sequence */ protected function createResponseVariable(ResultResponseVariable $itemVariable) { /** @var taoResultServer_models_classes_ResponseVariable $variable */ $variable = $this->createVariableFromItemVariable( $itemVariable, new taoResultServer_models_classes_ResponseVariable() ); if ($itemVariable->getCandidateResponse()->hasValues()) { $variable->setCandidateResponse($this->serializeValueCollection($itemVariable->getCandidateResponse()->getValues())); } if ($itemVariable->hasCorrectResponse()) { $variable->setCorrectResponse($this->serializeValueCollection($itemVariable->getCorrectResponse()->getValues())); } if ($itemVariable->hasChoiceSequence()) { $this->logInfo('Qti Result Parser does not handle Response ChoiceSequence'); } return $variable; } /** * Helper to serialize qti valueCollection to string * * @param ValueCollection $valueCollection * @return string */ protected function serializeValueCollection(ValueCollection $valueCollection) { $values = array_map( function (Value $value) { return $value->getValue(); }, iterator_to_array($valueCollection) ); return implode(';', $values); } /** * @throws LogicException If assessmentResult is not loaded */ protected function assertIsLoaded() { if (!$this->assessmentResult) { throw new LogicException('Result parser is not loaded and cannot parse QTI XML result.'); } } }