<?phpnamespace App\EventSubscriber\Tournament;use App\Entity\ContestPlayer;use App\Entity\Phase;use App\Entity\Transaction;use App\Event\Tournament\TournamentEndedEvent;use App\Factory\TransactionFactory;use App\Helper\ContestHelper;use App\Helper\TournamentHelper;use App\Service\TournamentService;use Doctrine\ORM\EntityManagerInterface;use LogicException;use Symfony\Component\EventDispatcher\EventSubscriberInterface;use Throwable;class TournamentEndedEventSubscriber implements EventSubscriberInterface{ public function __construct( private EntityManagerInterface $entityManager, private TransactionFactory $transactionFactory, private TournamentService $tournamentService ) { } public function onTournamentEndedEvent(TournamentEndedEvent $tournamentEndedEvent): void { $tournament = $tournamentEndedEvent->getTournament(); $jackpot = $this->tournamentService->calculateJackpot($tournament); /** @var Phase $penultimatePhase the before last phase */ $penultimatePhase = array_reverse($tournament->getPhases()->toArray())[1]; /** @var Phase|null $beforePenultimatePhase */ $beforePenultimatePhase = array_reverse($tournament->getPhases()->toArray())[2] ?? null; $finalContest = TournamentHelper::getFinalContest($tournament); foreach ($tournament->getPrizes() as $prize) { $rewardedPs = $jackpot / 100 * $prize->getValue(); if ($prize->getRank() === 1) { $player = $finalContest->getWinner(); $this->transactionFactory ->forPlayer($player) ->givePs($rewardedPs) ->because(Transaction::TOURNAMENT_WINNER_TYPE) ->save() ; $prize->addPlayer($player); continue; } if ($prize->getRank() === 2) { $contestPlayers = $finalContest->getContestPlayers()->filter(function (ContestPlayer $contestPlayer) use ($finalContest) { return $contestPlayer->getPlayer() !== $finalContest->getWinner(); }); if ($contestPlayers->isEmpty()) { continue; } /** @var ContestPlayer $contestPlayer */ $contestPlayer = $contestPlayers->first(); $player = $contestPlayer->getPlayer(); $this->transactionFactory ->forPlayer($player) ->givePs($rewardedPs) ->because(Transaction::TOURNAMENT_WINNER_TYPE) ->save() ; $prize->addPlayer($player); continue; } if ($prize->getRank() === 3) { $players = null; foreach ($penultimatePhase->getContests() as $contest) { try { $players[] = ContestHelper::getLoser($contest); } catch (Throwable) { continue; } } if (empty($players)) { continue; } foreach ($players as $player) { $this->transactionFactory ->forPlayer($player) ->givePs($rewardedPs) ->because(Transaction::TOURNAMENT_WINNER_TYPE) ->save() ; $prize->addPlayer($player); } continue; } if ($prize->getRank() === 4) { // handle tournament that does not have before penultimate phase if (!$beforePenultimatePhase) { continue; } $players = null; // loops through all contests of the tournament foreach ($beforePenultimatePhase->getContests() as $contest) { try { $players[] = ContestHelper::getLoser($contest); } catch (Throwable) { continue; } } if (empty($players)) { continue; } foreach ($players as $player) { $this->transactionFactory ->forPlayer($player) ->givePs($rewardedPs) ->because(Transaction::TOURNAMENT_WINNER_TYPE) ->save() ; $prize->addPlayer($player); } continue; } throw new LogicException('Unsupported prize ranking passed: ' . $prize->getRank()); } $this->entityManager->flush(); } public static function getSubscribedEvents(): array { return [ TournamentEndedEvent::class => 'onTournamentEndedEvent', ]; }}