src/Controller/SKOverlayController.php line 94

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\CoreConfigData;
  4. use App\Kernel;
  5. use Doctrine\ORM\EntityManagerInterface;
  6. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  7. use Symfony\Component\Filesystem\Filesystem;
  8. use Symfony\Component\Filesystem\Path;
  9. use Symfony\Component\Finder\Finder;
  10. use Symfony\Component\HttpFoundation\JsonResponse;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpFoundation\Response;
  13. use Symfony\Component\Mercure\HubInterface;
  14. use Symfony\Component\Mercure\Update;
  15. use Symfony\Component\Routing\Annotation\Route;
  16. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  17. use Symfony\Component\Serializer\Encoder\CsvEncoder;
  18. use Symfony\Component\Serializer\Encoder\JsonEncoder;
  19. use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
  20. use Symfony\Component\Serializer\Serializer;
  21. use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
  22. use Symfony\Contracts\HttpClient\HttpClientInterface;
  23. #[Route('/skoverlay')]
  24. class SKOverlayController extends AbstractController
  25. {
  26.     #[Route('/'name'app_skoverlay_index')]
  27.     public function app_skoverlay_index (
  28.     ): Response {
  29.         return $this->render("sk_overlay/index.html.twig");
  30.     }
  31.     #[Route('/set/{id<\w+>}/{context}'name'app_skoverlay_set')]
  32.     public function app_skoverlay_set (
  33.         EntityManagerInterface $entityManager,
  34.         Request $request,
  35.         string $id,
  36.         string $context ""
  37.     ): Response {
  38.         $core_config_data_repository $entityManager->getRepository(CoreConfigData::class);
  39.         $config_key "app_coverage_engine_overlay";
  40.         if ($id$config_key .= "_${id}";
  41.         if ($context$config_key .= "_${context}";
  42.         $config_key .= "_data";
  43.         $processed $core_config_data_repository->findOneBy([
  44.             "config_key" => $config_key
  45.         ]);
  46.         if (!$processed$processed = new CoreConfigData();
  47.         $processed->setConfigKey("app_coverage_engine_overlay_${id}_data")->setConfigValue($request->getContent());
  48.         $entityManager->persist($processed);
  49.         $entityManager->flush();
  50.         return new JsonResponse(
  51.             [
  52.                 "success" => true,
  53.             ]
  54.         );
  55.     }
  56.     #[Route('/push/{topic<\w+>}'name'app_skoverlay_push')]
  57.     public function app_skoverlay_push (
  58.         Request $request,
  59.         HubInterface $hub,
  60.         $topic "ANZID",
  61.     ): Response {
  62.         $update = new Update(
  63.             $topic,
  64.             $request->getContent()
  65.         );
  66.         $response $hub->publish($update);
  67.         return new JsonResponse(
  68.             [
  69.                 "success" => true,
  70.                 "data" => $request->getContent(),
  71.                 "response" => $response,
  72.             ]
  73.         );
  74.     }
  75.     #[Route('/get/{id<^\w+$>}/{context}'name'app_skoverlay_get')]
  76.     public function app_skoverlay_get (
  77.         EntityManagerInterface $entityManager,
  78.         Request $request,
  79.         string $id,
  80.         string $context ""
  81.     ): Response {
  82.         $core_config_data_repository $entityManager->getRepository(CoreConfigData::class);
  83.         $config_key "app_coverage_engine_overlay";
  84.         if ($id$config_key .= "_${id}";
  85.         if ($context$config_key .= "_${context}";
  86.         $config_key .= "_data";
  87.         $processed $core_config_data_repository->findOneBy([
  88.             "config_key" => $config_key
  89.         ]);
  90.         if (!$processed) {
  91.             return new JsonResponse(
  92.                 [
  93.                     "success" => false,
  94.                     "message" => "No configuration set for given string."
  95.                 ]
  96.             );
  97.         }
  98.         return new JsonResponse(
  99.             [
  100.                 "success" => true,
  101.                 "data" => json_decode($processed->getConfigValue())
  102.             ]
  103.         );
  104.     }
  105.     #[Route('/edit/{engine<^\w+$>}/{id<^\w+$>}/{delay<\d+>}'name'app_skoverlay_edit')]
  106.     public function app_skoverlay_edit (
  107.         $engine "anzid",
  108.         $id "ANZID",
  109.         $delay 10000
  110.     ): Response {
  111.         $cardsearch = [];
  112.         if ($engine == "cardoverlay") {
  113.             $serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);
  114.             $cardsearch json_encode($serializer->decode(file_get_contents("library/fab_cardlist.csv"), "csv"));
  115.         }
  116.         return $this->render("sk_overlay/edit/${engine}.html.twig", [
  117.             "console" => $id,
  118.             "delay" => $delay,
  119.             "cardsearch" => $cardsearch,
  120.         ]);
  121.     }
  122.     #[Route('/view/{engine<^\w+$>}/{id<^\w+$>}/{delay<\d+>}'name'app_skoverlay_view')]
  123.     public function app_skoverlay_view (
  124.         Request $request,
  125.         $engine "anzid",
  126.         $id "ANZID",
  127.         $delay 10000
  128.     ): Response {
  129.         $safari $request->query->get("safari") ?: 0;
  130.         return $this->render("sk_overlay/view/${engine}.html.twig", [
  131.             "console" => $id,
  132.             "delay" => $delay,
  133.             "safari" => $safari,
  134.             "get" => $request->query->all()
  135.         ]);
  136.     }
  137.     #[Route('/cardsearch/{game}'name'app_skoverlay_cardsearch')]
  138.     public function app_skoverlay_cardsearch (
  139.         HttpClientInterface $client,
  140.         Kernel $kernel,
  141.         Request $request,
  142.         $game "fab"
  143.     ): Response {
  144.         $query $request->query->get("q");
  145.         if (strlen($query) < 2) return new JsonResponse([]);
  146.         if ($game === "lorcana") {
  147.             $serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);
  148.             $cardsearch = ($serializer->decode(file_get_contents("library/lorcana_cardlist.csv"), "csv"));
  149.             return new JsonResponse($cardsearch);
  150.         } else if ($game === "fab") {
  151.             $serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);
  152.             $cardsearch = ($serializer->decode(file_get_contents("library/fab_cardlist.csv"), "csv"));
  153.             return new JsonResponse($cardsearch);
  154.         } else {
  155.             $req null;
  156.             if ($game === "mtgarena") {
  157.                 $req "https://api.scryfall.com/cards/search?q=$query+f%3Ahistoric";
  158.             } else {
  159.                 $req "https://api.scryfall.com/cards/search?include_extras=true&unique=prints&q=$query";
  160.             }
  161.             try {
  162.                 $response $client->request('GET'$req, [
  163. //                    'headers' => [
  164. //                        'Accept' => 'application/json',
  165. //                    ],
  166.                     'timeout' => 5
  167.                 ]);
  168.             } catch (TransportExceptionInterface $e) {
  169.                 return new JsonResponse([]);
  170.             }
  171.             $json json_decode($response->getContent());
  172.             $response_json = [];
  173.             if ($game === "mtgarena") {
  174.                 foreach ($json->data as $element) {
  175.                     $cardName $element->name;
  176.                     $cardNameCondensed explode("//"str_replace([" "",",], ""$cardName), 2)[0];
  177.                     $finder = new Finder();
  178.                     $finder->files()->in($kernel->getProjectDir() . "/public/images/assets/cards/mtgarena/*")->name("/.*" $cardNameCondensed ".*" "\.(jpg|png)/");
  179.                     if (!$finder->getIterator()->current()) {
  180.                         $cardNameCondensed trim(explode("//"$cardName2)[0]);
  181.                         $finder->files()->in($kernel->getProjectDir() . "/public/images/assets/cards/mtgarena/*")->name("/.*" $cardNameCondensed ".*" "\.(jpg|png)/");
  182.                     }
  183.                     if (!$finder->getIterator()->current()) {
  184.                         $cardNameCondensed trim(explode("//"str_replace(["'",], ""$cardName), 2)[0]);
  185.                         $finder->files()->in($kernel->getProjectDir() . "/public/images/assets/cards/mtgarena/*")->name("/.*" $cardNameCondensed ".*" "\.(jpg|png)/");
  186.                     }
  187.                     if (!$finder->getIterator()->current()) {
  188.                         $cardNameCondensed trim(explode("//"str_replace(["'"" "], ""$cardName), 2)[0]);
  189.                         $finder->files()->in($kernel->getProjectDir() . "/public/images/assets/cards/mtgarena/*")->name("/.*" $cardNameCondensed ".*" "\.(jpg|png)/");
  190.                     }
  191.                     if ($finder->getIterator()->current()) {
  192.                         $cardImageRelativePath "/" Path::makeRelative($finder->getIterator()->current(), $kernel->getProjectDir() . "/public/");
  193.                     } else {
  194.                         $cardImageRelativePath '/images/mtgarena-cardback.png';
  195.                     }
  196.                     if (!property_exists($element"image_uris")) continue;
  197.                     $response_json[] = [
  198.                         "cardname" => $element->name " (" $element->set_name ")",
  199.                         "url" => $cardImageRelativePath
  200.                     ];
  201.                 }
  202.             } else {
  203.                 foreach ($json->data as $element) {
  204.                     if (!property_exists($element"image_uris")) continue;
  205.                     $cardImageRelativePath $element->image_uris->png;
  206.                     $response_json[] = [
  207.                         "cardname" => $element->name " (" $element->set_name ")",
  208.                         "url" => $cardImageRelativePath
  209.                     ];
  210.                 }
  211.             }
  212.             return new JsonResponse($response_json);
  213.         }
  214.     }
  215.     #[Route('/playerview/{id}'name'app_skoverlay_playerview')]
  216.     public function app_skoverlay_playerview (
  217.         $id 1943
  218.     ): Response {
  219.         $serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);
  220.         $demographics = ($serializer->decode(file_get_contents("library/fab_ptdemographics.csv"), "csv"));
  221.         foreach ($demographics as $demographic) {
  222.             if ($demographic["player_id"] == $id) {
  223.                 return $this->render("sk_overlay/view/playerview.html.twig", [
  224.                     "player" => $demographic
  225.                 ]);
  226.             }
  227.         }
  228.         var_dump($demographics);
  229.         return new Response();
  230.     }
  231.     #[Route('/playerhistory/{id}'name'app_skoverlay_playerhistory')]
  232.     public function app_skoverlay_playerhistory (
  233.         $id 1943
  234.     ): Response {
  235.         $serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);
  236.         $demographics = ($serializer->decode(file_get_contents("library/fab_ptdemographics.csv"), "csv"));
  237.         foreach ($demographics as $demographic) {
  238.             if ($demographic["player_id"] == $id) {
  239.                 $history = [];
  240.                 for ($i 1$i <= 14$i++) {
  241.                     if (array_key_exists("m" $i "_opponent"$demographic)) {
  242.                         $history[$i] = [
  243.                             "round"    => $i,
  244.                             "opponent" => $demographic["m" $i "_opponent"],
  245.                             "hero"     => $demographic["m" $i "_opp_hero"],
  246.                             "result"   => $demographic["m" $i "_result"],
  247.                         ];
  248.                     }
  249.                 }
  250.                 return $this->render("sk_overlay/view/playerhistory.html.twig", [
  251.                     "player" => $demographic,
  252.                     "history" => $history,
  253.                 ]);
  254.             }
  255.         }
  256.         var_dump($demographics);
  257.         return new Response();
  258.     }
  259.     #[Route('/standings/{page}'name'app_skoverlay_standings')]
  260.     public function app_skoverlay_standings (
  261.         Kernel $kernel,
  262.         HttpClientInterface $httpClient,
  263.         Request $request,
  264.         EntityManagerInterface $entityManager,
  265.         Int $page,
  266.     ): Response {
  267.         $core_config_data_repository $entityManager->getRepository(CoreConfigData::class);
  268.         $config_key "app_coverlay_eventdata";
  269.         $value $core_config_data_repository->findOneBy([
  270.             "config_key" => $config_key
  271.         ]);
  272.         $event_json json_decode($value->getConfigValue());
  273.         $round_id = ($event_json->standings_round);
  274.         $standings_response $httpClient->request(
  275.             'GET',
  276.             $this->generateUrl("app_coverlay_fn_cachestandings", array("id" => $round_id),UrlGeneratorInterface::ABSOLUTE_URL
  277.             )
  278.         );
  279.         $json json_decode($standings_response->getContent());
  280.         return $this->render('c_overlay/view/magicanzid_standings.html.twig', [
  281.             "standings" => array_slice($json, ($page 1) * 1616),
  282.             "page" => $page 1,
  283.         ]);
  284.     }
  285.     #[Route('/standingsnyse/{round}/{page}'name'app_skoverlay_standingsnyse')]
  286.     public function app_skoverlay_standingsnyse (
  287.         Kernel $kernel,
  288.         HttpClientInterface $httpClient,
  289.         Request $request,
  290.         EntityManagerInterface $entityManager,
  291.         Int $round,
  292.         Int $page,
  293.     ): Response {
  294.         $standings_response $httpClient->request(
  295.             'GET',
  296.             $this->generateUrl("app_coverlay_fn_cachestandings", array("id" => $round),UrlGeneratorInterface::ABSOLUTE_URL
  297.             )
  298.         );
  299.         $json json_decode($standings_response->getContent());
  300.         return $this->render('c_overlay/view/magicnyse_standings.html.twig', [
  301.             "standings" => array_slice($json, ($page 1) * 1616),
  302.             "page" => $page 1,
  303.         ]);
  304.     }
  305.     #[Route('/newstandings/{page}/{round}'name'app_skoverlay_newstandings')]
  306.     public function app_skoverlay_newstandings (
  307.         Kernel $kernel,
  308.         HttpClientInterface $httpClient,
  309.         Request $request,
  310.         EntityManagerInterface $entityManager,
  311.         Int $page,
  312.         Int $round = -1
  313.     ): Response {
  314.         $standings_export_path $this->getParameter('kernel.project_dir') . '/private/lorcana_standings.csv';
  315.         $filesystem = new Filesystem();
  316.         $standings = [];
  317.         if ($filesystem->exists($standings_export_path)) {
  318.             $standings_file file_get_contents($standings_export_path);
  319.             $encoder = new CsvEncoder();
  320.             $standings $encoder->decode($standings_file"csv");
  321.         }
  322. //       $standings = [];
  323. //
  324. //       for ($i = 1; $i < 100; $i++) {
  325. //
  326. //           $standings[] = (object) [
  327. //               "FirstName" => "Player",
  328. //               "LastName" => "Player",
  329. //               "Points" => 10
  330. //           ];
  331. //
  332. //       }
  333.         return $this->render('c_overlay/view/lorcana_standings.html.twig', [
  334.             "standings" => array_slice($standings, ($page 1) * 1616),
  335.             "page" => $page 1,
  336.         ]);
  337.     }
  338.     private function usort_helper($a$b) {
  339.         if ($a $b) { return 1; }
  340.         if ($a $b) { return -1; }
  341.         return 0;
  342.     }
  343.     #[Route('/playerstowatch/{page}/{round}'name'app_skoverlay_playerstowatch')]
  344.     public function app_skoverlay_playerstowatch (
  345.         Kernel $kernel,
  346.         HttpClientInterface $httpClient,
  347.         Request $request,
  348.         EntityManagerInterface $entityManager,
  349.         Int $page,
  350.         Int $round = -1
  351.     ): Response {
  352.         $playerdata $this->_getDecklistPlayerData();
  353.         $core_config_data_repository $entityManager->getRepository(CoreConfigData::class);
  354.         $config_key "app_coverlay_eventdata";
  355.         $value $core_config_data_repository->findOneBy([
  356.             "config_key" => $config_key
  357.         ]);
  358.         $event_json json_decode($value->getConfigValue());
  359.         $current_round substr($event_json->broadcast_round,1);
  360.         if ($round > -1$current_round $round;
  361.         $current_round max(1$current_round 1);
  362.         $standings_api_path $this->getParameter('kernel.project_dir') . '/private/tournament_standings_'.$current_round.'_api.json';
  363.         $standings_export_path $this->getParameter('kernel.project_dir') . '/private/tournament_standings_'.$current_round.'_export.csv';
  364.         $filesystem = new Filesystem();
  365.         $standings = [];
  366.         if ($filesystem->exists($standings_export_path)) {
  367.             $standings_file file_get_contents($standings_export_path);
  368.             $encoder = new CsvEncoder();
  369.             $standings $encoder->decode($standings_file"csv");
  370.         } else if ($filesystem->exists($standings_api_path)) {
  371.             $standings_file file_get_contents($standings_api_path);
  372.             $encoder = new JsonEncoder();
  373.             $standings $encoder->decode($standings_file"json");
  374.         } else {
  375.         }
  376.         return $this->render('c_overlay/view/magicanzid_playerstowatch.html.twig', [
  377.             "standings" => $standings,
  378.             "playerlist" => [
  379.                 "Aintrazi, Ali",
  380.                 "Anderson, Todd",
  381.                 "Baeckstrom, Andrew",
  382.                 "Brodie, Daniel",
  383. //                "Bursavich, Austin",
  384.                 "Clark, Mason",
  385.                 "Corrigan, Michael",
  386.                 "Kiihne, Zachary",
  387.                 "Krueger, Will",
  388.                 "Loveman, Eli",
  389.                 "Malka, Sol",
  390.                 "mcvety, max",
  391.                 "Merriam, Ross",
  392.                 "Nettles, Logan",
  393.                 "Pardee, Carolyn",
  394.                 "Pardee, Samuel",
  395.                 "Rabin, Noah",
  396.                 "Snook, Adam",
  397.                 "Stein, Abraham",
  398.                 "Steuer, Nathan",
  399.                 "Syed, Zan",
  400.                 "Taylor, Robert",
  401.                 "Warfield, Skyler",
  402.                 "Yu, Jarvis",
  403.             ]
  404.         ]);
  405.     }
  406.     #[Route('/archetypes/{page}/{format}'name'app_skoverlay_archetypes')]
  407.     public function app_skoverlay_archetypes (
  408.         Kernel $kernel,
  409.         HttpClientInterface $httpClient,
  410.         Request $request,
  411.         EntityManagerInterface $entityManager,
  412.         Int $page,
  413.         $format "Pioneer"
  414.     ): Response {
  415.         $archetypes = [];
  416.         $total 0;
  417.         $playerdata $this->_getDecklistPlayerData();
  418.         foreach ($playerdata as $player) {
  419.             foreach ($player->Decklists as $decklist) {
  420.                 if ($decklist->Format == $format) {
  421.                     if (!array_key_exists($decklist->Name$archetypes)) {
  422.                         $archetypes[$decklist->Name] = [
  423.                             "archetype" => $decklist->Name,
  424.                             "count" => 0,
  425.                             "percent" => 0,
  426.                             "keycards" => []
  427.                         ];
  428.                     }
  429.                     $archetypes[$decklist->Name]["count"]++;
  430.                     $total++;
  431.                 }
  432.             }
  433.         }
  434.         foreach ($archetypes as &$archetype) {
  435.             $archetype["percent"] = $archetype["count"] / $total;
  436.         }
  437.         usort($archetypes, function($a$b) {
  438.             return $b["count"] - $a["count"];
  439.         });
  440.         return $this->render('c_overlay/view/magicanzid_archetypes.html.twig', [
  441.             "archetypes" => array_slice($archetypes, ($page 1) * 1212),
  442.             "format" => $format
  443.         ]);
  444.     }
  445.     private function _getDecklistPlayerData() {
  446.         $player_path $this->getParameter('kernel.project_dir') . '/private/tournament_players.json';
  447.         $player_file file_get_contents($player_path);
  448.         $player_json json_decode($player_file);
  449.         $players = [];
  450.         foreach ($player_json as $element) {
  451.             $players[$element->ID] = $element;
  452.         }
  453.         $decklist_path $this->getParameter('kernel.project_dir') . '/private/tournament_decklists.json';
  454.         $decklist_file file_get_contents($decklist_path);
  455.         $decklist_json json_decode($decklist_file);
  456.         foreach ($decklist_json as $element) {
  457.             if (!array_key_exists($element->PlayerId$players)) { continue; }
  458.             foreach ($players[$element->PlayerId]->Decklists as $decklist) {
  459.                 if ($decklist->ID === $element->ID) {
  460.                     if ($element->Format == "Draft") {
  461.                         $colors = [
  462.                             "W" => false,
  463.                             "U" => false,
  464.                             "B" => false,
  465.                             "R" => false,
  466.                             "G" => false,
  467.                         ];
  468.                         foreach ($element->Cards as $card) {
  469.                             if (!$card->IsSideboard) {
  470.                                 foreach (["W""U""B""R""G"] as $color) {
  471.                                     if (str_contains($card->CardManaCost$color)) {
  472.                                         $colors[$color] = true;
  473.                                     }
  474.                                 }
  475.                             }
  476.                         }
  477.                         $element->IsWhite $colors["W"];
  478.                         $element->IsBlue  $colors["U"];
  479.                         $element->IsBlack $colors["B"];
  480.                         $element->IsRed   $colors["R"];
  481.                         $element->IsGreen $colors["G"];
  482.                         $element->White $colors["W"] ? 0;
  483.                         $element->Blue  $colors["U"] ? 0;
  484.                         $element->Black $colors["B"] ? 0;
  485.                         $element->Red   $colors["R"] ? 0;
  486.                         $element->Green $colors["G"] ? 0;
  487.                     }
  488.                     $decklist->Decklist $element;
  489.                 }
  490.             }
  491.         }
  492.         ksort($players);
  493.         return $players;
  494.     }
  495.     private function _getPlayerData() {
  496.         $player_path $this->getParameter('kernel.project_dir') . '/private/tournament_players.json';
  497.         $player_file file_get_contents($player_path);
  498.         $player_json json_decode($player_file);
  499.         $players = [];
  500.         foreach ($player_json as $element) {
  501.             $players[$element->ID] = $element;
  502.         }
  503.         $decklist_path $this->getParameter('kernel.project_dir') . '/private/tournament_decklists.json';
  504.         $decklist_file file_get_contents($decklist_path);
  505.         $decklist_json json_decode($decklist_file);
  506.         if (!$decklist_json->Error) {
  507.             foreach ($decklist_json as $element) {
  508.                 foreach ($players[$element->PlayerId]->Decklists as $decklist) {
  509.                     if ($decklist->ID === $element->ID) {
  510.                         $decklist->Decklist $element;
  511.                     }
  512.                 }
  513.             }
  514.         }
  515.         return $players;
  516.     }
  517.     #[Route('/anziddecklist/{match}/{player}'name'app_coverlay_anziddecklist')]
  518.     public function app_coverlay_decksideboard (
  519.         Kernel $kernel,
  520.         HttpClientInterface $httpClient,
  521.         Request $request,
  522.         EntityManagerInterface $entityManager,
  523.         String $match,
  524.         String $player
  525.     ): Response {
  526.         $core_config_data_repository $entityManager->getRepository(CoreConfigData::class);
  527.         $config_key "app_coverlay_eventdata";
  528.         $value $core_config_data_repository->findOneBy([
  529.             "config_key" => $config_key
  530.         ]);
  531.         $event_json json_decode($value->getConfigValue());
  532.         $config_key "app_coverlay_matchdata_" $event_json->broadcast_round "_m" .$match;
  533.         $value $core_config_data_repository->findOneBy([
  534.             "config_key" => $config_key
  535.         ]);
  536.         $match_json json_decode($value->getConfigValue());
  537.         $playerdata $this->_getDecklistPlayerData();
  538.         $deck = [
  539.             "main" => [],
  540.             "side" => []
  541.         ];
  542.         $decklist_player null;
  543.         $colors = [
  544.             "W" => false,
  545.             "U" => false,
  546.             "B" => false,
  547.             "R" => false,
  548.             "G" => false,
  549.         ];
  550.         foreach ($playerdata[$match_json->{"p".$player."_name"}]->Decklists as $decklist) {
  551.             if ($decklist->Format == $match_json->format) {
  552.                 $decklist_player $decklist->Decklist;
  553.                 foreach (array_merge($decklist->Decklist->Cards$decklist->Decklist->Sideboard) as $card) {
  554.                     if ($card->IsSideboard) {
  555.                         $deck["side"][] = [
  556.                             "cardname" => explode(" // "$card->CardName)[0],
  557.                             "quantity" => $card->Quantity,
  558.                         ];
  559.                     } else {
  560.                         $deck["main"][] = [
  561.                             "cardname" => explode(" // "$card->CardName)[0],
  562.                             "quantity" => $card->Quantity,
  563.                         ];
  564.                         foreach (["W""U""B""R""G"] as $color) {
  565.                             if (str_contains($card->CardManaCost$color)) {
  566.                                 $colors[$color] = true;
  567.                             }
  568.                         }
  569.                     }
  570.                 }
  571.             }
  572.         }
  573.         if (strtoupper($decklist_player->Archetype) == "ALL OTHER DECKLISTS") {
  574.             $decklist_player->Archetype "";
  575.         }
  576.         return $this->render("c_overlay/view/magicanzid_decklist.html.twig", [
  577.             "player" => $decklist_player,
  578.             "decklist" => $deck,
  579.             "colors" => $colors
  580.         ]);
  581.     }
  582. }