From 090985b931cd18307f69fb5fd175e89670f4e6dd Mon Sep 17 00:00:00 2001 From: Benjamin Kraft Date: Sun, 2 Jun 2024 15:56:05 +0200 Subject: [PATCH] ugly display, can update elo and riot id --- public/elotracker/RiotRequest.php | 70 ++++++++++++ public/elotracker/Tracker.php | 180 ++++++++++++++++++++++++++++++ public/elotracker/index.php | 18 ++- public/elotracker/update.php | 6 + public/favicon.ico | Bin 0 -> 41662 bytes public/util/dotenv.php | 1 + 6 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 public/elotracker/RiotRequest.php create mode 100644 public/elotracker/Tracker.php create mode 100644 public/elotracker/update.php create mode 100644 public/favicon.ico diff --git a/public/elotracker/RiotRequest.php b/public/elotracker/RiotRequest.php new file mode 100644 index 0000000..30b8784 --- /dev/null +++ b/public/elotracker/RiotRequest.php @@ -0,0 +1,70 @@ +endpoint = $endpoint; + } + + public function useRouting(): void { + $this->host = "https://europe.api.riotgames.com"; + } + + public function setHeaders($headers): void { + $this->headers = $headers; + } + + public function setQueries($queries): void { + $this->queries = $queries; + } + + protected function getHeaderString(): string { + $api_key = getenv("RIOT_API_KEY"); + $header = "X-Riot-Token: $api_key\r\n"; + foreach ($this->headers as $key => $value) { + $header .= "$key: $value\r\n"; + } + return $header; + } + + private function getFinalURL(): string { + $queryString = "?"; + foreach ($this->queries as $key => $value) { + $queryString .= "$key=$value&"; + } + $url = $this->host . "/" . $this->endpoint . $queryString; + return str_replace(" ", "", $url); + } + + public function run() { + $opts = [ + "http" => [ + "method" => "GET", + "header" => $this->getHeaderString() + ] + ]; + $context = stream_context_create($opts); + $url = $this->getFinalURL(); + $result = @file_get_contents($url, false, $context); + $this->responseHeader = $http_response_header; + preg_match_all("/HTTP\/\d\.\d\s+(\d+)\s+/", $this->responseHeader[0], $matches); + $this->responseCode = intval($matches[1][0]); + + if ($this->responseCode == 404 && !$this->triedEUNE) { + $this->host = "https://eun1.api.riotgames.com"; + $this->triedEUNE = true; + return $this->run(); + } + + return json_decode($result); + } + +} \ No newline at end of file diff --git a/public/elotracker/Tracker.php b/public/elotracker/Tracker.php new file mode 100644 index 0000000..cfc6da6 --- /dev/null +++ b/public/elotracker/Tracker.php @@ -0,0 +1,180 @@ +conn = new MySQLConnection(); + $this->readAccounts(); + $this->readEntries(); + } + + private function readAccounts(): void { + $accounts = []; + + $sql = $this->conn->query("SELECT * FROM `accounts`"); + while ($row = $sql->fetch_assoc()) { + $account = new Account(); + $account->puuid = $row["puuid"]; + $account->gameName = $row["gameName"]; + $account->tagLine = $row["tagLine"]; + + $accounts[$account->puuid] = $account; + } + + $this->accounts = $accounts; + } + + private function readEntries(): void { + $sql = $this->conn->query(" + SELECT accounts.puuid AS puuid, date, tier, `rank`, points + FROM accounts LEFT JOIN elo_entries ON id = accountId + ORDER BY accounts.puuid, date + "); + + $result = []; + + while ($row = $sql->fetch_assoc()) { + $puuid = $row["puuid"]; + $date = $row["date"]; + + if (!isset($result[$puuid])) + $result[$puuid] = []; + + if (!$date) + continue; + + $elo = new Elo(); + $elo->tier = $row["tier"]; + $elo->rank = $row["rank"]; + $elo->points = $row["points"]; + + $result[$puuid][$date] = $elo; + } + + $this->entries = $result; + } + + public function update(): void { + + foreach ($this->accounts as $puuid => $account) { + $account->updateRiotID(); + $account->addNewEloEntry($this->entries[$puuid]); + } + + } +} + +class Account { + public string $puuid; + public string $gameName; + public string $tagLine; + + /** + * @param Elo[] $eloEntries + */ + public function addNewEloEntry(array &$eloEntries): void { + $summonerId = (new RiotRequest("lol/summoner/v4/summoners/by-puuid/$this->puuid"))->run()->id; + $fetchedLeagues = (new RiotRequest("lol/league/v4/entries/by-summoner/$summonerId"))->run(); + + $currentElo = end($eloEntries); + + foreach ($fetchedLeagues as $fetchedElo) { + if ($fetchedElo->queueType === "RANKED_SOLO_5x5" && ($fetchedElo->wins + $fetchedElo->losses >= 5)) { + if (!$currentElo || + $currentElo->tier !== $fetchedElo->tier || + $currentElo->rank !== $fetchedElo->rank || + $currentElo->points !== $fetchedElo->leaguePoints){ + + $currentElo = new Elo(); + $currentElo->tier = $fetchedElo->tier; + $currentElo->rank = $fetchedElo->rank; + $currentElo->points = $fetchedElo->leaguePoints; + + $date = (new DateTime("now"))->format("Y-m-d H:i:s"); + $eloEntries[$date] = $currentElo; + + $conn = new MySQLConnection(); + + $sqlAccountId = $conn->query(" + SELECT id + FROM `accounts` + WHERE puuid = '$this->puuid' + ")->fetch_assoc()["id"]; + + $conn->prepare(" + INSERT INTO `elo_entries` + (accountId, date, tier, `rank`, points) + VALUES (?, ?, ?, ?, ?) + ")->execute([ + $sqlAccountId, $date, $currentElo->tier, $currentElo->rank, $currentElo->points + ]); + } + } + } + } + public function updateRiotID(): void { + $request = new RiotRequest("riot/account/v1/accounts/by-puuid/$this->puuid"); + $request->useRouting(); + $result = $request->run(); + if ($request->responseCode == 200) { + $this->gameName = $result->gameName; + $this->tagLine = $result->tagLine; + + $conn = new MySQLConnection(); + $conn->query(" + UPDATE `accounts` + SET `gameName` = '$this->gameName', `tagLine` = '$this->tagLine' + WHERE `puuid` = '$this->puuid' + "); + + } + } +} + +class Elo { + public string $tier; + public string $rank; + public int $points; + public function value() : int { + $tiers = [ + "CHALLENGER" => 2800, + "GRANDMASTER" => 2800, + "MASTER" => 2800, + "DIAMOND" => 2400, + "EMERALD" => 2000, + "PLATINUM" => 1600, + "GOLD" => 1200, + "SILVER" => 800, + "BRONZE" => 400, + "IRON" => 0, + ]; + + $ranks = [ + "I" => 300, + "II" => 200, + "III" => 100, + "IV" => 0, + ]; + + $tier = $this->tier; + + if ($tier === "MASTER" || $tier === "GRANDMASTER" || $tier === "CHALLENGER") + return $tiers[$tier] + $this->points; + + return $tiers[$tier] + $ranks[$this->rank] + $this->points; + } +} diff --git a/public/elotracker/index.php b/public/elotracker/index.php index 744956e..6707cea 100644 --- a/public/elotracker/index.php +++ b/public/elotracker/index.php @@ -7,8 +7,22 @@ accounts as $puuid => $account){ + $entries = $tracker->entries[$puuid]; + + if (sizeof($entries) > 0){ + echo "

$account->gameName#$account->tagLine

"; + foreach ($entries as $date => $elo){ + $eloValue = $elo->value(); + echo "$date = $eloValue
"; + } + } +} ?> diff --git a/public/elotracker/update.php b/public/elotracker/update.php new file mode 100644 index 0000000..36eace0 --- /dev/null +++ b/public/elotracker/update.php @@ -0,0 +1,6 @@ +update(); \ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..abf2c62a7803b22b5969671a8084817dfbf507d7 GIT binary patch literal 41662 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

cVmngk`NELak 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 $value) putenv("$key=$value"); +unset($key, $value);