mirror of
https://github.com/MarijnDoeve/TijdVoorDeTest.git
synced 2026-07-12 21:05:19 +02:00
Bold the correct answer in the raw answers export sheet (#208)
Makes it easy to visually spot which answer was correct when scanning the GDPR export's per-candidate/per-question crosstab.
This commit is contained in:
@@ -223,7 +223,7 @@ class DataExportService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Raw crosstab: one row per candidate, one column per question, cell = the answer text they gave. */
|
/** Raw crosstab: one row per candidate, one column per question, cell = the answer text they gave (bold when correct). */
|
||||||
private function fillRawAnswersSheet(Worksheet $sheet, Quiz $quiz): void
|
private function fillRawAnswersSheet(Worksheet $sheet, Quiz $quiz): void
|
||||||
{
|
{
|
||||||
/** @var list<Question> $questions */
|
/** @var list<Question> $questions */
|
||||||
@@ -240,11 +240,14 @@ class DataExportService
|
|||||||
|
|
||||||
/** @var array<string, array<string, string>> $answersByCandidateAndQuestion */
|
/** @var array<string, array<string, string>> $answersByCandidateAndQuestion */
|
||||||
$answersByCandidateAndQuestion = [];
|
$answersByCandidateAndQuestion = [];
|
||||||
|
/** @var array<string, array<string, bool>> $correctnessByCandidateAndQuestion */
|
||||||
|
$correctnessByCandidateAndQuestion = [];
|
||||||
foreach ($questions as $question) {
|
foreach ($questions as $question) {
|
||||||
foreach ($question->answers as $answer) {
|
foreach ($question->answers as $answer) {
|
||||||
foreach ($answer->givenAnswers as $givenAnswer) {
|
foreach ($answer->givenAnswers as $givenAnswer) {
|
||||||
$candidateId = $givenAnswer->candidate->id->toString();
|
$candidateId = $givenAnswer->candidate->id->toString();
|
||||||
$answersByCandidateAndQuestion[$candidateId][$question->id->toString()] = $answer->text;
|
$answersByCandidateAndQuestion[$candidateId][$question->id->toString()] = $answer->text;
|
||||||
|
$correctnessByCandidateAndQuestion[$candidateId][$question->id->toString()] = $answer->isRightAnswer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -252,13 +255,22 @@ class DataExportService
|
|||||||
$row = 2;
|
$row = 2;
|
||||||
foreach ($quiz->candidateData as $quizCandidate) {
|
foreach ($quiz->candidateData as $quizCandidate) {
|
||||||
$candidate = $quizCandidate->candidate;
|
$candidate = $quizCandidate->candidate;
|
||||||
|
$candidateId = $candidate->id->toString();
|
||||||
|
|
||||||
$line = [$candidate->name];
|
$line = [$candidate->name];
|
||||||
foreach ($questions as $question) {
|
foreach ($questions as $question) {
|
||||||
$line[] = $answersByCandidateAndQuestion[$candidate->id->toString()][$question->id->toString()] ?? '';
|
$line[] = $answersByCandidateAndQuestion[$candidateId][$question->id->toString()] ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$sheet->fromArray($line, null, 'A'.$row);
|
$sheet->fromArray($line, null, 'A'.$row);
|
||||||
|
|
||||||
|
foreach ($questions as $columnIndex => $question) {
|
||||||
|
if ($correctnessByCandidateAndQuestion[$candidateId][$question->id->toString()] ?? false) {
|
||||||
|
$column = Coordinate::stringFromColumnIndex(2 + $columnIndex);
|
||||||
|
$sheet->getStyle($column.$row)->getFont()->setBold(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
++$row;
|
++$row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Tvdt\Tests\Service;
|
namespace Tvdt\Tests\Service;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader;
|
use PhpOffice\PhpSpreadsheet\Reader;
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
use PHPUnit\Framework\Attributes\CoversClass;
|
use PHPUnit\Framework\Attributes\CoversClass;
|
||||||
@@ -201,6 +202,50 @@ final class DataExportServiceTest extends DatabaseTestCase
|
|||||||
$this->assertSame('Man', $claudiaRow[$questionColumnIndex]);
|
$this->assertSame('Man', $claudiaRow[$questionColumnIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRawAnswersSheetBoldsCorrectAnswersOnly(): void
|
||||||
|
{
|
||||||
|
$season = $this->getSeasonByCode('krtek');
|
||||||
|
$quiz = $this->entityManager->getRepository(Quiz::class)->findOneBy(['name' => 'Quiz 1', 'season' => $season]);
|
||||||
|
$this->assertInstanceOf(Quiz::class, $quiz);
|
||||||
|
|
||||||
|
/** @var Question $firstQuestion */
|
||||||
|
$firstQuestion = $quiz->questions->first();
|
||||||
|
$correctAnswer = $firstQuestion->answers->filter(static fn (Answer $answer): bool => $answer->isRightAnswer)->first();
|
||||||
|
$wrongAnswer = $firstQuestion->answers->filter(static fn (Answer $answer): bool => !$answer->isRightAnswer)->first();
|
||||||
|
$this->assertInstanceOf(Answer::class, $correctAnswer);
|
||||||
|
$this->assertInstanceOf(Answer::class, $wrongAnswer);
|
||||||
|
|
||||||
|
$candidateWithCorrectAnswer = $this->getCandidateBySeasonAndName($season, 'Claudia');
|
||||||
|
$candidateWithWrongAnswer = $this->getCandidateBySeasonAndName($season, 'Eelco');
|
||||||
|
|
||||||
|
$this->quizCandidateRepository->createIfNotExist($quiz, $candidateWithCorrectAnswer);
|
||||||
|
$this->quizCandidateRepository->createIfNotExist($quiz, $candidateWithWrongAnswer);
|
||||||
|
|
||||||
|
$this->entityManager->persist(new GivenAnswer($candidateWithCorrectAnswer, $quiz, $correctAnswer));
|
||||||
|
$this->entityManager->persist(new GivenAnswer($candidateWithWrongAnswer, $quiz, $wrongAnswer));
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
$zip = $this->openZip($this->getUserByEmail('user2@example.org'));
|
||||||
|
$quizContent = $zip->getFromName('krtek-Krtek-Weekend/Quiz-1.xlsx');
|
||||||
|
$this->assertIsString($quizContent);
|
||||||
|
$zip->close();
|
||||||
|
|
||||||
|
$sheet = $this->loadSheet($quizContent, 'Raw answers');
|
||||||
|
$rows = $sheet->toArray();
|
||||||
|
$header = $rows[0];
|
||||||
|
|
||||||
|
$questionColumnIndex = array_search($firstQuestion->question, $header, true);
|
||||||
|
$this->assertIsInt($questionColumnIndex);
|
||||||
|
$column = Coordinate::stringFromColumnIndex($questionColumnIndex + 1);
|
||||||
|
|
||||||
|
$candidateNames = array_column(\array_slice($rows, 1), 0);
|
||||||
|
$correctRowNumber = 2 + array_search('Claudia', $candidateNames, true);
|
||||||
|
$wrongRowNumber = 2 + array_search('Eelco', $candidateNames, true);
|
||||||
|
|
||||||
|
$this->assertTrue($sheet->getStyle($column.$correctRowNumber)->getFont()->getBold(), 'Expected the correct answer to be bold');
|
||||||
|
$this->assertFalse($sheet->getStyle($column.$wrongRowNumber)->getFont()->getBold(), 'Expected the wrong answer to not be bold');
|
||||||
|
}
|
||||||
|
|
||||||
public function testQuizInfoSheetShowsDropoutsFinalizationAndDisabledQuestions(): void
|
public function testQuizInfoSheetShowsDropoutsFinalizationAndDisabledQuestions(): void
|
||||||
{
|
{
|
||||||
$season = $this->getSeasonByCode('krtek');
|
$season = $this->getSeasonByCode('krtek');
|
||||||
|
|||||||
Reference in New Issue
Block a user