Show answers for HotSpot question - refs #7705

1.10.x
Angel Fernando Quiroz Campos 9 years ago
parent 8b8fd28e17
commit ef99fae435
  1. 41
      main/exercice/exercise.class.php
  2. 2
      main/exercice/exercise_result.php
  3. 92
      main/exercice/hotspot_answers.as.php
  4. 24
      main/inc/lib/events.lib.php
  5. 212
      main/plugin/hotspot2/js/hotspot_solution.js

@ -3137,7 +3137,7 @@ class Exercise
$totalScore += $answerWeighting;
}
} else {
$studentChoice = $choice[$answerId];
$studentChoice = $choice[$answerAutoId];
if ($studentChoice) {
$questionScore += $answerWeighting;
$totalScore += $answerWeighting;
@ -4036,25 +4036,24 @@ class Exercise
if ($show_result) {
// if ($origin != 'learnpath') {
echo '</table></td></tr>';
echo '<tr>
<td colspan="2">';
echo '<i>'.get_lang('HotSpot').'</i><br /><br />';
echo '<object type="application/x-shockwave-flash" data="'
. api_get_path(WEB_CODE_PATH)
. 'plugin/hotspot/hotspot_solution.swf?modifyAnswers='
. Security::remove_XSS($questionId)
. '&exe_id='
. $exeId
. '&from_db=1" width="552" height="352">
<param name="movie" value="../plugin/hotspot/hotspot_solution.swf?modifyAnswers='
. Security::remove_XSS($questionId)
. '&exe_id='
. $exeId
. '&from_db=1" />
</object>';
echo '</td>
</tr>';
echo "
<tr>
<td colspan=\"2\">
<p><em>" . get_lang('HotSpot') . "</em></p>
<div id=\"hotspot-solution\"></div>
<script>
$(document).on('ready', function () {
HotSpotSolution.init({
questionId: $questionId,
exerciseId: $exeId,
selector: '#hotspot-solution'
});
});
</script>
</td>
</tr>
";
// }
}
}
@ -4143,7 +4142,7 @@ class Exercise
Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id);
if (isset($exerciseResultCoordinates[$questionId]) && !empty($exerciseResultCoordinates[$questionId])) {
foreach ($exerciseResultCoordinates[$questionId] as $idx => $val) {
Event::saveExerciseAttemptHotspot($exeId, $quesId, $idx, $choice[$idx], $val, $this->id);
Event::saveExerciseAttemptHotspot($exeId, $quesId, $idx, $choice[$idx], $val, false, $this->id);
}
}
} else {

@ -75,6 +75,8 @@ $interbreadcrumb[] = array(
"name" => get_lang('Exercises'),
);
$htmlHeadXtra[] = '<script src="../plugin/hotspot2/js/hotspot_solution.js"></script>';
if ($origin != 'learnpath') {
// So we are not in learnpath tool
Display::display_header($nameTools, get_lang('Exercise'));

@ -13,7 +13,6 @@ include('../inc/global.inc.php');
// Set vars
$questionId = intval($_GET['modifyAnswers']);
$exe_id = intval($_GET['exe_id']);
$from_db = isset($_GET['from_db']) ? $_GET['from_db'] : 0;
$objQuestion = Question :: read($questionId);
$TBL_ANSWERS = Database::get_course_table(TABLE_QUIZ_ANSWER);
$documentPath = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document';
@ -24,10 +23,6 @@ $pictureSize = getimagesize($picturePath.'/'.$objQuestion->selectPicture());
$pictureWidth = $pictureSize[0];
$pictureHeight = $pictureSize[1];
$courseLang = $_course['language'];
$course_code = Database::escape_string($_course['id']);
$coursePath = $_course['path'];
$answer_type = $objQuestion->selectType();
$course_id = api_get_course_int_id();
@ -42,64 +37,79 @@ if ($answer_type == HOT_SPOT_DELINEATION) {
}
$result = Database::query($sql);
// Init
$output = "hotspot_lang=$courseLang&hotspot_image=$pictureName&hotspot_image_width=$pictureWidth&hotspot_image_height=$pictureHeight&courseCode=$coursePath";
$i = 0;
$data['lang'] = [
'Square' => get_lang('square'),
'Circle' => get_lang('circle'),
'Poly' => get_lang('poly'),
'Status1' => get_lang('status1'),
'Status2_poly' => get_lang('status2_poly'),
'Status2_other' => get_lang('status2_other'),
'Status3' => get_lang('status3'),
'ShowUserPoints' => get_lang('showUserPoints'),
'LabelPolyMenu' => get_lang('labelPolyMenu'),
'Triesleft' => get_lang('triesleft'),
'ExeFinished' => get_lang('exeFinished'),
'NextAnswer' => get_lang('nextAnswer'),
'Delineation' => get_lang('delineation'),
'LabelDelineationMenu' => get_lang('labelDelineationMenu'),
'Oar' => get_lang('oar')
];
$data['image'] = $objQuestion->selectPicturePath();
$data['image_width'] = $pictureWidth;
$data['image_height'] = $pictureHeight;
$data['courseCode'] = $_course['path'];
$data['hotspots'] = [];
while ($hotspot = Database::fetch_array($result)) {
$output .= "&hotspot_".$hotspot['id']."=true";
$hotSpot = [];
$hotSpot['id'] = $hotspot['id'];
// Square or rectancle
if ($hotspot['hotspot_type'] == 'square' ) {
$output .= "&hotspot_".$hotspot['id']."_type=square";
$hotSpot['type'] = 'square';
}
// Circle or ovale
if ($hotspot['hotspot_type'] == 'circle') {
$output .= "&hotspot_".$hotspot['id']."_type=circle";
$hotSpot['type'] = 'circle';
}
// Polygon
if ($hotspot['hotspot_type'] == 'poly') {
$output .= "&hotspot_".$hotspot['id']."_type=poly";
$hotSpot['type'] = 'poly';
}
// Delineation
if ($hotspot['hotspot_type'] == 'delineation') {
$output .= "&hotspot_".$hotspot['id']."_type=delineation";
$hotSpot['type'] = 'delineation';
}
// oar
if ($hotspot['hotspot_type'] == 'oar') {
$output .= "&hotspot_".$hotspot['id']."_type=delineation";
$hotSpot['type'] = 'delineation';
}
$output .= "&hotspot_".$hotspot['id']."_coord=".$hotspot['hotspot_coordinates']."";
$i++;
}
// Generate empty (the maximum number of points is 12 - it is said so in the user interface)
$i++;
for ($i; $i <= 12; $i++) {
$output .= "&hotspot_".$i."=false";
$hotSpot['coord'] = $hotspot['hotspot_coordinates'];
$data['hotspots'][] = $hotSpot;
}
$data['answers'] = [];
// Get clicks
if(isset($_SESSION['exerciseResultCoordinates']) && $from_db==0) {
foreach ($_SESSION['exerciseResultCoordinates'][$questionId] as $coordinate) {
$output2 .= $coordinate."|";
}
} else {
// get it from db
$tbl_track_e_hotspot = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT);
$sql = "SELECT hotspot_coordinate
FROM $tbl_track_e_hotspot
WHERE hotspot_question_id = $questionId AND
c_id = $course_id AND
hotspot_exe_id = $exe_id
ORDER by hotspot_id";
$rs = @Database::query($sql); // don't output error because we are in Flash execution.
while($row = Database :: fetch_array($rs)) {
$output2 .= $row['hotspot_coordinate']."|";
}
$tbl_track_e_hotspot = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT);
$sql = "SELECT hotspot_coordinate
FROM $tbl_track_e_hotspot
WHERE hotspot_question_id = $questionId AND
c_id = $course_id AND
hotspot_exe_id = $exe_id
ORDER by hotspot_id";
$rs = Database::query($sql); // don't output error because we are in Flash execution.
while($row = Database :: fetch_array($rs, 'ASSOC')) {
$data['answers'][] = $row['hotspot_coordinate'];
}
$output .= "&p_hotspot_answers=".api_substr($output2,0,-1)."&done=done";
$explode = explode('&', $output);
echo $output;
$data['done'] = 'done';
header('Content-Type: application/json');
echo json_encode($data);

@ -613,17 +613,19 @@ class Event
)));
} else {
$sql = "INSERT INTO $tbl_track_e_hotspot (hotspot_course_code, hotspot_user_id, c_id, hotspot_exe_id, hotspot_question_id, hotspot_answer_id, hotspot_correct, hotspot_coordinate)
VALUES (
'".api_get_course_id()."',
".api_get_user_id()."',".
" ".api_get_course_int_id().", ".
" '".Database :: escape_string($exe_id)."', ".
" '".Database :: escape_string($question_id)."',".
" '".Database :: escape_string($answer_id)."',".
" '".Database :: escape_string($correct)."',".
" '".Database :: escape_string($coords)."')";
return $result = Database::query($sql);
return Database::insert(
$tbl_track_e_hotspot,
[
'hotspot_course_code' => api_get_course_id(),
'hotspot_user_id' => api_get_user_id(),
'c_id' => api_get_course_int_id(),
'hotspot_exe_id' => $exe_id,
'hotspot_question_id' => $question_id,
'hotspot_answer_id' => $answer_id,
'hotspot_correct' => $correct,
'hotspot_coordinate' => $coords
]
);
}
}

@ -0,0 +1,212 @@
var HotSpotSolution = (function () {
var Answer = function () {
this.x = 0;
this.y = 0;
};
var Square = function () {
this.x = 0,
this.y = 0,
this.width = 0,
this.height = 0
};
var Ellipse = function () {
this.centerX = 0;
this.centerY = 0;
this.radiusX = 0;
this.radiusY = 0;
};
var Polygon = function () {
this.points = [];
};
var config, lang, hotSpots = [], answers = [];
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);
};
CanvasSVG.prototype.addHotSpot = function (hotSpot) {
var hotSpotSVG = null;
if (hotSpot instanceof Square) {
hotSpotSVG = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
hotSpotSVG.setAttribute('x', hotSpot.x);
hotSpotSVG.setAttribute('y', hotSpot.y);
hotSpotSVG.setAttribute('width', hotSpot.width);
hotSpotSVG.setAttribute('height', hotSpot.height);
} else if (hotSpot instanceof Ellipse) {
hotSpotSVG = document.createElementNS('http://www.w3.org/2000/svg', 'ellipse');
hotSpotSVG.setAttribute('cx', hotSpot.centerX);
hotSpotSVG.setAttribute('cy', hotSpot.centerY);
hotSpotSVG.setAttribute('rx', hotSpot.radiusX);
hotSpotSVG.setAttribute('ry', hotSpot.radiusY);
} else if (hotSpot instanceof Polygon) {
var pointsPaired = [];
hotSpot.points.forEach(function (point) {
pointsPaired.push(point.join(','));
});
hotSpotSVG = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
hotSpotSVG.setAttribute(
'points',
pointsPaired.join(' ')
);
}
if (!hotSpotSVG) {
return;
}
var color = colors[hotSpots.length - 1];
hotSpotSVG.setAttribute('stroke-width', 2);
hotSpotSVG.setAttribute('stroke', 'rgb(' + color + ')');
hotSpotSVG.setAttribute('fill', 'rgba(' + color + ', 0.5)');
this.el.appendChild(hotSpotSVG);
};
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 = hotSpots.length;
this.el.appendChild(pointSVG);
this.el.appendChild(textSVG);
};
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 = position[0];
hotSpot.y = position[1];
hotSpot.width = coords[1];
hotSpot.height = 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];
break;
case 'poly':
hotSpot = new Polygon();
coords.forEach(function (coord) {
hotSpot.points.push(coord.split(';'));
});
break;
}
return hotSpot;
};
var colors = [
'66, 113, 181',
'254, 142, 22',
'69, 199, 240',
'188, 214, 49',
'214, 49, 115',
'215, 215, 215',
'144, 175, 221',
'174, 134, 64',
'79, 146, 66',
'244, 235, 36',
'237, 32, 36',
'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();
image.onload = function () {
var canvasSVG = new CanvasSVG(this);
hotSpotAnswerInfo.hotspots.forEach(function (hotSpotInfo) {
var hotSpot = decodeHotSpot(hotSpotInfo);
if (!hotSpot) {
return;
}
hotSpots.push(hotSpot);
canvasSVG.addHotSpot(hotSpot);
});
hotSpotAnswerInfo.answers.forEach(function (answerInfo) {
var answer = decodeAnswer(answerInfo);
answers.push(answer);
canvasSVG.addAnswer(answer);
});
$(config.selector)
.css('width', this.width)
.append(canvasSVG.el);
};
image.src = hotSpotAnswerInfo.image;
lang = hotSpotAnswerInfo.lang;
};
return {
init: function (settings) {
config = $.extend({
questionId: 0,
exerciseId: 0,
selector: ''
}, settings);
if (!config.questionId || !config.selector) {
return;
}
var xhrHotSpotAnswers = $.getJSON('/main/exercice/hotspot_answers.as.php', {
modifyAnswers: parseInt(config.questionId),
exe_id: parseInt(config.exerciseId)
});
$.when(xhrHotSpotAnswers).done(startAnswer);
}
};
})();
Loading…
Cancel
Save