public function convert(BaseQuestionType $question, $interactionIdentifier, $interactionLabel) { /** @var tokenhighlight $question */ // Grab those `template` and convert those highlights to <hottext> $html = new SimpleHtmlDom(); $html->load($question->get_template()); $tokens = $html->find('span.lrn_token'); $indexIdentifierMap = []; foreach ($tokens as $key => &$span) { $span->outertext = '<hottext identifier="TOKEN_' . intval($key) . '">' . $span->innertext . '</hottext>'; $indexIdentifierMap[$key] = 'TOKEN_' . intval($key); } $htmlContent = $html->save(); $contentComponents = QtiMarshallerUtil::unmarshallElement($htmlContent); $contentCollection = ContentCollectionBuilder::buildBlockStaticCollectionContent($contentComponents); // Build the interaction $interaction = new HottextInteraction($interactionIdentifier, $contentCollection); $interaction->setLabel($interactionLabel); $interaction->setPrompt($this->convertStimulusForPrompt($question->get_stimulus())); // Learnosity does not enforce number of choices, thus using default such the min choice would be 1 // and max would be the `max_selection` if set, otherwise use token count $interaction->setMinChoices(1); $interaction->setMaxChoices(is_int($question->get_max_selection()) ? $question->get_max_selection() : count($tokens)); // Build validation $builder = new TokenhighlightValidationBuilder($indexIdentifierMap); list($responseDeclaration, $responseProcessing) = $builder->buildValidation($interaction->getResponseIdentifier(), $question->get_validation()); return [$interaction, $responseDeclaration, $responseProcessing]; }
public function convert(BaseQuestionType $questionType, $interactionIdentifier, $interactionLabel) { //TODO: Need validation a question shall have at least 1 {{response}} and 1 item in `possible_responses` /** @var clozeassociation $question */ $question = $questionType; // Replace {{ response }} with `gap` elements $index = 0; $template = preg_replace_callback('/{{response}}/', function ($match) use(&$index) { $gapIdentifier = self::GAP_IDENTIFIER_PREFIX . $index; $replacement = '<gap identifier="' . $gapIdentifier . '"/>'; $index++; return $replacement; }, $question->get_template()); $content = ContentCollectionBuilder::buildBlockStaticCollectionContent(QtiMarshallerUtil::unmarshallElement($template)); // Map `possible_responses` to gaps // TODO: Detect `img` $gapChoices = new GapChoiceCollection(); $possibleResponses = $question->get_possible_responses(); $matchMax = $question->get_duplicate_responses() ? count($possibleResponses) : 1; foreach ($possibleResponses as $index => $possibleResponse) { $gapChoice = new GapText(self::GAPCHOICE_IDENTIFIER_PREFIX . $index, $matchMax); $gapChoiceContent = new TextOrVariableCollection(); $gapChoiceContent->attach(new TextRun($possibleResponse)); $gapChoice->setContent($gapChoiceContent); $gapChoices->attach($gapChoice); } $interaction = new GapMatchInteraction($interactionIdentifier, $gapChoices, $content); $interaction->setLabel($interactionLabel); $interaction->setPrompt($this->convertStimulusForPrompt($question->get_stimulus())); $validationBuilder = new ClozeassociationValidationBuilder($possibleResponses); list($responseDeclaration, $responseProcessing) = $validationBuilder->buildValidation($interaction->getResponseIdentifier(), $question->get_validation()); return [$interaction, $responseDeclaration, $responseProcessing]; }