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;
 }
 private function transformCoordinates(QtiCoords $coords, $shape, Object $imageObject)
 {
     $width = $imageObject->getWidth();
     $height = $imageObject->getHeight();
     $coords = explode(',', $coords);
     switch ($shape) {
         // rect: left-x, top-y, right-x, bottom-y.
         case QtiShape::RECT:
             $leftX = round($coords[0] / $width * 100, 2);
             $topY = round($coords[1] / $height * 100, 2);
             $rightX = round($coords[2] / $width * 100, 2);
             $bottomY = round($coords[3] / $height * 100, 2);
             $result = [['x' => $leftX, 'y' => $topY], ['x' => $rightX, 'y' => $topY], ['x' => $rightX, 'y' => $bottomY], ['x' => $leftX, 'y' => $bottomY]];
             return $result;
         case QtiShape::CIRCLE:
             // circle: center-x, center-y, radius. Note. When the radius value is a percentage value, user agents
             // should calculate the final radius value based on the associated object's width and height. The radius should be the smaller value of the two.
             LogService::log('Unable to map QTI `circle` Shape. Mapping it as `rect` instead');
             $radius = $coords[2];
             $leftX = round(($coords[0] - $radius) / $width * 100, 2);
             $topY = round(($coords[1] + $radius) / $height * 100, 2);
             $rightX = round(($coords[0] + $radius) / $width * 100, 2);
             $bottomY = round(($coords[1] - $radius) / $height * 100, 2);
             $result = [['x' => $leftX, 'y' => $topY], ['x' => $rightX, 'y' => $topY], ['x' => $rightX, 'y' => $bottomY], ['x' => $leftX, 'y' => $bottomY]];
             return $result;
         case QtiShape::POLY:
             // poly: x1, y1, x2, y2, ..., xN, yN. The first x and y coordinate pair and the last should be the same to close the polygon.
             // When these coordinate values are not the same, user agents should infer an additional coordinate pair to close the polygon.
             $result = [];
             for ($i = 0; $i < count($coords); $i += 2) {
                 $result[] = ['x' => round($coords[$i] / $width * 100, 2), 'y' => round($coords[$i + 1] / $height * 100, 2)];
             }
             return $result;
         case QtiShape::ELLIPSE:
         default:
             LogService::log('Unsupported QTI Shape mapping conversion. Area mapping conversion is ignored');
             return [];
     }
 }