public function test_mod_stopwatch_string_to_duration()
 {
     $H = 3600;
     $M = 60;
     $this->assertEquals($H + 15 * $M + 20, mod_stopwatch_string_to_duration('1:15:20'));
     $this->assertEquals(4 * $M + 59, mod_stopwatch_string_to_duration('0:04:59'));
     $this->assertEquals(2, mod_stopwatch_string_to_duration('00:00:02'));
     $this->assertEquals(2, mod_stopwatch_string_to_duration('0:02'));
     $this->assertEquals(2, mod_stopwatch_string_to_duration('2'));
     $this->assertEquals(58, mod_stopwatch_string_to_duration('00:58'));
     $this->assertEquals(58, mod_stopwatch_string_to_duration('00:00:58'));
 }
$cmd = optional_param('cmd', null, PARAM_ALPHA);
$durationstr = optional_param('durationstr', null, PARAM_NOTAGS);
if ($cmid) {
    list($course, $cm) = get_course_and_cm_from_cmid($cmid, 'stopwatch');
} elseif ($stopwatchid) {
    list($course, $cm) = get_course_and_cm_from_instance($stopwatchid, 'stopwatch');
} else {
    print_error('You must specify a course_module ID or an instance ID');
}
require_login($course, true, $cm);
$stopwatch = $PAGE->activityrecord;
$cmcontext = context_module::instance($cm->id);
$cansubmit = has_capability('mod/stopwatch:submit', $cmcontext, null, false);
$cangrade = has_capability('mod/stopwatch:grade', $cmcontext);
if ($cmd === 'updateduration' && $cansubmit && $durationstr && confirm_sesskey()) {
    mod_stopwatch_update_timer($cm, $stopwatch, mod_stopwatch_string_to_duration($durationstr));
    redirect($cm->url);
}
if ($cmd === 'updategrades' && $cangrade && confirm_sesskey()) {
    $durationarray = optional_param_array('duration', array(), PARAM_NOTAGS);
    $gradearray = optional_param_array('grade', array(), PARAM_FLOAT);
    mod_stopwatch_update_grades($cm, $stopwatch, $durationarray, $gradearray);
    redirect($cm->url);
}
\mod_stopwatch\event\course_module_viewed::create_from_cm($cm, $course, $stopwatch)->trigger();
// Mark viewed if required
$completion = new completion_info($course);
$completion->set_module_viewed($cm);
/// Print the page header
$PAGE->set_url($cm->url);
$PAGE->set_title($cm->get_formatted_name());
function mod_stopwatch_update_grades($cm, $stopwatch, $durationarray, $gradearray)
{
    global $DB, $CFG;
    require_once $CFG->libdir . '/gradelib.php';
    $currentgrades = mod_stopwatch_get_all_users($cm, $stopwatch);
    $newgrades = array();
    foreach ($currentgrades as $userid => $record) {
        if ($record->id) {
            $params = array('id' => $record->id);
        } else {
            $params = array('userid' => $userid, 'courseid' => $cm->course, 'stopwatchid' => $stopwatch->id);
        }
        $now = time();
        $updateobj = array();
        if (array_key_exists($userid, $durationarray)) {
            if (empty($durationarray[$userid])) {
                if (!empty($record->duration)) {
                    $updateobj['duration'] = 0;
                }
            } else {
                $duration = mod_stopwatch_string_to_duration($durationarray[$userid]);
                if ($record->duration != $duration) {
                    $updateobj['duration'] = $duration;
                }
            }
        }
        if ($stopwatch->grade && array_key_exists($userid, $gradearray)) {
            $grade = empty($gradearray[$userid]) ? null : (double) $gradearray[$userid];
            $existinggrade = !strlen($record->grade) ? null : (double) $record->grade;
            if ($existinggrade !== $grade) {
                $updateobj['grade'] = $grade;
                $updateobj['timegraded'] = $now;
                $newgrades[$userid] = array('userid' => $userid, 'rawgrade' => $grade);
            }
        }
        if (empty($updateobj)) {
            continue;
        }
        $updateobj += $params;
        $updateobj['timemodified'] = $now;
        if (!empty($updateobj['id'])) {
            $DB->update_record('stopwatch_user', $updateobj);
        } else {
            $updateobj['timecreated'] = $now;
            $DB->insert_record('stopwatch_user', $updateobj);
        }
    }
    if ($newgrades) {
        // Attempt to update the grade item if relevant
        $grademodule = fullclone($stopwatch);
        $grademodule->cmidnumber = $cm->idnumber;
        $grademodule->modname = $cm->modname;
        grade_update_mod_grades($grademodule);
    }
}