예제 #1
0
        }
    }

    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);
}