<?php
namespace App\Controller;
use App\Entity\CoreConfigData;
use App\Kernel;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
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 Symfony\Component\Mercure\HubInterface;
use Symfony\Component\Mercure\Update;
use Symfony\Component\Routing\Annotation\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,
HubInterface $hub,
$topic = "ANZID",
): Response {
$update = new Update(
$topic,
$request->getContent()
);
$response = $hub->publish($update);
return new JsonResponse(
[
"success" => true,
"data" => $request->getContent(),
"response" => $response,
]
);
}
#[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,
$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%3Ahistoric";
} 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) {
$cardName = $element->name;
$cardNameCondensed = explode("//", str_replace([" ", ",",], "", $cardName), 2)[0];
$finder = new Finder();
$finder->files()->in($kernel->getProjectDir() . "/public/images/assets/cards/mtgarena/*")->name("/.*" . $cardNameCondensed . ".*" . "\.(jpg|png)/");
if (!$finder->getIterator()->current()) {
$cardNameCondensed = trim(explode("//", $cardName, 2)[0]);
$finder->files()->in($kernel->getProjectDir() . "/public/images/assets/cards/mtgarena/*")->name("/.*" . $cardNameCondensed . ".*" . "\.(jpg|png)/");
}
if (!$finder->getIterator()->current()) {
$cardNameCondensed = trim(explode("//", str_replace(["'",], "", $cardName), 2)[0]);
$finder->files()->in($kernel->getProjectDir() . "/public/images/assets/cards/mtgarena/*")->name("/.*" . $cardNameCondensed . ".*" . "\.(jpg|png)/");
}
if (!$finder->getIterator()->current()) {
$cardNameCondensed = trim(explode("//", str_replace(["'", " "], "", $cardName), 2)[0]);
$finder->files()->in($kernel->getProjectDir() . "/public/images/assets/cards/mtgarena/*")->name("/.*" . $cardNameCondensed . ".*" . "\.(jpg|png)/");
}
if ($finder->getIterator()->current()) {
$cardImageRelativePath = "/" . Path::makeRelative($finder->getIterator()->current(), $kernel->getProjectDir() . "/public/");
} else {
$cardImageRelativePath = '/images/mtgarena-cardback.png';
}
if (!property_exists($element, "image_uris")) continue;
$response_json[] = [
"cardname" => $element->name . " (" . $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
]);
}
}