]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-8002 - Don't show overall feedback for incomplete quiz attempts.
authortjhunt <tjhunt>
Fri, 22 Dec 2006 12:52:13 +0000 (12:52 +0000)
committertjhunt <tjhunt>
Fri, 22 Dec 2006 12:52:13 +0000 (12:52 +0000)
Also, cleanup of mod/quiz/index.php

lang/en_utf8/quiz.php
mod/quiz/index.php
mod/quiz/locallib.php
mod/quiz/review.php
mod/quiz/view.php

index 305f3b8c3264d0c797459772cadbd7b0fef9e5eb..f80dcdc2f613e7463996a3b66f87672a33fa2615 100644 (file)
@@ -223,6 +223,7 @@ $string['gradeboundary'] = 'Grade boundary';
 $string['gradeessays'] = 'Grade Essays';
 $string['gradehighest'] = 'Highest grade';
 $string['grademethod'] = 'Grading method';
+$string['gradesofar'] = '$a->method: $a->mygrade / $a->quizgrade.';
 $string['gradingdetails'] = 'Marks for this submission: $a->raw/$a->max.';
 $string['gradingdetailsadjustment'] = 'With previous penalties this gives <strong>$a->cur/$a->max</strong>.';
 $string['gradingdetailspenalty'] = 'This submission attracted a penalty of $a.';
@@ -542,7 +543,7 @@ $string['wronguse'] = 'You can not use this page like that';
 $string['xhtml'] = 'XHTML Format';
 $string['xml'] = 'Moodle XML format';
 $string['xmltypeunsupported'] = 'Question type $a is not supported by xml import';
-$string['yourfinalgradeis'] = 'Your final grade for this quiz is $a';
+$string['yourfinalgradeis'] = 'Your final grade for this quiz is $a.';
 $string['zerosignificantfiguresnotallowed'] = 'The correct answer cannot have zero significant figures!';
 
 ?>
index a956e4ec80fb3ed895befbe14b25e7f0a9ece66b..b61f655b421414dc61f224e6e366d8b1d6add1b2 100644 (file)
 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
 * @package quiz
 */
-
     require_once("../../config.php");
     require_once("locallib.php");
 
     $id = required_param('id', PARAM_INT);
-
-    if (! $course = get_record("course", "id", $id)) {
+    if (!$course = get_record("course", "id", $id)) {
         error("Course ID is incorrect");
     }
-
+    $coursecontext = get_context_instance(CONTEXT_COURSE, $id);
     require_login($course->id);
-
     add_to_log($course->id, "quiz", "view all", "index.php?id=$course->id", "");
 
-
 // Print the header
-
     $strquizzes = get_string("modulenameplural", "quiz");
-    $streditquestions = has_capability('moodle/question:manage', get_context_instance(CONTEXT_COURSE, $course->id))
-                        ? "<form target=\"_parent\" method=\"get\" "
-                           ." action=\"$CFG->wwwroot/question/edit.php\">"
-                           ."<input type=\"hidden\" name=\"courseid\" "
-                           ." value=\"$course->id\" />"
-                           ."<input type=\"submit\" "
-                           ." value=\"".get_string("editquestions", "quiz")."\" /></form>"
-
-                        : "";
-    $strquiz  = get_string("modulename", "quiz");
-
-    print_header_simple("$strquizzes", "", "$strquizzes",
-                 "", "", true, $streditquestions, navmenu($course));
+    $streditquestions = '';
+    if (has_capability('moodle/question:manage', $coursecontext)) {
+        $streditquestions =
+                "<form target=\"_parent\" method=\"get\" action=\"$CFG->wwwroot/question/edit.php\">
+                   <input type=\"hidden\" name=\"courseid\" value=\"$course->id\" />
+                   <input type=\"submit\" value=\"".get_string("editquestions", "quiz")."\" />
+                </form>";
+    }
+    print_header_simple($strquizzes, '', $strquizzes,
+                 '', '', true, $streditquestions, navmenu($course));
 
 // Get all the appropriate data
-
-    if (! $quizzes = get_all_instances_in_course("quiz", $course)) {
+    if (!$quizzes = get_all_instances_in_course("quiz", $course)) {
         notice("There are no quizzes", "../../course/view.php?id=$course->id");
         die;
     }
 
-// Print the list of instances (your module will probably extend this)
-
-    $timenow = time();
-    $strname  = get_string("name");
-    $strweek  = get_string("week");
-    $strtopic  = get_string("topic");
-    $strbestgrade  = get_string("bestgrade", "quiz");
-    $strquizcloses = get_string("quizcloses", "quiz");
-    $strattempts = get_string("attempts", "quiz");
-    $strusers  = $course->students;
-
-    $context = get_context_instance(CONTEXT_COURSE, $id);
-    if (has_capability('mod/quiz:viewreports', $context)) {
-        $gradecol = $strattempts;
-    } else {
-        $gradecol = $strbestgrade;
-    }
-
+// Configure table for displaying the list of instances.
+    $headings = array(get_string('name'), get_string('quizcloses', 'quiz'));
+    $align = array('left', 'left');
+    $colsize = array('', '');
     if ($course->format == "weeks") {
-        $table->head  = array ($strweek, $strname, $strquizcloses, $gradecol);
-        $table->align = array ("center", "left", "left", "left");
-        $table->size = array (10, "", "", "");
+        array_unshift($headings, get_string('week'));
+        array_unshift($align, 'center');
+        array_unshift($colsize, 10);
     } else if ($course->format == "topics") {
-        $table->head  = array ($strtopic, $strname, $strquizcloses, $gradecol);
-        $table->align = array ("center", "left", "left", "left");
-        $table->size = array (10, "", "", "");
-    } else {
-        $table->head  = array ($strname, $strquizcloses, $gradecol);
-        $table->align = array ("left", "left", "left");
-        $table->size = array ("", "", "");
+        array_unshift($headings, get_string('topic'));
+        array_unshift($align, 'center');
+        array_unshift($colsize, 10);
     }
 
-    $currentsection = "";
+    if (has_capability('mod/quiz:viewreports', $coursecontext)) {
+        array_push($headings, get_string('attempts', 'quiz'));
+        array_push($align, 'left');
+        array_push($colsize, '');
+        $showing = 'stats';
+    } else if (has_capability('mod/quiz:attempt', $coursecontext)) {
+        array_push($headings, get_string('bestgrade', 'quiz'), get_string('feedback', 'quiz'));
+        array_push($align, 'left', 'left');
+        array_push($colsize, '', '');
+        $showing = 'scores';
+    }
 
+    $table->head = $headings;
+    $table->align = $align;
+    $table->size = $colsize;
+
+// Poplate the table with the list of instances.
+    $currentsection = '';
     foreach ($quizzes as $quiz) {
-      
+
         $cm = get_coursemodule_from_instance('quiz', $quiz->id);
         $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-        
-        if (!$quiz->visible) {
-            //Show dimmed if the mod is hidden
-            $link = "<a class=\"dimmed\" href=\"view.php?id=$quiz->coursemodule\">".format_string($quiz->name,true)."</a>";
-        } else {
-            //Show normal if the mod is visible
-            $link = "<a href=\"view.php?id=$quiz->coursemodule\">".format_string($quiz->name,true)."</a>";
-        }
-
-        $bestgrade = quiz_get_best_grade($quiz, $USER->id);
+        $data = array();
 
-        $printsection = "";
-        if ($quiz->section !== $currentsection) {
-            if ($quiz->section) {
-                $printsection = $quiz->section;
-            }
-            if ($currentsection !== "") {
-                $table->data[] = 'hr';
+        // Section number if necessary.
+        $strsection = '';
+        if ($course->format == "weeks" or $course->format == "topics") {
+            if ($quiz->section !== $currentsection) {
+                if ($quiz->section) {
+                    $strsection = $quiz->section;
+                }
+                if ($currentsection !== "") {
+                    $table->data[] = 'hr';
+                }
+                $currentsection = $quiz->section;
             }
-            $currentsection = $quiz->section;
         }
+        $data[] = $strsection;
 
-        $closequiz = $quiz->timeclose ? userdate($quiz->timeclose) : '';
+        // Link to the instance.
+        $class = '';
+        if (!$quiz->visible) {
+            $class = ' class="dimmed"';
+        }
+        $data[] = "<a$class href=\"view.php?id=$quiz->coursemodule\">" . format_string($quiz->name, true) . '</a>';
+
+        // Close date.
+        if ($quiz->timeclose) {
+            $data[] = userdate($quiz->timeclose);
+        } else {
+            $data[] = '';
+        }
 
-        $gradecol = '';
-        $feedbackcol = '';
+        if ($showing == 'stats') {
 
-        if (has_capability('mod/quiz:viewreports', $context)) {
+            // Number of students who have attempted this quiz.
             if ($a->attemptnum = count_records('quiz_attempts', 'quiz', $quiz->id, 'preview', 0)) {
-                $a->studentnum = count_records_select('quiz_attempts', "quiz = '$quiz->id' AND preview = '0'", 'COUNT(DISTINCT userid)');
+                $a->studentnum = count_records_select('quiz_attempts',
+                        "quiz = '$quiz->id' AND preview = '0'", 'COUNT(DISTINCT userid)');
                 $a->studentstring  = $course->students;
-                $gradecol = "<a href=\"report.php?mode=overview&amp;q=$quiz->id\">".get_string('numattempts', 'quiz', $a).'</a>';
+                $data[] = "<a href=\"report.php?mode=overview&amp;q=$quiz->id\">" .
+                        get_string('numattempts', 'quiz', $a) . '</a>';
             }
-        } else {
-            // If student has no grade for this quiz, 
-            // or the quiz has no grade, display nothing in grade col
-            if ($bestgrade !== NULL && $quiz->grade != 0) {
-                //If all quiz's attempts have visible results, show bestgrade
-                if (all_attempt_results_visible($quiz, $USER)) {
-                    $gradecol = "$bestgrade / $quiz->grade";
-                    $feedbackcol = quiz_feedback_for_grade($bestgrade, $quiz->id);
+        } else if ($showing = 'scores') {
+
+            // Grade and feedback.
+            $bestgrade = quiz_get_best_grade($quiz, $USER->id);
+            $attempts = quiz_get_user_attempts($quiz->id, $USER->id, 'all');
+            list($someoptions, $alloptions) = quiz_get_combined_reviewoptions($quiz, $attempts, $context);
+
+            $grade = '';
+            $feedback = '';
+            if ($quiz->grade && !is_null($bestgrade)) {
+                if ($alloptions->scores) {
+                    $grade = "$bestgrade / $quiz->grade";
+                }
+                if ($alloptions->overallfeedback) {
+                    $feedback = quiz_feedback_for_grade($bestgrade, $quiz->id);
                 }
             }
+            $data[] = $grade;
+            $data[] = $feedback;
         }
 
-        if ($course->format == "weeks" or $course->format == "topics") {
-            $table->data[] = array ($printsection, $link, $closequiz, $gradecol, $feedbackcol);
-        } else {
-            $table->data[] = array ($link, $closequiz, $gradecol, $feedbackcol);
-        }
-    }
+        $table->data[] = $data;
+    } // End of loop over quiz instances.
 
+// Display the table.
     echo '<br />';
-
     print_table($table);
 
 // Finish the page
-
     print_footer($course);
-
 ?>
index ea1e09660306a173faf7770f5471e7618096c5f9..c474a700bb69b9abf4e5bcbe1b887b0ddb58d65f 100644 (file)
@@ -81,25 +81,37 @@ function quiz_create_attempt($quiz, $attemptnumber) {
 /**
  * Returns an unfinished attempt (if there is one) for the given
  * user on the given quiz. This function does not return preview attempts.
- * 
+ *
  * @param integer $quizid the id of the quiz.
  * @param integer $userid the id of the user.
- * 
- * @return mixed the unfinished attempt if there is one, false if not. 
+ *
+ * @return mixed the unfinished attempt if there is one, false if not.
  */
 function quiz_get_user_attempt_unfinished($quizid, $userid) {
-    return get_record_select("quiz_attempts", "quiz = $quizid AND userid = $userid AND timefinish = 0 AND preview = 0");
+    $attempts = quiz_get_user_attempts($quizid, $userid, 'unfinished');
+    if ($attempts) {
+        return array_shift($attempts);
+    } else {
+        return false;
+    }
 }
 
 /**
  * @param integer $quizid the quiz id.
  * @param integer $userid the userid.
- * @return an array of all the ueser's attempts at this quiz. Returns an empty array if there are none.
+ * @param string $status 'all', 'finished' or 'unfinished' to control
+ * @return an array of all the user's attempts at this quiz. Returns an empty array if there are none.
  */
-function quiz_get_user_attempts($quizid, $userid) {
-    if ($attempts = get_records_select("quiz_attempts", "quiz = '$quizid' AND userid = '$userid' AND timefinish > 0",
-            "attempt ASC")) {
-        return $attempts;                        
+function quiz_get_user_attempts($quizid, $userid, $status = 'finished') {
+    $status_condition = array(
+        'all' => '',
+        'finished' => ' AND timefinish > 0',
+        'unfinished' => ' AND timefinish = 0'
+    );
+    if ($attempts = get_records_select('quiz_attempts',
+            "quiz = '$quizid' AND userid = '$userid' AND preview = 0" . $status_condition[$status],
+            'attempt ASC')) {
+        return $attempts;
     } else {
         return array();
     }
@@ -267,7 +279,7 @@ function quiz_get_all_question_grades($quiz) {
 
 /**
  * Get the best current grade for a particular user in a quiz.
- * 
+ *
  * @param object $quiz the quiz object.
  * @param integer $userid the id of the user.
  * @return float the user's current grade for this quiz.
@@ -286,7 +298,7 @@ function quiz_get_best_grade($quiz, $userid) {
 /**
  * Convert the raw grade stored in $attempt into a grade out of the maximum
  * grade for this quiz.
- * 
+ *
  * @param float $rawgrade the unadjusted grade, fof example $attempt->sumgrades
  * @param object $quiz the quiz object. Only the fields grade, sumgrades and decimalpoints are used.
  * @return float the rescaled grade.
@@ -302,7 +314,7 @@ function quiz_rescale_grade($rawgrade, $quiz) {
 /**
  * Get the feedback text that should be show to a student who
  * got this grade on this quiz.
- * 
+ *
  * @param float $grade a grade on this quiz.
  * @param integer $quizid the id of the quiz object.
  * @return string the comment that corresponds to this grade (empty string if there is not one.
@@ -314,7 +326,7 @@ function quiz_feedback_for_grade($grade, $quizid) {
     if (empty($feedback)) {
         $feedback = '';
     }
-    
+
     return $feedback;
 }
 
@@ -332,10 +344,10 @@ function quiz_has_feedback($quizid) {
 }
 
 /**
- * The quiz grade is the score that student's results are marked out of. When it 
+ * The quiz grade is the score that student's results are marked out of. When it
  * changes, the corresponding data in quiz_grades and quiz_feedback needs to be
  * rescaled.
- * 
+ *
  * @param float $newgrade the new maximum grade for the quiz.
  * @param object $quiz the quiz we are updating. Passed by reference so its grade field can be updated too.
  * @return boolean indicating success or failure.
@@ -349,14 +361,14 @@ function quiz_set_grade($newgrade, &$quiz) {
 
     // Use a transaction, so that on those databases that support it, this is safer.
     begin_sql();
-    
+
     // Update the quiz table.
     $success = set_field('quiz', 'grade', $newgrade, 'id', $quiz->instance);
-    
+
     // Rescaling the other data is only possible if the old grade was non-zero.
     if ($quiz->grade > 1e-7) {
         global $CFG;
-    
+
         $factor = $newgrade/$quiz->grade;
         $quiz->grade = $newgrade;
 
@@ -375,7 +387,7 @@ function quiz_set_grade($newgrade, &$quiz) {
                 WHERE quizid = $quiz->id
         ", false);
     }
-    
+
     if ($success) {
         return commit_sql();
     } else {
@@ -407,7 +419,7 @@ function quiz_save_best_grade($quiz, $userid = null) {
     // Calculate the best grade
     $bestgrade = quiz_calculate_best_grade($quiz, $attempts);
     $bestgrade = quiz_rescale_grade($bestgrade, $quiz);
-    
+
     // Save the best grade in the database
     if ($grade = get_record('quiz_grades', 'quiz', $quiz->id, 'userid', $userid)) {
         $grade->grade = $bestgrade;
@@ -609,7 +621,7 @@ function quiz_get_question_review($quiz, $question) {
  */
 function quiz_get_renderoptions($reviewoptions, $state) {
     $options = new stdClass;
-    
+
     // Show the question in readonly (review) mode if the question is in
     // the closed state
     $options->readonly = question_state_is_closed($state);
@@ -626,6 +638,9 @@ function quiz_get_renderoptions($reviewoptions, $state) {
     // Show general feedback if the question has been graded and the quiz allows it.
     $options->generalfeedback = question_state_is_graded($state) && ($reviewoptions & QUIZ_REVIEW_GENERALFEEDBACK & QUIZ_REVIEW_IMMEDIATELY);
 
+    // Show overallfeedback once the attempt is over.
+    $options->overallfeedback = false;
+
     // Always show responses and scores
     $options->responses = true;
     $options->scores = true;
@@ -636,12 +651,12 @@ function quiz_get_renderoptions($reviewoptions, $state) {
 
 /**
  * Determine review options
- * 
+ *
  * @param object $quiz the quiz instance.
  * @param object $attempt the attempt in question.
  * @param $context the roles and permissions context,
  *          normally the context for the quiz module instance.
- * 
+ *
  * @return object an object with boolean fields responses, scores, feedback,
  *          correct_responses, solutions and general feedback
  */
@@ -661,7 +676,8 @@ function quiz_get_reviewoptions($quiz, $attempt, $context=null) {
         $options->correct_responses = true;
         $options->solutions = false;
         $options->generalfeedback = true;
-        
+        $options->overallfeedback = true;
+
         // Show a link to the comment box only for closed attempts
         if ($attempt->timefinish) {
             $options->questioncommentlink = '/mod/quiz/comment.php';
@@ -680,36 +696,40 @@ function quiz_get_reviewoptions($quiz, $attempt, $context=null) {
         $options->correct_responses = ($quiz->review & $quiz_state_mask & QUIZ_REVIEW_ANSWERS) ? 1 : 0;
         $options->solutions = ($quiz->review & $quiz_state_mask & QUIZ_REVIEW_SOLUTIONS) ? 1 : 0;
         $options->generalfeedback = ($quiz->review & $quiz_state_mask & QUIZ_REVIEW_GENERALFEEDBACK) ? 1 : 0;
+        $options->overallfeedback = $attempt->timefinish && ($quiz->review & $quiz_state_mask & QUIZ_REVIEW_FEEDBACK);
     }
-    
+
     return $options;
 }
-////////////////////////////////////////////////////////////////////////////////
+
 /**
-* Return boolean indicating if the quiz has attempts with hidden grades
-*
-* Selects all attempts matching specified quiz & user, and examines each to
-* check they all have visible results.
-* @return boolean        If the quiz has attempts without visible results
-* @param object $quiz    The quiz being examined
-* @param object $user    The user concerned
-*/
-function all_attempt_results_visible($quiz, $user) {
-    global $CFG;
-    $sql = 'SELECT timefinish, preview FROM '.$CFG->prefix.'quiz_attempts qa'.
-        ' WHERE qa.quiz='.$quiz->id.' AND qa.userid='.$user->id.
-        ' ORDER BY id DESC';
-    if ($attempts = get_records_sql($sql)) {
-        foreach ($attempts as $attempt) {            
-            $attemptoptions = quiz_get_reviewoptions($quiz, $attempt);
-            //if any attempt has scores option not set, not all attempt results are
-            //visible
-            if (!$attemptoptions->scores) {
-                return false;
-            }
-        }
+ * Combines the review options from a number of different quiz attempts.
+ * Returns an array of two ojects, so he suggested way of calling this
+ * funciton is:
+ * list($someoptions, $alloptions) = quiz_get_combined_reviewoptions(...)
+ *
+ * @param object $quiz the quiz instance.
+ * @param array $attempts an array of attempt objects.
+ * @param $context the roles and permissions context,
+ *          normally the context for the quiz module instance.
+ *
+ * @return array of two options objects, one showing which options are true for
+ *          at least one of the attempts, the other showing which options are true
+ *          for all attempts.
+ */
+function quiz_get_combined_reviewoptions($quiz, $attempts, $context=null) {
+    $fields = array('readonly', 'scores', 'feedback', 'correct_responses', 'solutions', 'generalfeedback', 'overallfeedback');
+    $someoptions = new stdClass;
+    $alloptions = new stdClass;
+    foreach ($fields as $field) {
+        $someoptions->$field = false;
+        $alloptions->$field = true;
     }
-    return true;
+    foreach ($attempts as $attempt) {
+        $attemptoptions = quiz_get_reviewoptions($quiz, $attempt, $context);
+        $someoptions->$field = $someoptions->$field || $attemptoptions->$field;
+        $alloptions->$field = $someoptions->$field && $attemptoptions->$field;
+    }
+    return array($someoptions, $alloptions);
 }
-
 ?>
index 9230a361163b80b99d0e7276e38f09c594738df0..c27842eaec97205209097e8663822261002c6d14 100644 (file)
@@ -30,7 +30,7 @@
     if (! $cm = get_coursemodule_from_instance("quiz", $quiz->id, $course->id)) {
         error("The course module for the quiz with id $quiz->id is missing");
     }
-    
+
     $grade = quiz_rescale_grade($attempt->sumgrades, $quiz);
     $feedback = quiz_feedback_for_grade($grade, $attempt->quiz);
 
                 $result->sumgrades = "0";
                 $result->grade = "0.0";
             }
-            
+
             $a = new stdClass;
             $percentage = round(($attempt->sumgrades/$quiz->sumgrades)*100, 0);
             $a->grade = $grade;
             $table->data[] = array("$strgrade:", get_string('outof', 'quiz', $a));
         }
     }
-    if ($options->feedback && $feedback) {
+    if ($options->overallfeedback && $feedback) {
         $table->data[] = array(get_string('feedback', 'quiz'), $feedback);
     }
     if ($isteacher and $attempt->userid == $USER->id) {
index 21b5c3b99e6abe9e883a1639835f26a9db8691fe..61871d14eb730dffe5e69c887152e1bd8e4f1ecb 100644 (file)
@@ -78,7 +78,7 @@
     $currenttab = 'info';
     include('tabs.php');
 
-    // Print quiz name 
+    // Print quiz name
 
     print_heading(format_string($quiz->name));
 
         if ($attempts) {
 
             // Work out which columns we need, taking account what data is available in each attempt.
-            $gradecolumn = 0;
-            $overallstats = 1;
-            foreach ($attempts as $attempt) {
-                $attemptoptions = quiz_get_reviewoptions($quiz, $attempt, $context);
-                if ($attemptoptions->scores) {
-                    $gradecolumn = 1;
-                } else {
-                    $overallstats = 0;
-                }
-            }
-            $gradecolumn = $gradecolumn && $quiz->grade && $quiz->sumgrades;
-            $markcolumn = $gradecolumn && ($quiz->grade <> $quiz->sumgrades);
+            list($someoptions, $alloptions) = quiz_get_combined_reviewoptions($quiz, $attempts, $context);
+
+            $gradecolumn = $someoptions->scores && $quiz->grade && $quiz->sumgrades;
+            $markcolumn = $gradecolumn && ($quiz->grade != $quiz->sumgrades);
+            $overallstats = $alloptions->scores;
+
             $feedbackcolumn = quiz_has_feedback($quiz->id);
+            $overallfeedback = $feedbackcolumn && $alloptions->overallfeedback;
 
             // prepare table header
             $table->head = array($strattempt, $strtimecompleted);
                 }
 
                 if ($feedbackcolumn) {
-                    if ($attemptoptions->feedback) {
+                    if ($attemptoptions->overallfeedback) {
                         $row[] = quiz_feedback_for_grade($attemptgrade, $quiz->id);
                     } else {
                         $row[] = '';
             print_heading(get_string("nomoreattempts", "quiz"));
         }
 
-        if ($numattempts && $quiz->sumgrades) {
-            if (!is_null($mygrade)) {
+        if ($numattempts && $quiz->sumgrades && !is_null($mygrade)) {
+            if ($overallstats) {
                 if ($available && $moreattempts) {
-                    $strbestgrade = $QUIZ_GRADE_METHOD[$quiz->grademethod];
-                    $grademessage = "$strbestgrade: $mygrade / $quiz->grade.";
+                    $a = new stdClass;
+                    $a->method = $QUIZ_GRADE_METHOD[$quiz->grademethod];
+                    $a->mygrade = $mygrade;
+                    $a->quizgrade = $quiz->grade;
+                    print_heading(get_string('gradesofar', 'quiz', $a));
                 } else {
-                    $grademessage = get_string("yourfinalgradeis", "quiz", "$mygrade / $quiz->grade");
-                }
-
-                if ($overallstats) {
-                    print_heading($grademessage);
-                }
-
-                if ($feedbackcolumn) {
-                    echo '<p align="center">', quiz_feedback_for_grade($mygrade, $quiz->id), '</p>';
+                    print_heading(get_string('yourfinalgradeis', 'quiz', "$mygrade / $quiz->grade"));
                 }
             }
 
-            if (!($moreattempts && $available)) {
-                print_continue($CFG->wwwroot . '/course/view.php?id=' . $course->id);
+            if ($overallfeedback) {
+                echo '<p align="center">', quiz_feedback_for_grade($mygrade, $quiz->id), '</p>';
             }
         }
 
         // Print a button to start/continue an attempt, if appropriate.
-        if ($quiz->questions && $available && $moreattempts) {
 
+        if (!$quiz->questions) {
+            print_heading(get_string("noquestions", "quiz"));
+
+        } else if ($available && $moreattempts) {
             echo "<br />";
             echo "<div align=\"center\">";
 
                     $buttontext = get_string('reattemptquiz', 'quiz');
                 }
 
-                // Work out if the quiz is temporarily unavailable becuase of the delay option.
+                // Work out if the quiz is temporarily unavailable because of the delay option.
                 if (!empty($attempts)) {
                     $tempunavailable = '';
                     $lastattempt = end($attempts);
                     // If so, display a message and prevent the start button from appearing.
                     if ($tempunavailable) {
                         print_simple_box($tempunavailable, "center");
+                        print_continue($CFG->wwwroot . '/course/view.php?id=' . $course->id);
                         $buttontext = '';
                     }
                 }
                 $buttontext = htmlspecialchars($buttontext, ENT_QUOTES);
 
                 // Do we need a confirm javascript alert?
-                $strconfirmstartattempt =  '';
-                if ($quiz->timelimit && $quiz->attempts) {
+                if ($unfinished) {
+                    $strconfirmstartattempt =  '';
+                } else if ($quiz->timelimit && $quiz->attempts) {
                     $strconfirmstartattempt = addslashes(get_string('confirmstartattempttimelimit','quiz', $quiz->attempts));
                 } else if ($quiz->timelimit) {
                     $strconfirmstartattempt = addslashes(get_string('confirmstarttimelimit','quiz'));
                 } else if ($quiz->attempts) {
                     $strconfirmstartattempt = addslashes(get_string('confirmstartattemptlimit','quiz', $quiz->attempts));
+                } else {
+                    $strconfirmstartattempt =  '';
                 }
 
                 // Prepare options depending on whether the quiz should be a popup.
@@ -398,9 +395,8 @@ document.write('<input type="button" value="<?php echo $buttontext ?>" onclick="
             }
 
             echo "</div>\n";
-
-        } else if (!$quiz->questions) {
-            print_heading(get_string("noquestions", "quiz"));
+        } else {
+            print_continue($CFG->wwwroot . '/course/view.php?id=' . $course->id);
         }
     }
 
@@ -439,7 +435,7 @@ function make_review_link($linktext, $quiz, $attempt) {
     if (!$attempt->timefinish) {
         return $linktext;
     }
-    
+
     $url = "review.php?q=$quiz->id&amp;attempt=$attempt->id";
     if ($quiz->popup) {
         $windowoptions = "left=0, top=0, channelmode=yes, fullscreen=yes, scrollbars=yes, resizeable=no, directories=no, toolbar=no, titlebar=no, location=no, status=no, menubar=no";