Validate answers for hotspots questions - refs #7705

1.10.x
Angel Fernando Quiroz Campos 10 years ago
parent d56df2c936
commit d8284f0ed4
  1. 9
      main/exercice/hotspot_actionscript.as.php
  2. 65
      main/plugin/hotspot2/js/hotspot_solution.js
  3. 337
      main/plugin/hotspot2/js/hotspot_user.js

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

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

@ -1,118 +1,251 @@
var HotSpotUser = (function () { var HotSpotUser = (function () {
var config, lang, canvas, image, hotspots; var Answer = function () {
this.x = 0;
config = {questionId: 0, selector: ''}; this.y = 0;
};
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);
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) { var startQuestion = function (hotSpotQuestionInfo) {
image = new Image(); var image = new Image();
image.onload = function () { image.onload = function () {
$(config.selector) var canvasSVG = new CanvasSVG(this);
.css('width', this.width + 'px')
.append(canvas.render().el);
};
image.src = hotSpotQuestionInfo.image;
hotspots = hotSpotQuestionInfo.hotspots; hotSpotQuestionInfo.hotspots.forEach(function (hotSpotInfo) {
var hotSpot = decodeHotSpot(hotSpotInfo);
lang = hotSpotQuestionInfo.lang; if (!hotSpot) {
}; return;
}
var getPointOnImage = function (x, y) { hotSpots.push(hotSpot);
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
};
return { $(config.selector)
x: Math.round(pointerPosition.left - canvasOffset.x), .css('width', this.width)
y: Math.round(pointerPosition.top - canvasOffset.y) .append(canvasSVG.el);
canvasSVG.setEvents();
canvasSVG.startMessagesPanel();
}; };
image.src = hotSpotQuestionInfo.image;
lang = hotSpotQuestionInfo.lang;
}; };
return { return {

Loading…
Cancel
Save