Skip to content

Commit cd38100

Browse files
committed
cleanup grade()
1 parent e547f53 commit cd38100

File tree

3 files changed

+19
-9
lines changed

3 files changed

+19
-9
lines changed

classes/local/answer_parser.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ public function __construct($tokenlist, array $knownvariables = [], bool $caretm
6666
}
6767
}
6868

69+
// If we only have one single token and it is an empty string, we set it to the $EMPTY token.
70+
$firsttoken = reset($tokenlist);
71+
if (count($tokenlist) === 1 && $firsttoken->value === '') {
72+
$tokenlist[0] = new token(token::EMPTY, '$EMPTY', $firsttoken->row, $firsttoken->column);
73+
}
74+
6975
// Once this is done, we can parse the expression normally.
7076
parent::__construct($tokenlist, $knownvariables);
7177
}

classes/local/evaluator.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -907,14 +907,19 @@ private function evaluate_the_right_thing($input, bool $godmode = false) {
907907
/**
908908
* Evaluate a single expression or an array of expressions.
909909
*
910-
* @param expression|for_loop|array $input
910+
* @param expression|for_loop|array|false $input
911911
* @param bool $godmode whether to run the evaluation in god mode
912912
* @return token|array
913913
*/
914914
public function evaluate($input, bool $godmode = false) {
915915
if (($input instanceof expression) || ($input instanceof for_loop)) {
916916
return $this->evaluate_the_right_thing($input, $godmode);
917917
}
918+
// For convenience, the evaluator accepts FALSE as an input, This allows
919+
// passing reset($array) with a possibly empty array.
920+
if ($input === false) {
921+
return new token(token::EMPTY, '$EMPTY');
922+
}
918923
if (!is_array($input)) {
919924
throw new Exception(get_string('error_evaluate_invocation', 'qtype_formulas', 'evaluate()'));
920925
}

question.php

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,7 +1466,7 @@ public function add_special_variables(array $studentanswers, float $conversionfa
14661466
// We calculate the sum of squares of all model answers.
14671467
$ssqmodelanswer = 0;
14681468
foreach ($this->get_evaluated_answers() as $answer) {
1469-
if ($answer === '$EMPTY' || trim($answer) === '') {
1469+
if ($answer === '$EMPTY') {
14701470
continue;
14711471
}
14721472
$ssqmodelanswer += $answer ** 2;
@@ -1554,13 +1554,12 @@ public function grade(array $response, bool $finalsubmit = false): array {
15541554
// failed evaluation, e.g. caused by an invalid answer.
15551555
$this->evaluator->clear_stack();
15561556

1557-
// Evaluate, if not empty.
1558-
if ($answer === '""' || (empty($answer) && !is_numeric($answer))) {
1559-
$evaluated = new token(token::EMPTY, '$EMPTY');
1560-
} else {
1561-
$evaluated = $this->evaluator->evaluate($parser->get_statements())[0];
1562-
}
1563-
$evaluatedresponse[] = token::unpack($evaluated); // $evaluated;
1557+
// Evaluate. If the answer was empty (an empty string or the '$EMPTY'), the parser
1558+
// will create an appropriate evaluable statement or return an empty array. The evaluator,
1559+
// on the other hand, will know how to deal with the "false" return value from reset()
1560+
// and return the $EMPTY token.
1561+
$statements = $parser->get_statements();
1562+
$evaluatedresponse[] = token::unpack($this->evaluator->evaluate(reset($statements)));
15641563
} catch (Throwable $t) {
15651564
// TODO: convert to non-capturing catch
15661565
// If parsing, validity check or evaluation fails, we consider the answer as wrong.

0 commit comments

Comments
 (0)