31 lines
1.2 KiB
PHP
31 lines
1.2 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services;
|
|
|
|
/** Grades one immutable server snapshot; no client-supplied answer key. */
|
|
final class RemediationAttemptGrader
|
|
{
|
|
public static function grade(array $questionIds, array $answerKey, array $answers): int
|
|
{
|
|
if (count($questionIds) !== 3 || count(array_unique($questionIds)) !== 3 ||
|
|
count($answerKey) !== 3 || array_keys($answers) !== [0, 1, 2]) {
|
|
throw new \InvalidArgumentException('Invalid quiz shape');
|
|
}
|
|
$correct = 0;
|
|
foreach ($questionIds as $index => $questionId) {
|
|
$key = $answerKey[$index] ?? null;
|
|
$selected = $answers[$index];
|
|
if (!is_array($key) || !is_int($selected) || $selected <= 0 ||
|
|
(int)($key['question_id'] ?? 0) !== (int)$questionId ||
|
|
!is_array($key['option_ids'] ?? null) ||
|
|
!in_array($selected, $key['option_ids'], true) ||
|
|
!in_array((int)($key['correct_option_id'] ?? 0), $key['option_ids'], true)) {
|
|
throw new \InvalidArgumentException('Answer does not belong to the attempt');
|
|
}
|
|
if ($selected === (int)$key['correct_option_id']) $correct++;
|
|
}
|
|
return $correct;
|
|
}
|
|
}
|