Skip to content

Commit

Permalink
Merge branch 'MDL-57757-master' of git://github.com/jleyva/moodle
Browse files Browse the repository at this point in the history
  • Loading branch information
dmonllao committed Mar 27, 2017
2 parents aad9ea0 + 79d5e88 commit 49ba56c
Show file tree
Hide file tree
Showing 6 changed files with 347 additions and 142 deletions.
134 changes: 126 additions & 8 deletions mod/lesson/classes/external.php
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,28 @@ public static function get_user_grade_returns() {
);
}

/**
* 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.
*
Expand Down Expand Up @@ -758,7 +780,8 @@ public static function get_user_attempt_grade($lessonid, $lessonattempt, $userid
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;
}
Expand All @@ -772,13 +795,7 @@ public static function get_user_attempt_grade($lessonid, $lessonattempt, $userid
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(),
)
);
Expand Down Expand Up @@ -1761,4 +1778,105 @@ public static function get_attempts_overview_returns() {
)
);
}

/**
* 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(),
)
);
}
}
8 changes: 8 additions & 0 deletions mod/lesson/db/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,12 @@
'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)
),
);
143 changes: 143 additions & 0 deletions mod/lesson/locallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
Loading

0 comments on commit 49ba56c

Please sign in to comment.