Просмотр исходного кода

Validate answers for hotspots questions - refs #7705

Angel Fernando Quiroz Campos 9 лет назад
Родитель
Сommit
d8284f0ed4

+ 2 - 7
main/exercice/hotspot_actionscript.as.php

@@ -60,7 +60,6 @@ $data['image_height'] = $pictureHeight;
 $data['courseCode'] = $_course['path'];
 $data['hotspots'] = [];
 
-$i = 0;
 $nmbrTries = 0;
 
 while ($hotspot = Database::fetch_assoc($result))
@@ -100,16 +99,12 @@ while ($hotspot = Database::fetch_assoc($result))
 	{
 		$nmbrTries++;
 	}
-    unset($hotSpot['type']);
-    //$hotSpot['coord'] = $hotspot['hotspot_coordinates'];
-	$i++;
+
+    $hotSpot['coord'] = $hotspot['hotspot_coordinates'];
 
     $data['hotspots'][] = $hotSpot;
 }
 
-// Generate empty
-$i++;
-
 $data['nmbrTries'] = $nmbrTries;
 $data['done'] = 'done';
 

+ 42 - 23
main/plugin/hotspot2/js/hotspot_solution.js

@@ -4,23 +4,37 @@ var HotSpotSolution = (function () {
         this.y = 0;
     };
 
+    var HotSpot = function () {
+        this.id = 0;
+        this.name = '';
+    };
+
     var Square = function () {
+        HotSpot.call(this);
+
         this.x = 0,
         this.y = 0,
         this.width = 0,
-        this.height = 0
+        this.height = 0;
     };
+    Square.prototype = Object.create(HotSpot.prototype);
 
     var Ellipse = function () {
+        HotSpot.call(this);
+
         this.centerX = 0;
         this.centerY = 0;
         this.radiusX = 0;
         this.radiusY = 0;
     };
+    Ellipse.prototype = Object.create(HotSpot.prototype);
 
     var Polygon = function () {
+        HotSpot.call(this);
+
         this.points = [];
     };
+    Polygon.prototype = Object.create(HotSpot.prototype);
 
     var config, lang, hotSpots = [], answers = [];
 
@@ -105,25 +119,30 @@ var HotSpotSolution = (function () {
                 var position = coords[0].split(';');
 
                 hotSpot = new Square();
-                hotSpot.x = position[0];
-                hotSpot.y = position[1];
-                hotSpot.width = coords[1];
-                hotSpot.height = coords[2];
+                hotSpot.x = parseInt(position[0]);
+                hotSpot.y = parseInt(position[1]);
+                hotSpot.width = parseInt(coords[1]);
+                hotSpot.height = parseInt(coords[2]);
                 break;
             case 'circle':
                 var center = coords[0].split(';');
 
                 hotSpot = new Ellipse();
-                hotSpot.centerX = center[0];
-                hotSpot.centerY = center[1];
-                hotSpot.radiusX = coords[1];
-                hotSpot.radiusY = coords[2];
+                hotSpot.centerX = parseInt(center[0]);
+                hotSpot.centerY = parseInt(center[1]);
+                hotSpot.radiusX = parseInt(coords[1]);
+                hotSpot.radiusY = parseInt(coords[2]);
                 break;
             case 'poly':
                 hotSpot = new Polygon();
 
-                coords.forEach(function (coord) {
-                    hotSpot.points.push(coord.split(';'));
+                coords.forEach(function (pairedCoord) {
+                    var coord = pairedCoord.split(';');
+
+                    hotSpot.points.push([
+                        parseInt(coord[0]),
+                        parseInt(coord[1])
+                    ]);
                 });
                 break;
         }
@@ -131,6 +150,17 @@ var HotSpotSolution = (function () {
         return hotSpot;
     };
 
+    var decodeAnswer = function (answerInfo) {
+        var answer = null,
+            coords = answerInfo.split(';');
+
+        answer = new Answer();
+        answer.x = coords[0];
+        answer.y = coords[1];
+
+        return answer;
+    };
+
     var colors = [
         '66, 113, 181',
         '254, 142, 22',
@@ -146,19 +176,8 @@ var HotSpotSolution = (function () {
         '59, 59, 59'
     ];
 
-    var decodeAnswer = function (answerInfo) {
-        var answer = null,
-            coords = answerInfo.split(';');
-
-        answer = new Answer();
-        answer.x = coords[0];
-        answer.y = coords[1];
-
-        return answer;
-    };
-
     var startAnswer = function (hotSpotAnswerInfo) {
-        image = new Image();
+        var image = new Image();
         image.onload = function () {
             var canvasSVG = new CanvasSVG(this);
 

+ 235 - 102
main/plugin/hotspot2/js/hotspot_user.js

@@ -1,118 +1,251 @@
 var HotSpotUser = (function () {
-    var config, lang, canvas, image, hotspots;
-
-    config = {questionId: 0, selector: ''};
-
-    var canvas = (function () {
-        var points = [],
-            messageText = document.createElement('div');
-
-        return {
-            el: document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
-            render: function () {
-                var self = this;
-
-                var imageSvg = document.createElementNS('http://www.w3.org/2000/svg', 'image');
-                imageSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'href', image.src);
-                imageSvg.setAttribute('width', image.width);
-                imageSvg.setAttribute('height', image.height);
-
-                canvas.el.setAttribute('version', '1.1');
-                canvas.el.setAttribute('viewBox', '0 0 ' + image.width + ' ' + image.height);
-                canvas.el.appendChild(imageSvg);
-                canvas.el.addEventListener('dragstart', function (e) {
-                    e.preventDefault();
-                }, false);
-                canvas.el.addEventListener('click', function (e) {
-                    e.preventDefault();
-
-                    if (points.length >= hotspots.length) {
-                        return;
-                    }
-
-                    var point = getPointOnImage(e.clientX, e.clientY);
-
-                    self.addPoint(point.x, point.y);
-                }, false);
-
-                $(messageText).text(lang.NextAnswer + ' ' + hotspots[0].answer);
-
-                $(config.selector).prepend(messageText);
-
-                return this;
-            },
-            addPoint: function (x, y) {
-                points.push([x, y]);
-
-                var pointSVG = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
-                pointSVG.setAttribute('cx', x);
-                pointSVG.setAttribute('cy', y);
-                pointSVG.setAttribute('r', 15);
-                pointSVG.setAttribute('fill', '#00677C');
-
-                var textSVG = document.createElementNS('http://www.w3.org/2000/svg', 'text');
-                textSVG.setAttribute('x', x);
-                textSVG.setAttribute('y', y);
-                textSVG.setAttribute('dy', 5);
-                textSVG.setAttribute('font-family', 'sans-serif');
-                textSVG.setAttribute('text-anchor', 'middle');
-                textSVG.setAttribute('fill', 'white');
-                textSVG.textContent = points.length;
-
-                var txtHotSpot = $('<input>').attr({
-                    type: 'hidden',
-                    name: 'hotspot[' + config.questionId + '][' + hotspots[points.length - 1].id + ']'
-                }).val([x, y].join(';'));
-
-                var txtChoice = $('<input>').attr({
-                    type: 'hidden',
-                    name: 'choice[' + config.questionId + '][' + hotspots[points.length - 1].id + ']'
-                }).val(1);
-
-                $(canvas.el).append(pointSVG);
-                $(canvas.el).append(textSVG);
-                $(config.selector).append(txtHotSpot);
-                $(config.selector).append(txtChoice);
-
-                if (points.length === hotspots.length) {
-                    $(messageText).text(lang.ExeFinished);
+    var Answer = function () {
+        this.x = 0;
+        this.y = 0;
+    };
 
-                    return;
-                }
+    var HotSpot = function () {
+        this.id = 0;
+        this.name = '';
+    };
+    HotSpot.prototype.checkPoint = function (x, y) {
+        return false;
+    };
+
+    var Square = function () {
+        HotSpot.call(this);
+
+        this.x = 0,
+        this.y = 0,
+        this.width = 0,
+        this.height = 0;
+    };
+    Square.prototype = Object.create(HotSpot.prototype);
+    Square.prototype.checkPoint = function (x, y) {
+        var left = this.x,
+            right = this.x + this.width,
+            top = this.y,
+            bottom = this.y + this.height;
+
+        var xIsValid = x >= left && x <= right,
+            yIsValid = y >= top && y <= bottom;
+
+        return xIsValid && yIsValid;
+    };
+
+    var Ellipse = function () {
+        HotSpot.call(this);
+
+        this.centerX = 0;
+        this.centerY = 0;
+        this.radiusX = 0;
+        this.radiusY = 0;
+    };
+    Ellipse.prototype = Object.create(HotSpot.prototype);
+    Ellipse.prototype.checkPoint = function (x, y) {
+        var dX = x - this.centerX,
+            dY = y - this.centerY;
+
+        return Math.pow(dX, 2) / Math.pow(this.radiusX, 2) + Math.pow(dY, 2) / Math.pow(this.radiusY, 2) <= 1;
+    };
+
+    var Polygon = function () {
+        HotSpot.call(this);
+
+        this.points = [];
+    };
+    Polygon.prototype = Object.create(HotSpot.prototype);
+    Polygon.prototype.checkPoint = function (x, y) {
+        var isInside = false;
 
-                $(messageText).text(lang.NextAnswer + ' ' + hotspots[points.length].answer);
+        for (var i = 0, j = this.points.length - 1; i < this.points.length; j = i++) {
+            var xi = this.points[i][0],
+                yi = this.points[i][1],
+                xj = this.points[j][0],
+                yj = this.points[j][1];
+
+            var intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
+
+            if (intersect) {
+                isInside = !isInside;
             }
+        }
+
+        return isInside;
+    };
+
+    var CanvasSVG = function (image) {
+        var imageSvg = document.createElementNS('http://www.w3.org/2000/svg', 'image');
+        imageSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'href', image.src);
+        imageSvg.setAttribute('width', image.width);
+        imageSvg.setAttribute('height', image.height);
+
+        this.el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
+        this.el.setAttribute('version', '1.1');
+        this.el.setAttribute('viewBox', '0 0 ' + image.width + ' ' + image.height);
+        this.el.appendChild(imageSvg);
+
+        this.messagesEl = document.createElement('div');
+    };
+    CanvasSVG.prototype.setEvents = function () {
+        var self = this;
+
+        var getPointOnImage = function (x, y) {
+            var pointerPosition = {
+                    left: x + window.scrollX,
+                    top: y + window.scrollY
+                },
+                canvasOffset = {
+                    x: self.el.getBoundingClientRect().x + window.scrollX,
+                    y: self.el.getBoundingClientRect().y + window.scrollY
+                };
+
+            return {
+                x: Math.round(pointerPosition.left - canvasOffset.x),
+                y: Math.round(pointerPosition.top - canvasOffset.y)
+            };
         };
-    })();
+
+        this.el.addEventListener('dragstart', function (e) {
+            e.preventDefault();
+        }, false);
+        this.el.addEventListener('click', function (e) {
+            e.preventDefault();
+
+            if (answers.length >= hotSpots.length) {
+                return;
+            }
+
+            var point = getPointOnImage(e.clientX, e.clientY);
+
+            var answer = new Answer();
+            answer.x = point.x;
+            answer.y = point.y;
+
+            answers.push(answer);
+            self.addAnswer(answer);
+
+            if (answers.length === hotSpots.length) {
+                self.messagesEl.textContent = lang.ExeFinished;
+
+                return;
+            }
+
+            self.messagesEl.textContent = lang.NextAnswer + ' ' + hotSpots[answers.length].name;
+        });
+    };
+    CanvasSVG.prototype.addAnswer = function (answer) {
+        var pointSVG = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
+        pointSVG.setAttribute('cx', answer.x);
+        pointSVG.setAttribute('cy', answer.y);
+        pointSVG.setAttribute('r', 15);
+        pointSVG.setAttribute('fill', '#00677C');
+
+        var textSVG = document.createElementNS('http://www.w3.org/2000/svg', 'text');
+        textSVG.setAttribute('x', answer.x);
+        textSVG.setAttribute('y', answer.y);
+        textSVG.setAttribute('dy', 5);
+        textSVG.setAttribute('font-family', 'sans-serif');
+        textSVG.setAttribute('text-anchor', 'middle');
+        textSVG.setAttribute('fill', 'white');
+        textSVG.textContent = answers.length;
+
+        this.el.appendChild(pointSVG);
+        this.el.appendChild(textSVG);
+
+        var hotSpot = hotSpots[answers.length - 1];
+
+        var hotspotTxt = document.createElement('input');
+        hotspotTxt.type = 'hidden';
+        hotspotTxt.name = 'hotspot[' + config.questionId + '][' + hotSpot.id + ']';
+        hotspotTxt.value = [answer.x, answer.y].join(';');
+
+        var choiceTxt = document.createElement('input');
+        choiceTxt.type = 'hidden';
+        choiceTxt.name = 'choice[' + config.questionId + '][' + hotSpot.id + ']';
+        choiceTxt.value = hotSpot.checkPoint(answer.x, answer.y) ? 1 : 0;
+
+        this.el.parentNode.appendChild(hotspotTxt);
+        this.el.parentNode.appendChild(choiceTxt);
+    };
+    CanvasSVG.prototype.startMessagesPanel = function () {
+        this.messagesEl.textContent = lang.NextAnswer + ' ' + hotSpots[0].name;
+
+        this.el.parentNode.parentNode.appendChild(this.messagesEl);
+    };
+
+    var decodeHotSpot = function (hotSpotInfo) {
+        var hotSpot = null,
+            coords = hotSpotInfo.coord.split('|');
+
+        switch (hotSpotInfo.type) {
+            case 'square':
+                var position = coords[0].split(';');
+
+                hotSpot = new Square();
+                hotSpot.x = parseInt(position[0]);
+                hotSpot.y = parseInt(position[1]);
+                hotSpot.width = parseInt(coords[1]);
+                hotSpot.height = parseInt(coords[2]);
+                break;
+            case 'circle':
+                var center = coords[0].split(';');
+
+                hotSpot = new Ellipse();
+                hotSpot.centerX = parseInt(center[0]);
+                hotSpot.centerY = parseInt(center[1]);
+                hotSpot.radiusX = parseInt(coords[1]);
+                hotSpot.radiusY = parseInt(coords[2]);
+                break;
+            case 'poly':
+                hotSpot = new Polygon();
+
+                coords.forEach(function (pairedCoord) {
+                    var coord = pairedCoord.split(';');
+
+                    hotSpot.points.push([
+                        parseInt(coord[0]),
+                        parseInt(coord[1])
+                    ]);
+                });
+                break;
+        }
+
+        if (hotSpot) {
+            hotSpot.id = parseInt(hotSpotInfo.id);
+            hotSpot.name = hotSpotInfo.answer;
+        }
+
+        return hotSpot;
+    };
+
+    var config, lang, hotSpots = [], answers = [];
 
     var startQuestion = function (hotSpotQuestionInfo) {
-        image = new Image();
+        var image = new Image();
         image.onload = function () {
-            $(config.selector)
-                .css('width', this.width + 'px')
-                .append(canvas.render().el);
-        };
-        image.src = hotSpotQuestionInfo.image;
+            var canvasSVG = new CanvasSVG(this);
 
-        hotspots = hotSpotQuestionInfo.hotspots;
+            hotSpotQuestionInfo.hotspots.forEach(function (hotSpotInfo) {
+                var hotSpot = decodeHotSpot(hotSpotInfo);
 
-        lang = hotSpotQuestionInfo.lang;
-    };
+                if (!hotSpot) {
+                    return;
+                }
 
-    var getPointOnImage = function (x, y) {
-        var pointerPosition = {
-            left: x + window.scrollX,
-            top: y + window.scrollY
-        },
-            canvasOffset = {
-                x: canvas.el.getBoundingClientRect().x + window.scrollX,
-                y: canvas.el.getBoundingClientRect().y + window.scrollY
-            };
+                hotSpots.push(hotSpot);
+            });
 
-        return {
-            x: Math.round(pointerPosition.left - canvasOffset.x),
-            y: Math.round(pointerPosition.top - canvasOffset.y)
+            $(config.selector)
+                .css('width', this.width)
+                .append(canvasSVG.el);
+
+            canvasSVG.setEvents();
+            canvasSVG.startMessagesPanel();
         };
+        image.src = hotSpotQuestionInfo.image;
+
+        lang = hotSpotQuestionInfo.lang;
     };
 
     return {