file upload

This commit is contained in:
potzplitz 2025-05-13 21:59:58 +02:00
parent 37cab5be3c
commit 22db148e39
9 changed files with 568 additions and 0 deletions

20
CheckForMostPlayedJob.php Normal file
View file

@ -0,0 +1,20 @@
<?php
require("database.php");
require("GetUserMostPlayed.php");
$database = new Database("localhost", "ScoreSniper", MARIAUSER, MARIAPASSWD);
while(true) {
$queryQueue = "INSERT into queueMostPlayed (user_id1, user_id2, state, progress, offset_player1, offset_player2) select value1, value2, 'waiting', '0', 0, 0 from status where value3 = 'waiting'";
$database->queryData($queryQueue);
$queryGetNew = "SELECT * from queueMostPlayed where state = 'waiting' order by queue_id asc";
$waitingUsers = $database->queryData($queryGetNew);
if($waitingUsers != null) {
getPlays();
}
sleep(1);
}

20
CheckForScoreFetchJob.php Normal file
View file

@ -0,0 +1,20 @@
<?php
require("database.php");
require("RequestMutualScores.php");
$database = new Database("localhost", "ScoreSniper", MARIAUSER, MARIAPASSWD);
while(true) {
$queryQueue = "INSERT into queueUserScores (user_id1, user_id2, state, progress, offset_player1, offset_player2) select user_id1, user_id2, 'waiting', '0', 0, 0 from queueMostPlayed where state = 'finished'";
$database->queryData($queryQueue);
$queryGetNew = "SELECT * from queueUserScores where state = 'waiting' order by queue_id asc";
$waitingUsers = $database->queryData($queryGetNew);
if($waitingUsers != null) {
getScores();
}
sleep(1);
}

24
CheckMutualMaps.php Normal file
View file

@ -0,0 +1,24 @@
<?php
if (!function_exists("CheckMutualMaps")) {
function CheckMutualMaps($player1, $player2) {
require("database.php");
$database = new Database("localhost", "ScoreSniper", MARIAUSER, MARIAPASSWD);
$query = "SELECT a.map_id
FROM UserMostPlayed a
WHERE a.user_id = :player_1
AND a.map_id IN (
SELECT b.map_id
FROM UserMostPlayed b
WHERE b.user_id = :player_2
)";
$binds = [
"player_1" => (string)$player1,
"player_2" => (string)$player2
];
return $database->queryData2($query, $binds);
}
}

100
GetComparableScores.php Normal file
View file

@ -0,0 +1,100 @@
<?php
require("database.php");
require("constants.php");
function getScore($player1, $player2, $random) {
$database = new Database("localhost", "ScoreSniper", MARIAUSER, MARIAPASSWD);
$query = "SELECT
a.map_id,
a.user_id AS user_player,
a.score AS score_player,
a.maxcombo AS maxcombo_player,
a.perfect AS perfect_player,
a.date AS date_player,
a.rank AS rank_player,
a.enabled_mods AS mods_player,
b.user_id AS user_target,
b.score AS score_target,
b.maxcombo AS maxcombo_target,
b.perfect AS perfect_target,
b.date AS date_target,
b.rank AS rank_target,
b.enabled_mods AS mods_target
FROM UserScores a
JOIN UserScores b ON a.map_id = b.map_id
WHERE a.user_id = :player2
AND b.user_id = :player1
AND a.score < b.score ";
if($random == 1) {
$query .= "ORDER BY RAND()
LIMIT 1";
}
$binds = [
"player1" => $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);
}
}

109
GetUserMostPlayed.php Normal file
View file

@ -0,0 +1,109 @@
<?php
require("database.php");
require("constants.php");
$database = new Database("localhost", "ScoreSniper", MARIAUSER, MARIAPASSWD);
if (!function_exists("getPlays")) {
function getPlays() {
global $database;
$queryQueue = "SELECT * FROM queueMostPlayed WHERE state != 'finished' ORDER BY queue_id ASC";
$queue = $database->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;
}
}

142
RequestMutualScores.php Normal file
View file

@ -0,0 +1,142 @@
<?php
require("database.php");
require("CheckMutualMaps.php");
require("constants.php");
if (!function_exists("getPlays")) {
function getScores() {
global $database;
$queryQueue = "SELECT * FROM queueUserScores WHERE state != 'finished' ORDER BY queue_id ASC";
$queue = $database->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";
}
}

45
database.php Normal file
View file

@ -0,0 +1,45 @@
<?php
if(!class_exists("Database")) {
class Database {
public $pdo;
private $rows;
public function __construct($host, $dbname, $user, $psswd) {
try {
$dsn = "mysql:host=$host;dbname=$dbname;charset=utf8mb4";
$this->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);
}
}
}
?>

60
snipe.php Normal file
View file

@ -0,0 +1,60 @@
<?php
require("database.php");
require("constants.php");
require("GetComparableScores.php");
$database = new Database("localhost", "ScoreSniper", MARIAUSER, MARIAPASSWD);
$player1 = $_GET['target'];
$player2 = $_GET['player'];
$random = $_GET['random'] ?? 0;
$queryStatus = "SELECT * from status where ((value1 = :value1 and value2 = :value2) or (value1 = :value2 and value2 = :value1))";
$bindsStatus = [
"value1" => $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);
}
}

48
todo.md Normal file
View file

@ -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