Ver código fonte

Validate on server the hotspots answers - refs #7705

Angel Fernando Quiroz Campos 9 anos atrás
pai
commit
6a73fbd679

+ 27 - 1
main/exercice/exercise.class.php

@@ -3027,7 +3027,33 @@ class Exercise
                         }
                     } else {
                         $studentChoice = $choice[$answerAutoId];
-                        if ($studentChoice) {
+
+                        $choiceIsValid = false;
+
+                        if (!empty($studentChoice)) {
+                            $hotspotType = $objAnswerTmp->selectHotspotType($answerId);
+                            $hotspotCoordinates = $objAnswerTmp->selectHotspotCoordinates($answerId);
+                            $choicePoint = Geometry::decodePoint($studentChoice);
+
+                            switch ($hotspotType) {
+                                case 'square':
+                                    $hotspotProperties = Geometry::decodeSquare($hotspotCoordinates);
+                                    $choiceIsValid = Geometry::pointIsInSquare($hotspotProperties, $choicePoint);
+                                    break;
+
+                                case 'circle':
+                                    $hotspotProperties = Geometry::decodeEllipse($hotspotCoordinates);
+                                    $choiceIsValid = Geometry::pointIsInEllipse($hotspotProperties, $choicePoint);
+                                    break;
+
+                                case 'poly':
+                                    $hotspotProperties = Geometry::decodePolygon($hotspotCoordinates);
+                                    $choiceIsValid = Geometry::pointIsInPolygon($hotspotProperties, $choicePoint);
+                                    break;
+                            }
+                        }
+
+                        if ($choiceIsValid) {
                             $questionScore  += $answerWeighting;
                             $totalScore     += $answerWeighting;
                         }

+ 9 - 1
main/exercice/hotspot_actionscript.as.php

@@ -111,6 +111,14 @@ while ($hotspot = Database::fetch_assoc($result))
 $data['nmbrTries'] = $nmbrTries;
 $data['done'] = 'done';
 
+$objAnswerTmp = new Answer($questionId);
+
+$attempList = Event::getAllExerciseEventByExeId(40);
+$userChoice = $attempList[$questionId][0];
+//var_dump($answer->selectHotspotCoordinates($questionId), $userChoice);
+
 header('Content-Type: application/json');
 
-echo json_encode($data);
+//echo '<pre>';
+echo json_encode($data, JSON_PRETTY_PRINT);
+//echo '</pre>';

+ 144 - 0
main/inc/lib/geometry.lib.php

@@ -333,3 +333,147 @@ function poly_get_max(&$coords1, &$coords2) {
     }
     return array('x'=>$mx,'y'=>$my);
 }
+
+/**
+ * Class Geometry
+ * Utils for decode hotspots and check if the user choices are correct
+ */
+class Geometry
+{
+    /**
+     * Decode a user choice as a point
+     * @param string $coordinates
+     * @return array The x and y properties for a point
+     */
+    public static function decodePoint($coordinates)
+    {
+        $coordinates = explode(';', $coordinates);
+
+        return [
+            'x' => intval($coordinates[0]),
+            'y' => intval($coordinates[1])
+        ];
+    }
+
+    /**
+     * Decode a square info as properties
+     * @param string $coordinates
+     * @return array The x, y, width, and height properties for a square
+     */
+    public static function decodeSquare($coordinates)
+    {
+        $coordinates = explode('|', $coordinates);
+        $originString = explode(';', $coordinates[0]);
+
+        return [
+            'x' => intval($originString[0]),
+            'y' => intval($originString[1]),
+            'width' => intval($coordinates[1]),
+            'height' => intval($coordinates[2])
+        ];
+    }
+
+    /**
+     * Decode an ellipse info as properties
+     * @param string $coordinates
+     * @return array The center_x, center_y, radius_x, radius_x properties for an ellipse
+     */
+    public static function decodeEllipse($coordinates)
+    {
+        $coordinates = explode('|', $coordinates);
+        $originString = explode(';', $coordinates[0]);
+
+        return [
+            'center_x' => intval($originString[0]),
+            'center_y' => intval($originString[1]),
+            'radius_x' => intval($coordinates[1]),
+            'radius_y' => intval($coordinates[2])
+        ];
+    }
+
+    /**
+     * Decode a polygon info as properties
+     * @param string $coordinates
+     * @return array The array of points for a polygon
+     */
+    public static function decodePolygon($coordinates)
+    {
+        $coordinates = explode('|', $coordinates);
+
+        $points = [];
+
+        foreach ($coordinates as $coordinate) {
+            $point = explode(';', $coordinate);
+
+            $points[] = [
+                intval($point[0]),
+                intval($point[1])
+            ];
+        }
+
+        return $points;
+    }
+
+    /**
+     * Check if the point is inside of a square
+     * @param array $properties The hotspot properties
+     * @param array $point The point properties
+     * @return boolean
+     */
+    public static function pointIsInSquare($properties, $point)
+    {
+        $left = $properties['x'];
+        $right = $properties['x'] + $properties['width'];
+        $top = $properties['y'];
+        $bottom = $properties['y'] + $properties['height'];
+
+        $xIsValid = $point['x'] >= $left && $point['x'] <= $right;
+        $yIsValid = $point['y'] >= $top && $point['y'] <= $bottom;
+
+        return $xIsValid && $yIsValid;
+    }
+
+    /**
+     * Check if the point is inside of an ellipse
+     * @param array $properties The hotspot properties
+     * @param array $point The point properties
+     * @return boolean
+     */
+    public static function pointIsInEllipse($properties, $point)
+    {
+        $dX = $point['x'] - $properties['center_x'];
+        $dY = $point['y'] - $properties['center_y'];
+
+        $dividend = pow($dX, 2) / pow($properties['radius_x'], 2);
+        $divider = pow($dY, 2) / pow($properties['radius_y'], 2);
+
+        return $dividend + $divider <= 1;
+    }
+
+    /**
+     * Check if the point is inside of a polygon
+     * @param array $properties The hotspot properties
+     * @param array $point The point properties
+     * @return boolean
+     */
+    public static function pointIsInPolygon($properties, $point) {
+        $points = $properties;
+        $isInside = false;
+
+        for ($i = 0, $j = count($points) - 1; $i < count($points); $j = $i++) {
+            $xi = $points[$i][0];
+            $yi = $points[$i][1];
+            $xj = $points[$j][0];
+            $yj = $points[$j][1];
+
+            $intersect = (($yi > $point['y']) !== ($yj > $point['y'])) &&
+                ($point['x'] < ($xj - $xi) * ($point['y'] - $yi) / ($yj - $yi) + $xi);
+
+            if ($intersect) {
+                $isInside = !$isInside;
+            }
+        }
+
+        return $isInside;
+    }
+}

+ 2 - 52
main/inc/lib/javascript/hotspot/js/hotspot.js

@@ -20,9 +20,6 @@ window.HotspotQuestion = (function () {
         HotspotModel.prototype.onChange = function (callback) {
             this.changeEvent = callback;
         };
-        HotspotModel.prototype.checkPoint = function (x, y) {
-            return false;
-        };
         HotspotModel.decode = function () {
             return new this;
         };
@@ -56,17 +53,6 @@ window.HotspotQuestion = (function () {
                 this.set('height', y - startY);
             }
         };
-        SquareModel.prototype.checkPoint = function (x, y) {
-            var left = this.get('x'),
-                right = this.get('x') + this.get('width'),
-                top = this.get('y'),
-                bottom = this.get('y') + this.get('height');
-
-            var xIsValid = x >= left && x <= right,
-                yIsValid = y >= top && y <= bottom;
-
-            return xIsValid && yIsValid;
-        };
         SquareModel.decode = function (hotspotInfo) {
             var coords = hotspotInfo.coord.split('|'),
                 position = coords[0].split(';'),
@@ -127,15 +113,6 @@ window.HotspotQuestion = (function () {
                 this.set('centerY', startY + this.get('radiusY'));
             }
         };
-        EllipseModel.prototype.checkPoint = function (x, y) {
-            var dX = x - this.get('centerX'),
-                dY = y - this.get('centerY');
-
-            var dividend = Math.pow(dX, 2) / Math.pow(this.get('radiusX'), 2),
-                divider = Math.pow(dY, 2) / Math.pow(this.get('radiusY'), 2);
-
-            return dividend + divider <= 1;
-        };
         EllipseModel.decode = function (hotspotInfo) {
             var coords = hotspotInfo.coord.split('|'),
                 center = coords[0].split(';'),
@@ -176,25 +153,6 @@ window.HotspotQuestion = (function () {
 
             this.set('points', points);
         };
-        PolygonModel.prototype.checkPoint = function (x, y) {
-            var points = this.get('points'),
-                isInside = false;
-
-            for (var i = 0, j = points.length - 1; i < points.length; j = i++) {
-                var xi = points[i][0],
-                    yi = points[i][1],
-                    xj = points[j][0],
-                    yj = points[j][1];
-
-                var intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
-
-                if (intersect) {
-                    isInside = !isInside;
-                }
-            }
-
-            return isInside;
-        };
         PolygonModel.decode = function (hotspotInfo) {
             var pairedPoints = hotspotInfo.coord.split('|'),
                 points = [];
@@ -874,11 +832,7 @@ window.HotspotQuestion = (function () {
                 type: 'hidden',
                 name: 'choice[' + config.questionId + '][' + hotspot.id + ']'
             }).val(function () {
-                if (hotspot.checkPoint(x, y)) {
-                    return 1;
-                }
-
-                return 0;
+                return [x, y].join(';');
             }).appendTo(this.el.parentNode);
         };
         UserHotspotsSVG.prototype.setEvents = function () {
@@ -968,11 +922,7 @@ window.HotspotQuestion = (function () {
                         return [point.x, point.y].join(';');
                     });
                     $('[name="choice[' + config.questionId + '][' + hotspot.id + ']"]').val(function () {
-                        if (hotspot.checkPoint(point.x, point.y)) {
-                            return 1;
-                        }
-
-                        return 0;
+                        return [point.x, point.y].join(';');
                     });
 
                     isMoving = false;