MDL-11517 reserved word MOD used in table alias in questions backup code
[moodle-pu.git] / mod / exercise / locallib.php
blobb607c74904774bd3ff4adba9db4160ca9009ccce
1 <?php // $Id$
3 /// Library of extra functions for the exercise module
5 //////////////////////////////////////////////////////////////////////////////////////
7 /*** Functions for the exercise module ******
9 function exercise_add_custom_scales($exercise) {
10 function exercise_compare_assessments($exercise, $assessment1, $assessment2) {
11 function exercise_copy_assessment($assessment, $submission, $withfeedback = false) {
12 function exercise_count_all_submissions_for_assessment($exercise, $user) {
13 function exercise_count_assessments($submission) {
14 function exercise_count_assessments_by_teacher($exercise, $teacher) {
15 function exercise_count_student_submissions($exercise) {
16 function exercise_count_teacher_assessments($exercise, $user) {
17 function exercise_count_teacher_submissions($exercise) {
18 function exercise_count_teacher_submissions_for_assessment($exercise, $user) {
19 function exercise_count_unassessed_student_submissions($exercise) {
20 function exercise_count_ungraded_assessments_student($exercise) {
21 function exercise_count_ungraded_assessments_teacher($exercise) {
22 function exercise_count_user_assessments($exercise, $user, $type = "all") { $type is all, student or teacher
23 function exercise_count_user_assessments_done($exercise,$user) {
24 function exercise_count_user_submissions($exercise, $user) {
26 function exercise_delete_submitted_files($exercise, $submission) {
27 function exercise_delete_user_files($exercise, $user, $exception) {
29 function exercise_file_area($exercise, $submission) { <--- in lib.php
30 function exercise_file_area_name($exercise, $submission) { <--- in lib.php
32 function exercise_get_assess_logs($course, $timestart) { <--- in lib.php
33 function exercise_get_assessments($submission) <--- in lib.php{
34 function exercise_get_best_submission_grades($exercise) { <--- in lib.php
35 function exercise_get_grade_logs($course, $timestart) { <--- in lib.php
36 function exercise_get_mean_submission_grades($exercise) { <--- in lib.php
37 function exercise_get_student_submission($exercise, $user) {
38 function exercise_get_student_submissions($exercise) {
39 function exercise_get_submission_assessment($submission, $user) {
40 function exercise_get_submit_logs($course, $timestart) {
41 function exercise_get_teacher_submission_assessments($exercise) { <--- in lib.php
42 function exercise_get_teacher_submissions($exercise) {
43 function exercise_get_ungraded_assessments($exercise) {
44 function exercise_get_unmailed_assessments($cutofftime) { <--- in lib.php
45 function exercise_get_unmailed_graded_assessments($cutofftime) { <--- in lib.php
46 function exercise_get_user_assessments($exercise, $user) {
47 function exercise_get_user_submissions($exercise, $user) {
49 function exercise_list_all_ungraded_assessments($exercise) {
50 function exercise_list_submissions_for_admin($exercise) {
51 function exercise_list_teacher_assessments($exercise, $user) {
52 function exercise_list_teacher_submissions($exercise, $user, $reassess) {
53 function exercise_list_unassessed_student_submissions($exercise, $user) {
54 function exercise_list_unassessed_teacher_submissions($exercise, $user) {
55 function exercise_list_ungraded_assessments($exercise, $stype) {
56 function exercise_list_user_submissions($exercise, $user) {
59 function exercise_print_assessment_form($exercise, $assessment, $allowchanges, $returnto)
60 function exercise_print_assessments_by_user_for_admin($exercise, $user) {
61 function exercise_print_assessments_for_admin($exercise, $submission) {
62 function exercise_print_assignment_info($exercise) {
63 function exercise_print_difference($time) {
64 function exercise_print_feedback($course, $submission) {
65 function exercise_print_league_table($exercise) {
66 function exercise_print_submission_assessments($exercise, $submission, $type) {
67 function exercise_print_submission_title($exercise, $submission) { <--- in lib.php
68 function exercise_print_tabbed_table($table) {
69 function exercise_print_teacher_assessment_form($exercise, $assessment, $submission, $returnto)
70 function exercise_print_teacher_table($course) {
71 function exercise_print_time_to_deadline($time) {
72 function exercise_print_upload_form($exercise) {
73 function exercise_print_user_assessments($exercise, $user) {
75 function exercise_test_for_resubmission($exercise, $user) {
76 function exercise_test_user_assessments($exercise, $user) {
77 ***************************************/
79 ///////////////////////////////////////////////////////////////////////////////////////////////
80 function exercise_add_custom_scales($exercise) {
81 global $EXERCISE_SCALES;
83 if (! $course = get_record("course", "id", $exercise->course)) {
84 error("Course is misconfigured");
87 if ($scales = get_records("scale", "courseid", $course->id, "name ASC")) {
88 foreach ($scales as $scale) {
89 $labels = explode(",", $scale->scale);
90 $EXERCISE_SCALES[] = array('name' => $scale->name, 'type' => 'radio', 'size' => count($labels),
91 'start' => trim($labels[0]), 'end' => trim($labels[count($labels) - 1]));
94 return;
97 ///////////////////////////////////////////////////////////////////////////////////////////////
98 function exercise_compare_assessments($exercise, $assessment1, $assessment2) {
99 global $EXERCISE_ASSESSMENT_COMPS, $EXERCISE_EWEIGHTS;
100 // first get the assignment elements for maxscores...
101 $elementsraw = get_records("exercise_elements", "exerciseid", $exercise->id, "elementno ASC");
102 foreach ($elementsraw as $element) {
103 $maxscore[] = $element->maxscore; // to renumber index 0,1,2...
104 $weight[] = $EXERCISE_EWEIGHTS[$element->weight]; // get real value and renumber index 0,1,2...
106 for ($i = 0; $i < 2; $i++) {
107 if ($i) {
108 $rawgrades = get_records("exercise_grades", "assessmentid", $assessment1->id, "elementno ASC");
109 } else {
110 $rawgrades = get_records("exercise_grades", "assessmentid", $assessment2->id, "elementno ASC");
112 foreach ($rawgrades as $grade) {
113 $grades[$i][] = $grade->grade;
116 $sumdiffs = 0;
117 $sumweights = 0;
118 switch ($exercise->gradingstrategy) {
119 case 1 : // accumulative grading and...
120 case 4 : // ...rubic grading
121 for ($i=0; $i < $exercise->nelements; $i++) {
122 $diff = ($grades[0][$i] - $grades[1][$i]) * $weight[$i] / $maxscore[$i];
123 $sumdiffs += $diff * $diff; // use squared distances
124 $sumweights += $weight[$i];
126 break;
127 case 2 : // error banded grading
128 // ignore maxscores here, the grades are either 0 or 1,
129 for ($i=0; $i < $exercise->nelements; $i++) {
130 $diff = ($grades[0][$i] - $grades[1][$i]) * $weight[$i];
131 $sumdiffs += $diff * $diff; // use squared distances
132 $sumweights += $weight[$i];
134 break;
135 case 3 : // criterion grading
136 // here we only need to look at the difference between the "zero" grade elements
137 $diff = ($grades[0][0] - $grades[1][0]) / (count($elementsraw) - 1);
138 $sumdiffs = $diff * $diff;
139 $sumweights = 1;
140 break;
142 // convert to a sensible grade (always out of 100)
143 $COMP = (object)$EXERCISE_ASSESSMENT_COMPS[$exercise->assessmentcomps];
144 $factor = $COMP->value;
145 $gradinggrade = (($factor - ($sumdiffs / $sumweights)) / $factor) * 100;
146 if ($gradinggrade < 0) {
147 $gradinggrade = 0;
149 return $gradinggrade;
152 ///////////////////////////////////////////////////////////////////////////////////////////////
153 function exercise_copy_assessment($assessment, $submission, $withfeedback = false) {
154 // adds a copy of the given assessment for the submission specified to the exercise_assessemnts table.
155 // The grades and optionally the comments are added to the exercise_grades table. Returns the new
156 // assessment object
157 global $USER;
159 $yearfromnow = time() + 365 * 86400;
160 $newassessment->exerciseid = $assessment->exerciseid;
161 $newassessment->submissionid = $submission->id;
162 $newassessment->userid = $USER->id;
163 $newassessment->timecreated = $yearfromnow;
164 $newassessment->timegraded = 0;
165 $newassessment->grade = $assessment->grade;
166 if ($withfeedback) {
167 $newassessment->generalcomment = addslashes($assessment->generalcomment);
168 $newassessment->teachercomment = addslashes($assessment->teachercomment);
170 if (!$newassessment->id = insert_record("exercise_assessments", $newassessment)) {
171 error("Copy Assessment: Could not insert exercise assessment!");
174 if ($grades = get_records("exercise_grades", "assessmentid", $assessment->id)) {
175 foreach ($grades as $grade) {
176 unset($grade->id); // clear id, insert record now seems to believe it!
177 if (!$withfeedback) {
178 $grade->feedback = '';
180 else {
181 $grade->feedback = addslashes($grade->feedback);
182 // $grade->feedback = $grade->feedback;
184 $grade->assessmentid = $newassessment->id;
185 if (!$grade->id = insert_record("exercise_grades", $grade)) {
186 error("Copy Assessment: Could not insert exercise grade!");
190 if ($withfeedback) {
191 // remove the slashes from comments as the new assessment record is used
192 // in assessments and in lib
193 $newassessment->generalcomment = stripslashes($assessment->generalcomment);
194 $newassessment->teachercomment = stripslashes($assessment->teachercomment);
197 return $newassessment;
202 ///////////////////////////////////////////////////////////////////////////////////////////////
203 function exercise_count_all_submissions_for_assessment($exercise, $user) {
204 // looks at all submissions and deducts the number which has been assessed by this user
205 $n = 0;
206 if ($submissions = get_records_select("exercise_submissions", "exerciseid = $exercise->id AND timecreated > 0")) {
207 $n =count($submissions);
208 foreach ($submissions as $submission) {
209 $n -= count_records("exercise_assessments", "submissionid", $submission->id, "userid", $user->id);
212 return $n;
216 ///////////////////////////////////////////////////////////////////////////////////////////////
217 function exercise_count_assessments($submission) {
218 // Return the (cold) assessments for this submission,
219 global $CFG;
221 $timethen = time() - $CFG->maxeditingtime;
222 return count_records_select("exercise_assessments", "submissionid = $submission->id AND
223 timecreated < $timethen");
227 ///////////////////////////////////////////////////////////////////////////////////////////////
228 function exercise_count_assessments_by_teacher($exercise, $teacher) {
229 // Return the number of assessments done by a teacher
231 return count_records_select("exercise_assessments", "exerciseid = $exercise->id AND
232 userid = $teacher->id");
236 ///////////////////////////////////////////////////////////////////////////////////////////////
237 function exercise_count_student_submissions($exercise) {
238 global $CFG;
240 // make sure it works on the site course
241 $select = "u.course = '$exercise->course' AND";
242 if ($exercise->course == SITEID) {
243 $select = '';
246 return count_records_sql("SELECT count(*) FROM {$CFG->prefix}exercise_submissions s
247 WHERE $select
248 AND s.exerciseid = $exercise->id
249 AND timecreated > 0");
253 ///////////////////////////////////////////////////////////////////////////////////////////////
254 function exercise_count_teacher_assessments($exercise, $user) {
255 // returns the number of assessments made by teachers on user's submissions
257 $n = 0;
258 if ($submissions = exercise_get_user_submissions($exercise, $user)) {
259 foreach ($submissions as $submission) {
260 if ($assessments = exercise_get_assessments($submission)) {
261 foreach ($assessments as $assessment) {
262 // count only teacher assessments
263 if (isteacher($exercise->course, $assessment->userid)) {
264 $n++;
270 return $n;
274 ///////////////////////////////////////////////////////////////////////////////////////////////
275 function exercise_count_teacher_submissions($exercise) {
277 return count_records("exercise_submissions", "isexercise", 1, "exerciseid", $exercise->id);
281 ///////////////////////////////////////////////////////////////////////////////////////////////
282 function exercise_count_teacher_submissions_for_assessment($exercise, $user) {
284 $n = 0;
285 if ($submissions = exercise_get_teacher_submissions($exercise)) {
286 $n =count($submissions);
287 foreach ($submissions as $submission) {
288 $n -= count_records("exercise_assessments", "submissionid", $submission->id, "userid", $user->id);
291 return $n;
295 ///////////////////////////////////////////////////////////////////////////////////////////////
296 function exercise_count_unassessed_student_submissions($exercise) {
297 // returns the number of students submissions which have not been assessed by a teacher
298 global $CFG;
300 if (! $course = get_record("course", "id", $exercise->course)) {
301 error("Course is misconfigured");
303 $timenow = time();
304 $n = 0;
305 // look at all the student submissions, exercise_get_student_submissions is group aware
306 $groupid = get_current_group($course->id);
307 if ($submissions = exercise_get_student_submissions($exercise, "time", $groupid)) {
308 foreach ($submissions as $submission) {
309 // only look at "cold" submissions
310 if ($submission->timecreated < $timenow - $CFG->maxeditingtime) {
311 $teacherassessed = false;
312 if ($assessments = exercise_get_assessments($submission)) {
313 foreach ($assessments as $assessment) {
314 // exercise_get_assessments only returns "cold" assessments, look for one made by a teacher
315 if (isteacher($course->id, $assessment->userid)) {
316 $teacherassessed = true;
317 break; // no need to look further
321 if (!$teacherassessed) {
322 $n++;
327 return $n;
331 ///////////////////////////////////////////////////////////////////////////////////////////////
332 function exercise_count_ungraded_assessments_student($exercise, $groupid = 0) {
333 // function returns the number of ungraded assessments by students of STUDENT submissions
335 $n = 0;
336 if ($submissions = exercise_get_student_submissions($exercise, $groupid)) {
337 foreach ($submissions as $submission) {
338 if ($assessments = exercise_get_assessments($submission)) {
339 foreach ($assessments as $assessment) {
340 if ($assessment->timegraded == 0) {
341 // ignore teacher assessments
342 if (!isteacher($exercise->course, $assessment->userid)) {
343 $n++;
350 return $n;
354 ///////////////////////////////////////////////////////////////////////////////////////////////
355 function exercise_count_ungraded_assessments_teacher($exercise) {
356 // function returns the number of ungraded assessments by students of TEACHER submissions
357 global $CFG;
359 $timenow = time();
360 $n = 0;
361 if ($submissions = exercise_get_teacher_submissions($exercise)) {
362 foreach ($submissions as $submission) {
363 if ($assessments = exercise_get_assessments($submission)) {
364 foreach ($assessments as $assessment) {
365 if ($assessment->timegraded == 0) {
366 // ignore teacher assessments
367 if (!isteacher($exercise->course, $assessment->userid)) {
368 // must have created a little time ago
369 if (($timenow - $assessment->timecreated) > $CFG->maxeditingtime) {
370 $n++;
378 return $n;
382 ///////////////////////////////////////////////////////////////////////////////////////////////
383 function exercise_count_user_assessments($exercise, $user, $stype = "all") {
384 // returns the number of assessments allocated/made by a user, all of them, or just those for the student or teacher submissions
385 // the student's self assessments are included in the count
386 // the maxeditingtime is NOT taken into account here also allocated assessments which have not yet
387 // been done are counted as well
389 $n = 0;
390 if ($assessments = exercise_get_user_assessments($exercise, $user)) {
391 foreach ($assessments as $assessment) {
392 switch ($stype) {
393 case "all" :
394 $n++;
395 break;
396 case "student" :
397 $submission = get_record("exercise_submissions", "id", $assessment->submissionid);
398 if (isstudent($exercise->course, $submission->userid)) {
399 $n++;
401 break;
402 case "teacher" :
403 $submission = get_record("exercise_submissions", "id", $assessment->submissionid);
404 if (isteacher($exercise->course, $submission->userid)) {
405 $n++;
407 break;
411 return $n;
415 ///////////////////////////////////////////////////////////////////////////////////////////////
416 function exercise_count_user_assessments_done($exercise, $user) {
417 // returns the number of assessments actually done by a user
418 // the student's self assessments are included in the count
419 // the maxeditingtime is NOT taken into account here
421 $n = 0;
422 $timenow = time();
423 if ($assessments = exercise_get_user_assessments($exercise, $user)) {
424 foreach ($assessments as $assessment) {
425 if ($assessment->timecreated < $timenow) {
426 $n++;
430 return $n;
434 ///////////////////////////////////////////////////////////////////////////////////////////////
435 function exercise_count_user_submissions($exercise, $user) {
436 // returns the number of submissions make by this user
437 return count_records("exercise_submissions", "exerciseid", $exercise->id, "userid", $user->id);
441 ///////////////////////////////////////////////////////////////////////////////////////////////
442 function exercise_delete_submitted_files($exercise, $submission) {
443 // Deletes the files in the exercise area for this submission
445 if ($basedir = exercise_file_area($exercise, $submission)) {
446 if ($files = get_directory_list($basedir)) {
447 foreach ($files as $file) {
448 if (unlink("$basedir/$file")) {
449 notify("Existing file '$file' has been deleted!");
451 else {
452 notify("Attempt to delete file $basedir/$file has failed!");
460 ///////////////////////////////////////////////////////////////////////////////////////////////
461 function exercise_delete_user_files($exercise, $user, $exception) {
462 // Deletes all the user files in the exercise area for a user
463 // EXCEPT for any file named $exception
465 if (!$submissions = exercise_get_submissions($exercise, $user)) {
466 notify("No submissions!");
467 return;
469 foreach ($submissions as $submission) {
470 if ($basedir = exercise_file_area($exercise, $submission)) {
471 if ($files = get_directory_list($basedir)) {
472 foreach ($files as $file) {
473 if ($file != $exception) {
474 unlink("$basedir/$file");
475 notify("Existing file '$file' has been deleted!");
484 ///////////////////////////////////////////////////////////////////////////////////////////////
485 function exercise_get_best_submission_grades($exercise) {
486 // Returns the grades of students' best submissions
487 global $CFG;
489 // make sure it works on the site course
490 $select = "u.course = '$exercise->course' AND";
491 if ($exercise->course == SITEID) {
492 $select = '';
495 return get_records_sql("SELECT DISTINCT s.userid, MAX(a.grade) AS grade FROM
496 {$CFG->prefix}exercise_submissions s,
497 {$CFG->prefix}exercise_assessments a
498 WHERE $select
499 AND s.exerciseid = $exercise->id
500 AND s.late = 0
501 AND a.submissionid = s.id
502 GROUP BY s.userid");
506 ///////////////////////////////////////////////////////////////////////////////////////////////
507 function exercise_get_mean_grade($submission) {
508 // Returns the mean grade of students' submission (may, very occassionally, be more than one assessment)
509 global $CFG;
511 return get_record_sql("SELECT AVG(a.grade) AS grade FROM
512 {$CFG->prefix}exercise_assessments a
513 WHERE a.submissionid = $submission->id
514 GROUP BY a.submissionid");
518 ///////////////////////////////////////////////////////////////////////////////////////////////
519 function exercise_get_student_submission($exercise, $user) {
520 // Return a submission for a particular user
521 global $CFG;
523 $submission = get_record("exercise_submissions", "exerciseid", $exercise->id, "userid", $user->id);
524 if (!empty($submission->timecreated)) {
525 return $submission;
527 return NULL;
531 ///////////////////////////////////////////////////////////////////////////////////////////////
532 function exercise_get_student_submissions($exercise, $order = "time", $groupid = 0) {
533 // Return all ENROLLED student submissions
534 // if order can grade|title|name|nothing, nothing is oldest first, youngest last
535 global $CFG;
537 if ($groupid) {
538 // just look at a single group
539 if ($order == "grade") {
540 // allow for multiple assessments of submissions (coming from different teachers)
542 // make sure it works on the site course
543 $select = "u.course = '$exercise->course' AND";
544 if ($exercise->course == SITEID) {
545 $select = '';
548 return get_records_sql("SELECT s.*, AVG(a.grade) AS grade FROM
549 {$CFG->prefix}groups_members g, {$CFG->prefix}exercise_submissions s,
550 {$CFG->prefix}exercise_assessments a
551 WHERE $select g.groupid = $groupid
552 AND s.exerciseid = $exercise->id
553 AND a.submissionid = s.id
554 GROUP BY s.id
555 ORDER BY a.grade DESC");
558 if ($order == "title") {
559 $order = "s.title";
560 } elseif ($order == "name") {
561 $order = "n.firstname, n.lastname, s.timecreated DESC";
562 } elseif ($order == "time") {
563 $order = "s.timecreated";
566 // make sure it works on the site course
567 $select = "u.course = '$exercise->course' AND";
568 if ($exercise->course == SITEID) {
569 $select = '';
572 return get_records_sql("SELECT s.* FROM {$CFG->prefix}user n,
573 {$CFG->prefix}groups_members g, {$CFG->prefix}exercise_submissions s
574 WHERE $select g.groupid = $groupid
575 AND s.exerciseid = $exercise->id
576 ORDER BY $order");
579 else { // no group - all users
580 if ($order == "grade") {
581 // allow for multiple assessments of submissions (coming from different teachers)
583 // make sure it works on the site course
584 $select = "u.course = '$exercise->course' AND";
585 if ($exercise->course == SITEID) {
586 $select = '';
589 return get_records_sql("SELECT s.*, AVG(a.grade) AS grade FROM {$CFG->prefix}exercise_submissions s,
590 {$CFG->prefix}exercise_assessments a
591 WHERE $select
592 AND s.exerciseid = $exercise->id
593 AND a.submissionid = s.id
594 GROUP BY s.id
595 ORDER BY a.grade DESC");
598 if ($order == "title") {
599 $order = "s.title";
600 } elseif ($order == "name") {
601 $order = "n.firstname, n.lastname, s.timecreated DESC";
602 } elseif ($order == "time") {
603 $order = "s.timecreated";
606 // make sure it works on the site course
607 $select = "u.course = '$exercise->course' AND";
608 if ($exercise->course == SITEID) {
609 $select = '';
612 return get_records_sql("SELECT s.* FROM {$CFG->prefix}exercise_submissions s,
613 {$CFG->prefix}user n
614 WHERE $select
615 AND s.exerciseid = $exercise->id
616 ORDER BY $order");
621 ///////////////////////////////////////////////////////////////////////////////////////////////
622 function exercise_get_submission_assessment($submission, $user = null) {
623 // Return a user's assessment for this submission
624 if ($user) {
625 return get_record("exercise_assessments", "submissionid", $submission->id, "userid", $user->id);
626 } else { // likely to be the teacher's assessment
627 return get_record("exercise_assessments", "submissionid", $submission->id);
632 ///////////////////////////////////////////////////////////////////////////////////////////////
633 function exercise_get_teacher_submissions($exercise) {
634 // Return all teacher submissions, ordered by title
635 global $CFG;
637 return get_records_sql("SELECT s.* FROM {$CFG->prefix}exercise_submissions s
638 WHERE s.isexercise = 1
639 AND s.exerciseid = $exercise->id
640 ORDER BY s.title");
644 ///////////////////////////////////////////////////////////////////////////////////////////////
645 function exercise_get_ungraded_assessments($exercise) {
646 global $CFG;
647 // Return all assessments which have not been graded or just graded
648 $cutofftime =time() - $CFG->maxeditingtime;
649 return get_records_select("exercise_assessments", "exerciseid = $exercise->id AND (timegraded = 0 OR
650 timegraded > $cutofftime)", "timecreated");
654 ///////////////////////////////////////////////////////////////////////////////////////////////
655 function exercise_get_ungraded_assessments_student($exercise) {
656 global $CFG;
657 // Return all assessments which have not been graded or just graded of student's submissions
659 // make sure it works on the site course
660 $select = "u.course = '$exercise->course' AND";
661 if ($exercise->course == SITEID) {
662 $select = '';
665 $cutofftime =time() - $CFG->maxeditingtime;
666 return get_records_sql("SELECT a.* FROM {$CFG->prefix}exercise_submissions s
667 {$CFG->prefix}exercise_assessments a
668 WHERE $select
669 AND s.exerciseid = $exercise->id
670 AND a.submissionid = s.id
671 AND (a.timegraded = 0 OR a.timegraded > $cutofftime)
672 AND a.timecreated < $cutofftime
673 ORDER BY a.timecreated ASC");
677 ///////////////////////////////////////////////////////////////////////////////////////////////
678 function exercise_get_ungraded_assessments_teacher($exercise) {
679 global $CFG;
680 // Return all assessments which have not been graded or just graded of teacher's submissions
682 $cutofftime =time() - $CFG->maxeditingtime;
683 return get_records_sql("SELECT a.* FROM {$CFG->prefix}exercise_submissions s, {$CFG->prefix}exercise_assessments a
684 WHERE s.isexercise = 1
685 AND s.exerciseid = $exercise->id
686 AND a.submissionid = s.id
687 AND (a.timegraded = 0 OR a.timegraded > $cutofftime)
688 AND a.timecreated < $cutofftime
689 ORDER BY a.timecreated ASC");
693 ///////////////////////////////////////////////////////////////////////////////////////////////
694 function exercise_get_user_assessments($exercise, $user) {
695 // Return all the user's assessments, newest first, oldest last
696 // students will have only one, teachers will have more...
697 return get_records_select("exercise_assessments", "exerciseid = $exercise->id AND userid = $user->id",
698 "timecreated DESC");
702 ///////////////////////////////////////////////////////////////////////////////////////////////
703 function exercise_list_all_ungraded_assessments($exercise) {
704 // lists all the assessments for comment by teacher
705 global $CFG;
707 $table->head = array (get_string("title", "exercise"), get_string("timeassessed", "exercise"), get_string("action", "exercise"));
708 $table->align = array ("left", "left", "left");
709 $table->size = array ("*", "*", "*");
710 $table->cellpadding = 2;
711 $table->cellspacing = 0;
712 $timenow = time();
714 if ($assessments = exercise_get_ungraded_assessments($exercise)) {
715 foreach ($assessments as $assessment) {
716 if (!isteacher($exercise->course, $assessment->userid)) {
717 if (($timenow - $assessment->timegraded) < $CFG->maxeditingtime) {
718 $action = "<a href=\"assessments.php?action=gradeassessment&amp;a=$exercise->id&amp;aid=$assessment->id\">".
719 get_string("edit", "exercise")."</a>";
721 else {
722 $action = "<a href=\"assessments.php?action=gradeassessment&amp;a=$exercise->id&amp;aid=$assessment->id\">".
723 get_string("gradeassessment", "exercise")."</a>";
725 $submission = get_record("exercise_submissions", "id", $assessment->submissionid);
726 $table->data[] = array(exercise_print_submission_title($exercise, $submission),
727 userdate($assessment->timecreated), $action);
730 if (isset($table->data)) {
731 print_table($table);
737 ///////////////////////////////////////////////////////////////////////////////////////////////
738 function exercise_list_submissions_for_admin($exercise) {
739 // list the teacher sublmissions first
740 global $CFG, $USER;
742 if (! $course = get_record("course", "id", $exercise->course)) {
743 error("Course is misconfigured");
745 if (! $cm = get_coursemodule_from_instance("exercise", $exercise->id, $course->id)) {
746 error("Course Module ID was incorrect");
748 $groupid = get_current_group($course->id);
750 exercise_print_assignment_info($exercise);
751 print_heading_with_help(get_string("administration"), "administration", "exercise");
752 echo"<p align=\"center\"><b><a href=\"assessments.php?action=teachertable&amp;id=$cm->id\">".
753 get_string("teacherassessmenttable", "exercise", $course->teacher)."</a></b></p>\n";
756 if (isteacheredit($course->id)) {
757 // list any teacher submissions
758 $table->head = array (get_string("title", "exercise"), get_string("submitted", "exercise"),
759 get_string("action", "exercise"));
760 $table->align = array ("left", "left", "left");
761 $table->size = array ("*", "*", "*");
762 $table->cellpadding = 2;
763 $table->cellspacing = 0;
765 if ($submissions = exercise_get_teacher_submissions($exercise)) {
766 foreach ($submissions as $submission) {
767 $action = "<a href=\"submissions.php?action=adminamendtitle&amp;id=$cm->id&amp;sid=$submission->id\">".
768 get_string("amendtitle", "exercise")."</a>";
769 if (isteacheredit($course->id)) {
770 $action .= " | <a href=\"submissions.php?action=adminconfirmdelete&amp;id=$cm->id&amp;sid=$submission->id\">".
771 get_string("delete", "exercise")."</a>";
773 $table->data[] = array(exercise_print_submission_title($exercise, $submission),
774 userdate($submission->timecreated), $action);
776 print_heading(get_string("studentsubmissions", "exercise", $course->teacher), "center");
777 print_table($table);
781 // list student assessments
782 // Get all the students...
783 if ($users = get_course_students($course->id, "u.lastname, u.firstname")) {
784 $timenow = time();
785 unset($table);
786 $table->head = array(get_string("name"), get_string("title", "exercise"),
787 get_string("assessed", "exercise"), get_string("action", "exercise"));
788 $table->align = array ("left", "left", "left", "left");
789 $table->size = array ("*", "*", "*", "*");
790 $table->cellpadding = 2;
791 $table->cellspacing = 0;
792 $nassessments = 0;
793 foreach ($users as $user) {
794 // check group membership, if necessary
795 if ($groupid) {
796 // check user's group
797 if (!groups_is_member($groupid, $user->id)) {
798 continue; // skip this user
801 if ($assessments = exercise_get_user_assessments($exercise, $user)) {
802 $title ='';
803 foreach ($assessments as $assessment) {
804 if (!$submission = get_record("exercise_submissions", "id", $assessment->submissionid)) {
805 error("exercise_list_submissions_for_admin: Submission record not found!");
807 $title .= $submission->title;
808 // test for allocated assesments which have not been done
809 if ($assessment->timecreated < $timenow) {
810 // show only warm or cold assessments
811 $title .= " {".number_format($assessment->grade * $exercise->grade / 100.0, 0);
812 if ($assessment->timegraded) {
813 $title .= "/".number_format($assessment->gradinggrade * $exercise->gradinggrade / 100.0, 0);
815 $title .= "} ";
816 if ($realassessments = exercise_count_user_assessments_done($exercise, $user)) {
817 $action = "<a href=\"assessments.php?action=adminlistbystudent&amp;id=$cm->id&amp;userid=$user->id\">".
818 get_string("view", "exercise")."</a>";
820 else {
821 $action ="";
823 $nassessments++;
824 $table->data[] = array(fullname($user), $title,
825 userdate($assessment->timecreated), $action);
830 if (isset($table->data)) {
831 if ($groupid) {
832 if (! groups_group_exists($groupid)) { //TODO:
833 error("List unassessed student submissions: group not found");
835 print_heading("$group->name ".get_string("studentassessments", "exercise", $course->student).
836 " [$nassessments]");
837 } else {
838 print_heading(get_string("studentassessments", "exercise", $course->student)." [$nassessments]");
840 print_table($table);
841 echo "<p align=\"center\">".get_string("noteonstudentassessments", "exercise");
842 echo "<br />{".get_string("maximumgrade").": $exercise->grade / ".
843 get_string("maximumgrade").": $exercise->gradinggrade}</p>\n";
844 // grading grade analysis
845 unset($table);
846 $table->head = array (get_string("count", "exercise"), get_string("mean", "exercise"),
847 get_string("standarddeviation", "exercise"), get_string("maximum", "exercise"),
848 get_string("minimum", "exercise"));
849 $table->align = array ("center", "center", "center", "center", "center");
850 $table->size = array ("*", "*", "*", "*", "*");
851 $table->cellpadding = 2;
852 $table->cellspacing = 0;
853 if ($groupid) {
854 $stats = get_record_sql("SELECT COUNT(*) as count, AVG(gradinggrade) AS mean,
855 STDDEV(gradinggrade) AS stddev, MIN(gradinggrade) AS min, MAX(gradinggrade) AS max
856 FROM {$CFG->prefix}groups_members g, {$CFG->prefix}exercise_assessments a
857 WHERE g.groupid = $groupid AND a.userid = g.userid AND a.timegraded > 0
858 AND a.exerciseid = $exercise->id");
859 } else { // no group/all participants
860 $stats = get_record_sql("SELECT COUNT(*) as count, AVG(gradinggrade) AS mean,
861 STDDEV(gradinggrade) AS stddev, MIN(gradinggrade) AS min, MAX(gradinggrade) AS max
862 FROM {$CFG->prefix}exercise_assessments a
863 WHERE a.timegraded > 0 AND a.exerciseid = $exercise->id");
865 $table->data[] = array($stats->count, number_format($stats->mean * $exercise->gradinggrade / 100.0, 1),
866 number_format($stats->stddev * $exercise->gradinggrade / 100.0, 1),
867 number_format($stats->max * $exercise->gradinggrade / 100.0, 1),
868 number_format($stats->min * $exercise->gradinggrade / 100.0, 1));
869 print_heading(get_string("gradinggrade", "exercise")." ".get_string("analysis", "exercise"));
870 print_table($table);
871 echo "<p align=\"center\"><a href=\"assessments.php?id=$cm->id&amp;action=regradestudentassessments\">".
872 get_string("regradestudentassessments", "exercise")."</a> ";
873 helpbutton("regrading", get_string("regradestudentassessments", "exercise"), "exercise");
874 echo "</p>\n";
878 // now the sudent submissions
879 unset($table);
880 if ($users) {
881 $table->head = array (get_string("submittedby", "exercise"), get_string("title", "exercise"),
882 get_string("submitted", "exercise"), get_string("action", "exercise"));
883 $table->align = array ("left", "left", "left", "left");
884 $table->size = array ("*", "*", "*", "*");
885 $table->cellpadding = 2;
886 $table->cellspacing = 0;
888 $nsubmissions = 0;
889 foreach ($users as $user) {
890 // check group membership, if necessary
891 if ($groupid) {
892 // check user's group
893 if (!groups_is_member($groupid, $user->id)) {
894 continue; // skip this user
897 if ($submissions = exercise_get_user_submissions($exercise, $user)) {
898 foreach ($submissions as $submission) {
899 $action = "<a href=\"submissions.php?action=adminamendtitle&amp;id=$cm->id&amp;sid=$submission->id\">".
900 get_string("amendtitle", "exercise")."</a>";
901 // has teacher already assessed this submission
902 if ($assessment = get_record_select("exercise_assessments",
903 "submissionid = $submission->id AND userid = $USER->id")) {
904 $curtime = time();
905 if (($curtime - $assessment->timecreated) > $CFG->maxeditingtime) {
906 $action .= " | <a href=\"assessments.php?action=assesssubmission&amp;id=$cm->id&amp;sid=$submission->id\">".
907 get_string("reassess", "exercise")."</a>";
909 else { // there's still time left to edit...
910 $action .= " | <a href=\"assessments.php?action=assesssubmission&amp;id=$cm->id&amp;sid=$submission->id\">".
911 get_string("edit", "exercise")."</a>";
914 else { // user has not assessed this submission
915 $action .= " | <a href=\"assessments.php?action=assesssubmission&amp;id=$cm->id&amp;sid=$submission->id\">".
916 get_string("assess", "exercise")."</a>";
918 if ($nassessments = exercise_count_assessments($submission)) {
919 $action .= " | <a href=\"assessments.php?action=adminlist&amp;id=$cm->id&amp;sid=$submission->id\">".
920 get_string("view", "exercise")." ($nassessments)</a>";
922 if ($submission->late) {
923 $action .= " | <a href=\"submissions.php?action=adminlateflag&amp;id=$cm->id&amp;sid=$submission->id\">".
924 get_string("clearlateflag", "exercise")."</a>";
926 $action .= " | <a href=\"submissions.php?action=adminconfirmdelete&amp;id=$cm->id&amp;sid=$submission->id\">".
927 get_string("delete", "exercise")."</a>";
928 $title = $submission->title;
929 if ($submission->resubmit) {
930 $title .= "*";
932 $datesubmitted = userdate($submission->timecreated);
933 if ($submission->late) {
934 $datesubmitted = "<font color=\"red\">".$datesubmitted."</font>";
936 $table->data[] = array(fullname($user), $title.
937 " ".exercise_print_submission_assessments($exercise, $submission),
938 $datesubmitted, $action);
939 $nsubmissions++;
943 if (isset($table->data)) {
944 if ($groupid) {
945 if (! groups_group_exists($groupid)) {
946 error("List unassessed student submissions: group not found");
948 print_heading("$group->name ".get_string("studentsubmissions", "exercise", $course->student).
949 " [$nsubmissions]");
950 } else {
951 print_heading(get_string("studentsubmissions", "exercise", $course->student)." [$nsubmissions]",
952 "center");
954 print_table($table);
955 echo "<p align=\"center\">[] - ".get_string("gradeforsubmission", "exercise");
956 echo "<br />".get_string("maximumgrade").": $exercise->grade</p>\n";
957 echo "<p align=\"center\">".get_string("resubmitnote", "exercise", $course->student)."</p>\n";
958 // grade analysis
959 unset($table);
960 $table->head = array (get_string("count", "exercise"), get_string("mean", "exercise"),
961 get_string("standarddeviation", "exercise"), get_string("maximum", "exercise"),
962 get_string("minimum", "exercise"));
963 $table->align = array ("center", "center", "center", "center", "center");
964 $table->size = array ("*", "*", "*", "*", "*");
965 $table->cellpadding = 2;
966 $table->cellspacing = 0;
968 /// NOTE: user_teachers was ripped from the following SQL without a proper fix - XXX TO DO
970 if ($groupid) {
971 $stats = get_record_sql("SELECT COUNT(*) as count, AVG(grade) AS mean,
972 STDDEV(grade) AS stddev, MIN(grade) AS min, MAX(grade) AS max
973 FROM {$CFG->prefix}groups_members g, {$CFG->prefix}exercise_assessments a,
974 {$CFG->prefix}exercise_submissions s
975 WHERE g.groupid = $groupid AND s.userid = g.userid AND a.submissionid = s.id
976 AND a.exerciseid = $exercise->id");
977 } else { // no group/all participants
978 $stats = get_record_sql("SELECT COUNT(*) as count, AVG(grade) AS mean,
979 STDDEV(grade) AS stddev, MIN(grade) AS min, MAX(grade) AS max
980 FROM {$CFG->prefix}exercise_assessments a
981 WHERE a.exerciseid = $exercise->id");
983 $table->data[] = array($stats->count, number_format($stats->mean * $exercise->grade / 100.0, 1),
984 number_format($stats->stddev * $exercise->grade / 100.0, 1),
985 number_format($stats->max * $exercise->grade / 100.0, 1),
986 number_format($stats->min * $exercise->grade / 100.0, 1));
987 print_heading(get_string("grade")." ".get_string("analysis", "exercise"));
988 print_table($table);
994 ///////////////////////////////////////////////////////////////////////////////////////////////
995 function exercise_list_teacher_assessments($exercise, $user) {
996 global $CFG;
997 $timenow = time();
999 if (! $course = get_record("course", "id", $exercise->course)) {
1000 error("Course is misconfigured");
1002 $table->head = array (get_string("title", "exercise"), get_string("action", "exercise"), get_string("comment", "exercise"));
1003 $table->align = array ("left", "left", "left");
1004 $table->size = array ("*", "*", "*");
1005 $table->cellpadding = 2;
1006 $table->cellspacing = 0;
1008 // get user's submissions
1009 if ($submissions = exercise_get_user_submissions($exercise, $user)) {
1010 foreach ($submissions as $submission) {
1011 // get the assessments
1012 if ($assessments = exercise_get_assessments($submission)) {
1013 foreach ($assessments as $assessment) {
1014 if (isteacher($exercise->course, $assessment->userid)) { // assessments by teachers only
1015 $action = "<a href=\"assessments.php?action=viewassessment&amp;a=$exercise->id&amp;aid=$assessment->id\">".
1016 get_string("view", "exercise")."</a>";
1017 // has teacher commented on teacher's assessment? shouldn't happen but leave test in
1018 if ($assessment->timegraded and ($timenow - $assessment->timegraded > $CFG->maxeditingtime)) {
1019 $comment = get_string("gradedbyteacher", "exercise", $course->teacher);
1021 else {
1022 $comment = userdate($assessment->timecreated);
1024 $table->data[] = array(exercise_print_submission_title($exercise, $submission), $action, $comment);
1030 if (isset($table->data)) {
1031 print_table($table);
1033 else {
1034 echo "<center>".get_string("noassessmentsdone", "exercise")."</center>\n";
1040 ///////////////////////////////////////////////////////////////////////////////////////////////
1041 function exercise_list_teacher_submissions($exercise, $user, $reassess = false) {
1042 // always allow user to reassess if that flag is true
1043 global $CFG;
1045 if (! $course = get_record("course", "id", $exercise->course)) {
1046 error("Course is misconfigured");
1048 if (! $cm = get_coursemodule_from_instance("exercise", $exercise->id, $course->id)) {
1049 error("Course Module ID was incorrect");
1052 $strexercises = get_string("modulenameplural", "exercise");
1053 $strexercise = get_string("modulename", "exercise");
1055 // get any assessment this user has done (could include hot one)
1056 if (!$assessment = get_record_select("exercise_assessments", "exerciseid = $exercise->id
1057 AND userid = $user->id")) {
1058 // the user has not yet assessed this exercise, set up a hot assessment record for this user for one
1059 // of the teacher submissions, first count the number of assessments for each teacher submission...
1060 if ($submissions = exercise_get_teacher_submissions($exercise)) {
1061 // mt_srand ((float)microtime()*1000000); // initialise random number generator, assume php>=4.2.0
1062 foreach ($submissions as $submission) {
1063 $n = count_records("exercise_assessments", "submissionid", $submission->id);
1064 // ...OK to have zero, we add a small random number to randomise things...
1065 $nassessments[$submission->id] = $n + mt_rand(0, 99) / 100;
1067 // ...put the submissions with the lowest number of assessments first...
1068 asort($nassessments);
1069 reset($nassessments);
1070 foreach ($nassessments as $submissionid => $n) { // break out of loop after the first element
1071 $submission = get_record("exercise_submissions", "id", $submissionid);
1072 // ... provided the user has NOT already assessed that submission...
1073 if (!$assessment = exercise_get_submission_assessment($submission, $user)) {
1074 $yearfromnow = time() + 365 * 86400;
1075 // ...create one and set timecreated way in the future, reset when record is updated
1076 $assessment->exerciseid = $exercise->id;
1077 $assessment->submissionid = $submission->id;
1078 $assessment->userid = $user->id;
1079 $assessment->grade = -1; // set impossible grade
1080 $assessment->timecreated = $yearfromnow;
1081 $assessment->mailed = 1; // no need to email to the teacher!
1082 if (!$assessment->id = insert_record("exercise_assessments", $assessment)) {
1083 error("Could not insert exercise assessment!");
1085 break;
1089 } else {
1090 // get hold of the teacher submission
1091 if (!$submission = get_record("exercise_submissions", "id", $assessment->submissionid)) {
1092 error("List teacher submissions: submission record not found");
1095 print_simple_box_start("center");
1096 print_heading_with_help(get_string("theexercise", "exercise"), "junk", "exercise");
1097 print_simple_box_start("center");
1098 echo "<p align=\"center\"><b>".get_string("description", "exercise").": </b>\n";
1099 echo exercise_print_submission_title($exercise, $submission);
1100 echo "</p>\n";
1101 print_simple_box_end();
1102 print_simple_box_end();
1104 $table->head = array (get_string("action", "exercise"), get_string("assessed", "exercise"),
1105 get_string("comment", "exercise"));
1106 $table->align = array ("left", "left", "left");
1107 $table->size = array ("*", "*", "*");
1108 $table->cellpadding = 2;
1109 $table->cellspacing = 0;
1111 // now list user's assessments (but only list those which come from teacher submissions)
1112 print_heading(get_string("yourassessment", "exercise"));
1113 $assessed = false;
1114 if ($assessments = exercise_get_user_assessments($exercise, $user)) {
1115 $timenow = time();
1116 foreach ($assessments as $assessment) {
1117 if (!$submission = get_record("exercise_submissions", "id", $assessment->submissionid)) {
1118 error ("exercise_list_teacher_submissions: unable to get submission");
1120 // submission from a teacher, i.e an exercise submission?
1121 if ($submission->isexercise) {
1122 $comment = '';
1123 if ($reassess) { // just show re-assess
1124 $action = "<a href=\"assessments.php?action=assesssubmission&amp;id=$cm->id&amp;sid=$submission->id\">".
1125 get_string("reassess", "exercise")."</a>";
1127 else { // reassess is false - assessment is a "normal state"
1128 // user assessment has three states: record created but not assessed (date created
1129 // in the future); just assessed but still editable; and "static" (may or may not
1130 // have been graded by teacher, that is shown in the comment)
1131 if ($assessment->timecreated > $timenow) { // user needs to assess this submission
1132 $action = "<a href=\"assessments.php?action=assesssubmission&amp;id=$cm->id&amp;sid=$submission->id\">".
1133 get_string("assess", "exercise")."</a>";
1135 elseif ($assessment->timecreated > ($timenow - $CFG->maxeditingtime)) {
1136 // there's still time left to edit...
1137 $action = "<a href=\"assessments.php?action=assesssubmission&amp;id=$cm->id&amp;sid=$submission->id\">".
1138 get_string("edit", "exercise")."</a>";
1140 else {
1141 $action = "<a href=\"assessments.php?action=viewassessment&amp;id=$cm->id&amp;aid=$assessment->id\">"
1142 .get_string("view", "exercise")."</a>";
1145 // show the date if in the past (otherwise the user hasn't done the assessment yet
1146 $assessmentdate = '';
1147 if ($assessment->timecreated < $timenow) {
1148 $assessmentdate = userdate($assessment->timecreated);
1149 // if user has submitted work, see if teacher has graded assessment
1150 if (exercise_count_user_submissions($exercise, $user) > 0) {
1151 if ($assessment->timegraded and (($timenow - $assessment->timegraded) > $CFG->maxeditingtime)) {
1152 $comment .= get_string("gradeforassessment", "exercise").": ".
1153 number_format($assessment->gradinggrade * $exercise->gradinggrade / 100.0, 1).
1154 " (".get_string("maximumgrade")." ".number_format($exercise->gradinggrade, 0).")";
1155 $assessed = true;
1157 else {
1158 $comment .= get_string("awaitingassessmentbythe", "exercise", $course->teacher);
1162 $table->data[] = array($action, $assessmentdate, $comment);
1165 print_table($table);
1166 if ($assessed) {
1167 echo "<p align=\"center\">".get_string("noteongradinggrade", "exercise", $course->teacher)."</p>\n";
1173 ///////////////////////////////////////////////////////////////////////////////////////////////
1174 function exercise_list_unassessed_student_submissions($exercise, $user) {
1175 // list the student submissions not assessed by the teacher
1176 global $CFG;
1178 $timenow = time();
1180 if (! $course = get_record("course", "id", $exercise->course)) {
1181 error("Course is misconfigured");
1183 if (! $cm = get_coursemodule_from_instance("exercise", $exercise->id, $course->id)) {
1184 error("Course Module ID was incorrect");
1187 $table->head = array (get_string("title", "exercise"), get_string("submittedby", "exercise"),
1188 get_string("submitted", "exercise"), get_string("action", "exercise"),
1189 get_string("comment", "exercise"));
1190 $table->align = array ("left", "left", "left", "left", "left");
1191 $table->size = array ("*", "*", "*", "*", "*");
1192 $table->cellpadding = 2;
1193 $table->cellspacing = 0;
1195 // get all the submissions, oldest first, youngest last
1196 // exercise_get_student_submissions is group aware
1197 $groupid = get_current_group($course->id);
1198 if ($groupid) {
1199 if (! groups_group_exists($groupid)) {
1200 error("List unassessed student submissions: group not found");
1202 print_heading(get_string("studentsubmissionsforassessment", "exercise", $group->name));
1204 if ($submissions = exercise_get_student_submissions($exercise, "time", $groupid)) {
1205 foreach ($submissions as $submission) {
1206 // only consider "cold" submissions
1207 if ($submission->timecreated < $timenow - $CFG->maxeditingtime) {
1208 $comment = "";
1209 // see if student has already submitted
1210 $submissionowner = get_record("user", "id", $submission->userid);
1211 if (exercise_count_user_submissions($exercise, $submissionowner) == 1) {
1212 // it's the student's first submission
1213 // see if there are no cold assessments for this submission
1214 if (!exercise_count_assessments($submission)) {
1215 // now see if the teacher has already assessed this submission
1216 $warm = false;
1217 if ($assessments = get_records("exercise_assessments", "submissionid", $submission->id)) {
1218 foreach ($assessments as $assessment) {
1219 if (isteacher($course->id, $assessment->userid)) {
1220 if ($assessment->timecreated > $timenow -$CFG->maxeditingtime) {
1221 $warm = true;
1223 break; // no need to look further
1227 // get their assessment
1228 if ($assessments = exercise_get_user_assessments($exercise, $submissionowner)) {
1229 foreach ($assessments as $assessment) {
1230 $studentassessment = $assessment;
1231 break; // there should only be one!
1233 $timegap = get_string("ago", "exercise", format_time($submission->timecreated -
1234 $timenow));
1235 if ($submission->late) {
1236 $timegap = "<font color=\"red\">".$timegap."</font>";
1238 if ($warm) {
1239 // last chance salon
1240 $action = "<a href=\"assessments.php?action=teacherassessment&amp;id=$cm->id&amp;aid=$studentassessment->id&amp;sid=$submission->id\">".
1241 get_string("edit", "exercise")."</a>";
1242 $table->data[] = array(exercise_print_submission_title($exercise, $submission),
1243 fullname($submissionowner),
1244 $timegap, $action, $comment);
1245 } else {
1246 $action = "<a href=\"assessments.php?action=teacherassessment&amp;id=$cm->id&amp;aid=$studentassessment->id&amp;sid=$submission->id\">".
1247 get_string("assess", "exercise")."</a>";
1248 $table->data[] = array(exercise_print_submission_title($exercise, $submission),
1249 fullname($submissionowner),
1250 $timegap, $action, $comment);
1252 } else {
1253 // there's no student assessment, odd!!
1257 // this is student's second... submission
1258 else {
1259 $teacherassessed = false;
1260 $warm = false;
1261 if ($assessments = get_records("exercise_assessments", "submissionid", $submission->id)) {
1262 foreach ($assessments as $assessment) {
1263 if (isteacher($course->id, $assessment->userid)) {
1264 $teacherassessed = true;
1265 if (!$teacher = get_record("user", "id", $assessment->userid)) {
1266 error("List unassessed student submissions: teacher record not found");
1268 $comment = get_string("resubmissionfor", "exercise",
1269 fullname($teacher));
1270 if ($assessment->timecreated > $timenow - $CFG->maxeditingtime) {
1271 $warm = true;
1273 break; // no need to look further
1277 if ($teacherassessed and $warm) {
1278 // last chance salon
1279 $action = "<a href=\"assessments.php?action=assessresubmission&amp;id=$cm->id&amp;sid=$submission->id\">".
1280 get_string("edit", "exercise")."</a>";
1281 $timegap = get_string("ago", "exercise", format_time($submission->timecreated -
1282 $timenow));
1283 if ($submission->late) {
1284 $timegap = "<font color=\"red\">".$timegap."</font>";
1286 $table->data[] = array(exercise_print_submission_title($exercise, $submission),
1287 fullname($submissionowner),
1288 $timegap, $action, $comment);
1290 if (!$teacherassessed) {
1291 // no teacher's assessment
1292 // find who did the previous assessment
1293 if (!$submissions = exercise_get_user_submissions($exercise, $submissionowner)) {
1294 error("List unassessed student submissions: submission records not found");
1296 // get the oldest submission, exercise_get_user_submissions returns that first
1297 foreach ($submissions as $tempsubmission) {
1298 $prevsubmission = $tempsubmission;
1299 break;
1301 // get the teacher's assessment of the student's previous submission
1302 if ($assessments = get_records("exercise_assessments", "submissionid",
1303 $prevsubmission->id)) {
1304 foreach ($assessments as $assessment) {
1305 if (isteacher($course->id, $assessment->userid)) {
1306 if (!$teacher = get_record("user", "id", $assessment->userid)) {
1307 error("List unassessed student submissions: teacher record not found");
1309 $comment = get_string("resubmissionfor", "exercise",
1310 fullname($teacher));
1311 break; // no need to look further
1316 $action = "<a href=\"assessments.php?action=assessresubmission&amp;id=$cm->id&amp;sid=$submission->id\">".
1317 get_string("assess", "exercise")."</a>";
1318 $timegap = get_string("ago", "exercise", format_time($submission->timecreated -
1319 $timenow));
1320 if ($submission->late) {
1321 $timegap = "<font color=\"red\">".$timegap."</font>";
1323 $table->data[] = array(exercise_print_submission_title($exercise, $submission),
1324 fullname($submissionowner),
1325 $timegap, $action, $comment);
1330 if (isset($table->data)) {
1331 print_table($table);
1337 ///////////////////////////////////////////////////////////////////////////////////////////////
1338 function exercise_list_unassessed_teacher_submissions($exercise, $user) {
1339 // list the teacher submissions not assessed by this user
1340 global $CFG;
1342 $table->head = array (get_string("title", "exercise"), get_string("action", "exercise"), get_string("comment", "exercise"));
1343 $table->align = array ("left", "left", "left");
1344 $table->size = array ("*", "*", "*");
1345 $table->cellpadding = 2;
1346 $table->cellspacing = 0;
1348 if ($submissions = exercise_get_teacher_submissions($exercise)) {
1349 foreach ($submissions as $submission) {
1350 $comment = "";
1351 // see if user already graded this assessment
1352 if ($assessment = get_record_select("exercise_assessments", "submissionid = $submission->id
1353 AND userid = $user->id")) {
1354 $timenow = time();
1355 if (($timenow - $assessment->timecreated < $CFG->maxeditingtime)) {
1356 // last chance salon
1357 $action = "<a href=\"assessments.php?action=assesssubmission&amp;a=$exercise->id&amp;sid=$submission->id\">".
1358 get_string("edit", "exercise")."</a>";
1359 $table->data[] = array(exercise_print_submission_title($exercise, $submission), $action, $comment);
1362 else { // no assessment
1363 $action = "<a href=\"assessments.php?action=assesssubmission&amp;a=$exercise->id&amp;sid=$submission->id\">".
1364 get_string("assess", "exercise")."</a>";
1365 $table->data[] = array(exercise_print_submission_title($exercise, $submission), $action, $comment);
1368 if (isset($table->data)) {
1369 print_table($table);
1375 ///////////////////////////////////////////////////////////////////////////////////////////////
1376 function exercise_list_ungraded_assessments($exercise, $stype) {
1377 global $CFG;
1379 if (! $course = get_record("course", "id", $exercise->course)) {
1380 error("Course is misconfigured");
1382 if (! $cm = get_coursemodule_from_instance("exercise", $exercise->id, $course->id)) {
1383 error("Course Module ID was incorrect");
1386 // lists all the assessments of student submissions for grading by teacher
1387 $table->head = array (get_string("title", "exercise"), get_string("submittedby", "exercise"),
1388 get_string("assessor", "exercise"), get_string("timeassessed", "exercise"), get_string("action", "exercise"));
1389 $table->align = array ("left", "left", "left", "left");
1390 $table->size = array ("*", "*", "*", "*");
1391 $table->cellpadding = 2;
1392 $table->cellspacing = 0;
1393 $timenow = time();
1395 switch ($stype) {
1396 case "student" :
1397 $assessments = exercise_get_ungraded_assessments_student($exercise);
1398 break;
1399 case "teacher" :
1400 $assessments = exercise_get_ungraded_assessments_teacher($exercise);
1401 break;
1403 if ($assessments) {
1404 foreach ($assessments as $assessment) {
1405 if (!isteacher($exercise->course, $assessment->userid)) { // don't let teacher grade their own assessments
1406 if (($timenow - $assessment->timegraded) < $CFG->maxeditingtime) {
1407 $action = "<a href=\"assessments.php?action=gradeassessment&amp;id=$cm->id&amp;stype=$stype&amp;aid=$assessment->id\">".
1408 get_string("edit", "exercise")."</a>";
1410 else {
1411 $action = "<a href=\"assessments.php?action=gradeassessment&amp;id=$cm->id&amp;stype=$stype&amp;aid=$assessment->id\">".
1412 get_string("grade")."</a>";
1414 $submission = get_record("exercise_submissions", "id", $assessment->submissionid);
1415 $submissionowner = get_record("user", "id", $submission->userid);
1416 $assessor = get_record("user", "id", $assessment->userid);
1417 $table->data[] = array(exercise_print_submission_title($exercise, $submission),
1418 fullname($submissionowner),
1419 fullname($assessor), userdate($assessment->timecreated), $action);
1422 if (isset($table->data)) {
1423 print_table($table);
1429 ///////////////////////////////////////////////////////////////////////////////////////////////
1430 function exercise_list_user_submissions($exercise, $user) {
1431 global $CFG;
1433 if (! $course = get_record("course", "id", $exercise->course)) {
1434 error("Course is misconfigured");
1436 if (! $cm = get_coursemodule_from_instance("exercise", $exercise->id, $course->id)) {
1437 error("Course Module ID was incorrect");
1440 $timenow = time();
1441 $table->head = array (get_string("title", "exercise"), get_string("action", "exercise"),
1442 get_string("submitted", "exercise"), get_string("assessment", "exercise"));
1443 $table->align = array ("left", "left", "left", "left");
1444 $table->size = array ("*", "*", "*", "*");
1445 $table->cellpadding = 2;
1446 $table->cellspacing = 0;
1448 if ($submissions = exercise_get_user_submissions($exercise, $user)) {
1449 foreach ($submissions as $submission) {
1450 $action = '';
1451 $comment = '';
1452 // allow user to delete submission if it's warm
1453 if ($submission->timecreated > $timenow - $CFG->maxeditingtime) {
1454 $action = "<a href=\"submissions.php?action=userconfirmdelete&amp;id=$cm->id&amp;sid=$submission->id\">".
1455 get_string("delete", "exercise")."</a>";
1457 // if this is a teacher's submission (an exercise description) ignore any assessments
1458 if (!$submission->isexercise) {
1459 // get the teacher assessments (could be more than one, if unlikely, when multiple teachers)
1460 if ($assessments = get_records_select("exercise_assessments", "exerciseid = $exercise->id AND
1461 submissionid = $submission->id")) {
1462 foreach ($assessments as $assessment) {
1463 // make sure it's real
1464 if ($assessment->timecreated < $timenow - $CFG->maxeditingtime) { // it's cold
1465 if ($action) {
1466 $action .= " | ";
1468 $action .= "<a href=\"assessments.php?action=viewassessment&amp;id=$cm->id&amp;aid=$assessment->id\">".
1469 get_string("viewteacherassessment", "exercise", $course->teacher)."</a>";
1470 if ($comment) {
1471 $comment .= " | ";
1473 $comment .= get_string("teacherassessment", "exercise", $course->teacher).": ".
1474 number_format($assessment->grade * $exercise->grade / 100.0, 1).
1475 " (".get_string("maximumgrade")." ".number_format($exercise->grade, 0).")";
1480 if (!$comment and isstudent($course->id, $user->id)) {
1481 $comment = get_string("awaitingassessmentbythe", "exercise", $course->teacher);
1483 $submissiondate = userdate($submission->timecreated);
1484 if ($submission->late) {
1485 $submissiondate = "<font color=\"red\">".$submissiondate."</font>";
1487 $table->data[] = array(exercise_print_submission_title($exercise, $submission), $action,
1488 $submissiondate, $comment);
1490 print_table($table);
1495 ///////////////////////////////////////////////////////////////////////////////////////////////
1496 function exercise_print_assessment_form($exercise, $assessment = false, $allowchanges = false, $returnto = '') {
1497 // prints several variants of the assessment form
1498 global $CFG, $USER, $EXERCISE_SCALES, $EXERCISE_EWEIGHTS;
1500 if (! $course = get_record("course", "id", $exercise->course)) {
1501 error("Course is misconfigured");
1503 if (! $cm = get_coursemodule_from_instance("exercise", $exercise->id, $course->id)) {
1504 error("Course Module ID was incorrect");
1507 $timenow = time();
1509 if ($assessment) {
1511 if (!$submission = get_record("exercise_submissions", "id", $assessment->submissionid)) {
1512 error ("exercise_print_assessment_form: Submission record not found");
1514 // test if this assessment is from a teacher or student.
1515 // Teacher's assessments are more complicated as we need to go back a couple of steps
1516 // to find the exercise. Student's assessments are directly associated with an exercise.
1517 if (isteacher($course->id, $assessment->userid)) {
1518 // A teacher's assessment, requires getting the student's assessment(s)
1519 // and finding which of those assessments which comes from a teacher submission,
1520 // that is the exercise
1521 $exercisefound = false;
1522 if (!$submissionowner = get_record("user", "id", $submission->userid)) {
1523 error ("exercise_print_assessment_form: User record not found");
1525 if ($initialassessments = exercise_get_user_assessments($exercise, $submissionowner)) {
1526 // should only be one but we'll loop anyway
1527 foreach($initialassessments as $initialassessment) {
1528 if (!$teachersubmission = get_record("exercise_submissions", "id", $initialassessment->submissionid)) {
1529 error ("exercise_print_assessment_form: Teacher Submission record not found");
1531 if ($teachersubmission->isexercise) {
1532 $exercisefound = true;
1533 break;
1537 if ($exercisefound) {
1538 print_heading(get_string("theexerciseandthesubmissionby", "exercise",
1539 fullname($submissionowner)));
1540 echo "<center><table border=\"1\" width=\"30%\"><tr>
1541 <td align=\"center\">\n";
1542 echo exercise_print_submission_title($exercise, $teachersubmission);
1543 echo "</td></tr></table><br clear=\"all\" />\n";
1546 else {
1547 // it's a student assessment, print instructions if it's their own assessment
1548 if ($assessment->userid == $USER->id) {
1549 print_heading_with_help(get_string("pleaseusethisform", "exercise"), "grading", "exercise");
1553 echo "<center><table border=\"1\" width=\"30%\"><tr>
1554 <td align=\"center\">\n";
1555 echo exercise_print_submission_title($exercise, $submission);
1556 echo "</td></tr></table><br clear=\"all\" />\n";
1558 // only show the grade if grading strategy > 0 and the grade is positive
1559 if ($exercise->gradingstrategy and $assessment->grade >= 0) {
1561 echo "<center><b>".get_string("thegradeis", "exercise").": ".
1562 number_format($assessment->grade * $exercise->grade / 100.0, 2)." (".
1563 get_string("maximumgrade")." ".number_format($exercise->grade, 0).")</b></center><br clear=\"all\" />\n";
1567 // now print the grading form with the teacher's comments if any
1568 // FORM is needed for Mozilla browsers, else radio bttons are not checked
1570 <form id="assessmentform" method="post" action="assessments.php">
1571 <input type="hidden" name="id" value="<?php echo $cm->id ?>" />
1572 <input type="hidden" name="aid" value="<?php echo $assessment->id ?>" />
1573 <input type="hidden" name="action" value="updateassessment" />
1574 <input type="hidden" name="resubmit" value="0" />
1575 <input type="hidden" name="returnto" value="<?php echo $returnto ?>" />
1576 <?php
1577 if ($assessment) {
1578 if (!$assessmentowner = get_record("user", "id", $assessment->userid)) {
1579 error("Exercise_print_assessment_form: could not find user record");
1581 if ($assessmentowner->id == $USER->id) {
1582 $formtitle = get_string("yourassessment", "exercise");
1584 else {
1585 $formtitle = get_string("assessmentby", "exercise", fullname($assessmentowner));
1588 else {
1589 $formtitle = get_string("assessmentform", "exercise");
1591 echo "<center><table cellpadding=\"2\" border=\"1\">\n";
1592 echo "<tr valign=\"top\">\n";
1594 echo " <td colspan=\"2\"><center><b>$formtitle</b></center></td>\n";
1596 echo "</tr>\n";
1598 // get the assignment elements...
1599 if (!$elementsraw = get_records("exercise_elements", "exerciseid", $exercise->id, "elementno ASC")) {
1600 print_string("noteonassignmentelements", "exercise");
1602 else {
1603 foreach ($elementsraw as $element) {
1604 $elements[] = $element; // to renumber index 0,1,2...
1608 if ($assessment) {
1609 $assessment->generalcomment = clean_text($assessment->generalcomment); //clean html first
1610 // get any previous grades...
1611 if ($gradesraw = get_records_select("exercise_grades", "assessmentid = $assessment->id", "elementno")) {
1612 foreach ($gradesraw as $grade) {
1613 $grade->feedback = clean_text($grade->feedback); //clean the html first
1614 $grades[] = $grade; // to renumber index 0,1,2...
1618 else {
1619 // setup dummy grades array
1620 for($i = 0; $i < count($elementsraw); $i++) { // gives a suitable sized loop
1621 $grades[$i]->feedback = get_string("yourfeedbackgoeshere", "exercise");
1622 $grades[$i]->grade = 0;
1626 // determine what sort of grading
1627 switch ($exercise->gradingstrategy) {
1628 case 0: // no grading
1629 // now print the form
1630 for ($i=0; $i < count($elements); $i++) {
1631 $iplus1 = $i+1;
1632 echo "<tr valign=\"top\">\n";
1633 echo " <td align=\"right\"><p><b>". get_string("element","exercise")." $iplus1:</b></p></td>\n";
1634 echo " <td>".text_to_html($elements[$i]->description);
1635 echo "</td></tr>\n";
1636 echo "<tr valign=\"top\">\n";
1637 echo " <td align=\"right\"><p><b>". get_string("feedback").":</b></p></td>\n";
1638 echo " <td>\n";
1639 if ($allowchanges) {
1640 echo " <textarea name=\"feedback[]\" rows=\"3\" cols=\"75\" wrap=\"virtual\">\n";
1641 if (isset($grades[$i]->feedback)) {
1642 echo $grades[$i]->feedback;
1644 echo "</textarea>\n";
1646 else {
1647 echo text_to_html($grades[$i]->feedback);
1649 echo " </td>\n";
1650 echo "</tr>\n";
1651 echo "<tr valign=\"top\">\n";
1652 echo " <td colspan=\"2\">&nbsp;</td>\n";
1653 echo "</tr>\n";
1655 break;
1657 case 1: // accumulative grading
1658 // now print the form
1659 for ($i=0; $i < count($elements); $i++) {
1660 $iplus1 = $i+1;
1661 echo "<tr valign=\"top\">\n";
1662 echo " <td align=\"right\"><p><b>". get_string("element","exercise")." $iplus1:</b></p></td>\n";
1664 echo " <td>".text_to_html($elements[$i]->description);
1665 echo "<p align=\"right\"><font size=\"1\">Weight: "
1666 .number_format($EXERCISE_EWEIGHTS[$elements[$i]->weight], 2)."</font>\n";
1667 echo "</td></tr>\n";
1668 echo "<tr valign=\"top\">\n";
1669 echo " <td align=\"right\"><p><b>". get_string("grade"). ":</b></p></td>\n";
1670 echo " <td valign=\"top\">\n";
1672 // get the appropriate scale
1673 $scalenumber=$elements[$i]->scale;
1674 $SCALE = (object)$EXERCISE_SCALES[$scalenumber];
1675 switch ($SCALE->type) {
1676 case 'radio' :
1677 // show selections highest first
1678 echo "<center><b>$SCALE->start</b>&nbsp;&nbsp;&nbsp;";
1679 for ($j = $SCALE->size - 1; $j >= 0 ; $j--) {
1680 $checked = false;
1681 if (isset($grades[$i]->grade)) {
1682 if ($j == $grades[$i]->grade) {
1683 $checked = true;
1686 else { // there's no previous grade so check the lowest option
1687 if ($j == 0) {
1688 $checked = true;
1691 if ($checked) {
1692 echo " <input type=\"RADIO\" name=\"grade[$i]\" value=\"$j\" checked=\"checked\" /> &nbsp;&nbsp;&nbsp;\n";
1694 else {
1695 echo " <input type=\"RADIO\" name=\"grade[$i]\" value=\"$j\" /> &nbsp;&nbsp;&nbsp;\n";
1698 echo "&nbsp;&nbsp;&nbsp;<b>$SCALE->end</b></center>\n";
1699 break;
1700 case 'selection' :
1701 unset($numbers);
1702 for ($j = $SCALE->size; $j >= 0; $j--) {
1703 $numbers[$j] = $j;
1705 if (isset($grades[$i]->grade)) {
1706 choose_from_menu($numbers, "grade[$i]", $grades[$i]->grade, "");
1708 else {
1709 choose_from_menu($numbers, "grade[$i]", 0, "");
1711 break;
1713 echo " </td>\n";
1714 echo "</tr>\n";
1716 echo "<tr valign=\"top\">\n";
1717 echo " <td align=\"right\"><p><b>". get_string("feedback").":</b></p></td>\n";
1718 echo " <td>\n";
1719 if ($allowchanges) {
1720 echo " <textarea name=\"feedback[]\" rows=\"3\" cols=\"75\" wrap=\"virtual\">\n";
1721 if (isset($grades[$i]->feedback)) {
1722 echo $grades[$i]->feedback;
1724 echo "</textarea>\n";
1726 else {
1727 echo text_to_html($grades[$i]->feedback);
1729 echo " </td>\n";
1730 echo "</tr>\n";
1731 echo "<tr valign=\"top\">\n";
1732 echo " <td colspan=\"2\">&nbsp;</td>\n";
1733 echo "</tr>\n";
1735 break;
1737 case 2: // error banded grading
1738 // now run through the elements
1739 $error = 0;
1740 for ($i=0; $i < count($elements) - 1; $i++) {
1741 $iplus1 = $i+1;
1742 echo "<tr valign=\"top\">\n";
1744 echo " <td align=\"right\"><p><b>". get_string("element","exercise")." $iplus1:</b></p></td>\n";
1746 echo " <td>".text_to_html($elements[$i]->description);
1747 echo "<p align=\"right\"><font size=\"1\">Weight: "
1748 .number_format($EXERCISE_EWEIGHTS[$elements[$i]->weight], 2)."</font>\n";
1749 echo "</td></tr>\n";
1750 echo "<tr valign=\"top\">\n";
1751 echo " <td align=\"right\"><p><b>". get_string("grade"). ":</b></p></td>\n";
1752 echo " <td valign=\"top\">\n";
1754 // get the appropriate scale - yes/no scale (0)
1755 $SCALE = (object) $EXERCISE_SCALES[0];
1756 switch ($SCALE->type) {
1757 case 'radio' :
1758 // show selections highest first
1759 echo "<center><b>$SCALE->start</b>&nbsp;&nbsp;&nbsp;";
1760 for ($j = $SCALE->size - 1; $j >= 0 ; $j--) {
1761 $checked = false;
1762 if (isset($grades[$i]->grade)) {
1763 if ($j == $grades[$i]->grade) {
1764 $checked = true;
1767 else { // there's no previous grade so check the lowest option
1768 if ($j == 0) {
1769 $checked = true;
1772 if ($checked) {
1773 echo " <input type=\"RADIO\" name=\"grade[$i]\" value=\"$j\" checked=\"checked\" /> &nbsp;&nbsp;&nbsp;\n";
1775 else {
1776 echo " <input type=\"RADIO\" name=\"grade[$i]\" value=\"$j\" /> &nbsp;&nbsp;&nbsp;\n";
1779 echo "&nbsp;&nbsp;&nbsp;<b>$SCALE->end</b></center>\n";
1780 break;
1781 case 'selection' :
1782 unset($numbers);
1783 for ($j = $SCALE->size; $j >= 0; $j--) {
1784 $numbers[$j] = $j;
1786 if (isset($grades[$i]->grade)) {
1787 choose_from_menu($numbers, "grade[$i]", $grades[$i]->grade, "");
1789 else {
1790 choose_from_menu($numbers, "grade[$i]", 0, "");
1792 break;
1795 echo " </td>\n";
1796 echo "</tr>\n";
1797 echo "<tr valign=\"top\">\n";
1798 echo " <td align=\"right\"><p><b>". get_string("feedback").":</b></p></td>\n";
1799 echo " <td>\n";
1800 if ($allowchanges) {
1801 echo " <textarea name=\"feedback[$i]\" rows=\"3\" cols=\"75\" wrap=\"virtual\">\n";
1802 if (isset($grades[$i]->feedback)) {
1803 echo $grades[$i]->feedback;
1805 echo "</textarea>\n";
1807 else {
1808 if (isset($grades[$i]->feedback)) {
1809 echo text_to_html($grades[$i]->feedback);
1812 echo "&nbsp;</td>\n";
1813 echo "</tr>\n";
1814 echo "<tr valign=\"top\">\n";
1815 echo " <td colspan=\"2\">&nbsp;</td>\n";
1816 echo "</tr>\n";
1817 if (empty($grades[$i]->grade)) {
1818 $error += $EXERCISE_EWEIGHTS[$elements[$i]->weight];
1821 // print the number of negative elements
1822 // echo "<tr><td>".get_string("numberofnegativeitems", "exercise")."</td><td>$negativecount</td></tr>\n";
1823 // echo "<tr valign=\"top\">\n";
1824 // echo " <td colspan=\"2\">&nbsp;</td>\n";
1825 echo "</table></center>\n";
1826 // now print the grade table
1827 echo "<p><center><b>".get_string("gradetable","exercise")."</b></center>\n";
1828 echo "<center><table cellpadding=\"5\" border=\"1\"><tr><td align=\"CENTER\">".
1829 get_string("numberofnegativeresponses", "exercise");
1830 echo "</td><td>". get_string("suggestedgrade", "exercise")."</td></tr>\n";
1831 for ($i=0; $i<=$exercise->nelements; $i++) {
1832 if ($i == intval($error + 0.5)) {
1833 echo "<tr><td align=\"CENTER\"><img src=\"$CFG->pixpath/t/right.gif\" alt=\"\" /> $i</td><td align=\"CENTER\">{$elements[$i]->maxscore}</td></tr>\n";
1835 else {
1836 echo "<tr><td align=\"CENTER\">$i</td><td align=\"CENTER\">{$elements[$i]->maxscore}</td></tr>\n";
1839 echo "</table></center>\n";
1840 echo "<p><center><table cellpadding=\"5\" border=\"1\"><tr><td align=\"right\"><b>".
1841 get_string("optionaladjustment", "exercise").":</b></td><td>\n";
1842 unset($numbers);
1843 for ($j = 20; $j >= -20; $j--) {
1844 $numbers[$j] = $j;
1846 if (isset($grades[$exercise->nelements]->grade)) {
1847 choose_from_menu($numbers, "grade[$exercise->nelements]", $grades[$exercise->nelements]->grade, "");
1849 else {
1850 choose_from_menu($numbers, "grade[$exercise->nelements]", 0, "");
1852 echo "</td></tr>\n";
1853 break;
1855 case 3: // criteria grading
1856 echo "<tr valign=\"top\">\n";
1858 echo " <td>&nbsp;</td>\n";
1860 echo " <td><b>". get_string("criterion","exercise")."</b></td>\n";
1862 echo " <td><b>".get_string("select")."</b></td>\n";
1863 echo " <td><b>".get_string("suggestedgrade", "exercise")."</b></td>\n";
1864 // find which criteria has been selected (saved in the zero element), if any
1865 if (isset($grades[0]->grade)) {
1866 $selection = $grades[0]->grade;
1868 else {
1869 $selection = 0;
1871 // now run through the elements
1872 for ($i=0; $i < count($elements); $i++) {
1873 $iplus1 = $i+1;
1874 echo "<tr valign=\"top\">\n";
1876 echo " <td>$iplus1</td><td>".text_to_html($elements[$i]->description)."</td>\n";
1877 if ($selection == $i) {
1878 echo " <td align=\"center\"><input type=\"RADIO\" name=\"grade[0]\" value=\"$i\" checked=\"checked\" /></td>\n";
1880 else {
1881 echo " <td align=\"center\"><input type=\"RADIO\" name=\"grade[0]\" value=\"$i\" /></td>\n";
1883 echo "<td align=\"center\">{$elements[$i]->maxscore}</td></tr>\n";
1885 echo "</table></center>\n";
1886 echo "<p><center><table cellpadding=\"5\" border=\"1\"><tr><td align=\"right\"><b>".
1887 get_string("optionaladjustment", "exercise")."</b></td><td>\n";
1888 unset($numbers);
1889 for ($j = 20; $j >= -20; $j--) {
1890 $numbers[$j] = $j;
1892 if (isset($grades[1]->grade)) {
1893 choose_from_menu($numbers, "grade[1]", $grades[1]->grade, "");
1895 else {
1896 choose_from_menu($numbers, "grade[1]", 0, "");
1898 echo "</td></tr>\n";
1899 break;
1901 case 4: // rubric grading
1902 // now run through the elements...
1903 for ($i=0; $i < count($elements); $i++) {
1904 $iplus1 = $i+1;
1905 echo "<tr valign=\"top\">\n";
1907 echo "<td align=\"right\"><b>".get_string("element", "exercise")." $iplus1:</b></td>\n";
1908 echo "<td>".text_to_html($elements[$i]->description).
1909 "<p align=\"right\"><font size=\"1\">Weight: "
1910 .number_format($EXERCISE_EWEIGHTS[$elements[$i]->weight], 2)."</font></td></tr>\n";
1911 echo "<tr valign=\"top\">\n";
1913 echo " <td align=\"center\"><b>".get_string("select")."</b></td>\n";
1914 echo " <td><b>". get_string("criterion","exercise")."</b></td></tr>\n";
1916 if (isset($grades[$i])) {
1917 $selection = $grades[$i]->grade;
1918 } else {
1919 $selection = 0;
1921 // ...and the rubrics
1922 if ($rubricsraw = get_records_select("exercise_rubrics", "exerciseid = $exercise->id AND
1923 elementno = $i", "rubricno ASC")) {
1924 unset($rubrics);
1925 foreach ($rubricsraw as $rubic) {
1926 $rubrics[] = $rubic; // to renumber index 0,1,2...
1928 for ($j=0; $j<5; $j++) {
1929 if (empty($rubrics[$j]->description)) {
1930 break; // out of inner for loop
1932 echo "<tr valign=\"top\">\n";
1934 if ($selection == $j) {
1935 echo " <td align=\"center\"><input type=\"RADIO\" name=\"grade[$i]\" value=\"$j\" checked=\"checked\" /></td>\n";
1936 }else {
1937 echo " <td align=\"center\"><input type=\"RADIO\" name=\"grade[$i]\" value=\"$j\" /></td>\n";
1939 echo "<td>".text_to_html($rubrics[$j]->description)."</td>\n";
1941 echo "<tr valign=\"top\">\n";
1942 echo " <td align=\"right\"><p><b>". get_string("feedback").":</b></p></td>\n";
1943 echo " <td>\n";
1944 if ($allowchanges) {
1945 echo " <textarea name=\"feedback[]\" rows=\"3\" cols=\"75\" wrap=\"virtual\">\n";
1946 if (isset($grades[$i]->feedback)) {
1947 echo $grades[$i]->feedback;
1949 echo "</textarea>\n";
1951 else {
1952 echo text_to_html($grades[$i]->feedback);
1954 echo " </td>\n";
1955 echo "</tr>\n";
1956 echo "<tr valign=\"top\">\n";
1957 echo " <td colspan=\"2\">&nbsp;</td>\n";
1958 echo "</tr>\n";
1961 break;
1962 } // end of outer switch
1964 // now get the general comment (present in all types)
1965 echo "<tr valign=\"top\">\n";
1966 switch ($exercise->gradingstrategy) {
1967 case 0:
1968 case 1:
1969 case 4 : // no grading, accumulative and rubic
1970 echo " <td align=\"right\"><p><b>". get_string("generalcomment", "exercise").":</b></p></td>\n";
1971 break;
1972 default :
1973 echo " <td align=\"right\"><p><b>". get_string("reasonforadjustment", "exercise").":</b></p></td>\n";
1975 echo " <td>\n";
1976 if ($allowchanges) {
1977 echo " <textarea name=\"generalcomment\" rows=\"5\" cols=\"75\" wrap=\"virtual\">\n";
1978 if (isset($assessment->generalcomment)) {
1979 echo $assessment->generalcomment;
1981 echo "</textarea>\n";
1983 else {
1984 if ($assessment) {
1985 if (isset($assessment->generalcomment)) {
1986 echo text_to_html($assessment->generalcomment);
1989 else {
1990 print_string("yourfeedbackgoeshere", "exercise");
1994 echo "&nbsp;</td>\n";
1996 echo "</tr>\n";
1998 echo "<tr valign=\"top\">\n";
2000 echo " <td colspan=\"2\">&nbsp;</td>\n";
2002 echo "</tr>\n";
2004 $timenow = time();
2006 // always show the teacher the grading grade if it's not their assessment!
2007 if (isteacher($course->id) and ($assessment->userid != $USER->id) and $exercise->gradinggrade) {
2008 echo "<tr><td align=\"right\"><b>".get_string("gradeforstudentsassessment", "exercise", $course->student).
2009 "</td><td>\n";
2010 echo number_format($exercise->gradinggrade * $assessment->gradinggrade / 100.0, 0);
2011 echo "</td></tr>\n";
2014 // ...and close the table, show buttons if needed...
2015 echo "</table><br />\n";
2016 if ($assessment and $allowchanges) {
2017 if (isteacher($course->id)) {
2018 // ...show two buttons...to resubmit or not to resubmit
2019 echo "<input type=\"button\" value=\"".get_string("studentnotallowed", "exercise", $course->student)."\"
2020 onclick=\"getElementById('assessmentform').submit();\" />\n";
2021 echo "<input type=\"button\" value=\"".get_string("studentallowedtoresubmit", "exercise", $course->student)."\"
2022 onclick=\"getElementById('assessmentform').resubmit.value='1';getElementById('assessmentform').submit();\" />\n";
2024 else {
2025 // ... show save button
2026 echo "<input type=\"submit\" value=\"".get_string("savemyassessment", "exercise")."\" />\n";
2029 echo "</center></form>\n";
2034 ///////////////////////////////////////////////////////////////////////////////////////////////
2035 function exercise_print_assessments_by_user_for_admin($exercise, $user) {
2037 if (! $course = get_record("course", "id", $exercise->course)) {
2038 error("Course is misconfigured");
2040 if (! $cm = get_coursemodule_from_instance("exercise", $exercise->id, $course->id)) {
2041 error("Course Module ID was incorrect");
2044 if ($assessments =exercise_get_user_assessments($exercise, $user)) {
2045 foreach ($assessments as $assessment) {
2046 echo "<p><center><b>".get_string("assessmentby", "exercise", fullname($user))."</b></center></p>\n";
2047 exercise_print_assessment_form($exercise, $assessment);
2048 echo "<p align=\"right\"><a href=\"assessments.php?action=adminamendgradinggrade&amp;id=$cm->id&amp;aid=$assessment->id\">".
2049 get_string("amend", "exercise")." ".get_string("gradeforstudentsassessment","exercise",
2050 $course->student)."</a>\n";
2051 echo " | <a href=\"assessments.php?action=adminconfirmdelete&amp;id=$cm->id&amp;aid=$assessment->id\">".
2052 get_string("delete", "exercise")."</a></p><hr />\n";
2058 ///////////////////////////////////////////////////////////////////////////////////////////////
2059 function exercise_print_assessments_for_admin($exercise, $submission) {
2061 if (! $course = get_record("course", "id", $exercise->course)) {
2062 error("Course is misconfigured");
2064 if (! $cm = get_coursemodule_from_instance("exercise", $exercise->id, $course->id)) {
2065 error("Course Module ID was incorrect");
2068 if ($assessments = exercise_get_assessments($submission)) {
2069 foreach ($assessments as $assessment) {
2070 if (!$user = get_record("user", "id", $assessment->userid)) {
2071 error (" exercise_print_assessments_for_admin: unable to get user record");
2073 echo "<p><center><b>".get_string("assessmentby", "exercise", fullname($user))."</b></center></p>\n";
2074 exercise_print_assessment_form($exercise, $assessment);
2075 echo "<p align=\"right\"><a href=\"assessments.php?action=adminconfirmdelete&amp;id=$cm->id&amp;aid=$assessment->id\">".
2076 get_string("delete", "exercise")."</a></p><hr />\n";
2082 ///////////////////////////////////////////////////////////////////////////////////////////////
2083 function exercise_print_assignment_info($exercise) {
2085 if (! $course = get_record("course", "id", $exercise->course)) {
2086 error("Course is misconfigured");
2088 if (! $cm = get_coursemodule_from_instance("exercise", $exercise->id, $course->id)) {
2089 error("Course Module ID was incorrect");
2091 // print standard assignment heading
2092 $strdifference = format_time($exercise->deadline - time());
2093 if (($exercise->deadline - time()) < 0) {
2094 $strdifference = "<font color=\"red\">$strdifference</font>";
2096 $strduedate = userdate($exercise->deadline)." ($strdifference)";
2097 print_simple_box_start("center");
2098 print_heading(format_string($exercise->name), "center");
2099 print_simple_box_start("center");
2100 echo "<b>".get_string("duedate", "exercise")."</b>: $strduedate<br />";
2101 $maxgrade = $exercise->grade + $exercise->gradinggrade;
2102 echo "<b>".get_string("maximumgrade")."</b>: $maxgrade<br />";
2103 echo "<b>".get_string("handlingofmultiplesubmissions", "exercise")."</b>:";
2104 if ($exercise->usemaximum) {
2105 echo get_string("usemaximum", "exercise")."<br />\n";
2107 else {
2108 echo get_string("usemean", "exercise")."<br />\n";
2110 echo "<b>".get_string("detailsofassessment", "exercise")."</b>:
2111 <a href=\"assessments.php?id=$cm->id&amp;action=displaygradingform\">".
2112 get_string("specimenassessmentform", "exercise")."</a><br />";
2113 print_simple_box_end();
2114 print_simple_box_end();
2115 echo "<br />";
2119 ///////////////////////////////////////////////////////////////////////////////////////////////
2120 function exercise_print_difference($time) {
2121 if ($time < 0) {
2122 $timetext = get_string("late", "assignment", format_time($time));
2123 return " (<font color=\"red\">$timetext</font>)";
2124 } else {
2125 $timetext = get_string("early", "assignment", format_time($time));
2126 return " ($timetext)";
2131 ///////////////////////////////////////////////////////////////////////////////////////////////
2132 function exercise_print_feedback($course, $submission) {
2133 global $CFG, $RATING;
2135 if (! $teacher = get_record("user", "id", $submission->teacher)) {
2136 error("Weird exercise error");
2139 echo "\n<table border=\"0\" cellpadding=\"1\" cellspacing=\"1\" align=\"center\"><tr><td bgcolor=#888888>";
2140 echo "\n<table border=\"0\" cellpadding=\"3\" cellspacing=\"0\" valign=\"top\">";
2142 echo "\n<tr>";
2143 echo "\n<td rowspan=\"3\" width=\"35\" valign=\"top\">";
2144 print_user_picture($teacher->id, $course->id, $teacher->picture);
2145 echo "</td>";
2146 echo "<td nowrap=\"nowrap\" width=\"100%\">".fullname($teacher);
2147 echo "&nbsp;&nbsp;<font size=\"2\"><i>".userdate($submission->timemarked)."</i>";
2148 echo "</tr>";
2150 echo "\n<tr><td width=\"100%\">";
2152 echo "<p align=\"right\"><font size=-1><i>";
2153 if ($submission->grade) {
2154 echo get_string("grade").": $submission->grade";
2155 } else {
2156 echo get_string("nograde");
2158 echo "</i></font></p>";
2160 echo text_to_html($submission->assessorcomment);
2161 echo "</td></tr></table>";
2162 echo "</td></tr></table>";
2166 ///////////////////////////////////////////////////////////////////////////////////////////////
2167 function exercise_print_league_table($exercise) {
2168 // print an order table of (student) submissions in grade order, only print the student's best submission when
2169 // there are multiple submissions
2170 if (! $course = get_record("course", "id", $exercise->course)) {
2171 error("Print league table: Course is misconfigured");
2173 $groupid = get_current_group($course->id);
2174 $nentries = $exercise->showleaguetable;
2175 if ($nentries == 99) {
2176 $nentries = 999999; // a large number
2179 if ($exercise->anonymous and isstudent($course->id)) {
2180 $table->head = array (get_string("title", "exercise"), get_string("grade"));
2181 $table->align = array ("left", "center");
2182 $table->size = array ("*", "*");
2183 } else { // show names
2184 $table->head = array (get_string("title", "exercise"), get_string("name"), get_string("grade"));
2185 $table->align = array ("left", "left", "center");
2186 $table->size = array ("*", "*", "*");
2188 $table->cellpadding = 2;
2189 $table->cellspacing = 0;
2191 if ($submissions = exercise_get_student_submissions($exercise, "grade", $groupid)) {
2192 $n = 1;
2193 foreach ($submissions as $submission) {
2194 if (empty($done[$submission->userid])) {
2195 if ($submission->late) {
2196 continue;
2198 if (!$user = get_record("user", "id", $submission->userid)) {
2199 error("Print league table: user not found");
2201 if ($exercise->anonymous and isstudent($course->id)) {
2202 $table->data[] = array(exercise_print_submission_title($exercise, $submission),
2203 number_format($submission->grade * $exercise->grade / 100.0, 1));
2204 } else {
2205 $table->data[] = array(exercise_print_submission_title($exercise, $submission),
2206 fullname($user),
2207 number_format($submission->grade * $exercise->grade / 100.0, 1));
2209 $n++;
2210 if ($n > $nentries) {
2211 break;
2213 $done[$submission->userid] = 'ok';
2216 print_heading(get_string("leaguetable", "exercise"));
2217 print_table($table);
2222 ///////////////////////////////////////////////////////////////////////////////////////////////
2223 function exercise_print_submission_assessments($exercise, $submission) {
2224 // Returns a list of grades for this submission
2226 if (! $course = get_record("course", "id", $exercise->course)) {
2227 error("Course is misconfigured");
2229 if (! $cm = get_coursemodule_from_instance("exercise", $exercise->id, $course->id)) {
2230 error("Course Module ID was incorrect");
2233 $str = '';
2234 if ($assessments = exercise_get_assessments($submission)) {
2235 foreach ($assessments as $assessment) {
2236 if (isteacher($exercise->course, $assessment->userid)) {
2237 $str .= "[".number_format($assessment->grade * $exercise->grade / 100.0, 0)."] ";
2239 else { // assessment by student - shouldn't happen!
2240 $str .= "{".number_format($assessment->grade * $exercise->grade / 100.0, 0)."} ";
2244 if (!$str) {
2245 $str = "&nbsp;"; // be kind to Mozilla browsers!
2247 return $str;
2251 //////////////////////////////////////////////////////////////////////////////////////
2252 function exercise_print_tabbed_heading($tabs) {
2253 // Prints a tabbed heading where one of the tabs highlighted.
2254 // $tabs is an object with several properties.
2255 // $tabs->names is an array of tab names
2256 // $tabs->urls is an array of links
2257 // $tabs->align is an array of column alignments (defaults to "center")
2258 // $tabs->size is an array of column sizes
2259 // $tabs->wrap is an array of "nowrap"s or nothing
2260 // $tabs->highlight is an index (zero based) of "active" heading .
2261 // $tabs->width is an percentage of the page (defualts to 80%)
2262 // $tabs->cellpadding padding on each cell (defaults to 5)
2264 global $CFG;
2266 if (isset($tabs->names)) {
2267 foreach ($tabs->names as $key => $name) {
2268 if (!empty($tabs->urls[$key])) {
2269 $url =$tabs->urls[$key];
2270 if ($tabs->highlight == $key) {
2271 $tabcontents[$key] = "<b>$name</b>";
2272 } else {
2273 $tabcontents[$key] = "<a class= \"dimmed\" href=\"$url\"><b>$name</b></a>";
2275 } else {
2276 $tabcontents[$key] = "<b>$name</b>";
2281 if (empty($tabs->width)) {
2282 $tabs->width = "80%";
2285 if (empty($tabs->cellpadding)) {
2286 $tabs->cellpadding = "5";
2289 // print_simple_box_start("center", "$table->width", "#ffffff", 0);
2290 echo "<table width=\"$tabs->width\" border=\"0\" valign=\"top\" align=\"center\" ";
2291 echo " cellpadding=\"$tabs->cellpadding\" cellspacing=\"0\" class=\"generaltable\">\n";
2293 if (!empty($tabs->names)) {
2294 echo "<tr>";
2295 echo "<td class=\"generaltablecell\">".
2296 "<img width=\"10\" src=\"$CFG->wwwroot/pix/spacer.gif\" alt=\"\" /></td>\n";
2297 foreach ($tabcontents as $key => $tab) {
2298 if (isset($align[$key])) {
2299 $alignment = "align=\"$align[$key]\"";
2300 } else {
2301 $alignment = "align=\"center\"";
2303 if (isset($size[$key])) {
2304 $width = "width=\"$size[$key]\"";
2305 } else {
2306 $width = "";
2308 if (isset($wrap[$key])) {
2309 $wrapping = "no wrap";
2310 } else {
2311 $wrapping = "";
2313 if ($key == $tabs->highlight) {
2314 echo "<td valign=\"top\" class=\"generaltabselected\" $alignment $width $wrapping>$tab</td>\n";
2315 } else {
2316 echo "<td valign=\"top\" class=\"generaltab\" $alignment $width $wrapping>$tab</td>\n";
2318 echo "<td class=\"generaltablecell\">".
2319 "<img width=\"10\" src=\"$CFG->wwwroot/pix/spacer.gif\" alt=\"\" /></td>\n";
2321 echo "</tr>\n";
2322 } else {
2323 echo "<tr><td>No names specified</td></tr>\n";
2325 // bottom stripe
2326 $ncells = count($tabs->names)*2 +1;
2327 $height = 2;
2328 echo "<tr><td colspan=\"$ncells\">".
2329 "<img height=\"$height\" src=\"$CFG->wwwroot/pix/spacer.gif\" alt=\"\" /></td></tr>\n";
2330 echo "</table>\n";
2331 // print_simple_box_end();
2333 return true;
2337 ///////////////////////////////////////////////////////////////////////////////////////////////
2338 function exercise_print_teacher_assessment_form($exercise, $assessment, $submission, $returnto = '') {
2339 // prints an assessment form based on the student's assessment
2340 // if the teacher is re-assessing a submission they would use exercise_print_assessment_form()
2341 // (for teachers only)
2342 global $CFG, $USER, $EXERCISE_SCALES, $EXERCISE_EWEIGHTS;
2344 if (! $course = get_record("course", "id", $exercise->course)) {
2345 error("Course is misconfigured");
2347 if (! $cm = get_coursemodule_from_instance("exercise", $exercise->id, $course->id)) {
2348 error("Course Module ID was incorrect");
2351 $timenow = time();
2353 if(!$submissionowner = get_record("user", "id", $submission->userid)) {
2354 error("Print teacher assessment form: User record not found");
2357 echo "<center><table border=\"1\" width=\"30%\"><tr>
2358 <td align=\"center\">\n";
2359 if (!$teachersubmission = get_record("exercise_submissions", "id", $assessment->submissionid)) {
2360 error ("Print teacher assessment form: Submission record not found");
2362 echo exercise_print_submission_title($exercise, $teachersubmission);
2363 echo "</td></tr></table><br clear=\"all\" />\n";
2365 echo "<center><table border=\"1\" width=\"30%\"><tr>
2366 <td align=\"center\">\n";
2367 echo exercise_print_submission_title($exercise, $submission);
2368 echo "</td></tr></table></center><br clear=\"all\" />\n";
2371 <form id="assessmentform" method="post" action="assessments.php">
2372 <input type="hidden" name="id" value="<?php echo $cm->id ?>" />
2373 <input type="hidden" name="said" value="<?php echo $assessment->id ?>" />
2374 <input type="hidden" name="sid" value="<?php echo $submission->id ?>" />
2375 <input type="hidden" name="action" value="updateteacherassessment" />
2376 <input type="hidden" name="resubmit" value="0" />
2377 <input type="hidden" name="returnto" value="<?php echo $returnto ?>" />
2378 <?php
2380 // now print a normal assessment form based on the student's assessment for this submission
2381 // and allow the teacher to grade and add additional comments
2382 $studentassessment = $assessment;
2383 $allowchanges = true;
2385 print_heading_with_help(get_string("pleasemakeyourownassessment", "exercise",
2386 fullname($submissionowner)), "grading", "exercise");
2388 // is there an existing assessment for the submission
2389 if (!$assessment = exercise_get_submission_assessment($submission, $USER)) {
2390 // copy student's assessment with their comments for the teacher's assessment
2391 $assessment = exercise_copy_assessment($studentassessment, $submission, true);
2394 // only show the grade if grading strategy > 0 and the grade is positive
2395 if ($exercise->gradingstrategy and $assessment->grade >= 0) {
2396 echo "<center><b>".get_string("thegradeis", "exercise").": ".
2397 number_format($assessment->grade * $exercise->grade / 100.0, 2)." (".
2398 get_string("maximumgrade")." ".number_format($exercise->grade, 0).")</b></center><br clear=\"all\" />\n";
2401 echo "<center><table cellpadding=\"2\" border=\"1\">\n";
2402 echo "<tr valign=\"top\">\n";
2403 echo " <td colspan=\"2\"><center><b>".get_string("yourassessment", "exercise").
2404 "</b></center></td>\n";
2405 echo "</tr>\n";
2407 // get the assignment elements...
2408 if (!$elementsraw = get_records("exercise_elements", "exerciseid", $exercise->id, "elementno ASC")) {
2409 error("Teacher assessment form: Elements not found");
2411 foreach ($elementsraw as $element) {
2412 $elements[] = $element; // to renumber index 0,1,2...
2415 // ...and get any previous grades...
2416 if ($gradesraw = get_records_select("exercise_grades", "assessmentid = $assessment->id", "elementno")) {
2417 foreach ($gradesraw as $grade) {
2418 $grades[] = $grade; // to renumber index 0,1,2...
2422 // determine what sort of grading
2423 switch ($exercise->gradingstrategy) {
2424 case 0: // no grading
2425 // now print the form
2426 for ($i=0; $i < count($elements); $i++) {
2427 $iplus1 = $i+1;
2428 echo "<tr valign=\"top\">\n";
2429 echo " <td align=\"right\"><p><b>". get_string("element","exercise")." $iplus1:</b></p></td>\n";
2430 echo " <td>".text_to_html($elements[$i]->description);
2431 echo "</td></tr>\n";
2432 echo "<tr valign=\"top\">\n";
2433 echo " <td align=\"right\"><p><b>". get_string("feedback").":</b></p></td>\n";
2434 echo " <td>\n";
2435 if ($allowchanges) {
2436 echo " <textarea name=\"feedback[]\" rows=\"3\" cols=\"75\" wrap=\"virtual\">\n";
2437 if (isset($grades[$i]->feedback)) {
2438 echo $grades[$i]->feedback;
2440 echo "</textarea>\n";
2442 else {
2443 echo text_to_html($grades[$i]->feedback);
2445 echo " </td>\n";
2446 echo "</tr>\n";
2447 echo "<tr valign=\"top\">\n";
2448 echo " <td colspan=\"2\">&nbsp;</td>\n";
2449 echo "</tr>\n";
2451 break;
2453 case 1: // accumulative grading
2454 // now print the form
2455 for ($i=0; $i < count($elements); $i++) {
2456 $iplus1 = $i+1;
2457 echo "<tr valign=\"top\">\n";
2458 echo " <td align=\"right\"><p><b>". get_string("element","exercise")." $iplus1:</b></p></td>\n";
2459 echo " <td>".text_to_html($elements[$i]->description);
2460 echo "<p align=\"right\"><font size=\"1\">Weight: "
2461 .number_format($EXERCISE_EWEIGHTS[$elements[$i]->weight], 2)."</font>\n";
2462 echo "</td></tr>\n";
2463 echo "<tr valign=\"top\">\n";
2464 echo " <td align=\"right\"><p><b>". get_string("grade"). ":</b></p></td>\n";
2465 echo " <td valign=\"top\">\n";
2467 // get the appropriate scale
2468 $scalenumber=$elements[$i]->scale;
2469 $SCALE = (object)$EXERCISE_SCALES[$scalenumber];
2470 switch ($SCALE->type) {
2471 case 'radio' :
2472 // show selections highest first
2473 echo "<center><b>$SCALE->start</b>&nbsp;&nbsp;&nbsp;";
2474 for ($j = $SCALE->size - 1; $j >= 0 ; $j--) {
2475 $checked = false;
2476 if (isset($grades[$i]->grade)) {
2477 if ($j == $grades[$i]->grade) {
2478 $checked = true;
2481 else { // there's no previous grade so check the lowest option
2482 if ($j == 0) {
2483 $checked = true;
2486 if ($checked) {
2487 echo " <input type=\"RADIO\" name=\"grade[$i]\" value=\"$j\" checked=\"checked\" /> &nbsp;&nbsp;&nbsp;\n";
2489 else {
2490 echo " <input type=\"RADIO\" name=\"grade[$i]\" value=\"$j\" /> &nbsp;&nbsp;&nbsp;\n";
2493 echo "&nbsp;&nbsp;&nbsp;<b>$SCALE->end</b></center>\n";
2494 break;
2495 case 'selection' :
2496 unset($numbers);
2497 for ($j = $SCALE->size; $j >= 0; $j--) {
2498 $numbers[$j] = $j;
2500 if (isset($grades[$i]->grade)) {
2501 choose_from_menu($numbers, "grade[$i]", $grades[$i]->grade, "");
2503 else {
2504 choose_from_menu($numbers, "grade[$i]", 0, "");
2506 break;
2508 echo " </td>\n";
2509 echo "</tr>\n";
2511 echo "<tr valign=\"top\">\n";
2512 echo " <td align=\"right\"><p><b>". get_string("feedback").":</b></p></td>\n";
2513 echo " <td>\n";
2514 if ($allowchanges) {
2515 echo " <textarea name=\"feedback[]\" rows=\"3\" cols=\"75\" wrap=\"virtual\">\n";
2516 if (isset($grades[$i]->feedback)) {
2517 echo $grades[$i]->feedback;
2519 echo "</textarea>\n";
2521 else {
2522 echo text_to_html($grades[$i]->feedback);
2524 echo " </td>\n";
2525 echo "</tr>\n";
2526 echo "<tr valign=\"top\">\n";
2527 echo " <td colspan=\"2\">&nbsp;</td>\n";
2528 echo "</tr>\n";
2530 break;
2532 case 2: // error banded grading
2533 // now run through the elements
2534 $error = 0;
2535 for ($i=0; $i < count($elements) - 1; $i++) {
2536 $iplus1 = $i+1;
2537 echo "<tr valign=\"top\">\n";
2538 echo " <td align=\"right\"><p><b>". get_string("element","exercise")." $iplus1:</b></p></td>\n";
2539 echo " <td>".text_to_html($elements[$i]->description);
2540 echo "<p align=\"right\"><font size=\"1\">Weight: "
2541 .number_format($EXERCISE_EWEIGHTS[$elements[$i]->weight], 2)."</font>\n";
2542 echo "</td></tr>\n";
2543 echo "<tr valign=\"top\">\n";
2544 echo " <td align=\"right\"><p><b>". get_string("grade"). ":</b></p></td>\n";
2545 echo " <td valign=\"top\">\n";
2547 // get the appropriate scale - yes/no scale (0)
2548 $SCALE = (object) $EXERCISE_SCALES[0];
2549 switch ($SCALE->type) {
2550 case 'radio' :
2551 // show selections highest first
2552 echo "<center><b>$SCALE->start</b>&nbsp;&nbsp;&nbsp;";
2553 for ($j = $SCALE->size - 1; $j >= 0 ; $j--) {
2554 $checked = false;
2555 if (isset($grades[$i]->grade)) {
2556 if ($j == $grades[$i]->grade) {
2557 $checked = true;
2560 else { // there's no previous grade so check the lowest option
2561 if ($j == 0) {
2562 $checked = true;
2565 if ($checked) {
2566 echo " <input type=\"RADIO\" name=\"grade[$i]\" value=\"$j\" checked=\"checked\" /> &nbsp;&nbsp;&nbsp;\n";
2568 else {
2569 echo " <input type=\"RADIO\" name=\"grade[$i]\" value=\"$j\" /> &nbsp;&nbsp;&nbsp;\n";
2572 echo "&nbsp;&nbsp;&nbsp;<b>$SCALE->end</b></center>\n";
2573 break;
2574 case 'selection' :
2575 unset($numbers);
2576 for ($j = $SCALE->size; $j >= 0; $j--) {
2577 $numbers[$j] = $j;
2579 if (isset($grades[$i]->grade)) {
2580 choose_from_menu($numbers, "grade[$i]", $grades[$i]->grade, "");
2582 else {
2583 choose_from_menu($numbers, "grade[$i]", 0, "");
2585 break;
2588 echo " </td>\n";
2589 echo "</tr>\n";
2590 echo "<tr valign=\"top\">\n";
2591 echo " <td align=\"right\"><p><b>". get_string("feedback").":</b></p></td>\n";
2592 echo " <td>\n";
2593 if ($allowchanges) {
2594 echo " <textarea name=\"feedback[$i]\" rows=\"3\" cols=\"75\" wrap=\"virtual\">\n";
2595 if (isset($grades[$i]->feedback)) {
2596 echo $grades[$i]->feedback;
2598 echo "</textarea>\n";
2600 else {
2601 if (isset($grades[$i]->feedback)) {
2602 echo text_to_html($grades[$i]->feedback);
2605 echo "&nbsp;</td>\n";
2606 echo "</tr>\n";
2607 echo "<tr valign=\"top\">\n";
2608 echo " <td colspan=\"2\">&nbsp;</td>\n";
2609 echo "</tr>\n";
2610 if (empty($grades[$i]->grade)) {
2611 $error += $EXERCISE_EWEIGHTS[$elements[$i]->weight];
2614 // print the number of negative elements
2615 // echo "<tr><td>".get_string("numberofnegativeitems", "exercise")."</td><td>$negativecount</td></tr>\n";
2616 // echo "<tr valign=\"top\">\n";
2617 // echo " <td colspan=\"2\">&nbsp;</td>\n";
2618 echo "</table></center>\n";
2619 // now print the grade table
2620 echo "<p><center><b>".get_string("gradetable","exercise")."</b></center>\n";
2621 echo "<center><table cellpadding=\"5\" border=\"1\"><tr><td align=\"CENTER\">".
2622 get_string("numberofnegativeresponses", "exercise");
2623 echo "</td><td>". get_string("suggestedgrade", "exercise")."</td></tr>\n";
2624 for ($i=0; $i<=$exercise->nelements; $i++) {
2625 if ($i == intval($error + 0.5)) {
2626 echo "<tr><td align=\"CENTER\"><img src=\"$CFG->pixpath/t/right.gif\" alt=\"\" /> $i</td><td align=\"CENTER\">{$elements[$i]->maxscore}</td></tr>\n";
2628 else {
2629 echo "<tr><td align=\"CENTER\">$i</td><td align=\"CENTER\">{$elements[$i]->maxscore}</td></tr>\n";
2632 echo "</table></center>\n";
2633 echo "<p><center><table cellpadding=\"5\" border=\"1\"><tr><td align=\"right\"><b>".
2634 get_string("optionaladjustment", "exercise")."</b></td><td>\n";
2635 unset($numbers);
2636 for ($j = 20; $j >= -20; $j--) {
2637 $numbers[$j] = $j;
2639 if (isset($grades[$exercise->nelements]->grade)) {
2640 choose_from_menu($numbers, "grade[$exercise->nelements]", $grades[$exercise->nelements]->grade, "");
2642 else {
2643 choose_from_menu($numbers, "grade[$exercise->nelements]", 0, "");
2645 echo "</td></tr>\n";
2646 break;
2648 case 3: // criteria grading
2649 echo "<tr valign=\"top\">\n";
2650 echo " <td>&nbsp;</td>\n";
2651 echo " <td><b>". get_string("criterion","exercise")."</b></td>\n";
2652 echo " <td><b>".get_string("select")."</b></td>\n";
2653 echo " <td><b>".get_string("suggestedgrade", "exercise")."</b></td>\n";
2654 // find which criteria has been selected (saved in the zero element), if any
2655 if (isset($grades[0]->grade)) {
2656 $selection = $grades[0]->grade;
2658 else {
2659 $selection = 0;
2661 // now run through the elements
2662 for ($i=0; $i < count($elements); $i++) {
2663 $iplus1 = $i+1;
2664 echo "<tr valign=\"top\">\n";
2665 echo " <td>$iplus1</td><td>".text_to_html($elements[$i]->description)."</td>\n";
2666 if ($selection == $i) {
2667 echo " <td align=\"center\"><input type=\"RADIO\" name=\"grade[0]\" value=\"$i\" checked=\"checked\" /></td>\n";
2669 else {
2670 echo " <td align=\"center\"><input type=\"RADIO\" name=\"grade[0]\" value=\"$i\" /></td>\n";
2672 echo "<td align=\"center\">{$elements[$i]->maxscore}</td></tr>\n";
2674 echo "</table></center>\n";
2675 echo "<p><center><table cellpadding=\"5\" border=\"1\"><tr><td align=\"right\"><b>".
2676 get_string("optionaladjustment", "exercise")."</b></td><td>\n";
2677 unset($numbers);
2678 for ($j = 20; $j >= -20; $j--) {
2679 $numbers[$j] = $j;
2681 if (isset($grades[1]->grade)) {
2682 choose_from_menu($numbers, "grade[1]", $grades[1]->grade, "");
2684 else {
2685 choose_from_menu($numbers, "grade[1]", 0, "");
2687 echo "</td></tr>\n";
2688 break;
2690 case 4: // rubric grading
2691 // now run through the elements...
2692 for ($i=0; $i < count($elements); $i++) {
2693 $iplus1 = $i+1;
2694 echo "<tr valign=\"top\">\n";
2695 echo "<td align=\"right\"><b>".get_string("element", "exercise")." $iplus1:</b></td>\n";
2696 echo "<td>".text_to_html($elements[$i]->description).
2697 "<p align=\"right\"><font size=\"1\">Weight: "
2698 .number_format($EXERCISE_EWEIGHTS[$elements[$i]->weight], 2)."</font></td></tr>\n";
2699 echo "<tr valign=\"top\">\n";
2700 echo " <td align=\"center\"><b>".get_string("select")."</b></td>\n";
2701 echo " <td><b>". get_string("criterion","exercise")."</b></td></tr>\n";
2702 if (isset($grades[$i])) {
2703 $selection = $grades[$i]->grade;
2704 } else {
2705 $selection = 0;
2707 // ...and the rubrics
2708 if ($rubricsraw = get_records_select("exercise_rubrics", "exerciseid = $exercise->id AND
2709 elementno = $i", "rubricno ASC")) {
2710 unset($rubrics);
2711 foreach ($rubricsraw as $rubic) {
2712 $rubrics[] = $rubic; // to renumber index 0,1,2...
2714 for ($j=0; $j<5; $j++) {
2715 if (empty($rubrics[$j]->description)) {
2716 break; // out of inner for loop
2718 echo "<tr valign=\"top\">\n";
2719 if ($selection == $j) {
2720 echo " <td align=\"center\"><input type=\"RADIO\" name=\"grade[$i]\" value=\"$j\" checked=\"checked\" /></td>\n";
2721 } else {
2722 echo " <td align=\"center\"><input type=\"RADIO\" name=\"grade[$i]\" value=\"$j\" /></td>\n";
2724 echo "<td>".text_to_html($rubrics[$j]->description)."</td>\n";
2726 echo "<tr valign=\"top\">\n";
2727 echo " <td align=\"right\"><p><b>". get_string("feedback").":</b></p></td>\n";
2728 echo " <td>\n";
2729 if ($allowchanges) {
2730 echo " <textarea name=\"feedback[]\" rows=\"3\" cols=\"75\" wrap=\"virtual\">\n";
2731 if (isset($grades[$i]->feedback)) {
2732 echo $grades[$i]->feedback;
2734 echo "</textarea>\n";
2736 else {
2737 echo text_to_html($grades[$i]->feedback);
2739 echo " </td>\n";
2740 echo "</tr>\n";
2741 echo "<tr valign=\"top\">\n";
2742 echo " <td colspan=\"2\">&nbsp;</td>\n";
2743 echo "</tr>\n";
2746 break;
2747 } // end of outer switch
2749 // now get the general comment (present in all types)
2750 echo "<tr valign=\"top\">\n";
2751 switch ($exercise->gradingstrategy) {
2752 case 0:
2753 case 1:
2754 case 4 : // no grading, accumulative and rubic
2755 echo " <td align=\"right\"><p><b>". get_string("generalcomment", "exercise").":</b></p></td>\n";
2756 break;
2757 default :
2758 echo " <td align=\"right\"><p><b>". get_string("reasonforadjustment", "exercise").":</b></p></td>\n";
2760 echo " <td>\n";
2761 if ($allowchanges) {
2762 echo " <textarea name=\"generalcomment\" rows=\"5\" cols=\"75\" wrap=\"virtual\">\n";
2763 if (isset($assessment->generalcomment)) {
2764 echo $assessment->generalcomment;
2766 echo "</textarea>\n";
2768 else {
2769 if ($assessment) {
2770 if (isset($assessment->generalcomment)) {
2771 echo text_to_html($assessment->generalcomment);
2774 else {
2775 print_string("yourfeedbackgoeshere", "exercise");
2778 echo "&nbsp;</td>\n";
2779 echo "</tr>\n";
2780 echo "<tr valign=\"top\">\n";
2781 echo " <td colspan=\"2\">&nbsp;</td>\n";
2782 echo "</tr>\n";
2784 // ...and close the table and show two buttons...to resubmit or not to resubmit
2785 echo "</table>\n";
2786 echo "<br /><input type=\"button\" value=\"".get_string("studentnotallowed", "exercise", $course->student)."\"
2787 onclick=\"getElementById('assessmentform').submit();\" />\n";
2788 echo "<input type=\"button\" value=\"".get_string("studentallowedtoresubmit", "exercise", $course->student)."\"
2789 onclick=\"getElementById('assessmentform').resubmit.value='1';getElementById('assessmentform').submit();\" />\n";
2790 echo "</center></form>\n";
2794 ///////////////////////////////////////////////////////////////////////////////////////////////
2795 function exercise_print_teacher_table($course) {
2796 // print how many assessments each teacher has done in each exercise
2798 if (! $exercises = get_all_instances_in_course("exercise", $course)) {
2799 notice("There are no exercises", "../../course/view.php?id=$course->id");
2800 die;
2803 $timenow = time();
2805 $table->head[] = '';
2806 $table->align[] = 'left';
2807 $table->size[] = '*';
2808 $table->head[] = get_string("total");
2809 $table->align[] = "center";
2810 $table->size[] = "*";
2811 foreach ($exercises as $exercise) {
2812 $table->head[] = format_string($exercise->name);
2813 $table->align[] = "center";
2814 $table->size[] = "*";
2816 $table->cellpadding = 2;
2817 $table->cellspacing = 0;
2819 if (!$teachers = get_course_teachers($course->id, "u.firstname, u.lastname")) {
2820 error("No teachers on this course!");
2822 for ($j = 0; $j < count($exercises); $j++) {
2823 $grand[$j] = 0;
2825 $grandtotal = 0;
2826 foreach ($teachers as $teacher) {
2827 unset($n);
2828 $total = 0;
2829 $j = 0;
2830 foreach ($exercises as $exercise) {
2831 $i = exercise_count_assessments_by_teacher($exercise, $teacher);
2832 $n[] = $i;
2833 $total += $i;
2834 $grand[$j] += $i;
2835 $j++;
2837 $grandtotal += $total;
2838 $table->data[] = array_merge(array(fullname($teacher)), array($total), $n);
2840 $table->data[] = array_merge(array(get_string("total")), array($grandtotal), $grand);
2841 print_heading(get_string("teacherassessmenttable", "exercise", $course->teacher));
2842 print_table($table);
2846 ///////////////////////////////////////////////////////////////////////////////////////////////
2847 function exercise_print_time_to_deadline($time) {
2848 if ($time < 0) {
2849 $timetext = get_string("afterdeadline", "exercise", format_time($time));
2850 return " (<font color=\"red\">$timetext</font>)";
2851 } else {
2852 $timetext = get_string("beforedeadline", "exercise", format_time($time));
2853 return " ($timetext)";
2858 ///////////////////////////////////////////////////////////////////////////////////////////////
2859 function exercise_print_upload_form($exercise) {
2861 global $CFG;
2863 if (! $course = get_record("course", "id", $exercise->course)) {
2864 error("Course is misconfigured");
2866 if (! $cm = get_coursemodule_from_instance("exercise", $exercise->id, $course->id)) {
2867 error("Course Module ID was incorrect");
2870 echo "<div align=\"center\">";
2871 echo "<form enctype=\"multipart/form-data\" method=\"post\" action=\"upload.php\">";
2872 echo " <input type=\"hidden\" name=\"id\" value=\"$cm->id\" />";
2873 require_once($CFG->dirroot.'/lib/uploadlib.php');
2874 upload_print_form_fragment(1,array('newfile'),null,true,array('title'),$course->maxbytes,$exercise->maxbytes,false);
2875 echo " <input type=\"submit\" name=\"save\" value=\"".get_string("uploadthisfile")."\" />";
2876 echo " (".get_string("maximumupload").": ".display_size($exercise->maxbytes).")\n";
2877 echo "</form>";
2878 echo "</div>";
2882 ///////////////////////////////////////////////////////////////////////////////////////////////
2883 function exercise_print_user_assessments($exercise, $user) {
2884 // Returns the number of assessments and a hyperlinked list of grading grades for the assessments made by this user
2886 if ($assessments = exercise_get_user_assessments($exercise, $user)) {
2887 $n = count($assessments);
2888 $str = "$n (";
2889 foreach ($assessments as $assessment) {
2890 if ($assessment->timegraded) {
2891 $gradingscaled = round($assessment->gradinggrade * $exercise->gradinggrade / 100.0);
2892 $str .= "<a href=\"assessments.php?action=viewassessment&amp;a=$exercise->id&amp;aid=$assessment->id\">";
2893 $str .= "$gradingscaled</a> ";
2895 else {
2896 $str .= "<a href=\"assessments.php?action=viewassessment&amp;a=$exercise->id&amp;aid=$assessment->id\">";
2897 $str .= "-</a> ";
2900 $str .= ")";
2902 else {
2903 $str ="0";
2905 return $str;
2909 ///////////////////////////////////////////////////////////////////////////////////////////////
2910 function exercise_test_for_resubmission($exercise, $user) {
2911 // see if any of the user's submissions have the resubmit flag set
2912 $result = false;
2913 if ($submissions = exercise_get_user_submissions($exercise, $user)) {
2914 foreach ($submissions as $submission) {
2915 if ($submission->resubmit) {
2916 $result =true;
2917 break;
2921 return $result;
2925 ///////////////////////////////////////////////////////////////////////////////////////////////
2926 function exercise_test_user_assessments($exercise, $user) {
2927 // see if user has assessed one of teacher's exercises/submissions...
2928 global $CFG;
2930 $result = false;
2931 $timenow =time();
2932 if ($submissions = exercise_get_teacher_submissions($exercise)) {
2933 foreach ($submissions as $submission) {
2934 if ($assessment = exercise_get_submission_assessment($submission, $user)) {
2935 // ...the date stamp on the assessment should be in the past
2936 if ($assessment->timecreated < $timenow) {
2937 $result = true;
2938 break;
2943 return $result;