feat: GameGridProvider accepts config for hint types, watched-only, and retry logic
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -24,9 +24,40 @@ class GameGridProvider
|
||||
private readonly EntityManagerInterface $em,
|
||||
) {}
|
||||
|
||||
public function generate(?User $user = null): Game
|
||||
/**
|
||||
* @param array{watchedOnly?: bool, hintTypes?: list<string>, awardTypeIds?: list<int>|null} $config
|
||||
*/
|
||||
public function generate(?User $user = null, array $config = []): ?Game
|
||||
{
|
||||
$mainActor = $this->actorRepository->findOneRandom(4);
|
||||
$watchedOnly = $config['watchedOnly'] ?? false;
|
||||
$hintTypes = $config['hintTypes'] ?? ['film', 'character', 'award'];
|
||||
$awardTypeIds = $config['awardTypeIds'] ?? null;
|
||||
|
||||
for ($attempt = 0; $attempt < 5; $attempt++) {
|
||||
$game = $this->tryGenerate($user, $watchedOnly, $hintTypes, $awardTypeIds);
|
||||
if ($game !== null) {
|
||||
return $game;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<string> $hintTypes
|
||||
* @param list<int>|null $awardTypeIds
|
||||
*/
|
||||
private function tryGenerate(?User $user, bool $watchedOnly, array $hintTypes, ?array $awardTypeIds): ?Game
|
||||
{
|
||||
if ($watchedOnly && $user !== null) {
|
||||
$mainActor = $this->actorRepository->findOneRandomInWatchedFilms($user, 4);
|
||||
} else {
|
||||
$mainActor = $this->actorRepository->findOneRandom(4);
|
||||
}
|
||||
|
||||
if ($mainActor === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$game = new Game();
|
||||
$game->setMainActor($mainActor);
|
||||
@@ -40,14 +71,23 @@ class GameGridProvider
|
||||
continue;
|
||||
}
|
||||
|
||||
$tryFindActor = 0;
|
||||
do {
|
||||
$actor = $this->actorRepository->findOneRandom(4, $char);
|
||||
++$tryFindActor;
|
||||
} while (
|
||||
in_array($actor->getId(), $usedActors)
|
||||
|| $tryFindActor < 5
|
||||
);
|
||||
$actor = null;
|
||||
for ($try = 0; $try < 5; $try++) {
|
||||
if ($watchedOnly && $user !== null) {
|
||||
$candidate = $this->actorRepository->findOneRandomInWatchedFilms($user, 4, $char);
|
||||
} else {
|
||||
$candidate = $this->actorRepository->findOneRandom(4, $char);
|
||||
}
|
||||
|
||||
if ($candidate !== null && !in_array($candidate->getId(), $usedActors)) {
|
||||
$actor = $candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($actor === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$usedActors[] = $actor->getId();
|
||||
|
||||
@@ -56,11 +96,12 @@ class GameGridProvider
|
||||
$row->setPosition(strpos(strtolower($actor->getName()), $char));
|
||||
$row->setRowOrder($rowOrder);
|
||||
|
||||
$hint = $this->generateHint($actor);
|
||||
if ($hint !== null) {
|
||||
$row->setHintType($hint['type']);
|
||||
$row->setHintData($hint['data']);
|
||||
$hint = $this->generateHint($actor, $hintTypes, $awardTypeIds);
|
||||
if ($hint === null) {
|
||||
return null; // Every row must have a hint
|
||||
}
|
||||
$row->setHintType($hint['type']);
|
||||
$row->setHintData($hint['data']);
|
||||
|
||||
$game->addRow($row);
|
||||
++$rowOrder;
|
||||
@@ -133,17 +174,17 @@ class GameGridProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a single hint for a row actor.
|
||||
*
|
||||
* @param list<string> $allowedTypes
|
||||
* @param list<int>|null $awardTypeIds
|
||||
* @return array{type: string, data: string}|null
|
||||
*/
|
||||
private function generateHint(Actor $rowActor): ?array
|
||||
private function generateHint(Actor $rowActor, array $allowedTypes = ['film', 'character', 'award'], ?array $awardTypeIds = null): ?array
|
||||
{
|
||||
$types = ['film', 'character', 'award'];
|
||||
$types = $allowedTypes;
|
||||
shuffle($types);
|
||||
|
||||
foreach ($types as $type) {
|
||||
$hint = $this->resolveHint($type, $rowActor);
|
||||
$hint = $this->resolveHint($type, $rowActor, $awardTypeIds);
|
||||
if ($hint !== null) {
|
||||
return $hint;
|
||||
}
|
||||
@@ -153,27 +194,33 @@ class GameGridProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<int>|null $awardTypeIds
|
||||
* @return array{type: string, data: string}|null
|
||||
*/
|
||||
private function resolveHint(string $type, Actor $rowActor): ?array
|
||||
private function resolveHint(string $type, Actor $rowActor, ?array $awardTypeIds = null): ?array
|
||||
{
|
||||
$actorId = $rowActor->getId();
|
||||
if ($actorId === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
case 'film':
|
||||
$role = $this->movieRoleRepository->findOneRandomByActor($rowActor->getId());
|
||||
$role = $this->movieRoleRepository->findOneRandomByActor($actorId);
|
||||
if ($role === null) {
|
||||
return null;
|
||||
}
|
||||
return ['type' => 'film', 'data' => (string) $role->getMovie()->getId()];
|
||||
|
||||
case 'character':
|
||||
$role = $this->movieRoleRepository->findOneRandomByActor($rowActor->getId());
|
||||
$role = $this->movieRoleRepository->findOneRandomByActor($actorId);
|
||||
if ($role === null) {
|
||||
return null;
|
||||
}
|
||||
return ['type' => 'character', 'data' => (string) $role->getId()];
|
||||
|
||||
case 'award':
|
||||
$award = $this->awardRepository->findOneRandomByActor($rowActor->getId());
|
||||
$award = $this->awardRepository->findOneRandomByActorAndTypes($actorId, $awardTypeIds);
|
||||
if ($award === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user