Validate on server the hotspots answers - refs #7705

1.10.x
Angel Fernando Quiroz Campos 9 years ago
parent db99d4dea9
commit 6a73fbd679
  1. 28
      main/exercice/exercise.class.php
  2. 10
      main/exercice/hotspot_actionscript.as.php
  3. 144
      main/inc/lib/geometry.lib.php
  4. 54
      main/inc/lib/javascript/hotspot/js/hotspot.js

@ -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;
}

@ -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>';

@ -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;
}
}

@ -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;

Loading…
Cancel
Save