mirror of
https://github.com/moodle/moodle.git
synced 2025-08-05 00:46:50 +02:00
Merge branch 'MDL-57757-master' of git://github.com/jleyva/moodle
This commit is contained in:
commit
49ba56cf38
6 changed files with 347 additions and 142 deletions
|
@ -708,6 +708,28 @@ class mod_lesson_external extends external_api {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes an attempt grade structure.
|
||||
*
|
||||
* @param int $required if the structure is required or optional
|
||||
* @return external_single_structure the structure
|
||||
* @since Moodle 3.3
|
||||
*/
|
||||
protected static function get_user_attempt_grade_structure($required = VALUE_REQUIRED) {
|
||||
$data = array(
|
||||
'nquestions' => new external_value(PARAM_INT, 'Number of questions answered'),
|
||||
'attempts' => new external_value(PARAM_INT, 'Number of question attempts'),
|
||||
'total' => new external_value(PARAM_FLOAT, 'Max points possible'),
|
||||
'earned' => new external_value(PARAM_FLOAT, 'Points earned by student'),
|
||||
'grade' => new external_value(PARAM_FLOAT, 'Calculated percentage grade'),
|
||||
'nmanual' => new external_value(PARAM_INT, 'Number of manually graded questions'),
|
||||
'manualpoints' => new external_value(PARAM_FLOAT, 'Point value for manually graded questions'),
|
||||
);
|
||||
return new external_single_structure(
|
||||
$data, 'Attempt grade', $required
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the parameters for get_user_attempt_grade.
|
||||
*
|
||||
|
@ -758,7 +780,8 @@ class mod_lesson_external extends external_api {
|
|||
self::check_can_view_user_data($params['userid'], $course, $cm, $context);
|
||||
}
|
||||
|
||||
$result = (array) lesson_grade($lesson, $params['lessonattempt'], $params['userid']);
|
||||
$result = array();
|
||||
$result['grade'] = (array) lesson_grade($lesson, $params['lessonattempt'], $params['userid']);
|
||||
$result['warnings'] = $warnings;
|
||||
return $result;
|
||||
}
|
||||
|
@ -772,13 +795,7 @@ class mod_lesson_external extends external_api {
|
|||
public static function get_user_attempt_grade_returns() {
|
||||
return new external_single_structure(
|
||||
array(
|
||||
'nquestions' => new external_value(PARAM_INT, 'Number of questions answered'),
|
||||
'attempts' => new external_value(PARAM_INT, 'Number of question attempts'),
|
||||
'total' => new external_value(PARAM_FLOAT, 'Max points possible'),
|
||||
'earned' => new external_value(PARAM_FLOAT, 'Points earned by student'),
|
||||
'grade' => new external_value(PARAM_FLOAT, 'Calculated percentage grade'),
|
||||
'nmanual' => new external_value(PARAM_INT, 'Number of manually graded questions'),
|
||||
'manualpoints' => new external_value(PARAM_FLOAT, 'Point value for manually graded questions'),
|
||||
'grade' => self::get_user_attempt_grade_structure(),
|
||||
'warnings' => new external_warnings(),
|
||||
)
|
||||
);
|
||||
|
@ -1761,4 +1778,105 @@ class mod_lesson_external extends external_api {
|
|||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the parameters for get_user_attempt.
|
||||
*
|
||||
* @return external_external_function_parameters
|
||||
* @since Moodle 3.3
|
||||
*/
|
||||
public static function get_user_attempt_parameters() {
|
||||
return new external_function_parameters (
|
||||
array(
|
||||
'lessonid' => new external_value(PARAM_INT, 'Lesson instance id.'),
|
||||
'userid' => new external_value(PARAM_INT, 'The user id. 0 for current user.'),
|
||||
'lessonattempt' => new external_value(PARAM_INT, 'The attempt number.'),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return information about the given user attempt (including answers).
|
||||
*
|
||||
* @param int $lessonid lesson instance id
|
||||
* @param int $userid the user id
|
||||
* @param int $lessonattempt the attempt number
|
||||
* @return array of warnings and page attempts
|
||||
* @since Moodle 3.3
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
public static function get_user_attempt($lessonid, $userid, $lessonattempt) {
|
||||
global $USER;
|
||||
|
||||
$params = array(
|
||||
'lessonid' => $lessonid,
|
||||
'userid' => $userid,
|
||||
'lessonattempt' => $lessonattempt,
|
||||
);
|
||||
$params = self::validate_parameters(self::get_user_attempt_parameters(), $params);
|
||||
$warnings = array();
|
||||
|
||||
list($lesson, $course, $cm, $context) = self::validate_lesson($params['lessonid']);
|
||||
|
||||
// Default value for userid.
|
||||
if (empty($params['userid'])) {
|
||||
$params['userid'] = $USER->id;
|
||||
}
|
||||
|
||||
// Extra checks so only users with permissions can view other users attempts.
|
||||
if ($USER->id != $params['userid']) {
|
||||
self::check_can_view_user_data($params['userid'], $course, $cm, $context);
|
||||
}
|
||||
|
||||
list($answerpages, $userstats) = lesson_get_user_detailed_report_data($lesson, $userid, $params['lessonattempt']);
|
||||
|
||||
$result = array(
|
||||
'answerpages' => $answerpages,
|
||||
'userstats' => $userstats,
|
||||
'warnings' => $warnings,
|
||||
);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the get_user_attempt return value.
|
||||
*
|
||||
* @return external_single_structure
|
||||
* @since Moodle 3.3
|
||||
*/
|
||||
public static function get_user_attempt_returns() {
|
||||
return new external_single_structure(
|
||||
array(
|
||||
'answerpages' => new external_multiple_structure(
|
||||
new external_single_structure(
|
||||
array(
|
||||
'title' => new external_value(PARAM_RAW, 'Page title.'),
|
||||
'contents' => new external_value(PARAM_RAW, 'Page contents.'),
|
||||
'qtype' => new external_value(PARAM_TEXT, 'Identifies the page type of this page.'),
|
||||
'grayout' => new external_value(PARAM_INT, 'If is required to apply a grayout.'),
|
||||
'answerdata' => new external_single_structure(
|
||||
array(
|
||||
'score' => new external_value(PARAM_TEXT, 'The score (text version).'),
|
||||
'response' => new external_value(PARAM_RAW, 'The response text.'),
|
||||
'responseformat' => new external_format_value('response.'),
|
||||
'answers' => new external_multiple_structure(
|
||||
new external_multiple_structure(new external_value(PARAM_RAW, 'Possible answers and info.'))
|
||||
)
|
||||
), 'Answer data (empty in content pages created in Moodle 1.x).', VALUE_OPTIONAL
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
'userstats' => new external_single_structure(
|
||||
array(
|
||||
'grade' => new external_value(PARAM_FLOAT, 'Attempt final grade.'),
|
||||
'completed' => new external_value(PARAM_INT, 'Time completed.'),
|
||||
'timetotake' => new external_value(PARAM_INT, 'Time taken.'),
|
||||
'gradeinfo' => self::get_user_attempt_grade_structure(VALUE_OPTIONAL)
|
||||
)
|
||||
),
|
||||
'warnings' => new external_warnings(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,4 +140,12 @@ $functions = array(
|
|||
'capabilities' => 'mod/lesson:viewreports',
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
|
||||
),
|
||||
'mod_lesson_get_user_attempt' => array(
|
||||
'classname' => 'mod_lesson_external',
|
||||
'methodname' => 'get_user_attempt',
|
||||
'description' => 'Return information about the given user attempt (including answers).',
|
||||
'type' => 'read',
|
||||
'capabilities' => 'mod/lesson:viewreports',
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1009,6 +1009,149 @@ function lesson_get_overview_report_table_and_data(lesson $lesson, $currentgroup
|
|||
return array($table, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return information about one user attempt (including answers)
|
||||
* @param lesson $lesson lesson instance
|
||||
* @param int $userid the user id
|
||||
* @param int $attempt the attempt number
|
||||
* @return array the user answers (array) and user data stats (object)
|
||||
* @since Moodle 3.3
|
||||
*/
|
||||
function lesson_get_user_detailed_report_data(lesson $lesson, $userid, $attempt) {
|
||||
global $DB;
|
||||
|
||||
$context = $lesson->context;
|
||||
if (!empty($userid)) {
|
||||
// Apply overrides.
|
||||
$lesson->update_effective_access($userid);
|
||||
}
|
||||
|
||||
$lessonpages = $lesson->load_all_pages();
|
||||
foreach ($lessonpages as $lessonpage) {
|
||||
if ($lessonpage->prevpageid == 0) {
|
||||
$pageid = $lessonpage->id;
|
||||
}
|
||||
}
|
||||
|
||||
// now gather the stats into an object
|
||||
$firstpageid = $pageid;
|
||||
$pagestats = array();
|
||||
while ($pageid != 0) { // EOL
|
||||
$page = $lessonpages[$pageid];
|
||||
$params = array ("lessonid" => $lesson->id, "pageid" => $page->id);
|
||||
if ($allanswers = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND pageid = :pageid", $params, "timeseen")) {
|
||||
// get them ready for processing
|
||||
$orderedanswers = array();
|
||||
foreach ($allanswers as $singleanswer) {
|
||||
// ordering them like this, will help to find the single attempt record that we want to keep.
|
||||
$orderedanswers[$singleanswer->userid][$singleanswer->retry][] = $singleanswer;
|
||||
}
|
||||
// this is foreach user and for each try for that user, keep one attempt record
|
||||
foreach ($orderedanswers as $orderedanswer) {
|
||||
foreach($orderedanswer as $tries) {
|
||||
$page->stats($pagestats, $tries);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no one answered yet...
|
||||
}
|
||||
//unset($orderedanswers); initialized above now
|
||||
$pageid = $page->nextpageid;
|
||||
}
|
||||
|
||||
$manager = lesson_page_type_manager::get($lesson);
|
||||
$qtypes = $manager->get_page_type_strings();
|
||||
|
||||
$answerpages = array();
|
||||
$answerpage = "";
|
||||
$pageid = $firstpageid;
|
||||
// cycle through all the pages
|
||||
// foreach page, add to the $answerpages[] array all the data that is needed
|
||||
// from the question, the users attempt, and the statistics
|
||||
// grayout pages that the user did not answer and Branch, end of branch, cluster
|
||||
// and end of cluster pages
|
||||
while ($pageid != 0) { // EOL
|
||||
$page = $lessonpages[$pageid];
|
||||
$answerpage = new stdClass;
|
||||
$data ='';
|
||||
|
||||
$answerdata = new stdClass;
|
||||
// Set some defaults for the answer data.
|
||||
$answerdata->score = null;
|
||||
$answerdata->response = null;
|
||||
$answerdata->responseformat = FORMAT_PLAIN;
|
||||
|
||||
$answerpage->title = format_string($page->title);
|
||||
|
||||
$options = new stdClass;
|
||||
$options->noclean = true;
|
||||
$options->overflowdiv = true;
|
||||
$options->context = $context;
|
||||
$answerpage->contents = format_text($page->contents, $page->contentsformat, $options);
|
||||
|
||||
$answerpage->qtype = $qtypes[$page->qtype].$page->option_description_string();
|
||||
$answerpage->grayout = $page->grayout;
|
||||
$answerpage->context = $context;
|
||||
|
||||
if (empty($userid)) {
|
||||
// there is no userid, so set these vars and display stats.
|
||||
$answerpage->grayout = 0;
|
||||
$useranswer = null;
|
||||
} elseif ($useranswers = $DB->get_records("lesson_attempts",array("lessonid"=>$lesson->id, "userid"=>$userid, "retry"=>$attempt,"pageid"=>$page->id), "timeseen")) {
|
||||
// get the user's answer for this page
|
||||
// need to find the right one
|
||||
$i = 0;
|
||||
foreach ($useranswers as $userattempt) {
|
||||
$useranswer = $userattempt;
|
||||
$i++;
|
||||
if ($lesson->maxattempts == $i) {
|
||||
break; // reached maxattempts, break out
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// user did not answer this page, gray it out and set some nulls
|
||||
$answerpage->grayout = 1;
|
||||
$useranswer = null;
|
||||
}
|
||||
$i = 0;
|
||||
$n = 0;
|
||||
$answerpages[] = $page->report_answers(clone($answerpage), clone($answerdata), $useranswer, $pagestats, $i, $n);
|
||||
$pageid = $page->nextpageid;
|
||||
}
|
||||
|
||||
$userstats = new stdClass;
|
||||
if (!empty($userid)) {
|
||||
$params = array("lessonid"=>$lesson->id, "userid"=>$userid);
|
||||
|
||||
$alreadycompleted = true;
|
||||
|
||||
if (!$grades = $DB->get_records_select("lesson_grades", "lessonid = :lessonid and userid = :userid", $params, "completed", "*", $attempt, 1)) {
|
||||
$userstats->grade = -1;
|
||||
$userstats->completed = -1;
|
||||
$alreadycompleted = false;
|
||||
} else {
|
||||
$userstats->grade = current($grades);
|
||||
$userstats->completed = $userstats->grade->completed;
|
||||
$userstats->grade = round($userstats->grade->grade, 2);
|
||||
}
|
||||
|
||||
if (!$times = $lesson->get_user_timers($userid, 'starttime', '*', $attempt, 1)) {
|
||||
$userstats->timetotake = -1;
|
||||
$alreadycompleted = false;
|
||||
} else {
|
||||
$userstats->timetotake = current($times);
|
||||
$userstats->timetotake = $userstats->timetotake->lessontime - $userstats->timetotake->starttime;
|
||||
}
|
||||
|
||||
if ($alreadycompleted) {
|
||||
$userstats->gradeinfo = lesson_grade($lesson, $attempt, $userid);
|
||||
}
|
||||
}
|
||||
|
||||
return array($answerpages, $userstats);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Abstract class that page type's MUST inherit from.
|
||||
*
|
||||
|
|
|
@ -264,103 +264,7 @@ if ($action === 'delete') {
|
|||
$userid = optional_param('userid', null, PARAM_INT); // if empty, then will display the general detailed view
|
||||
$try = optional_param('try', null, PARAM_INT);
|
||||
|
||||
if (!empty($userid)) {
|
||||
// Apply overrides.
|
||||
$lesson->update_effective_access($userid);
|
||||
}
|
||||
|
||||
$lessonpages = $lesson->load_all_pages();
|
||||
foreach ($lessonpages as $lessonpage) {
|
||||
if ($lessonpage->prevpageid == 0) {
|
||||
$pageid = $lessonpage->id;
|
||||
}
|
||||
}
|
||||
|
||||
// now gather the stats into an object
|
||||
$firstpageid = $pageid;
|
||||
$pagestats = array();
|
||||
while ($pageid != 0) { // EOL
|
||||
$page = $lessonpages[$pageid];
|
||||
$params = array ("lessonid" => $lesson->id, "pageid" => $page->id);
|
||||
if ($allanswers = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND pageid = :pageid", $params, "timeseen")) {
|
||||
// get them ready for processing
|
||||
$orderedanswers = array();
|
||||
foreach ($allanswers as $singleanswer) {
|
||||
// ordering them like this, will help to find the single attempt record that we want to keep.
|
||||
$orderedanswers[$singleanswer->userid][$singleanswer->retry][] = $singleanswer;
|
||||
}
|
||||
// this is foreach user and for each try for that user, keep one attempt record
|
||||
foreach ($orderedanswers as $orderedanswer) {
|
||||
foreach($orderedanswer as $tries) {
|
||||
$page->stats($pagestats, $tries);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no one answered yet...
|
||||
}
|
||||
//unset($orderedanswers); initialized above now
|
||||
$pageid = $page->nextpageid;
|
||||
}
|
||||
|
||||
$manager = lesson_page_type_manager::get($lesson);
|
||||
$qtypes = $manager->get_page_type_strings();
|
||||
|
||||
$answerpages = array();
|
||||
$answerpage = "";
|
||||
$pageid = $firstpageid;
|
||||
// cycle through all the pages
|
||||
// foreach page, add to the $answerpages[] array all the data that is needed
|
||||
// from the question, the users attempt, and the statistics
|
||||
// grayout pages that the user did not answer and Branch, end of branch, cluster
|
||||
// and end of cluster pages
|
||||
while ($pageid != 0) { // EOL
|
||||
$page = $lessonpages[$pageid];
|
||||
$answerpage = new stdClass;
|
||||
$data ='';
|
||||
|
||||
$answerdata = new stdClass;
|
||||
// Set some defaults for the answer data.
|
||||
$answerdata->score = null;
|
||||
$answerdata->response = null;
|
||||
$answerdata->responseformat = FORMAT_PLAIN;
|
||||
|
||||
$answerpage->title = format_string($page->title);
|
||||
|
||||
$options = new stdClass;
|
||||
$options->noclean = true;
|
||||
$options->overflowdiv = true;
|
||||
$options->context = $context;
|
||||
$answerpage->contents = format_text($page->contents, $page->contentsformat, $options);
|
||||
|
||||
$answerpage->qtype = $qtypes[$page->qtype].$page->option_description_string();
|
||||
$answerpage->grayout = $page->grayout;
|
||||
$answerpage->context = $context;
|
||||
|
||||
if (empty($userid)) {
|
||||
// there is no userid, so set these vars and display stats.
|
||||
$answerpage->grayout = 0;
|
||||
$useranswer = null;
|
||||
} elseif ($useranswers = $DB->get_records("lesson_attempts",array("lessonid"=>$lesson->id, "userid"=>$userid, "retry"=>$try,"pageid"=>$page->id), "timeseen")) {
|
||||
// get the user's answer for this page
|
||||
// need to find the right one
|
||||
$i = 0;
|
||||
foreach ($useranswers as $userattempt) {
|
||||
$useranswer = $userattempt;
|
||||
$i++;
|
||||
if ($lesson->maxattempts == $i) {
|
||||
break; // reached maxattempts, break out
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// user did not answer this page, gray it out and set some nulls
|
||||
$answerpage->grayout = 1;
|
||||
$useranswer = null;
|
||||
}
|
||||
$i = 0;
|
||||
$n = 0;
|
||||
$answerpages[] = $page->report_answers(clone($answerpage), clone($answerdata), $useranswer, $pagestats, $i, $n);
|
||||
$pageid = $page->nextpageid;
|
||||
}
|
||||
list($answerpages, $userstats) = lesson_get_user_detailed_report_data($lesson, $userid, $try);
|
||||
|
||||
/// actually start printing something
|
||||
$table = new html_table();
|
||||
|
@ -380,24 +284,7 @@ if ($action === 'delete') {
|
|||
$table->align = array('right', 'left');
|
||||
$table->attributes['class'] = 'compacttable generaltable form-inline';
|
||||
|
||||
$params = array("lessonid"=>$lesson->id, "userid"=>$userid);
|
||||
if (!$grades = $DB->get_records_select("lesson_grades", "lessonid = :lessonid and userid = :userid", $params, "completed", "*", $try, 1)) {
|
||||
$grade = -1;
|
||||
$completed = -1;
|
||||
} else {
|
||||
$grade = current($grades);
|
||||
$completed = $grade->completed;
|
||||
$grade = round($grade->grade, 2);
|
||||
}
|
||||
|
||||
if (!$times = $lesson->get_user_timers($userid, 'starttime', '*', $try, 1)) {
|
||||
$timetotake = -1;
|
||||
} else {
|
||||
$timetotake = current($times);
|
||||
$timetotake = $timetotake->lessontime - $timetotake->starttime;
|
||||
}
|
||||
|
||||
if ($timetotake == -1 || $completed == -1 || $grade == -1) {
|
||||
if (empty($userstats->gradeinfo)) {
|
||||
$table->align = array("center");
|
||||
|
||||
$table->data[] = array(get_string("notcompleted", "lesson"));
|
||||
|
@ -407,10 +294,10 @@ if ($action === 'delete') {
|
|||
$gradeinfo = lesson_grade($lesson, $try, $user->id);
|
||||
|
||||
$table->data[] = array(get_string('name').':', $OUTPUT->user_picture($user, array('courseid'=>$course->id)).fullname($user, true));
|
||||
$table->data[] = array(get_string("timetaken", "lesson").":", format_time($timetotake));
|
||||
$table->data[] = array(get_string("completed", "lesson").":", userdate($completed));
|
||||
$table->data[] = array(get_string('rawgrade', 'lesson').':', $gradeinfo->earned.'/'.$gradeinfo->total);
|
||||
$table->data[] = array(get_string("grade", "lesson").":", $grade."%");
|
||||
$table->data[] = array(get_string("timetaken", "lesson").":", format_time($userstats->timetotake));
|
||||
$table->data[] = array(get_string("completed", "lesson").":", userdate($userstats->completed));
|
||||
$table->data[] = array(get_string('rawgrade', 'lesson').':', $userstats->gradeinfo->earned.'/'.$userstats->gradeinfo->total);
|
||||
$table->data[] = array(get_string("grade", "lesson").":", $userstats->grade."%");
|
||||
}
|
||||
echo html_writer::table($table);
|
||||
|
||||
|
|
|
@ -576,26 +576,26 @@ class mod_lesson_external_testcase extends externallib_advanced_testcase {
|
|||
$result = mod_lesson_external::get_user_attempt_grade($this->lesson->id, $attemptnumber, $this->student->id);
|
||||
$result = external_api::clean_returnvalue(mod_lesson_external::get_user_attempt_grade_returns(), $result);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
$this->assertEquals(1, $result['nquestions']);
|
||||
$this->assertEquals(1, $result['attempts']);
|
||||
$this->assertEquals(1, $result['total']);
|
||||
$this->assertEquals(1, $result['earned']);
|
||||
$this->assertEquals(100, $result['grade']);
|
||||
$this->assertEquals(0, $result['nmanual']);
|
||||
$this->assertEquals(0, $result['manualpoints']);
|
||||
$this->assertEquals(1, $result['grade']['nquestions']);
|
||||
$this->assertEquals(1, $result['grade']['attempts']);
|
||||
$this->assertEquals(1, $result['grade']['total']);
|
||||
$this->assertEquals(1, $result['grade']['earned']);
|
||||
$this->assertEquals(100, $result['grade']['grade']);
|
||||
$this->assertEquals(0, $result['grade']['nmanual']);
|
||||
$this->assertEquals(0, $result['grade']['manualpoints']);
|
||||
|
||||
// With custom scoring, in this case, we don't retrieve any values since we are using questions without particular score.
|
||||
$DB->set_field('lesson', 'custom', 1, array('id' => $this->lesson->id));
|
||||
$result = mod_lesson_external::get_user_attempt_grade($this->lesson->id, $attemptnumber, $this->student->id);
|
||||
$result = external_api::clean_returnvalue(mod_lesson_external::get_user_attempt_grade_returns(), $result);
|
||||
$this->assertCount(0, $result['warnings']);
|
||||
$this->assertEquals(1, $result['nquestions']);
|
||||
$this->assertEquals(1, $result['attempts']);
|
||||
$this->assertEquals(0, $result['total']);
|
||||
$this->assertEquals(0, $result['earned']);
|
||||
$this->assertEquals(0, $result['grade']);
|
||||
$this->assertEquals(0, $result['nmanual']);
|
||||
$this->assertEquals(0, $result['manualpoints']);
|
||||
$this->assertEquals(1, $result['grade']['nquestions']);
|
||||
$this->assertEquals(1, $result['grade']['attempts']);
|
||||
$this->assertEquals(0, $result['grade']['total']);
|
||||
$this->assertEquals(0, $result['grade']['earned']);
|
||||
$this->assertEquals(0, $result['grade']['grade']);
|
||||
$this->assertEquals(0, $result['grade']['nmanual']);
|
||||
$this->assertEquals(0, $result['grade']['manualpoints']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1185,4 +1185,53 @@ class mod_lesson_external_testcase extends externallib_advanced_testcase {
|
|||
// Check students.
|
||||
$this->assertCount(2, $result['data']['students']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get_user_attempt
|
||||
*/
|
||||
public function test_get_user_attempt() {
|
||||
global $DB;
|
||||
|
||||
// Create a finished and unfinished attempt with incorrect answer.
|
||||
$this->setCurrentTimeStart();
|
||||
$this->create_attempt($this->student, true, true);
|
||||
|
||||
$DB->set_field('lesson', 'retake', 1, array('id' => $this->lesson->id));
|
||||
sleep(1);
|
||||
$this->create_attempt($this->student, false, false);
|
||||
|
||||
$this->setAdminUser();
|
||||
// Test first attempt finished.
|
||||
$result = mod_lesson_external::get_user_attempt($this->lesson->id, $this->student->id, 0);
|
||||
$result = external_api::clean_returnvalue(mod_lesson_external::get_user_attempt_returns(), $result);
|
||||
|
||||
$this->assertCount(2, $result['answerpages']); // 2 pages in the lesson.
|
||||
$this->assertCount(2, $result['answerpages'][0]['answerdata']['answers']); // 2 possible answers in true/false.
|
||||
$this->assertEquals(100, $result['userstats']['grade']); // Correct answer.
|
||||
$this->assertEquals(1, $result['userstats']['gradeinfo']['total']); // Total correct answers.
|
||||
$this->assertEquals(100, $result['userstats']['gradeinfo']['grade']); // Correct answer.
|
||||
|
||||
// Test second attempt unfinished.
|
||||
$result = mod_lesson_external::get_user_attempt($this->lesson->id, $this->student->id, 1);
|
||||
$result = external_api::clean_returnvalue(mod_lesson_external::get_user_attempt_returns(), $result);
|
||||
|
||||
$this->assertCount(2, $result['answerpages']); // 2 pages in the lesson.
|
||||
$this->assertCount(2, $result['answerpages'][0]['answerdata']['answers']); // 2 possible answers in true/false.
|
||||
$this->assertArrayNotHasKey('gradeinfo', $result['userstats']); // No grade info since it not finished.
|
||||
|
||||
// Check as student I can get this information for only me.
|
||||
$this->setUser($this->student);
|
||||
// Test first attempt finished.
|
||||
$result = mod_lesson_external::get_user_attempt($this->lesson->id, $this->student->id, 0);
|
||||
$result = external_api::clean_returnvalue(mod_lesson_external::get_user_attempt_returns(), $result);
|
||||
|
||||
$this->assertCount(2, $result['answerpages']); // 2 pages in the lesson.
|
||||
$this->assertCount(2, $result['answerpages'][0]['answerdata']['answers']); // 2 possible answers in true/false.
|
||||
$this->assertEquals(100, $result['userstats']['grade']); // Correct answer.
|
||||
$this->assertEquals(1, $result['userstats']['gradeinfo']['total']); // Total correct answers.
|
||||
$this->assertEquals(100, $result['userstats']['gradeinfo']['grade']); // Correct answer.
|
||||
|
||||
$this->setExpectedException('moodle_exception');
|
||||
$result = mod_lesson_external::get_user_attempt($this->lesson->id, $this->teacher->id, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2016120513; // The current module version (Date: YYYYMMDDXX)
|
||||
$plugin->version = 2016120514; // The current module version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2016112900; // Requires this Moodle version
|
||||
$plugin->component = 'mod_lesson'; // Full name of the plugin (used for diagnostics)
|
||||
$plugin->cron = 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue