dblink, "SHOW TABLES LIKE '" . $table . "'"); if (!$check || mysqli_num_rows($check) === 0) { return false; } $hours = defined('PLUS_STATS_INTERVAL_HOURS') ? (float) PLUS_STATS_INTERVAL_HOURS : 6.0; $interval = (int) max(600, round($hours * 3600)); $now = time(); $res = mysqli_query($database->dblink, "SELECT MAX(recorded_at) AS last FROM " . $table); $row = $res ? mysqli_fetch_assoc($res) : null; $last = $row ? (int) $row['last'] : 0; if ($last > 0 && ($now - $last) < $interval) { return false; } $this->writePlayerStatisticsSnapshot($now); $this->trimPlayerStatistics($now); return true; } /** * Scrie efectiv instantaneul. * * Populatia, satele si punctele vin dintr-o singura interogare. Trupele se * numara separat, fiindca hrana consumata are nevoie de datele de unitate * din PHP (fiecare unitate are alt consum). */ private function writePlayerStatisticsSnapshot($now) { global $database; $table = TB_PREFIX . 'player_statistics_history'; // rang, populatie, sate si puncte de lupta, per jucator $q = "SELECT u.id AS uid, u.oldrank AS rank, COALESCE(SUM(v.pop), 0) AS population, COUNT(CASE WHEN v.type != 99 THEN v.wref END) AS villages, u.apall AS attack_points, u.dpall AS defence_points FROM " . TB_PREFIX . "users u LEFT JOIN " . TB_PREFIX . "vdata v ON v.owner = u.id WHERE u.id > 5 AND u.access > 0 GROUP BY u.id"; $res = mysqli_query($database->dblink, $q); if (!$res) { return; } $players = array(); while ($row = mysqli_fetch_assoc($res)) { $players[(int) $row['uid']] = array( 'rank' => (int) $row['rank'], 'population' => (int) $row['population'], 'villages' => (int) $row['villages'], 'attack_points' => (int) $row['attack_points'], 'defence_points' => (int) $row['defence_points'], 'troop_count' => 0, 'troop_upkeep' => 0, ); } if (!$players) { return; } $this->addTroopTotals($players); // scriem in loturi, ca sa nu facem o interogare per jucator $values = array(); foreach ($players as $uid => $p) { $values[] = '(' . (int) $uid . ',' . (int) $now . ',' . $p['rank'] . ',' . $p['population'] . ',' . $p['villages'] . ',' . $p['troop_count'] . ',' . $p['troop_upkeep'] . ',' . $p['attack_points'] . ',' . $p['defence_points'] . ')'; } foreach (array_chunk($values, 200) as $chunk) { mysqli_query($database->dblink, "INSERT IGNORE INTO " . $table . " (uid, recorded_at, `rank`, population, villages, troop_count, troop_upkeep, attack_points, defence_points) VALUES " . implode(',', $chunk)); } } /** * Aduna trupele fiecarui jucator si hrana pe care o consuma. * * Se numara trupele din satele proprii SI intaririle trimise altora * (enforcement.`from` pastreaza satul de origine, deci ele raman ale * trimitatorului). Trupele straine stationate la tine NU se numara: nu sunt * armata ta. * * Numarul brut de unitati e inselator - 1000 de falange nu inseamna cat 1000 * de calareti de elita - de aceea inregistram si hrana consumata, care e * cantarul propriu al jocului si pondereaza automat unitatile dupa putere. */ private function addTroopTotals(array &$players) { global $database; // consumul fiecarei unitati, din datele de joc $upkeep = array(); for ($i = 1; $i <= 90; $i++) { $name = 'u' . $i; if (isset($GLOBALS[$name]) && isset($GLOBALS[$name]['pop'])) { $upkeep[$i] = (int) $GLOBALS[$name]['pop']; } } if (!$upkeep) { return; } // suma pe coloane, pentru trupele din satele proprii $sumCount = array(); $sumUpkeep = array(); foreach ($upkeep as $i => $cost) { $sumCount[] = 'SUM(t.u' . $i . ')'; $sumUpkeep[] = 'SUM(t.u' . $i . ') * ' . $cost; } $sources = array( // trupele din satele proprii "SELECT v.owner AS uid, " . implode(' + ', $sumCount) . " AS cnt, " . implode(' + ', $sumUpkeep) . " AS upk FROM " . TB_PREFIX . "units t JOIN " . TB_PREFIX . "vdata v ON v.wref = t.vref GROUP BY v.owner", // intaririle trimise altora: raman ale satului de origine "SELECT v.owner AS uid, " . implode(' + ', $sumCount) . " AS cnt, " . implode(' + ', $sumUpkeep) . " AS upk FROM " . TB_PREFIX . "enforcement t JOIN " . TB_PREFIX . "vdata v ON v.wref = t.`from` GROUP BY v.owner", ); foreach ($sources as $q) { $res = @mysqli_query($database->dblink, $q); while ($res && ($row = mysqli_fetch_assoc($res))) { $uid = (int) $row['uid']; if (!isset($players[$uid])) { continue; } $players[$uid]['troop_count'] += (int) $row['cnt']; $players[$uid]['troop_upkeep'] += (int) $row['upk']; } } } /** Sterge instantaneele mai vechi decat retentia configurata. */ private function trimPlayerStatistics($now) { global $database; $days = defined('PLUS_STATS_KEEP_DAYS') ? (int) PLUS_STATS_KEEP_DAYS : 0; if ($days <= 0) { return; // 0 = pastram tot } mysqli_query($database->dblink, "DELETE FROM " . TB_PREFIX . "player_statistics_history WHERE recorded_at < " . (int) ($now - $days * 86400) . " LIMIT 5000"); } }