/** Called to grade the output from a given testcase run when * the template was used to generate a program that does both the test * execution and the grading of the result. * Returns a single TestResult object. * Should not be called if the execution failed (syntax error, exception * etc). */ function grade_known_good(&$output, &$testcase) { $result = json_decode($output); if ($result === null || !isset($result->fraction) || !is_numeric($result->fraction)) { $errormessage = "Bad grading result from template:'" . $output . "'"; $outcome = new qtype_coderunner_test_result(qtype_coderunner_grader::tidy($testcase->testcode), $testcase->mark, false, 0.0, qtype_coderunner_grader::tidy($testcase->expected), $errormessage, qtype_coderunner_grader::tidy($testcase->stdin), qtype_coderunner_grader::tidy($testCase->extra)); } else { // First copy any missing fields from test case into result foreach (get_object_vars($testcase) as $key => $value) { if (!isset($result->{$key})) { $result->{$key} = $value; } } if (!isset($result->awarded)) { $result->awarded = $result->mark * $result->fraction; } if (!isset($result->got)) { $result->got = ''; } $result->iscorrect = abs($result->fraction - 1.0) < 1.0E-6; $outcome = new qtype_coderunner_test_result(qtype_coderunner_grader::tidy($result->testcode), $result->mark, $result->iscorrect, $result->awarded, qtype_coderunner_grader::tidy($result->expected), qtype_coderunner_grader::tidy($result->got), qtype_coderunner_grader::tidy($result->stdin), qtype_coderunner_grader::tidy($result->extra)); /* To accommodate generalised template graders that need to * have their own custom attributes, we also add any other result * attributes not already used into the TestResult object. */ foreach ((array) $result as $key => $value) { if (!isset($outcome->{$key})) { $outcome->{$key} = $value; } } } return $outcome; }
/** Called to grade the output generated by a student's code for * a given testcase. Returns a single TestResult object, which * must have called tidy on the expected, output and stdin fields * to limit their lengths. */ public function grade(&$output, &$testcase, $isBad = false) { if ($isBad) { $outcome = new qtype_coderunner_test_result(qtype_coderunner_grader::tidy($testcase->testcode), $testcase->mark, false, 0.0, qtype_coderunner_grader::tidy($testcase->expected), qtype_coderunner_grader::tidy($output), qtype_coderunner_grader::tidy($testcase->stdin), qtype_coderunner_grader::tidy($testcase->extra)); } else { $outcome = $this->grade_known_good($output, $testcase); } return $outcome; }
/** Called to grade the output generated by a student's code for * a given testcase. Returns a single TestResult object. * Should not be called if the execution failed (syntax error, exception * etc). */ function grade_known_good(&$output, &$testCase) { $regex = '/' . str_replace('/', '\\/', $testCase->expected) . '/ms'; $isCorrect = preg_match($regex, $output); $awardedMark = $isCorrect ? $testCase->mark : 0.0; if (isset($testCase->stdin)) { $resultStdin = qtype_coderunner_grader::tidy($testCase->stdin); } else { $resultStdin = null; } return new qtype_coderunner_test_result(qtype_coderunner_grader::tidy($testCase->testcode), $testCase->mark, $isCorrect, $awardedMark, qtype_coderunner_grader::snip($testCase->expected), qtype_coderunner_grader::snip($output), $resultStdin, qtype_coderunner_grader::tidy($testCase->extra)); }
/** This grader tests if the expected output matches the actual * output after removing all empty lines and trailing white space, * collapsing all sequences of space or tab characters to a single * space and converting all letters to lower case. [These changes * are of course applied to both expected and actual outputs.] * * As requested by Ulrich Dangel. */ function grade_known_good(&$output, &$testCase) { $cleanedOutput = qtype_coderunner_grader::clean($output); $cleanedExpected = qtype_coderunner_grader::clean($testCase->expected); $isCorrect = $this->reduce($cleanedOutput) == $this->reduce($cleanedExpected); $awardedMark = $isCorrect ? $testCase->mark : 0.0; if (isset($testCase->stdin)) { $resultStdin = qtype_coderunner_grader::tidy($testCase->stdin); } else { $resultStdin = null; } return new qtype_coderunner_test_result(qtype_coderunner_grader::tidy($testCase->testcode), $testCase->mark, $isCorrect, $awardedMark, qtype_coderunner_grader::snip($cleanedExpected), qtype_coderunner_grader::snip($cleanedOutput), $resultStdin, qtype_coderunner_grader::tidy($testCase->extra)); }