plus) && (int) $session->plus == 1); $psEnabled = defined('NEW_FUNCTIONS_PLUS_STATISTICS') && NEW_FUNCTIONS_PLUS_STATISTICS; /** * Deseneaza un grafic de linie ca SVG. * * $points - lista de perechi [timestamp, valoare] * $invert - true pentru rang, unde valoarea mai MICA e mai buna, deci axa se * deseneaza invers (locul 1 sus) */ function ps_line_chart(array $points, $title, $color = '#7db72f', $invert = false) { $w = 560; $h = 170; $padL = 52; $padR = 12; $padT = 22; $padB = 26; $out = ''; $out .= ''; $out .= '' . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . ''; if (count($points) < 2) { $out .= '' . htmlspecialchars(defined('PLUSSTATS_NODATA') ? PLUSSTATS_NODATA : 'Not enough data yet', ENT_QUOTES, 'UTF-8') . ''; return $out; } $values = array_map(function ($p) { return (float) $p[1]; }, $points); $times = array_map(function ($p) { return (int) $p[0]; }, $points); $minV = min($values); $maxV = max($values); // o linie perfect plata ar imparti la zero; ii dam putin spatiu if ($maxV - $minV < 0.0001) { $maxV = $minV + 1; } $minT = min($times); $maxT = max($times); $spanT = max(1, $maxT - $minT); $plotW = $w - $padL - $padR; $plotH = $h - $padT - $padB; $x = function ($t) use ($padL, $plotW, $minT, $spanT) { return $padL + ($t - $minT) / $spanT * $plotW; }; $y = function ($v) use ($padT, $plotH, $minV, $maxV, $invert) { $frac = ($v - $minV) / ($maxV - $minV); // la rang, valoarea mica inseamna loc bun, deci o punem sus return $invert ? $padT + $frac * $plotH : $padT + (1 - $frac) * $plotH; }; // grila si etichete pe axa verticala for ($i = 0; $i <= 3; $i++) { $v = $minV + ($maxV - $minV) * $i / 3; $yy = $y($v); $out .= ''; $out .= '' . number_format($v) . ''; } // linia propriu-zisa $d = ''; foreach ($points as $i => $p) { $d .= ($i === 0 ? 'M' : 'L') . round($x($p[0]), 1) . ',' . round($y($p[1]), 1) . ' '; } // suprafata de sub linie, pentru lizibilitate $area = $d . 'L' . round($x($times[count($times) - 1]), 1) . ',' . ($padT + $plotH) . ' L' . round($x($times[0]), 1) . ',' . ($padT + $plotH) . ' Z'; $out .= ''; $out .= ''; // punctele de capat, cu valorile $first = $points[0]; $lastP = $points[count($points) - 1]; foreach (array($first, $lastP) as $p) { $out .= ''; } // datele de la capete $out .= '' . date('d.m', $minT) . ''; $out .= '' . date('d.m', $maxT) . ''; // valoarea curenta, in dreapta sus $out .= '' . number_format($lastP[1]) . ''; $out .= ''; return $out; } ?>
' . (defined('PLUSSTATS_DISABLED') ? PLUSSTATS_DISABLED : 'Graphical statistics are not enabled on this server.') . '
'; return; } if (!$psHasPlus) { echo '
' . (defined('PLUSSTATS_NEEDPLUS') ? PLUSSTATS_NEEDPLUS : 'Graphical statistics are a Travian Plus feature. Activate Plus to see the development of your account.') . '
'; return; } // ------------------------------------------------- // DATELE // ------------------------------------------------- $psRows = array(); $psUid = (int) $session->uid; $psQ = @mysqli_query($database->dblink, "SELECT recorded_at, `rank`, population, villages, troop_count, troop_upkeep FROM " . TB_PREFIX . "player_statistics_history WHERE uid = " . $psUid . " ORDER BY recorded_at ASC LIMIT 400"); while ($psQ && ($psRow = mysqli_fetch_assoc($psQ))) { $psRows[] = $psRow; } if (count($psRows) < 2) { echo '
' . (defined('PLUSSTATS_WAIT') ? PLUSSTATS_WAIT : 'Your account is being recorded. The graphs appear once at least two snapshots exist.') . '
'; return; } $psSeries = array('rank' => array(), 'population' => array(), 'villages' => array(), 'troop_upkeep' => array(), 'troop_count' => array()); foreach ($psRows as $psRow) { $t = (int) $psRow['recorded_at']; // rangul 0 inseamna "neclasat inca" - il sarim, ca sa nu strice scara if ((int) $psRow['rank'] > 0) { $psSeries['rank'][] = array($t, (int) $psRow['rank']); } $psSeries['population'][] = array($t, (int) $psRow['population']); $psSeries['villages'][] = array($t, (int) $psRow['villages']); $psSeries['troop_upkeep'][] = array($t, (int) $psRow['troop_upkeep']); $psSeries['troop_count'][] = array($t, (int) $psRow['troop_count']); } echo '
' . (defined('PLUSSTATS_INTRO') ? PLUSSTATS_INTRO : 'The development of your account over time.') . '
'; echo '
' . ps_line_chart($psSeries['rank'], defined('PLUSSTATS_RANK') ? PLUSSTATS_RANK : 'Ranking', '#3b7dd8', true) . '
'; echo '
' . ps_line_chart($psSeries['population'], defined('PLUSSTATS_POP') ? PLUSSTATS_POP : 'Population', '#7db72f') . '
'; echo '
' . ps_line_chart($psSeries['villages'], defined('PLUSSTATS_VILLAGES') ? PLUSSTATS_VILLAGES : 'Villages', '#8e6fc4') . '
'; echo '
' . ps_line_chart($psSeries['troop_upkeep'], defined('PLUSSTATS_ARMY') ? PLUSSTATS_ARMY : 'Army strength (crop upkeep per hour)', '#d9822b') . '
'; // ------------------------------------------------- // REZUMAT: acum fata de primul instantaneu // ------------------------------------------------- $psFirst = $psRows[0]; $psLast = $psRows[count($psRows) - 1]; $psFields = array( 'rank' => defined('PLUSSTATS_RANK') ? PLUSSTATS_RANK : 'Ranking', 'population' => defined('PLUSSTATS_POP') ? PLUSSTATS_POP : 'Population', 'villages' => defined('PLUSSTATS_VILLAGES') ? PLUSSTATS_VILLAGES : 'Villages', 'troop_count' => defined('PLUSSTATS_TROOPS') ? PLUSSTATS_TROOPS : 'Troops', 'troop_upkeep' => defined('PLUSSTATS_UPKEEP') ? PLUSSTATS_UPKEEP : 'Crop upkeep per hour', ); ?> $psLabel) { $a = (int) $psFirst[$psKey]; $b = (int) $psLast[$psKey]; $d = $b - $a; // la rang, scaderea numarului inseamna urcare in clasament $good = ($psKey === 'rank') ? ($d < 0) : ($d > 0); $cls = ($d == 0) ? '' : ($good ? 'ps-delta-up' : 'ps-delta-down'); $sign = ($d > 0) ? '+' : ''; ?>