public function testSimpleCase()
 {
     $data = json_decode($this->getFixtureFileContents('learnosityjsons/tokenhighlight.json'), true);
     $assessmentItem = $this->convertToAssessmentItem($data);
     // Has <hottextInteraction> as the first and only interaction
     /** @var HottextInteraction $interaction */
     $interaction = $assessmentItem->getComponentsByClassName('hottextInteraction', true)->getArrayCopy()[0];
     $this->assertTrue($interaction instanceof HottextInteraction);
     // And its prompt is mapped correctly to item body
     $promptString = QtiMarshallerUtil::marshallCollection($interaction->getPrompt()->getComponents());
     $this->assertEquals('<p>[This is the stem.]</p>', $promptString);
     // Assert we have 3 hottext elements
     /** @var Hottext[] $hottexts */
     $hottexts = $interaction->getComponentsByClassName('hottext', true)->getArrayCopy(true);
     $this->assertEquals(3, $interaction->getComponentsByClassName('hottext', true)->count());
     $this->assertEquals('TOKEN_0', $hottexts[0]->getIdentifier());
     $this->assertEquals('Risus et tincidunt turpis facilisis.', QtiMarshallerUtil::marshallCollection($hottexts[0]->getComponents()));
     $this->assertEquals('TOKEN_1', $hottexts[1]->getIdentifier());
     $this->assertEquals('Curabitur eu nulla justo. Curabitur vulputate ut nisl et bibendum. ' . 'Nunc diam enim, porta sed eros vitae. dignissim, et tincidunt turpis facilisis.', QtiMarshallerUtil::marshallCollection($hottexts[1]->getComponents()));
     $this->assertEquals('TOKEN_2', $hottexts[2]->getIdentifier());
     $this->assertEquals('Curabitur eu nulla justo. Curabitur vulputate ut nisl et bibendum.', QtiMarshallerUtil::marshallCollection($hottexts[2]->getComponents()));
     // Assert we have the correct response processing template
     $responseProcessingTemplate = $assessmentItem->getResponseProcessing()->getTemplate();
     $this->assertEquals(Constants::RESPONSE_PROCESSING_TEMPLATE_MATCH_CORRECT, $responseProcessingTemplate);
     // Assert we have the correct response declaration values and map entries
     /** @var ResponseDeclaration $responseDeclaration */
     $responseDeclaration = $assessmentItem->getResponseDeclarations()->getArrayCopy()[0];
     $this->assertEquals(BaseType::IDENTIFIER, $responseDeclaration->getBaseType());
     $this->assertEquals(Cardinality::MULTIPLE, $responseDeclaration->getCardinality());
     /** @var Value[] $values */
     $values = $responseDeclaration->getCorrectResponse()->getValues()->getArrayCopy(true);
     $this->assertEquals('TOKEN_0', $values[0]->getValue());
     $this->assertEquals('TOKEN_2', $values[1]->getValue());
     $this->assertNull($responseDeclaration->getMapping());
 }
 public function testShorttextQuestionWithSimpleValidation()
 {
     $data = json_decode($this->getFixtureFileContents('learnosityjsons/shorttext.json'), true);
     $assessmentItem = $this->convertToAssessmentItem($data);
     // Has <textEntryInteraction> as the first and only interaction
     /** @var TextEntryInteraction $interaction */
     $interaction = $assessmentItem->getComponentsByClassName('textEntryInteraction', true)->getArrayCopy()[0];
     // Test basic attributes
     $this->assertTrue($interaction instanceof TextEntryInteraction);
     $this->assertEquals('placeholdertext', $interaction->getPlaceholderText());
     $this->assertEquals(15, $interaction->getExpectedLength());
     // Shorttext shall have one simple `map_response` <responseDeclaration> and <responseProcessing>
     /** @var ResponseDeclaration $responseDeclaration */
     $responseDeclaration = $assessmentItem->getResponseDeclarations()->getArrayCopy()[0];
     $this->assertEquals(Constants::RESPONSE_PROCESSING_TEMPLATE_MAP_RESPONSE, $assessmentItem->getResponseProcessing()->getTemplate());
     /** @var Value[] $values */
     $values = $responseDeclaration->getCorrectResponse()->getValues()->getArrayCopy(true);
     $this->assertEquals('hello', $values[0]->getValue());
     $this->assertEquals('anotherhello', $values[1]->getValue());
     /** @var MapEntry[] $mapEntries */
     $mapEntries = $responseDeclaration->getMapping()->getMapEntries()->getArrayCopy(true);
     $this->assertEquals('hello', $mapEntries[0]->getMapKey());
     $this->assertEquals(2, $mapEntries[0]->getMappedValue());
     $this->assertEquals('anotherhello', $mapEntries[1]->getMapKey());
     $this->assertEquals(1, $mapEntries[1]->getMappedValue());
     // Check itembody is correct that the stimulus is appended before
     $itemBodyContent = QtiMarshallerUtil::marshallCollection($assessmentItem->getItemBody()->getComponents());
     $expectedString = '<p>[This is the stem.]</p><div><textEntryInteraction responseIdentifier="shorttexttestreference" expectedLength="15" placeholderText="placeholdertext" label="shorttexttestreference"/></div>';
     $this->assertEquals($expectedString, $itemBodyContent);
 }
 public function testSimpleCaseWithNoValidation()
 {
     $stimulus = '<strong>Where is Learnosity office in Australia located?</strong>';
     $options = ['ChoiceA' => 'Melbourne', 'ChoiceB' => 'Sydney', 'ChoiceC' => 'Jakarta'];
     $question = $this->buildMcq($options);
     $question->set_stimulus($stimulus);
     $mcqMapper = new McqMapper();
     /** @var ChoiceInteraction $interaction */
     list($interaction, $responseDeclaration, $responseProcessing) = $mcqMapper->convert($question, 'testIdentifier', 'testIdentifierLabel');
     // Check usual
     $this->assertTrue($interaction instanceof ChoiceInteraction);
     $this->assertEquals('testIdentifier', $interaction->getResponseIdentifier());
     $this->assertEquals('testIdentifierLabel', $interaction->getLabel());
     $this->assertEquals($stimulus, QtiMarshallerUtil::marshallCollection($interaction->getPrompt()->getComponents()));
     $this->assertNull($responseDeclaration);
     $this->assertNull($responseProcessing);
     // Check `options` mapping are correct
     /** @var SimpleChoice[] $choices */
     $choices = $interaction->getSimpleChoices()->getArrayCopy(true);
     $this->assertEquals('ChoiceA', $choices[0]->getIdentifier());
     $this->assertEquals('Melbourne', QtiMarshallerUtil::marshallCollection($choices[0]->getContent()));
     $this->assertEquals('ChoiceB', $choices[1]->getIdentifier());
     $this->assertEquals('Sydney', QtiMarshallerUtil::marshallCollection($choices[1]->getContent()));
     $this->assertEquals('ChoiceC', $choices[2]->getIdentifier());
     $this->assertEquals('Jakarta', QtiMarshallerUtil::marshallCollection($choices[2]->getContent()));
     // Check the default values are correct
     $this->assertEquals(1, $interaction->getMaxChoices());
     $this->assertEquals(1, $interaction->getMinChoices());
     $this->assertEquals(Orientation::VERTICAL, $interaction->getOrientation());
 }
 public function testSimpleCase()
 {
     $data = json_decode($this->getFixtureFileContents('learnosityjsons/orderlist.json'), true);
     $assessmentItem = $this->convertToAssessmentItem($data);
     /** @var OrderInteraction $interaction */
     $interaction = $assessmentItem->getComponentsByClassName('orderInteraction', true)->getArrayCopy()[0];
     $this->assertTrue($interaction instanceof OrderInteraction);
     // And its prompt is mapped correctly
     $promptString = QtiMarshallerUtil::marshallCollection($interaction->getPrompt()->getComponents());
     $this->assertEquals('<p>[This is the stem.]</p>', $promptString);
     // Assert its choices are correct
     /** @var SimpleChoice[] $simpleChoices */
     $simpleChoices = $interaction->getSimpleChoices()->getArrayCopy(true);
     $this->assertEquals('CHOICE_0', $simpleChoices[0]->getIdentifier());
     $this->assertEquals('[Choice A]', QtiMarshallerUtil::marshallCollection($simpleChoices[0]->getComponents()));
     $this->assertEquals('CHOICE_1', $simpleChoices[1]->getIdentifier());
     $this->assertEquals('[Choice B]', QtiMarshallerUtil::marshallCollection($simpleChoices[1]->getComponents()));
     $this->assertEquals('CHOICE_2', $simpleChoices[2]->getIdentifier());
     $this->assertEquals('[Choice C]', QtiMarshallerUtil::marshallCollection($simpleChoices[2]->getComponents()));
     $this->assertEquals('CHOICE_3', $simpleChoices[3]->getIdentifier());
     $this->assertEquals('[Choice D]', QtiMarshallerUtil::marshallCollection($simpleChoices[3]->getComponents()));
     // Also assert its validation is match_correct and correct
     /** @var ResponseDeclaration $responseDeclaration */
     $responseDeclaration = $assessmentItem->getResponseDeclarations()->getArrayCopy()[0];
     $this->assertEquals(Cardinality::ORDERED, $responseDeclaration->getCardinality());
     /** @var Value[] $correctResponseValues */
     $correctResponseValues = $responseDeclaration->getCorrectResponse()->getValues()->getArrayCopy(true);
     $this->assertEquals('CHOICE_3', $correctResponseValues[0]->getValue());
     $this->assertEquals('CHOICE_1', $correctResponseValues[1]->getValue());
     $this->assertEquals('CHOICE_0', $correctResponseValues[2]->getValue());
     $this->assertEquals('CHOICE_2', $correctResponseValues[3]->getValue());
     $this->assertEquals(Constants::RESPONSE_PROCESSING_TEMPLATE_MATCH_CORRECT, $assessmentItem->getResponseProcessing()->getTemplate());
 }
 public function testSingularResponsesWithNoValidation()
 {
     $question = $this->buildSimpleChoiceMatrixQuestion();
     /** @var MatchInteraction $interaction */
     $mapper = new ChoicematrixMapper();
     list($interaction, $responseDeclaration, $responseProcessing) = $mapper->convert($question, 'testIdentifier', 'testIdentifier');
     $this->assertEquals('My stimulus string', QtiMarshallerUtil::marshallCollection($interaction->getPrompt()->getComponents()));
     $this->assertFalse($interaction->mustShuffle());
     $this->assertEquals(2, $interaction->getMaxAssociations());
     $this->assertEquals(2, $interaction->getMinAssociations());
     // Assert its source choices (stems)
     /** @var SimpleAssociableChoice[] $stemAssociableChoices */
     $stemAssociableChoices = $interaction->getSourceChoices()->getSimpleAssociableChoices()->getArrayCopy(true);
     $this->assertEquals('Stem 1', QtiMarshallerUtil::marshallCollection($stemAssociableChoices[0]->getContent()));
     $this->assertEquals('STEM_0', $stemAssociableChoices[0]->getIdentifier());
     $this->assertEquals('Stem 2', QtiMarshallerUtil::marshallCollection($stemAssociableChoices[1]->getContent()));
     $this->assertEquals('STEM_1', $stemAssociableChoices[1]->getIdentifier());
     foreach ($stemAssociableChoices as $choice) {
         $this->assertEquals(1, $choice->getMatchMax());
         $this->assertEquals(1, $choice->getMatchMin());
     }
     // Assert its target choices (options)
     /** @var SimpleAssociableChoice[] $optionAssociableChoices */
     $optionAssociableChoices = $interaction->getTargetChoices()->getSimpleAssociableChoices()->getArrayCopy(true);
     $this->assertEquals('Option 1', QtiMarshallerUtil::marshallCollection($optionAssociableChoices[0]->getContent()));
     $this->assertEquals('OPTION_0', $optionAssociableChoices[0]->getIdentifier());
     $this->assertEquals('Option 2', QtiMarshallerUtil::marshallCollection($optionAssociableChoices[1]->getContent()));
     $this->assertEquals('OPTION_1', $optionAssociableChoices[1]->getIdentifier());
     $this->assertEquals('Option 3', QtiMarshallerUtil::marshallCollection($optionAssociableChoices[2]->getContent()));
     $this->assertEquals('OPTION_2', $optionAssociableChoices[2]->getIdentifier());
     foreach ($optionAssociableChoices as $choice) {
         $this->assertEquals(2, $choice->getMatchMax());
         $this->assertEquals(1, $choice->getMatchMin());
     }
 }
 public function testMappingSimpleQuestionWithNoValidation()
 {
     $placeholder = 'placeholdertest';
     $stimulus = '<strong>stimulushere</strong>';
     $questionReference = 'questionReferenceOne';
     $question = new plaintext('plaintext');
     $question->set_placeholder($placeholder);
     $question->set_stimulus($stimulus);
     $mapper = new PlaintextMapper();
     /** @var ExtendedTextInteraction $interaction */
     list($interaction, $responseDeclaration, $responseProcessing) = $mapper->convert($question, $questionReference, $questionReference);
     // No validation shall be mapped for longtext
     $this->assertNull($responseDeclaration);
     $this->assertNull($responseProcessing);
     // Assert question mapped correctly to ExtendedTextInteraction
     $this->assertTrue($interaction instanceof ExtendedTextInteraction);
     $this->assertEquals($questionReference, $interaction->getResponseIdentifier());
     $this->assertEquals($questionReference, $interaction->getLabel());
     $this->assertEquals($stimulus, QtiMarshallerUtil::marshallCollection($interaction->getPrompt()->getComponents()));
     $this->assertEquals($placeholder, $interaction->getPlaceholderText());
     // Assert question mapped correctly with default values
     $this->assertEquals(TextFormat::PLAIN, $interaction->getFormat());
     $this->assertEquals(1, $interaction->getMinStrings());
     $this->assertEquals(1, $interaction->getMaxStrings());
 }
 public function getQuestionType()
 {
     /* @var QtiExtendedTextInteraction $interaction */
     $interaction = $this->interaction;
     $longtext = new longtext('longtext');
     LogService::log('No validation mapping supported for this interaction. Ignoring any ' . '<responseProcessing> and <responseDeclaration> if any');
     if (!empty($interaction->getPrompt())) {
         $promptContent = $interaction->getPrompt()->getContent();
         $longtext->set_stimulus(QtiMarshallerUtil::marshallCollection($promptContent));
     }
     if ($interaction->getPlaceholderText()) {
         $longtext->set_placeholder($interaction->getPlaceholderText());
     }
     /** As per QTI spec
      *  When multiple strings are accepted, expectedLength applies to each string.
      *  `expectedLength` works as a only as a 'hint' to student so we do not want to force a hard limit
      */
     if ($interaction->getExpectedLength() > 0) {
         $maxStrings = $interaction->getMaxStrings() > 0 ? $interaction->getMaxStrings() : 1;
         $expectedLength = $interaction->getExpectedLength() / 5;
         $longtext->set_max_length($maxStrings * $expectedLength);
         $longtext->set_submit_over_limit(true);
     }
     return $longtext;
 }
 public function testSimpleCase()
 {
     /** @var AssessmentItem $assessmentItem */
     $question = json_decode($this->getFixtureFileContents('learnosityjsons/data_clozedropdown.json'), true);
     $assessmentItem = $this->convertToAssessmentItem($question);
     $interactions = $assessmentItem->getComponentsByClassName('inlineChoiceInteraction', true)->getArrayCopy();
     /** @var InlineChoiceInteraction $interactionOne */
     $interactionOne = $interactions[0];
     /** @var InlineChoiceInteraction $interactionTwo */
     $interactionTwo = $interactions[1];
     $this->assertTrue($interactionOne instanceof InlineChoiceInteraction);
     $this->assertTrue($interactionTwo instanceof InlineChoiceInteraction);
     $content = QtiMarshallerUtil::marshallCollection($assessmentItem->getItemBody()->getContent());
     $this->assertNotEmpty($content);
     // Assert response processing template
     $this->assertEquals(Constants::RESPONSE_PROCESSING_TEMPLATE_MATCH_CORRECT, $assessmentItem->getResponseProcessing()->getTemplate());
     // Assert response declarations
     $responseDeclarations = $assessmentItem->getResponseDeclarations()->getArrayCopy();
     /** @var ResponseDeclaration $responseDeclarationOne */
     $responseDeclarationOne = $responseDeclarations[0];
     /** @var ResponseDeclaration $responseDeclarationTwo */
     $responseDeclarationTwo = $responseDeclarations[1];
     // Check has the correct identifiers, also correct `correctResponse` values
     $this->assertEquals($responseDeclarationOne->getIdentifier(), $interactionOne->getResponseIdentifier());
     $this->assertNull($responseDeclarationOne->getMapping());
     $this->assertEquals('INLINECHOICE_2', $responseDeclarationOne->getCorrectResponse()->getValues()->getArrayCopy()[0]->getValue());
     $this->assertEquals('Choice C', QtiMarshallerUtil::marshallCollection($interactionOne->getComponentByIdentifier('INLINECHOICE_2')->getComponents()));
     $this->assertEquals($responseDeclarationTwo->getIdentifier(), $interactionTwo->getResponseIdentifier());
     $this->assertNull($responseDeclarationTwo->getMapping());
     $this->assertEquals('INLINECHOICE_1', $responseDeclarationTwo->getCorrectResponse()->getValues()->getArrayCopy()[0]->getValue());
     $this->assertEquals('Choice B', QtiMarshallerUtil::marshallCollection($interactionTwo->getComponentByIdentifier('INLINECHOICE_1')->getComponents()));
 }
 public function getPrompt()
 {
     if ($this->interaction->getPrompt() instanceof Prompt) {
         $promptContent = $this->interaction->getPrompt()->getContent();
         return QtiMarshallerUtil::marshallCollection($promptContent);
     }
     return '';
 }
 public function testMappingItemWithSharedPassage()
 {
     $data = json_decode($this->getFixtureFileContents('learnosityjsons/item_mcq_sharedpassage.json'), true);
     $assessmentItem = $this->convertToAssessmentItem($data);
     /** @var Object $object */
     $object = $assessmentItem->getComponentsByClassName('object', true)->getArrayCopy()[0];
     $this->assertEquals('text/html', $object->getType());
     $this->assertEquals('<p>This is the content of my shared passage</p>', QtiMarshallerUtil::marshallCollection($object->getComponents()));
 }
 private function buildTemplate(ItemBody $itemBody, array $interactionXmls)
 {
     // Build item's HTML content
     $content = QtiMarshallerUtil::marshallCollection($itemBody->getComponents());
     foreach ($interactionXmls as $interactionXml) {
         $content = str_replace($interactionXml, '{{response}}', $content);
     }
     return $content;
 }
 private function buildOptions(SimpleChoiceCollection $simpleChoices)
 {
     /* @var $choice SimpleChoice */
     $options = [];
     foreach ($simpleChoices as $key => $choice) {
         // Store 'SimpleChoice' identifier to key for validation purposes
         $options[] = ['label' => QtiMarshallerUtil::marshallCollection($choice->getContent()), 'value' => $choice->getIdentifier()];
     }
     return $options;
 }
 protected function buildPossibleResponseMapping(QtiGraphicGapMatchInteraction $interaction)
 {
     $possibleResponseMapping = [];
     $gapChoices = $interaction->getGapImgs();
     /** @var GapChoice $gapChoice */
     foreach ($gapChoices as $gapChoice) {
         $gapChoiceContent = QtiMarshallerUtil::marshallCollection($gapChoice->getComponents());
         $possibleResponseMapping[$gapChoice->getIdentifier()] = $gapChoiceContent;
     }
     return $possibleResponseMapping;
 }
 private function buildOptions(SimpleMatchSet $simpleMatchSet, &$mapping)
 {
     $options = [];
     $choiceCollection = $simpleMatchSet->getSimpleAssociableChoices();
     /** @var SimpleAssociableChoice $choice */
     foreach ($choiceCollection as $choice) {
         $contentStr = QtiMarshallerUtil::marshallCollection($choice->getContent());
         $options[] = $contentStr;
         $mapping[$choice->getIdentifier()] = count($options) - 1;
     }
     return $options;
 }
 public function getQuestionType()
 {
     /** @var HotspotInteraction $interaction */
     $interaction = $this->interaction;
     $imageObject = $interaction->getObject();
     // Yes, width and height is necessary unfortunately
     if ($imageObject->getHeight() < 0 || $imageObject->getWidth() < 0) {
         throw new MappingException('Hotspot interaction image object need to specifiy both width and height for conversion');
     }
     // Slab the image object
     $hotspot = new hotspot('hotspot');
     $hotspot->set_image($this->buildHotspotImage($imageObject));
     // Support mapping for <prompt>
     if ($interaction->getPrompt() instanceof Prompt) {
         $promptContent = $interaction->getPrompt()->getContent();
         $hotspot->set_stimulus(QtiMarshallerUtil::marshallCollection($promptContent));
     }
     // Map the hotspot areas
     $areas = $this->buildAreas($interaction->getHotspotChoices(), $imageObject);
     $hotspot->set_areas($areas);
     // Setup the area attributes with assumption
     // TODO: Let's say the default fill is always clear, and the stroke would be blackish
     $globalAttributes = new hotspot_area_attributes_global();
     $globalAttributes->set_fill("rgba(0,0,0,0)");
     $globalAttributes->set_stroke("rgba(25, 90, 107, 0.5)");
     $areaAttributes = new hotspot_area_attributes();
     $areaAttributes->set_global($globalAttributes);
     $hotspot->set_area_attributes($areaAttributes);
     // Partial support for @maxChoices
     // @maxChoices of 0 or more than 1 would then would set `multiple_responses` to true
     $maxChoices = $interaction->getMaxChoices();
     if ($maxChoices !== 1) {
         if ($maxChoices !== 0 && $maxChoices !== count($areas)) {
             // We do not support specifying amount of areas
             LogService::log("Allowing multiple responses of max " . count($areas) . " options, however " . "maxChoices of {$maxChoices} would be ignored since we can't support exact number");
         }
         $hotspot->set_multiple_responses(true);
     }
     // Ignoring @minChoices
     if (!empty($interaction->getMinChoices())) {
         LogService::log('Attribute minChoices is not supported. Thus, ignored');
     }
     // Build validation
     $validationBuilder = new HotspotInteractionValidationBuilder($this->responseDeclaration, $areas, $maxChoices);
     $validation = $validationBuilder->buildValidation($this->responseProcessingTemplate);
     if (!empty($validation)) {
         $hotspot->set_validation($validation);
     }
     return $hotspot;
 }
 public function testSimpleCase()
 {
     $data = json_decode($this->getFixtureFileContents('learnosityjsons/choicematrix.json'), true);
     $assessmentItem = $this->convertToAssessmentItem($data);
     /** @var MatchInteraction $interaction */
     $interaction = $assessmentItem->getComponentsByClassName('matchInteraction', true)->getArrayCopy()[0];
     $this->assertTrue($interaction instanceof MatchInteraction);
     // And its prompt is mapped correctly
     $promptString = QtiMarshallerUtil::marshallCollection($interaction->getPrompt()->getComponents());
     $this->assertEquals('<p>[This is the stem.]</p>', $promptString);
     // Assert its source choices (stems)
     /** @var SimpleAssociableChoice[] $stemAssociableChoices */
     $stemAssociableChoices = $interaction->getSourceChoices()->getSimpleAssociableChoices()->getArrayCopy(true);
     $this->assertEquals('[Stem 1]', QtiMarshallerUtil::marshallCollection($stemAssociableChoices[0]->getContent()));
     $this->assertEquals('STEM_0', $stemAssociableChoices[0]->getIdentifier());
     $this->assertEquals('[Stem 2]', QtiMarshallerUtil::marshallCollection($stemAssociableChoices[1]->getContent()));
     $this->assertEquals('STEM_1', $stemAssociableChoices[1]->getIdentifier());
     $this->assertEquals('[Stem 3]', QtiMarshallerUtil::marshallCollection($stemAssociableChoices[2]->getContent()));
     $this->assertEquals('STEM_2', $stemAssociableChoices[2]->getIdentifier());
     $this->assertEquals('[Stem 4]', QtiMarshallerUtil::marshallCollection($stemAssociableChoices[3]->getContent()));
     $this->assertEquals('STEM_3', $stemAssociableChoices[3]->getIdentifier());
     foreach ($stemAssociableChoices as $choice) {
         $this->assertEquals(1, $choice->getMatchMax());
         $this->assertEquals(1, $choice->getMatchMin());
     }
     // Assert its target choices (options)
     /** @var SimpleAssociableChoice[] $optionAssociableChoices */
     $optionAssociableChoices = $interaction->getTargetChoices()->getSimpleAssociableChoices()->getArrayCopy(true);
     $this->assertEquals('True', QtiMarshallerUtil::marshallCollection($optionAssociableChoices[0]->getContent()));
     $this->assertEquals('OPTION_0', $optionAssociableChoices[0]->getIdentifier());
     $this->assertEquals('False', QtiMarshallerUtil::marshallCollection($optionAssociableChoices[1]->getContent()));
     $this->assertEquals('OPTION_1', $optionAssociableChoices[1]->getIdentifier());
     foreach ($optionAssociableChoices as $choice) {
         $this->assertEquals(4, $choice->getMatchMax());
         $this->assertEquals(1, $choice->getMatchMin());
     }
     // Assert its valdation, woo hooo!
     $this->assertEquals(Constants::RESPONSE_PROCESSING_TEMPLATE_MATCH_CORRECT, $assessmentItem->getResponseProcessing()->getTemplate());
     /** @var ResponseDeclaration $responseDeclaration */
     $responseDeclaration = $assessmentItem->getResponseDeclarations()->getArrayCopy()[0];
     $this->assertEquals(Cardinality::MULTIPLE, $responseDeclaration->getCardinality());
     $this->assertEquals(BaseType::DIRECTED_PAIR, $responseDeclaration->getBaseType());
     /** @var Value[] $values */
     $values = $responseDeclaration->getCorrectResponse()->getValues()->getArrayCopy(true);
     $this->assertDirectPair($values[0]->getValue(), 'STEM_0', 'OPTION_0');
     $this->assertDirectPair($values[1]->getValue(), 'STEM_1', 'OPTION_1');
     $this->assertDirectPair($values[2]->getValue(), 'STEM_2', 'OPTION_1');
     $this->assertDirectPair($values[3]->getValue(), 'STEM_3', 'OPTION_0');
     $this->assertNull($responseDeclaration->getMapping());
 }
 public function getQuestionType()
 {
     /* @var \qtism\data\content\interactions\InlineChoiceInteraction $interaction */
     $interaction = $this->validateInteraction($this->interaction);
     $template = '{{response}}';
     foreach ($interaction->getContent() as $inlineChoice) {
         $this->choicesMapping[$inlineChoice->getIdentifier()] = QtiMarshallerUtil::marshallCollection($inlineChoice->getContent());
     }
     $question = new clozedropdown('clozedropdown', $template, [array_values($this->choicesMapping)]);
     $validation = $this->buildValidation();
     if ($validation) {
         $question->set_validation($validation);
     }
     return $question;
 }
 public function testSimpleCase()
 {
     /** @var AssessmentItem $assessmentItem */
     $question = json_decode($this->getFixtureFileContents('learnosityjsons/data_clozetext.json'), true);
     $assessmentItem = $this->convertToAssessmentItem($question);
     $interactions = $assessmentItem->getComponentsByClassName('textEntryInteraction', true)->getArrayCopy();
     /** @var TextEntryInteraction $interactionOne */
     $interactionOne = $interactions[0];
     /** @var TextEntryInteraction $interactionTwo */
     $interactionTwo = $interactions[1];
     $this->assertTrue($interactionOne instanceof TextEntryInteraction);
     $this->assertTrue($interactionTwo instanceof TextEntryInteraction);
     $this->assertEquals(15, $interactionOne->getExpectedLength());
     $this->assertEquals(15, $interactionTwo->getExpectedLength());
     $content = QtiMarshallerUtil::marshallCollection($assessmentItem->getItemBody()->getContent());
     $this->assertNotEmpty($content);
     // Assert response declarations
     $responseDeclarations = $assessmentItem->getResponseDeclarations()->getArrayCopy();
     /** @var ResponseDeclaration $responseDeclarationOne */
     $responseDeclarationOne = $responseDeclarations[0];
     /** @var ResponseDeclaration $responseDeclarationTwo */
     $responseDeclarationTwo = $responseDeclarations[1];
     // Check has the correct identifiers
     $this->assertEquals($responseDeclarationOne->getIdentifier(), $interactionOne->getResponseIdentifier());
     $this->assertEquals($responseDeclarationTwo->getIdentifier(), $interactionTwo->getResponseIdentifier());
     // Also correct `correctResponse` values
     $this->assertEquals('responseone', $responseDeclarationOne->getCorrectResponse()->getValues()->getArrayCopy()[0]->getValue());
     $this->assertEquals('otherresponseone', $responseDeclarationOne->getCorrectResponse()->getValues()->getArrayCopy()[1]->getValue());
     $this->assertEquals('anotherresponseone', $responseDeclarationOne->getCorrectResponse()->getValues()->getArrayCopy()[2]->getValue());
     $this->assertEquals('responsetwo', $responseDeclarationTwo->getCorrectResponse()->getValues()->getArrayCopy()[0]->getValue());
     $this->assertEquals('otherresponsetwo', $responseDeclarationTwo->getCorrectResponse()->getValues()->getArrayCopy()[1]->getValue());
     $this->assertEquals('anotherresponsetwo', $responseDeclarationTwo->getCorrectResponse()->getValues()->getArrayCopy()[2]->getValue());
     // Also correct `mapping` entries
     $this->assertEquals('responseone', $responseDeclarationOne->getMapping()->getMapEntries()->getArrayCopy()[0]->getMapKey());
     $this->assertEquals(3, $responseDeclarationOne->getMapping()->getMapEntries()->getArrayCopy()[0]->getMappedValue());
     $this->assertEquals('otherresponseone', $responseDeclarationOne->getMapping()->getMapEntries()->getArrayCopy()[1]->getMapKey());
     $this->assertEquals(2, $responseDeclarationOne->getMapping()->getMapEntries()->getArrayCopy()[1]->getMappedValue());
     $this->assertEquals('anotherresponseone', $responseDeclarationOne->getMapping()->getMapEntries()->getArrayCopy()[2]->getMapKey());
     $this->assertEquals(1, $responseDeclarationOne->getMapping()->getMapEntries()->getArrayCopy()[2]->getMappedValue());
     $this->assertEquals('responsetwo', $responseDeclarationTwo->getMapping()->getMapEntries()->getArrayCopy()[0]->getMapKey());
     $this->assertEquals(3, $responseDeclarationTwo->getMapping()->getMapEntries()->getArrayCopy()[0]->getMappedValue());
     $this->assertEquals('otherresponsetwo', $responseDeclarationTwo->getMapping()->getMapEntries()->getArrayCopy()[1]->getMapKey());
     $this->assertEquals(2, $responseDeclarationTwo->getMapping()->getMapEntries()->getArrayCopy()[1]->getMappedValue());
     $this->assertEquals('anotherresponsetwo', $responseDeclarationTwo->getMapping()->getMapEntries()->getArrayCopy()[2]->getMapKey());
     $this->assertEquals(1, $responseDeclarationTwo->getMapping()->getMapEntries()->getArrayCopy()[2]->getMappedValue());
     // Assert response processing template
     $this->assertEquals(Constants::RESPONSE_PROCESSING_TEMPLATE_MAP_RESPONSE, $assessmentItem->getResponseProcessing()->getTemplate());
 }
 public function map($itemReference, ItemBody $itemBody, QtiComponentCollection $interactionComponents, QtiComponentCollection $responseDeclarations = null, ResponseProcessingTemplate $responseProcessingTemplate = null)
 {
     $this->itemReference = $itemReference;
     $questionsXmls = [];
     $responseDeclarationsMap = [];
     if ($responseDeclarations) {
         /** @var ResponseDeclaration $responseDeclaration */
         foreach ($responseDeclarations as $responseDeclaration) {
             $responseDeclarationsMap[$responseDeclaration->getIdentifier()] = $responseDeclaration;
         }
     }
     foreach ($interactionComponents as $component) {
         /* @var $component Interaction */
         $questionReference = $this->itemReference . '_' . $component->getResponseIdentifier();
         // Process <responseDeclaration>
         $responseDeclaration = isset($responseDeclarationsMap[$component->getResponseIdentifier()]) ? $responseDeclarationsMap[$component->getResponseIdentifier()] : null;
         $mapper = $this->getMapperInstance($component->getQtiClassName(), [$component, $responseDeclaration, $responseProcessingTemplate]);
         $question = $mapper->getQuestionType();
         $this->questions[$questionReference] = new Question($question->get_type(), $questionReference, $question);
         $questionsXmls[$questionReference] = ['qtiClassName' => $component->getQtiClassName(), 'responseIdentifier' => $component->getResponseIdentifier()];
     }
     // Build item's HTML content
     $extraContentHtml = new SimpleHtmlDom();
     if (!$extraContentHtml->load(QtiMarshallerUtil::marshallCollection($itemBody->getComponents()), false)) {
         throw new \Exception('Issues with the content for itemBody, it might not be valid');
     }
     foreach ($questionsXmls as $questionReference => $interactionData) {
         // Append this question span to our `item` content as it is
         $this->content .= '<span class="learnosity-response question-' . $questionReference . '"></span>';
         // Clean up interaction HTML content
         $qtiClassName = $interactionData['qtiClassName'];
         $responseIdentifier = $interactionData['responseIdentifier'];
         $toFind = $qtiClassName . '[responseIdentifier="' . $responseIdentifier . '"]';
         foreach ($extraContentHtml->find($toFind) as &$tag) {
             $tag->outertext = '';
         }
     }
     $extraContent = $extraContentHtml->save();
     // Making assumption question always has stimulus `right`?
     // So, prepend the extra content on the stimulus on the first question
     if (!empty(trim($extraContent))) {
         $firstQuestionReference = key($this->questions);
         $newStimulus = $extraContent . $this->questions[$firstQuestionReference]->get_data()->get_stimulus();
         $this->questions[$firstQuestionReference]->get_data()->set_stimulus($newStimulus);
         LogService::log('Extra <itemBody> content is prepended to question stimulus and please verify as this `might` break item content structure');
     }
     return true;
 }
 public function testSimpleCommonCase()
 {
     /** @var AssessmentItem $assessmentItem */
     $question = json_decode($this->getFixtureFileContents('learnosityjsons/data_imageclozeassociation.json'), true);
     $assessmentItem = $this->convertToAssessmentItem($question);
     /** @var GraphicGapMatchInteraction $interaction */
     $interaction = $assessmentItem->getComponentsByClassName('graphicGapMatchInteraction', true)->getArrayCopy()[0];
     $this->assertTrue($interaction instanceof GraphicGapMatchInteraction);
     // And its prompt is mapped correctly
     $promptString = QtiMarshallerUtil::marshallCollection($interaction->getPrompt()->getComponents());
     $this->assertEquals('<p>[This is the stem.]</p>', $promptString);
     // And its gapimages mapped well
     /** @var GapImg[] $gapImages */
     $gapImages = $interaction->getGapImgs()->getArrayCopy();
     $this->assertEquals(3, count($gapImages));
     $this->assertEquals('CHOICE_0', $gapImages[0]->getIdentifier());
     $object0 = $gapImages[0]->getComponents()->current();
     $this->assertEquals('image/png', $object0->getType());
     $this->assertEquals(56, $object0->getWidth());
     $this->assertEquals(13, $object0->getHeight());
     $this->assertEquals('CHOICE_1', $gapImages[1]->getIdentifier());
     $object1 = $gapImages[1]->getComponents()->current();
     $this->assertEquals('image/png', $object1->getType());
     $this->assertEquals(56, $object1->getWidth());
     $this->assertEquals(13, $object1->getHeight());
     $this->assertEquals('CHOICE_2', $gapImages[2]->getIdentifier());
     $object2 = $gapImages[2]->getComponents()->current();
     $this->assertEquals('image/png', $object2->getType());
     $this->assertEquals(100, $object2->getWidth());
     $this->assertEquals(100, $object2->getHeight());
     // And its associableHotspot
     // TODO: Do more through assert with coords and matchmax/matchmin check
     $this->assertEquals(3, $interaction->getAssociableHotspots()->count());
     // And its response processing and response declaration
     $this->assertEquals(Constants::RESPONSE_PROCESSING_TEMPLATE_MATCH_CORRECT, $assessmentItem->getResponseProcessing()->getTemplate());
     /** @var ResponseDeclaration $responseDeclaration */
     $responseDeclaration = $assessmentItem->getResponseDeclarations()->getArrayCopy()[0];
     $this->assertEquals(Cardinality::MULTIPLE, $responseDeclaration->getCardinality());
     $this->assertEquals(BaseType::DIRECTED_PAIR, $responseDeclaration->getBaseType());
     /** @var Value[] $values */
     $values = $responseDeclaration->getCorrectResponse()->getValues()->getArrayCopy(true);
     $this->assertDirectPair($values[0]->getValue(), 'ASSOCIABLEHOTSPOT_0', 'CHOICE_2');
     $this->assertDirectPair($values[1]->getValue(), 'ASSOCIABLEHOTSPOT_1', 'CHOICE_1');
     $this->assertDirectPair($values[2]->getValue(), 'ASSOCIABLEHOTSPOT_2', 'CHOICE_0');
     // And, we don't have mapping because we simply won't
     $this->assertEquals(null, $responseDeclaration->getMapping());
 }
 public function testSimpleWithNoValidation()
 {
     $data = json_decode($this->getFixtureFileContents('learnosityjsons/item_plaintext.json'), true);
     $assessmentItem = $this->convertToAssessmentItem($data);
     // Plaintext shall have no <responseDeclaration> and <responseProcessing>
     $this->assertEquals(0, $assessmentItem->getResponseDeclarations()->count());
     $this->assertNull($assessmentItem->getResponseProcessing());
     // Has <extendedTextInteraction> as the first and only interaction
     /** @var ExtendedTextInteraction $interaction */
     $interaction = $assessmentItem->getComponentsByClassName('extendedTextInteraction', true)->getArrayCopy()[0];
     $this->assertTrue($interaction instanceof ExtendedTextInteraction);
     // And its prompt is mapped correctly
     $promptString = QtiMarshallerUtil::marshallCollection($interaction->getPrompt()->getComponents());
     $this->assertEquals('<p>Write an essay</p>', $promptString);
     // And it is a HTML text by default
     $this->assertEquals(TextFormat::PLAIN, $interaction->getFormat());
 }
 private function buildTemplate(QtiGapMatchInteraction $interaction)
 {
     $templateCollection = new QtiComponentCollection();
     foreach ($interaction->getComponents() as $component) {
         // Ignore `prompt` and the `gapChoice` since they are going to be mapped somewhere else :)
         if (!$component instanceof Prompt && !$component instanceof GapChoice) {
             $templateCollection->attach($component);
         }
     }
     $gapIdentifiers = [];
     $content = QtiMarshallerUtil::marshallCollection($templateCollection);
     foreach ($interaction->getComponentsByClassName('gap', true) as $gap) {
         /** @var Gap $gap */
         $gapIdentifiers[] = $gap->getIdentifier();
         $gapString = QtiMarshallerUtil::marshall($gap);
         $content = str_replace($gapString, '{{response}}', $content);
     }
     return [$content, $gapIdentifiers];
 }
 protected function marshallChildrenKnown(QtiComponent $component, array $elements)
 {
     /** @var Object $component */
     switch ($this->getMIMEType($component->getType())) {
         case self::MIME_IMAGE:
             $this->checkObjectComponents($component, '<img> tag');
             $element = self::getDOMCradle()->createElement('img');
             $element->setAttribute('src', $component->getData());
             return $element;
             break;
         case self::MIME_AUDIO:
             $this->checkObjectComponents($component, '`audioplayer` feature');
             $element = self::getDOMCradle()->createElement('span');
             $element->setAttribute('class', 'learnosity-feature');
             $element->setAttribute('data-type', 'audioplayer');
             $element->setAttribute('data-src', $component->getData());
             return $element;
             break;
         case self::MIME_VIDEO:
             $this->checkObjectComponents($component, '`videoplayer` feature');
             $element = self::getDOMCradle()->createElement('span');
             $element->setAttribute('class', 'learnosity-feature');
             $element->setAttribute('data-type', 'videoplayer');
             $element->setAttribute('data-src', $component->getData());
             return $element;
             break;
         case self::MIME_HTML:
             $fragment = self::getDOMCradle()->createDocumentFragment();
             $fragment->appendXML(QtiMarshallerUtil::marshallCollection(ContentCollectionBuilder::buildFlowCollectionContent($component->getComponents())));
             $element = self::getDOMCradle()->createElement('div');
             $element->setAttribute('data-type', 'sharedpassage');
             $element->appendChild($fragment);
             return $element;
             break;
         default:
             // TODO: Need to think external HTML object file, what we are going to do with them?
             // Just parse <object> as default
             LogService::log('Unknown <object> MIME type, outputting <object> as it is');
             return parent::marshallChildrenKnown($component, $elements);
     }
 }
 public function testSimpleCase()
 {
     $data = json_decode($this->getFixtureFileContents('learnosityjsons/data_hotspot.json'), true);
     $assessmentItem = $this->convertToAssessmentItem($data);
     // Simple validation on <responseDeclaration> and <responseProcessing>
     $this->assertEquals(1, $assessmentItem->getResponseDeclarations()->count());
     $this->assertNotNull($assessmentItem->getResponseProcessing());
     // Get dah interaction
     /** @var HotspotInteraction $interaction */
     $interaction = $assessmentItem->getComponentsByClassName('hotspotInteraction', true)->getArrayCopy()[0];
     // And its prompt is mapped correctly
     $promptString = QtiMarshallerUtil::marshallCollection($interaction->getPrompt()->getComponents());
     $this->assertEquals('<p>[This is the stem.]</p>', $promptString);
     // All the choices also mapped properly
     /** @var HotspotChoice[] $choices */
     $choices = $interaction->getHotspotChoices()->getArrayCopy(true);
     $this->assertEquals($choices[0]->getIdentifier(), 'CHOICE_0');
     $this->assertEquals($choices[0]->getShape(), QtiShape::POLY);
     // QtiShape shall be POLY
     $this->assertEquals($choices[0]->getCoords()->count(), 96);
     $this->assertEquals($choices[1]->getIdentifier(), 'CHOICE_1');
     $this->assertEquals($choices[2]->getIdentifier(), 'CHOICE_2');
     $this->assertEquals($choices[3]->getIdentifier(), 'CHOICE_3');
     // Check `minChoices` and `maxChoices`
     $this->assertEquals(0, $interaction->getMinChoices());
     $this->assertEquals(1, $interaction->getMaxChoices());
     // Simple validation on <responseDeclaration> and <responseProcessing>
     $this->assertEquals(1, $assessmentItem->getResponseDeclarations()->count());
     $this->assertNotNull($assessmentItem->getResponseProcessing());
     // Check the response declaration looks good
     /** @var ResponseDeclaration $responseDeclaration */
     $responseDeclaration = $assessmentItem->getResponseDeclarations()->getArrayCopy(true)[$interaction->getResponseIdentifier()];
     $this->assertEquals(BaseType::IDENTIFIER, $responseDeclaration->getBaseType());
     $this->assertEquals(Cardinality::SINGLE, $responseDeclaration->getCardinality());
     $correctResponse = $responseDeclaration->getCorrectResponse();
     $this->assertTrue($correctResponse instanceof CorrectResponse);
     /** @var Value[] $values */
     $values = $correctResponse->getValues()->getArrayCopy(true);
     $this->assertEquals($values[0]->getValue(), 'CHOICE_0');
     $this->assertNull($responseDeclaration->getMapping());
 }
 public function testWithNoValidation()
 {
     $template = '<p><span class="lrn_token">Hello</span></p>' . '<p><span class="lrn_token">Welcome to my world!</span></p>' . '<p><span class="lrn_token">Brown sugar</span></p>';
     $question = new tokenhighlight('tokenhighlight', $template, 'custom');
     $mapper = new TokenhighlightMapper();
     /** @var HottextInteraction $interaction */
     list($interaction, $responseDeclaration, $responseProcessing) = $mapper->convert($question, 'testIdentifier', 'testIdentifierLabel');
     $this->assertTrue($interaction instanceof HottextInteraction);
     $this->assertNull($responseDeclaration);
     $this->assertNull($responseProcessing);
     // Assert those hottext
     /** @var Hottext[] $hottexts */
     $hottexts = $interaction->getComponentsByClassName('hottext', true)->getArrayCopy(true);
     $this->assertEquals(3, $interaction->getComponentsByClassName('hottext', true)->count());
     $this->assertEquals('TOKEN_0', $hottexts[0]->getIdentifier());
     $this->assertEquals('Hello', QtiMarshallerUtil::marshallCollection($hottexts[0]->getComponents()));
     $this->assertEquals('TOKEN_1', $hottexts[1]->getIdentifier());
     $this->assertEquals('Welcome to my world!', QtiMarshallerUtil::marshallCollection($hottexts[1]->getComponents()));
     $this->assertEquals('TOKEN_2', $hottexts[2]->getIdentifier());
     $this->assertEquals('Brown sugar', QtiMarshallerUtil::marshallCollection($hottexts[2]->getComponents()));
 }
 public function getQuestionType()
 {
     /* @var QtiOrderInteraction $interaction */
     $interaction = $this->interaction;
     if (!$this->validate($interaction)) {
         return null;
     }
     $list = [];
     $this->orderMapping = [];
     /** @var SimpleChoice $simpleChoice */
     foreach ($interaction->getSimpleChoices() as $simpleChoice) {
         $this->orderMapping[$simpleChoice->getIdentifier()] = count($this->orderMapping);
         $list[] = QtiMarshallerUtil::marshallCollection($simpleChoice->getContent());
     }
     $question = new orderlist('orderlist', $list);
     $question->set_stimulus($this->getPrompt());
     // Build `validation` object
     $validation = $this->buildValidation();
     if ($validation) {
         $question->set_validation($validation);
     }
     return $question;
 }
 public function testWithNoValidation()
 {
     $orderlist = $this->buildOrderlist(['ant', 'elephant', 'dog'], 'Order these animal from big to small');
     /** @var orderlist_validation $validation */
     $orderlistMapper = new OrderlistMapper();
     list($interaction, $responseDeclaration, $responseProcessing) = $orderlistMapper->convert($orderlist, 'testIdentifier', 'testIdentifierLabel');
     $this->assertNull($responseDeclaration);
     $this->assertNull($responseProcessing);
     /** @var OrderInteraction $interaction */
     $this->assertTrue($interaction instanceof OrderInteraction);
     $this->assertEquals(false, $interaction->mustShuffle());
     $this->assertEquals(-1, $interaction->getMaxChoices());
     $this->assertEquals(-1, $interaction->getMinChoices());
     $this->assertEquals(Orientation::VERTICAL, $interaction->getOrientation());
     /** @var SimpleChoice[] $choices */
     $choices = $interaction->getSimpleChoices()->getArrayCopy(true);
     $this->assertEquals('CHOICE_0', $choices[0]->getIdentifier());
     $this->assertEquals('ant', QtiMarshallerUtil::marshallCollection($choices[0]->getComponents()));
     $this->assertEquals('CHOICE_1', $choices[1]->getIdentifier());
     $this->assertEquals('elephant', QtiMarshallerUtil::marshallCollection($choices[1]->getComponents()));
     $this->assertEquals('CHOICE_2', $choices[2]->getIdentifier());
     $this->assertEquals('dog', QtiMarshallerUtil::marshallCollection($choices[2]->getComponents()));
 }
 public function testSimpleCommonCase()
 {
     /** @var AssessmentItem $assessmentItem */
     $question = json_decode($this->getFixtureFileContents('learnosityjsons/data_clozeassociation.json'), true);
     $assessmentItem = $this->convertToAssessmentItem($question);
     /** @var GapMatchInteraction $interaction */
     $interaction = $assessmentItem->getComponentsByClassName('gapMatchInteraction', true)->getArrayCopy()[0];
     $this->assertTrue($interaction instanceof GapMatchInteraction);
     $this->assertFalse($interaction->mustShuffle());
     // And its prompt is mapped correctly
     $promptString = QtiMarshallerUtil::marshallCollection($interaction->getPrompt()->getComponents());
     $this->assertEquals('<p>[This is the stem.]</p>', $promptString);
     // And its choices mapped well
     /** @var GapText[] $gapChoices */
     $gapChoices = $interaction->getGapChoices()->getArrayCopy();
     $this->assertEquals(2, count($gapChoices));
     $this->assertEquals('CHOICE_0', $gapChoices[0]->getIdentifier());
     $this->assertEquals('Choice A', QtiMarshallerUtil::marshallCollection($gapChoices[0]->getContent()));
     $this->assertEquals('CHOICE_1', $gapChoices[1]->getIdentifier());
     $this->assertEquals('Choice B', QtiMarshallerUtil::marshallCollection($gapChoices[1]->getContent()));
     // And its gaps
     $content = QtiMarshallerUtil::marshallCollection($interaction->getContent());
     $expectedContent = '<p>Risus <gap identifier="GAP_0"/>, et tincidunt turpis facilisis. Curabitur eu nulla justo. Curabitur vulputate ut nisl et bibendum. Nunc diam enim, porta sed eros vitae. <gap identifier="GAP_1"/> dignissim, et tincidunt turpis facilisis. Curabitur eu nulla justo. Curabitur vulputate ut nisl et bibendum.</p>';
     $this->assertEquals($expectedContent, $content);
     // And its response processing and response declaration
     $this->assertEquals(Constants::RESPONSE_PROCESSING_TEMPLATE_MATCH_CORRECT, $assessmentItem->getResponseProcessing()->getTemplate());
     /** @var ResponseDeclaration $responseDeclaration */
     $responseDeclaration = $assessmentItem->getResponseDeclarations()->getArrayCopy()[0];
     $this->assertEquals(Cardinality::MULTIPLE, $responseDeclaration->getCardinality());
     $this->assertEquals(BaseType::DIRECTED_PAIR, $responseDeclaration->getBaseType());
     /** @var Value[] $values */
     $values = $responseDeclaration->getCorrectResponse()->getValues()->getArrayCopy(true);
     $this->assertDirectPair($values[0]->getValue(), 'GAP_0', 'CHOICE_0');
     $this->assertDirectPair($values[1]->getValue(), 'GAP_1', 'CHOICE_1');
     // And, we don't have mapping because we simply won't
     $this->assertEquals(null, $responseDeclaration->getMapping());
 }
 private function buildTemplate(HottextInteraction $interaction)
 {
     $templateCollection = new QtiComponentCollection();
     foreach ($interaction->getComponents() as $component) {
         // Ignore `prompt` since its going to be mapped to `stimulus`
         if (!$component instanceof Prompt) {
             $templateCollection->attach($component);
         }
     }
     $content = QtiMarshallerUtil::marshallCollection($templateCollection);
     foreach ($interaction->getComponentsByClassName('hottext') as $hottext) {
         /** @var Hottext $hottext */
         $hottextString = QtiMarshallerUtil::marshall($hottext);
         $tokenSpan = new span();
         $tokenSpan->setClass('lrn_token');
         $inlineCollection = new InlineCollection();
         foreach ($hottext->getComponents() as $c) {
             $inlineCollection->attach($c);
         }
         $tokenSpan->setContent($inlineCollection);
         $content = str_replace($hottextString, QtiMarshallerUtil::marshall($tokenSpan), $content);
     }
     return $content;
 }
 private function assertInteractionTwo(ChoiceInteraction $interaction, ResponseDeclaration $responseDeclaration)
 {
     // And its prompt is mapped correctly
     $promptString = QtiMarshallerUtil::marshallCollection($interaction->getPrompt()->getComponents());
     $this->assertEquals('Pick the odd one out', $promptString);
     // All the choices also mapped properly
     /** @var SimpleChoice[] $simpleChoices */
     $simpleChoices = $interaction->getSimpleChoices()->getArrayCopy(true);
     $this->assertEquals($simpleChoices[0]->getIdentifier(), 'CHOICE_0');
     $this->assertEquals(QtiMarshallerUtil::marshallCollection($simpleChoices[0]->getContent()), 'Tomato');
     $this->assertEquals($simpleChoices[1]->getIdentifier(), 'CHOICE_1');
     $this->assertEquals(QtiMarshallerUtil::marshallCollection($simpleChoices[1]->getContent()), 'Orange');
     $this->assertEquals($simpleChoices[2]->getIdentifier(), 'CHOICE_2');
     $this->assertEquals(QtiMarshallerUtil::marshallCollection($simpleChoices[2]->getContent()), 'Celery');
     $this->assertEquals($simpleChoices[3]->getIdentifier(), 'CHOICE_3');
     $this->assertEquals(QtiMarshallerUtil::marshallCollection($simpleChoices[3]->getContent()), 'Pear');
     // Check usual stuff
     $this->assertEquals(1, $interaction->getMinChoices());
     $this->assertEquals(1, $interaction->getMaxChoices());
     $this->assertFalse($interaction->mustShuffle());
     $this->assertEquals(Orientation::HORIZONTAL, $interaction->getOrientation());
     // Check the response declaration fine for mcq with multiple responses
     $this->assertEquals(BaseType::IDENTIFIER, $responseDeclaration->getBaseType());
     $this->assertEquals(Cardinality::SINGLE, $responseDeclaration->getCardinality());
     $correctResponse = $responseDeclaration->getCorrectResponse();
     $this->assertTrue($correctResponse instanceof CorrectResponse);
     /** @var Value[] $values */
     $values = $correctResponse->getValues()->getArrayCopy(true);
     $this->assertEquals($values[0]->getValue(), 'CHOICE_2');
     $this->assertNull($responseDeclaration->getMapping());
 }