} } echo $myarr[$high]; unset($t);*/ /* -------------------------- * new stuff ----------------------------- */ $arr = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14); $searchfor = 6; //echo binsearch($searchfor, $arr); function binsearch($needle, $haystack) { $high = count($haystack); $low = 0; while (strcmp($high, $low) == 0) { $probe = ($high + $low) / 2; if ($haystack[$probe] < $needle) { $low = $probe; } else { $high = $probe; } } if ($high == count($haystack) || $haystack[$high] != $needle) { return false; } else { return $high; } } $tE = binsearch($searchfor, $arr); //echo $arr[$tE];
function updateLeaderboard($lbid = "") { global $db; global $config; global $colNames_details; global $colNames_scores; global $colNames_times; global $colNames_players; global $date; global $today; if ($lbid === "") { $r = getLeaderboardId(); $r = getLeaderboardIdFromSteam(); } elseif ($lbid === "yesterday") { $r = getLeaderboardId(1); $yesterday = true; } else { $r = $lbid; } if ($r == 0) { echo "[!] couldn't retrieve the leaderboard from the db,\n"; echo "[!] trying to retrieve it from steam\n"; $lbid = getLeaderboardIdFromSteam($yesterday ? 1 : $lbid); } else { $lbid = $r; } // get today's number of entries $url = $config['leaderboards']['baseUrl'] . $lbid . '/?xml=1&start=0&end=1'; $data = getData($url); $xml = new SimpleXMLElement($data); $how_many = $xml->totalLeaderboardEntries; // get all entries for today $rank = 1; $rank_hax = 999999; $current_count = 1; // start the huge loop $q = $db->prepare("\n SELECT date\n FROM dates\n WHERE dayid = :lbid"); $q->execute(array(':lbid' => $lbid)); $date = $q->fetch()[0]; if ($date == date('Y-m-d')) { $q = $db->prepare("\n UPDATE dates\n SET done = 1,\n entries = :entries\n WHERE dayid = :lbid"); $q->execute(array(':lbid' => $lbid, ':entries' => $how_many)); } // get a list of known, diehard cheaters // previously disabled, now once again enforced. // seems like they just won't get bored. // players who have cheated 3 times or more $res = $db->query("\n SELECT DISTINCT steamid\n FROM players\n WHERE hax >= 3\n ORDER BY steamid ASC"); $permabanned = $res->fetchAll(PDO::FETCH_COLUMN); // players who have been caught today $res = $db->query("\n SELECT DISTINCT steamid\n FROM scores\n WHERE dayid = {$lbid}\n AND hidden = 1\n ORDER BY steamid ASC"); $todaysbanned = $res->fetchAll(PDO::FETCH_COLUMN); // manually hidden $res = $db->query("\n SELECT DISTINCT steamid\n FROM scores\n WHERE dayid = {$lbid}\n AND hidden = 3\n ORDER BY steamid ASC"); $todayshidden = $res->fetchAll(PDO::FETCH_COLUMN); // alts to skip $res = $db->query("\n SELECT DISTINCT steamid\n FROM alt_accounts\n WHERE alt_id = {$lbid}\n ORDER BY steamid ASC"); $known_alts = $res->fetchAll(PDO::FETCH_COLUMN); $entries = 0; while ($current_count <= $how_many) { echo "[" . date('H:i:s') . "] " . "updating leaderboards: {$current_count} / {$how_many} done\n"; $url = $config['leaderboards']['baseUrl'] . $lbid . "/?xml=1&start={$current_count}&end=" . ($current_count + 4999); // get the xml element for the leaderboards try { $data = getData($url); $xml = new SimpleXMLElement($data); $how_many = $xml->totalLeaderboardEntries; } catch (Exception $e) { echo "[" . date('H:i:s') . "] " . "[{$c}/{$t}] Failed to update leaderboard: {$e->getMessage()}\n"; sleep(10); updateLeaderboard(); } // prepare the arrays that will hold 5k entries each $scores = array(); $times = array(); $details = array(); $players = array(); $alts_to_check = array(); // populate the arrays foreach ($xml->entries->entry as $e) { // skip ongoing / crashed runs if ($e->score <= 0) { if (binsearch($e->steamid, $known_alts) !== false) { continue; } $alts_to_check[] = $e->steamid; continue; } // compute the unique hash between dailyid and the steamid // return a binary hash since we're storing blobs and not chars $hash = md5($lbid . $e->steamid, true); // pre-populate the detailed score array // needed because the earlier versions of the game didn't have some // fields and we still want to use a common insert routine // [0] = hash, [1] = dayid, [2] = stage, [3] = swag, [4] = xxx // [5] = lamb, [6] = mega, [7] = rush, [8] = expl, [9] = dmg // [10]= time, [11]= item, [12]= floor, [13]= type, [14]= time // [15]= end, [16]= build $tmp = array($hash, $lbid, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // convert the detailed score blob into useful ints for ($i = 0; $i <= strlen($e->details) - 1; $i += 8) { $hex = substr($e->details, $i, 8); $dec = implode('', array_reverse(str_split($hex, 2))); $tmp[$i / 8 + 2] = hexdec($dec); } // get the time $time = floor($tmp[14] / 30); $tmp[14] = $time; // get the floor value for the time leaderboard $floor = $tmp[12]; // keep tally of the real amount of entries $entries++; // everyone is innocent... $hidden = 0; $perma = false; $ban = $e->steamid; // hide today's cheaters' scores and don't increase // their hax value if (binsearch($ban, $todaysbanned) !== false) { $hidden = 1; } elseif (binsearch($ban, $todayshidden) !== false) { $hidden = 3; } elseif (binsearch($ban, $permabanned) !== false) { $perma = true; $hidden = 3; } // determine the level of cheating unless we've manually hidden // this score if ($hidden == 0 && $perma === false) { // exp.bonus > 26k (game can be broken up to 40k afaik // using the partial-room completion strategy. // see the comment below for the relevant db query) // if ($tmp[8] > 26000 || $tmp[3] > 16500) { $hidden = 2; } // schwag > 16k // by game engine (40k) if ($tmp[3] > 16500 || $tmp[8] > 26000 || $floor >= 6 && $time <= 120) { // ... until proven guilty $hidden = 1; } } // adjust rank accordingly if ($hidden == 1 || $hidden == 3 || $perma === true) { $final_rank = $rank_hax; } else { $final_rank = $rank; $rank++; } // add the detailed score to the main array $details[] = $tmp; // populate the score array and the 'hidden' value $scores[] = array('hash' => $hash, 'dayid' => $lbid, 'steamid' => $e->steamid, 'score' => $e->score, 'rank' => $final_rank, 'hidden' => $hidden); // do the same with the times array $times[] = array('hash' => $hash, 'dayid' => $lbid, 'steamid' => $e->steamid, 'floor' => $floor, 'time' => $time, 'rank' => 999999, 'hidden' => $hidden); // populate the players array $players[] = array('steamid' => $e->steamid); } if (count($details) == 0) { break; } // scores, times and players aren't that huge bulkInsert('players', $colNames_players, $players); bulkInsert('scores', $colNames_scores, $scores); bulkInsert('times', $colNames_times, $times); // the detailed score array is huge, we need to partition it // in smaller bulks or mariadb will die for an excess of prepared // parameters if (count($details) > 2500) { foreach (array_chunk($details, floor(count($details) / 2)) as $bulk) { bulkInsert('details', $colNames_details, $bulk); } } else { bulkInsert('details', $colNames_details, $details); } $current_count += 4999; } // set today's amount of players setTodaysEntries($lbid, $entries, $rank); // compute time rankings computeTimeRankings($lbid); // fix last_updated in scores and times tables if we just updated // a 'yesterday' daily if ($yesterday === true) { fixDates($lbid); } checkAltAccounts($alts_to_check, $lbid); }