src/Controller/SKOverlayController.php line 94
<?phpnamespace App\Controller;use App\Entity\CoreConfigData;use App\Kernel;use App\Service\CardImageService;use Doctrine\ORM\EntityManagerInterface;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;use Symfony\Component\DependencyInjection\Attribute\Autowire;use Symfony\Component\Filesystem\Filesystem;use Symfony\Component\Filesystem\Path;use Symfony\Component\Finder\Finder;use Symfony\Component\HttpFoundation\JsonResponse;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpFoundation\Response;use App\Service\MercurePublisher;use Symfony\Component\Routing\Attribute\Route;use Symfony\Component\Routing\Generator\UrlGeneratorInterface;use Symfony\Component\Serializer\Encoder\CsvEncoder;use Symfony\Component\Serializer\Encoder\JsonEncoder;use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;use Symfony\Component\Serializer\Serializer;use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;use Symfony\Contracts\HttpClient\HttpClientInterface;#[Route('/skoverlay')]class SKOverlayController extends AbstractController{#[Route('/', name: 'app_skoverlay_index')]public function app_skoverlay_index (): Response {return $this->render("sk_overlay/index.html.twig");}#[Route('/set/{id<\w+>}/{context}', name: 'app_skoverlay_set')]public function app_skoverlay_set (EntityManagerInterface $entityManager,Request $request,string $id,string $context = ""): Response {$core_config_data_repository = $entityManager->getRepository(CoreConfigData::class);$config_key = "app_coverage_engine_overlay";if ($id) $config_key .= "_{$id}";if ($context) $config_key .= "_{$context}";$config_key .= "_data";$processed = $core_config_data_repository->findOneBy(["config_key" => $config_key]);if (!$processed) $processed = new CoreConfigData();$processed->setConfigKey("app_coverage_engine_overlay_{$id}_data")->setConfigValue($request->getContent());$entityManager->persist($processed);$entityManager->flush();return new JsonResponse(["success" => true,]);}#[Route('/push/{topic<\w+>}', name: 'app_skoverlay_push')]public function app_skoverlay_push (Request $request,MercurePublisher $mercurePublisher,$topic = "ANZID",): Response {$mercurePublisher->publishRaw($topic, $request->getContent());return new JsonResponse(["success" => true,"data" => $request->getContent(),]);}#[Route('/get/{id<^\w+$>}/{context}', name: 'app_skoverlay_get')]public function app_skoverlay_get (EntityManagerInterface $entityManager,Request $request,string $id,string $context = ""): Response {$core_config_data_repository = $entityManager->getRepository(CoreConfigData::class);$config_key = "app_coverage_engine_overlay";if ($id) $config_key .= "_{$id}";if ($context) $config_key .= "_{$context}";$config_key .= "_data";$processed = $core_config_data_repository->findOneBy(["config_key" => $config_key]);if (!$processed) {return new JsonResponse(["success" => false,"message" => "No configuration set for given string."]);}return new JsonResponse(["success" => true,"data" => json_decode($processed->getConfigValue())]);}#[Route('/edit/{engine<^\w+$>}/{id<^\w+$>}/{delay<\d+>}', name: 'app_skoverlay_edit')]public function app_skoverlay_edit ($engine = "anzid",$id = "ANZID",$delay = 10000): Response {$cardsearch = [];if ($engine == "cardoverlay") {$serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);$cardsearch = json_encode($serializer->decode(file_get_contents("library/fab_cardlist.csv"), "csv"));}return $this->render("sk_overlay/edit/{$engine}.html.twig", ["console" => $id,"delay" => $delay,"cardsearch" => $cardsearch,]);}#[Route('/view/{engine<^\w+$>}/{id<^\w+$>}/{delay<\d+>}', name: 'app_skoverlay_view')]public function app_skoverlay_view (Request $request,$engine = "anzid",$id = "ANZID",$delay = 10000): Response {$safari = $request->query->get("safari") ?: 0;return $this->render("sk_overlay/view/{$engine}.html.twig", ["console" => $id,"delay" => $delay,"safari" => $safari,"get" => $request->query->all()]);}#[Route('/cardsearch/{game}', name: 'app_skoverlay_cardsearch')]public function app_skoverlay_cardsearch (HttpClientInterface $client,Kernel $kernel,Request $request,CardImageService $cardImageService,#[Autowire('%env(PLAYERLINK_AC_TOURNAMENT_FORMAT)%')] string $tournamentFormat,$game = "fab"): Response {$query = $request->query->get("q");if (strlen($query) < 2) return new JsonResponse([]);if ($game === "lorcana") {$serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);$cardsearch = ($serializer->decode(file_get_contents("library/lorcana_cardlist.csv"), "csv"));return new JsonResponse($cardsearch);} else if ($game === "fab") {$serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);$cardsearch = ($serializer->decode(file_get_contents("library/fab_cardlist.csv"), "csv"));return new JsonResponse($cardsearch);} else {$req = null;if ($game === "mtgarena") {$req = "https://api.scryfall.com/cards/search?q=$query+(f:$tournamentFormat)";} else {$req = "https://api.scryfall.com/cards/search?include_extras=true&unique=prints&q=$query";}try {$response = $client->request('GET', $req, [// 'headers' => [// 'Accept' => 'application/json',// ],'timeout' => 5]);} catch (TransportExceptionInterface $e) {return new JsonResponse([]);}$json = json_decode($response->getContent());$response_json = [];if ($game === "mtgarena") {foreach ($json->data as $element) {$cardNameTemp = $element->name;$setCodeTemp = strtoupper($element->set);$cardNameArray = [];if (str_contains($cardNameTemp, "//")) {$cardNameArray = explode("//", $cardNameTemp);} else {$cardNameArray[] = $cardNameTemp;}$time = time();foreach ($cardNameArray as $cardName) {// Use CardImageService to get the card image URL (tries CDN first, falls back to local)$cardImageRelativePath = $cardImageService->getCardImageUrl(trim($cardName), $setCodeTemp);if (!property_exists($element, "image_uris") && !property_exists($element, "card_faces")) continue;$response_json[] = ["cardname" => explode("//", $cardName, 2)[0] . " (" . $element->set_name . ")","url" => $cardImageRelativePath];}}} else {foreach ($json->data as $element) {if (!property_exists($element, "image_uris")) continue;$cardImageRelativePath = $element->image_uris->png;$response_json[] = ["cardname" => $element->name . " (" . $element->set_name . ")","url" => $cardImageRelativePath];}}return new JsonResponse($response_json);}}#[Route('/playerview/{id}', name: 'app_skoverlay_playerview')]public function app_skoverlay_playerview ($id = 1943): Response {$serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);$demographics = ($serializer->decode(file_get_contents("library/fab_ptdemographics.csv"), "csv"));foreach ($demographics as $demographic) {if ($demographic["player_id"] == $id) {return $this->render("sk_overlay/view/playerview.html.twig", ["player" => $demographic]);}}var_dump($demographics);return new Response();}#[Route('/playerhistory/{id}', name: 'app_skoverlay_playerhistory')]public function app_skoverlay_playerhistory ($id = 1943): Response {$serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);$demographics = ($serializer->decode(file_get_contents("library/fab_ptdemographics.csv"), "csv"));foreach ($demographics as $demographic) {if ($demographic["player_id"] == $id) {$history = [];for ($i = 1; $i <= 14; $i++) {if (array_key_exists("m" . $i . "_opponent", $demographic)) {$history[$i] = ["round" => $i,"opponent" => $demographic["m" . $i . "_opponent"],"hero" => $demographic["m" . $i . "_opp_hero"],"result" => $demographic["m" . $i . "_result"],];}}return $this->render("sk_overlay/view/playerhistory.html.twig", ["player" => $demographic,"history" => $history,]);}}var_dump($demographics);return new Response();}#[Route('/standings/{page}', name: 'app_skoverlay_standings')]public function app_skoverlay_standings (Kernel $kernel,HttpClientInterface $httpClient,Request $request,EntityManagerInterface $entityManager,Int $page,): Response {$core_config_data_repository = $entityManager->getRepository(CoreConfigData::class);$config_key = "app_coverlay_eventdata";$value = $core_config_data_repository->findOneBy(["config_key" => $config_key]);$event_json = json_decode($value->getConfigValue());$round_id = ($event_json->standings_round);$standings_response = $httpClient->request('GET',$this->generateUrl("app_coverlay_fn_cachestandings", array("id" => $round_id),UrlGeneratorInterface::ABSOLUTE_URL));$json = json_decode($standings_response->getContent());return $this->render('c_overlay/view/magicanzid_standings.html.twig', ["standings" => array_slice($json, ($page - 1) * 16, 16),"page" => $page - 1,]);}#[Route('/standingsnyse/{round}/{page}', name: 'app_skoverlay_standingsnyse')]public function app_skoverlay_standingsnyse (Kernel $kernel,HttpClientInterface $httpClient,Request $request,EntityManagerInterface $entityManager,Int $round,Int $page,): Response {$standings_response = $httpClient->request('GET',$this->generateUrl("app_coverlay_fn_cachestandings", array("id" => $round),UrlGeneratorInterface::ABSOLUTE_URL));$json = json_decode($standings_response->getContent());return $this->render('c_overlay/view/magicnyse_standings.html.twig', ["standings" => array_slice($json, ($page - 1) * 16, 16),"page" => $page - 1,]);}#[Route('/newstandings/{page}/{round}', name: 'app_skoverlay_newstandings')]public function app_skoverlay_newstandings (Kernel $kernel,HttpClientInterface $httpClient,Request $request,EntityManagerInterface $entityManager,Int $page,Int $round = -1): Response {$standings_export_path = $this->getParameter('kernel.project_dir') . '/private/lorcana_standings.csv';$filesystem = new Filesystem();$standings = [];if ($filesystem->exists($standings_export_path)) {$standings_file = file_get_contents($standings_export_path);$encoder = new CsvEncoder();$standings = $encoder->decode($standings_file, "csv");}// $standings = [];//// for ($i = 1; $i < 100; $i++) {//// $standings[] = (object) [// "FirstName" => "Player",// "LastName" => "Player",// "Points" => 10// ];//// }return $this->render('c_overlay/view/lorcana_standings.html.twig', ["standings" => array_slice($standings, ($page - 1) * 16, 16),"page" => $page - 1,]);}private function usort_helper($a, $b) {if ($a < $b) { return 1; }if ($a > $b) { return -1; }return 0;}#[Route('/playerstowatch/{page}/{round}', name: 'app_skoverlay_playerstowatch')]public function app_skoverlay_playerstowatch (Kernel $kernel,HttpClientInterface $httpClient,Request $request,EntityManagerInterface $entityManager,Int $page,Int $round = -1): Response {$playerdata = $this->_getDecklistPlayerData();$core_config_data_repository = $entityManager->getRepository(CoreConfigData::class);$config_key = "app_coverlay_eventdata";$value = $core_config_data_repository->findOneBy(["config_key" => $config_key]);$event_json = json_decode($value->getConfigValue());$current_round = substr($event_json->broadcast_round,1);if ($round > -1) $current_round = $round;$current_round = max(1, $current_round - 1);$standings_api_path = $this->getParameter('kernel.project_dir') . '/private/tournament_standings_'.$current_round.'_api.json';$standings_export_path = $this->getParameter('kernel.project_dir') . '/private/tournament_standings_'.$current_round.'_export.csv';$filesystem = new Filesystem();$standings = [];if ($filesystem->exists($standings_export_path)) {$standings_file = file_get_contents($standings_export_path);$encoder = new CsvEncoder();$standings = $encoder->decode($standings_file, "csv");} else if ($filesystem->exists($standings_api_path)) {$standings_file = file_get_contents($standings_api_path);$encoder = new JsonEncoder();$standings = $encoder->decode($standings_file, "json");} else {}return $this->render('c_overlay/view/magicanzid_playerstowatch.html.twig', ["standings" => $standings,"playerlist" => ["Aintrazi, Ali","Anderson, Todd","Baeckstrom, Andrew","Brodie, Daniel",// "Bursavich, Austin","Clark, Mason","Corrigan, Michael","Kiihne, Zachary","Krueger, Will","Loveman, Eli","Malka, Sol","mcvety, max","Merriam, Ross","Nettles, Logan","Pardee, Carolyn","Pardee, Samuel","Rabin, Noah","Snook, Adam","Stein, Abraham","Steuer, Nathan","Syed, Zan","Taylor, Robert","Warfield, Skyler","Yu, Jarvis",]]);}#[Route('/archetypes/{page}/{format}', name: 'app_skoverlay_archetypes')]public function app_skoverlay_archetypes (Kernel $kernel,HttpClientInterface $httpClient,Request $request,EntityManagerInterface $entityManager,Int $page,$format = "Pioneer"): Response {$archetypes = [];$total = 0;$playerdata = $this->_getDecklistPlayerData();foreach ($playerdata as $player) {foreach ($player->Decklists as $decklist) {if ($decklist->Format == $format) {if (!array_key_exists($decklist->Name, $archetypes)) {$archetypes[$decklist->Name] = ["archetype" => $decklist->Name,"count" => 0,"percent" => 0,"keycards" => []];}$archetypes[$decklist->Name]["count"]++;$total++;}}}foreach ($archetypes as &$archetype) {$archetype["percent"] = $archetype["count"] / $total;}usort($archetypes, function($a, $b) {return $b["count"] - $a["count"];});return $this->render('c_overlay/view/magicanzid_archetypes.html.twig', ["archetypes" => array_slice($archetypes, ($page - 1) * 12, 12),"format" => $format]);}private function _getDecklistPlayerData() {$player_path = $this->getParameter('kernel.project_dir') . '/private/tournament_players.json';$player_file = file_get_contents($player_path);$player_json = json_decode($player_file);$players = [];foreach ($player_json as $element) {$players[$element->ID] = $element;}$decklist_path = $this->getParameter('kernel.project_dir') . '/private/tournament_decklists.json';$decklist_file = file_get_contents($decklist_path);$decklist_json = json_decode($decklist_file);foreach ($decklist_json as $element) {if (!array_key_exists($element->PlayerId, $players)) { continue; }foreach ($players[$element->PlayerId]->Decklists as $decklist) {if ($decklist->ID === $element->ID) {if ($element->Format == "Draft") {$colors = ["W" => false,"U" => false,"B" => false,"R" => false,"G" => false,];foreach ($element->Cards as $card) {if (!$card->IsSideboard) {foreach (["W", "U", "B", "R", "G"] as $color) {if (str_contains($card->CardManaCost, $color)) {$colors[$color] = true;}}}}$element->IsWhite = $colors["W"];$element->IsBlue = $colors["U"];$element->IsBlack = $colors["B"];$element->IsRed = $colors["R"];$element->IsGreen = $colors["G"];$element->White = $colors["W"] ? 1 : 0;$element->Blue = $colors["U"] ? 1 : 0;$element->Black = $colors["B"] ? 1 : 0;$element->Red = $colors["R"] ? 1 : 0;$element->Green = $colors["G"] ? 1 : 0;}$decklist->Decklist = $element;}}}ksort($players);return $players;}private function _getPlayerData() {$player_path = $this->getParameter('kernel.project_dir') . '/private/tournament_players.json';$player_file = file_get_contents($player_path);$player_json = json_decode($player_file);$players = [];foreach ($player_json as $element) {$players[$element->ID] = $element;}$decklist_path = $this->getParameter('kernel.project_dir') . '/private/tournament_decklists.json';$decklist_file = file_get_contents($decklist_path);$decklist_json = json_decode($decklist_file);if (!$decklist_json->Error) {foreach ($decklist_json as $element) {foreach ($players[$element->PlayerId]->Decklists as $decklist) {if ($decklist->ID === $element->ID) {$decklist->Decklist = $element;}}}}return $players;}#[Route('/anziddecklist/{match}/{player}', name: 'app_coverlay_anziddecklist')]public function app_coverlay_decksideboard (Kernel $kernel,HttpClientInterface $httpClient,Request $request,EntityManagerInterface $entityManager,String $match,String $player): Response {$core_config_data_repository = $entityManager->getRepository(CoreConfigData::class);$config_key = "app_coverlay_eventdata";$value = $core_config_data_repository->findOneBy(["config_key" => $config_key]);$event_json = json_decode($value->getConfigValue());$config_key = "app_coverlay_matchdata_" . $event_json->broadcast_round . "_m" .$match;$value = $core_config_data_repository->findOneBy(["config_key" => $config_key]);$match_json = json_decode($value->getConfigValue());$playerdata = $this->_getDecklistPlayerData();$deck = ["main" => [],"side" => []];$decklist_player = null;$colors = ["W" => false,"U" => false,"B" => false,"R" => false,"G" => false,];foreach ($playerdata[$match_json->{"p".$player."_name"}]->Decklists as $decklist) {if ($decklist->Format == $match_json->format) {$decklist_player = $decklist->Decklist;foreach (array_merge($decklist->Decklist->Cards, $decklist->Decklist->Sideboard) as $card) {if ($card->IsSideboard) {$deck["side"][] = ["cardname" => explode(" // ", $card->CardName)[0],"quantity" => $card->Quantity,];} else {$deck["main"][] = ["cardname" => explode(" // ", $card->CardName)[0],"quantity" => $card->Quantity,];foreach (["W", "U", "B", "R", "G"] as $color) {if (str_contains($card->CardManaCost, $color)) {$colors[$color] = true;}}}}}}if (strtoupper($decklist_player->Archetype) == "ALL OTHER DECKLISTS") {$decklist_player->Archetype = "";}return $this->render("c_overlay/view/magicanzid_decklist.html.twig", ["player" => $decklist_player,"decklist" => $deck,"colors" => $colors]);}}