Skip to content

Commit 3c97019

Browse files
committed
nrw11 - Add more grading data in structured form
1 parent 1cb04cf commit 3c97019

5 files changed

Lines changed: 42 additions & 2 deletions

File tree

api/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ The grading route returns the following fields:
124124
- a map from the PRT names to floats `scoreweights`, containing the weighting for each part. `scoreweights['total']` contains the default total mark for the question. The mark for a question part is its `score[prt] * scoreweights[prt] * scoreweights['total']`.
125125
- a string field `specificfeedback` containing the rendered specific feedback text
126126
- a map from the PRT names to strings `prts`, containing the rendered PRT feedback
127+
- a map from the PRT names to objects `prtresults`, containing structured PRT grading data. Each entry includes `score`, `penalty`, `answernotes` (the full answer-note path as an array), `prtanswernotes` (the PRT-node answer notes only), `errors`, and `fverrors`.
127128
- a string map `gradingassets`, containing a list of assets used in the grading response, see [Plots/Assets](#plotsassets)
128129
- a string field `responsesummary` containing a summary of response. (See [Reporting](../doc/en/Authoring/../STACK_question_admin/Reporting.md).)
129130
- an array of arrays `iframes` of arguments to create iframes to hold JS panels e.g. JSXGraph, GeoGebra
@@ -177,7 +178,7 @@ In the outcomes object, each test will key an object:
177178
- boolean: `passed`: Did the test pass?
178179
- string: `reason`: Reason for failure. A test empty message or the part of the output (e.g. score) which doesn't match the expected result.
179180
- object: `inputs`: Keyed by input name. Details of the inputs and their values.
180-
- object: `outcomes`: Keyed by PRT name. Details of the outcomes and expected outcomes for each PRT.
181+
- object: `outcomes`: Keyed by PRT name. Details of the outcomes and expected outcomes for each PRT. Each PRT outcome includes the legacy delimiter-separated `answernote` string, plus structured `answernotes` and `prtanswernotes` arrays.
181182

182183
Example result object:
183184
```
@@ -205,6 +206,8 @@ Example result object:
205206
"score": 1,
206207
"penalty": 0,
207208
"answernote": "prt1-1-T",
209+
"answernotes": ["prt1-1-T"],
210+
"prtanswernotes": ["prt1-1-T"],
208211
"expectedscore": 1,
209212
"expectedpenalty": 0,
210213
"expectedanswernote": "prt1-1-T",

api/controller/GradingController.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ public function __invoke(Request $request, Response $response, array $args): Res
9090
foreach ($question->prts as $index => $prt) {
9191
$result = $question->get_prt_result($index, $data['answers'], true);
9292
$scores[$index] = $result->get_score();
93+
$gradingresponse->prtresults[$index] = $this->prt_result_summary($result);
9394

9495
$errors = $result->get_errors();
9596
if ($errors) {
@@ -189,4 +190,16 @@ private function standard_prt_feedback(\qtype_stack_question $question, \prt_eva
189190

190191
return '';
191192
}
193+
194+
// phpcs:ignore moodle.Commenting.MissingDocblock.Function
195+
private function prt_result_summary(\prt_evaluatable $result): array {
196+
return [
197+
'score' => $result->get_score(),
198+
'penalty' => $result->get_penalty(),
199+
'answernotes' => $result->get_answernotes(),
200+
'prtanswernotes' => $result->get_answernotes(false),
201+
'errors' => $result->get_errors(),
202+
'fverrors' => $result->get_fverrors(),
203+
];
204+
}
192205
}

api/dtos/StackGradingResponse.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class StackGradingResponse {
3838
public $specificfeedback;
3939
/** @var array */
4040
public $prts;
41+
/** @var array */
42+
public $prtresults = [];
4143
// phpcs:ignore moodle.Commenting.VariableComment.Missing
4244
public $gradingassets;
4345
/** @var string */

stack/questiontestresult.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,18 @@ public function get_prt_states() {
180180
$actualpenalty = $this->round_prt_scores($actualpenalty + 0);
181181
}
182182
$state->penalty = $actualpenalty;
183-
$state->answernote = implode(' | ', $actualresult->get_answernotes());
183+
$state->answernotes = $actualresult->get_answernotes();
184+
$state->prtanswernotes = $actualresult->get_answernotes(false);
185+
$state->answernote = implode(' | ', $state->answernotes);
184186
$state->trace = implode("\n", $actualresult->get_trace());
185187
$state->feedback = $actualresult->get_feedback();
186188
$state->debuginfo = $actualresult->get_debuginfo();
187189
} else {
188190
$state->score = '';
189191
$state->penalty = '';
190192
$state->answernote = '';
193+
$state->answernotes = [];
194+
$state->prtanswernotes = [];
191195
$state->trace = '';
192196
$state->feedback = '';
193197
$state->debuginfo = '';
@@ -400,6 +404,8 @@ public function passed_with_reasons() {
400404
'score' => $state->score,
401405
'penalty' => $state->penalty,
402406
'answernote' => $state->answernote,
407+
'answernotes' => $state->answernotes,
408+
'prtanswernotes' => $state->prtanswernotes,
403409
'expectedscore' => $state->expectedscore,
404410
'expectedpenalty' => $state->expectedpenalty,
405411
'expectedanswernote' => $state->expectedanswernote,

tests/api_controller_test.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,10 @@ public function test_grade(): void {
275275
$this->assertEquals(5, $this->output->scoreweights->total);
276276
$this->assertEquals('<p>[[feedback:prt1]]</p>', $this->output->specificfeedback);
277277
$this->assertStringContainsString('correct', $this->output->prts->prt1);
278+
$this->assertEquals(1, $this->output->prtresults->prt1->score);
279+
$this->assertEquals(0, $this->output->prtresults->prt1->penalty);
280+
$this->assertEquals(['1-0-T'], $this->output->prtresults->prt1->answernotes);
281+
$this->assertEquals(['1-0-T'], $this->output->prtresults->prt1->prtanswernotes);
278282
$this->assertEquals(0, count((array)$this->output->gradingassets));
279283
$this->assertEquals(
280284
'Seed: 86; ans1: matrix([35,30],[28,24]) [score]; prt1: # = 1 | 1-0-T',
@@ -307,6 +311,10 @@ public function test_grade_multipleprts(): void {
307311
'<p>Perhaps you could think of some non-polynomial examples as well?</p>',
308312
$this->output->prts->poly
309313
);
314+
$this->assertEquals(['ODD', 'EVEN'], $this->output->prtresults->oddeven->answernotes);
315+
$this->assertEquals(['ODD', 'EVEN'], $this->output->prtresults->oddeven->prtanswernotes);
316+
$this->assertEquals(['ATLogic_True.', 'unique-0-T'], $this->output->prtresults->unique->answernotes);
317+
$this->assertEquals(['unique-0-T'], $this->output->prtresults->unique->prtanswernotes);
310318
$this->assertEquals(0, count((array)$this->output->gradingassets));
311319
$this->assertEquals(
312320
'Seed: -1; ans1: x^3 [score]; ans2: x^2 [score]; ans3: 0 [score]; ans4: true [score]; ' .
@@ -435,6 +443,14 @@ public function test_test_controller(): void {
435443
$this->assertEquals(0, $results->results->{'86'}->fails);
436444
$this->assertEquals('', $results->results->{'86'}->messages);
437445
$this->assertEquals(4, count(get_object_vars($results->results->{'86'}->outcomes)));
446+
$this->assertEquals(
447+
['1-0-T'],
448+
$results->results->{'86'}->outcomes->{'1'}->outcomes->prt1->answernotes
449+
);
450+
$this->assertEquals(
451+
['1-0-T'],
452+
$results->results->{'86'}->outcomes->{'1'}->outcomes->prt1->prtanswernotes
453+
);
438454
}
439455

440456
public function test_test_controller_fail(): void {

0 commit comments

Comments
 (0)