protected function buildTemplate(QtiGraphicGapMatchInteraction $interaction, Object $object)
 {
     $associableHotspots = [];
     foreach ($interaction->getAssociableHotspots() as $associableHotspot) {
         /** @var AssociableHotspot $associableHotspot */
         $associableHotspots[$associableHotspot->getIdentifier()] = QtiCoordinateUtil::convertQtiCoordsToPercentage([$object->getWidth(), $object->getHeight()], explode(',', $associableHotspot->getCoords()), $associableHotspot->getShape());
     }
     return $associableHotspots;
 }
 /**
  * Unmarshall a DOMElement object corresponding to a graphicGapMatchInteraction element.
  *
  * @param \DOMElement $element A DOMElement object.
  * @return \qtism\data\QtiComponent A GraphicGapMatchInteraction object.
  * @throws \qtism\data\storage\xml\marshalling\UnmarshallingException
  */
 protected function unmarshall(DOMElement $element)
 {
     if (($responseIdentifier = self::getDOMElementAttributeAs($element, 'responseIdentifier')) !== null) {
         $objectElts = self::getChildElementsByTagName($element, 'object');
         if (count($objectElts) > 0) {
             $object = $this->getMarshallerFactory()->createMarshaller($objectElts[0])->unmarshall($objectElts[0]);
             $associableHotspotElts = self::getChildElementsByTagName($element, 'associableHotspot');
             if (count($associableHotspotElts) > 0) {
                 $associableHotspots = new AssociableHotspotCollection();
                 foreach ($associableHotspotElts as $associableHotspotElt) {
                     $associableHotspots[] = $this->getMarshallerFactory()->createMarshaller($associableHotspotElt)->unmarshall($associableHotspotElt);
                 }
                 $gapImgElts = self::getChildElementsByTagName($element, 'gapImg');
                 if (count($gapImgElts) > 0) {
                     $gapImgs = new GapImgCollection();
                     foreach ($gapImgElts as $gapImgElt) {
                         $gapImgs[] = $this->getMarshallerFactory()->createMarshaller($gapImgElt)->unmarshall($gapImgElt);
                     }
                     $component = new GraphicGapMatchInteraction($responseIdentifier, $object, $gapImgs, $associableHotspots);
                     $promptElts = self::getChildElementsByTagName($element, 'prompt');
                     if (count($promptElts) > 0) {
                         $promptElt = $promptElts[0];
                         $prompt = $this->getMarshallerFactory()->createMarshaller($promptElt)->unmarshall($promptElt);
                         $component->setPrompt($prompt);
                     }
                     if (($xmlBase = self::getXmlBase($element)) !== false) {
                         $component->setXmlBase($xmlBase);
                     }
                     $this->fillBodyElement($component, $element);
                     return $component;
                 } else {
                     $msg = "A 'graphicGapMatchInteraction' element must contain at least one 'gapImg' element, none given.";
                     throw new UnmarshallingException($msg, $element);
                 }
             } else {
                 $msg = "A 'graphiGapMatchInteraction' element must contain at least one 'associableHotspot' element, none given.";
                 throw new UnmarshallingException($msg, $element);
             }
         } else {
             $msg = "A 'graphicGapMatchInteraction' element must contain exactly one 'object' element, none given.";
             throw new UnmarshallingException($msg, $element);
         }
     } else {
         $msg = "The mandatory 'responseIdentifier' attribute is missing from the 'graphicGapMatchInteraction' element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 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 imageclozeassociation $question */
     $question = $questionType;
     // Map `possible_responses` to `gapImg`(s)
     $possibleResponses = $question->get_possible_responses();
     $matchMax = !is_null($question->get_duplicate_responses()) ? count($possibleResponses) : 1;
     $gapImageCollection = $this->buildGapImgCollection($possibleResponses, $matchMax);
     // Build the main background image `object`
     $imageObject = $this->buildMainImageObject($question->get_image());
     // Build associable hotspots based on `response_positions`
     $associableHotspotCollection = $this->buildAssociableHotspotCollection($question->get_response_positions(), $imageObject->getWidth(), $imageObject->getHeight());
     // Build dah` interaction
     $interaction = new GraphicGapMatchInteraction($interactionIdentifier, $imageObject, $gapImageCollection, $associableHotspotCollection);
     $interaction->setLabel($interactionLabel);
     $interaction->setPrompt($this->convertStimulusForPrompt($question->get_stimulus()));
     $validationBuilder = new ImageclozeassociationValidationBuilder($possibleResponses);
     list($responseDeclaration, $responseProcessing) = $validationBuilder->buildValidation($interaction->getResponseIdentifier(), $question->get_validation());
     return [$interaction, $responseDeclaration, $responseProcessing];
 }
 public function testMarshall()
 {
     $prompt = new Prompt();
     $prompt->setContent(new FlowStaticCollection(array(new TextRun('Prompt...'))));
     $object = new Object('myimg.png', 'image/png');
     $img1 = new Object('img1.png', 'image/png');
     $gapImg1 = new GapImg('gapImg1', 1, $img1);
     $img2 = new Object('img2.png', 'image/png');
     $gapImg2 = new GapImg('gapImg2', 1, $img2);
     $img3 = new Object('img3.png', 'image/png');
     $gapImg3 = new GapImg('gapImg3', 1, $img3);
     $gapImgs = new GapImgCollection(array($gapImg1, $gapImg2, $gapImg3));
     $choice1 = new AssociableHotspot('choice1', 1, QtiShape::CIRCLE, new QtiCoords(QtiShape::CIRCLE, array(0, 0, 15)));
     $choice2 = new AssociableHotspot('choice2', 1, QtiShape::CIRCLE, new QtiCoords(QtiShape::CIRCLE, array(2, 2, 15)));
     $choice3 = new AssociableHotspot('choice3', 1, QtiShape::CIRCLE, new QtiCoords(QtiShape::CIRCLE, array(4, 4, 15)));
     $choices = new AssociableHotspotCollection(array($choice1, $choice2, $choice3));
     $graphicGapMatchInteraction = new GraphicGapMatchInteraction('RESPONSE', $object, $gapImgs, $choices, 'my-gaps');
     $graphicGapMatchInteraction->setPrompt($prompt);
     $element = $this->getMarshallerFactory('2.1.0')->createMarshaller($graphicGapMatchInteraction)->marshall($graphicGapMatchInteraction);
     $dom = new DOMDocument('1.0', 'UTF-8');
     $element = $dom->importNode($element, true);
     $this->assertEquals('<graphicGapMatchInteraction id="my-gaps" responseIdentifier="RESPONSE"><prompt>Prompt...</prompt><object data="myimg.png" type="image/png"/><gapImg identifier="gapImg1" matchMax="1"><object data="img1.png" type="image/png"/></gapImg><gapImg identifier="gapImg2" matchMax="1"><object data="img2.png" type="image/png"/></gapImg><gapImg identifier="gapImg3" matchMax="1"><object data="img3.png" type="image/png"/></gapImg><associableHotspot identifier="choice1" shape="circle" coords="0,0,15" matchMax="1"/><associableHotspot identifier="choice2" shape="circle" coords="2,2,15" matchMax="1"/><associableHotspot identifier="choice3" shape="circle" coords="4,4,15" matchMax="1"/></graphicGapMatchInteraction>', $dom->saveXML($element));
 }