diff --git a/src/Service/GameGridGenerator.php b/src/Service/GameGridGenerator.php index d13cb57..4353557 100644 --- a/src/Service/GameGridGenerator.php +++ b/src/Service/GameGridGenerator.php @@ -9,12 +9,15 @@ use App\Entity\Game; use App\Entity\GameRow; use App\Entity\User; use App\Repository\ActorRepository; +use App\Repository\MovieRoleRepository; use Doctrine\ORM\EntityManagerInterface; class GameGridGenerator { public function __construct( private readonly ActorRepository $actorRepository, + private readonly MovieRoleRepository $movieRoleRepository, + private readonly WikidataAwardGateway $wikidataAwardGateway, private readonly EntityManagerInterface $em, ) {} @@ -28,6 +31,8 @@ class GameGridGenerator $usedActors = [$mainActor->getId()]; $rowOrder = 0; + $usedMovieRoleIds = []; + $usedHintKeys = []; foreach (str_split(strtolower($mainActor->getName())) as $char) { if (!preg_match('/[a-z]/', $char)) { @@ -50,6 +55,12 @@ class GameGridGenerator $row->setPosition(strpos(strtolower($actor->getName()), $char)); $row->setRowOrder($rowOrder); + $hint = $this->generateHint($mainActor, $usedMovieRoleIds, $usedHintKeys); + if ($hint !== null) { + $row->setHintType($hint['type']); + $row->setHintData($hint['data']); + } + $game->addRow($row); ++$rowOrder; } @@ -115,4 +126,86 @@ class GameGridGenerator 'middle' => $leftSize, ]; } + + /** + * @param list $usedMovieRoleIds MovieRole IDs already used (for DB exclusion) + * @param list $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 $usedMovieRoleIds + * @param list $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; + } }