feat: generate hints per row in GameGridGenerator
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,12 +9,15 @@ use App\Entity\Game;
|
|||||||
use App\Entity\GameRow;
|
use App\Entity\GameRow;
|
||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
use App\Repository\ActorRepository;
|
use App\Repository\ActorRepository;
|
||||||
|
use App\Repository\MovieRoleRepository;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
class GameGridGenerator
|
class GameGridGenerator
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ActorRepository $actorRepository,
|
private readonly ActorRepository $actorRepository,
|
||||||
|
private readonly MovieRoleRepository $movieRoleRepository,
|
||||||
|
private readonly WikidataAwardGateway $wikidataAwardGateway,
|
||||||
private readonly EntityManagerInterface $em,
|
private readonly EntityManagerInterface $em,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@@ -28,6 +31,8 @@ class GameGridGenerator
|
|||||||
|
|
||||||
$usedActors = [$mainActor->getId()];
|
$usedActors = [$mainActor->getId()];
|
||||||
$rowOrder = 0;
|
$rowOrder = 0;
|
||||||
|
$usedMovieRoleIds = [];
|
||||||
|
$usedHintKeys = [];
|
||||||
|
|
||||||
foreach (str_split(strtolower($mainActor->getName())) as $char) {
|
foreach (str_split(strtolower($mainActor->getName())) as $char) {
|
||||||
if (!preg_match('/[a-z]/', $char)) {
|
if (!preg_match('/[a-z]/', $char)) {
|
||||||
@@ -50,6 +55,12 @@ class GameGridGenerator
|
|||||||
$row->setPosition(strpos(strtolower($actor->getName()), $char));
|
$row->setPosition(strpos(strtolower($actor->getName()), $char));
|
||||||
$row->setRowOrder($rowOrder);
|
$row->setRowOrder($rowOrder);
|
||||||
|
|
||||||
|
$hint = $this->generateHint($mainActor, $usedMovieRoleIds, $usedHintKeys);
|
||||||
|
if ($hint !== null) {
|
||||||
|
$row->setHintType($hint['type']);
|
||||||
|
$row->setHintData($hint['data']);
|
||||||
|
}
|
||||||
|
|
||||||
$game->addRow($row);
|
$game->addRow($row);
|
||||||
++$rowOrder;
|
++$rowOrder;
|
||||||
}
|
}
|
||||||
@@ -115,4 +126,86 @@ class GameGridGenerator
|
|||||||
'middle' => $leftSize,
|
'middle' => $leftSize,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param list<int> $usedMovieRoleIds MovieRole IDs already used (for DB exclusion)
|
||||||
|
* @param list<string> $usedHintKeys Semantic keys like "film:42" to avoid duplicate hints
|
||||||
|
* @return array{type: string, data: string}|null
|
||||||
|
*/
|
||||||
|
private function generateHint(Actor $mainActor, array &$usedMovieRoleIds, array &$usedHintKeys): ?array
|
||||||
|
{
|
||||||
|
$types = ['film', 'character', 'award'];
|
||||||
|
shuffle($types);
|
||||||
|
|
||||||
|
foreach ($types as $type) {
|
||||||
|
$hint = $this->resolveHint($type, $mainActor, $usedMovieRoleIds, $usedHintKeys);
|
||||||
|
if ($hint !== null) {
|
||||||
|
return $hint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param list<int> $usedMovieRoleIds
|
||||||
|
* @param list<string> $usedHintKeys
|
||||||
|
* @return array{type: string, data: string}|null
|
||||||
|
*/
|
||||||
|
private function resolveHint(string $type, Actor $mainActor, array &$usedMovieRoleIds, array &$usedHintKeys): ?array
|
||||||
|
{
|
||||||
|
switch ($type) {
|
||||||
|
case 'film':
|
||||||
|
$role = $this->movieRoleRepository->findOneRandomByActor(
|
||||||
|
$mainActor->getId(),
|
||||||
|
$usedMovieRoleIds,
|
||||||
|
);
|
||||||
|
if ($role === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$movieId = (string) $role->getMovie()->getId();
|
||||||
|
$key = 'film:' . $movieId;
|
||||||
|
if (in_array($key, $usedHintKeys)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$usedMovieRoleIds[] = $role->getId();
|
||||||
|
$usedHintKeys[] = $key;
|
||||||
|
return ['type' => 'film', 'data' => $movieId];
|
||||||
|
|
||||||
|
case 'character':
|
||||||
|
$role = $this->movieRoleRepository->findOneRandomByActor(
|
||||||
|
$mainActor->getId(),
|
||||||
|
$usedMovieRoleIds,
|
||||||
|
);
|
||||||
|
if ($role === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$roleId = (string) $role->getId();
|
||||||
|
$key = 'character:' . $roleId;
|
||||||
|
if (in_array($key, $usedHintKeys)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$usedMovieRoleIds[] = $role->getId();
|
||||||
|
$usedHintKeys[] = $key;
|
||||||
|
return ['type' => 'character', 'data' => $roleId];
|
||||||
|
|
||||||
|
case 'award':
|
||||||
|
try {
|
||||||
|
$awards = $this->wikidataAwardGateway->getAwards($mainActor);
|
||||||
|
} catch (\Throwable) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
foreach ($awards as $award) {
|
||||||
|
$text = $award['name'] . ' (' . $award['year'] . ')';
|
||||||
|
$key = 'award:' . $text;
|
||||||
|
if (!in_array($key, $usedHintKeys)) {
|
||||||
|
$usedHintKeys[] = $key;
|
||||||
|
return ['type' => 'award', 'data' => $text];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user