Skip to content
This repository was archived by the owner on Oct 15, 2025. It is now read-only.

Commit 12a788a

Browse files
committed
refactor: Rewrite DbRunner and Challenge page
* Typed query result: We previously returned the raw "array" and type-hinted them everywhere. Now, the DbRunner returns a QueryResultDto that wraps this type. * Improved "Result Presenter": Instead of passing the result everywhere, retrieve it directly in the tabs rather than receiving it from the Executor. * The executor now creates a new SolutionEvent without comparing the results. * Added a new Comparer that provides more comprehensive difference information. * Removed "Module" from the component namespace. * Update DbRunner return style * All the cells are string now * The first row is header * The rows started from the second are the rows
1 parent 9ed22ed commit 12a788a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+758
-844
lines changed

assets/controllers/challenge_executor_controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export default class extends Controller<HTMLElement> {
5353
const query = editorView.state.doc.toString();
5454

5555
console.debug("Executing query", { query });
56-
await component.action("execute", {
56+
await component.action("createNewQuery", {
5757
query,
5858
});
5959

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Entity\ChallengeDto\CompareResult;
6+
7+
use Symfony\Component\Translation\TranslatableMessage;
8+
9+
use function Symfony\Component\Translation\t;
10+
11+
/**
12+
* The columns name (first row) is different.
13+
*/
14+
readonly class ColumnDifferent implements CompareResult
15+
{
16+
public function correct(): bool
17+
{
18+
return false;
19+
}
20+
21+
public function reason(): TranslatableMessage
22+
{
23+
return t('challenge.compare-result.column-different');
24+
}
25+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Entity\ChallengeDto\CompareResult;
6+
7+
use Symfony\Component\Translation\TranslatableMessage;
8+
9+
/**
10+
* The result of a comparison.
11+
*/
12+
interface CompareResult
13+
{
14+
public function correct(): bool;
15+
16+
public function reason(): TranslatableMessage;
17+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Entity\ChallengeDto\CompareResult;
6+
7+
use Symfony\Component\Translation\TranslatableMessage;
8+
9+
use function Symfony\Component\Translation\t;
10+
11+
readonly class EmptyAnswer implements CompareResult
12+
{
13+
public function correct(): bool
14+
{
15+
return false;
16+
}
17+
18+
public function reason(): TranslatableMessage
19+
{
20+
return t('challenge.compare-result.empty-answer');
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Entity\ChallengeDto\CompareResult;
6+
7+
use Symfony\Component\Translation\TranslatableMessage;
8+
9+
use function Symfony\Component\Translation\t;
10+
11+
readonly class EmptyResult implements CompareResult
12+
{
13+
public function correct(): bool
14+
{
15+
return false;
16+
}
17+
18+
public function reason(): TranslatableMessage
19+
{
20+
return t('challenge.compare-result.empty-result');
21+
}
22+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Entity\ChallengeDto\CompareResult;
6+
7+
use Symfony\Component\Translation\TranslatableMessage;
8+
9+
use function Symfony\Component\Translation\t;
10+
11+
readonly class RowDifferent implements CompareResult
12+
{
13+
/**
14+
* @param int $row the row number that is different
15+
*/
16+
public function __construct(public int $row)
17+
{
18+
}
19+
20+
public function correct(): bool
21+
{
22+
return false;
23+
}
24+
25+
public function reason(): TranslatableMessage
26+
{
27+
return t('challenge.compare-result.row-different', [
28+
'%row%' => $this->row,
29+
]);
30+
}
31+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Entity\ChallengeDto\CompareResult;
6+
7+
use Symfony\Component\Translation\TranslatableMessage;
8+
9+
use function Symfony\Component\Translation\t;
10+
11+
readonly class RowUnmatched implements CompareResult
12+
{
13+
/**
14+
* @param int $expected the expected row number
15+
* @param int $actual the actual row number
16+
*/
17+
public function __construct(
18+
public int $expected,
19+
public int $actual,
20+
) {
21+
}
22+
23+
public function correct(): bool
24+
{
25+
return false;
26+
}
27+
28+
public function reason(): TranslatableMessage
29+
{
30+
return t('challenge.compare-result.row-unmatched', [
31+
'%expected%' => $this->expected,
32+
'%actual%' => $this->actual,
33+
]);
34+
}
35+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Entity\ChallengeDto\CompareResult;
6+
7+
use Symfony\Component\Translation\TranslatableMessage;
8+
9+
use function Symfony\Component\Translation\t;
10+
11+
/**
12+
* There is no different.
13+
*/
14+
readonly class Same implements CompareResult
15+
{
16+
public function correct(): bool
17+
{
18+
return true;
19+
}
20+
21+
public function reason(): TranslatableMessage
22+
{
23+
return t('challenge.compare-result.same');
24+
}
25+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Entity\ChallengeDto;
6+
7+
use Symfony\Component\Translation\TranslatableMessage;
8+
9+
/**
10+
* A DTO for the result of a query that may contain the error from DbRunner.
11+
*
12+
* If there is no error, the errorCode will be 0.
13+
*/
14+
class FallableQueryResultDto
15+
{
16+
public ?QueryResultDto $result = null;
17+
public ?TranslatableMessage $errorMessage = null;
18+
19+
public function getResult(): ?QueryResultDto
20+
{
21+
return $this->result;
22+
}
23+
24+
public function setResult(?QueryResultDto $result): self
25+
{
26+
$this->result = $result;
27+
28+
return $this;
29+
}
30+
31+
public function getErrorMessage(): ?TranslatableMessage
32+
{
33+
return $this->errorMessage;
34+
}
35+
36+
public function setErrorMessage(?TranslatableMessage $errorMessage): self
37+
{
38+
$this->errorMessage = $errorMessage;
39+
40+
return $this;
41+
}
42+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Entity\ChallengeDto;
6+
7+
use App\Service\DbRunner;
8+
9+
/**
10+
* The typed wrapper for the result of a query from {@link DbRunner}.
11+
*/
12+
class QueryResultDto
13+
{
14+
/**
15+
* @var array<array<int, string>> the result of the user's query
16+
*/
17+
private array $result;
18+
19+
/**
20+
* @return array<array<int, string>> the result of the user's query
21+
*/
22+
public function getResult(): array
23+
{
24+
return $this->result;
25+
}
26+
27+
/**
28+
* @param array<array<int, string>> $result the result of the user's query
29+
*/
30+
public function setResult(array $result): self
31+
{
32+
$this->result = $result;
33+
34+
return $this;
35+
}
36+
}

0 commit comments

Comments
 (0)