From 7c148abb66c95b503a9551e929c49b20ebf73fca Mon Sep 17 00:00:00 2001
From: Elmar Ludwig <elmar.ludwig@uni-osnabrueck.de>
Date: Sat, 24 Apr 2021 21:50:36 +0200
Subject: [PATCH] don't allow multiple tries for not autocorrectable text
 exercise, fixes #54

---
 controllers/sheets.php    | 7 ++-----
 exercises/Exercise.php    | 9 +++++++--
 exercises/tb_exercise.php | 4 ++--
 lib/VipsAssignment.php    | 3 ++-
 4 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/controllers/sheets.php b/controllers/sheets.php
index 4b124f3..d575bec 100644
--- a/controllers/sheets.php
+++ b/controllers/sheets.php
@@ -300,16 +300,13 @@ class SheetsController extends StudipController
      * SHEETS/EXAMS
      *
      * Displays an exercise (from student perspective)
-     *
-     * This function is also invoked by a function in vips_solutions.inc.php to show the
-     * solution of a student to a lecturer.
      */
     function show_exercise_action()
     {
         $exercise_id   = Request::int('exercise_id');
         $assignment_id = Request::int('assignment_id');
         $assignment    = VipsAssignment::find($assignment_id);
-        $solver_id     = Request::option('solver_id');  // solver is handed over via address line, ie. user is either a lecturer or a student who is looking at corrections
+        $solver_id     = Request::option('solver_id');  // solver is handed over via address line, ie. user is a lecturer
 
         check_exercise_assignment($exercise_id, $assignment);
         check_assignment_access($assignment);
@@ -380,7 +377,7 @@ class SheetsController extends StudipController
             $max_tries = $assignment->options['max_tries'] ?: 3;
             $tries_left = $max_tries - $solution->countTries();
 
-            if ($reached_points == $max_points || $tries_left <= 0) {
+            if ($reached_points == $max_points || !$solution->corrected || $solution->corrector_id || $tries_left <= 0) {
                 $show_solution = true;
             }
         }
diff --git a/exercises/Exercise.php b/exercises/Exercise.php
index e7b5efd..367b8e9 100644
--- a/exercises/Exercise.php
+++ b/exercises/Exercise.php
@@ -301,8 +301,13 @@ abstract class Exercise extends SimpleORMap
             }
 
             $points += $item['points'];
-            // only true if all items are marked as 'safe'
-            $safe &= $item['safe'];
+
+            if ($item['safe'] === NULL) {
+                $safe = NULL;
+            } else if ($safe !== NULL) {
+                // only true if all items are marked as 'safe'
+                $safe &= $item['safe'];
+            }
         }
 
         if ($this->isMultipleChoice()) {
diff --git a/exercises/tb_exercise.php b/exercises/tb_exercise.php
index edee68d..b6f8ad8 100644
--- a/exercises/tb_exercise.php
+++ b/exercises/tb_exercise.php
@@ -91,7 +91,7 @@ class tb_exercise extends Exercise
         $musterLoesung   = normalizeText($musterLoesung, true);
 
         if ($studentSolution == '' || $studentSolution == $answerDefault) {
-            $result[] = ['points' => 0, 'safe' => count($solution->files) == 0];
+            $result[] = ['points' => 0, 'safe' => count($solution->files) == 0 ? true : NULL];
         } else if ($musterLoesung == $studentSolution) {
             $result[] = ['points' => 1, 'safe' => true];
         } else if ($this->task['compare'] === 'levenshtein') {
@@ -104,7 +104,7 @@ class tb_exercise extends Exercise
             $similarity = max(1 - $levenshtein, 0);
             $result[] = ['points' => $similarity, 'safe' => false];
         } else {
-            $result[] = ['points' => 0, 'safe' => false];
+            $result[] = ['points' => 0, 'safe' => NULL];
         }
 
         return $result;
diff --git a/lib/VipsAssignment.php b/lib/VipsAssignment.php
index 7d6964c..57b6caf 100644
--- a/lib/VipsAssignment.php
+++ b/lib/VipsAssignment.php
@@ -730,9 +730,10 @@ class VipsAssignment extends SimpleORMap
         $selftest   = $this->type === 'selftest';
         $evaluation = $exercise->evaluate($solution);
         $feedback   = $exercise->options['feedback'];
+        $eval_safe  = $selftest ? $evaluation['safe'] !== NULL : $evaluation['safe'];
 
         $reached_points = round_to_half_point($evaluation['percent'] * $max_points);
-        $corrected      = (int) ($corrected || $selftest || $evaluation['safe']);
+        $corrected      = (int) ($corrected || $eval_safe);
 
         // insert solution points
         $solution->corrected = $corrected;
-- 
GitLab