From f5bba1732aff69fb08d0435582c33210280efb9e Mon Sep 17 00:00:00 2001 From: cytopia Date: Sat, 9 Mar 2019 11:09:40 +0100 Subject: [PATCH] Fix #525 Add PHPMemcachedAdmin --- .devilbox/www/htdocs/credits.php | 5 + .../Config/Memcache.php | 25 + .../Library/Bootstrap.php | 30 + .../Library/Command/Factory.php | 110 ++++ .../Library/Command/Interface.php | 178 ++++++ .../Library/Command/Memcache.php | 309 ++++++++++ .../Library/Command/Memcached.php | 287 +++++++++ .../Library/Command/Server.php | 486 +++++++++++++++ .../Library/Configuration/Loader.php | 186 ++++++ .../Library/Data/Analysis.php | 327 +++++++++++ .../Library/Data/Error.php | 60 ++ .../Library/Data/Version.php | 72 +++ .../Library/HTML/Components.php | 143 +++++ .../Public/Scripts/Highcharts/highcharts.js | 391 +++++++++++++ .../Highcharts/standalone-framework.js | 17 + .../Public/Scripts/script.js | 299 ++++++++++ .../Public/Styles/Style.css | 238 ++++++++ .../View/Commands/Commands.phtml | 197 +++++++ .../View/Configure/Configure.phtml | 151 +++++ .../phpmemcachedadmin-1.3.0/View/Footer.phtml | 18 + .../phpmemcachedadmin-1.3.0/View/Header.phtml | 62 ++ .../View/LiveStats/Frame.phtml | 70 +++ .../View/LiveStats/Stats.phtml | 87 +++ .../View/Stats/Error.phtml | 58 ++ .../View/Stats/Items.phtml | 56 ++ .../View/Stats/Slabs.phtml | 126 ++++ .../View/Stats/Stats.phtml | 551 ++++++++++++++++++ .../phpmemcachedadmin-1.3.0/commands.php | 255 ++++++++ .../vendor/phpmemcachedadmin-1.3.0/index.php | 141 +++++ .../vendor/phpmemcachedadmin-1.3.0/spam.php | 13 + .../vendor/phpmemcachedadmin-1.3.0/stats.php | 155 +++++ .devilbox/www/include/lib/Html.php | 5 + 32 files changed, 5108 insertions(+) create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Config/Memcache.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Bootstrap.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Factory.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Interface.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Memcache.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Memcached.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Server.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Configuration/Loader.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Data/Analysis.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Data/Error.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Data/Version.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/HTML/Components.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Public/Scripts/Highcharts/highcharts.js create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Public/Scripts/Highcharts/standalone-framework.js create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Public/Scripts/script.js create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Public/Styles/Style.css create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Commands/Commands.phtml create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Configure/Configure.phtml create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Footer.phtml create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Header.phtml create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/LiveStats/Frame.phtml create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/LiveStats/Stats.phtml create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Stats/Error.phtml create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Stats/Items.phtml create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Stats/Slabs.phtml create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Stats/Stats.phtml create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/commands.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/index.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/spam.php create mode 100644 .devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/stats.php diff --git a/.devilbox/www/htdocs/credits.php b/.devilbox/www/htdocs/credits.php index 7e762129..f8896407 100644 --- a/.devilbox/www/htdocs/credits.php +++ b/.devilbox/www/htdocs/credits.php @@ -82,6 +82,11 @@ MIT amnuts/opcache-gui + + PHPMemcachedAdmin + Apache 2.0 + elijaa/phpmemcachedadmin + phpMyAdmin GPL 2.0 diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Config/Memcache.php b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Config/Memcache.php new file mode 100644 index 00000000..e52d40fd --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Config/Memcache.php @@ -0,0 +1,25 @@ + 'Server', + 'slabs_api' => 'Server', + 'items_api' => 'Server', + 'get_api' => 'Server', + 'set_api' => 'Server', + 'delete_api' => 'Server', + 'flush_all_api' => 'Server', + 'connection_timeout' => 1, + 'max_item_dump'=> 100, + 'refresh_rate' => 2, + 'memory_alert' => 80, + 'hit_rate_alert' => 90, + 'eviction_alert' => 0, + 'file_path' => '/tmp', + 'servers' => array ( + 'Devilbox Memcached' => array ( + 'memcd' => array ( + 'hostname' => 'memcd', + 'port' => '11211', + ), + ), + ), +); diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Bootstrap.php b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Bootstrap.php new file mode 100644 index 00000000..777140e3 --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Bootstrap.php @@ -0,0 +1,30 @@ + $data) { + $_REQUEST[$index] = htmlentities($data); +} + +# Autoloader +function autoloader($class) +{ + require_once str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php'; +} +spl_autoload_register('autoloader'); + +# Loading ini file +$_ini = Library_Configuration_Loader::singleton(); + +# Date timezone +date_default_timezone_set('Europe/Paris'); diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Factory.php b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Factory.php new file mode 100644 index 00000000..6e595dba --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Factory.php @@ -0,0 +1,110 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * Factory for communication with Memcache Server + * + * @author elijaa@free.fr + * @since 30/03/2010 + */ +class Library_Command_Factory +{ + private static $_object = array(); + + # No explicit call of constructor + private function __construct() + {} + + # No explicit call of clone() + private function __clone() + {} + + /** + * Accessor to command class instance by command type + * + * @param String $command Type of command + * + * @return void + */ + public static function instance($command) + { + # Importing configuration + $_ini = Library_Configuration_Loader::singleton(); + + # Instance does not exists + if (! isset(self::$_object[$_ini->get($command)]) || ($_ini->get($command) != 'Server')) { + # Switching by API + switch ($_ini->get($command)) { + case 'Memcache' : + # PECL Memcache API + require_once 'Memcache.php'; + self::$_object['Memcache'] = new Library_Command_Memcache(); + break; + + case 'Memcached' : + # PECL Memcached API + require_once 'Memcached.php'; + self::$_object['Memcached'] = new Library_Command_Memcached(); + break; + + case 'Server' : + default : + # Server API (eg communicating directly with the memcache server) + require_once 'Server.php'; + self::$_object['Server'] = new Library_Command_Server(); + break; + } + } + return self::$_object[$_ini->get($command)]; + } + + /** + * Accessor to command class instance by type + * + * @param String $command Type of command + * + * @return void + */ + public static function api($api) + { + # Instance does not exists + if (! isset(self::$_object[$api]) || ($api != 'Server')) { + # Switching by API + switch ($api) { + case 'Memcache' : + # PECL Memcache API + require_once 'Memcache.php'; + self::$_object['Memcache'] = new Library_Command_Memcache(); + break; + + case 'Memcached' : + # PECL Memcached API + require_once 'Memcached.php'; + self::$_object['Memcached'] = new Library_Command_Memcached(); + break; + + case 'Server' : + default : + # Server API (eg communicating directly with the memcache server) + require_once 'Server.php'; + self::$_object['Server'] = new Library_Command_Server(); + break; + } + } + return self::$_object[$api]; + } +} \ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Interface.php b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Interface.php new file mode 100644 index 00000000..65b2d74a --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Interface.php @@ -0,0 +1,178 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * Interface of communication to MemCache Server + * + * @author elijaa@free.fr + * @since 20/03/2010 + */ +interface Library_Command_Interface +{ + /** + * Constructor + * + * @return void + */ + function __construct(); + + /** + * Send stats command to server + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * + * @return Array|Boolean + */ + function stats($server, $port); + + /** + * Send stats settings command to server + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * + * @return Array|Boolean + */ + public function settings($server, $port); + + /** + * Retrieve slabs stats + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * + * @return Array|Boolean + */ + function slabs($server, $port); + + /** + * Retrieve items from a slabs + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param Integer $slab Slab ID + * + * @return Array|Boolean + */ + function items($server, $port, $slab); + + /** + * Send get command to server to retrieve an item + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to retrieve + * + * @return String + */ + function get($server, $port, $key); + + /** + * Set an item + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to store + * @param Mixed $data Data to store + * @param Integer $duration Duration + * + * @return String + */ + function set($server, $port, $key, $data, $duration); + + /** + * Delete an item + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to delete + * + * @return String + */ + function delete($server, $port, $key); + + /** + * Increment the key by value + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to increment + * @param Integer $value Value to increment + * + * @return String + */ + function increment($server, $port, $key, $value); + + /** + * Decrement the key by value + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to decrement + * @param Integer $value Value to decrement + * + * @return String + */ + function decrement($server, $port, $key, $value); + + /** + * Flush all items on a server after delay + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param Integer $delay Delay before flushing server + * + * @return String + */ + function flush_all($server, $port, $delay); + + /** + * Search for item + * Return all the items matching parameters if successful, false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to search + * @param Boolean $level Level of detail + * @param Boolean $more More action + * + * @return array + */ + function search($server, $port, $search, $level = false, $more = false); + + /** + * Execute a telnet command on a server + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $command Command to execute + * + * @return String + */ + function telnet($server, $port, $command); +} \ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Memcache.php b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Memcache.php new file mode 100644 index 00000000..571d539e --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Memcache.php @@ -0,0 +1,309 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * Sending command to memcache server via PECL memcache API http://pecl.php.net/package/memcache + * + * @author elijaa@free.fr + * @since 20/03/2010 + */ +class Library_Command_Memcache implements Library_Command_Interface +{ + private static $_ini; + private static $_memcache; + + /** + * Constructor + * + * @param Array $ini Array from ini_parse + * + * @return void + */ + public function __construct() + { + # Importing configuration + self::$_ini = Library_Configuration_Loader::singleton(); + + # Initializing + self::$_memcache = new Memcache(); + } + + /** + * Send stats command to server + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * + * @return Array|Boolean + */ + public function stats($server, $port) + { + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command + if (($return = self::$_memcache->getExtendedStats())) { + # Delete server key based + $stats = $return[$server . ':' . $port]; + return $stats; + } + return false; + } + + /** + * Send stats settings command to server + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * + * @return Array|Boolean + */ + public function settings($server, $port) + { + return false; + } + + /** + * Send stats items command to server to retrieve slabs stats + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * + * @return Array|Boolean + */ + public function slabs($server, $port) + { + # Initializing + $slabs = array(); + + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command : slabs + if (($slabs = self::$_memcache->getStats('slabs'))) { + # Finding uptime + $stats = $this->stats($server, $port); + $slabs['uptime'] = $stats['uptime']; + unset($stats); + + # Executing command : items + if (($result = self::$_memcache->getStats('items'))) { + # Indexing by slabs + foreach ($result['items'] as $id => $items) { + foreach ($items as $key => $value) { + $slabs[$id]['items:' . $key] = $value; + } + } + return $slabs; + } + } + return false; + } + + /** + * Send stats cachedump command to server to retrieve slabs items + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param Interger $slab Slab ID + * + * @return Array|Boolean + */ + public function items($server, $port, $slab) + { + # Initializing + $items = false; + + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command : slabs stats + if (($items = self::$_memcache->getStats('cachedump', $slab, self::$_ini->get('max_item_dump')))) { + return $items; + } + return false; + } + + /** + * Send get command to server to retrieve an item + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to retrieve + * + * @return String + */ + public function get($server, $port, $key) + { + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command : get + if ($item = self::$_memcache->get($key)) { + return print_r($item, true); + } + return 'NOT_FOUND'; + } + + /** + * Set an item + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to store + * @param Mixed $data Data to store + * @param Integer $duration Duration + * + * @return String + */ + function set($server, $port, $key, $data, $duration) + { + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command : set + if (self::$_memcache->set($key, $data, 0, $duration)) { + return 'STORED'; + } + return 'ERROR'; + } + + /** + * Delete an item + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to delete + * + * @return String + */ + public function delete($server, $port, $key) + { + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command : delete + if (self::$_memcache->delete($key)) { + return 'DELETED'; + } + return 'NOT_FOUND'; + } + + /** + * Increment the key by value + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to increment + * @param Integer $value Value to increment + * + * @return String + */ + function increment($server, $port, $key, $value) + { + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command : increment + if ($result = self::$_memcache->increment($key, $value)) { + return $result; + } + return 'NOT_FOUND'; + } + + /** + * Decrement the key by value + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to decrement + * @param Integer $value Value to decrement + * + * @return String + */ + function decrement($server, $port, $key, $value) + { + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command : decrement + if ($result = self::$_memcache->decrement($key, $value)) { + return $result; + } + return 'NOT_FOUND'; + } + + /** + * Flush all items on a server + * Warning, delay won't work with Memcache API + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param Integer $delay Delay before flushing server + * + * @return String + */ + function flush_all($server, $port, $delay) + { + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command : flush_all + self::$_memcache->flush(); + return 'OK'; + } + + /** + * Search for item + * Return all the items matching parameters if successful, false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to search + * + * @return array + */ + function search($server, $port, $search, $level = false, $more = false) + { + throw new Exception('PECL Memcache does not support search function, use Server instead'); + } + + /** + * Execute a telnet command on a server + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $command Command to execute + * + * @return String + */ + function telnet($server, $port, $command) + { + throw new Exception('PECL Memcache does not support telnet, use Server instead'); + } +} \ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Memcached.php b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Memcached.php new file mode 100644 index 00000000..015c552c --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Memcached.php @@ -0,0 +1,287 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * Sending command to memcache server via PECL memcache API http://pecl.php.net/package/memcache + * + * @author elijaa@free.fr + * @since 20/03/2010 + */ +class Library_Command_Memcached implements Library_Command_Interface +{ + private static $_ini; + private static $_memcache; + + /** + * Constructor + * + * @param Array $ini Array from ini_parse + * + * @return void + */ + public function __construct() + { + # Importing configuration + self::$_ini = Library_Configuration_Loader::singleton(); + + # Initializing + self::$_memcache = new Memcached(); + } + + /** + * Send stats command to server + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * + * @return Array|Boolean + */ + public function stats($server, $port) + { + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command + if (($return = self::$_memcache->getStats())) { + # Delete server key based + $stats = $return[$server . ':' . $port]; + + # Adding value that miss + $stats['delete_hits'] = ''; + $stats['delete_misses'] = ''; + $stats['incr_hits'] = ''; + $stats['incr_misses'] = ''; + $stats['decr_hits'] = ''; + $stats['decr_misses'] = ''; + $stats['cas_hits'] = ''; + $stats['cas_misses'] = ''; + $stats['cas_badval'] = ''; + + return $stats; + } + return false; + } + + /** + * Send stats settings command to server + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * + * @return Array|Boolean + */ + public function settings($server, $port) + { + return false; + } + + /** + * Send stats items command to server to retrieve slabs stats + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * + * @return Array|Boolean + */ + public function slabs($server, $port) + { + throw new Exception('PECL Memcache does not support slabs stats, use Server or Memcache instead'); + } + + /** + * Send stats cachedump command to server to retrieve slabs items + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param Interger $slab Slab ID + * + * @return Array|Boolean + */ + public function items($server, $port, $slab) + { + throw new Exception('PECL Memcache does not support slabs items stats, use Server or Memcache instead'); + } + + /** + * Send get command to server to retrieve an item + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to retrieve + * + * @return String + */ + public function get($server, $port, $key) + { + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command : get + if ($item = self::$_memcache->get($key)) { + return print_r($item, true); + } + return self::$_memcache->getResultMessage(); + } + + /** + * Set an item + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to store + * @param Mixed $data Data to store + * @param Integer $duration Duration + * + * @return String + */ + function set($server, $port, $key, $data, $duration) + { + # Adding server + self::$_memcache->addServer($server, $port); + + # Checking duration + if ($duration == '') { + $duration = 0; + } + + # Executing command : set + self::$_memcache->set($key, $data, $duration); + return self::$_memcache->getResultMessage(); + } + + /** + * Delete an item + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to delete + * + * @return String + */ + public function delete($server, $port, $key) + { + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command : delete + self::$_memcache->delete($key); + return self::$_memcache->getResultMessage(); + } + + /** + * Increment the key by value + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to increment + * @param Integer $value Value to increment + * + * @return String + */ + function increment($server, $port, $key, $value) + { + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command : increment + if ($result = self::$_memcache->increment($key, $value)) { + return $result; + } + return self::$_memcache->getResultMessage(); + } + + /** + * Decrement the key by value + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to decrement + * @param Integer $value Value to decrement + * + * @return String + */ + function decrement($server, $port, $key, $value) + { + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command : decrement + if ($result = self::$_memcache->decrement($key, $value)) { + return $result; + } + return self::$_memcache->getResultMessage(); + } + + /** + * Flush all items on a server + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param Integer $delay Delay before flushing server + * + * @return String + */ + public function flush_all($server, $port, $delay) + { + # Adding server + self::$_memcache->addServer($server, $port); + + # Executing command : delete + self::$_memcache->flush($delay); + return self::$_memcache->getResultMessage(); + } + + /** + * Search for item + * Return all the items matching parameters if successful, false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to search + * + * @return Array + */ + function search($server, $port, $search, $level = false, $more = false) + { + throw new Exception('PECL Memcached does not support search function, use Server instead'); + } + + /** + * Execute a telnet command on a server + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $command Command to execute + * + * @return String + */ + function telnet($server, $port, $command) + { + throw new Exception('PECL Memcached does not support telnet, use Server instead'); + } +} \ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Server.php b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Server.php new file mode 100644 index 00000000..40a6ceaa --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Command/Server.php @@ -0,0 +1,486 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * Sending command to memcache server + * + * @author elijaa@free.fr + * @since 20/03/2010 + */ +class Library_Command_Server implements Library_Command_Interface +{ + private static $_ini; + private static $_log; + + /** + * Constructor + * + * @param Array $ini Array from ini_parse + * + * @return void + */ + public function __construct() + { + # Importing configuration + self::$_ini = Library_Configuration_Loader::singleton(); + } + + /** + * Executing a Command on a MemCache Server + * With the help of http://github.com/memcached/memcached/blob/master/doc/protocol.txt + * Return the response, or false otherwise + * + * @param String $command Command + * @param String $server Server Hostname + * @param Integer $port Server Port + * + * @return String|Boolean + */ + public function exec($command, $server, $port) + { + # Variables + $buffer = ''; + $handle = null; + + # Socket Opening + if (! ($handle = @fsockopen($server, $port, $errno, $errstr, self::$_ini->get('connection_timeout')))) { + # Adding error to log + self::$_log = utf8_encode($errstr); + Library_Data_Error::add(utf8_encode($errstr)); + return false; + } + + # Sending Command ... + fwrite($handle, $command . "\r\n"); + + # Getting first line + $buffer = fgets($handle); + + # Checking if result is valid + if ($this->end($buffer, $command)) { + # Closing socket + fclose($handle); + + # Adding error to log + self::$_log = $buffer; + + return false; + } + + # Reading Results + while ((! feof($handle))) { + # Getting line + $line = fgets($handle); + + $buffer .= $line; + + # Checking for end of MemCache command + if ($this->end($line, $command)) { + break; + } + } + # Closing socket + fclose($handle); + + return $buffer; + } + + /** + * Check if response is at the end from memcached server + * Return true if response end, true otherwise + * + * @param String $buffer Buffer received from memcached server + * @param String $command Command issued to memcached server + * + * @return Boolean + */ + private function end($buffer, $command) + { + # incr or decr also return integer + if ((preg_match('/^(incr|decr)/', $command))) { + if (preg_match('/^(END|ERROR|SERVER_ERROR|CLIENT_ERROR|NOT_FOUND|[0-9]*)/', $buffer)) { + return true; + } + } else { + # Checking command response end + if (preg_match('/^(END|DELETED|OK|ERROR|SERVER_ERROR|CLIENT_ERROR|NOT_FOUND|STORED|RESET|TOUCHED)/', $buffer)) { + return true; + } + } + return false; + } + + /** + * Parse result to make an array + * + * @param String $string String to parse + * @param Boolean $string (optionnal) Parsing stats ? + * + * @return Array + */ + public function parse($string, $stats = true) + { + # Variable + $return = array(); + + # Exploding by \r\n + $lines = preg_split('/\r\n/', $string); + + # Stats + if ($stats) { + # Browsing each line + foreach ($lines as $line) { + $data = preg_split('/ /', $line); + if (isset($data[2])) { + $return[$data[1]] = $data[2]; + } + } + } # Items + else { + # Browsing each line + foreach ($lines as $line) { + $data = preg_split('/ /', $line); + if (isset($data[1])) { + $return[$data[1]] = array(substr($data[2], 1), $data[4]); + } + } + } + return $return; + } + + /** + * Send stats command to server + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * + * @return Array|Boolean + */ + public function stats($server, $port) + { + # Executing command + if (($return = $this->exec('stats', $server, $port))) { + return $this->parse($return); + } + return false; + } + + /** + * Send stats settings command to server + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * + * @return Array|Boolean + */ + public function settings($server, $port) + { + # Executing command + if (($return = $this->exec('stats settings', $server, $port))) { + return $this->parse($return); + } + return false; + } + + /** + * Send stats items command to server to retrieve slabs stats + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * + * @return Array|Boolean + */ + public function slabs($server, $port) + { + # Initializing + $slabs = array(); + + # Finding uptime + $stats = $this->stats($server, $port); + $slabs['uptime'] = $stats['uptime']; + unset($stats); + + # Executing command : slabs stats + if (($result = $this->exec('stats slabs', $server, $port))) { + # Parsing result + $result = $this->parse($result); + $slabs['active_slabs'] = $result['active_slabs']; + $slabs['total_malloced'] = $result['total_malloced']; + unset($result['active_slabs']); + unset($result['total_malloced']); + + # Indexing by slabs + foreach ($result as $key => $value) { + $key = preg_split('/:/', $key); + $slabs[$key[0]][$key[1]] = $value; + } + + # Executing command : items stats + if (($result = $this->exec('stats items', $server, $port))) { + # Parsing result + $result = $this->parse($result); + + # Indexing by slabs + foreach ($result as $key => $value) { + $key = preg_split('/:/', $key); + $slabs[$key[1]]['items:' . $key[2]] = $value; + } + + return $slabs; + } + } + return false; + } + + /** + * Send stats cachedump command to server to retrieve slabs items + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param Interger $slab Slab ID + * + * @return Array|Boolean + */ + public function items($server, $port, $slab) + { + # Initializing + $items = false; + + # Executing command : stats cachedump + if (($result = $this->exec('stats cachedump ' . $slab . ' ' . self::$_ini->get('max_item_dump'), $server, $port))) { + # Parsing result + $items = $this->parse($result, false); + } + return $items; + } + + /** + * Send get command to server to retrieve an item + * Return the result if successful or false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to retrieve + * + * @return String + */ + public function get($server, $port, $key) + { + # Executing command : get + if (($string = $this->exec('get ' . $key, $server, $port))) { + $string = preg_replace('/^VALUE ' . preg_quote($key, '/') . '[0-9 ]*\r\n/', '', $string); + if (ord($string[0]) == 0x78 && in_array(ord($string[1]), array(0x01, 0x5e, 0x9c, 0xda))) { + return gzuncompress($string); + } + return $string; + } + return self::$_log; + } + + /** + * Set an item + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to store + * @param Mixed $data Data to store + * @param Integer $duration Duration + * + * @return String + */ + function set($server, $port, $key, $data, $duration) + { + # Formatting data + $data = preg_replace('/\r/', '', $data); + + # Executing command : set + if (($result = $this->exec('set ' . $key . ' 0 ' . $duration . ' ' . strlen($data) . "\r\n" . $data, $server, $port))) { + return $result; + } + return self::$_log; + } + + /** + * Delete an item + * Return true if successful, false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to delete + * + * @return String + */ + public function delete($server, $port, $key) + { + # Executing command : delete + if (($result = $this->exec('delete ' . $key, $server, $port))) { + return $result; + } + return self::$_log; + } + + /** + * Increment the key by value + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to increment + * @param Integer $value Value to increment + * + * @return String + */ + function increment($server, $port, $key, $value) + { + # Executing command : increment + if (($result = $this->exec('incr ' . $key . ' ' . $value, $server, $port))) { + return $result; + } + return self::$_log; + } + + /** + * Decrement the key by value + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to decrement + * @param Integer $value Value to decrement + * + * @return String + */ + function decrement($server, $port, $key, $value) + { + # Executing command : decrement + if (($result = $this->exec('decr ' . $key . ' ' . $value, $server, $port))) { + return $result; + } + return self::$_log; + } + + /** + * Flush all items on a server + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param Integer $delay Delay before flushing server + * + * @return String + */ + function flush_all($server, $port, $delay) + { + # Executing command : flush_all + if (($result = $this->exec('flush_all ' . $delay, $server, $port))) { + return $result; + } + return self::$_log; + } + + /** + * Search for item + * Return all the items matching parameters if successful, false otherwise + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $key Key to search + * @param String $level Level of Detail + * @param String $more More action + * + * @return array + */ + function search($server, $port, $search, $level = false, $more = false) + { + $slabs = array(); + $items = false; + + # Executing command : stats + if (($level == 'full') && ($result = $this->exec('stats', $server, $port))) { + # Parsing result + $result = $this->parse($result); + $infinite = (isset($result['time'], $result['uptime'])) ? ($result['time'] - $result['uptime']) : 0; + } + + # Executing command : slabs stats + if (($result = $this->exec('stats slabs', $server, $port))) { + # Parsing result + $result = $this->parse($result); + unset($result['active_slabs']); + unset($result['total_malloced']); + # Indexing by slabs + foreach ($result as $key => $value) { + $key = preg_split('/:/', $key); + $slabs[$key[0]] = true; + } + } + + # Exploring each slabs + foreach ($slabs as $slab => $unused) { + # Executing command : stats cachedump + if (($result = $this->exec('stats cachedump ' . $slab . ' 0', $server, $port))) { + # Parsing result + preg_match_all('/^ITEM ((?:.*)' . preg_quote($search, '/') . '(?:.*)) \[([0-9]*) b; ([0-9]*) s\]\r\n/imU', $result, $matchs, PREG_SET_ORDER); + foreach ($matchs as $item) { + # Search & Delete + if ($more == 'delete') { + $items[] = $item[1] . ' : ' . $this->delete($server, $port, $item[1]); + # Basic search + } else { + # Detail level + if ($level == 'full') { + $items[] = $item[1] . ' : [' . trim(Library_Data_Analysis::byteResize($item[2])) . 'b, expire in ' . (($item[3] == $infinite) ? '∞' : Library_Data_Analysis::uptime($item[3] - time(), true)) . ']'; + } else { + $items[] = $item[1]; + } + } + } + } + unset($slabs[$slab]); + } + + if (is_array($items)) { + sort($items); + } + + return $items; + } + + /** + * Execute a telnet command on a server + * Return the result + * + * @param String $server Hostname + * @param Integer $port Hostname Port + * @param String $command Command to execute + * + * @return String + */ + function telnet($server, $port, $command) + { + # Executing command + if (($result = $this->exec($command, $server, $port))) { + return $result; + } + return self::$_log; + } +} diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Configuration/Loader.php b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Configuration/Loader.php new file mode 100644 index 00000000..64d5349a --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Configuration/Loader.php @@ -0,0 +1,186 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * Configuration class for editing, saving, ... + * + * @author elijaa@free.fr + * @since 19/05/2010 + */ +class Library_Configuration_Loader +{ + # Singleton + protected static $_instance = null; + + # Configuration file + protected static $_iniPath = './Config/Memcache.php'; + + # Configuration needed keys and default values + protected static $_iniKeys = array('stats_api' => 'Server', + 'slabs_api' => 'Server', + 'items_api' => 'Server', + 'get_api' => 'Server', + 'set_api' => 'Server', + 'delete_api' => 'Server', + 'flush_all_api' => 'Server', + 'connection_timeout' => 1, + 'max_item_dump' => 100, + 'refresh_rate' => 2, + 'memory_alert' => 80, + 'hit_rate_alert' => 90, + 'eviction_alert' => 0, + 'file_path' => 'Temp/', + 'servers' => array('Default' => array('127.0.0.1:11211' => array('hostname' => '127.0.0.1', 'port' => 11211)))); + + # Storage + protected static $_ini = array(); + + /** + * Constructor, load configuration file and parse server list + * + * @return Void + */ + protected function __construct() + { + # Checking ini File + if (file_exists(self::$_iniPath)) { + # Opening ini file + self::$_ini = require self::$_iniPath; + } else { + # Fallback + self::$_ini = self::$_iniKeys; + } + } + + /** + * Get Library_Configuration_Loader singleton + * + * @return Library_Configuration_Loader + */ + public static function singleton() + { + if (! isset(self::$_instance)) { + self::$_instance = new self(); + } + return self::$_instance; + } + + /** + * Config key to retrieve + * Return the value, or false if does not exists + * + * @param String $key Key to get + * + * @return Mixed + */ + public function get($key) + { + if (isset(self::$_ini[$key])) { + return self::$_ini[$key]; + } + return false; + } + + /** + * Servers to retrieve from cluster + * Return the value, or false if does not exists + * + * @param String $cluster Cluster to retreive + * + * @return Array + */ + public function cluster($cluster) + { + if (isset(self::$_ini['servers'][$cluster])) { + return self::$_ini['servers'][$cluster]; + } + return array(); + } + + /** + * Check and return server data + * Return the value, or false if does not exists + * + * @param String $server Server to retreive + * + * @return Array + */ + public function server($server) + { + foreach (self::$_ini['servers'] as $cluster => $servers) { + if (isset(self::$_ini['servers'][$cluster][$server])) { + return self::$_ini['servers'][$cluster][$server]; + } + } + return array(); + } + + /** + * Config key to set + * + * @param String $key Key to set + * @param Mixed $value Value to set + * + * @return Boolean + */ + public function set($key, $value) + { + self::$_ini[$key] = $value; + } + + /** + * Return actual ini file path + * + * @return String + */ + public function path() + { + return self::$_iniPath; + } + + /** + * Check if every ini keys are set + * Return true if ini is correct, false otherwise + * + * @return Boolean + */ + public function check() + { + # Checking configuration keys + foreach (array_keys(self::$_iniKeys) as $iniKey) { + # Ini file key not set + if (isset(self::$_ini[$iniKey]) === false) { + return false; + } + } + return true; + } + + /** + * Write ini file + * Return true if written, false otherwise + * + * @return Boolean + */ + public function write() + { + if ($this->check()) { + return is_numeric(file_put_contents(self::$_iniPath, '<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * Analysis of memcached command response + * + * @author elijaa@free.fr + * @since 20/03/2010 + */ +class Library_Data_Analysis +{ + private static $_non_additive = array( + 'libevent', + 'pid', + 'pointer_size', + 'time', + 'uptime', + 'version', + ); + + /** + * Merge two arrays of stats from Command_XX::stats() + * + * @param Array $array Statistic from Command_XX::stats() + * @param Array $stats Statistic from Command_XX::stats() + * + * @return Array + */ + public static function merge($array, $stats) + { + # Checking input + if (! is_array($array)) { + return $stats; + } elseif (! is_array($stats)) { + return $array; + } + + # Merging Stats + foreach ($stats as $key => $value) { + if (! isset($array[$key]) || in_array($key, self::$_non_additive)) { + $array[$key] = $value; + } else { + $array[$key] += $value; + } + } + return $array; + } + + /** + * Diff two arrays of stats from Command_XX::stats() + * + * @param Array $array Statistic from Command_XX::stats() + * @param Array $stats Statistic from Command_XX::stats() + * + * @return Array + */ + public static function diff($array, $stats) + { + # Checking input + if (! is_array($array)) { + return $stats; + } elseif (! is_array($stats)) { + return $array; + } + + # Diff for each key + foreach ($stats as $key => $value) { + if (isset($array[$key]) && ! in_array($key, self::$_non_additive)) { + $stats[$key] = $value - $array[$key]; + } + } + + return $stats; + } + + /** + * Analyse and return memcache stats command + * + * @param Array $stats Statistic from Command_XX::stats() + * + * @return Array + */ + public static function stats($stats) + { + if (! is_array($stats) || (count($stats) == 0)) { + return false; + } + + # Command set() + $stats['set_rate'] = ($stats['cmd_set'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_set'] / $stats['uptime'], 1); + + # Command get() + $stats['get_hits_percent'] = ($stats['cmd_get'] == 0) ? ' - ' : sprintf('%.1f', $stats['get_hits'] / $stats['cmd_get'] * 100, 1); + $stats['get_misses_percent'] = ($stats['cmd_get'] == 0) ? ' - ' : sprintf('%.1f', $stats['get_misses'] / $stats['cmd_get'] * 100, 1); + $stats['get_rate'] = ($stats['cmd_get'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_get'] / $stats['uptime'], 1); + + # Command delete(), version > 1.2.X + if (isset($stats['delete_hits'], $stats['delete_misses'])) { + $stats['cmd_delete'] = $stats['delete_hits'] + $stats['delete_misses']; + $stats['delete_hits_percent'] = ($stats['cmd_delete'] == 0) ? ' - ' : sprintf('%.1f', $stats['delete_hits'] / $stats['cmd_delete'] * 100, 1); + $stats['delete_misses_percent'] = ($stats['cmd_delete'] == 0) ? ' - ' : sprintf('%.1f', $stats['delete_misses'] / $stats['cmd_delete'] * 100, 1); + } else { + $stats['cmd_delete'] = 0; + $stats['delete_hits_percent'] = ' - '; + $stats['delete_misses_percent'] = ' - '; + } + $stats['delete_rate'] = ($stats['cmd_delete'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_delete'] / $stats['uptime'], 1); + + # Command cas(), version > 1.2.X + if (isset($stats['cas_hits'], $stats['cas_misses'], $stats['cas_badval'])) { + $stats['cmd_cas'] = $stats['cas_hits'] + $stats['cas_misses'] + $stats['cas_badval']; + $stats['cas_hits_percent'] = ($stats['cmd_cas'] == 0) ? ' - ' : sprintf('%.1f', $stats['cas_hits'] / $stats['cmd_cas'] * 100, 1); + $stats['cas_misses_percent'] = ($stats['cmd_cas'] == 0) ? ' - ' : sprintf('%.1f', $stats['cas_misses'] / $stats['cmd_cas'] * 100, 1); + $stats['cas_badval_percent'] = ($stats['cmd_cas'] == 0) ? ' - ' : sprintf('%.1f', $stats['cas_badval'] / $stats['cmd_cas'] * 100, 1); + } else { + $stats['cmd_cas'] = 0; + $stats['cas_hits_percent'] = ' - '; + $stats['cas_misses_percent'] = ' - '; + $stats['cas_badval_percent'] = ' - '; + } + $stats['cas_rate'] = ($stats['cmd_cas'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_cas'] / $stats['uptime'], 1); + + # Command increment(), version > 1.2.X + if (isset($stats['incr_hits'], $stats['incr_misses'])) { + $stats['cmd_incr'] = $stats['incr_hits'] + $stats['incr_misses']; + $stats['incr_hits_percent'] = ($stats['cmd_incr'] == 0) ? ' - ' : sprintf('%.1f', $stats['incr_hits'] / $stats['cmd_incr'] * 100, 1); + $stats['incr_misses_percent'] = ($stats['cmd_incr'] == 0) ? ' - ' : sprintf('%.1f', $stats['incr_misses'] / $stats['cmd_incr'] * 100, 1); + } else { + $stats['cmd_incr'] = 0; + $stats['incr_hits_percent'] = ' - '; + $stats['incr_misses_percent'] = ' - '; + } + $stats['incr_rate'] = ($stats['cmd_incr'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_incr'] / $stats['uptime'], 1); + + # Command decrement(), version > 1.2.X + if (isset($stats['decr_hits'], $stats['decr_misses'])) { + $stats['cmd_decr'] = $stats['decr_hits'] + $stats['decr_misses']; + $stats['decr_hits_percent'] = ($stats['cmd_decr'] == 0) ? ' - ' : sprintf('%.1f', $stats['decr_hits'] / $stats['cmd_decr'] * 100, 1); + $stats['decr_misses_percent'] = ($stats['cmd_decr'] == 0) ? ' - ' : sprintf('%.1f', $stats['decr_misses'] / $stats['cmd_decr'] * 100, 1); + } else { + $stats['cmd_decr'] = 0; + $stats['decr_hits_percent'] = ' - '; + $stats['decr_misses_percent'] = ' - '; + } + $stats['decr_rate'] = ($stats['cmd_decr'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_decr'] / $stats['uptime'], 1); + + # Command decrement(), version > 1.4.7 + if (isset($stats['touch_hits'], $stats['touch_misses'])) { + $stats['cmd_touch'] = $stats['touch_hits'] + $stats['touch_misses']; + $stats['touch_hits_percent'] = ($stats['cmd_touch'] == 0) ? ' - ' : sprintf('%.1f', $stats['touch_hits'] / $stats['cmd_touch'] * 100, 1); + $stats['touch_misses_percent'] = ($stats['cmd_touch'] == 0) ? ' - ' : sprintf('%.1f', $stats['touch_misses'] / $stats['cmd_touch'] * 100, 1); + } else { + $stats['cmd_touch'] = 0; + $stats['touch_hits_percent'] = ' - '; + $stats['touch_misses_percent'] = ' - '; + } + $stats['touch_rate'] = ($stats['cmd_touch'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_touch'] / $stats['uptime'], 1); + + # Total hit & miss + #$stats['cmd_total'] = $stats['cmd_get'] + $stats['cmd_set'] + $stats['cmd_delete'] + $stats['cmd_cas'] + $stats['cmd_incr'] + $stats['cmd_decr']; + #$stats['hit_percent'] = ($stats['cmd_get'] == 0) ? '0.0' : sprintf('%.1f', ($stats['get_hits']) / ($stats['get_hits'] + $stats['get_misses']) * 100, 1); + #$stats['miss_percent'] = ($stats['cmd_get'] == 0) ? '0.0' : sprintf('%.1f', ($stats['get_misses']) / ($stats['get_hits'] + $stats['get_misses']) * 100, 1); + + + # Command flush_all + if (isset($stats['cmd_flush'])) { + $stats['flush_rate'] = ($stats['cmd_flush'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_flush'] / $stats['uptime'], 1); + } else { + $stats['flush_rate'] = '0.0'; + } + + # Cache size + $stats['bytes_percent'] = ($stats['limit_maxbytes'] == 0) ? '0.0' : sprintf('%.1f', $stats['bytes'] / $stats['limit_maxbytes'] * 100, 1); + + # Request rate + $stats['request_rate'] = sprintf('%.1f', ($stats['cmd_get'] + $stats['cmd_set'] + $stats['cmd_delete'] + $stats['cmd_cas'] + $stats['cmd_incr'] + $stats['cmd_decr']) / $stats['uptime'], 1); + $stats['hit_rate'] = sprintf('%.1f', ($stats['get_hits']) / $stats['uptime'], 1); + $stats['miss_rate'] = sprintf('%.1f', ($stats['get_misses']) / $stats['uptime'], 1); + + # Eviction & reclaimed rate + $stats['eviction_rate'] = ($stats['evictions'] == 0) ? '0.0' : sprintf('%.1f', $stats['evictions'] / $stats['uptime'], 1); + $stats['reclaimed_rate'] = (! isset($stats['reclaimed']) || ($stats['reclaimed'] == 0)) ? '0.0' : sprintf('%.1f', $stats['reclaimed'] / $stats['uptime'], 1); + + return $stats; + } + + /** + * Analyse and return memcache slabs command + * + * @param Array $slabs Statistic from Command_XX::slabs() + * + * @return Array + */ + public static function slabs($slabs) + { + # Initializing Used Slabs + $slabs['used_slabs'] = 0; + $slabs['total_wasted'] = 0; + + # Request Rate par Slabs + foreach ($slabs as $id => $slab) { + # Check if it's a Slab + if (is_numeric($id)) { + # Check if Slab is used + if ($slab['used_chunks'] > 0) { + $slabs['used_slabs'] ++; + } + $slabs[$id]['request_rate'] = sprintf('%.1f', ($slab['get_hits'] + $slab['cmd_set'] + $slab['delete_hits'] + $slab['cas_hits'] + $slab['cas_badval'] + $slab['incr_hits'] + $slab['decr_hits']) / $slabs['uptime'], 1); + $slabs[$id]['mem_wasted'] = (($slab['total_chunks'] * $slab['chunk_size']) < $slab['mem_requested']) ? (($slab['total_chunks'] - $slab['used_chunks']) * $slab['chunk_size']) : (($slab['total_chunks'] * $slab['chunk_size']) - $slab['mem_requested']); + $slabs['total_wasted'] += $slabs[$id]['mem_wasted']; + } + } + + # Cheking server total malloced > 0 + if (! isset($slabs['total_malloced'])) { + $slabs['total_malloced'] = 0; + } + + return $slabs; + } + + /** + * Calculate Uptime + * + * @param Integer $uptime Uptime timestamp + * @param Boolean $compact Compact Mode + * + * @return String + */ + public static function uptime($uptime, $compact = false) + { + if ($uptime > 0) { + $days = floor($uptime / 60 / 60 / 24); + $hours = $uptime / 60 / 60 % 24; + $mins = $uptime / 60 % 60; + if (($days + $hours + $mins) == 0) { + return ' less than 1 min'; + } + if ($compact == false) { + return $days . ' day' . (($days > 1) ? 's' : '') . ' ' . $hours . ' hr' . (($hours > 1) ? 's' : '') . ' ' . $mins . ' min' . (($mins > 1) ? 's' : ''); + } else { + return $days . 'd ' . $hours . 'h ' . $mins . 'm'; + } + } + return ' - '; + } + + /** + * Resize a byte value + * + * @param Integer $value Value to resize + * + * @return String + */ + public static function byteResize($value) + { + # Unit list + $units = array('', 'K', 'M', 'G', 'T'); + + # Resizing + foreach ($units as $unit) { + if ($value < 1024) { + break; + } + $value /= 1024; + } + return sprintf('%.1f %s', $value, $unit); + } + + /** + * Resize a value + * + * @param Integer $value Value to resize + * + * @return String + */ + public static function valueResize($value) + { + # Unit list + $units = array('', 'K', 'M', 'G', 'T'); + + # Resizing + foreach ($units as $unit) { + if ($value < 1000) { + break; + } + $value /= 1000; + } + return sprintf('%.1f%s', $value, $unit); + } + + /** + * Resize a hit value + * + * @param Integer $value Hit value to resize + * + * @return String + */ + public static function hitResize($value) + { + # Unit list + $units = array('', 'K', 'M', 'G', 'T'); + + # Resizing + foreach ($units as $unit) { + if ($value < 10000000) { + break; + } + $value /= 1000; + } + return sprintf('%.0f%s', $value, $unit); + } +} diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Data/Error.php b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Data/Error.php new file mode 100644 index 00000000..8c2d2f8a --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Data/Error.php @@ -0,0 +1,60 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * Error container + * + * @author elijaa@free.fr + * @since 11/10/2010 + */ +class Library_Data_Error +{ + private static $_errors = array(); + + /** + * Add an error to the container + * Return true if successful, false otherwise + * + * @param String $error Error message + * + * @return Boolean + */ + public static function add($error) + { + return array_push(self::$_errors, $error); + } + + /** + * Return last Error message + * + * @return Mixed + */ + public static function last() + { + return (isset(self::$_errors[count(self::$_errors) - 1])) ? self::$_errors[count(self::$_errors) - 1] : null; + } + + /** + * Return errors count + * + * @return Integer + */ + public static function count() + { + return count(self::$_errors); + } +} \ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Data/Version.php b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Data/Version.php new file mode 100644 index 00000000..f82ded9a --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/Data/Version.php @@ -0,0 +1,72 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * Version container + * + * @author cyrille.mahieux@free.fr + * @since 24/08/2011 + */ +class Library_Data_Version +{ + # Version file + protected static $_file = 'latest'; + + # Google Code latest version data file + protected static $_latest = 'https://blog.elijaa.org/public/latest'; + + # Time between HTTP check + protected static $_time = 1296000; # 15 days + + + /** + * Check for the latest version, from local cache or via http + * Return true if a newer version is available, false otherwise + * + * @return Boolean + */ + public static function check() + { + # Loading ini file + $_ini = Library_Configuration_Loader::singleton(); + + # Version definition file path + $path = rtrim($_ini->get('file_path'), '/') . DIRECTORY_SEPARATOR . self::$_file; + + # Checking if path is writable + if (is_writable($_ini->get('file_path'))) { + # Checking if file was modified for less than 15 days ago + if ((is_array($stats = @stat($path))) && (isset($stats['mtime'])) && ($stats['mtime'] > (time() - self::$_time))) { + # Opening file and checking for latest version + return (version_compare(CURRENT_VERSION, file_get_contents($path)) == - 1); + } else { + # Getting last version from Google Code + if ($latest = @file_get_contents(self::$_latest)) { + # Saving latest version in file + file_put_contents($path, $latest); + + # Checking for latest version + return (version_compare(CURRENT_VERSION, $latest) == - 1); + } else { + # To avoid error spam + file_put_contents($path, 'Net unreachable'); + return true; + } + } + } + } +} \ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/HTML/Components.php b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/HTML/Components.php new file mode 100644 index 00000000..8830147a --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Library/HTML/Components.php @@ -0,0 +1,143 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * Manipulation of HTML + * + * @author elijaa@free.fr + * @since 05/04/2010 + */ +class Library_HTML_Components +{ + + /** + * Dump server list in an HTML select + * + * @return String + */ + public static function serverSelect($name, $selected = '', $class = '', $events = '') + { + # Loading ini file + $_ini = Library_Configuration_Loader::singleton(); + + # Select Name + $serverList = ''; + } + + /** + * Dump cluster list in an HTML select + * + * @return String + */ + public static function clusterSelect($name, $selected = '', $class = '', $events = '') + { + # Loading ini file + $_ini = Library_Configuration_Loader::singleton(); + + # Select Name + $clusterList = ''; + } + + /** + * Dump server response in proper formatting + * + * @param String $hostname Hostname + * @param String $port Port + * @param Mixed $data Data (reponse) + * + * @return String + */ + public static function serverResponse($hostname, $port, $data) + { + $header = 'Server ' . $hostname . ':' . $port . "\r\n"; + $return = ''; + if (is_array($data)) { + foreach ($data as $string) { + $return .= $string . "\r\n"; + } + return $header . htmlentities($return, ENT_NOQUOTES | 0, 'UTF-8') . "\r\n"; + } + return $header . $return . $data . "\r\n"; + } + + /** + * Dump api list un HTML select with select name + * + * @param String $iniAPI API Name from ini file + * @param String $id Select ID + * + * @return String + */ + public static function apiList($iniAPI = '', $id) + { + return ''; + } + + /** + * Used to see if an option is selected + * + * @param String $actual Actual value + * @param String $selected Selected value + * + * @return String + */ + private static function selected($actual, $selected) + { + if ($actual == $selected) { + return 'selected="selected"'; + } + } +} \ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Public/Scripts/Highcharts/highcharts.js b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Public/Scripts/Highcharts/highcharts.js new file mode 100644 index 00000000..3abfda45 --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Public/Scripts/Highcharts/highcharts.js @@ -0,0 +1,391 @@ +/* + Highcharts JS v5.0.9 (2017-03-08) + + (c) 2009-2016 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(I,a){"object"===typeof module&&module.exports?module.exports=I.document?a(I):a:I.Highcharts=a(I)})("undefined"!==typeof window?window:this,function(I){I=function(){var a=window,B=a.document,z=a.navigator&&a.navigator.userAgent||"",C=B&&B.createElementNS&&!!B.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,E=/(edge|msie|trident)/i.test(z)&&!window.opera,u=!C,h=/Firefox/.test(z),n=h&&4>parseInt(z.split("Firefox/")[1],10);return a.Highcharts?a.Highcharts.error(16,!0):{product:"Highcharts", +version:"5.0.9",deg2rad:2*Math.PI/360,doc:B,hasBidiBug:n,hasTouch:B&&void 0!==B.documentElement.ontouchstart,isMS:E,isWebKit:/AppleWebKit/.test(z),isFirefox:h,isTouchDevice:/(Mobile|Android|Windows Phone)/.test(z),SVG_NS:"http://www.w3.org/2000/svg",chartCount:0,seriesTypes:{},symbolSizes:{},svg:C,vml:u,win:a,charts:[],marginNames:["plotTop","marginRight","marginBottom","plotLeft"],noop:function(){}}}();(function(a){var B=[],z=a.charts,C=a.doc,E=a.win;a.error=function(u,h){u=a.isNumber(u)?"Highcharts error #"+ +u+": www.highcharts.com/errors/"+u:u;if(h)throw Error(u);E.console&&console.log(u)};a.Fx=function(a,h,n){this.options=h;this.elem=a;this.prop=n};a.Fx.prototype={dSetter:function(){var a=this.paths[0],h=this.paths[1],n=[],t=this.now,l=a.length,k;if(1===t)n=this.toD;else if(l===h.length&&1>t)for(;l--;)k=parseFloat(a[l]),n[l]=isNaN(k)?a[l]:t*parseFloat(h[l]-k)+k;else n=h;this.elem.attr("d",n,null,!0)},update:function(){var a=this.elem,h=this.prop,n=this.now,t=this.options.step;if(this[h+"Setter"])this[h+ +"Setter"]();else a.attr?a.element&&a.attr(h,n,null,!0):a.style[h]=n+this.unit;t&&t.call(a,n,this)},run:function(a,h,n){var u=this,l=function(a){return l.stopped?!1:u.step(a)},k;this.startTime=+new Date;this.start=a;this.end=h;this.unit=n;this.now=this.start;this.pos=0;l.elem=this.elem;l.prop=this.prop;l()&&1===B.push(l)&&(l.timerId=setInterval(function(){for(k=0;k=k+this.startTime){this.now=this.end;this.pos=1;this.update();a=e[this.prop]=!0;for(c in e)!0!==e[c]&&(a=!1);a&&l&&l.call(u);u=!1}else this.pos=t.easing((h-this.startTime)/k),this.now=this.start+(this.end-this.start)*this.pos,this.update(),u=!0;return u},initPath:function(u,h,n){function t(a){var b,f;for(r=a.length;r--;)b="M"===a[r]||"L"===a[r],f=/[a-zA-Z]/.test(a[r+3]),b&&f&&a.splice(r+1,0,a[r+1],a[r+2],a[r+1],a[r+ +2])}function l(a,f){for(;a.lengthe?"AM":"PM",P:12>e?"am":"pm",S:A(l.getSeconds()),L:A(Math.round(h% +1E3),3)},a.dateFormats);for(k in t)for(;-1!==u.indexOf("%"+k);)u=u.replace("%"+k,"function"===typeof t[k]?t[k](h):t[k]);return n?u.substr(0,1).toUpperCase()+u.substr(1):u};a.formatSingle=function(u,h){var n=/\.([0-9])/,t=a.defaultOptions.lang;/f$/.test(u)?(n=(n=u.match(n))?n[1]:-1,null!==h&&(h=a.numberFormat(h,n,t.decimalPoint,-1=n&&(h=[1/n]))); +for(t=0;t=u||!l&&k<=(h[t]+(h[t+1]||h[t]))/2);t++);return e=a.correctFloat(e*n,-Math.round(Math.log(.001)/Math.LN10))};a.stableSort=function(a,h){var n=a.length,t,l;for(l=0;ln&&(n=a[h]);return n};a.destroyObjectProperties= +function(a,h){for(var n in a)a[n]&&a[n]!==h&&a[n].destroy&&a[n].destroy(),delete a[n]};a.discardElement=function(u){var h=a.garbageBin;h||(h=a.createElement("div"));u&&h.appendChild(u);h.innerHTML=""};a.correctFloat=function(a,h){return parseFloat(a.toPrecision(h||14))};a.setAnimation=function(u,h){h.renderer.globalAnimation=a.pick(u,h.options.chart.animation,!0)};a.animObject=function(u){return a.isObject(u)?a.merge(u):{duration:u?500:0}};a.timeUnits={millisecond:1,second:1E3,minute:6E4,hour:36E5, +day:864E5,week:6048E5,month:24192E5,year:314496E5};a.numberFormat=function(u,h,n,t){u=+u||0;h=+h;var l=a.defaultOptions.lang,k=(u.toString().split(".")[1]||"").length,e,c;-1===h?h=Math.min(k,20):a.isNumber(h)||(h=2);c=(Math.abs(u)+Math.pow(10,-Math.max(h,k)-1)).toFixed(h);k=String(a.pInt(c));e=3u?"-":"")+(e?k.substr(0,e)+t:"");u+=k.substr(e).replace(/(\d{3})(?=\d)/g,"$1"+t);h&&(u+=n+c.slice(-h));return u};Math.easeInOutSine= +function(a){return-.5*(Math.cos(Math.PI*a)-1)};a.getStyle=function(u,h){return"width"===h?Math.min(u.offsetWidth,u.scrollWidth)-a.getStyle(u,"padding-left")-a.getStyle(u,"padding-right"):"height"===h?Math.min(u.offsetHeight,u.scrollHeight)-a.getStyle(u,"padding-top")-a.getStyle(u,"padding-bottom"):(u=E.getComputedStyle(u,void 0))&&a.pInt(u.getPropertyValue(h))};a.inArray=function(a,h){return h.indexOf?h.indexOf(a):[].indexOf.call(h,a)};a.grep=function(a,h){return[].filter.call(a,h)};a.find=function(a, +h){return[].find.call(a,h)};a.map=function(a,h){for(var n=[],t=0,l=a.length;t>16,(h&65280)>>8,h&255,1]:4===n&&(t=[(h&3840)>>4|(h&3840)>>8,(h&240)>>4|h&240,(h&15)<<4|h&15,1])),!t)for(l=this.parsers.length;l--&&!t;)k=this.parsers[l],(n=k.regex.exec(h))&&(t=k.parse(n));this.rgba=t||[]},get:function(a){var h= +this.input,t=this.rgba,l;this.stops?(l=E(h),l.stops=[].concat(l.stops),B(this.stops,function(k,e){l.stops[e]=[l.stops[e][0],k.get(a)]})):l=t&&z(t[0])?"rgb"===a||!a&&1===t[3]?"rgb("+t[0]+","+t[1]+","+t[2]+")":"a"===a?t[3]:"rgba("+t.join(",")+")":h;return l},brighten:function(a){var h,t=this.rgba;if(this.stops)B(this.stops,function(l){l.brighten(a)});else if(z(a)&&0!==a)for(h=0;3>h;h++)t[h]+=u(255*a),0>t[h]&&(t[h]=0),255w.width)w={width:0,height:0}}else w=this.htmlGetBBox();f.isSVG&&(a=w.width,f=w.height,c&&"11px"===c.fontSize&&17===Math.round(f)&&(w.height=f=14),g&&(w.width=Math.abs(f*Math.sin(d))+Math.abs(a*Math.cos(d)), +w.height=Math.abs(f*Math.cos(d))+Math.abs(a*Math.sin(d))));if(m&&0]*>/g,"")))},textSetter:function(a){a!==this.textStr&&(delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this))},fillSetter:function(a,g,f){"string"===typeof a?f.setAttribute(g,a):a&&this.colorGradient(a,g,f)},visibilitySetter:function(a,g,f){"inherit"===a?f.removeAttribute(g):f.setAttribute(g,a)},zIndexSetter:function(a, +g){var w=this.renderer,f=this.parentGroup,b=(f||w).element||w.box,d,c=this.element,q;d=this.added;var D;k(a)&&(c.zIndex=a,a=+a,this[g]===a&&(d=!1),this[g]=a);if(d){(a=this.zIndex)&&f&&(f.handleZ=!0);g=b.childNodes;for(D=0;Da||!k(a)&&k(d)||0>a&&!k(d)&&b!==w.box)&&(b.insertBefore(c,f),q=!0);q||b.appendChild(c)}return q},_defaultSetter:function(a,g,f){f.setAttribute(g,a)}};B.prototype.yGetter=B.prototype.xGetter;B.prototype.translateXSetter=B.prototype.translateYSetter= +B.prototype.rotationSetter=B.prototype.verticalAlignSetter=B.prototype.scaleXSetter=B.prototype.scaleYSetter=function(a,g){this[g]=a;this.doTransform=!0};B.prototype["stroke-widthSetter"]=B.prototype.strokeSetter=function(a,g,f){this[g]=a;this.stroke&&this["stroke-width"]?(B.prototype.fillSetter.call(this,this.stroke,"stroke",f),f.setAttribute("stroke-width",this["stroke-width"]),this.hasStroke=!0):"stroke-width"===g&&0===a&&this.hasStroke&&(f.removeAttribute("stroke"),this.hasStroke=!1)};z=a.SVGRenderer= +function(){this.init.apply(this,arguments)};z.prototype={Element:B,SVG_NS:M,init:function(a,g,b,d,c,D){var w;d=this.createElement("svg").attr({version:"1.1","class":"highcharts-root"}).css(this.getStyle(d));w=d.element;a.appendChild(w);-1===a.innerHTML.indexOf("xmlns")&&u(w,"xmlns",this.SVG_NS);this.isSVG=!0;this.box=w;this.boxWrapper=d;this.alignedObjects=[];this.url=(f||q)&&p.getElementsByTagName("base").length?N.location.href.replace(/#.*?$/,"").replace(/<[^>]*>/g,"").replace(/([\('\)])/g,"\\$1").replace(/ /g, +"%20"):"";this.createElement("desc").add().element.appendChild(p.createTextNode("Created with Highcharts 5.0.9"));this.defs=this.createElement("defs").add();this.allowHTML=D;this.forExport=c;this.gradients={};this.cache={};this.cacheKeys=[];this.imgCount=0;this.setSize(g,b,!1);var y;f&&a.getBoundingClientRect&&(g=function(){t(a,{left:0,top:0});y=a.getBoundingClientRect();t(a,{left:Math.ceil(y.left)-y.left+"px",top:Math.ceil(y.top)-y.top+"px"})},g(),this.unSubPixelFix=C(N,"resize",g))},getStyle:function(a){return this.style= +b({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},setStyle:function(a){this.boxWrapper.css(this.getStyle(a))},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();c(this.gradients||{});this.gradients=null;a&&(this.defs=a.destroy());this.unSubPixelFix&&this.unSubPixelFix();return this.alignedObjects=null},createElement:function(a){var g=new this.Element; +g.init(this,a);return g},draw:J,getRadialAttr:function(a,g){return{cx:a[0]-a[2]/2+g.cx*a[2],cy:a[1]-a[2]/2+g.cy*a[2],r:g.r*a[2]}},buildText:function(a){var g=a.element,f=this,w=f.forExport,b=K(a.textStr,"").toString(),c=-1!==b.indexOf("\x3c"),q=g.childNodes,D,y,x,r,G=u(g,"x"),m=a.styles,e=a.textWidth,l=m&&m.lineHeight,v=m&&m.textOutline,k=m&&"ellipsis"===m.textOverflow,h=m&&"nowrap"===m.whiteSpace,F=m&&m.fontSize,A,J=q.length,m=e&&!a.added&&this.box,n=function(a){var w;w=/(px|em)$/.test(a&&a.style.fontSize)? +a.style.fontSize:F||f.style.fontSize||12;return l?L(l):f.fontMetrics(w,a.getAttribute("style")?a:g).h};A=[b,k,h,l,v,F,e].join();if(A!==a.textCache){for(a.textCache=A;J--;)g.removeChild(q[J]);c||v||k||e||-1!==b.indexOf(" ")?(D=/<.*class="([^"]+)".*>/,y=/<.*style="([^"]+)".*>/,x=/<.*href="(http[^"]+)".*>/,m&&m.appendChild(g),b=c?b.replace(/<(b|strong)>/g,'\x3cspan style\x3d"font-weight:bold"\x3e').replace(/<(i|em)>/g,'\x3cspan style\x3d"font-style:italic"\x3e').replace(//g, +"\x3c/span\x3e").split(//g):[b],b=d(b,function(a){return""!==a}),H(b,function(b,d){var c,q=0;b=b.replace(/^\s+|\s+$/g,"").replace(//g,"\x3c/span\x3e|||");c=b.split("|||");H(c,function(b){if(""!==b||1===c.length){var m={},v=p.createElementNS(f.SVG_NS,"tspan"),l,F;D.test(b)&&(l=b.match(D)[1],u(v,"class",l));y.test(b)&&(F=b.match(y)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),u(v,"style",F));x.test(b)&&!w&&(u(v,"onclick",'location.href\x3d"'+b.match(x)[1]+ +'"'),t(v,{cursor:"pointer"}));b=(b.replace(/<(.|\n)*?>/g,"")||" ").replace(/</g,"\x3c").replace(/>/g,"\x3e");if(" "!==b){v.appendChild(p.createTextNode(b));q?m.dx=0:d&&null!==G&&(m.x=G);u(v,m);g.appendChild(v);!q&&d&&(!S&&w&&t(v,{display:"block"}),u(v,"dy",n(v)));if(e){m=b.replace(/([^\^])-/g,"$1- ").split(" ");l=1e,void 0===r&&(r=A),k&&r?(P/=2,""===L||!A&&.5>P?m=[]:(L=b.substring(0,L.length+(A?-1:1)*Math.ceil(P)),m=[L+(3e&&(e=H)),m.length&&v.appendChild(p.createTextNode(m.join(" ").replace(/- /g,"-")));a.rotation=K}q++}}})}),r&&a.attr("title",a.textStr),m&&m.removeChild(g), +v&&a.applyTextOutline&&a.applyTextOutline(v)):g.appendChild(p.createTextNode(b.replace(/</g,"\x3c").replace(/>/g,"\x3e")))}},getContrast:function(a){a=n(a).rgba;return 510f?d>g+q&&dD?d>g+q&&db&&D>a+q&&Dd&&D>a+q&&Da?a+3:Math.round(1.2*a);return{h:g,b:Math.round(.8*g),f:a}},rotCorr:function(a,g,f){var b=a;g&&f&&(b=Math.max(b*Math.cos(g*e),4));return{x:-a/3*Math.sin(g* +e),y:b}},label:function(f,d,c,q,D,y,m,G,r){var w=this,e=w.g("button"!==r&&"label"),v=e.text=w.text("",0,0,m).attr({zIndex:1}),p,l,F=0,A=3,h=0,J,t,S,n,M,K={},L,u,O=/^url\((.*?)\)$/.test(q),R=O,P,Q,N,U;r&&e.addClass("highcharts-"+r);R=O;P=function(){return(L||0)%2/2};Q=function(){var a=v.element.style,g={};l=(void 0===J||void 0===t||M)&&k(v.textStr)&&v.getBBox();e.width=(J||l.width||0)+2*A+h;e.height=(t||l.height||0)+2*A;u=A+w.fontMetrics(a&&a.fontSize,v).b;R&&(p||(e.box=p=w.symbols[q]||O?w.symbol(q): +w.rect(),p.addClass(("button"===r?"":"highcharts-label-box")+(r?" highcharts-"+r+"-box":"")),p.add(e),a=P(),g.x=a,g.y=(G?-u:0)+a),g.width=Math.round(e.width),g.height=Math.round(e.height),p.attr(b(g,K)),K={})};N=function(){var a=h+A,g;g=G?0:u;k(J)&&l&&("center"===M||"right"===M)&&(a+={center:.5,right:1}[M]*(J-l.width));if(a!==v.x||g!==v.y)v.attr("x",a),void 0!==g&&v.attr("y",g);v.x=a;v.y=g};U=function(a,g){p?p.attr(a,g):K[a]=g};e.onAdd=function(){v.add(e);e.attr({text:f||0===f?f:"",x:d,y:c});p&&k(D)&& +e.attr({anchorX:D,anchorY:y})};e.widthSetter=function(g){J=a.isNumber(g)?g:null};e.heightSetter=function(a){t=a};e["text-alignSetter"]=function(a){M=a};e.paddingSetter=function(a){k(a)&&a!==A&&(A=e.padding=a,N())};e.paddingLeftSetter=function(a){k(a)&&a!==h&&(h=a,N())};e.alignSetter=function(a){a={left:0,center:.5,right:1}[a];a!==F&&(F=a,l&&e.attr({x:S}))};e.textSetter=function(a){void 0!==a&&v.textSetter(a);Q();N()};e["stroke-widthSetter"]=function(a,g){a&&(R=!0);L=this["stroke-width"]=a;U(g,a)}; +e.strokeSetter=e.fillSetter=e.rSetter=function(a,g){"fill"===g&&a&&(R=!0);U(g,a)};e.anchorXSetter=function(a,g){D=a;U(g,Math.round(a)-P()-S)};e.anchorYSetter=function(a,g){y=a;U(g,a-n)};e.xSetter=function(a){e.x=a;F&&(a-=F*((J||l.width)+2*A));S=Math.round(a);e.attr("translateX",S)};e.ySetter=function(a){n=e.y=Math.round(a);e.attr("translateY",n)};var W=e.css;return b(e,{css:function(a){if(a){var g={};a=x(a);H(e.textProps,function(f){void 0!==a[f]&&(g[f]=a[f],delete a[f])});v.css(g)}return W.call(e, +a)},getBBox:function(){return{width:l.width+2*A,height:l.height+2*A,x:l.x-A,y:l.y-A}},shadow:function(a){a&&(Q(),p&&p.shadow(a));return e},destroy:function(){g(e.element,"mouseenter");g(e.element,"mouseleave");v&&(v=v.destroy());p&&(p=p.destroy());B.prototype.destroy.call(e);e=w=Q=N=U=null}})}};a.Renderer=z})(I);(function(a){var B=a.attr,z=a.createElement,C=a.css,E=a.defined,u=a.each,h=a.extend,n=a.isFirefox,t=a.isMS,l=a.isWebKit,k=a.pInt,e=a.SVGRenderer,c=a.win,p=a.wrap;h(a.SVGElement.prototype, +{htmlCss:function(a){var b=this.element;if(b=a&&"SPAN"===b.tagName&&a.width)delete a.width,this.textWidth=b,this.updateTransform();a&&"ellipsis"===a.textOverflow&&(a.whiteSpace="nowrap",a.overflow="hidden");this.styles=h(this.styles,a);C(this.element,a);return this},htmlGetBBox:function(){var a=this.element;"text"===a.nodeName&&(a.style.position="absolute");return{x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}},htmlUpdateTransform:function(){if(this.added){var a=this.renderer, +b=this.element,c=this.translateX||0,d=this.translateY||0,e=this.x||0,p=this.y||0,v=this.textAlign||"left",f={left:0,center:.5,right:1}[v],y=this.styles;C(b,{marginLeft:c,marginTop:d});this.shadows&&u(this.shadows,function(a){C(a,{marginLeft:c+1,marginTop:d+1})});this.inverted&&u(b.childNodes,function(f){a.invertChild(f,b)});if("SPAN"===b.tagName){var G=this.rotation,F=k(this.textWidth),q=y&&y.whiteSpace,x=[G,v,b.innerHTML,this.textWidth,this.textAlign].join();x!==this.cTT&&(y=a.fontMetrics(b.style.fontSize).b, +E(G)&&this.setSpanRotation(G,f,y),C(b,{width:"",whiteSpace:q||"nowrap"}),b.offsetWidth>F&&/[ \-]/.test(b.textContent||b.innerText)&&C(b,{width:F+"px",display:"block",whiteSpace:q||"normal"}),this.getSpanCorrection(b.offsetWidth,y,f,G,v));C(b,{left:e+(this.xCorr||0)+"px",top:p+(this.yCorr||0)+"px"});l&&(y=b.offsetHeight);this.cTT=x}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,e){var d={},m=t?"-ms-transform":l?"-webkit-transform":n?"MozTransform":c.opera?"-o-transform":"";d[m]=d.transform= +"rotate("+a+"deg)";d[m+(n?"Origin":"-origin")]=d.transformOrigin=100*b+"% "+e+"px";C(this.element,d)},getSpanCorrection:function(a,b,c){this.xCorr=-a*c;this.yCorr=-b}});h(e.prototype,{html:function(a,b,c){var d=this.createElement("span"),e=d.element,m=d.renderer,v=m.isSVG,f=function(a,f){u(["opacity","visibility"],function(b){p(a,b+"Setter",function(a,b,d,c){a.call(this,b,d,c);f[d]=b})})};d.textSetter=function(a){a!==e.innerHTML&&delete this.bBox;e.innerHTML=this.textStr=a;d.htmlUpdateTransform()}; +v&&f(d,d.element.style);d.xSetter=d.ySetter=d.alignSetter=d.rotationSetter=function(a,f){"align"===f&&(f="textAlign");d[f]=a;d.htmlUpdateTransform()};d.attr({text:a,x:Math.round(b),y:Math.round(c)}).css({fontFamily:this.style.fontFamily,fontSize:this.style.fontSize,position:"absolute"});e.style.whiteSpace="nowrap";d.css=d.htmlCss;v&&(d.add=function(a){var b,c=m.box.parentNode,q=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)q.push(a),a=a.parentGroup;u(q.reverse(),function(a){var y,e=B(a.element, +"class");e&&(e={className:e});b=a.div=a.div||z("div",e,{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px",display:a.display,opacity:a.opacity,pointerEvents:a.styles&&a.styles.pointerEvents},b||c);y=b.style;h(a,{on:function(){d.on.apply({element:q[0].div},arguments);return a},translateXSetter:function(f,g){y.left=f+"px";a[g]=f;a.doTransform=!0},translateYSetter:function(f,g){y.top=f+"px";a[g]=f;a.doTransform=!0}});f(a,y)})}}else b=c;b.appendChild(e);d.added=!0;d.alignOnAdd&& +d.htmlUpdateTransform();return d});return d}})})(I);(function(a){var B,z,C=a.createElement,E=a.css,u=a.defined,h=a.deg2rad,n=a.discardElement,t=a.doc,l=a.each,k=a.erase,e=a.extend;B=a.extendClass;var c=a.isArray,p=a.isNumber,H=a.isObject,b=a.merge;z=a.noop;var m=a.pick,d=a.pInt,r=a.SVGElement,A=a.SVGRenderer,v=a.win;a.svg||(z={docMode8:t&&8===t.documentMode,init:function(a,b){var f=["\x3c",b,' filled\x3d"f" stroked\x3d"f"'],d=["position: ","absolute",";"],c="div"===b;("shape"===b||c)&&d.push("left:0;top:0;width:1px;height:1px;"); +d.push("visibility: ",c?"hidden":"visible");f.push(' style\x3d"',d.join(""),'"/\x3e');b&&(f=c||"span"===b||"img"===b?f.join(""):a.prepVML(f),this.element=C(f));this.renderer=a},add:function(a){var f=this.renderer,b=this.element,d=f.box,c=a&&a.inverted,d=a?a.element||a:d;a&&(this.parentGroup=a);c&&f.invertChild(b,d);d.appendChild(b);this.added=!0;this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform();if(this.onAdd)this.onAdd();this.className&&this.attr("class",this.className);return this}, +updateTransform:r.prototype.htmlUpdateTransform,setSpanRotation:function(){var a=this.rotation,b=Math.cos(a*h),d=Math.sin(a*h);E(this.element,{filter:a?["progid:DXImageTransform.Microsoft.Matrix(M11\x3d",b,", M12\x3d",-d,", M21\x3d",d,", M22\x3d",b,", sizingMethod\x3d'auto expand')"].join(""):"none"})},getSpanCorrection:function(a,b,d,c,q){var f=c?Math.cos(c*h):1,e=c?Math.sin(c*h):0,y=m(this.elemHeight,this.element.offsetHeight),r;this.xCorr=0>f&&-a;this.yCorr=0>e&&-y;r=0>f*e;this.xCorr+=e*b*(r?1- +d:d);this.yCorr-=f*b*(c?r?d:1-d:1);q&&"left"!==q&&(this.xCorr-=a*d*(0>f?-1:1),c&&(this.yCorr-=y*d*(0>e?-1:1)),E(this.element,{textAlign:q}))},pathToVML:function(a){for(var f=a.length,b=[];f--;)p(a[f])?b[f]=Math.round(10*a[f])-5:"Z"===a[f]?b[f]="x":(b[f]=a[f],!a.isArc||"wa"!==a[f]&&"at"!==a[f]||(b[f+5]===b[f+7]&&(b[f+7]+=a[f+7]>a[f+5]?1:-1),b[f+6]===b[f+8]&&(b[f+8]+=a[f+8]>a[f+6]?1:-1)));return b.join(" ")||"x"},clip:function(a){var f=this,b;a?(b=a.members,k(b,f),b.push(f),f.destroyClip=function(){k(b, +f)},a=a.getCSS(f)):(f.destroyClip&&f.destroyClip(),a={clip:f.docMode8?"inherit":"rect(auto)"});return f.css(a)},css:r.prototype.htmlCss,safeRemoveChild:function(a){a.parentNode&&n(a)},destroy:function(){this.destroyClip&&this.destroyClip();return r.prototype.destroy.apply(this)},on:function(a,b){this.element["on"+a]=function(){var a=v.event;a.target=a.srcElement;b(a)};return this},cutOffPath:function(a,b){var f;a=a.split(/[ ,]/);f=a.length;if(9===f||11===f)a[f-4]=a[f-2]=d(a[f-2])-10*b;return a.join(" ")}, +shadow:function(a,b,c){var f=[],q,e=this.element,y=this.renderer,r,v=e.style,g,D=e.path,p,l,G,k;D&&"string"!==typeof D.value&&(D="x");l=D;if(a){G=m(a.width,3);k=(a.opacity||.15)/G;for(q=1;3>=q;q++)p=2*G+1-2*q,c&&(l=this.cutOffPath(D.value,p+.5)),g=['\x3cshape isShadow\x3d"true" strokeweight\x3d"',p,'" filled\x3d"false" path\x3d"',l,'" coordsize\x3d"10 10" style\x3d"',e.style.cssText,'" /\x3e'],r=C(y.prepVML(g),null,{left:d(v.left)+m(a.offsetX,1),top:d(v.top)+m(a.offsetY,1)}),c&&(r.cutOff=p+1),g=['\x3cstroke color\x3d"', +a.color||"#000000",'" opacity\x3d"',k*q,'"/\x3e'],C(y.prepVML(g),null,null,r),b?b.element.appendChild(r):e.parentNode.insertBefore(r,e),f.push(r);this.shadows=f}return this},updateShadows:z,setAttr:function(a,b){this.docMode8?this.element[a]=b:this.element.setAttribute(a,b)},classSetter:function(a){(this.added?this.element:this).className=a},dashstyleSetter:function(a,b,d){(d.getElementsByTagName("stroke")[0]||C(this.renderer.prepVML(["\x3cstroke/\x3e"]),null,null,d))[b]=a||"solid";this[b]=a},dSetter:function(a, +b,d){var f=this.shadows;a=a||[];this.d=a.join&&a.join(" ");d.path=a=this.pathToVML(a);if(f)for(d=f.length;d--;)f[d].path=f[d].cutOff?this.cutOffPath(a,f[d].cutOff):a;this.setAttr(b,a)},fillSetter:function(a,b,d){var f=d.nodeName;"SPAN"===f?d.style.color=a:"IMG"!==f&&(d.filled="none"!==a,this.setAttr("fillcolor",this.renderer.color(a,d,b,this)))},"fill-opacitySetter":function(a,b,d){C(this.renderer.prepVML(["\x3c",b.split("-")[0],' opacity\x3d"',a,'"/\x3e']),null,null,d)},opacitySetter:z,rotationSetter:function(a, +b,d){d=d.style;this[b]=d[b]=a;d.left=-Math.round(Math.sin(a*h)+1)+"px";d.top=Math.round(Math.cos(a*h))+"px"},strokeSetter:function(a,b,d){this.setAttr("strokecolor",this.renderer.color(a,d,b,this))},"stroke-widthSetter":function(a,b,d){d.stroked=!!a;this[b]=a;p(a)&&(a+="px");this.setAttr("strokeweight",a)},titleSetter:function(a,b){this.setAttr(b,a)},visibilitySetter:function(a,b,d){"inherit"===a&&(a="visible");this.shadows&&l(this.shadows,function(f){f.style[b]=a});"DIV"===d.nodeName&&(a="hidden"=== +a?"-999em":0,this.docMode8||(d.style[b]=a?"visible":"hidden"),b="top");d.style[b]=a},xSetter:function(a,b,d){this[b]=a;"x"===b?b="left":"y"===b&&(b="top");this.updateClipping?(this[b]=a,this.updateClipping()):d.style[b]=a},zIndexSetter:function(a,b,d){d.style[b]=a}},z["stroke-opacitySetter"]=z["fill-opacitySetter"],a.VMLElement=z=B(r,z),z.prototype.ySetter=z.prototype.widthSetter=z.prototype.heightSetter=z.prototype.xSetter,z={Element:z,isIE8:-1n[0]&&b.push([1,n[1]]);l(b,function(g,b){r.test(g[1])?(m=a.color(g[1]),D=m.get("rgb"),y=m.get("a")):(D=g[1],y=1);H.push(100*g[0]+"% "+D);b?(w=y,G=D):(h=y,t=D)});if("fill"===c)if("gradient"===p)c=k.x1||k[0]||0,b=k.y1||k[1]||0,A=k.x2||k[2]||0,k=k.y2||k[3]||0,F='angle\x3d"'+(90-180*Math.atan((k-b)/(A-c))/Math.PI)+'"', +u();else{var g=k.r,z=2*g,B=2*g,E=k.cx,V=k.cy,I=d.radialReference,T,g=function(){I&&(T=e.getBBox(),E+=(I[0]-T.x)/T.width-.5,V+=(I[1]-T.y)/T.height-.5,z*=I[2]/T.width,B*=I[2]/T.height);F='src\x3d"'+a.getOptions().global.VMLRadialGradientURL+'" size\x3d"'+z+","+B+'" origin\x3d"0.5,0.5" position\x3d"'+E+","+V+'" color2\x3d"'+t+'" ';u()};e.added?g():e.onAdd=g;g=G}else g=D}else r.test(b)&&"IMG"!==d.tagName?(m=a.color(b),e[c+"-opacitySetter"](m.get("a"),c,d),g=m.get("rgb")):(g=d.getElementsByTagName(c), +g.length&&(g[0].opacity=1,g[0].type="solid"),g=b);return g},prepVML:function(a){var b=this.isIE8;a=a.join("");b?(a=a.replace("/\x3e",' xmlns\x3d"urn:schemas-microsoft-com:vml" /\x3e'),a=-1===a.indexOf('style\x3d"')?a.replace("/\x3e",' style\x3d"display:inline-block;behavior:url(#default#VML);" /\x3e'):a.replace('style\x3d"','style\x3d"display:inline-block;behavior:url(#default#VML);')):a=a.replace("\x3c","\x3chcv:");return a},text:A.prototype.html,path:function(a){var b={coordsize:"10 10"};c(a)?b.d= +a:H(a)&&e(b,a);return this.createElement("shape").attr(b)},circle:function(a,b,d){var f=this.symbol("circle");H(a)&&(d=a.r,b=a.y,a=a.x);f.isCircle=!0;f.r=d;return f.attr({x:a,y:b})},g:function(a){var b;a&&(b={className:"highcharts-"+a,"class":"highcharts-"+a});return this.createElement("div").attr(b)},image:function(a,b,d,c,q){var f=this.createElement("img").attr({src:a});1b&&k-m*dc&&(f=Math.round((e-k)/Math.cos(b*n)));else if(e=k+(1-m)*d,k-m*dc&&(A=c-a.x+A*m,v=-1),A=Math.min(r,A),AA||l.autoRotation&&(t.styles||{}).width)f=A;f&&(y.width=f,(l.options.labels.style||{}).textOverflow||(y.textOverflow="ellipsis"),t.css(y))},getPosition:function(a,l,k,e){var c=this.axis,p=c.chart,h=e&&p.oldChartHeight||p.chartHeight;return{x:a?c.translate(l+k,null,null,e)+c.transB:c.left+c.offset+(c.opposite? +(e&&p.oldChartWidth||p.chartWidth)-c.right-c.left:0),y:a?h-c.bottom+c.offset-(c.opposite?c.height:0):h-c.translate(l+k,null,null,e)-c.transB}},getLabelPosition:function(a,h,k,e,c,p,H,b){var m=this.axis,d=m.transA,r=m.reversed,l=m.staggerLines,v=m.tickRotCorr||{x:0,y:0},f=c.y;z(f)||(f=0===m.side?k.rotation?-8:-k.getBBox().height:2===m.side?v.y+8:Math.cos(k.rotation*n)*(v.y-k.getBBox(!1,0).height/2));a=a+c.x+v.x-(p&&e?p*d*(r?-1:1):0);h=h+f-(p&&!e?p*d*(r?1:-1):0);l&&(k=H/(b||1)%l,m.opposite&&(k=l-k- +1),h+=m.labelOffset/l*k);return{x:a,y:Math.round(h)}},getMarkPath:function(a,h,k,e,c,p){return p.crispLine(["M",a,h,"L",a+(c?0:-k),h+(c?k:0)],e)},renderGridLine:function(a,h,k){var e=this.axis,c=e.options,p=this.gridLine,l={},b=this.pos,m=this.type,d=e.tickmarkOffset,r=e.chart.renderer,A=m?m+"Grid":"grid",v=c[A+"LineWidth"],f=c[A+"LineColor"],c=c[A+"LineDashStyle"];p||(l.stroke=f,l["stroke-width"]=v,c&&(l.dashstyle=c),m||(l.zIndex=1),a&&(l.opacity=0),this.gridLine=p=r.path().attr(l).addClass("highcharts-"+ +(m?m+"-":"")+"grid-line").add(e.gridGroup));if(!a&&p&&(a=e.getPlotLinePath(b+d,p.strokeWidth()*k,a,!0)))p[this.isNew?"attr":"animate"]({d:a,opacity:h})},renderMark:function(a,l,k){var e=this.axis,c=e.options,p=e.chart.renderer,n=this.type,b=n?n+"Tick":"tick",m=e.tickSize(b),d=this.mark,r=!d,A=a.x;a=a.y;var v=h(c[b+"Width"],!n&&e.isXAxis?1:0),c=c[b+"Color"];m&&(e.opposite&&(m[0]=-m[0]),r&&(this.mark=d=p.path().addClass("highcharts-"+(n?n+"-":"")+"tick").add(e.axisGroup),d.attr({stroke:c,"stroke-width":v})), +d[r?"attr":"animate"]({d:this.getMarkPath(A,a,m[0],d.strokeWidth()*k,e.horiz,p),opacity:l}))},renderLabel:function(a,l,k,e){var c=this.axis,p=c.horiz,n=c.options,b=this.label,m=n.labels,d=m.step,r=c.tickmarkOffset,A=!0,v=a.x;a=a.y;b&&E(v)&&(b.xy=a=this.getLabelPosition(v,a,b,p,m,r,e,d),this.isFirst&&!this.isLast&&!h(n.showFirstLabel,1)||this.isLast&&!this.isFirst&&!h(n.showLastLabel,1)?A=!1:!p||c.isRadial||m.step||m.rotation||l||0===k||this.handleOverflow(a),d&&e%d&&(A=!1),A&&E(a.y)?(a.opacity=k, +b[this.isNew?"attr":"animate"](a)):b.attr("y",-9999),this.isNew=!1)},render:function(a,l,k){var e=this.axis,c=e.horiz,p=this.getPosition(c,this.pos,e.tickmarkOffset,l),n=p.x,b=p.y,e=c&&n===e.pos+e.len||!c&&b===e.pos?-1:1;k=h(k,1);this.isActive=!0;this.renderGridLine(l,k,e);this.renderMark(p,k,e);this.renderLabel(p,l,k,a)},destroy:function(){C(this,this.axis)}}})(I);(function(a){var B=a.addEvent,z=a.animObject,C=a.arrayMax,E=a.arrayMin,u=a.AxisPlotLineOrBandExtension,h=a.color,n=a.correctFloat,t=a.defaultOptions, +l=a.defined,k=a.deg2rad,e=a.destroyObjectProperties,c=a.each,p=a.extend,H=a.fireEvent,b=a.format,m=a.getMagnitude,d=a.grep,r=a.inArray,A=a.isArray,v=a.isNumber,f=a.isString,y=a.merge,G=a.normalizeTickInterval,F=a.pick,q=a.PlotLineOrBand,x=a.removeEvent,J=a.splat,K=a.syncTimeout,L=a.Tick;a.Axis=function(){this.init.apply(this,arguments)};a.Axis.prototype={defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y", +year:"%Y"},endOnTick:!1,labels:{enabled:!0,style:{color:"#666666",cursor:"default",fontSize:"11px"},x:0},minPadding:.01,maxPadding:.01,minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:!1,tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",title:{align:"middle",style:{color:"#666666"}},type:"linear",minorGridLineColor:"#f2f2f2",minorGridLineWidth:1,minorTickColor:"#999999",lineColor:"#ccd6eb",lineWidth:1,gridLineColor:"#e6e6e6",tickColor:"#ccd6eb"}, +defaultYAxisOptions:{endOnTick:!0,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8},maxPadding:.05,minPadding:.05,startOnTick:!0,title:{rotation:270,text:"Values"},stackLabels:{enabled:!1,formatter:function(){return a.numberFormat(this.total,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"#000000",textOutline:"1px contrast"}},gridLineWidth:1,lineWidth:0},defaultLeftAxisOptions:{labels:{x:-15},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:15},title:{rotation:90}},defaultBottomAxisOptions:{labels:{autoRotation:[-45], +x:0},title:{rotation:0}},defaultTopAxisOptions:{labels:{autoRotation:[-45],x:0},title:{rotation:0}},init:function(a,b){var g=b.isX;this.chart=a;this.horiz=a.inverted?!g:g;this.isXAxis=g;this.coll=this.coll||(g?"xAxis":"yAxis");this.opposite=b.opposite;this.side=b.side||(this.horiz?this.opposite?0:2:this.opposite?1:3);this.setOptions(b);var d=this.options,c=d.type;this.labelFormatter=d.labels.formatter||this.defaultLabelFormatter;this.userOptions=b;this.minPixelPadding=0;this.reversed=d.reversed;this.visible= +!1!==d.visible;this.zoomEnabled=!1!==d.zoomEnabled;this.hasNames="category"===c||!0===d.categories;this.categories=d.categories||this.hasNames;this.names=this.names||[];this.isLog="logarithmic"===c;this.isDatetimeAxis="datetime"===c;this.positiveValuesOnly=this.isLog&&!this.allowNegativeLog;this.isLinked=l(d.linkedTo);this.ticks={};this.labelEdge=[];this.minorTicks={};this.plotLinesAndBands=[];this.alternateBands={};this.len=0;this.minRange=this.userMinRange=d.minRange||d.maxZoom;this.range=d.range; +this.offset=d.offset||0;this.stacks={};this.oldStacks={};this.stacksTouched=0;this.min=this.max=null;this.crosshair=F(d.crosshair,J(a.options.tooltip.crosshairs)[g?0:1],!1);var f;b=this.options.events;-1===r(this,a.axes)&&(g?a.axes.splice(a.xAxis.length,0,this):a.axes.push(this),a[this.coll].push(this));this.series=this.series||[];a.inverted&&g&&void 0===this.reversed&&(this.reversed=!0);this.removePlotLine=this.removePlotBand=this.removePlotBandOrLine;for(f in b)B(this,f,b[f]);this.lin2log=d.linearToLogConverter|| +this.lin2log;this.isLog&&(this.val2lin=this.log2lin,this.lin2val=this.lin2log)},setOptions:function(a){this.options=y(this.defaultOptions,"yAxis"===this.coll&&this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions,this.defaultLeftAxisOptions][this.side],y(t[this.coll],a))},defaultLabelFormatter:function(){var g=this.axis,d=this.value,c=g.categories,f=this.dateTimeLabelFormat,q=t.lang,e=q.numericSymbols,q=q.numericSymbolMagnitude||1E3,w=e&&e.length, +m,r=g.options.labels.format,g=g.isLog?Math.abs(d):g.tickInterval;if(r)m=b(r,this);else if(c)m=d;else if(f)m=a.dateFormat(f,d);else if(w&&1E3<=g)for(;w--&&void 0===m;)c=Math.pow(q,w+1),g>=c&&0===10*d%c&&null!==e[w]&&0!==d&&(m=a.numberFormat(d/c,-1)+e[w]);void 0===m&&(m=1E4<=Math.abs(d)?a.numberFormat(d,-1):a.numberFormat(d,-1,void 0,""));return m},getSeriesExtremes:function(){var a=this,b=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=a.threshold=null;a.softThreshold=!a.isXAxis;a.buildStacks&&a.buildStacks(); +c(a.series,function(g){if(g.visible||!b.options.chart.ignoreHiddenSeries){var c=g.options,f=c.threshold,q;a.hasVisibleSeries=!0;a.positiveValuesOnly&&0>=f&&(f=null);if(a.isXAxis)c=g.xData,c.length&&(g=E(c),v(g)||g instanceof Date||(c=d(c,function(a){return v(a)}),g=E(c)),a.dataMin=Math.min(F(a.dataMin,c[0]),g),a.dataMax=Math.max(F(a.dataMax,c[0]),C(c)));else if(g.getExtremes(),q=g.dataMax,g=g.dataMin,l(g)&&l(q)&&(a.dataMin=Math.min(F(a.dataMin,g),g),a.dataMax=Math.max(F(a.dataMax,q),q)),l(f)&&(a.threshold= +f),!c.softThreshold||a.positiveValuesOnly)a.softThreshold=!1}})},translate:function(a,b,d,c,f,q){var g=this.linkedParent||this,D=1,e=0,m=c?g.oldTransA:g.transA;c=c?g.oldMin:g.min;var r=g.minPixelPadding;f=(g.isOrdinal||g.isBroken||g.isLog&&f)&&g.lin2val;m||(m=g.transA);d&&(D*=-1,e=g.len);g.reversed&&(D*=-1,e-=D*(g.sector||g.len));b?(a=(a*D+e-r)/m+c,f&&(a=g.lin2val(a))):(f&&(a=g.val2lin(a)),a=D*(a-c)*m+e+D*r+(v(q)?m*q:0));return a},toPixels:function(a,b){return this.translate(a,!1,!this.horiz,null, +!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-(b?0:this.pos),!0,!this.horiz,null,!0)},getPlotLinePath:function(a,b,d,c,f){var g=this.chart,q=this.left,D=this.top,e,m,r=d&&g.oldChartHeight||g.chartHeight,p=d&&g.oldChartWidth||g.chartWidth,x;e=this.transB;var k=function(a,b,g){if(ag)c?a=Math.min(Math.max(b,a),g):x=!0;return a};f=F(f,this.translate(a,null,null,d));a=d=Math.round(f+e);e=m=Math.round(r-f-e);v(f)?this.horiz?(e=D,m=r-this.bottom,a=d=k(a,q,q+this.width)):(a=q,d= +p-this.right,e=m=k(e,D,D+this.height)):x=!0;return x&&!c?null:g.renderer.crispLine(["M",a,e,"L",d,m],b||1)},getLinearTickPositions:function(a,b,d){var g,c=n(Math.floor(b/a)*a);d=n(Math.ceil(d/a)*a);var f=[];if(this.single)return[b];for(b=c;b<=d;){f.push(b);b=n(b+a);if(b===g)break;g=b}return f},getMinorTickPositions:function(){var a=this,b=a.options,d=a.tickPositions,f=a.minorTickInterval,q=[],e=a.pointRangePadding||0,m=a.min-e,e=a.max+e,r=e-m;if(r&&r/f=this.minRange,e,m,r,p,v,x;this.isXAxis&&void 0===this.minRange&&!this.isLog&&(l(a.min)||l(a.max)?this.minRange= +null:(c(this.series,function(a){p=a.xData;for(m=v=a.xIncrement?1:p.length-1;0=t?(L=t,h=0):g.dataMax<= +t&&(K=t,k=0)),g.min=F(z,L,g.dataMin),g.max=F(B,K,g.dataMax));q&&(g.positiveValuesOnly&&!b&&0>=Math.min(g.min,F(g.dataMin,g.min))&&a.error(10,1),g.min=n(e(g.min),15),g.max=n(e(g.max),15));g.range&&l(g.max)&&(g.userMin=g.min=z=Math.max(g.min,g.minFromRange()),g.userMax=B=g.max,g.range=null);H(g,"foundExtremes");g.beforePadding&&g.beforePadding();g.adjustForMinRange();!(J||g.axisPointRange||g.usePercentage||x)&&l(g.min)&&l(g.max)&&(e=g.max-g.min)&&(!l(z)&&h&&(g.min-=e*h),!l(B)&&k&&(g.max+=e*k));v(f.floor)? +g.min=Math.max(g.min,f.floor):v(f.softMin)&&(g.min=Math.min(g.min,f.softMin));v(f.ceiling)?g.max=Math.min(g.max,f.ceiling):v(f.softMax)&&(g.max=Math.max(g.max,f.softMax));u&&l(g.dataMin)&&(t=t||0,!l(z)&&g.min=t?g.min=t:!l(B)&&g.max>t&&g.dataMax<=t&&(g.max=t));g.tickInterval=g.min===g.max||void 0===g.min||void 0===g.max?1:x&&!y&&A===g.linkedParent.options.tickPixelInterval?y=g.linkedParent.tickInterval:F(y,this.tickAmount?(g.max-g.min)/Math.max(this.tickAmount-1,1):void 0,J?1:(g.max- +g.min)*A/Math.max(g.len,A));p&&!b&&c(g.series,function(a){a.processData(g.min!==g.oldMin||g.max!==g.oldMax)});g.setAxisTranslation(!0);g.beforeSetTickPositions&&g.beforeSetTickPositions();g.postProcessTickInterval&&(g.tickInterval=g.postProcessTickInterval(g.tickInterval));g.pointRange&&!y&&(g.tickInterval=Math.max(g.pointRange,g.tickInterval));b=F(f.minTickInterval,g.isDatetimeAxis&&g.closestPointRange);!y&&g.tickIntervalg.tickInterval&&1E3g.max)),!!this.tickAmount));this.tickAmount||(g.tickInterval=g.unsquish());this.setTickPositions()},setTickPositions:function(){var a=this.options,b,d=a.tickPositions,c=a.tickPositioner,f=a.startOnTick,q=a.endOnTick;this.tickmarkOffset=this.categories&&"between"===a.tickmarkPlacement&&1===this.tickInterval?.5:0;this.minorTickInterval="auto"===a.minorTickInterval&&this.tickInterval?this.tickInterval/5:a.minorTickInterval;this.single= +this.min===this.max&&l(this.min)&&!this.tickAmount&&!1!==a.allowDecimals;this.tickPositions=b=d&&d.slice();!b&&(b=this.isDatetimeAxis?this.getTimeTicks(this.normalizeTimeTickInterval(this.tickInterval,a.units),this.min,this.max,a.startOfWeek,this.ordinalPositions,this.closestPointRange,!0):this.isLog?this.getLogTickPositions(this.tickInterval,this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max),b.length>this.len&&(b=[b[0],b.pop()]),this.tickPositions=b,c&&(c=c.apply(this, +[this.min,this.max])))&&(this.tickPositions=b=c);this.paddedTicks=b.slice(0);this.trimTicks(b,f,q);this.isLinked||(this.single&&(this.min-=.5,this.max+=.5),d||c||this.adjustTickAmount())},trimTicks:function(a,b,d){var g=a[0],c=a[a.length-1],f=this.minPointOffset||0;if(!this.isLinked){if(b)this.min=g;else for(;this.min-f>a[0];)a.shift();if(d)this.max=c;else for(;this.max+fb&&(this.finalTickAmt=b,b=5);this.tickAmount=b},adjustTickAmount:function(){var a= +this.tickInterval,b=this.tickPositions,d=this.tickAmount,c=this.finalTickAmt,f=b&&b.length;if(fd&&(this.tickInterval*=2,this.setTickPositions());if(l(c)){for(a=d=b.length;a--;)(3===c&&1===a%2||2>=c&&0c&&(a=c)),l(d)&&(bc&&(b=c))),this.displayBtn=void 0!==a||void 0!==b,this.setExtremes(a,b,!1,void 0,{trigger:"zoom"}); +return!0},setAxisSize:function(){var a=this.chart,b=this.options,d=b.offsets||[0,0,0,0],c=this.horiz,f=F(b.width,a.plotWidth-d[3]+d[1]),q=F(b.height,a.plotHeight-d[0]+d[2]),e=F(b.top,a.plotTop+d[0]),b=F(b.left,a.plotLeft+d[3]),d=/%$/;d.test(q)&&(q=Math.round(parseFloat(q)/100*a.plotHeight));d.test(e)&&(e=Math.round(parseFloat(e)/100*a.plotHeight+a.plotTop));this.left=b;this.top=e;this.width=f;this.height=q;this.bottom=a.chartHeight-q-e;this.right=a.chartWidth-f-b;this.len=Math.max(c?f:q,0);this.pos= +c?b:e},getExtremes:function(){var a=this.isLog,b=this.lin2log;return{min:a?n(b(this.min)):this.min,max:a?n(b(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,g=this.lin2log,d=b?g(this.min):this.min,b=b?g(this.max):this.max;null===a?a=d:d>a?a=d:ba?"right":195a?"left":"center"}, +tickSize:function(a){var b=this.options,g=b[a+"Length"],d=F(b[a+"Width"],"tick"===a&&this.isXAxis?1:0);if(d&&g)return"inside"===b[a+"Position"]&&(g=-g),[g,d]},labelMetrics:function(){return this.chart.renderer.fontMetrics(this.options.labels.style&&this.options.labels.style.fontSize,this.ticks[0]&&this.ticks[0].label)},unsquish:function(){var a=this.options.labels,b=this.horiz,d=this.tickInterval,f=d,q=this.len/(((this.categories?1:0)+this.max-this.min)/d),e,m=a.rotation,r=this.labelMetrics(),p,x= +Number.MAX_VALUE,v,h=function(a){a/=q||1;a=1=a)p=h(Math.abs(r.h/Math.sin(k*a))),b=p+Math.abs(a/360),b(d.step||0)&&!d.rotation&&(this.staggerLines||1)*this.len/c||!b&&(f&&f-a.spacing[3]||.33*a.chartWidth)},renderUnsquish:function(){var a=this.chart,b=a.renderer,d=this.tickPositions,q=this.ticks,e=this.options.labels,m=this.horiz,r=this.getSlotWidth(),p=Math.max(1,Math.round(r-2*(e.padding||5))),x={},v=this.labelMetrics(),k=e.style&&e.style.textOverflow,h,l=0,A,n;f(e.rotation)||(x.rotation=e.rotation||0);c(d,function(a){(a=q[a])&&a.labelLength>l&&(l=a.labelLength)});this.maxLabelLength= +l;if(this.autoRotation)l>p&&l>v.h?x.rotation=this.labelRotation:this.labelRotation=0;else if(r&&(h={width:p+"px"},!k))for(h.textOverflow="clip",A=d.length;!m&&A--;)if(n=d[A],p=q[n].label)p.styles&&"ellipsis"===p.styles.textOverflow?p.css({textOverflow:"clip"}):q[n].labelLength>r&&p.css({width:r+"px"}),p.getBBox().height>this.len/d.length-(v.h-v.f)&&(p.specCss={textOverflow:"ellipsis"});x.rotation&&(h={width:(l>.5*a.chartHeight?.33*a.chartHeight:a.chartHeight)+"px"},k||(h.textOverflow="ellipsis")); +if(this.labelAlign=e.align||this.autoLabelAlign(this.labelRotation))x.align=this.labelAlign;c(d,function(a){var b=(a=q[a])&&a.label;b&&(b.attr(x),h&&b.css(y(h,b.specCss)),delete b.specCss,a.rotation=x.rotation)});this.tickRotCorr=b.rotCorr(v.b,this.labelRotation||0,0!==this.side)},hasData:function(){return this.hasVisibleSeries||l(this.min)&&l(this.max)&&!!this.tickPositions},addTitle:function(a){var b=this.chart.renderer,d=this.horiz,g=this.opposite,c=this.options.title,f;this.axisTitle||((f=c.textAlign)|| +(f=(d?{low:"left",middle:"center",high:"right"}:{low:g?"right":"left",middle:"center",high:g?"left":"right"})[c.align]),this.axisTitle=b.text(c.text,0,0,c.useHTML).attr({zIndex:7,rotation:c.rotation||0,align:f}).addClass("highcharts-axis-title").css(c.style).add(this.axisGroup),this.axisTitle.isNew=!0);this.axisTitle[a?"show":"hide"](!0)},generateTick:function(a){var b=this.ticks;b[a]?b[a].addLabel():b[a]=new L(this,a)},getOffset:function(){var a=this,b=a.chart,d=b.renderer,f=a.options,q=a.tickPositions, +e=a.ticks,m=a.horiz,r=a.side,p=b.inverted?[1,0,3,2][r]:r,x,v,h=0,k,y=0,A=f.title,n=f.labels,G=0,J=b.axisOffset,b=b.clipOffset,t=[-1,1,1,-1][r],u,H=f.className,L=a.axisParent,K=this.tickSize("tick");x=a.hasData();a.showAxis=v=x||F(f.showEmpty,!0);a.staggerLines=a.horiz&&n.staggerLines;a.axisGroup||(a.gridGroup=d.g("grid").attr({zIndex:f.gridZIndex||1}).addClass("highcharts-"+this.coll.toLowerCase()+"-grid "+(H||"")).add(L),a.axisGroup=d.g("axis").attr({zIndex:f.zIndex||2}).addClass("highcharts-"+this.coll.toLowerCase()+ +" "+(H||"")).add(L),a.labelGroup=d.g("axis-labels").attr({zIndex:n.zIndex||7}).addClass("highcharts-"+a.coll.toLowerCase()+"-labels "+(H||"")).add(L));if(x||a.isLinked)c(q,function(b,d){a.generateTick(b,d)}),a.renderUnsquish(),!1===n.reserveSpace||0!==r&&2!==r&&{1:"left",3:"right"}[r]!==a.labelAlign&&"center"!==a.labelAlign||c(q,function(a){G=Math.max(e[a].getLabelSize(),G)}),a.staggerLines&&(G*=a.staggerLines,a.labelOffset=G*(a.opposite?-1:1));else for(u in e)e[u].destroy(),delete e[u];A&&A.text&& +!1!==A.enabled&&(a.addTitle(v),v&&(h=a.axisTitle.getBBox()[m?"height":"width"],k=A.offset,y=l(k)?0:F(A.margin,m?5:10)));a.renderLine();a.offset=t*F(f.offset,J[r]);a.tickRotCorr=a.tickRotCorr||{x:0,y:0};d=0===r?-a.labelMetrics().h:2===r?a.tickRotCorr.y:0;y=Math.abs(G)+y;G&&(y=y-d+t*(m?F(n.y,a.tickRotCorr.y+8*t):n.x));a.axisTitleMargin=F(k,y);J[r]=Math.max(J[r],a.axisTitleMargin+h+t*a.offset,y,x&&q.length&&K?K[0]+t*a.offset:0);f=f.offset?0:2*Math.floor(a.axisLine.strokeWidth()/2);b[p]=Math.max(b[p], +f)},getLinePath:function(a){var b=this.chart,d=this.opposite,g=this.offset,f=this.horiz,c=this.left+(d?this.width:0)+g,g=b.chartHeight-this.bottom-(d?this.height:0)+g;d&&(a*=-1);return b.renderer.crispLine(["M",f?this.left:c,f?g:this.top,"L",f?b.chartWidth-this.right:c,f?g:b.chartHeight-this.bottom],a)},renderLine:function(){this.axisLine||(this.axisLine=this.chart.renderer.path().addClass("highcharts-axis-line").add(this.axisGroup),this.axisLine.attr({stroke:this.options.lineColor,"stroke-width":this.options.lineWidth, +zIndex:7}))},getTitlePosition:function(){var a=this.horiz,b=this.left,d=this.top,f=this.len,c=this.options.title,q=a?b:d,e=this.opposite,m=this.offset,r=c.x||0,p=c.y||0,x=this.chart.renderer.fontMetrics(c.style&&c.style.fontSize,this.axisTitle).f,f={low:q+(a?0:f),middle:q+f/2,high:q+(a?f:0)}[c.align],b=(a?d+this.height:b)+(a?1:-1)*(e?-1:1)*this.axisTitleMargin+(2===this.side?x:0);return{x:a?f+r:b+(e?this.width:0)+m+r,y:a?b+p-(e?this.height:0)+m:f+p}},renderMinorTick:function(a){var b=this.chart.hasRendered&& +v(this.oldMin),d=this.minorTicks;d[a]||(d[a]=new L(this,a,"minor"));b&&d[a].isNew&&d[a].render(null,!0);d[a].render(null,!1,1)},renderTick:function(a,b){var d=this.isLinked,g=this.ticks,f=this.chart.hasRendered&&v(this.oldMin);if(!d||a>=this.min&&a<=this.max)g[a]||(g[a]=new L(this,a)),f&&g[a].isNew&&g[a].render(b,!0,.1),g[a].render(b)},render:function(){var a=this,b=a.chart,d=a.options,f=a.isLog,e=a.lin2log,m=a.isLinked,r=a.tickPositions,p=a.axisTitle,x=a.ticks,v=a.minorTicks,h=a.alternateBands,k= +d.stackLabels,y=d.alternateGridColor,l=a.tickmarkOffset,A=a.axisLine,n=a.showAxis,G=z(b.renderer.globalAnimation),J,t;a.labelEdge.length=0;a.overlap=!1;c([x,v,h],function(a){for(var b in a)a[b].isActive=!1});if(a.hasData()||m)a.minorTickInterval&&!a.categories&&c(a.getMinorTickPositions(),function(b){a.renderMinorTick(b)}),r.length&&(c(r,function(b,d){a.renderTick(b,d)}),l&&(0===a.min||a.single)&&(x[-1]||(x[-1]=new L(a,-1,null,!0)),x[-1].render(-1))),y&&c(r,function(d,g){t=void 0!==r[g+1]?r[g+1]+ +l:a.max-l;0===g%2&&d=c.second?0:t*Math.floor(f.getMilliseconds()/t));if(G>=c.second)f[z.hcSetSeconds](G>=c.minute?0:t*Math.floor(f.getSeconds()/t));if(G>=c.minute)f[z.hcSetMinutes](G>=c.hour?0:t*Math.floor(f[z.hcGetMinutes]()/t));if(G>=c.hour)f[z.hcSetHours](G>=c.day?0:t*Math.floor(f[z.hcGetHours]()/t));if(G>=c.day)f[z.hcSetDate](G>=c.month?1:t*Math.floor(f[z.hcGetDate]()/t)); +G>=c.month&&(f[z.hcSetMonth](G>=c.year?0:t*Math.floor(f[z.hcGetMonth]()/t)),v=f[z.hcGetFullYear]());if(G>=c.year)f[z.hcSetFullYear](v-v%t);if(G===c.week)f[z.hcSetDate](f[z.hcGetDate]()-f[z.hcGetDay]()+e(m,1));v=f[z.hcGetFullYear]();m=f[z.hcGetMonth]();var x=f[z.hcGetDate](),J=f[z.hcGetHours]();if(z.hcTimezoneOffset||z.hcGetTimezoneOffset)q=(!p||!!z.hcGetTimezoneOffset)&&(b-k>4*c.month||l(k)!==l(b)),f=f.getTime(),f=new z(f+l(f));p=f.getTime();for(k=1;pd.length&&h(d,function(a){0===a%18E5&&"000000000"===C("%H%M%S%L",a)&&(r[a]="day")})}d.info=n(a,{higherRanks:r,totalRange:G*t});return d};B.prototype.normalizeTimeTickInterval=function(a,e){var b=e||[["millisecond",[1,2,5,10,20,25,50,100,200,500]],["second",[1,2,5,10,15,30]],["minute",[1,2,5,10,15,30]],["hour",[1,2,3,4,6,8,12]],["day",[1,2]],["week",[1,2]],["month",[1,2, +3,4,6]],["year",null]];e=b[b.length-1];var m=c[e[0]],d=e[1],r;for(r=0;rn&&(!l||r<=t)&&void 0!==r&&h.push(r),r>t&&(A=!0),r=d;else n=c(n),t=c(t),a=k[l?"minorTickInterval":"tickInterval"],a=u("auto"===a?null:a,this._minorAutoInterval,k.tickPixelInterval/(l?5:1)*(t-n)/((l?e/this.tickPositions.length:e)||1)),a=E(a,null,z(a)),h=C(this.getLinearTickPositions(a, +n,t),p),l||(this._minorAutoInterval=a/5);l||(this.tickInterval=a);return h};B.prototype.log2lin=function(a){return Math.log(a)/Math.LN10};B.prototype.lin2log=function(a){return Math.pow(10,a)}})(I);(function(a){var B=a.dateFormat,z=a.each,C=a.extend,E=a.format,u=a.isNumber,h=a.map,n=a.merge,t=a.pick,l=a.splat,k=a.syncTimeout,e=a.timeUnits;a.Tooltip=function(){this.init.apply(this,arguments)};a.Tooltip.prototype={init:function(a,e){this.chart=a;this.options=e;this.crosshairs=[];this.now={x:0,y:0}; +this.isHidden=!0;this.split=e.split&&!a.inverted;this.shared=e.shared||this.split},cleanSplit:function(a){z(this.chart.series,function(c){var e=c&&c.tt;e&&(!e.isActive||a?c.tt=e.destroy():e.isActive=!1)})},getLabel:function(){var a=this.chart.renderer,e=this.options;this.label||(this.split?this.label=a.g("tooltip"):(this.label=a.label("",0,0,e.shape||"callout",null,null,e.useHTML,null,"tooltip").attr({padding:e.padding,r:e.borderRadius}),this.label.attr({fill:e.backgroundColor,"stroke-width":e.borderWidth}).css(e.style).shadow(e.shadow)), +this.label.attr({zIndex:8}).add());return this.label},update:function(a){this.destroy();this.init(this.chart,n(!0,this.options,a))},destroy:function(){this.label&&(this.label=this.label.destroy());this.split&&this.tt&&(this.cleanSplit(this.chart,!0),this.tt=this.tt.destroy());clearTimeout(this.hideTimer);clearTimeout(this.tooltipTimeout)},move:function(a,e,k,b){var c=this,d=c.now,r=!1!==c.options.animation&&!c.isHidden&&(1v-r?v:v-r);else if(x)d[a]=Math.max(q,g+r+f>b?g:g+r);else return!1},n=function(a,b,f,g){var q;gb-c?q=!1:d[a]=gb-f/2?b-f-2:g-f/2;return q},q=function(a){var b= +v;v=f;f=b;p=a},x=function(){!1!==l.apply(0,v)?!1!==n.apply(0,f)||p||(q(!0),x()):p?d.x=d.y=0:(q(!0),x())};(b.inverted||1x&&(r=!1);a=(c.series&&c.series.yAxis&&c.series.yAxis.pos)+(c.plotY||0);a-=m.plotTop;b.push({target:c.isHeader? +m.plotHeight+v:a,rank:c.isHeader?1:0,size:h.tt.getBBox().height+1,point:c,x:x,tt:q})});this.cleanSplit();a.distribute(b,m.plotHeight+v);z(b,function(a){var b=a.point,d=b.series;a.tt.attr({visibility:void 0===a.pos?"hidden":"inherit",x:r||b.isHeader?a.x:b.plotX+m.plotLeft+t(k.distance,16),y:a.pos+m.plotTop,anchorX:b.isHeader?b.plotX+m.plotLeft:b.plotX+d.xAxis.pos,anchorY:b.isHeader?a.pos+m.plotTop-15:b.plotY+d.yAxis.pos})})},updatePosition:function(a){var c=this.chart,e=this.getLabel(),e=(this.options.positioner|| +this.getPosition).call(this,e.width,e.height,a);this.move(Math.round(e.x),Math.round(e.y||0),a.plotX+c.plotLeft,a.plotY+c.plotTop)},getDateFormat:function(a,p,k,b){var c=B("%m-%d %H:%M:%S.%L",p),d,r,h={millisecond:15,second:12,minute:9,hour:6,day:3},v="millisecond";for(r in e){if(a===e.week&&+B("%w",p)===k&&"00:00:00.000"===c.substr(6)){r="week";break}if(e[r]>a){r=v;break}if(h[r]&&c.substr(h[r])!=="01-01 00:00:00.000".substr(h[r]))break;"week"!==r&&(v=r)}r&&(d=b[r]);return d},getXDateFormat:function(a, +e,k){e=e.dateTimeLabelFormats;var b=k&&k.closestPointRange;return(b?this.getDateFormat(b,a.x,k.options.startOfWeek,e):e.day)||e.year},tooltipFooterHeaderFormatter:function(a,e){var c=e?"footer":"header";e=a.series;var b=e.tooltipOptions,m=b.xDateFormat,d=e.xAxis,r=d&&"datetime"===d.options.type&&u(a.key),c=b[c+"Format"];r&&!m&&(m=this.getXDateFormat(a,b,d));r&&m&&(c=c.replace("{point.key}","{point.key:"+m+"}"));return E(c,{point:a,series:e})},bodyFormatter:function(a){return h(a,function(a){var c= +a.series.tooltipOptions;return(c.pointFormatter||a.point.tooltipFormatter).call(a.point,c.pointFormat)})}}})(I);(function(a){var B=a.addEvent,z=a.attr,C=a.charts,E=a.color,u=a.css,h=a.defined,n=a.doc,t=a.each,l=a.extend,k=a.fireEvent,e=a.offset,c=a.pick,p=a.removeEvent,H=a.splat,b=a.Tooltip,m=a.win;a.Pointer=function(a,b){this.init(a,b)};a.Pointer.prototype={init:function(a,e){this.options=e;this.chart=a;this.runChartClick=e.chart.events&&!!e.chart.events.click;this.pinchDown=[];this.lastValidTouch= +{};b&&e.tooltip.enabled&&(a.tooltip=new b(a,e.tooltip),this.followTouchMove=c(e.tooltip.followTouchMove,!0));this.setDOMEvents()},zoomOption:function(a){var b=this.chart,d=b.options.chart,e=d.zoomType||"",b=b.inverted;/touch/.test(a.type)&&(e=c(d.pinchType,e));this.zoomX=a=/x/.test(e);this.zoomY=e=/y/.test(e);this.zoomHor=a&&!b||e&&b;this.zoomVert=e&&!b||a&&b;this.hasZoom=a||e},normalize:function(a,b){var d,c;a=a||m.event;a.target||(a.target=a.srcElement);c=a.touches?a.touches.length?a.touches.item(0): +a.changedTouches[0]:a;b||(this.chartPosition=b=e(this.chart.container));void 0===c.pageX?(d=Math.max(a.x,a.clientX-b.left),b=a.y):(d=c.pageX-b.left,b=c.pageY-b.top);return l(a,{chartX:Math.round(d),chartY:Math.round(b)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};t(this.chart.axes,function(d){b[d.isXAxis?"xAxis":"yAxis"].push({axis:d,value:d.toValue(a[d.horiz?"chartX":"chartY"])})});return b},getKDPoints:function(a,b,e){var d=[],f,m,r;t(a,function(a){f=a.noSharedTooltip&&b;m=!b&&a.directTouch; +a.visible&&!f&&!m&&c(a.options.enableMouseTracking,!0)&&(r=a.searchPoint(e,!f&&1===a.kdDimensions))&&r.series&&d.push(r)});d.sort(function(a,d){var f=a.distX-d.distX,c=a.dist-d.dist,e=(d.series.group&&d.series.group.zIndex)-(a.series.group&&a.series.group.zIndex);return 0!==f&&b?f:0!==c?c:0!==e?e:a.series.index>d.series.index?-1:1});if(b)for(a=d.length;a--;)(d[a].x!==d[0].x||d[a].series.noSharedTooltip)&&d.splice(a,1);return d},getPointFromEvent:function(a){a=a.target;for(var b;a&&!b;)b=a.point,a= +a.parentNode;return b},getHoverData:function(a,b,e,m,f,k){var d=a;a=b;var r;if(m)f?(r=[],t(e,function(a){var b=a.noSharedTooltip&&f,e=!f&&a.directTouch;a.visible&&!b&&!e&&c(a.options.enableMouseTracking,!0)&&(a=a.searchKDTree({clientX:d.clientX,plotY:d.plotY},!b&&1===a.kdDimensions))&&a.series&&r.push(a)}),0===r.length&&(r=[d])):r=[d];else{if(a&&!a.options.stickyTracking)r=this.getKDPoints([a],f,k);else{if(!f)if(a)a.options.stickyTracking||(e=[a]);else for(m=0;mk+x&&(c=k+x),fq+p&&(f=q+p),this.hasDragged=Math.sqrt(Math.pow(g-c,2)+Math.pow(n-f,2)),10q.max&&(h=q.max-f,D=!0);D?(K-=.8*(K-p[m][0]),x||(g-=.8*(g-p[m][1])),l()):p[m]=[K,g];F||(c[m]=y-v,c[n]=f);c=F?1/t:t;e[n]=f;e[m]=h;k[F?a?"scaleY":"scaleX":"scale"+d]=t;k["translate"+d]=c* +v+(K-c*J)},pinch:function(a){var n=this,l=n.chart,k=n.pinchDown,e=a.touches,c=e.length,p=n.lastValidTouch,H=n.hasZoom,b=n.selectionMarker,m={},d=1===c&&(n.inClass(a.target,"highcharts-tracker")&&l.runTrackerClick||n.runChartClick),r={};1d-6&&k(J||b.chartWidth-2*t-g-c.x)&&(this.itemX=g,this.itemY+=L+this.lastLineHeight+u,this.lastLineHeight=0);this.maxItemWidth=Math.max(this.maxItemWidth,p);this.lastItemY=L+this.itemY+u;this.lastLineHeight=Math.max(f,this.lastLineHeight);a._legendItemPos=[this.itemX,this.itemY];e?this.itemX+=p:(this.itemY+=L+f+u,this.lastLineHeight=f);this.offsetWidth=J||Math.max((e?this.itemX-g-q:p)+t, +this.offsetWidth)},getAllItems:function(){var a=[];h(this.chart.series,function(b){var d=b&&b.options;b&&k(d.showInLegend,u(d.linkedTo)?!1:void 0,!0)&&(a=a.concat(b.legendItems||("point"===d.legendType?b.data:b)))});return a},adjustMargins:function(a,c){var b=this.chart,e=this.options,m=e.align.charAt(0)+e.verticalAlign.charAt(0)+e.layout.charAt(0);e.floating||h([/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/],function(d,f){d.test(m)&&!u(a[f])&&(b[t[f]]=Math.max(b[t[f]],b.legend[(f+1)% +2?"legendHeight":"legendWidth"]+[1,-1,-1,1][f]*e[f%2?"x":"y"]+k(e.margin,12)+c[f]))})},render:function(){var a=this,e=a.chart,d=e.renderer,k=a.group,p,n,f,y,t=a.box,u=a.options,q=a.padding;a.itemX=a.initialItemX;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;k||(a.group=k=d.g("legend").attr({zIndex:7}).add(),a.contentGroup=d.g().attr({zIndex:1}).add(k),a.scrollGroup=d.g().add(a.contentGroup));a.renderTitle();p=a.getAllItems();c(p,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&& +b.options.legendIndex||0)});u.reversed&&p.reverse();a.allItems=p;a.display=n=!!p.length;a.lastLineHeight=0;h(p,function(b){a.renderItem(b)});f=(u.width||a.offsetWidth)+q;y=a.lastItemY+a.lastLineHeight+a.titleHeight;y=a.handleOverflow(y);y+=q;t||(a.box=t=d.rect().addClass("highcharts-legend-box").attr({r:u.borderRadius}).add(k),t.isNew=!0);t.attr({stroke:u.borderColor,"stroke-width":u.borderWidth||0,fill:u.backgroundColor||"none"}).shadow(u.shadow);0d&&!1!==n.enabled?(this.clipHeight=f=Math.max(d-20-this.titleHeight-K,0),this.currentPage=k(this.currentPage,1),this.fullHeight=a,h(g,function(a,b){var d=a._legendItemPos[1];a=Math.round(a.legendItem.getBBox().height); +var c=u.length;if(!c||d-u[c-1]>f&&(L||d)!==u[c-1])u.push(L||d),c++;b===g.length-1&&d+a-u[c-1]>f&&u.push(d);d!==L&&(L=d)}),l||(l=b.clipRect=c.clipRect(0,K,9999,0),b.contentGroup.clip(l)),D(f),x||(this.nav=x=c.g().attr({zIndex:1}).add(this.group),this.up=c.symbol("triangle",0,0,q,q).on("click",function(){b.scroll(-1,t)}).add(x),this.pager=c.text("",15,10).addClass("highcharts-legend-navigation").css(n.style).add(x),this.down=c.symbol("triangle-down",0,0,q,q).on("click",function(){b.scroll(1,t)}).add(x)), +b.scroll(0),a=d):x&&(D(),this.nav=x.destroy(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0);return a},scroll:function(a,c){var b=this.pages,m=b.length;a=this.currentPage+a;var k=this.clipHeight,p=this.options.navigation,f=this.pager,h=this.padding;a>m&&(a=m);0m&&(e=typeof a[0],"string"===e?c.name=a[0]:"number"===e&&(c.x=a[0]),d++);h=h.value;)h=c[++k];h&&h.color&&!this.options.color&&(this.color=h.color);return h},destroy:function(){var a=this.series.chart,c=a.hoverPoints,h;a.pointCount--;c&&(this.setState(),E(c,this),c.length|| +(a.hoverPoints=null));if(this===a.hoverPoint)this.onMouseOut();if(this.graphic||this.dataLabel)k(this),this.destroyElements();this.legendItem&&a.legend.destroyItem(this);for(h in this)this[h]=null},destroyElements:function(){for(var a=["graphic","dataLabel","dataLabelUpper","connector","shadowGroup"],c,k=6;k--;)c=a[k],this[c]&&(this[c]=this[c].destroy())},getLabelConfig:function(){return{x:this.category,y:this.y,color:this.color,colorIndex:this.colorIndex,key:this.name||this.category,series:this.series, +point:this,percentage:this.percentage,total:this.total||this.stackTotal}},tooltipFormatter:function(a){var c=this.series,e=c.tooltipOptions,k=l(e.valueDecimals,""),b=e.valuePrefix||"",m=e.valueSuffix||"";z(c.pointArrayMap||["y"],function(c){c="{point."+c;if(b||m)a=a.replace(c+"}",b+c+"}"+m);a=a.replace(c+"}",c+":,."+k+"f}")});return h(a,{point:this,series:this.series})},firePointEvent:function(a,c,k){var e=this,b=this.series.options;(b.point.events[a]||e.options&&e.options.events&&e.options.events[a])&& +this.importEvents();"click"===a&&b.allowPointSelect&&(k=function(a){e.select&&e.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});u(this,a,c,k)},visible:!0}})(I);(function(a){var B=a.addEvent,z=a.animObject,C=a.arrayMax,E=a.arrayMin,u=a.correctFloat,h=a.Date,n=a.defaultOptions,t=a.defaultPlotOptions,l=a.defined,k=a.each,e=a.erase,c=a.extend,p=a.fireEvent,H=a.grep,b=a.isArray,m=a.isNumber,d=a.isString,r=a.merge,A=a.pick,v=a.removeEvent,f=a.splat,y=a.SVGElement,G=a.syncTimeout,F=a.win;a.Series=a.seriesType("line", +null,{lineWidth:2,allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},marker:{lineWidth:0,lineColor:"#ffffff",radius:4,states:{hover:{animation:{duration:50},enabled:!0,radiusPlus:2,lineWidthPlus:1},select:{fillColor:"#cccccc",lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:{align:"center",formatter:function(){return null===this.y?"":a.numberFormat(this.y,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"contrast",textOutline:"1px contrast"},verticalAlign:"bottom", +x:0,y:0,padding:5},cropThreshold:300,pointRange:0,softThreshold:!0,states:{hover:{animation:{duration:50},lineWidthPlus:1,marker:{},halo:{size:10,opacity:.25}},select:{marker:{}}},stickyTracking:!0,turboThreshold:1E3},{isCartesian:!0,pointClass:a.Point,sorted:!0,requireSorting:!0,directTouch:!1,axisTypes:["xAxis","yAxis"],colorCounter:0,parallelArrays:["x","y"],coll:"series",init:function(a,b){var d=this,f,e,g=a.series,q;d.chart=a;d.options=b=d.setOptions(b);d.linkedSeries=[];d.bindAxes();c(d,{name:b.name, +state:"",visible:!1!==b.visible,selected:!0===b.selected});e=b.events;for(f in e)B(d,f,e[f]);if(e&&e.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;d.getColor();d.getSymbol();k(d.parallelArrays,function(a){d[a+"Data"]=[]});d.setData(b.data,!1);d.isCartesian&&(a.hasCartesianSeries=!0);g.length&&(q=g[g.length-1]);d._i=A(q&&q._i,-1)+1;a.orderSeries(this.insert(g))},insert:function(a){var b=this.options.index,c;if(m(b)){for(c=a.length;c--;)if(b>=A(a[c].options.index, +a[c]._i)){a.splice(c+1,0,this);break}-1===c&&a.unshift(this);c+=1}else a.push(this);return A(c,a.length-1)},bindAxes:function(){var b=this,c=b.options,d=b.chart,f;k(b.axisTypes||[],function(e){k(d[e],function(a){f=a.options;if(c[e]===f.index||void 0!==c[e]&&c[e]===f.id||void 0===c[e]&&0===f.index)b.insert(a.series),b[e]=a,a.isDirty=!0});b[e]||b.optionalAxis===e||a.error(18,!0)})},updateParallelArrays:function(a,b){var c=a.series,d=arguments,f=m(b)?function(d){var f="y"===d&&c.toYData?c.toYData(a): +a[d];c[d+"Data"][b]=f}:function(a){Array.prototype[b].apply(c[a+"Data"],Array.prototype.slice.call(d,2))};k(c.parallelArrays,f)},autoIncrement:function(){var a=this.options,b=this.xIncrement,c,d=a.pointIntervalUnit,b=A(b,a.pointStart,0);this.pointInterval=c=A(this.pointInterval,a.pointInterval,1);d&&(a=new h(b),"day"===d?a=+a[h.hcSetDate](a[h.hcGetDate]()+c):"month"===d?a=+a[h.hcSetMonth](a[h.hcGetMonth]()+c):"year"===d&&(a=+a[h.hcSetFullYear](a[h.hcGetFullYear]()+c)),c=a-b);this.xIncrement=b+c;return b}, +setOptions:function(a){var b=this.chart,c=b.options.plotOptions,b=b.userOptions||{},d=b.plotOptions||{},f=c[this.type];this.userOptions=a;c=r(f,c.series,a);this.tooltipOptions=r(n.tooltip,n.plotOptions[this.type].tooltip,b.tooltip,d.series&&d.series.tooltip,d[this.type]&&d[this.type].tooltip,a.tooltip);null===f.marker&&delete c.marker;this.zoneAxis=c.zoneAxis;a=this.zones=(c.zones||[]).slice();!c.negativeColor&&!c.negativeFillColor||c.zones||a.push({value:c[this.zoneAxis+"Threshold"]||c.threshold|| +0,className:"highcharts-negative",color:c.negativeColor,fillColor:c.negativeFillColor});a.length&&l(a[a.length-1].value)&&a.push({color:this.color,fillColor:this.fillColor});return c},getCyclic:function(a,b,c){var d,f=this.chart,g=this.userOptions,e=a+"Index",q=a+"Counter",k=c?c.length:A(f.options.chart[a+"Count"],f[a+"Count"]);b||(d=A(g[e],g["_"+e]),l(d)||(f.series.length||(f[q]=0),g["_"+e]=d=f[q]%k,f[q]+=1),c&&(b=c[d]));void 0!==d&&(this[e]=d);this[a]=b},getColor:function(){this.options.colorByPoint? +this.options.color=null:this.getCyclic("color",this.options.color||t[this.type].color,this.chart.options.colors)},getSymbol:function(){this.getCyclic("symbol",this.options.marker.symbol,this.chart.options.symbols)},drawLegendSymbol:a.LegendSymbolMixin.drawLineMarker,setData:function(c,f,e,h){var q=this,g=q.points,p=g&&g.length||0,l,x=q.options,r=q.chart,n=null,v=q.xAxis,t=x.turboThreshold,y=this.xData,u=this.yData,G=(l=q.pointArrayMap)&&l.length;c=c||[];l=c.length;f=A(f,!0);if(!1!==h&&l&&p===l&&!q.cropped&& +!q.hasGroupedData&&q.visible)k(c,function(a,b){g[b].update&&a!==x.data[b]&&g[b].update(a,!1,null,!1)});else{q.xIncrement=null;q.colorCounter=0;k(this.parallelArrays,function(a){q[a+"Data"].length=0});if(t&&l>t){for(e=0;null===n&&em||this.forceCrop))if(c[f-1]v)c=[],d=[];else if(c[0]v)e=this.cropData(this.xData,this.yData,r,v),c=e.xData,d=e.yData,e=e.start,g=!0;for(m=c.length||1;--m;)f=n?h(c[m])-h(c[m-1]):c[m]-c[m-1],0f&&this.requireSorting&&a.error(15);this.cropped=g;this.cropStart=e;this.processedXData=c;this.processedYData= +d;this.closestPointRange=q},cropData:function(a,b,c,d){var f=a.length,g=0,e=f,q=A(this.cropShoulder,1),k;for(k=0;k=c){g=Math.max(0,k-q);break}for(c=k;cd){e=c+q;break}return{xData:a.slice(g,e),yData:b.slice(g,e),start:g,end:e}},generatePoints:function(){var a=this.options.data,b=this.data,c,d=this.processedXData,e=this.processedYData,g=this.pointClass,k=d.length,m=this.cropStart||0,h,l=this.hasGroupedData,p,n=[],r;b||l||(b=[],b.length=a.length,b=this.data=b);for(r=0;r< +k;r++)h=m+r,l?(p=(new g).init(this,[d[r]].concat(f(e[r]))),p.dataGroup=this.groupMap[r]):(p=b[h])||void 0===a[h]||(b[h]=p=(new g).init(this,a[h],d[r])),p.index=h,n[r]=p;if(b&&(k!==(c=b.length)||l))for(r=0;r=q&&(d[r-1]||l)<=k,h&&l)if(h=p.length)for(;h--;)null!==p[h]&&(e[g++]=p[h]);else e[g++]=p;this.dataMin=E(e);this.dataMax=C(e)},translate:function(){this.processedXData||this.processData();this.generatePoints();var a=this.options,b=a.stacking,c=this.xAxis,d=c.categories,f=this.yAxis,e=this.points,k=e.length,h=!!this.modifyValue,p=a.pointPlacement, +r="between"===p||m(p),n=a.threshold,v=a.startFromThreshold?n:0,t,y,G,F,H=Number.MAX_VALUE;"between"===p&&(p=.5);m(p)&&(p*=A(a.pointRange||c.pointRange));for(a=0;a=C&&(z.isNull=!0);z.plotX=t=u(Math.min(Math.max(-1E5,c.translate(B,0,0,0,1,p,"flags"===this.type)),1E5));b&&this.visible&&!z.isNull&&E&&E[B]&&(F=this.getStackIndicator(F,B,this.index),I=E[B],C=I.points[F.key], +y=C[0],C=C[1],y===v&&F.key===E[B].base&&(y=A(n,f.min)),f.positiveValuesOnly&&0>=y&&(y=null),z.total=z.stackTotal=I.total,z.percentage=I.total&&z.y/I.total*100,z.stackY=C,I.setOffset(this.pointXOffset||0,this.barW||0));z.yBottom=l(y)?f.translate(y,0,1,0,1):null;h&&(C=this.modifyValue(C,z));z.plotY=y="number"===typeof C&&Infinity!==C?Math.min(Math.max(-1E5,f.translate(C,0,1,0,1)),1E5):void 0;z.isInside=void 0!==y&&0<=y&&y<=f.len&&0<=t&&t<=c.len;z.clientX=r?u(c.translate(B,0,0,0,1,p)):t;z.negative=z.y< +(n||0);z.category=d&&void 0!==d[z.x]?d[z.x]:z.x;z.isNull||(void 0!==G&&(H=Math.min(H,Math.abs(t-G))),G=t);z.zone=this.zones.length&&z.getZone()}this.closestPointRangePx=H},getValidPoints:function(a,b){var c=this.chart;return H(a||this.points||[],function(a){return b&&!c.isInsidePlot(a.plotX,a.plotY,c.inverted)?!1:!a.isNull})},setClip:function(a){var b=this.chart,c=this.options,d=b.renderer,f=b.inverted,e=this.clipBox,q=e||b.clipBox,k=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,q.height, +c.xAxis,c.yAxis].join(),m=b[k],h=b[k+"m"];m||(a&&(q.width=0,b[k+"m"]=h=d.clipRect(-99,f?-b.plotLeft:-b.plotTop,99,f?b.chartWidth:b.chartHeight)),b[k]=m=d.clipRect(q),m.count={length:0});a&&!m.count[this.index]&&(m.count[this.index]=!0,m.count.length+=1);!1!==c.clip&&(this.group.clip(a||e?m:b.clipRect),this.markerGroup.clip(h),this.sharedClipKey=k);a||(m.count[this.index]&&(delete m.count[this.index],--m.count.length),0===m.count.length&&k&&b[k]&&(e||(b[k]=b[k].destroy()),b[k+"m"]&&(this.markerGroup.clip(), +b[k+"m"]=b[k+"m"].destroy())))},animate:function(a){var b=this.chart,c=z(this.options.animation),d;a?this.setClip(c):(d=this.sharedClipKey,(a=b[d])&&a.animate({width:b.plotSizeX},c),b[d+"m"]&&b[d+"m"].animate({width:b.plotSizeX+99},c),this.animate=null)},afterAnimate:function(){this.setClip();p(this,"afterAnimate")},drawPoints:function(){var a=this.points,b=this.chart,c,d,f,e,k=this.options.marker,h,p,l,r,n=this.markerGroup,v=A(k.enabled,this.xAxis.isRadial?!0:null,this.closestPointRangePx>=2*k.radius); +if(!1!==k.enabled||this._hasPointMarkers)for(d=0;df&&b.shadow));g&&(g.startX=c.xMap,g.isArea=c.isArea)})},applyZones:function(){var a=this,b=this.chart,c=b.renderer,d=this.zones,f,e,m=this.clips||[],h,p=this.graph,l=this.area,r=Math.max(b.chartWidth,b.chartHeight),n=this[(this.zoneAxis||"y")+"Axis"],v,t,y=b.inverted,u,G,F,H,z=!1;d.length&&(p||l)&&n&&void 0!==n.min&&(t=n.reversed,u=n.horiz,p&&p.hide(),l&&l.hide(), +v=n.getExtremes(),k(d,function(d,g){f=t?u?b.plotWidth:0:u?0:n.toPixels(v.min);f=Math.min(Math.max(A(e,f),0),r);e=Math.min(Math.max(Math.round(n.toPixels(A(d.value,v.max),!0)),0),r);z&&(f=e=n.toPixels(v.max));G=Math.abs(f-e);F=Math.min(f,e);H=Math.max(f,e);n.isXAxis?(h={x:y?H:F,y:0,width:G,height:r},u||(h.x=b.plotHeight-h.x)):(h={x:0,y:y?H:F,width:r,height:G},u&&(h.y=b.plotWidth-h.y));y&&c.isVML&&(h=n.isXAxis?{x:0,y:t?F:H,height:h.width,width:b.chartWidth}:{x:h.y-b.plotLeft-b.spacingBox.x,y:0,width:h.height, +height:b.chartHeight});m[g]?m[g].animate(h):(m[g]=c.clipRect(h),p&&a["zone-graph-"+g].clip(m[g]),l&&a["zone-area-"+g].clip(m[g]));z=d.value>v.max}),this.clips=m)},invertGroups:function(a){function b(){k(["group","markerGroup"],function(b){c[b]&&(d.renderer.isVML&&c[b].attr({width:c.yAxis.len,height:c.xAxis.len}),c[b].width=c.yAxis.len,c[b].height=c.xAxis.len,c[b].invert(a))})}var c=this,d=c.chart,f;c.xAxis&&(f=B(d,"resize",b),B(c,"destroy",f),b(a),c.invertGroups=b)},plotGroup:function(a,b,c,d,f){var e= +this[a],k=!e;k&&(this[a]=e=this.chart.renderer.g(b).attr({zIndex:d||.1}).add(f),e.addClass("highcharts-series-"+this.index+" highcharts-"+this.type+"-series highcharts-color-"+this.colorIndex+" "+(this.options.className||"")));e.attr({visibility:c})[k?"attr":"animate"](this.getPlotBox());return e},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;a.inverted&&(b=c,c=this.xAxis);return{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},render:function(){var a= +this,b=a.chart,c,d=a.options,f=!!a.animate&&b.renderer.isSVG&&z(d.animation).duration,e=a.visible?"inherit":"hidden",k=d.zIndex,m=a.hasRendered,h=b.seriesGroup,p=b.inverted;c=a.plotGroup("group","series",e,k,h);a.markerGroup=a.plotGroup("markerGroup","markers",e,k,h);f&&a.animate(!0);c.inverted=a.isCartesian?p:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());a.drawDataLabels&&a.drawDataLabels();a.visible&&a.drawPoints();a.drawTracker&&!1!==a.options.enableMouseTracking&&a.drawTracker();a.invertGroups(p); +!1===d.clip||a.sharedClipKey||m||c.clip(b.clipRect);f&&a.animate();m||(a.animationTimeout=G(function(){a.afterAnimate()},f));a.isDirty=!1;a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirty||this.isDirtyData,c=this.group,d=this.xAxis,f=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:A(d&&d.left,a.plotLeft),translateY:A(f&&f.top,a.plotTop)}));this.translate();this.render();b&&delete this.kdTree},kdDimensions:1,kdAxisArray:["clientX", +"plotY"],searchPoint:function(a,b){var c=this.xAxis,d=this.yAxis,f=this.chart.inverted;return this.searchKDTree({clientX:f?c.len-a.chartY+c.pos:a.chartX-c.pos,plotY:f?d.len-a.chartX+d.pos:a.chartY-d.pos},b)},buildKDTree:function(){function a(c,d,f){var e,g;if(g=c&&c.length)return e=b.kdAxisArray[d%f],c.sort(function(a,b){return a[e]-b[e]}),g=Math.floor(g/2),{point:c[g],left:a(c.slice(0,g),d+1,f),right:a(c.slice(g+1),d+1,f)}}this.buildingKdTree=!0;var b=this,c=b.kdDimensions;delete b.kdTree;G(function(){b.kdTree= +a(b.getValidPoints(null,!b.directTouch),c,c);b.buildingKdTree=!1},b.options.kdNow?0:1)},searchKDTree:function(a,b){function c(a,b,g,m){var h=b.point,p=d.kdAxisArray[g%m],q,r,n=h;r=l(a[f])&&l(h[f])?Math.pow(a[f]-h[f],2):null;q=l(a[e])&&l(h[e])?Math.pow(a[e]-h[e],2):null;q=(r||0)+(q||0);h.dist=l(q)?Math.sqrt(q):Number.MAX_VALUE;h.distX=l(r)?Math.sqrt(r):Number.MAX_VALUE;p=a[p]-h[p];q=0>p?"left":"right";r=0>p?"right":"left";b[q]&&(q=c(a,b[q],g+1,m),n=q[k]v;)r--;this.updateParallelArrays(g,"splice",r,0,0);this.updateParallelArrays(g,r);k&&g.name&&(k[v]=g.name);l.splice(r,0,a);p&&(this.data.splice(r,0,null),this.processData());"point"===f.legendType&&this.generatePoints(); +d&&(h[0]&&h[0].remove?h[0].remove(!1):(h.shift(),this.updateParallelArrays(g,"shift"),l.shift()));this.isDirtyData=this.isDirty=!0;c&&m.redraw(e)},removePoint:function(a,c,d){var f=this,e=f.data,h=e[a],m=f.points,k=f.chart,l=function(){m&&m.length===e.length&&m.splice(a,1);e.splice(a,1);f.options.data.splice(a,1);f.updateParallelArrays(h||{series:f},"splice",a,1);h&&h.destroy();f.isDirty=!0;f.isDirtyData=!0;c&&k.redraw()};A(d,k);c=b(c,!0);h?h.firePointEvent("remove",null,l):l()},remove:function(a, +c,d){function f(){e.destroy();h.isDirtyLegend=h.isDirtyBox=!0;h.linkSeries();b(a,!0)&&h.redraw(c)}var e=this,h=e.chart;!1!==d?k(e,"remove",null,f):f()},update:function(a,c){var d=this,f=this.chart,e=this.userOptions,h=this.oldType||this.type,m=a.type||e.type||f.options.chart.type,k=r[h].prototype,p=["group","markerGroup","dataLabelsGroup"],g;if(m&&m!==h||void 0!==a.zIndex)p.length=0;n(p,function(a){p[a]=d[a];delete d[a]});a=H(e,{animation:!1,index:this.index,pointStart:this.xData[0]},{data:this.options.data}, +a);this.remove(!1,null,!1);for(g in k)this[g]=void 0;l(this,r[m||h].prototype);n(p,function(a){d[a]=p[a]});this.init(f,a);this.oldType=h;f.linkSeries();b(c,!0)&&f.redraw(!1)}});l(C.prototype,{update:function(a,c){var d=this.chart;a=d.options[this.coll][this.options.index]=H(this.userOptions,a);this.destroy(!0);this.init(d,l(a,{events:void 0}));d.isDirtyBox=!0;b(c,!0)&&d.redraw()},remove:function(a){for(var c=this.chart,d=this.coll,f=this.series,e=f.length;e--;)f[e]&&f[e].remove(!1);t(c.axes,this); +t(c[d],this);c.options[d].splice(this.options.index,1);n(c[d],function(a,b){a.options.index=b});this.destroy();c.isDirtyBox=!0;b(a,!0)&&c.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}})})(I);(function(a){var B=a.color,z=a.each,C=a.map,E=a.pick,u=a.Series,h=a.seriesType;h("area","line",{softThreshold:!1,threshold:0},{singleStacks:!1,getStackPoints:function(){var a=[],h=[],l=this.xAxis,k=this.yAxis,e=k.stacks[this.stackKey],c={}, +p=this.points,u=this.index,b=k.series,m=b.length,d,r=E(k.options.reversedStacks,!0)?1:-1,A,v;if(this.options.stacking){for(A=0;Aa&&l>h?(l=Math.max(a,h),e=2*h-l):lE&&e>h?(e=Math.max(E,h),l=2*h-e):e=Math.abs(c)&&.5a.closestPointRange* +a.xAxis.transA,k=a.borderWidth=n(h.borderWidth,k?0:1),b=a.yAxis,m=a.translatedThreshold=b.getThreshold(h.threshold),d=n(h.minPointLength,5),l=a.getColumnMetrics(),u=l.width,v=a.barW=Math.max(u,1+2*k),f=a.pointXOffset=l.offset;c.inverted&&(m-=.5);h.pointPadding&&(v=Math.ceil(v));t.prototype.translate.apply(a);C(a.points,function(e){var h=n(e.yBottom,m),k=999+Math.abs(h),k=Math.min(Math.max(-k,e.plotY),b.len+k),l=e.plotX+f,p=v,r=Math.min(k,h),t,y=Math.max(k,h)-r;Math.abs(y)d?h-d:m-(t?d:0));e.barX=l;e.pointWidth=u;e.tooltipPos=c.inverted?[b.len+b.pos-c.plotLeft-k,a.xAxis.len-l-p/2,y]:[l+p/2,k+b.pos-c.plotTop,y];e.shapeType="rect";e.shapeArgs=a.crispCol.apply(a,e.isNull?[e.plotX,b.len/2,0,0]:[l,r,p,y])})},getSymbol:a.noop,drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,drawGraph:function(){this.group[this.dense?"addClass":"removeClass"]("highcharts-dense-data")},pointAttribs:function(a,c){var e=this.options,k,b=this.pointAttrToOptions|| +{};k=b.stroke||"borderColor";var m=b["stroke-width"]||"borderWidth",d=a&&a.color||this.color,l=a[k]||e[k]||this.color||d,n=a[m]||e[m]||this[m]||0,b=e.dashStyle;a&&this.zones.length&&(d=(d=a.getZone())&&d.color||a.options.color||this.color);c&&(a=h(e.states[c],a.options.states&&a.options.states[c]||{}),c=a.brightness,d=a.color||void 0!==c&&z(d).brighten(a.brightness).get()||d,l=a[k]||l,n=a[m]||n,b=a.dashStyle||b);k={fill:d,stroke:l,"stroke-width":n};e.borderRadius&&(k.r=e.borderRadius);b&&(k.dashstyle= +b);return k},drawPoints:function(){var a=this,c=this.chart,k=a.options,l=c.renderer,b=k.animationLimit||250,m;C(a.points,function(d){var e=d.graphic;if(u(d.plotY)&&null!==d.y){m=d.shapeArgs;if(e)e[c.pointCountl;++l)k=n[l],a=2>l||2===l&&/%$/.test(k),n[l]=z(k,[h,E,t,n[2]][l])+ +(a?u:0);n[3]>n[2]&&(n[3]=n[2]);return n}}})(I);(function(a){var B=a.addEvent,z=a.defined,C=a.each,E=a.extend,u=a.inArray,h=a.noop,n=a.pick,t=a.Point,l=a.Series,k=a.seriesType,e=a.setAnimation;k("pie","line",{center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30,enabled:!0,formatter:function(){return null===this.y?void 0:this.point.name},x:0},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,stickyTracking:!1,tooltip:{followPointer:!0},borderColor:"#ffffff", +borderWidth:1,states:{hover:{brightness:.1,shadow:!1}}},{isCartesian:!1,requireSorting:!1,directTouch:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttribs:a.seriesTypes.column.prototype.pointAttribs,animate:function(a){var c=this,e=c.points,b=c.startAngleRad;a||(C(e,function(a){var d=a.graphic,e=a.shapeArgs;d&&(d.attr({r:a.startR||c.center[3]/2,start:b,end:b}),d.animate({r:e.r,start:e.start,end:e.end},c.options.animation))}),c.animate=null)},updateTotals:function(){var a, +e=0,h=this.points,b=h.length,k,d=this.options.ignoreHiddenPoint;for(a=0;ak.y&&(k.y=null),e+=d&&!k.visible?0:k.y;this.total=e;for(a=0;a1.5*Math.PI?l-=2*Math.PI:l<-Math.PI/ +2&&(l+=2*Math.PI);x.slicedTranslation={translateX:Math.round(Math.cos(l)*b),translateY:Math.round(Math.sin(l)*b)};d=Math.cos(l)*a[2]/2;k=Math.sin(l)*a[2]/2;x.tooltipPos=[a[0]+.7*d,a[1]+.7*k];x.half=l<-Math.PI/2||l>Math.PI/2?1:0;x.angle=l;h=Math.min(h,u/5);x.labelPos=[a[0]+d+Math.cos(l)*u,a[1]+k+Math.sin(l)*u,a[0]+d+Math.cos(l)*h,a[1]+k+Math.sin(l)*h,a[0]+d,a[1]+k,0>u?"center":x.half?"right":"left",l]}},drawGraph:null,drawPoints:function(){var a=this,e=a.chart.renderer,h,b,k,d,l=a.options.shadow;l&& +!a.shadowGroup&&(a.shadowGroup=e.g("shadow").add(a.group));C(a.points,function(c){if(null!==c.y){b=c.graphic;d=c.shapeArgs;h=c.getTranslate();var m=c.shadowGroup;l&&!m&&(m=c.shadowGroup=e.g("shadow").add(a.shadowGroup));m&&m.attr(h);k=a.pointAttribs(c,c.selected&&"select");b?b.setRadialReference(a.center).attr(k).animate(E(d,h)):(c.graphic=b=e[c.shapeType](d).setRadialReference(a.center).attr(h).add(a.group),c.visible||b.attr({visibility:"hidden"}),b.attr(k).attr({"stroke-linejoin":"round"}).shadow(l, +m));b.addClass(c.getClassName())}})},searchPoint:h,sortByAngle:function(a,e){a.sort(function(a,b){return void 0!==a.angle&&(b.angle-a.angle)*e})},drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,getCenter:a.CenteredSeriesMixin.getCenter,getSymbol:h},{init:function(){t.prototype.init.apply(this,arguments);var a=this,e;a.name=n(a.name,"Slice");e=function(c){a.slice("select"===c.type)};B(a,"select",e);B(a,"unselect",e);return a},setVisible:function(a,e){var c=this,b=c.series,h=b.chart,d=b.options.ignoreHiddenPoint; +e=n(e,d);a!==c.visible&&(c.visible=c.options.visible=a=void 0===a?!c.visible:a,b.options.data[u(c,b.data)]=c.options,C(["graphic","dataLabel","connector","shadowGroup"],function(b){if(c[b])c[b][a?"show":"hide"](!0)}),c.legendItem&&h.legend.colorizeItem(c,a),a||"hover"!==c.state||c.setState(""),d&&(b.isDirty=!0),e&&h.redraw())},slice:function(a,h,k){var b=this.series;e(k,b.chart);n(h,!0);this.sliced=this.options.sliced=z(a)?a:!this.sliced;b.options.data[u(this,b.data)]=this.options;this.graphic.animate(this.getTranslate()); +this.shadowGroup&&this.shadowGroup.animate(this.getTranslate())},getTranslate:function(){return this.sliced?this.slicedTranslation:{translateX:0,translateY:0}},haloPath:function(a){var c=this.shapeArgs;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(c.x,c.y,c.r+a,c.r+a,{innerR:this.shapeArgs.r,start:c.start,end:c.end})}})})(I);(function(a){var B=a.addEvent,z=a.arrayMax,C=a.defined,E=a.each,u=a.extend,h=a.format,n=a.map,t=a.merge,l=a.noop,k=a.pick,e=a.relativeLength,c=a.Series, +p=a.seriesTypes,H=a.stableSort;a.distribute=function(a,c){function b(a,b){return a.target-b.target}var e,h=!0,k=a,f=[],l;l=0;for(e=a.length;e--;)l+=a[e].size;if(l>c){H(a,function(a,b){return(b.rank||0)-(a.rank||0)});for(l=e=0;l<=c;)l+=a[e].size,e++;f=a.splice(e-1,a.length)}H(a,b);for(a=n(a,function(a){return{size:a.size,targets:[a.target]}});h;){for(e=a.length;e--;)h=a[e],l=(Math.min.apply(0,h.targets)+Math.max.apply(0,h.targets))/2,h.pos=Math.min(Math.max(0,l-h.size/2),c-h.size);e=a.length;for(h= +!1;e--;)0a[e].pos&&(a[e-1].size+=a[e].size,a[e-1].targets=a[e-1].targets.concat(a[e].targets),a[e-1].pos+a[e-1].size>c&&(a[e-1].pos=c-a[e-1].size),a.splice(e,1),h=!0)}e=0;E(a,function(a){var b=0;E(a.targets,function(){k[e].pos=a.pos+b;b+=k[e].size;e++})});k.push.apply(k,f);H(k,b)};c.prototype.drawDataLabels=function(){var a=this,c=a.options,d=c.dataLabels,e=a.points,l,n,f=a.hasRendered||0,p,u,F=k(d.defer,!0),q=a.chart.renderer;if(d.enabled||a._hasPointLabels)a.dlProcessOptions&& +a.dlProcessOptions(d),u=a.plotGroup("dataLabelsGroup","data-labels",F&&!f?"hidden":"visible",d.zIndex||6),F&&(u.attr({opacity:+f}),f||B(a,"afterAnimate",function(){a.visible&&u.show(!0);u[c.animation?"animate":"attr"]({opacity:1},{duration:200})})),n=d,E(e,function(b){var f,e=b.dataLabel,m,g,r,v=b.connector,y=!e,x;l=b.dlOptions||b.options&&b.options.dataLabels;if(f=k(l&&l.enabled,n.enabled)&&null!==b.y)for(g in d=t(n,l),m=b.getLabelConfig(),p=d.format?h(d.format,m):d.formatter.call(m,d),x=d.style, +r=d.rotation,x.color=k(d.color,x.color,a.color,"#000000"),"contrast"===x.color&&(x.color=d.inside||0>d.distance||c.stacking?q.getContrast(b.color||a.color):"#000000"),c.cursor&&(x.cursor=c.cursor),m={fill:d.backgroundColor,stroke:d.borderColor,"stroke-width":d.borderWidth,r:d.borderRadius||0,rotation:r,padding:d.padding,zIndex:1},m)void 0===m[g]&&delete m[g];!e||f&&C(p)?f&&C(p)&&(e?m.text=p:(e=b.dataLabel=q[r?"text":"label"](p,0,-9999,d.shape,null,null,d.useHTML,null,"data-label"),e.addClass("highcharts-data-label-color-"+ +b.colorIndex+" "+(d.className||"")+(d.useHTML?"highcharts-tracker":""))),e.attr(m),e.css(x).shadow(d.shadow),e.added||e.add(u),a.alignDataLabel(b,e,d,null,y)):(b.dataLabel=e.destroy(),v&&(b.connector=v.destroy()))})};c.prototype.alignDataLabel=function(a,c,d,e,h){var b=this.chart,f=b.inverted,l=k(a.plotX,-9999),m=k(a.plotY,-9999),n=c.getBBox(),q,p=d.rotation,r=d.align,t=this.visible&&(a.series.forceDL||b.isInsidePlot(l,Math.round(m),f)||e&&b.isInsidePlot(l,f?e.x+1:e.y+e.height-1,f)),A="justify"=== +k(d.overflow,"justify");t&&(q=d.style.fontSize,q=b.renderer.fontMetrics(q,c).b,e=u({x:f?b.plotWidth-m:l,y:Math.round(f?b.plotHeight-l:m),width:0,height:0},e),u(d,{width:n.width,height:n.height}),p?(A=!1,f=b.renderer.rotCorr(q,p),f={x:e.x+d.x+e.width/2+f.x,y:e.y+d.y+{top:0,middle:.5,bottom:1}[d.verticalAlign]*e.height},c[h?"attr":"animate"](f).attr({align:r}),l=(p+720)%360,l=180l,"left"===r?f.y-=l?n.height:0:"center"===r?(f.x-=n.width/2,f.y-=n.height/2):"right"===r&&(f.x-=n.width,f.y-=l?0: +n.height)):(c.align(d,null,e),f=c.alignAttr),A?this.justifyDataLabel(c,d,f,n,e,h):k(d.crop,!0)&&(t=b.isInsidePlot(f.x,f.y)&&b.isInsidePlot(f.x+n.width,f.y+n.height)),d.shape&&!p&&c.attr({anchorX:a.plotX,anchorY:a.plotY}));t||(c.attr({y:-9999}),c.placed=!1)};c.prototype.justifyDataLabel=function(a,c,d,e,h,k){var b=this.chart,l=c.align,m=c.verticalAlign,n,q,p=a.box?0:a.padding||0;n=d.x+p;0>n&&("right"===l?c.align="left":c.x=-n,q=!0);n=d.x+e.width-p;n>b.plotWidth&&("left"===l?c.align="right":c.x=b.plotWidth- +n,q=!0);n=d.y+p;0>n&&("bottom"===m?c.verticalAlign="top":c.y=-n,q=!0);n=d.y+e.height-p;n>b.plotHeight&&("top"===m?c.verticalAlign="bottom":c.y=b.plotHeight-n,q=!0);q&&(a.placed=!k,a.align(c,null,h))};p.pie&&(p.pie.prototype.drawDataLabels=function(){var b=this,e=b.data,d,h=b.chart,l=b.options.dataLabels,p=k(l.connectorPadding,10),f=k(l.connectorWidth,1),t=h.plotWidth,u=h.plotHeight,F,q=l.distance,x=b.center,B=x[2]/2,C=x[1],H=0k-2?v:w,f),g._attr={visibility:O,align:I[6]},g._pos={x:N+l.x+({left:p,right:-p}[I[6]]||0),y:w+l.y-10},I.x=N,I.y=w,null===b.options.size&&(D=g.getBBox().width,v=null,N-Dt-p&&(v=Math.round(N+D-t+p),P[1]=Math.max(v, +P[1])),0>w-M/2?P[0]=Math.max(Math.round(-w+M/2),P[0]):w+M/2>u&&(P[2]=Math.max(Math.round(w+M/2-u),P[2])),g.sideOverflow=v)}),0===z(P)||this.verifyDataLabelOverflow(P))&&(this.placeDataLabels(),H&&f&&E(this.points,function(a){var c;F=a.connector;if((g=a.dataLabel)&&g._pos&&a.visible){O=g._attr.visibility;if(c=!F)a.connector=F=h.renderer.path().addClass("highcharts-data-label-connector highcharts-color-"+a.colorIndex).add(b.dataLabelsGroup),F.attr({"stroke-width":f,stroke:l.connectorColor||a.color|| +"#666666"});F[c?"attr":"animate"]({d:b.connectorPath(a.labelPos)});F.attr("visibility",O)}else F&&(a.connector=F.destroy())}))},p.pie.prototype.connectorPath=function(a){var b=a.x,c=a.y;return k(this.options.dataLabels.softConnector,!0)?["M",b+("left"===a[6]?5:-5),c,"C",b,c,2*a[2]-a[4],2*a[3]-a[5],a[2],a[3],"L",a[4],a[5]]:["M",b+("left"===a[6]?5:-5),c,"L",a[2],a[3],"L",a[4],a[5]]},p.pie.prototype.placeDataLabels=function(){E(this.points,function(a){var b=a.dataLabel;b&&a.visible&&((a=b._pos)?(b.sideOverflow&& +(b._attr.width=b.getBBox().width-b.sideOverflow,b.css({width:b._attr.width+"px",textOverflow:"ellipsis"}),b.shortened=!0),b.attr(b._attr),b[b.moved?"animate":"attr"](a),b.moved=!0):b&&b.attr({y:-9999}))},this)},p.pie.prototype.alignDataLabel=l,p.pie.prototype.verifyDataLabelOverflow=function(a){var b=this.center,c=this.options,h=c.center,k=c.minSize||80,l,f;null!==h[0]?l=Math.max(b[2]-Math.max(a[1],a[3]),k):(l=Math.max(b[2]-a[1]-a[3],k),b[0]+=(a[3]-a[1])/2);null!==h[1]?l=Math.max(Math.min(l,b[2]- +Math.max(a[0],a[2])),k):(l=Math.max(Math.min(l,b[2]-a[0]-a[2]),k),b[1]+=(a[0]-a[2])/2);lk(this.translatedThreshold,f.yAxis.len)),p=k(d.inside,!!this.options.stacking);m&&(h=t(m),0>h.y&&(h.height+=h.y,h.y=0),m=h.y+h.height-f.yAxis.len, +0a+c||f+kb+e||h+lthis.pointCount))},pan:function(a,b){var c=this,d=c.hoverPoints,e;d&&n(d,function(a){a.setState()});n("xy"===b?[1,0]:[1],function(b){b=c[b?"xAxis":"yAxis"][0];var d=b.horiz,f=a[d?"chartX":"chartY"],d=d?"mouseDownX":"mouseDownY",h=c[d],k=(b.pointRange||0)/2,g=b.getExtremes(),l=b.toValue(h-f,!0)+k,k=b.toValue(h+b.len-f,!0)-k,m=km&&0>g&&(b.setExtremes(h,l,!1,!1,{trigger:"pan"}),e=!0);c[d]=f});e&&c.redraw(!1);E(c.container,{cursor:"move"})}});t(m.prototype,{select:function(a,c){var d=this,f=d.series,h=f.chart;a=b(a,!d.selected);d.firePointEvent(a?"select":"unselect",{accumulate:c},function(){d.selected=d.options.selected=a;f.options.data[e(d,f.data)]=d.options;d.setState(a&&"select");c||n(h.getSelectedPoints(), +function(a){a.selected&&a!==d&&(a.selected=a.options.selected=!1,f.options.data[e(a,f.data)]=a.options,a.setState(""),a.firePointEvent("unselect"))})})},onMouseOver:function(a){var b=this.series.chart.pointer;this.firePointEvent("mouseOver");b.runPointActions(a,this)},onMouseOut:function(){var a=this.series.chart;this.firePointEvent("mouseOut");n(a.hoverPoints||[],function(a){a.setState()});a.hoverPoints=a.hoverPoint=null},importEvents:function(){if(!this.hasImportedEvents){var a=H(this.series.options.point, +this.options).events,b;this.events=a;for(b in a)B(this,b,a[b]);this.hasImportedEvents=!0}},setState:function(a,c){var d=Math.floor(this.plotX),e=this.plotY,f=this.series,k=f.options.states[a]||{},l=h[f.type].marker&&f.options.marker,m=l&&!1===l.enabled,n=l&&l.states&&l.states[a]||{},p=!1===n.enabled,g=f.stateMarkerGraphic,r=this.marker||{},u=f.chart,v=f.halo,z,A=l&&f.markerAttribs;a=a||"";if(!(a===this.state&&!c||this.selected&&"select"!==a||!1===k.enabled||a&&(p||m&&!1===n.enabled)||a&&r.states&& +r.states[a]&&!1===r.states[a].enabled)){A&&(z=f.markerAttribs(this,a));if(this.graphic)this.state&&this.graphic.removeClass("highcharts-point-"+this.state),a&&this.graphic.addClass("highcharts-point-"+a),this.graphic.attr(f.pointAttribs(this,a)),z&&this.graphic.animate(z,b(u.options.chart.animation,n.animation,l.animation)),g&&g.hide();else{if(a&&n){l=r.symbol||f.symbol;g&&g.currentSymbol!==l&&(g=g.destroy());if(g)g[c?"animate":"attr"]({x:z.x,y:z.y});else l&&(f.stateMarkerGraphic=g=u.renderer.symbol(l, +z.x,z.y,z.width,z.height).add(f.markerGroup),g.currentSymbol=l);g&&g.attr(f.pointAttribs(this,a))}g&&(g[a&&u.isInsidePlot(d,e,u.inverted)?"show":"hide"](),g.element.point=this)}(d=k.halo)&&d.size?(v||(f.halo=v=u.renderer.path().add(A?f.markerGroup:f.group)),v[c?"animate":"attr"]({d:this.haloPath(d.size)}),v.attr({"class":"highcharts-halo highcharts-color-"+b(this.colorIndex,f.colorIndex)}),v.point=this,v.attr(t({fill:this.color||f.color,"fill-opacity":d.opacity,zIndex:-1},d.attributes))):v&&v.point&& +v.point.haloPath&&v.animate({d:v.point.haloPath(0)});this.state=a}},haloPath:function(a){return this.series.chart.renderer.symbols.circle(Math.floor(this.plotX)-a,this.plotY-a,2*a,2*a)}});t(d.prototype,{onMouseOver:function(){var a=this.chart,b=a.hoverSeries;if(b&&b!==this)b.onMouseOut();this.options.events.mouseOver&&l(this,"mouseOver");this.setState("hover");a.hoverSeries=this},onMouseOut:function(){var a=this.options,b=this.chart,c=b.tooltip,d=b.hoverPoint;b.hoverSeries=null;if(d)d.onMouseOut(); +this&&a.events.mouseOut&&l(this,"mouseOut");!c||a.stickyTracking||c.shared&&!this.noSharedTooltip||c.hide();this.setState()},setState:function(a){var c=this,d=c.options,e=c.graph,h=d.states,k=d.lineWidth,d=0;a=a||"";if(c.state!==a&&(n([c.group,c.markerGroup,c.dataLabelsGroup],function(b){b&&(c.state&&b.removeClass("highcharts-series-"+c.state),a&&b.addClass("highcharts-series-"+a))}),c.state=a,!h[a]||!1!==h[a].enabled)&&(a&&(k=h[a].lineWidth||k+(h[a].lineWidthPlus||0)),e&&!e.dashstyle))for(k={"stroke-width":k}, +e.animate(k,b(c.chart.options.chart.animation,h[a]&&h[a].animation));c["zone-graph-"+d];)c["zone-graph-"+d].attr(k),d+=1},setVisible:function(a,b){var c=this,d=c.chart,e=c.legendItem,f,h=d.options.chart.ignoreHiddenSeries,k=c.visible;f=(c.visible=a=c.options.visible=c.userOptions.visible=void 0===a?!k:a)?"show":"hide";n(["group","dataLabelsGroup","markerGroup","tracker","tt"],function(a){if(c[a])c[a][f]()});if(d.hoverSeries===c||(d.hoverPoint&&d.hoverPoint.series)===c)c.onMouseOut();e&&d.legend.colorizeItem(c, +a);c.isDirty=!0;c.options.stacking&&n(d.series,function(a){a.options.stacking&&a.visible&&(a.isDirty=!0)});n(c.linkedSeries,function(b){b.setVisible(a,!1)});h&&(d.isDirtyBox=!0);!1!==b&&d.redraw();l(c,f)},show:function(){this.setVisible(!0)},hide:function(){this.setVisible(!1)},select:function(a){this.selected=a=void 0===a?!this.selected:a;this.checkbox&&(this.checkbox.checked=a);l(this,a?"select":"unselect")},drawTracker:a.drawTrackerGraph})})(I);(function(a){var B=a.Chart,z=a.each,C=a.inArray,E= +a.isArray,u=a.isObject,h=a.pick,n=a.splat;B.prototype.setResponsive=function(h){var l=this.options.responsive,k=[],e=this.currentResponsive;l&&l.rules&&z(l.rules,function(c){void 0===c._id&&(c._id=a.uniqueKey());this.matchResponsiveRule(c,k,h)},this);var c=a.merge.apply(0,a.map(k,function(c){return a.find(l.rules,function(a){return a._id===c}).chartOptions})),k=k.toString()||void 0;k!==(e&&e.ruleIds)&&(e&&this.update(e.undoOptions,h),k?(this.currentResponsive={ruleIds:k,mergedOptions:c,undoOptions:this.currentOptions(c)}, +this.update(c,h)):this.currentResponsive=void 0)};B.prototype.matchResponsiveRule=function(a,l){var k=a.condition;(k.callback||function(){return this.chartWidth<=h(k.maxWidth,Number.MAX_VALUE)&&this.chartHeight<=h(k.maxHeight,Number.MAX_VALUE)&&this.chartWidth>=h(k.minWidth,0)&&this.chartHeight>=h(k.minHeight,0)}).call(this)&&l.push(a._id)};B.prototype.currentOptions=function(a){function h(a,c,k,l){var b,e;for(b in a)if(!l&&-1-1&&(g.splice(i,1),this.HCEvents[c]=g),this.removeEventListener?a(this,c,k):this.attachEvent&&d(this,c,k)):(b(this,c),this.HCEvents[c]=[])):(b(this),this.HCEvents={})},trigger:function(b,a){var d=this.HCEvents[b]|| +[],c=d.length,h,f;for(h=function(){a.defaultPrevented=!0};c--;){f=d[c];if(a.stopped)break;a.preventDefault=h;a.target=this;f.call(this,a)===!1&&a.preventDefault()}}});return c}var q,f=document,o=[],j=[],p,m;Math.easeInOutSine=function(c,a,d,b){return-d/2*(Math.cos(Math.PI*c/b)-1)+a};return{init:function(c){if(!f.defaultView)this._getStyle=function(a,d){var b;return a.style[d]?a.style[d]:(d==="opacity"&&(d="filter"),b=a.currentStyle[d.replace(/\-(\w)/g,function(a,b){return b.toUpperCase()})],d==="filter"&& +(b=b.replace(/alpha\(opacity=([0-9]+)\)/,function(b,a){return a/100})),b===""?1:b)},this.adapterRun=function(a,d){var b={width:"clientWidth",height:"clientHeight"}[d];if(b)return a.style.zoom=1,a[b]-2*parseInt(HighchartsAdapter._getStyle(a,"padding"),10)};if(!Array.prototype.forEach)this.each=function(a,d){for(var b=0,c=a.length;b=b.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();a=this.options.curAnim[this.prop]=!0;for(e in b.curAnim)b.curAnim[e]!== +!0&&(a=!1);a&&b.complete&&b.complete.call(this.elem);b=!1}else e=c-this.startTime,this.state=e/b.duration,this.pos=b.easing(e,0,1,b.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update(),b=!0;return b}};this.animate=function(a,d,b){var e,f="",g,i,h;a.stopAnimation=!1;if(typeof b!=="object"||b===null)e=arguments,b={duration:e[2],easing:e[3],complete:e[4]};if(typeof b.duration!=="number")b.duration=400;b.easing=Math[b.easing]||Math.easeInOutSine;b.curAnim=Highcharts.extend({},d); +for(h in d)i=new m(a,b,h),g=null,h==="d"?(i.paths=c.init(a,a.d,d.d),i.toD=d.d,e=0,g=1):a.attr?e=a.attr(h):(e=parseFloat(this._getStyle(a,h))||0,h!=="opacity"&&(f="px")),g||(g=parseFloat(d[h])),i.custom(e,g,f)}},_getStyle:function(c,a){return window.getComputedStyle(c).getPropertyValue(a)},getScript:function(c,a){var d=f.getElementsByTagName("head")[0],b=f.createElement("script");b.type="text/javascript";b.src=c;b.onload=a;d.appendChild(b)},inArray:function(c,a){return a.indexOf?a.indexOf(c):o.indexOf.call(a, +c)},adapterRun:function(c,a){return parseInt(HighchartsAdapter._getStyle(c,a),10)},grep:function(c,a){return o.filter.call(c,a)},map:function(c,a){for(var d=[],b=0,e=c.length;b' + + '
' + + '
Name (Optionnal)
' + + '
IP/Hostname
' + + '
Port
' + + '

'; + clusterDiv.setAttribute('id', 'cluster_' + cluster_id); + document.getElementById('server_form').appendChild(clusterDiv); + addServer(cluster_id); +} +function addServer(current_cluster_id) { + var serverDiv = document.createElement('div'); + server_id++; + serverDiv.innerHTML = '
' + + ' ' + + ' ' + + ' ' + + 'Delete' + '
'; + serverDiv.setAttribute('id', 'server_' + server_id); + document.getElementById('cluster_' + current_cluster_id).insertBefore(serverDiv, document.getElementById('cluster_' + current_cluster_id + '_commands')); +} +function deleteServerOrCluster(divID) { + var div = document.getElementById(divID); + div.parentNode.removeChild(div); +} +function nameOnChange(target) { + portObject = document.getElementById('port_' + target); + portObject.setAttribute("onchange", "return false;"); + hostObject = document.getElementById('host_' + target); + hostObject.setAttribute("onchange", "return false;"); +} +function hostOnFocus(object) { + if (object.value == 'hostname') { + object.value = ''; + } +} +function hostOnBlur(object) { + if (object.value == '') { + object.value = 'hostname'; + } +} +function hostOnChange(target) { + document.getElementById(target); + if (object.value == '') { + object.value = 'port'; + } +} +function portOnFocus(object) { + if (object.value == 'port') { + object.value = ''; + } +} +function portOnBlur(object) { + if (object.value == '') { + object.value = 'port'; + } +} +function hostOrPortOnChange(target) { + + nameObject = document.getElementById('name_' + target); + hostObject = document.getElementById('host_' + target); + portObject = document.getElementById('port_' + target); + if ((nameObject.value == '') || ((nameObject.value != hostObject.value + ':' + portObject.value))) { + nameObject.value = hostObject.value + ':' + portObject.value; + } +} +function ajax(url, target) { + if (window.XMLHttpRequest) { + req = new XMLHttpRequest(); + req.onreadystatechange = function() { + ajaxDone(target); + }; + req.open("GET", url, true); + req.send(null); + } else if (window.ActiveXObject) { + req = new ActiveXObject('Microsoft.XMLHTTP'); + if (req) { + req.onreadystatechange = function() { + ajaxDone(target); + }; + req.open("GET", url, true); + req.send(); + } + } + setTimeout("ajax(page, 'stats')", timeout); +} +function ajaxDone(target) { + if (req.readyState == 4) { + if (req.status == 200 || req.status == 304) { + results = req.responseText; + document.getElementById(target).innerHTML = results; + } else { + document.getElementById(target).innerHTML = "Loading stats error : " + + req.statusText; + } + } +} \ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Public/Styles/Style.css b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Public/Styles/Style.css new file mode 100644 index 00000000..a97b1a6c --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/Public/Styles/Style.css @@ -0,0 +1,238 @@ +body { + background-color: #FEFEFE; + font-family: Verdana,Tahoma,"Segoe UI", Arial; + font-size: 0.8em; + margin-top: 10px; +} + +a { + color: #EEE; + text-decoration: none; + cursor: pointer; +} + +a:hover { + color: #A00 +} + +input,select,textarea { + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; + border-width: 1px; + border-style: solid; + border-color: #AAA; + width: 298px; + font-family: Tahoma; + font-size: 1em; +} + +textarea { + width: 494px; + resize: none; +} + +select { + width: 300px; +} + +input:focus,textarea:focus { + border-width: 1px; + border-style: solid; + border-color: #EEE; +} + +input:hover { + color: #A00; +} +input[type=submit] { + cursor: pointer; +} + +img { + border: none; +} /** hr */ +hr { + height: 0; + border: none; + border-bottom-width: 1px; + border-bottom-style: solid; + border-bottom-color: #EEE; +} + +.menu { + border-width: 1px; + border-style: solid; + border-color: #a0312a; + color: #eee; + width: 198px; +} + +.item { + font-family: "Bitstream Vera Sans Mono", + "Lucida Sans Typewriter", + "DejaVu Sans Mono", + Consolas, + "Andale Mono", + "Lucida Console", + "Liberation Mono", + "Nimbus Mono L", + Monaco, + "Courier New", + Courier, + monospace; + cursor: hand; +} + +.loading { + text-decoration: blink; + visibility: hidden; +} + +.full-size { + width: 980px; +} + +.size-0 { + width: 494px; +} + +.size-1 { + width: 696px; +} + +.size-2 { + width: 398px; +} + +.size-4 { + width: 290px; +} + +.size-5 { + width: 226px; +} + +.padding { + padding: 3px 7px 3px 7px; +} + +.corner { + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; +} + +.header { + border-width: 1px; + border-style: solid; + border-color: #9c3c36; + background: #B5463F; + font-weight: bold; + color: #fff; + clear: both +} + +.sub-header { + border-width: 1px; + border-style: solid; + border-color: #514845; + background: #635855; + font-weight: bold; + color: #fff; + clear: both; + margin-top: 10px +} + +.container { + border-width: 1px; + border-style: solid; + border-color: #d0d0d0; + background: #ebebeb; + font-weight: none; + color: #000; + margin-top: 1px; + clear: both +} + +.list { + border-width: 1px; + border-style: solid; + border-color: #9c3c36; + background: #B5463F; + font-weight: bold; + color: #fff +} + +.button { + padding: 1px 20px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px +} + +.live { + font-family: "Bitstream Vera Sans Mono", + "Lucida Sans Typewriter", + "DejaVu Sans Mono", + Consolas, + "Andale Mono", + "Lucida Console", + "Liberation Mono", + "Nimbus Mono L", + Monaco, + "Courier New", + Courier, + monospace; + font-size: 12px; + overflow: visible; + white-space: pre-wrap +} + +.line { + min-height: 18px; + padding-top: 3px; + padding-bottom: 2px; + clear: both +} + +.left { + float: left; + min-width: 126px; + font-weight: bold +} +.right { + float: right +} +.setting { + min-width: 180px +} + +.slabs { + min-width: 104px +} +.help { + cursor:help; +} + +.container hr { + height: 0; + border: none; + border-bottom-width: 1px; + border-bottom-style: solid; + border-bottom-color: #fff; +} + +.grey { + color: #EEE +} + +.green { + color: #40aaba +} + +.red { + background: #b5463f; + color: #fff; + font-weight: bold +} \ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Commands/Commands.phtml b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Commands/Commands.phtml new file mode 100644 index 00000000..f663886b --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Commands/Commands.phtml @@ -0,0 +1,197 @@ +
+
Console
+
+

+        
+
+ + + + + +
+ +
Execute predefined Command
+
+ + + + + +
+
+
+ Execute command on one or all memcached servers
+
+
+
+ Command + + + +
+ + + + + +
+ Server + + + +
+
+ API + + get('get_api'), 'request_api'); ?> + +
+
+
+ +
+
+
+ Available commands : +
    +
  • get : retreive a key value
  • +
  • set : set a key/value pair
  • +
  • delete : delete a specific key
  • +
  • increment : increment a numeric key value
  • +
  • decrement : decrement a numeric key value
  • +
  • flush all : flush a Memcached server
  • +
+
+
+
+ +
Execute Telnet Commands
+
+ + + + + +
+
+ Execute telnet command on one or all memcached servers
+
+
+
+ +
+
+ Server + + + +
+
+
+ +
+
+ You can use this thing to execute any telnet command to any memcached server +
+ It will connect to the server, execute the command and return it in the console +
+
+
+
+ For more informations about memcached commands, see memcached protocol + here +
+
+ +
Search Key
+
+ + + + + +
+
+ Search for a key on one or all memcached servers
+
+
+
+ Key + + + +
+
+ Server + + + +
+
+ Detail Level + + + +
+
+ Action + + + +
+
+
+ +
+
+ Warning !
This thing is only for debuging issue, do not use it in a production environment as it can lock + or impact your memcached servers performances. +
Also keep in mind that it does not list all keys. It lists keys up to a certain buffer size (1 or 2MB), and it list key that are expired. +
+
You can also use a PCRE regular expression +
+
+
\ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Configure/Configure.phtml b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Configure/Configure.phtml new file mode 100644 index 00000000..847b5155 --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Configure/Configure.phtml @@ -0,0 +1,151 @@ +
+
+ +
Live Stats Configuration
+
+
+
+ Alert & refresh rate for Live Stats
+
+
+
+ Refresh Rate in sec + +
+
+ Memory Alert + +
+
+ Hit Rate Alert + +
+
+ Eviction Alert + +
+
+ Temp Path + +
+
+
+ +
+
+
+ +
Miscellaneous Configuration
+
+
+
+ Server connection timeout & miscellaneous
+
+
+
+ Timeout in sec + +
+
+ Max Items + +
+
+
+ +
+
+
+ +
+
+
Server List
+
+
+
+ Servers list used by phpMemcacheAdmin

+ The server name will be filled by default with hostname:port +
+
+get('servers') as $cluster => $servers) + { + $cluster_id++; ?> +
+
+ Cluster +
+
Name (Optionnal)
+
IP/Hostname
+
Port
+
+ $server) + { + $server_id++; ?> +
+
+ + + onchange="hostOrPortOnChange()" + onKeyUp="hostOrPortOnChange()" + + onfocus="hostOnFocus(this)" + onblur="hostOnBlur(this)"/> + + onchange="hostOrPortOnChange()" + onKeyUp="hostOrPortOnChange()" + + onfocus="portOnFocus(this)" + onblur="portOnBlur(this)"/> + Delete +
+
+ + +
+
+ +
+
+
+ Add New Cluster + +
+
+
+ + +
+
+ For more information about configuring phpMemcachedAdmin, see installation guide + here +
+
+
+
\ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Footer.phtml b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Footer.phtml new file mode 100644 index 00000000..9ab59bd3 --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Footer.phtml @@ -0,0 +1,18 @@ + +
+ A newer version of phpMemcachedAdmin may be available, visit PHPMemcachedAdmin Blog to know more. + + +
+ + \ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Header.phtml b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Header.phtml new file mode 100644 index 00000000..f1634411 --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Header.phtml @@ -0,0 +1,62 @@ +'; ?> + + + + PHPMemcachedAdmin <?php echo CURRENT_VERSION; ?> + + + + + +
+
PHPMemcachedAdmin +
+
+ + Live Stats | + + See Live Stats | + + Actually seeing + + See Stats for + + | + + Executing Commands on Servers + + Execute Commands on Servers + +
+get('file_path')) === false) { +?> +
+ Warning : Temporary directory 'get('file_path') ?>' is not writable, please fix this error and try again. +
+ + + diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/LiveStats/Frame.phtml b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/LiveStats/Frame.phtml new file mode 100644 index 00000000..48d3b5bc --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/LiveStats/Frame.phtml @@ -0,0 +1,70 @@ + + +
+
Live Stats
+ $_ini->get('refresh_rate')) + { ?> +
+ Connections errors were discovered, to prevent any problem, refresh rate was increased by + get('refresh_rate')); ?> seconds. +
+ +
+
+ Actually looking at stats + +
+
+        Loading live stats, please wait ~get('refresh_rate')); ?> seconds ...
+        
+
+
+
+ SIZE + Total cache size on this server +
+
+ %MEM + Percentage of total cache size used on this server +
+
+ %HIT + Global hit percent on this server : get_hits / (get_hits + get_misses) +
+
+ TIME + Time taken to connect to the server and proceed the request, high value can indicate a latency or server problem +
+
+ REQ/s + Total request per second (get, set, delete, incr, ...) issued to this server +
+
+ CONN + Current connections, monitor that this number doesn't come too close to the server max connection setting +
+
+ GET/s, SET/s, DEL/s + Get, set or delete commands per second issued to this server +
+
+ EVI/s + Number of times an item which had an explicit expire time set had to be evicted before it expired +
+
+ READ/s + Total number of bytes read by this server from network +
+
+ WRITE/s + Total number of bytes sent by this server to network +
+
+
diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/LiveStats/Stats.phtml b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/LiveStats/Stats.phtml new file mode 100644 index 00000000..f4193c3f --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/LiveStats/Stats.phtml @@ -0,0 +1,87 @@ +get('refresh_rate') . ' sec)' . EOL . EOL; + +# Table header +echo '' . sprintf('%-36s', 'NAME') . sprintf('%10s', 'SIZE') . sprintf('%7s', '%MEM') . sprintf('%8s', 'TIME') . +sprintf('%6s', 'CONN') . sprintf('%7s', '%HIT') . sprintf('%8s', 'REQ/s') . sprintf('%8s', 'GET/s') . sprintf('%8s', 'SET/s') . +sprintf('%8s', 'DEL/s') . sprintf('%8s', 'EVI/s') . sprintf('%11s', 'READ/s') . sprintf('%10s', 'WRITE/s') . '' . EOL . '
'; + +# Showing stats for every server +foreach($stats as $server => $data) +{ + # Server name + echo sprintf('%-36.36s', $server); + + # Checking for stats validity + if((isset($data['time'], $data['bytes_percent'], $data['get_hits_percent'], $data['query_time'], $data['request_rate'], $data['curr_connections'], + $data['get_rate'], $data['set_rate'], $data['delete_rate'], $data['eviction_rate'], $data['bytes_read'], $data['bytes_written'])) && ($data['time'] > 0)) + { + # Total Memory + echo sprintf('%10s', Library_Data_Analysis::byteResize($data['limit_maxbytes']) . 'b'); + + # Memory Occupation / Alert State + if($data['bytes_percent'] > $_ini->get('memory_alert')) + { + echo str_pad('', 7 - strlen($data['bytes_percent']), ' ') . '' . sprintf('%.1f', $data['bytes_percent']) . ''; + } + else + { + echo sprintf('%7.1f', $data['bytes_percent']); + } + + # Query Time + echo sprintf('%5.0f', Library_Data_Analysis::valueResize($data['query_time'])) . ' ms'; + + # Current connection + echo sprintf('%6s', $data['curr_connections']); + + # Hit percent (get) + if($data['get_hits_percent'] < $_ini->get('hit_rate_alert')) + { + echo str_pad('', 7 - strlen($data['get_hits_percent']), ' ') . '' . sprintf('%.1f', $data['get_hits_percent']) . ''; + } + else + { + echo sprintf('%7.1f', $data['get_hits_percent']); + } + + # Request rate + echo sprintf('%8s', Library_Data_Analysis::valueResize($data['request_rate'])); + + # Get rate + echo sprintf('%8s', Library_Data_Analysis::valueResize($data['get_rate'])); + + # Set rate + echo sprintf('%8s', Library_Data_Analysis::valueResize($data['set_rate'])); + + # Delete rate + echo sprintf('%8s', Library_Data_Analysis::valueResize($data['delete_rate'])); + + # Eviction rate + if($data['eviction_rate'] > $_ini->get('eviction_alert')) + { + echo str_pad('', 8 - strlen(Library_Data_Analysis::valueResize($data['eviction_rate'])), ' ') . '' . Library_Data_Analysis::valueResize($data['eviction_rate']) . ''; + } + else + { + echo sprintf('%8s', Library_Data_Analysis::valueResize($data['eviction_rate'])); + } + + # Bytes read + echo sprintf('%11s', Library_Data_Analysis::byteResize($data['bytes_read'] / $data['time']) . 'b'); + + # Bytes written + echo sprintf('%10s', Library_Data_Analysis::byteResize($data['bytes_written'] / $data['time']) . 'b'); + } + else + { + echo str_pad('', 20, ' ') . 'An error has occured when retreiving or calculating stats'; + } + + # End of Line + echo EOL . '
'; +} \ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Stats/Error.phtml b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Stats/Error.phtml new file mode 100644 index 00000000..f53f5385 --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Stats/Error.phtml @@ -0,0 +1,58 @@ + +
+ cluster($_REQUEST['server'])) ? 'All servers from Cluster ' . $_REQUEST['server'] : 'Server ' . $_REQUEST['server'], ' did not respond !'; + } + # All servers stats + else + { + echo 'Servers did not respond !'; + } ?> +
+
+ Error message +
+ +
+
+ Please check above error message, your configuration or your server status and retry +
+ +
+ No slabs used in this server ! +
+
+ Error message +
+ Maybe this server is not used, check your configuration or your server status and retry +
+ +
+ No item in this slab ! +
+
+ Error message +
+ This slab is allocated, but is empty +
+
+ Go back to Server Slabs +
+Console
+
+
+
+
+                                         Click on an item's key below to see it's content here
+
+
+
+
+ + + + + +
+ +
+ Items in Slab , only showing first get('max_item_dump'); ?> items + + Back to Server Slabs + +
+
+ $data) +{ + # Checking if first item + if($notFirst) { echo '
'; } + ?> + 70) ? substr($key, 0, 70) . '[..]' : $key); ?> + + + Size : Bytes, + Expiration : + + + +
\ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Stats/Slabs.phtml b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Stats/Slabs.phtml new file mode 100644 index 00000000..45d45208 --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Stats/Slabs.phtml @@ -0,0 +1,126 @@ +
+
Slabs Stats
+
+
+ Slabs Used + +
+
+ Memory Used + Bytes +
+
+ Wasted + Bytes +
+
+
+ + + +
+
+ For more informations about memcached slabs stats, see memcached protocol + here +
+
+ + + + $slab) +{ + # If Slab is Used + if(is_numeric($id)) + { + # Making a new line + if($actualSlab >= 4) + { +?> + + + + + +'; +} +?> + +
0) { echo 'style="padding-left:9px;"'; } ?> valign="top"> +
Slab Stats + See Slab Items +
+
+
+ Chunk Size + Bytes +
+
+ Used Chunk + + [ %] +
+
+ Total Chunk + +
+
+ Total Page + +
+
+ Wasted + Bytes +
+
+ Hits + 999) ? Library_Data_Analysis::hitResize($slab['request_rate']) : $slab['request_rate']; ?> Request/sec +
+ 0) +{ ?> +
+ Evicted + +
+ + +
+ Slab is allocated but empty +
+ +
+
\ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Stats/Stats.phtml b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Stats/Stats.phtml new file mode 100644 index 00000000..7903a17a --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/View/Stats/Stats.phtml @@ -0,0 +1,551 @@ +
+
Get Stats
+
+
+ Hits + + [%] +
+
+ Miss + + [%] +
+
+ Rate + Request/sec +
+
+ +
Set Stats
+
+
+ Total + +
+
+ Rate + Request/sec +
+
+ +
Delete Stats
+
+
+ Hits + + [%] +
+
+ Miss + + [%] +
+
+ Rate + +
+
+ +
Cas Stats
+
+
+ Hits + + [%] +
+
+ Miss + + [%] +
+
+ Bad Value + + [%] +
+
+ Rate + +
+
+ +
Increment Stats
+
+
+ Hits + + [%] +
+
+ Miss + + [%] +
+
+ Rate + +
+
+ +
Decrement Stats
+
+
+ Hits + + [%] +
+
+ Miss + + [%] +
+
+ Rate + +
+
+ +
Touch Stats
+
+
+ Hits + + [%] +
+
+ Miss + + [%] +
+
+ Rate + +
+
+ +
Flush Stats
+
+
+ Total + +
+
+ Rate + +
+
+
+ +
+server($_REQUEST['server']))) +{ ?> + + +
server($_REQUEST['server'])) ? 'Server' : 'Cluster'; ?> Stats
+
+server($_REQUEST['server']))) +{ ?> +
+ Uptime + +
+
+ Memcached + Version +
+ +
+ Curr Connections + +
+
+ Total Connections + +
+
+ Max Connections Errors + +
+
+ Current Items + +
+
+ Total Items + +
+server($_REQUEST['server']))) +{ ?> +
+ Oldest Item + +
+ +
+ +
Eviction & Reclaimed Stats
+
+
+ Items Eviction + +
+
+ Rate + Eviction/sec +
+
+ Reclaimed + +
+
+ Rate + +
+ +
+ Expired unfetched + +
+
+ Evicted unfetched + +
+
+ +server($_REQUEST['server']))) +{ ?> +
Server Configuration
+
+
+ Accepting Connections + +
+
+ Max Bytes + +
+
+ Max Connection + +
+
+ TCP/UDP Port + +
+
+ Listen Interface + +
+
+ Evictions + +
+
+ Path to Domain Socket + +
+
+ Domain Socket Umask + +
+
+ Chunk Size + +
+
+ Chunk Growth Factor + +
+
+ Max Threads + +
+
+ Detail Enabled + +
+
+ Max IO Ops/Event + +
+
+ CAS Enabled + +
+
+ TCP Listen Backlog + +
+
+ SASL Auth + +
+
+cluster($_REQUEST['server']))) +{ ?> +
Cluster Servers List
+
+ $server) + { ?> +
+ 27) ? substr($name, 0, 27) . ' [...]' : $name; ?> + See Server Stats +
+ +
+
+ 8) && ($remaining >= 0)) + { ?> +
+ + Server 1) ? 's are' : ' is'; ?> not displayed + See all Servers +
+ +
+ +
+ $stats['limit_maxbytes']) + { + $slabs['total_wasted'] = $stats['limit_maxbytes'] - ($slabs['total_malloced'] - $slabs['total_wasted']); + $slabs['total_malloced'] = $stats['limit_maxbytes']; + } + + # Making cache size stats + $wasted_percent = sprintf('%.1f', $slabs['total_wasted'] / $stats['limit_maxbytes'] * 100); + $used_percent = sprintf('%.1f', ($slabs['total_malloced'] - $slabs['total_wasted']) / $stats['limit_maxbytes'] * 100); + $free_percent = sprintf('%.1f', ($stats['limit_maxbytes'] - $slabs['total_malloced']) / $stats['limit_maxbytes'] * 100); +?> +
+
Cache Size Stats
+
+
+ Used + Bytes +
+
+ Total + Bytes +
+
+ Wasted + Bytes +
+ +
+ +
Cache Size Graphic
+
+
+ +
+server($_REQUEST['server']))) +{ ?> +
Hash Table Stats
+
+
+ Power Level + +
+
+ Size + +
+
+ Expanding + +
+
+cluster($_REQUEST['server']))) +{ ?> +
Hash Table Stats
+
+
+ Size + +
+
+ +
Slab Reassign & Automove
+
+
+ Slabs Moved + +
+
+ Reassigning + +
+
+ +
Hit & Miss Rate Graphic
+
+
+ +
+ +
Network Stats
+
+
+ Bytes Read + Bytes +
+
+ Bytes Written + Bytes +
+
+
\ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/commands.php b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/commands.php new file mode 100644 index 00000000..0a6d9e71 --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/commands.php @@ -0,0 +1,255 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * Executing commands + * + * @author elijaa@free.fr + * @since 06/04/2010 + */ +# Require +require_once 'Library/Bootstrap.php'; + +# Initializing requests & response +$request = (isset($_REQUEST['request_command'])) ? $_REQUEST['request_command'] : null; + +# Starting +ob_start(); + +# Display by request rype +switch ($request) { + # Memcache::get command + case 'get' : + # Ask for get on a cluster + if (isset($_REQUEST['request_server']) && ($cluster = $_ini->cluster($_REQUEST['request_server']))) { + foreach ($cluster as $server) { + # Dumping server get command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->get($server['hostname'], $server['port'], $_REQUEST['request_key'])); + } + } # Ask for get on one server + elseif (isset($_REQUEST['request_server']) && ($server = $_ini->server($_REQUEST['request_server']))) { + # Dumping server get command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->get($server['hostname'], $server['port'], $_REQUEST['request_key'])); + } # Ask for get on all servers + else { + foreach ($_ini->get('servers') as $cluster => $servers) { + # Asking for each server stats + foreach ($servers as $server) { + # Dumping server get command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->get($server['hostname'], $server['port'], $_REQUEST['request_key'])); + } + } + } + break; + + # Memcache::set command + case 'set' : + # Ask for set on a cluster + if (isset($_REQUEST['request_server']) && ($cluster = $_ini->cluster($_REQUEST['request_server']))) { + foreach ($cluster as $server) { + # Dumping server get command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->set($server['hostname'], $server['port'], $_REQUEST['request_key'], $_REQUEST['request_data'], $_REQUEST['request_duration'])); + } + } # Ask for set on one server + elseif (isset($_REQUEST['request_server']) && ($server = $_ini->server($_REQUEST['request_server']))) { + # Dumping server set command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->set($server['hostname'], $server['port'], $_REQUEST['request_key'], $_REQUEST['request_data'], $_REQUEST['request_duration'])); + } # Ask for set on all servers + else { + foreach ($_ini->get('servers') as $cluster => $servers) { + # Asking for each server stats + foreach ($servers as $server) { + # Dumping server set command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->set($server['hostname'], $server['port'], $_REQUEST['request_key'], $_REQUEST['request_data'], $_REQUEST['request_duration'])); + } + } + } + break; + + # Memcache::delete command + case 'delete' : + # Ask for delete on a cluster + if (isset($_REQUEST['request_server']) && ($cluster = $_ini->cluster($_REQUEST['request_server']))) { + foreach ($cluster as $server) { + # Dumping server get command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->delete($server['hostname'], $server['port'], $_REQUEST['request_key'])); + } + } # Ask for delete on one server + elseif (isset($_REQUEST['request_server']) && ($server = $_ini->server($_REQUEST['request_server']))) { + # Dumping server delete command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->delete($server['hostname'], $server['port'], $_REQUEST['request_key'])); + } # Ask for delete on all servers + else { + foreach ($_ini->get('servers') as $cluster => $servers) { + # Asking for each server stats + foreach ($servers as $server) { + # Dumping server delete command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->delete($server['hostname'], $server['port'], $_REQUEST['request_key'])); + } + } + } + break; + + # Memcache::increment command + case 'increment' : + # Checking value + if (! isset($_REQUEST['request_value']) || ! is_numeric($_REQUEST['request_value'])) { + $_REQUEST['request_value'] = 1; + } + + # Ask for increment on a cluster + if (isset($_REQUEST['request_server']) && ($cluster = $_ini->cluster($_REQUEST['request_server']))) { + foreach ($cluster as $server) { + # Dumping server increment command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->increment($server['hostname'], $server['port'], $_REQUEST['request_key'], $_REQUEST['request_value'])); + } + } # Ask for increment on one server + elseif (isset($_REQUEST['request_server']) && ($server = $_ini->server($_REQUEST['request_server']))) { + # Dumping server increment command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->increment($server['hostname'], $server['port'], $_REQUEST['request_key'], $_REQUEST['request_value'])); + } # Ask for increment on all servers + else { + foreach ($_ini->get('servers') as $cluster => $servers) { + # Asking for each server stats + foreach ($servers as $server) { + # Dumping server increment command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->increment($server['hostname'], $server['port'], $_REQUEST['request_key'], $_REQUEST['request_value'])); + } + } + } + break; + + # Memcache::decrement command + case 'decrement' : + # Checking value + if (! isset($_REQUEST['request_value']) || ! is_numeric($_REQUEST['request_value'])) { + $_REQUEST['request_value'] = 1; + } + + # Ask for decrement on a cluster + if (isset($_REQUEST['request_server']) && ($cluster = $_ini->cluster($_REQUEST['request_server']))) { + foreach ($cluster as $server) { + # Dumping server decrement command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->decrement($server['hostname'], $server['port'], $_REQUEST['request_key'], $_REQUEST['request_value'])); + } + } # Ask for decrement on one server + elseif (isset($_REQUEST['request_server']) && ($server = $_ini->server($_REQUEST['request_server']))) { + # Dumping server decrement command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->decrement($server['hostname'], $server['port'], $_REQUEST['request_key'], $_REQUEST['request_value'])); + } # Ask for decrement on all servers + else { + foreach ($_ini->get('servers') as $cluster => $servers) { + # Asking for each server stats + foreach ($servers as $server) { + # Dumping server decrement command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->decrement($server['hostname'], $server['port'], $_REQUEST['request_key'], $_REQUEST['request_value'])); + } + } + } + break; + + # Memcache::flush_all command + case 'flush_all' : + # Checking delay + if (! isset($_REQUEST['request_delay']) || ! is_numeric($_REQUEST['request_delay'])) { + $_REQUEST['request_delay'] = 0; + } + + # Ask for flush_all on a cluster + if (isset($_REQUEST['request_server']) && ($cluster = $_ini->cluster($_REQUEST['request_server']))) { + foreach ($cluster as $server) { + # Dumping server get command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->flush_all($server['hostname'], $server['port'], $_REQUEST['request_delay'])); + } + } # Ask for flush_all on one server + elseif (isset($_REQUEST['request_server']) && ($server = $_ini->server($_REQUEST['request_server']))) { + # Dumping server flush_all command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->flush_all($server['hostname'], $server['port'], $_REQUEST['request_delay'])); + } # Ask for flush_all on all servers + else { + foreach ($_ini->get('servers') as $cluster => $servers) { + # Asking for each server stats + foreach ($servers as $server) { + # Dumping server flush_all command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api($_REQUEST['request_api'])->flush_all($server['hostname'], $server['port'], $_REQUEST['request_delay'])); + } + } + } + break; + + # Memcache::search command + case 'search' : + # Ask for search on a cluster + if (isset($_REQUEST['request_server']) && ($cluster = $_ini->cluster($_REQUEST['request_server']))) { + foreach ($cluster as $server) { + # Dumping server get command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api('Server')->search($server['hostname'], $server['port'], $_REQUEST['request_key'], $_REQUEST['request_level'], $_REQUEST['request_more'])); + } + } # Ask for search on one server + elseif (isset($_REQUEST['request_server']) && ($server = $_ini->server($_REQUEST['request_server']))) { + # Dumping server search command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api('Server')->search($server['hostname'], $server['port'], $_REQUEST['request_key'], $_REQUEST['request_level'], $_REQUEST['request_more'])); + } # Ask for search on all servers + else { + # Looking into each cluster + foreach ($_ini->get('servers') as $cluster => $servers) { + # Asking for each server stats + foreach ($servers as $server) { + # Dumping server search command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api('Server')->search($server['hostname'], $server['port'], $_REQUEST['request_key'], $_REQUEST['request_level'], $_REQUEST['request_more'])); + } + } + } + break; + + # Memcache::telnet command + case 'telnet' : + # Ask for a telnet command on a cluster + if (isset($_REQUEST['request_server']) && ($cluster = $_ini->cluster($_REQUEST['request_server']))) { + foreach ($cluster as $server) { + # Dumping server telnet command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api('Server')->telnet($server['hostname'], $server['port'], $_REQUEST['request_telnet'])); + } + } # Ask for a telnet command on one server + elseif (isset($_REQUEST['request_server']) && ($server = $_ini->server($_REQUEST['request_server']))) { + # Dumping server telnet command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api('Server')->telnet($server['hostname'], $server['port'], $_REQUEST['request_telnet'])); + } # Ask for a telnet command on all servers + else { + # Looking into each cluster + foreach ($_ini->get('servers') as $cluster => $servers) { + # Asking for each server stats + foreach ($servers as $server) { + # Dumping server telnet command response + echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'], Library_Command_Factory::api('Server')->telnet($server['hostname'], $server['port'], $_REQUEST['request_telnet'])); + } + } + } + break; + # Default : No command + default : + # Showing header + include 'View/Header.phtml'; + + # Showing formulary + include 'View/Commands/Commands.phtml'; + + # Showing footer + include 'View/Footer.phtml'; + break; +} + +ob_end_flush(); \ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/index.php b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/index.php new file mode 100644 index 00000000..881b4118 --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/index.php @@ -0,0 +1,141 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * Stats viewing + * + * @author elijaa@free.fr + * @since 20/03/2010 + */ +# Require +require_once 'Library/Bootstrap.php'; + +# Initializing requests +$request = (isset($_REQUEST['show'])) ? $_REQUEST['show'] : null; + +# Getting default cluster +if (! isset($_REQUEST['server'])) { + $clusters = array_keys($_ini->get('servers')); + $cluster = isset($clusters[0]) ? $clusters[0] : null; + $_REQUEST['server'] = $cluster; +} + +# Showing header +include 'View/Header.phtml'; + +# Display by request type +switch ($request) { + # Items : Display of all items for a single slab for a single server + case 'items' : + # Initializing items array + $server = null; + $items = false; + + # Ask for one server and one slabs items + if (isset($_REQUEST['server']) && ($server = $_ini->server($_REQUEST['server']))) { + $items = Library_Command_Factory::instance('items_api')->items($server['hostname'], $server['port'], $_REQUEST['slab']); + } + + # Getting stats to calculate server boot time + $stats = Library_Command_Factory::instance('stats_api')->stats($server['hostname'], $server['port']); + $infinite = (isset($stats['time'], $stats['uptime'])) ? ($stats['time'] - $stats['uptime']) : 0; + + # Items are well formed + if ($items !== false) { + # Showing items + include 'View/Stats/Items.phtml'; + } # Items are not well formed + else { + include 'View/Stats/Error.phtml'; + } + unset($items); + break; + + # Slabs : Display of all slabs for a single server + case 'slabs' : + # Initializing slabs array + $slabs = false; + + # Ask for one server slabs + if (isset($_REQUEST['server']) && ($server = $_ini->server($_REQUEST['server']))) { + # Spliting server in hostname:port + $slabs = Library_Command_Factory::instance('slabs_api')->slabs($server['hostname'], $server['port']); + } + + # Slabs are well formed + if ($slabs !== false) { + # Analysis + $slabs = Library_Data_Analysis::slabs($slabs); + include 'View/Stats/Slabs.phtml'; + } # Slabs are not well formed + else { + include 'View/Stats/Error.phtml'; + } + unset($slabs); + break; + + # Default : Stats for all or specific single server + default : + # Initializing stats & settings array + $stats = array(); + $slabs = array(); + $slabs['total_malloced'] = 0; + $slabs['total_wasted'] = 0; + $settings = array(); + $status = array(); + + $cluster = null; + $server = null; + + # Ask for a particular cluster stats + if (isset($_REQUEST['server']) && ($cluster = $_ini->cluster($_REQUEST['server']))) { + foreach ($cluster as $name => $server) { + # Getting Stats & Slabs stats + $data = array(); + $data['stats'] = Library_Command_Factory::instance('stats_api')->stats($server['hostname'], $server['port']); + $data['slabs'] = Library_Data_Analysis::slabs(Library_Command_Factory::instance('slabs_api')->slabs($server['hostname'], $server['port'])); + $stats = Library_Data_Analysis::merge($stats, $data['stats']); + + # Computing stats + if (isset($data['slabs']['total_malloced'], $data['slabs']['total_wasted'])) { + $slabs['total_malloced'] += $data['slabs']['total_malloced']; + $slabs['total_wasted'] += $data['slabs']['total_wasted']; + } + $status[$name] = ($data['stats'] != array()) ? $data['stats']['version'] : ''; + $uptime[$name] = ($data['stats'] != array()) ? $data['stats']['uptime'] : ''; + } + } # Asking for a server stats + elseif (isset($_REQUEST['server']) && ($server = $_ini->server($_REQUEST['server']))) { + # Getting Stats & Slabs stats + $stats = Library_Command_Factory::instance('stats_api')->stats($server['hostname'], $server['port']); + $slabs = Library_Data_Analysis::slabs(Library_Command_Factory::instance('slabs_api')->slabs($server['hostname'], $server['port'])); + $settings = Library_Command_Factory::instance('stats_api')->settings($server['hostname'], $server['port']); + } + + # Stats are well formed + if (($stats !== false) && ($stats != array())) { + # Analysis + $stats = Library_Data_Analysis::stats($stats); + include 'View/Stats/Stats.phtml'; + } # Stats are not well formed + else { + include 'View/Stats/Error.phtml'; + } + unset($stats); + break; +} +# Showing footer +include 'View/Footer.phtml'; \ No newline at end of file diff --git a/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/spam.php b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/spam.php new file mode 100644 index 00000000..bd18dad5 --- /dev/null +++ b/.devilbox/www/htdocs/vendor/phpmemcachedadmin-1.3.0/spam.php @@ -0,0 +1,13 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * Live Stats top style + * + * @author Cyrille Mahieux : elijaa(at)free.fr + * @since 12/04/2010 + */ +# Require +require_once 'Library/Bootstrap.php'; + +# Initializing requests +$request = (isset($_REQUEST['request_command'])) ? $_REQUEST['request_command'] : null; + +# Stat of a particular cluster +if (isset($_REQUEST['cluster']) && ($_REQUEST['cluster'] != null)) { + $cluster = $_REQUEST['cluster']; +} else { + # Getting default cluster + $clusters = array_keys($_ini->get('servers')); + $cluster = isset($clusters[0]) ? $clusters[0] : null; + $_REQUEST['cluster'] = $cluster; +} + +# Checking writing status in temporary folder +if (is_writable($_ini->get('file_path')) === false) { + # Trying to change permissions + chmod($_ini->get('file_path'), 0775); +} + +# Hashing cluster +$hash = md5($_REQUEST['cluster']); + +# Cookie @FIXME not a perfect method +if (! isset($_COOKIE['live_stats_id' . $hash])) { + # Cleaning temporary directory + $files = glob($_ini->get('file_path') . '*', GLOB_NOSORT); + foreach ($files as $path) { + # Getting file last modification time + $stats = @stat($path); + + # Deleting file older than 24 hours + if (isset($stats['mtime']) && ($stats['mtime'] < (time() - 60 * 60 * 24))) { + @unlink($path); + } + } + + # Generating unique id + $live_stats_id = rand() . $hash; + + # Cookie + setcookie('live_stats_id' . $hash, $live_stats_id, time() + 60 * 60 * 24); +} else { + # Backup from a previous request + $live_stats_id = $_COOKIE['live_stats_id' . $hash]; +} + +# Live stats dump file +$file_path = rtrim($_ini->get('file_path'), '/') . DIRECTORY_SEPARATOR . 'live_stats.' . $live_stats_id; + +# Display by request type +switch ($request) { + # Ajax ask : stats + case 'live_stats' : + # Opening old stats dump + $previous = @unserialize(file_get_contents($file_path)); + + # Initializing variables + $actual = array(); + $stats = array(); + $time = 0; + + # Requesting stats for each server + foreach ($_ini->cluster($cluster) as $name => $server) { + # Start query time calculation + $time = microtime(true); + + # Asking server for stats + $actual[$name] = Library_Command_Factory::instance('stats_api')->stats($server['hostname'], $server['port']); + + # Calculating query time length + $actual[$name]['query_time'] = max((microtime(true) - $time) * 1000, 1); + } + + # Analysing stats + foreach ($_ini->cluster($cluster) as $name => $server) { + # Making an alias @FIXME Used ? + $server = $name; + + # Diff between old and new dump + $stats[$server] = Library_Data_Analysis::diff($previous[$server], $actual[$server]); + } + + # Making stats for each server + foreach ($stats as $server => $array) { + # Analysing request + if ((isset($stats[$server]['uptime'])) && ($stats[$server]['uptime'] > 0)) { + # Computing stats + $stats[$server] = Library_Data_Analysis::stats($stats[$server]); + + # Because we make a diff on every key, we must reasign some values + $stats[$server]['bytes_percent'] = sprintf('%.1f', $actual[$server]['bytes'] / $actual[$server]['limit_maxbytes'] * 100); + $stats[$server]['bytes'] = $actual[$server]['bytes']; + $stats[$server]['limit_maxbytes'] = $actual[$server]['limit_maxbytes']; + $stats[$server]['curr_connections'] = $actual[$server]['curr_connections']; + $stats[$server]['query_time'] = $actual[$server]['query_time']; + } + } + + # Saving new stats dump + file_put_contents($file_path, serialize($actual)); + + # Showing stats + include 'View/LiveStats/Stats.phtml'; + break; + + # Default : No command + default : + # Initializing : making stats dump + $stats = array(); + foreach ($_ini->cluster($cluster) as $name => $server) { + $stats[$name] = Library_Command_Factory::instance('stats_api')->stats($server['hostname'], $server['port']); + } + + # Saving first stats dump + file_put_contents($file_path, serialize($stats)); + + # Searching for connection error, adding some time to refresh rate to prevent error + $refresh_rate = max($_ini->get('refresh_rate'), count($_ini->cluster($cluster)) * 0.25 + (Library_Data_Error::count() * (0.5 + $_ini->get('connection_timeout')))); + + # Showing header + include 'View/Header.phtml'; + + # Showing live stats frame + include 'View/LiveStats/Frame.phtml'; + + # Showing footer + include 'View/Footer.phtml'; + + break; +} \ No newline at end of file diff --git a/.devilbox/www/include/lib/Html.php b/.devilbox/www/include/lib/Html.php index 3c089d1b..db6d1cd2 100644 --- a/.devilbox/www/include/lib/Html.php +++ b/.devilbox/www/include/lib/Html.php @@ -104,6 +104,11 @@ class Html 'path' => '/vendor/phpredmin/public/index.php', 'target' => '_blank' ), + array( + 'name' => 'PHPMemcachedAdmin', + 'path' => '/vendor/phpmemcachedadmin-1.3.0/index.php', + 'target' => '_blank' + ), array( 'name' => 'Opcache GUI', 'path' => '/opcache.php'