diff --git a/CheckForMostPlayedJob.php b/CheckForMostPlayedJob.php new file mode 100644 index 0000000..f7eeb82 --- /dev/null +++ b/CheckForMostPlayedJob.php @@ -0,0 +1,20 @@ +queryData($queryQueue); + + $queryGetNew = "SELECT * from queueMostPlayed where state = 'waiting' order by queue_id asc"; + $waitingUsers = $database->queryData($queryGetNew); + + if($waitingUsers != null) { + getPlays(); + } + sleep(1); +} \ No newline at end of file diff --git a/CheckForScoreFetchJob.php b/CheckForScoreFetchJob.php new file mode 100644 index 0000000..b410cc0 --- /dev/null +++ b/CheckForScoreFetchJob.php @@ -0,0 +1,20 @@ +queryData($queryQueue); + + $queryGetNew = "SELECT * from queueUserScores where state = 'waiting' order by queue_id asc"; + $waitingUsers = $database->queryData($queryGetNew); + + if($waitingUsers != null) { + getScores(); + } + sleep(1); +} \ No newline at end of file diff --git a/CheckMutualMaps.php b/CheckMutualMaps.php new file mode 100644 index 0000000..0ae6b35 --- /dev/null +++ b/CheckMutualMaps.php @@ -0,0 +1,24 @@ + (string)$player1, + "player_2" => (string)$player2 + ]; + + return $database->queryData2($query, $binds); + } +} \ No newline at end of file diff --git a/GetComparableScores.php b/GetComparableScores.php new file mode 100644 index 0000000..c3c862c --- /dev/null +++ b/GetComparableScores.php @@ -0,0 +1,100 @@ + $player1, + "player2" => $player2 + ]; + + $result = $database->queryData2($query, $binds); + + if (!$result || count($result) === 0) { + echo json_encode(["error" => "no mutual beatmap where player1 < player2"], JSON_PRETTY_PRINT); + return; + } + + header('Content-Type: application/json; charset=utf-8'); + + if($random == 1) { + header('Content-Type: application/json; charset=utf-8'); + echo json_encode([ + "map_id" => $result[0]['map_id'], + "player" => [ + "user_id" => $result[0]['user_player'], + "score" => $result[0]['score_player'], + "maxcombo" => $result[0]['maxcombo_player'], + "perfect" => $result[0]['perfect_player'], + "date" => $result[0]['date_player'], + "rank" => $result[0]['rank_player'], + "mods" => $result[0]['mods_player'] + ], + "target" => [ + "user_id" => $result[0]['user_target'], + "score" => $result[0]['score_target'], + "maxcombo" => $result[0]['maxcombo_target'], + "perfect" => $result[0]['perfect_target'], + "date" => $result[0]['date_target'], + "rank" => $result[0]['rank_target'], + "mods" => $result[0]['mods_target'] + ] + ], JSON_PRETTY_PRINT); + } else { + $originalCount = count($result); + for ($i = 0; $i < $originalCount; $i++) { + $output[] = [ + "map_id" => $result[$i]['map_id'], + "player" => [ + "user_id" => $result[$i]['user_player'], + "score" => $result[$i]['score_player'], + "maxcombo" => $result[$i]['maxcombo_player'], + "perfect" => $result[$i]['perfect_player'], + "date" => $result[$i]['date_player'], + "rank" => $result[$i]['rank_player'], + "mods" => $result[$i]['mods_player'] + ], + "target" => [ + "user_id" => $result[$i]['user_target'], + "score" => $result[$i]['score_target'], + "maxcombo" => $result[$i]['maxcombo_target'], + "perfect" => $result[$i]['perfect_target'], + "date" => $result[$i]['date_target'], + "rank" => $result[$i]['rank_target'], + "mods" => $result[$i]['mods_target'] + ] + ]; + } + echo json_encode($output, JSON_PRETTY_PRINT); + } +} \ No newline at end of file diff --git a/GetUserMostPlayed.php b/GetUserMostPlayed.php new file mode 100644 index 0000000..6b5af89 --- /dev/null +++ b/GetUserMostPlayed.php @@ -0,0 +1,109 @@ +queryData($queryQueue); + + while (count(array_filter($queue, fn($q) => $q['state'] !== 'finished')) > 0) { + for ($i = 0; $i < count($queue); $i++) { + $players = [$queue[$i]['user_id1'], $queue[$i]['user_id2']]; + $offsets = [ + $queue[$i]['offset_player1'], + $queue[$i]['offset_player2'] + ]; + + $updateStatus = "UPDATE status set process_description = :process_description, value3 = :value3 where value1 = :value1 and value2 = :value2"; + $BindsStatusU = [ + "value3" => "processing_maps", + "value1" => $players[0], + "value2" => $players[1], + "process_description" => "Fetching most played Beatmaps for user " . $players[0] . " and " . $players[1] + ]; + + $database->queryData2($updateStatus, $BindsStatusU); + + $queryStatusU = "UPDATE queueMostPlayed set state = 'processing' where user_id1 = :value1 and user_id2 = :value2"; + $bindsStatusU = [ + "value1" => $players[0], + "value2" => $players[1] + ]; + + $database->queryData2($queryStatusU, $bindsStatusU); + + $done1 = requestMapAndWriteToDB($players, $offsets, 0); + $done2 = requestMapAndWriteToDB($players, $offsets, 1); + + if ($done1 === false && $done2 === false) { + $setFinishedStatusQ = "UPDATE queueMostPlayed SET state = 'finished' WHERE user_id1 = :user_id1 AND user_id2 = :user_id2"; + $setFinishedStatusB = [ + "user_id1" => $players[0], + "user_id2" => $players[1] + ]; + $database->queryData2($setFinishedStatusQ, $setFinishedStatusB); + + $updateStatus = "UPDATE status set process_description = 'Fetching most played maps from both users finished', value3 = :value3 where value1 = :value1 and value2 = :value2"; + $BindsStatusU = [ + "value3" => "finished", + "value1" => $players[0], + "value2" => $players[1] + ]; + + $database->queryData2($updateStatus, $BindsStatusU); + echo "Beide Spieler fertig, Queue-Eintrag abgeschlossen.\n"; + } + } + + $queue = $database->queryData($queryQueue); + } + } +} + +if (!function_exists("requestMapAndWriteToDB")) { + function requestMapAndWriteToDB($players, &$offsets, $player) { + global $database; + + $score_url = "https://osu.ppy.sh/users/" . $players[$player] . "/beatmapsets/most_played?limit=100&offset=" . $offsets[$player]; + + $response = @file_get_contents($score_url); + $ParsedResponse = json_decode($response, true); + + if (empty($ParsedResponse) || !is_array($ParsedResponse)) { + echo "Keine weiteren Maps für Spieler " . $players[$player] . "\n"; + return false; + } + + $offsets[$player] += count($ParsedResponse); + + $queueUpdate = "UPDATE queueMostPlayed + SET offset_player1 = :offset_player1, offset_player2 = :offset_player2 + WHERE user_id1 = :user_id1 AND user_id2 = :user_id2"; + $bindsQueue = [ + "offset_player1" => $offsets[0], + "offset_player2" => $offsets[1], + "user_id1" => $players[0], + "user_id2" => $players[1] + ]; + $database->queryData2($queueUpdate, $bindsQueue); + + $insertMapsQ = "INSERT INTO UserMostPlayed (user_id, map_id) VALUES (:user_id, :map_id)"; + foreach ($ParsedResponse as $entry) { + $insertMapsB = [ + "user_id" => $players[$player], + "map_id" => $entry['beatmap_id'] + ]; + $database->queryData2($insertMapsQ, $insertMapsB); + } + + $maps = array_column($ParsedResponse, "beatmap_id"); + + sleep(1); + return true; + } +} \ No newline at end of file diff --git a/RequestMutualScores.php b/RequestMutualScores.php new file mode 100644 index 0000000..891448c --- /dev/null +++ b/RequestMutualScores.php @@ -0,0 +1,142 @@ +queryData($queryQueue); + + while (count(array_filter($queue, fn($q) => $q['state'] !== 'finished')) > 0) { + for ($i = 0; $i < count($queue); $i++) { + $players = [$queue[$i]['user_id1'], $queue[$i]['user_id2']]; + $offsets = [ + $queue[$i]['offset_player1'], + $queue[$i]['offset_player2'] + ]; + + $offsets[0]++; + $offsets[1]++; + + $updateStatusQ = "UPDATE status set value3 = 'processing_scores', process_description = 'Fetching scores for both users' where value1 = :value1 and value2 = :value2"; + $updateStatusB = [ + "value1" => $players[0], + "value2" => $players[1] + ]; + $database->queryData2($updateStatusQ, $updateStatusB); + + $maps = CheckMutualMaps($players[0], $players[1]); + + $queryStatusU = "UPDATE queueUserScores set state = 'processing', progress = :progress, offset_player1 = :offset_player1, offset_player2 = :offset_player2 where user_id1 = :value1 and user_id2 = :value2"; + $bindsStatusU = [ + "value1" => $players[0], + "value2" => $players[1], + "offset_player1" => $offsets[0], + "offset_player2" => $offsets[1], + "progress" => $offsets[1] . " / " . count($maps) + ]; + $database->queryData2($queryStatusU, $bindsStatusU); + + if (isset($maps[$offsets[0]])) { + requestScoresAndWriteToDB($players[0], $maps[$offsets[0]]['map_id']); + } + + if (isset($maps[$offsets[1]])) { + requestScoresAndWriteToDB($players[1], $maps[$offsets[1]]['map_id']); + } + + if (($offsets[0] >= count($maps)) && ($offsets[1] >= count($maps))) { + $setFinishedStatusQ = "UPDATE queueUserScores SET state = 'finished' WHERE user_id1 = :user_id1 AND user_id2 = :user_id2"; + $setFinishedStatusB = [ + "user_id1" => $players[0], + "user_id2" => $players[1], + ]; + $database->queryData2($setFinishedStatusQ, $setFinishedStatusB); + + $deleteFinished = "DELETE FROM queueMostPlayed WHERE user_id1 = :user_id1 AND user_id2 = :user_id2"; + $deleteBinds = [ + "user_id1" => $players[0], + "user_id2" => $players[1] + ]; + $database->queryData2($deleteFinished, $deleteBinds); + + $updateStatus = "UPDATE status set value3 = :value3, process_description = 'finished fetching scores on mutual beatmaps' where value1 = :value1 and value2 = :value2"; + $BindsStatusU = [ + "value3" => "finished", + "value1" => $players[0], + "value2" => $players[1] + ]; + + $database->queryData2($updateStatus, $BindsStatusU); + + echo "Beide Spieler fertig, Queue-Eintrag abgeschlossen.\n"; + continue; + } + } + + $queue = $database->queryData($queryQueue); + } + } +} + +if(!function_exists("requestScoresAndWriteToDB")) { + function requestScoresAndWriteToDB($userid, $map) { + global $database; + + sleep(1); + $score_url = "https://osu.ppy.sh/api/get_scores?k=" . OSUKEY . "&b=" . $map . "&u=" . $userid; + + $response = @file_get_contents($score_url); + $ParsedResponse = json_decode($response, true); + + if (!isset($ParsedResponse[0]['score_id'])) { + echo "score nicht gefunden \n"; + return; + } + + $score_id = (int)$ParsedResponse[0]['score_id']; + + $checkQuery = "SELECT COUNT(*) AS cnt FROM UserScores WHERE score_id = :score_id"; + $checkBinds = ['score_id' => $score_id]; + $checkResult = $database->queryData2($checkQuery, $checkBinds); + $exists = isset($checkResult[0]['cnt']) && $checkResult[0]['cnt'] > 0; + + if ($exists) { + echo "score $score_id existiert schon\n"; + return; + } + + $query = "INSERT INTO UserScores + (score_id, score, maxcombo, user_id, perfect, date, rank, enabled_mods, map_id) + VALUES + (:score_id, :score, :maxcombo, :user_id, :perfect, :date, :rank, :enabled_mods, :map_id) + ON DUPLICATE KEY UPDATE + score = VALUES(score), + maxcombo = VALUES(maxcombo), + user_id = VALUES(user_id), + perfect = VALUES(perfect), + date = VALUES(date), + rank = VALUES(rank), + enabled_mods = VALUES(enabled_mods), + map_id = VALUES(map_id)"; + + + $binds = [ + "score_id" => $score_id, + "score" => (int)$ParsedResponse[0]['score'], + "maxcombo" => (int)$ParsedResponse[0]['maxcombo'], + "user_id" => (int)$ParsedResponse[0]['user_id'], + "perfect" => (int)$ParsedResponse[0]['perfect'], + "date" => $ParsedResponse[0]['date'], + "rank" => $ParsedResponse[0]['rank'], + "enabled_mods" => (int)$ParsedResponse[0]['enabled_mods'], + "map_id" => (int)$map + ]; + + $database->queryData2($query, $binds); + echo "score $score_id eingefügt\n"; + } +} \ No newline at end of file diff --git a/database.php b/database.php new file mode 100644 index 0000000..39fc9b4 --- /dev/null +++ b/database.php @@ -0,0 +1,45 @@ +pdo = new PDO($dsn, $user, $psswd); + $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + } catch (PDOException $e) { + + echo "Verbindung fehlgeschlagen."; + } + } + + public function rows(): int { // returns count of rows of select in current instance + return $this->rows; + } + + public function queryData($query) { // deprecated + $stmt = $this->pdo->query($query); + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + public function queryData2($query, $binds) { // prepared + $stmt = $this->pdo->prepare($query); + + foreach ($binds as $param => $value) { + $stmt->bindValue($param, $value); + } + + $stmt->execute(); + $this->rows = $stmt->rowCount(); + + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } + } +} + +?> diff --git a/snipe.php b/snipe.php new file mode 100644 index 0000000..8b3906f --- /dev/null +++ b/snipe.php @@ -0,0 +1,60 @@ + $player1, + "value2" => $player2 +]; + +$status = $database->queryData2($queryStatus, $bindsStatus); + +if($status[0]['value3'] == 'finished' || $status[0]['value3'] == 'processing_scores') { + getScore($player1, $player2, $random); + +} else if($status[0]['value3'] == 'processing_maps') { + + header('Content-Type: application/json; charset=utf-8'); + echo json_encode(["status" => "processing", "state" => $status[0]['process_description']]); + +} else if($status[0]['value3'] == 'waiting') { + + header('Content-Type: application/json; charset=utf-8'); + echo json_encode(["status" => "processing", "state" => $status[0]['process_description']]); + +} else { + + $query = "SELECT (select count(1) from UserScores where user_id = :player1) as exist_user1, (select count(1) from UserScores where user_id = :player2) as exist_user2"; + $binds = [ + "player1" => $player1, + "player2" => $player2 + ]; + + $status = $database->queryData2($query, $binds); + + if($status[0]['exist_user1'] <= 0 || $status[0]['exist_user2'] <= 0) { + + header('Content-Type: application/json; charset=utf-8'); + echo json_encode(["message" => "User(s) not found, starting to fetch mutual scores"]); + + $queryStatus = "INSERT into status (process_name, process_description, value1, value2, value3) values ('fetch_scores', :description, :value1, :value2, :value3)"; + $binds = [ + "description" => "Waiting in Queue", + "value1" => (string)$player1, + "value2" => (string)$player2, + "value3" => "waiting" + ]; + + $database->queryData2($queryStatus, $binds); + + } +} \ No newline at end of file diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..0a451c9 --- /dev/null +++ b/todo.md @@ -0,0 +1,48 @@ +most_played abfragen (https://osu.ppy.sh/users/$userid/beatmapsets/most_played?limit=100&offset=100) +-> in db speichern => userid, scoreid, (maybe noch map infos als json string), recnum => done +-> mit sql maps abfragen die beide spieler gespielt haben => done +-> von diesen maps dann die scores abfragen +-> vergleichen + +------------------------------------- + +request hanlder + +GetUserMostPlayed.php mit sql queue verbinden + +sql tabelle (queue) +-> spalten: user_id, state(running, error, waiting), progress(x/y scores completed) + +------------------------------------- + +scores abfragen + +------------------------------------- + +flow + +erster visit auf seite +GetUserMostPlayed.php -> RequestMutualScores.php => function call auf CheckMutualMaps.hph + + + + +------------------------------------ +requesthandler.php darf nicht aufgerufen werden sondern muss immer mit einer while true schleife laufen und wenn in status tabelle ein datensatz mit waiting ist, werden diese nach der PID reihenfolge verarbeitet. + + + + +----------------------------- + + +bedingung für scores fertig gefetched + +wenn offset bei beiden spielern == anzahl von den zu verarbeitenden maps + + +-------------------------- + + + +möglich machen in den querys, dass wenn die user ids vertauscht sind, auch diese dann noch richtig erkannt werden \ No newline at end of file