From bdf227442ddb38a8b60d03efe09b6c5ed04bf89a Mon Sep 17 00:00:00 2001 From: oldperl Date: Mon, 14 Nov 2011 14:21:22 +0000 Subject: [PATCH] edit: phpdoc stuff add: pChart lib - no more usage of google api. There has to be the wp-content/cache writable for images add: test-folder for later use new: class agents, new isBot-functionality within this class, old function is deprecated, uses an ini-file with botnames --- trunk/includes/class.agents.php | 207 + trunk/includes/data/uas_20110628-02.ini | 11077 ++++++++++++++++ trunk/includes/functions.semr.php | 207 +- trunk/includes/functions.semr_template.php | 18 + trunk/includes/pChart/GPLv3.txt | 675 + trunk/includes/pChart/change.log | Bin 0 -> 24242 bytes .../pChart/class/pBarcode128.class.php | 184 + .../pChart/class/pBarcode39.class.php | 200 + trunk/includes/pChart/class/pBubble.class.php | 326 + trunk/includes/pChart/class/pCache.class.php | 280 + trunk/includes/pChart/class/pData.class.php | 787 ++ trunk/includes/pChart/class/pDraw.class.php | 6193 +++++++++ trunk/includes/pChart/class/pImage.class.php | 472 + .../pChart/class/pIndicator.class.php | 241 + trunk/includes/pChart/class/pPie.class.php | 1500 +++ trunk/includes/pChart/class/pRadar.class.php | 681 + .../includes/pChart/class/pScatter.class.php | 1158 ++ trunk/includes/pChart/class/pSplit.class.php | 131 + trunk/includes/pChart/class/pSpring.class.php | 868 ++ trunk/includes/pChart/class/pStock.class.php | 216 + .../includes/pChart/class/pSurface.class.php | 315 + trunk/includes/pChart/data/128B.db | 107 + trunk/includes/pChart/data/39.db | 44 + trunk/includes/pChart/fonts/Bedizen.ttf | Bin 0 -> 42912 bytes trunk/includes/pChart/fonts/Forgotte.ttf | Bin 0 -> 42148 bytes trunk/includes/pChart/fonts/GeosansLight.ttf | Bin 0 -> 60072 bytes trunk/includes/pChart/fonts/MankSans.ttf | Bin 0 -> 58492 bytes trunk/includes/pChart/fonts/Silkscreen.ttf | Bin 0 -> 16172 bytes trunk/includes/pChart/fonts/advent_light.ttf | Bin 0 -> 45768 bytes trunk/includes/pChart/fonts/calibri.ttf | Bin 0 -> 811052 bytes trunk/includes/pChart/fonts/pf_arma_five.ttf | Bin 0 -> 21936 bytes trunk/includes/pChart/fonts/verdana.ttf | Bin 0 -> 189144 bytes trunk/includes/pChart/index.php | 6 + trunk/includes/pChart/palettes/autumn.color | 6 + trunk/includes/pChart/palettes/blind.color | 6 + trunk/includes/pChart/palettes/evening.color | 6 + trunk/includes/pChart/palettes/kitchen.color | 6 + trunk/includes/pChart/palettes/light.color | 7 + trunk/includes/pChart/palettes/navy.color | 6 + trunk/includes/pChart/palettes/shade.color | 6 + trunk/includes/pChart/palettes/spring.color | 6 + trunk/includes/pChart/palettes/summer.color | 6 + trunk/includes/pChart/readme.txt | Bin 0 -> 11944 bytes trunk/semmelstatzR-database.php | 102 +- trunk/semmelstatzR-history.php | 267 +- trunk/semmelstatzR-log.php | 48 +- trunk/semmelstatzR-options.php | 62 +- trunk/semmelstatzR-statz.php | 118 +- trunk/semmelstatzR-templates.php | 48 +- trunk/semmelstatzR.php | 15 +- trunk/semmelstatzR_startup.php | 47 +- trunk/semr_image.php | 39 +- trunk/test/agents.php | 5 + 53 files changed, 26319 insertions(+), 380 deletions(-) create mode 100644 trunk/includes/class.agents.php create mode 100644 trunk/includes/data/uas_20110628-02.ini create mode 100644 trunk/includes/pChart/GPLv3.txt create mode 100644 trunk/includes/pChart/change.log create mode 100644 trunk/includes/pChart/class/pBarcode128.class.php create mode 100644 trunk/includes/pChart/class/pBarcode39.class.php create mode 100644 trunk/includes/pChart/class/pBubble.class.php create mode 100644 trunk/includes/pChart/class/pCache.class.php create mode 100644 trunk/includes/pChart/class/pData.class.php create mode 100644 trunk/includes/pChart/class/pDraw.class.php create mode 100644 trunk/includes/pChart/class/pImage.class.php create mode 100644 trunk/includes/pChart/class/pIndicator.class.php create mode 100644 trunk/includes/pChart/class/pPie.class.php create mode 100644 trunk/includes/pChart/class/pRadar.class.php create mode 100644 trunk/includes/pChart/class/pScatter.class.php create mode 100644 trunk/includes/pChart/class/pSplit.class.php create mode 100644 trunk/includes/pChart/class/pSpring.class.php create mode 100644 trunk/includes/pChart/class/pStock.class.php create mode 100644 trunk/includes/pChart/class/pSurface.class.php create mode 100644 trunk/includes/pChart/data/128B.db create mode 100644 trunk/includes/pChart/data/39.db create mode 100644 trunk/includes/pChart/fonts/Bedizen.ttf create mode 100644 trunk/includes/pChart/fonts/Forgotte.ttf create mode 100644 trunk/includes/pChart/fonts/GeosansLight.ttf create mode 100644 trunk/includes/pChart/fonts/MankSans.ttf create mode 100644 trunk/includes/pChart/fonts/Silkscreen.ttf create mode 100644 trunk/includes/pChart/fonts/advent_light.ttf create mode 100644 trunk/includes/pChart/fonts/calibri.ttf create mode 100644 trunk/includes/pChart/fonts/pf_arma_five.ttf create mode 100644 trunk/includes/pChart/fonts/verdana.ttf create mode 100644 trunk/includes/pChart/index.php create mode 100644 trunk/includes/pChart/palettes/autumn.color create mode 100644 trunk/includes/pChart/palettes/blind.color create mode 100644 trunk/includes/pChart/palettes/evening.color create mode 100644 trunk/includes/pChart/palettes/kitchen.color create mode 100644 trunk/includes/pChart/palettes/light.color create mode 100644 trunk/includes/pChart/palettes/navy.color create mode 100644 trunk/includes/pChart/palettes/shade.color create mode 100644 trunk/includes/pChart/palettes/spring.color create mode 100644 trunk/includes/pChart/palettes/summer.color create mode 100644 trunk/includes/pChart/readme.txt create mode 100644 trunk/test/agents.php diff --git a/trunk/includes/class.agents.php b/trunk/includes/class.agents.php new file mode 100644 index 0000000..f4cb741 --- /dev/null +++ b/trunk/includes/class.agents.php @@ -0,0 +1,207 @@ +. + * + * $Id$ + * + */ + +class Agents { + + private $_sAgent; + + private $_aBots = array( + 'aipbot', + 'amfibibot', + 'appie', + 'ask jeeves/teoma', + 'aspseek', + 'axadine', + 'baiduspider', + 'becomebot', + 'blogcorpuscrawler', + 'blogpulse', + 'blogsnowbot', + 'boitho.com', + 'bruinbot', + 'cerberian', + 'cfnetwork', + 'check_http', + 'cipinetbot', + 'claymont', + 'cometsearch@cometsystems.com', + 'converacrawler', + 'cydralspider', + 'digger', + 'es.net_crawler', + 'eventax', + 'everyfeed-spider', + 'exabot@exava.com', + 'faxobot', + 'findlinks', + 'fireball', + 'francis', + 'gaisbot', + 'gamekitbot', + 'gazz@nttr.co.jp', + 'geonabot', + 'getrax crawler', + 'gigabot', + 'girafa.com', + 'goforitbot', + 'googlebot', + 'grub-client', + 'holmes', + 'houxoucrawler', + 'http://www.almaden.ibm.com/cs/crawler', + 'http://www.istarthere.com', + 'http://www.relevantnoise.com', + 'httrack ?', + 'ia_archiver', + 'ichiro', + 'iltrovatore-setaccio', + 'inelabot', + 'infoseek', + 'inktomi.com', + 'irlbot', + 'jetbot', + 'jobspider_ba', + 'kazoombot', + 'larbin', + 'libwww', + 'linkwalker', + 'lmspider', + 'mackster', + 'mediapartners-google', + 'microsoft url control', + 'mj12bot', + 'moreoverbot', + 'mozdex', + 'msnbot', + 'msrbot', + 'naverbot', + 'netresearchserver', + 'ng/2.0', + 'np(bot)', + 'nutch', + 'objectssearch', + 'ocelli', + 'omniexplorer_bot', + 'openbot', + 'overture', + 'patwebbot', + 'php', + 'phpdig', + 'pilgrim html-crawler', + 'pipeliner', + 'pompos', + 'psbot', + 'python-urllib', + 'quepasacreep', + 'robozilla', + 'rpt-httpclient', + 'savvybot', + 'scooter', + 'search.ch', + 'seekbot', + 'semager', + 'seznambot', + 'sherlock', + 'shelob', + 'sitesearch', + 'snapbot', + 'snappreviewbot', + 'speedy spider', + 'sphere scout', + 'stackrambler', + 'steeler', + 'surveybot', + 'szukacz', + 'technoratibot', + 'telnet', + 'themiragorobot', + 'thesubot', + 'thumbshots-de-bot', + 'topicblogs', + 'turnitinbot', + 'tutorgigbot', + 'tutorial crawler', + 'twiceler', + 'vagabondo', + 'versus', + 'voilabot', + 'w3c_css_validator', + 'w3c_validator', + 'w3c-checklink', + 'web downloader', + 'webcopier', + 'webcrawler', + 'webfilter robot', + 'west wind internet protocols', + 'wget', + 'wwweasel robot', + 'wwwster', + 'xaldon webspider', + 'xenu', + 'yahoo! slurp', + 'yahoofeedseeker', + 'yahoo-mmcrawler', + 'zao', + 'zipppbot', + 'zyborg', + ); + + public function __construct($sAgent = null) { + if(!is_null($sAgent)) { + $this->_sAgent = $sAgent; + } + $this->_getIniFile(); + } + + public function isBot($sAgent = null) { + if(is_null($sAgent) && empty($this->_sAgent)) return false; + $sAgent = (is_null($sAgent))?$this->_sAgent:$sAgent; + + foreach($this->_aBots as $bot) { + if(stristr($sAgent, $bot) !== false) { + return true; + } + } + return false; + } + + private function _getIniFile($sFile = null) { + if(is_null($sFile)) $sFile = dirname(__FILE__)."/data/uas_20110628-02.ini"; // default ini + + if(is_file($sFile) && is_readable($sFile)) { + $aTmpIni = parse_ini_file($sFile, true); + $this->_aBots = array(); + foreach($aTmpIni['robots'] as $value) { + $this->_aBots[] = $value[2]; + } + //print_r($this->_aBots); + } + } +} +?> diff --git a/trunk/includes/data/uas_20110628-02.ini b/trunk/includes/data/uas_20110628-02.ini new file mode 100644 index 0000000..6befacf --- /dev/null +++ b/trunk/includes/data/uas_20110628-02.ini @@ -0,0 +1,11077 @@ +; Data (format ini) for UASparser - http://user-agent-string.info/download/UASparser +; Version: 20110628-02 +; Checksum: +; MD5 - http://user-agent-string.info/rpc/get_data.php?format=ini&md5=y +; SHA1 - http://user-agent-string.info/rpc/get_data.php?format=ini&sha1=y +; +[robots] +; bot_id[] = "bot useragentstring" +; bot_id[] = "bot Family" +; bot_id[] = "bot Name" +; bot_id[] = "bot URL" +; bot_id[] = "bot Company" +; bot_id[] = "bot Company URL" +; bot_id[] = "bot ico" +; bot_id[] = "bot OS id" +; bot_id[] = "bot info URL" +1490[] = "192.comAgent" +1490[] = "192.comAgent" +1490[] = "192.comAgent" +1490[] = "http://www.192.com/support/web-crawler.cfm" +1490[] = "i-CD Publishing (UK) Limited" +1490[] = "http://www.icdpublishing.co.uk/" +1490[] = "bot.png" +1490[] = "" +1490[] = "/list-of-ua/bot-detail?bot=192.comAgent" +1773[] = "50.nu/0.01 ( +http://50.nu/bot.html )" +1773[] = "50.nu" +1773[] = "50.nu/0.01" +1773[] = "http://50.nu/bot.html" +1773[] = "Innovate it" +1773[] = "http://innovateit.com/" +1773[] = "bot.png" +1773[] = "" +1773[] = "/list-of-ua/bot-detail?bot=50.nu" +1633[] = "Mozilla/5.0 (compatible; 80bot/0.71; http://www.80legs.com/spider.html;) Gecko/2008032620" +1633[] = "80legs" +1633[] = "80legs/0.71" +1633[] = "http://www.80legs.com/webcrawler.html" +1633[] = "Computational Crawling, LP " +1633[] = "http://compucrawl.com/" +1633[] = "bot.png" +1633[] = "" +1633[] = "/list-of-ua/bot-detail?bot=80legs" +1871[] = "Mozilla/5.0 (compatible; 008/0.83; http://www.80legs.com/spider.html;) Gecko/2008032620" +1871[] = "80legs" +1871[] = "80legs/0.83" +1871[] = "http://www.80legs.com/webcrawler.html" +1871[] = "Computational Crawling, LP" +1871[] = "http://compucrawl.com/" +1871[] = "bot.png" +1871[] = "" +1871[] = "/list-of-ua/bot-detail?bot=80legs" +5311[] = "Mozilla/5.0 (compatible; 008/0.83; http://www.80legs.com/webcrawler.html;) Gecko/2008032620" +5311[] = "80legs" +5311[] = "80legs/0.83 b" +5311[] = "http://www.80legs.com/webcrawler.html" +5311[] = "Computational Crawling, LP" +5311[] = "http://compucrawl.com/" +5311[] = "bot.png" +5311[] = "" +5311[] = "/list-of-ua/bot-detail?bot=80legs" +3422[] = "Mozilla/5.0 (compatible; abby/1.0; +http://www.ellerdale.com/crawler.html)" +3422[] = "abby" +3422[] = "abby/1.0" +3422[] = "http://www.ellerdale.com/crawler.html" +3422[] = "Ellerdale Inc." +3422[] = "http://www.ellerdale.com/" +3422[] = "bot_abby.png" +3422[] = "" +3422[] = "/list-of-ua/bot-detail?bot=abby" +1941[] = "AboutUsBot" +1941[] = "AboutUsBot" +1941[] = "AboutUsBot" +1941[] = "http://www.aboutus.org/AboutUs:Bot" +1941[] = "AboutUs, Inc. " +1941[] = "http://www.aboutus.org/AboutUs.org" +1941[] = "bot_AboutUsBot.png" +1941[] = "" +1941[] = "/list-of-ua/bot-detail?bot=AboutUsBot" +1735[] = "Mozilla/5.0 (compatible; AboutUsBot/0.9; +http://www.aboutus.org/AboutUsBot)" +1735[] = "AboutUsBot" +1735[] = "AboutUsBot/0.9" +1735[] = "http://www.aboutus.org/AboutUs:Bot" +1735[] = "AboutUs, Inc." +1735[] = "http://www.aboutus.org/AboutUs.org" +1735[] = "bot_AboutUsBot.png" +1735[] = "" +1735[] = "/list-of-ua/bot-detail?bot=AboutUsBot" +5077[] = "Mozilla/5.0 (compatible; AboutUsBot Johnny5/2.0; +http://www.AboutUs.org/)" +5077[] = "AboutUsBot" +5077[] = "AboutUsBot Johnny5/2.0" +5077[] = "http://www.aboutus.org/AboutUs:Bot" +5077[] = "AboutUs, Inc." +5077[] = "http://www.aboutus.org/AboutUs.org" +5077[] = "bot_AboutUsBot.png" +5077[] = "" +5077[] = "/list-of-ua/bot-detail?bot=AboutUsBot" +6246[] = "Abrave Spider v4 Robot 1 (http://robot.abrave.co.uk)" +6246[] = "Abrave Spider" +6246[] = "Abrave Spider/4-1" +6246[] = "http://robot.abrave.co.uk/" +6246[] = "Gallent Limited" +6246[] = "http://www.gallent.co.uk/" +6246[] = "bot.png" +6246[] = "" +6246[] = "/list-of-ua/bot-detail?bot=Abrave Spider" +6247[] = "Abrave Spider v4 Robot 2 (http://robot.abrave.co.uk)" +6247[] = "Abrave Spider" +6247[] = "Abrave Spider/4-2" +6247[] = "http://robot.abrave.co.uk/" +6247[] = "Gallent Limited" +6247[] = "http://www.gallent.co.uk/" +6247[] = "bot.png" +6247[] = "" +6247[] = "/list-of-ua/bot-detail?bot=Abrave Spider" +892[] = "Accelobot" +892[] = "Accelobot" +892[] = "Accelobot" +892[] = "http://www.accelobot.com/" +892[] = "Accelovation, Inc." +892[] = "http://www.accelovation.com/" +892[] = "bot.png" +892[] = "" +892[] = "/list-of-ua/bot-detail?bot=Accelobot" +162[] = "Accoona-AI-Agent/1.1.1 (crawler at accoona dot com)" +162[] = "Accoona-AI-Agent" +162[] = "Accoona-AI-Agent/1.1.1" +162[] = "" +162[] = "Accoona Corp." +162[] = "http://accoona.com/" +162[] = "bot_accoona-ai-agent.png" +162[] = "" +162[] = "/list-of-ua/bot-detail?bot=Accoona-AI-Agent" +512[] = "Accoona-AI-Agent/1.1.2 (aicrawler at accoonabot dot com)" +512[] = "Accoona-AI-Agent" +512[] = "Accoona-AI-Agent/1.1.2" +512[] = "" +512[] = "Accoona Corp." +512[] = "" +512[] = "bot_accoona-ai-agent.png" +512[] = "" +512[] = "/list-of-ua/bot-detail?bot=Accoona-AI-Agent" +1273[] = "Acoon-Robot 4.0.0RC2 (http://www.acoon.de)" +1273[] = "Acoon-Robot" +1273[] = "Acoon-Robot 4.0.0RC2" +1273[] = "" +1273[] = "Acoon GmbH" +1273[] = "http://www.acoon.com/" +1273[] = "bot.png" +1273[] = "" +1273[] = "/list-of-ua/bot-detail?bot=Acoon-Robot" +1282[] = "Acoon-Robot 4.0.1 (http://www.acoon.de)" +1282[] = "Acoon-Robot" +1282[] = "Acoon-Robot 4.0.1" +1282[] = "" +1282[] = "Acoon GmbH" +1282[] = "http://www.acoon.com/" +1282[] = "bot.png" +1282[] = "" +1282[] = "/list-of-ua/bot-detail?bot=Acoon-Robot" +1287[] = "Acoon-Robot 4.0.2 (http://www.acoon.de)" +1287[] = "Acoon-Robot" +1287[] = "Acoon-Robot 4.0.2" +1287[] = "" +1287[] = "Acoon GmbH" +1287[] = "http://www.acoon.com/" +1287[] = "bot.png" +1287[] = "" +1287[] = "/list-of-ua/bot-detail?bot=Acoon-Robot" +1297[] = "Acoon-Robot 4.0.2.17 (http://www.acoon.de)" +1297[] = "Acoon-Robot" +1297[] = "Acoon-Robot 4.0.2.17" +1297[] = "" +1297[] = "Acoon GmbH" +1297[] = "http://www.acoon.com/" +1297[] = "bot.png" +1297[] = "" +1297[] = "/list-of-ua/bot-detail?bot=Acoon-Robot" +1685[] = "OpenAcoon v4.1.0 (www.openacoon.de)" +1685[] = "Acoon-Robot" +1685[] = "OpenAcoon v4.1.0" +1685[] = "http://www.openacoon.de/" +1685[] = "Acoon GmbH" +1685[] = "http://www.acoon.com/" +1685[] = "bot.png" +1685[] = "" +1685[] = "/list-of-ua/bot-detail?bot=Acoon-Robot" +829[] = "Acorn/Nutch-0.9 (Non-Profit Search Engine; acorn.isara.org; acorn at isara dot org)" +829[] = "Acorn" +829[] = "Acorn/Nutch-0.9" +829[] = "http://acorn.isara.org/" +829[] = "Isara" +829[] = "http://www.isara.org/" +829[] = "bot.png" +829[] = "" +829[] = "/list-of-ua/bot-detail?bot=Acorn" +494[] = "www.adressendeutschland.de" +494[] = "adressendeutschland.de" +494[] = "adressendeutschland.de" +494[] = "http://www.adressendeutschland.de/konzept.html" +494[] = "http://www.arktosmedia.de/" +494[] = "Arktos MEDIA GmbH" +494[] = "bot.png" +494[] = "" +494[] = "/list-of-ua/bot-detail?bot=adressendeutschland.de" +676[] = "AdsBot-Google (+http://www.google.com/adsbot.html)" +676[] = "AdsBot-Google" +676[] = "AdsBot-Google" +676[] = "http://www.google.com/adsbot.html" +676[] = "Google Inc." +676[] = "http://www.google.com/" +676[] = "bot.png" +676[] = "" +676[] = "/list-of-ua/bot-detail?bot=AdsBot-Google" +715[] = "AdsBot-Google" +715[] = "AdsBot-Google" +715[] = "AdsBot-Google b" +715[] = "http://www.google.com/adsbot.html" +715[] = "Google Inc." +715[] = "http://www.google.com/" +715[] = "bot.png" +715[] = "" +715[] = "/list-of-ua/bot-detail?bot=AdsBot-Google" +2102[] = "Mozilla/5.0 (compatible; aiHitBot-DM/2.0.2 +http://www.aihit.com)" +2102[] = "aiHitBot" +2102[] = "aiHitBot-DM/2.0.2" +2102[] = "" +2102[] = "aiHit Ltd." +2102[] = "http://www.aihit.com/" +2102[] = "bot.png" +2102[] = "" +2102[] = "/list-of-ua/bot-detail?bot=aiHitBot" +2188[] = "Mozilla/5.0 (compatible; aiHitBot/1.0-DS; +http://www.aihit.com/)" +2188[] = "aiHitBot" +2188[] = "aiHitBot/1.0-DS" +2188[] = "" +2188[] = "aiHit Ltd." +2188[] = "http://www.aihit.com/" +2188[] = "bot.png" +2188[] = "" +2188[] = "/list-of-ua/bot-detail?bot=aiHitBot" +2223[] = "Mozilla/5.0 (compatible; aiHitBot/1.0; +http://www.aihit.com/)" +2223[] = "aiHitBot" +2223[] = "aiHitBot/1.0" +2223[] = "" +2223[] = "aiHit Ltd." +2223[] = "http://www.aihit.com/" +2223[] = "bot.png" +2223[] = "" +2223[] = "/list-of-ua/bot-detail?bot=aiHitBot" +89[] = "appie 1.1 (www.walhello.com)" +89[] = "aippie" +89[] = "appie 1.1" +89[] = "http://www.walhello.com/aboutgl.html" +89[] = "Walhello.com" +89[] = "http://www.walhello.com/" +89[] = "bot.png" +89[] = "" +89[] = "/list-of-ua/bot-detail?bot=aippie" +1555[] = "Mozilla/5.0 (compatible; akula/k311; +http://k311.fd.cvut.cz/)" +1555[] = "akula" +1555[] = "akula/k311" +1555[] = "http://k311.fd.cvut.cz/" +1555[] = "ÄŒVUT Fakulta dopravní" +1555[] = "http://www.fd.cvut.cz/" +1555[] = "bot.png" +1555[] = "" +1555[] = "/list-of-ua/bot-detail?bot=akula" +1550[] = "Mozilla/5.0 (compatible; akula/12.0rc-2; +http://k311.fd.cvut.cz/)" +1550[] = "akula" +1550[] = "akula/12.0rc-2" +1550[] = "http://k311.fd.cvut.cz/" +1550[] = "ÄŒVUT Fakulta dopravní" +1550[] = "http://www.fd.cvut.cz/" +1550[] = "bot.png" +1550[] = "" +1550[] = "/list-of-ua/bot-detail?bot=akula" +90[] = "http://www.almaden.ibm.com/cs/crawler [bc22]" +90[] = "Almaden" +90[] = "Almaden bc22" +90[] = "http://www.almaden.ibm.com/cs/crawler/" +90[] = "IBM Almaden Research Center" +90[] = "http://www.almaden.ibm.com/" +90[] = "bot.png" +90[] = "" +90[] = "/list-of-ua/bot-detail?bot=Almaden" +148[] = "http://www.almaden.ibm.com/cs/crawler [hc4]" +148[] = "Almaden" +148[] = "Almaden hc4" +148[] = "http://www.almaden.ibm.com/cs/crawler/" +148[] = "IBM Almaden Research Center" +148[] = "http://www.almaden.ibm.com/" +148[] = "bot.png" +148[] = "" +148[] = "/list-of-ua/bot-detail?bot=Almaden" +214[] = "http://www.almaden.ibm.com/cs/crawler [bc14]" +214[] = "Almaden" +214[] = "Almaden bc14" +214[] = "http://www.almaden.ibm.com/cs/crawler/" +214[] = "IBM Almaden Research Center" +214[] = "http://www.almaden.ibm.com/" +214[] = "bot.png" +214[] = "" +214[] = "/list-of-ua/bot-detail?bot=Almaden" +236[] = "http://www.almaden.ibm.com/cs/crawler [bc5]" +236[] = "Almaden" +236[] = "Almaden bc5" +236[] = "http://www.almaden.ibm.com/cs/crawler/" +236[] = "IBM Almaden Research Center" +236[] = "http://www.almaden.ibm.com/" +236[] = "bot.png" +236[] = "" +236[] = "/list-of-ua/bot-detail?bot=Almaden" +278[] = "http://www.almaden.ibm.com/cs/crawler [fc13]" +278[] = "Almaden" +278[] = "Almaden fc13" +278[] = "http://www.almaden.ibm.com/cs/crawler/" +278[] = "IBM Almaden Research Center" +278[] = "http://www.almaden.ibm.com/" +278[] = "bot.png" +278[] = "" +278[] = "/list-of-ua/bot-detail?bot=Almaden" +394[] = "http://www.almaden.ibm.com/cs/crawler [bc6]" +394[] = "Almaden" +394[] = "Almaden bc6" +394[] = "http://www.almaden.ibm.com/cs/crawler/" +394[] = "IBM Almaden Research Center" +394[] = "http://www.almaden.ibm.com/" +394[] = "bot.png" +394[] = "" +394[] = "/list-of-ua/bot-detail?bot=Almaden" +471[] = "http://www.almaden.ibm.com/cs/crawler [bc12]" +471[] = "Almaden" +471[] = "Almaden bc12" +471[] = "http://www.almaden.ibm.com/cs/crawler/" +471[] = "IBM Almaden Research Center" +471[] = "http://www.almaden.ibm.com/" +471[] = "bot.png" +471[] = "" +471[] = "/list-of-ua/bot-detail?bot=Almaden" +671[] = "http://www.almaden.ibm.com/cs/crawler" +671[] = "Almaden" +671[] = "Almaden" +671[] = "http://www.almaden.ibm.com/cs/crawler/" +671[] = "IBM Almaden Research Center" +671[] = "http://www.almaden.ibm.com/" +671[] = "bot.png" +671[] = "" +671[] = "/list-of-ua/bot-detail?bot=Almaden" +1849[] = "http://www.amagit.com/" +1849[] = "Amagit.COM" +1849[] = "Amagit.COM" +1849[] = "" +1849[] = "Joshua Schwarz" +1849[] = "http://contacts.joshuaschwarz.com/" +1849[] = "bot.png" +1849[] = "" +1849[] = "/list-of-ua/bot-detail?bot=Amagit.COM" +128[] = "Amfibibot/0.07 (Amfibi Robot; http://www.amfibi.com; agent@amfibi.com)" +128[] = "Amfibibot" +128[] = "Amfibibot/0.07" +128[] = "http://www.amfibi.com/" +128[] = "Barcelona Internet Telecom" +128[] = "http://www.bcntelecom.com/" +128[] = "bot.png" +128[] = "" +128[] = "/list-of-ua/bot-detail?bot=Amfibibot" +2110[] = "amibot - http://www.amidalla.de - tech@amidalla.com libwww-perl/5.831" +2110[] = "amibot" +2110[] = "amibot" +2110[] = "http://www.amidalla.de/info.htm" +2110[] = "amidalla.de" +2110[] = "http://www.amidalla.de/" +2110[] = "bot_amibot.png" +2110[] = "" +2110[] = "/list-of-ua/bot-detail?bot=amibot" +5623[] = "Mozilla/5.0 (compatible; AntBot/1.0; +http://www.ant.com/)" +5623[] = "AntBot" +5623[] = "AntBot/1.0" +5623[] = "" +5623[] = "Ant.com" +5623[] = "http://www.ant.com/" +5623[] = "bot_AntBot.png" +5623[] = "" +5623[] = "/list-of-ua/bot-detail?bot=AntBot" +3236[] = "Mozilla/5.0 (compatible; AportWorm/3.2; +http://www.aport.ru/help)" +3236[] = "AportWorm" +3236[] = "AportWorm/3.2" +3236[] = "http://www.aport.ru/help/" +3236[] = "Golden Telecom" +3236[] = "http://goldentelecom.ru/" +3236[] = "bot.png" +3236[] = "" +3236[] = "/list-of-ua/bot-detail?bot=AportWorm" +2057[] = "http://arachnode.net 1.2" +2057[] = "arachnode.net" +2057[] = "arachnode.net/1.2" +2057[] = "http://arachnode.codeplex.com/" +2057[] = "arachnode.net, llc" +2057[] = "http://arachnode.net/" +2057[] = "bot.png" +2057[] = "" +2057[] = "/list-of-ua/bot-detail?bot=arachnode.net" +6237[] = "http://arachnode.net 2.5" +6237[] = "arachnode.net" +6237[] = "arachnode.net/2.5" +6237[] = "http://arachnode.codeplex.com/" +6237[] = "arachnode.net, llc" +6237[] = "http://arachnode.net/" +6237[] = "bot.png" +6237[] = "" +6237[] = "/list-of-ua/bot-detail?bot=arachnode.net" +5272[] = "Mozilla/5.0 (compatible; archive.org_bot +http://www.archive.org/details/archive.org_bot)" +5272[] = "archive.org_bot" +5272[] = "archive.org_bot" +5272[] = "http://www.archive.org/details/archive.org_bot" +5272[] = "Internet Archive" +5272[] = "http://www.archive.org/" +5272[] = "bot.png" +5272[] = "" +5272[] = "/list-of-ua/bot-detail?bot=archive.org_bot" +1042[] = "ASAHA Search Engine Turkey V.001 (http://www.asaha.com/)" +1042[] = "ASAHA Search Engine Turkey" +1042[] = "ASAHA Search Engine Turkey V.001" +1042[] = "http://www.asaha.com/beta/" +1042[] = "asaha.com" +1042[] = "http://www.asaha.com/" +1042[] = "bot.png" +1042[] = "" +1042[] = "/list-of-ua/bot-detail?bot=ASAHA Search Engine Turkey" +37[] = "Mozilla/2.0 (compatible; Ask Jeeves/Teoma; +http://sp.ask.com/docs/about/tech_crawling.html)" +37[] = "Ask Jeeves/Teoma" +37[] = "Ask Jeeves/Teoma - b" +37[] = "http://about.ask.com/en/docs/about/webmasters.shtml" +37[] = "Ask Jeeves Inc." +37[] = "http://about.ask.com/en/docs/about/index.shtml" +37[] = "bot_AskJeeves.png" +37[] = "" +37[] = "/list-of-ua/bot-detail?bot=Ask Jeeves/Teoma" +131[] = "Mozilla/2.0 (compatible; Ask Jeeves/Teoma)" +131[] = "Ask Jeeves/Teoma" +131[] = "Ask Jeeves/Teoma" +131[] = "http://about.ask.com/en/docs/about/webmasters.shtml" +131[] = "Ask Jeeves Inc." +131[] = "http://about.ask.com/en/docs/about/index.shtml" +131[] = "bot_AskJeeves.png" +131[] = "" +131[] = "/list-of-ua/bot-detail?bot=Ask Jeeves/Teoma" +411[] = "Mozilla/2.0 (compatible; Ask Jeeves/Teoma; +http://about.ask.com/en/docs/about/webmasters.shtml)" +411[] = "Ask Jeeves/Teoma" +411[] = "Ask Jeeves/Teoma - c" +411[] = "http://about.ask.com/en/docs/about/webmasters.shtml" +411[] = "Ask Jeeves Inc." +411[] = "http://about.ask.com/en/docs/about/index.shtml" +411[] = "bot_AskJeeves.png" +411[] = "" +411[] = "/list-of-ua/bot-detail?bot=Ask Jeeves/Teoma" +694[] = "Mozilla/5.0 (compatible; Ask Jeeves/Teoma; +http://about.ask.com/en/docs/about/webmasters.shtml)" +694[] = "Ask Jeeves/Teoma" +694[] = "Ask Jeeves/Teoma" +694[] = "http://about.ask.com/en/docs/about/webmasters.shtml" +694[] = "Ask Jeeves Inc." +694[] = "http://about.ask.com/en/docs/about/index.shtml" +694[] = "bot_AskJeeves.png" +694[] = "" +694[] = "/list-of-ua/bot-detail?bot=Ask Jeeves/Teoma" +890[] = "Mozilla/2.0 (compatible; Ask Jeeves/Teoma; http://about.ask.com/en/docs/about/webmasters.shtml)" +890[] = "Ask Jeeves/Teoma" +890[] = "Ask Jeeves/Teoma - d" +890[] = "http://about.ask.com/en/docs/about/webmasters.shtml" +890[] = "Ask Jeeves Inc." +890[] = "http://about.ask.com/en/docs/about/index.shtml" +890[] = "bot_AskJeeves.png" +890[] = "" +890[] = "/list-of-ua/bot-detail?bot=Ask Jeeves/Teoma" +2050[] = "BabalooSpider/1.3 (BabalooSpider; http://www.babaloo.si; spider@babaloo.si)" +2050[] = "BabalooSpider" +2050[] = "BabalooSpider/1.3" +2050[] = "" +2050[] = "Babaloo d.o.o." +2050[] = "http://www.babaloo.si/" +2050[] = "bot_BabalooSpider.png" +2050[] = "" +2050[] = "/list-of-ua/bot-detail?bot=BabalooSpider" +6231[] = "BacklinkCrawler (http://www.backlinktest.com/crawler.html)" +6231[] = "BacklinkCrawler" +6231[] = "BacklinkCrawler" +6231[] = "http://www.backlinktest.com/crawler.html" +6231[] = "2.0Promotion GbR" +6231[] = "http://2.0promotion.de/" +6231[] = "bot.png" +6231[] = "" +6231[] = "/list-of-ua/bot-detail?bot=BacklinkCrawler" +14[] = "Baiduspider+(+http://www.baidu.com/search/spider.htm)" +14[] = "Baiduspider" +14[] = "Baiduspider" +14[] = "http://www.baidu.com/search/spider.htm" +14[] = "Baidu" +14[] = "http://www.baidu.com/" +14[] = "bot_baiduspider.png" +14[] = "" +14[] = "/list-of-ua/bot-detail?bot=Baiduspider" +1474[] = "Baiduspider+(+http://www.baidu.jp/spider/)" +1474[] = "Baiduspider" +1474[] = "Baiduspider japan" +1474[] = "" +1474[] = "Baidu Japan Inc" +1474[] = "http://www.baidu.jp/" +1474[] = "bot_baiduspider.png" +1474[] = "" +1474[] = "/list-of-ua/bot-detail?bot=Baiduspider" +2125[] = "baypup/colbert (Baypup; http://sf.baypup.com/webmasters; jason@baypup.com)" +2125[] = "baypup" +2125[] = "baypup/colbert" +2125[] = "http://www.baypup.com/webmasters" +2125[] = "Flatland Industries, Inc." +2125[] = "http://www.flatlandindustries.com/" +2125[] = "bot_Baypup.png" +2125[] = "" +2125[] = "/list-of-ua/bot-detail?bot=baypup" +1770[] = "baypup/1.1 (Baypup; http://www.baypup.com/; jason@baypup.com)" +1770[] = "baypup" +1770[] = "baypup/1.1" +1770[] = "" +1770[] = "Flatland Industries, Inc." +1770[] = "http://www.flatlandindustries.com/" +1770[] = "bot_Baypup.png" +1770[] = "" +1770[] = "/list-of-ua/bot-detail?bot=baypup" +2162[] = "baypup/colbert (Baypup; http://www.baypup.com/webmasters; jason@baypup.com)" +2162[] = "baypup" +2162[] = "baypup/colbert" +2162[] = "http://www.baypup.com/webmasters" +2162[] = "Flatland Industries, Inc." +2162[] = "http://www.flatlandindustries.com/" +2162[] = "bot_Baypup.png" +2162[] = "" +2162[] = "/list-of-ua/bot-detail?bot=baypup" +2063[] = "BDFetch" +2063[] = "BDFetch" +2063[] = "BDFetch" +2063[] = "" +2063[] = "BDProtect Inc." +2063[] = "http://www.brandprotect.com/" +2063[] = "bot_BDFetch.png" +2063[] = "" +2063[] = "/list-of-ua/bot-detail?bot=BDFetch" +285[] = "Mozilla/5.0 (compatible; BecomeBot/2.3; MSIE 6.0 compatible; +http://www.become.com/site_owners.html)" +285[] = "BecomeBot" +285[] = "BecomeBot/2.3" +285[] = "http://www.become.com/site_owners.html" +285[] = "Become, Inc." +285[] = "http://www.become.com/" +285[] = "bot_becomebot.png" +285[] = "" +285[] = "/list-of-ua/bot-detail?bot=BecomeBot" +360[] = "Mozilla/5.0 (compatible; BecomeBot/3.0; MSIE 6.0 compatible; +http://www.become.com/site_owners.html)" +360[] = "BecomeBot" +360[] = "BecomeBot/3.0" +360[] = "http://www.become.com/site_owners.html" +360[] = "Become, Inc." +360[] = "http://www.become.com/" +360[] = "bot_becomebot.png" +360[] = "" +360[] = "/list-of-ua/bot-detail?bot=BecomeBot" +566[] = "Mozilla/5.0 (compatible; BecomeBot/3.0; +http://www.become.com/site_owners.html)" +566[] = "BecomeBot" +566[] = "BecomeBot/3.0 b" +566[] = "http://www.become.com/site_owners.html" +566[] = "Become, Inc." +566[] = "http://www.become.com/" +566[] = "bot.png" +566[] = "" +566[] = "/list-of-ua/bot-detail?bot=BecomeBot" +712[] = "Mozilla/5.0 (compatible; BecomeJPBot/2.3; MSIE 6.0 compatible; +http://www.become.co.jp/site_owners.html)" +712[] = "BecomeBot" +712[] = "BecomeBot/2.3 b" +712[] = "http://www.become.com/site_owners.html" +712[] = "Become, Inc." +712[] = "http://www.become.com/" +712[] = "bot.png" +712[] = "" +712[] = "/list-of-ua/bot-detail?bot=BecomeBot" +602[] = "Bigsearch.ca/Nutch-0.9-dev (Bigsearch.ca Internet Spider; http://www.bigsearch.ca/; info@enhancededge.com)" +602[] = "Bigsearch.ca" +602[] = "Bigsearch.ca/Nutch-0.9-dev" +602[] = "" +602[] = "bigsearch.ca" +602[] = "http://www.bigsearch.ca/" +602[] = "bot.png" +602[] = "" +602[] = "/list-of-ua/bot-detail?bot=Bigsearch.ca" +789[] = "Bigsearch.ca/Nutch-1.0-dev (Bigsearch.ca Internet Spider; http://www.bigsearch.ca/; info@enhancededge.com)" +789[] = "Bigsearch.ca" +789[] = "Bigsearch.ca/Nutch-1.0-dev" +789[] = "" +789[] = "bigsearch.ca" +789[] = "http://www.bigsearch.ca/" +789[] = "bot.png" +789[] = "" +789[] = "/list-of-ua/bot-detail?bot=Bigsearch.ca" +5357[] = "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)" +5357[] = "bingbot" +5357[] = "bingbot/2.0" +5357[] = "http://www.bing.com/bingbot.htm" +5357[] = "Microsoft Corporation" +5357[] = "http://www.microsoft.com/" +5357[] = "bot_msnbot.png" +5357[] = "" +5357[] = "/list-of-ua/bot-detail?bot=bingbot" +2022[] = "bitlybot" +2022[] = "bitlybot" +2022[] = "bitlybot" +2022[] = "http://code.google.com/p/bitly-bot/" +2022[] = "Rahul Garg" +2022[] = "http://www.google.com/profiles/mr.rahulgarg" +2022[] = "bot.png" +2022[] = "" +2022[] = "/list-of-ua/bot-detail?bot=bitlybot" +4733[] = "Mozilla/5.0 (compatible; bixolabs/1.0; +http://bixolabs.com/crawler/general; crawler@bixolabs.com)" +4733[] = "bixolabs" +4733[] = "bixolabs/1.0" +4733[] = "http://bixolabs.com/crawler/general/" +4733[] = "Bixo Labs" +4733[] = "http://bixolabs.com/" +4733[] = "bot.png" +4733[] = "" +4733[] = "/list-of-ua/bot-detail?bot=bixolabs" +5238[] = "Mozilla/5.0 (compatible; bixolabs/1.0; +http://bixolabs.com/crawler/general; crawler@mail.bixolabs.com)" +5238[] = "bixolabs" +5238[] = "bixolabs/1.0 b" +5238[] = "http://bixolabs.com/crawler/general/" +5238[] = "Bixo Labs" +5238[] = "http://bixolabs.com/" +5238[] = "bot.png" +5238[] = "" +5238[] = "/list-of-ua/bot-detail?bot=bixolabs" +548[] = "Blaiz-Bee/2.00.5622 (+http://www.blaiz.net)" +548[] = "Blaiz-Bee" +548[] = "Blaiz-Bee/2.00.5622" +548[] = "http://www.rawgrunt.com/index.html" +548[] = "Blaiz Enterprises" +548[] = "http://www.blaiz.net/" +548[] = "bot.png" +548[] = "" +548[] = "/list-of-ua/bot-detail?bot=Blaiz-Bee" +580[] = "Blaiz-Bee/2.00.5655 (+http://www.blaiz.net)" +580[] = "Blaiz-Bee" +580[] = "Blaiz-Bee/2.00.5655" +580[] = "http://www.rawgrunt.com/index.html" +580[] = "Blaiz Enterprises" +580[] = "http://www.blaiz.net/" +580[] = "bot.png" +580[] = "" +580[] = "/list-of-ua/bot-detail?bot=Blaiz-Bee" +665[] = "Blaiz-Bee/2.00.6082 (+http://www.blaiz.net)" +665[] = "Blaiz-Bee" +665[] = "Blaiz-Bee/2.00.6082" +665[] = "http://www.rawgrunt.com/index.html" +665[] = "Blaiz Enterprises" +665[] = "" +665[] = "bot.png" +665[] = "" +665[] = "/list-of-ua/bot-detail?bot=Blaiz-Bee" +749[] = "Blaiz-Bee/2.00.8315 (BE Internet Search Engine http://www.rawgrunt.com)" +749[] = "Blaiz-Bee" +749[] = "Blaiz-Bee/2.00.8315" +749[] = "http://www.rawgrunt.com/index.html" +749[] = "Blaiz Enterprises" +749[] = "" +749[] = "bot.png" +749[] = "" +749[] = "/list-of-ua/bot-detail?bot=Blaiz-Bee" +4519[] = "Mozilla/5.0 (compatible; BlinkaCrawler/1.0; +http://www.blinka.jp/crawler/)" +4519[] = "BlinkaCrawler" +4519[] = "BlinkaCrawler/1.0" +4519[] = "http://www.blinka.jp/crawler/" +4519[] = "Blinka project" +4519[] = "http://www.blinka.jp/" +4519[] = "bot.png" +4519[] = "" +4519[] = "/list-of-ua/bot-detail?bot=BlinkaCrawler" +1726[] = "Bloggsi/1.0 (http://bloggsi.com/)" +1726[] = "Bloggsi" +1726[] = "Bloggsi/1.0" +1726[] = "http://bloggsi.com/" +1726[] = "Stefan Fischerländer" +1726[] = "" +1726[] = "bot.png" +1726[] = "" +1726[] = "/list-of-ua/bot-detail?bot=Bloggsi" +1637[] = "BlogPulseLive (support@blogpulse.com)" +1637[] = "BlogPulse" +1637[] = "BlogPulseLive" +1637[] = "http://www.blogpulse.com/" +1637[] = "Nielsen Company" +1637[] = "http://www.nielsen-online.com/" +1637[] = "bot.png" +1637[] = "" +1637[] = "/list-of-ua/bot-detail?bot=BlogPulse" +1754[] = "BlogPulse (ISSpider-3.0)" +1754[] = "BlogPulse" +1754[] = "BlogPulse" +1754[] = "http://www.blogpulse.com/" +1754[] = "Nielsen Company" +1754[] = "http://www.nielsen-online.com/" +1754[] = "bot.png" +1754[] = "" +1754[] = "/list-of-ua/bot-detail?bot=BlogPulse" +146[] = "boitho.com-dc/0.83 ( http://www.boitho.com/dcbot.html )" +146[] = "boitho.com-dc" +146[] = "boitho.com-dc/0.83" +146[] = "http://www.boitho.com/dcbot.html" +146[] = "Boitho" +146[] = "http://www.boitho.com/" +146[] = "bot.png" +146[] = "" +146[] = "/list-of-ua/bot-detail?bot=boitho.com-dc" +328[] = "boitho.com-dc/0.79 ( http://www.boitho.com/dcbot.html )" +328[] = "boitho.com-dc" +328[] = "boitho.com-dc/0.79" +328[] = "http://www.boitho.com/dcbot.html" +328[] = "Boitho" +328[] = "http://www.boitho.com/" +328[] = "bot.png" +328[] = "" +328[] = "/list-of-ua/bot-detail?bot=boitho.com-dc" +456[] = "boitho.com-dc/0.85 ( http://www.boitho.com/dcbot.html )" +456[] = "boitho.com-dc" +456[] = "boitho.com-dc/0.85" +456[] = "http://www.boitho.com/dcbot.html" +456[] = "Boitho" +456[] = "http://www.boitho.com/" +456[] = "bot.png" +456[] = "" +456[] = "/list-of-ua/bot-detail?bot=boitho.com-dc" +833[] = "boitho.com-dc/0.86 ( http://www.boitho.com/dcbot.html )" +833[] = "boitho.com-dc" +833[] = "boitho.com-dc/0.86" +833[] = "http://www.boitho.com/dcbot.html" +833[] = "Boitho" +833[] = "http://www.boitho.com/" +833[] = "bot.png" +833[] = "" +833[] = "/list-of-ua/bot-detail?bot=boitho.com-dc" +1479[] = "boitho.com-dc/0.82 ( http://www.boitho.com/dcbot.html )" +1479[] = "boitho.com-dc" +1479[] = "boitho.com-dc/0.82" +1479[] = "http://www.boitho.com/dcbot.html" +1479[] = "Boitho" +1479[] = "http://www.boitho.com/" +1479[] = "bot.png" +1479[] = "" +1479[] = "/list-of-ua/bot-detail?bot=boitho.com-dc" +1733[] = "Nokia6680/1.0 (4.04.07) SymbianOS/8.0 Series60/2.6 Profile/MIDP-2.0 Configuration/CLDC-1.1 (botmobi find.mobi/bot.html find@mtld.mobi)" +1733[] = "botmobi" +1733[] = "botmobi" +1733[] = "http://find.mobi/bot.html" +1733[] = "mTLD, Ltd." +1733[] = "http://mtld.mobi/" +1733[] = "bot.png" +1733[] = "" +1733[] = "/list-of-ua/bot-detail?bot=botmobi" +1753[] = "BotOnParade, http://www.bots-on-para.de/bot.html" +1753[] = "BotOnParade" +1753[] = "BotOnParade" +1753[] = "http://www.bots-on-para.de/bot.html" +1753[] = "Angus Internetmarketing" +1753[] = "http://www.angus.co.uk/" +1753[] = "bot.png" +1753[] = "" +1753[] = "/list-of-ua/bot-detail?bot=BotOnParade" +1752[] = "Browsershots" +1752[] = "Browsershots" +1752[] = "Browsershots" +1752[] = "http://trac.browsershots.org/wiki/PrivacyPolicy" +1752[] = "Browsershots.org" +1752[] = "http://browsershots.org/" +1752[] = "bot.png" +1752[] = "" +1752[] = "/list-of-ua/bot-detail?bot=Browsershots" +237[] = "btbot/0.4 (+http://www.btbot.com/btbot.html)" +237[] = "btbot" +237[] = "btbot/0.4" +237[] = "http://www.btbot.com/btbot.html" +237[] = "btbot.com" +237[] = "http://www.btbot.com/" +237[] = "bot.png" +237[] = "" +237[] = "/list-of-ua/bot-detail?bot=btbot" +1516[] = "Mozilla/5.0 (compatible; Butterfly/1.0; +http://labs.topsy.com/butterfly.html) Gecko/2009032608 Firefox/3.0.8" +1516[] = "Butterfly" +1516[] = "Butterfly/1.0" +1516[] = "http://labs.topsy.com/butterfly.html" +1516[] = "Topsy Labs" +1516[] = "http://labs.topsy.com/" +1516[] = "bot.png" +1516[] = "" +1516[] = "/list-of-ua/bot-detail?bot=Butterfly" +5100[] = "Mozilla/5.0 (compatible; Butterfly/1.0; +http://labs.topsy.com/butterfly/) Gecko/2009032608 Firefox/3.0.8" +5100[] = "Butterfly" +5100[] = "Butterfly/1.0 a" +5100[] = "http://labs.topsy.com/butterfly.html" +5100[] = "Topsy Labs" +5100[] = "http://labs.topsy.com/" +5100[] = "bot.png" +5100[] = "" +5100[] = "/list-of-ua/bot-detail?bot=Butterfly" +817[] = "Mozilla/5.0 (compatible; BuzzRankingBot/1.0; +http://www.buzzrankingbot.com/)" +817[] = "BuzzRankingBot" +817[] = "BuzzRankingBot/1.0" +817[] = "http://www.buzzrankingbot.com/" +817[] = "Matthieu Aubry" +817[] = "http://giik.net/" +817[] = "bot.png" +817[] = "" +817[] = "/list-of-ua/bot-detail?bot=BuzzRankingBot" +4939[] = "CamontSpider/1.0 +http://epweb2.ph.bham.ac.uk/user/slater/camont/info.html" +4939[] = "CamontSpider" +4939[] = "CamontSpider/1.0" +4939[] = "http://epweb2.ph.bham.ac.uk/user/slater/camont/info.html" +4939[] = "Camtology consortium" +4939[] = "http://www.hep.phy.cam.ac.uk/~parker/camtology/about.html" +4939[] = "bot.png" +4939[] = "" +4939[] = "/list-of-ua/bot-detail?bot=CamontSpider" +1481[] = "CatchBot/1.0; +http://www.catchbot.com" +1481[] = "CatchBot" +1481[] = "CatchBot/1.0" +1481[] = "http://www.catchbot.com/" +1481[] = "Reed Business Information Pty Limited" +1481[] = "http://www.reedbusiness.com/" +1481[] = "bot_CatchBot.png" +1481[] = "" +1481[] = "/list-of-ua/bot-detail?bot=CatchBot" +5665[] = "CatchBot/3.0; +http://www.catchbot.com" +5665[] = "CatchBot" +5665[] = "CatchBot/3.0" +5665[] = "http://www.catchbot.com/" +5665[] = "Reed Business Information Pty Limited" +5665[] = "http://www.reedbusiness.com/" +5665[] = "bot_CatchBot.png" +5665[] = "" +5665[] = "/list-of-ua/bot-detail?bot=CatchBot" +4977[] = "CatchBot/2.0; +http://www.catchbot.com" +4977[] = "CatchBot" +4977[] = "CatchBot/2.0" +4977[] = "http://www.catchbot.com/" +4977[] = "Reed Business Information Pty Limited" +4977[] = "http://www.reedbusiness.com/" +4977[] = "bot_CatchBot.png" +4977[] = "" +4977[] = "/list-of-ua/bot-detail?bot=CatchBot" +499[] = "Cazoodle/Nutch-0.9-dev (Cazoodle Nutch Crawler; http://www.cazoodle.com; mqbot@cazoodle.com)" +499[] = "CazoodleBot" +499[] = "CazoodleBot a" +499[] = "http://www.cazoodle.com/cazoodlebot.php" +499[] = "Cazoodle Inc." +499[] = "http://www.cazoodle.com/" +499[] = "bot.png" +499[] = "" +499[] = "/list-of-ua/bot-detail?bot=CazoodleBot" +588[] = "CazoodleBot/Nutch-0.9-dev (CazoodleBot Crawler; http://www.cazoodle.com; mqbot@cazoodle.com)" +588[] = "CazoodleBot" +588[] = "CazoodleBot d" +588[] = "http://www.cazoodle.com/cazoodlebot.php" +588[] = "Cazoodle Inc." +588[] = "http://www.cazoodle.com/" +588[] = "bot.png" +588[] = "" +588[] = "/list-of-ua/bot-detail?bot=CazoodleBot" +742[] = "CazoodleBot/0.1 (CazoodleBot Crawler; http://www.cazoodle.com; mqbot@cazoodle.com)" +742[] = "CazoodleBot" +742[] = "CazoodleBot b" +742[] = "http://www.cazoodle.com/cazoodlebot.php" +742[] = "Cazoodle Inc." +742[] = "http://www.cazoodle.com/" +742[] = "bot.png" +742[] = "" +742[] = "/list-of-ua/bot-detail?bot=CazoodleBot" +928[] = "CazoodleBot/Nutch-0.9-dev (CazoodleBot Crawler; http://www.cazoodle.com/cazoodlebot; cazoodlebot@cazoodle.com)" +928[] = "CazoodleBot" +928[] = "CazoodleBot c" +928[] = "http://www.cazoodle.com/cazoodlebot.php" +928[] = "Cazoodle Inc." +928[] = "http://www.cazoodle.com/" +928[] = "bot.png" +928[] = "" +928[] = "/list-of-ua/bot-detail?bot=CazoodleBot" +969[] = "CazoodleBot/CazoodleBot-0.1 (CazoodleBot Crawler; http://www.cazoodle.com/cazoodlebot; cazoodlebot@cazoodle.com)" +969[] = "CazoodleBot" +969[] = "CazoodleBot-0.1" +969[] = "http://www.cazoodle.com/cazoodlebot.php" +969[] = "Cazoodle Inc." +969[] = "http://www.cazoodle.com/" +969[] = "bot.png" +969[] = "" +969[] = "/list-of-ua/bot-detail?bot=CazoodleBot" +1482[] = "CazoodleBot/0.0.2 (http://www.cazoodle.com/contact.php; cbot@cazoodle.com)" +1482[] = "CazoodleBot" +1482[] = "CazoodleBot/0.0.2" +1482[] = "http://www.cazoodle.com/cazoodlebot.php" +1482[] = "Cazoodle Inc." +1482[] = "http://www.cazoodle.com/" +1482[] = "bot.png" +1482[] = "" +1482[] = "/list-of-ua/bot-detail?bot=CazoodleBot" +1238[] = "CCBot/1.0 (+http://www.commoncrawl.org/bot.html)" +1238[] = "CCBot" +1238[] = "CCBot/1.0" +1238[] = "http://www.commoncrawl.org/faq.htm" +1238[] = "CommonCrawl Foundation" +1238[] = "http://www.commoncrawl.org/" +1238[] = "bot.png" +1238[] = "" +1238[] = "/list-of-ua/bot-detail?bot=CCBot" +184[] = "ccubee/3.2" +184[] = "ccubee" +184[] = "ccubee/3.2" +184[] = "http://empyreum.com/technologies/platforms/ccubee/" +184[] = "EMPYREUM k. s." +184[] = "http://empyreum.com/" +184[] = "bot.png" +184[] = "" +184[] = "/list-of-ua/bot-detail?bot=ccubee" +200[] = "ccubee/3.3" +200[] = "ccubee" +200[] = "ccubee/3.3" +200[] = "http://empyreum.com/technologies/platforms/ccubee/" +200[] = "EMPYREUM k. s." +200[] = "http://empyreum.com/" +200[] = "bot.png" +200[] = "" +200[] = "/list-of-ua/bot-detail?bot=ccubee" +207[] = "ccubee/3.7" +207[] = "ccubee" +207[] = "ccubee/3.7" +207[] = "http://empyreum.com/technologies/platforms/ccubee/" +207[] = "EMPYREUM k. s." +207[] = "http://empyreum.com/" +207[] = "bot.png" +207[] = "" +207[] = "/list-of-ua/bot-detail?bot=ccubee" +263[] = "ccubee/4.0" +263[] = "ccubee" +263[] = "ccubee/4.0" +263[] = "http://empyreum.com/technologies/platforms/ccubee/" +263[] = "EMPYREUM k. s." +263[] = "http://empyreum.com/" +263[] = "bot.png" +263[] = "" +263[] = "/list-of-ua/bot-detail?bot=ccubee" +327[] = "ccubee/3.5" +327[] = "ccubee" +327[] = "ccubee/3.5" +327[] = "http://empyreum.com/technologies/platforms/ccubee/" +327[] = "EMPYREUM k. s." +327[] = "http://empyreum.com/" +327[] = "bot.png" +327[] = "" +327[] = "/list-of-ua/bot-detail?bot=ccubee" +560[] = "ccubee/9.0" +560[] = "ccubee" +560[] = "ccubee/9.0" +560[] = "http://empyreum.com/technologies/platforms/ccubee/" +560[] = "EMPYREUM k. s." +560[] = "http://empyreum.com/" +560[] = "bot.png" +560[] = "" +560[] = "/list-of-ua/bot-detail?bot=ccubee" +594[] = "ccubee/10.0" +594[] = "ccubee" +594[] = "ccubee/10.0" +594[] = "http://empyreum.com/technologies/platforms/ccubee/" +594[] = "EMPYREUM k. s." +594[] = "http://empyreum.com/" +594[] = "bot.png" +594[] = "" +594[] = "/list-of-ua/bot-detail?bot=ccubee" +824[] = "ccubee/3.5" +824[] = "ccubee" +824[] = "ccubee/3.5" +824[] = "http://empyreum.com/technologies/platforms/ccubee/" +824[] = "EMPYREUM k. s." +824[] = "http://empyreum.com/" +824[] = "bot.png" +824[] = "" +824[] = "/list-of-ua/bot-detail?bot=ccubee" +1023[] = "ccubee/2008" +1023[] = "ccubee" +1023[] = "ccubee/2008" +1023[] = "http://empyreum.com/technologies/platforms/ccubee/" +1023[] = "EMPYREUM k. s." +1023[] = "http://empyreum.com/" +1023[] = "bot.png" +1023[] = "" +1023[] = "/list-of-ua/bot-detail?bot=ccubee" +812[] = "mozilla/4.0 (compatible; changedetection/1.0 (admin@changedetection.com))" +812[] = "changedetection" +812[] = "changedetection/1.0" +812[] = "" +812[] = "FreeFind.com" +812[] = "http://www.freefind.com/" +812[] = "bot.png" +812[] = "" +812[] = "/list-of-ua/bot-detail?bot=changedetection" +959[] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; http://www.changedetection.com/bot.html )" +959[] = "ChangeDetection" +959[] = "ChangeDetection" +959[] = "http://www.changedetection.com/bot.html" +959[] = "FreeFind.com" +959[] = "http://www.freefind.com/" +959[] = "bot.png" +959[] = "" +959[] = "/list-of-ua/bot-detail?bot=ChangeDetection" +1270[] = "Mozilla/5.0 (compatible; Charlotte/1.1; http://www.searchme.com/support/)" +1270[] = "Charlotte" +1270[] = "Charlotte/1.1" +1270[] = "http://www.searchme.com/support/)" +1270[] = "Searchme, Inc." +1270[] = "http://www.searchme.com/" +1270[] = "bot.png" +1270[] = "" +1270[] = "/list-of-ua/bot-detail?bot=Charlotte" +76[] = "City4you/1.3 Cesky (+http://www.city4you.pl)" +76[] = "City4you" +76[] = "City4you/1.3 Cesky" +76[] = "" +76[] = "city4you" +76[] = "http://www.city4you.pl/" +76[] = "bot.png" +76[] = "" +76[] = "/list-of-ua/bot-detail?bot=City4you" +3409[] = "Cityreview Robot (+http://www.cityreview.org/crawler/)" +3409[] = "cityreview" +3409[] = "cityreview" +3409[] = "http://www.cityreview.org/crawler/" +3409[] = "SISTRIX GmbH" +3409[] = "http://www.sistrix.com/" +3409[] = "bot_cityreview.png" +3409[] = "" +3409[] = "/list-of-ua/bot-detail?bot=cityreview" +393[] = "CJB.NET Proxy" +393[] = "CJB.NET Proxy" +393[] = "CJB.NET Proxy" +393[] = "http://proxy.cjb.net/" +393[] = "CJB.NET" +393[] = "http://www.cjb.net/" +393[] = "bot.png" +393[] = "" +393[] = "/list-of-ua/bot-detail?bot=CJB.NET Proxy" +5909[] = "Mozilla/5.0 (compatible; CligooRobot/2.0; +http://www.cligoo.de/wk/technik.php)" +5909[] = "CligooRobot" +5909[] = "CligooRobot/2.0" +5909[] = "http://www.cligoo.de/wk/technik.php" +5909[] = "cligoo medien service UG" +5909[] = "http://www.cligoo.de/" +5909[] = "bot.png" +5909[] = "" +5909[] = "/list-of-ua/bot-detail?bot=CligooRobot" +608[] = "Combine/3 http://combine.it.lth.se/" +608[] = "Combine" +608[] = "Combine/3" +608[] = "http://combine.it.lth.se/" +608[] = "Lunds universitet" +608[] = "http://www.lu.se/" +608[] = "bot.png" +608[] = "" +608[] = "/list-of-ua/bot-detail?bot=Combine" +32[] = "ConveraMultiMediaCrawler/0.1 (+http://www.authoritativeweb.com/crawl)" +32[] = "ConveraCrawler" +32[] = "ConveraMultiMediaCrawler/0.1" +32[] = "http://www.authoritativeweb.com/crawl" +32[] = "Convera Corporation" +32[] = "http://www.authoritativeweb.com/" +32[] = "bot.png" +32[] = "" +32[] = "/list-of-ua/bot-detail?bot=ConveraCrawler" +80[] = "ConveraCrawler/0.9d (+http://www.authoritativeweb.com/crawl)" +80[] = "ConveraCrawler" +80[] = "ConveraCrawler 0.9d" +80[] = "http://www.authoritativeweb.com/crawl" +80[] = "Convera Corporation" +80[] = "http://www.authoritativeweb.com/" +80[] = "bot.png" +80[] = "" +80[] = "/list-of-ua/bot-detail?bot=ConveraCrawler" +688[] = "ConveraCrawler/0.9e (+http://www.authoritativeweb.com/crawl)" +688[] = "ConveraCrawler" +688[] = "ConveraCrawler 0.9e" +688[] = "http://www.authoritativeweb.com/crawl" +688[] = "Convera Corporation" +688[] = "http://www.authoritativeweb.com/" +688[] = "bot.png" +688[] = "" +688[] = "/list-of-ua/bot-detail?bot=ConveraCrawler" +1495[] = "copyright sheriff (+http://www.copyrightsheriff.com/)" +1495[] = "copyright sheriff" +1495[] = "copyright sheriff" +1495[] = "" +1495[] = "CopyrightSheriff .Com" +1495[] = "http://www.copyrightsheriff.com/" +1495[] = "bot.png" +1495[] = "" +1495[] = "/list-of-ua/bot-detail?bot=copyright sheriff" +2170[] = "CorpusCrawler 2.0.0 (http://corpora.fi.muni.cz/crawler/)" +2170[] = "CorpusCrawler" +2170[] = "CorpusCrawler 2.0.0" +2170[] = "http://corpora.fi.muni.cz/crawler/" +2170[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +2170[] = "http://nlp.fi.muni.cz/en/nlplab" +2170[] = "bot_CorpusCrawler.png" +2170[] = "" +2170[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +2181[] = "CorpusCrawler 2.0.8 (http://corpora.fi.muni.cz/crawler/)" +2181[] = "CorpusCrawler" +2181[] = "CorpusCrawler 2.0.8" +2181[] = "http://corpora.fi.muni.cz/crawler/" +2181[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +2181[] = "http://nlp.fi.muni.cz/en/nlplab" +2181[] = "bot_CorpusCrawler.png" +2181[] = "" +2181[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +2194[] = "CorpusCrawler 2.0.9 (http://corpora.fi.muni.cz/crawler/)" +2194[] = "CorpusCrawler" +2194[] = "CorpusCrawler 2.0.9" +2194[] = "http://corpora.fi.muni.cz/crawler/" +2194[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +2194[] = "http://nlp.fi.muni.cz/en/nlplab" +2194[] = "bot_CorpusCrawler.png" +2194[] = "" +2194[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +2212[] = "CorpusCrawler 2.0.10 (http://corpora.fi.muni.cz/crawler/)" +2212[] = "CorpusCrawler" +2212[] = "CorpusCrawler 2.0.10" +2212[] = "http://corpora.fi.muni.cz/crawler/" +2212[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +2212[] = "http://nlp.fi.muni.cz/en/nlplab" +2212[] = "bot_CorpusCrawler.png" +2212[] = "" +2212[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +2242[] = "CorpusCrawler 2.0.15 (http://corpora.fi.muni.cz/crawler/)" +2242[] = "CorpusCrawler" +2242[] = "CorpusCrawler 2.0.15" +2242[] = "http://corpora.fi.muni.cz/crawler/" +2242[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +2242[] = "http://nlp.fi.muni.cz/en/nlplab" +2242[] = "bot_CorpusCrawler.png" +2242[] = "" +2242[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +2235[] = "CorpusCrawler 2.0.12 (http://corpora.fi.muni.cz/crawler/)" +2235[] = "CorpusCrawler" +2235[] = "CorpusCrawler 2.0.12" +2235[] = "http://corpora.fi.muni.cz/crawler/" +2235[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +2235[] = "http://nlp.fi.muni.cz/en/nlplab" +2235[] = "bot_CorpusCrawler.png" +2235[] = "" +2235[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +2239[] = "CorpusCrawler 2.0.13 (http://corpora.fi.muni.cz/crawler/)" +2239[] = "CorpusCrawler" +2239[] = "CorpusCrawler 2.0.13" +2239[] = "http://corpora.fi.muni.cz/crawler/" +2239[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +2239[] = "http://nlp.fi.muni.cz/en/nlplab" +2239[] = "bot_CorpusCrawler.png" +2239[] = "" +2239[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +2241[] = "CorpusCrawler 2.0.14 (http://corpora.fi.muni.cz/crawler/)" +2241[] = "CorpusCrawler" +2241[] = "CorpusCrawler 2.0.14" +2241[] = "http://corpora.fi.muni.cz/crawler/" +2241[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +2241[] = "http://nlp.fi.muni.cz/en/nlplab" +2241[] = "bot_CorpusCrawler.png" +2241[] = "" +2241[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +2952[] = "CorpusCrawler 2.0.22 (http://corpora.fi.muni.cz/crawler/);Project:CzCorpus" +2952[] = "CorpusCrawler" +2952[] = "CorpusCrawler 2.0.22" +2952[] = "http://corpora.fi.muni.cz/crawler/" +2952[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +2952[] = "http://nlp.fi.muni.cz/en/nlplab" +2952[] = "bot_CorpusCrawler.png" +2952[] = "" +2952[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +2999[] = "CorpusCrawler 2.0.24 (http://corpora.fi.muni.cz/crawler/);Project:CzCorpus" +2999[] = "CorpusCrawler" +2999[] = "CorpusCrawler 2.0.24" +2999[] = "http://corpora.fi.muni.cz/crawler/" +2999[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +2999[] = "http://nlp.fi.muni.cz/en/nlplab" +2999[] = "bot_CorpusCrawler.png" +2999[] = "" +2999[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +3003[] = "CorpusCrawler 2.0.25 (http://corpora.fi.muni.cz/crawler/);Project:CzCorpus" +3003[] = "CorpusCrawler" +3003[] = "CorpusCrawler 2.0.25" +3003[] = "http://corpora.fi.muni.cz/crawler/" +3003[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +3003[] = "http://nlp.fi.muni.cz/en/nlplab" +3003[] = "bot_CorpusCrawler.png" +3003[] = "" +3003[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +2773[] = "CorpusCrawler 2.0.17 (http://corpora.fi.muni.cz/crawler/);Project:CzCorpus" +2773[] = "CorpusCrawler" +2773[] = "CorpusCrawler 2.0.17" +2773[] = "http://corpora.fi.muni.cz/crawler/" +2773[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +2773[] = "http://nlp.fi.muni.cz/en/nlplab" +2773[] = "bot_CorpusCrawler.png" +2773[] = "" +2773[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +2844[] = "CorpusCrawler 2.0.19 (http://corpora.fi.muni.cz/crawler/);Project:CzCorpus" +2844[] = "CorpusCrawler" +2844[] = "CorpusCrawler 2.0.19" +2844[] = "http://corpora.fi.muni.cz/crawler/" +2844[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +2844[] = "http://nlp.fi.muni.cz/en/nlplab" +2844[] = "bot_CorpusCrawler.png" +2844[] = "" +2844[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +2937[] = "CorpusCrawler 2.0.20 (http://corpora.fi.muni.cz/crawler/);Project:CzCorpus" +2937[] = "CorpusCrawler" +2937[] = "CorpusCrawler 2.0.20" +2937[] = "http://corpora.fi.muni.cz/crawler/" +2937[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +2937[] = "http://nlp.fi.muni.cz/en/nlplab" +2937[] = "bot_CorpusCrawler.png" +2937[] = "" +2937[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +2948[] = "CorpusCrawler 2.0.21 (http://corpora.fi.muni.cz/crawler/);Project:CzCorpus" +2948[] = "CorpusCrawler" +2948[] = "CorpusCrawler 2.0.21" +2948[] = "http://corpora.fi.muni.cz/crawler/" +2948[] = "NLP - at the Faculty of Informatics, Masaryk University, Brno" +2948[] = "http://nlp.fi.muni.cz/en/nlplab" +2948[] = "bot_CorpusCrawler.png" +2948[] = "" +2948[] = "/list-of-ua/bot-detail?bot=CorpusCrawler" +5860[] = "Covario-IDS/1.0 (Covario; http://www.covario.com/ids; support at covario dot com)" +5860[] = "Covario-IDS" +5860[] = "Covario-IDS/1.0" +5860[] = "http://www.covario.com/ids" +5860[] = "Covario Inc." +5860[] = "http://www.covario.com/" +5860[] = "bot.png" +5860[] = "" +5860[] = "/list-of-ua/bot-detail?bot=Covario-IDS" +317[] = "csci_b659/0.13" +317[] = "csci_b659" +317[] = "csci_b659/0.13" +317[] = "http://informatics.indiana.edu/fil/Class/b659/" +317[] = "Indiana University" +317[] = "http://www.indiana.edu/" +317[] = "bot.png" +317[] = "" +317[] = "/list-of-ua/bot-detail?bot=csci_b659" +725[] = "DataFountains/Dmoz Downloader (http://ivia.ucr.edu/useragents.shtml)" +725[] = "DataFountains" +725[] = "DataFountains at Dmoz" +725[] = "http://ivia.ucr.edu/useragents.shtml" +725[] = "University of California" +725[] = "http://www.universityofcalifornia.edu/" +725[] = "bot.png" +725[] = "" +725[] = "/list-of-ua/bot-detail?bot=DataFountains" +755[] = "DataFountains/DMOZ Feature Vector Corpus Creator (http://ivia.ucr.edu/useragents.shtml)" +755[] = "DataFountains" +755[] = "DataFountains at Dmoz b" +755[] = "http://ivia.ucr.edu/useragents.shtml" +755[] = "University of California" +755[] = "http://www.universityofcalifornia.edu/" +755[] = "bot.png" +755[] = "" +755[] = "/list-of-ua/bot-detail?bot=DataFountains" +422[] = "DataparkSearch/4.40.1 (+http://www.dataparksearch.org/)" +422[] = "DataparkSearch" +422[] = "DataparkSearch/4.40" +422[] = "http://www.dataparksearch.org/" +422[] = "DataPark" +422[] = "http://www.datapark.ru/" +422[] = "bot.png" +422[] = "" +422[] = "/list-of-ua/bot-detail?bot=DataparkSearch" +630[] = "Mozilla/4.0 (compatible; MSIE is not me; DAUMOA/1.0.0; DAUM Web Robot; Daum Communications Corp., Korea)" +630[] = "Daumoa" +630[] = "DAUMOA/1.0.0" +630[] = "http://ws.daum.net/aboutWebSearch_en.html" +630[] = "Daum Communications Corp." +630[] = "http://info.daum.net/" +630[] = "bot.png" +630[] = "" +630[] = "/list-of-ua/bot-detail?bot=Daumoa" +807[] = "Mozilla/4.0 (compatible; MSIE is not me; DAUMOA/1.0.1; DAUM Web Robot; Daum Communications Corp., Korea)" +807[] = "Daumoa" +807[] = "DAUMOA/1.0.1" +807[] = "http://ws.daum.net/aboutWebSearch_en.html" +807[] = "Daum Communications Corp." +807[] = "http://info.daum.net/" +807[] = "bot.png" +807[] = "" +807[] = "/list-of-ua/bot-detail?bot=Daumoa" +967[] = "Mozilla/4.0 (compatible; MSIE enviable; DAUMOA/1.0.1; DAUM Web Robot; Daum Communications Corp., Korea; +http://ws.daum.net/aboutkr.html)" +967[] = "Daumoa" +967[] = "DAUMOA/1.0.1 b" +967[] = "http://ws.daum.net/aboutWebSearch_en.html" +967[] = "Daum Communications Corp." +967[] = "http://info.daum.net/" +967[] = "bot.png" +967[] = "" +967[] = "/list-of-ua/bot-detail?bot=Daumoa" +1150[] = "Mozilla/4.0 (compatible; MSIE enviable; DAUMOA 2.0; DAUM Web Robot; Daum Communications Corp., Korea; +http://ws.daum.net/aboutkr.html)" +1150[] = "Daumoa" +1150[] = "Daumoa/2.0" +1150[] = "http://ws.daum.net/aboutWebSearch_en.html" +1150[] = "Daum Communications Corp." +1150[] = "http://info.daum.net/" +1150[] = "bot.png" +1150[] = "" +1150[] = "/list-of-ua/bot-detail?bot=Daumoa" +1466[] = "Mozilla/5.0 (compatible; MSIE or Firefox mutant; not on Windows server; +http://ws.daum.net/aboutWebSearch.html) Daumoa/2.0" +1466[] = "Daumoa" +1466[] = "Daumoa/2.0 b" +1466[] = "http://ws.daum.net/aboutWebSearch_en.html" +1466[] = "Daum Communications Corp." +1466[] = "http://info.daum.net/" +1466[] = "bot.png" +1466[] = "" +1466[] = "/list-of-ua/bot-detail?bot=Daumoa" +1530[] = "Mozilla/5.0 (compatible; DBLBot/1.0; +http://www.dontbuylists.com/)" +1530[] = "DBLBot" +1530[] = "DBLBot/1.0" +1530[] = "http://www.dontbuylists.com/faq.htm" +1530[] = "Dontbuylists.com" +1530[] = "http://www.dontbuylists.com/team.htm" +1530[] = "bot.png" +1530[] = "" +1530[] = "/list-of-ua/bot-detail?bot=DBLBot" +1568[] = "DealGates Bot/1.1 by Luc Michalski (http://spider.dealgates.com/bot.html)" +1568[] = "DealGates Bot" +1568[] = "DealGates Bot/1.1" +1568[] = "http://www.dealgates.net/bot.html" +1568[] = "Luc Michalski" +1568[] = "http://www.dealgates.net/" +1568[] = "bot.png" +1568[] = "" +1568[] = "/list-of-ua/bot-detail?bot=DealGates Bot" +731[] = "Mozilla/5.0 (compatible; del.icio.us-thumbnails/1.0; FreeBSD) KHTML/4.3.2 (like Gecko)" +731[] = "del.icio.us-thumbnails" +731[] = "del.icio.us-thumbnails/1.0" +731[] = "" +731[] = "Yahoo! Inc" +731[] = "http://www.yahoo.com/" +731[] = "bot.png" +731[] = "" +731[] = "/list-of-ua/bot-detail?bot=del.icio.us-thumbnails" +752[] = "del.icio.us-thumbnails/1.0 Mozilla/5.0 (compatible; Konqueror/3.4; FreeBSD) KHTML/3.4.2 (like Gecko)" +752[] = "del.icio.us-thumbnails" +752[] = "del.icio.us-thumbnails/1.0" +752[] = "" +752[] = "Yahoo!" +752[] = "http://www.yahoo.com/" +752[] = "bot.png" +752[] = "" +752[] = "/list-of-ua/bot-detail?bot=del.icio.us-thumbnails" +652[] = "Mozilla/4.0 (compatible; DepSpid/5.07; +http://about.depspid.net)" +652[] = "DepSpid" +652[] = "DepSpid/5.07" +652[] = "http://about.depspid.net/" +652[] = "Bjoern Henke" +652[] = "http://www.bjoernhenke.de/" +652[] = "bot.png" +652[] = "" +652[] = "/list-of-ua/bot-detail?bot=DepSpid" +811[] = "depspid - the dependency spider" +811[] = "DepSpid" +811[] = "DepSpid" +811[] = "http://about.depspid.net/" +811[] = "Bjoern Henke" +811[] = "http://www.bjoernhenke.de/" +811[] = "bot.png" +811[] = "" +811[] = "/list-of-ua/bot-detail?bot=DepSpid" +938[] = "Mozilla/4.0 (compatible; DepSpid/5.10; +http://about.depspid.net)" +938[] = "DepSpid" +938[] = "DepSpid/5.10" +938[] = "http://about.depspid.net/" +938[] = "Bjoern Henke" +938[] = "http://www.bjoernhenke.de/" +938[] = "bot.png" +938[] = "" +938[] = "/list-of-ua/bot-detail?bot=DepSpid" +1137[] = "Mozilla/4.0 (compatible; DepSpid/5.24; +http://about.depspid.net)" +1137[] = "DepSpid" +1137[] = "DepSpid/5.24" +1137[] = "http://about.depspid.net/" +1137[] = "Bjoern Henke" +1137[] = "http://www.bjoernhenke.de/" +1137[] = "bot.png" +1137[] = "" +1137[] = "/list-of-ua/bot-detail?bot=DepSpid" +1164[] = "Mozilla/4.0 (compatible; DepSpid/5.25; +http://about.depspid.net)" +1164[] = "DepSpid" +1164[] = "DepSpid/5.25" +1164[] = "http://about.depspid.net/" +1164[] = "Bjoern Henke" +1164[] = "http://www.bjoernhenke.de/" +1164[] = "bot.png" +1164[] = "" +1164[] = "/list-of-ua/bot-detail?bot=DepSpid" +1214[] = "Mozilla/4.0 (compatible; DepSpid/5.26; +http://about.depspid.net)" +1214[] = "DepSpid" +1214[] = "DepSpid/5.26" +1214[] = "http://about.depspid.net/" +1214[] = "Bjoern Henke" +1214[] = "http://www.bjoernhenke.de/" +1214[] = "bot.png" +1214[] = "" +1214[] = "/list-of-ua/bot-detail?bot=DepSpid" +1771[] = "mozilla/5.0 (compatible; discobot/1.1; +http://discoveryengine.com/discobot.html)" +1771[] = "discobot" +1771[] = "discobot/1.1" +1771[] = "http://www.discoveryengine.com/discobot.html" +1771[] = "discoveryengine.com. " +1771[] = "http://www.discoveryengine.com/" +1771[] = "bot.png" +1771[] = "" +1771[] = "/list-of-ua/bot-detail?bot=discobot" +6244[] = "Mozilla/5.0 (compatible; discobot/1.0; +http://discoveryengine.com/discobot.html)" +6244[] = "discobot" +6244[] = "discobot/1.0" +6244[] = "http://www.discoveryengine.com/discobot.html" +6244[] = "" +6244[] = "http://www.discoveryengine.com/" +6244[] = "bot.png" +6244[] = "" +6244[] = "/list-of-ua/bot-detail?bot=discobot" +1650[] = "Mozilla/5.0 (compatible; DKIMRepBot/1.0; +http://www.dkim-reputation.org)" +1650[] = "DKIMRepBot" +1650[] = "DKIMRepBot/1.0" +1650[] = "http://www.dkim-reputation.org/" +1650[] = "DKIM" +1650[] = "http://www.dkim.org/" +1650[] = "bot.png" +1650[] = "" +1650[] = "/list-of-ua/bot-detail?bot=DKIMRepBot" +1731[] = "Mozilla/5.0 (compatible; DNS-Digger-Explorer/1.0; +http://www.dnsdigger.com)" +1731[] = "DNS-Digger-Explorer" +1731[] = "DNS-Digger-Explorer/1.0" +1731[] = "" +1731[] = "DNSDigger" +1731[] = "http://www.dnsdigger.com/" +1731[] = "bot.png" +1731[] = "" +1731[] = "/list-of-ua/bot-detail?bot=DNS-Digger-Explorer" +5218[] = "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; DomainDB-1.1; http://domaindb.com/crawler/)" +5218[] = "DomainDB" +5218[] = "DomainDB/1.1" +5218[] = "http://domaindb.com/crawler/" +5218[] = "Triop AB" +5218[] = "http://triop.se/" +5218[] = "bot.png" +5218[] = "" +5218[] = "/list-of-ua/bot-detail?bot=DomainDB" +1459[] = "Mozilla/5.0 (compatible; DotBot/1.1; http://www.dotnetdotcom.org/, crawler@dotnetdotcom.org)" +1459[] = "DotBot" +1459[] = "DotBot/1.1" +1459[] = "http://www.dotnetdotcom.org/" +1459[] = "dotnetdotcom.org" +1459[] = "http://www.dotnetdotcom.org/#cont" +1459[] = "bot.png" +1459[] = "" +1459[] = "/list-of-ua/bot-detail?bot=DotBot" +3333[] = "Mozilla/5.0 (compatible; dotSemantic/1.0; +http://www.dotsemantic.org)" +3333[] = "dotSemantic" +3333[] = "dotSemantic/1.0" +3333[] = "http://www.dotsemantic.org" +3333[] = "dotSemantic Projekt" +3333[] = "" +3333[] = "bot.png" +3333[] = "" +3333[] = "/list-of-ua/bot-detail?bot=dotSemantic" +1225[] = "DuckDuckBot/1.0; (+http://duckduckgo.com/duckduckbot.html)" +1225[] = "DuckDuckBot" +1225[] = "DuckDuckBot/1.0" +1225[] = "http://duckduckgo.com/duckduckbot.html" +1225[] = "Duck Duck Go, Inc." +1225[] = "http://duckduckgo.com/blog/" +1225[] = "bot.png" +1225[] = "" +1225[] = "/list-of-ua/bot-detail?bot=DuckDuckBot" +117[] = "e-SocietyRobot(http://www.yama.info.waseda.ac.jp/~yamana/es/)" +117[] = "e-SocietyRobot" +117[] = "e-SocietyRobot" +117[] = "http://www.yama.info.waseda.ac.jp/~yamana/es" +117[] = "Waseda University Yamana Laboratory" +117[] = "http://www.yama.info.waseda.ac.jp/" +117[] = "bot.png" +117[] = "" +117[] = "/list-of-ua/bot-detail?bot=e-SocietyRobot" +5187[] = "eCairn-Grabber/1.0 (+http://ecairn.com/grabber) curl/7.15" +5187[] = "eCairn-Grabber" +5187[] = "eCairn-Grabber/1.0" +5187[] = "http://ecairn.com/grabber" +5187[] = "eCairn Inc." +5187[] = "http://ecairn.com/" +5187[] = "bot_eCairn-Grabber.png" +5187[] = "" +5187[] = "/list-of-ua/bot-detail?bot=eCairn-Grabber" +556[] = "EDI/1.6.5 (Edacious & Intelligent Web Robot, Daum Communications Corp.)" +556[] = "EDI" +556[] = "EDI/1.6.5" +556[] = "" +556[] = "Daum Communications Corp." +556[] = "http://info.daum.net/" +556[] = "bot.png" +556[] = "" +556[] = "/list-of-ua/bot-detail?bot=EDI" +569[] = "Mozilla/4.0 (compatible; EDI/1.6.6; Edacious & Intelligent Web Robot; Daum Communications Corp., Korea)" +569[] = "EDI" +569[] = "EDI/1.6.6" +569[] = "" +569[] = "Daum Communications Corp." +569[] = "http://info.daum.net/" +569[] = "bot.png" +569[] = "" +569[] = "/list-of-ua/bot-detail?bot=EDI" +600[] = "Mozilla/4.0 (compatible; MSIE is not me; EDI/1.6.6; Edacious & Intelligent Web Robot; Daum Communications Corp., Korea)" +600[] = "EDI" +600[] = "EDI/1.6.6 b" +600[] = "" +600[] = "Daum Communications Corp." +600[] = "http://info.daum.net/" +600[] = "bot.png" +600[] = "" +600[] = "/list-of-ua/bot-detail?bot=EDI" +488[] = "egothor/8.0f (+http://ego.ms.mff.cuni.cz/)" +488[] = "egothor" +488[] = "egothor/8.0f" +488[] = "http://ego.ms.mff.cuni.cz/" +488[] = "Katedra softwarového inženýrství Univerzity Karlovi" +488[] = "http://kocour.ms.mff.cuni.cz/cs/" +488[] = "bot.png" +488[] = "" +488[] = "/list-of-ua/bot-detail?bot=egothor" +597[] = "Mozilla/5.0 (compatible; egothor/8.0g; +http://ego.ms.mff.cuni.cz/)" +597[] = "egothor" +597[] = "egothor/8.0g" +597[] = "https://kocour.ms.mff.cuni.cz/ego/" +597[] = "Katedra softwarového inženýrství Univerzity Karlovi" +597[] = "http://kocour.ms.mff.cuni.cz/cs/" +597[] = "bot.png" +597[] = "" +597[] = "/list-of-ua/bot-detail?bot=egothor" +1115[] = "Mozilla/5.0 (compatible; egothor/11.0d; +http://ego.ms.mff.cuni.cz/)" +1115[] = "egothor" +1115[] = "egothor/11.0d" +1115[] = "https://kocour.ms.mff.cuni.cz/ego/" +1115[] = "Katedra softwarového inženýrství Univerzity Karlovi" +1115[] = "http://kocour.ms.mff.cuni.cz/cs/" +1115[] = "bot.png" +1115[] = "" +1115[] = "/list-of-ua/bot-detail?bot=egothor" +1169[] = "Mozilla/5.0 (compatible; egothor/11.0d; +https://kocour.ms.mff.cuni.cz/ego/)" +1169[] = "egothor" +1169[] = "egothor/11.0d b" +1169[] = "https://kocour.ms.mff.cuni.cz/ego/" +1169[] = "Katedra softwarového inženýrství Univerzity Karlovi" +1169[] = "http://kocour.ms.mff.cuni.cz/cs/" +1169[] = "bot.png" +1169[] = "" +1169[] = "/list-of-ua/bot-detail?bot=egothor" +1323[] = "Mozilla/5.0 (compatible; egothor/12.0rc-2; +http://ego.ms.mff.cuni.cz/)" +1323[] = "egothor" +1323[] = "egothor/12.0rc-2" +1323[] = "https://kocour.ms.mff.cuni.cz/ego/" +1323[] = "Katedra softwarového inženýrství Univerzity Karlovi" +1323[] = "http://kocour.ms.mff.cuni.cz/cs/" +1323[] = "bot.png" +1323[] = "" +1323[] = "/list-of-ua/bot-detail?bot=egothor" +192[] = "ejupiter.com" +192[] = "ejupiter.com" +192[] = "ejupiter.com" +192[] = "http://robot.ejupiter.com/16/robot_privacy.html" +192[] = "eJupiter Inc" +192[] = "http://www.ejupiter.com/" +192[] = "bot.png" +192[] = "" +192[] = "/list-of-ua/bot-detail?bot=ejupiter.com" +564[] = "crawler43.ejupiter.com" +564[] = "ejupiter.com" +564[] = "ejupiter.com 43" +564[] = "http://robot.ejupiter.com/16/robot_privacy.html" +564[] = "eJupiter Inc" +564[] = "http://www.ejupiter.com/" +564[] = "bot.png" +564[] = "" +564[] = "/list-of-ua/bot-detail?bot=ejupiter.com" +1198[] = "EnaBot/1.1 (http://www.enaball.com/crawler.html)" +1198[] = "EnaBot" +1198[] = "EnaBot/1.1" +1198[] = "http://www.enaball.com/crawler.html" +1198[] = "Enaball Inc." +1198[] = "http://www.enaball.com/" +1198[] = "bot.png" +1198[] = "" +1198[] = "/list-of-ua/bot-detail?bot=EnaBot" +1205[] = "EnaBot/1.2 (http://www.enaball.com/crawler.html)" +1205[] = "EnaBot" +1205[] = "EnaBot/1.2" +1205[] = "http://www.enaball.com/crawler.html" +1205[] = "Enaball Inc." +1205[] = "http://www.enaball.com/" +1205[] = "bot.png" +1205[] = "" +1205[] = "/list-of-ua/bot-detail?bot=EnaBot" +1027[] = "Enterprise_Search/1.00.143;MSSQL (http://www.innerprise.net/es-spider.asp)" +1027[] = "Enterprise_Search" +1027[] = "Enterprise_Search/1.00.143" +1027[] = "http://www.innerprise.net/hosted-bi.asp" +1027[] = "Innerprise" +1027[] = "http://www.innerprise.net/" +1027[] = "bot.png" +1027[] = "" +1027[] = "/list-of-ua/bot-detail?bot=Enterprise_Search" +547[] = "envolk/1.7 (+http://www.envolk.com/envolkspiderinfo.html)" +547[] = "envolk" +547[] = "envolk/1.7" +547[] = "http://www.envolk.com/envolkspiderinfo.html" +547[] = "Envolk" +547[] = "http://www.envolk.com/" +547[] = "bot.png" +547[] = "" +547[] = "/list-of-ua/bot-detail?bot=envolk" +5806[] = "EuripBot/1.1 (+http://www.eurip.com) GetRobots" +5806[] = "EuripBot" +5806[] = "EuripBot/1.1" +5806[] = "http://www.eurip.com/service/webmaster/euripbot.html" +5806[] = "EURIP - European Internet Portal" +5806[] = "http://www.eurip.com/" +5806[] = "bot.png" +5806[] = "" +5806[] = "/list-of-ua/bot-detail?bot=EuripBot" +1500[] = "Eurobot/1.1 (http://eurobot.ayell.eu)" +1500[] = "Eurobot" +1500[] = "Eurobot/1.1" +1500[] = "http://eurobot.ayell.de/" +1500[] = "Ayell Euronet" +1500[] = "http://www.ayell.eu/" +1500[] = "bot_eurobot.png" +1500[] = "" +1500[] = "/list-of-ua/bot-detail?bot=Eurobot" +4730[] = "Eurobot/1.2 (http://eurobot.ayell.eu)" +4730[] = "Eurobot" +4730[] = "Eurobot/1.2" +4730[] = "http://eurobot.ayell.eu/" +4730[] = "Ayell Euronet" +4730[] = "http://www.ayell.eu/" +4730[] = "bot_eurobot.png" +4730[] = "" +4730[] = "/list-of-ua/bot-detail?bot=Eurobot" +6243[] = "Mozilla/5.0 (compatible; Evrinid Iudex 1.0.0; +http://www.evri.com/evrinid)" +6243[] = "EvriNid" +6243[] = "EvriNid/1.0.0" +6243[] = "http://corporate.evri.com/about-us/evrinid/" +6243[] = "Evri Inc." +6243[] = "http://corporate.evri.com/" +6243[] = "bot.png" +6243[] = "" +6243[] = "/list-of-ua/bot-detail?bot=EvriNid" +679[] = "Mozilla/5.0 (compatible; Exabot/3.0; +http://www.exabot.com/go/robot)" +679[] = "Exabot" +679[] = "Exabot/3.0" +679[] = "http://www.exabot.com/go/robot" +679[] = "Exalead S.A." +679[] = "http://www.exalead.com/" +679[] = "bot_Exabot.png" +679[] = "" +679[] = "/list-of-ua/bot-detail?bot=Exabot" +753[] = "Mozilla/5.0 (compatible; Exabot-Images/3.0; +http://www.exabot.com/go/robot)" +753[] = "Exabot" +753[] = "Exabot-Images/3.0" +753[] = "http://www.exabot.com/go/robot" +753[] = "Exalead S.A." +753[] = "http://www.exalead.com/" +753[] = "bot_Exabot.png" +753[] = "" +753[] = "/list-of-ua/bot-detail?bot=Exabot" +1994[] = "Mozilla/5.0 (compatible; Exabot/3.0 (BiggerBetter); +http://www.exabot.com/go/robot)" +1994[] = "Exabot" +1994[] = "Exabot/3.0/BiggerBetter" +1994[] = "http://www.exabot.com/go/robot" +1994[] = "Exalead S.A." +1994[] = "http://www.exalead.com/" +1994[] = "bot_Exabot.png" +1994[] = "" +1994[] = "/list-of-ua/bot-detail?bot=Exabot" +425[] = "exactseek.com" +425[] = "ExactSEEK" +425[] = "ExactSEEK" +425[] = "http://www.exactseek.com/" +425[] = "Jayde Online, Inc." +425[] = "http://www.jaydeonlineinc.com/" +425[] = "bot.png" +425[] = "" +425[] = "/list-of-ua/bot-detail?bot=ExactSEEK" +1523[] = "facebookexternalhit/1.0 (+http://www.facebook.com/externalhit_uatext.php)" +1523[] = "FacebookExternalHit" +1523[] = "FacebookExternalHit/1.0" +1523[] = "http://www.facebook.com/externalhit_uatext.php" +1523[] = "Facebook" +1523[] = "http://www.facebook.com/" +1523[] = "bot_facebook.png" +1523[] = "" +1523[] = "/list-of-ua/bot-detail?bot=FacebookExternalHit" +5611[] = "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)" +5611[] = "FacebookExternalHit" +5611[] = "FacebookExternalHit/1.1" +5611[] = "http://www.facebook.com/externalhit_uatext.php" +5611[] = "Facebook" +5611[] = "http://www.facebook.com/" +5611[] = "bot_facebook.png" +5611[] = "" +5611[] = "/list-of-ua/bot-detail?bot=FacebookExternalHit" +1061[] = "Factbot 1.09" +1061[] = "factbot" +1061[] = "Factbot 1.09" +1061[] = "http://www.factbites.com/webmasters.php" +1061[] = "Rapid Intelligence Pty Ltd" +1061[] = "http://www.rapint.com/" +1061[] = "bot.png" +1061[] = "" +1061[] = "/list-of-ua/bot-detail?bot=factbot" +4501[] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1 + FairShare-http://fairshare.cc)" +4501[] = "FairShare" +4501[] = "FairShare" +4501[] = "http://support.attributor.com/kbfairshare/doku.php" +4501[] = "Attributor Corporation" +4501[] = "http://www.attributor.com/" +4501[] = "bot_FairShare.png" +4501[] = "" +4501[] = "/list-of-ua/bot-detail?bot=FairShare" +1717[] = "Mozilla/5.0 (compatible; Falconsbot; +http://iws.seu.edu.cn/services/falcons/contact_us.jsp)" +1717[] = "Falconsbot" +1717[] = "Falconsbot" +1717[] = "http://ws.nju.edu.cn/falcons/contact_us.jsp" +1717[] = "Institute of Web Science" +1717[] = "http://iws.seu.edu.cn/page/english/" +1717[] = "bot.png" +1717[] = "" +1717[] = "/list-of-ua/bot-detail?bot=Falconsbot" +3703[] = "Mozilla/5.0 (compatible; Falconsbot; +http://ws.nju.edu.cn/falcons/)" +3703[] = "Falconsbot" +3703[] = "Falconsbot" +3703[] = "http://ws.nju.edu.cn/falcons/contact_us.jsp" +3703[] = "Institute of Web Science" +3703[] = "http://iws.seu.edu.cn/page/english/" +3703[] = "bot.png" +3703[] = "" +3703[] = "/list-of-ua/bot-detail?bot=Falconsbot" +312[] = "FAST Enterprise Crawler/6.4 (crawler@fast.no)" +312[] = "FAST Enterprise Crawler" +312[] = "FAST Enterprise Crawler/6.4" +312[] = "http://www.fast.no/glossary.aspx?m=48&amid=415" +312[] = "Fast Search & Transfer" +312[] = "http://www.fastsearch.com/" +312[] = "bot.png" +312[] = "" +312[] = "/list-of-ua/bot-detail?bot=FAST Enterprise Crawler" +809[] = "FAST Enterprise Crawler 6 used by FAST (jim.mosher@fastsearch.com)" +809[] = "FAST Enterprise Crawler" +809[] = "FAST Enterprise Crawler/6" +809[] = "http://www.fast.no/glossary.aspx?m=48&amid=415" +809[] = "Fast Search & Transfer" +809[] = "http://www.fastsearch.com/" +809[] = "bot.png" +809[] = "" +809[] = "/list-of-ua/bot-detail?bot=FAST Enterprise Crawler" +1005[] = "FAST Enterprise Crawler 6 used by Virk.dk - udvikling (thomas.bentzen@capgemini.com)" +1005[] = "FAST Enterprise Crawler" +1005[] = "FAST Enterprise Crawler 6 at virk.dk" +1005[] = "http://www.fast.no/glossary.aspx?m=48&amid=415" +1005[] = "Fast Search & Transfer" +1005[] = "http://www.fastsearch.com/" +1005[] = "bot.png" +1005[] = "" +1005[] = "/list-of-ua/bot-detail?bot=FAST Enterprise Crawler" +47[] = "FAST MetaWeb Crawler (helpdesk at fastsearch dot com)" +47[] = "FAST MetaWeb Crawler" +47[] = "FAST MetaWeb Crawler" +47[] = "http://www.fast.no/glossary.aspx?m=48&amid=415" +47[] = "Fast Search & Transfer" +47[] = "http://www.fastsearch.com/" +47[] = "bot.png" +47[] = "" +47[] = "/list-of-ua/bot-detail?bot=FAST MetaWeb Crawler" +4722[] = "Mozilla/5.0 (FauBot/0.1; +http://buzzvolume.com/fau/)" +4722[] = "FauBot" +4722[] = "FauBot/0.1" +4722[] = "http://buzzvolume.com/fau" +4722[] = "BuzzVolume" +4722[] = "http://buzzvolume.com/" +4722[] = "bot.png" +4722[] = "" +4722[] = "/list-of-ua/bot-detail?bot=FauBot" +808[] = "favorstarbot/1.0 (+http://favorstar.com/bot.html)" +808[] = "favorstarbot" +808[] = "favorstarbot/1.0" +808[] = "http://favorstar.com/bot.html" +808[] = "favorstar.com" +808[] = "http://favorstar.com/" +808[] = "bot.png" +808[] = "" +808[] = "/list-of-ua/bot-detail?bot=favorstarbot" +1595[] = "FeedCatBot/3.0 (+http://www.feedcat.net/)" +1595[] = "FeedCatBot" +1595[] = "FeedCatBot/3.0" +1595[] = "http://www.feedcat.net/" +1595[] = "FEEDCAT.NET" +1595[] = "" +1595[] = "bot.png" +1595[] = "" +1595[] = "/list-of-ua/bot-detail?bot=FeedCatBot" +3002[] = "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; FeedFinder-2.0; http://bloggz.se/crawler)" +3002[] = "FeedFinder/bloggz.se" +3002[] = "FeedFinder-2.0" +3002[] = "http://bloggz.se/crawler/" +3002[] = "Triop AB" +3002[] = "http://triop.se/" +3002[] = "bot_FeedFinder_bloggz.png" +3002[] = "" +3002[] = "/list-of-ua/bot-detail?bot=FeedFinder/bloggz.se" +118[] = "Findexa Crawler (http://www.findexa.no/gulesider/article26548.ece)" +118[] = "Findexa Crawler" +118[] = "Findexa Crawler" +118[] = "http://www.findexa.no/gulesider/article26548.ece" +118[] = "Findexa AS" +118[] = "http://www.findexa.no/" +118[] = "bot.png" +118[] = "" +118[] = "/list-of-ua/bot-detail?bot=Findexa Crawler" +1856[] = "findlinks/1.1.5-beta7 (+http://wortschatz.uni-leipzig.de/findlinks/)" +1856[] = "findlinks" +1856[] = "findlinks/1.1.4-beta7" +1856[] = "http://wortschatz.uni-leipzig.de/findlinks/" +1856[] = "Universität Leipzig" +1856[] = "http://www.uni-leipzig.de/" +1856[] = "bot_findlinks.png" +1856[] = "" +1856[] = "/list-of-ua/bot-detail?bot=findlinks" +5292[] = "findlinks/1.1.6-beta4 (+http://wortschatz.uni-leipzig.de/findlinks/)" +5292[] = "findlinks" +5292[] = "findlinks/1.1.6-beta4" +5292[] = "http://wortschatz.uni-leipzig.de/findlinks/" +5292[] = "Universität Leipzig" +5292[] = "http://www.uni-leipzig.de/" +5292[] = "bot_findlinks.png" +5292[] = "" +5292[] = "/list-of-ua/bot-detail?bot=findlinks" +5352[] = "findlinks/1.1.6-beta5 (+http://wortschatz.uni-leipzig.de/findlinks/)" +5352[] = "findlinks" +5352[] = "findlinks/1.1.6-beta5" +5352[] = "http://wortschatz.uni-leipzig.de/findlinks/" +5352[] = "Universität Leipzig" +5352[] = "http://www.uni-leipzig.de/" +5352[] = "bot_findlinks.png" +5352[] = "" +5352[] = "/list-of-ua/bot-detail?bot=findlinks" +5646[] = "findlinks/2.0 (+http://wortschatz.uni-leipzig.de/findlinks/)" +5646[] = "findlinks" +5646[] = "findlinks/2.0" +5646[] = "http://wortschatz.uni-leipzig.de/findlinks/" +5646[] = "Universität Leipzig" +5646[] = "http://www.uni-leipzig.de/" +5646[] = "bot_findlinks.png" +5646[] = "" +5646[] = "/list-of-ua/bot-detail?bot=findlinks" +5685[] = "findlinks/1.1.6-beta6 (+http://wortschatz.uni-leipzig.de/findlinks/)" +5685[] = "findlinks" +5685[] = "findlinks/1.1.6-beta6" +5685[] = "http://wortschatz.uni-leipzig.de/findlinks/" +5685[] = "Universität Leipzig" +5685[] = "http://www.uni-leipzig.de/" +5685[] = "bot_findlinks.png" +5685[] = "" +5685[] = "/list-of-ua/bot-detail?bot=findlinks" +5715[] = "findlinks/2.0.1 (+http://wortschatz.uni-leipzig.de/findlinks/)" +5715[] = "findlinks" +5715[] = "findlinks/2.0.1" +5715[] = "http://wortschatz.uni-leipzig.de/findlinks/" +5715[] = "Universität Leipzig" +5715[] = "http://www.uni-leipzig.de/" +5715[] = "bot_findlinks.png" +5715[] = "" +5715[] = "/list-of-ua/bot-detail?bot=findlinks" +4853[] = "findlinks/1.1.6-beta1 (+http://wortschatz.uni-leipzig.de/findlinks/)" +4853[] = "findlinks" +4853[] = "findlinks/1.1.6-beta1" +4853[] = "http://wortschatz.uni-leipzig.de/findlinks/" +4853[] = "Universität Leipzig" +4853[] = "http://www.uni-leipzig.de/" +4853[] = "bot_findlinks.png" +4853[] = "" +4853[] = "/list-of-ua/bot-detail?bot=findlinks" +5052[] = "findlinks/1.1.6-beta2 (+http://wortschatz.uni-leipzig.de/findlinks/)" +5052[] = "findlinks" +5052[] = "findlinks/1.1.6-beta2" +5052[] = "http://wortschatz.uni-leipzig.de/findlinks/" +5052[] = "Universität Leipzig" +5052[] = "http://www.uni-leipzig.de/" +5052[] = "bot_findlinks.png" +5052[] = "" +5052[] = "/list-of-ua/bot-detail?bot=findlinks" +5243[] = "findlinks/1.1.6-beta1 (+http://wortschatz.uni-leipzig.de/findlinks/; YaCy 0.1; yacy.net)" +5243[] = "findlinks" +5243[] = "findlinks/1.1.6-beta1 Yacy" +5243[] = "http://wortschatz.uni-leipzig.de/findlinks/" +5243[] = "Universität Leipzig" +5243[] = "http://www.uni-leipzig.de/" +5243[] = "bot_findlinks.png" +5243[] = "" +5243[] = "/list-of-ua/bot-detail?bot=findlinks" +5277[] = "findlinks/1.1.6-beta3 (+http://wortschatz.uni-leipzig.de/findlinks/)" +5277[] = "findlinks" +5277[] = "findlinks/1.1.6-beta3" +5277[] = "http://wortschatz.uni-leipzig.de/findlinks/" +5277[] = "Universität Leipzig" +5277[] = "http://www.uni-leipzig.de/" +5277[] = "bot_findlinks.png" +5277[] = "" +5277[] = "/list-of-ua/bot-detail?bot=findlinks" +5843[] = "findlinks/2.0.2 (+http://wortschatz.uni-leipzig.de/findlinks/)" +5843[] = "findlinks" +5843[] = "findlinks/2.0.2" +5843[] = "http://wortschatz.uni-leipzig.de/findlinks/" +5843[] = "Universität Leipzig" +5843[] = "http://www.uni-leipzig.de/" +5843[] = "bot_findlinks.png" +5843[] = "" +5843[] = "/list-of-ua/bot-detail?bot=findlinks" +6011[] = "findlinks/2.0.4 (+http://wortschatz.uni-leipzig.de/findlinks/)" +6011[] = "findlinks" +6011[] = "findlinks/2.0.4" +6011[] = "http://wortschatz.uni-leipzig.de/findlinks/" +6011[] = "Universität Leipzig" +6011[] = "http://www.uni-leipzig.de/" +6011[] = "bot_findlinks.png" +6011[] = "" +6011[] = "/list-of-ua/bot-detail?bot=findlinks" +6177[] = "findlinks/1.1.3-beta9 (+http://wortschatz.uni-leipzig.de/findlinks/)" +6177[] = "findlinks" +6177[] = "findlinks/1.1.3-beta9" +6177[] = "http://wortschatz.uni-leipzig.de/findlinks/" +6177[] = "Universität Leipzig" +6177[] = "http://www.uni-leipzig.de/" +6177[] = "bot_findlinks.png" +6177[] = "" +6177[] = "/list-of-ua/bot-detail?bot=findlinks" +1582[] = "flatlandbot/baypup (Flatland Industries Web Spider; http://www.flatlandindustries.com/flatlandbot; jason@flatlandindustries.com)" +1582[] = "Flatland Industries Web Spider" +1582[] = "flatlandbot/baypup" +1582[] = "http://www.flatlandindustries.com/flatlandbot" +1582[] = "Flatland Industries, Inc." +1582[] = "http://www.flatlandindustries.com/" +1582[] = "bot.png" +1582[] = "" +1582[] = "/list-of-ua/bot-detail?bot=Flatland Industries Web Spider" +844[] = "great-plains-web-spider/gpws (Flatland Industries Web Spider; http://www.flatlandindustries.com/flatlandbot.php; jason@flatlandindustries.com)" +844[] = "flatlandbot" +844[] = "flatlandbot c" +844[] = "http://www.flatlandindustries.com/flatlandbot.php" +844[] = "Flatland Industries, Inc." +844[] = "http://www.flatlandindustries.com/" +844[] = "bot.png" +844[] = "" +844[] = "/list-of-ua/bot-detail?bot=flatlandbot" +876[] = "great-plains-web-spider/flatlandbot (Flatland Industries Web Robot; http://www.flatlandindustries.com/flatlandbot.php; jason@flatlandindustries.com)" +876[] = "flatlandbot" +876[] = "flatlandbot b" +876[] = "http://www.flatlandindustries.com/flatlandbot.php" +876[] = "Flatland Industries, Inc." +876[] = "http://www.flatlandindustries.com/" +876[] = "bot.png" +876[] = "" +876[] = "/list-of-ua/bot-detail?bot=flatlandbot" +877[] = "flatlandbot/flatlandbot (Flatland Industries Web Spider; http://www.flatlandindustries.com/flatlandbot.php; jason@flatlandindustries.com)" +877[] = "flatlandbot" +877[] = "flatlandbot" +877[] = "http://www.flatlandindustries.com/flatlandbot.php" +877[] = "Flatland Industries, Inc." +877[] = "http://www.flatlandindustries.com/" +877[] = "bot.png" +877[] = "" +877[] = "/list-of-ua/bot-detail?bot=flatlandbot" +925[] = "great-plains-web-spider/flatlandbot (Flatland Industries Web Spider; http://www.flatlandindustries.com/flatlandbot.php; jason@flatlandindustries.com)" +925[] = "flatlandbot" +925[] = "flatlandbot d" +925[] = "http://www.flatlandindustries.com/flatlandbot.php" +925[] = "Flatland Industries, Inc." +925[] = "http://www.flatlandindustries.com/" +925[] = "bot.png" +925[] = "" +925[] = "/list-of-ua/bot-detail?bot=flatlandbot" +6202[] = "FlightDeckReportsBot/2.0 (http://www.flightdeckreports.com/pages/bot)" +6202[] = "FlightDeckReportsBot" +6202[] = "FlightDeckReportsBot/2.0" +6202[] = "http://www.flightdeckreports.com/pages/bot" +6202[] = "Flight Deck Reports, LLC." +6202[] = "http://www.flightdeckreports.com/" +6202[] = "bot.png" +6202[] = "" +6202[] = "/list-of-ua/bot-detail?bot=FlightDeckReportsBot" +6068[] = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6 (FlipboardProxy/0.0.5; +http://flipboard.com/browserproxy)" +6068[] = "FlipboardProxy" +6068[] = "FlipboardProxy/0.0.5" +6068[] = "http://flipboard.com/browserproxy" +6068[] = "Flipboard, Inc." +6068[] = "http://flipboard.com/" +6068[] = "bot.png" +6068[] = "" +6068[] = "/list-of-ua/bot-detail?bot=FlipboardProxy" +1536[] = "http://www.uni-koblenz.de/~flocke/robot-info.txt" +1536[] = "Flocke bot" +1536[] = "Flocke bot" +1536[] = "http://www.uni-koblenz.de/~flocke/robot-info.txt" +1536[] = "" +1536[] = "" +1536[] = "bot.png" +1536[] = "" +1536[] = "/list-of-ua/bot-detail?bot=Flocke bot" +1870[] = "FollowSite Bot ( http://www.followsite.com/bot.html )" +1870[] = "FollowSite Bot" +1870[] = "FollowSite Bot" +1870[] = "http://www.followsite.com/bot.html" +1870[] = "ASX Networks ApS" +1870[] = "http://asxnetworks.com/" +1870[] = "bot.png" +1870[] = "" +1870[] = "/list-of-ua/bot-detail?bot=FollowSite Bot" +1663[] = "Mozilla/4.0 (compatible; Fooooo_Web_Video_Crawl http://fooooo.com/bot.html)" +1663[] = "Fooooo_Web_Video_Crawl" +1663[] = "Fooooo_Web_Video_Crawl" +1663[] = "http://fooooo.com/bot.html" +1663[] = "Bank of innvation Inc." +1663[] = "http://en.boi.jp/" +1663[] = "bot.png" +1663[] = "" +1663[] = "/list-of-ua/bot-detail?bot=Fooooo_Web_Video_Crawl" +306[] = "Forschungsportal/0.8-dev (Testinstallation; http://www.forschungsportal.net/; fpcrawler@rrzn.uni-hannover.de)" +306[] = "Forschungsportal" +306[] = "Forschungsportal/0.8-dev" +306[] = "http://www.forschungsportal.net/" +306[] = "Bundesministerium für Bildung und Forschung" +306[] = "http://www.bmbf.de/" +306[] = "bot.png" +306[] = "" +306[] = "/list-of-ua/bot-detail?bot=Forschungsportal" +804[] = "Francis/2.0 (francis@neomo.de http://www.neomo.de/pages/crawler.php)" +804[] = "Francis" +804[] = "Francis/2.0" +804[] = "http://www.neomo.de/pages/crawler.php" +804[] = "Neomo GmbH & Co. KG." +804[] = "http://www.neomo.de/" +804[] = "bot.png" +804[] = "" +804[] = "/list-of-ua/bot-detail?bot=Francis" +851[] = "Mozilla/5.0 (compatible; FunnelBack; http://cyan.funnelback.com/robot.html)" +851[] = "FunnelBack" +851[] = "FunnelBack" +851[] = "http://cyan.funnelback.com/robot.html" +851[] = "Funnelback Pty Ltd" +851[] = "http://www.funnelback.com/" +851[] = "bot.png" +851[] = "" +851[] = "/list-of-ua/bot-detail?bot=FunnelBack" +531[] = "Mozilla/4.0 compatible FurlBot/Furl Search 2.0 (FurlBot; http://www.furl.net; wn.furlbot@looksmart.net)" +531[] = "FurlBot" +531[] = "FurlBot/Furl Search 2.0" +531[] = "" +531[] = "LookSmart, Ltd." +531[] = "http://search.looksmart.com/" +531[] = "bot.png" +531[] = "" +531[] = "/list-of-ua/bot-detail?bot=FurlBot" +1035[] = "FyberSpider/1.2 (http://www.fybersearch.com/fyberspider.php)" +1035[] = "FyberSpider" +1035[] = "FyberSpider/1.2" +1035[] = "http://www.fybersearch.com/fyberspider.php" +1035[] = "FyberSearch" +1035[] = "http://www.fybersearch.com/" +1035[] = "bot.png" +1035[] = "" +1035[] = "/list-of-ua/bot-detail?bot=FyberSpider" +4946[] = "FyberSpider/1.3 (http://www.fybersearch.com/fyberspider.php)" +4946[] = "FyberSpider" +4946[] = "FyberSpider/1.3" +4946[] = "http://www.fybersearch.com/fyberspider.php" +4946[] = "FyberSearch" +4946[] = "http://www.fybersearch.com/" +4946[] = "bot_FyberSpider.png" +4946[] = "" +4946[] = "/list-of-ua/bot-detail?bot=FyberSpider" +217[] = "g2Crawler (nobody@airmail.net)" +217[] = "g2crawler" +217[] = "g2crawler" +217[] = "http://g2crawler.blogspot.com/" +217[] = "" +217[] = "" +217[] = "bot.png" +217[] = "" +217[] = "/list-of-ua/bot-detail?bot=g2crawler" +137[] = "Gaisbot/3.0+(robot@gais.cs.ccu.edu.tw;+http://gais.cs.ccu.edu.tw/robot.php)" +137[] = "Gaisbot" +137[] = "Gaisbot/3.0" +137[] = "http://gais.cs.ccu.edu.tw/robot.php" +137[] = "National Chung Cheng University" +137[] = "http://www.ccu.edu.tw/index_e.htm" +137[] = "bot_gaisbot.png" +137[] = "" +137[] = "/list-of-ua/bot-detail?bot=Gaisbot" +303[] = "Gaisbot/3.0+(robot06@gais.cs.ccu.edu.tw;+http://gais.cs.ccu.edu.tw/robot.php)" +303[] = "Gaisbot" +303[] = "Gaisbot/3.0 - 06" +303[] = "http://gais.cs.ccu.edu.tw/robot.php" +303[] = "National Chung Cheng University" +303[] = "http://www.ccu.edu.tw/index_e.htm" +303[] = "bot_gaisbot.png" +303[] = "" +303[] = "/list-of-ua/bot-detail?bot=Gaisbot" +741[] = "Gallent Search Spider v1.4 Robot 3 (http://www.GallentSearch.com/robot)" +741[] = "Gallent Search Spider" +741[] = "Gallent Search Spider v1.4 Robot 3" +741[] = "" +741[] = "Gallent Limited" +741[] = "http://www.gallentsearch.com/" +741[] = "bot.png" +741[] = "" +741[] = "/list-of-ua/bot-detail?bot=Gallent Search Spider" +6226[] = "GarlikCrawler/1.1 (http://garlik.com/, crawler@garik.com)" +6226[] = "GarlikCrawler" +6226[] = "GarlikCrawler/1.1" +6226[] = "" +6226[] = "Garlik" +6226[] = "http://garlik.com/" +6226[] = "bot.png" +6226[] = "" +6226[] = "/list-of-ua/bot-detail?bot=GarlikCrawler" +190[] = "genieBot (wgao@genieknows.com)" +190[] = "genieBot" +190[] = "genieBot a" +190[] = "http://64.5.245.11/faq/faq.html" +190[] = "IT Interactive Services Inc." +190[] = "http://www.genieknows.com/" +190[] = "bot.png" +190[] = "" +190[] = "/list-of-ua/bot-detail?bot=genieBot" +215[] = "genieBot ((http://64.5.245.11/faq/faq.html))" +215[] = "genieBot" +215[] = "genieBot b" +215[] = "http://64.5.245.11/faq/faq.html" +215[] = "IT Interactive Services Inc." +215[] = "http://www.genieknows.com/" +215[] = "bot.png" +215[] = "" +215[] = "/list-of-ua/bot-detail?bot=genieBot" +1133[] = "GeonaBot/1.2; http://www.geona.com/" +1133[] = "GeonaBot" +1133[] = "GeonaBot/1.2" +1133[] = "http://www.geona.net/about.htm" +1133[] = "Gold Vision Communications" +1133[] = "http://www.goldvision.com/" +1133[] = "bot.png" +1133[] = "" +1133[] = "/list-of-ua/bot-detail?bot=GeonaBot" +1052[] = "Giant/1.0 (Openmaru bot; robot@openmaru.com)" +1052[] = "Giant/1.0" +1052[] = "Giant/1.0" +1052[] = "" +1052[] = "openmaru studio" +1052[] = "http://www.openmaru.com/" +1052[] = "bot.png" +1052[] = "" +1052[] = "/list-of-ua/bot-detail?bot=Giant/1.0" +920[] = "Gigabot/3.0 (http://www.gigablast.com/spider.html)" +920[] = "Gigabot" +920[] = "Gigabot/3.0" +920[] = "http://www.gigablast.com/spider.html" +920[] = "Gigablast Inc" +920[] = "http://www.gigablast.com/" +920[] = "bot_gigabot.png" +920[] = "" +920[] = "/list-of-ua/bot-detail?bot=Gigabot" +1573[] = "GingerCrawler/1.0 (Language Assistant for Dyslexics; www.gingersoftware.com/crawler_agent.htm; support at ginger software dot com)" +1573[] = "GingerCrawler" +1573[] = "GingerCrawler/1.0" +1573[] = "http://www.gingersoftware.com/crawler_agent.htm" +1573[] = "Ginger Software" +1573[] = "http://www.gingersoftware.com/" +1573[] = "bot.png" +1573[] = "" +1573[] = "/list-of-ua/bot-detail?bot=GingerCrawler" +45[] = "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; Girafabot; girafabot at girafa dot com; http://www.girafa.com)" +45[] = "Girafabot" +45[] = "Girafabot" +45[] = "" +45[] = "Girafa Inc." +45[] = "http://www.girafa.com/" +45[] = "bot_girafabot.png" +45[] = "" +45[] = "/list-of-ua/bot-detail?bot=Girafabot" +656[] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Girafabot; girafabot at girafa dot com; http://www.girafa.com)" +656[] = "Girafabot" +656[] = "Girafabot b" +656[] = "" +656[] = "Girafa Inc." +656[] = "http://www.girafa.com/" +656[] = "bot_girafabot.png" +656[] = "" +656[] = "/list-of-ua/bot-detail?bot=Girafabot" +657[] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; Girafabot [girafa.com])" +657[] = "Girafabot" +657[] = "Girafabot c" +657[] = "" +657[] = "Girafa Inc." +657[] = "http://www.girafa.com/" +657[] = "bot_girafabot.png" +657[] = "" +657[] = "/list-of-ua/bot-detail?bot=Girafabot" +226[] = "GOFORITBOT ( http://www.goforit.com/about/ )" +226[] = "GOFORITBOT" +226[] = "GOFORITBOT" +226[] = "http://www.goforit.com/about/" +226[] = "GoForIt Entertainment LLC" +226[] = "http://www.goforit.com/" +226[] = "bot.png" +226[] = "" +226[] = "/list-of-ua/bot-detail?bot=GOFORITBOT" +2133[] = "gonzo2[P] +http://www.suchen.de/faq.html" +2133[] = "gonzo" +2133[] = "gonzo2" +2133[] = "http://www.suchen.de/faq.html" +2133[] = "SEARCHTEQ" +2133[] = "http://www.searchteq.de/" +2133[] = "bot_gonzo.png" +2133[] = "" +2133[] = "/list-of-ua/bot-detail?bot=gonzo" +2132[] = "gonzo1[P] +http://www.suchen.de/faq.html" +2132[] = "gonzo" +2132[] = "gonzo1" +2132[] = "http://www.suchen.de/faq.html" +2132[] = "SEARCHTEQ" +2132[] = "http://www.searchteq.de/" +2132[] = "bot_gonzo.png" +2132[] = "" +2132[] = "/list-of-ua/bot-detail?bot=gonzo" +5380[] = "gonzo/1[P] (+http://www.suchen.de/faq.html)" +5380[] = "gonzo" +5380[] = "gonzo/1" +5380[] = "http://www.suchen.de/faq.html" +5380[] = "SEARCHTEQ" +5380[] = "http://www.searchteq.de/" +5380[] = "bot_gonzo.png" +5380[] = "" +5380[] = "/list-of-ua/bot-detail?bot=gonzo" +25[] = "Googlebot-Image/1.0" +25[] = "Googlebot" +25[] = "Googlebot-Image/1.0" +25[] = "http://www.google.com/bot.html" +25[] = "Google Inc." +25[] = "http://www.google.com/" +25[] = "bot_googlebot.png" +25[] = "" +25[] = "/list-of-ua/bot-detail?bot=Googlebot" +31[] = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" +31[] = "Googlebot" +31[] = "Googlebot/2.1" +31[] = "http://www.google.com/bot.html" +31[] = "Google Inc." +31[] = "http://www.google.com/" +31[] = "bot_googlebot.png" +31[] = "" +31[] = "/list-of-ua/bot-detail?bot=Googlebot" +982[] = "Mediapartners-Google" +982[] = "Googlebot" +982[] = "Mediapartners-Google" +982[] = "http://www.google.com/bot.html" +982[] = "Google Inc." +982[] = "http://www.google.com/" +982[] = "bot_googlebot.png" +982[] = "" +982[] = "/list-of-ua/bot-detail?bot=Googlebot" +4726[] = "Googlebot-Video/1.0" +4726[] = "Googlebot" +4726[] = "Googlebot-Video/1.0" +4726[] = "http://www.google.com/bot.html" +4726[] = "Google Inc." +4726[] = "http://www.google.com/" +4726[] = "bot_googlebot.png" +4726[] = "" +4726[] = "/list-of-ua/bot-detail?bot=Googlebot" +1932[] = "Mozilla/5.0 (compatible; GurujiBot/1.0; +http://www.guruji.com/en/WebmasterFAQ.html)" +1932[] = "GurujiBot" +1932[] = "GurujiBot/1.0" +1932[] = "http://www.guruji.com/en/WebmasterFAQ.html" +1932[] = "Guruji.com Software Private Limited" +1932[] = "http://www.guruji.com/" +1932[] = "bot.png" +1932[] = "" +1932[] = "/list-of-ua/bot-detail?bot=GurujiBot" +5165[] = "Mozilla/5.0 (compatible; Hailoobot/1.2; +http://www.hailoo.com/spider.html)" +5165[] = "Hailoobot" +5165[] = "Hailoobot/1.2" +5165[] = "http://www.hailoo.com/spider.html" +5165[] = "Hailoo" +5165[] = "http://www.hailoo.com/" +5165[] = "bot.png" +5165[] = "" +5165[] = "/list-of-ua/bot-detail?bot=Hailoobot" +756[] = "HatenaScreenshot/1.0 (checker)" +756[] = "HatenaScreenshot" +756[] = "HatenaScreenshot/1.0 (checker)" +756[] = "http://screenshot.hatena.ne.jp/help" +756[] = "hatena" +756[] = "http://www.hatena.ne.jp/company/" +756[] = "bot.png" +756[] = "" +756[] = "/list-of-ua/bot-detail?bot=HatenaScreenshot" +1872[] = "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.8.1.20) Gecko/20090429 HeartRails_Capture/0.6 (+http://capture.heartrails.com/) BonEcho/2.0.0.20" +1872[] = "HeartRails_Capture" +1872[] = "HeartRails_Capture/0.6" +1872[] = "http://capture.heartrails.com/help/question" +1872[] = "HeartRails Inc." +1872[] = "http://www.heartrails.com/" +1872[] = "bot.png" +1872[] = "" +1872[] = "/list-of-ua/bot-detail?bot=HeartRails_Capture" +1546[] = "Mozilla/5.0 (compatible; heritrix/1.12.1 +http://www.webarchiv.cz)" +1546[] = "heritrix" +1546[] = "heritrix/1.12.1" +1546[] = "http://crawler.archive.org/" +1546[] = "Internet Archive" +1546[] = "http://www.archive.org/" +1546[] = "bot_heritrix.png" +1546[] = "" +1546[] = "/list-of-ua/bot-detail?bot=heritrix" +859[] = "Mozilla/5.0 (compatible; heritrix/1.12.0 +http://www.accelobot.com)" +859[] = "heritrix" +859[] = "heritrix/1.12.0" +859[] = "http://crawler.archive.org/" +859[] = "Internet Archive" +859[] = "http://www.archive.org/" +859[] = "bot_heritrix.png" +859[] = "" +859[] = "/list-of-ua/bot-detail?bot=heritrix" +1658[] = "Mozilla/5.0 (compatible; heritrix/1.14.3 +http://archive.org)" +1658[] = "heritrix" +1658[] = "heritrix/1.14.3" +1658[] = "http://crawler.archive.org/" +1658[] = "Internet Archive" +1658[] = "http://www.archive.org/" +1658[] = "bot_heritrix.png" +1658[] = "" +1658[] = "/list-of-ua/bot-detail?bot=heritrix" +1704[] = "Mozilla/5.0 (compatible; heritrix/2.0.2 +http://seekda.com)" +1704[] = "heritrix" +1704[] = "heritrix/2.0.2" +1704[] = "http://crawler.archive.org/" +1704[] = "Internet Archive" +1704[] = "http://www.archive.org/" +1704[] = "bot_heritrix.png" +1704[] = "" +1704[] = "/list-of-ua/bot-detail?bot=heritrix" +1887[] = "Mozilla/5.0 (compatible; heritrix/1.14.2 +http://rjpower.org)" +1887[] = "heritrix" +1887[] = "heritrix/1.14.2" +1887[] = "http://crawler.archive.org/" +1887[] = "Internet Archive" +1887[] = "http://www.archive.org/" +1887[] = "bot_heritrix.png" +1887[] = "" +1887[] = "/list-of-ua/bot-detail?bot=heritrix" +2026[] = "Mozilla/5.0 (compatible; heritrix/2.0.2 +http://aihit.com)" +2026[] = "heritrix" +2026[] = "heritrix/2.0.2" +2026[] = "http://crawler.archive.org/" +2026[] = "Internet Archive" +2026[] = "http://www.archive.org/" +2026[] = "bot_heritrix.png" +2026[] = "" +2026[] = "/list-of-ua/bot-detail?bot=heritrix" +2016[] = "Mozilla/5.0 (compatible; heritrix/1.12.1b +http://netarkivet.dk/website/info.html)" +2016[] = "heritrix" +2016[] = "heritrix/1.12.1b" +2016[] = "http://crawler.archive.org/" +2016[] = "Internet Archive" +2016[] = "http://www.archive.org/" +2016[] = "bot_heritrix.png" +2016[] = "" +2016[] = "/list-of-ua/bot-detail?bot=heritrix" +2021[] = "Mozilla/5.0 (compatible; heritrix/1.14.3 +http://www.webarchiv.cz)" +2021[] = "heritrix" +2021[] = "heritrix/1.14.3" +2021[] = "http://crawler.archive.org/" +2021[] = "Internet Archive" +2021[] = "http://www.archive.org/" +2021[] = "bot_heritrix.png" +2021[] = "" +2021[] = "/list-of-ua/bot-detail?bot=heritrix" +2081[] = "Mozilla/5.0 (compatible; heritrix/1.14.3.r6601 +http://www.buddybuzz.net/yptrino)" +2081[] = "heritrix" +2081[] = "heritrix/1.14.3.r6601" +2081[] = "http://crawler.archive.org/" +2081[] = "Internet Archive" +2081[] = "http://www.archive.org/" +2081[] = "bot_heritrix.png" +2081[] = "" +2081[] = "/list-of-ua/bot-detail?bot=heritrix" +2079[] = "Mozilla/5.0 (compatible; heritrix/3.0.0-SNAPSHOT-20091120.021634 +http://crawler.archive.org)" +2079[] = "heritrix" +2079[] = "heritrix/3.0.0" +2079[] = "http://crawler.archive.org/" +2079[] = "Internet Archive" +2079[] = "http://www.archive.org/" +2079[] = "bot_heritrix.png" +2079[] = "" +2079[] = "/list-of-ua/bot-detail?bot=heritrix" +2947[] = "Mozilla/5.0 (compatible; heritrix/1.14.2 +http://www.webarchiv.cz)" +2947[] = "heritrix" +2947[] = "heritrix/1.14.2" +2947[] = "http://crawler.archive.org/" +2947[] = "Internet Archive" +2947[] = "http://www.archive.org/" +2947[] = "bot_heritrix.png" +2947[] = "" +2947[] = "/list-of-ua/bot-detail?bot=heritrix" +623[] = "HiddenMarket-1.0-beta (www.hiddenmarket.net/crawler.php)" +623[] = "HiddenMarket" +623[] = "HiddenMarket-1.0-beta" +623[] = "http://www.hiddenmarket.net/crawler.php" +623[] = "HiddenMarket Group, Inc." +623[] = "http://www.hiddenmarket.net/" +623[] = "bot.png" +623[] = "" +623[] = "/list-of-ua/bot-detail?bot=HiddenMarket" +1519[] = "holmes/3.12.4 (http://morfeo.centrum.cz/bot)" +1519[] = "Holmes" +1519[] = "holmes/3.12.4 - morfeo" +1519[] = "http://www.ucw.cz/holmes/" +1519[] = "Martin MareÅ¡ and Robert Å palek" +1519[] = "http://www.ucw.cz/holmes/" +1519[] = "bot.png" +1519[] = "" +1519[] = "/list-of-ua/bot-detail?bot=Holmes" +1583[] = "holmes/3.11 (http://morfeo.centrum.cz/bot)" +1583[] = "Holmes" +1583[] = "holmes/3.11" +1583[] = "http://www.ucw.cz/holmes/" +1583[] = "Martin MareÅ¡ and Robert Å palek" +1583[] = "http://www.ucw.cz/holmes/" +1583[] = "bot.png" +1583[] = "" +1583[] = "/list-of-ua/bot-detail?bot=Holmes" +517[] = "holmes/3.9 (onet.pl)" +517[] = "Holmes" +517[] = "holmes/3.9 - onet.pl" +517[] = "http://www.ucw.cz/holmes/" +517[] = "Martin MareÅ¡ and Robert Å palek" +517[] = "http://www.ucw.cz/holmes/" +517[] = "bot.png" +517[] = "" +517[] = "/list-of-ua/bot-detail?bot=Holmes" +554[] = "holmes/3.9 (OnetSzukaj/5.0; +http://szukaj.onet.pl)" +554[] = "Holmes" +554[] = "holmes/3.9 - onet.pl b" +554[] = "http://www.ucw.cz/holmes/" +554[] = "Martin MareÅ¡ and Robert Å palek" +554[] = "http://www.ucw.cz/holmes/" +554[] = "bot.png" +554[] = "" +554[] = "/list-of-ua/bot-detail?bot=Holmes" +669[] = "holmes/3.10.1 (OnetSzukaj/5.0; +http://szukaj.onet.pl)" +669[] = "Holmes" +669[] = "holmes/3.10.1 - onet.pl" +669[] = "http://www.ucw.cz/holmes/" +669[] = "Martin MareÅ¡ and Robert Å palek" +669[] = "http://www.ucw.cz/holmes/" +669[] = "bot.png" +669[] = "" +669[] = "/list-of-ua/bot-detail?bot=Holmes" +927[] = "holmes/3.11 (OnetSzukaj/5.0; +http://szukaj.onet.pl)" +927[] = "Holmes" +927[] = "holmes/3.11 - onet.pl" +927[] = "http://www.ucw.cz/holmes/" +927[] = "Martin MareÅ¡ and Robert Å palek" +927[] = "http://www.ucw.cz/holmes/" +927[] = "bot.png" +927[] = "" +927[] = "/list-of-ua/bot-detail?bot=Holmes" +3600[] = "HolmesBot (http://holmes.ge)" +3600[] = "HolmesBot" +3600[] = "HolmesBot" +3600[] = "" +3600[] = "Georgian Railway Telecom" +3600[] = "http://grt.ge/" +3600[] = "bot.png" +3600[] = "" +3600[] = "/list-of-ua/bot-detail?bot=HolmesBot" +281[] = "HooWWWer/2.1.3 (debugging run) (+http://cosco.hiit.fi/search/hoowwwer/ | mailto:crawler-infohiit.fi)" +281[] = "HooWWWer" +281[] = "HooWWWer/2.1.3" +281[] = "http://cosco.hiit.fi/search/hoowwwer/" +281[] = "CoSCo" +281[] = "http://cosco.hiit.fi/" +281[] = "bot.png" +281[] = "" +281[] = "/list-of-ua/bot-detail?bot=HooWWWer" +307[] = "HooWWWer/2.2.0 (debugging run) (+http://cosco.hiit.fi/search/hoowwwer/ | mailto:crawler-infohiit.fi)" +307[] = "HooWWWer" +307[] = "HooWWWer/2.2.0" +307[] = "http://cosco.hiit.fi/search/hoowwwer/" +307[] = "CoSCo" +307[] = "http://cosco.hiit.fi/" +307[] = "bot.png" +307[] = "" +307[] = "/list-of-ua/bot-detail?bot=HooWWWer" +3235[] = "Mozilla/4.0 (compatible; HostTracker.com/1.0;+http://host-tracker.com/)" +3235[] = "HostTracker.com" +3235[] = "HostTracker.com/1.0" +3235[] = "http://host-tracker.com/" +3235[] = "host-tracker.com " +3235[] = "" +3235[] = "bot_HostTracker.com.png" +3235[] = "" +3235[] = "/list-of-ua/bot-detail?bot=HostTracker.com" +805[] = "cinetic_htdig" +805[] = "ht://Dig" +805[] = "ht://Dig" +805[] = "" +805[] = "The ht://Dig Group" +805[] = "http://htdig.sourceforge.net/" +805[] = "bot.png" +805[] = "" +805[] = "/list-of-ua/bot-detail?bot=ht://Dig" +5302[] = "HuaweiSymantecSpider/1.0+DSE-support@huaweisymantec.com+(compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR ; http://www.huaweisymantec.com/en/IRL/spider)" +5302[] = "HuaweiSymantecSpider" +5302[] = "HuaweiSymantecSpider/1.0" +5302[] = "http://www.huaweisymantec.com/en/IRL/spider/" +5302[] = "Huawei Symantec Technologies Co.,Ltd." +5302[] = "http://www.huaweisymantec.com/" +5302[] = "bot.png" +5302[] = "" +5302[] = "/list-of-ua/bot-detail?bot=HuaweiSymantecSpider" +761[] = "iaskspider/2.0(+http://iask.com/help/help_index.html)" +761[] = "iaskspider" +761[] = "iaskspider/2.0" +761[] = "http://iask.com/help/help_index.html" +761[] = "SINA Corporation" +761[] = "http://corp.sina.com.cn/eng/" +761[] = "bot.png" +761[] = "" +761[] = "/list-of-ua/bot-detail?bot=iaskspider" +155[] = "ia_archiver-web.archive.org" +155[] = "ia_archiver" +155[] = "ia_archiver" +155[] = "http://www.alexa.com/site/help/webmasters" +155[] = "Alexa Internet, Inc." +155[] = "http://www.alexa.com/" +155[] = "bot_ia_archiver.png" +155[] = "" +155[] = "/list-of-ua/bot-detail?bot=ia_archiver" +1461[] = "ia_archiver (+http://www.alexa.com/site/help/webmasters; crawler@alexa.com)" +1461[] = "ia_archiver" +1461[] = "ia_archiver alexa" +1461[] = "http://www.alexa.com/site/help/webmasters" +1461[] = "Alexa Internet, Inc." +1461[] = "http://www.alexa.com/" +1461[] = "bot_ia_archiver.png" +1461[] = "" +1461[] = "/list-of-ua/bot-detail?bot=ia_archiver" +1738[] = "ICC-Crawler(Mozilla-compatible; ; http://kc.nict.go.jp/project1/crawl.html)" +1738[] = "ICC-Crawler" +1738[] = "ICC-Crawler" +1738[] = "http://kc.nict.go.jp/project1/crawl.html" +1738[] = "NICT" +1738[] = "http://nict.go.jp/" +1738[] = "bot.png" +1738[] = "" +1738[] = "/list-of-ua/bot-detail?bot=ICC-Crawler" +1765[] = "ICC-Crawler/2.0 (Mozilla-compatible; ; http://kc.nict.go.jp/project1/crawl.html)" +1765[] = "ICC-Crawler" +1765[] = "ICC-Crawler/2.0" +1765[] = "http://kc.nict.go.jp/project1/crawl.html" +1765[] = "NICT" +1765[] = "http://nict.go.jp/" +1765[] = "bot.png" +1765[] = "" +1765[] = "/list-of-ua/bot-detail?bot=ICC-Crawler" +1044[] = "ICF_Site_Crawler+(see+http://www.infocenter.fi/spiderinfo.html)" +1044[] = "ICF_Site_Crawler" +1044[] = "ICF_Site_Crawler" +1044[] = "http://www.infocenter.fi/spiderinfo.html" +1044[] = "Info Center Finland Ltd." +1044[] = "http://www.infocenter.fi/" +1044[] = "bot.png" +1044[] = "" +1044[] = "/list-of-ua/bot-detail?bot=ICF_Site_Crawler" +124[] = "ichiro/1.0 (ichiro@nttr.co.jp)" +124[] = "ichiro" +124[] = "ichiro/1.0" +124[] = "http://help.goo.ne.jp/door/crawler.html" +124[] = "NTT-Resonant Inc." +124[] = "http://www.nttr.co.jp/" +124[] = "bot_ichiro.png" +124[] = "" +124[] = "/list-of-ua/bot-detail?bot=ichiro" +144[] = "ichiro/2.0 (ichiro@nttr.co.jp)" +144[] = "ichiro" +144[] = "ichiro/2.0" +144[] = "http://help.goo.ne.jp/door/crawler.html" +144[] = "NTT-Resonant Inc." +144[] = "http://www.nttr.co.jp/" +144[] = "bot_ichiro.png" +144[] = "" +144[] = "/list-of-ua/bot-detail?bot=ichiro" +223[] = "ichiro/2.0 (http://help.goo.ne.jp/door/crawler.html)" +223[] = "ichiro" +223[] = "ichiro/2.0" +223[] = "http://help.goo.ne.jp/door/crawler.html" +223[] = "NTT-Resonant Inc." +223[] = "http://www.nttr.co.jp/" +223[] = "bot_ichiro.png" +223[] = "" +223[] = "/list-of-ua/bot-detail?bot=ichiro" +540[] = "ichiro/2.01 (http://help.goo.ne.jp/door/crawler.html)" +540[] = "ichiro" +540[] = "ichiro/2.01" +540[] = "http://help.goo.ne.jp/door/crawler.html" +540[] = "NTT-Resonant Inc." +540[] = "http://www.nttr.co.jp/" +540[] = "bot_ichiro.png" +540[] = "" +540[] = "/list-of-ua/bot-detail?bot=ichiro" +1197[] = "ichiro/3.0 (http://help.goo.ne.jp/door/crawler.html)" +1197[] = "ichiro" +1197[] = "ichiro/3.0" +1197[] = "http://help.goo.ne.jp/door/crawler.html" +1197[] = "NTT-Resonant Inc." +1197[] = "http://www.nttr.co.jp/" +1197[] = "bot_ichiro.png" +1197[] = "" +1197[] = "/list-of-ua/bot-detail?bot=ichiro" +3445[] = "ichiro/4.0 (http://help.goo.ne.jp/door/crawler.html)" +3445[] = "ichiro" +3445[] = "ichiro/4.0" +3445[] = "http://help.goo.ne.jp/door/crawler.html" +3445[] = "NTT-Resonant Inc." +3445[] = "http://www.nttr.co.jp/" +3445[] = "bot_ichiro.png" +3445[] = "" +3445[] = "/list-of-ua/bot-detail?bot=ichiro" +5902[] = "ichiro/5.0 (http://help.goo.ne.jp/door/crawler.html)" +5902[] = "ichiro" +5902[] = "ichiro/5.0" +5902[] = "http://help.goo.ne.jp/door/crawler.html" +5902[] = "NTT-Resonant Inc." +5902[] = "http://www.nttr.co.jp/" +5902[] = "bot_ichiro.png" +5902[] = "" +5902[] = "/list-of-ua/bot-detail?bot=ichiro" +5862[] = "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.0.1; compatible; iCjobs Stellenangebote Jobs; http://www.icjobs.de) Gecko/20100401 iCjobs/3.2.3" +5862[] = "iCjobs" +5862[] = "iCjobs/3.2.3" +5862[] = "http://www.icjobs.de/bot.htm" +5862[] = "Intelligence Competence Center AG" +5862[] = "http://www.iccenter.net/" +5862[] = "bot.png" +5862[] = "" +5862[] = "/list-of-ua/bot-detail?bot=iCjobs" +764[] = "IlseBot/1.1" +764[] = "IlseBot" +764[] = "IlseBot/1.1" +764[] = "" +764[] = "ilse.nl" +764[] = "http://ilse.nl/" +764[] = "bot.png" +764[] = "" +764[] = "/list-of-ua/bot-detail?bot=IlseBot" +378[] = "IlTrovatore/1.2 (IlTrovatore; http://www.iltrovatore.it/bot.html; bot@iltrovatore.it)" +378[] = "IlTrovatore" +378[] = "IlTrovatore/1.2" +378[] = "http://www.iltrovatore.it/bot.html" +378[] = "Il Trovatore" +378[] = "http://www.iltrovatore.it/" +378[] = "bot.png" +378[] = "" +378[] = "/list-of-ua/bot-detail?bot=IlTrovatore" +81[] = "IlTrovatore-Setaccio/1.2 (It search engine; http://www.iltrovatore.it/bot.html; bot@iltrovatore.it)" +81[] = "IlTrovatore-Setaccio" +81[] = "IlTrovatore-Setaccio/1.2" +81[] = "http://www.iltrovatore.it/bot.html" +81[] = "Il Trovatore" +81[] = "http://www.iltrovatore.it/" +81[] = "bot.png" +81[] = "" +81[] = "/list-of-ua/bot-detail?bot=IlTrovatore-Setaccio" +168[] = "IlTrovatore-Setaccio/1.2 (Italy search engine; http://www.iltrovatore.it/bot.html; bot@iltrovatore.it)" +168[] = "IlTrovatore-Setaccio" +168[] = "IlTrovatore-Setaccio/1.2 b" +168[] = "http://www.iltrovatore.it/bot.html" +168[] = "Il Trovatore" +168[] = "http://www.iltrovatore.it/" +168[] = "bot.png" +168[] = "" +168[] = "/list-of-ua/bot-detail?bot=IlTrovatore-Setaccio" +85[] = "InfociousBot (+http://corp.infocious.com/tech_crawler.php)" +85[] = "InfociousBot" +85[] = "InfociousBot b" +85[] = "http://corp.infocious.com/tech_craw.php" +85[] = "Infocious Inc." +85[] = "http://corp.infocious.com/" +85[] = "bot.png" +85[] = "" +85[] = "/list-of-ua/bot-detail?bot=InfociousBot" +882[] = "InternetSeer.com" +882[] = "InternetSeer" +882[] = "InternetSeer (Web Monitor)" +882[] = "" +882[] = "InternetSeer" +882[] = "http://internetseer.com/" +882[] = "bot.png" +882[] = "" +882[] = "/list-of-ua/bot-detail?bot=InternetSeer" +167[] = "Ipselonbot/0.47-beta (Ipselon; http://www.ipselon.com/intl/en/ipselonbot.html; ipselonbot@ipselon.com)" +167[] = "Ipselonbot" +167[] = "Ipselonbot/0.47-beta" +167[] = "http://www.ipselon.com/intl/en/ipselonbot.html" +167[] = "Ipselon Networks s.l." +167[] = "http://www.ipselon.com/" +167[] = "bot.png" +167[] = "" +167[] = "/list-of-ua/bot-detail?bot=Ipselonbot" +197[] = "Ipselonbot/1.0-beta (+; http://www.ipselon.com/intl/en/ipselonbot.html)" +197[] = "Ipselonbot" +197[] = "Ipselonbot/1.0-beta" +197[] = "http://www.ipselon.com/intl/en/ipselonbot.html" +197[] = "Ipselon Networks s.l." +197[] = "http://www.ipselon.com/" +197[] = "bot.png" +197[] = "" +197[] = "/list-of-ua/bot-detail?bot=Ipselonbot" +242[] = "IRLbot/2.0 (+http://irl.cs.tamu.edu/crawler)" +242[] = "IRLbot" +242[] = "IRLbot/2.0" +242[] = "http://irl.cs.tamu.edu/crawler/" +242[] = "Texas A&M University" +242[] = "http://www.tamu.edu/" +242[] = "bot.png" +242[] = "" +242[] = "/list-of-ua/bot-detail?bot=IRLbot" +267[] = "IRLbot/2.0 (compatible; MSIE 6.0; http://irl.cs.tamu.edu/crawler)" +267[] = "IRLbot" +267[] = "IRLbot/2.0 b" +267[] = "http://irl.cs.tamu.edu/crawler/" +267[] = "Texas A&M University" +267[] = "http://www.tamu.edu/" +267[] = "bot.png" +267[] = "" +267[] = "/list-of-ua/bot-detail?bot=IRLbot" +729[] = "IRLbot/3.0 (compatible; MSIE 6.0; http://irl.cs.tamu.edu/crawler)" +729[] = "IRLbot" +729[] = "IRLbot/3.0" +729[] = "http://irl.cs.tamu.edu/crawler/" +729[] = "Texas A&M University" +729[] = "http://www.tamu.edu/" +729[] = "bot.png" +729[] = "" +729[] = "/list-of-ua/bot-detail?bot=IRLbot" +1220[] = "IRLbot/3.0 (compatible; MSIE 6.0; http://irl.cs.tamu.edu/crawler/)" +1220[] = "IRLbot" +1220[] = "IRLbot/3.0 b" +1220[] = "http://irl.cs.tamu.edu/crawler/" +1220[] = "Texas A&M University" +1220[] = "http://www.tamu.edu/" +1220[] = "bot.png" +1220[] = "" +1220[] = "/list-of-ua/bot-detail?bot=IRLbot" +1540[] = "JadynAve - http://www.jadynave.com/robot" +1540[] = "JadynAve" +1540[] = "JadynAve" +1540[] = "" +1540[] = "Yesup Ecommerce Solutions Inc" +1540[] = "http://www.yesup.net/" +1540[] = "bot.png" +1540[] = "" +1540[] = "/list-of-ua/bot-detail?bot=JadynAve" +1859[] = "Mozilla/5.0 (compatible; JadynAveBot; +http://www.jadynave.com/robot)" +1859[] = "JadynAveBot" +1859[] = "JadynAveBot" +1859[] = "http://www.jadynave.com/robot" +1859[] = "Yesup Ecommerce Solutions Inc." +1859[] = "http://www.yesup.net/" +1859[] = "bot.png" +1859[] = "" +1859[] = "/list-of-ua/bot-detail?bot=JadynAveBot" +797[] = "Jambot/0.1.1 (Jambot; http://www.jambot.com/blog; crawler@jambot.com)" +797[] = "Jambot" +797[] = "Jambot/0.1.1" +797[] = "http://www.jambot.com/blog/static.php?page=webmaster-robot" +797[] = "" +797[] = "" +797[] = "bot.png" +797[] = "" +797[] = "/list-of-ua/bot-detail?bot=Jambot" +5202[] = "JUST-CRAWLER(+http://www.justsystems.com/jp/tech/crawler/)" +5202[] = "JUST-CRAWLER" +5202[] = "JUST-CRAWLER" +5202[] = "http://www.justsystems.com/jp/tech/crawler/" +5202[] = "JustSystems Corporation" +5202[] = "http://www.justsystems.com/" +5202[] = "bot.png" +5202[] = "" +5202[] = "/list-of-ua/bot-detail?bot=JUST-CRAWLER" +5[] = "Jyxobot/1" +5[] = "Jyxobot" +5[] = "Jyxobot" +5[] = "" +5[] = "Jyxo s.r.o." +5[] = "http://jyxo.cz/" +5[] = "bot_Jyxobot.png" +5[] = "" +5[] = "/list-of-ua/bot-detail?bot=Jyxobot" +1599[] = "JyxobotRSS/0.06" +1599[] = "Jyxobot" +1599[] = "JyxobotRSS/0.06" +1599[] = "" +1599[] = "Jyxo s.r.o." +1599[] = "http://jyxo.cz/" +1599[] = "bot_Jyxobot.png" +1599[] = "" +1599[] = "/list-of-ua/bot-detail?bot=Jyxobot" +391[] = "kakle-spider/0.1 (kakle-spider; http://www.kakle.com/bot.html; support@kakle.com)" +391[] = "Kakle Bot" +391[] = "kakle-spider/0.1" +391[] = "http://www.kakle.com/bot.html" +391[] = "Kakle Inc." +391[] = "http://www.kakle.com" +391[] = "bot.png" +391[] = "" +391[] = "/list-of-ua/bot-detail?bot=Kakle Bot" +1524[] = "kalooga/KaloogaBot (Kalooga; http://www.kalooga.com/info.html?page=crawler)" +1524[] = "Kalooga" +1524[] = "Kalooga" +1524[] = "http://www.kalooga.com/info.html?page=crawler" +1524[] = "Kalooga" +1524[] = "http://www.kalooga.com/" +1524[] = "bot.png" +1524[] = "" +1524[] = "/list-of-ua/bot-detail?bot=Kalooga" +1484[] = "kalooga/KaloogaBot (Kalooga; http://www.kalooga.com/info.html?page=crawler; crawler@kalooga.com)" +1484[] = "Kalooga" +1484[] = "Kalooga" +1484[] = "http://www.kalooga.com/info.html?page=crawler" +1484[] = "Kalooga" +1484[] = "http://www.kalooga.com/" +1484[] = "bot.png" +1484[] = "" +1484[] = "/list-of-ua/bot-detail?bot=Kalooga" +3292[] = "Karneval-Bot (Version: 1.06, powered by www.karnevalsuchmaschine.de +http://www.karnevalsuchmaschine.de/bot.html)" +3292[] = "Karneval-Bot" +3292[] = "Karneval-Bot/1.06" +3292[] = "http://www.karnevalsuchmaschine.de/zeige/bot.html" +3292[] = "Föderation Europäischer Narren" +3292[] = "http://www.fen-sued.de/" +3292[] = "bot.png" +3292[] = "" +3292[] = "/list-of-ua/bot-detail?bot=Karneval-Bot" +1542[] = "KeywenBot/4.1 http://www.keywen.com/Encyclopedia/Links" +1542[] = "KeywenBot" +1542[] = "KeywenBot/4.1" +1542[] = "http://www.keywen.com/Encyclopedia/Links/" +1542[] = "Michael Charnine" +1542[] = "" +1542[] = "bot.png" +1542[] = "" +1542[] = "/list-of-ua/bot-detail?bot=KeywenBot" +539[] = "Kongulo v0.1 personal web crawler" +539[] = "Kongulo" +539[] = "Kongulo v0.1" +539[] = "http://goog-kongulo.sourceforge.net/" +539[] = "Google Inc." +539[] = "http://www.google.com/" +539[] = "bot.png" +539[] = "" +539[] = "/list-of-ua/bot-detail?bot=Kongulo" +479[] = "KRetrieve/1.1/dbsearchexpert.com" +479[] = "KRetrieve" +479[] = "KRetrieve/1.1" +479[] = "http://www.dbsearchexpert.com/" +479[] = "" +479[] = "" +479[] = "bot.png" +479[] = "" +479[] = "/list-of-ua/bot-detail?bot=KRetrieve" +396[] = "Krugle/Krugle,Nutch/0.8+ (Krugle web crawler; http://www.krugle.com/crawler/info.html; webcrawler@krugle.com)" +396[] = "Krugle" +396[] = "Krugle (Nutch/0.8+)" +396[] = "http://corp.krugle.com/crawler/info.html" +396[] = "Steve Larsen" +396[] = "http://blog.krugle.com/?page_id=5" +396[] = "bot.png" +396[] = "" +396[] = "/list-of-ua/bot-detail?bot=Krugle" +633[] = "Krugle/Krugle,Nutch/0.8+ (Krugle web crawler; http://corp.krugle.com/crawler/info.html; webcrawler@krugle.com)" +633[] = "Krugle" +633[] = "Krugle (Nutch/0.8+) b" +633[] = "http://corp.krugle.com/crawler/info.html" +633[] = "Steve Larsen" +633[] = "http://blog.krugle.com/?page_id=5" +633[] = "bot.png" +633[] = "" +633[] = "/list-of-ua/bot-detail?bot=Krugle" +83[] = "ksibot/5.2m (+http://ego.ms.mff.cuni.cz/)" +83[] = "ksibot" +83[] = "ksibot/5.2m" +83[] = "http://ego.ms.mff.cuni.cz/" +83[] = "Katedra softwarového inženýrství" +83[] = "http://kocour.ms.mff.cuni.cz/" +83[] = "bot.png" +83[] = "" +83[] = "/list-of-ua/bot-detail?bot=ksibot" +266[] = "ksibot/7.0d (+http://ego.ms.mff.cuni.cz/)" +266[] = "ksibot" +266[] = "ksibot/7.0d" +266[] = "http://ego.ms.mff.cuni.cz/" +266[] = "Katedra softwarového inženýrství" +266[] = "http://kocour.ms.mff.cuni.cz/" +266[] = "bot.png" +266[] = "" +266[] = "/list-of-ua/bot-detail?bot=ksibot" +405[] = "ksibot/8.0a (+http://ego.ms.mff.cuni.cz/)" +405[] = "ksibot" +405[] = "ksibot/8.0a" +405[] = "http://ego.ms.mff.cuni.cz/" +405[] = "Katedra softwarového inženýrství" +405[] = "http://kocour.ms.mff.cuni.cz/" +405[] = "bot.png" +405[] = "" +405[] = "/list-of-ua/bot-detail?bot=ksibot" +4264[] = "L.webis/0.50 (http://webalgo.iit.cnr.it/index.php?pg=lwebis)" +4264[] = "L.webis" +4264[] = "L.webis/0.50" +4264[] = "http://webalgo.iit.cnr.it/index.php?pg=lwebis" +4264[] = "Institute of Informatics and Telematics (IIT)" +4264[] = "http://www.iit.cnr.it/" +4264[] = "bot_L.webis.png" +4264[] = "" +4264[] = "/list-of-ua/bot-detail?bot=L.webis" +4590[] = "L.webis/0.51 (http://webalgo.iit.cnr.it/index.php?pg=lwebis)" +4590[] = "L.webis" +4590[] = "L.webis/0.51" +4590[] = "http://webalgo.iit.cnr.it/index.php?pg=lwebis" +4590[] = "Institute of Informatics and Telematics (IIT)" +4590[] = "http://www.iit.cnr.it/" +4590[] = "bot_L.webis.png" +4590[] = "" +4590[] = "/list-of-ua/bot-detail?bot=L.webis" +4591[] = "L.webis/0.53 (http://webalgo.iit.cnr.it/index.php?pg=lwebis)" +4591[] = "L.webis" +4591[] = "L.webis/0.53" +4591[] = "http://webalgo.iit.cnr.it/index.php?pg=lwebis" +4591[] = "Institute of Informatics and Telematics (IIT)" +4591[] = "http://www.iit.cnr.it/" +4591[] = "bot_L.webis.png" +4591[] = "" +4591[] = "/list-of-ua/bot-detail?bot=L.webis" +3398[] = "L.webis/0.44 (http://webalgo.iit.cnr.it/index.php?pg=lwebis)" +3398[] = "L.webis" +3398[] = "L.webis/0.44" +3398[] = "http://webalgo.iit.cnr.it/index.php?pg=lwebis" +3398[] = "Institute of Informatics and Telematics (IIT)" +3398[] = "http://www.iit.cnr.it/" +3398[] = "bot_L.webis.png" +3398[] = "" +3398[] = "/list-of-ua/bot-detail?bot=L.webis" +631[] = "LapozzBot/1.4 (+http://robot.lapozz.hu)" +631[] = "LapozzBot" +631[] = "LapozzBot/1.4 hu" +631[] = "http://robot.lapozz.hu/" +631[] = "lapozz.hu" +631[] = "http://www.lapozz.hu/" +631[] = "bot.png" +631[] = "" +631[] = "/list-of-ua/bot-detail?bot=LapozzBot" +632[] = "LapozzBot/1.4 (+http://robot.lapozz.com)" +632[] = "LapozzBot" +632[] = "LapozzBot/1.4 com" +632[] = "http://robot.lapozz.com/" +632[] = "lapozz.hu" +632[] = "http://www.lapozz.hu/" +632[] = "bot_lapozzbot.png" +632[] = "" +632[] = "/list-of-ua/bot-detail?bot=LapozzBot" +881[] = "Larbin (larbin2.6.3@unspecified.mail)" +881[] = "Larbin" +881[] = "Larbin/2.6.3" +881[] = "" +881[] = "Sebastien Ailleret" +881[] = "http://larbin.sourceforge.net/" +881[] = "bot.png" +881[] = "" +881[] = "/list-of-ua/bot-detail?bot=Larbin" +778[] = "LarbinWebCrawler (spider@download11.com)" +778[] = "LarbinWebCrawler" +778[] = "LarbinWebCrawler" +778[] = "" +778[] = "Download11.com" +778[] = "http://download11.com/" +778[] = "bot.png" +778[] = "" +778[] = "/list-of-ua/bot-detail?bot=LarbinWebCrawler" +1780[] = "LexxeBot/1.0 (lexxebot@lexxe.com)" +1780[] = "LexxeBot" +1780[] = "LexxeBot/1.0" +1780[] = "http://lexxe.com/about/webmasters.cfm" +1780[] = "Lexxe Pty Ltd" +1780[] = "http://lexxe.com/" +1780[] = "bot.png" +1780[] = "" +1780[] = "/list-of-ua/bot-detail?bot=LexxeBot" +5180[] = "Lijit Crawler (+http://www.lijit.com/robot/crawler)" +5180[] = "Lijit" +5180[] = "Lijit" +5180[] = "http://www.lijit.com/robot/crawler" +5180[] = "Lijit Networks Inc." +5180[] = "http://www.lijit.com/" +5180[] = "bot.png" +5180[] = "" +5180[] = "/list-of-ua/bot-detail?bot=Lijit" +1504[] = "LinguaBot/v0.001-dev (MultiLinual Sarch Engine v0.001; LinguaSeek; admin at linguaseek dot com)" +1504[] = "LinguaBot" +1504[] = "LinguaBot/v0.001-dev" +1504[] = "" +1504[] = "linguaseek.com " +1504[] = "http://linguaseek.com/" +1504[] = "bot.png" +1504[] = "" +1504[] = "/list-of-ua/bot-detail?bot=LinguaBot" +2155[] = "Linguee Bot (http://www.linguee.com/bot)" +2155[] = "Linguee Bot" +2155[] = "Linguee Bot" +2155[] = "http://www.linguee.com/bot" +2155[] = "Linguee GmbH" +2155[] = "http://www.linguee.com/" +2155[] = "bot_Linguee.png" +2155[] = "" +2155[] = "/list-of-ua/bot-detail?bot=Linguee Bot" +481[] = "Link Valet Online 1.1" +481[] = "Link Valet Online" +481[] = "Link Valet Online 1.1" +481[] = "http://valet.htmlhelp.com/" +481[] = "Web Design Group" +481[] = "http://www.htmlhelp.com/" +481[] = "bot.png" +481[] = "" +481[] = "/list-of-ua/bot-detail?bot=Link Valet Online" +483[] = "Link Valet Online 1.2" +483[] = "Link Valet Online" +483[] = "Link Valet Online 1.2" +483[] = "http://valet.htmlhelp.com/" +483[] = "Web Design Group" +483[] = "http://www.htmlhelp.com/" +483[] = "bot.png" +483[] = "" +483[] = "/list-of-ua/bot-detail?bot=Link Valet Online" +1798[] = "LinkAider (http://linkaider.com/crawler/)" +1798[] = "LinkAider" +1798[] = "LinkAider" +1798[] = "http://linkaider.com/crawler/" +1798[] = "Ivinco" +1798[] = "http://linkaider.com/" +1798[] = "bot.png" +1798[] = "" +1798[] = "/list-of-ua/bot-detail?bot=LinkAider" +6044[] = "linkdex.com/v2.0" +6044[] = "linkdex.com" +6044[] = "linkdex.com/v2.0" +6044[] = "" +6044[] = "Linkdex Limited" +6044[] = "http://www.linkdex.com/" +6044[] = "bot.png" +6044[] = "" +6044[] = "/list-of-ua/bot-detail?bot=linkdex.com" +774[] = "Mozilla/5.0 (compatible; LinksManager.com_bot +http://linksmanager.com/linkchecker.html)" +774[] = "linksmanager_bot" +774[] = "linksmanager_bot" +774[] = "http://linksmanager.com/linkchecker.html" +774[] = "CreativeNetVentures, Inc." +774[] = "http://cnvi.com/" +774[] = "bot.png" +774[] = "" +774[] = "/list-of-ua/bot-detail?bot=linksmanager_bot" +130[] = "LinkWalker" +130[] = "LinkWalker" +130[] = "LinkWalker" +130[] = "" +130[] = "SEVENtwentyfour Inc." +130[] = "http://www.seventwentyfour.com/" +130[] = "bot.png" +130[] = "" +130[] = "/list-of-ua/bot-detail?bot=LinkWalker" +678[] = "LinkWalker/2.0" +678[] = "LinkWalker" +678[] = "LinkWalker/2.0" +678[] = "" +678[] = "SEVENtwentyfour Inc." +678[] = "http://www.seventwentyfour.com/" +678[] = "bot.png" +678[] = "" +678[] = "/list-of-ua/bot-detail?bot=LinkWalker" +4844[] = "livedoor ScreenShot/0.10" +4844[] = "livedoor ScreenShot" +4844[] = "livedoor ScreenShot/0.10" +4844[] = "http://helpguide.livedoor.com/help/screenshot/qa/grp584?id=3042" +4844[] = "livedoor Co.,Ltd." +4844[] = "http://corp.livedoor.com/" +4844[] = "bot.png" +4844[] = "" +4844[] = "/list-of-ua/bot-detail?bot=livedoor ScreenShot" +20[] = "lmspider (lmspider@scansoft.com)" +20[] = "lmspider" +20[] = "lmspider" +20[] = "http://www.nuance.com/" +20[] = "Nuance Communications, Inc." +20[] = "http://www.nuance.com/" +20[] = "bot.png" +20[] = "" +20[] = "/list-of-ua/bot-detail?bot=lmspider" +820[] = "lmspider/Nutch-0.9-dev (For research purposes.; www.nuance.com)" +820[] = "lmspider" +820[] = "lmspider b" +820[] = "http://www.nuance.com/" +820[] = "Nuance Communications, Inc." +820[] = "http://www.nuance.com/" +820[] = "bot.png" +820[] = "" +820[] = "/list-of-ua/bot-detail?bot=lmspider" +4996[] = "magpie-crawler/1.1 (U; Linux amd64; en-GB; +http://www.brandwatch.net)" +4996[] = "magpie-crawler" +4996[] = "magpie-crawler/1.1" +4996[] = "http://www.brandwatch.com/how-it-works/gathering-data/" +4996[] = "Brandwatch" +4996[] = "http://www.brandwatch.com/" +4996[] = "bot.png" +4996[] = "" +4996[] = "/list-of-ua/bot-detail?bot=magpie-crawler" +1210[] = "Mahiti.Com/Mahiti Crawler-1.0 (Mahiti.Com; http://mahiti.com ; mahiti.com)" +1210[] = "Mahiti Crawler" +1210[] = "Mahiti Crawler-1.0" +1210[] = "" +1210[] = "Mahiti.Com" +1210[] = "http://mahiti.com/" +1210[] = "bot.png" +1210[] = "" +1210[] = "/list-of-ua/bot-detail?bot=Mahiti Crawler" +1502[] = "Mail.Ru/1.0" +1502[] = "Mail.Ru" +1502[] = "Mail.Ru/1.0" +1502[] = "" +1502[] = "Mail.Ru" +1502[] = "http://corp.mail.ru/" +1502[] = "bot.png" +1502[] = "" +1502[] = "/list-of-ua/bot-detail?bot=Mail.Ru" +6134[] = "Mail.RU/2.0" +6134[] = "Mail.Ru" +6134[] = "Mail.Ru/2.0" +6134[] = "" +6134[] = "Mail.Ru" +6134[] = "http://corp.mail.ru/" +6134[] = "bot.png" +6134[] = "" +6134[] = "/list-of-ua/bot-detail?bot=Mail.Ru" +525[] = "Megatext/Nutch-0.8.1 (Beta; http://www.megatext.cz/; microton@microton.cz)" +525[] = "Megatext" +525[] = "Megatext-0.8.1 beta" +525[] = "" +525[] = "Microton, s.r.o." +525[] = "http://www.microton.cz/" +525[] = "bot.png" +525[] = "" +525[] = "/list-of-ua/bot-detail?bot=Megatext" +609[] = "Megatext/Megatext-0.5 (beta; http://www.megatext.cz/; microton@microton.cz)" +609[] = "Megatext" +609[] = "Megatext-0.5 beta" +609[] = "" +609[] = "Microton, s.r.o." +609[] = "http://www.microton.cz/" +609[] = "bot.png" +609[] = "" +609[] = "/list-of-ua/bot-detail?bot=Megatext" +5960[] = "MetaGeneratorCrawler/1.1 (www.metagenerator.info)" +5960[] = "MetaGeneratorCrawler" +5960[] = "MetaGeneratorCrawler/1.1" +5960[] = "http://www.metagenerator.info/" +5960[] = "Jan Bogutzki" +5960[] = "http://jan.bogutzki.de/" +5960[] = "bot.png" +5960[] = "" +5960[] = "/list-of-ua/bot-detail?bot=MetaGeneratorCrawler" +5280[] = "Mozilla/5.0 (compatible; MetamojiCrawler/1.0; +http://www.metamoji.com/jp/crawler.html" +5280[] = "MetamojiCrawler" +5280[] = "MetamojiCrawler/1.0" +5280[] = "http://www.metamoji.com/jp/crawler.html" +5280[] = "MetaMoJi Corporation" +5280[] = "http://www.metamoji.com/" +5280[] = "bot.png" +5280[] = "" +5280[] = "/list-of-ua/bot-detail?bot=MetamojiCrawler" +114[] = "Metaspinner/0.01 (Metaspinner; http://www.meta-spinner.de/; support@meta-spinner.de/)" +114[] = "Metaspinner/0.01" +114[] = "Metaspinner/0.01" +114[] = "http://www.meta-spinner.de/" +114[] = "metaspinnner media GmbH" +114[] = "http://www.metaspinner-media.de/" +114[] = "bot.png" +114[] = "" +114[] = "/list-of-ua/bot-detail?bot=Metaspinner/0.01" +295[] = "MetaTagRobot/1.6 (http://www.widexl.com/remote/search-engines/metatag-analyzer.html)" +295[] = "MetaTagRobot" +295[] = "MetaTagRobot/1.6" +295[] = "http://www.widexl.com/remote/search-engines/metatag-analyzer.html" +295[] = "widexl.com" +295[] = "http://www.widexl.com/" +295[] = "bot.png" +295[] = "" +295[] = "/list-of-ua/bot-detail?bot=MetaTagRobot" +496[] = "MetaTagRobot/2.1 (http://www.widexl.com/remote/search-engines/metatag-analyzer.html)" +496[] = "MetaTagRobot" +496[] = "MetaTagRobot/2.1" +496[] = "http://www.widexl.com/remote/search-engines/metatag-analyzer.html" +496[] = "" +496[] = "http://www.widexl.com/" +496[] = "bot.png" +496[] = "" +496[] = "/list-of-ua/bot-detail?bot=MetaTagRobot" +4589[] = "MetaURI API +metauri.com" +4589[] = "MetaURI" +4589[] = "MetaURI" +4589[] = "http://metauri.com/static/about" +4589[] = "Stateless Systems" +4589[] = "http://statelesssystems.com/" +4589[] = "bot_MetaURI.png" +4589[] = "" +4589[] = "/list-of-ua/bot-detail?bot=MetaURI" +125[] = "miniRank/1.2 (miniRank; http://minirank.com/; MiniRank)" +125[] = "miniRank" +125[] = "miniRank/1.2" +125[] = "http://www.minirank.com/" +125[] = "TitaniumLine.com" +125[] = "http://titaniumline.com/" +125[] = "bot.png" +125[] = "" +125[] = "/list-of-ua/bot-detail?bot=miniRank" +232[] = "miniRank/1.5 (miniRank; www.minirank.com; robot)" +232[] = "miniRank" +232[] = "miniRank/1.5" +232[] = "http://www.minirank.com/" +232[] = "TitaniumLine.com" +232[] = "http://titaniumline.com/" +232[] = "bot.png" +232[] = "" +232[] = "/list-of-ua/bot-detail?bot=miniRank" +326[] = "miniRank/1.6 (Website ranking; www.minirank.com; robot)" +326[] = "miniRank" +326[] = "miniRank/1.6" +326[] = "http://www.minirank.com/" +326[] = "TitaniumLine.com" +326[] = "http://titaniumline.com/" +326[] = "bot.png" +326[] = "" +326[] = "/list-of-ua/bot-detail?bot=miniRank" +520[] = "miniRank/2.0 (miniRank; http://minirank.com/; website ranking engine)" +520[] = "miniRank" +520[] = "miniRank/2.0" +520[] = "http://www.minirank.com/" +520[] = "TitaniumLine.com" +520[] = "http://titaniumline.com/" +520[] = "bot.png" +520[] = "" +520[] = "/list-of-ua/bot-detail?bot=miniRank" +689[] = "miniRank/3.1 (miniRank; www.minirank.com; website ranking engine)" +689[] = "miniRank" +689[] = "miniRank/3.1" +689[] = "http://www.minirank.com/" +689[] = "TitaniumLine.com" +689[] = "http://titaniumline.com/" +689[] = "bot.png" +689[] = "" +689[] = "/list-of-ua/bot-detail?bot=miniRank" +1676[] = "Mozilla/5.0 (compatible; MJ12bot/v1.2.5; http://www.majestic12.co.uk/bot.php?+)" +1676[] = "MJ12bot" +1676[] = "MJ12bot/v1.2.5" +1676[] = "http://majestic12.co.uk/bot.php" +1676[] = "Majestic-12" +1676[] = "http://www.majestic12.co.uk/" +1676[] = "bot_mj12bot.png" +1676[] = "" +1676[] = "/list-of-ua/bot-detail?bot=MJ12bot" +1517[] = "Mozilla/5.0 (compatible; MJ12bot/v1.2.4; http://www.majestic12.co.uk/bot.php?+)" +1517[] = "MJ12bot" +1517[] = "MJ12bot/v1.2.4" +1517[] = "http://majestic12.co.uk/bot.php" +1517[] = "Majestic-12" +1517[] = "http://www.majestic12.co.uk/" +1517[] = "bot_mj12bot.png" +1517[] = "" +1517[] = "/list-of-ua/bot-detail?bot=MJ12bot" +1602[] = "Mozilla/5.0 (compatible; MJ12bot/v1.2.1; http://www.majestic12.co.uk/bot.php?+)" +1602[] = "MJ12bot" +1602[] = "MJ12bot/v1.2.1" +1602[] = "http://majestic12.co.uk/bot.php" +1602[] = "Majestic-12" +1602[] = "http://www.majestic12.co.uk/" +1602[] = "bot_mj12bot.png" +1602[] = "" +1602[] = "/list-of-ua/bot-detail?bot=MJ12bot" +1908[] = "Mozilla/5.0 (compatible; MJ12bot/v1.2.3; http://www.majestic12.co.uk/bot.php?+)" +1908[] = "MJ12bot" +1908[] = "MJ12bot/v1.2.3" +1908[] = "http://majestic12.co.uk/bot.php" +1908[] = "Majestic-12" +1908[] = "http://www.majestic12.co.uk/" +1908[] = "bot_mj12bot.png" +1908[] = "" +1908[] = "/list-of-ua/bot-detail?bot=MJ12bot" +1909[] = "Mozilla/5.0 (compatible; MJ12bot/v1.3.0; http://www.majestic12.co.uk/bot.php?+)" +1909[] = "MJ12bot" +1909[] = "MJ12bot/v1.3.0" +1909[] = "http://majestic12.co.uk/bot.php" +1909[] = "Majestic-12" +1909[] = "http://www.majestic12.co.uk/" +1909[] = "bot_mj12bot.png" +1909[] = "" +1909[] = "/list-of-ua/bot-detail?bot=MJ12bot" +2024[] = "Mozilla/5.0 (compatible; MJ12bot/v1.3.1; http://www.majestic12.co.uk/bot.php?+)" +2024[] = "MJ12bot" +2024[] = "MJ12bot/v1.3.1" +2024[] = "http://majestic12.co.uk/bot.php" +2024[] = "Majestic-12" +2024[] = "http://www.majestic12.co.uk/" +2024[] = "bot_mj12bot.png" +2024[] = "" +2024[] = "/list-of-ua/bot-detail?bot=MJ12bot" +2185[] = "Mozilla/5.0 (compatible; MJ12bot/v1.3.2; http://www.majestic12.co.uk/bot.php?+)" +2185[] = "MJ12bot" +2185[] = "MJ12bot/v1.3.2" +2185[] = "http://majestic12.co.uk/bot.php" +2185[] = "Majestic-12" +2185[] = "http://www.majestic12.co.uk/" +2185[] = "bot_mj12bot.png" +2185[] = "" +2185[] = "/list-of-ua/bot-detail?bot=MJ12bot" +4846[] = "Mozilla/5.0 (compatible; MJ12bot/v1.3.3; http://www.majestic12.co.uk/bot.php?+)" +4846[] = "MJ12bot" +4846[] = "MJ12bot/v1.3.3" +4846[] = "http://majestic12.co.uk/bot.php" +4846[] = "Majestic-12" +4846[] = "http://www.majestic12.co.uk/" +4846[] = "bot_mj12bot.png" +4846[] = "" +4846[] = "/list-of-ua/bot-detail?bot=MJ12bot" +1213[] = "MLBot (www.metadatalabs.com)" +1213[] = "MLBot" +1213[] = "MLBot" +1213[] = "http://www.metadatalabs.com/mlbot/" +1213[] = "metadata labs" +1213[] = "http://www.metadatalabs.com/" +1213[] = "bot.png" +1213[] = "" +1213[] = "/list-of-ua/bot-detail?bot=MLBot" +1283[] = "MLBot (www.metadatalabs.com/mlbot)" +1283[] = "MLBot" +1283[] = "MLBot b" +1283[] = "http://www.metadatalabs.com/mlbot/" +1283[] = "metadata labs" +1283[] = "http://www.metadatalabs.com/" +1283[] = "bot.png" +1283[] = "" +1283[] = "/list-of-ua/bot-detail?bot=MLBot" +994[] = "MnoGoSearch/3.3.2" +994[] = "MnoGoSearch" +994[] = "MnoGoSearch/3.3.2" +994[] = "http://www.mnogosearch.org/products.html" +994[] = "Lavtech.Com" +994[] = "http://www.lavtech.com/" +994[] = "bot.png" +994[] = "" +994[] = "/list-of-ua/bot-detail?bot=MnoGoSearch" +1247[] = "MnoGoSearch/3.3.6" +1247[] = "MnoGoSearch" +1247[] = "MnoGoSearch/3.3.6" +1247[] = "http://www.mnogosearch.org/products.html" +1247[] = "Lavtech.Com" +1247[] = "http://www.lavtech.com/" +1247[] = "bot.png" +1247[] = "" +1247[] = "/list-of-ua/bot-detail?bot=MnoGoSearch" +1867[] = "MnoGoSearch/3.3.9" +1867[] = "MnoGoSearch" +1867[] = "MnoGoSearch/3.3.9" +1867[] = "http://www.mnogosearch.org/products.html" +1867[] = "Lavtech.Com" +1867[] = "http://www.lavtech.com/" +1867[] = "bot.png" +1867[] = "" +1867[] = "/list-of-ua/bot-detail?bot=MnoGoSearch" +2195[] = "MnoGoSearch/3.2.37" +2195[] = "MnoGoSearch" +2195[] = "MnoGoSearch/3.2.37" +2195[] = "http://www.mnogosearch.org/products.html" +2195[] = "Lavtech.Com" +2195[] = "http://www.lavtech.com/" +2195[] = "bot.png" +2195[] = "" +2195[] = "/list-of-ua/bot-detail?bot=MnoGoSearch" +1563[] = "DoCoMo/2.0 N902iS(c100;TB;W24H12)(compatible; moba-crawler; http://crawler.dena.jp/)" +1563[] = "moba-crawler" +1563[] = "moba-crawler" +1563[] = "http://crawler.dena.jp/" +1563[] = "DeNA Co.,Ltd." +1563[] = "http://dena.jp/" +1563[] = "bot.png" +1563[] = "" +1563[] = "/list-of-ua/bot-detail?bot=moba-crawler" +2196[] = "MojeekBot/0.2 (archi; http://www.mojeek.com/bot.html)" +2196[] = "MojeekBot" +2196[] = "MojeekBot/0.2" +2196[] = "http://www.mojeek.com/bot.html" +2196[] = "Mojeek Ltd." +2196[] = "http://www.mojeek.com/" +2196[] = "bot_MojeekBot.png" +2196[] = "" +2196[] = "/list-of-ua/bot-detail?bot=MojeekBot" +5683[] = "Mozilla/5.0 (compatible; MojeekBot/0.2; http://www.mojeek.com/bot.html#relaunch)" +5683[] = "MojeekBot" +5683[] = "MojeekBot/0.2 Relaunch" +5683[] = "http://www.mojeek.com/bot.html" +5683[] = "Mojeek Ltd." +5683[] = "http://www.mojeek.com/" +5683[] = "bot_MojeekBot.png" +5683[] = "" +5683[] = "/list-of-ua/bot-detail?bot=MojeekBot" +538[] = "Motoricerca-Robots.txt-Checker/1.0 (http://tool.motoricerca.info/robots-checker.phtml)" +538[] = "Motoricerca-Robots.txt-Checker" +538[] = "Motoricerca-Robots.txt-Checker/1.0" +538[] = "http://tool.motoricerca.info/robots-checker.phtml" +538[] = "Motoricerca.info" +538[] = "http://www.motoricerca.info/" +538[] = "bot.png" +538[] = "" +538[] = "/list-of-ua/bot-detail?bot=Motoricerca-Robots.txt-Checker" +135[] = "Mozdex/0.7.2-dev (Mozdex; http://www.mozdex.com/bot.html; spider@mozdex.com)" +135[] = "mozDex" +135[] = "Mozdex/0.7.2-dev" +135[] = "http://www.mozdex.com/bot.html" +135[] = "Mozdex.com" +135[] = "http://www.mozdex.com/" +135[] = "bot.png" +135[] = "" +135[] = "/list-of-ua/bot-detail?bot=mozDex" +350[] = "Mozdex/0.7.2 (Mozdex; http://www.mozdex.com/bot.html; spider@mozdex.com)" +350[] = "mozDex" +350[] = "Mozdex/0.7.2" +350[] = "http://www.mozdex.com/bot.html" +350[] = "Mozdex.com" +350[] = "http://www.mozdex.com/" +350[] = "bot.png" +350[] = "" +350[] = "/list-of-ua/bot-detail?bot=mozDex" +624[] = "Mozdex/0.7.1 (Mozdex; http://www.mozdex.com/bot.html; spider@mozdex.com)" +624[] = "mozDex" +624[] = "Mozdex/0.7.1" +624[] = "http://www.mozdex.com/bot.html" +624[] = "Mozdex.com" +624[] = "http://www.mozdex.com/" +624[] = "bot.png" +624[] = "" +624[] = "/list-of-ua/bot-detail?bot=mozDex" +1533[] = "Mozilla/5.0 (compatible; Mp3Bot/0.4; +http://mp3realm.org/mp3bot/)" +1533[] = "Mp3Bot" +1533[] = "Mp3Bot/0.4" +1533[] = "http://mp3realm.org/mp3bot/" +1533[] = "Mp3Realm.Org" +1533[] = "http://mp3realm.org/" +1533[] = "bot_Mp3Bot.png" +1533[] = "" +1533[] = "/list-of-ua/bot-detail?bot=Mp3Bot" +2120[] = "Mozilla/5.0 (compatible; Mp3Bot/0.7; +http://mp3realm.org/mp3bot/)" +2120[] = "Mp3Bot" +2120[] = "Mp3Bot/0.7" +2120[] = "http://mp3realm.org/mp3bot/" +2120[] = "Mp3Realm.Org" +2120[] = "http://mp3realm.org/" +2120[] = "bot_Mp3Bot.png" +2120[] = "" +2120[] = "/list-of-ua/bot-detail?bot=Mp3Bot" +416[] = "MQbot metaquerier.cs.uiuc.edu/crawler" +416[] = "MQbot" +416[] = "MQbot" +416[] = "http://metaquerier.cs.uiuc.edu/crawler/" +416[] = "University of Illinois at Urbana-Champaign" +416[] = "http://www.uiuc.edu/" +416[] = "bot.png" +416[] = "" +416[] = "/list-of-ua/bot-detail?bot=MQbot" +562[] = "MQBOT/Nutch-0.9-dev (MQBOT Nutch Crawler; http://falcon.cs.uiuc.edu; mqbot@cs.uiuc.edu)" +562[] = "MQbot" +562[] = "MQBOT/Nutch-0.9-dev" +562[] = "http://metaquerier.cs.uiuc.edu/crawler/" +562[] = "University of Illinois at Urbana-Champaign" +562[] = "http://www.uiuc.edu/" +562[] = "bot.png" +562[] = "" +562[] = "/list-of-ua/bot-detail?bot=MQbot" +587[] = "MQBOT/Nutch-0.9-dev (MQBOT Crawler; http://falcon.cs.uiuc.edu; mqbot@cs.uiuc.edu)" +587[] = "MQbot" +587[] = "MQBOT/Nutch-0.9-dev b" +587[] = "http://metaquerier.cs.uiuc.edu/crawler/" +587[] = "University of Illinois at Urbana-Champaign" +587[] = "http://www.uiuc.edu/" +587[] = "bot.png" +587[] = "" +587[] = "/list-of-ua/bot-detail?bot=MQbot" +865[] = "MQBOT/Nutch-0.9-dev (MQBOT Nutch Crawler; http://vwbot.cs.uiuc.edu; mqbot@cs.uiuc.edu)" +865[] = "MQbot" +865[] = "MQBOT/Nutch-0.9-dev c" +865[] = "http://metaquerier.cs.uiuc.edu/crawler/" +865[] = "University of Illinois at Urbana-Champaign" +865[] = "http://www.uiuc.edu/" +865[] = "bot.png" +865[] = "" +865[] = "/list-of-ua/bot-detail?bot=MQbot" +3[] = "msnbot/1.0 (+http://search.msn.com/msnbot.htm)" +3[] = "MSNBot" +3[] = "MSNBot/1.0" +3[] = "http://search.msn.com/msnbot.htm" +3[] = "Microsoft" +3[] = "http://www.microsoft.com/" +3[] = "bot_msnbot.png" +3[] = "" +3[] = "/list-of-ua/bot-detail?bot=MSNBot" +1497[] = "msnbot/2.0b (+http://search.msn.com/msnbot.htm)" +1497[] = "MSNBot" +1497[] = "MSNBot/2.0b" +1497[] = "http://search.msn.com/msnbot.htm" +1497[] = "Microsoft" +1497[] = "http://www.microsoft.com/" +1497[] = "bot_msnbot.png" +1497[] = "" +1497[] = "/list-of-ua/bot-detail?bot=MSNBot" +1180[] = "msnbot/1.1 (+http://search.msn.com/msnbot.htm)" +1180[] = "MSNBot" +1180[] = "MSNBot/1.1" +1180[] = "http://search.msn.com/msnbot.htm" +1180[] = "Microsoft" +1180[] = "http://www.microsoft.com/" +1180[] = "bot_msnbot.png" +1180[] = "" +1180[] = "/list-of-ua/bot-detail?bot=MSNBot" +1468[] = "msnbot-media/1.1 (+http://search.msn.com/msnbot.htm)" +1468[] = "MSNBot" +1468[] = "msnbot-media/1.1" +1468[] = "http://search.msn.com/msnbot.htm" +1468[] = "Microsoft" +1468[] = "http://www.microsoft.com/" +1468[] = "bot_msnbot.png" +1468[] = "" +1468[] = "/list-of-ua/bot-detail?bot=MSNBot" +4095[] = "msnbot/2.0b (+http://search.msn.com/msnbot.htm)." +4095[] = "MSNBot" +4095[] = "MSNBot/2.0b + ." +4095[] = "http://search.msn.com/msnbot.htm" +4095[] = "Microsoft" +4095[] = "http://www.microsoft.com/" +4095[] = "bot_msnbot.png" +4095[] = "" +4095[] = "/list-of-ua/bot-detail?bot=MSNBot" +4411[] = "msnbot/2.0b (+http://search.msn.com/msnbot.htm)._" +4411[] = "MSNBot" +4411[] = "MSNBot/2.0b + ._" +4411[] = "http://search.msn.com/msnbot.htm" +4411[] = "Microsoft" +4411[] = "http://www.microsoft.com/" +4411[] = "bot_msnbot.png" +4411[] = "" +4411[] = "/list-of-ua/bot-detail?bot=MSNBot" +6010[] = "msnbot-NewsBlogs/2.0b (+http://search.msn.com/msnbot.htm)" +6010[] = "MSNBot" +6010[] = "msnbot-NewsBlogs/2.0b" +6010[] = "http://search.msn.com/msnbot.htm" +6010[] = "Microsoft" +6010[] = "http://www.microsoft.com/" +6010[] = "bot_msnbot.png" +6010[] = "" +6010[] = "/list-of-ua/bot-detail?bot=MSNBot" +252[] = "MSRBOT" +252[] = "MSRBOT" +252[] = "MSRBOT" +252[] = "http://research.microsoft.com/research/sv/msrbot/" +252[] = "Microsoft" +252[] = "http://www.microsoft.com/" +252[] = "bot.png" +252[] = "" +252[] = "/list-of-ua/bot-detail?bot=MSRBOT" +546[] = "MSRBOT (http://research.microsoft.com/research/sv/msrbot/)" +546[] = "MSRBOT" +546[] = "MSRBOT b" +546[] = "http://research.microsoft.com/research/sv/msrbot/" +546[] = "Microsoft" +546[] = "http://www.microsoft.com/" +546[] = "bot.png" +546[] = "" +546[] = "/list-of-ua/bot-detail?bot=MSRBOT" +791[] = "MSRBOT (http://research.microsoft.com/research/sv/msrbot)" +791[] = "MSRBOT" +791[] = "MSRBOT c" +791[] = "http://research.microsoft.com/research/sv/msrbot/" +791[] = "Microsoft" +791[] = "http://www.microsoft.com/" +791[] = "bot.png" +791[] = "" +791[] = "/list-of-ua/bot-detail?bot=MSRBOT" +1024[] = "MSRBOT (http://research.microsoft.com/research/sv/msrbot/" +1024[] = "MSRBOT" +1024[] = "MSRBOT d" +1024[] = "http://research.microsoft.com/research/sv/msrbot/" +1024[] = "Microsoft" +1024[] = "http://www.microsoft.com/" +1024[] = "bot.png" +1024[] = "" +1024[] = "/list-of-ua/bot-detail?bot=MSRBOT" +977[] = "multicrawler (+http://sw.deri.org/2006/04/multicrawler/robots.html)" +977[] = "MultiCrawler" +977[] = "MultiCrawler" +977[] = "http://sw.deri.org/2006/04/multicrawler/robots.html" +977[] = "Semantic Web Search Engine" +977[] = "http://swse.org/" +977[] = "bot.png" +977[] = "" +977[] = "/list-of-ua/bot-detail?bot=MultiCrawler" +442[] = "Mozilla/4.0 (compatible; MyFamilyBot/1.0; http://www.myfamilyinc.com)" +442[] = "MyFamilyBot" +442[] = "MyFamilyBot/1.0" +442[] = "http://www.ancestry.com/learn/bot.aspx" +442[] = "MyFamily.com, Inc." +442[] = "http://www.myfamilyinc.com/" +442[] = "bot.png" +442[] = "" +442[] = "/list-of-ua/bot-detail?bot=MyFamilyBot" +528[] = "Mozilla/4.0 (compatible; MyFamilyBot/1.0; http://www.ancestry.com/learn/bot.aspx)" +528[] = "MyFamilyBot" +528[] = "MyFamilyBot/1.0 b" +528[] = "http://www.ancestry.com/learn/bot.aspx" +528[] = "MyFamily.com, Inc." +528[] = "http://www.myfamilyinc.com/" +528[] = "bot.png" +528[] = "" +528[] = "/list-of-ua/bot-detail?bot=MyFamilyBot" +813[] = "mozilla/4.0 (compatible; myfamilybot/1.0; http://www.ancestry.com/learn/bot.aspx)" +813[] = "MyFamilyBot" +813[] = "MyFamilyBot/1.0" +813[] = "http://www.ancestry.com/learn/bot.aspx" +813[] = "The Generations Network, Inc." +813[] = "http://www.myfamilyinc.com/" +813[] = "bot.png" +813[] = "" +813[] = "/list-of-ua/bot-detail?bot=MyFamilyBot" +2028[] = "Mozilla/5.0 (compatible; Najdi.si/3.1)" +2028[] = "Najdi.si" +2028[] = "Najdi.si/3.1" +2028[] = "http://www.najdi.si/help/aboutsearch.html#q5" +2028[] = "Najdi.si d.o.o." +2028[] = "http://www.najdi.si/" +2028[] = "bot_najdi.png" +2028[] = "" +2028[] = "/list-of-ua/bot-detail?bot=Najdi.si" +1476[] = "Yeti/1.0 (NHN Corp.; http://help.naver.com/robots/)" +1476[] = "NaverBot" +1476[] = "Yeti/1.0" +1476[] = "http://help.naver.com/robots/" +1476[] = "NHN Corporation" +1476[] = "http://www.nhncorp.com/" +1476[] = "bot_NaverBot.png" +1476[] = "" +1476[] = "/list-of-ua/bot-detail?bot=NaverBot" +1494[] = "Mozilla/4.0 (compatible; NaverBot/1.0; http://help.naver.com/customer_webtxt_02.jsp)" +1494[] = "NaverBot" +1494[] = "NaverBot/1.0" +1494[] = "http://help.naver.com/robots/" +1494[] = "NHN Corporation" +1494[] = "http://www.nhncorp.com/" +1494[] = "bot_NaverBot.png" +1494[] = "" +1494[] = "/list-of-ua/bot-detail?bot=NaverBot" +814[] = "navissobot/1.7 (+http://navisso.com/)" +814[] = "navissobot" +814[] = "navissobot/1.7" +814[] = "http://navisso.com/topics?c=navissobot" +814[] = "Navisso Search" +814[] = "http://navisso.com/" +814[] = "bot.png" +814[] = "" +814[] = "/list-of-ua/bot-detail?bot=navissobot" +832[] = "nestReader/0.2 (discovery; http://echonest.com/reader.shtml; reader at echonest.com)" +832[] = "nestReader" +832[] = "nestReader/0.2" +832[] = "http://echonest.com/reader.shtml" +832[] = "The Echo Nest Corporation" +832[] = "http://echonest.com/" +832[] = "bot.png" +832[] = "" +832[] = "/list-of-ua/bot-detail?bot=nestReader" +6225[] = "Mozilla/5.0 (compatible; NetcraftSurveyAgent/1.0; +info@netcraft.com)" +6225[] = "NetcraftSurveyAgent" +6225[] = "NetcraftSurveyAgent/1.0" +6225[] = "" +6225[] = "Netcraft Ltd" +6225[] = "http://www.netcraft.com/" +6225[] = "bot.png" +6225[] = "" +6225[] = "/list-of-ua/bot-detail?bot=NetcraftSurveyAgent" +873[] = "Netintelligence LiveAssessment - www.netintelligence.com" +873[] = "Netintelligence LiveAssessment" +873[] = "Netintelligence LiveAssessment" +873[] = "" +873[] = "Netintelligence Limited" +873[] = "http://www.netintelligence.com/" +873[] = "bot.png" +873[] = "" +873[] = "/list-of-ua/bot-detail?bot=Netintelligence LiveAssessment" +1095[] = "nrsbot/5.0(loopip.com/robot.html)" +1095[] = "NetResearchServer" +1095[] = "nrsbot/5.0" +1095[] = "http://loopip.com/robot.html" +1095[] = "LoopIP LLC" +1095[] = "http://loopip.com/" +1095[] = "bot.png" +1095[] = "" +1095[] = "/list-of-ua/bot-detail?bot=NetResearchServer" +5092[] = "nrsbot/6.0(loopip.com/robot.html)" +5092[] = "NetResearchServer" +5092[] = "nrsbot/6.0" +5092[] = "http://loopip.com/robot.html" +5092[] = "LoopIP LLC" +5092[] = "http://loopip.com/" +5092[] = "bot.png" +5092[] = "" +5092[] = "/list-of-ua/bot-detail?bot=NetResearchServer" +368[] = "NetWhatCrawler/0.06-dev (NetWhatCrawler from NetWhat.com; http://www.netwhat.com; support@netwhat.com)" +368[] = "NetWhatCrawler" +368[] = "NetWhatCrawler/0.06-dev" +368[] = "" +368[] = "GreenWave Online, Inc." +368[] = "http://www.sonicrun.com/" +368[] = "bot.png" +368[] = "" +368[] = "/list-of-ua/bot-detail?bot=NetWhatCrawler" +771[] = "NextGenSearchBot 1 (for information visit http://about.zoominfo.com/About/NextGenSearchBot.aspx)" +771[] = "NextGenSearchBot" +771[] = "NextGenSearchBot 1" +771[] = "http://www.zoominfo.com/About/misc/NextGenSearchBot.aspx" +771[] = "Zoom Information Inc." +771[] = "http://www.zoominfo.com/" +771[] = "bot.png" +771[] = "" +771[] = "/list-of-ua/bot-detail?bot=NextGenSearchBot" +1102[] = "NextGenSearchBot 1 (for information visit http://www.zoominfo.com/About/misc/NextGenSearchBot.aspx)" +1102[] = "NextGenSearchBot" +1102[] = "NextGenSearchBot 1 b" +1102[] = "http://www.zoominfo.com/About/misc/NextGenSearchBot.aspx" +1102[] = "Zoom Information Inc." +1102[] = "http://www.zoominfo.com/" +1102[] = "bot.png" +1102[] = "" +1102[] = "/list-of-ua/bot-detail?bot=NextGenSearchBot" +563[] = "Mozilla/5.0 (compatible; nextthing.org/1.0; +http://www.nextthing.org/bot)" +563[] = "nextthing.org" +563[] = "nextthing.org/1.0" +563[] = "http://www.nextthing.org/bot/" +563[] = "Andrew Wooster" +563[] = "http://www.cs.hmc.edu/~awooster/" +563[] = "bot.png" +563[] = "" +563[] = "/list-of-ua/bot-detail?bot=nextthing.org" +38[] = "NG/2.0" +38[] = "NG" +38[] = "NG/2.0" +38[] = "" +38[] = "Exalead" +38[] = "http://exalead.com/" +38[] = "bot.png" +38[] = "" +38[] = "/list-of-ua/bot-detail?bot=NG" +465[] = "NG-Search/0.90 (NG-SearchBot; http://www.ng-search.com; )" +465[] = "NG-Search" +465[] = "NG-Search/0.90" +465[] = "" +465[] = "NG-Marketing" +465[] = "http://www.ng-search.com/" +465[] = "bot.png" +465[] = "" +465[] = "/list-of-ua/bot-detail?bot=NG-Search" +515[] = "NG-Search/0.9.8 (NG-SearchBot; http://www.ng-search.com)" +515[] = "NG-Search" +515[] = "NG-Search/0.9.8" +515[] = "" +515[] = "NG-Marketing" +515[] = "http://www.ng-search.com/" +515[] = "bot.png" +515[] = "" +515[] = "/list-of-ua/bot-detail?bot=NG-Search" +290[] = "Mozilla/5.0 (Windows;) NimbleCrawler 1.14 obeys UserAgent NimbleCrawler For problems contact: crawler@healthline.com" +290[] = "NimbleCrawler" +290[] = "NimbleCrawler/1.14" +290[] = "" +290[] = "Healthline Networks, Inc." +290[] = "http://www.healthline.com/" +290[] = "bot.png" +290[] = "" +290[] = "/list-of-ua/bot-detail?bot=NimbleCrawler" +201[] = "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.7) NimbleCrawler 1.11 obeys UserAgent NimbleCrawler For problems contact: crawler_at_dataalchemy.com" +201[] = "NimbleCrawler" +201[] = "NimbleCrawler/1.11" +201[] = "" +201[] = "Healthline Networks, Inc." +201[] = "http://www.healthline.com/" +201[] = "bot.png" +201[] = "" +201[] = "/list-of-ua/bot-detail?bot=NimbleCrawler" +209[] = "Mozilla/5.0 (Windows;) NimbleCrawler 1.12 obeys UserAgent NimbleCrawler For problems contact: crawler@healthline.com" +209[] = "NimbleCrawler" +209[] = "NimbleCrawler/1.12" +209[] = "" +209[] = "Healthline Networks, Inc." +209[] = "http://www.healthline.com/" +209[] = "bot.png" +209[] = "" +209[] = "/list-of-ua/bot-detail?bot=NimbleCrawler" +282[] = "Mozilla/5.0 (Windows;) NimbleCrawler 1.13 obeys UserAgent NimbleCrawler For problems contact: crawler@healthline.com" +282[] = "NimbleCrawler" +282[] = "NimbleCrawler/1.13" +282[] = "" +282[] = "Healthline Networks, Inc." +282[] = "http://www.healthline.com/" +282[] = "bot.png" +282[] = "" +282[] = "/list-of-ua/bot-detail?bot=NimbleCrawler" +294[] = "Mozilla/5.0 (Windows;) NimbleCrawler 1.15 obeys UserAgent NimbleCrawler For problems contact: crawler@healthline.com" +294[] = "NimbleCrawler" +294[] = "NimbleCrawler/1.15" +294[] = "" +294[] = "Healthline Networks, Inc." +294[] = "http://www.healthline.com/" +294[] = "bot.png" +294[] = "" +294[] = "/list-of-ua/bot-detail?bot=NimbleCrawler" +341[] = "Mozilla/5.0 (Windows;) NimbleCrawler 2.0.0 obeys UserAgent NimbleCrawler For problems contact: crawler@healthline.com" +341[] = "NimbleCrawler" +341[] = "NimbleCrawler/2.0.0" +341[] = "" +341[] = "Healthline Networks, Inc." +341[] = "http://www.healthline.com/" +341[] = "bot.png" +341[] = "" +341[] = "/list-of-ua/bot-detail?bot=NimbleCrawler" +431[] = "Mozilla/5.0 (Windows;) NimbleCrawler 2.0.1 obeys UserAgent NimbleCrawler For problems contact: crawler@healthline.com" +431[] = "NimbleCrawler" +431[] = "NimbleCrawler/2.0.1" +431[] = "" +431[] = "Healthline Networks, Inc." +431[] = "http://www.healthline.com/" +431[] = "bot.png" +431[] = "" +431[] = "/list-of-ua/bot-detail?bot=NimbleCrawler" +1072[] = "Mozilla/5.0 (Windows;) NimbleCrawler 2.0.2 obeys UserAgent NimbleCrawler For problems contact: crawler@healthline.com" +1072[] = "NimbleCrawler" +1072[] = "NimbleCrawler/2.0.2" +1072[] = "" +1072[] = "Healthline Networks, Inc." +1072[] = "http://www.healthline.com/" +1072[] = "bot.png" +1072[] = "" +1072[] = "/list-of-ua/bot-detail?bot=NimbleCrawler" +4866[] = "nodestackbot/0.1 (bot@nodestack.com http://nodestack.com/bot.html)" +4866[] = "nodestackbot" +4866[] = "nodestackbot/0.1" +4866[] = "http://nodestack.com/bot.html" +4866[] = "nodestack.com" +4866[] = "" +4866[] = "bot.png" +4866[] = "" +4866[] = "/list-of-ua/bot-detail?bot=nodestackbot" +349[] = "noyona_0_1" +349[] = "noyona" +349[] = "noyona_0_1" +349[] = "http://www.noyona.com/index.pl" +349[] = "" +349[] = "" +349[] = "bot.png" +349[] = "" +349[] = "/list-of-ua/bot-detail?bot=noyona" +366[] = "NPBot/3 (NPBot; http://www.nameprotect.com; npbot@nameprotect.com)" +366[] = "NPBot" +366[] = "NPBot/3" +366[] = "http://www.nameprotect.com/botinfo.html" +366[] = "NameProtect Inc." +366[] = "http://www.nameprotect.com/" +366[] = "bot.png" +366[] = "" +366[] = "/list-of-ua/bot-detail?bot=NPBot" +4336[] = "Nuhk/2.4 ( http://www.neti.ee/cgi-bin/abi/Otsing/Nuhk/)" +4336[] = "Nuhk" +4336[] = "Nuhk/2.4" +4336[] = "http://www.neti.ee/cgi-bin/abi/Otsing/Nuhk/" +4336[] = "Elion" +4336[] = "http://www.neti.ee/" +4336[] = "bot.png" +4336[] = "" +4336[] = "/list-of-ua/bot-detail?bot=Nuhk" +6114[] = "Nuhk/2.4 (+http://www.neti.ee/cgi-bin/abi/otsing.html)" +6114[] = "Nuhk" +6114[] = "Nuhk/2.4 b" +6114[] = "http://www.neti.ee/cgi-bin/abi/Otsing/Nuhk/" +6114[] = "Elion" +6114[] = "http://www.neti.ee/" +6114[] = "bot.png" +6114[] = "" +6114[] = "/list-of-ua/bot-detail?bot=Nuhk" +335[] = "NuSearch Spider (compatible; MSIE 6.0)" +335[] = "NuSearch Spider" +335[] = "NuSearch Spider" +335[] = "http://www.nusearch.com/" +335[] = "nusearch.com" +335[] = "http://www.nusearch.com/" +335[] = "bot.png" +335[] = "" +335[] = "/list-of-ua/bot-detail?bot=NuSearch Spider" +480[] = "Nusearch Spider (www.nusearch.com)" +480[] = "NuSearch Spider" +480[] = "NuSearch Spider - b" +480[] = "http://www.nusearch.com/" +480[] = "nusearch.com" +480[] = "http://www.nusearch.com/" +480[] = "bot.png" +480[] = "" +480[] = "/list-of-ua/bot-detail?bot=NuSearch Spider" +82[] = "NutchCVS/0.8-dev (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)" +82[] = "Nutch" +82[] = "NutchCSV/0.8-dev" +82[] = "http://www.nutch.org/docs/en/bot.html" +82[] = "lucene" +82[] = "http://lucene.apache.org/" +82[] = "bot_Nutch.png" +82[] = "" +82[] = "/list-of-ua/bot-detail?bot=Nutch" +84[] = "NutchCVS/0.06-dev (http://www.nutch.org/docs/en/bot.html; rhwarren+nutch@uwaterloo.ca)" +84[] = "Nutch" +84[] = "NutchCVS/0.06-dev at uwaterloo.ca" +84[] = "http://www.nutch.org/docs/en/bot.html" +84[] = "lucene" +84[] = "http://lucene.apache.org/" +84[] = "bot_Nutch.png" +84[] = "" +84[] = "/list-of-ua/bot-detail?bot=Nutch" +86[] = "NutchCVS/0.7 (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)" +86[] = "Nutch" +86[] = "NutchCVS/0.7" +86[] = "http://www.nutch.org/docs/en/bot.html" +86[] = "lucene" +86[] = "http://lucene.apache.org/" +86[] = "bot_Nutch.png" +86[] = "" +86[] = "/list-of-ua/bot-detail?bot=Nutch" +100[] = "NutchOSU-VLIB/0.7 (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)" +100[] = "Nutch" +100[] = "NutchOSU-VLIB/0.7" +100[] = "http://www.nutch.org/docs/en/bot.html" +100[] = "lucene" +100[] = "http://lucene.apache.org/" +100[] = "bot_Nutch.png" +100[] = "" +100[] = "/list-of-ua/bot-detail?bot=Nutch" +120[] = "InternetArchive/0.8-dev (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)" +120[] = "Nutch" +120[] = "InternetArchive/0.8-dev" +120[] = "http://www.nutch.org/docs/en/bot.html" +120[] = "lucene" +120[] = "http://lucene.apache.org/" +120[] = "bot_Nutch.png" +120[] = "" +120[] = "/list-of-ua/bot-detail?bot=Nutch" +133[] = "NutchCVS/0.7.1 (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)" +133[] = "Nutch" +133[] = "NutchCVS/0.7.1" +133[] = "http://www.nutch.org/docs/en/bot.html" +133[] = "lucene" +133[] = "http://lucene.apache.org/" +133[] = "bot_Nutch.png" +133[] = "" +133[] = "/list-of-ua/bot-detail?bot=Nutch" +177[] = "NutchCVS/0.7.1 (Nutch; http://www.vvdb.org; voorzitter@vvdb.org)" +177[] = "Nutch" +177[] = "NutchCVS/0.7.1 vvdg.org" +177[] = "http://www.nutch.org/docs/en/bot.html" +177[] = "lucene" +177[] = "http://lucene.apache.org/" +177[] = "bot_Nutch.png" +177[] = "" +177[] = "/list-of-ua/bot-detail?bot=Nutch" +321[] = "NutchCVS/0.06-dev (Nutch; http://www.nutch.org/docs/en/bot.html; nutch-agent@lists.sourceforge.net)" +321[] = "Nutch" +321[] = "NutchCVS/0.06-dev" +321[] = "http://www.nutch.org/docs/en/bot.html" +321[] = "lucene" +321[] = "http://lucene.apache.org/" +321[] = "bot_Nutch.png" +321[] = "" +321[] = "/list-of-ua/bot-detail?bot=Nutch" +323[] = "NutchCVS/0.7.1 (Nutch running at UW; http://www.nutch.org/docs/en/bot.html; sycrawl@cs.washington.edu)" +323[] = "Nutch" +323[] = "NutchCVS/0.7.1 at washihinton.edu" +323[] = "http://www.nutch.org/docs/en/bot.html" +323[] = "lucene" +323[] = "http://lucene.apache.org/" +323[] = "bot_Nutch.png" +323[] = "" +323[] = "/list-of-ua/bot-detail?bot=Nutch" +338[] = "NutchCVS/0.7.1 (Nutch running at UW; http://crawlers.cs.washington.edu/; sycrawl@cs.washington.edu)" +338[] = "Nutch" +338[] = "NutchCVS/0.7.1 at UW" +338[] = "http://www.nutch.org/docs/en/bot.html" +338[] = "lucene" +338[] = "http://lucene.apache.org/" +338[] = "bot_Nutch.png" +338[] = "" +338[] = "/list-of-ua/bot-detail?bot=Nutch" +343[] = "NutchCVS/0.7.2 (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)" +343[] = "Nutch" +343[] = "NutchCVS/0.7.2" +343[] = "http://www.nutch.org/docs/en/bot.html" +343[] = "lucene" +343[] = "http://lucene.apache.org/" +343[] = "bot_Nutch.png" +343[] = "" +343[] = "/list-of-ua/bot-detail?bot=Nutch" +382[] = "NutchCVS/0.8-dev (Nutch running at UW; http://www.nutch.org/docs/en/bot.html; sycrawl@cs.washington.edu)" +382[] = "Nutch" +382[] = "NutchCSV/0.8-dev at UW" +382[] = "http://www.nutch.org/docs/en/bot.html" +382[] = "lucene" +382[] = "http://lucene.apache.org/" +382[] = "bot_Nutch.png" +382[] = "" +382[] = "/list-of-ua/bot-detail?bot=Nutch" +482[] = "asked/Nutch-0.8 (web crawler; http://asked.jp; epicurus at gmail dot com)" +482[] = "Nutch" +482[] = "Nutch/0.8 at asked.jp" +482[] = "http://www.nutch.org/docs/en/bot.html" +482[] = "lucene" +482[] = "http://lucene.apache.org/" +482[] = "bot_Nutch.png" +482[] = "" +482[] = "/list-of-ua/bot-detail?bot=Nutch" +484[] = "HouxouCrawler/Nutch-0.9-dev (houxou.com's nutch-based crawler which serves special interest on-line communities; http://www.houxou.com/crawler; crawler at houxou dot com)" +484[] = "Nutch" +484[] = "Nutch/0.9-dev at houxou.com" +484[] = "http://www.nutch.org/docs/en/bot.html" +484[] = "lucene" +484[] = "http://lucene.apache.org/" +484[] = "bot_Nutch.png" +484[] = "" +484[] = "/list-of-ua/bot-detail?bot=Nutch" +485[] = "BilgiBetaBot/0.8-dev (bilgi.com (Beta) ; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)" +485[] = "Nutch" +485[] = "Nutch/0.8-dev at bilgi.com" +485[] = "http://www.nutch.org/docs/en/bot.html" +485[] = "lucene" +485[] = "http://lucene.apache.org/" +485[] = "bot_Nutch.png" +485[] = "" +485[] = "/list-of-ua/bot-detail?bot=Nutch" +491[] = "HouxouCrawler/Nutch-0.8 (houxou.com's nutch-based crawler which serves special interest on-line communities; http://www.houxou.com/crawler; crawler at houxou dot com)" +491[] = "Nutch" +491[] = "Nutch/0.8 at houxou.com" +491[] = "http://www.nutch.org/docs/en/bot.html" +491[] = "lucene" +491[] = "http://lucene.apache.org/" +491[] = "bot_Nutch.png" +491[] = "" +491[] = "/list-of-ua/bot-detail?bot=Nutch" +493[] = "NutchCVS/0.7.1 (Nutch; http://lucene.apache.org/nutch/bot.html; raphael@unterreuth.de)" +493[] = "Nutch" +493[] = "NutchCVS/0.7.1 at unterreuth.de" +493[] = "http://www.nutch.org/docs/en/bot.html" +493[] = "lucene" +493[] = "http://lucene.apache.org/" +493[] = "bot_Nutch.png" +493[] = "" +493[] = "/list-of-ua/bot-detail?bot=Nutch" +710[] = "heeii/Nutch-0.9-dev (heeii.com; www.heeii.com; nutch at heeii.com)" +710[] = "Nutch" +710[] = "heeii/Nutch-0.9-dev at heeii.com" +710[] = "http://www.nutch.org/docs/en/bot.html" +710[] = "lucene" +710[] = "http://lucene.apache.org/" +710[] = "bot_Nutch.png" +710[] = "" +710[] = "/list-of-ua/bot-detail?bot=Nutch" +716[] = "HouxouCrawler/Nutch-0.8.2-dev (houxou.com's nutch-based crawler which serves special interest on-line communities; http://www.houxou.com/crawler; crawler at houxou dot com)" +716[] = "Nutch" +716[] = "Nutch/0.8.2-dev at houxou.com" +716[] = "http://www.nutch.org/docs/en/bot.html" +716[] = "lucene" +716[] = "http://lucene.apache.org/" +716[] = "bot_Nutch.png" +716[] = "" +716[] = "/list-of-ua/bot-detail?bot=Nutch" +917[] = "NutchCVS/Nutch-0.9 (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)" +917[] = "Nutch" +917[] = "NutchCSV/0.9" +917[] = "http://www.nutch.org/docs/en/bot.html" +917[] = "lucene" +917[] = "http://lucene.apache.org/" +917[] = "bot_Nutch.png" +917[] = "" +917[] = "/list-of-ua/bot-detail?bot=Nutch" +1089[] = "HouxouCrawler/Nutch-0.9 (houxou.com's nutch-based crawler which serves special interest on-line communities; http://www.houxou.com/crawler; crawler at houxou dot com)" +1089[] = "Nutch" +1089[] = "Nutch/0.9 at houxou.com" +1089[] = "http://www.nutch.org/docs/en/bot.html" +1089[] = "lucene" +1089[] = "http://lucene.apache.org/" +1089[] = "bot_Nutch.png" +1089[] = "" +1089[] = "/list-of-ua/bot-detail?bot=Nutch" +2087[] = "Zscho.de Crawler/Nutch-1.0-Zscho.de-semantic_patch (Zscho.de Crawler, collecting for machine learning; http://zscho.de/)" +2087[] = "Nutch" +2087[] = "Nutch/1.0 at zscho.de" +2087[] = "http://www.nutch.org/docs/en/bot.html" +2087[] = "lucene" +2087[] = "http://lucene.apache.org/" +2087[] = "bot_Nutch.png" +2087[] = "" +2087[] = "/list-of-ua/bot-detail?bot=Nutch" +5939[] = "nWormFeedFinder (http://www.nworm.com)" +5939[] = "nworm" +5939[] = "nwormFeedFinder" +5939[] = "http://www.nworm.com/crawlers.php" +5939[] = "Daniel Schlicker (mangora IT)" +5939[] = "http://www.mangora.de/" +5939[] = "bot.png" +5939[] = "" +5939[] = "/list-of-ua/bot-detail?bot=nworm" +6245[] = "Nymesis/2.0 (http://nymesis.com)" +6245[] = "Nymesis" +6245[] = "Nymesis/2.0" +6245[] = "http://www.nymesis.com/about/" +6245[] = "nymesis.com" +6245[] = "http://www.nymesis.com/" +6245[] = "bot.png" +6245[] = "" +6245[] = "/list-of-ua/bot-detail?bot=Nymesis" +164[] = "oBot" +164[] = "oBot" +164[] = "oBot" +164[] = "" +164[] = "Cobion AG" +164[] = "" +164[] = "bot.png" +164[] = "" +164[] = "/list-of-ua/bot-detail?bot=oBot" +178[] = "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; obot)" +178[] = "oBot" +178[] = "oBot - b" +178[] = "" +178[] = "Cobion AG" +178[] = "" +178[] = "bot.png" +178[] = "" +178[] = "/list-of-ua/bot-detail?bot=oBot" +5228[] = "Ocelli/1.4 (http://www.globalspec.com/Ocelli)" +5228[] = "Ocelli" +5228[] = "Ocelli/1.4" +5228[] = "http://www.globalspec.com/Ocelli" +5228[] = "GlobalSpec, Inc." +5228[] = "http://www.globalspec.com/" +5228[] = "bot.png" +5228[] = "" +5228[] = "/list-of-ua/bot-detail?bot=Ocelli" +93[] = "OmniExplorer_Bot/4.02 (+http://www.omni-explorer.com) WorldIndexer" +93[] = "OmniExplorer_Bot" +93[] = "OmniExplorer_Bot/4.02" +93[] = "http://www.omni-explorer.com/" +93[] = "" +93[] = "" +93[] = "bot.png" +93[] = "" +93[] = "/list-of-ua/bot-detail?bot=OmniExplorer_Bot" +116[] = "OmniExplorer_Bot/4.06 (+http://www.omni-explorer.com) WorldIndexer" +116[] = "OmniExplorer_Bot" +116[] = "OmniExplorer_Bot/4.06" +116[] = "http://www.omni-explorer.com/" +116[] = "" +116[] = "" +116[] = "bot.png" +116[] = "" +116[] = "/list-of-ua/bot-detail?bot=OmniExplorer_Bot" +308[] = "OmniExplorer_Bot/6.47 (+http://www.omni-explorer.com) WorldIndexer" +308[] = "OmniExplorer_Bot" +308[] = "OmniExplorer_Bot/6.47" +308[] = "http://www.omni-explorer.com/" +308[] = "" +308[] = "" +308[] = "bot.png" +308[] = "" +308[] = "/list-of-ua/bot-detail?bot=OmniExplorer_Bot" +109[] = "Mozilla/5.0 (compatible; OnetSzukaj/5.0; +http://szukaj.onet.pl)" +109[] = "OnetSzukaj" +109[] = "OnetSzukaj/5.0" +109[] = "" +109[] = "Onet.pl" +109[] = "http://www.onet.pl/" +109[] = "bot.png" +109[] = "" +109[] = "/list-of-ua/bot-detail?bot=OnetSzukaj" +219[] = "Mozilla/5.0 (compatible; OnetSzukaj/5.0; +http://szukaj.onet.pl" +219[] = "OnetSzukaj" +219[] = "OnetSzukaj/5.0 b" +219[] = "" +219[] = "Onet.pl" +219[] = "http://www.onet.pl/" +219[] = "bot.png" +219[] = "" +219[] = "/list-of-ua/bot-detail?bot=OnetSzukaj" +1522[] = "OOZBOT/0.20 ( Setooz výrazný ako say-th-uuz, znamená mosty. ; http://www.setooz.com/oozbot.html ; agentname at setooz dot_com )" +1522[] = "OOZBOT" +1522[] = "OOZBOT/0.20 b" +1522[] = "http://www.setooz.com/oozbot.html" +1522[] = "SETU Software Systems P. Ltd." +1522[] = "http://www.setooz.com/" +1522[] = "bot.png" +1522[] = "" +1522[] = "/list-of-ua/bot-detail?bot=OOZBOT" +1469[] = "OOZBOT/0.20 ( -- ; http://www.setooz.com/oozbot.html ; agentname at setooz dot_com )" +1469[] = "OOZBOT" +1469[] = "OOZBOT/0.20" +1469[] = "http://www.setooz.com/oozbot.html" +1469[] = "SETU Software Systems P. Ltd." +1469[] = "http://www.setooz.com/" +1469[] = "bot.png" +1469[] = "" +1469[] = "/list-of-ua/bot-detail?bot=OOZBOT" +1703[] = "OOZBOT/0.20 ( http://www.setooz.com/oozbot.html ; agentname at setooz dot_com )" +1703[] = "OOZBOT" +1703[] = "OOZBOT/0.20 c" +1703[] = "http://www.setooz.com/oozbot.html" +1703[] = "SETU Software Systems P. Ltd." +1703[] = "http://www.setooz.com/" +1703[] = "bot.png" +1703[] = "" +1703[] = "/list-of-ua/bot-detail?bot=OOZBOT" +355[] = "Openfind data gatherer, Openbot/3.0+(robot-response@openfind.com.tw;+http://www.openfind.com.tw/robot.html)" +355[] = "Openbot" +355[] = "Openbot/3.0" +355[] = "http://www.openfind.com.tw/robot.html" +355[] = "Openfind Information Technology INC." +355[] = "http://www.openfind.com/" +355[] = "bot.png" +355[] = "" +355[] = "/list-of-ua/bot-detail?bot=Openbot" +5859[] = "OpenCalaisSemanticProxy" +5859[] = "OpenCalaisSemanticProxy" +5859[] = "OpenCalaisSemanticProxy" +5859[] = "http://www.opencalais.com/open-calais-semanticproxy-robot-agent-name" +5859[] = "Thomson Reuters" +5859[] = "http://thomsonreuters.com/" +5859[] = "bot.png" +5859[] = "" +5859[] = "/list-of-ua/bot-detail?bot=OpenCalaisSemanticProxy" +310[] = "Orbiter (+http://www.dailyorbit.com/bot.htm)" +310[] = "Orbiter" +310[] = "Orbiter" +310[] = "http://www.dailyorbit.com/bot.htm" +310[] = "DailyOrbit.com" +310[] = "http://www.dailyorbit.com/" +310[] = "bot_orbiter.png" +310[] = "" +310[] = "/list-of-ua/bot-detail?bot=Orbiter" +1681[] = "Orgbybot/OrgbyBot v1.2 (Spidering the net for Orgby; http://www.orgby.com/ ; Orgby.com Search Engine)" +1681[] = "OrgbyBot" +1681[] = "OrgbyBot/1.2" +1681[] = "http://orgby.com/bot/" +1681[] = "Orgby.com" +1681[] = "" +1681[] = "bot.png" +1681[] = "" +1681[] = "/list-of-ua/bot-detail?bot=OrgbyBot" +2233[] = "Orgbybot/OrgbyBot v1.3 (Spider; http://orgby.com/bot/ ; Orgby.com Search Engine)" +2233[] = "OrgbyBot" +2233[] = "OrgbyBot/1.3" +2233[] = "http://orgby.com/bot/" +2233[] = "Orgby.com" +2233[] = "" +2233[] = "bot.png" +2233[] = "" +2233[] = "/list-of-ua/bot-detail?bot=OrgbyBot" +1496[] = "Mozilla/5.0 (compatible; OsO; http://oso.octopodus.com/abot.html)" +1496[] = "OsObot" +1496[] = "OsObot" +1496[] = "http://oso.octopodus.com/abot.html" +1496[] = "Denis Chatelain" +1496[] = "http://buildingasearchengine.blogspot.com/" +1496[] = "bot.png" +1496[] = "" +1496[] = "/list-of-ua/bot-detail?bot=OsObot" +1037[] = "owsBot/0.1 (Nutch; www.oneworldstreet.com; nutch-agent@lucene.apache.org)" +1037[] = "owsBot" +1037[] = "owsBot/0.1" +1037[] = "" +1037[] = "OneWorldStreet.com" +1037[] = "http://www.oneworldstreet.com/" +1037[] = "bot.png" +1037[] = "" +1037[] = "/list-of-ua/bot-detail?bot=owsBot" +1040[] = "owsBot/0.2 (owsBot; www.oneworldstreet.com; owsBot)" +1040[] = "owsBot" +1040[] = "owsBot/0.2" +1040[] = "" +1040[] = "OneWorldStreet.com" +1040[] = "http://www.oneworldstreet.com/" +1040[] = "bot.png" +1040[] = "" +1040[] = "/list-of-ua/bot-detail?bot=owsBot" +253[] = "PageBitesHyperBot/600 (http://www.pagebites.com/)" +253[] = "PageBitesHyperBot" +253[] = "PageBitesHyperBot/600" +253[] = "" +253[] = "PageBites Inc." +253[] = "http://www.pagebites.com/" +253[] = "bot_pagebiteshyperbot.png" +253[] = "" +253[] = "/list-of-ua/bot-detail?bot=PageBitesHyperBot" +398[] = "page_verifier (http://www.securecomputing.com/goto/pv)" +398[] = "page_verifier" +398[] = "page_verifier" +398[] = "http://www.securecomputing.com/goto/pv" +398[] = "Secure Computing Corporation" +398[] = "http://www.securecomputing.com/" +398[] = "bot.png" +398[] = "" +398[] = "/list-of-ua/bot-detail?bot=page_verifier" +886[] = "panscient.com" +886[] = "Panscient web crawler" +886[] = "Panscient web crawler" +886[] = "http://panscient.com/faq.html" +886[] = "Panscient, Inc." +886[] = "http://panscient.com/" +886[] = "bot.png" +886[] = "" +886[] = "/list-of-ua/bot-detail?bot=Panscient web crawler" +1938[] = "Mozilla/5.0 (compatible;+ParchBot/1.0;++http://www.parchmenthill.com/search.htm)" +1938[] = "ParchBot" +1938[] = "ParchBot/1.0" +1938[] = "http://www.parchmenthill.com/search.htm" +1938[] = "Parchment Hill" +1938[] = "http://www.parchmenthill.com/" +1938[] = "bot.png" +1938[] = "" +1938[] = "/list-of-ua/bot-detail?bot=ParchBot" +5376[] = "Mozilla/5.0 (compatible; Peew/1.0; http://www.peew.de/crawler/)" +5376[] = "Peew" +5376[] = "Peew/1.0" +5376[] = "http://www.peew.de/crawler/" +5376[] = "Marco Schmidt" +5376[] = "http://www.peew.de/" +5376[] = "bot.png" +5376[] = "" +5376[] = "/list-of-ua/bot-detail?bot=Peew" +690[] = "Pingdom GIGRIB (http://www.pingdom.com)" +690[] = "Pingdom GIGRIB" +690[] = "Pingdom GIGRIB" +690[] = "http://uptime.pingdom.com/general/what_is" +690[] = "Pingdom" +690[] = "http://www.pingdom.com/" +690[] = "bot.png" +690[] = "" +690[] = "/list-of-ua/bot-detail?bot=Pingdom GIGRIB" +2197[] = "pingdom.com_bot_version_1.4_(http://www.pingdom.com/)" +2197[] = "pingdom.com_bot" +2197[] = "pingdom.com_bot 1.4" +2197[] = "" +2197[] = "Pingdom AB" +2197[] = "http://www.pingdom.com/" +2197[] = "bot_pingdomcom_bot.png" +2197[] = "" +2197[] = "/list-of-ua/bot-detail?bot=pingdom.com_bot" +1895[] = "Mozilla/5.0 (compatible; Plukkie/1.1; http://www.botje.com/plukkie.htm)" +1895[] = "Plukkie" +1895[] = "Plukkie/1.1" +1895[] = "http://www.botje.com/plukkie.htm" +1895[] = "Botje.nl" +1895[] = "http://botje.nl/" +1895[] = "bot.png" +1895[] = "" +1895[] = "/list-of-ua/bot-detail?bot=Plukkie" +2073[] = "Mozilla/5.0 (compatible; Plukkie/1.2; http://www.botje.com/plukkie.htm)" +2073[] = "Plukkie" +2073[] = "Plukkie/1.2" +2073[] = "http://www.botje.com/plukkie.htm" +2073[] = "Botje.nl" +2073[] = "http://botje.nl/" +2073[] = "bot.png" +2073[] = "" +2073[] = "/list-of-ua/bot-detail?bot=Plukkie" +4876[] = "Mozilla/5.0 (compatible; Plukkie/1.3; http://www.botje.com/plukkie.htm)" +4876[] = "Plukkie" +4876[] = "Plukkie/1.3" +4876[] = "http://www.botje.com/plukkie.htm" +4876[] = "Botje.nl" +4876[] = "" +4876[] = "bot.png" +4876[] = "" +4876[] = "/list-of-ua/bot-detail?bot=Plukkie" +141[] = "Mozilla/5.0 (compatible; Pogodak.co.yu/3.1)" +141[] = "Pogodak.co.yu" +141[] = "Pogodak.co.yu/3.1" +141[] = "" +141[] = "Pogodak d.o.o." +141[] = "http://www.pogodak.co.yu/" +141[] = "bot.png" +141[] = "" +141[] = "/list-of-ua/bot-detail?bot=Pogodak.co.yu" +616[] = "Mozilla/5.0 (compatible; polixea.de-Robot +http://www.polixea.de)" +616[] = "polixea.de" +616[] = "polixea.de" +616[] = "" +616[] = "POLIXEA AG" +616[] = "http://www.polixea.net/" +616[] = "bot.png" +616[] = "" +616[] = "/list-of-ua/bot-detail?bot=polixea.de" +4940[] = "Pompos/1.3 http://dir.com/pompos.html" +4940[] = "Pompos" +4940[] = "Pompos/1.3" +4940[] = "http://dir.com/pompos.html" +4940[] = "Iliad" +4940[] = "http://www.iliad.fr/" +4940[] = "bot.png" +4940[] = "" +4940[] = "/list-of-ua/bot-detail?bot=Pompos" +760[] = "posterus (seek.se) +http://www.seek.se/studio/index.php?id=47&t=details" +760[] = "posterus" +760[] = "posterus" +760[] = "http://www.seek.se/studio/index.php?id=47&t=details" +760[] = "Seek.se" +760[] = "http://www.seek.se/" +760[] = "bot.png" +760[] = "" +760[] = "/list-of-ua/bot-detail?bot=posterus" +5360[] = "PostPost/1.0 (+http://postpo.st/crawlers)" +5360[] = "PostPost" +5360[] = "PostPost/1.0" +5360[] = "http://postpo.st/crawlers" +5360[] = "Boathouse group" +5360[] = "http://www.boathouseinc.com/" +5360[] = "bot_PostPost.png" +5360[] = "" +5360[] = "/list-of-ua/bot-detail?bot=PostPost" +56[] = "psbot/0.1 (+http://www.picsearch.com/bot.html)" +56[] = "psbot" +56[] = "psbot/0.1" +56[] = "http://www.picsearch.com/bot.html" +56[] = "picsearch.com" +56[] = "http://www.picsearch.com/" +56[] = "bot_psbot.png" +56[] = "" +56[] = "/list-of-ua/bot-detail?bot=psbot" +2135[] = "Mozilla/5.0 (compatible; ptd-crawler; +http://bixolabs.com/crawler/ptd/; crawler@bixolabs.com)" +2135[] = "ptd-crawler" +2135[] = "ptd-crawler" +2135[] = "http://bixolabs.com/crawler/ptd/" +2135[] = "Bixolabs" +2135[] = "http://bixolabs.com/" +2135[] = "bot_ptd-crawler.png" +2135[] = "" +2135[] = "/list-of-ua/bot-detail?bot=ptd-crawler" +5620[] = "Qirina Hurdler v. 1.05 10.11.01 (+http://www.qirina.com/hurdler.html)" +5620[] = "Qirina Hurdler" +5620[] = "Qirina Hurdler v. 1.05 10.11.01" +5620[] = "http://www.qirina.com/hurdler.html" +5620[] = "Locust Swarm" +5620[] = "http://www.locustswarm.com/" +5620[] = "bot_QirinaHurdler.png" +5620[] = "" +5620[] = "/list-of-ua/bot-detail?bot=Qirina Hurdler" +1982[] = "Qseero v1.0.0" +1982[] = "Qseero" +1982[] = "Qseero 1.0.0" +1982[] = "" +1982[] = "Qseero, Inc." +1982[] = "http://q0.com/" +1982[] = "bot.png" +1982[] = "" +1982[] = "/list-of-ua/bot-detail?bot=Qseero" +5057[] = "Mozilla/5.0 (compatible; Qualidator.com Bot 1.0;)" +5057[] = "Qualidator.com Bot" +5057[] = "Qualidator.com Bot 1.0" +5057[] = "http://www.qualidator.com/Web/de/Support/FAQ_OnlineTestStatistiken.htm" +5057[] = "seven49.net GmbH" +5057[] = "http://www.seven49.net/" +5057[] = "bot_Qualidator.png" +5057[] = "" +5057[] = "/list-of-ua/bot-detail?bot=Qualidator.com Bot" +914[] = "Mozilla/5.0 (compatible; Quantcastbot/1.0; www.quantcast.com)" +914[] = "Quantcastbot" +914[] = "Quantcastbot/1.0" +914[] = "" +914[] = "Quantcast Corporation" +914[] = "http://www.quantcast.com/" +914[] = "bot.png" +914[] = "" +914[] = "/list-of-ua/bot-detail?bot=Quantcastbot" +6024[] = "quickobot/quickobot-1 (Quicko Labs; http://quicko.co; robot at quicko dot co)" +6024[] = "quickobot" +6024[] = "quickobot-1" +6024[] = "http://www.searchenabler.com/quickobot/" +6024[] = "Quicko Labs Pvt Ltd. " +6024[] = "http://www.searchenabler.com/" +6024[] = "bot.png" +6024[] = "" +6024[] = "/list-of-ua/bot-detail?bot=quickobot" +1815[] = "R6_FeedFetcher(www.radian6.com/crawler)" +1815[] = "R6 bot" +1815[] = "R6_FeedFetcher" +1815[] = "http://www.radian6.com/crawler/" +1815[] = "Radian6 Technologies Inc" +1815[] = "http://www.radian6.com/" +1815[] = "bot.png" +1815[] = "" +1815[] = "/list-of-ua/bot-detail?bot=R6 bot" +4936[] = "R6_CommentReader(www.radian6.com/crawler)" +4936[] = "R6 bot" +4936[] = "R6_CommentReader" +4936[] = "http://www.radian6.com/crawler/" +4936[] = "Radian6 Technologies Inc" +4936[] = "http://www.radian6.com/" +4936[] = "bot.png" +4936[] = "" +4936[] = "/list-of-ua/bot-detail?bot=R6 bot" +6252[] = "RankurBot/Rankur2.1 (http://rankur.com; info at rankur dot com)" +6252[] = "RankurBot" +6252[] = "RankurBot/2.1" +6252[] = "http://rankur.com/technology.html" +6252[] = "Advance Solutions EU Ltd." +6252[] = "http://www.advancesolutions.eu/" +6252[] = "bot.png" +6252[] = "" +6252[] = "/list-of-ua/bot-detail?bot=RankurBot" +856[] = "RedBot/redbot-1.0 (Rediff.com Crawler; redbot at rediff dot com)" +856[] = "RedBot" +856[] = "RedBot1.0" +856[] = "" +856[] = "Rediff.com India Limited." +856[] = "http://www.rediff.com/" +856[] = "bot.png" +856[] = "" +856[] = "/list-of-ua/bot-detail?bot=RedBot" +337[] = "Robo Crawler 6.4.5 (robocrawler@bb.softbank.co.jp)" +337[] = "Robo Crawler" +337[] = "Robo Crawler 6.4.5" +337[] = "http://www.softbank.co.jp/" +337[] = "SOFTBANK CORP." +337[] = "http://www.softbank.co.jp/" +337[] = "bot.png" +337[] = "" +337[] = "/list-of-ua/bot-detail?bot=Robo Crawler" +5362[] = "Robots_Tester_http_www.searchenginepromotionhelp.com" +5362[] = "Robots_Tester" +5362[] = "Robots_Tester" +5362[] = "http://www.searchenginepromotionhelp.com/m/robots-text-tester/robots-checker.php" +5362[] = "Search Engine Promotion Help" +5362[] = "http://www.searchenginepromotionhelp.com/" +5362[] = "bot.png" +5362[] = "" +5362[] = "/list-of-ua/bot-detail?bot=Robots_Tester" +1711[] = "Robozilla/1.0" +1711[] = "Robozilla" +1711[] = "Robozilla/1.0" +1711[] = "http://www.dmoz.org/guidelines/robozilla.html" +1711[] = "DMOZ" +1711[] = "http://www.dmoz.org/" +1711[] = "bot.png" +1711[] = "" +1711[] = "/list-of-ua/bot-detail?bot=Robozilla" +2145[] = "Ronzoobot/1.3 (http://www.ronzoo.com/about.php)" +2145[] = "Ronzoobot" +2145[] = "Ronzoobot/1.3" +2145[] = "http://www.ronzoo.com/about.php" +2145[] = "Ronzoo" +2145[] = "" +2145[] = "bot_Ronzoobot.png" +2145[] = "" +2145[] = "/list-of-ua/bot-detail?bot=Ronzoobot" +2078[] = "Ronzoobot/1.2 (http://www.ronzoo.com/about.php)" +2078[] = "Ronzoobot" +2078[] = "Ronzoobot/1.2" +2078[] = "http://www.ronzoo.com/about.php" +2078[] = "Ronzoo" +2078[] = "" +2078[] = "bot_Ronzoobot.png" +2078[] = "" +2078[] = "/list-of-ua/bot-detail?bot=Ronzoobot" +1601[] = "RSSMicro.com RSS/Atom Feed Robot" +1601[] = "RSSMicro.com RSS/Atom Feed Robot" +1601[] = "RSSMicro.com RSS/Atom Feed Robot" +1601[] = "" +1601[] = "RSSMicro.com" +1601[] = "http://rssmicro.com/" +1601[] = "bot.png" +1601[] = "" +1601[] = "/list-of-ua/bot-detail?bot=RSSMicro.com RSS/Atom Feed Robot" +3415[] = "Ruky-Roboter (Version: 1.06, powered by www.ruky.de +http://www.ruky.de/bot.html)" +3415[] = "Ruky-Roboter" +3415[] = "Ruky-Roboter/1.06" +3415[] = "http://www.ruky.de/zeige/bot.html" +3415[] = "ruky.de" +3415[] = "" +3415[] = "bot.png" +3415[] = "" +3415[] = "/list-of-ua/bot-detail?bot=Ruky-Roboter" +1816[] = "http://domino.research.ibm.com/comm/research_projects.nsf/pages/sai-crawler.callingcard.html" +1816[] = "SAI Crawler" +1816[] = "SAI Crawler" +1816[] = "http://domino.research.ibm.com/comm/research_projects.nsf/pages/sai-crawler.callingcard.html" +1816[] = "IBM" +1816[] = "http://www.ibm.com/" +1816[] = "bot.png" +1816[] = "" +1816[] = "/list-of-ua/bot-detail?bot=SAI Crawler" +1906[] = "SanszBot/1.7(http://www.sansz.org/sanszbot, spider@sansz.org) (spider@sansz.org)" +1906[] = "SanszBot" +1906[] = "SanszBot/1.7" +1906[] = "http://www.sansz.org/sanszbot" +1906[] = "Peres Levente (Sansz Foundation)" +1906[] = "http://www.sansz.org/" +1906[] = "bot.png" +1906[] = "" +1906[] = "/list-of-ua/bot-detail?bot=SanszBot" +88[] = "SBIder/0.7 (SBIder; http://www.sitesell.com/sbider.html; http://support.sitesell.com/contact-support.html)" +88[] = "SBIder" +88[] = "SBIder/0.7" +88[] = "http://www.sitesell.com/sbider.html" +88[] = "SiteSell" +88[] = "http://www.sitesell.com/" +88[] = "bot.png" +88[] = "" +88[] = "/list-of-ua/bot-detail?bot=SBIder" +123[] = "SBIder/0.8-dev (SBIder; http://www.sitesell.com/sbider.html; http://support.sitesell.com/contact-support.html)" +123[] = "SBIder" +123[] = "SBIder/0.8dev" +123[] = "http://www.sitesell.com/sbider.html" +123[] = "SiteSell" +123[] = "http://www.sitesell.com/" +123[] = "bot.png" +123[] = "" +123[] = "/list-of-ua/bot-detail?bot=SBIder" +606[] = "SBIder/SBIder-0.8.2-dev (http://www.sitesell.com/sbider.html)" +606[] = "SBIder" +606[] = "SBIder-0.8.2-dev" +606[] = "http://www.sitesell.com/sbider.html" +606[] = "SiteSell Inc." +606[] = "http://www.sitesell.com/" +606[] = "bot.png" +606[] = "" +606[] = "/list-of-ua/bot-detail?bot=SBIder" +2138[] = "SBIder/Nutch-1.0-dev (http://www.sitesell.com/sbider.html)" +2138[] = "SBIder" +2138[] = "SBIder/1.0" +2138[] = "http://www.sitesell.com/sbider.html" +2138[] = "SiteSell" +2138[] = "http://www.sitesell.com/" +2138[] = "bot.png" +2138[] = "" +2138[] = "/list-of-ua/bot-detail?bot=SBIder" +1950[] = "Mozilla/5.0 (compatible; SecretSerachEngineLabs.com-SBSearch/0.9; http://www.secretsearchenginelabs.com/secret-web-crawler.php)" +1950[] = "SBSearch" +1950[] = "SBSearch/0.9" +1950[] = "http://www.secretsearchenginelabs.com/secret-web-crawler.php" +1950[] = "SecretSearchEngineLabs.com" +1950[] = "http://www.secretsearchenginelabs.com/" +1950[] = "bot.png" +1950[] = "" +1950[] = "/list-of-ua/bot-detail?bot=SBSearch" +1779[] = "Mozilla/5.0 (compatible; Scarlett/ 1.0; +http://www.ellerdale.com/crawler.html)" +1779[] = "Scarlett" +1779[] = "Scarlett/ 1.0" +1779[] = "http://www.ellerdale.com/crawler.html" +1779[] = "Ellerdale Project" +1779[] = "http://www.ellerdale.com/" +1779[] = "bot.png" +1779[] = "" +1779[] = "/list-of-ua/bot-detail?bot=Scarlett" +462[] = "schibstedsokbot (compatible; Mozilla/5.0; MSIE 5.0; FAST FreshCrawler 6; +http://www.schibstedsok.no/bot/)" +462[] = "schibstedsokbot" +462[] = "schibstedsokbot" +462[] = "" +462[] = "Schibsted ASA" +462[] = "http://www.schibsted.no/" +462[] = "bot.png" +462[] = "" +462[] = "/list-of-ua/bot-detail?bot=schibstedsokbot" +501[] = "Mozilla/3.0 (compatible; ScollSpider; http://www.webwobot.com)" +501[] = "ScollSpider" +501[] = "ScollSpider" +501[] = "http://www.webwobot.com/ScollSpider.php" +501[] = "WebWoBot.com" +501[] = "http://www.webwobot.com/" +501[] = "bot.png" +501[] = "" +501[] = "/list-of-ua/bot-detail?bot=ScollSpider" +9[] = "Scooter/3.3" +9[] = "Scooter" +9[] = "Scooter/3.3" +9[] = "" +9[] = "AltaVista" +9[] = "http://www.altavista.com/" +9[] = "bot.png" +9[] = "" +9[] = "/list-of-ua/bot-detail?bot=Scooter" +1565[] = "Mozilla/5.0 (compatible; ScoutJet; +http://www.scoutjet.com/)" +1565[] = "ScoutJet" +1565[] = "ScoutJet a" +1565[] = "http://www.scoutjet.com/" +1565[] = "" +1565[] = "" +1565[] = "bot_ScoutJet.png" +1565[] = "" +1565[] = "/list-of-ua/bot-detail?bot=ScoutJet" +3203[] = "Mozilla/5.0 (compatible; ScoutJet; http://www.scoutjet.com/)" +3203[] = "ScoutJet" +3203[] = "ScoutJet" +3203[] = "http://www.scoutjet.com/" +3203[] = "blekko, inc." +3203[] = "http://blekko.com/" +3203[] = "bot_ScoutJet.png" +3203[] = "" +3203[] = "/list-of-ua/bot-detail?bot=ScoutJet" +301[] = "Search Engine World Robots.txt Validator at http://www.searchengineworld.com/cgi-bin/robotcheck.cgi" +301[] = "Search Engine World Robots.txt Validator" +301[] = "Search Engine World Robots.txt Validator" +301[] = "http://www.searchengineworld.com/cgi-bin/robotcheck.cgi" +301[] = "searchengineworld" +301[] = "http://www.searchengineworld.com/" +301[] = "bot.png" +301[] = "" +301[] = "/list-of-ua/bot-detail?bot=Search Engine World Robots.txt Validator" +4512[] = "Mozilla/5.0 (compatible; Search17Bot/1.1; http://www.search17.com/bot.php)" +4512[] = "Search17Bot" +4512[] = "Search17Bot/1.1" +4512[] = "http://www.search17.com/bot.php" +4512[] = "search17.com" +4512[] = "http://www.search17.com/" +4512[] = "bot.png" +4512[] = "" +4512[] = "/list-of-ua/bot-detail?bot=Search17Bot" +151[] = "Sensis Web Crawler (search_comments\at\sensis\dot\com\dot\au)" +151[] = "Sensis Web Crawler" +151[] = "Sensis Web Crawler - b" +151[] = "" +151[] = "Telstra Corporation Ltd." +151[] = "http://telstra.com/" +151[] = "bot_sensiswebcrawler.png" +151[] = "" +151[] = "/list-of-ua/bot-detail?bot=Sensis Web Crawler" +221[] = "Sensis Web Crawler (search_comments\\at\\sensis\\dot\\com\\dot\\au)" +221[] = "Sensis Web Crawler" +221[] = "Sensis Web Crawler" +221[] = "http://www.sensis.com.au/help.do" +221[] = "Telstra Corporation Ltd." +221[] = "http://www.telstra.com/" +221[] = "bot_sensiswebcrawler.png" +221[] = "" +221[] = "/list-of-ua/bot-detail?bot=Sensis Web Crawler" +6040[] = "Mozilla/5.0 (compatible; SEODat/0.1 http://crawler.seodat.com)" +6040[] = "SEODat" +6040[] = "SEODat/0.1" +6040[] = "" +6040[] = "SEODAT" +6040[] = "http://www.seodat.com/" +6040[] = "bot.png" +6040[] = "" +6040[] = "/list-of-ua/bot-detail?bot=SEODat" +3142[] = "SEOENGBot/1.2 (+http://learn.seoeng.com/seoengbot.htm)" +3142[] = "SEOENGBot" +3142[] = "SEOENGBot/1.2 old" +3142[] = "http://www.seoengine.com/seoengbot.htm" +3142[] = "SEO Engine" +3142[] = "http://www.seoengine.com/" +3142[] = "bot_SEOENGBot.png" +3142[] = "" +3142[] = "/list-of-ua/bot-detail?bot=SEOENGBot" +5999[] = "SEOENGBot/1.2 (+http://learn.seoengine.com/seoengbot.htm)" +5999[] = "SEOENGBot" +5999[] = "SEOENGBot/1.2" +5999[] = "http://www.seoengine.com/seoengbot.htm" +5999[] = "SEO Engine" +5999[] = "http://www.seoengine.com/" +5999[] = "bot_SEOENGBot.png" +5999[] = "" +5999[] = "/list-of-ua/bot-detail?bot=SEOENGBot" +6229[] = "Setooz/Nutch-1.0 (http://www.setooz.com)" +6229[] = "Setoozbot" +6229[] = "Setoozbot/1.0" +6229[] = "http://setooz.com/bot.html" +6229[] = "SETU Software Systems" +6229[] = "http://www.setusoftware.com/" +6229[] = "bot.png" +6229[] = "" +6229[] = "/list-of-ua/bot-detail?bot=Setoozbot" +1463[] = "Mozilla/5.0 (compatible; Seznam screenshot-generator 2.0; +http://fulltext.sblog.cz/screenshot/)" +1463[] = "SeznamBot" +1463[] = "Seznam screenshot-generator 2.0" +1463[] = "http://fulltext.sblog.cz/robot/" +1463[] = "Seznam.cz, a.s." +1463[] = "http://www.seznam.cz/" +1463[] = "seznam.png" +1463[] = "" +1463[] = "/list-of-ua/bot-detail?bot=SeznamBot" +1464[] = "SeznamBot/2.0 (+http://fulltext.sblog.cz/robot/)" +1464[] = "SeznamBot" +1464[] = "SeznamBot/2.0" +1464[] = "http://fulltext.sblog.cz/robot/" +1464[] = "Seznam.cz, a.s." +1464[] = "http://www.seznam.cz/" +1464[] = "seznam.png" +1464[] = "" +1464[] = "/list-of-ua/bot-detail?bot=SeznamBot" +1992[] = "SeznamBot/2.0 (+http://fulltext.seznam.cz/)" +1992[] = "SeznamBot" +1992[] = "SeznamBot/2.0" +1992[] = "http://fulltext.sblog.cz/robot/" +1992[] = "Seznam.cz, a.s." +1992[] = "http://www.seznam.cz/" +1992[] = "seznam.png" +1992[] = "" +1992[] = "/list-of-ua/bot-detail?bot=SeznamBot" +3132[] = "SeznamBot/2.0-Test (+http://fulltext.sblog.cz/robot/)" +3132[] = "SeznamBot" +3132[] = "SeznamBot/2.0-test" +3132[] = "http://fulltext.sblog.cz/robot/" +3132[] = "Seznam.cz, a.s." +3132[] = "http://www.seznam.cz/" +3132[] = "seznam.png" +3132[] = "" +3132[] = "/list-of-ua/bot-detail?bot=SeznamBot" +4437[] = "SeznamBot/3.0-alpha (+http://fulltext.sblog.cz/)" +4437[] = "SeznamBot" +4437[] = "SeznamBot/3.0-alpha" +4437[] = "http://fulltext.sblog.cz/robot/" +4437[] = "Seznam.cz, a.s." +4437[] = "http://www.seznam.cz/" +4437[] = "seznam.png" +4437[] = "" +4437[] = "/list-of-ua/bot-detail?bot=SeznamBot" +5857[] = "SeznamBot/3.0-beta (+http://fulltext.sblog.cz/)" +5857[] = "SeznamBot" +5857[] = "SeznamBot/3.0-beta" +5857[] = "http://fulltext.sblog.cz/robot/" +5857[] = "Seznam.cz, a.s." +5857[] = "http://www.seznam.cz/" +5857[] = "seznam.png" +5857[] = "" +5857[] = "/list-of-ua/bot-detail?bot=SeznamBot" +6189[] = "SeznamBot/3.0 (+http://fulltext.sblog.cz/)" +6189[] = "SeznamBot" +6189[] = "SeznamBot/3.0" +6189[] = "http://fulltext.sblog.cz/robot/" +6189[] = "Seznam.cz, a.s." +6189[] = "http://www.seznam.cz/" +6189[] = "seznam.png" +6189[] = "" +6189[] = "/list-of-ua/bot-detail?bot=SeznamBot" +1562[] = "Shelob (shelob@gmx.net)" +1562[] = "Shelob" +1562[] = "Shelob" +1562[] = "http://mattwork.potsdam.edu/projects/wiki/index.php/Shelob" +1562[] = "M@" +1562[] = "http://mattwork.potsdam.edu/projects/wiki/index.php/Category:Me" +1562[] = "bot.png" +1562[] = "" +1562[] = "/list-of-ua/bot-detail?bot=Shelob" +262[] = "Shim-Crawler(Mozilla-compatible; http://www.logos.ic.i.u-tokyo.ac.jp/crawler/; crawl@logos.ic.i.u-tokyo.ac.jp)" +262[] = "Shim-Crawler" +262[] = "Shim-Crawler" +262[] = "http://www.logos.ic.i.u-tokyo.ac.jp/crawler/index.en.html" +262[] = "Chikayama-Taura Lab, The University of Tokyo" +262[] = "http://www.logos.ic.i.u-tokyo.ac.jp/" +262[] = "bot.png" +262[] = "" +262[] = "/list-of-ua/bot-detail?bot=Shim-Crawler" +536[] = "Shim-Crawler(Mozilla-compatible; http://www.logos.ic.i.u-tokyo.ac.jp/crawl/; crawl@logos.ic.i.u-tokyo.ac.jp)" +536[] = "Shim-Crawler" +536[] = "Shim-Crawler - b" +536[] = "http://www.logos.ic.i.u-tokyo.ac.jp/crawler/index.en.html" +536[] = "Chikayama-Taura Lab, The University of Tokyo" +536[] = "http://www.logos.ic.i.u-tokyo.ac.jp/" +536[] = "bot.png" +536[] = "" +536[] = "/list-of-ua/bot-detail?bot=Shim-Crawler" +747[] = "ShopWiki/1.0 ( +http://www.shopwiki.com/wiki/Help:Bot)" +747[] = "ShopWiki" +747[] = "ShopWiki/1.0" +747[] = "http://www.shopwiki.com/wiki/Help:Bot" +747[] = "ShopWiki Corp" +747[] = "http://www.shopwiki.com/" +747[] = "bot.png" +747[] = "" +747[] = "/list-of-ua/bot-detail?bot=ShopWiki" +208[] = "Silk/1.0" +208[] = "silk" +208[] = "silk/1.0 -a" +208[] = "http://www.slider.com/silk.html" +208[] = "Slider.com" +208[] = "http://www.slider.com/" +208[] = "bot.png" +208[] = "" +208[] = "/list-of-ua/bot-detail?bot=silk" +227[] = "silk/1.0 (+http://www.slider.com/silk.htm)/3.7" +227[] = "silk" +227[] = "silk/1.0" +227[] = "http://www.slider.com/silk.htm" +227[] = "Slider.com" +227[] = "http://www.slider.com/" +227[] = "bot.png" +227[] = "" +227[] = "/list-of-ua/bot-detail?bot=silk" +911[] = "Sirketcebot/v.01 (http://www.sirketce.com/bot.html)" +911[] = "Sirketce/Busiverse" +911[] = "Sirketcebot/v.01" +911[] = "http://www.sirketce.com/bot.html" +911[] = "BERI.L Teknoloji Ltd." +911[] = "http://www.berilteknoloji.com/" +911[] = "bot.png" +911[] = "" +911[] = "/list-of-ua/bot-detail?bot=Sirketce/Busiverse" +1480[] = "Busiversebot/v1.0 (http://www.busiverse.com/bot.php)" +1480[] = "Sirketce/Busiverse" +1480[] = "Busiversebot/v1.0" +1480[] = "http://www.busiverse.com/bot.php" +1480[] = "BerilTech" +1480[] = "http://www.sirketce.com.tr/" +1480[] = "bot.png" +1480[] = "" +1480[] = "/list-of-ua/bot-detail?bot=Sirketce/Busiverse" +6109[] = "Sitedomain-Bot(Sitedomain-Bot 1.0, http://www.sitedomain.de/sitedomain-bot/)" +6109[] = "Sitedomain-Bot" +6109[] = "Sitedomain-Bot 1.0" +6109[] = "http://www.sitedomain.de/sitedomain-bot/" +6109[] = "Sitedomain.de" +6109[] = "http://www.sitedomain.de/" +6109[] = "bot.png" +6109[] = "" +6109[] = "/list-of-ua/bot-detail?bot=Sitedomain-Bot" +874[] = "Mozilla/5.0 (compatible; SkreemRBot +http://skreemr.com)" +874[] = "SkreemRBot" +874[] = "SkreemRBot" +874[] = "" +874[] = "SkreemR" +874[] = "http://skreemr.com/" +874[] = "bot.png" +874[] = "" +874[] = "/list-of-ua/bot-detail?bot=SkreemRBot" +1866[] = "smart.apnoti.com Robot/v1.34 (http://smart.apnoti.com/en/aboutApnotiWebCrawler.html)" +1866[] = "smart.apnoti.com Robot" +1866[] = "smart.apnoti.com Robot/v1.34" +1866[] = "http://smart.apnoti.com/en/aboutApnotiWebCrawler.html" +1866[] = "apnoti.com GmbH" +1866[] = "http://www.apnoti.com/" +1866[] = "bot.png" +1866[] = "" +1866[] = "/list-of-ua/bot-detail?bot=smart.apnoti.com Robot" +101[] = "snap.com beta crawler v0" +101[] = "snap.com" +101[] = "snap.com beta crawler v0" +101[] = "" +101[] = " Idealab" +101[] = "http://www.idealab.com/" +101[] = "bot.png" +101[] = "" +101[] = "/list-of-ua/bot-detail?bot=snap.com" +408[] = "Snapbot/1.0" +408[] = "Snapbot" +408[] = "Snapbot/1.0" +408[] = "" +408[] = "Snap" +408[] = "http://www.snap.com/" +408[] = "bot.png" +408[] = "" +408[] = "/list-of-ua/bot-detail?bot=Snapbot" +754[] = "Snapbot/1.0 (+http://www.snap.com)" +754[] = "Snapbot" +754[] = "Snapbot/1.0 b" +754[] = "" +754[] = "Snap" +754[] = "http://www.snap.com/" +754[] = "bot.png" +754[] = "" +754[] = "/list-of-ua/bot-detail?bot=Snapbot" +815[] = "Mozilla/5.0 (compatible; SnapPreviewBot; en-US; rv:1.8.0.9) Gecko/20061206 Firefox/1.5.0.9" +815[] = "SnapBot" +815[] = "SnapPreviewBot" +815[] = "" +815[] = "Snap" +815[] = "http://www.snap.com/" +815[] = "bot.png" +815[] = "" +815[] = "/list-of-ua/bot-detail?bot=SnapBot" +825[] = "Snapbot/1.0 (Snap Shots, +http://www.snap.com)" +825[] = "Snapbot" +825[] = "Snapbot/1.0 c" +825[] = "" +825[] = "Snap" +825[] = "http://www.snap.com/" +825[] = "bot.png" +825[] = "" +825[] = "/list-of-ua/bot-detail?bot=Snapbot" +921[] = "Snapbot/1.0 (Site Search Crawler, +http://www.snap.com)" +921[] = "Snapbot" +921[] = "Snapbot/1.0 d" +921[] = "" +921[] = "Snap" +921[] = "http://www.snap.com/" +921[] = "bot.png" +921[] = "" +921[] = "/list-of-ua/bot-detail?bot=Snapbot" +835[] = "Snappy/1.1 ( http://www.urltrends.com/ )" +835[] = "Snappy" +835[] = "Snappy/1.1" +835[] = "http://www.urltrends.com/" +835[] = "Xerocity Design Group, LLC." +835[] = "http://www.xerocity.com/" +835[] = "bot_snappy.png" +835[] = "" +835[] = "/list-of-ua/bot-detail?bot=Snappy" +1600[] = "SniffRSS/0.5beta (+http://www.blogator.com/)" +1600[] = "SniffRSS" +1600[] = "SniffRSS/0.5beta" +1600[] = "" +1600[] = "blogator.com" +1600[] = "http://www.blogator.com/" +1600[] = "bot.png" +1600[] = "" +1600[] = "/list-of-ua/bot-detail?bot=SniffRSS" +1471[] = "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)" +1471[] = "Sogou" +1471[] = "Sogou web spider/4.0" +1471[] = "http://www.sogou.com/docs/help/webmasters.htm#07" +1471[] = "sogou.com" +1471[] = "http://www.sogou.com/" +1471[] = "bot.png" +1471[] = "" +1471[] = "/list-of-ua/bot-detail?bot=Sogou" +1470[] = "Sogou develop spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)" +1470[] = "Sogou" +1470[] = "Sogou develop spider/4.0" +1470[] = "http://www.sogou.com/docs/help/webmasters.htm#07" +1470[] = "sogou.com" +1470[] = "http://www.sogou.com/" +1470[] = "bot.png" +1470[] = "" +1470[] = "/list-of-ua/bot-detail?bot=Sogou" +523[] = "sogou spider" +523[] = "sogou spider" +523[] = "sogou spider" +523[] = "http://www.sogou.com/docs/help/webmasters.htm#07" +523[] = "SOGOU.COM" +523[] = "http://www.sogou.com/" +523[] = "bot.png" +523[] = "" +523[] = "/list-of-ua/bot-detail?bot=sogou spider" +768[] = "sogou web spider http://www.sogou.com/docs/help/webmasters.htm#07" +768[] = "sogou spider" +768[] = "sogou spider b" +768[] = "http://www.sogou.com/docs/help/webmasters.htm#07" +768[] = "SOGOU.COM" +768[] = "http://www.sogou.com/" +768[] = "bot.png" +768[] = "" +768[] = "/list-of-ua/bot-detail?bot=sogou spider" +770[] = "sogou web spider(+http://www.sogou.com/docs/help/webmasters.htm#07)" +770[] = "sogou spider" +770[] = "sogou spider c" +770[] = "http://www.sogou.com/docs/help/webmasters.htm#07" +770[] = "SOGOU.COM" +770[] = "http://www.sogou.com/" +770[] = "bot.png" +770[] = "" +770[] = "/list-of-ua/bot-detail?bot=sogou spider" +773[] = "Sogou web spider/3.0(+http://www.sogou.com/docs/help/webmasters.htm#07)" +773[] = "sogou spider" +773[] = "Sogou web spider/3.0" +773[] = "http://www.sogou.com/docs/help/webmasters.htm#07" +773[] = "SOGOU.COM" +773[] = "http://www.sogou.com/" +773[] = "bot.png" +773[] = "" +773[] = "/list-of-ua/bot-detail?bot=sogou spider" +1853[] = "Sosospider+(+http://help.soso.com/webspider.htm)" +1853[] = "Sosospider" +1853[] = "Sosospider" +1853[] = "http://help.soso.com/webspider.htm" +1853[] = "Tencent, Inc." +1853[] = "http://www.tencent.com/" +1853[] = "bot_soso.png" +1853[] = "" +1853[] = "/list-of-ua/bot-detail?bot=Sosospider" +4911[] = "Mozilla/5.0 (compatible; spbot/2.0.3; +http://www.seoprofiler.com/bot/ )" +4911[] = "spbot" +4911[] = "spbot/2.0.3" +4911[] = "http://www.seoprofiler.com/bot/" +4911[] = "Axandra GmbH" +4911[] = "http://www.axandra.com/" +4911[] = "bot_spbot.png" +4911[] = "" +4911[] = "/list-of-ua/bot-detail?bot=spbot" +4922[] = "Mozilla/5.0 (compatible; spbot/2.0.4; +http://www.seoprofiler.com/bot )" +4922[] = "spbot" +4922[] = "spbot/2.0.4" +4922[] = "http://www.seoprofiler.com/bot/" +4922[] = "Axandra GmbH" +4922[] = "http://www.axandra.com/" +4922[] = "bot_spbot.png" +4922[] = "" +4922[] = "/list-of-ua/bot-detail?bot=spbot" +3379[] = "Mozilla/5.0 (compatible; spbot/1.0; +http://www.seoprofiler.com/bot/ )" +3379[] = "spbot" +3379[] = "spbot/1.0" +3379[] = "http://www.seoprofiler.com/bot/" +3379[] = "Axandra GmbH" +3379[] = "http://www.axandra.com/" +3379[] = "bot_spbot.png" +3379[] = "" +3379[] = "/list-of-ua/bot-detail?bot=spbot" +5386[] = "Mozilla/5.0 (compatible; spbot/2.1; +http://www.seoprofiler.com/bot )" +5386[] = "spbot" +5386[] = "spbot/2.1" +5386[] = "http://www.seoprofiler.com/bot/" +5386[] = "Axandra GmbH" +5386[] = "http://www.axandra.com/" +5386[] = "bot_spbot.png" +5386[] = "" +5386[] = "/list-of-ua/bot-detail?bot=spbot" +5748[] = "Mozilla/5.0 (compatible; spbot/3.0; +http://www.seoprofiler.com/bot )" +5748[] = "spbot" +5748[] = "spbot/3.0" +5748[] = "http://www.seoprofiler.com/bot/" +5748[] = "Axandra GmbH" +5748[] = "http://www.axandra.com/" +5748[] = "bot_spbot.png" +5748[] = "" +5748[] = "/list-of-ua/bot-detail?bot=spbot" +3561[] = "Mozilla/5.0 (compatible; spbot/1.1; +http://www.seoprofiler.com/bot/ )" +3561[] = "spbot" +3561[] = "spbot/1.1" +3561[] = "http://www.seoprofiler.com/bot/" +3561[] = "Axandra GmbH" +3561[] = "http://www.axandra.com/" +3561[] = "bot_spbot.png" +3561[] = "" +3561[] = "/list-of-ua/bot-detail?bot=spbot" +3734[] = "Mozilla/5.0 (compatible; spbot/2.0; +http://www.seoprofiler.com/bot/ )" +3734[] = "spbot" +3734[] = "spbot/2.0" +3734[] = "http://www.seoprofiler.com/bot/" +3734[] = "Axandra GmbH" +3734[] = "http://www.axandra.com/" +3734[] = "bot_spbot.png" +3734[] = "" +3734[] = "/list-of-ua/bot-detail?bot=spbot" +3589[] = "Mozilla/5.0 (compatible; spbot/1.2; +http://www.seoprofiler.com/bot/ )" +3589[] = "spbot" +3589[] = "spbot/1.2" +3589[] = "http://www.seoprofiler.com/bot/" +3589[] = "Axandra GmbH" +3589[] = "http://www.axandra.com/" +3589[] = "bot_spbot.png" +3589[] = "" +3589[] = "/list-of-ua/bot-detail?bot=spbot" +4097[] = "Mozilla/5.0 (compatible; spbot/2.0.1; +http://www.seoprofiler.com/bot/ )" +4097[] = "spbot" +4097[] = "spbot/2.0.1" +4097[] = "http://www.seoprofiler.com/bot/" +4097[] = "Axandra GmbH" +4097[] = "http://www.axandra.com/" +4097[] = "bot_spbot.png" +4097[] = "" +4097[] = "/list-of-ua/bot-detail?bot=spbot" +4377[] = "Mozilla/5.0 (compatible; spbot/2.0.2; +http://www.seoprofiler.com/bot/ )" +4377[] = "spbot" +4377[] = "spbot/2.0.2" +4377[] = "http://www.seoprofiler.com/bot/" +4377[] = "Axandra GmbH" +4377[] = "http://www.axandra.com/" +4377[] = "bot_spbot.png" +4377[] = "" +4377[] = "/list-of-ua/bot-detail?bot=spbot" +999[] = "Speedy Spider (http://www.entireweb.com/about/search_tech/speedy_spider/)" +999[] = "Speedy" +999[] = "Speedy Spider" +999[] = "http://www.entireweb.com/about/search_tech/speedy_spider/" +999[] = "Entireweb.com" +999[] = "http://www.entireweb.com/" +999[] = "bot_Speedy.png" +999[] = "" +999[] = "/list-of-ua/bot-detail?bot=Speedy" +1885[] = "Speedy Spider (Entireweb; Beta/1.2; http://www.entireweb.com/about/search_tech/speedyspider/)" +1885[] = "Speedy" +1885[] = "Speedy Spider Beta/1.2" +1885[] = "http://www.entireweb.com/about/search_tech/speedy_spider/" +1885[] = "Entireweb.com" +1885[] = "http://www.entireweb.com/" +1885[] = "bot_Speedy.png" +1885[] = "" +1885[] = "/list-of-ua/bot-detail?bot=Speedy" +4185[] = "Mozilla/5.0 (compatible; Speedy Spider; http://www.entireweb.com/about/search_tech/speedy_spider/)" +4185[] = "Speedy" +4185[] = "Speedy Spider" +4185[] = "http://www.entireweb.com/about/search_tech/speedy_spider/" +4185[] = "Entireweb.com" +4185[] = "http://www.entireweb.com/" +4185[] = "bot_Speedy.png" +4185[] = "" +4185[] = "/list-of-ua/bot-detail?bot=Speedy" +1784[] = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1; aggregator:Spinn3r (Spinn3r 3.1); http://spinn3r.com/robot) Gecko/20021130" +1784[] = "Spinn3r" +1784[] = "Spinn3r 3.1" +1784[] = "http://spinn3r.com/robot" +1784[] = "Tailrank Inc" +1784[] = "http://tailrank.com/" +1784[] = "bot.png" +1784[] = "" +1784[] = "/list-of-ua/bot-detail?bot=Spinn3r" +5066[] = "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.19; aggregator:Spinn3r (Spinn3r 3.1); http://spinn3r.com/robot) Gecko/2010040121 Firefox/3.0.19" +5066[] = "Spinn3r" +5066[] = "Spinn3r 3.1" +5066[] = "http://spinn3r.com/robot" +5066[] = "Tailrank Inc" +5066[] = "http://tailrank.com/" +5066[] = "bot.png" +5066[] = "" +5066[] = "/list-of-ua/bot-detail?bot=Spinn3r" +934[] = "Spock Crawler (http://www.spock.com/crawler)" +934[] = "Spock Crawler" +934[] = "Spock Crawler" +934[] = "http://www.spock.com/crawler" +934[] = "spock.com" +934[] = "http://www.spock.com/" +934[] = "bot.png" +934[] = "" +934[] = "/list-of-ua/bot-detail?bot=Spock Crawler" +1472[] = "SpokeSpider/1.0 (http://support.spoke.com/webspider/) Mozilla/5.0 (not really)" +1472[] = "SpokeSpider" +1472[] = "SpokeSpider/1.0" +1472[] = "http://support.spoke.com/webspider/" +1472[] = "Spoke Software " +1472[] = "http://www.spoke.com/company/" +1472[] = "bot.png" +1472[] = "" +1472[] = "/list-of-ua/bot-detail?bot=SpokeSpider" +296[] = "sproose/0.1-alpha (sproose crawler; http://www.sproose.com/bot.html; crawler@sproose.com)" +296[] = "sproose" +296[] = "sproose/0.1-alpha" +296[] = "http://www.sproose.com/bot.html" +296[] = "Sproose, Inc." +296[] = "http://www.sproose.com/" +296[] = "bot.png" +296[] = "" +296[] = "/list-of-ua/bot-detail?bot=sproose" +435[] = "sproose/0.1 (sproose bot; http://www.sproose.com/bot.html; crawler@sproose.com)" +435[] = "sproose" +435[] = "sproose/0.1" +435[] = "http://www.sproose.com/bot.html" +435[] = "Sproose, Inc." +435[] = "http://www.sproose.com/" +435[] = "bot.png" +435[] = "" +435[] = "/list-of-ua/bot-detail?bot=sproose" +545[] = "sproose/1.0beta (sproose bot; http://www.sproose.com/bot.html; crawler@sproose.com)" +545[] = "Sproose" +545[] = "Sproose/1.0beta" +545[] = "http://www.sproose.com/bot.html" +545[] = "Sproose, Inc." +545[] = "http://www.sproose.com/" +545[] = "bot.png" +545[] = "" +545[] = "/list-of-ua/bot-detail?bot=Sproose" +392[] = "SrevBot/2.0 (SrevBot; http://winsrev.com/bot.html; bot@winsrev.com)" +392[] = "SrevBot" +392[] = "SrevBot/2.0" +392[] = "http://www.winsrev.com/" +392[] = "" +392[] = "" +392[] = "bot.png" +392[] = "" +392[] = "/list-of-ua/bot-detail?bot=SrevBot" +410[] = "SrevBot/1.2 (SrevBot; http://winsrev.com/bot.html; bot@winsrev.comg)" +410[] = "SrevBot" +410[] = "SrevBot/1.2" +410[] = "http://www.winsrev.com/" +410[] = "" +410[] = "" +410[] = "bot.png" +410[] = "" +410[] = "/list-of-ua/bot-detail?bot=SrevBot" +5231[] = "Mozilla/5.0 (compatible; SSLBot/1.0; http://www.sslstats.com/sslbot)" +5231[] = "SSLBot" +5231[] = "SSLBot/1.0" +5231[] = "http://www.sslstats.com/sslbot/" +5231[] = "sslstats.com" +5231[] = "http://www.sslstats.com/" +5231[] = "bot.png" +5231[] = "" +5231[] = "/list-of-ua/bot-detail?bot=SSLBot" +132[] = "StackRambler/2.0 (MSIE incompatible)" +132[] = "StackRambler" +132[] = "StackRambler/2.0" +132[] = "http://www.rambler.ru/doc/robots.shtml" +132[] = "Rambler Media Group" +132[] = "http://ramblermedia.com/" +132[] = "bot_stackrambler.png" +132[] = "" +132[] = "/list-of-ua/bot-detail?bot=StackRambler" +5145[] = "StatoolsBot (+http://www.statools.com/bot.html)" +5145[] = "StatoolsBot" +5145[] = "StatoolsBot" +5145[] = "http://www.statools.com/bot.html" +5145[] = "StaTools.com" +5145[] = "http://www.statools.com/" +5145[] = "bot.png" +5145[] = "" +5145[] = "/list-of-ua/bot-detail?bot=StatoolsBot" +567[] = "Steeler/3.2 (http://www.tkl.iis.u-tokyo.ac.jp/~crawler/)" +567[] = "Steeler" +567[] = "Steeler/3.2" +567[] = "http://www.tkl.iis.u-tokyo.ac.jp/~crawler/" +567[] = "Kitsuregawa Laboratory, The University of Tokyo" +567[] = "http://www.tkl.iis.u-tokyo.ac.jp/" +567[] = "bot_Steeler.png" +567[] = "" +567[] = "/list-of-ua/bot-detail?bot=Steeler" +1092[] = "Steeler/3.3 (http://www.tkl.iis.u-tokyo.ac.jp/~crawler/)" +1092[] = "Steeler" +1092[] = "Steeler/3.3" +1092[] = "http://www.tkl.iis.u-tokyo.ac.jp/~crawler/" +1092[] = "Kitsuregawa Laboratory, The University of Tokyo" +1092[] = "http://www.tkl.iis.u-tokyo.ac.jp/" +1092[] = "bot_Steeler.png" +1092[] = "" +1092[] = "/list-of-ua/bot-detail?bot=Steeler" +2099[] = "Mozilla/5.0 (compatible; Steeler/3.5; http://www.tkl.iis.u-tokyo.ac.jp/~crawler/)" +2099[] = "Steeler" +2099[] = "Steeler/3.5" +2099[] = "http://www.tkl.iis.u-tokyo.ac.jp/~crawler/" +2099[] = "Kitsuregawa Laboratory, The University of Tokyo" +2099[] = "http://www.tkl.iis.u-tokyo.ac.jp/" +2099[] = "bot_Steeler.png" +2099[] = "" +2099[] = "/list-of-ua/bot-detail?bot=Steeler" +5188[] = "Stroke.cz (http://stroke.cz)" +5188[] = "Strokebot" +5188[] = "Strokebot" +5188[] = "http://stroke.cz/oou/" +5188[] = "care4u, s. r. o." +5188[] = "http://care4u.cz/" +5188[] = "bot_strokebot.png" +5188[] = "" +5188[] = "/list-of-ua/bot-detail?bot=Strokebot" +5802[] = "Mozilla/5.0 (compatible; suggybot v0.01a, http://blog.suggy.com/was-ist-suggy/suggy-webcrawler/)" +5802[] = "suggybot" +5802[] = "suggybot/0.01a" +5802[] = "http://blog.suggy.com/was-ist-suggy/suggy-webcrawler/" +5802[] = "Suggy GbR" +5802[] = "http://www.suggy.com/" +5802[] = "bot.png" +5802[] = "" +5802[] = "/list-of-ua/bot-detail?bot=suggybot" +2098[] = "Surphace Scout&v4.0 - scout at surphace dot com" +2098[] = "Surphace Scout" +2098[] = "Surphace Scout/4.0" +2098[] = "" +2098[] = "Surphace (AOL news)" +2098[] = "http://www.surphace.com/" +2098[] = "bot_Surphace_Scout.png" +2098[] = "" +2098[] = "/list-of-ua/bot-detail?bot=Surphace Scout" +235[] = "SurveyBot/2.3 (Whois Source)" +235[] = "SurveyBot" +235[] = "SurveyBot/2.3" +235[] = "http://www.whois.sc/info/webmasters/surveybot.html" +235[] = "Name Intelligence, Inc." +235[] = "http://www.nameintelligence.com/" +235[] = "bot_surveybot.png" +235[] = "" +235[] = "/list-of-ua/bot-detail?bot=SurveyBot" +1078[] = "SygolBot http://www.sygol.com" +1078[] = "SygolBot" +1078[] = "SygolBot" +1078[] = "http://www.sygol.com/SygolBot.asp" +1078[] = "Giorgio Galeotti" +1078[] = "http://www.sygol.com/" +1078[] = "bot.png" +1078[] = "" +1078[] = "/list-of-ua/bot-detail?bot=SygolBot" +204[] = "SynooBot/0.7.1 (SynooBot; http://www.synoo.de/bot.html; webmaster@synoo.com)" +204[] = "SynooBot" +204[] = "SynooBot/0.7.1" +204[] = "http://www.synoo.de/bot.html" +204[] = "Synoo" +204[] = "http://www.synoo.de/" +204[] = "bot.png" +204[] = "" +204[] = "/list-of-ua/bot-detail?bot=SynooBot" +333[] = "SynooBot (compatible; Synoobot/0.7.1; http://www.synoo.com/search/bot.html)" +333[] = "SynooBot" +333[] = "SynooBot/0.7.1 com" +333[] = " http://www.synoo.com/search/bot.html" +333[] = "Synoo" +333[] = "http://www.synoo.com/" +333[] = "bot.png" +333[] = "" +333[] = "/list-of-ua/bot-detail?bot=SynooBot" +470[] = "Szukacz/1.5 (robot; www.szukacz.pl/html/jak_dziala_robot.html; info@szukacz.pl)" +470[] = "Szukacz" +470[] = "Szukacz/1.5" +470[] = "http://www.szukacz.pl/jakdzialarobot.html" +470[] = "24 Godziny Sp. z o.o." +470[] = "http://www.szukacz.pl/" +470[] = "bot.png" +470[] = "" +470[] = "/list-of-ua/bot-detail?bot=Szukacz" +565[] = "Szukacz/1.5 (robot; www.szukacz.pl/jakdzialarobot.html; info@szukacz.pl)" +565[] = "Szukacz" +565[] = "Szukacz/1.5 b" +565[] = "http://www.szukacz.pl/jakdzialarobot.html" +565[] = "24 Godziny Sp. z o.o." +565[] = "http://www.szukacz.pl/" +565[] = "bot.png" +565[] = "" +565[] = "/list-of-ua/bot-detail?bot=Szukacz" +96[] = "Szukankobot /1.0 (+http://www.szukanko.pl/addurl.php)" +96[] = "Szukankobot" +96[] = "Szukankobot /1.0" +96[] = "http://www.szukanko.pl/" +96[] = "szukanko.pl" +96[] = "http://www.szukanko.pl/" +96[] = "bot.png" +96[] = "" +96[] = "/list-of-ua/bot-detail?bot=Szukankobot" +1772[] = "Mozilla/5.0 (compatible; Tagoobot/3.0; +http://www.tagoo.ru)" +1772[] = "Tagoobot" +1772[] = "Tagoobot/3.0" +1772[] = "" +1772[] = "Tagoo" +1772[] = "http://www.tagoo.ru/" +1772[] = "bot.png" +1772[] = "" +1772[] = "/list-of-ua/bot-detail?bot=Tagoobot" +1971[] = "taptubot *** please read http://www.taptu.com/corp/taptubot ***" +1971[] = "taptubot" +1971[] = "taptubot" +1971[] = "http://www.taptu.com/corp/taptubot" +1971[] = "Taptu Limited" +1971[] = "http://www.taptu.com/" +1971[] = "bot.png" +1971[] = "" +1971[] = "/list-of-ua/bot-detail?bot=taptubot" +1727[] = "Technoratibot/7.0" +1727[] = "Technoratibot" +1727[] = "Technoratibot/7.0" +1727[] = "" +1727[] = "Technorati Inc." +1727[] = "http://www.technorati.com/" +1727[] = "bot.png" +1727[] = "" +1727[] = "/list-of-ua/bot-detail?bot=Technoratibot" +1728[] = "Technoratibot/8.0" +1728[] = "Technoratibot" +1728[] = "Technoratibot/8.0" +1728[] = "" +1728[] = "Technorati Inc." +1728[] = "http://www.technorati.com/" +1728[] = "bot.png" +1728[] = "" +1728[] = "/list-of-ua/bot-detail?bot=Technoratibot" +352[] = "TeragramCrawler" +352[] = "TeragramCrawler" +352[] = "TeragramCrawler" +352[] = "" +352[] = "Teragram Corporation" +352[] = "http://www.teragram.com/" +352[] = "bot.png" +352[] = "" +352[] = "/list-of-ua/bot-detail?bot=TeragramCrawler" +412[] = "textractor.queuekeeper/0.1 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)" +412[] = "textractor" +412[] = "textractor.queuekeeper/0.1" +412[] = "http://ufal.mff.cuni.cz/project/textractor/" +412[] = "Institute of Formal and Applied Linguistics (ÚFAL)" +412[] = "http://ufal.mff.cuni.cz/" +412[] = "bot.png" +412[] = "" +412[] = "/list-of-ua/bot-detail?bot=textractor" +445[] = "textractor.harvester/h7/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)" +445[] = "textractor" +445[] = "textractor.harvester/h7/1.0" +445[] = "http://ufal.mff.cuni.cz/project/textractor/" +445[] = "Institute of Formal and Applied Linguistics (ÚFAL)" +445[] = "http://ufal.mff.cuni.cz/" +445[] = "bot.png" +445[] = "" +445[] = "/list-of-ua/bot-detail?bot=textractor" +447[] = "textractor.harvester/h3/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)" +447[] = "textractor" +447[] = "textractor.harvester/h3/1.0" +447[] = "http://ufal.mff.cuni.cz/project/textractor/" +447[] = "Institute of Formal and Applied Linguistics (ÚFAL)" +447[] = "http://ufal.mff.cuni.cz/" +447[] = "bot.png" +447[] = "" +447[] = "/list-of-ua/bot-detail?bot=textractor" +645[] = "textractor.harvester/h2/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)" +645[] = "textractor" +645[] = "textractor.harvester/h2/1.0" +645[] = "http://ufal.mff.cuni.cz/project/textractor/" +645[] = "Institute of Formal and Applied Linguistics (ÚFAL)" +645[] = "http://ufal.mff.cuni.cz/" +645[] = "bot.png" +645[] = "" +645[] = "/list-of-ua/bot-detail?bot=textractor" +646[] = "textractor.harvester/h27/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)" +646[] = "textractor" +646[] = "textractor.harvester/h27/1.0" +646[] = "http://ufal.mff.cuni.cz/project/textractor/" +646[] = "Institute of Formal and Applied Linguistics (ÚFAL)" +646[] = "http://ufal.mff.cuni.cz/" +646[] = "bot.png" +646[] = "" +646[] = "/list-of-ua/bot-detail?bot=textractor" +648[] = "textractor.harvester/h24/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)" +648[] = "textractor" +648[] = "textractor.harvester/h24/1.0" +648[] = "http://ufal.mff.cuni.cz/project/textractor/" +648[] = "Institute of Formal and Applied Linguistics (ÚFAL)" +648[] = "http://ufal.mff.cuni.cz/" +648[] = "bot.png" +648[] = "" +648[] = "/list-of-ua/bot-detail?bot=textractor" +961[] = "textractor.harvester/h5/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)" +961[] = "textractor" +961[] = "textractor.harvester/h5/1.0" +961[] = "http://ufal.mff.cuni.cz/project/textractor/" +961[] = "Institute of Formal and Applied Linguistics (ÚFAL)" +961[] = "http://ufal.mff.cuni.cz/" +961[] = "bot.png" +961[] = "" +961[] = "/list-of-ua/bot-detail?bot=textractor" +962[] = "textractor.harvester/h39/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)" +962[] = "textractor" +962[] = "textractor.harvester/h39/1.0" +962[] = "http://ufal.mff.cuni.cz/project/textractor/" +962[] = "Institute of Formal and Applied Linguistics (ÚFAL)" +962[] = "http://ufal.mff.cuni.cz/" +962[] = "bot.png" +962[] = "" +962[] = "/list-of-ua/bot-detail?bot=textractor" +963[] = "textractor.harvester/h37/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)" +963[] = "textractor" +963[] = "textractor.harvester/h37/1.0" +963[] = "http://ufal.mff.cuni.cz/project/textractor/" +963[] = "Institute of Formal and Applied Linguistics (ÚFAL)" +963[] = "http://ufal.mff.cuni.cz/" +963[] = "bot.png" +963[] = "" +963[] = "/list-of-ua/bot-detail?bot=textractor" +964[] = "textractor.harvester/h38/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)" +964[] = "textractor" +964[] = "textractor.harvester/h38/1.0" +964[] = "http://ufal.mff.cuni.cz/project/textractor/" +964[] = "Institute of Formal and Applied Linguistics (ÚFAL)" +964[] = "http://ufal.mff.cuni.cz/" +964[] = "bot.png" +964[] = "" +964[] = "/list-of-ua/bot-detail?bot=textractor" +965[] = "textractor.harvester/h12/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)" +965[] = "textractor" +965[] = "textractor.harvester/h12/1.0" +965[] = "http://ufal.mff.cuni.cz/project/textractor/" +965[] = "Institute of Formal and Applied Linguistics (ÚFAL)" +965[] = "http://ufal.mff.cuni.cz/" +965[] = "bot.png" +965[] = "" +965[] = "/list-of-ua/bot-detail?bot=textractor" +966[] = "textractor.harvester/h34/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)" +966[] = "textractor" +966[] = "textractor.harvester/h34/1.0" +966[] = "http://ufal.mff.cuni.cz/project/textractor/" +966[] = "Institute of Formal and Applied Linguistics (ÚFAL)" +966[] = "http://ufal.mff.cuni.cz/" +966[] = "bot.png" +966[] = "" +966[] = "/list-of-ua/bot-detail?bot=textractor" +218[] = "Mozilla/5.0 (compatible; Theophrastus/2.0; +http://users.cs.cf.ac.uk/N.A.Smith/theophrastus.php)" +218[] = "Theophrastus" +218[] = "Theophrastus/2.0" +218[] = "http://users.cs.cf.ac.uk/N.A.Smith/theophrastus.php" +218[] = "" +218[] = "" +218[] = "bot.png" +218[] = "" +218[] = "/list-of-ua/bot-detail?bot=Theophrastus" +2004[] = "Thumbnail.CZ robot 1.1 (http://thumbnail.cz/why-no-robots-txt.html)" +2004[] = "Thumbnail.CZ robot" +2004[] = "Thumbnail.CZ robot 1.1" +2004[] = "http://thumbnail.cz/why-no-robots-txt.html" +2004[] = "Miroslav Suchý" +2004[] = "http://miroslav.suchy.cz/" +2004[] = "bot.png" +2004[] = "" +2004[] = "/list-of-ua/bot-detail?bot=Thumbnail.CZ robot" +2175[] = "ThumbShots-Bot (+http://thumbshots.in/bot.html)" +2175[] = "ThumbShots-Bot" +2175[] = "ThumbShots-Bot" +2175[] = "http://thumbshots.in/bot.html" +2175[] = "Kristian Fischer" +2175[] = "http://www.kfsw.de/" +2175[] = "bot.png" +2175[] = "" +2175[] = "/list-of-ua/bot-detail?bot=ThumbShots-Bot" +194[] = "thumbshots-de-Bot (Version: 1.02, powered by www.thumbshots.de)" +194[] = "thumbshots-de-Bot" +194[] = "thumbshots-de-Bot 1.02" +194[] = "http://www.thumbshots.de/content-39-seite_auszuschliessen.html" +194[] = "Mobile & More Mobilkommunikation GmbH" +194[] = "http://www.mobile-more.com/" +194[] = "bot.png" +194[] = "" +194[] = "/list-of-ua/bot-detail?bot=thumbshots-de-Bot" +5828[] = "thumbshots-de-bot (+http://www.thumbshots.de/)" +5828[] = "thumbshots-de-Bot" +5828[] = "thumbshots-de-bot" +5828[] = "http://www.thumbshots.de/content-39-seite_auszuschliessen.html" +5828[] = "Mobile & More Mobilkommunikation GmbH" +5828[] = "http://www.mobile-more.com/" +5828[] = "bot.png" +5828[] = "" +5828[] = "/list-of-ua/bot-detail?bot=thumbshots-de-Bot" +2003[] = "TinEye/1.0; +http://www.tineye.com/" +2003[] = "TinEye" +2003[] = "TinEye/1.0" +2003[] = "http://tineye.com/crawler.html " +2003[] = "Idée Inc." +2003[] = "http://ideeinc.com/" +2003[] = "bot_TinEye.png" +2003[] = "" +2003[] = "/list-of-ua/bot-detail?bot=TinEye" +2183[] = "TinEye/1.1 (http://tineye.com/crawler.html)" +2183[] = "TinEye" +2183[] = "TinEye/1.1" +2183[] = "http://tineye.com/crawler.html" +2183[] = "Idée Inc." +2183[] = "http://ideeinc.com/" +2183[] = "bot_TinEye.png" +2183[] = "" +2183[] = "/list-of-ua/bot-detail?bot=TinEye" +1838[] = "Mozilla/5.0 (compatible; Topicbot/12.0rc-2; +http://topicbot.awardspace.us/)" +1838[] = "Topicbot" +1838[] = "Topicbot/12.0rc-2" +1838[] = "http://topicbot.awardspace.us/" +1838[] = "Research Group TopicBot" +1838[] = "http://topicbot.awardspace.us/" +1838[] = "bot.png" +1838[] = "" +1838[] = "/list-of-ua/bot-detail?bot=Topicbot" +4000[] = "Mozilla/4.0 (Toread-Crawler/1.1; +http://news.toread.cc/crawler.php)" +4000[] = "Toread-Crawler" +4000[] = "Toread-Crawler/1.1" +4000[] = "http://news.toread.cc/crawler.php" +4000[] = "sidefeed, Inc" +4000[] = "http://sidefeed.com/" +4000[] = "bot_Toread-Crawler.png" +4000[] = "" +4000[] = "/list-of-ua/bot-detail?bot=Toread-Crawler" +1293[] = "Touche (+http://www.touche.com.ve)" +1293[] = "Touche" +1293[] = "Touche" +1293[] = "http://www.touche.com.ve/Acerca.jsp" +1293[] = "Touché" +1293[] = "http://www.touche.com.ve/" +1293[] = "bot.png" +1293[] = "" +1293[] = "/list-of-ua/bot-detail?bot=Touche" +6146[] = "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.0; trendictionbot0.4.2; trendiction media ssppiiddeerr; http://www.trendiction.com/bot/; please let us know of any problems; ssppiiddeerr at trendiction.com) Gecko/20071127 Firefox/2.0.0.11" +6146[] = "trendictionbot" +6146[] = "trendictionbot/0.4.2" +6146[] = "http://www.trendiction.com/en/publisher/bot" +6146[] = "Trendiction S.A." +6146[] = "http://www.trendiction.com/" +6146[] = "bot.png" +6146[] = "" +6146[] = "/list-of-ua/bot-detail?bot=trendictionbot" +489[] = "TurnitinBot/2.0 (http://www.turnitin.com/robot/crawlerinfo.html)" +489[] = "TurnitinBot" +489[] = "TurnitinBot/2.0" +489[] = "http://www.turnitin.com/robot/crawlerinfo.html" +489[] = "iParadigms, LLC." +489[] = "http://www.iparadigms.com/" +489[] = "bot.png" +489[] = "" +489[] = "/list-of-ua/bot-detail?bot=TurnitinBot" +703[] = "TurnitinBot/2.1 (http://www.turnitin.com/robot/crawlerinfo.html)" +703[] = "TurnitinBot" +703[] = "TurnitinBot/2.1" +703[] = "http://www.turnitin.com/robot/crawlerinfo.html" +703[] = "iParadigms, LLC." +703[] = "http://www.iparadigms.com/" +703[] = "bot.png" +703[] = "" +703[] = "/list-of-ua/bot-detail?bot=TurnitinBot" +40[] = "TutorGigBot/1.5 ( +http://www.tutorgig.info )" +40[] = "TutorGigBot" +40[] = "TutorGigBot" +40[] = "http://www.tutorgig.com/help.html" +40[] = "TutorGig" +40[] = "http://www.tutorgig.com/" +40[] = "bot.png" +40[] = "" +40[] = "/list-of-ua/bot-detail?bot=TutorGigBot" +1763[] = "TwengaBot/1.1 (+http://www.twenga.com/bot.html)" +1763[] = "TwengaBot" +1763[] = "TwengaBot/1.1" +1763[] = "http://www.twenga.com/bot.html" +1763[] = "Twenga SA" +1763[] = "http://www.twenga.com/" +1763[] = "bot.png" +1763[] = "" +1763[] = "/list-of-ua/bot-detail?bot=TwengaBot" +5006[] = "TwengaBot-Discover (http://www.twenga.fr/bot-discover.html)" +5006[] = "TwengaBot" +5006[] = "TwengaBot-Discover" +5006[] = "http://www.twenga.com/bot.html" +5006[] = "Twenga SA" +5006[] = "http://www.twenga.com/" +5006[] = "bot.png" +5006[] = "" +5006[] = "/list-of-ua/bot-detail?bot=TwengaBot" +5839[] = "TwengaBot" +5839[] = "TwengaBot" +5839[] = "TwengaBot" +5839[] = "http://www.twenga.com/bot.html" +5839[] = "Twenga SA" +5839[] = "http://www.twenga.com/" +5839[] = "bot.png" +5839[] = "" +5839[] = "/list-of-ua/bot-detail?bot=TwengaBot" +1462[] = "Mozilla/5.0 (Twiceler-0.9 http://www.cuil.com/twiceler/robot.html)" +1462[] = "Twiceler" +1462[] = "Twiceler-0.9" +1462[] = "http://www.cuil.com/twiceler/robot.html" +1462[] = "Cuil, Inc. " +1462[] = "http://www.cuil.com/" +1462[] = "bot_Twiceler.png" +1462[] = "" +1462[] = "/list-of-ua/bot-detail?bot=Twiceler" +1759[] = "Twiceler-0.9 http://www.cuill.com/twiceler/robot.html" +1759[] = "Twiceler" +1759[] = "Twiceler-0.9 b" +1759[] = "http://www.cuil.com/twiceler/robot.html" +1759[] = "Cuil, Inc." +1759[] = "http://www.cuil.com/" +1759[] = "bot_Twiceler.png" +1759[] = "" +1759[] = "/list-of-ua/bot-detail?bot=Twiceler" +6065[] = "UnwindFetchor/1.0 (+http://www.gnip.com/)" +6065[] = "UnwindFetchor" +6065[] = "UnwindFetchor/1.0" +6065[] = "" +6065[] = "Gnip, inc." +6065[] = "http://gnip.com/" +6065[] = "bot.png" +6065[] = "" +6065[] = "/list-of-ua/bot-detail?bot=UnwindFetchor" +345[] = "updated/0.1-beta (updated; http://www.updated.com; crawler@updated.com)" +345[] = "updated" +345[] = "updated/0.1-beta" +345[] = "" +345[] = "Updated.com Inc." +345[] = "http://www.updated.com/" +345[] = "bot.png" +345[] = "" +345[] = "/list-of-ua/bot-detail?bot=updated" +437[] = "updated/0.1-alpha (updated crawler; http://www.updated.com; crawler@updated.com)" +437[] = "updated" +437[] = "updated/0.1-alpha" +437[] = "" +437[] = "Updated.com Inc." +437[] = "http://www.updated.com/" +437[] = "bot.png" +437[] = "" +437[] = "/list-of-ua/bot-detail?bot=updated" +1662[] = "UptimeDog Robot (www.uptimedog.com)" +1662[] = "UptimeDog" +1662[] = "UptimeDog" +1662[] = "http://www.uptimedog.com/" +1662[] = "San Pedro Software Inc." +1662[] = "http://mosw.com/" +1662[] = "bot.png" +1662[] = "" +1662[] = "/list-of-ua/bot-detail?bot=UptimeDog" +1505[] = "urlfan-bot/1.0; +http://www.urlfan.com/site/bot/350.html" +1505[] = "urlfan-bot" +1505[] = "urlfan-bot/1.0" +1505[] = "http://www.urlfan.com/site/bot/350.html" +1505[] = "://URLFAN" +1505[] = "http://www.urlfan.com/" +1505[] = "bot.png" +1505[] = "" +1505[] = "/list-of-ua/bot-detail?bot=urlfan-bot" +5727[] = "Mozilla/5.0 (compatible; Urlfilebot/2.2; +http://urlfile.com/bot.html)" +5727[] = "Urlfilebot (Urlbot)" +5727[] = "Urlfilebot/2.2" +5727[] = "http://urlfile.com/bot.html" +5727[] = "Urlfile" +5727[] = "http://urlfile.com/" +5727[] = "bot.png" +5727[] = "" +5727[] = "/list-of-ua/bot-detail?bot=Urlfilebot (Urlbot)" +439[] = "Vagabondo/3.0 (webagent at wise-guys dot nl)" +439[] = "Vagabondo" +439[] = "Vagabondo/3.0" +439[] = "http://webagent.wise-guys.nl/" +439[] = "WiseGuys Internet BV" +439[] = "http://www.wise-guys.nl/" +439[] = "bot.png" +439[] = "" +439[] = "/list-of-ua/bot-detail?bot=Vagabondo" +1766[] = "Mozilla/4.0 (compatible; Vagabondo/4.0Beta; webcrawler at wise-guys dot nl; http://webagent.wise-guys.nl/; http://www.wise-guys.nl/)" +1766[] = "Vagabondo" +1766[] = "Vagabondo/4.0Beta" +1766[] = "http://webagent.wise-guys.nl/" +1766[] = "WiseGuys Internet BV" +1766[] = "http://www.wise-guys.nl/" +1766[] = "bot.png" +1766[] = "" +1766[] = "/list-of-ua/bot-detail?bot=Vagabondo" +5275[] = "Mozilla/4.0 (compatible; Vagabondo/4.0; http://webagent.wise-guys.nl/)" +5275[] = "Vagabondo" +5275[] = "Vagabondo/4.0" +5275[] = "http://webagent.wise-guys.nl/" +5275[] = "WiseGuys Internet BV" +5275[] = "http://www.wise-guys.nl/" +5275[] = "bot.png" +5275[] = "" +5275[] = "/list-of-ua/bot-detail?bot=Vagabondo" +658[] = "VERASYS 2k Mozilla/4.0 (compatible; en) (compatible; MSIE 6.0; Windows NT 5.2; (+ http://web.verasys.ro); SV1; Unix; .NET CLR 1.1.4322)" +658[] = "VERASYS 2k" +658[] = "VERASYS 2k" +658[] = "http://www.ghita.ro/article/1/verasys_2k.html" +658[] = "Serban Ghita" +658[] = "http://www.ghita.ro/" +658[] = "bot.png" +658[] = "" +658[] = "/list-of-ua/bot-detail?bot=VERASYS 2k" +329[] = "Mozilla/5.0 (compatible; Vermut +http://vermut.aol.com)" +329[] = "Vermut" +329[] = "Vermut" +329[] = "http://vermut.aol.com/" +329[] = "America Online, Inc." +329[] = "http://www.aol.com/" +329[] = "bot.png" +329[] = "" +329[] = "/list-of-ua/bot-detail?bot=Vermut" +195[] = "Vespa Crawler" +195[] = "Vespa Crawler" +195[] = "Vespa Crawler" +195[] = "http://jobs.yahoo.no/index.html" +195[] = "Yahoo!" +195[] = "http://www.yahoo.com/" +195[] = "bot.png" +195[] = "" +195[] = "/list-of-ua/bot-detail?bot=Vespa Crawler" +5065[] = "Mozilla/5.0 (compatible; VideoSurf_bot +http://www.videosurf.com/bot.html)" +5065[] = "VideoSurf_bot" +5065[] = "VideoSurf_bot" +5065[] = "http://www.videosurf.com/bot.html" +5065[] = "VideoSurf Inc." +5065[] = "http://www.videosurf.com/" +5065[] = "bot.png" +5065[] = "" +5065[] = "/list-of-ua/bot-detail?bot=VideoSurf_bot" +376[] = "virus_detector (virus_harvester@securecomputing.com)" +376[] = "virus_detector" +376[] = "virus_detector" +376[] = "http://www.securecomputing.com/sg2_antivirus.cfm?menu=solutions" +376[] = "Secure Computing Corporation." +376[] = "http://www.securecomputing.com/" +376[] = "bot.png" +376[] = "" +376[] = "/list-of-ua/bot-detail?bot=virus_detector" +629[] = "Visbot/1.1 (Visvo.com - The Category Search Engine!; http://www.visvo.com/bot.html; bot@visvo.com)" +629[] = "visbot" +629[] = "visbot/1.1" +629[] = "http://www.visvo.com/bot.html" +629[] = "" +629[] = "" +629[] = "bot.png" +629[] = "" +629[] = "/list-of-ua/bot-detail?bot=visbot" +798[] = "VisBot/2.0 (Visvo.com Crawler; http://www.visvo.com/bot.html; bot@visvo.com)" +798[] = "visbot" +798[] = "visbot/2.0" +798[] = "http://www.visvo.com/bot.html" +798[] = "" +798[] = "" +798[] = "bot.png" +798[] = "" +798[] = "/list-of-ua/bot-detail?bot=visbot" +612[] = "VMBot/0.7.2 (VMBot; http://www.VerticalMatch.com/; vmbot@tradedot.com)" +612[] = "VMBot" +612[] = "VMBot/0.7.2" +612[] = "" +612[] = "Vertical Search Engine (China)" +612[] = "http://www.verticalmatch.com/" +612[] = "bot.png" +612[] = "" +612[] = "/list-of-ua/bot-detail?bot=VMBot" +698[] = "VMBot/0.9 (VMBot; http://www.verticalmatch.com; vmbot@tradedot.com)" +698[] = "VMBot" +698[] = "VMBot/0.9" +698[] = "" +698[] = "Vertical Search Engine (China)" +698[] = "http://www.verticalmatch.com/" +698[] = "bot.png" +698[] = "" +698[] = "/list-of-ua/bot-detail?bot=VMBot" +888[] = "void-bot/0.1 (bot@void.be; http://www.void.be/)" +888[] = "void-bot" +888[] = "void-bot/0.1" +888[] = "http://www.void.be/void-bot.html" +888[] = "Void Security" +888[] = "http://www.void.be/" +888[] = "bot.png" +888[] = "" +888[] = "/list-of-ua/bot-detail?bot=void-bot" +222[] = "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) VoilaBot BETA 1.2 (http://www.voila.com/)" +222[] = "VoilaBot" +222[] = "VoilaBot BETA 1.2" +222[] = "http://www.voila.com/" +222[] = "France Telecom" +222[] = "http://www.francetelecom.com/" +222[] = "bot.png" +222[] = "" +222[] = "/list-of-ua/bot-detail?bot=VoilaBot" +1567[] = "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.1) VoilaBot BETA 1.2 (support.voilabot@orange-ftgroup.com)" +1567[] = "VoilaBot" +1567[] = "VoilaBot BETA 1.2" +1567[] = "" +1567[] = "France Telecom" +1567[] = "http://www.francetelecom.com/" +1567[] = "bot.png" +1567[] = "" +1567[] = "/list-of-ua/bot-detail?bot=VoilaBot" +225[] = "VORTEX/1.2 (+http://marty.anstey.ca/robots/vortex/)" +225[] = "VORTEX" +225[] = "VORTEX/1.2" +225[] = "http://marty.anstey.ca/projects/robots/vortex/" +225[] = "Marty Anstey" +225[] = "http://marty.anstey.ca/" +225[] = "bot.png" +225[] = "" +225[] = "/list-of-ua/bot-detail?bot=VORTEX" +1586[] = "voyager/2.0 (http://www.kosmix.com/crawler.html)" +1586[] = "voyager" +1586[] = "voyager/2.0" +1586[] = "http://www.kosmix.com/corp/crawler.html" +1586[] = "Kosmix Corporation" +1586[] = "http://www.kosmix.com/html/about.html" +1586[] = "bot.png" +1586[] = "" +1586[] = "/list-of-ua/bot-detail?bot=voyager" +1619[] = "voyager/1.0 (+http://www.kosmix.com/html/crawler.html)" +1619[] = "voyager" +1619[] = "voyager/1.0" +1619[] = "http://www.kosmix.com/corp/crawler.html" +1619[] = "Kosmix Corporation" +1619[] = "http://www.kosmix.com/html/about.html" +1619[] = "bot.png" +1619[] = "" +1619[] = "/list-of-ua/bot-detail?bot=voyager" +929[] = "VWBOT/Nutch-0.9-dev (VWBOT Nutch Crawler; http://vwbot.cs.uiuc.edu; vwbot@cs.uiuc.edu)" +929[] = "VWBot" +929[] = "VWBot/Nutch-0.9-dev" +929[] = "http://vwbot.cs.uiuc.edu/" +929[] = "University of Illinois at Urbana-Champaign" +929[] = "http://www.cs.uiuc.edu/" +929[] = "bot.png" +929[] = "" +929[] = "/list-of-ua/bot-detail?bot=VWBot" +5642[] = "WatchMouse/18990 (http://watchmouse.com/ ; hk)" +5642[] = "WatchMouse" +5642[] = "WatchMouse/18990 hk" +5642[] = "http://www.watchmouse.com/" +5642[] = "WatchMouse" +5642[] = "" +5642[] = "bot_WatchMouse.png" +5642[] = "" +5642[] = "/list-of-ua/bot-detail?bot=WatchMouse" +5639[] = "WatchMouse/18990 (http://watchmouse.com/ ; ny)" +5639[] = "WatchMouse" +5639[] = "WatchMouse/18990 ny" +5639[] = "http://www.watchmouse.com/" +5639[] = "WatchMouse" +5639[] = "" +5639[] = "bot_WatchMouse.png" +5639[] = "" +5639[] = "/list-of-ua/bot-detail?bot=WatchMouse" +5640[] = "WatchMouse/18990 (http://watchmouse.com/ ; se.watchmouse.com)" +5640[] = "WatchMouse" +5640[] = "WatchMouse/18990 se.watchmouse.com" +5640[] = "http://www.watchmouse.com/" +5640[] = "WatchMouse" +5640[] = "" +5640[] = "bot_WatchMouse.png" +5640[] = "" +5640[] = "/list-of-ua/bot-detail?bot=WatchMouse" +5641[] = "WatchMouse/18990 (http://watchmouse.com/ ; it)" +5641[] = "WatchMouse" +5641[] = "WatchMouse/18990 it" +5641[] = "http://www.watchmouse.com/" +5641[] = "WatchMouse" +5641[] = "" +5641[] = "bot_WatchMouse.png" +5641[] = "" +5641[] = "/list-of-ua/bot-detail?bot=WatchMouse" +5643[] = "WatchMouse/18990 (http://watchmouse.com/ ; bc.watchmouse.com)" +5643[] = "WatchMouse" +5643[] = "WatchMouse/18990 bc" +5643[] = "http://www.watchmouse.com/" +5643[] = "WatchMouse" +5643[] = "" +5643[] = "bot_WatchMouse.png" +5643[] = "" +5643[] = "/list-of-ua/bot-detail?bot=WatchMouse" +5644[] = "WatchMouse/18990 (http://watchmouse.com/ ; uk)" +5644[] = "WatchMouse" +5644[] = "WatchMouse/18990 uk" +5644[] = "http://www.watchmouse.com/" +5644[] = "WatchMouse" +5644[] = "" +5644[] = "bot_WatchMouse.png" +5644[] = "" +5644[] = "/list-of-ua/bot-detail?bot=WatchMouse" +5635[] = "WatchMouse/18990 (http://watchmouse.com/ ; d2.watchmouse.com)" +5635[] = "WatchMouse" +5635[] = "WatchMouse/18990 d2.watchmouse.com" +5635[] = "http://www.watchmouse.com/" +5635[] = "WatchMouse" +5635[] = "" +5635[] = "bot_WatchMouse.png" +5635[] = "" +5635[] = "/list-of-ua/bot-detail?bot=WatchMouse" +5636[] = "WatchMouse/18990 (http://watchmouse.com/ ; liz)" +5636[] = "WatchMouse" +5636[] = "WatchMouse/18990 liz" +5636[] = "http://www.watchmouse.com/" +5636[] = "WatchMouse" +5636[] = "" +5636[] = "bot_WatchMouse.png" +5636[] = "" +5636[] = "/list-of-ua/bot-detail?bot=WatchMouse" +5637[] = "WatchMouse/18990 (http://watchmouse.com/ ; d3.watchmouse.com)" +5637[] = "WatchMouse" +5637[] = "WatchMouse/18990 d3.watchmouse.com" +5637[] = "http://www.watchmouse.com/" +5637[] = "WatchMouse" +5637[] = "" +5637[] = "bot_WatchMouse.png" +5637[] = "" +5637[] = "/list-of-ua/bot-detail?bot=WatchMouse" +5638[] = "WatchMouse/18990 (http://watchmouse.com/ ; gab)" +5638[] = "WatchMouse" +5638[] = "WatchMouse/18990 gab" +5638[] = "http://www.watchmouse.com/" +5638[] = "WatchMouse" +5638[] = "" +5638[] = "bot_WatchMouse.png" +5638[] = "" +5638[] = "/list-of-ua/bot-detail?bot=WatchMouse" +4546[] = "Web-sniffer/1.0.31 (+http://web-sniffer.net/)" +4546[] = "Web-sniffer" +4546[] = "Web-sniffer/1.0.31" +4546[] = "" +4546[] = "Lingo4you GbR" +4546[] = "http://www.lingo4u.de/" +4546[] = "bot.png" +4546[] = "" +4546[] = "/list-of-ua/bot-detail?bot=Web-sniffer" +902[] = "WebAlta Crawler/1.3.33 (http://www.webalta.net/ru/about_webmaster.html) (Windows; U; Windows NT 5.1; ru-RU)" +902[] = "WebAlta Crawler" +902[] = "WebAlta Crawler/1.3.33" +902[] = "http://www.webalta.net/ru/about_webmaster.html" +902[] = "Webalta" +902[] = "http://www.webalta.ru/" +902[] = "bot.png" +902[] = "" +902[] = "/list-of-ua/bot-detail?bot=WebAlta Crawler" +922[] = "WebAlta Crawler/1.3.34 (http://www.webalta.net/ru/about_webmaster.html) (Windows; U; Windows NT 5.1; ru-RU)" +922[] = "WebAlta Crawler" +922[] = "WebAlta Crawler/1.3.34" +922[] = "http://www.webalta.net/ru/about_webmaster.html" +922[] = "Webalta" +922[] = "http://www.webalta.ru/" +922[] = "bot.png" +922[] = "" +922[] = "/list-of-ua/bot-detail?bot=WebAlta Crawler" +5701[] = "WebAlta Crawler/1.3.25 (http://www.webalta.net/ru/about_webmaster.html) (Windows; U; Windows NT 5.1; ru-RU)" +5701[] = "WebAlta Crawler" +5701[] = "WebAlta Crawler/1.3.25" +5701[] = "http://www.webalta.net/ru/about_webmaster.html" +5701[] = "Webalta" +5701[] = "http://www.webalta.ru/" +5701[] = "bot.png" +5701[] = "" +5701[] = "/list-of-ua/bot-detail?bot=WebAlta Crawler" +153[] = "WebMiner (Web Miner; http://64.124.122.252/feedback.html)" +153[] = "WebarooBot" +153[] = "WebMiner (Web Miner)" +153[] = "http://www.webaroo.com/company/site-owners" +153[] = "Webaroo Inc." +153[] = "http://www.webaroo.com/" +153[] = "bot.png" +153[] = "" +153[] = "/list-of-ua/bot-detail?bot=WebarooBot" +170[] = "RufusBot (Rufus Web Miner; http://64.124.122.252/feedback.html)" +170[] = "WebarooBot" +170[] = "RufusBot (Rufus Web Miner)" +170[] = "http://www.webaroo.com/company/site-owners" +170[] = "Webaroo Inc." +170[] = "http://www.webaroo.com/" +170[] = "bot.png" +170[] = "" +170[] = "/list-of-ua/bot-detail?bot=WebarooBot" +765[] = "WebarooBot (Webaroo Bot; http://64.124.122.252/feedback.html)" +765[] = "WebarooBot" +765[] = "WebarooBot (Webaroo Bot)" +765[] = "http://www.webaroo.com/company/site-owners" +765[] = "Webaroo Inc." +765[] = "http://www.webaroo.com/" +765[] = "bot.png" +765[] = "" +765[] = "/list-of-ua/bot-detail?bot=WebarooBot" +788[] = "WebarooBot (Webaroo Bot; http://www.webaroo.com/rooSiteOwners.html)" +788[] = "WebarooBot" +788[] = "WebarooBot (Webaroo Bot) b" +788[] = "http://www.webaroo.com/company/site-owners" +788[] = "Webaroo Inc." +788[] = "http://www.webaroo.com/" +788[] = "bot.png" +788[] = "" +788[] = "/list-of-ua/bot-detail?bot=WebarooBot" +1751[] = "WebImages 0.3 ( http://herbert.groot.jebbink.nl/?app=WebImages )" +1751[] = "WebImages" +1751[] = "WebImages 0.3" +1751[] = "" +1751[] = "Herbert Groot Jebbink" +1751[] = "http://herbert.groot.jebbink.nl/ " +1751[] = "bot.png" +1751[] = "" +1751[] = "/list-of-ua/bot-detail?bot=WebImages" +1478[] = "mozilla/5.0 (compatible; webmastercoffee/0.7; +http://webmastercoffee.com/about)" +1478[] = "webmastercoffee" +1478[] = "webmastercoffee/0.7" +1478[] = "http://webmastercoffee.com/about" +1478[] = "Martin Schwartz" +1478[] = "http://webmastercoffee.com/" +1478[] = "bot.png" +1478[] = "" +1478[] = "/list-of-ua/bot-detail?bot=webmastercoffee" +469[] = "WebRankSpider/1.37 (+http://ulm191.server4you.de/crawler/)" +469[] = "WebRankSpider" +469[] = "WebRankSpider/1.37" +469[] = "http://ulm191.server4you.de/crawler/" +469[] = "" +469[] = "" +469[] = "bot.png" +469[] = "" +469[] = "/list-of-ua/bot-detail?bot=WebRankSpider" +758[] = "Webscope/Nutch-0.9-dev (http://www.cs.washington.edu/homes/mjc/agent.html)" +758[] = "Webscope Crawler" +758[] = "Webscope Crawler" +758[] = "http://www.cs.washington.edu/homes/mjc/agent.html" +758[] = "University of Washington Computer Science & Engineering" +758[] = "http://www.cs.washington.edu/" +758[] = "bot.png" +758[] = "" +758[] = "/list-of-ua/bot-detail?bot=Webscope Crawler" +5361[] = "WebWatch/Robot_txtChecker" +5361[] = "WebWatch/Robot_txtChecker" +5361[] = "WebWatch/Robot_txtChecker" +5361[] = "http://www.ukoln.ac.uk/web-focus/webwatch/services/robots-txt/" +5361[] = "UKOLN" +5361[] = "http://www.ukoln.ac.uk/" +5361[] = "bot.png" +5361[] = "" +5361[] = "/list-of-ua/bot-detail?bot=WebWatch/Robot_txtChecker" +786[] = "wectar/Nutch-0.9 (wectar - wectar extracted from the glorious web; http://goosebumps4all.net/wectar)" +786[] = "wectar" +786[] = "wectar/Nutch-0.9" +786[] = "http://wectar.com/" +786[] = "Martin Dudek" +786[] = "" +786[] = "bot.png" +786[] = "" +786[] = "/list-of-ua/bot-detail?bot=wectar" +861[] = "wectar/Nutch-0.9 (nectar extracted form the glorious web; http://goosebumps4all.net/wectar; see website)" +861[] = "wectar" +861[] = "wectar/Nutch-0.9 b" +861[] = "http://wectar.com/" +861[] = "Martin Dudek" +861[] = "" +861[] = "bot.png" +861[] = "" +861[] = "/list-of-ua/bot-detail?bot=wectar" +5389[] = "WikioFeedBot 1.0 (http://www.wikio.com)" +5389[] = "WikioFeedBot" +5389[] = "WikioFeedBot 1.0" +5389[] = "" +5389[] = "Wikio" +5389[] = "http://www.wikio.com/" +5389[] = "bot.png" +5389[] = "" +5389[] = "/list-of-ua/bot-detail?bot=WikioFeedBot" +5710[] = "wikiwix-bot-3.0" +5710[] = "wikiwix-bot" +5710[] = "wikiwix-bot/3.0" +5710[] = "" +5710[] = "wikiwix.com" +5710[] = "http://www.wikiwix.com/" +5710[] = "bot.png" +5710[] = "" +5710[] = "/list-of-ua/bot-detail?bot=wikiwix-bot" +872[] = "Willow Internet Crawler by Twotrees V2.1" +872[] = "Willow Internet Crawler" +872[] = "Willow Internet Crawler 2.1" +872[] = "" +872[] = "Twotrees Technologies, LLC." +872[] = "http://www.twotrees.com/" +872[] = "bot.png" +872[] = "" +872[] = "/list-of-ua/bot-detail?bot=Willow Internet Crawler" +406[] = "WinkBot/0.06 (Wink.com search engine web crawler; http://www.wink.com/Wink:WinkBot; winkbot@wink.com)" +406[] = "WinkBot" +406[] = "WinkBot/0.06" +406[] = "http://www.wink.com/Wink:WinkBot" +406[] = "Wink Technologies, Inc" +406[] = "http://www.wink.com/" +406[] = "bot.png" +406[] = "" +406[] = "/list-of-ua/bot-detail?bot=WinkBot" +1805[] = "WinWebBot/1.0; (Balaena Ltd, UK); http://www.balaena.com/winwebbot.html; winwebbot@balaena.com;)" +1805[] = "WinWebBot" +1805[] = "WinWebBot/1.0" +1805[] = "http://www.balaena.com/winwebbot.html" +1805[] = "Balaena Ltd" +1805[] = "http://www.balaena.com/" +1805[] = "bot.png" +1805[] = "" +1805[] = "/list-of-ua/bot-detail?bot=WinWebBot" +238[] = "WIRE/0.10 (Linux; i686; Bot,Robot,Spider,Crawler)" +238[] = "WIRE" +238[] = "WIRE/0.10" +238[] = "http://www.cwr.cl/projects/WIRE/" +238[] = "Universidad de Chile" +238[] = "http://www.dcc.uchile.cl/" +238[] = "bot.png" +238[] = "" +238[] = "/list-of-ua/bot-detail?bot=WIRE" +415[] = "WIRE/0.11 (Linux; i686; Bot,Robot,Spider,Crawler,aromano@cli.di.unipi.it)" +415[] = "WIRE" +415[] = "WIRE/0.11" +415[] = "http://www.cwr.cl/projects/WIRE/" +415[] = "Universidad de Chile" +415[] = "http://www.dcc.uchile.cl/" +415[] = "bot.png" +415[] = "" +415[] = "/list-of-ua/bot-detail?bot=WIRE" +452[] = "WIRE/0.11 (Linux; i686; Robot,Spider,Crawler,aromano@cli.di.unipi.it)" +452[] = "WIRE" +452[] = "WIRE/0.11 b" +452[] = "http://www.cwr.cl/projects/WIRE/" +452[] = "Universidad de Chile" +452[] = "http://www.dcc.uchile.cl/" +452[] = "bot.png" +452[] = "" +452[] = "/list-of-ua/bot-detail?bot=WIRE" +5183[] = "WMCAI-robot (http://www.topicmaster.jp/wmcai/crawler.html)" +5183[] = "WMCAI_robot" +5183[] = "WMCAI_robot" +5183[] = "http://www.topicmaster.jp/wmcai/crawler.html" +5183[] = "NTT Corporation" +5183[] = "http://www.ntt.co.jp/" +5183[] = "bot.png" +5183[] = "" +5183[] = "/list-of-ua/bot-detail?bot=WMCAI_robot" +1501[] = "Mozilla/5.0 (compatible; woriobot +http://worio.com)" +1501[] = "woriobot" +1501[] = "woriobot" +1501[] = "Worio" +1501[] = "http://worio.com/" +1501[] = "" +1501[] = "bot.png" +1501[] = "" +1501[] = "/list-of-ua/bot-detail?bot=woriobot" +626[] = "www.fi crawler, contact crawler@www.fi" +626[] = "www.fi crawler" +626[] = "www.fi crawler" +626[] = "" +626[] = "Fonecta" +626[] = "http://www.fonecta.fi/" +626[] = "bot.png" +626[] = "" +626[] = "/list-of-ua/bot-detail?bot=www.fi crawler" +364[] = "wwwster/1.4 (Beta, mailto:gue@cis.uni-muenchen.de)" +364[] = "wwwster" +364[] = "wwwster/1.4 Beta" +364[] = "" +364[] = "CIS" +364[] = "http://www.cis.uni-muenchen.de/" +364[] = "bot.png" +364[] = "" +364[] = "/list-of-ua/bot-detail?bot=wwwster" +2205[] = "Mozilla/5.0 (compatible; XmarksFetch/1.0; +http://www.xmarks.com/about/crawler; info@xmarks.com)" +2205[] = "XmarksFetch" +2205[] = "XmarksFetch/1.0" +2205[] = "http://www.xmarks.com/about/crawler" +2205[] = "Xmarks, Inc." +2205[] = "http://www.xmarks.com/" +2205[] = "bot_XmarksFetch.png" +2205[] = "" +2205[] = "/list-of-ua/bot-detail?bot=XmarksFetch" +340[] = "XML Sitemaps Generator 1.0" +340[] = "XML Sitemaps Generator" +340[] = "XML Sitemaps Generator 1.0" +340[] = "http://www.xml-sitemaps.com/" +340[] = "XML-Sitemaps.com" +340[] = "http://www.xml-sitemaps.com/" +340[] = "bot.png" +340[] = "" +340[] = "/list-of-ua/bot-detail?bot=XML Sitemaps Generator" +4999[] = "Mozilla/5.0 (compatible; XML Sitemaps Generator; http://www.xml-sitemaps.com) Gecko XML-Sitemaps/1.0" +4999[] = "XML Sitemaps Generator" +4999[] = "XML Sitemaps Generator/1.0" +4999[] = "http://www.xml-sitemaps.com/" +4999[] = "xml-sitemaps.com" +4999[] = "" +4999[] = "bot.png" +4999[] = "" +4999[] = "/list-of-ua/bot-detail?bot=XML Sitemaps Generator" +4898[] = "Yaanb/1.5.001 (compatible; Win64;)" +4898[] = "Yaanb" +4898[] = "Yaanb/1.5.001" +4898[] = "http://www.yaanb.com/company/?p=bot" +4898[] = "Yaanb" +4898[] = "http://www.yaanb.com/company/" +4898[] = "bot_Yaanb.png" +4898[] = "" +4898[] = "/list-of-ua/bot-detail?bot=Yaanb" +4914[] = "Yaanb/1.5.001 (compatible; Win64;+http://www.yaanb.com/company/bot.hmtl)" +4914[] = "Yaanb" +4914[] = "Yaanb/1.5.001 b" +4914[] = "http://www.yaanb.com/company/?p=bot" +4914[] = "Yaanb" +4914[] = "" +4914[] = "bot_Yaanb.png" +4914[] = "" +4914[] = "/list-of-ua/bot-detail?bot=Yaanb" +1653[] = "yacybot (i386 Linux 2.6.28-gentoo-r5; java 1.5.0_18; Europe/en) http://yacy.net/bot.html" +1653[] = "yacybot" +1653[] = "yacybot" +1653[] = "http://yacy.net/bot.html" +1653[] = "Michael Christen" +1653[] = "" +1653[] = "bot_yacybot.png" +1653[] = "" +1653[] = "/list-of-ua/bot-detail?bot=yacybot" +1604[] = "yacybot (i386 Linux 2.6.28-11-generic; java 1.6.0_13; Europe/de) http://yacy.net/bot.html" +1604[] = "yacybot" +1604[] = "yacybot" +1604[] = "http://yacy.net/bot.html" +1604[] = "Michael Christen" +1604[] = "" +1604[] = "bot_yacybot.png" +1604[] = "" +1604[] = "/list-of-ua/bot-detail?bot=yacybot" +1645[] = "yacybot (amd64 Linux 2.6.24-23-generic; java 1.6.0_07; Europe/de) http://yacy.net/bot.html" +1645[] = "yacybot" +1645[] = "yacybot" +1645[] = "http://yacy.net/bot.html" +1645[] = "Michael Christen" +1645[] = "" +1645[] = "bot_yacybot.png" +1645[] = "" +1645[] = "/list-of-ua/bot-detail?bot=yacybot" +1712[] = "yacybot (x86 Windows Vista 6.1; java 1.6.0_13; Europe/de) http://yacy.net/bot.html" +1712[] = "yacybot" +1712[] = "yacybot" +1712[] = "http://yacy.net/bot.html" +1712[] = "Michael Christen" +1712[] = "" +1712[] = "bot_yacybot.png" +1712[] = "" +1712[] = "/list-of-ua/bot-detail?bot=yacybot" +1776[] = "yacybot (i386 Linux 2.6.28-13-generic; java 1.6.0_13; Europe/en) http://yacy.net/bot.html" +1776[] = "yacybot" +1776[] = "yacybot" +1776[] = "http://yacy.net/bot.html" +1776[] = "Michael Christen" +1776[] = "" +1776[] = "bot_yacybot.png" +1776[] = "" +1776[] = "/list-of-ua/bot-detail?bot=yacybot" +1894[] = "yacybot (amd64 Windows 7 6.1; java 1.6.0_14; Europe/de) http://yacy.net/bot.html" +1894[] = "yacybot" +1894[] = "yacybot" +1894[] = "http://yacy.net/bot.html" +1894[] = "Michael Christen" +1894[] = "" +1894[] = "bot_yacybot.png" +1894[] = "" +1894[] = "/list-of-ua/bot-detail?bot=yacybot" +1957[] = "yacybot (i386 Linux 2.6.23; java 1.6.0_06; Europe/en) http://yacy.net/bot.html" +1957[] = "yacybot" +1957[] = "yacybot" +1957[] = "http://yacy.net/bot.html" +1957[] = "Michael Christen" +1957[] = "" +1957[] = "bot_yacybot.png" +1957[] = "" +1957[] = "/list-of-ua/bot-detail?bot=yacybot" +2017[] = "yacybot (amd64 Linux 2.6.18-164.el5; java 1.6.0; Europe/de) http://yacy.net/bot.html" +2017[] = "yacybot" +2017[] = "yacybot" +2017[] = "http://yacy.net/bot.html" +2017[] = "Michael Christen" +2017[] = "" +2017[] = "bot_yacybot.png" +2017[] = "" +2017[] = "/list-of-ua/bot-detail?bot=yacybot" +2071[] = "yacybot (i386 Linux 2.6.24-23-generic; java 1.6.0_16; Europe/en) http://yacy.net/bot.html" +2071[] = "yacybot" +2071[] = "yacybot" +2071[] = "http://yacy.net/bot.html" +2071[] = "Michael Christen" +2071[] = "" +2071[] = "bot_yacybot.png" +2071[] = "" +2071[] = "/list-of-ua/bot-detail?bot=yacybot" +2088[] = "yacybot (i386 Linux 2.6.23; java 1.6.0_17; Europe/en) http://yacy.net/bot.html" +2088[] = "yacybot" +2088[] = "yacybot" +2088[] = "http://yacy.net/bot.html" +2088[] = "Michael Christen" +2088[] = "" +2088[] = "bot_yacybot.png" +2088[] = "" +2088[] = "/list-of-ua/bot-detail?bot=yacybot" +2091[] = "yacybot (amd64 Linux 2.6.26-2-openvz-amd64; java 1.6.0_12; UTC/en) http://yacy.net/bot.html" +2091[] = "yacybot" +2091[] = "yacybot" +2091[] = "http://yacy.net/bot.html" +2091[] = "Michael Christen" +2091[] = "" +2091[] = "bot_yacybot.png" +2091[] = "" +2091[] = "/list-of-ua/bot-detail?bot=yacybot" +2279[] = "yacybot (amd64 Linux 2.6.32-gentoo; java 1.6.0_17; Europe/en) http://yacy.net/bot.html" +2279[] = "yacybot" +2279[] = "yacybot" +2279[] = "http://yacy.net/bot.html" +2279[] = "Michael Christen" +2279[] = "" +2279[] = "bot_yacybot.png" +2279[] = "" +2279[] = "/list-of-ua/bot-detail?bot=yacybot" +2300[] = "yacybot (x86 Windows 2003 5.2; java 1.6.0_16; Europe/de) http://yacy.net/bot.html" +2300[] = "yacybot" +2300[] = "yacybot" +2300[] = "http://yacy.net/bot.html" +2300[] = "Michael Christen" +2300[] = "" +2300[] = "bot_yacybot.png" +2300[] = "" +2300[] = "/list-of-ua/bot-detail?bot=yacybot" +3034[] = "yacybot (i386 Linux 2.6.26-2-686; java 1.6.0_0; Europe/de) http://yacy.net/bot.html" +3034[] = "yacybot" +3034[] = "yacybot" +3034[] = "http://yacy.net/bot.html" +3034[] = "Michael Christen" +3034[] = "" +3034[] = "bot_yacybot.png" +3034[] = "" +3034[] = "/list-of-ua/bot-detail?bot=yacybot" +3238[] = "yacybot (i386 Linux 2.6.30-2-686; java 1.6.0_0; SystemV/en) http://yacy.net/bot.html" +3238[] = "yacybot" +3238[] = "yacybot" +3238[] = "http://yacy.net/bot.html" +3238[] = "Michael Christen" +3238[] = "" +3238[] = "bot_yacybot.png" +3238[] = "" +3238[] = "/list-of-ua/bot-detail?bot=yacybot" +3221[] = "yacybot (i386 Linux 2.6.31-18-generic; java 1.6.0_0; Europe/en) http://yacy.net/bot.html" +3221[] = "yacybot" +3221[] = "yacybot" +3221[] = "http://yacy.net/bot.html" +3221[] = "Michael Christen" +3221[] = "" +3221[] = "bot_yacybot.png" +3221[] = "" +3221[] = "/list-of-ua/bot-detail?bot=yacybot" +4830[] = "yacybot (i386 Linux 2.6.31-21-generic; java 1.6.0_0; Europe/en) http://yacy.net/bot.html" +4830[] = "yacybot" +4830[] = "yacybot" +4830[] = "http://yacy.net/bot.html" +4830[] = "Michael Christen" +4830[] = "" +4830[] = "bot_yacybot.png" +4830[] = "" +4830[] = "/list-of-ua/bot-detail?bot=yacybot" +4423[] = "yacybot (amd64 Linux 2.6.28-18-generic; java 1.6.0_16; GMT/en) http://yacy.net/bot.html" +4423[] = "yacybot" +4423[] = "yacybot" +4423[] = "http://yacy.net/bot.html" +4423[] = "Michael Christen" +4423[] = "" +4423[] = "bot_yacybot.png" +4423[] = "" +4423[] = "/list-of-ua/bot-detail?bot=yacybot" +4747[] = "yacybot (x86 Windows XP 5.1; java 1.6.0_18; Europe/de) http://yacy.net/bot.html" +4747[] = "yacybot" +4747[] = "yacybot" +4747[] = "http://yacy.net/bot.html" +4747[] = "Michael Christen" +4747[] = "" +4747[] = "bot_yacybot.png" +4747[] = "" +4747[] = "/list-of-ua/bot-detail?bot=yacybot" +4974[] = "yacybot (amd64 Linux 2.6.26-2-amd64; java 1.6.0_0; Europe/en) http://yacy.net/bot.html" +4974[] = "yacybot" +4974[] = "yacybot" +4974[] = "http://yacy.net/bot.html" +4974[] = "Michael Christen" +4974[] = "" +4974[] = "bot_yacybot.png" +4974[] = "" +4974[] = "/list-of-ua/bot-detail?bot=yacybot" +4975[] = "yacybot (i386 Linux 2.6.32-22-generic; java 1.6.0_20; Europe/de) http://yacy.net/bot.html" +4975[] = "yacybot" +4975[] = "yacybot" +4975[] = "http://yacy.net/bot.html" +4975[] = "Michael Christen" +4975[] = "" +4975[] = "bot_yacybot.png" +4975[] = "" +4975[] = "/list-of-ua/bot-detail?bot=yacybot" +5216[] = "yacybot (x86 Windows 2003 5.2; java 1.6.0_20; America/de) http://yacy.net/bot.html" +5216[] = "yacybot" +5216[] = "yacybot" +5216[] = "http://yacy.net/bot.html" +5216[] = "Michael Christen" +5216[] = "" +5216[] = "bot_yacybot.png" +5216[] = "" +5216[] = "/list-of-ua/bot-detail?bot=yacybot" +5176[] = "yacybot (amd64 Linux 2.6.26-2-amd64; java 1.6.0_20; Europe/en) http://yacy.net/bot.html" +5176[] = "yacybot" +5176[] = "yacybot" +5176[] = "http://yacy.net/bot.html" +5176[] = "Michael Christen" +5176[] = "" +5176[] = "bot_yacybot.png" +5176[] = "" +5176[] = "/list-of-ua/bot-detail?bot=yacybot" +4[] = "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)" +4[] = "Yahoo!" +4[] = "Yahoo! Slurp" +4[] = "http://help.yahoo.com/help/us/ysearch/slurp" +4[] = "Yahoo! Inc." +4[] = "http://www.yahoo.com/" +4[] = "bot_yahoo!slurp.png" +4[] = "" +4[] = "/list-of-ua/bot-detail?bot=Yahoo!" +193[] = "Mozilla/5.0 (compatible; Yahoo! Slurp China; http://misc.yahoo.com.cn/help.html)" +193[] = "Yahoo!" +193[] = "Yahoo! Slurp China" +193[] = "http://misc.yahoo.com.cn/help.html" +193[] = "Yahoo! Inc." +193[] = "http://www.yahoo.com/" +193[] = "bot_yahoo!slurp.png" +193[] = "" +193[] = "/list-of-ua/bot-detail?bot=Yahoo!" +1564[] = "Mozilla/5.0 (compatible; Yahoo! Slurp/3.0; http://help.yahoo.com/help/us/ysearch/slurp)" +1564[] = "Yahoo!" +1564[] = "Yahoo! Slurp/3.0" +1564[] = "http://help.yahoo.com/help/us/ysearch/slurp" +1564[] = "Yahoo! Inc." +1564[] = "http://www.yahoo.com/" +1564[] = "bot_yahoo!slurp.png" +1564[] = "" +1564[] = "/list-of-ua/bot-detail?bot=Yahoo!" +1793[] = "Mozilla/5.0 (Yahoo-MMCrawler/4.0; mailto:vertical-crawl-support@yahoo-inc.com)" +1793[] = "Yahoo!" +1793[] = "Yahoo-MMCrawler/4.0" +1793[] = "http://help.yahoo.com/" +1793[] = "Yahoo! Inc" +1793[] = "http://www.yahoo.com/" +1793[] = "bot_yahoo!slurp.png" +1793[] = "" +1793[] = "/list-of-ua/bot-detail?bot=Yahoo!" +1548[] = "Y!J-BRI/0.0.1 crawler ( http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html )" +1548[] = "Yahoo! JAPAN" +1548[] = "Y!J-BRI/0.0.1" +1548[] = "http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html" +1548[] = "Yahoo! Inc" +1548[] = "http://www.yahoo.com/" +1548[] = "bot_yahoo!slurp.png" +1548[] = "" +1548[] = "/list-of-ua/bot-detail?bot=Yahoo! JAPAN" +1558[] = "Y!J-BSC/1.0 (http://help.yahoo.co.jp/help/jp/blog-search/)" +1558[] = "Yahoo! JAPAN" +1558[] = "Y!J-BSC/1.0" +1558[] = "http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html" +1558[] = "Yahoo! Inc" +1558[] = "http://www.yahoo.com/" +1558[] = "bot_yahoo!slurp.png" +1558[] = "" +1558[] = "/list-of-ua/bot-detail?bot=Yahoo! JAPAN" +5982[] = "Y!J-BRO/YFSJ crawler (compatible; Mozilla 4.0; MSIE 5.5; http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html; YahooFeedSeekerJp/2.0)" +5982[] = "Yahoo! JAPAN" +5982[] = "Y!J-BRO/YFSJ" +5982[] = "http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html" +5982[] = "Yahoo! Inc" +5982[] = "http://www.yahoo.com/" +5982[] = "bot_yahoo!slurp.png" +5982[] = "" +5982[] = "/list-of-ua/bot-detail?bot=Yahoo! JAPAN" +605[] = "Yandex/1.01.001 (compatible; Win16; I)" +605[] = "YandexBot" +605[] = "Yandex/1.01.001" +605[] = "http://yandex.com/bots" +605[] = "Yandex LLC" +605[] = "http://company.yandex.com/" +605[] = "bot_Yandex.png" +605[] = "" +605[] = "/list-of-ua/bot-detail?bot=YandexBot" +1458[] = "Yandex/1.01.001 (compatible; Win16; P)" +1458[] = "YandexBot" +1458[] = "Yandex/1.01.001" +1458[] = "http://yandex.com/bots" +1458[] = "Yandex LLC" +1458[] = "http://company.yandex.com/" +1458[] = "bot_Yandex.png" +1458[] = "" +1458[] = "/list-of-ua/bot-detail?bot=YandexBot" +1690[] = "YandexSomething/1.0" +1690[] = "YandexBot" +1690[] = "YandexSomething/1.0" +1690[] = "http://yandex.com/bots" +1690[] = "Yandex LLC" +1690[] = "http://company.yandex.com/" +1690[] = "bot_Yandex.png" +1690[] = "" +1690[] = "/list-of-ua/bot-detail?bot=YandexBot" +1869[] = "Yandex/1.01.001 (compatible; Win16; H)" +1869[] = "YandexBot" +1869[] = "Yandex/1.01.001" +1869[] = "http://yandex.com/bots" +1869[] = "Yandex LLC" +1869[] = "http://company.yandex.com/" +1869[] = "bot_Yandex.png" +1869[] = "" +1869[] = "/list-of-ua/bot-detail?bot=YandexBot" +1943[] = "Yandex/1.01.001 (compatible; Win16; m)" +1943[] = "YandexBot" +1943[] = "Yandex/1.01.001" +1943[] = "http://yandex.com/bots" +1943[] = "Yandex LLC" +1943[] = "http://company.yandex.com/" +1943[] = "bot_Yandex.png" +1943[] = "" +1943[] = "/list-of-ua/bot-detail?bot=YandexBot" +5010[] = "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)" +5010[] = "YandexBot" +5010[] = "YandexBot/3.0" +5010[] = "http://yandex.com/bots" +5010[] = "Yandex LLC" +5010[] = "http://company.yandex.com/" +5010[] = "bot_Yandex.png" +5010[] = "" +5010[] = "/list-of-ua/bot-detail?bot=YandexBot" +5014[] = "Mozilla/5.0 (compatible; YandexImages/3.0; +http://yandex.com/bots)" +5014[] = "YandexBot" +5014[] = "YandexImages/3.0" +5014[] = "http://yandex.com/bots" +5014[] = "Yandex LLC" +5014[] = "http://company.yandex.com/" +5014[] = "bot_Yandex.png" +5014[] = "" +5014[] = "/list-of-ua/bot-detail?bot=YandexBot" +5016[] = "Mozilla/5.0 (compatible; YandexBot/3.0; MirrorDetector; +http://yandex.com/bots)" +5016[] = "YandexBot" +5016[] = "YandexBot/3.0-MirrorDetector" +5016[] = "http://yandex.com/bots" +5016[] = "Yandex LLC" +5016[] = "http://company.yandex.com/" +5016[] = "bot_Yandex.png" +5016[] = "" +5016[] = "/list-of-ua/bot-detail?bot=YandexBot" +5090[] = "Mozilla/5.0 (compatible; YandexWebmaster/2.0; +http://yandex.com/bots)" +5090[] = "YandexBot" +5090[] = "YandexWebmaster/2.0" +5090[] = "http://yandex.com/bots" +5090[] = "Yandex LLC" +5090[] = "http://company.yandex.com/" +5090[] = "bot_Yandex.png" +5090[] = "" +5090[] = "/list-of-ua/bot-detail?bot=YandexBot" +1512[] = "Yanga WorldSearch Bot v1.1/beta (http://www.yanga.co.uk/)" +1512[] = "Yanga" +1512[] = "Yanga v1.1/beta" +1512[] = "http://yandex.com/bots" +1512[] = "Gigabase Ltd." +1512[] = "http://www.gigabase.com/" +1512[] = "bot.png" +1512[] = "" +1512[] = "/list-of-ua/bot-detail?bot=Yanga" +653[] = "YodaoBot/1.0 (http://www.yodao.com/help/webmaster/spider/; )" +653[] = "YodaoBot" +653[] = "YodaoBot/1.0" +653[] = "http://www.yodao.com/help/webmaster/spider/" +653[] = "Yodao" +653[] = "http://www.yodao.com/" +653[] = "bot.png" +653[] = "" +653[] = "/list-of-ua/bot-detail?bot=YodaoBot" +728[] = "Mozilla/5.0 (compatible; YodaoBot/1.0; http://www.yodao.com/help/webmaster/spider/; )" +728[] = "YodaoBot" +728[] = "YodaoBot/1.0" +728[] = "http://www.yodao.com/help/webmaster/spider/" +728[] = "yodao.com" +728[] = "http://www.yodao.com/" +728[] = "bot.png" +728[] = "" +728[] = "/list-of-ua/bot-detail?bot=YodaoBot" +1818[] = "Mozilla/5.0 (compatible;YodaoBot-Image/1.0;http://www.youdao.com/help/webmaster/spider/;)" +1818[] = "YodaoBot" +1818[] = "YodaoBot-Image/1.0" +1818[] = "http://www.youdao.com/help/webmaster/spider/" +1818[] = "youdao" +1818[] = "http://www.youdao.com/" +1818[] = "bot.png" +1818[] = "" +1818[] = "/list-of-ua/bot-detail?bot=YodaoBot" +891[] = "Mozilla/5.0 (compatible; Yoono; http://www.yoono.com/)" +891[] = "Yoono Bot" +891[] = "Yoono Bot" +891[] = "http://blog.yoono.com/blog/?page_id=40" +891[] = "Yoono Team" +891[] = "http://www.yoono.com/" +891[] = "bot.png" +891[] = "" +891[] = "/list-of-ua/bot-detail?bot=Yoono Bot" +1507[] = "Mozilla/5.0 (compatible; YoudaoBot/1.0; http://www.youdao.com/help/webmaster/spider/; )" +1507[] = "YoudaoBot" +1507[] = "YoudaoBot/1.0" +1507[] = "http://www.youdao.com/help/webmaster/spider/" +1507[] = "youdao.com" +1507[] = "http://www.youdao.com/" +1507[] = "bot.png" +1507[] = "" +1507[] = "/list-of-ua/bot-detail?bot=YoudaoBot" +1509[] = "YowedoBot/Yowedo 1.0 (Search Engine crawler for yowedo.com; http://yowedo.com/en/partners.html; crawler@yowedo.com)" +1509[] = "YowedoBot" +1509[] = "YowedoBot/1.0" +1509[] = "http://yowedo.com/en/partners.html" +1509[] = "yowedo.com" +1509[] = "http://yowedo.com/" +1509[] = "bot.png" +1509[] = "" +1509[] = "/list-of-ua/bot-detail?bot=YowedoBot" +5718[] = "yrspider (Mozilla/5.0 (compatible; YRSpider; +http://www.yunrang.com/yrspider.html))" +5718[] = "YRSpider" +5718[] = "YRSpider" +5718[] = "http://www.yunrang.com/yrspider.html" +5718[] = "yunrang" +5718[] = "http://www.yunrang.com/" +5718[] = "bot.png" +5718[] = "" +5718[] = "/list-of-ua/bot-detail?bot=YRSpider" +43[] = "ZACATEK_CZ_BOT (www.zacatek.cz)" +43[] = "ZACATEK_CZ" +43[] = "ZACATEK_CZ_BOT" +43[] = "http://www.zacatek.cz/" +43[] = "webprovider - Adam Haken" +43[] = "http://www.webprovider.cz/" +43[] = "bot.png" +43[] = "" +43[] = "/list-of-ua/bot-detail?bot=ZACATEK_CZ" +581[] = "Zeusbot/0.07 (Ulysseek's web-crawling robot; http://www.zeusbot.com; agent@zeusbot.com)" +581[] = "Zeusbot" +581[] = "Zeusbot/0.07" +581[] = "http://www.zeusbot.com/" +581[] = "Ulysseek" +581[] = "http://www.ulysseek.com/" +581[] = "bot.png" +581[] = "" +581[] = "/list-of-ua/bot-detail?bot=Zeusbot" +5655[] = "Zookabot/2.1;++http://zookabot.com" +5655[] = "ZookaBot" +5655[] = "ZookaBot/2.1" +5655[] = "http://zookabot.com/" +5655[] = "Hwacha ApS" +5655[] = "http://hwacha.dk/" +5655[] = "bot_Zookabot.png" +5655[] = "" +5655[] = "/list-of-ua/bot-detail?bot=ZookaBot" +5007[] = "Zookabot/2.0;++http://zookabot.com" +5007[] = "Zookabot" +5007[] = "Zookabot/2.0" +5007[] = "http://zookabot.com/" +5007[] = "Hwacha ApS" +5007[] = "http://hwacha.dk/" +5007[] = "bot_Zookabot.png" +5007[] = "" +5007[] = "/list-of-ua/bot-detail?bot=Zookabot" +6001[] = "Zookabot/2.2;++http://zookabot.com" +6001[] = "Zookabot" +6001[] = "Zookabot/2.2" +6001[] = "http://zookabot.com/" +6001[] = "Hwacha ApS" +6001[] = "http://hwacha.dk/" +6001[] = "bot_Zookabot.png" +6001[] = "" +6001[] = "/list-of-ua/bot-detail?bot=Zookabot" +913[] = "ZoomSpider - wrensoft.com [ZSEBOT]" +913[] = "ZoomSpider (ZSEBOT)" +913[] = "ZoomSpider (ZSEBOT)" +913[] = "http://wrensoft.com/zoom/support/useragent.html" +913[] = "PassMark Software Pty Ltd." +913[] = "http://www.passmark.com/" +913[] = "bot.png" +913[] = "" +913[] = "/list-of-ua/bot-detail?bot=ZoomSpider (ZSEBOT)" +140[] = "Mozilla/4.0 compatible ZyBorg/1.0 Dead Link Checker (wn.dlc@looksmart.net; http://www.WISEnutbot.com)" +140[] = "ZyBorg" +140[] = "ZyBorg/1.0 Dead Link Checker" +140[] = "http://www.wisenutbot.com/" +140[] = "LookSmart, Ltd." +140[] = "http://aboutus.looksmart.com/" +140[] = "bot.png" +140[] = "" +140[] = "/list-of-ua/bot-detail?bot=ZyBorg" +159[] = "Mozilla/4.0 compatible ZyBorg/1.0 (wn-14.zyborg@looksmart.net; http://www.WISEnutbot.com)" +159[] = "ZyBorg" +159[] = "ZyBorg/1.0" +159[] = "http://www.wisenutbot.com/" +159[] = "LookSmart, Ltd." +159[] = "http://aboutus.looksmart.com/" +159[] = "bot.png" +159[] = "" +159[] = "/list-of-ua/bot-detail?bot=ZyBorg" +401[] = "Mozilla/4.0 compatible ZyBorg/1.0 (wn-16.zyborg@looksmart.net; http://www.WISEnutbot.com)" +401[] = "ZyBorg" +401[] = "ZyBorg/1.0 - b" +401[] = "http://www.wisenutbot.com/" +401[] = "LookSmart, Ltd." +401[] = "http://aboutus.looksmart.com/" +401[] = "bot.png" +401[] = "" +401[] = "/list-of-ua/bot-detail?bot=ZyBorg" +3441[] = "^Nail (http://CaretNail.com)" +3441[] = "^Nail" +3441[] = "^Nail" +3441[] = "http://caret.us.com/caretnail/index.html" +3441[] = "HydraByte, Inc." +3441[] = "http://www.hydrabyte.com/" +3441[] = "bot_Nail.png" +3441[] = "" +3441[] = "/list-of-ua/bot-detail?bot=^Nail" +[os] +; os_id[] = "OS Family" +; os_id[] = "OS Name" +; os_id[] = "OS URL" +; os_id[] = "OS Company" +; os_id[] = "OS Company URL" +; os_id[] = "OS ico" +1[] = "Windows" +1[] = "Windows XP" +1[] = "http://www.microsoft.com/windowsxp/default.mspx" +1[] = "Microsoft Corporation." +1[] = "http://www.microsoft.com/" +1[] = "windowsxp.png" +2[] = "Windows" +2[] = "Windows 2000" +2[] = "http://www.microsoft.com/windows2000/default.mspx" +2[] = "Microsoft Corporation." +2[] = "http://www.microsoft.com/" +2[] = "windows.png" +3[] = "Windows" +3[] = "Windows 2003 Server" +3[] = "http://www.microsoft.com/windowsserver2003/default.mspx" +3[] = "Microsoft Corporation." +3[] = "http://www.microsoft.com/" +3[] = "windowsxp.png" +4[] = "Windows" +4[] = "Windows 95" +4[] = "http://www.microsoft.com/windows95/" +4[] = "Microsoft Corporation." +4[] = "http://www.microsoft.com/" +4[] = "windows.png" +5[] = "Windows" +5[] = "Windows 98" +5[] = "http://www.microsoft.com/windows98/" +5[] = "Microsoft Corporation." +5[] = "http://www.microsoft.com/" +5[] = "windows.png" +6[] = "Windows" +6[] = "Windows 3.x" +6[] = "http://www.microsoft.com/windows/" +6[] = "Microsoft Corporation." +6[] = "http://www.microsoft.com/" +6[] = "windows.png" +7[] = "Windows" +7[] = "Windows CE" +7[] = "http://www.microsoft.com/windows/embedded/default.mspx" +7[] = "Microsoft Corporation." +7[] = "http://www.microsoft.com/" +7[] = "windowsce.png" +8[] = "Windows" +8[] = "Windows ME" +8[] = "http://www.microsoft.com/WindowsMe/" +8[] = "Microsoft Corporation." +8[] = "http://www.microsoft.com/" +8[] = "windows.png" +9[] = "Windows" +9[] = "Windows Vista" +9[] = "http://www.microsoft.com/windowsvista/" +9[] = "Microsoft Corporation." +9[] = "http://www.microsoft.com/" +9[] = "windowsvista.png" +10[] = "JVM" +10[] = "JVM (Platform Micro Edition)" +10[] = "http://java.sun.com/" +10[] = "Sun Microsystems, Inc." +10[] = "http://www.sun.com/" +10[] = "java.png" +11[] = "Linux" +11[] = "Linux (CentOS)" +11[] = "http://www.centos.org/" +11[] = "" +11[] = "http://www.centos.org/" +11[] = "linux_centos.png" +12[] = "Linux" +12[] = "Linux (Ubuntu)" +12[] = "http://www.ubuntulinux.org/" +12[] = "Canonical Ltd." +12[] = "http://www.canonical.com/" +12[] = "linux_ubuntu.png" +13[] = "Linux" +13[] = "Linux (Debian)" +13[] = "http://www.debian.org/" +13[] = "Software in the Public Interest, Inc." +13[] = "http://www.spi-inc.org/" +13[] = "linux_debian.png" +14[] = "Linux" +14[] = "Linux (Fedora)" +14[] = "http://fedora.redhat.com/" +14[] = "Red Hat, Inc." +14[] = "http://www.redhat.com/" +14[] = "linux_fedora.png" +15[] = "Linux" +15[] = "Linux (Gentoo)" +15[] = "http://www.gentoo.org/" +15[] = "Gentoo Foundation, Inc." +15[] = "http://www.gentoo.org/foundation/en/" +15[] = "linux_gentoo.png" +16[] = "Linux" +16[] = "Linux (Linspire)" +16[] = "http://en.wikipedia.org/wiki/Linspire" +16[] = "Linspire, Inc." +16[] = "http://www.linspire.com/" +16[] = "linux_linspire.png" +17[] = "Linux" +17[] = "Linux (Mandriva)" +17[] = "http://www.mandriva.com/" +17[] = "" +17[] = "" +17[] = "linux_mandriva.png" +18[] = "Linux" +18[] = "Linux (RedHat)" +18[] = "http://www.redhat.com/rhel/" +18[] = "Red Hat, Inc." +18[] = "http://www.redhat.com/" +18[] = "linux_redhat.png" +19[] = "Linux" +19[] = "Linux" +19[] = "http://en.wikipedia.org/wiki/Linux" +19[] = "" +19[] = "" +19[] = "linux.png" +20[] = "Linux" +20[] = "Linux (Slackware)" +20[] = "http://www.slackware.com/" +20[] = "Slackware Linux, Inc." +20[] = "" +20[] = "linux_slackware.png" +21[] = "Linux" +21[] = "Linux (Kanotix)" +21[] = "http://kanotix.com/" +21[] = "" +21[] = "" +21[] = "linux_kanotix.png" +22[] = "Linux" +22[] = "Linux (SUSE)" +22[] = "http://www.novell.com/linux/" +22[] = "Novell, Inc." +22[] = "http://www.novell.com/" +22[] = "linux_suse.png" +23[] = "Linux" +23[] = "Linux (Knoppix)" +23[] = "http://www.knoppix.net/" +23[] = "Klaus Knopper" +23[] = "http://www.knopper.net/knopper/" +23[] = "linux_knoppix.png" +24[] = "BSD" +24[] = "NetBSD" +24[] = "http://www.netbsd.org/" +24[] = "NetBSD Foundation, Inc." +24[] = "" +24[] = "netbsd.png" +25[] = "BSD" +25[] = "FreeBSD" +25[] = "http://www.freebsd.org/" +25[] = "FreeBSD Foundation" +25[] = "http://www.freebsdfoundation.org/" +25[] = "freebsd.png" +26[] = "BSD" +26[] = "OpenBSD" +26[] = "http://www.openbsd.org/" +26[] = "" +26[] = "" +26[] = "openbsd.png" +29[] = "Solaris" +29[] = "Solaris" +29[] = "http://www.sun.com/software/solaris/" +29[] = "Sun Microsystems, Inc. (now Oracle Corporation)" +29[] = "http://www.oracle.com/" +29[] = "solaris.png" +30[] = "Amiga OS" +30[] = "Amiga OS" +30[] = "http://www.amiga.com/amigaos/" +30[] = "Amiga, Inc." +30[] = "http://www.amiga.com/" +30[] = "amiga.png" +31[] = "IRIX" +31[] = "IRIX" +31[] = "http://www.sgi.com/products/software/irix/" +31[] = "Silicon Graphics, Inc." +31[] = "http://www.sgi.com/" +31[] = "irix.png" +32[] = "OpenVMS" +32[] = "OpenVMS" +32[] = "http://h71000.www7.hp.com/" +32[] = "Hewlett-Packard Development Company, L.P." +32[] = "http://www.hp.com/" +32[] = "openvms.png" +33[] = "BeOS" +33[] = "BeOS" +33[] = "" +33[] = "Be, Inc." +33[] = "http://www.beincorporated.com/" +33[] = "beos.png" +34[] = "Symbian OS" +34[] = "Symbian OS" +34[] = "http://www.symbian.org/" +34[] = "Symbian Foundation" +34[] = "http://www.symbian.org/" +34[] = "symbian.png" +35[] = "Palm OS" +35[] = "Palm OS" +35[] = "http://en.wikipedia.org/wiki/Palm_OS" +35[] = "Palm, Inc." +35[] = "http://www.palm.com/" +35[] = "palmos.png" +37[] = "Windows" +37[] = "MSN TV (WebTV)" +37[] = "http://www.msntv.com/" +37[] = "Microsoft Corporation." +37[] = "http://www.microsoft.com/" +37[] = "webtv.png" +39[] = "OS/2" +39[] = "OS/2 Warp" +39[] = "http://www-306.ibm.com/software/os/warp/" +39[] = "IBM Corporation" +39[] = "http://www.ibm.com/" +39[] = "os2warp.png" +40[] = "RISK OS" +40[] = "RISK OS" +40[] = "" +40[] = "RISCOS Ltd" +40[] = "http://www.riscos.com/" +40[] = "riskos.png" +41[] = "HP-UX" +41[] = "HP-UX" +41[] = "http://www.hp.com/products1/unix/" +41[] = "Hewlett-Packard Development Company, L.P." +41[] = "http://www.hp.com/" +41[] = "hpux.png" +42[] = "Nintendo" +42[] = "Nintendo Wii" +42[] = "http://wii.nintendo.com/" +42[] = "Nintendo of America Inc." +42[] = "http://www.nintendo.com/" +42[] = "wii.png" +43[] = "Windows" +43[] = "Windows" +43[] = "http://www.microsoft.com/windows/" +43[] = "Microsoft Corporation." +43[] = "http://www.microsoft.com/" +43[] = "windows.png" +44[] = "Mac OS" +44[] = "Mac OS" +44[] = "http://en.wikipedia.org/wiki/Mac_OS" +44[] = "Apple Computer, Inc." +44[] = "http://www.apple.com/" +44[] = "macos.png" +45[] = "AIX" +45[] = "AIX" +45[] = "http://www.ibm.com/aix/" +45[] = "IBM Corporation" +45[] = "http://www.ibm.com/" +45[] = "aix.png" +46[] = "Windows" +46[] = "Windows NT" +46[] = "http://www.microsoft.com/windows/" +46[] = "Microsoft Corporation." +46[] = "http://www.microsoft.com/" +46[] = "windows.png" +47[] = "JVM" +47[] = "JVM (Java)" +47[] = "http://java.sun.com/" +47[] = "Sun Microsystems, Inc." +47[] = "http://www.sun.com/" +47[] = "java.png" +49[] = "Plan 9" +49[] = "Plan 9" +49[] = "http://plan9.bell-labs.com/plan9/" +49[] = "Lucent Technologies" +49[] = "http://www.lucent.com/" +49[] = "plan9.png" +50[] = "RIM OS" +50[] = "RIM OS" +50[] = "http://www.blackberry.com/" +50[] = "Research In Motion Limited" +50[] = "http://www.rim.com/" +50[] = "mobile.png" +52[] = "QNX" +52[] = "QNX x86pc" +52[] = "http://www.qnx.com/" +52[] = "QNX Software Systems" +52[] = "http://www.qnx.com/" +52[] = "qnx.png" +53[] = "MorphOS" +53[] = "MorphOS" +53[] = "http://www.morphos.org/" +53[] = "MorphOS development team" +53[] = "" +53[] = "morphos.png" +55[] = "Linux" +55[] = "Linux (VectorLinux)" +55[] = "http://vectorlinux.com/" +55[] = "Robert S. Lange" +55[] = "" +55[] = "linux_vector.png" +56[] = "Linux" +56[] = "Linux (Mint)" +56[] = "http://linuxmint.com/" +56[] = "clem" +56[] = "" +56[] = "linuxmint.png" +57[] = "SCO" +57[] = "SCO OpenServer" +57[] = "http://www.sco.com/products/openserver/" +57[] = "The SCO Group" +57[] = "http://www.sco.com/" +57[] = "sco.png" +58[] = "Linux" +58[] = "Linux (Arch Linux)" +58[] = "http://archlinux.org/" +58[] = "Judd Vinet" +58[] = "http://www.zeroflux.org/" +58[] = "linux_archlinux.png" +59[] = "SkyOS" +59[] = "SkyOS" +59[] = "http://www.skyos.org/" +59[] = "SkyOS Team" +59[] = "http://www.skyos.org/" +59[] = "skyos.png" +61[] = "BSD" +61[] = "DragonFly BSD" +61[] = "http://www.dragonflybsd.org/" +61[] = "DragonFly BSD Team" +61[] = "http://www.dragonflybsd.org/team/" +61[] = "dragonflybsd.png" +62[] = "Linux" +62[] = "Android" +62[] = "http://www.openhandsetalliance.com/android_overview.html" +62[] = "Open Handset Alliance" +62[] = "http://www.openhandsetalliance.com/" +62[] = "android.png" +64[] = "Windows" +64[] = "Windows 7" +64[] = "http://www.microsoft.com/windows/windows-7/" +64[] = "Microsoft Corporation." +64[] = "http://www.microsoft.com/" +64[] = "windows-7.png" +65[] = "iPhone OS" +65[] = "iPhone OS" +65[] = "http://developer.apple.com/iphone/" +65[] = "Apple Inc." +65[] = "http://www.apple.com/" +65[] = "iphone.png" +69[] = "Palm OS" +69[] = "webOS" +69[] = "http://developer.palm.com/" +69[] = "Palm, Inc." +69[] = "http://www.palm.com/" +69[] = "palmos.png" +70[] = "Haiku OS" +70[] = "Haiku OS" +70[] = "http://www.haiku-os.org/" +70[] = "Haiku Inc." +70[] = "http://www.haiku-os.org/about/haiku_inc" +70[] = "haiku.png" +72[] = "DangerOS" +72[] = "Danger Hiptop" +72[] = "http://developer.danger.com/" +72[] = "Danger, Inc." +72[] = "http://www.danger.com/" +72[] = "dangeros.png" +74[] = "Syllable" +74[] = "Syllable" +74[] = "http://syllable.org/" +74[] = "Kristian Van Der Vliet, Kaj de Vos, Rick Caudill, Arno Klenke, Henrik Isaksson" +74[] = "" +74[] = "syllable.png" +75[] = "Linux" +75[] = "Linux (Maemo)" +75[] = "http://maemo.org/" +75[] = "Nokia" +75[] = "http://www.nokia.com/" +75[] = "maemo.png" +83[] = "Mac OS X" +83[] = "Mac OS X 10.4 Tiger" +83[] = "http://www.apple.com/macosx/" +83[] = "Apple Computer, Inc." +83[] = "http://www.apple.com/" +83[] = "macosx.png" +84[] = "Mac OS X" +84[] = "Mac OS X 10.5 Leopard" +84[] = "http://www.apple.com/macosx/" +84[] = "Apple Computer, Inc." +84[] = "http://www.apple.com/" +84[] = "macosx.png" +85[] = "Mac OS X" +85[] = "Mac OS X 10.6 Snow Leopard" +85[] = "http://www.apple.com/macosx/" +85[] = "Apple Computer, Inc." +85[] = "http://www.apple.com/" +85[] = "macosx.png" +86[] = "Mac OS X" +86[] = "Mac OS X" +86[] = "http://www.apple.com/macosx/" +86[] = "Apple Computer, Inc." +86[] = "http://www.apple.com/" +86[] = "macosx.png" +87[] = "OS/2" +87[] = "OS/2" +87[] = "http://en.wikipedia.org/wiki/OS/2" +87[] = "IBM Corporation" +87[] = "http://www.ibm.com/" +87[] = "os2.png" +88[] = "Windows" +88[] = "Windows Mobile" +88[] = "http://www.microsoft.com/windowsmobile/en-us/default.mspx" +88[] = "Microsoft Corporation." +88[] = "http://www.microsoft.com/" +88[] = "windowsMobile.png" +90[] = "Mac OS X" +90[] = "Mac OS X 10.3 Panther" +90[] = "http://www.apple.com/macosx/" +90[] = "Apple Computer, Inc." +90[] = "http://www.apple.com/" +90[] = "macosx.png" +91[] = "MINIX" +91[] = "MINIX 3 " +91[] = "http://www.minix3.org/" +91[] = "Andrew S. Tanenbaum" +91[] = "http://www.cs.vu.nl/~ast/" +91[] = "minix.png" +92[] = "Linux" +92[] = "PClinuxOS" +92[] = "http://pclinuxos.com/" +92[] = "PCLinuxOS community" +92[] = "" +92[] = "pclinuxos.png" +93[] = "Linux" +93[] = "Jolicloud" +93[] = "http://www.jolicloud.com/" +93[] = "Tariq Krim and Romain Huet" +93[] = "" +93[] = "jolicloud.png" +94[] = "XrossMediaBar (XMB)" +94[] = "XrossMediaBar (XMB)" +94[] = "http://en.wikipedia.org/wiki/XrossMediaBar" +94[] = "Sony Computer Entertainment" +94[] = "http://www.scei.co.jp/" +94[] = "XMB.png" +95[] = "AROS" +95[] = "AROS" +95[] = "http://www.aros.org/" +95[] = "AROS Development Team" +95[] = "" +95[] = "aros.png" +96[] = "Windows" +96[] = "Windows Phone 7" +96[] = "http://www.windowsphone7.com/" +96[] = "Microsoft Corporation." +96[] = "http://www.microsoft.com/" +96[] = "windowsMobile.png" +97[] = "Linux" +97[] = "Chromium OS" +97[] = "http://sites.google.com/a/chromium.org/dev/chromium-os" +97[] = "Google Inc." +97[] = "http://www.google.com/" +97[] = "ChromiumOS.png" +98[] = "Nintendo" +98[] = "Nintendo DS" +98[] = "http://www.nintendods.com/" +98[] = "Nintendo of America Inc." +98[] = "http://www.nintendo.com/" +98[] = "nintendo_ds.png" +99[] = "Linux" +99[] = "GNU OS" +99[] = "http://www.gnu.org/" +99[] = "Free Software Foundation, Inc." +99[] = "http://www.fsf.org/" +99[] = "gnu_os.png" +[browser] +; browser_id[] = "Browser type" +; browser_id[] = "Browser Name" +; browser_id[] = "Browser URL" +; browser_id[] = "Browser Company" +; browser_id[] = "Browser Company URL" +; browser_id[] = "Browser ico" +; browser_id[] = "Browser info URL" +1[] = "0" +1[] = "Camino" +1[] = "http://www.caminobrowser.org/" +1[] = "Mozilla Foundation" +1[] = "http://www.mozilla.org/" +1[] = "camino.png" +1[] = "/list-of-ua/browser-detail?browser=Camino" +2[] = "0" +2[] = "SeaMonkey" +2[] = "http://www.mozilla.org/projects/seamonkey/" +2[] = "Mozilla Foundation" +2[] = "http://www.mozilla.org/" +2[] = "seamonkey.png" +2[] = "/list-of-ua/browser-detail?browser=SeaMonkey" +3[] = "0" +3[] = "Firefox" +3[] = "http://www.mozilla.org/products/firefox/" +3[] = "Mozilla Foundation" +3[] = "http://www.mozilla.org/" +3[] = "firefox.png" +3[] = "/list-of-ua/browser-detail?browser=Firefox" +4[] = "0" +4[] = "Netscape Navigator" +4[] = "http://browser.netscape.com/" +4[] = "Netscape Communications Corp." +4[] = "http://www.netscape.com/" +4[] = "netscape.png" +4[] = "/list-of-ua/browser-detail?browser=Netscape Navigator" +5[] = "0" +5[] = "Epiphany" +5[] = "http://www.gnome.org/projects/epiphany/" +5[] = "GNOME Foundation" +5[] = "http://www.gnome.org/" +5[] = "epiphany.png" +5[] = "/list-of-ua/browser-detail?browser=Epiphany" +6[] = "0" +6[] = "Galeon" +6[] = "http://galeon.sourceforge.net/" +6[] = "GNOME Foundation" +6[] = "http://www.gnome.org/" +6[] = "galeon.png" +6[] = "/list-of-ua/browser-detail?browser=Galeon" +7[] = "0" +7[] = "Flock" +7[] = "http://www.flock.com/" +7[] = "Flock, Inc." +7[] = "http://www.flock.com/" +7[] = "flock.png" +7[] = "/list-of-ua/browser-detail?browser=Flock" +8[] = "3" +8[] = "Minimo" +8[] = "http://www.mozilla.org/projects/minimo/" +8[] = "Mozilla Foundation" +8[] = "http://www.mozilla.org/" +8[] = "minimo.png" +8[] = "/list-of-ua/browser-detail?browser=Minimo" +9[] = "0" +9[] = "K-Meleon" +9[] = "http://kmeleon.sourceforge.net/" +9[] = "Adnrew Mutch" +9[] = "http://tln.lib.mi.us/~amutch/" +9[] = "k-meleon.png" +9[] = "/list-of-ua/browser-detail?browser=K-Meleon" +10[] = "0" +10[] = "K-Ninja" +10[] = "http://www.geocities.com/grenleef/" +10[] = "" +10[] = "" +10[] = "k-ninja.png" +10[] = "/list-of-ua/browser-detail?browser=K-Ninja" +11[] = "0" +11[] = "Kazehakase" +11[] = "http://kazehakase.sourceforge.jp/" +11[] = "" +11[] = "" +11[] = "kazehakase.png" +11[] = "/list-of-ua/browser-detail?browser=Kazehakase" +14[] = "0" +14[] = "Firebird (old name for Firefox)" +14[] = "http://www.mozilla.org/products/firefox/" +14[] = "Mozilla Foundation" +14[] = "http://www.mozilla.org/" +14[] = "phoenix.png" +14[] = "/list-of-ua/browser-detail?browser=Firebird (old name for Firefox)" +15[] = "0" +15[] = "Phoenix (old name for Firefox)" +15[] = "http://www.mozilla.org/products/firefox/" +15[] = "Mozilla Foundation" +15[] = "http://www.mozilla.org/" +15[] = "phoenix.png" +15[] = "/list-of-ua/browser-detail?browser=Phoenix (old name for Firefox)" +16[] = "0" +16[] = "Konqueror" +16[] = "http://www.konqueror.org/" +16[] = "KDE e.V." +16[] = "http://ev.kde.org/" +16[] = "konqueror2.png" +16[] = "/list-of-ua/browser-detail?browser=Konqueror" +17[] = "0" +17[] = "Opera" +17[] = "http://www.opera.com/" +17[] = "Opera Software ASA." +17[] = "http://www.opera.com/" +17[] = "opera.png" +17[] = "/list-of-ua/browser-detail?browser=Opera" +18[] = "0" +18[] = "OmniWeb" +18[] = "http://www.omnigroup.com/applications/omniweb/" +18[] = "Omni Development, Inc." +18[] = "http://www.omnigroup.com/" +18[] = "omniweb.png" +18[] = "/list-of-ua/browser-detail?browser=OmniWeb" +19[] = "0" +19[] = "Sunrise" +19[] = "http://www.sunrisebrowser.com/" +19[] = "" +19[] = "" +19[] = "sunrise.png" +19[] = "/list-of-ua/browser-detail?browser=Sunrise" +21[] = "0" +21[] = "Shiira" +21[] = "http://shiira.jp/en" +21[] = "Shiira Project" +21[] = "http://shiira.jp/en" +21[] = "shiira.png" +21[] = "/list-of-ua/browser-detail?browser=Shiira" +22[] = "0" +22[] = "Safari" +22[] = "http://en.wikipedia.org/wiki/Safari_%28web_browser%29" +22[] = "Apple Inc." +22[] = "http://www.apple.com/" +22[] = "safari.png" +22[] = "/list-of-ua/browser-detail?browser=Safari" +23[] = "0" +23[] = "Dillo" +23[] = "http://www.dillo.org/" +23[] = "" +23[] = "" +23[] = "dillo.png" +23[] = "/list-of-ua/browser-detail?browser=Dillo" +24[] = "0" +24[] = "iCab" +24[] = "http://www.icab.de/" +24[] = "Alexander Clauss" +24[] = "" +24[] = "icab.png" +24[] = "/list-of-ua/browser-detail?browser=iCab" +25[] = "0" +25[] = "Lynx" +25[] = "http://lynx.isc.org/" +25[] = "" +25[] = "" +25[] = "lynx.png" +25[] = "/list-of-ua/browser-detail?browser=Lynx" +27[] = "0" +27[] = "Elinks" +27[] = "http://elinks.or.cz/" +27[] = "Mikulas Patocka" +27[] = "" +27[] = "elinks.png" +27[] = "/list-of-ua/browser-detail?browser=Elinks" +28[] = "1" +28[] = "Wget" +28[] = "http://www.gnu.org/software/wget/" +28[] = "Free Software Foundation, Inc." +28[] = "http://www.gnu.org/" +28[] = "wget.png" +28[] = "/list-of-ua/browser-detail?browser=Wget" +29[] = "0" +29[] = "Amiga Aweb" +29[] = "http://aweb.sunsite.dk/" +29[] = "AmiTrix Development Inc." +29[] = "http://www.amitrix.com/" +29[] = "aweb.png" +29[] = "/list-of-ua/browser-detail?browser=Amiga Aweb" +30[] = "0" +30[] = "Amiga Voyager" +30[] = "http://v3.vapor.com/" +30[] = "VaporWare" +30[] = "http://www.vapor.com/" +30[] = "voyager.png" +30[] = "/list-of-ua/browser-detail?browser=Amiga Voyager" +31[] = "0" +31[] = "IBrowse" +31[] = "http://www.ibrowse-dev.net/" +31[] = "Omnipresence Intl." +31[] = "http://www.omnipresence.com/" +31[] = "ibrowse.png" +31[] = "/list-of-ua/browser-detail?browser=IBrowse" +32[] = "3" +32[] = "Openwave Mobile Browser" +32[] = "http://www.openwave.com/" +32[] = "Openwave Systems Inc." +32[] = "http://www.openwave.com/" +32[] = "openwave.png" +32[] = "/list-of-ua/browser-detail?browser=Openwave Mobile Browser" +33[] = "3" +33[] = "NetFront" +33[] = "http://www.access-company.com/" +33[] = "ACCESS CO.,LTD" +33[] = "http://www.access-company.com/" +33[] = "netfront.png" +33[] = "/list-of-ua/browser-detail?browser=NetFront" +35[] = "0" +35[] = "IE" +35[] = "http://www.microsoft.com/ie/" +35[] = "Microsoft Corporation." +35[] = "http://www.microsoft.com/" +35[] = "msie.png" +35[] = "/list-of-ua/browser-detail?browser=IE" +39[] = "1" +39[] = "Offline Explorer" +39[] = "http://www.metaproducts.com/" +39[] = "MetaProducts Corporation." +39[] = "" +39[] = "offline_explorer.png" +39[] = "/list-of-ua/browser-detail?browser=Offline Explorer" +40[] = "0" +40[] = "AOL Explorer" +40[] = "http://daol.aol.com/software/" +40[] = "America Online, Inc." +40[] = "http://www.aol.com/" +40[] = "aol.png" +40[] = "/list-of-ua/browser-detail?browser=AOL Explorer" +41[] = "0" +41[] = "Avant Browser" +41[] = "http://avantbrowser.com/" +41[] = "Avant Force" +41[] = "http://avantbrowser.com/" +41[] = "avantbrowser.png" +41[] = "/list-of-ua/browser-detail?browser=Avant Browser" +42[] = "1" +42[] = "AvantGo" +42[] = "http://www.avantgo.com/" +42[] = "Sybase Inc." +42[] = "http://www.sybase.com/" +42[] = "avantgo.png" +42[] = "/list-of-ua/browser-detail?browser=AvantGo" +43[] = "3" +43[] = "Blazer" +43[] = "http://en.wikipedia.org/wiki/Blazer_(web_browser)" +43[] = "Palm. Inc." +43[] = "http://www.palm.com/" +43[] = "blazer.png" +43[] = "/list-of-ua/browser-detail?browser=Blazer" +44[] = "0" +44[] = "Crazy Browser" +44[] = "http://www.crazybrowser.com/" +44[] = "CrazyBrowser.com" +44[] = "http://www.crazybrowser.com/" +44[] = "crazybrowser.png" +44[] = "/list-of-ua/browser-detail?browser=Crazy Browser" +45[] = "0" +45[] = "Deepnet Explorer" +45[] = "http://www.deepnetexplorer.com/" +45[] = "Deepnet Technologies Ltd" +45[] = "http://www.deepnetexplorer.com/" +45[] = "deepnet.png" +45[] = "/list-of-ua/browser-detail?browser=Deepnet Explorer" +46[] = "1" +46[] = "HTTrack" +46[] = "http://www.httrack.com/" +46[] = "Xavier Roche" +46[] = "http://www.httrack.com/" +46[] = "httrack.png" +46[] = "/list-of-ua/browser-detail?browser=HTTrack" +47[] = "0" +47[] = "IceWeasel" +47[] = "http://www.gnu.org/software/gnuzilla/" +47[] = "Software in the Public Interest, Inc." +47[] = "http://www.spi-inc.org/" +47[] = "iceweasel.png" +47[] = "/list-of-ua/browser-detail?browser=IceWeasel" +48[] = "0" +48[] = "iRider" +48[] = "http://www.irider.com/irider/index.htm" +48[] = "Wymea Bay" +48[] = "http://www.irider.com/company/index.htm" +48[] = "irider.png" +48[] = "/list-of-ua/browser-detail?browser=iRider" +49[] = "1" +49[] = "iSiloX" +49[] = "http://www.isilox.com/" +49[] = "DC & Co." +49[] = "http://www.isilox.com/" +49[] = "isilox.png" +49[] = "/list-of-ua/browser-detail?browser=iSiloX" +50[] = "0" +50[] = "KKman" +50[] = "http://www.kkman.com/" +50[] = "Skysoft Co., Ltd." +50[] = "http://www.skysoft.com.tw/" +50[] = "kkman.png" +50[] = "/list-of-ua/browser-detail?browser=KKman" +51[] = "5" +51[] = "libwww-perl" +51[] = "http://search.cpan.org/dist/libwww-perl/" +51[] = "Gisle Aas" +51[] = "" +51[] = "libwwwperl.png" +51[] = "/list-of-ua/browser-detail?browser=libwww-perl" +52[] = "0" +52[] = "Lunascape" +52[] = "http://www.lunascape.tv/" +52[] = "Lunascape & Co., Ltd." +52[] = "http://www.lunascape.co.jp/" +52[] = "lunascape.png" +52[] = "/list-of-ua/browser-detail?browser=Lunascape" +53[] = "0" +53[] = "Maxthon" +53[] = "http://www.maxthon.com/" +53[] = "Maxthon International Limited." +53[] = "http://www.maxthon.com/" +53[] = "maxthon.png" +53[] = "/list-of-ua/browser-detail?browser=Maxthon" +54[] = "0" +54[] = "Mozilla" +54[] = "http://www.mozilla.org/projects/browsers.html" +54[] = "Mozilla Foundation" +54[] = "http://www.mozilla.com/" +54[] = "mozilla.png" +54[] = "/list-of-ua/browser-detail?browser=Mozilla" +55[] = "0" +55[] = "MultiZilla" +55[] = "http://multizilla.mozdev.org/" +55[] = "HJ van Rantwijk" +55[] = "http://multizilla.mozdev.org/" +55[] = "multizilla.png" +55[] = "/list-of-ua/browser-detail?browser=MultiZilla" +56[] = "0" +56[] = "NetCaptor" +56[] = "http://www.netcaptor.com/" +56[] = "Stilesoft Inc." +56[] = "http://www.netcaptor.com/" +56[] = "netcaptor.png" +56[] = "/list-of-ua/browser-detail?browser=NetCaptor" +57[] = "0" +57[] = "NetBox" +57[] = "http://www.netgem.com/" +57[] = "Netgem" +57[] = "http://www.netgem.com/" +57[] = "netgem.png" +57[] = "/list-of-ua/browser-detail?browser=NetBox" +58[] = "0" +58[] = "NetSurf" +58[] = "http://www.netsurf-browser.org/" +58[] = "NetSurf's Development Team" +58[] = "http://www.netsurf-browser.org/about/team" +58[] = "netsurf.png" +58[] = "/list-of-ua/browser-detail?browser=NetSurf" +59[] = "0" +59[] = "Sleipnir" +59[] = "http://www.fenrir.co.jp/sleipnir/" +59[] = "Fenrir Inc." +59[] = "http://www.fenrir-inc.com/" +59[] = "sleipnir.png" +59[] = "/list-of-ua/browser-detail?browser=Sleipnir" +61[] = "0" +61[] = "Swiftfox" +61[] = "http://www.getswiftfox.com/" +61[] = "Jason Halme" +61[] = "" +61[] = "swiftfox.png" +61[] = "/list-of-ua/browser-detail?browser=Swiftfox" +62[] = "1" +62[] = "Teleport Pro" +62[] = "http://www.tenmax.com/teleport/pro/home.htm" +62[] = "Tennyson Maxwell Information Systems, Inc." +62[] = "http://www.tenmax.com/" +62[] = "teleportpro.png" +62[] = "/list-of-ua/browser-detail?browser=Teleport Pro" +71[] = "1" +71[] = "WebCopier" +71[] = "http://www.maximumsoft.com/products/wc_index.html" +71[] = "MaximumSoft Corp." +71[] = "http://www.maximumsoft.com/" +71[] = "webcopier.png" +71[] = "/list-of-ua/browser-detail?browser=WebCopier" +74[] = "0" +74[] = "Phaseout" +74[] = "http://www.phaseout.net/" +74[] = "PhaseOut.net" +74[] = "http://www.phaseout.net/" +74[] = "phaseout.png" +74[] = "/list-of-ua/browser-detail?browser=Phaseout" +79[] = "4" +79[] = "Thunderbird" +79[] = "http://www.mozilla.com/en-US/thunderbird/" +79[] = "Mozilla Foundation" +79[] = "http://www.mozilla.org/" +79[] = "thunderbird.png" +79[] = "/list-of-ua/browser-detail?browser=Thunderbird" +81[] = "0" +81[] = "Doris" +81[] = "http://www.anygraaf.fi/browser/indexe.htm" +81[] = "Anygraaf" +81[] = "http://www.anygraaf.fi/" +81[] = "doris.png" +81[] = "/list-of-ua/browser-detail?browser=Doris" +82[] = "0" +82[] = "Enigma browser" +82[] = "http://www.suttondesigns.com/" +82[] = "Advanced Search Technologies, Inc." +82[] = "http://www.advancedsearchcorp.com/" +82[] = "enigmabrowser.png" +82[] = "/list-of-ua/browser-detail?browser=Enigma browser" +85[] = "5" +85[] = "Jakarta Commons-HttpClient" +85[] = "http://jakarta.apache.org/commons/httpclient/" +85[] = "Apache Software Foundation" +85[] = "http://www.apache.org/" +85[] = "jakarta.png" +85[] = "/list-of-ua/browser-detail?browser=Jakarta Commons-HttpClient" +86[] = "5" +86[] = "cURL" +86[] = "http://curl.haxx.se/" +86[] = "team Haxx" +86[] = "http://www.haxx.se/" +86[] = "curl.png" +86[] = "/list-of-ua/browser-detail?browser=cURL" +87[] = "0" +87[] = "Amaya" +87[] = "http://www.w3.org/Amaya/" +87[] = "World Wide Web Consortium" +87[] = "http://www.w3.org/" +87[] = "amaya.png" +87[] = "/list-of-ua/browser-detail?browser=Amaya" +88[] = "1" +88[] = "GetRight" +88[] = "http://www.getright.com/" +88[] = "Headlight Software, Inc." +88[] = "http://www.headlightinc.com/" +88[] = "getright.png" +88[] = "/list-of-ua/browser-detail?browser=GetRight" +89[] = "0" +89[] = "Off By One" +89[] = "http://offbyone.com/" +89[] = "Home Page Software Inc." +89[] = "http://homepagesw.com/" +89[] = "offbyone.png" +89[] = "/list-of-ua/browser-detail?browser=Off By One" +90[] = "5" +90[] = "Python-urllib" +90[] = "http://www.python.org/doc/current/lib/module-urllib.html" +90[] = "Python Software Foundation" +90[] = "http://www.python.org/psf/" +90[] = "pythonurllib.png" +90[] = "/list-of-ua/browser-detail?browser=Python-urllib" +91[] = "0" +91[] = "w3m" +91[] = "http://www.w3m.org/" +91[] = "Sakamoto Hironori" +91[] = "http://www2u.biglobe.ne.jp/%7Ehsaka/" +91[] = "w3m.png" +91[] = "/list-of-ua/browser-detail?browser=w3m" +93[] = "1" +93[] = "WebZIP" +93[] = "http://www.spidersoft.com/webzip/" +93[] = "Spidersoft" +93[] = "http://www.spidersoft.com/" +93[] = "webzip.png" +93[] = "/list-of-ua/browser-detail?browser=WebZIP" +94[] = "0" +94[] = "ICE browser" +94[] = "http://www.icesoft.com/products/icebrowser.html" +94[] = "ICEsoft Technologies Inc." +94[] = "http://www.icesoft.com/" +94[] = "icebrowser.png" +94[] = "/list-of-ua/browser-detail?browser=ICE browser" +96[] = "0" +96[] = "IceApe" +96[] = "http://www.debian.org/" +96[] = "Software in the Public Interest, Inc." +96[] = "http://www.spi-inc.org/" +96[] = "seamonkey.png" +96[] = "/list-of-ua/browser-detail?browser=IceApe" +99[] = "0" +99[] = "HotJava" +99[] = "http://java.sun.com/products/archive/hotjava/index.html" +99[] = "Sun Microsystems, Inc." +99[] = "http://www.sun.com/" +99[] = "hotjava.png" +99[] = "/list-of-ua/browser-detail?browser=HotJava" +100[] = "1" +100[] = "JoBo" +100[] = "http://www.matuschek.net/jobo/" +100[] = "Daniel Matuschek" +100[] = "http://www.matuschek.net/" +100[] = "jobo.png" +100[] = "/list-of-ua/browser-detail?browser=JoBo" +105[] = "5" +105[] = "POE-Component-Client-HTTP" +105[] = "http://search.cpan.org/dist/POE-Component-Client-HTTP/" +105[] = "" +105[] = "" +105[] = "perl.png" +105[] = "/list-of-ua/browser-detail?browser=POE-Component-Client-HTTP" +111[] = "5" +111[] = "Snoopy" +111[] = "http://sourceforge.net/projects/snoopy" +111[] = "Andrei Zmievski" +111[] = "" +111[] = "unknown.png" +111[] = "/list-of-ua/browser-detail?browser=Snoopy" +117[] = "0" +117[] = "NCSA Mosaic" +117[] = "http://www.ncsa.uiuc.edu/Projects/mosaic.html" +117[] = "NCSA" +117[] = "http://www.ncsa.uiuc.edu/" +117[] = "ncsa.png" +117[] = "/list-of-ua/browser-detail?browser=NCSA Mosaic" +119[] = "0" +119[] = "Kapiko" +119[] = "http://ufoxlab.googlepages.com/" +119[] = "Ufox lab." +119[] = "" +119[] = "kapiko.png" +119[] = "/list-of-ua/browser-detail?browser=Kapiko" +120[] = "0" +120[] = "Chrome" +120[] = "http://www.google.com/chrome" +120[] = "Google Inc." +120[] = "http://www.google.com/" +120[] = "chrome.png" +120[] = "/list-of-ua/browser-detail?browser=Chrome" +121[] = "5" +121[] = "Adobe AIR runtime" +121[] = "http://www.adobe.com/products/air/" +121[] = "Adobe Systems" +121[] = "http://www.adobe.com/" +121[] = "adobeair.png" +121[] = "/list-of-ua/browser-detail?browser=Adobe AIR runtime" +122[] = "5" +122[] = "LWP::Simple" +122[] = "http://search.cpan.org/perldoc?LWP::Simple" +122[] = "CPAN" +122[] = "http://cpan.org/" +122[] = "lwp.png" +122[] = "/list-of-ua/browser-detail?browser=LWP::Simple" +123[] = "5" +123[] = "WWW::Mechanize" +123[] = "http://search.cpan.org/dist/WWW-Mechanize/" +123[] = "CPAN" +123[] = "http://cpan.org/" +123[] = "lwp.png" +123[] = "/list-of-ua/browser-detail?browser=WWW::Mechanize" +124[] = "10" +124[] = "Xenu" +124[] = "http://home.snafu.de/tilman/xenulink.html" +124[] = "Tilman Hausherr" +124[] = "http://home.snafu.de/tilman/index.html" +124[] = "xenu.png" +124[] = "/list-of-ua/browser-detail?browser=Xenu" +125[] = "1" +125[] = "SiteSucker" +125[] = "http://www.sitesucker.us/" +125[] = "Rick Cranisky" +125[] = "" +125[] = "sitesucker.png" +125[] = "/list-of-ua/browser-detail?browser=SiteSucker" +126[] = "0" +126[] = "Arora" +126[] = "http://arora.googlecode.com/" +126[] = "Benjamin Meyer" +126[] = "http://www.blogger.com/profile/00185079236289035707" +126[] = "arora.png" +126[] = "/list-of-ua/browser-detail?browser=Arora" +128[] = "0" +128[] = "Firefox (Shiretoko)" +128[] = "http://www.mozilla.org/projects/firefox/3.1a1/releasenotes/" +128[] = "Mozilla Foundation" +128[] = "http://www.mozilla.org/" +128[] = "firefox.png" +128[] = "/list-of-ua/browser-detail?browser=Firefox (Shiretoko)" +129[] = "0" +129[] = "Firefox (Minefield)" +129[] = "http://www.mozilla.org/projects/minefield/" +129[] = "Mozilla Foundation" +129[] = "http://www.mozilla.org/" +129[] = "firefox.png" +129[] = "/list-of-ua/browser-detail?browser=Firefox (Minefield)" +130[] = "0" +130[] = "Iron" +130[] = "http://www.srware.net/en/software_srware_iron.php" +130[] = "" +130[] = "" +130[] = "iron.png" +130[] = "/list-of-ua/browser-detail?browser=Iron" +131[] = "0" +131[] = "Lobo" +131[] = "http://lobobrowser.org/java-browser.jsp" +131[] = "" +131[] = "" +131[] = "lobo.png" +131[] = "/list-of-ua/browser-detail?browser=Lobo" +132[] = "0" +132[] = "Links" +132[] = "http://links.twibright.com/" +132[] = "Twibright Labs" +132[] = "http://twibright.com/" +132[] = "links2.png" +132[] = "/list-of-ua/browser-detail?browser=Links" +133[] = "3" +133[] = "Fennec" +133[] = "https://wiki.mozilla.org/Fennec" +133[] = "Mozilla Foundation" +133[] = "http://www.mozilla.org/" +133[] = "fennec.png" +133[] = "/list-of-ua/browser-detail?browser=Fennec" +134[] = "4" +134[] = "Lotus Notes" +134[] = "http://www.ibm.com/software/lotus/products/notes/" +134[] = "IBM" +134[] = "http://www.ibm.com/" +134[] = "lotusnotes.png" +134[] = "/list-of-ua/browser-detail?browser=Lotus Notes" +135[] = "6" +135[] = "Klondike" +135[] = "http://web.archive.org/web/20071012053920/www.apachesoftware.com/products.html" +135[] = "Apache Software Consulting Inc." +135[] = "http://web.archive.org/web/*/www.apachesoftware.com" +135[] = "klondike.png" +135[] = "/list-of-ua/browser-detail?browser=Klondike" +136[] = "6" +136[] = "WapTiger" +136[] = "http://www.waptiger.com/waptiger/" +136[] = "infotiger" +136[] = "http://www.infotiger.com/" +136[] = "wap.png" +136[] = "/list-of-ua/browser-detail?browser=WapTiger" +137[] = "10" +137[] = "W3C Validator" +137[] = "http://validator.w3.org/" +137[] = "World Wide Web Consortium" +137[] = "http://www.w3.org/" +137[] = "w3.png" +137[] = "/list-of-ua/browser-detail?browser=W3C Validator" +138[] = "10" +138[] = "W3C Checklink" +138[] = "http://validator.w3.org/checklink" +138[] = "World Wide Web Consortium" +138[] = "http://www.w3.org/" +138[] = "w3.png" +138[] = "/list-of-ua/browser-detail?browser=W3C Checklink" +139[] = "10" +139[] = "HTMLParser" +139[] = "http://htmlparser.sourceforge.net/" +139[] = "" +139[] = "" +139[] = "htmlparser.png" +139[] = "/list-of-ua/browser-detail?browser=HTMLParser" +140[] = "5" +140[] = "Java" +140[] = "http://www.sun.com/java/" +140[] = "Sun Microsystems, Inc." +140[] = "http://www.sun.com/" +140[] = "java.png" +140[] = "/list-of-ua/browser-detail?browser=Java" +141[] = "0" +141[] = "Bolt" +141[] = "http://boltbrowser.com/" +141[] = "Bitstream" +141[] = "" +141[] = "bolt.png" +141[] = "/list-of-ua/browser-detail?browser=Bolt" +142[] = "0" +142[] = "Demeter" +142[] = "http://www.hurrikenux.com/Demeter/" +142[] = "hurrikenux Creative" +142[] = "http://www.hurrikenux.com/" +142[] = "demeter.png" +142[] = "/list-of-ua/browser-detail?browser=Demeter" +143[] = "5" +143[] = "FeedParser" +143[] = "http://feedparser.org/" +143[] = "Mark Pilgrim" +143[] = "http://diveintomark.org/" +143[] = "lib.png" +143[] = "/list-of-ua/browser-detail?browser=FeedParser" +144[] = "0" +144[] = "Orca" +144[] = "http://www.orcabrowser.com/" +144[] = "Avant Force team" +144[] = "http://www.avantforce.com/" +144[] = "orca.png" +144[] = "/list-of-ua/browser-detail?browser=Orca" +145[] = "0" +145[] = "Fluid" +145[] = "http://fluidapp.com/" +145[] = "Todd Ditchendorf" +145[] = "http://www.ditchnet.org/wp/" +145[] = "fluid.png" +145[] = "/list-of-ua/browser-detail?browser=Fluid" +146[] = "20" +146[] = "Bookdog" +146[] = "http://sheepsystems.com/products/bookdog/" +146[] = "Sheep Systems" +146[] = "http://sheepsystems.com/" +146[] = "bookdog.png" +146[] = "/list-of-ua/browser-detail?browser=Bookdog" +147[] = "50" +147[] = "Anonymouse.org" +147[] = "http://anonymouse.org/" +147[] = "Anonymous S.A." +147[] = "http://anonymouse.org/" +147[] = "anonymouse_org.png" +147[] = "/list-of-ua/browser-detail?browser=Anonymouse.org" +148[] = "0" +148[] = "Midori" +148[] = "http://software.twotoasts.de/index.php?/pages/midori_summary.html" +148[] = "TwoToasts.de" +148[] = "http://www.twotoasts.de/" +148[] = "midori.png" +148[] = "/list-of-ua/browser-detail?browser=Midori" +149[] = "18" +149[] = "Boxxe" +149[] = "" +149[] = "Team boxee" +149[] = "http://www.boxee.tv/" +149[] = "boxee.png" +149[] = "/list-of-ua/browser-detail?browser=Boxxe" +150[] = "20" +150[] = "gPodder" +150[] = "http://gpodder.org/" +150[] = "Thomas Perl and the gPodder Team" +150[] = "" +150[] = "gpodder.png" +150[] = "/list-of-ua/browser-detail?browser=gPodder" +151[] = "3" +151[] = "Obigo" +151[] = "http://en.wikipedia.org/wiki/Obigo_Browser" +151[] = "Obigo Ltd" +151[] = "http://www.obigo.com/" +151[] = "obigo.png" +151[] = "/list-of-ua/browser-detail?browser=Obigo" +152[] = "3" +152[] = "SEMC Browser" +152[] = "" +152[] = "Sony Ericsson Mobile Communications AB" +152[] = "http://www.sonyericsson.com/" +152[] = "semc.png" +152[] = "/list-of-ua/browser-detail?browser=SEMC Browser" +153[] = "0" +153[] = "Firefox (GranParadiso)" +153[] = "https://wiki.mozilla.org/Firefox3" +153[] = "Mozilla Foundation" +153[] = "http://www.mozilla.org/" +153[] = "firefox.png" +153[] = "/list-of-ua/browser-detail?browser=Firefox (GranParadiso)" +154[] = "10" +154[] = "WDG Validator" +154[] = "http://www.htmlhelp.com/tools/validator/" +154[] = "Web Design Group" +154[] = "http://www.htmlhelp.com/" +154[] = "wdg.png" +154[] = "/list-of-ua/browser-detail?browser=WDG Validator" +155[] = "10" +155[] = "WDG CSSCheck" +155[] = "http://www.htmlhelp.com/tools/csscheck/" +155[] = "Web Design Group" +155[] = "http://www.htmlhelp.com/" +155[] = "wdg.png" +155[] = "/list-of-ua/browser-detail?browser=WDG CSSCheck" +156[] = "10" +156[] = "WDG Page Valet" +156[] = "http://valet.htmlhelp.com/page/" +156[] = "Web Design Group" +156[] = "http://www.htmlhelp.com/" +156[] = "wdg.png" +156[] = "/list-of-ua/browser-detail?browser=WDG Page Valet" +157[] = "3" +157[] = "IE Mobile" +157[] = "http://www.microsoft.com/windowsmobile/en-us/downloads/microsoft/internet-explorer-mobile.mspx" +157[] = "Microsoft Corporation." +157[] = "http://www.microsoft.com/" +157[] = "msie.png" +157[] = "/list-of-ua/browser-detail?browser=IE Mobile" +158[] = "3" +158[] = "BlackBerry" +158[] = "http://www.blackberry.com/" +158[] = "Research In Motion Limited" +158[] = "http://www.rim.com/" +158[] = "blackberry.png" +158[] = "/list-of-ua/browser-detail?browser=BlackBerry" +159[] = "3" +159[] = "Polaris" +159[] = "http://www.infraware.co.kr/eng/01_product/product02.asp" +159[] = "Infraware" +159[] = "http://www.infraware.co.kr/" +159[] = "polaris.png" +159[] = "/list-of-ua/browser-detail?browser=Polaris" +160[] = "0" +160[] = "Hv3" +160[] = "http://tkhtml.tcl.tk/hv3.html" +160[] = "tkhtml.tcl.tk" +160[] = "http://tkhtml.tcl.tk/" +160[] = "hv3.png" +160[] = "/list-of-ua/browser-detail?browser=Hv3" +161[] = "6" +161[] = "WinWap" +161[] = "http://www.winwap.com/mobile_applications/winwap_browser" +161[] = "Winwap Technologies" +161[] = "http://www.winwap.com/" +161[] = "winwap.png" +161[] = "/list-of-ua/browser-detail?browser=WinWap" +162[] = "18" +162[] = "XBMC" +162[] = "http://xbmc.org/" +162[] = "Team-XBMC" +162[] = "http://xbmc.org/about/team/" +162[] = "xbmc.png" +162[] = "/list-of-ua/browser-detail?browser=XBMC" +163[] = "5" +163[] = "XML-RPC for PHP" +163[] = "http://phpxmlrpc.sourceforge.net/" +163[] = "" +163[] = "" +163[] = "php-xmlrpc.png" +163[] = "/list-of-ua/browser-detail?browser=XML-RPC for PHP" +165[] = "18" +165[] = "FlyCast" +165[] = "http://www.flycast.fm/" +165[] = "FlyCast Inc." +165[] = "" +165[] = "flycast.png" +165[] = "/list-of-ua/browser-detail?browser=FlyCast" +166[] = "15" +166[] = "Bloglines" +166[] = "http://www.bloglines.com/" +166[] = "IAS Search & Media" +166[] = "http://www.iac.com/" +166[] = "bloglines.png" +166[] = "/list-of-ua/browser-detail?browser=Bloglines" +167[] = "15" +167[] = "Gregarius" +167[] = "http://devlog.gregarius.net/" +167[] = "Marco Bonetti" +167[] = "http://www.linkedin.com/in/mbonetti" +167[] = "gregarius.png" +167[] = "/list-of-ua/browser-detail?browser=Gregarius" +168[] = "5" +168[] = "SimplePie" +168[] = "http://simplepie.org/" +168[] = "Ryan Parman and Geoffrey Sneddon" +168[] = "" +168[] = "simplepie.png" +168[] = "/list-of-ua/browser-detail?browser=SimplePie" +169[] = "5" +169[] = "PycURL" +169[] = "http://pycurl.sourceforge.net/" +169[] = "" +169[] = "" +169[] = "curl.png" +169[] = "/list-of-ua/browser-detail?browser=PycURL" +170[] = "15" +170[] = "Apple-PubSub" +170[] = "http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/pubsub.1.html" +170[] = "Apple Inc." +170[] = "http://www.apple.com/" +170[] = "apple.png" +170[] = "/list-of-ua/browser-detail?browser=Apple-PubSub" +171[] = "15" +171[] = "Feedfetcher-Google" +171[] = "http://www.google.com/feedfetcher.html" +171[] = "Google" +171[] = "http://www.google.com/" +171[] = "feedfetcher-google.png" +171[] = "/list-of-ua/browser-detail?browser=Feedfetcher-Google" +172[] = "10" +172[] = "FeedValidator" +172[] = "http://feedvalidator.org/" +172[] = "Mark Pilgrim" +172[] = "http://diveintomark.org/" +172[] = "feedvalidator.png" +172[] = "/list-of-ua/browser-detail?browser=FeedValidator" +173[] = "5" +173[] = "MagpieRSS" +173[] = "http://magpierss.sourceforge.net/" +173[] = "kellan" +173[] = "" +173[] = "magpierss.png" +173[] = "/list-of-ua/browser-detail?browser=MagpieRSS" +174[] = "15" +174[] = "BlogBridge" +174[] = "http://www.blogbridge.com/" +174[] = "Salas Associates, Inc." +174[] = "" +174[] = "blogbridge.png" +174[] = "/list-of-ua/browser-detail?browser=BlogBridge" +175[] = "18" +175[] = "Miro" +175[] = "http://www.getmiro.com/" +175[] = "Participatory Culture Foundation" +175[] = "http://www.participatoryculture.org/" +175[] = "miro.png" +175[] = "/list-of-ua/browser-detail?browser=Miro" +176[] = "15" +176[] = "Liferea" +176[] = "http://liferea.sourceforge.net/" +176[] = "" +176[] = "" +176[] = "liferea.png" +176[] = "/list-of-ua/browser-detail?browser=Liferea" +177[] = "15" +177[] = "Seznam RSS reader" +177[] = "" +177[] = "Seznam.cz, a.s." +177[] = "http://www.seznam.cz/" +177[] = "seznamrssreader.png" +177[] = "/list-of-ua/browser-detail?browser=Seznam RSS reader" +178[] = "20" +178[] = "PHP" +178[] = "http://php.net/" +178[] = "The PHP Group" +178[] = "" +178[] = "php.png" +178[] = "/list-of-ua/browser-detail?browser=PHP" +179[] = "10" +179[] = "REL Link Checker Lite" +179[] = "http://www.relsoftware.com/rlc/" +179[] = "REL Software, Inc." +179[] = "http://www.relsoftware.com/company/" +179[] = "RELlinkchecker.png" +179[] = "/list-of-ua/browser-detail?browser=REL Link Checker Lite" +180[] = "15" +180[] = "CPG Dragonfly RSS Module" +180[] = "http://dragonflycms.org/" +180[] = "" +180[] = "" +180[] = "dragonflycms.png" +180[] = "/list-of-ua/browser-detail?browser=CPG Dragonfly RSS Module" +181[] = "15" +181[] = "Newsbeuter" +181[] = "http://www.newsbeuter.org/" +181[] = "Andreas Krennmair" +181[] = "http://synflood.at/" +181[] = "newsbeuter.png" +181[] = "/list-of-ua/browser-detail?browser=Newsbeuter" +182[] = "10" +182[] = "W3C CSS Validator" +182[] = "http://jigsaw.w3.org/css-validator/" +182[] = "World Wide Web Consortium" +182[] = "http://www.w3.org/" +182[] = "w3.png" +182[] = "/list-of-ua/browser-detail?browser=W3C CSS Validator" +183[] = "10" +183[] = "PHP link checker" +183[] = "http://www.hotscripts.com/listing/php-link-checker/" +183[] = "" +183[] = "" +183[] = "php.png" +183[] = "/list-of-ua/browser-detail?browser=PHP link checker" +184[] = "20" +184[] = "GoldenPod" +184[] = "http://random.zerodogg.org/goldenpod" +184[] = "Eskild Hustvedt" +184[] = "http://random.zerodogg.org/" +184[] = "perl.png" +184[] = "/list-of-ua/browser-detail?browser=GoldenPod" +185[] = "0" +185[] = "Cheshire" +185[] = "http://greenhouse.aol.com/prod.jsp?prod_id=32" +185[] = "America Online, Inc." +185[] = "http://www.aol.com/" +185[] = "aol.png" +185[] = "/list-of-ua/browser-detail?browser=Cheshire" +187[] = "0" +187[] = "CometBird" +187[] = "http://www.cometbird.com/" +187[] = "cometbird.com" +187[] = "" +187[] = "cometbird.png" +187[] = "/list-of-ua/browser-detail?browser=CometBird" +188[] = "0" +188[] = "IceCat" +188[] = "http://www.gnu.org/software/gnuzilla/" +188[] = "Free Software Foundation, Inc." +188[] = "http://www.fsf.org/" +188[] = "icecat.png" +188[] = "/list-of-ua/browser-detail?browser=IceCat" +189[] = "0" +189[] = "Stainless" +189[] = "http://www.stainlessapp.com/" +189[] = "Mesa Dynamics, LLC" +189[] = "http://www.mesadynamics.com/" +189[] = "stainless.png" +189[] = "/list-of-ua/browser-detail?browser=Stainless" +190[] = "20" +190[] = "Prism" +190[] = "http://prism.mozilla.com/" +190[] = "Mozilla Labs" +190[] = "http://labs.mozilla.com/" +190[] = "prism.png" +190[] = "/list-of-ua/browser-detail?browser=Prism" +191[] = "18" +191[] = "MPlayer" +191[] = "http://www.mplayerhq.hu/" +191[] = "The MPlayer Project" +191[] = "" +191[] = "mplayer.png" +191[] = "/list-of-ua/browser-detail?browser=MPlayer" +192[] = "20" +192[] = "ActiveXperts Network Monitor" +192[] = "http://www.activexperts.com/activmonitor/" +192[] = "ActiveXperts Software B.V." +192[] = "http://www.activexperts.com/" +192[] = "activexperts-network-monitor.png" +192[] = "/list-of-ua/browser-detail?browser=ActiveXperts Network Monitor" +193[] = "3" +193[] = "Motorola Internet Browser" +193[] = "http://www.motorola.com/content.jsp?globalObjectId=1827-4343" +193[] = "Motorola, Inc." +193[] = "http://www.motorola.com/" +193[] = "mib.png" +193[] = "/list-of-ua/browser-detail?browser=Motorola Internet Browser" +194[] = "15" +194[] = "Abilon" +194[] = "" +194[] = "SisyphSoft" +194[] = "http://web.archive.org/web/20050721080030/http://www.abilon.org/" +194[] = "abilon.png" +194[] = "/list-of-ua/browser-detail?browser=Abilon" +195[] = "20" +195[] = "HTTP nagios plugin" +195[] = "" +195[] = "Nagios Enterprises, LLC." +195[] = "http://www.nagios.org/" +195[] = "nagios.png" +195[] = "/list-of-ua/browser-detail?browser=HTTP nagios plugin" +196[] = "18" +196[] = "Windows Media Player" +196[] = "http://www.microsoft.com/windows/windowsmedia/" +196[] = "Microsoft Corporation." +196[] = "http://www.microsoft.com/" +196[] = "wmp.png" +196[] = "/list-of-ua/browser-detail?browser=Windows Media Player" +197[] = "18" +197[] = "VLC media player" +197[] = "http://www.videolan.org/vlc/" +197[] = "VideoLAN team" +197[] = "http://www.videolan.org/" +197[] = "vlc.png" +197[] = "/list-of-ua/browser-detail?browser=VLC media player" +198[] = "10" +198[] = "P3P Validator" +198[] = "http://www.w3.org/P3P/validator.html" +198[] = "World Wide Web Consortium" +198[] = "http://www.w3.org/" +198[] = "w3.png" +198[] = "/list-of-ua/browser-detail?browser=P3P Validator" +199[] = "10" +199[] = "CSE HTML Validator" +199[] = "http://online.htmlvalidator.com/php/onlinevallite.php" +199[] = "AI Internet Solutions" +199[] = "http://www.htmlvalidator.com/" +199[] = "csehtmlvalidator.png" +199[] = "/list-of-ua/browser-detail?browser=CSE HTML Validator" +200[] = "15" +200[] = "Omea Reader" +200[] = "http://www.jetbrains.com/omea/reader/" +200[] = "JetBrains" +200[] = "http://www.jetbrains.com/" +200[] = "omeareader.png" +200[] = "/list-of-ua/browser-detail?browser=Omea Reader" +201[] = "20" +201[] = "GSiteCrawler" +201[] = "http://gsitecrawler.com/" +201[] = "SOFTplus Entwicklungen GmbH" +201[] = "http://www.softplus.net/" +201[] = "gsitecrawler.png" +201[] = "/list-of-ua/browser-detail?browser=GSiteCrawler" +202[] = "15" +202[] = "YahooFeedSeeker" +202[] = "http://publisher.yahoo.com/rssguide" +202[] = "Yahoo! Inc" +202[] = "http://www.yahoo.com/" +202[] = "YahooFeedSeeker.png" +202[] = "/list-of-ua/browser-detail?browser=YahooFeedSeeker" +204[] = "0" +204[] = "TheWorld Browser" +204[] = "http://www.ioage.com/" +204[] = "Phoenix Studio" +204[] = "" +204[] = "the_world.png" +204[] = "/list-of-ua/browser-detail?browser=TheWorld Browser" +205[] = "20" +205[] = "WebCollage" +205[] = "http://www.jwz.org/webcollage/" +205[] = "Jamie Zawinski" +205[] = "http://www.jwz.org/" +205[] = "webcollage.png" +205[] = "/list-of-ua/browser-detail?browser=WebCollage" +206[] = "15" +206[] = "NewsGatorOnline" +206[] = "http://www.newsgator.com/" +206[] = "NewsGator Technologies, Inc." +206[] = "http://www.newsgator.com/companyinfo/default.aspx" +206[] = "newsgator-online.png" +206[] = "/list-of-ua/browser-detail?browser=NewsGatorOnline" +207[] = "20" +207[] = "PRTG Network Monitor" +207[] = "http://www.paessler.com/prtg" +207[] = "Paessler AG" +207[] = "http://www.paessler.com/" +207[] = "PRTG_Network_Monitor.png" +207[] = "/list-of-ua/browser-detail?browser=PRTG Network Monitor" +208[] = "18" +208[] = "Songbird" +208[] = "http://getsongbird.com/" +208[] = "Pioneers of the Inevitable" +208[] = "http://getsongbird.com/about/" +208[] = "songbird.png" +208[] = "/list-of-ua/browser-detail?browser=Songbird" +209[] = "18" +209[] = "RSS Radio" +209[] = "http://www.dorada.co.uk/" +209[] = "Dorada Software" +209[] = "" +209[] = "rssradio.png" +209[] = "/list-of-ua/browser-detail?browser=RSS Radio" +210[] = "5" +210[] = "Feed::Find" +210[] = "http://search.cpan.org/dist/Feed-Find/" +210[] = "Benjamin Trott" +210[] = "" +210[] = "perl.png" +210[] = "/list-of-ua/browser-detail?browser=Feed::Find" +211[] = "3" +211[] = "Palm Pre web browser" +211[] = "http://www.palm.com/us/products/phones/pre/index.html" +211[] = "Palm Inc." +211[] = "http://www.palm.com/" +211[] = "palmpre.png" +211[] = "/list-of-ua/browser-detail?browser=Palm Pre web browser" +212[] = "0" +212[] = "Firefox (BonEcho)" +212[] = "http://www.mozilla.org/projects/bonecho/releases/2.0a1.html" +212[] = "Mozilla Foundation" +212[] = "http://www.mozilla.org/" +212[] = "firefox.png" +212[] = "/list-of-ua/browser-detail?browser=Firefox (BonEcho)" +213[] = "18" +213[] = "QuickTime" +213[] = "http://www.apple.com/quicktime/" +213[] = "Apple Inc." +213[] = "http://www.apple.com/" +213[] = "quicktime.png" +213[] = "/list-of-ua/browser-detail?browser=QuickTime" +214[] = "5" +214[] = "PHPcrawl" +214[] = "http://phpcrawl.cuab.de/" +214[] = "Uwe Hunfeld" +214[] = "" +214[] = "php.png" +214[] = "/list-of-ua/browser-detail?browser=PHPcrawl" +216[] = "0" +216[] = "GreenBrowser" +216[] = "http://www.morequick.com/indexen.htm" +216[] = "More Quick Tools" +216[] = "http://www.morequick.com/" +216[] = "green_browser.png" +216[] = "/list-of-ua/browser-detail?browser=GreenBrowser" +217[] = "15" +217[] = "Awasu" +217[] = "http://www.awasu.com/" +217[] = "Awasu Pty. Ltd." +217[] = "" +217[] = "awasu.png" +217[] = "/list-of-ua/browser-detail?browser=Awasu" +218[] = "18" +218[] = "CorePlayer" +218[] = "http://www.coreplayer.com/" +218[] = "CoreCodec, inc." +218[] = "" +218[] = "CorePlayer.png" +218[] = "/list-of-ua/browser-detail?browser=CorePlayer" +219[] = "0" +219[] = "QtWeb" +219[] = "http://www.qtweb.net/" +219[] = "QtWeb.NET" +219[] = "" +219[] = "qt_web.png" +219[] = "/list-of-ua/browser-detail?browser=QtWeb" +220[] = "3" +220[] = "TeaShark" +220[] = "http://www.teashark.com/" +220[] = "TeaShark" +220[] = "" +220[] = "teashark.png" +220[] = "/list-of-ua/browser-detail?browser=TeaShark" +221[] = "5" +221[] = "LibSoup" +221[] = "http://live.gnome.org/LibSoup" +221[] = "The GNOME Project" +221[] = "http://www.gnome.org/" +221[] = "libsoup.png" +221[] = "/list-of-ua/browser-detail?browser=LibSoup" +222[] = "15" +222[] = "NetNewsWire" +222[] = "http://www.newsgator.com/Individuals/NetNewsWire/" +222[] = "NewsGator Technologies, Inc." +222[] = "http://www.newsgator.com/" +222[] = "netnewswire.png" +222[] = "/list-of-ua/browser-detail?browser=NetNewsWire" +223[] = "20" +223[] = "Google App Engine" +223[] = "http://code.google.com/appengine/" +223[] = "Google" +223[] = "http://www.google.com/" +223[] = "google_appengine.png" +223[] = "/list-of-ua/browser-detail?browser=Google App Engine" +225[] = "3" +225[] = "UC Browser" +225[] = "http://www.ucweb.com/English/product.shtml" +225[] = "UCWEB Technology Ltd." +225[] = "http://www.ucweb.com/" +225[] = "ucweb.png" +225[] = "/list-of-ua/browser-detail?browser=UC Browser" +226[] = "3" +226[] = "Nokia Web Browser" +226[] = "http://nokia.com/browser" +226[] = "Nokia" +226[] = "http://www.nokia.com/" +226[] = "nokia.png" +226[] = "/list-of-ua/browser-detail?browser=Nokia Web Browser" +227[] = "20" +227[] = "LFTP" +227[] = "http://lftp.yar.ru/" +227[] = "Alexander V. Lukyanov" +227[] = "" +227[] = "lftp.png" +227[] = "/list-of-ua/browser-detail?browser=LFTP" +228[] = "0" +228[] = "Oregano" +228[] = "http://www.oreganouk.net/oregano2.html" +228[] = "Genesys Developments Ltd" +228[] = "http://www.oreganouk.net/" +228[] = "oregano.png" +228[] = "/list-of-ua/browser-detail?browser=Oregano" +229[] = "5" +229[] = "Summer" +229[] = "http://wrya.net/services/trac/summer" +229[] = "Robin Sonefors" +229[] = "http://flukkost.nu/" +229[] = "libsummer.png" +229[] = "/list-of-ua/browser-detail?browser=Summer" +230[] = "0" +230[] = "Acoo Browser" +230[] = "http://www.acoobrowser.com/" +230[] = "" +230[] = "" +230[] = "acco.png" +230[] = "/list-of-ua/browser-detail?browser=Acoo Browser" +231[] = "15" +231[] = "NewsFox" +231[] = "http://newsfox.mozdev.org/" +231[] = "NewsFox team" +231[] = "http://newsfox.mozdev.org/team.html" +231[] = "newsfox.png" +231[] = "/list-of-ua/browser-detail?browser=NewsFox" +232[] = "0" +232[] = "Hydra Browser" +232[] = "http://hydrabrowser.com/" +232[] = "Quantum" +232[] = "" +232[] = "hydrabrowser.png" +232[] = "/list-of-ua/browser-detail?browser=Hydra Browser" +233[] = "0" +233[] = "wKiosk" +233[] = "http://www.app4mac.com/store/index.php?target=products&product_id=9" +233[] = "app4mac Inc." +233[] = "http://www.app4mac.com/" +233[] = "wkiosk.png" +233[] = "/list-of-ua/browser-detail?browser=wKiosk" +234[] = "20" +234[] = "Paparazzi!" +234[] = "http://derailer.org/paparazzi/" +234[] = "Nate Weaver (Wevah)" +234[] = "http://derailer.org/" +234[] = "paparazzi.png" +234[] = "/list-of-ua/browser-detail?browser=Paparazzi!" +235[] = "5" +235[] = "xine" +235[] = "http://www.xine-project.org/" +235[] = "xine team" +235[] = "http://www.xine-project.org/authors" +235[] = "xine.png" +235[] = "/list-of-ua/browser-detail?browser=xine" +236[] = "20" +236[] = "webfs" +236[] = "http://plan9.bell-labs.com/magic/man2html/4/webfs" +236[] = "Lucent Technologies" +236[] = "http://plan9.bell-labs.com/plan9/" +236[] = "plan9.png" +236[] = "/list-of-ua/browser-detail?browser=webfs" +237[] = "15" +237[] = "NewsBreak" +237[] = "http://www.iliumsoft.com/site/nw/newsbreak.php" +237[] = "Ilium Software, Inc." +237[] = "http://www.iliumsoft.com/" +237[] = "newsbreak.png" +237[] = "/list-of-ua/browser-detail?browser=NewsBreak" +238[] = "20" +238[] = "LinkbackPlugin for Laconica" +238[] = "http://laconi.ca/" +238[] = "Laconica Developer Community" +238[] = "http://laconi.ca/trac/wiki/DeveloperCommunity" +238[] = "laconica.png" +238[] = "/list-of-ua/browser-detail?browser=LinkbackPlugin for Laconica" +239[] = "20" +239[] = "Microsoft WebDAV client" +239[] = "" +239[] = "Microsoft Corporation." +239[] = "http://www.microsoft.com/" +239[] = "webdav.png" +239[] = "/list-of-ua/browser-detail?browser=Microsoft WebDAV client" +240[] = "20" +240[] = "GnomeVFS" +240[] = "http://developer.gnome.org/doc/API/2.0/gnome-vfs-2" +240[] = "The GNOME Project" +240[] = "http://www.gnome.org/" +240[] = "webdav.png" +240[] = "/list-of-ua/browser-detail?browser=GnomeVFS" +241[] = "0" +241[] = "Uzbl" +241[] = "http://www.uzbl.org/" +241[] = "" +241[] = "" +241[] = "uzbl.png" +241[] = "/list-of-ua/browser-detail?browser=Uzbl" +242[] = "10" +242[] = "Cynthia" +242[] = "http://www.contentquality.com/" +242[] = "HiSoftware Inc." +242[] = "http://www.hisoftware.com/" +242[] = "cynthia.png" +242[] = "/list-of-ua/browser-detail?browser=Cynthia" +243[] = "15" +243[] = "Sage" +243[] = "http://sage.mozdev.org" +243[] = "Peter Andrews" +243[] = "http://petea.org/" +243[] = "sage.png" +243[] = "/list-of-ua/browser-detail?browser=Sage" +244[] = "18" +244[] = "Banshee" +244[] = "http://banshee-project.org/" +244[] = "Novell, Inc." +244[] = "http://www.novell.com/" +244[] = "banshee.png" +244[] = "/list-of-ua/browser-detail?browser=Banshee" +245[] = "0" +245[] = "Wyzo" +245[] = "http://www.wyzo.com/" +245[] = "Radical Software Ltd." +245[] = "http://www.radicalsoft.com/" +245[] = "wyzo.png" +245[] = "/list-of-ua/browser-detail?browser=Wyzo" +246[] = "15" +246[] = "RSSOwl" +246[] = "http://www.rssowl.org/" +246[] = "Benjamin Pasero" +246[] = "" +246[] = "rssowl.png" +246[] = "/list-of-ua/browser-detail?browser=RSSOwl" +247[] = "0" +247[] = "ABrowse" +247[] = "http://en.wikipedia.org/wiki/ABrowse" +247[] = "Kurt Skauen" +247[] = "http://www.syllable.org/" +247[] = "abrowse.png" +247[] = "/list-of-ua/browser-detail?browser=ABrowse" +248[] = "20" +248[] = "Funambol Outlook Sync Client" +248[] = "https://www.forge.funambol.org/download/" +248[] = "Funambol, Inc." +248[] = "http://funambol.com/" +248[] = "funambol-outlook.png" +248[] = "/list-of-ua/browser-detail?browser=Funambol Outlook Sync Client" +249[] = "20" +249[] = "Funambol Mozilla Sync Client" +249[] = "https://mozilla-plugin.forge.funambol.org/ " +249[] = "Carlo Codega" +249[] = "http://sazilla.blogspot.com" +249[] = "funambol-mozilla.png" +249[] = "/list-of-ua/browser-detail?browser=Funambol Mozilla Sync Client" +250[] = "15" +250[] = "RSS Menu" +250[] = "http://www.edot-studios.com/webgroups2/index.php?menu_item=212" +250[] = "e dot studios" +250[] = "http://www.edot-studios.com/" +250[] = "rss_menu.png" +250[] = "/list-of-ua/browser-detail?browser=RSS Menu" +251[] = "18" +251[] = "foobar2000" +251[] = "http://www.foobar2000.org/" +251[] = "Peter Pawlowski" +251[] = "" +251[] = "foobar2000.png" +251[] = "/list-of-ua/browser-detail?browser=foobar2000" +252[] = "5" +252[] = "GStreamer" +252[] = "http://gstreamer.freedesktop.org/" +252[] = "GStreamer community" +252[] = "http://gstreamer.freedesktop.org/" +252[] = "GStreamer.png" +252[] = "/list-of-ua/browser-detail?browser=GStreamer" +253[] = "20" +253[] = "NetFront Mobile Content Viewer" +253[] = "http://www.access-company.com/products/mobile_solutions/netfrontmobile/contentviewer/index.html" +253[] = "ACCESS CO., LTD." +253[] = "http://www.access-company.com/" +253[] = "netfront.png" +253[] = "/list-of-ua/browser-detail?browser=NetFront Mobile Content Viewer" +254[] = "5" +254[] = "PHP OpenID library" +254[] = "http://openidenabled.com/php-openid/" +254[] = "JanRain, Inc." +254[] = "http://www.janrain.com/" +254[] = "PHP_OpenID_lib.png" +254[] = "/list-of-ua/browser-detail?browser=PHP OpenID library" +255[] = "0" +255[] = "Blackbird" +255[] = "http://www.blackbirdbrowser.com/" +255[] = "40A, Inc." +255[] = "" +255[] = "blackbird.png" +255[] = "/list-of-ua/browser-detail?browser=Blackbird" +256[] = "15" +256[] = "GreatNews" +256[] = "http://www.curiostudio.com/" +256[] = "Curio Studio" +256[] = "" +256[] = "GreatNews.png" +256[] = "/list-of-ua/browser-detail?browser=GreatNews" +257[] = "0" +257[] = "DeskBrowse" +257[] = "http://www.deskbrowse.org/" +257[] = "Off Leash Developments, Inc" +257[] = "http://offleashdevelopments.com/" +257[] = "deskbrowse.png" +257[] = "/list-of-ua/browser-detail?browser=DeskBrowse" +258[] = "20" +258[] = "Tulip Chain" +258[] = "http://ostermiller.org/tulipchain/" +258[] = "Stephen "deadsea" Ostermiller" +258[] = "http://ostermiller.org/" +258[] = "TulipChain.png" +258[] = "/list-of-ua/browser-detail?browser=Tulip Chain" +259[] = "1" +259[] = "Axel" +259[] = "http://axel.alioth.debian.org/" +259[] = "Y Giridhar Appaji Nag" +259[] = "http://www.appaji.net/" +259[] = "terminal.png" +259[] = "/list-of-ua/browser-detail?browser=Axel" +260[] = "3" +260[] = "MicroB" +260[] = "http://browser.garage.maemo.org/" +260[] = "Nokia" +260[] = "http://www.nokia.com/" +260[] = "microb.png" +260[] = "/list-of-ua/browser-detail?browser=MicroB" +261[] = "3" +261[] = "Tear" +261[] = "http://tear.garage.maemo.org/" +261[] = "Kamen Bundev" +261[] = "http://bundyo.org/" +261[] = "tear.png" +261[] = "/list-of-ua/browser-detail?browser=Tear" +262[] = "10" +262[] = "LinkExaminer" +262[] = "http://www.analogx.com/contents/download/Network/lnkexam/Freeware.htm" +262[] = "AnalogX, LLC." +262[] = "http://www.analogx.com/" +262[] = "LinkExaminer.png" +262[] = "/list-of-ua/browser-detail?browser=LinkExaminer" +263[] = "0" +263[] = "Abolimba" +263[] = "http://www.aborange.de/products/freeware/abolimba-multibrowser.php" +263[] = "Mathias Gerlach, Jochen Milchsack" +263[] = "http://www.aborange.de/" +263[] = "abolimba.png" +263[] = "/list-of-ua/browser-detail?browser=Abolimba" +264[] = "0" +264[] = "Beonex" +264[] = "http://www.beonex.com/" +264[] = "Ben Bucksch" +264[] = "http://www.bucksch.org/" +264[] = "beonex.png" +264[] = "/list-of-ua/browser-detail?browser=Beonex" +265[] = "0" +265[] = "DocZilla" +265[] = "http://www.doczilla.com/" +265[] = "CITEC" +265[] = "http://www.citec.com/" +265[] = "doczilla.png" +265[] = "/list-of-ua/browser-detail?browser=DocZilla" +266[] = "0" +266[] = "retawq" +266[] = "http://retawq.sourceforge.net/" +266[] = "Arne Thomaßen" +266[] = "" +266[] = "terminal.png" +266[] = "/list-of-ua/browser-detail?browser=retawq" +267[] = "3" +267[] = "Jasmine" +267[] = "" +267[] = "SAMSUNG" +267[] = "http://www.samsung.com/" +267[] = "jasmine.png" +267[] = "/list-of-ua/browser-detail?browser=Jasmine" +268[] = "3" +268[] = "Opera Mini" +268[] = "http://www.operamini.com" +268[] = "Opera Software ASA." +268[] = "http://www.opera.com/" +268[] = "opera.png" +268[] = "/list-of-ua/browser-detail?browser=Opera Mini" +269[] = "0" +269[] = "Dooble" +269[] = "http://dooble.sourceforge.net/" +269[] = "Dooble team" +269[] = "" +269[] = "dooble.png" +269[] = "/list-of-ua/browser-detail?browser=Dooble" +270[] = "0" +270[] = "Madfox" +270[] = "http://en.wikipedia.org/wiki/Madfox" +270[] = "Robin Lu" +270[] = "" +270[] = "madfox.png" +270[] = "/list-of-ua/browser-detail?browser=Madfox" +271[] = "20" +271[] = "DownloadStudio" +271[] = "http://www.conceiva.com/products/downloadstudio/default.asp" +271[] = "Conceiva" +271[] = "http://www.conceiva.com/" +271[] = "downloadstudio.png" +271[] = "/list-of-ua/browser-detail?browser=DownloadStudio" +272[] = "20" +272[] = "WinPodder" +272[] = "http://winpodder.com/" +272[] = "Mike Versteeg" +272[] = "http://mikeversteeg.com/" +272[] = "winpodder.png" +272[] = "/list-of-ua/browser-detail?browser=WinPodder" +273[] = "0" +273[] = "Bunjalloo" +273[] = "http://code.google.com/p/quirkysoft/" +273[] = "quirkysoft" +273[] = "" +273[] = "bunjalloo.png" +273[] = "/list-of-ua/browser-detail?browser=Bunjalloo" +274[] = "10" +274[] = "LinkChecker" +274[] = "http://linkchecker.sourceforge.net/" +274[] = "Bastian Kleineidam" +274[] = "" +274[] = "LinkChecker.png" +274[] = "/list-of-ua/browser-detail?browser=LinkChecker" +275[] = "0" +275[] = "IE 8.0 (Compatibility View)" +275[] = "http://blogs.msdn.com/ie/archive/2008/08/27/introducing-compatibility-view.aspx" +275[] = "Microsoft Corporation." +275[] = "http://www.microsoft.com/" +275[] = "msie.png" +275[] = "/list-of-ua/browser-detail?browser=IE 8.0 (Compatibility View)" +276[] = "5" +276[] = "urlgrabber" +276[] = "http://linux.duke.edu/projects/urlgrabber/" +276[] = "Michael Stenner and Ryan Tomayko" +276[] = "" +276[] = "php.png" +276[] = "/list-of-ua/browser-detail?browser=urlgrabber" +277[] = "4" +277[] = "Spicebird" +277[] = "http://www.spicebird.com/" +277[] = "Synovel Technologies" +277[] = "http://www.synovel.com/" +277[] = "spicebird.png" +277[] = "/list-of-ua/browser-detail?browser=Spicebird" +278[] = "0" +278[] = "Firefox (Namoroka)" +278[] = "https://wiki.mozilla.org/Firefox/Namoroka" +278[] = "Mozilla Foundation" +278[] = "http://www.mozilla.org/" +278[] = "firefox.png" +278[] = "/list-of-ua/browser-detail?browser=Firefox (Namoroka)" +279[] = "0" +279[] = "rekonq" +279[] = "http://rekonq.sourceforge.net/" +279[] = "Andrea Diamantini" +279[] = "http://www.adjam.org/" +279[] = "rekonq.png" +279[] = "/list-of-ua/browser-detail?browser=rekonq" +280[] = "10" +280[] = "Multipage Validator" +280[] = "http://www.validator.ca/" +280[] = "Réseau Proze" +280[] = "http://www.proze.net/" +280[] = "MultipageValidator.png" +280[] = "/list-of-ua/browser-detail?browser=Multipage Validator" +281[] = "0" +281[] = "X-Smiles" +281[] = "http://www.xsmiles.org/" +281[] = "X-Smiles.org" +281[] = "" +281[] = "x-smiles.png" +281[] = "/list-of-ua/browser-detail?browser=X-Smiles" +282[] = "5" +282[] = "WinHTTP" +282[] = "http://msdn.microsoft.com/en-us/library/aa382925(VS.85).aspx" +282[] = "Microsoft Corporation." +282[] = "http://www.microsoft.com/" +282[] = "DLLicon.png" +282[] = "/list-of-ua/browser-detail?browser=WinHTTP" +283[] = "1" +283[] = "Xaldon WebSpider" +283[] = "http://www.xaldon.de/products_webspider.html" +283[] = "xaldon Technologies" +283[] = "http://www.xaldon.de/" +283[] = "XaldonWebSpider.png" +283[] = "/list-of-ua/browser-detail?browser=Xaldon WebSpider" +284[] = "20" +284[] = "Seznam WAP Proxy" +284[] = "http://www.smobil.cz/mobilni-vyhledavani" +284[] = "Seznam.cz, a.s." +284[] = "http://www.seznam.cz/" +284[] = "seznam.png" +284[] = "/list-of-ua/browser-detail?browser=Seznam WAP Proxy" +285[] = "20" +285[] = "Google Wireless Transcoder" +285[] = "http://google.com/gwt/n" +285[] = "Google" +285[] = "http://www.google.com/" +285[] = "feedfetcher-google.png" +285[] = "/list-of-ua/browser-detail?browser=Google Wireless Transcoder" +286[] = "20" +286[] = "Google Listen" +286[] = "http://listen.googlelabs.com/" +286[] = "Google" +286[] = "http://www.google.com/" +286[] = "google_listen.png" +286[] = "/list-of-ua/browser-detail?browser=Google Listen" +287[] = "5" +287[] = "Typhoeus" +287[] = "http://github.com/pauldix/typhoeus/tree/master" +287[] = "Paul Dix" +287[] = "http://www.pauldix.net/" +287[] = "typhoeus.png" +287[] = "/list-of-ua/browser-detail?browser=Typhoeus" +288[] = "0" +288[] = "OWB" +288[] = "http://www.sand-labs.org/owb" +288[] = "Sand-labs.org" +288[] = "http://www.sand-labs.org/" +288[] = "owb.png" +288[] = "/list-of-ua/browser-detail?browser=OWB" +289[] = "0" +289[] = "Browzar" +289[] = "http://www.browzar.com/" +289[] = "Browzar Ltd" +289[] = "" +289[] = "browzar.png" +289[] = "/list-of-ua/browser-detail?browser=Browzar" +290[] = "20" +290[] = "Claws Mail GtkHtml2 plugin" +290[] = "http://www.claws-mail.org/plugin.php?plugin=gtkhtml2" +290[] = "Colin Leroy" +290[] = "" +290[] = "Claws_Mail_GtkHtml_plugin.png" +290[] = "/list-of-ua/browser-detail?browser=Claws Mail GtkHtml2 plugin" +291[] = "20" +291[] = "Vuze" +291[] = "http://www.vuze.com/" +291[] = "Vuze, Inc" +291[] = "" +291[] = "vuze.png" +291[] = "/list-of-ua/browser-detail?browser=Vuze" +292[] = "0" +292[] = "GlobalMojo" +292[] = "http://globalmojo.com/" +292[] = "KPG VENTURES" +292[] = "http://www.kpgventures.com/" +292[] = "globalmojo.png" +292[] = "/list-of-ua/browser-detail?browser=GlobalMojo" +293[] = "18" +293[] = "GOM Player" +293[] = "http://www.gomlab.com/" +293[] = "GRETECH CORP." +293[] = "http://www.gretech.com/" +293[] = "GomPlayer.png" +293[] = "/list-of-ua/browser-detail?browser=GOM Player" +294[] = "5" +294[] = "Python-webchecker" +294[] = "http://www.python.org/doc/essays/ppt/sd99east/sld070.htm" +294[] = "Guido van Rossum/Sam Bayer" +294[] = "" +294[] = "pythonurllib.png" +294[] = "/list-of-ua/browser-detail?browser=Python-webchecker" +296[] = "10" +296[] = "W3C mobileOK Checker" +296[] = "http://validator.w3.org/mobile/" +296[] = "World Wide Web Consortium" +296[] = "http://www.w3.org/" +296[] = "w3.png" +296[] = "/list-of-ua/browser-detail?browser=W3C mobileOK Checker" +297[] = "20" +297[] = "Siege" +297[] = "http://www.joedog.org/index/siege-home" +297[] = "Joe Dog Software" +297[] = "http://www.joedog.org/" +297[] = "joedog.png" +297[] = "/list-of-ua/browser-detail?browser=Siege" +298[] = "1" +298[] = "iSiloXC" +298[] = "http://www.isilox.com/" +298[] = "DC & Co." +298[] = "http://www.isilox.com/" +298[] = "terminal.png" +298[] = "/list-of-ua/browser-detail?browser=iSiloXC" +299[] = "20" +299[] = "AB (Apache Bench)" +299[] = "http://en.wikipedia.org/wiki/ApacheBench" +299[] = "Apache Software Foundation" +299[] = "http://www.apache.org/" +299[] = "ab.png" +299[] = "/list-of-ua/browser-detail?browser=AB (Apache Bench)" +300[] = "10" +300[] = "anw LoadControl" +300[] = "http://webtool.anw.de/analyze/?ladezeit" +300[] = "ANW GmbH & Co. KG" +300[] = "http://www.anw.de/" +300[] = "anw.png" +300[] = "/list-of-ua/browser-detail?browser=anw LoadControl" +301[] = "10" +301[] = "anw HTMLChecker" +301[] = "http://webtool.topsubmit.de/analyze/?html" +301[] = "ANW GmbH & Co. KG" +301[] = "http://www.anw.de/" +301[] = "anw.png" +301[] = "/list-of-ua/browser-detail?browser=anw HTMLChecker" +302[] = "0" +302[] = "Edbrowse" +302[] = "http://edbrowse.sourceforge.net/" +302[] = "Karl Dahlke" +302[] = "" +302[] = "Edbrowse.png" +302[] = "/list-of-ua/browser-detail?browser=Edbrowse" +303[] = "20" +303[] = "muCommander" +303[] = "http://www.mucommander.com/" +303[] = "Maxence Bernard" +303[] = "" +303[] = "muCommander.png" +303[] = "/list-of-ua/browser-detail?browser=muCommander" +304[] = "18" +304[] = "XMPlay" +304[] = "http://www.xmplay.com/" +304[] = "un4seen developments" +304[] = "http://www.un4seen.com/" +304[] = "XMPlay.png" +304[] = "/list-of-ua/browser-detail?browser=XMPlay" +305[] = "15" +305[] = "NFReader" +305[] = "http://www.gaijin.at/dlnfreader.php" +305[] = "Gaijin.at" +305[] = "http://www.gaijin.at/" +305[] = "NFReader.png" +305[] = "/list-of-ua/browser-detail?browser=NFReader" +306[] = "3" +306[] = "uZard Web" +306[] = "http://www.uzard.com/" +306[] = "Logicplant Co." +306[] = "http://www.logicplant.com/" +306[] = "uzard.png" +306[] = "/list-of-ua/browser-detail?browser=uZard Web" +307[] = "5" +307[] = "Indy Library" +307[] = "http://www.indyproject.org/" +307[] = "Chad Z. Hower (Kudzu) and the Indy Pit Crew" +307[] = "" +307[] = "DLLicon.png" +307[] = "/list-of-ua/browser-detail?browser=Indy Library" +308[] = "0" +308[] = "Multi-Browser XP" +308[] = "http://www.multibrowser.de/" +308[] = "Binh Nguyen-Huu" +308[] = "" +308[] = "Multi-BrowserXP.png" +308[] = "/list-of-ua/browser-detail?browser=Multi-Browser XP" +309[] = "10" +309[] = "LinkWalker" +309[] = "" +309[] = "BDProtect Inc" +309[] = "http://www.brandprotect.com/" +309[] = "LinkWalker.png" +309[] = "/list-of-ua/browser-detail?browser=LinkWalker" +310[] = "0" +310[] = "NetPositive" +310[] = "http://en.wikipedia.org/wiki/NetPositive" +310[] = "Be Inc." +310[] = "http://en.wikipedia.org/wiki/Be_Inc." +310[] = "netpositive.png" +310[] = "/list-of-ua/browser-detail?browser=NetPositive" +311[] = "20" +311[] = "Radio Downloader" +311[] = "http://www.nerdoftheherd.com/tools/radiodld/" +311[] = "Matt Robinson" +311[] = "http://www.nerdoftheherd.com/" +311[] = "RadioDownloader.png" +311[] = "/list-of-ua/browser-detail?browser=Radio Downloader" +312[] = "1" +312[] = "WebStripper" +312[] = "http://webstripper.net/" +312[] = "Mike Sutton" +312[] = "http://solentsoftware.com/" +312[] = "webstripper.png" +312[] = "/list-of-ua/browser-detail?browser=WebStripper" +313[] = "20" +313[] = "Cyberduck" +313[] = "http://cyberduck.ch/" +313[] = "David Kocher" +313[] = "dkocher.name" +313[] = "Cyberduck.png" +313[] = "/list-of-ua/browser-detail?browser=Cyberduck" +314[] = "0" +314[] = "WorldWideWeb" +314[] = "http://www.w3.org/People/Berners-Lee/WorldWideWeb" +314[] = "Tim Berners-Lee" +314[] = "http://www.w3.org/People/Berners-Lee/Overview.html" +314[] = "1stBrowser.png" +314[] = "/list-of-ua/browser-detail?browser=WorldWideWeb" +315[] = "20" +315[] = "iVideo" +315[] = "http://tinyurl.com/DownloadiVideo" +315[] = "ZETZ mobile" +315[] = "http://www.zetzmobile.com/" +315[] = "iVideo.png" +315[] = "/list-of-ua/browser-detail?browser=iVideo" +316[] = "15" +316[] = "RSS Popper" +316[] = "http://www.rsspopper.com/" +316[] = "Paradisoft" +316[] = "http://www.paradisoft.com/" +316[] = "rss.png" +316[] = "/list-of-ua/browser-detail?browser=RSS Popper" +317[] = "20" +317[] = "Jamcast" +317[] = "http://www.sdstechnologies.com/" +317[] = "Software Development Solutions, Inc." +317[] = "http://www.sdstechnologies.com/" +317[] = "Jamcast.png" +317[] = "/list-of-ua/browser-detail?browser=Jamcast" +318[] = "0" +318[] = "Comodo Dragon" +318[] = "http://www.comodo.com/home/internet-security/browser.php" +318[] = "Comodo Group, Inc." +318[] = "http://www.comodo.com/" +318[] = "Comodo_Dragon.png" +318[] = "/list-of-ua/browser-detail?browser=Comodo Dragon" +319[] = "1" +319[] = "SuperBot" +319[] = "http://www.sparkleware.com/superbot/index.html" +319[] = "Sparkleware" +319[] = "http://www.sparkleware.com/" +319[] = "SuperBot.png" +319[] = "/list-of-ua/browser-detail?browser=SuperBot" +320[] = "0" +320[] = "My Internet Browser" +320[] = "http://myinternetbrowser.webove-stranky.org/" +320[] = "Media WebPublishing" +320[] = "" +320[] = "MyInternetBrowser.png" +320[] = "/list-of-ua/browser-detail?browser=My Internet Browser" +321[] = "3" +321[] = "Opera Mobile" +321[] = "http://www.opera.com/mobile/" +321[] = "Opera Software ASA." +321[] = "http://www.opera.com/" +321[] = "opera.png" +321[] = "/list-of-ua/browser-detail?browser=Opera Mobile" +322[] = "0" +322[] = "Kirix Strata" +322[] = "http://www.kirix.com/" +322[] = "Kirix Corporation" +322[] = "http://www.kirix.com/about-us.html" +322[] = "kirix-strata.png" +322[] = "/list-of-ua/browser-detail?browser=Kirix Strata" +323[] = "0" +323[] = "TT Explorer" +323[] = "http://tt.qq.com/" +323[] = "Tencent" +323[] = "http://tt.qq.com/" +323[] = "tt_explorer.png" +323[] = "/list-of-ua/browser-detail?browser=TT Explorer" +324[] = "0" +324[] = "LBrowser" +324[] = "http://wiki.freespire.org/index.php/Web_Browser" +324[] = "Xandros Incorporated" +324[] = "http://www.xandros.com/" +324[] = "LBrowser.png" +324[] = "/list-of-ua/browser-detail?browser=LBrowser" +325[] = "4" +325[] = "Outlook 2007" +325[] = "http://office.microsoft.com/outlook" +325[] = "Microsoft Corporation." +325[] = "http://www.microsoft.com/" +325[] = "outlook-2007.png" +325[] = "/list-of-ua/browser-detail?browser=Outlook 2007" +326[] = "4" +326[] = "Outlook 2010" +326[] = "http://en.wikipedia.org/wiki/Microsoft_Office_2010" +326[] = "Microsoft Corporation." +326[] = "http://www.microsoft.com/" +326[] = "outlook-2010.png" +326[] = "/list-of-ua/browser-detail?browser=Outlook 2010" +327[] = "4" +327[] = "Windows Live Mail" +327[] = "http://download.live.com/wlmail" +327[] = "Microsoft Corporation." +327[] = "http://www.microsoft.com/" +327[] = "Windows_Live_Mail.png" +327[] = "/list-of-ua/browser-detail?browser=Windows Live Mail" +328[] = "0" +328[] = "Tjusig" +328[] = "http://www.tjusig.cz/" +328[] = "Lukáš Ingr" +328[] = "" +328[] = "tjusig.png" +328[] = "/list-of-ua/browser-detail?browser=Tjusig" +329[] = "0" +329[] = "SiteKiosk" +329[] = "http://www.sitekiosk.com/SiteKiosk/Default.aspx" +329[] = "PROVISIO GmbH / LLC" +329[] = "http://www.provisio.com/" +329[] = "sitekiosk.png" +329[] = "/list-of-ua/browser-detail?browser=SiteKiosk" +330[] = "4" +330[] = "The Bat!" +330[] = "http://www.ritlabs.com/en/products/thebat/" +330[] = "RITLabs SRL" +330[] = "http://www.ritlabs.com/" +330[] = "thebat.png" +330[] = "/list-of-ua/browser-detail?browser=The Bat!" +331[] = "20" +331[] = "Novell BorderManager" +331[] = "http://www.novell.com/products/bordermanager/" +331[] = "Novell, Inc" +331[] = "http://www.novell.com/" +331[] = "Novell_BorderManager.png" +331[] = "/list-of-ua/browser-detail?browser=Novell BorderManager" +332[] = "4" +332[] = "Shredder" +332[] = "http://www.mozillamessaging.com/en-US/thunderbird/3.0a1/releasenotes/" +332[] = "Mozilla Foundation" +332[] = "http://www.mozilla.org/" +332[] = "thunderbird.png" +332[] = "/list-of-ua/browser-detail?browser=Shredder" +333[] = "18" +333[] = "Public Radio Player" +333[] = "http://www.publicradioplayer.org/" +333[] = "Public Radio Exchange (PRX)" +333[] = "http://www.prx.org/" +333[] = "PRP.png" +333[] = "/list-of-ua/browser-detail?browser=Public Radio Player" +334[] = "15" +334[] = "Rss Bandit" +334[] = "http://rssbandit.org/" +334[] = "Infragistics, Inc." +334[] = "http://www.infragistics.com/" +334[] = "RssBandit.png" +334[] = "/list-of-ua/browser-detail?browser=Rss Bandit" +335[] = "4" +335[] = "Postbox" +335[] = "http://www.postbox-inc.com/" +335[] = "Postbox, Inc." +335[] = "http://www.postbox-inc.com/" +335[] = "postbox.png" +335[] = "/list-of-ua/browser-detail?browser=Postbox" +336[] = "10" +336[] = "2Bone LinkChecker" +336[] = "http://www.2bone.com/links/linkchecker.shtml" +336[] = "2Bone" +336[] = "http://www.2bone.com/" +336[] = "2bone.png" +336[] = "/list-of-ua/browser-detail?browser=2Bone LinkChecker" +337[] = "10" +337[] = "Checkbot" +337[] = "http://degraaff.org/checkbot/" +337[] = "Hans de Graaff" +337[] = "http://degraaff.org/" +337[] = "perl.png" +337[] = "/list-of-ua/browser-detail?browser=Checkbot" +338[] = "4" +338[] = "GcMail" +338[] = "http://www.gcmail.de/" +338[] = "Monika Verse" +338[] = "" +338[] = "gcmail.png" +338[] = "/list-of-ua/browser-detail?browser=GcMail" +339[] = "0" +339[] = "Swiftweasel" +339[] = "http://swiftweasel.tuxfamily.org/" +339[] = "SticKK" +339[] = "" +339[] = "swiftweasel.png" +339[] = "/list-of-ua/browser-detail?browser=Swiftweasel" +340[] = "15" +340[] = "Fastladder FeedFetcher" +340[] = "http://fastladder.com/" +340[] = "livedoor Co.,Ltd. " +340[] = "http://corp.livedoor.com/" +340[] = "fastladderFeedFetcher.png" +340[] = "/list-of-ua/browser-detail?browser=Fastladder FeedFetcher" +341[] = "0" +341[] = "Firefox (Lorentz)" +341[] = "http://www.mozilla.com/en-US/firefox/lorentz/" +341[] = "Mozilla Foundation" +341[] = "http://www.mozilla.org/" +341[] = "firefox.png" +341[] = "/list-of-ua/browser-detail?browser=Firefox (Lorentz)" +342[] = "18" +342[] = "Pocket Tunes" +342[] = "http://www.pocket-tunes.com/" +342[] = "NormSoft, Inc." +342[] = "http://www.normsoft.com/" +342[] = "PocketTunes.png" +342[] = "/list-of-ua/browser-detail?browser=Pocket Tunes" +343[] = "15" +343[] = "SharpReader" +343[] = "http://www.sharpreader.net/" +343[] = "Luke Hutteman" +343[] = "http://www.hutteman.com/" +343[] = "sharpreader.png" +343[] = "/list-of-ua/browser-detail?browser=SharpReader" +344[] = "15" +344[] = "YeahReader" +344[] = "http://www.yeahreader.com/" +344[] = "ExtraLabs Software" +344[] = "http://www.extralabs.net/" +344[] = "YeahReader.png" +344[] = "/list-of-ua/browser-detail?browser=YeahReader" +345[] = "0" +345[] = "Pale Moon" +345[] = "http://www.palemoon.org/" +345[] = "Moonchild Productions" +345[] = "http://www.moonchildproductions.net/" +345[] = "pale_moon.png" +345[] = "/list-of-ua/browser-detail?browser=Pale Moon" +346[] = "20" +346[] = "Holmes" +346[] = "http://www.ucw.cz/holmes/" +346[] = "Martin MareÅ¡ and Robert Å palek" +346[] = "" +346[] = "holmes.png" +346[] = "/list-of-ua/browser-detail?browser=Holmes" +347[] = "20" +347[] = "Google Earth" +347[] = "http://earth.google.com/" +347[] = "Google Inc." +347[] = "http://google.com/" +347[] = "google_earth.png" +347[] = "/list-of-ua/browser-detail?browser=Google Earth" +348[] = "5" +348[] = "ROME library" +348[] = "https://rome.dev.java.net/" +348[] = "A. Abdelnur, P. Chanezon and E. Chien" +348[] = "" +348[] = "ROME_lib.png" +348[] = "/list-of-ua/browser-detail?browser=ROME library" +349[] = "15" +349[] = "Akregator" +349[] = "http://akregator.kde.org/" +349[] = "" +349[] = "s" +349[] = "akregator.png" +349[] = "/list-of-ua/browser-detail?browser=Akregator" +350[] = "0" +350[] = "Mini Browser" +350[] = "http://dmkho.tripod.com/" +350[] = "DMKHO" +350[] = "" +350[] = "minibrowser.png" +350[] = "/list-of-ua/browser-detail?browser=Mini Browser" +351[] = "0" +351[] = "Espial TV Browser" +351[] = "http://www.espial.com/products/evo_browser/" +351[] = "Espial Group" +351[] = "http://www.espial.com/" +351[] = "EspialTVBrowser.png" +351[] = "/list-of-ua/browser-detail?browser=Espial TV Browser" +352[] = "0" +352[] = "UltraBrowser " +352[] = "http://www.ultrabrowser.com/" +352[] = "UltraBrowser.com, Inc." +352[] = "" +352[] = "UltraBrowser.png" +352[] = "/list-of-ua/browser-detail?browser=UltraBrowser " +353[] = "0" +353[] = "BrowseX" +353[] = "http://pdqi.com/browsex/" +353[] = "Peter MacDonald" +353[] = "http://pdqi.com/" +353[] = "browsex.png" +353[] = "/list-of-ua/browser-detail?browser=BrowseX" +354[] = "3" +354[] = "Android Webkit" +354[] = "http://developer.android.com/reference/android/webkit/package-summary.html" +354[] = "Google Inc." +354[] = "http://www.google.com/" +354[] = "androidWebkit.png" +354[] = "/list-of-ua/browser-detail?browser=Android Webkit" +355[] = "0" +355[] = "Weltweitimnetz Browser" +355[] = "http://weltweitimnetz.de/software/Browser.en.page" +355[] = "Philipp Ruppel" +355[] = "http://weltweitimnetz.de/" +355[] = "WeltweitimnetzBrowser.png" +355[] = "/list-of-ua/browser-detail?browser=Weltweitimnetz Browser" +356[] = "4" +356[] = "PocoMail" +356[] = "http://www.pocomail.com/" +356[] = "Poco Systems Inc" +356[] = "http://www.pocosystems.com/" +356[] = "pocomail.png" +356[] = "/list-of-ua/browser-detail?browser=PocoMail" +357[] = "0" +357[] = "Element Browser" +357[] = "http://www.elementsoftware.co.uk/software/elementbrowser/" +357[] = "Element Software UK." +357[] = "http://www.elementsoftware.co.uk/" +357[] = "elementbrowser.png" +357[] = "/list-of-ua/browser-detail?browser=Element Browser" +358[] = "0" +358[] = "SlimBrowser" +358[] = "http://slimbrowser.flashpeak.com/" +358[] = "FlashPeak Inc." +358[] = "http://www.flashpeak.com/" +358[] = "slimbrowser.png" +358[] = "/list-of-ua/browser-detail?browser=SlimBrowser" +359[] = "20" +359[] = "LeechCraft" +359[] = "http://leechcraft.org/" +359[] = "" +359[] = "" +359[] = "LeechCraft.png" +359[] = "/list-of-ua/browser-detail?browser=LeechCraft" +360[] = "5" +360[] = "HTTP_Request2" +360[] = "http://pear.php.net/package/http_request2" +360[] = "" +360[] = "" +360[] = "php.png" +360[] = "/list-of-ua/browser-detail?browser=HTTP_Request2" +361[] = "0" +361[] = "Conkeror" +361[] = "http://conkeror.org/" +361[] = "Mozilla Foundation" +361[] = "http://www.mozilla.org/" +361[] = "conkeror.png" +361[] = "/list-of-ua/browser-detail?browser=Conkeror" +362[] = "3" +362[] = "Dolphin" +362[] = "http://www.dolphin-browser.com/" +362[] = "Samsung" +362[] = "http://www.samsung.com/" +362[] = "dolphin.png" +362[] = "/list-of-ua/browser-detail?browser=Dolphin" +363[] = "15" +363[] = "Netvibes feed reader" +363[] = "" +363[] = "Netvibes team" +363[] = "http://about.netvibes.com/" +363[] = "netvibes.png" +363[] = "/list-of-ua/browser-detail?browser=Netvibes feed reader" +364[] = "5" +364[] = "Chilkat HTTP .NET" +364[] = "http://www.chilkatsoft.com/HttpDotNet.asp" +364[] = "Chilkat Software, Inc." +364[] = "http://www.chilkatsoft.com/" +364[] = "chilkat.png" +364[] = "/list-of-ua/browser-detail?browser=Chilkat HTTP .NET" +365[] = "5" +365[] = "IXR lib" +365[] = "http://scripts.incutio.com/xmlrpc/" +365[] = "Incutio Ltd." +365[] = "http://www.incutio.com/" +365[] = "Incutio.png" +365[] = "/list-of-ua/browser-detail?browser=IXR lib" +366[] = "20" +366[] = "Web-sniffer" +366[] = "http://web-sniffer.net/" +366[] = "Lingo4you GbR" +366[] = "http://www.lingo4u.de/" +366[] = "Web-sniffer.png" +366[] = "/list-of-ua/browser-detail?browser=Web-sniffer" +367[] = "20" +367[] = "Atomic Email Hunter" +367[] = "http://www.massmailsoftware.com/extractweb/" +367[] = "AtomPark Software Inc." +367[] = "http://www.atompark.com/" +367[] = "Atomic_Email_Hunter.png" +367[] = "/list-of-ua/browser-detail?browser=Atomic Email Hunter" +368[] = "20" +368[] = "iGetter" +368[] = "http://www.igetter.net/" +368[] = "Presenta Ltd." +368[] = "" +368[] = "iGetter.png" +368[] = "/list-of-ua/browser-detail?browser=iGetter" +369[] = "1" +369[] = "webfetch" +369[] = "http://tony.aiu.to/sa/webfetch/" +369[] = "Tony Aiuto" +369[] = "http://tony.aiu.to/" +369[] = "terminal.png" +369[] = "/list-of-ua/browser-detail?browser=webfetch" +370[] = "20" +370[] = "Apache Synapse" +370[] = "http://synapse.apache.org/" +370[] = "Apache Software Foundation" +370[] = "http://www.apache.org/" +370[] = "apache.png" +370[] = "/list-of-ua/browser-detail?browser=Apache Synapse" +371[] = "0" +371[] = "lolifox" +371[] = "http://lolifox.com/" +371[] = "Atachi Hayashime" +371[] = "" +371[] = "lolifox.png" +371[] = "/list-of-ua/browser-detail?browser=lolifox" +372[] = "0" +372[] = "SkipStone" +372[] = "http://www.muhri.net/skipstone/" +372[] = "Maher Awamy" +372[] = "http://www.muhri.net/" +372[] = "skipStone.png" +372[] = "/list-of-ua/browser-detail?browser=SkipStone" +373[] = "20" +373[] = "Powermarks" +373[] = "http://www.kaylon.com/power.html" +373[] = "Kaylon Technologies Inc." +373[] = "http://www.kaylon.com/" +373[] = "powermarks.png" +373[] = "/list-of-ua/browser-detail?browser=Powermarks" +374[] = "15" +374[] = "Safari RSS reader" +374[] = "http://www.apple.com/safari/" +374[] = "Apple Inc." +374[] = "http://www.apple.com/" +374[] = "rss.png" +374[] = "/list-of-ua/browser-detail?browser=Safari RSS reader" +375[] = "20" +375[] = "Google Friend Connect" +375[] = "http://www.google.com/friendconnect/" +375[] = "Google Inc." +375[] = "http://www.google.com/" +375[] = "google_friend_connect.png" +375[] = "/list-of-ua/browser-detail?browser=Google Friend Connect" +376[] = "15" +376[] = "Feed Viewer" +376[] = "http://feedviewer.codeplex.com/" +376[] = "vasek7" +376[] = "http://www.codeplex.com/site/users/view/vasek7" +376[] = "" +376[] = "/list-of-ua/browser-detail?browser=Feed Viewer" +377[] = "0" +377[] = "RockMelt" +377[] = "http://www.rockmelt.com/" +377[] = "Tim Howes and Eric Vishria" +377[] = "" +377[] = "rockmelt.png" +377[] = "/list-of-ua/browser-detail?browser=RockMelt" +378[] = "0" +378[] = "Epic" +378[] = "http://www.epicbrowser.com/" +378[] = "Hidden Reflex" +378[] = "http://www.hiddenreflex.com/" +378[] = "epic.png" +378[] = "/list-of-ua/browser-detail?browser=Epic" +379[] = "0" +379[] = "InternetSurfboard" +379[] = "http://inetsurfboard.sourceforge.net/" +379[] = "Philipp Ruppel" +379[] = "" +379[] = "internetSurfboard.png" +379[] = "/list-of-ua/browser-detail?browser=InternetSurfboard" +380[] = "0" +380[] = "Vonkeror" +380[] = "http://zzo38computer.cjb.net/vonkeror/" +380[] = "zzo38" +380[] = "http://zzo38computer.cjb.net/" +380[] = "conkeror.png" +380[] = "/list-of-ua/browser-detail?browser=Vonkeror" +381[] = "15" +381[] = "IE RSS reader" +381[] = "http://en.wikipedia.org/wiki/Windows_RSS_Platform" +381[] = "Microsoft" +381[] = "http://www.microsoft.com/" +381[] = "rss.png" +381[] = "/list-of-ua/browser-detail?browser=IE RSS reader" +382[] = "15" +382[] = "Trileet NewsRoom" +382[] = "http://feedmonger.blogspot.com/" +382[] = "Trileet Inc." +382[] = "http://www.trileet.com/" +382[] = "rss.png" +382[] = "/list-of-ua/browser-detail?browser=Trileet NewsRoom" +383[] = "10" +383[] = "Validator.nu" +383[] = "http://validator.nu/" +383[] = "Henri Sivonen" +383[] = "http://hsivonen.iki.fi/author/" +383[] = "validator_nu.png" +383[] = "/list-of-ua/browser-detail?browser=Validator.nu" +384[] = "5" +384[] = "Zend_Http_Client" +384[] = "http://framework.zend.com/manual/en/zend.http.html" +384[] = "Zend Technologies Ltd." +384[] = "http://www.zend.com/" +384[] = "zend_http_client.png" +384[] = "/list-of-ua/browser-detail?browser=Zend_Http_Client" +385[] = "3" +385[] = "Skyfire" +385[] = "http://www.skyfire.com/" +385[] = "Skyfire Labs, Inc." +385[] = "http://www.skyfire.com/about" +385[] = "skyfire.png" +385[] = "/list-of-ua/browser-detail?browser=Skyfire" +386[] = "3" +386[] = "GO Browser" +386[] = "http://www.gobrowser.cn/" +386[] = "GO Dev Team" +386[] = "" +386[] = "go_browser.png" +386[] = "/list-of-ua/browser-detail?browser=GO Browser" +387[] = "0" +387[] = "Surf" +387[] = "http://surf.suckless.org/" +387[] = "suckless.org" +387[] = "http://suckless.org/" +387[] = "surf.png" +387[] = "/list-of-ua/browser-detail?browser=Surf" +388[] = "20" +388[] = "iGooMap" +388[] = "http://www.pointworks.de/software/igoomap/index.php" +388[] = "PointWorks.de" +388[] = "http://www.pointworks.de/" +388[] = "igoomap.png" +388[] = "/list-of-ua/browser-detail?browser=iGooMap" +389[] = "18" +389[] = "iTunes" +389[] = "http://www.apple.com/itunes/" +389[] = "Apple Inc." +389[] = "http://www.apple.com/" +389[] = "itunes.png" +389[] = "/list-of-ua/browser-detail?browser=iTunes" +390[] = "0" +390[] = "BlackHawk" +390[] = "http://www.netgate.sk/blackhawk/help/welcome-to-blackhawk-web-browser.html" +390[] = "NETGATE Technologies s.r.o. " +390[] = "http://www.netgate.sk/" +390[] = "blackhawk.png" +390[] = "/list-of-ua/browser-detail?browser=BlackHawk" +392[] = "3" +392[] = "Kindle Browser" +392[] = "http://en.wikipedia.org/wiki/Amazon_Kindle" +392[] = "Amazon.com" +392[] = "http://www.amazon.com/" +392[] = "kindle.png" +392[] = "/list-of-ua/browser-detail?browser=Kindle Browser" +393[] = "20" +393[] = "Microsoft Office Existence Discovery" +393[] = "http://blogs.msdn.com/b/vsofficedeveloper/archive/2008/03/11/office-existence-discovery-protocol.aspx" +393[] = "Microsoft Corporation." +393[] = "http://www.microsoft.com/" +393[] = "webdav.png" +393[] = "/list-of-ua/browser-detail?browser=Microsoft Office Existence Discovery" +394[] = "3" +394[] = "Mobile Safari" +394[] = "http://en.wikipedia.org/wiki/Safari_%28web_browser%29" +394[] = "Apple Inc." +394[] = "http://www.apple.com/" +394[] = "safari.png" +394[] = "/list-of-ua/browser-detail?browser=Mobile Safari" +395[] = "20" +395[] = "BrownRecluse" +395[] = "http://softbytelabs.com/us/br/index.html" +395[] = "SoftByte Labs, Inc." +395[] = "http://softbytelabs.com/" +395[] = "BrownRecluse.png" +395[] = "/list-of-ua/browser-detail?browser=BrownRecluse" +396[] = "20" +396[] = "BookmarkTracker" +396[] = "http://www.bookmarktracker.com/" +396[] = "BookmarkTracker.com, Inc." +396[] = "" +396[] = "BookmarkTracker.png" +396[] = "/list-of-ua/browser-detail?browser=BookmarkTracker" +397[] = "5" +397[] = "BinGet" +397[] = "http://www.bin-co.com/php/scripts/load/" +397[] = "Binny VA" +397[] = "http://binnyva.com/" +397[] = "php.png" +397[] = "/list-of-ua/browser-detail?browser=BinGet" +398[] = "0" +398[] = "Feedreader" +398[] = "http://www.feedreader.com/download" +398[] = "i-Systems Inc." +398[] = "" +398[] = "" +398[] = "/list-of-ua/browser-detail?browser=Feedreader" +399[] = "0" +399[] = "Webian Shell" +399[] = "http://webian.org/shell/" +399[] = "Ben Francis" +399[] = "http://tola.me.uk/" +399[] = "webianshell.png" +399[] = "/list-of-ua/browser-detail?browser=Webian Shell" +400[] = "0" +400[] = "Kylo" +400[] = "http://kylo.tv/" +400[] = "Hillcrest Laboratories" +400[] = "http://hillcrestlabs.com/" +400[] = "kylo.png" +400[] = "/list-of-ua/browser-detail?browser=Kylo" +401[] = "0" +401[] = "Fireweb Navigator" +401[] = "http://www.arsslensoft.tk/?q=node/7" +401[] = "Arsslensoft Foundation" +401[] = "http://www.arsslensoft.fi5.us/" +401[] = "Fireweb.png" +401[] = "/list-of-ua/browser-detail?browser=Fireweb Navigator" +402[] = "5" +402[] = "Evolution/Camel.Stream" +402[] = "http://live.gnome.org/Evolution/Camel.Stream" +402[] = "GNOME Project" +402[] = "http://www.gnome.org/" +402[] = "DLLicon.png" +402[] = "/list-of-ua/browser-detail?browser=Evolution/Camel.Stream" +[browser_type] +; browser_type_id[] = "Browser type" +0[] = "Browser" +1[] = "Offline Browser" +3[] = "Mobile Browser" +4[] = "Email client" +5[] = "Library" +6[] = "Wap Browser" +10[] = "Validator" +15[] = "Feed Reader" +18[] = "Multimedia Player" +20[] = "Other" +50[] = "Useragent Anonymizer" +[browser_reg] +; browser_reg_id[] = "Browser regstring" +; browser_reg_id[] = "Browser id" +49[] = "/mozilla.*Blazer\/([0-9a-z\+\-\.]+)/si" +49[] = "43" +69[] = "/mozilla.*rv:[0-9\.]+.*gecko\/[0-9]+.*firefox\/([0-9a-z\+\-\.]+).*swiftfox/si" +69[] = "61" +94[] = "/^Mozilla.*Thunderbird\/([0-9a-zA-Z\.]+)/si" +94[] = "79" +149[] = "/mozilla.*rv:[0-9\.]+.*gecko.*kapiko\/([0-9a-z\+\-\.]+).*/si" +149[] = "119" +197[] = "/IEMobile ([0-9\.]+)/si" +197[] = "157" +218[] = "/Miro\/([0-9a-z\-\.]+).*http:\/\/www\.getmiro\.com\//si" +218[] = "175" +359[] = "/\/szn-mobile-transcoder/si" +359[] = "284" +361[] = "/Google Wireless Transcoder/si" +361[] = "285" +414[] = "/^Mozilla.*Shredder\/([0-9a-zA-Z\.]+)/si" +414[] = "332" +407[] = "/^Mozilla.*MSIE.*MSOffice 12/si" +407[] = "325" +408[] = "/^Mozilla.*MSIE.*MSOffice 14/si" +408[] = "326" +5[] = "/mozilla.*gecko\/[0-9]+.*epiphany\/([0-9a-z\+\-\.]+).*/si" +5[] = "5" +59[] = "/mozilla.*Lunascape\/([0-9a-z\+\-\.]+).*/si" +59[] = "52" +117[] = "/Blazer ([0-9\.]+)/si" +117[] = "43" +157[] = "/mozilla.*applewebkit.*arora\/([0-9a-z\+\-\.]+).*/si" +157[] = "126" +175[] = "/^W3C-checklink\/([0-9a-z\+\-\.]+).*/si" +175[] = "138" +179[] = "/Bolt\/([0-9\.]+)/si" +179[] = "141" +180[] = "/Demeter\/([0-9\.]+)/si" +180[] = "142" +184[] = "/mozilla.*applewebkit.*fluid\/([0-9a-z\+\-\.]+).*/si" +184[] = "145" +203[] = "/Hv3\/([0-9a-z\.])/si" +203[] = "160" +230[] = "/Cheshire\/([0-9a-z\.]+)/si" +230[] = "185" +232[] = "/mozilla.*rv:[0-9\.]+.*gecko.*CometBird\/([0-9a-z\+\-\.]+).*/si" +232[] = "187" +233[] = "/mozilla.*rv:[0-9\.]+.*gecko.*IceCat\/([0-9a-z\+\-\.]+).*/si" +233[] = "188" +234[] = "/mozilla.*applewebkit.*Stainless\/([0-9a-z\+\-\.]+).*safari/si" +234[] = "189" +235[] = "/mozilla.*rv:[0-9\.]+.*gecko.*Prism\/([0-9a-z\+\-\.]+).*/si" +235[] = "190" +266[] = "/^Mozilla\/.*webOS\/[0-9\.]+.*AppleWebKit.*Pre\/([0-9\.]+)$/si" +266[] = "211" +322[] = "/^Mozilla\/.*Mobile Content Viewer\/([0-9\.]+).*NetFront/si" +322[] = "253" +396[] = "/mozilla.*Comodo_Dragon\/([0-9a-z\+\-\.]+).*/si" +396[] = "318" +403[] = "/^Mozilla.*Gecko.*Strata\/([0-9\.]+)/si" +403[] = "322" +406[] = "/^Mozilla.*rv:[0-9\.]+.*Gecko.*Firefox.*LBrowser\/([0-9a-z\-\.]+)/si" +406[] = "324" +409[] = "/^Outlook-Express\/7\.0 \(MSIE 7\.0; Windows/si" +409[] = "327" +439[] = "/^Mozilla.*Windows.*AppleWebKit.*MiniBrowser\/([0-9\.]+)/si" +439[] = "350" +446[] = "/^Mozilla.*AppleWebKit.*Element Browser ([0-9\.]+)/si" +446[] = "357" +489[] = "/^Outlook-Express\/7\.0 \(MSIE 6\.0; Windows/si" +489[] = "327" +494[] = "/^Mozilla\/.*Gecko\/.*Firefox\/.*Kylo\/([0-9\.]+)$/si" +494[] = "400" +495[] = "/^Outlook-Express\/7\.0 \(MSIE 8; Windows/si" +495[] = "327" +278[] = "/^Mozilla\/.*AppleWebKit.*NetNewsWire\/([0-9a-z\.]+)$/si" +278[] = "222" +410[] = "/^Mozilla.*MSIE.*Windows.*Tjusig ([0-9\.]+)/si" +410[] = "328" +411[] = "/^Mozilla.*MSIE.*Windows.*SiteKiosk ([0-9\.]+)/s" +411[] = "329" +444[] = "/Mozilla.*AppleWebKit.*WeltweitimnetzBrowser\/([0-9\.]+)/si" +444[] = "355" +476[] = "/^Mozilla.*AppleWebKit.*Skyfire\/([0-9\.]+)/si" +476[] = "385" +7[] = "/mozilla.*gecko\/[0-9]+.*flock\/([0-9a-z\+\-\.]+).*/si" +7[] = "7" +162[] = "/mozilla.*applewebkit.*iron\/([0-9a-z\+\-\.]+).*/si" +162[] = "130" +22[] = "/mozilla.*applewebkit.*shiira\/([0-9a-z\+\-\.]+).*safari/si" +22[] = "21" +54[] = "/mozilla.*rv:[0-9\.]+.*gecko\/[0-9]+.*IceWeasel\/([0-9a-z\+\-\.]+).*/si" +54[] = "47" +114[] = "/^Mozilla.*AppleWebKit.*Shiira\/([0-9a-zA-z\.\-]+)/si" +114[] = "21" +163[] = "/mozilla..*lobo\/([0-9a-z\+\-\.]+).*/si" +163[] = "131" +182[] = "/mozilla.*applewebkit.*shiira.*safari/si" +182[] = "21" +183[] = "/mozilla.*firefox.*orca\/([0-9a-z\+\-\.]+).*/si" +183[] = "144" +314[] = "/^Mozilla\/.*Gecko.* Firefox.*Wyzo\/([0-9a-z\.]+)/si" +314[] = "245" +340[] = "/Opera\/.*Opera Mini\/([0-9\.]+)/si" +340[] = "268" +369[] = "/mozilla.*rv:[0-9\.]+.*gecko.*GlobalMojo\/([0-9a-z\+\-\.]+).*/si" +369[] = "292" +431[] = "/mozilla.*rv:[0-9\.]+.*gecko.*Palemoon\/([0-9a-z\+\-\.]+).*/si" +431[] = "345" +434[] = "/mozilla.*flock\/([0-9\.]+).*chrome/si" +434[] = "7" +436[] = "/mozilla.*rv:[0-9\.]+.*gecko.*myibrow\/([0-9a-z\.]+)/si" +436[] = "320" +440[] = "/^Mozilla.*Escape ([0-9\.]+)/si" +440[] = "351" +441[] = "/^Mozilla.*Windows.*UltraBrowser ([0-9\.]+)/si" +441[] = "352" +442[] = "/^Mozilla.*BrowseX \(([0-9\.]+)/si" +442[] = "353" +463[] = "/^Mozilla\/.*Gecko.*lolifox\/([0-9\.]+)/si" +463[] = "371" +468[] = "/Mozilla.*AppleWebKit.*RockMelt\/([0-9a-z\.]+)/si" +468[] = "377" +469[] = "/^Mozilla.*rv:[0-9\.]+.*gecko\/[0-9]+.*Epic\/([0-9\.]+)/si" +469[] = "378" +470[] = "/Mozilla.*AppleWebKit.*InternetSurfboard\/([0-9\.a-z]+)/si" +470[] = "379" +471[] = "/^Mozilla.*Gecko.*Vonkeror\/([0-9\.]+)/si" +471[] = "380" +484[] = "/^Mozilla.*WebKi.*BlackHawk\/([0-9\.]+).*Chrome/si" +484[] = "390" +496[] = "/^Mozilla\/.*Treco.*Fireweb Navigator\/([0-9a-z\.]+)/si" +496[] = "401" +246[] = "/mozilla.*rv:[0-9\.]+.*gecko.*Navigator\/([0-9a-z\+\-\.]+).*/si" +246[] = "4" +400[] = "/Opera mobi.*Version\/([0-9\.]+)/si" +400[] = "321" +401[] = "/Opera Mobi.*Opera ([0-9\.]+)/si" +401[] = "321" +402[] = "/Opera ([0-9\.]+).*Opera Mobi/si" +402[] = "321" +438[] = "/HTC.*Opera\/([0-9\.]+).*Windows/si" +438[] = "321" +443[] = "/Mozilla.*Linux.*Android.*AppleWebKit.*Version\/([0-9\.]+)/si" +443[] = "354" +488[] = "/mozilla.*applewebkit.*version\/([0-9a-z\+\-\.]+).*mobile.*safari\/[0-9a-z\+\-\.]+.*/si" +488[] = "394" +150[] = "/mozilla.*chrome\/([0-9a-z\+\-\.]+).*/si" +150[] = "120" +271[] = "/mozilla.*rv:[0-9\.]+.*gecko\/[0-9]+.*Tablet browser ([0-9a-z\+\-\.]+).*/si" +271[] = "260" +342[] = "/Mozilla\/.*Gecko.*Firefox.*Madfox\/([0-9a-z\.]+)/si" +342[] = "270" +422[] = "/^2Bone_LinkChecker\/([0-9\.]+)/si" +422[] = "336" +486[] = "/^Mozilla.*Linux.*Kindle\/([0-9\.]+)/si" +486[] = "392" +1[] = "/mozilla.*rv:[0-9\.]+.*gecko\/[0-9]+.*seamonkey\/([0-9a-z\+\-\.]+).*/si" +1[] = "2" +2[] = "/mozilla.*rv:[0-9\.]+.*gecko\/[0-9]+.*camino\/([0-9a-z\+\-\.]+).*/si" +2[] = "1" +3[] = "/mozilla.*rv:[0-9\.]+.*gecko.*firefox\/([0-9a-z\+\-\.]+).*/si" +3[] = "3" +4[] = "/mozilla.*netscape[0-9]?\/([0-9a-z\+\-\.]+).*/si" +4[] = "4" +6[] = "/mozilla.*gecko\/[0-9]+.*galeon\/([0-9a-z\+\-\.]+).*/si" +6[] = "6" +8[] = "/mozilla.*gecko\/[0-9]+.*minimo\/([0-9a-z\+\-\.]+).*/si" +8[] = "8" +9[] = "/mozilla.*gecko\/[0-9]+.*k\-meleon\/([0-9a-z\+\-\.]+).*/si" +9[] = "9" +10[] = "/mozilla.*gecko\/[0-9]+.*k-ninja\/([0-9a-z\+\-\.]+).*/si" +10[] = "10" +11[] = "/mozilla.*gecko.*kazehakase\/([0-9a-z\+\-\.]+).*/si" +11[] = "11" +170[] = "/mozilla.*rv:[0-9\.]+.*gecko\/[0-9]+.*fennec\/([0-9a-z\+\-\.]+).*/si" +170[] = "133" +14[] = "/mozilla.*rv[ :][0-9\.]+.*gecko\/[0-9]+.*firebird\/([0-9a-z\+\-\.]+).*/si" +14[] = "14" +15[] = "/mozilla.*rv:[0-9\.]+.*gecko\/[0-9]+.*phoenix\/([0-9a-z\+\-\.]+).*/si" +15[] = "15" +16[] = "/mozilla.*konqueror\/([0-9a-z\+\-\.]+).*/si" +16[] = "16" +17[] = "/mozilla.*opera ([0-9][0-9a-z\+\-\.]+).*/si" +17[] = "17" +19[] = "/mozilla.*applewebkit\/[0-9]+.*omniweb\/v[0-9\.]+/si" +19[] = "18" +20[] = "/mozilla.*applewebkit\/[0-9]+.*sunrisebrowser\/([0-9a-z\+\-\.]+)/si" +20[] = "19" +303[] = "/^xine\/([0-9a-z\.]+)/si" +303[] = "235" +23[] = "/mozilla.*applewebkit.*version\/([0-9a-z\+\-\.]+).*safari\/[0-9a-z\+\-\.]+.*/si" +23[] = "22" +24[] = "/dillo\/([0-9a-z\+\-\.]+).*/si" +24[] = "23" +25[] = "/icab[ \/]([0-9a-z\+\-\.]+).*/si" +25[] = "24" +26[] = "/^lynx\/([0-9a-z\.]+).*/si" +26[] = "25" +28[] = "/^elinks \(([0-9a-z\.]+).*/si" +28[] = "27" +29[] = "/^elinks\/([0-9a-z\.]+).*/si" +29[] = "27" +30[] = "/^elinks$/si" +30[] = "27" +31[] = "/^Wget\/([0-9a-z\+\-\.]+).*/si" +31[] = "28" +32[] = "/Amiga\-Aweb\/([0-9a-z\+\-\.]+).*/si" +32[] = "29" +33[] = "/AmigaVoyager\/([0-9a-z\+\-\.]+).*/si" +33[] = "30" +35[] = "/UP\.Browser\/([0-9a-zA-Z\.]+).*/s" +35[] = "32" +36[] = "/UP\/([0-9a-zA-Z\.]+).*/s" +36[] = "32" +37[] = "/NetFront\/([0-9a-z\.]+).*/si" +37[] = "33" +223[] = "/^CPG RSS Module File Reader/si" +223[] = "180" +42[] = "/offline explorer\/([0-9a-z\+\-\.]+).*/si" +42[] = "39" +304[] = "/^webfs\/([0-9\.]+) \(plan 9\)$/si" +304[] = "236" +44[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*AOL ([0-9a-z\+\-\.]+)/si" +44[] = "40" +45[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*America Online Browser ([0-9a-z\+\-\.]+)/si" +45[] = "40" +46[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*Avant Browser ([0-9a-z\+\-\.]+)/si" +46[] = "41" +48[] = "/mozilla.*AvantGo ([0-9a-z\+\-\.]+)/si" +48[] = "42" +50[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*Crazy Browser ([0-9a-z \+\-\.]+)/si" +50[] = "44" +51[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*Deepnet Explorer ([0-9a-z\+\-\.]+)/si" +51[] = "45" +53[] = "/mozilla.*HTTrack ([0-9a-z\+\-\.]+).*/si" +53[] = "46" +55[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*iRider ([0-9a-z\+\-\.]+)/si" +55[] = "48" +56[] = "/.*isilox\/([0-9a-z\+\-\.]+).*/si" +56[] = "49" +57[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*KKman([0-9a-z\+\-\.]+)/si" +57[] = "50" +58[] = "/libwww\-perl\/([0-9a-z\+\-\.]+).*/si" +58[] = "51" +60[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*Maxthon ([0-9a-z\+\-\.]+)/si" +60[] = "53" +61[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*MyIE2/si" +61[] = "53" +63[] = "/mozilla.*MultiZilla ([0-9a-z\+\-\.]+).*/si" +63[] = "55" +64[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*NetCaptor ([0-9a-z\+\-\.]+)/si" +64[] = "56" +65[] = "/Netgem\/([0-9a-z\+\-\.]+).*/si" +65[] = "57" +66[] = "/netsurf\/([0-9a-z\+\-\.]+).*/si" +66[] = "58" +67[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*Sleipnir\/([0-9a-z\+\-\.]+)/si" +67[] = "59" +70[] = "/Teleport Pro\/([0-9a-z\+\-\.]+).*/si" +70[] = "62" +77[] = "/sunrise[ \/]([0-9a-z\+\-\.\/]+)/si" +77[] = "19" +78[] = "/mozilla.*galeon\/([0-9a-z\+\-\.]+).*/si" +78[] = "6" +80[] = "/Openwave/si" +80[] = "32" +302[] = "/Mozilla\/.*AppleWebKit.*Paparazzi!\/([0-9a-z\.]+)/si" +302[] = "234" +86[] = "/webcopier.*v([0-9a-z\.]+)/si" +86[] = "71" +89[] = "/MSIE.*PhaseOut/si" +89[] = "74" +97[] = "/doris\/([0-9a-z\+\-\.]+).*/si" +97[] = "81" +98[] = "/^Enigma browser$/si" +98[] = "82" +100[] = "/lwp\-request\/([0-9a-z\+\-\.]+).*/si" +100[] = "51" +102[] = "/Jakarta Commons-HttpClient\/([0-9a-zA-Z\.\-]+)/si" +102[] = "85" +104[] = "/^curl ([0-9a-zA-Z\.\-]+)/si" +104[] = "86" +106[] = "/amaya\/([0-9a-zA-Z\.\-+]+)/si" +106[] = "87" +107[] = "/GetRight\/([0-9a-zA-Z\.\-\+]+)/si" +107[] = "88" +108[] = "/^Mozilla.*OmniWeb\/([1-9a-zA-z\.\-]+)/si" +108[] = "18" +109[] = "/Mozilla.*OffByOne/si" +109[] = "89" +110[] = "/Python\-urllib\/([0-9a-zA-Z\.\-]+)/si" +110[] = "90" +111[] = "/w3m\/([0-9a-zA-z\-\+\.]+)/si" +111[] = "91" +113[] = "/^WebZIP\/([0-9a-zA-Z\.\-]+)/si" +113[] = "93" +115[] = "/ICEbrowser\/([0-9a-z_\.\-]+)/si" +115[] = "94" +327[] = "/ICE browser\/([0-9a-z_\.\-]+)/si" +327[] = "94" +118[] = "/Iceape\/([0-9a-zA-z\.\-]+)/si" +118[] = "96" +120[] = "/Jakarta Commons\-HttpClient/si" +120[] = "85" +122[] = "/HotJava\/([0-9a-zA-Z\.\- ]+)/si" +122[] = "99" +123[] = "/JoBo\/([0-9a-z\.\-]+)/si" +123[] = "100" +371[] = "/^Python-webchecker\/([0-9]+)$/si" +371[] = "294" +126[] = "/Sleipnir Version ([0-9a-z\.]+)/si" +126[] = "59" +130[] = "/poe-component-client-http\/([0-9a-z\.\-]+)/si" +130[] = "105" +300[] = "/Mozilla.*MSIE.*Hydra Browser/si" +300[] = "232" +169[] = "/^Mozilla\/(3\.0).*Sun\)$/si" +169[] = "99" +301[] = "/^Mozilla.*AppleWebKit.*wKiosk/si" +301[] = "233" +137[] = "/snoopy v([1-9\.]+)/si" +137[] = "111" +141[] = "/NetFront([0-9a-z\.]+).*/si" +141[] = "33" +147[] = "/NCSA_Mosaic\/([0-9a-z\+\-\.]+).*/si" +147[] = "117" +151[] = "/mozilla.*applewebkit.*AdobeAIR\/([0-9a-z\+\-\.]+).*/si" +151[] = "121" +152[] = "/^lwp-trivial\/([0-9.]+)$/si" +152[] = "122" +153[] = "/^WWW-Mechanize\/([0-9a-z\+\-\.]+)/si" +153[] = "123" +156[] = "/^SiteSucker\/([0-9a-z\.]+)/si" +156[] = "125" +155[] = "/^Xenu Link Sleuth ([0-9a-z\+\-\.]+)$/si" +155[] = "124" +160[] = "/mozilla.*rv:[0-9\.]+.*gecko\/[0-9]+.*Shiretoko\/([0-9a-z\+\-\.]+).*/si" +160[] = "128" +161[] = "/mozilla.*rv:[0-9\.]+.*gecko\/[0-9]+.*Minefield\/([0-9a-z\+\-\.]+).*/si" +161[] = "129" +164[] = "/^links \(([0-9a-z\.]+).*/si" +164[] = "132" +167[] = "/Netbox\/([0-9a-z\+\-\.]+).*/si" +167[] = "57" +171[] = "/mozilla.*Lotus-Notes\/([0-9a-z\+\-\.]+).*/si" +171[] = "134" +172[] = "/^klondike\/([0-9a-z\+\-\.]+).*/si" +172[] = "135" +173[] = "/^WapTiger\/5.0 \(http:\/\/www\.waptiger\.com\/.*/si" +173[] = "136" +174[] = "/^W3C_Validator\/([0-9a-z\+\-\.]+).*/si" +174[] = "137" +176[] = "/^HTMLParser\/([0-9a-z\.]+)$/si" +176[] = "139" +177[] = "/^LWP::Simple\/([0-9a-z\.]+)$/si" +177[] = "122" +178[] = "/^Java\/([0-9a-z\._]+)/si" +178[] = "140" +181[] = "/^UniversalFeedParser\/([0-9\.]+)/si" +181[] = "143" +185[] = "/Bookdog\/([0-9\.]+)/si" +185[] = "146" +186[] = "/http:\/\/Anonymouse.org\/ \(Unix\)/si" +186[] = "147" +187[] = "/Midori\/([0-9\.]+)/si" +187[] = "148" +188[] = "/boxee.*\(.*\ ([0-9a-zA-Z\.]+)\)/si" +188[] = "149" +189[] = "/^gPodder\/([0-9\.]+)/si" +189[] = "150" +192[] = "/NF-Browser\/([0-9\.]+)/si" +192[] = "33" +194[] = "/^WDG_Validator\/([0-9\.]+)/si" +194[] = "154" +195[] = "/^CSSCheck\/([0-9\.]+)/si" +195[] = "155" +196[] = "/^Page Valet\/([0-9a-z\.]+)/si" +196[] = "156" +198[] = "/mozilla.*Lunascape ([0-9a-z\+\-\.]+).*/si" +198[] = "52" +199[] = "/^BlackBerry[0-9a-z]+\/([0-9\.]+)/si" +199[] = "158" +204[] = "/^WinWAP\/([0-9\.]+)/si" +204[] = "161" +205[] = "/^XBMC\/([0-9a-z\.\-]+)/si" +205[] = "162" +206[] = "/^XML-RPC for PHP ([0-9\.]+)$/si" +206[] = "163" +207[] = "/^OmniWeb\/([0-9a-z\.\-]+)/si" +207[] = "18" +208[] = "/^FlyCast\/([0-9\.]+)/si" +208[] = "165" +209[] = "/^Bloglines\/([0-9\.]+)/si" +209[] = "166" +210[] = "/^Gregarius\/([0-9\.]+)/si" +210[] = "167" +211[] = "/^SimplePie\/([0-9a-z\. ]+)/si" +211[] = "168" +212[] = "/^PycURL\/([0-9\.]+)$/si" +212[] = "169" +213[] = "/^Apple-PubSub\/([0-9\.]+)$/si" +213[] = "170" +214[] = "/^Feedfetcher-Google.*http:\/\/www\.google\.com\/feedfetcher\.html/si" +214[] = "171" +215[] = "/^FeedValidator\/([0-9\.]+)$/si" +215[] = "172" +216[] = "/^MagpieRSS\/([0-9\.]+)/si" +216[] = "173" +217[] = "/^BlogBridge ([0-9\.]+)/si" +217[] = "174" +219[] = "/^Liferea\/([0-9\.]+).*http:\/\/liferea\.sf\.net\//si" +219[] = "176" +220[] = "/^HomePage Rss Reader ([0-9\.]+)/si" +220[] = "177" +221[] = "/^PHP\/([0-9a-z\.\-]+)$/si" +221[] = "178" +222[] = "/^REL Link Checker Lite ([0-9\.]+)$/si" +222[] = "179" +224[] = "/^Dragonfly File Reader/si" +224[] = "180" +225[] = "/^CPG Dragonfly RSS Module Feed Viewer/si" +225[] = "180" +226[] = "/^newsbeuter\/([0-9\.]+)/si" +226[] = "181" +227[] = "/^Jigsaw\/[0-9\.]+ W3C_CSS_Validator_JFouffa\/([0-9\.]+)$/si" +227[] = "182" +228[] = "/^FPLinkChecker\/([0-9\.]+)$/si" +228[] = "183" +229[] = "/^GoldenPod ([0-9\.]+)/si" +229[] = "184" +231[] = "/mozilla.*rv:[0-9\.]+.*gecko\/[0-9]+.*chimera\/([0-9a-z\+\-\.]+).*/si" +231[] = "1" +236[] = "/^curl\/([0-9a-zA-Z\.\-]+)/si" +236[] = "86" +238[] = "/^Mozilla\/4\.0.*Win32.*ActiveXperts\.Http\.([0-9\.]+)/si" +238[] = "192" +241[] = "/^check_http\/([0-9a-z\.]+) \(nagios\-plugins/si" +241[] = "195" +244[] = "/^P3P Validator$/si" +244[] = "198" +247[] = "/^JetBrains Omea Reader ([0-9\.]+)/si" +247[] = "200" +248[] = "/^GSiteCrawler\/([0-9a-z\.]+)/si" +248[] = "201" +249[] = "/^YahooFeedSeeker\/([0-9\.]+)/si" +249[] = "202" +250[] = "/^Democracy\/([0-9\.]+)/si" +250[] = "175" +251[] = "/^Java([0-9\._]+)$/si" +251[] = "140" +253[] = "/^mozilla\/.*MSIE [0-9\.]+.*TheWorld/si" +253[] = "204" +258[] = "/^NewsGatorOnline\/([0-9\.]+) \(http:\/\/www\.newsgator\.com/si" +258[] = "206" +260[] = "/^Web Downloader\/([0-9\.]+)$/si" +260[] = "39" +261[] = "/^Opera\/[0-9\.]+.*Presto\/[0-9\.]+ Version\/([0-9\.]+)$/si" +261[] = "17" +262[] = "/mozilla.*rv:[0-9\.]+.*gecko.*Songbird\/([0-9\.]+)/si" +262[] = "208" +264[] = "/^RSS_Radio ([0-9\.]+)$/si" +264[] = "209" +265[] = "/^Feed::Find\/([0-9\.]+)$/si" +265[] = "210" +267[] = "/mozilla.*rv:[0-9\.]+.*gecko.*BonEcho\/([0-9a-z\+\-\.]+).*/si" +267[] = "212" +272[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*GreenBrowser/si" +272[] = "216" +273[] = "/^Awasu\/([0-9a-z\.]+)$/si" +273[] = "217" +274[] = "/^CorePlayer.*CorePlayer\/([0-9\._]+)$/si" +274[] = "218" +275[] = "/^Mozilla\/.*AppleWebKit.*QtWeb Internet Browser\/([0-9\.]+)/si" +275[] = "219" +276[] = "/^Mozilla\/.*AppleWebKit.*TeaShark\/([0-9\.]+)$/si" +276[] = "220" +277[] = "/^libsoup\/([0-9a-z\.]+)$/si" +277[] = "221" +279[] = "/^NetNewsWire\/([0-9a-z\.]+).*http:\/\/www\.newsgator\.com\/Individuals\/NetNews/si" +279[] = "222" +295[] = "/^Mozilla.*RISC.*Oregano ([0-9\.]+)/si" +295[] = "228" +293[] = "/^lftp\/([0-9a-z\.]+)$/s" +293[] = "227" +294[] = "/^WinWAP-SPBE\/([0-9\.]+)/si" +294[] = "161" +287[] = "/NokiaN93/si" +287[] = "226" +289[] = "/Nokia.*SymbianOS.*Series60/si" +289[] = "226" +296[] = "/^libsummer\/([0-9\.]+)/si" +296[] = "229" +292[] = "/SymbianOS.*Series60.*Nokia.*AppleWebKit/si" +292[] = "226" +297[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*Acoo Browser/si" +297[] = "230" +298[] = "/^Mozilla.*NewsFox\/([0-9\.]+)/si" +298[] = "231" +305[] = "/^Ilium Software NewsBreak/si" +305[] = "237" +306[] = "/^LinkbackPlugin\/([0-9a-z\.]+) Laconica\//si" +306[] = "238" +307[] = "/^Microsoft Data Access Internet Publishing Provider DAV/si" +307[] = "239" +308[] = "/^gvfs\/([0-9a-z\.]+)/si" +308[] = "240" +311[] = "/^Cynthia ([0-9\.]+)$/si" +311[] = "242" +313[] = "/^Banshee ([0-9a-z\.]+).*http:\/\/banshee-project\.org/si" +313[] = "244" +316[] = "/^Mozilla\/.*ABrowse ([0-9\.]+).*Syllable/si" +316[] = "247" +317[] = "/^Funambol Outlook Plug-in.*([0-9\.]+)$/si" +317[] = "248" +318[] = "/^Funambol Mozilla Sync Client v([0-9\.]+)$/si" +318[] = "249" +320[] = "/^foobar2000\/([0-9a-z\._]+$)/si" +320[] = "251" +321[] = "/^GStreamer souphttpsrc libsoup\/[0-9\.]+$/si" +321[] = "252" +323[] = "/^php-openid\/([0-9\.]+)/si" +323[] = "254" +324[] = "/NCSA Mosaic\/([0-9a-z\+\-\.]+).*/si" +324[] = "117" +325[] = "/mozilla.*rv:[0-9\.]+.*gecko.*Blackbird\/([0-9a-z\+\-\.]+).*/si" +325[] = "255" +328[] = "/^GreatNews\/([0-9\.]+)$/si" +328[] = "256" +329[] = "/mozilla.*applewebkit.*DeskBrowse\/([0-9a-z\+\-\.]+).*/si" +329[] = "257" +330[] = "/^TulipChain\/([0-9\.]+).*ostermiller.org\/tulipchain.*Java/si" +330[] = "258" +331[] = "/^Mozilla\/.*AppleWebKit\/.*Maxthon\/([0-9\.]+)/si" +331[] = "53" +333[] = "/^Mozilla\/.*Linux.*AppleWebKit.*tear/si" +333[] = "261" +334[] = "/^LinkExaminer\/([0-9\.]+) \(Windows\)$/si" +334[] = "262" +335[] = "/^Mozilla\/.*MSIE.*http:\/\/www\.Abolimba\.de/si" +335[] = "263" +336[] = "/^Mozilla\/.*Gecko\/.*Beonex\/([0-9a-z\.\-]+)/si" +336[] = "264" +337[] = "/^DocZilla\/([0-9\.]+).*Gecko\//si" +337[] = "265" +338[] = "/^retawq\/([0-9a-z\.]+).*\(text\)$/si" +338[] = "266" +339[] = "/^SAMSUNG.*Jasmine\/([0-9\.]+)/si" +339[] = "267" +341[] = "/Mozilla\/.*AppleWebKit.*Dooble/si" +341[] = "269" +345[] = "/^Bunjalloo\/([0-9\.]+).*Nintendo/si" +345[] = "273" +346[] = "/^LinkChecker\/([0-9\.]+).*linkchecker\.sourceforge\.net/si" +346[] = "274" +348[] = "/urlgrabber\/([0-9\.]+)/si" +348[] = "276" +349[] = "/mozilla.*rv:[0-9\.]+.*gecko.*Spicebird\/([0-9a-z\+\-\.]+).*/si" +349[] = "277" +352[] = "/mozilla.*rv:[0-9\.]+.*gecko\/[0-9]+.*Namoroka\/([0-9a-z\+\-\.]+).*/si" +352[] = "278" +353[] = "/mozilla.*applewebkit.*rekonq/si" +353[] = "279" +354[] = "/^W3C_Multipage_Validator\/([0-9a-z\.]+).*http:\/\/www\.validator\.ca\//si" +354[] = "280" +355[] = "/^X\-Smiles\/([0-9a-z\.]+)/si" +355[] = "281" +360[] = "/^SZN-Image-Resizer$/si" +360[] = "284" +362[] = "/^Google-Listen\/([0-9a-z\.]+)/si" +362[] = "286" +364[] = "/^Mozilla\/.*Origyn Web Browser/si" +364[] = "288" +365[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*Browzar/si" +365[] = "289" +366[] = "/^Claws Mail GtkHtml2 plugin ([0-9a-z\.]+).*http:\/\/www.claws-mail.org\/plugins.php/si" +366[] = "290" +367[] = "/Python\-urllib$/si" +367[] = "90" +370[] = "/^GomPlayer ([0-9, ]+)/si" +370[] = "293" +372[] = "/^W3C-mobileOK\/DDC-([0-9\.]+).* http:\/\/www.w3.org\/2006\/07\/mobileok-ddc/si" +372[] = "296" +373[] = "/^JoeDog\/.*Siege ([0-9\.]+)/si" +373[] = "297" +374[] = "/^iSiloXC\/([0-9\.]+)/si" +374[] = "298" +375[] = "/^ApacheBench\/([0-9a-z\-\.]+)$/si" +375[] = "299" +376[] = "/^anw webtool LoadControl\/([0-9\.]+)$/si" +376[] = "300" +377[] = "/^topSUBMIT.de HTMLChecker\/([0-9\.]+)$/si" +377[] = "301" +378[] = "/^edbrowse\/([0-9\.\-]+)/si" +378[] = "302" +379[] = "/^muCommander v([0-9\.]+)/si" +379[] = "303" +381[] = "/^XMPlay\/([0-9\.]+)$/si" +381[] = "304" +383[] = "/^Mozilla\/.*uZardWeb\/([0-9\.]+)/si" +383[] = "306" +384[] = "/^Mozilla\/3.0 \(compatible; Indy Library\)$/si" +384[] = "307" +385[] = "/^Mozilla\/.*MSIE.*Multi\-Browser ([0-9\.]+).*www\.multibrowser\.de/si" +385[] = "308" +386[] = "/^LinkWalker\/([0-9\.]+).*www\.seventwentyfour\.com/si" +386[] = "309" +387[] = "/^Mozilla.*compatible.*NetPositive\/([0-9\.]+)/si" +387[] = "310" +388[] = "/^Radio Downloader ([0-9\.]+)$/si" +388[] = "311" +389[] = "/^WebStripper\/([0-9\.]+)/si" +389[] = "312" +390[] = "/^Cyberduck\/([0-9\.]+)/si" +390[] = "313" +391[] = "/^WorldWideweb \(NEXT\)$/si" +391[] = "314" +393[] = "/^Mozilla\/4.0 \(compatible; RSS Popper\)$/si" +393[] = "316" +394[] = "/^Win.*Jamcast\/([0-9\.]+)/si" +394[] = "317" +395[] = "/^Jamcast ([0-9\.]+)$/si" +395[] = "317" +399[] = "/^MyIBrow\/([0-9\.]+).*Windows/si" +399[] = "320" +405[] = "/^Mozilla.*MSIE.*TencentTraveler ([0-9\.]+)/si" +405[] = "323" +412[] = "/^The Bat! ([0-9\.]+)$/si" +412[] = "330" +413[] = "/^Mozilla.*compatible.*BorderManager ([0-9\.]+)/si" +413[] = "331" +415[] = "/^PublicRadioPlayer\/([0-9\.]+)/si" +415[] = "333" +416[] = "/^PublicRadioApp\/([0-9\.]+)/si" +416[] = "333" +418[] = "/^RssBandit\/([0-9\.]+)/si" +418[] = "334" +419[] = "/^Microsoft Office\/14.*MSOffice 14/si" +419[] = "326" +420[] = "/^Mozilla.*Postbox\/([0-9a-zA-Z\.]+)/si" +420[] = "335" +423[] = "/^Checkbot\/([0-9\.]+)/si" +423[] = "337" +424[] = "/^GcMail Browser\/([0-9\.]+)/si" +424[] = "338" +425[] = "/mozilla.*rv:[0-9\.]+.*gecko.*Swiftweasel\/([0-9a-z\+\-\.]+).*/si" +425[] = "339" +426[] = "/^Fastladder FeedFetcher\/([0-9\.]+).*fastladder.com/si" +426[] = "340" +427[] = "/mozilla.*rv:[0-9\.]+.*gecko.*Lorentz\/([0-9a-z\+\-\.]+).*/si" +427[] = "341" +428[] = "/^PocketTunes\/([0-9a-z\.]+)$/si" +428[] = "342" +433[] = "/^mozilla.*AppleWebKit.*Google Earth\/([0-9\.]+)/si " +433[] = "347" +435[] = "/^Rome Client \(http:\/\/tinyurl\.com\/64t5n\) Ver: ([0-9\.]+)/si" +435[] = "348" +437[] = "/^Akregator\/([0-9\.]+).*librss\/remnants/si" +437[] = "349" +445[] = "/^Pocomail\/([0-9\.]+)$/si" +445[] = "356" +447[] = "/^Mozilla.*MSIE.*SlimBrowser/si" +447[] = "358" +449[] = "/^LeechCraft.*LeechCraft\/Poshuku ([0-9a-z\-\.]+)/si" +449[] = "359" +450[] = "/^HTTP_Request2\/([0-9\.]+)/si" +450[] = "360" +451[] = "/^Mozilla.*Gecko.*Conkeror\/([0-9\.]+)/si" +451[] = "361" +452[] = "/^Mozilla.*NUCLEUS.*Dolfin\/([0-9\.]+)/si" +452[] = "362" +454[] = "/^Mozilla.*SAMSUNG.*Dolfin\/([0-9\.]+)/si" +454[] = "362" +458[] = "/^Web-sniffer\/([0-9\.]+).*web-sniffer\.net\/\)$/si" +458[] = "366" +459[] = "/^Atomic_Email_Hunter\/([0-9\.]+)$/si" +459[] = "367" +461[] = "/^webfetch\/([0-9\.]+)/si" +461[] = "369" +466[] = "/^AppleSyndication\/([0-9\.]+)$/si" +466[] = "374" +472[] = "/^Windows-RSS-Platform\/([0-9\.]+).*MSIE.* Windows/si" +472[] = "381" +473[] = "/^Trileet NewsRoom.*feedmonger\.blogspot\.com/si" +473[] = "382" +474[] = "/^Validator.nu\/([0-9\.]+)$/si" +474[] = "383" +475[] = "/^Zend_Http_Client$/si" +475[] = "384" +477[] = "/^Mozilla.*Android.*GoBrowser\/([0-9\.]+)/si" +477[] = "386" +478[] = "/^Mozilla.*Android.*GoBrowser/si" +478[] = "386" +482[] = "/^Xenu Link Sleuth\/([0-9a-z\+\-\.]+)$/si" +482[] = "124" +487[] = "/^Microsoft Office Existence Discovery/si" +487[] = "393" +490[] = "/^BrownReclusePro v([0-9\.]+).*SoftByteLabs.com/si" +490[] = "395" +493[] = "/^Mozilla.*Gecko\/[0-9]+.*WebianShell\/([0-9a-z\.]+)/si" +493[] = "399" +497[] = "/^CamelHttpStream\/([0-9\.]+)$/si" +497[] = "402" +404[] = "/^Mozilla.*MSIE.*TencentTraveler/si" +404[] = "323" +47[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*Avant Browser/si" +47[] = "41" +52[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*Deepnet Explorer/si" +52[] = "45" +79[] = "/mozilla.*applewebkit\/[0-9a-z\+\-\.]+.*/si" +79[] = "22" +82[] = "/mozilla.*\/[0-9\.]+.*gecko.*firefox.*/si" +82[] = "3" +166[] = "/mozilla.*MSIE [0-9a-z\+\-\.]+.*Maxthon/si" +166[] = "53" +193[] = "/mozilla.*rv:[0-9\.]+.*gecko.*GranParadiso\/([0-9a-z\+\-\.]+).*/si" +193[] = "153" +239[] = "/^MOT.*MIB\/([0-9\.]+)/si" +239[] = "193" +18[] = "/^opera\/([0-9a-z\+\-\.]+).*/si" +18[] = "17" +34[] = "/IBrowse\/([0-9a-z\+\-\.]+).*/si" +34[] = "31" +103[] = "/IBrowse/si" +103[] = "31" +105[] = "/Aweb.*Amiga/si" +105[] = "29" +138[] = "/Lynx/si" +138[] = "25" +139[] = "/libwww\-perl/si" +139[] = "51" +143[] = "/^opera ([0-9a-z\+\-\.]+).*/si" +143[] = "17" +190[] = "/^Samsung-[a-zA-Z09]+.*AU-MIC-[a-zA-Z0-9]+\/([0-9\.]+)/si" +190[] = "151" +191[] = "/^SonyEricsson.*SEMC-Browser\/([0-9\.]+)/si" +191[] = "152" +201[] = "/Browser\/Teleca|Teleca\/.*MIDP/si" +201[] = "151" +237[] = "/^MPlayer\//si" +237[] = "191" +242[] = "/^Windows\-Media\-Player\/([0-9\.]+)$/si" +242[] = "196" +243[] = "/^VLC media player \- version ([0-9a-z\-\.]+) .* VideoLAN team$/si" +243[] = "197" +245[] = "/^CSE HTML Validator Lite Online/si" +245[] = "199" +268[] = "/^QuickTime\/([0-9\.]+)/" +268[] = "213" +269[] = "/^QuickTime.*qtver=([0-9\.a-z]+)/si" +269[] = "213" +270[] = "/^PHPCrawl$/si" +270[] = "214" +280[] = "/http:\/\/code\.google\.com\/appengine/si" +280[] = "223" +299[] = "/^Mozilla.*Danger hiptop/si" +299[] = "33" +309[] = "/^Webkit\/.*Uzbl/si" +309[] = "241" +310[] = "/^Uzbl.*Webkit/si" +310[] = "241" +312[] = "/^Mozilla\/5\.0 \(Sage\)$/si" +312[] = "243" +357[] = "/^Xaldon_WebSpider\/([0-9a-z\.]+)/si" +357[] = "283" +358[] = "/^Xaldon WebSpider ([0-9a-z\.]+)/si" +358[] = "283" +397[] = "/Mozilla\/4.*OS\/2/si" +397[] = "4" +455[] = "/^Netvibes.*http:\/\/www\.netvibes\.com/si" +455[] = "363" +457[] = "/^The Incutio XML-RPC PHP Library/si" +457[] = "365" +479[] = "/\/GoBrowser\/([0-9\.]+)/si" +479[] = "386" +481[] = "/^iGooMap\/([0-9a-z\.]+).*pointworks/si" +481[] = "388" +491[] = "/^ColdFusion \(BookmarkTracker\.com\)$/si" +491[] = "396" +492[] = "/^BinGet\/([0-9a-zA-Z\.]+)/si" +492[] = "397" +480[] = "/^Surf\/([0-9\.]+).*AppleWebKit/si" +480[] = "387" +62[] = "/mozilla.*(rv:[0-9\.]+).*gecko\/[0-9]+.*/si" +62[] = "54" +202[] = "/Polaris\/([0-9\.]+)/si" +202[] = "159" +240[] = "/^Abilon$/si" +240[] = "194" +254[] = "/^webcollage\/([0-9\.]+)$/si" +254[] = "205" +255[] = "/^webcollage\-noporn\/([0-9\.]+)$/si" +255[] = "205" +256[] = "/^webcollage\.[a-z]+\/([0-9\.]+)$/si" +256[] = "205" +257[] = "/^webcollage1\/([0-9\.]+)$/si" +257[] = "205" +319[] = "/^RSS Menu\/([0-9\.]+)/si" +319[] = "250" +350[] = "/.*Obigo Browser ([0-9\.]+)/si" +350[] = "151" +392[] = "/^iVideo ([a-z0-9\.\ ]+).*iPhone OS/si" +392[] = "315" +462[] = "/^Mozilla\/4\.0 \(compatible; Synapse\)$/si" +462[] = "370" +464[] = "/^Mozilla.*SkipStone ([0-9\.]+)/si" +464[] = "372" +465[] = "/^Mozilla\/.*compatible.*Powermarks\/([0-9\.]+)/si" +465[] = "373" +483[] = "/^iTunes\/([0-9\.]+)/si" +483[] = "389" +95[] = "/^DoCoMo\//si" +95[] = "33" +165[] = "/mozilla.*PlayStation\ Portable.*/si" +165[] = "33" +200[] = "/Obigo.*Profile\/MIDP/si" +200[] = "151" +259[] = "/^Mozilla.*PRTG Network Monitor/si" +259[] = "207" +281[] = "/UCWEB/si" +281[] = "225" +315[] = "/^RSSOwl\/([0-9]\.[0-9]\.[0-9])/si" +315[] = "246" +332[] = "/^Axel ([0-9\.]+)/si" +332[] = "259" +343[] = "/^DownloadStudio\/([0-9\.]+)$/si" +343[] = "271" +344[] = "/^WinPodder.*http:\/\/winpodder\.com/si" +344[] = "272" +363[] = "/^Typhoeus.*http:\/\/github.com\/pauldix\/typhoeus/si" +363[] = "287" +368[] = "/^Azureus ([0-9a-z\.]+)/si" +368[] = "291" +380[] = "/^muCommander-file-API/si" +380[] = "303" +382[] = "/^NFReader\/([0-9\.]+)/si" +382[] = "305" +398[] = "/^SuperBot\/([0-9\.]+)/si" +398[] = "319" +417[] = "/PLAYSTATION 3/si" +417[] = "33" +421[] = "/^Postbox ([0-9a-z\.]+)/si" +421[] = "335" +429[] = "/^SharpReader\/([0-9\.]+)/si" +429[] = "343" +430[] = "/^YeahReader/si" +430[] = "344" +448[] = "/^LeechCraft/si" +448[] = "359" +453[] = "/^SAMSUNG.*Dolfin\/([0-9\.]+)/si" +453[] = "362" +456[] = "/^Chilkat\/([0-9\.]+) \(\+http:\/\/www\.chilkatsoft\.com\/ChilkatHttpUA\.asp\)/si" +456[] = "364" +460[] = "/^iGetter\/([0-9a-z\.]+).*/si" +460[] = "368" +467[] = "/^GoogleFriendConnect\/([0-9\.]+)$/si" +467[] = "375" +485[] = "/^Typhoeus.*http:\/\/github.com\/dbalatero\/typhoeus/si" +485[] = "287" +351[] = "/ObigoInternetBrowser/si" +351[] = "151" +83[] = "/mozilla.*(rv:[0-9\.]+).*/si" +83[] = "54" +263[] = "/^Avant Browser/si" +263[] = "41" +432[] = "/^holmes\/([0-9\.]+)/si" +432[] = "346" +347[] = "/^Mozilla\/.*MSIE 7\.0.*Trident\/4\.0/si" +347[] = "275" +326[] = "/^Mozilla\/4.0 \(compatible; MSIE ([0-9\.]+); Windows/si" +326[] = "35" +39[] = "/mozilla\/.*MSIE ([0-9b\.]+).*/si" +39[] = "35" +81[] = "/MSIE ([0-9a-z\+\-\.]+).*windows ce/si" +81[] = "157" +40[] = "/^Mozilla\/([0-9a-z\.\[\] ]+) \([a-z0-9;. \-]+\)/si" +40[] = "4" +356[] = "/WinHttp/si" +356[] = "282" +[browser_os] +; browser_id[] = "OS id" +18[] = "44" +23[] = "19" +39[] = "43" +43[] = "35" +59[] = "43" +62[] = "43" +65[] = "43" +69[] = "43" +70[] = "43" +71[] = "43" +82[] = "43" +83[] = "43" +88[] = "43" +93[] = "43" +95[] = "43" +97[] = "33" +98[] = "43" +100[] = "47" +102[] = "43" +107[] = "10" +108[] = "43" +109[] = "43" +113[] = "43" +116[] = "43" +124[] = "43" +125[] = "44" +146[] = "44" +151[] = "10" +152[] = "47" +159[] = "10" +170[] = "44" +179[] = "43" +194[] = "43" +200[] = "43" +201[] = "43" +209[] = "43" +217[] = "43" +220[] = "10" +221[] = "19" +225[] = "10" +235[] = "19" +237[] = "73" +239[] = "43" +240[] = "19" +248[] = "43" +251[] = "43" +256[] = "43" +260[] = "75" +261[] = "75" +271[] = "43" +272[] = "43" +281[] = "47" +282[] = "43" +283[] = "43" +286[] = "62" +293[] = "43" +304[] = "43" +305[] = "43" +310[] = "33" +311[] = "43" +312[] = "43" +313[] = "44" +314[] = "77" +316[] = "43" +330[] = "43" +334[] = "43" +344[] = "43" +349[] = "19" +356[] = "43" +362[] = "62" +367[] = "43" +369[] = "43" +373[] = "43" +388[] = "86" +393[] = "43" +395[] = "43" +[os_reg] +; os_reg_id[] = "OS regstring" +; os_reg_id[] = "OS id" +40[] = "/palm/si" +40[] = "35" +64[] = "/Win 9x 4\.90/si" +64[] = "8" +71[] = "/MorphOS/si" +71[] = "53" +92[] = "/iPhone OS ([0-9_]+) like Mac OS X/si" +92[] = "65" +67[] = "/Solaris/si" +67[] = "29" +90[] = "/iPhone OS 2_0/si" +90[] = "65" +102[] = "/Series60/si" +102[] = "34" +136[] = "/iPhone.*like Mac OS X/si" +136[] = "65" +138[] = "/^HTC_HD2.*Opera.*windows/si" +138[] = "96" +96[] = "/BeOS.*Haiku BePC/si" +96[] = "70" +125[] = "/Windows Mobile/si" +125[] = "88" +1[] = "/windows nt 5\.1/si" +1[] = "1" +5[] = "/.*windows 95.*/si" +5[] = "4" +3[] = "/windows nt 5\.0/si" +3[] = "2" +4[] = "/.*windows nt 5\.2( |;).*/si" +4[] = "3" +56[] = "/Series80\/2\.0/si" +56[] = "34" +6[] = "/.*win95.*/si" +6[] = "4" +7[] = "/windows 98/si" +7[] = "5" +8[] = "/.*win16( |;).*/si" +8[] = "6" +9[] = "/.*win98( |;).*/si" +9[] = "5" +10[] = "/.*windows 4\.10( |;).*/si" +10[] = "5" +11[] = "/windows ce|PocketPC/si" +11[] = "7" +12[] = "/.*windows me( |;).*/si" +12[] = "8" +13[] = "/.*windows nt 6\.0( |;).*/si" +13[] = "9" +14[] = "/j2me/si" +14[] = "10" +15[] = "/centos/si" +15[] = "11" +16[] = "/ubuntu/si" +16[] = "12" +17[] = "/linux.*debian/si" +17[] = "13" +18[] = "/linux.*fedora/si" +18[] = "14" +19[] = "/linux.*gentoo/si" +19[] = "15" +20[] = "/linux.*linspire/si" +20[] = "16" +21[] = "/linux.*mandriva/si" +21[] = "17" +22[] = "/linux.*mdk/si" +22[] = "17" +23[] = "/linux.*redhat/si" +23[] = "18" +25[] = "/linux.*slackware/si" +25[] = "20" +26[] = "/linux.*kanotix/si" +26[] = "21" +27[] = "/linux.*suse/si" +27[] = "22" +28[] = "/linux.*knoppix/si" +28[] = "23" +29[] = "/.*netbsd.*/si" +29[] = "24" +30[] = "/.*freebsd.*/si" +30[] = "25" +31[] = "/.*openbsd.*/si" +31[] = "26" +116[] = "/Mac OS X (10_6|10\.6)/si" +116[] = "85" +34[] = "/sunos/si" +34[] = "29" +35[] = "/amiga/si" +35[] = "30" +36[] = "/irix/si" +36[] = "31" +37[] = "/open.*vms/si" +37[] = "32" +38[] = "/beos/si" +38[] = "33" +42[] = "/webtv/si" +42[] = "37" +43[] = "/os\/2.*warp/si" +43[] = "39" +45[] = "/RISC.OS/si" +45[] = "40" +46[] = "/hp-ux/si" +46[] = "41" +47[] = "/Nintendo.Wii/si" +47[] = "42" +53[] = "/winnt/si" +53[] = "46" +57[] = "/SonyEricssonP900/si" +57[] = "34" +58[] = "/plan 9/si" +58[] = "49" +59[] = "/NetFront.*Profile\/MIDP/si" +59[] = "10" +61[] = "/Series90.*Nokia7710/si" +61[] = "34" +63[] = "/linux.*\(Dropline GNOME\).*/si" +63[] = "20" +65[] = "/WinNT4\.0/si" +65[] = "46" +66[] = "/linux.*red hat/si" +66[] = "18" +68[] = "/QNX x86pc/si" +68[] = "52" +69[] = "/Red Hat modified/si" +69[] = "18" +70[] = "/Windows\-NT/si" +70[] = "46" +137[] = "/iPad.*OS.*like Mac OS X/si" +137[] = "65" +73[] = "/CYGWIN_NT\-5.0/si" +73[] = "2" +75[] = "/^DoCoMo.*F900i/si" +75[] = "34" +76[] = "/Vector Linux/si" +76[] = "55" +77[] = "/riscos/si" +77[] = "40" +78[] = "/Linux Mint/si" +78[] = "56" +79[] = "/SCO_SV/si" +79[] = "57" +80[] = "/suse\-linux/si" +80[] = "22" +81[] = "/Arch Linux ([0-9a-zA-Z\.\-]+)/si" +81[] = "58" +83[] = "/SkyOS/si" +83[] = "59" +84[] = "/.*windows 3\.1.*/si" +84[] = "6" +86[] = "/Android ([0-9\.]+)/si" +86[] = "62" +87[] = "/windows nt 6\.1/si" +87[] = "64" +88[] = "/.*windows 2000( |;).*/si" +88[] = "2" +117[] = "/Mac OS X (10_5|10\.5)/si" +117[] = "84" +95[] = "/webOS\/.*AppleWebKit/si" +95[] = "69" +98[] = "/Windows NT 6\.0/si" +98[] = "9" +118[] = "/Mac OS X (10_4|10\.4)/si" +118[] = "83" +103[] = "/Danger hiptop [0-9\.]+/si" +103[] = "72" +110[] = "/Windows_XP\/5.1/si" +110[] = "1" +134[] = "/SymbianOS/si" +134[] = "34" +114[] = "/.*windows 7.*/si" +114[] = "64" +115[] = "/iPhone OS [0-9\.]+/si" +115[] = "65" +120[] = "/Mozilla.*Linux.*Maemo/si" +120[] = "75" +124[] = "/S60; SymbOS/si" +124[] = "34" +130[] = "/PCLinuxOS\/([0-9a-z\.\-]+)/si" +130[] = "92" +131[] = "/^Mozilla\/.*Linux.*Jolicloud/si" +131[] = "93" +132[] = "/PLAYSTATION 3/si" +132[] = "94" +139[] = "/^Mozilla.*CrOS.*Chrome/si" +139[] = "97" +140[] = "/Android.*Linux.*Opera Mobi/si" +140[] = "62" +119[] = "/Mac OS X/si" +119[] = "86" +24[] = "/linux/si" +24[] = "19" +82[] = "/Gentoo i686/si" +82[] = "15" +105[] = "/Konqueror.*SUSE/si" +105[] = "22" +106[] = "/Konqueror.*Fedora/si" +106[] = "14" +107[] = "/Obigo.*MIDP/si" +107[] = "10" +108[] = "/Teleca.*MIDP/si" +108[] = "10" +123[] = "/Windows 2000/si" +123[] = "2" +121[] = "/Windows NT 4/si" +121[] = "46" +39[] = "/symbian/si" +39[] = "34" +44[] = "/os\/2/si" +44[] = "87" +55[] = "/.*windows XP.*/si" +55[] = "1" +85[] = "/.*dragonfly.*/si" +85[] = "61" +122[] = "/Windows ME/si" +122[] = "8" +93[] = "/NT4\.0/si" +93[] = "46" +133[] = "/PlayStation Portable/si" +133[] = "94" +48[] = "/windows/si" +48[] = "43" +49[] = "/mac_powerpc/si" +49[] = "44" +50[] = "/Macintosh/si" +50[] = "44" +51[] = "/aix/si" +51[] = "45" +52[] = "/Win32/si" +52[] = "43" +54[] = "/java\/[0-9a-z\.]+/si" +54[] = "47" +60[] = "/BlackBerry/si" +60[] = "50" +109[] = "/Syllable/si" +109[] = "74" +74[] = "/powerpc\-apple/si" +74[] = "44" +135[] = "/AROS/si" +135[] = "95" +94[] = "/java[0-9a-z\.]+/si" +94[] = "47" +100[] = "/Series 60/si" +100[] = "34" +101[] = "/os=Mac/si" +101[] = "44" +111[] = "/SO=MAC10,6/si" +111[] = "44" +112[] = "/so=Mac 10.5.8/si" +112[] = "44" +127[] = "/Minix 3/si" +127[] = "91" +141[] = "/Nintendo DS/Si" +141[] = "98" +142[] = "/^Opera.*Android/si" +142[] = "62" +143[] = "/NokiaN97/si" +143[] = "34" +144[] = "/Nokia.*XpressMusic/si" +144[] = "34" +145[] = "/NokiaE66/si" +145[] = "34" +146[] = "/Nokia6700/si" +146[] = "34" +147[] = "/\(GNU;/si" +147[] = "99" +99[] = "/ mac/si" +99[] = "44" +126[] = "/Darwin 10\.3/si" +126[] = "90" +128[] = "/iPhone/si" +128[] = "65" +148[] = "/Unix/si" +148[] = "19" +129[] = "/Darwin/si" +129[] = "44" diff --git a/trunk/includes/functions.semr.php b/trunk/includes/functions.semr.php index 2f4893c..1e51417 100644 --- a/trunk/includes/functions.semr.php +++ b/trunk/includes/functions.semr.php @@ -26,6 +26,24 @@ * $Id$ * */ +/** + * based upon semmelstatz + * Copyright (c) 2005-2009 Andreas 'Redunzl' Mueller (redunzl@gmx.de) + * + * @license http://www.gnu.org/licenses/gpl-2.0.html + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ ### Encodierung der IP-Adresse durch simple arithmetische Operation function sem_encodeIP($ip) { $ip_parts = split("[.]", $ip); @@ -85,160 +103,29 @@ return $useronline; } -### Prüfen, ob Besucher ein Bot ist - function sem_AreYouBot($user_agent) { - global $isBot; - $bots = array( - 'aipbot', - 'amfibibot', - 'appie', - 'ask jeeves/teoma', - 'aspseek', - 'axadine', - 'baiduspider', - 'becomebot', - 'blogcorpuscrawler', - 'blogpulse', - 'blogsnowbot', - 'boitho.com', - 'bruinbot', - 'cerberian', - 'cfnetwork', - 'check_http', - 'cipinetbot', - 'claymont', - 'cometsearch@cometsystems.com', - 'converacrawler', - 'cydralspider', - 'digger', - 'es.net_crawler', - 'eventax', - 'everyfeed-spider', - 'exabot@exava.com', - 'faxobot', - 'findlinks', - 'fireball', - 'francis', - 'gaisbot', - 'gamekitbot', - 'gazz@nttr.co.jp', - 'geonabot', - 'getrax crawler', - 'gigabot', - 'girafa.com', - 'goforitbot', - 'googlebot', - 'grub-client', - 'holmes', - 'houxoucrawler', - 'http://www.almaden.ibm.com/cs/crawler', - 'http://www.istarthere.com', - 'http://www.relevantnoise.com', - 'httrack ?', - 'ia_archiver', - 'ichiro', - 'iltrovatore-setaccio', - 'inelabot', - 'infoseek', - 'inktomi.com', - 'irlbot', - 'jetbot', - 'jobspider_ba', - 'kazoombot', - 'larbin', - 'libwww', - 'linkwalker', - 'lmspider', - 'mackster', - 'mediapartners-google', - 'microsoft url control', - 'mj12bot', - 'moreoverbot', - 'mozdex', - 'msnbot', - 'msrbot', - 'naverbot', - 'netresearchserver', - 'ng/2.0', - 'np(bot)', - 'nutch', - 'objectssearch', - 'ocelli', - 'omniexplorer_bot', - 'openbot', - 'overture', - 'patwebbot', - 'php', - 'phpdig', - 'pilgrim html-crawler', - 'pipeliner', - 'pompos', - 'psbot', - 'python-urllib', - 'quepasacreep', - 'robozilla', - 'rpt-httpclient', - 'savvybot', - 'scooter', - 'search.ch', - 'seekbot', - 'semager', - 'seznambot', - 'sherlock', - 'shelob', - 'sitesearch', - 'snapbot', - 'snappreviewbot', - 'speedy spider', - 'sphere scout', - 'stackrambler', - 'steeler', - 'surveybot', - 'szukacz', - 'technoratibot', - 'telnet', - 'themiragorobot', - 'thesubot', - 'thumbshots-de-bot', - 'topicblogs', - 'turnitinbot', - 'tutorgigbot', - 'tutorial crawler', - 'twiceler', - 'vagabondo', - 'versus', - 'voilabot', - 'w3c_css_validator', - 'w3c_validator', - 'w3c-checklink', - 'web downloader', - 'webcopier', - 'webcrawler', - 'webfilter robot', - 'west wind internet protocols', - 'wget', - 'wwweasel robot', - 'wwwster', - 'xaldon webspider', - 'xenu', - 'yahoo! slurp', - 'yahoofeedseeker', - 'yahoo-mmcrawler', - 'zao', - 'zipppbot', - 'zyborg', - ); - foreach($bots as $bot) { - if(stristr($user_agent, $bot) !== false) { - return true; - } - } - return false; - } +/** + * Check if agent is a bot + * + * @deprecated use Agents-object in the future + * + * @param string $user_agent + * @return boolean + */ +function sem_AreYouBot($user_agent) { + require_once 'class.agents.php'; + $oCheckAgent = new Agents($user_agent); + return $oCheckAgent->isBot(); +} ### Referer nach Suchmaschinen-Queries und interner Suche prüfen und Suchstring extrahieren - function sem_getKeyword($referer) { - $keyword = @parse_url($referer); +function sem_getKeyword($referer) { + if(empty($referer)) return false; + $homehost = '%'.(substr($_SERVER['SERVER_NAME'],0,4) == 'www.')? + substr($_SERVER['SERVER_NAME'],4) . '%': + $_SERVER['SERVER_NAME'] . '%'; + + $keyword = parse_url($referer); + if(!isset($keyword['host']) || !isset($keyword['query'])) return false; if (preg_match("/google\./i", $keyword["host"])) { if (preg_match("/imgurl/i", $keyword["query"])) { @@ -374,18 +261,18 @@ ### Zeigt Copyright-Notiz an function sem_showCopyright() { - print ""; } ### statz-Tabelle leeren (NICHT LÖSCHEN!!!) - function sem_truncateStatzTable() { - global $wpdb, $userip; - $wpdb->query('TRUNCATE TABLE '.$wpdb->statz); - sem_optStatzTable(); - $wpdb->query("INSERT INTO `$wpdb->statz`(ip, time, referer, page, username) VALUES('127.0.0.1', NOW(),NULL,0,'statz-Tabelle geleert')"); - } +function sem_truncateStatzTable() { + global $wpdb, $userip; + $wpdb->query('TRUNCATE TABLE '.$wpdb->statz); + sem_optStatzTable(); + return $wpdb->query("INSERT INTO `$wpdb->statz`(ip, time, referer, page, username) VALUES('127.0.0.1', NOW(),NULL,0,'statz-Tabelle geleert')"); +} ### Obsolet, bleibt aber aus Kompatibilitätsgründen zu SEMMELSTATZ_DELETE function sem_delOldRecords($days) { @@ -470,7 +357,7 @@ } } -### Summen der vergangenen Tage in die statzhist schreiben */ +/* Summen der vergangenen Tage in die statzhist schreiben */ function sem_writeOldDaysToHist() { global $wpdb; if(!$wpdb->get_var("SELECT date FROM ".$wpdb->statzhist." WHERE substring(date,1,10) <= DATE_SUB(CURDATE(), INTERVAL 1 DAY)")) { diff --git a/trunk/includes/functions.semr_template.php b/trunk/includes/functions.semr_template.php index e473d05..dd54eec 100644 --- a/trunk/includes/functions.semr_template.php +++ b/trunk/includes/functions.semr_template.php @@ -26,6 +26,24 @@ * $Id$ * */ +/** + * based upon semmelstatz + * Copyright (c) 2005-2009 Andreas 'Redunzl' Mueller (redunzl@gmx.de) + * + * @license http://www.gnu.org/licenses/gpl-2.0.html + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ ### Zeigt die letzten $num_posts-Posts an: Titel und absolutes Datum - CSS-id: #lastposts function sem_showLastPosts($num_posts = 10) { global $wpdb; diff --git a/trunk/includes/pChart/GPLv3.txt b/trunk/includes/pChart/GPLv3.txt new file mode 100644 index 0000000..10926e8 --- /dev/null +++ b/trunk/includes/pChart/GPLv3.txt @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + diff --git a/trunk/includes/pChart/change.log b/trunk/includes/pChart/change.log new file mode 100644 index 0000000000000000000000000000000000000000..7b223a6e4e064b2ef148a6501625263b6e235d1c GIT binary patch literal 24242 zcmdU%S8pBH6@}+HK>ouG5Cskr)3W56x2vvzlw^{&6eEE^kyL@$LNY4;@k!Qq7I#jW znOjIYra@4;W#*iHc3ry+|MTzPcE9N+-R89?m;Uqgn%DmB+C)2C?$3A4+DF~(?sd1- z9e1bN=~Mk~>Gw(ZK);jXyEolI_e!7ab#J;Cx|%ya>V5gsu3dh2(bw(TKXkjI;6&6M zin6@=U-bG$x6*yC-JgzNH;M?e6IReeJ)S_J7hn z?(XY%Rll41d3d&WyY{N?I!V0#zB|$`TYAk-tbM)vw)^bt-_Lb|KBe_1?b`LX7kd|L z|9I)z{p8v|k`7wOOIdZ-uGS9}n#zf^Y|@ny+tK@-WC!nMDSP_xy^?O?4-l%KdR?Q1wh& z_*!f1YKPZaeNR`Ju9w}vwAZ%ou=QMQ&1u?W>)dO{{g0A8nLl_JtZOBm3*OH3(<+9PS$q0WIvf0 Dp4B|f~+&z`QzG3UG*xsj+p(ptY94b$$K{QO4u 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 = ""; + $this->Reverse = ""; + + $FileHandle = @fopen($BasePath."data/128B.db", "r"); + + if (!$FileHandle) { die("Cannot find barcode database (".$BasePath."128B.db)."); } + + while (!feof($FileHandle)) + { + $Buffer = fgets($FileHandle,4096); + $Buffer = str_replace(chr(10),"",$Buffer); + $Buffer = str_replace(chr(13),"",$Buffer); + $Values = preg_split("/;/",$Buffer); + + $this->Codes[$Values[1]]["ID"] = $Values[0]; + $this->Codes[$Values[1]]["Code"] = $Values[2]; + $this->Reverse[$Values[0]]["Code"] = $Values[2]; + $this->Reverse[$Values[0]]["Asc"] = $Values[1]; + } + fclose($FileHandle); + } + + /* Return the projected size of a barcode */ + function getSize($TextString,$Format="") + { + $Angle = isset($Format["Angle"]) ? $Format["Angle"] : 0; + $ShowLegend = isset($Format["ShowLegend"]) ? $Format["ShowLegend"] : FALSE; + $LegendOffset = isset($Format["LegendOffset"]) ? $Format["LegendOffset"] : 5; + $DrawArea = isset($Format["DrawArea"]) ? $Format["DrawArea"] : FALSE; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : 12; + $Height = isset($Format["Height"]) ? $Format["Height"] : 30; + + $TextString = $this->encode128($TextString); + $BarcodeLength = strlen($this->Result); + + if ( $DrawArea ) { $WOffset = 20; } else { $WOffset = 0; } + if ( $ShowLegend ) { $HOffset = $FontSize+$LegendOffset+$WOffset; } else { $HOffset = 0; } + + $X1 = cos($Angle * PI / 180) * ($WOffset+$BarcodeLength); + $Y1 = sin($Angle * PI / 180) * ($WOffset+$BarcodeLength); + + $X2 = $X1 + cos(($Angle+90) * PI / 180) * ($HOffset+$Height); + $Y2 = $Y1 + sin(($Angle+90) * PI / 180) * ($HOffset+$Height); + + + $AreaWidth = max(abs($X1),abs($X2)); + $AreaHeight = max(abs($Y1),abs($Y2)); + + return(array("Width"=>$AreaWidth,"Height"=>$AreaHeight)); + } + + function encode128($Value,$Format="") + { + $this->Result = "11010010000"; + $this->CRC = 104; + $TextString = ""; + + for($i=1;$i<=strlen($Value);$i++) + { + $CharCode = ord($this->mid($Value,$i,1)); + if ( isset($this->Codes[$CharCode]) ) + { + $this->Result = $this->Result.$this->Codes[$CharCode]["Code"]; + $this->CRC = $this->CRC + $i*$this->Codes[$CharCode]["ID"]; + $TextString = $TextString.chr($CharCode); + } + } + $this->CRC = $this->CRC - floor($this->CRC/103)*103; + + $this->Result = $this->Result.$this->Reverse[$this->CRC]["Code"]; + $this->Result = $this->Result."1100011101011"; + + return($TextString); + } + + /* Create the encoded string */ + function draw($Object,$Value,$X,$Y,$Format="") + { + $this->pChartObject = $Object; + + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Height = isset($Format["Height"]) ? $Format["Height"] : 30; + $Angle = isset($Format["Angle"]) ? $Format["Angle"] : 0; + $ShowLegend = isset($Format["ShowLegend"]) ? $Format["ShowLegend"] : FALSE; + $LegendOffset = isset($Format["LegendOffset"]) ? $Format["LegendOffset"] : 5; + $DrawArea = isset($Format["DrawArea"]) ? $Format["DrawArea"] : FALSE; + $AreaR = isset($Format["AreaR"]) ? $Format["AreaR"] : 255; + $AreaG = isset($Format["AreaG"]) ? $Format["AreaG"] : 255; + $AreaB = isset($Format["AreaB"]) ? $Format["AreaB"] : 255; + $AreaBorderR = isset($Format["AreaBorderR"]) ? $Format["AreaBorderR"] : $AreaR; + $AreaBorderG = isset($Format["AreaBorderG"]) ? $Format["AreaBorderG"] : $AreaG; + $AreaBorderB = isset($Format["AreaBorderB"]) ? $Format["AreaBorderB"] : $AreaB; + + $TextString = $this->encode128($Value); + + if ( $DrawArea ) + { + $X1 = $X + cos(($Angle-135) * PI / 180) * 10; + $Y1 = $Y + sin(($Angle-135) * PI / 180) * 10; + + $X2 = $X1 + cos($Angle * PI / 180) * (strlen($this->Result)+20); + $Y2 = $Y1 + sin($Angle * PI / 180) * (strlen($this->Result)+20); + + if ( $ShowLegend ) + { + $X3 = $X2 + cos(($Angle+90) * PI / 180) * ($Height+$LegendOffset+$this->pChartObject->FontSize+10); + $Y3 = $Y2 + sin(($Angle+90) * PI / 180) * ($Height+$LegendOffset+$this->pChartObject->FontSize+10); + } + else + { + $X3 = $X2 + cos(($Angle+90) * PI / 180) * ($Height+20); + $Y3 = $Y2 + sin(($Angle+90) * PI / 180) * ($Height+20); + } + + $X4 = $X3 + cos(($Angle+180) * PI / 180) * (strlen($this->Result)+20); + $Y4 = $Y3 + sin(($Angle+180) * PI / 180) * (strlen($this->Result)+20); + + $Polygon = array($X1,$Y1,$X2,$Y2,$X3,$Y3,$X4,$Y4); + $Settings = array("R"=>$AreaR,"G"=>$AreaG,"B"=>$AreaB,"BorderR"=>$AreaBorderR,"BorderG"=>$AreaBorderG,"BorderB"=>$AreaBorderB); + $this->pChartObject->drawPolygon($Polygon,$Settings); + } + + for($i=1;$i<=strlen($this->Result);$i++) + { + if ( $this->mid($this->Result,$i,1) == 1 ) + { + $X1 = $X + cos($Angle * PI / 180) * $i; + $Y1 = $Y + sin($Angle * PI / 180) * $i; + $X2 = $X1 + cos(($Angle+90) * PI / 180) * $Height; + $Y2 = $Y1 + sin(($Angle+90) * PI / 180) * $Height; + + $Settings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + $this->pChartObject->drawLine($X1,$Y1,$X2,$Y2,$Settings); + } + } + + if ( $ShowLegend ) + { + $X1 = $X + cos($Angle * PI / 180) * (strlen($this->Result)/2); + $Y1 = $Y + sin($Angle * PI / 180) * (strlen($this->Result)/2); + + $LegendX = $X1 + cos(($Angle+90) * PI / 180) * ($Height+$LegendOffset); + $LegendY = $Y1 + sin(($Angle+90) * PI / 180) * ($Height+$LegendOffset); + + $Settings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Angle"=>-$Angle,"Align"=>TEXT_ALIGN_TOPMIDDLE); + $this->pChartObject->drawText($LegendX,$LegendY,$TextString,$Settings); + } + } + + function left($value,$NbChar) { return substr($value,0,$NbChar); } + function right($value,$NbChar) { return substr($value,strlen($value)-$NbChar,$NbChar); } + function mid($value,$Depart,$NbChar) { return substr($value,$Depart-1,$NbChar); } + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/class/pBarcode39.class.php b/trunk/includes/pChart/class/pBarcode39.class.php new file mode 100644 index 0000000..554be9b --- /dev/null +++ b/trunk/includes/pChart/class/pBarcode39.class.php @@ -0,0 +1,200 @@ +MOD43 = $EnableMOD43; + $this->Codes = ""; + $this->Reverse = ""; + + $FileHandle = @fopen($BasePath."data/39.db", "r"); + + if (!$FileHandle) { die("Cannot find barcode database (".$BasePath."data/39.db)."); } + + while (!feof($FileHandle)) + { + $Buffer = fgets($FileHandle,4096); + $Buffer = str_replace(chr(10),"",$Buffer); + $Buffer = str_replace(chr(13),"",$Buffer); + $Values = preg_split("/;/",$Buffer); + + $this->Codes[$Values[0]] = $Values[1]; + } + fclose($FileHandle); + } + + /* Return the projected size of a barcode */ + function getSize($TextString,$Format="") + { + $Angle = isset($Format["Angle"]) ? $Format["Angle"] : 0; + $ShowLegend = isset($Format["ShowLegend"]) ? $Format["ShowLegend"] : FALSE; + $LegendOffset = isset($Format["LegendOffset"]) ? $Format["LegendOffset"] : 5; + $DrawArea = isset($Format["DrawArea"]) ? $Format["DrawArea"] : FALSE; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : 12; + $Height = isset($Format["Height"]) ? $Format["Height"] : 30; + + $TextString = $this->encode39($TextString); + $BarcodeLength = strlen($this->Result); + + if ( $DrawArea ) { $WOffset = 20; } else { $WOffset = 0; } + if ( $ShowLegend ) { $HOffset = $FontSize+$LegendOffset+$WOffset; } else { $HOffset = 0; } + + $X1 = cos($Angle * PI / 180) * ($WOffset+$BarcodeLength); + $Y1 = sin($Angle * PI / 180) * ($WOffset+$BarcodeLength); + + $X2 = $X1 + cos(($Angle+90) * PI / 180) * ($HOffset+$Height); + $Y2 = $Y1 + sin(($Angle+90) * PI / 180) * ($HOffset+$Height); + + + $AreaWidth = max(abs($X1),abs($X2)); + $AreaHeight = max(abs($Y1),abs($Y2)); + + return(array("Width"=>$AreaWidth,"Height"=>$AreaHeight)); + } + + /* Create the encoded string */ + function encode39($Value) + { + $this->Result = "100101101101"."0"; + $TextString = ""; + for($i=1;$i<=strlen($Value);$i++) + { + $CharCode = ord($this->mid($Value,$i,1)); + if ( $CharCode >= 97 && $CharCode <= 122 ) { $CharCode = $CharCode - 32; } + + if ( isset($this->Codes[chr($CharCode)]) ) + { + $this->Result = $this->Result.$this->Codes[chr($CharCode)]."0"; + $TextString = $TextString.chr($CharCode); + } + } + + if ( $this->MOD43 ) + { + $Checksum = $this->checksum($TextString); + $this->Result = $this->Result.$this->Codes[$Checksum]."0"; + } + + $this->Result = $this->Result."100101101101"; + $TextString = "*".$TextString."*"; + + return($TextString); + } + + /* Create the encoded string */ + function draw($Object,$Value,$X,$Y,$Format="") + { + $this->pChartObject = $Object; + + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Height = isset($Format["Height"]) ? $Format["Height"] : 30; + $Angle = isset($Format["Angle"]) ? $Format["Angle"] : 0; + $ShowLegend = isset($Format["ShowLegend"]) ? $Format["ShowLegend"] : FALSE; + $LegendOffset = isset($Format["LegendOffset"]) ? $Format["LegendOffset"] : 5; + $DrawArea = isset($Format["DrawArea"]) ? $Format["DrawArea"] : FALSE; + $AreaR = isset($Format["AreaR"]) ? $Format["AreaR"] : 255; + $AreaG = isset($Format["AreaG"]) ? $Format["AreaG"] : 255; + $AreaB = isset($Format["AreaB"]) ? $Format["AreaB"] : 255; + $AreaBorderR = isset($Format["AreaBorderR"]) ? $Format["AreaBorderR"] : $AreaR; + $AreaBorderG = isset($Format["AreaBorderG"]) ? $Format["AreaBorderG"] : $AreaG; + $AreaBorderB = isset($Format["AreaBorderB"]) ? $Format["AreaBorderB"] : $AreaB; + + $TextString = $this->encode39($Value); + + if ( $DrawArea ) + { + $X1 = $X + cos(($Angle-135) * PI / 180) * 10; + $Y1 = $Y + sin(($Angle-135) * PI / 180) * 10; + + $X2 = $X1 + cos($Angle * PI / 180) * (strlen($this->Result)+20); + $Y2 = $Y1 + sin($Angle * PI / 180) * (strlen($this->Result)+20); + + if ( $ShowLegend ) + { + $X3 = $X2 + cos(($Angle+90) * PI / 180) * ($Height+$LegendOffset+$this->pChartObject->FontSize+10); + $Y3 = $Y2 + sin(($Angle+90) * PI / 180) * ($Height+$LegendOffset+$this->pChartObject->FontSize+10); + } + else + { + $X3 = $X2 + cos(($Angle+90) * PI / 180) * ($Height+20); + $Y3 = $Y2 + sin(($Angle+90) * PI / 180) * ($Height+20); + } + + $X4 = $X3 + cos(($Angle+180) * PI / 180) * (strlen($this->Result)+20); + $Y4 = $Y3 + sin(($Angle+180) * PI / 180) * (strlen($this->Result)+20); + + $Polygon = array($X1,$Y1,$X2,$Y2,$X3,$Y3,$X4,$Y4); + $Settings = array("R"=>$AreaR,"G"=>$AreaG,"B"=>$AreaB,"BorderR"=>$AreaBorderR,"BorderG"=>$AreaBorderG,"BorderB"=>$AreaBorderB); + $this->pChartObject->drawPolygon($Polygon,$Settings); + } + + for($i=1;$i<=strlen($this->Result);$i++) + { + if ( $this->mid($this->Result,$i,1) == 1 ) + { + $X1 = $X + cos($Angle * PI / 180) * $i; + $Y1 = $Y + sin($Angle * PI / 180) * $i; + $X2 = $X1 + cos(($Angle+90) * PI / 180) * $Height; + $Y2 = $Y1 + sin(($Angle+90) * PI / 180) * $Height; + + $Settings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + $this->pChartObject->drawLine($X1,$Y1,$X2,$Y2,$Settings); + } + } + + if ( $ShowLegend ) + { + $X1 = $X + cos($Angle * PI / 180) * (strlen($this->Result)/2); + $Y1 = $Y + sin($Angle * PI / 180) * (strlen($this->Result)/2); + + $LegendX = $X1 + cos(($Angle+90) * PI / 180) * ($Height+$LegendOffset); + $LegendY = $Y1 + sin(($Angle+90) * PI / 180) * ($Height+$LegendOffset); + + $Settings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Angle"=>-$Angle,"Align"=>TEXT_ALIGN_TOPMIDDLE); + $this->pChartObject->drawText($LegendX,$LegendY,$TextString,$Settings); + } + } + + function checksum( $string ) + { + $checksum = 0; + $length = strlen( $string ); + $charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%'; + + for( $i=0; $i < $length; ++$i ) + $checksum += strpos( $charset, $string[$i] ); + + return substr( $charset, ($checksum % 43), 1 ); + } + + function left($value,$NbChar) { return substr($value,0,$NbChar); } + function right($value,$NbChar) { return substr($value,strlen($value)-$NbChar,$NbChar); } + function mid($value,$Depart,$NbChar) { return substr($value,$Depart-1,$NbChar); } + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/class/pBubble.class.php b/trunk/includes/pChart/class/pBubble.class.php new file mode 100644 index 0000000..dbe123f --- /dev/null +++ b/trunk/includes/pChart/class/pBubble.class.php @@ -0,0 +1,326 @@ +pChartObject = $pChartObject; + $this->pDataObject = $pDataObject; + } + + /* Prepare the scale */ + function bubbleScale($DataSeries,$WeightSeries) + { + if ( !is_array($DataSeries) ) { $DataSeries = array($DataSeries); } + if ( !is_array($WeightSeries) ) { $WeightSeries = array($WeightSeries); } + + /* Parse each data series to find the new min & max boundaries to scale */ + $NewPositiveSerie = ""; $NewNegativeSerie = ""; $MaxValues = 0; $LastPositive = 0; $LastNegative = 0; + foreach($DataSeries as $Key => $SerieName) + { + $SerieWeightName = $WeightSeries[$Key]; + + $this->pDataObject->setSerieDrawable($SerieWeightName,FALSE); + + if ( count($this->pDataObject->Data["Series"][$SerieName]["Data"]) > $MaxValues ) { $MaxValues = count($this->pDataObject->Data["Series"][$SerieName]["Data"]); } + + foreach($this->pDataObject->Data["Series"][$SerieName]["Data"] as $Key => $Value) + { + if ( $Value >= 0 ) + { + $BubbleBounds = $Value + $this->pDataObject->Data["Series"][$SerieWeightName]["Data"][$Key]; + + if ( !isset($NewPositiveSerie[$Key]) ) + { $NewPositiveSerie[$Key] = $BubbleBounds; } + elseif ( $NewPositiveSerie[$Key] < $BubbleBounds ) + { $NewPositiveSerie[$Key] = $BubbleBounds; } + + $LastPositive = $BubbleBounds; + } + else + { + $BubbleBounds = $Value - $this->pDataObject->Data["Series"][$SerieWeightName]["Data"][$Key]; + + if ( !isset($NewNegativeSerie[$Key]) ) + { $NewNegativeSerie[$Key] = $BubbleBounds; } + elseif ( $NewNegativeSerie[$Key] > $BubbleBounds ) + { $NewNegativeSerie[$Key] = $BubbleBounds; } + + $LastNegative = $BubbleBounds; + } + } + } + + /* Check for missing values and all the fake positive serie */ + if ( $NewPositiveSerie != "" ) + { + for ($i=0; $i<$MaxValues; $i++) { if (!isset($NewPositiveSerie[$i])) { $NewPositiveSerie[$i] = $LastPositive; } } + + $this->pDataObject->addPoints($NewPositiveSerie,"BubbleFakePositiveSerie"); + } + + /* Check for missing values and all the fake negative serie */ + if ( $NewNegativeSerie != "" ) + { + for ($i=0; $i<$MaxValues; $i++) { if (!isset($NewNegativeSerie[$i])) { $NewNegativeSerie[$i] = $LastNegative; } } + + $this->pDataObject->addPoints($NewNegativeSerie,"BubbleFakeNegativeSerie"); + } + } + + function resetSeriesColors() + { + $Data = $this->pDataObject->getData(); + $Palette = $this->pDataObject->getPalette(); + + $ID = 0; + foreach($Data["Series"] as $SerieName => $SeriesParameters) + { + if ( $SeriesParameters["isDrawable"] ) + { + $this->pDataObject->Data["Series"][$SerieName]["Color"]["R"] = $Palette[$ID]["R"]; + $this->pDataObject->Data["Series"][$SerieName]["Color"]["G"] = $Palette[$ID]["G"]; + $this->pDataObject->Data["Series"][$SerieName]["Color"]["B"] = $Palette[$ID]["B"]; + $this->pDataObject->Data["Series"][$SerieName]["Color"]["Alpha"] = $Palette[$ID]["Alpha"]; + $ID++; + } + } + } + + /* Prepare the scale */ + function drawBubbleChart($DataSeries,$WeightSeries,$Format="") + { + $ForceAlpha = isset($Format["ForceAlpha"]) ? $Format["ForceAlpha"] : VOID; + $DrawBorder = isset($Format["DrawBorder"]) ? $Format["DrawBorder"] : TRUE; + $BorderWidth = isset($Format["BorderWidth"]) ? $Format["BorderWidth"] : 1; + $Shape = isset($Format["Shape"]) ? $Format["Shape"] : BUBBLE_SHAPE_ROUND; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 0; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 0; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 0; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : 30; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + + if ( !is_array($DataSeries) ) { $DataSeries = array($DataSeries); } + if ( !is_array($WeightSeries) ) { $WeightSeries = array($WeightSeries); } + + $Data = $this->pDataObject->getData(); + $Palette = $this->pDataObject->getPalette(); + + if ( isset($Data["Series"]["BubbleFakePositiveSerie"] ) ) { $this->pDataObject->setSerieDrawable("BubbleFakePositiveSerie",FALSE); } + if ( isset($Data["Series"]["BubbleFakeNegativeSerie"] ) ) { $this->pDataObject->setSerieDrawable("BubbleFakeNegativeSerie",FALSE); } + + $this->resetSeriesColors(); + + list($XMargin,$XDivs) = $this->pChartObject->scaleGetXSettings(); + + foreach($DataSeries as $Key => $SerieName) + { + $AxisID = $Data["Series"][$SerieName]["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + if (isset($Data["Series"][$SerieName]["Description"])) { $SerieDescription = $Data["Series"][$SerieName]["Description"]; } else { $SerieDescription = $SerieName; } + + $XStep = ($this->pChartObject->GraphAreaX2-$this->pChartObject->GraphAreaX1-$XMargin*2)/$XDivs; + + $X = $this->pChartObject->GraphAreaX1 + $XMargin; + $Y = $this->pChartObject->GraphAreaY1 + $XMargin; + + $Color = array("R"=>$Palette[$Key]["R"],"G"=>$Palette[$Key]["G"],"B"=>$Palette[$Key]["B"],"Alpha"=>$Palette[$Key]["Alpha"]); + + if ( $ForceAlpha != VOID ) { $Color["Alpha"]=$ForceAlpha; } + + if ( $DrawBorder ) + { + if ( $BorderWidth != 1 ) + { + if ( $Surrounding != NULL ) + { $BorderR = $Palette[$Key]["R"]+$Surrounding; $BorderG = $Palette[$Key]["G"]+$Surrounding; $BorderB = $Palette[$Key]["B"]+$Surrounding; } + else + { $BorderR = $BorderR; $BorderG = $BorderG; $BorderB = $BorderB; } + if ( $ForceAlpha != VOID ) { $BorderAlpha = $ForceAlpha/2; } + $BorderColor = array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha); + } + else + { + $Color["BorderAlpha"] = $BorderAlpha; + + if ( $Surrounding != NULL ) + { $Color["BorderR"] = $Palette[$Key]["R"]+$Surrounding; $Color["BorderG"] = $Palette[$Key]["G"]+$Surrounding; $Color["BorderB"] = $Palette[$Key]["B"]+$Surrounding; } + else + { $Color["BorderR"] = $BorderR; $Color["BorderG"] = $BorderG; $Color["BorderB"] = $BorderB; } + if ( $ForceAlpha != VOID ) { $Color["BorderAlpha"] = $ForceAlpha/2; } + } + } + + foreach($Data["Series"][$SerieName]["Data"] as $iKey => $Point) + { + $Weight = $Point + $Data["Series"][$WeightSeries[$Key]]["Data"][$iKey]; + + $PosArray = $this->pChartObject->scaleComputeY($Point,array("AxisID"=>$AxisID)); + $WeightArray = $this->pChartObject->scaleComputeY($Weight,array("AxisID"=>$AxisID)); + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = 0; } else { $XStep = ($this->pChartObject->GraphAreaX2-$this->pChartObject->GraphAreaX1-$XMargin*2)/$XDivs; } + $Y = floor($PosArray); $CircleRadius = floor(abs($PosArray - $WeightArray)/2); + + if ( $Shape == BUBBLE_SHAPE_SQUARE ) + { + if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("RECT",floor($X-$CircleRadius).",".floor($Y-$CircleRadius).",".floor($X+$CircleRadius).",".floor($Y+$CircleRadius),$this->pChartObject->toHTMLColor($Palette[$Key]["R"],$Palette[$Key]["G"],$Palette[$Key]["B"]),$SerieDescription,$Data["Series"][$WeightSeries[$Key]]["Data"][$iKey]); } + + if ( $BorderWidth != 1 ) + { + $this->pChartObject->drawFilledRectangle($X-$CircleRadius-$BorderWidth,$Y-$CircleRadius-$BorderWidth,$X+$CircleRadius+$BorderWidth,$Y+$CircleRadius+$BorderWidth,$BorderColor); + $this->pChartObject->drawFilledRectangle($X-$CircleRadius,$Y-$CircleRadius,$X+$CircleRadius,$Y+$CircleRadius,$Color); + } + else + $this->pChartObject->drawFilledRectangle($X-$CircleRadius,$Y-$CircleRadius,$X+$CircleRadius,$Y+$CircleRadius,$Color); + } + elseif ( $Shape == BUBBLE_SHAPE_ROUND ) + { + if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".floor($CircleRadius),$this->pChartObject->toHTMLColor($Palette[$Key]["R"],$Palette[$Key]["G"],$Palette[$Key]["B"]),$SerieDescription,$Data["Series"][$WeightSeries[$Key]]["Data"][$iKey]); } + + if ( $BorderWidth != 1 ) + { + $this->pChartObject->drawFilledCircle($X,$Y,$CircleRadius+$BorderWidth,$BorderColor); + $this->pChartObject->drawFilledCircle($X,$Y,$CircleRadius,$Color); + } + else + $this->pChartObject->drawFilledCircle($X,$Y,$CircleRadius,$Color); + } + + $X = $X + $XStep; + } + elseif ( $Data["Orientation"] == SCALE_POS_TOPBOTTOM ) + { + if ( $XDivs == 0 ) { $XStep = 0; } else { $XStep = ($this->pChartObject->GraphAreaY2-$this->pChartObject->GraphAreaY1-$XMargin*2)/$XDivs; } + $X = floor($PosArray); $CircleRadius = floor(abs($PosArray - $WeightArray)/2); + + if ( $Shape == BUBBLE_SHAPE_SQUARE ) + { + if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("RECT",floor($X-$CircleRadius).",".floor($Y-$CircleRadius).",".floor($X+$CircleRadius).",".floor($Y+$CircleRadius),$this->pChartObject->toHTMLColor($Palette[$Key]["R"],$Palette[$Key]["G"],$Palette[$Key]["B"]),$SerieDescription,$Data["Series"][$WeightSeries[$Key]]["Data"][$iKey]); } + + if ( $BorderWidth != 1 ) + { + $this->pChartObject->drawFilledRectangle($X-$CircleRadius-$BorderWidth,$Y-$CircleRadius-$BorderWidth,$X+$CircleRadius+$BorderWidth,$Y+$CircleRadius+$BorderWidth,$BorderColor); + $this->pChartObject->drawFilledRectangle($X-$CircleRadius,$Y-$CircleRadius,$X+$CircleRadius,$Y+$CircleRadius,$Color); + } + else + $this->pChartObject->drawFilledRectangle($X-$CircleRadius,$Y-$CircleRadius,$X+$CircleRadius,$Y+$CircleRadius,$Color); + } + elseif ( $Shape == BUBBLE_SHAPE_ROUND ) + { + if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".floor($CircleRadius),$this->pChartObject->toHTMLColor($Palette[$Key]["R"],$Palette[$Key]["G"],$Palette[$Key]["B"]),$SerieDescription,$Data["Series"][$WeightSeries[$Key]]["Data"][$iKey]); } + + if ( $BorderWidth != 1 ) + { + $this->pChartObject->drawFilledCircle($X,$Y,$CircleRadius+$BorderWidth,$BorderColor); + $this->pChartObject->drawFilledCircle($X,$Y,$CircleRadius,$Color); + } + else + $this->pChartObject->drawFilledCircle($X,$Y,$CircleRadius,$Color); + } + + $Y = $Y + $XStep; + } + } + } + } + + function writeBubbleLabel($SerieName,$SerieWeightName,$Points,$Format="") + { + $OverrideTitle = isset($Format["OverrideTitle"]) ? $Format["OverrideTitle"] : NULL; + $DrawPoint = isset($Format["DrawPoint"]) ? $Format["DrawPoint"] : LABEL_POINT_BOX; + + if ( !is_array($Points) ) { $Point = $Points; $Points = ""; $Points[] = $Point; } + + $Data = $this->pDataObject->getData(); + $Palette = $this->pDataObject->getPalette(); + + if ( !isset($Data["Series"][$SerieName]) || !isset($Data["Series"][$SerieWeightName]) ) + return(0); + + list($XMargin,$XDivs) = $this->pChartObject->scaleGetXSettings(); + + $AxisID = $Data["Series"][$SerieName]["Axis"]; + $AxisMode = $Data["Axis"][$AxisID]["Display"]; + $AxisFormat = $Data["Axis"][$AxisID]["Format"]; + $AxisUnit = $Data["Axis"][$AxisID]["Unit"]; + $XStep = ($this->pChartObject->GraphAreaX2-$this->pChartObject->GraphAreaX1-$XMargin*2)/$XDivs; + + $X = $this->pChartObject->GraphAreaX1 + $XMargin; + $Y = $this->pChartObject->GraphAreaY1 + $XMargin; + + $Color = array("R"=>$Data["Series"][$SerieName]["Color"]["R"],"G"=>$Data["Series"][$SerieName]["Color"]["G"],"B"=>$Data["Series"][$SerieName]["Color"]["B"],"Alpha"=>$Data["Series"][$SerieName]["Color"]["Alpha"]); + + foreach($Points as $Key => $Point) + { + $Value = $Data["Series"][$SerieName]["Data"][$Point]; + $PosArray = $this->pChartObject->scaleComputeY($Value,array("AxisID"=>$AxisID)); + + if ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Point]) ) + $Abscissa = $Data["Series"][$Data["Abscissa"]]["Data"][$Point]." : "; + else + $Abscissa = ""; + + $Value = $this->pChartObject->scaleFormat($Value,$AxisMode,$AxisFormat,$AxisUnit); + $Weight = $Data["Series"][$SerieWeightName]["Data"][$Point]; + $Caption = $Abscissa.$Value." / ".$Weight; + + if ( isset($Data["Series"][$SerieName]["Description"]) ) + $Description = $Data["Series"][$SerieName]["Description"]; + else + $Description = "No description"; + + $Series = ""; + $Series[] = array("Format"=>$Color,"Caption"=>$Caption); + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = 0; } else { $XStep = ($this->pChartObject->GraphAreaX2-$this->pChartObject->GraphAreaX1-$XMargin*2)/$XDivs; } + + $X = floor($X + $Point * $XStep); + $Y = floor($PosArray); + } + else + { + if ( $XDivs == 0 ) { $YStep = 0; } else { $YStep = ($this->pChartObject->GraphAreaY2-$this->pChartObject->GraphAreaY1-$XMargin*2)/$XDivs; } + + $X = floor($PosArray); + $Y = floor($Y + $Point * $YStep); + } + + if ( $DrawPoint == LABEL_POINT_CIRCLE ) + $this->pChartObject->drawFilledCircle($X,$Y,3,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0)); + elseif ( $DrawPoint == LABEL_POINT_BOX ) + $this->pChartObject->drawFilledRectangle($X-2,$Y-2,$X+2,$Y+2,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0)); + + $this->pChartObject->drawLabelBox($X,$Y-3,$Description,$Series,$Format); + } + } + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/class/pCache.class.php b/trunk/includes/pChart/class/pCache.class.php new file mode 100644 index 0000000..4e4a450 --- /dev/null +++ b/trunk/includes/pChart/class/pCache.class.php @@ -0,0 +1,280 @@ +CacheFolder = $CacheFolder; + $this->CacheIndex = $CacheIndex; + $this->CacheDB = $CacheDB; + + if (!file_exists($this->CacheFolder."/".$this->CacheIndex)) { touch($this->CacheFolder."/".$this->CacheIndex); } + if (!file_exists($this->CacheFolder."/".$this->CacheDB)) { touch($this->CacheFolder."/".$this->CacheDB); } + } + + /* Flush the cache contents */ + function flush() + { + if (file_exists($this->CacheFolder."/".$this->CacheIndex)) { unlink($this->CacheFolder."/".$this->CacheIndex); touch($this->CacheFolder."/".$this->CacheIndex); } + if (file_exists($this->CacheFolder."/".$this->CacheDB)) { unlink($this->CacheFolder."/".$this->CacheDB); touch($this->CacheFolder."/".$this->CacheDB); } + } + + /* Return the MD5 of the data array to clearly identify the chart */ + function getHash($Data,$Marker="") + { return(md5($Marker.serialize($Data->Data))); } + + /* Write the generated picture to the cache */ + function writeToCache($ID,$pChartObject) + { + /* Compute the paths */ + $TemporaryFile = $this->CacheFolder."/tmp_".rand(0,1000).".png"; + $Database = $this->CacheFolder."/".$this->CacheDB; + $Index = $this->CacheFolder."/".$this->CacheIndex; + + /* Flush the picture to a temporary file */ + imagepng($pChartObject->Picture ,$TemporaryFile); + + /* Retrieve the files size */ + $PictureSize = filesize($TemporaryFile); + $DBSize = filesize($Database); + + /* Save the index */ + $Handle = fopen($Index,"a"); + fwrite($Handle, $ID.",".$DBSize.",".$PictureSize.",".time().",0 \r\n"); + fclose($Handle); + + /* Get the picture raw contents */ + $Handle = fopen($TemporaryFile,"r"); + $Raw = fread($Handle,$PictureSize); + fclose($Handle); + + /* Save the picture in the solid database file */ + $Handle = fopen($Database,"a"); + fwrite($Handle, $Raw); + fclose($Handle); + + /* Remove temporary file */ + unlink($TemporaryFile); + } + + /* Remove object older than the specified TS */ + function removeOlderThan($Expiry) + { $this->dbRemoval(array("Expiry"=>$Expiry)); } + + /* Remove an object from the cache */ + function remove($ID) + { $this->dbRemoval(array("Name"=>$ID)); } + + /* Remove with specified criterias */ + function dbRemoval($Settings) + { + $ID = isset($Settings["Name"]) ? $Settings["Name"] : NULL; + $Expiry = isset($Settings["Expiry"]) ? $Settings["Expiry"] : -(24*60*60); + $TS = time()-$Expiry; + + /* Compute the paths */ + $Database = $this->CacheFolder."/".$this->CacheDB; + $Index = $this->CacheFolder."/".$this->CacheIndex; + $DatabaseTemp = $this->CacheFolder."/".$this->CacheDB.".tmp"; + $IndexTemp = $this->CacheFolder."/".$this->CacheIndex.".tmp"; + + /* Single file removal */ + if ( $ID != NULL ) + { + /* Retrieve object informations */ + $Object = $this->isInCache($ID,TRUE); + + /* If it's not in the cache DB, go away */ + if ( !$Object ) { return(0); } + } + + /* Create the temporary files */ + if (!file_exists($DatabaseTemp)) { touch($DatabaseTemp); } + if (!file_exists($IndexTemp)) { touch($IndexTemp); } + + /* Open the file handles */ + $IndexHandle = @fopen($Index, "r"); + $IndexTempHandle = @fopen($IndexTemp, "w"); + $DBHandle = @fopen($Database, "r"); + $DBTempHandle = @fopen($DatabaseTemp, "w"); + + /* Remove the selected ID from the database */ + while (!feof($IndexHandle)) + { + $Entry = fgets($IndexHandle, 4096); + $Entry = str_replace("\r","",$Entry); + $Entry = str_replace("\n","",$Entry); + $Settings = preg_split("/,/",$Entry); + + if ( $Entry != "" ) + { + $PicID = $Settings[0]; + $DBPos = $Settings[1]; + $PicSize = $Settings[2]; + $GeneratedTS = $Settings[3]; + $Hits = $Settings[4]; + + if ( $Settings[0] != $ID && $GeneratedTS > $TS) + { + $CurrentPos = ftell($DBTempHandle); + fwrite($IndexTempHandle, $PicID.",".$CurrentPos.",".$PicSize.",".$GeneratedTS.",".$Hits."\r\n"); + + fseek($DBHandle,$DBPos); + $Picture = fread($DBHandle,$PicSize); + fwrite($DBTempHandle,$Picture); + } + } + } + + /* Close the handles */ + fclose($IndexHandle); + fclose($IndexTempHandle); + fclose($DBHandle); + fclose($DBTempHandle); + + /* Remove the prod files */ + unlink($Database); + unlink($Index); + + /* Swap the temp & prod DB */ + rename($DatabaseTemp,$Database); + rename($IndexTemp,$Index); + } + + function isInCache($ID,$Verbose=FALSE,$UpdateHitsCount=FALSE) + { + /* Compute the paths */ + $Index = $this->CacheFolder."/".$this->CacheIndex; + + /* Search the picture in the index file */ + $Handle = @fopen($Index, "r"); + while (!feof($Handle)) + { + $IndexPos = ftell($Handle); + $Entry = fgets($Handle, 4096); + if ( $Entry != "" ) + { + $Settings = preg_split("/,/",$Entry); + $PicID = $Settings[0]; + if ( $PicID == $ID ) + { + fclose($Handle); + + $DBPos = $Settings[1]; + $PicSize = $Settings[2]; + $GeneratedTS = $Settings[3]; + $Hits = intval($Settings[4]); + + if ( $UpdateHitsCount ) + { + $Hits++; + if ( strlen($Hits) < 7 ) { $Hits = $Hits.str_repeat(" ",7-strlen($Hits)); } + + $Handle = @fopen($Index, "r+"); + fseek($Handle,$IndexPos); + fwrite($Handle, $PicID.",".$DBPos.",".$PicSize.",".$GeneratedTS.",".$Hits."\r\n"); + fclose($Handle); + } + + if ($Verbose) + { return(array("DBPos"=>$DBPos,"PicSize"=>$PicSize,"GeneratedTS"=>$GeneratedTS,"Hits"=>$Hits)); } + else + { return(TRUE); } + } + } + } + fclose($Handle); + + /* Picture isn't in the cache */ + return(FALSE); + } + + /* Automatic output method based on the calling interface */ + function autoOutput($ID,$Destination="output.png") + { + if (php_sapi_name() == "cli") + $this->saveFromCache($ID,$Destination); + else + $this->strokeFromCache($ID); + } + + function strokeFromCache($ID) + { + /* Get the raw picture from the cache */ + $Picture = $this->getFromCache($ID); + + /* Do we have a hit? */ + if ( $Picture == NULL ) { return(FALSE); } + + header('Content-type: image/png'); + echo $Picture; + + return(TRUE); + } + + function saveFromCache($ID,$Destination) + { + /* Get the raw picture from the cache */ + $Picture = $this->getFromCache($ID); + + /* Do we have a hit? */ + if ( $Picture == NULL ) { return(FALSE); } + + /* Flush the picture to a file */ + $Handle = fopen($Destination,"w"); + fwrite($Handle,$Picture); + fclose($Handle); + + /* All went fine */ + return(TRUE); + } + + function getFromCache($ID) + { + /* Compute the path */ + $Database = $this->CacheFolder."/".$this->CacheDB; + + /* Lookup for the picture in the cache */ + $CacheInfo = $this->isInCache($ID,TRUE,TRUE); + + /* Not in the cache */ + if (!$CacheInfo) { return(NULL); } + + /* Get the database extended information */ + $DBPos = $CacheInfo["DBPos"]; + $PicSize = $CacheInfo["PicSize"]; + + /* Extract the picture from the solid cache file */ + $Handle = @fopen($Database, "r"); + fseek($Handle,$DBPos); + $Picture = fread($Handle,$PicSize); + fclose($Handle); + + /* Return back the raw picture data */ + return($Picture); + } + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/class/pData.class.php b/trunk/includes/pChart/class/pData.class.php new file mode 100644 index 0000000..2750519 --- /dev/null +++ b/trunk/includes/pChart/class/pData.class.php @@ -0,0 +1,787 @@ +array("R"=>188,"G"=>224,"B"=>46,"Alpha"=>100), + "1"=>array("R"=>224,"G"=>100,"B"=>46,"Alpha"=>100), + "2"=>array("R"=>224,"G"=>214,"B"=>46,"Alpha"=>100), + "3"=>array("R"=>46,"G"=>151,"B"=>224,"Alpha"=>100), + "4"=>array("R"=>176,"G"=>46,"B"=>224,"Alpha"=>100), + "5"=>array("R"=>224,"G"=>46,"B"=>117,"Alpha"=>100), + "6"=>array("R"=>92,"G"=>224,"B"=>46,"Alpha"=>100), + "7"=>array("R"=>224,"G"=>176,"B"=>46,"Alpha"=>100)); + + /* Class creator */ + function pData() + { + $this->Data = ""; + $this->Data["XAxisDisplay"] = AXIS_FORMAT_DEFAULT; + $this->Data["XAxisFormat"] = NULL; + $this->Data["XAxisName"] = NULL; + $this->Data["XAxisUnit"] = NULL; + $this->Data["Abscissa"] = NULL; + $this->Data["AbsicssaPosition"] = AXIS_POSITION_BOTTOM; + + $this->Data["Axis"][0]["Display"] = AXIS_FORMAT_DEFAULT; + $this->Data["Axis"][0]["Position"] = AXIS_POSITION_LEFT; + $this->Data["Axis"][0]["Identity"] = AXIS_Y; + } + + /* Add a single point or an array to the given serie */ + function addPoints($Values,$SerieName="Serie1") + { + if (!isset($this->Data["Series"][$SerieName])) + $this->initialise($SerieName); + + if ( is_array($Values) ) + { + foreach($Values as $Key => $Value) + { $this->Data["Series"][$SerieName]["Data"][] = $Value; } + } + else + $this->Data["Series"][$SerieName]["Data"][] = $Values; + + if ( $Values != VOID ) + { + $StrippedData = $this->stripVOID($this->Data["Series"][$SerieName]["Data"]); + if ( empty($StrippedData) ) { $this->Data["Series"][$SerieName]["Max"] = 0; $this->Data["Series"][$SerieName]["Min"] =0; return(0); } + $this->Data["Series"][$SerieName]["Max"] = max($StrippedData); + $this->Data["Series"][$SerieName]["Min"] = min($StrippedData); + } + } + + /* Strip VOID values */ + function stripVOID($Values) + { if (!is_array($Values)) { return(array()); } $Result = array(); foreach($Values as $Key => $Value) { if ( $Value != VOID ) { $Result[] = $Value; } } return($Result); } + + /* Return the number of values contained in a given serie */ + function getSerieCount($Serie) + { if (isset($this->Data["Series"][$Serie]["Data"])) { return(sizeof($this->Data["Series"][$Serie]["Data"])); } else { return(0); } } + + /* Remove a serie from the pData object */ + function removeSerie($Series) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + foreach($Series as $Key => $Serie) { if (isset($this->Data["Series"][$Serie])) { unset($this->Data["Series"][$Serie]); } } + } + + /* Return a value from given serie & index */ + function getValueAt($Serie,$Index=0) + { if (isset($this->Data["Series"][$Serie]["Data"][$Index])) { return($this->Data["Series"][$Serie]["Data"][$Index]); } else { return(NULL); } } + + /* Return the values array */ + function getValues($Serie) + { if (isset($this->Data["Series"][$Serie]["Data"])) { return($this->Data["Series"][$Serie]["Data"]); } else { return(NULL); } } + + /* Reverse the values in the given serie */ + function reverseSerie($Series) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + foreach($Series as $Key => $Serie) { if (isset($this->Data["Series"][$Serie]["Data"])) { $this->Data["Series"][$Serie]["Data"] = array_reverse($this->Data["Series"][$Serie]["Data"]); } } + } + + /* Return the sum of the serie values */ + function getSum($Serie) + { if (isset($this->Data["Series"][$Serie])) { return(array_sum($this->Data["Series"][$Serie]["Data"])); } else { return(NULL); } } + + /* Return the max value of a given serie */ + function getMax($Serie) + { if (isset($this->Data["Series"][$Serie]["Max"])) { return($this->Data["Series"][$Serie]["Max"]); } else { return(NULL); } } + + /* Return the min value of a given serie */ + function getMin($Serie) + { if (isset($this->Data["Series"][$Serie]["Min"])) { return($this->Data["Series"][$Serie]["Min"]); } else { return(NULL); } } + + /* Set the description of a given serie */ + function setSerieShape($Series,$Shape=SERIE_SHAPE_FILLEDCIRCLE) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + foreach($Series as $Key => $Serie) { if (isset($this->Data["Series"][$Serie]) ) { $this->Data["Series"][$Serie]["Shape"] = $Shape; } } + } + + /* Set the description of a given serie */ + function setSerieDescription($Series,$Description="My serie") + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + foreach($Series as $Key => $Serie) { if (isset($this->Data["Series"][$Serie]) ) { $this->Data["Series"][$Serie]["Description"] = $Description; } } + } + + /* Set a serie as "drawable" while calling a rendering function */ + function setSerieDrawable($Series,$Drawable=TRUE) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + foreach($Series as $Key => $Serie) { if (isset($this->Data["Series"][$Serie]) ) { $this->Data["Series"][$Serie]["isDrawable"] = $Drawable; } } + } + + /* Set the icon associated to a given serie */ + function setSeriePicture($Series,$Picture=NULL) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + foreach($Series as $Key => $Serie) { if (isset($this->Data["Series"][$Serie]) ) { $this->Data["Series"][$Serie]["Picture"] = $Picture; } } + } + + /* Set the name of the X Axis */ + function setXAxisName($Name) + { $this->Data["XAxisName"] = $Name; } + + /* Set the display mode of the X Axis */ + function setXAxisDisplay($Mode,$Format=NULL) + { $this->Data["XAxisDisplay"] = $Mode; $this->Data["XAxisFormat"] = $Format; } + + /* Set the unit that will be displayed on the X axis */ + function setXAxisUnit($Unit) + { $this->Data["XAxisUnit"] = $Unit; } + + /* Set the serie that will be used as abscissa */ + function setAbscissa($Serie) + { if (isset($this->Data["Series"][$Serie])) { $this->Data["Abscissa"] = $Serie; } } + + function setAbsicssaPosition($Position = AXIS_POSITION_BOTTOM) + { $this->Data["AbsicssaPosition"] = $Position; } + + /* Set the name of the abscissa axis */ + function setAbscissaName($Name) + { $this->Data["AbscissaName"] = $Name; } + + /* Create a scatter group specifyin X and Y data series */ + function setScatterSerie($SerieX,$SerieY,$ID=0) + { if (isset($this->Data["Series"][$SerieX]) && isset($this->Data["Series"][$SerieY]) ) { $this->initScatterSerie($ID); $this->Data["ScatterSeries"][$ID]["X"] = $SerieX; $this->Data["ScatterSeries"][$ID]["Y"] = $SerieY; } } + + /* Set the shape of a given sctatter serie */ + function setScatterSerieShape($ID,$Shape=SERIE_SHAPE_FILLEDCIRCLE) + { if (isset($this->Data["ScatterSeries"][$ID]) ) { $this->Data["ScatterSeries"][$ID]["Shape"] = $Shape; } } + + /* Set the description of a given scatter serie */ + function setScatterSerieDescription($ID,$Description="My serie") + { if (isset($this->Data["ScatterSeries"][$ID]) ) { $this->Data["ScatterSeries"][$ID]["Description"] = $Description; } } + + /* Set the icon associated to a given scatter serie */ + function setScatterSeriePicture($ID,$Picture=NULL) + { if (isset($this->Data["ScatterSeries"][$ID]) ) { $this->Data["ScatterSeries"][$ID]["Picture"] = $Picture; } } + + /* Set a scatter serie as "drawable" while calling a rendering function */ + function setScatterSerieDrawable($ID ,$Drawable=TRUE) + { if (isset($this->Data["ScatterSeries"][$ID]) ) { $this->Data["ScatterSeries"][$ID]["isDrawable"] = $Drawable; } } + + /* Define if a scatter serie should be draw with ticks */ + function setScatterSerieTicks($ID,$Width=0) + { if ( isset($this->Data["ScatterSeries"][$ID]) ) { $this->Data["ScatterSeries"][$ID]["Ticks"] = $Width; } } + + /* Define if a scatter serie should be draw with a special weight */ + function setScatterSerieWeight($ID,$Weight=0) + { if ( isset($this->Data["ScatterSeries"][$ID]) ) { $this->Data["ScatterSeries"][$ID]["Weight"] = $Weight; } } + + /* Associate a color to a scatter serie */ + function setScatterSerieColor($ID,$Format) + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + + if ( isset($this->Data["ScatterSeries"][$ID]) ) + { + $this->Data["ScatterSeries"][$ID]["Color"]["R"] = $R; + $this->Data["ScatterSeries"][$ID]["Color"]["G"] = $G; + $this->Data["ScatterSeries"][$ID]["Color"]["B"] = $B; + $this->Data["ScatterSeries"][$ID]["Color"]["Alpha"] = $Alpha; + } + } + + /* Compute the series limits for an individual and global point of view */ + function limits() + { + $GlobalMin = ABSOLUTE_MAX; + $GlobalMax = ABSOLUTE_MIN; + + foreach($this->Data["Series"] as $Key => $Value) + { + if ( $this->Data["Abscissa"] != $Key && $this->Data["Series"][$Key]["isDrawable"] == TRUE) + { + if ( $GlobalMin > $this->Data["Series"][$Key]["Min"] ) { $GlobalMin = $this->Data["Series"][$Key]["Min"]; } + if ( $GlobalMax < $this->Data["Series"][$Key]["Max"] ) { $GlobalMax = $this->Data["Series"][$Key]["Max"]; } + } + } + $this->Data["Min"] = $GlobalMin; + $this->Data["Max"] = $GlobalMax; + + return(array($GlobalMin,$GlobalMax)); + } + + /* Mark all series as drawable */ + function drawAll() + { foreach($this->Data["Series"] as $Key => $Value) { if ( $this->Data["Abscissa"] != $Key ) { $this->Data["Series"][$Key]["isDrawable"]=TRUE; } } } + + /* Return the average value of the given serie */ + function getSerieAverage($Serie) + { + if ( isset($this->Data["Series"][$Serie]) ) + { + $SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]); + return(array_sum($SerieData)/sizeof($SerieData)); + } + else + return(NULL); + } + + /* Return the geometric mean of the given serie */ + function getGeometricMean($Serie) + { + if ( isset($this->Data["Series"][$Serie]) ) + { + $SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]); + $Seriesum = 1; foreach($SerieData as $Key => $Value) { $Seriesum = $Seriesum * $Value; } + return(pow($Seriesum,1/sizeof($SerieData))); + } + else + return(NULL); + } + + /* Return the harmonic mean of the given serie */ + function getHarmonicMean($Serie) + { + if ( isset($this->Data["Series"][$Serie]) ) + { + $SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]); + $Seriesum = 0; foreach($SerieData as $Key => $Value) { $Seriesum = $Seriesum + 1/$Value; } + return(sizeof($SerieData)/$Seriesum); + } + else + return(NULL); + } + + /* Return the standard deviation of the given serie */ + function getStandardDeviation($Serie) + { + if ( isset($this->Data["Series"][$Serie]) ) + { + $Average = $this->getSerieAverage($Serie); + $SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]); + + $DeviationSum = 0; + foreach($SerieData as $Key => $Value) + $DeviationSum = $DeviationSum + ($Value-$Average)*($Value-$Average); + + $Deviation = sqrt($DeviationSum/count($SerieData)); + + return($Deviation); + } + else + return(NULL); + } + + /* Return the Coefficient of variation of the given serie */ + function getCoefficientOfVariation($Serie) + { + if ( isset($this->Data["Series"][$Serie]) ) + { + $Average = $this->getSerieAverage($Serie); + $StandardDeviation = $this->getStandardDeviation($Serie); + + if ( $StandardDeviation != 0 ) + return($StandardDeviation/$Average); + else + return(NULL); + } + else + return(NULL); + } + + /* Return the median value of the given serie */ + function getSerieMedian($Serie) + { + if ( isset($this->Data["Series"][$Serie]) ) + { + $SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]); + sort($SerieData); + $SerieCenter = floor(sizeof($SerieData)/2); + + if ( isset($SerieData[$SerieCenter]) ) + return($SerieData[$SerieCenter]); + else + return(NULL); + } + else + return(NULL); + } + + /* Return the x th percentil of the given serie */ + function getSeriePercentile($Serie="Serie1",$Percentil=95) + { + if (!isset($this->Data["Series"][$Serie]["Data"])) { return(NULL); } + + $Values = count($this->Data["Series"][$Serie]["Data"])-1; + if ( $Values < 0 ) { $Values = 0; } + + $PercentilID = floor(($Values/100)*$Percentil+.5); + $SortedValues = $this->Data["Series"][$Serie]["Data"]; + sort($SortedValues); + + if ( is_numeric($SortedValues[$PercentilID]) ) + return($SortedValues[$PercentilID]); + else + return(NULL); + } + + /* Add random values to a given serie */ + function addRandomValues($SerieName="Serie1",$Options="") + { + $Values = isset($Options["Values"]) ? $Options["Values"] : 20; + $Min = isset($Options["Min"]) ? $Options["Min"] : 0; + $Max = isset($Options["Max"]) ? $Options["Max"] : 100; + $withFloat = isset($Options["withFloat"]) ? $Options["withFloat"] : FALSE; + + for ($i=0;$i<=$Values;$i++) + { + if ( $withFloat ) { $Value = rand($Min*100,$Max*100)/100; } else { $Value = rand($Min,$Max); } + $this->addPoints($Value,$SerieName); + } + } + + /* Test if we have valid data */ + function containsData() + { + if (!isset($this->Data["Series"])) { return(FALSE); } + + $Result = FALSE; + foreach($this->Data["Series"] as $Key => $Value) + { if ( $this->Data["Abscissa"] != $Key && $this->Data["Series"][$Key]["isDrawable"]==TRUE) { $Result=TRUE; } } + return($Result); + } + + /* Set the display mode of an Axis */ + function setAxisDisplay($AxisID,$Mode=AXIS_FORMAT_DEFAULT,$Format=NULL) + { + if ( isset($this->Data["Axis"][$AxisID] ) ) + { + $this->Data["Axis"][$AxisID]["Display"] = $Mode; + if ( $Format != NULL ) { $this->Data["Axis"][$AxisID]["Format"] = $Format; } + } + } + + /* Set the position of an Axis */ + function setAxisPosition($AxisID,$Position=AXIS_POSITION_LEFT) + { if ( isset($this->Data["Axis"][$AxisID] ) ) { $this->Data["Axis"][$AxisID]["Position"] = $Position; } } + + /* Associate an unit to an axis */ + function setAxisUnit($AxisID,$Unit) + { if ( isset($this->Data["Axis"][$AxisID] ) ) { $this->Data["Axis"][$AxisID]["Unit"] = $Unit; } } + + /* Associate a name to an axis */ + function setAxisName($AxisID,$Name) + { if ( isset($this->Data["Axis"][$AxisID] ) ) { $this->Data["Axis"][$AxisID]["Name"] = $Name; } } + + /* Associate a color to an axis */ + function setAxisColor($AxisID,$Format) + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + + if ( isset($this->Data["Axis"][$AxisID] ) ) + { + $this->Data["Axis"][$AxisID]["Color"]["R"] = $R; + $this->Data["Axis"][$AxisID]["Color"]["G"] = $G; + $this->Data["Axis"][$AxisID]["Color"]["B"] = $B; + $this->Data["Axis"][$AxisID]["Color"]["Alpha"] = $Alpha; + } + } + + + /* Design an axis as X or Y member */ + function setAxisXY($AxisID,$Identity=AXIS_Y) + { if ( isset($this->Data["Axis"][$AxisID] ) ) { $this->Data["Axis"][$AxisID]["Identity"] = $Identity; } } + + /* Associate one data serie with one axis */ + function setSerieOnAxis($Series,$AxisID) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + foreach($Series as $Key => $Serie) + { + $PreviousAxis = $this->Data["Series"][$Serie]["Axis"]; + + /* Create missing axis */ + if ( !isset($this->Data["Axis"][$AxisID] ) ) + { $this->Data["Axis"][$AxisID]["Position"] = AXIS_POSITION_LEFT; $this->Data["Axis"][$AxisID]["Identity"] = AXIS_Y;} + + $this->Data["Series"][$Serie]["Axis"] = $AxisID; + + /* Cleanup unused axis */ + $Found = FALSE; + foreach($this->Data["Series"] as $SerieName => $Values) { if ( $Values["Axis"] == $PreviousAxis ) { $Found = TRUE; } } + if (!$Found) { unset($this->Data["Axis"][$PreviousAxis]); } + } + } + + /* Define if a serie should be draw with ticks */ + function setSerieTicks($Series,$Width=0) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + foreach($Series as $Key => $Serie) { if ( isset($this->Data["Series"][$Serie]) ) { $this->Data["Series"][$Serie]["Ticks"] = $Width; } } + } + + /* Define if a serie should be draw with a special weight */ + function setSerieWeight($Series,$Weight=0) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + foreach($Series as $Key => $Serie) { if ( isset($this->Data["Series"][$Serie]) ) { $this->Data["Series"][$Serie]["Weight"] = $Weight; } } + } + + /* Returns the palette of the given serie */ + function getSeriePalette($Serie) + { + if ( !isset($this->Data["Series"][$Serie]) ) { return(NULL); } + + $Result = ""; + $Result["R"] = $this->Data["Series"][$Serie]["Color"]["R"]; + $Result["G"] = $this->Data["Series"][$Serie]["Color"]["G"]; + $Result["B"] = $this->Data["Series"][$Serie]["Color"]["B"]; + $Result["Alpha"] = $this->Data["Series"][$Serie]["Color"]["Alpha"]; + + return($Result); + } + + /* Set the color of one serie */ + function setPalette($Series,$Format=NULL) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + + foreach($Series as $Key => $Serie) + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + + if ( isset($this->Data["Series"][$Serie]) ) + { + $OldR = $this->Data["Series"][$Serie]["Color"]["R"]; $OldG = $this->Data["Series"][$Serie]["Color"]["G"]; $OldB = $this->Data["Series"][$Serie]["Color"]["B"]; + $this->Data["Series"][$Serie]["Color"]["R"] = $R; + $this->Data["Series"][$Serie]["Color"]["G"] = $G; + $this->Data["Series"][$Serie]["Color"]["B"] = $B; + $this->Data["Series"][$Serie]["Color"]["Alpha"] = $Alpha; + + /* Do reverse processing on the internal palette array */ + foreach ($this->Palette as $Key => $Value) + { if ($Value["R"] == $OldR && $Value["G"] == $OldG && $Value["B"] == $OldB) { $this->Palette[$Key]["R"] = $R; $this->Palette[$Key]["G"] = $G; $this->Palette[$Key]["B"] = $B; $this->Palette[$Key]["Alpha"] = $Alpha;} } + } + } + } + + /* Load a palette file */ + function loadPalette($FileName,$Overwrite=FALSE) + { + if ( !file_exists($FileName) ) { return(-1); } + if ( $Overwrite ) { $this->Palette = ""; } + + $fileHandle = @fopen($FileName, "r"); + if (!$fileHandle) { return(-1); } + while (!feof($fileHandle)) + { + $buffer = fgets($fileHandle, 4096); + if ( preg_match("/,/",$buffer) ) + { + list($R,$G,$B,$Alpha) = preg_split("/,/",$buffer); + if ( $this->Palette == "" ) { $ID = 0; } else { $ID = count($this->Palette); } + $this->Palette[$ID] = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + } + } + fclose($fileHandle); + + /* Apply changes to current series */ + $ID = 0; + if ( isset($this->Data["Series"])) + { + foreach($this->Data["Series"] as $Key => $Value) + { + if ( !isset($this->Palette[$ID]) ) + $this->Data["Series"][$Key]["Color"] = array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>0); + else + $this->Data["Series"][$Key]["Color"] = $this->Palette[$ID]; + $ID++; + } + } + } + + /* Initialise a given scatter serie */ + function initScatterSerie($ID) + { + if ( isset($this->Data["ScatterSeries"][$ID]) ) { return(0); } + + $this->Data["ScatterSeries"][$ID]["Description"] = "Scatter ".$ID; + $this->Data["ScatterSeries"][$ID]["isDrawable"] = TRUE; + $this->Data["ScatterSeries"][$ID]["Picture"] = NULL; + $this->Data["ScatterSeries"][$ID]["Ticks"] = 0; + $this->Data["ScatterSeries"][$ID]["Weight"] = 0; + + if ( isset($this->Palette[$ID]) ) + $this->Data["ScatterSeries"][$ID]["Color"] = $this->Palette[$ID]; + else + { + $this->Data["ScatterSeries"][$ID]["Color"]["R"] = rand(0,255); + $this->Data["ScatterSeries"][$ID]["Color"]["G"] = rand(0,255); + $this->Data["ScatterSeries"][$ID]["Color"]["B"] = rand(0,255); + $this->Data["ScatterSeries"][$ID]["Color"]["Alpha"] = 100; + } + } + + /* Initialise a given serie */ + function initialise($Serie) + { + if ( isset($this->Data["Series"]) ) { $ID = count($this->Data["Series"]); } else { $ID = 0; } + + $this->Data["Series"][$Serie]["Description"] = $Serie; + $this->Data["Series"][$Serie]["isDrawable"] = TRUE; + $this->Data["Series"][$Serie]["Picture"] = NULL; + $this->Data["Series"][$Serie]["Max"] = NULL; + $this->Data["Series"][$Serie]["Min"] = NULL; + $this->Data["Series"][$Serie]["Axis"] = 0; + $this->Data["Series"][$Serie]["Ticks"] = 0; + $this->Data["Series"][$Serie]["Weight"] = 0; + $this->Data["Series"][$Serie]["Shape"] = SERIE_SHAPE_FILLEDCIRCLE; + + if ( isset($this->Palette[$ID]) ) + $this->Data["Series"][$Serie]["Color"] = $this->Palette[$ID]; + else + { + $this->Data["Series"][$Serie]["Color"]["R"] = rand(0,255); + $this->Data["Series"][$Serie]["Color"]["G"] = rand(0,255); + $this->Data["Series"][$Serie]["Color"]["B"] = rand(0,255); + $this->Data["Series"][$Serie]["Color"]["Alpha"] = 100; + } + } + + function normalize($NormalizationFactor=100,$UnitChange=NULL,$Round=1) + { + $Abscissa = $this->Data["Abscissa"]; + + $SelectedSeries = ""; + $MaxVal = 0; + foreach($this->Data["Axis"] as $AxisID => $Axis) + { + if ( $UnitChange != NULL ) { $this->Data["Axis"][$AxisID]["Unit"] = $UnitChange; } + + foreach($this->Data["Series"] as $SerieName => $Serie) + { + if ($Serie["Axis"] == $AxisID && $Serie["isDrawable"] == TRUE && $SerieName != $Abscissa) + { + $SelectedSeries[$SerieName] = $SerieName; + + if ( count($Serie["Data"] ) > $MaxVal ) { $MaxVal = count($Serie["Data"]); } + } + } + } + + for($i=0;$i<=$MaxVal-1;$i++) + { + $Factor = 0; + foreach ($SelectedSeries as $Key => $SerieName ) + { + $Value = $this->Data["Series"][$SerieName]["Data"][$i]; + if ( $Value != VOID ) + $Factor = $Factor + abs($Value); + } + + if ( $Factor != 0 ) + { + $Factor = $NormalizationFactor / $Factor; + + foreach ($SelectedSeries as $Key => $SerieName ) + { + $Value = $this->Data["Series"][$SerieName]["Data"][$i]; + + if ( $Value != VOID && $Factor != $NormalizationFactor ) + $this->Data["Series"][$SerieName]["Data"][$i] = round(abs($Value)*$Factor,$Round); + elseif ( $Value == VOID || $Value == 0 ) + $this->Data["Series"][$SerieName]["Data"][$i] = VOID; + elseif ( $Factor == $NormalizationFactor ) + $this->Data["Series"][$SerieName]["Data"][$i] = $NormalizationFactor; + } + } + } + + foreach ($SelectedSeries as $Key => $SerieName ) + { + $this->Data["Series"][$SerieName]["Max"] = max($this->stripVOID($this->Data["Series"][$SerieName]["Data"])); + $this->Data["Series"][$SerieName]["Min"] = min($this->stripVOID($this->Data["Series"][$SerieName]["Data"])); + } + } + + /* Load data from a CSV (or similar) data source */ + function importFromCSV($FileName,$Options="") + { + $Delimiter = isset($Options["Delimiter"]) ? $Options["Delimiter"] : ","; + $GotHeader = isset($Options["GotHeader"]) ? $Options["GotHeader"] : FALSE; + $SkipColumns = isset($Options["SkipColumns"]) ? $Options["SkipColumns"] : array(-1); + $DefaultSerieName = isset($Options["DefaultSerieName"]) ? $Options["DefaultSerieName"] : "Serie"; + + $Handle = @fopen($FileName,"r"); + if ($Handle) + { + $HeaderParsed = FALSE; $SerieNames = ""; + while (!feof($Handle)) + { + $Buffer = fgets($Handle, 4096); + $Buffer = str_replace(chr(10),"",$Buffer); + $Buffer = str_replace(chr(13),"",$Buffer); + $Values = preg_split("/".$Delimiter."/",$Buffer); + + if ( $Buffer != "" ) + { + if ( $GotHeader && !$HeaderParsed ) + { + foreach($Values as $Key => $Name) { if ( !in_array($Key,$SkipColumns) ) { $SerieNames[$Key] = $Name; } } + $HeaderParsed = TRUE; + } + else + { + if ($SerieNames == "" ) { foreach($Values as $Key => $Name) { if ( !in_array($Key,$SkipColumns) ) { $SerieNames[$Key] = $DefaultSerieName.$Key; } } } + foreach($Values as $Key => $Value) { if ( !in_array($Key,$SkipColumns) ) { $this->addPoints($Value,$SerieNames[$Key]); } } + } + } + } + fclose($Handle); + } + } + + /* Create a dataset based on a formula */ + function createFunctionSerie($SerieName,$Formula="",$Options="") + { + $MinX = isset($Options["MinX"]) ? $Options["MinX"] : -10; + $MaxX = isset($Options["MaxX"]) ? $Options["MaxX"] : 10; + $XStep = isset($Options["XStep"]) ? $Options["XStep"] : 1; + $AutoDescription = isset($Options["AutoDescription"]) ? $Options["AutoDescription"] : FALSE; + $RecordAbscissa = isset($Options["RecordAbscissa"]) ? $Options["RecordAbscissa"] : FALSE; + $AbscissaSerie = isset($Options["AbscissaSerie"]) ? $Options["AbscissaSerie"] : "Abscissa"; + + if ( $Formula == "" ) { return(0); } + + $Result = ""; $Abscissa = ""; + for($i=$MinX; $i<=$MaxX; $i=$i+$XStep) + { + $Expression = "\$return = '!'.(".str_replace("z",$i,$Formula).");"; + if ( @eval($Expression) === FALSE ) { $return = VOID; } + if ( $return == "!" ) { $return = VOID; } else { $return = $this->right($return,strlen($return)-1); } + if ( $return == "NAN" ) { $return = VOID; } + if ( $return == "INF" ) { $return = VOID; } + if ( $return == "-INF" ) { $return = VOID; } + + $Abscissa[] = $i; + $Result[] = $return; + } + + $this->addPoints($Result,$SerieName); + if ( $AutoDescription ) { $this->setSerieDescription($SerieName,$Formula); } + if ( $RecordAbscissa ) { $this->addPoints($Abscissa,$AbscissaSerie); } + } + + function negateValues($Series) + { + if ( !is_array($Series) ) { $Series = $this->convertToArray($Series); } + foreach($Series as $Key => $SerieName) + { + if (isset($this->Data["Series"][$SerieName])) + { + $Data = ""; + foreach($this->Data["Series"][$SerieName]["Data"] as $Key => $Value) + { if ( $Value == VOID ) { $Data[] = VOID; } else { $Data[] = -$Value; } } + $this->Data["Series"][$SerieName]["Data"] = $Data; + + $this->Data["Series"][$SerieName]["Max"] = max($this->stripVOID($this->Data["Series"][$SerieName]["Data"])); + $this->Data["Series"][$SerieName]["Min"] = min($this->stripVOID($this->Data["Series"][$SerieName]["Data"])); + } + } + } + + /* Return the data & configuration of the series */ + function getData() + { return($this->Data); } + + /* Save a palette element */ + function savePalette($ID,$Color) + { $this->Palette[$ID] = $Color; } + + /* Return the palette of the series */ + function getPalette() + { return($this->Palette); } + + /* Called by the scaling algorithm to save the config */ + function saveAxisConfig($Axis) { $this->Data["Axis"]=$Axis; } + + /* Save the Y Margin if set */ + function saveYMargin($Value) { $this->Data["YMargin"]=$Value; } + + /* Save extended configuration to the pData object */ + function saveExtendedData($Tag,$Values) { $this->Data["Extended"][$Tag]=$Values; } + + /* Called by the scaling algorithm to save the orientation of the scale */ + function saveOrientation($Orientation) { $this->Data["Orientation"]=$Orientation; } + + /* Convert a string to a single elements array */ + function convertToArray($Value) + { $Values = ""; $Values[] = $Value; return($Values); } + + /* Class string wrapper */ + function __toString() + { return("pData object."); } + + function left($value,$NbChar) { return substr($value,0,$NbChar); } + function right($value,$NbChar) { return substr($value,strlen($value)-$NbChar,$NbChar); } + function mid($value,$Depart,$NbChar) { return substr($value,$Depart-1,$NbChar); } + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/class/pDraw.class.php b/trunk/includes/pChart/class/pDraw.class.php new file mode 100644 index 0000000..750fbb5 --- /dev/null +++ b/trunk/includes/pChart/class/pDraw.class.php @@ -0,0 +1,6193 @@ +DataSet->getData(); + + foreach($Data["Series"] as $SerieName => $Serie) + { if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) { $Results++; } } + + return($Results); + } + + /* Fix box coordinates */ + function fixBoxCoordinates($Xa,$Ya,$Xb,$Yb) + { + $X1 = min($Xa,$Xb); $Y1 = min($Ya,$Yb); + $X2 = max($Xa,$Xb); $Y2 = max($Ya,$Yb); + + return(array($X1,$Y1,$X2,$Y2)); + } + + /* Draw a polygon */ + function drawPolygon($Points,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $NoFill = isset($Format["NoFill"]) ? $Format["NoFill"] : FALSE; + $NoBorder = isset($Format["NoBorder"]) ? $Format["NoBorder"] : FALSE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B; + $BorderAlpha = isset($Format["Alpha"]) ? $Format["Alpha"] : $Alpha / 2; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $SkipX = isset($Format["SkipX"]) ? $Format["SkipX"] : OUT_OF_SIGHT; + $SkipY = isset($Format["SkipY"]) ? $Format["SkipY"] : OUT_OF_SIGHT; + + /* Calling the ImageFilledPolygon() function over the $Points array will round it */ + $Backup = $Points; + + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + + if ( $SkipX != OUT_OF_SIGHT ) { $SkipX = floor($SkipX); } + if ( $SkipY != OUT_OF_SIGHT ) { $SkipY = floor($SkipY); } + + $RestoreShadow = $this->Shadow; + if ( !$NoFill ) + { + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + for($i=0;$i<=count($Points)-1;$i=$i+2) + { $Shadow[] = $Points[$i] + $this->ShadowX; $Shadow[] = $Points[$i+1] + $this->ShadowY; } + $this->drawPolygon($Shadow,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"NoBorder"=>TRUE)); + } + + $FillColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + + if ( count($Points) >= 6 ) + { ImageFilledPolygon($this->Picture,$Points,count($Points)/2,$FillColor); } + } + + if ( !$NoBorder ) + { + $Points = $Backup; + + if ( $NoFill ) + $BorderSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + else + $BorderSettings = array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha); + + for($i=0;$i<=count($Points)-1;$i=$i+2) + { + if ( isset($Points[$i+2]) ) + { + if ( !($Points[$i] == $Points[$i+2] && $Points[$i] == $SkipX ) && !($Points[$i+1] == $Points[$i+3] && $Points[$i+1] == $SkipY ) ) + $this->drawLine($Points[$i],$Points[$i+1],$Points[$i+2],$Points[$i+3],$BorderSettings); + } + else + { + if ( !($Points[$i] == $Points[0] && $Points[$i] == $SkipX ) && !($Points[$i+1] == $Points[1] && $Points[$i+1] == $SkipY ) ) + $this->drawLine($Points[$i],$Points[$i+1],$Points[0],$Points[1],$BorderSettings); + } + } + } + + $this->Shadow = $RestoreShadow; + } + + /* Apply AALias correction to the rounded box boundaries */ + function offsetCorrection($Value,$Mode) + { + $Value = round($Value,1); + + if ( $Value == 0 && $Mode == 1 ) { return(.9); } + if ( $Value == 0 ) { return(0); } + + if ( $Mode == 1) + { if ( $Value == 1 ) { return(.9); }; if ( $Value == .1 ) { return(.9); }; if ( $Value == .2 ) { return(.8); }; if ( $Value == .3 ) { return(.8); }; if ( $Value == .4 ) { return(.7); }; if ( $Value == .5 ) { return(.5); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.6); }; if ( $Value == .9 ) { return(.9); }; } + + if ( $Mode == 2) + { if ( $Value == 1 ) { return(.9); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.4); }; if ( $Value == .5 ) { return(.5); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.8); }; if ( $Value == .9 ) { return(.9); }; } + + if ( $Mode == 3) + { if ( $Value == 1 ) { return(.1); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.4); }; if ( $Value == .5 ) { return(.9); }; if ( $Value == .6 ) { return(.6); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.4); }; if ( $Value == .9 ) { return(.5); }; } + + if ( $Mode == 4) + { if ( $Value == 1 ) { return(-1); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.1); }; if ( $Value == .5 ) { return(-.1); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.1); }; if ( $Value == .8 ) { return(.1); }; if ( $Value == .9 ) { return(.1); }; } + } + + /* Draw a rectangle with rounded corners */ + function drawRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + + list($X1,$Y1,$X2,$Y2) = $this->fixBoxCoordinates($X1,$Y1,$X2,$Y2); + + if ( $X2 - $X1 < $Radius ) { $Radius = floor((($X2-$X1))/2); } + if ( $Y2 - $Y1 < $Radius ) { $Radius = floor((($Y2-$Y1))/2); } + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"NoBorder"=>TRUE); + + if ( $Radius <= 0 ) { $this->drawRectangle($X1,$Y1,$X2,$Y2,$Color); return(0); } + + if ( $this->Antialias ) + { + $this->drawLine($X1+$Radius,$Y1,$X2-$Radius,$Y1,$Color); + $this->drawLine($X2,$Y1+$Radius,$X2,$Y2-$Radius,$Color); + $this->drawLine($X2-$Radius,$Y2,$X1+$Radius,$Y2,$Color); + $this->drawLine($X1,$Y1+$Radius,$X1,$Y2-$Radius,$Color); + } + else + { + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + imageline($this->Picture,$X1+$Radius,$Y1,$X2-$Radius,$Y1,$Color); + imageline($this->Picture,$X2,$Y1+$Radius,$X2,$Y2-$Radius,$Color); + imageline($this->Picture,$X2-$Radius,$Y2,$X1+$Radius,$Y2,$Color); + imageline($this->Picture,$X1,$Y1+$Radius,$X1,$Y2-$Radius,$Color); + } + + $Step = 360 / (2 * PI * $Radius); + for($i=0;$i<=90;$i=$i+$Step) + { + $X = cos(($i+180)*PI/180) * $Radius + $X1 + $Radius; + $Y = sin(($i+180)*PI/180) * $Radius + $Y1 + $Radius; + $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + $X = cos(($i+90)*PI/180) * $Radius + $X1 + $Radius; + $Y = sin(($i+90)*PI/180) * $Radius + $Y2 - $Radius; + $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + $X = cos($i*PI/180) * $Radius + $X2 - $Radius; + $Y = sin($i*PI/180) * $Radius + $Y2 - $Radius; + $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + $X = cos(($i+270)*PI/180) * $Radius + $X2 - $Radius; + $Y = sin(($i+270)*PI/180) * $Radius + $Y1 + $Radius; + $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + } + } + + /* Draw a rectangle with rounded corners */ + function drawRoundedFilledRectangle($X1,$Y1,$X2,$Y2,$Radius,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + + /* Temporary fix for AA issue */ + $Y1 = floor($Y1); $Y2 = floor($Y2); $X1 = floor($X1); $X2 = floor($X2); + + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + if ( $BorderR == -1 ) { $BorderR = $R; $BorderG = $G; $BorderB = $B; } + + list($X1,$Y1,$X2,$Y2) = $this->fixBoxCoordinates($X1,$Y1,$X2,$Y2); + + if ( $X2 - $X1 < $Radius*2 ) { $Radius = floor((($X2-$X1))/4); } + if ( $Y2 - $Y1 < $Radius*2 ) { $Radius = floor((($Y2-$Y1))/4); } + + $RestoreShadow = $this->Shadow; + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + $this->drawRoundedFilledRectangle($X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,$Radius,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa)); + } + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"NoBorder"=>TRUE); + + if ( $Radius <= 0 ) { $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$Color); return(0); } + + $YTop = $Y1+$Radius; + $YBottom = $Y2-$Radius; + + $Step = 360 / (2 * PI * $Radius); + $Positions = ""; $Radius--; $MinY = ""; $MaxY = ""; + for($i=0;$i<=90;$i=$i+$Step) + { + $Xp1 = cos(($i+180)*PI/180) * $Radius + $X1 + $Radius; + $Xp2 = cos(((90-$i)+270)*PI/180) * $Radius + $X2 - $Radius; + $Yp = floor(sin(($i+180)*PI/180) * $Radius + $YTop); + if ( $MinY == "" || $Yp > $MinY ) { $MinY = $Yp; } + + if ( $Xp1 <= floor($X1) ) { $Xp1++; } + if ( $Xp2 >= floor($X2) ) { $Xp2--; } + $Xp1++; + + if ( !isset($Positions[$Yp]) ) + { $Positions[$Yp]["X1"] = $Xp1; $Positions[$Yp]["X2"] = $Xp2; } + else + { $Positions[$Yp]["X1"] = ($Positions[$Yp]["X1"]+$Xp1)/2; $Positions[$Yp]["X2"] = ($Positions[$Yp]["X2"]+$Xp2)/2; } + + $Xp1 = cos(($i+90)*PI/180) * $Radius + $X1 + $Radius; + $Xp2 = cos((90-$i)*PI/180) * $Radius + $X2 - $Radius; + $Yp = floor(sin(($i+90)*PI/180) * $Radius + $YBottom); + if ( $MaxY == "" || $Yp < $MaxY ) { $MaxY = $Yp; } + + if ( $Xp1 <= floor($X1) ) { $Xp1++; } + if ( $Xp2 >= floor($X2) ) { $Xp2--; } + $Xp1++; + + if ( !isset($Positions[$Yp]) ) + { $Positions[$Yp]["X1"] = $Xp1; $Positions[$Yp]["X2"] = $Xp2; } + else + { $Positions[$Yp]["X1"] = ($Positions[$Yp]["X1"]+$Xp1)/2; $Positions[$Yp]["X2"] = ($Positions[$Yp]["X2"]+$Xp2)/2; } + } + + $ManualColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + foreach($Positions as $Yp => $Bounds) + { + $X1 = $Bounds["X1"]; $X1Dec = $this->getFirstDecimal($X1); if ( $X1Dec != 0 ) { $X1 = floor($X1)+1; } + $X2 = $Bounds["X2"]; $X2Dec = $this->getFirstDecimal($X2); if ( $X2Dec != 0 ) { $X2 = floor($X2)-1; } + imageline($this->Picture,$X1,$Yp,$X2,$Yp,$ManualColor); + } + $this->drawFilledRectangle($X1,$MinY+1,floor($X2),$MaxY-1,$Color); + + $Radius++; + $this->drawRoundedRectangle($X1,$Y1,$X2+1,$Y2-1,$Radius,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + + $this->Shadow = $RestoreShadow; + } + + /* Draw a rectangle with rounded corners */ + function drawRoundedFilledRectangle_deprecated($X1,$Y1,$X2,$Y2,$Radius,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + if ( $BorderR == -1 ) { $BorderR = $R; $BorderG = $G; $BorderB = $B; } + + list($X1,$Y1,$X2,$Y2) = $this->fixBoxCoordinates($X1,$Y1,$X2,$Y2); + + if ( $X2 - $X1 < $Radius ) { $Radius = floor((($X2-$X1)+2)/2); } + if ( $Y2 - $Y1 < $Radius ) { $Radius = floor((($Y2-$Y1)+2)/2); } + + $RestoreShadow = $this->Shadow; + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + $this->drawRoundedFilledRectangle($X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,$Radius,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa)); + } + + if ( $this->getFirstDecimal($X2) >= 5 ) { $XOffset2 = 1; } else { $XOffset2 = 0; } + if ( $this->getFirstDecimal($X1) <= 5 ) { $XOffset1 = 1; } else { $XOffset1 = 0; } + + if ( !$this->Antialias ) { $XOffset1 = 1; $XOffset2 = 1; } + + $YTop = floor($Y1+$Radius); + $YBottom = floor($Y2-$Radius); + + $this->drawFilledRectangle($X1-$XOffset1,$YTop,$X2+$XOffset2,$YBottom,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"NoBorder"=>TRUE)); + + $Step = 360 / (2 * PI * $Radius); + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + $Color2 = $this->allocateColor($this->Picture,255,0,0,$Alpha); + $Drawn = ""; + + if ( $Alpha < 100 ) { $Drawn[$YTop] = FALSE; } + if ( $Alpha < 100 ) { $Drawn[$YBottom] = TRUE; } + + for($i=0;$i<=90;$i=$i+$Step) + { + $Xp1 = cos(($i+180)*PI/180) * $Radius + $X1 + $Radius; + $Xp2 = cos(((90-$i)+270)*PI/180) * $Radius + $X2 - $Radius; + $Yp = sin(($i+180)*PI/180) * $Radius + $YTop; + + if ( $this->getFirstDecimal($Xp1) > 5 ) { $XOffset1 = 1; } else { $XOffset1 = 0; } + if ( $this->getFirstDecimal($Xp2) > 5 ) { $XOffset2 = 1; } else { $XOffset2 = 0; } + if ( $this->getFirstDecimal($Yp) > 5 ) { $YOffset = 1; } else { $YOffset = 0; } + + if ( !isset($Drawn[$Yp+$YOffset]) || $Alpha == 100 ) + imageline($this->Picture,$Xp1+$XOffset1,$Yp+$YOffset,$Xp2+$XOffset2,$Yp+$YOffset,$Color); + + $Drawn[$Yp+$YOffset] = $Xp2; + + $Xp1 = cos(($i+90)*PI/180) * $Radius + $X1 + $Radius; + $Xp2 = cos((90-$i)*PI/180) * $Radius + $X2 - $Radius; + $Yp = sin(($i+90)*PI/180) * $Radius + $YBottom; + + if ( $this->getFirstDecimal($Xp1) > 7 ) { $XOffset1 = 1; } else { $XOffset1 = 0; } + if ( $this->getFirstDecimal($Xp2) > 7 ) { $XOffset2 = 1; } else { $XOffset2 = 0; } + if ( $this->getFirstDecimal($Yp) > 5 ) { $YOffset = 1; } else { $YOffset = 0; } + + if ( !isset($Drawn[$Yp+$YOffset]) || $Alpha == 100 ) + imageline($this->Picture,$Xp1+$XOffset1,$Yp+$YOffset,$Xp2+$XOffset2,$Yp+$YOffset,$Color); + + $Drawn[$Yp+$YOffset] = $Xp2; + } + + $this->drawRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + + $this->Shadow = $RestoreShadow; + } + + /* Draw a rectangle */ + function drawRectangle($X1,$Y1,$X2,$Y2,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + $NoAngle = isset($Format["NoAngle"]) ? $Format["NoAngle"] : FALSE; + + if ($X1 > $X2) { list($X1, $X2) = array($X2, $X1); } + if ($Y1 > $Y2) { list($Y1, $Y2) = array($Y2, $Y1); } + + if ( $this->Antialias ) + { + if ( $NoAngle ) + { + $this->drawLine($X1+1,$Y1,$X2-1,$Y1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + $this->drawLine($X2,$Y1+1,$X2,$Y2-1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + $this->drawLine($X2-1,$Y2,$X1+1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + $this->drawLine($X1,$Y1+1,$X1,$Y2-1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + } + else + { + $this->drawLine($X1+1,$Y1,$X2-1,$Y1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + $this->drawLine($X2,$Y1,$X2,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + $this->drawLine($X2-1,$Y2,$X1+1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + $this->drawLine($X1,$Y1,$X1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + } + } + else + { + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + imagerectangle($this->Picture,$X1,$Y1,$X2,$Y2,$Color); + } + } + + /* Draw a filled rectangle */ + function drawFilledRectangle($X1,$Y1,$X2,$Y2,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + $NoAngle = isset($Format["NoAngle"]) ? $Format["NoAngle"] : NULL; + $Dash = isset($Format["Dash"]) ? $Format["Dash"] : FALSE; + $DashStep = isset($Format["DashStep"]) ? $Format["DashStep"] : 4; + $DashR = isset($Format["DashR"]) ? $Format["DashR"] : 0; + $DashG = isset($Format["DashG"]) ? $Format["DashG"] : 0; + $DashB = isset($Format["DashB"]) ? $Format["DashB"] : 0; + $NoBorder = isset($Format["NoBorder"]) ? $Format["NoBorder"] : FALSE; + + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + + if ($X1 > $X2) { list($X1, $X2) = array($X2, $X1); } + if ($Y1 > $Y2) { list($Y1, $Y2) = array($Y2, $Y1); } + + $RestoreShadow = $this->Shadow; + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + $this->drawFilledRectangle($X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"Ticks"=>$Ticks,"NoAngle"=>$NoAngle)); + } + + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + if ( $NoAngle ) + { + imagefilledrectangle($this->Picture,ceil($X1)+1,ceil($Y1),floor($X2)-1,floor($Y2),$Color); + imageline($this->Picture,ceil($X1),ceil($Y1)+1,ceil($X1),floor($Y2)-1,$Color); + imageline($this->Picture,floor($X2),ceil($Y1)+1,floor($X2),floor($Y2)-1,$Color); + } + else + imagefilledrectangle($this->Picture,ceil($X1),ceil($Y1),floor($X2),floor($Y2),$Color); + + if ( $Dash ) + { + if ( $BorderR != -1 ) { $iX1=$X1+1; $iY1=$Y1+1; $iX2=$X2-1; $iY2=$Y2-1; } else { $iX1=$X1; $iY1=$Y1; $iX2=$X2; $iY2=$Y2; } + + $Color = $this->allocateColor($this->Picture,$DashR,$DashG,$DashB,$Alpha); + $Y=$iY1-$DashStep; + for($X=$iX1; $X<=$iX2+($iY2-$iY1); $X=$X+$DashStep) + { + $Y=$Y+$DashStep; + if ( $X > $iX2 ) { $Xa = $X-($X-$iX2); $Ya = $iY1+($X-$iX2); } else { $Xa = $X; $Ya = $iY1; } + if ( $Y > $iY2 ) { $Xb = $iX1+($Y-$iY2); $Yb = $Y-($Y-$iY2); } else { $Xb = $iX1; $Yb = $Y; } + imageline($this->Picture,$Xa,$Ya,$Xb,$Yb,$Color); + } + } + + if ( $this->Antialias && !$NoBorder ) + { + if ( $X1 < ceil($X1) ) + { + $AlphaA = $Alpha * (ceil($X1) - $X1); + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$AlphaA); + imageline($this->Picture,ceil($X1)-1,ceil($Y1),ceil($X1)-1,floor($Y2),$Color); + } + + if ( $Y1 < ceil($Y1) ) + { + $AlphaA = $Alpha * (ceil($Y1) - $Y1); + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$AlphaA); + imageline($this->Picture,ceil($X1),ceil($Y1)-1,floor($X2),ceil($Y1)-1,$Color); + } + + if ( $X2 > floor($X2) ) + { + $AlphaA = $Alpha * (.5-($X2 - floor($X2))); + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$AlphaA); + imageline($this->Picture,floor($X2)+1,ceil($Y1),floor($X2)+1,floor($Y2),$Color); + } + + if ( $Y2 > floor($Y2) ) + { + $AlphaA = $Alpha * (.5-($Y2 - floor($Y2))); + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$AlphaA); + imageline($this->Picture,ceil($X1),floor($Y2)+1,floor($X2),floor($Y2)+1,$Color); + } + } + + if ( $BorderR != -1 ) + $this->drawRectangle($X1,$Y1,$X2,$Y2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$Ticks,"NoAngle"=>$NoAngle)); + + $this->Shadow = $RestoreShadow; + } + + /* Draw a rectangular marker of the specified size */ + function drawRectangleMarker($X,$Y,$Format="") + { + $Size = isset($Format["Size"]) ? $Format["Size"] : 4; + + $HalfSize = floor($Size/2); + $this->drawFilledRectangle($X-$HalfSize,$Y-$HalfSize,$X+$HalfSize,$Y+$HalfSize,$Format); + } + + /* Drawn a spline based on the bezier function */ + function drawSpline($Coordinates,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Force = isset($Format["Force"]) ? $Format["Force"] : 30; + $Forces = isset($Format["Forces"]) ? $Format["Forces"] : NULL; + $ShowC = isset($Format["ShowControl"]) ? $Format["ShowControl"] : FALSE; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + $PathOnly = isset($Format["PathOnly"]) ? $Format["PathOnly"] : FALSE; + $Weight = isset($Format["Weight"]) ? $Format["Weight"] : NULL; + + $Cpt = NULL; $Mode = NULL; $Result = ""; + for($i=1;$i<=count($Coordinates)-1;$i++) + { + $X1 = $Coordinates[$i-1][0]; $Y1 = $Coordinates[$i-1][1]; + $X2 = $Coordinates[$i][0]; $Y2 = $Coordinates[$i][1]; + + if ( $Forces != NULL ) { $Force = $Forces[$i]; } + + /* First segment */ + if ( $i == 1 ) + { $Xv1 = $X1; $Yv1 = $Y1; } + else + { + $Angle1 = $this->getAngle($XLast,$YLast,$X1,$Y1); + $Angle2 = $this->getAngle($X1,$Y1,$X2,$Y2); + $XOff = cos($Angle2 * PI / 180) * $Force + $X1; + $YOff = sin($Angle2 * PI / 180) * $Force + $Y1; + + $Xv1 = cos($Angle1 * PI / 180) * $Force + $XOff; + $Yv1 = sin($Angle1 * PI / 180) * $Force + $YOff; + } + + /* Last segment */ + if ( $i == count($Coordinates)-1 ) + { $Xv2 = $X2; $Yv2 = $Y2; } + else + { + $Angle1 = $this->getAngle($X2,$Y2,$Coordinates[$i+1][0],$Coordinates[$i+1][1]); + $Angle2 = $this->getAngle($X1,$Y1,$X2,$Y2); + $XOff = cos(($Angle2+180) * PI / 180) * $Force + $X2; + $YOff = sin(($Angle2+180) * PI / 180) * $Force + $Y2; + + $Xv2 = cos(($Angle1+180) * PI / 180) * $Force + $XOff; + $Yv2 = sin(($Angle1+180) * PI / 180) * $Force + $YOff; + } + + $Path = $this->drawBezier($X1,$Y1,$X2,$Y2,$Xv1,$Yv1,$Xv2,$Yv2,$Format); + if ($PathOnly) { $Result[] = $Path; } + + $XLast = $X1; $YLast = $Y1; + } + + return($Result); + } + + /* Draw a bezier curve with two controls points */ + function drawBezier($X1,$Y1,$X2,$Y2,$Xv1,$Yv1,$Xv2,$Yv2,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $ShowC = isset($Format["ShowControl"]) ? $Format["ShowControl"] : FALSE; + $Segments = isset($Format["Segments"]) ? $Format["Segments"] : NULL; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + $NoDraw = isset($Format["NoDraw"]) ? $Format["NoDraw"] : FALSE; + $PathOnly = isset($Format["PathOnly"]) ? $Format["PathOnly"] : FALSE; + $Weight = isset($Format["Weight"]) ? $Format["Weight"] : NULL; + $DrawArrow = isset($Format["DrawArrow"]) ? $Format["DrawArrow"] : FALSE; + $ArrowSize = isset($Format["ArrowSize"]) ? $Format["ArrowSize"] : 10; + $ArrowRatio = isset($Format["ArrowRatio"]) ? $Format["ArrowRatio"] : .5; + $ArrowTwoHeads = isset($Format["ArrowTwoHeads"]) ? $Format["ArrowTwoHeads"] : FALSE; + + if ( $Segments == NULL ) + { + $Length = $this->getLength($X1,$Y1,$X2,$Y2); + $Precision = ($Length*125)/1000; + } + else + $Precision = $Segments; + + $P[0]["X"] = $X1; $P[0]["Y"] = $Y1; + $P[1]["X"] = $Xv1; $P[1]["Y"] = $Yv1; + $P[2]["X"] = $Xv2; $P[2]["Y"] = $Yv2; + $P[3]["X"] = $X2; $P[3]["Y"] = $Y2; + + /* Compute the bezier points */ + $Q = ""; $ID = 0; $Path = ""; + for($i=0;$i<=$Precision;$i=$i+1) + { + $u = $i / $Precision; + + $C = ""; + $C[0] = (1 - $u) * (1 - $u) * (1 - $u); + $C[1] = ($u * 3) * (1 - $u) * (1 - $u); + $C[2] = 3 * $u * $u * (1 - $u); + $C[3] = $u * $u * $u; + + for($j=0;$j<=3;$j++) + { + if ( !isset($Q[$ID]) ) { $Q[$ID] = ""; } + if ( !isset($Q[$ID]["X"]) ) { $Q[$ID]["X"] = 0; } + if ( !isset($Q[$ID]["Y"]) ) { $Q[$ID]["Y"] = 0; } + + $Q[$ID]["X"] = $Q[$ID]["X"] + $P[$j]["X"] * $C[$j]; + $Q[$ID]["Y"] = $Q[$ID]["Y"] + $P[$j]["Y"] * $C[$j]; + } + $ID++; + } + $Q[$ID]["X"] = $X2; $Q[$ID]["Y"] = $Y2; + + if ( !$NoDraw ) + { + /* Display the control points */ + if ( $ShowC && !$PathOnly ) + { + $Xv1 = floor($Xv1); $Yv1 = floor($Yv1); $Xv2 = floor($Xv2); $Yv2 = floor($Yv2); + + $this->drawLine($X1,$Y1,$X2,$Y2,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>30)); + + $MyMarkerSettings = array("R"=>255,"G"=>0,"B"=>0,"BorderR"=>255,"BorderB"=>255,"BorderG"=>255,"Size"=>4); + $this->drawRectangleMarker($Xv1,$Yv1,$MyMarkerSettings); + $this->drawText($Xv1+4,$Yv1,"v1"); + $MyMarkerSettings = array("R"=>0,"G"=>0,"B"=>255,"BorderR"=>255,"BorderB"=>255,"BorderG"=>255,"Size"=>4); + $this->drawRectangleMarker($Xv2,$Yv2,$MyMarkerSettings); + $this->drawText($Xv2+4,$Yv2,"v2"); + } + + /* Draw the bezier */ + $LastX = NULL; $LastY = NULL; $Cpt = NULL; $Mode = NULL; $ArrowS = NULL; + foreach ($Q as $Key => $Point) + { + $X = $Point["X"]; $Y = $Point["Y"]; + + /* Get the first segment */ + if ( $ArrowS == NULL && $LastX != NULL && $LastY != NULL ) + { $ArrowS["X2"] = $LastX; $ArrowS["Y2"] = $LastY; $ArrowS["X1"] = $X; $ArrowS["Y1"] = $Y; } + + if ( $LastX != NULL && $LastY != NULL && !$PathOnly) + list($Cpt,$Mode) = $this->drawLine($LastX,$LastY,$X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Cpt"=>$Cpt,"Mode"=>$Mode,"Weight"=>$Weight)); + + /* Get the last segment */ + $ArrowE["X1"] = $LastX; $ArrowE["Y1"] = $LastY; $ArrowE["X2"] = $X; $ArrowE["Y2"] = $Y; + + $LastX = $X; $LastY = $Y; + } + + if ( $DrawArrow && !$PathOnly ) + { + $ArrowSettings = array("FillR"=>$R,"FillG"=>$G,"FillB"=>$B,"Alpha"=>$Alpha,"Size"=>$ArrowSize,"Ratio"=>$ArrowRatio); + if ( $ArrowTwoHeads ) + $this->drawArrow($ArrowS["X1"],$ArrowS["Y1"],$ArrowS["X2"],$ArrowS["Y2"],$ArrowSettings); + + $this->drawArrow($ArrowE["X1"],$ArrowE["Y1"],$ArrowE["X2"],$ArrowE["Y2"],$ArrowSettings); + } + } + return($Q); + } + + /* Draw a line between two points */ + function drawLine($X1,$Y1,$X2,$Y2,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + $Cpt = isset($Format["Cpt"]) ? $Format["Cpt"] : 1; + $Mode = isset($Format["Mode"]) ? $Format["Mode"] : 1; + $Weight = isset($Format["Weight"]) ? $Format["Weight"] : NULL; + $Threshold = isset($Format["Threshold"]) ? $Format["Threshold"] : NULL; + + if ( $this->Antialias == FALSE && $Ticks == NULL ) + { + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $ShadowColor = $this->allocateColor($this->Picture,$this->ShadowR,$this->ShadowG,$this->ShadowB,$this->Shadowa); + imageline($this->Picture,$X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,$ShadowColor); + } + + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + imageline($this->Picture,$X1,$Y1,$X2,$Y2,$Color); + return(0); + } + + $Distance = sqrt(($X2-$X1)*($X2-$X1)+($Y2-$Y1)*($Y2-$Y1)); + if ( $Distance == 0 ) { return(-1); } + + /* Derivative algorithm for overweighted lines, re-route to polygons primitives */ + if ( $Weight != NULL ) + { + $Angle = $this->getAngle($X1,$Y1,$X2,$Y2); + $PolySettings = array ("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderAlpha"=>$Alpha); + + if ( $Ticks == NULL ) + { + $Points = ""; + $Points[] = cos(deg2rad($Angle-90)) * $Weight + $X1; $Points[] = sin(deg2rad($Angle-90)) * $Weight + $Y1; + $Points[] = cos(deg2rad($Angle+90)) * $Weight + $X1; $Points[] = sin(deg2rad($Angle+90)) * $Weight + $Y1; + $Points[] = cos(deg2rad($Angle+90)) * $Weight + $X2; $Points[] = sin(deg2rad($Angle+90)) * $Weight + $Y2; + $Points[] = cos(deg2rad($Angle-90)) * $Weight + $X2; $Points[] = sin(deg2rad($Angle-90)) * $Weight + $Y2; + + $this->drawPolygon($Points,$PolySettings); + } + else + { + for($i=0;$i<=$Distance;$i=$i+$Ticks*2) + { + $Xa = (($X2-$X1)/$Distance) * $i + $X1; $Ya = (($Y2-$Y1)/$Distance) * $i + $Y1; + $Xb = (($X2-$X1)/$Distance) * ($i+$Ticks) + $X1; $Yb = (($Y2-$Y1)/$Distance) * ($i+$Ticks) + $Y1; + + $Points = ""; + $Points[] = cos(deg2rad($Angle-90)) * $Weight + $Xa; $Points[] = sin(deg2rad($Angle-90)) * $Weight + $Ya; + $Points[] = cos(deg2rad($Angle+90)) * $Weight + $Xa; $Points[] = sin(deg2rad($Angle+90)) * $Weight + $Ya; + $Points[] = cos(deg2rad($Angle+90)) * $Weight + $Xb; $Points[] = sin(deg2rad($Angle+90)) * $Weight + $Yb; + $Points[] = cos(deg2rad($Angle-90)) * $Weight + $Xb; $Points[] = sin(deg2rad($Angle-90)) * $Weight + $Yb; + + $this->drawPolygon($Points,$PolySettings); + } + } + + return(1); + } + + $XStep = ($X2-$X1) / $Distance; + $YStep = ($Y2-$Y1) / $Distance; + + for($i=0;$i<=$Distance;$i++) + { + $X = $i * $XStep + $X1; + $Y = $i * $YStep + $Y1; + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + + if ( $Threshold != NULL ) + { + foreach($Threshold as $Key => $Parameters) + { + if ( $Y <= $Parameters["MinX"] && $Y >= $Parameters["MaxX"]) + { + if ( isset($Parameters["R"]) ) { $RT = $Parameters["R"]; } else { $RT = 0; } + if ( isset($Parameters["G"]) ) { $GT = $Parameters["G"]; } else { $GT = 0; } + if ( isset($Parameters["B"]) ) { $BT = $Parameters["B"]; } else { $BT = 0; } + if ( isset($Parameters["Alpha"]) ) { $AlphaT = $Parameters["Alpha"]; } else { $AlphaT = 0; } + $Color = array("R"=>$RT,"G"=>$GT,"B"=>$BT,"Alpha"=>$AlphaT); + } + } + } + + if ( $Ticks != NULL ) + { + if ( $Cpt % $Ticks == 0 ) + { $Cpt = 0; if ( $Mode == 1 ) { $Mode = 0; } else { $Mode = 1; } } + + if ( $Mode == 1 ) + $this->drawAntialiasPixel($X,$Y,$Color); + + $Cpt++; + } + else + $this->drawAntialiasPixel($X,$Y,$Color); + } + + return(array($Cpt,$Mode)); + } + + /* Draw a circle */ + function drawCircle($Xc,$Yc,$Height,$Width,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + + $Height = abs($Height); + $Width = abs($Width); + + if ( $Height == 0 ) { $Height = 1; } + if ( $Width == 0 ) { $Width = 1; } + $Xc = floor($Xc); $Yc = floor($Yc); + + $RestoreShadow = $this->Shadow; + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + $this->drawCircle($Xc+$this->ShadowX,$Yc+$this->ShadowY,$Height,$Width,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"Ticks"=>$Ticks)); + } + + if ( $Width == 0 ) { $Width = $Height; } + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + $Step = 360 / (2 * PI * max($Width,$Height)); + $Mode = 1; $Cpt = 1; + for($i=0;$i<=360;$i=$i+$Step) + { + $X = cos($i*PI/180) * $Height + $Xc; + $Y = sin($i*PI/180) * $Width + $Yc; + + if ( $Ticks != NULL ) + { + if ( $Cpt % $Ticks == 0 ) + { $Cpt = 0; if ( $Mode == 1 ) { $Mode = 0; } else { $Mode = 1; } } + + if ( $Mode == 1 ) + $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + $Cpt++; + } + else + $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + } + $this->Shadow = $RestoreShadow; + } + + /* Draw a filled circle */ + function drawFilledCircle($X,$Y,$Radius,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + + if ( $Radius == 0 ) { $Radius = 1; } + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + $X = floor($X); $Y = floor($Y); + + $Radius = abs($Radius); + + $RestoreShadow = $this->Shadow; + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + $this->drawFilledCircle($X+$this->ShadowX,$Y+$this->ShadowY,$Radius,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"Ticks"=>$Ticks)); + } + + $this->Mask = ""; + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + for ($i=0; $i<=$Radius*2; $i++) + { + $Slice = sqrt($Radius * $Radius - ($Radius - $i) * ($Radius - $i)); + $XPos = floor($Slice); + $YPos = $Y + $i - $Radius; + $AAlias = $Slice - floor($Slice); + + $this->Mask[$X-$XPos][$YPos] = TRUE; + $this->Mask[$X+$XPos][$YPos] = TRUE; + imageline($this->Picture,$X-$XPos,$YPos,$X+$XPos,$YPos,$Color); + } + if ( $this->Antialias ) + $this->drawCircle($X,$Y,$Radius,$Radius,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + + $this->Mask = ""; + + if ( $BorderR != -1 ) + $this->drawCircle($X,$Y,$Radius,$Radius,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$Ticks)); + + $this->Shadow = $RestoreShadow; + } + + /* Write text */ + function drawText($X,$Y,$Text,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : $this->FontColorR; + $G = isset($Format["G"]) ? $Format["G"] : $this->FontColorG; + $B = isset($Format["B"]) ? $Format["B"] : $this->FontColorB; + $Angle = isset($Format["Angle"]) ? $Format["Angle"] : 0; + $Align = isset($Format["Align"]) ? $Format["Align"] : TEXT_ALIGN_BOTTOMLEFT; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : $this->FontColorA; + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize; + $ShowOrigine = isset($Format["ShowOrigine"]) ? $Format["ShowOrigine"] : FALSE; + $TOffset = isset($Format["TOffset"]) ? $Format["TOffset"] : 2; + $DrawBox = isset($Format["DrawBox"]) ? $Format["DrawBox"] : FALSE; + $DrawBoxBorder = isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : TRUE; + $BorderOffset = isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 6; + $BoxRounded = isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : FALSE; + $RoundedRadius = isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 6; + $BoxR = isset($Format["BoxR"]) ? $Format["BoxR"] : 255; + $BoxG = isset($Format["BoxG"]) ? $Format["BoxG"] : 255; + $BoxB = isset($Format["BoxB"]) ? $Format["BoxB"] : 255; + $BoxAlpha = isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 50; + $BoxSurrounding = isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : ""; + $BoxBorderR = isset($Format["BoxR"]) ? $Format["BoxR"] : 0; + $BoxBorderG = isset($Format["BoxG"]) ? $Format["BoxG"] : 0; + $BoxBorderB = isset($Format["BoxB"]) ? $Format["BoxB"] : 0; + $BoxBorderAlpha = isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 50; + $NoShadow = isset($Format["NoShadow"]) ? $Format["NoShadow"] : FALSE; + + $Shadow = $this->Shadow; + if ( $NoShadow ) { $this->Shadow = FALSE; } + + if ( $BoxSurrounding != "" ) { $BoxBorderR = $BoxR - $BoxSurrounding; $BoxBorderG = $BoxG - $BoxSurrounding; $BoxBorderB = $BoxB - $BoxSurrounding; $BoxBorderAlpha = $BoxAlpha; } + + if ( $ShowOrigine ) + { + $MyMarkerSettings = array("R"=>255,"G"=>0,"B"=>0,"BorderR"=>255,"BorderB"=>255,"BorderG"=>255,"Size"=>4); + $this->drawRectangleMarker($X,$Y,$MyMarkerSettings); + } + + $TxtPos = $this->getTextBox($X,$Y,$FontName,$FontSize,$Angle,$Text); + + if ( $DrawBox && ($Angle == 0 || $Angle == 90 || $Angle == 180 || $Angle == 270)) + { + $T[0]["X"]=0;$T[0]["Y"]=0;$T[1]["X"]=0;$T[1]["Y"]=0;$T[2]["X"]=0;$T[2]["Y"]=0;$T[3]["X"]=0;$T[3]["Y"]=0; + if ( $Angle == 0 ) { $T[0]["X"]=-$TOffset;$T[0]["Y"]=$TOffset;$T[1]["X"]=$TOffset;$T[1]["Y"]=$TOffset;$T[2]["X"]=$TOffset;$T[2]["Y"]=-$TOffset;$T[3]["X"]=-$TOffset;$T[3]["Y"]=-$TOffset; } + + $X1 = min($TxtPos[0]["X"],$TxtPos[1]["X"],$TxtPos[2]["X"],$TxtPos[3]["X"]) - $BorderOffset + 3; + $Y1 = min($TxtPos[0]["Y"],$TxtPos[1]["Y"],$TxtPos[2]["Y"],$TxtPos[3]["Y"]) - $BorderOffset; + $X2 = max($TxtPos[0]["X"],$TxtPos[1]["X"],$TxtPos[2]["X"],$TxtPos[3]["X"]) + $BorderOffset + 3; + $Y2 = max($TxtPos[0]["Y"],$TxtPos[1]["Y"],$TxtPos[2]["Y"],$TxtPos[3]["Y"]) + $BorderOffset - 3; + + $X1 = $X1 - $TxtPos[$Align]["X"] + $X + $T[0]["X"]; + $Y1 = $Y1 - $TxtPos[$Align]["Y"] + $Y + $T[0]["Y"]; + $X2 = $X2 - $TxtPos[$Align]["X"] + $X + $T[0]["X"]; + $Y2 = $Y2 - $TxtPos[$Align]["Y"] + $Y + $T[0]["Y"]; + + $Settings = array("R"=>$BoxR,"G"=>$BoxG,"B"=>$BoxB,"Alpha"=>$BoxAlpha,"BorderR"=>$BoxBorderR,"BorderG"=>$BoxBorderG,"BorderB"=>$BoxBorderB,"BorderAlpha"=>$BoxBorderAlpha); + + if ( $BoxRounded ) + { $this->drawRoundedFilledRectangle($X1,$Y1,$X2,$Y2,$RoundedRadius,$Settings); } + else + { $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$Settings); } + } + + $X = $X - $TxtPos[$Align]["X"] + $X; + $Y = $Y - $TxtPos[$Align]["Y"] + $Y; + + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $C_ShadowColor = $this->allocateColor($this->Picture,$this->ShadowR,$this->ShadowG,$this->ShadowB,$this->Shadowa); + imagettftext($this->Picture,$FontSize,$Angle,$X+$this->ShadowX,$Y+$this->ShadowY,$C_ShadowColor,$FontName,$Text); + } + + $C_TextColor = $this->AllocateColor($this->Picture,$R,$G,$B,$Alpha); + imagettftext($this->Picture,$FontSize,$Angle,$X,$Y,$C_TextColor,$FontName,$Text); + + $this->Shadow = $Shadow; + + return($TxtPos); + } + + /* Draw a gradient within a defined area */ + function drawGradientArea($X1,$Y1,$X2,$Y2,$Direction,$Format="") + { + $StartR = isset($Format["StartR"]) ? $Format["StartR"] : 90; + $StartG = isset($Format["StartG"]) ? $Format["StartG"] : 90; + $StartB = isset($Format["StartB"]) ? $Format["StartB"] : 90; + $EndR = isset($Format["EndR"]) ? $Format["EndR"] : 0; + $EndG = isset($Format["EndG"]) ? $Format["EndG"] : 0; + $EndB = isset($Format["EndB"]) ? $Format["EndB"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Levels = isset($Format["Levels"]) ? $Format["Levels"] : NULL; + + $Shadow = $this->Shadow; + $this->Shadow = FALSE; + + if ( $StartR == $EndR && $StartG == $EndG && $StartB == $EndB ) + { + $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,array("R"=>$StartR,"G"=>$StartG,"B"=>$StartB,"Alpha"=>$Alpha)); + return(0); + } + + if ( $Levels != NULL ) + { $EndR=$StartR+$Levels; $EndG=$StartG+$Levels; $EndB=$StartB+$Levels; } + + if ($X1 > $X2) { list($X1, $X2) = array($X2, $X1); } + if ($Y1 > $Y2) { list($Y1, $Y2) = array($Y2, $Y1); } + + if ( $Direction == DIRECTION_VERTICAL ) { $Width = abs($Y2-$Y1); } + if ( $Direction == DIRECTION_HORIZONTAL ) { $Width = abs($X2-$X1); } + + $Step = max(abs($EndR-$StartR),abs($EndG-$StartG),abs($EndB-$StartB)); + $StepSize = $Width/$Step; + $RStep = ($EndR-$StartR)/$Step; + $GStep = ($EndG-$StartG)/$Step; + $BStep = ($EndB-$StartB)/$Step; + + $R=$StartR;$G=$StartG;$B=$StartB; + switch($Direction) + { + case DIRECTION_VERTICAL: + $StartY = $Y1; $EndY = floor($Y2)+1; $LastY2 = $StartY; + for($i=0;$i<=$Step;$i++) + { + $Y2 = floor($StartY + ($i * $StepSize)); + + if ($Y2 > $EndY) { $Y2 = $EndY; } + if (($Y1 != $Y2 && $Y1 < $Y2) || $Y2 == $EndY) + { + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$Color); + $LastY2 = max($LastY2,$Y2); + $Y1 = $Y2+1; + } + $R = $R + $RStep; $G = $G + $GStep; $B = $B + $BStep; + } + if ( $LastY2 < $EndY && isset($Color)) { for ($i=$LastY2+1;$i<=$EndY;$i++) { $this->drawLine($X1,$i,$X2,$i,$Color); } } + break; + + case DIRECTION_HORIZONTAL: + $StartX = $X1; $EndX = $X2; + for($i=0;$i<=$Step;$i++) + { + $X2 = floor($StartX + ($i * $StepSize)); + + if ($X2 > $EndX) { $X2 = $EndX; } + if (($X1 != $X2 && $X1 < $X2) || $X2 == $EndX) + { + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$Color); + $X1 = $X2+1; + } + $R = $R + $RStep; $G = $G + $GStep; $B = $B + $BStep; + } + if ( $X2 < $EndX && isset($Color)) { $this->drawFilledRectangle($X2,$Y1,$EndX,$Y2,$Color); } + break; + } + + $this->Shadow = $Shadow; + + } + + /* Draw an aliased pixel */ + function drawAntialiasPixel($X,$Y,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + + if ( $X < 0 || $Y < 0 || $X >= $this->XSize || $Y >= $this->YSize ) + return(-1); + + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + if ( !$this->Antialias ) + { + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $ShadowColor = $this->allocateColor($this->Picture,$this->ShadowR,$this->ShadowG,$this->ShadowB,$this->Shadowa); + imagesetpixel($this->Picture,$X+$this->ShadowX,$Y+$this->ShadowY,$ShadowColor); + } + + $PlotColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + imagesetpixel($this->Picture,$X,$Y,$PlotColor); + + return(0); + } + + $Plot = ""; + $Xi = floor($X); + $Yi = floor($Y); + + if ( $Xi == $X && $Yi == $Y) + { + if ( $Alpha == 100 ) + $this->drawAlphaPixel($X,$Y,100,$R,$G,$B); + else + $this->drawAlphaPixel($X,$Y,$Alpha,$R,$G,$B); + } + else + { + $Alpha1 = (((1 - ($X - floor($X))) * (1 - ($Y - floor($Y))) * 100) / 100) * $Alpha; + if ( $Alpha1 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi,$Yi,$Alpha1,$R,$G,$B); } + + $Alpha2 = ((($X - floor($X)) * (1 - ($Y - floor($Y))) * 100) / 100) * $Alpha; + if ( $Alpha2 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi+1,$Yi,$Alpha2,$R,$G,$B); } + + $Alpha3 = (((1 - ($X - floor($X))) * ($Y - floor($Y)) * 100) / 100) * $Alpha; + if ( $Alpha3 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi,$Yi+1,$Alpha3,$R,$G,$B); } + + $Alpha4 = ((($X - floor($X)) * ($Y - floor($Y)) * 100) / 100) * $Alpha; + if ( $Alpha4 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi+1,$Yi+1,$Alpha4,$R,$G,$B); } + } + } + + /* Draw a semi-transparent pixel */ + function drawAlphaPixel($X,$Y,$Alpha,$R,$G,$B) + { + if ( isset($this->Mask[$X])) { if ( isset($this->Mask[$X][$Y]) ) { return(0); } } + + if ( $X < 0 || $Y < 0 || $X >= $this->XSize || $Y >= $this->YSize ) + return(-1); + + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $AlphaFactor = floor(($Alpha / 100) * $this->Shadowa); + $ShadowColor = $this->allocateColor($this->Picture,$this->ShadowR,$this->ShadowG,$this->ShadowB,$AlphaFactor); + imagesetpixel($this->Picture,$X+$this->ShadowX,$Y+$this->ShadowY,$ShadowColor); + } + + $C_Aliased = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + imagesetpixel($this->Picture,$X,$Y,$C_Aliased); + } + + /* Convert apha to base 10 */ + function convertAlpha($AlphaValue) + { return((127/100)*(100-$AlphaValue)); } + + /* Allocate a color with transparency */ + function allocateColor($Picture,$R,$G,$B,$Alpha=100) + { + if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; } + if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; } + if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; } + if ( $Alpha < 0 ) { $Alpha = 0; } + if ( $Alpha > 100) { $Alpha = 100; } + + $Alpha = $this->convertAlpha($Alpha); + return(imagecolorallocatealpha($Picture,$R,$G,$B,$Alpha)); + } + + /* Load a PNG file and draw it over the chart */ + function drawFromPNG($X,$Y,$FileName) + { $this->drawFromPicture(1,$FileName,$X,$Y); } + + /* Load a GIF file and draw it over the chart */ + function drawFromGIF($X,$Y,$FileName) + { $this->drawFromPicture(2,$FileName,$X,$Y); } + + /* Load a JPEG file and draw it over the chart */ + function drawFromJPG($X,$Y,$FileName) + { $this->drawFromPicture(3,$FileName,$X,$Y); } + + function getPicInfo($FileName) + { + $Infos = getimagesize($FileName); + $Width = $Infos[0]; + $Height = $Infos[1]; + $Type = $Infos["mime"]; + + if ( $Type == "image/png") { $Type = 1; } + if ( $Type == "image/gif") { $Type = 2; } + if ( $Type == "image/jpeg ") { $Type = 3; } + + return(array($Width,$Height,$Type)); + } + + /* Generic loader function for external pictures */ + function drawFromPicture($PicType,$FileName,$X,$Y) + { + if ( file_exists($FileName)) + { + list($Width,$Height) = $this->getPicInfo($FileName); + + if ( $PicType == 1 ) + { $Raster = imagecreatefrompng($FileName); } + elseif ( $PicType == 2 ) + { $Raster = imagecreatefromgif($FileName); } + elseif ( $PicType == 3 ) + { $Raster = imagecreatefromjpeg($FileName); } + else + { return(0); } + + + $RestoreShadow = $this->Shadow; + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + if ( $PicType == 3 ) + $this->drawFilledRectangle($X+$this->ShadowX,$Y+$this->ShadowY,$X+$Width+$this->ShadowX,$Y+$Height+$this->ShadowY,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa)); + else + { + $TranparentID = imagecolortransparent($Raster); + for ($Xc=0;$Xc<=$Width-1;$Xc++) + { + for ($Yc=0;$Yc<=$Height-1;$Yc++) + { + $RGBa = imagecolorat($Raster,$Xc,$Yc); + $Values = imagecolorsforindex($Raster,$RGBa); + if ( $Values["alpha"] < 120 ) + { + $AlphaFactor = floor(($this->Shadowa / 100) * ((100 / 127) * (127-$Values["alpha"]))); + $this->drawAlphaPixel($X+$Xc+$this->ShadowX,$Y+$Yc+$this->ShadowY,$AlphaFactor,$this->ShadowR,$this->ShadowG,$this->ShadowB); + } + } + } + } + } + $this->Shadow = $RestoreShadow; + + imagecopy($this->Picture,$Raster,$X,$Y,0,0,$Width,$Height); + imagedestroy($Raster); + } + } + + /* Draw an arrow */ + function drawArrow($X1,$Y1,$X2,$Y2,$Format="") + { + $FillR = isset($Format["FillR"]) ? $Format["FillR"] : 0; + $FillG = isset($Format["FillG"]) ? $Format["FillG"] : 0; + $FillB = isset($Format["FillB"]) ? $Format["FillB"] : 0; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $FillR; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $FillG; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $FillB; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Size = isset($Format["Size"]) ? $Format["Size"] : 10; + $Ratio = isset($Format["Ratio"]) ? $Format["Ratio"] : .5; + $TwoHeads = isset($Format["TwoHeads"]) ? $Format["TwoHeads"] : FALSE; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : FALSE; + + /* Calculate the line angle */ + $Angle = $this->getAngle($X1,$Y1,$X2,$Y2); + + /* Override Shadow support, this will be managed internally */ + $RestoreShadow = $this->Shadow; + if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 ) + { + $this->Shadow = FALSE; + $this->drawArrow($X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,array("FillR"=>$this->ShadowR,"FillG"=>$this->ShadowG,"FillB"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"Size"=>$Size,"Ratio"=>$Ratio,"TwoHeads"=>$TwoHeads,"Ticks"=>$Ticks)); + } + + /* Draw the 1st Head */ + $TailX = cos(($Angle-180)*PI/180)*$Size+$X2; + $TailY = sin(($Angle-180)*PI/180)*$Size+$Y2; + + $Points = ""; + $Points[] = $X2; $Points[] = $Y2; + $Points[] = cos(($Angle-90)*PI/180)*$Size*$Ratio+$TailX; $Points[] = sin(($Angle-90)*PI/180)*$Size*$Ratio+$TailY; + $Points[] = cos(($Angle-270)*PI/180)*$Size*$Ratio+$TailX; $Points[] = sin(($Angle-270)*PI/180)*$Size*$Ratio+$TailY; + $Points[] = $X2; $Points[] = $Y2; + + /* Visual correction */ + if ($Angle == 180 || $Angle == 360 ) { $Points[4] = $Points[2]; } + if ($Angle == 90 || $Angle == 270 ) { $Points[5] = $Points[3]; } + + $ArrowColor = $this->allocateColor($this->Picture,$FillR,$FillG,$FillB,$Alpha); + ImageFilledPolygon($this->Picture,$Points,4,$ArrowColor); + + $this->drawLine($Points[0],$Points[1],$Points[2],$Points[3],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + $this->drawLine($Points[2],$Points[3],$Points[4],$Points[5],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + $this->drawLine($Points[0],$Points[1],$Points[4],$Points[5],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + + /* Draw the second head */ + if ( $TwoHeads ) + { + $Angle = $this->getAngle($X2,$Y2,$X1,$Y1); + + $TailX2 = cos(($Angle-180)*PI/180)*$Size+$X1; + $TailY2 = sin(($Angle-180)*PI/180)*$Size+$Y1; + + $Points = ""; + $Points[] = $X1; $Points[] = $Y1; + $Points[] = cos(($Angle-90)*PI/180)*$Size*$Ratio+$TailX2; $Points[] = sin(($Angle-90)*PI/180)*$Size*$Ratio+$TailY2; + $Points[] = cos(($Angle-270)*PI/180)*$Size*$Ratio+$TailX2; $Points[] = sin(($Angle-270)*PI/180)*$Size*$Ratio+$TailY2; + $Points[] = $X1; $Points[] = $Y1; + + /* Visual correction */ + if ($Angle == 180 || $Angle == 360 ) { $Points[4] = $Points[2]; } + if ($Angle == 90 || $Angle == 270 ) { $Points[5] = $Points[3]; } + + $ArrowColor = $this->allocateColor($this->Picture,$FillR,$FillG,$FillB,$Alpha); + ImageFilledPolygon($this->Picture,$Points,4,$ArrowColor); + + $this->drawLine($Points[0],$Points[1],$Points[2],$Points[3],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + $this->drawLine($Points[2],$Points[3],$Points[4],$Points[5],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + $this->drawLine($Points[0],$Points[1],$Points[4],$Points[5],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + + $this->drawLine($TailX,$TailY,$TailX2,$TailY2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + } + else + $this->drawLine($X1,$Y1,$TailX,$TailY,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + + /* Re-enable shadows */ + $this->Shadow = $RestoreShadow; + } + + /* Draw a label with associated arrow */ + function drawArrowLabel($X1,$Y1,$Text,$Format="") + { + $FillR = isset($Format["FillR"]) ? $Format["FillR"] : 0; + $FillG = isset($Format["FillG"]) ? $Format["FillG"] : 0; + $FillB = isset($Format["FillB"]) ? $Format["FillB"] : 0; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $FillR; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $FillG; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $FillB; + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Length = isset($Format["Length"]) ? $Format["Length"] : 50; + $Angle = isset($Format["Angle"]) ? $Format["Angle"] : 315; + $Size = isset($Format["Size"]) ? $Format["Size"] : 10; + $Position = isset($Format["Position"]) ? $Format["Position"] : POSITION_TOP; + $RoundPos = isset($Format["RoundPos"]) ? $Format["RoundPos"] : FALSE; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + + $Angle = $Angle % 360; + + $X2 = sin(($Angle+180)*PI/180)*$Length+$X1; + $Y2 = cos(($Angle+180)*PI/180)*$Length+$Y1; + + if ( $RoundPos && $Angle > 0 && $Angle < 180 ) { $Y2 = ceil($Y2); } + if ( $RoundPos && $Angle > 180 ) { $Y2 = floor($Y2); } + + $this->drawArrow($X2,$Y2,$X1,$Y1,$Format); + + $Size = imagettfbbox($FontSize,0,$FontName,$Text); + $TxtWidth = max(abs($Size[2]-$Size[0]),abs($Size[0]-$Size[6])); + $TxtHeight = max(abs($Size[1]-$Size[7]),abs($Size[3]-$Size[1])); + + if ( $Angle > 0 && $Angle < 180 ) + { + $this->drawLine($X2,$Y2,$X2-$TxtWidth,$Y2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + if ( $Position == POSITION_TOP ) + $this->drawText($X2,$Y2-2,$Text,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Align"=>TEXT_ALIGN_BOTTOMRIGHT)); + else + $this->drawText($X2,$Y2+4,$Text,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Align"=>TEXT_ALIGN_TOPRIGHT)); + } + else + { + $this->drawLine($X2,$Y2,$X2+$TxtWidth,$Y2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + if ( $Position == POSITION_TOP ) + $this->drawText($X2,$Y2-2,$Text,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha)); + else + $this->drawText($X2,$Y2+4,$Text,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Align"=>TEXT_ALIGN_TOPLEFT)); + } + } + + /* Draw a progress bar filled with specified % */ + function drawProgress($X,$Y,$Percent,$Format="") + { + if ( $Percent > 100 ) { $Percent = 100; } + if ( $Percent < 0 ) { $Percent = 0; } + + $Width = isset($Format["Width"]) ? $Format["Width"] : 200; + $Height = isset($Format["Height"]) ? $Format["Height"] : 20; + $Orientation = isset($Format["Orientation"]) ? $Format["Orientation"] : ORIENTATION_HORIZONTAL; + $ShowLabel = isset($Format["ShowLabel"]) ? $Format["ShowLabel"] : FALSE; + $LabelPos = isset($Format["LabelPos"]) ? $Format["LabelPos"] : LABEL_POS_INSIDE; + $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 10; + $R = isset($Format["R"]) ? $Format["R"] : 130; + $G = isset($Format["G"]) ? $Format["G"] : 130; + $B = isset($Format["B"]) ? $Format["B"] : 130; + $RFade = isset($Format["RFade"]) ? $Format["RFade"] : -1; + $GFade = isset($Format["GFade"]) ? $Format["GFade"] : -1; + $BFade = isset($Format["BFade"]) ? $Format["BFade"] : -1; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B; + $BoxBorderR = isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 0; + $BoxBorderG = isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 0; + $BoxBorderB = isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 0; + $BoxBackR = isset($Format["BoxBackR"]) ? $Format["BoxBackR"] : 255; + $BoxBackG = isset($Format["BoxBackG"]) ? $Format["BoxBackG"] : 255; + $BoxBackB = isset($Format["BoxBackB"]) ? $Format["BoxBackB"] : 255; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $BoxSurrounding = isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : NULL; + $NoAngle = isset($Format["NoAngle"]) ? $Format["NoAngle"] : FALSE; + + if ( $RFade != -1 && $GFade != -1 && $BFade != -1 ) + { + $RFade = (($RFade-$R)/100)*$Percent+$R; + $GFade = (($GFade-$G)/100)*$Percent+$G; + $BFade = (($BFade-$B)/100)*$Percent+$B; + } + + if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; } + if ( $BoxSurrounding != NULL ) { $BoxBorderR = $BoxBackR + $Surrounding; $BoxBorderG = $BoxBackG + $Surrounding; $BoxBorderB = $BoxBackB + $Surrounding; } + + if ( $Orientation == ORIENTATION_VERTICAL ) + { + $InnerHeight = (($Height-2)/100)*$Percent; + $this->drawFilledRectangle($X,$Y,$X+$Width,$Y-$Height,array("R"=>$BoxBackR,"G"=>$BoxBackG,"B"=>$BoxBackB,"BorderR"=>$BoxBorderR,"BorderG"=>$BoxBorderG,"BorderB"=>$BoxBorderB,"NoAngle"=>$NoAngle)); + + $RestoreShadow = $this->Shadow; $this->Shadow = FALSE; + if ( $RFade != -1 && $GFade != -1 && $BFade != -1 ) + { + $GradientOptions = array("StartR"=>$RFade,"StartG"=>$GFade,"StartB"=>$BFade,"EndR"=>$R,"EndG"=>$G,"EndB"=>$B); + $this->drawGradientArea($X+1,$Y-1,$X+$Width-1,$Y-$InnerHeight,DIRECTION_VERTICAL,$GradientOptions); + + if ( $Surrounding ) + $this->drawRectangle($X+1,$Y-1,$X+$Width-1,$Y-$InnerHeight,array("R"=>255,"G"=>255,"B"=>255,"Alpha"=>$Surrounding)); + } + else + $this->drawFilledRectangle($X+1,$Y-1,$X+$Width-1,$Y-$InnerHeight,array("R"=>$R,"G"=>$G,"B"=>$B,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB)); + + $this->Shadow = $RestoreShadow; + + if ( $ShowLabel && $LabelPos == LABEL_POS_BOTTOM ) { $this->drawText($X+($Width/2),$Y+$Margin,$Percent."%",array("Align"=>TEXT_ALIGN_TOPMIDDLE)); } + if ( $ShowLabel && $LabelPos == LABEL_POS_TOP ) { $this->drawText($X+($Width/2),$Y-$Height-$Margin,$Percent."%",array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); } + if ( $ShowLabel && $LabelPos == LABEL_POS_INSIDE ) { $this->drawText($X+($Width/2),$Y-$InnerHeight-$Margin,$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLELEFT,"Angle"=>90)); } + if ( $ShowLabel && $LabelPos == LABEL_POS_CENTER ) { $this->drawText($X+($Width/2),$Y-($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"Angle"=>90)); } + } + else + { + if ( $Percent == 100 ) + $InnerWidth = $Width-1; + else + $InnerWidth = (($Width-2)/100)*$Percent; + + $this->drawFilledRectangle($X,$Y,$X+$Width,$Y+$Height,array("R"=>$BoxBackR,"G"=>$BoxBackG,"B"=>$BoxBackB,"BorderR"=>$BoxBorderR,"BorderG"=>$BoxBorderG,"BorderB"=>$BoxBorderB,"NoAngle"=>$NoAngle)); + + $RestoreShadow = $this->Shadow; $this->Shadow = FALSE; + if ( $RFade != -1 && $GFade != -1 && $BFade != -1 ) + { + $GradientOptions = array("StartR"=>$R,"StartG"=>$G,"StartB"=>$B,"EndR"=>$RFade,"EndG"=>$GFade,"EndB"=>$BFade); + $this->drawGradientArea($X+1,$Y+1,$X+$InnerWidth,$Y+$Height-1,DIRECTION_HORIZONTAL,$GradientOptions); + + if ( $Surrounding ) + $this->drawRectangle($X+1,$Y+1,$X+$InnerWidth,$Y+$Height-1,array("R"=>255,"G"=>255,"B"=>255,"Alpha"=>$Surrounding)); + } + else + $this->drawFilledRectangle($X+1,$Y+1,$X+$InnerWidth,$Y+$Height-1,array("R"=>$R,"G"=>$G,"B"=>$B,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB)); + + $this->Shadow = $RestoreShadow; + + if ( $ShowLabel && $LabelPos == LABEL_POS_LEFT ) { $this->drawText($X-$Margin,$Y+($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLERIGHT)); } + if ( $ShowLabel && $LabelPos == LABEL_POS_RIGHT ) { $this->drawText($X+$Width+$Margin,$Y+($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLELEFT)); } + if ( $ShowLabel && $LabelPos == LABEL_POS_CENTER ) { $this->drawText($X+($Width/2),$Y+($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE)); } + if ( $ShowLabel && $LabelPos == LABEL_POS_INSIDE ) { $this->drawText($X+$InnerWidth+$Margin,$Y+($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLELEFT)); } + } + } + + /* Get the legend box size */ + function getLegendSize($Format="") + { + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize; + $BoxSize = isset($Format["BoxSize"]) ? $Format["BoxSize"] : 5; + $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5; + $Style = isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND; + $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL; + $BoxWidth = isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 5; + $BoxHeight = isset($Format["BoxHeight"]) ? $Format["BoxHeight"] : 5; + $IconAreaWidth = isset($Format["IconAreaWidth"]) ? $Format["IconAreaWidth"] : $BoxWidth; + $IconAreaHeight = isset($Format["IconAreaHeight"]) ? $Format["IconAreaHeight"] : $BoxHeight; + $XSpacing = isset($Format["XSpacing"]) ? $Format["XSpacing"] : 5; + + $Data = $this->DataSet->getData(); + + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] && isset($Serie["Picture"])) + { + list($PicWidth,$PicHeight) = $this->getPicInfo($Serie["Picture"]); + if ( $IconAreaWidth < $PicWidth ) { $IconAreaWidth = $PicWidth; } + if ( $IconAreaHeight < $PicHeight ) { $IconAreaHeight = $PicHeight; } + } + } + + $YStep = max($this->FontSize,$IconAreaHeight) + 5; + $XStep = $IconAreaWidth + 5; + $XStep = $XSpacing; + + $X=100; $Y=100; + + $Boundaries = ""; $Boundaries["L"] = $X; $Boundaries["T"] = $Y; $Boundaries["R"] = 0; $Boundaries["B"] = 0; $vY = $Y; $vX = $X; + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + if ( $Mode == LEGEND_VERTICAL ) + { + $BoxArray = $this->getTextBox($vX+$IconAreaWidth+4,$vY+$IconAreaHeight/2,$FontName,$FontSize,0,$Serie["Description"]); + + if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; } + if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } + if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; } + + $Lines = preg_split("/\n/",$Serie["Description"]); + $vY = $vY + max($this->FontSize*count($Lines),$IconAreaHeight) + 5; + } + elseif ( $Mode == LEGEND_HORIZONTAL ) + { + $Lines = preg_split("/\n/",$Serie["Description"]); + $Width = ""; + foreach($Lines as $Key => $Value) + { + $BoxArray = $this->getTextBox($vX+$IconAreaWidth+6,$Y+$IconAreaHeight/2+(($this->FontSize+3)*$Key),$FontName,$FontSize,0,$Value); + + if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; } + if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } + if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; } + + $Width[] = $BoxArray[1]["X"]; + } + + $vX=max($Width)+$XStep; + } + } + } + $vY=$vY-$YStep; $vX=$vX-$XStep; + + $TopOffset = $Y - $Boundaries["T"]; + if ( $Boundaries["B"]-($vY+$IconAreaHeight) < $TopOffset ) { $Boundaries["B"] = $vY+$IconAreaHeight+$TopOffset; } + + $Width = ($Boundaries["R"]+$Margin) - ($Boundaries["L"]-$Margin); + $Height = ($Boundaries["B"]+$Margin) - ($Boundaries["T"]-$Margin); + + return(array("Width"=>$Width,"Height"=>$Height)); + } + + /* Draw the legend of the active series */ + function drawLegend($X,$Y,$Format="") + { + $Family = isset($Format["Family"]) ? $Format["Family"] : LEGEND_FAMILY_BOX; + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize; + $FontR = isset($Format["FontR"]) ? $Format["FontR"] : $this->FontColorR; + $FontG = isset($Format["FontG"]) ? $Format["FontG"] : $this->FontColorG; + $FontB = isset($Format["FontB"]) ? $Format["FontB"] : $this->FontColorB; + $BoxWidth = isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 5; + $BoxHeight = isset($Format["BoxHeight"]) ? $Format["BoxHeight"] : 5; + $IconAreaWidth = isset($Format["IconAreaWidth"]) ? $Format["IconAreaWidth"] : $BoxWidth; + $IconAreaHeight = isset($Format["IconAreaHeight"]) ? $Format["IconAreaHeight"] : $BoxHeight; + $XSpacing = isset($Format["XSpacing"]) ? $Format["XSpacing"] : 5; + $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5; + $R = isset($Format["R"]) ? $Format["R"] : 200; + $G = isset($Format["G"]) ? $Format["G"] : 200; + $B = isset($Format["B"]) ? $Format["B"] : 200; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $Style = isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND; + $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL; + + if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; } + + $Data = $this->DataSet->getData(); + + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] && isset($Serie["Picture"])) + { + list($PicWidth,$PicHeight) = $this->getPicInfo($Serie["Picture"]); + if ( $IconAreaWidth < $PicWidth ) { $IconAreaWidth = $PicWidth; } + if ( $IconAreaHeight < $PicHeight ) { $IconAreaHeight = $PicHeight; } + } + } + + $YStep = max($this->FontSize,$IconAreaHeight) + 5; + $XStep = $IconAreaWidth + 5; + $XStep = $XSpacing; + + $Boundaries = ""; $Boundaries["L"] = $X; $Boundaries["T"] = $Y; $Boundaries["R"] = 0; $Boundaries["B"] = 0; $vY = $Y; $vX = $X; + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + if ( $Mode == LEGEND_VERTICAL ) + { + $BoxArray = $this->getTextBox($vX+$IconAreaWidth+4,$vY+$IconAreaHeight/2,$FontName,$FontSize,0,$Serie["Description"]); + + if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; } + if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } + if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; } + + $Lines = preg_split("/\n/",$Serie["Description"]); + $vY = $vY + max($this->FontSize*count($Lines),$IconAreaHeight) + 5; + } + elseif ( $Mode == LEGEND_HORIZONTAL ) + { + $Lines = preg_split("/\n/",$Serie["Description"]); + $Width = ""; + foreach($Lines as $Key => $Value) + { + $BoxArray = $this->getTextBox($vX+$IconAreaWidth+6,$Y+$IconAreaHeight/2+(($this->FontSize+3)*$Key),$FontName,$FontSize,0,$Value); + + if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; } + if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } + if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; } + + $Width[] = $BoxArray[1]["X"]; + } + + $vX=max($Width)+$XStep; + } + } + } + $vY=$vY-$YStep; $vX=$vX-$XStep; + + $TopOffset = $Y - $Boundaries["T"]; + if ( $Boundaries["B"]-($vY+$IconAreaHeight) < $TopOffset ) { $Boundaries["B"] = $vY+$IconAreaHeight+$TopOffset; } + + if ( $Style == LEGEND_ROUND ) + $this->drawRoundedFilledRectangle($Boundaries["L"]-$Margin,$Boundaries["T"]-$Margin,$Boundaries["R"]+$Margin,$Boundaries["B"]+$Margin,$Margin,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB)); + elseif ( $Style == LEGEND_BOX ) + $this->drawFilledRectangle($Boundaries["L"]-$Margin,$Boundaries["T"]-$Margin,$Boundaries["R"]+$Margin,$Boundaries["B"]+$Margin,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB)); + + $RestoreShadow = $this->Shadow; $this->Shadow = FALSE; + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; + $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"]; + + if ( isset($Serie["Picture"]) ) + { + $Picture = $Serie["Picture"]; + list($PicWidth,$PicHeight) = $this->getPicInfo($Picture); + $PicX = $X+$IconAreaWidth/2; $PicY = $Y+$IconAreaHeight/2; + + $this->drawFromPNG($PicX-$PicWidth/2,$PicY-$PicHeight/2,$Picture); + } + else + { + if ( $Family == LEGEND_FAMILY_BOX ) + { + if ( $BoxWidth != $IconAreaWidth ) { $XOffset = floor(($IconAreaWidth-$BoxWidth)/2); } else { $XOffset = 0; } + if ( $BoxHeight != $IconAreaHeight ) { $YOffset = floor(($IconAreaHeight-$BoxHeight)/2); } else { $YOffset = 0; } + + $this->drawFilledRectangle($X+1+$XOffset,$Y+1+$YOffset,$X+$BoxWidth+$XOffset+1,$Y+$BoxHeight+1+$YOffset,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20)); + $this->drawFilledRectangle($X+$XOffset,$Y+$YOffset,$X+$BoxWidth+$XOffset,$Y+$BoxHeight+$YOffset,array("R"=>$R,"G"=>$G,"B"=>$B,"Surrounding"=>20)); + } + elseif ( $Family == LEGEND_FAMILY_CIRCLE ) + { + $this->drawFilledCircle($X+1+$IconAreaWidth/2,$Y+1+$IconAreaHeight/2,min($IconAreaHeight/2,$IconAreaWidth/2),array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20)); + $this->drawFilledCircle($X+$IconAreaWidth/2,$Y+$IconAreaHeight/2,min($IconAreaHeight/2,$IconAreaWidth/2),array("R"=>$R,"G"=>$G,"B"=>$B,"Surrounding"=>20)); + } + elseif ( $Family == LEGEND_FAMILY_LINE ) + { + $this->drawLine($X+1,$Y+1+$IconAreaHeight/2,$X+1+$IconAreaWidth,$Y+1+$IconAreaHeight/2,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20,"Ticks"=>$Ticks,"Weight"=>$Weight)); + $this->drawLine($X,$Y+$IconAreaHeight/2,$X+$IconAreaWidth,$Y+$IconAreaHeight/2,array("R"=>$R,"G"=>$G,"B"=>$B,"Ticks"=>$Ticks,"Weight"=>$Weight)); + } + } + + if ( $Mode == LEGEND_VERTICAL ) + { + $Lines = preg_split("/\n/",$Serie["Description"]); + foreach($Lines as $Key => $Value) + $this->drawText($X+$IconAreaWidth+4,$Y+$IconAreaHeight/2+(($this->FontSize+3)*$Key),$Value,array("R"=>$FontR,"G"=>$FontG,"B"=>$FontB,"Align"=>TEXT_ALIGN_MIDDLELEFT,"FontSize"=>$FontSize,"FontName"=>$FontName)); + + $Y=$Y+max($this->FontSize*count($Lines),$IconAreaHeight) + 5; + } + elseif ( $Mode == LEGEND_HORIZONTAL ) + { + $Lines = preg_split("/\n/",$Serie["Description"]); + $Width = ""; + foreach($Lines as $Key => $Value) + { + $BoxArray = $this->drawText($X+$IconAreaWidth+4,$Y+$IconAreaHeight/2+(($this->FontSize+3)*$Key),$Value,array("R"=>$FontR,"G"=>$FontG,"B"=>$FontB,"Align"=>TEXT_ALIGN_MIDDLELEFT,"FontSize"=>$FontSize,"FontName"=>$FontName)); + $Width[] = $BoxArray[1]["X"]; + } + $X=max($Width)+2+$XStep; + } + } + } + + + $this->Shadow = $RestoreShadow; + } + + function drawScale($Format="") + { + $Pos = isset($Format["Pos"]) ? $Format["Pos"] : SCALE_POS_LEFTRIGHT; + $Floating = isset($Format["Floating"]) ? $Format["Floating"] : FALSE; + $Mode = isset($Format["Mode"]) ? $Format["Mode"] : SCALE_MODE_FLOATING; + $RemoveXAxis = isset($Format["RemoveXAxis"]) ? $Format["RemoveXAxis"] : FALSE; + $MinDivHeight = isset($Format["MinDivHeight"]) ? $Format["MinDivHeight"] : 20; + $Factors = isset($Format["Factors"]) ? $Format["Factors"] : array(1,2,5); + $ManualScale = isset($Format["ManualScale"]) ? $Format["ManualScale"] : array("0"=>array("Min"=>-100,"Max"=>100)); + $XMargin = isset($Format["XMargin"]) ? $Format["XMargin"] : AUTO; + $YMargin = isset($Format["YMargin"]) ? $Format["YMargin"] : 0; + $ScaleSpacing = isset($Format["ScaleSpacing"]) ? $Format["ScaleSpacing"] : 15; + $InnerTickWidth = isset($Format["InnerTickWidth"]) ? $Format["InnerTickWidth"] : 2; + $OuterTickWidth = isset($Format["OuterTickWidth"]) ? $Format["OuterTickWidth"] : 2; + $DrawXLines = isset($Format["DrawXLines"]) ? $Format["DrawXLines"] : TRUE; + $DrawYLines = isset($Format["DrawYLines"]) ? $Format["DrawYLines"] : ALL; + $GridTicks = isset($Format["GridTicks"]) ? $Format["GridTicks"] : 4; + $GridR = isset($Format["GridR"]) ? $Format["GridR"] : 255; + $GridG = isset($Format["GridG"]) ? $Format["GridG"] : 255; + $GridB = isset($Format["GridB"]) ? $Format["GridB"] : 255; + $GridAlpha = isset($Format["GridAlpha"]) ? $Format["GridAlpha"] : 40; + $AxisRo = isset($Format["AxisR"]) ? $Format["AxisR"] : 0; + $AxisGo = isset($Format["AxisG"]) ? $Format["AxisG"] : 0; + $AxisBo = isset($Format["AxisB"]) ? $Format["AxisB"] : 0; + $AxisAlpha = isset($Format["AxisAlpha"]) ? $Format["AxisAlpha"] : 100; + $TickRo = isset($Format["TickR"]) ? $Format["TickR"] : 0; + $TickGo = isset($Format["TickG"]) ? $Format["TickG"] : 0; + $TickBo = isset($Format["TickB"]) ? $Format["TickB"] : 0; + $TickAlpha = isset($Format["TickAlpha"]) ? $Format["TickAlpha"] : 100; + $DrawSubTicks = isset($Format["DrawSubTicks"]) ? $Format["DrawSubTicks"] : FALSE; + $InnerSubTickWidth = isset($Format["InnerSubTickWidth"]) ? $Format["InnerSubTickWidth"] : 0; + $OuterSubTickWidth = isset($Format["OuterSubTickWidth"]) ? $Format["OuterSubTickWidth"] : 2; + $SubTickR = isset($Format["SubTickR"]) ? $Format["SubTickR"] : 255; + $SubTickG = isset($Format["SubTickG"]) ? $Format["SubTickG"] : 0; + $SubTickB = isset($Format["SubTickB"]) ? $Format["SubTickB"] : 0; + $SubTickAlpha = isset($Format["SubTickAlpha"]) ? $Format["SubTickAlpha"] : 100; + $AutoAxisLabels = isset($Format["AutoAxisLabels"]) ? $Format["AutoAxisLabels"] : TRUE; + $XReleasePercent = isset($Format["XReleasePercent"]) ? $Format["XReleasePercent"] : 1; + $DrawArrows = isset($Format["DrawArrows"]) ? $Format["DrawArrows"] : FALSE; + $ArrowSize = isset($Format["ArrowSize"]) ? $Format["ArrowSize"] : 8; + $CycleBackground = isset($Format["CycleBackground"]) ? $Format["CycleBackground"] : FALSE; + $BackgroundR1 = isset($Format["BackgroundR1"]) ? $Format["BackgroundR1"] : 255; + $BackgroundG1 = isset($Format["BackgroundG1"]) ? $Format["BackgroundG1"] : 255; + $BackgroundB1 = isset($Format["BackgroundB1"]) ? $Format["BackgroundB1"] : 255; + $BackgroundAlpha1 = isset($Format["BackgroundAlpha1"]) ? $Format["BackgroundAlpha1"] : 20; + $BackgroundR2 = isset($Format["BackgroundR2"]) ? $Format["BackgroundR2"] : 230; + $BackgroundG2 = isset($Format["BackgroundG2"]) ? $Format["BackgroundG2"] : 230; + $BackgroundB2 = isset($Format["BackgroundB2"]) ? $Format["BackgroundB2"] : 230; + $BackgroundAlpha2 = isset($Format["BackgroundAlpha2"]) ? $Format["BackgroundAlpha2"] : 20; + $LabelingMethod = isset($Format["LabelingMethod"]) ? $Format["LabelingMethod"] : LABELING_ALL; + $LabelSkip = isset($Format["LabelSkip"]) ? $Format["LabelSkip"] : 0; + $LabelRotation = isset($Format["LabelRotation"]) ? $Format["LabelRotation"] : 0; + $SkippedAxisTicks = isset($Format["SkippedAxisTicks"]) ? $Format["SkippedAxisTicks"] : $GridTicks+2; + $SkippedAxisR = isset($Format["SkippedAxisR"]) ? $Format["SkippedAxisR"] : $GridR; + $SkippedAxisG = isset($Format["SkippedAxisG"]) ? $Format["SkippedAxisG"] : $GridG; + $SkippedAxisB = isset($Format["SkippedAxisB"]) ? $Format["SkippedAxisB"] : $GridB; + $SkippedAxisAlpha = isset($Format["SkippedAxisAlpha"]) ? $Format["SkippedAxisAlpha"] : $GridAlpha-30; + $SkippedTickR = isset($Format["SkippedTickR"]) ? $Format["SkippedTickR"] : $TickRo; + $SkippedTickG = isset($Format["SkippedTickG"]) ? $Format["SkippedTickG"] : $TickGo; + $SkippedTickB = isset($Format["SkippedTicksB"]) ? $Format["SkippedTickB"] : $TickBo; + $SkippedTickAlpha = isset($Format["SkippedTickAlpha"]) ? $Format["SkippedTickAlpha"] : $TickAlpha-80; + $SkippedInnerTickWidth = isset($Format["SkippedInnerTickWidth"]) ? $Format["SkippedInnerTickWidth"] : 0; + $SkippedOuterTickWidth = isset($Format["SkippedOuterTickWidth"]) ? $Format["SkippedOuterTickWidth"] : 2; + + /* Floating scale require X & Y margins to be set manually */ + if ( $Floating && ( $XMargin == AUTO || $YMargin == 0 ) ) { $Floating = FALSE; } + + /* Skip a NOTICE event in case of an empty array */ + if ( $DrawYLines == NONE || $DrawYLines == FALSE ) { $DrawYLines = array("zarma"=>"31"); } + + /* Define the color for the skipped elements */ + $SkippedAxisColor = array("R"=>$SkippedAxisR,"G"=>$SkippedAxisG,"B"=>$SkippedAxisB,"Alpha"=>$SkippedAxisAlpha,"Ticks"=>$SkippedAxisTicks); + $SkippedTickColor = array("R"=>$SkippedTickR,"G"=>$SkippedTickG,"B"=>$SkippedTickB,"Alpha"=>$SkippedTickAlpha); + + $Data = $this->DataSet->getData(); + if ( isset($Data["Abscissa"]) ) { $Abscissa = $Data["Abscissa"]; } else { $Abscissa = NULL; } + + /* Unset the abscissa axis, needed if we display multiple charts on the same picture */ + if ( $Abscissa != NULL ) + { + foreach($Data["Axis"] as $AxisID => $Parameters) + { if ($Parameters["Identity"] == AXIS_X) { unset($Data["Axis"][$AxisID]); } } + } + + /* Build the scale settings */ + $GotXAxis = FALSE; + foreach($Data["Axis"] as $AxisID => $AxisParameter) + { + if ( $AxisParameter["Identity"] == AXIS_X ) { $GotXAxis = TRUE; } + + if ( $Pos == SCALE_POS_LEFTRIGHT && $AxisParameter["Identity"] == AXIS_Y) + { $Height = $this->GraphAreaY2-$this->GraphAreaY1 - $YMargin*2; } + elseif ( $Pos == SCALE_POS_LEFTRIGHT && $AxisParameter["Identity"] == AXIS_X) + { $Height = $this->GraphAreaX2-$this->GraphAreaX1; } + elseif ( $Pos == SCALE_POS_TOPBOTTOM && $AxisParameter["Identity"] == AXIS_Y) + { $Height = $this->GraphAreaX2-$this->GraphAreaX1 - $YMargin*2;; } + else + { $Height = $this->GraphAreaY2-$this->GraphAreaY1; } + + $AxisMin = ABSOLUTE_MAX; $AxisMax = OUT_OF_SIGHT; + if ( $Mode == SCALE_MODE_FLOATING || $Mode == SCALE_MODE_START0 ) + { + foreach($Data["Series"] as $SerieID => $SerieParameter) + { + if ( $SerieParameter["Axis"] == $AxisID && $Data["Series"][$SerieID]["isDrawable"] && $Data["Abscissa"] != $SerieID) + { + $AxisMax = max($AxisMax,$Data["Series"][$SerieID]["Max"]); + $AxisMin = min($AxisMin,$Data["Series"][$SerieID]["Min"]); + } + } + $AutoMargin = (($AxisMax-$AxisMin)/100)*$XReleasePercent; + + $Data["Axis"][$AxisID]["Min"] = $AxisMin-$AutoMargin; $Data["Axis"][$AxisID]["Max"] = $AxisMax+$AutoMargin; + if ( $Mode == SCALE_MODE_START0 ) { $Data["Axis"][$AxisID]["Min"] = 0; } + } + elseif ( $Mode == SCALE_MODE_MANUAL ) + { + if ( isset($ManualScale[$AxisID]["Min"]) && isset($ManualScale[$AxisID]["Max"]) ) + { + $Data["Axis"][$AxisID]["Min"] = $ManualScale[$AxisID]["Min"]; + $Data["Axis"][$AxisID]["Max"] = $ManualScale[$AxisID]["Max"]; + } + else + { echo "Manual scale boundaries not set."; exit(); } + } + elseif ( $Mode == SCALE_MODE_ADDALL || $Mode == SCALE_MODE_ADDALL_START0 ) + { + $Series = ""; + foreach($Data["Series"] as $SerieID => $SerieParameter) + { if ( $SerieParameter["Axis"] == $AxisID && $SerieParameter["isDrawable"] && $Data["Abscissa"] != $SerieID ) { $Series[$SerieID] = count($Data["Series"][$SerieID]["Data"]); } } + + for ($ID=0;$ID<=max($Series)-1;$ID++) + { + $PointMin = 0; $PointMax = 0; + foreach($Series as $SerieID => $ValuesCount ) + { + if (isset($Data["Series"][$SerieID]["Data"][$ID]) && $Data["Series"][$SerieID]["Data"][$ID] != NULL ) + { + $Value = $Data["Series"][$SerieID]["Data"][$ID]; + if ( $Value > 0 ) { $PointMax = $PointMax + $Value; } else { $PointMin = $PointMin + $Value; } + } + } + $AxisMax = max($AxisMax,$PointMax); + $AxisMin = min($AxisMin,$PointMin); + } + $AutoMargin = (($AxisMax-$AxisMin)/100)*$XReleasePercent; + $Data["Axis"][$AxisID]["Min"] = $AxisMin-$AutoMargin; $Data["Axis"][$AxisID]["Max"] = $AxisMax+$AutoMargin; + } + $MaxDivs = floor($Height/$MinDivHeight); + + if ( $Mode == SCALE_MODE_ADDALL_START0 ) { $Data["Axis"][$AxisID]["Min"] = 0; } + + $Scale = $this->computeScale($Data["Axis"][$AxisID]["Min"],$Data["Axis"][$AxisID]["Max"],$MaxDivs,$Factors,$AxisID); + + $Data["Axis"][$AxisID]["Margin"] = $AxisParameter["Identity"] == AXIS_X ? $XMargin : $YMargin; + $Data["Axis"][$AxisID]["ScaleMin"] = $Scale["XMin"]; + $Data["Axis"][$AxisID]["ScaleMax"] = $Scale["XMax"]; + $Data["Axis"][$AxisID]["Rows"] = $Scale["Rows"]; + $Data["Axis"][$AxisID]["RowHeight"] = $Scale["RowHeight"]; + + if ( isset($Scale["Format"]) ) { $Data["Axis"][$AxisID]["Format"] = $Scale["Format"]; } + + if ( !isset($Data["Axis"][$AxisID]["Display"]) ) { $Data["Axis"][$AxisID]["Display"] = NULL; } + if ( !isset($Data["Axis"][$AxisID]["Format"]) ) { $Data["Axis"][$AxisID]["Format"] = NULL; } + if ( !isset($Data["Axis"][$AxisID]["Unit"]) ) { $Data["Axis"][$AxisID]["Unit"] = NULL; } + } + + /* Still no X axis */ + if ( $GotXAxis == FALSE ) + { + if ( $Abscissa != NULL ) + { + $Points = count($Data["Series"][$Abscissa]["Data"]); + if ( $AutoAxisLabels ) + $AxisName = isset($Data["Series"][$Abscissa]["Description"]) ? $Data["Series"][$Abscissa]["Description"] : NULL; + else + $AxisName = NULL; + } + else + { + $Points = 0; + $AxisName = isset($Data["XAxisName"]) ? $Data["XAxisName"] : NULL; + foreach($Data["Series"] as $SerieID => $SerieParameter) + { if ( $SerieParameter["isDrawable"] ) { $Points = max($Points,count($SerieParameter["Data"])); } } + } + + $AxisID = count($Data["Axis"]); + $Data["Axis"][$AxisID]["Identity"] = AXIS_X; + if ( $Pos == SCALE_POS_LEFTRIGHT ) { $Data["Axis"][$AxisID]["Position"] = AXIS_POSITION_BOTTOM; } else { $Data["Axis"][$AxisID]["Position"] = AXIS_POSITION_LEFT; } + if ( isset($Data["AbscissaName"]) ) { $Data["Axis"][$AxisID]["Name"] = $Data["AbscissaName"]; } + if ( $XMargin == AUTO ) + { + if ( $Pos == SCALE_POS_LEFTRIGHT ) + { $Height = $this->GraphAreaX2-$this->GraphAreaX1; } + else + { $Height = $this->GraphAreaY2-$this->GraphAreaY1; } + + if ( $Points == 1 ) + $Data["Axis"][$AxisID]["Margin"] = $Height / 2; + else + $Data["Axis"][$AxisID]["Margin"] = ($Height/$Points) / 2; + } + else + { $Data["Axis"][$AxisID]["Margin"] = $XMargin; } + $Data["Axis"][$AxisID]["Rows"] = $Points-1; + if ( !isset($Data["Axis"][$AxisID]["Display"]) ) { $Data["Axis"][$AxisID]["Display"] = NULL; } + if ( !isset($Data["Axis"][$AxisID]["Format"]) ) { $Data["Axis"][$AxisID]["Format"] = NULL; } + if ( !isset($Data["Axis"][$AxisID]["Unit"]) ) { $Data["Axis"][$AxisID]["Unit"] = NULL; } + } + + /* Do we need to reverse the abscissa position? */ + if ( $Pos != SCALE_POS_LEFTRIGHT ) + { + if ( $Data["AbsicssaPosition"] == AXIS_POSITION_BOTTOM ) + { $Data["AbsicssaPosition"] = AXIS_POSITION_LEFT; } + else + { $Data["AbsicssaPosition"] = AXIS_POSITION_RIGHT; } + } + $Data["Axis"][$AxisID]["Position"] = $Data["AbsicssaPosition"]; + + $this->DataSet->saveOrientation($Pos); + $this->DataSet->saveAxisConfig($Data["Axis"]); + $this->DataSet->saveYMargin($YMargin); + + $FontColorRo = $this->FontColorR; $FontColorGo = $this->FontColorG; $FontColorBo = $this->FontColorB; + + $AxisPos["L"] = $this->GraphAreaX1; $AxisPos["R"] = $this->GraphAreaX2; $AxisPos["T"] = $this->GraphAreaY1; $AxisPos["B"] = $this->GraphAreaY2; + foreach($Data["Axis"] as $AxisID => $Parameters) + { + if ( isset($Parameters["Color"]) ) + { + $AxisR = $Parameters["Color"]["R"]; $AxisG = $Parameters["Color"]["G"]; $AxisB = $Parameters["Color"]["B"]; + $TickR = $Parameters["Color"]["R"]; $TickG = $Parameters["Color"]["G"]; $TickB = $Parameters["Color"]["B"]; + $this->setFontProperties(array("R"=>$Parameters["Color"]["R"],"G"=>$Parameters["Color"]["G"],"B"=>$Parameters["Color"]["B"])); + } + else + { + $AxisR = $AxisRo; $AxisG = $AxisGo; $AxisB = $AxisBo; + $TickR = $TickRo; $TickG = $TickGo; $TickB = $TickBo; + $this->setFontProperties(array("R"=>$FontColorRo,"G"=>$FontColorGo,"B"=>$FontColorBo)); + } + + $LastValue = "w00t"; $ID = 1; + if ( $Parameters["Identity"] == AXIS_X ) + { + if ( $Pos == SCALE_POS_LEFTRIGHT ) + { + if ( $Parameters["Position"] == AXIS_POSITION_BOTTOM ) + { + if ( $LabelRotation == 0 ) { $LabelAlign = TEXT_ALIGN_TOPMIDDLE; $YLabelOffset = 2; } + if ( $LabelRotation > 0 && $LabelRotation < 190 ) { $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $YLabelOffset = 5; } + if ( $LabelRotation == 180 ) { $LabelAlign = TEXT_ALIGN_BOTTOMMIDDLE; $YLabelOffset = 5; } + if ( $LabelRotation > 180 && $LabelRotation < 360 ) { $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $YLabelOffset = 2; } + + if ( !$RemoveXAxis ) + { + if ( $Floating ) + { $FloatingOffset = $YMargin; $this->drawLine($this->GraphAreaX1+$Parameters["Margin"],$AxisPos["B"],$this->GraphAreaX2-$Parameters["Margin"],$AxisPos["B"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($this->GraphAreaX1,$AxisPos["B"],$this->GraphAreaX2,$AxisPos["B"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($this->GraphAreaX2-$Parameters["Margin"],$AxisPos["B"],$this->GraphAreaX2+($ArrowSize*2),$AxisPos["B"],array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + } + + $Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Parameters["Margin"]*2; + + if ($Parameters["Rows"] == 0 ) { $Step = $Width; } else { $Step = $Width / ($Parameters["Rows"]); } + + $MaxBottom = $AxisPos["B"]; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $XPos = $this->GraphAreaX1 + $Parameters["Margin"] + $Step*$i; + $YPos = $AxisPos["B"]; + + if ( $Abscissa != NULL ) + { if ( isset($Data["Series"][$Abscissa]["Data"][$i]) ) { $Value = $this->scaleFormat($Data["Series"][$Abscissa]["Data"][$i],$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); } else { $Value = ""; } } + else + { + if ( isset($Parameters["ScaleMin"]) && isset ($Parameters["RowHeight"]) ) + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); + else + $Value = $i; + } + + $ID++; $Skipped = TRUE; + if ( $this->isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip) && !$RemoveXAxis) + { + $Bounds = $this->drawText($XPos,$YPos+$OuterTickWidth+$YLabelOffset,$Value,array("Angle"=>$LabelRotation,"Align"=>$LabelAlign)); + $TxtBottom = $YPos+$OuterTickWidth+2+($Bounds[0]["Y"]-$Bounds[2]["Y"]); + $MaxBottom = max($MaxBottom,$TxtBottom); + $LastValue = $Value; + $Skipped = FALSE; + } + + if ( $RemoveXAxis ) { $Skipped = FALSE; } + + if ( $Skipped ) + { + if ( $DrawXLines ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,$SkippedAxisColor); } + if ( ($SkippedInnerTickWidth !=0 || $SkippedOuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos,$YPos-$SkippedInnerTickWidth,$XPos,$YPos+$SkippedOuterTickWidth,$SkippedTickColor); } + } + else + { + if ( $DrawXLines && ($XPos != $this->GraphAreaX1 && $XPos != $this->GraphAreaX2) ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + if ( ($InnerTickWidth !=0 || $OuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos,$YPos-$InnerTickWidth,$XPos,$YPos+$OuterTickWidth,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); } + } + } + + if ( isset($Parameters["Name"]) && !$RemoveXAxis) + { + $YPos = $MaxBottom+2; + $XPos = $this->GraphAreaX1+($this->GraphAreaX2-$this->GraphAreaX1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_TOPMIDDLE)); + $MaxBottom = $Bounds[0]["Y"]; + + $this->DataSet->Data["GraphArea"]["Y2"] = $MaxBottom + $this->FontSize; + } + + $AxisPos["B"] = $MaxBottom + $ScaleSpacing; + } + elseif ( $Parameters["Position"] == AXIS_POSITION_TOP ) + { + if ( $LabelRotation == 0 ) { $LabelAlign = TEXT_ALIGN_BOTTOMMIDDLE; $YLabelOffset = 2; } + if ( $LabelRotation > 0 && $LabelRotation < 190 ) { $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $YLabelOffset = 2; } + if ( $LabelRotation == 180 ) { $LabelAlign = TEXT_ALIGN_TOPMIDDLE; $YLabelOffset = 5; } + if ( $LabelRotation > 180 && $LabelRotation < 360 ) { $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $YLabelOffset = 5; } + + if ( !$RemoveXAxis ) + { + if ( $Floating ) + { $FloatingOffset = $YMargin; $this->drawLine($this->GraphAreaX1+$Parameters["Margin"],$AxisPos["T"],$this->GraphAreaX2-$Parameters["Margin"],$AxisPos["T"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($this->GraphAreaX1,$AxisPos["T"],$this->GraphAreaX2,$AxisPos["T"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($this->GraphAreaX2-$Parameters["Margin"],$AxisPos["T"],$this->GraphAreaX2+($ArrowSize*2),$AxisPos["T"],array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + } + + $Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Parameters["Margin"]*2; + + if ($Parameters["Rows"] == 0 ) { $Step = $Width; } else { $Step = $Width / $Parameters["Rows"]; } + + $MinTop = $AxisPos["T"]; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $XPos = $this->GraphAreaX1 + $Parameters["Margin"] + $Step*$i; + $YPos = $AxisPos["T"]; + + if ( $Abscissa != NULL ) + { if ( isset($Data["Series"][$Abscissa]["Data"][$i]) ) { $Value = $this->scaleFormat($Data["Series"][$Abscissa]["Data"][$i],$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); } else { $Value = ""; } } + else + { + if ( isset($Parameters["ScaleMin"]) && isset ($Parameters["RowHeight"]) ) + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); + else + $Value = $i; + } + + $ID++; $Skipped = TRUE; + if ( $this->isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip) && !$RemoveXAxis) + { + $Bounds = $this->drawText($XPos,$YPos-$OuterTickWidth-$YLabelOffset,$Value,array("Angle"=>$LabelRotation,"Align"=>$LabelAlign)); + $TxtBox = $YPos-$OuterTickWidth-2-($Bounds[0]["Y"]-$Bounds[2]["Y"]); + $MinTop = min($MinTop,$TxtBox); + $LastValue = $Value; + $Skipped = FALSE; + } + + if ( $RemoveXAxis ) { $Skipped = FALSE; } + + if ( $Skipped ) + { + if ( $DrawXLines ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,$SkippedAxisColor); } + if ( ($SkippedInnerTickWidth !=0 || $SkippedOuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos,$YPos+$SkippedInnerTickWidth,$XPos,$YPos-$SkippedOuterTickWidth,$SkippedTickColor); } + } + else + { + if ( $DrawXLines ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + if ( ($InnerTickWidth !=0 || $OuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos,$YPos+$InnerTickWidth,$XPos,$YPos-$OuterTickWidth,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); } + } + + } + + if ( isset($Parameters["Name"]) && !$RemoveXAxis ) + { + $YPos = $MinTop-2; + $XPos = $this->GraphAreaX1+($this->GraphAreaX2-$this->GraphAreaX1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + $MinTop = $Bounds[2]["Y"]; + + $this->DataSet->Data["GraphArea"]["Y1"] = $MinTop; + } + + $AxisPos["T"] = $MinTop - $ScaleSpacing; + } + } + elseif ( $Pos == SCALE_POS_TOPBOTTOM ) + { + if ( $Parameters["Position"] == AXIS_POSITION_LEFT ) + { + if ( $LabelRotation == 0 ) { $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $XLabelOffset = -2; } + if ( $LabelRotation > 0 && $LabelRotation < 190 ) { $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $XLabelOffset = -6; } + if ( $LabelRotation == 180 ) { $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $XLabelOffset = -2; } + if ( $LabelRotation > 180 && $LabelRotation < 360 ) { $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $XLabelOffset = -5; } + + if ( !$RemoveXAxis ) + { + if ( $Floating ) + { $FloatingOffset = $YMargin; $this->drawLine($AxisPos["L"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["L"],$this->GraphAreaY2-$Parameters["Margin"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($AxisPos["L"],$this->GraphAreaY1,$AxisPos["L"],$this->GraphAreaY2,array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($AxisPos["L"],$this->GraphAreaY2-$Parameters["Margin"],$AxisPos["L"],$this->GraphAreaY2+($ArrowSize*2),array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + } + + $Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Parameters["Margin"]*2; + + if ($Parameters["Rows"] == 0 ) { $Step = $Height; } else { $Step = $Height / $Parameters["Rows"]; } + + $MinLeft = $AxisPos["L"]; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $YPos = $this->GraphAreaY1 + $Parameters["Margin"] + $Step*$i; + $XPos = $AxisPos["L"]; + + if ( $Abscissa != NULL ) + { if ( isset($Data["Series"][$Abscissa]["Data"][$i]) ) { $Value = $this->scaleFormat($Data["Series"][$Abscissa]["Data"][$i],$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); } else { $Value = ""; } } + else + { + if ( isset($Parameters["ScaleMin"]) && isset ($Parameters["RowHeight"]) ) + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); + else + $Value = $i; + } + + $ID++; $Skipped = TRUE; + if ( $this->isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip) && !$RemoveXAxis) + { + $Bounds = $this->drawText($XPos-$OuterTickWidth+$XLabelOffset,$YPos,$Value,array("Angle"=>$LabelRotation,"Align"=>$LabelAlign)); + $TxtBox = $XPos-$OuterTickWidth-2-($Bounds[1]["X"]-$Bounds[0]["X"]); + $MinLeft = min($MinLeft,$TxtBox); + $LastValue = $Value; + $Skipped = FALSE; + } + + if ( $RemoveXAxis ) { $Skipped = FALSE; } + + if ( $Skipped ) + { + if ( $DrawXLines ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,$SkippedAxisColor); } + if ( ($SkippedInnerTickWidth !=0 || $SkippedOuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos-$SkippedOuterTickWidth,$YPos,$XPos+$SkippedInnerTickWidth,$YPos,$SkippedTickColor); } + } + else + { + if ( $DrawXLines && ($YPos != $this->GraphAreaY1 && $YPos != $this->GraphAreaY2) ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + if ( ($InnerTickWidth !=0 || $OuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos-$OuterTickWidth,$YPos,$XPos+$InnerTickWidth,$YPos,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); } + } + + } + if ( isset($Parameters["Name"]) && !$RemoveXAxis ) + { + $XPos = $MinLeft-2; + $YPos = $this->GraphAreaY1+($this->GraphAreaY2-$this->GraphAreaY1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE,"Angle"=>90)); + $MinLeft = $Bounds[0]["X"]; + + $this->DataSet->Data["GraphArea"]["X1"] = $MinLeft; + } + + $AxisPos["L"] = $MinLeft - $ScaleSpacing; + } + elseif ( $Parameters["Position"] == AXIS_POSITION_RIGHT ) + { + if ( $LabelRotation == 0 ) { $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $XLabelOffset = 2; } + if ( $LabelRotation > 0 && $LabelRotation < 190 ) { $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $XLabelOffset = 6; } + if ( $LabelRotation == 180 ) { $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $XLabelOffset = 5; } + if ( $LabelRotation > 180 && $LabelRotation < 360 ) { $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $XLabelOffset = 7; } + + if ( !$RemoveXAxis ) + { + if ( $Floating ) + { $FloatingOffset = $YMargin; $this->drawLine($AxisPos["R"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["R"],$this->GraphAreaY2-$Parameters["Margin"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($AxisPos["R"],$this->GraphAreaY1,$AxisPos["R"],$this->GraphAreaY2,array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($AxisPos["R"],$this->GraphAreaY2-$Parameters["Margin"],$AxisPos["R"],$this->GraphAreaY2+($ArrowSize*2),array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + } + + $Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Parameters["Margin"]*2; + + if ($Parameters["Rows"] == 0 ) { $Step = $Height; } else { $Step = $Height / $Parameters["Rows"]; } + + $MaxRight = $AxisPos["R"]; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $YPos = $this->GraphAreaY1 + $Parameters["Margin"] + $Step*$i; + $XPos = $AxisPos["R"]; + + if ( $Abscissa != NULL ) + { if ( isset($Data["Series"][$Abscissa]["Data"][$i]) ) { $Value = $this->scaleFormat($Data["Series"][$Abscissa]["Data"][$i],$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); } else { $Value = ""; } } + else + { + if ( isset($Parameters["ScaleMin"]) && isset ($Parameters["RowHeight"]) ) + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); + else + $Value = $i; + } + + $ID++; $Skipped = TRUE; + if ( $this->isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip) && !$RemoveXAxis) + { + $Bounds = $this->drawText($XPos+$OuterTickWidth+$XLabelOffset,$YPos,$Value,array("Angle"=>$LabelRotation,"Align"=>$LabelAlign)); + $TxtBox = $XPos+$OuterTickWidth+2+($Bounds[1]["X"]-$Bounds[0]["X"]); + $MaxRight = max($MaxRight,$TxtBox); + $LastValue = $Value; + $Skipped = FALSE; + } + + if ( $RemoveXAxis ) { $Skipped = FALSE; } + + if ( $Skipped ) + { + if ( $DrawXLines ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,$SkippedAxisColor); } + if ( ($SkippedInnerTickWidth != 0 || $SkippedOuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos+$SkippedOuterTickWidth,$YPos,$XPos-$SkippedInnerTickWidth,$YPos,$SkippedTickColor); } + } + else + { + if ( $DrawXLines ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + if ( ($InnerTickWidth != 0 || $OuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos+$OuterTickWidth,$YPos,$XPos-$InnerTickWidth,$YPos,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); } + } + + } + + if ( isset($Parameters["Name"]) && !$RemoveXAxis) + { + $XPos = $MaxRight+4; + $YPos = $this->GraphAreaY1+($this->GraphAreaY2-$this->GraphAreaY1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE,"Angle"=>270)); + $MaxRight = $Bounds[1]["X"]; + + $this->DataSet->Data["GraphArea"]["X2"] = $MaxRight + $this->FontSize; + } + + $AxisPos["R"] = $MaxRight + $ScaleSpacing; + } + } + } + + + + if ( $Parameters["Identity"] == AXIS_Y ) + { + if ( $Pos == SCALE_POS_LEFTRIGHT ) + { + if ( $Parameters["Position"] == AXIS_POSITION_LEFT ) + { + + if ( $Floating ) + { $FloatingOffset = $XMargin; $this->drawLine($AxisPos["L"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["L"],$this->GraphAreaY2-$Parameters["Margin"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($AxisPos["L"],$this->GraphAreaY1,$AxisPos["L"],$this->GraphAreaY2,array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($AxisPos["L"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["L"],$this->GraphAreaY1-($ArrowSize*2),array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + + $Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Parameters["Margin"]*2; + $Step = $Height / $Parameters["Rows"]; $SubTicksSize = $Step /2; $MinLeft = $AxisPos["L"]; + $LastY = NULL; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $YPos = $this->GraphAreaY2 - $Parameters["Margin"] - $Step*$i; + $XPos = $AxisPos["L"]; + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Parameters["Display"],$Parameters["Format"],$Parameters["Unit"]); + + if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); } + if ( $LastY != NULL && $CycleBackground && ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->drawFilledRectangle($this->GraphAreaX1+$FloatingOffset,$LastY,$this->GraphAreaX2-$FloatingOffset,$YPos,$BGColor); } + + if ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + + if ( $DrawSubTicks && $i != $Parameters["Rows"] ) + $this->drawLine($XPos-$OuterSubTickWidth,$YPos-$SubTicksSize,$XPos+$InnerSubTickWidth,$YPos-$SubTicksSize,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha)); + + $this->drawLine($XPos-$OuterTickWidth,$YPos,$XPos+$InnerTickWidth,$YPos,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); + $Bounds = $this->drawText($XPos-$OuterTickWidth-2,$YPos,$Value,array("Align"=>TEXT_ALIGN_MIDDLERIGHT)); + $TxtLeft = $XPos-$OuterTickWidth-2-($Bounds[1]["X"]-$Bounds[0]["X"]); + $MinLeft = min($MinLeft,$TxtLeft); + + $LastY = $YPos; + } + + if ( isset($Parameters["Name"]) ) + { + $XPos = $MinLeft-2; + $YPos = $this->GraphAreaY1+($this->GraphAreaY2-$this->GraphAreaY1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE,"Angle"=>90)); + $MinLeft = $Bounds[2]["X"]; + + $this->DataSet->Data["GraphArea"]["X1"] = $MinLeft; + } + + $AxisPos["L"] = $MinLeft - $ScaleSpacing; + } + elseif ( $Parameters["Position"] == AXIS_POSITION_RIGHT ) + { + if ( $Floating ) + { $FloatingOffset = $XMargin; $this->drawLine($AxisPos["R"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["R"],$this->GraphAreaY2-$Parameters["Margin"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($AxisPos["R"],$this->GraphAreaY1,$AxisPos["R"],$this->GraphAreaY2,array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($AxisPos["R"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["R"],$this->GraphAreaY1-($ArrowSize*2),array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + + $Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Parameters["Margin"]*2; + $Step = $Height / $Parameters["Rows"]; $SubTicksSize = $Step /2; $MaxLeft = $AxisPos["R"]; + $LastY = NULL; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $YPos = $this->GraphAreaY2 - $Parameters["Margin"] - $Step*$i; + $XPos = $AxisPos["R"]; + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Parameters["Display"],$Parameters["Format"],$Parameters["Unit"]); + + if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); } + if ( $LastY != NULL && $CycleBackground && ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->drawFilledRectangle($this->GraphAreaX1+$FloatingOffset,$LastY,$this->GraphAreaX2-$FloatingOffset,$YPos,$BGColor); } + + if ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + + if ( $DrawSubTicks && $i != $Parameters["Rows"] ) + $this->drawLine($XPos-$OuterSubTickWidth,$YPos-$SubTicksSize,$XPos+$InnerSubTickWidth,$YPos-$SubTicksSize,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha)); + + $this->drawLine($XPos-$InnerTickWidth,$YPos,$XPos+$OuterTickWidth,$YPos,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); + $Bounds = $this->drawText($XPos+$OuterTickWidth+2,$YPos,$Value,array("Align"=>TEXT_ALIGN_MIDDLELEFT)); + $TxtLeft = $XPos+$OuterTickWidth+2+($Bounds[1]["X"]-$Bounds[0]["X"]); + $MaxLeft = max($MaxLeft,$TxtLeft); + + $LastY = $YPos; + } + + if ( isset($Parameters["Name"]) ) + { + $XPos = $MaxLeft+6; + $YPos = $this->GraphAreaY1+($this->GraphAreaY2-$this->GraphAreaY1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE,"Angle"=>270)); + $MaxLeft = $Bounds[2]["X"]; + + $this->DataSet->Data["GraphArea"]["X2"] = $MaxLeft + $this->FontSize; + } + $AxisPos["R"] = $MaxLeft + $ScaleSpacing; + } + } + elseif ( $Pos == SCALE_POS_TOPBOTTOM ) + { + if ( $Parameters["Position"] == AXIS_POSITION_TOP ) + { + if ( $Floating ) + { $FloatingOffset = $XMargin; $this->drawLine($this->GraphAreaX1+$Parameters["Margin"],$AxisPos["T"],$this->GraphAreaX2-$Parameters["Margin"],$AxisPos["T"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($this->GraphAreaX1,$AxisPos["T"],$this->GraphAreaX2,$AxisPos["T"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($this->GraphAreaX2-$Parameters["Margin"],$AxisPos["T"],$this->GraphAreaX2+($ArrowSize*2),$AxisPos["T"],array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + + $Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Parameters["Margin"]*2; + $Step = $Width / $Parameters["Rows"]; $SubTicksSize = $Step /2; $MinTop = $AxisPos["T"]; + $LastX = NULL; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $XPos = $this->GraphAreaX1 + $Parameters["Margin"] + $Step*$i; + $YPos = $AxisPos["T"]; + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Parameters["Display"],$Parameters["Format"],$Parameters["Unit"]); + + if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); } + if ( $LastX != NULL && $CycleBackground && ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->drawFilledRectangle($LastX,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,$BGColor); } + + if ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + + if ( $DrawSubTicks && $i != $Parameters["Rows"] ) + $this->drawLine($XPos+$SubTicksSize,$YPos-$OuterSubTickWidth,$XPos+$SubTicksSize,$YPos+$InnerSubTickWidth,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha)); + + $this->drawLine($XPos,$YPos-$OuterTickWidth,$XPos,$YPos+$InnerTickWidth,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); + $Bounds = $this->drawText($XPos,$YPos-$OuterTickWidth-2,$Value,array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + $TxtHeight = $YPos-$OuterTickWidth-2-($Bounds[1]["Y"]-$Bounds[2]["Y"]); + $MinTop = min($MinTop,$TxtHeight); + + $LastX = $XPos; + } + + if ( isset($Parameters["Name"]) ) + { + $YPos = $MinTop-2; + $XPos = $this->GraphAreaX1+($this->GraphAreaX2-$this->GraphAreaX1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + $MinTop = $Bounds[2]["Y"]; + + $this->DataSet->Data["GraphArea"]["Y1"] = $MinTop; + } + + $AxisPos["T"] = $MinTop - $ScaleSpacing; + } + elseif ( $Parameters["Position"] == AXIS_POSITION_BOTTOM ) + { + if ( $Floating ) + { $FloatingOffset = $XMargin; $this->drawLine($this->GraphAreaX1+$Parameters["Margin"],$AxisPos["B"],$this->GraphAreaX2-$Parameters["Margin"],$AxisPos["B"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->drawLine($this->GraphAreaX1,$AxisPos["B"],$this->GraphAreaX2,$AxisPos["B"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->drawArrow($this->GraphAreaX2-$Parameters["Margin"],$AxisPos["B"],$this->GraphAreaX2+($ArrowSize*2),$AxisPos["B"],array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + + $Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Parameters["Margin"]*2; + $Step = $Width / $Parameters["Rows"]; $SubTicksSize = $Step /2; $MaxBottom = $AxisPos["B"]; + $LastX = NULL; + for($i=0;$i<=$Parameters["Rows"];$i++) + { + $XPos = $this->GraphAreaX1 + $Parameters["Margin"] + $Step*$i; + $YPos = $AxisPos["B"]; + $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Parameters["Display"],$Parameters["Format"],$Parameters["Unit"]); + + if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); } + if ( $LastX != NULL && $CycleBackground && ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->drawFilledRectangle($LastX,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,$BGColor); } + + if ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + + if ( $DrawSubTicks && $i != $Parameters["Rows"] ) + $this->drawLine($XPos+$SubTicksSize,$YPos-$OuterSubTickWidth,$XPos+$SubTicksSize,$YPos+$InnerSubTickWidth,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha)); + + $this->drawLine($XPos,$YPos-$OuterTickWidth,$XPos,$YPos+$InnerTickWidth,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); + $Bounds = $this->drawText($XPos,$YPos+$OuterTickWidth+2,$Value,array("Align"=>TEXT_ALIGN_TOPMIDDLE)); + $TxtHeight = $YPos+$OuterTickWidth+2+($Bounds[1]["Y"]-$Bounds[2]["Y"]); + $MaxBottom = max($MaxBottom,$TxtHeight); + + $LastX = $XPos; + } + + if ( isset($Parameters["Name"]) ) + { + $YPos = $MaxBottom+2; + $XPos = $this->GraphAreaX1+($this->GraphAreaX2-$this->GraphAreaX1)/2; + $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_TOPMIDDLE)); + $MaxBottom = $Bounds[0]["Y"]; + + $this->DataSet->Data["GraphArea"]["Y2"] = $MaxBottom + $this->FontSize; + } + + $AxisPos["B"] = $MaxBottom + $ScaleSpacing; + } + } + } + } + } + + function isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip) + { + if ( $LabelingMethod == LABELING_DIFFERENT && $Value != $LastValue ) { return(TRUE); } + if ( $LabelingMethod == LABELING_DIFFERENT && $Value == $LastValue ) { return(FALSE); } + if ( $LabelingMethod == LABELING_ALL && $LabelSkip == 0 ) { return(TRUE); } + if ( $LabelingMethod == LABELING_ALL && ($ID+$LabelSkip) % ($LabelSkip+1) != 1 ) { return(FALSE); } + + return(TRUE); + } + + /* Compute the scale, check for the best visual factors */ + function computeScale($XMin,$XMax,$MaxDivs,$Factors,$AxisID=0) + { + /* Compute each factors */ + $Results = ""; + foreach ($Factors as $Key => $Factor) + $Results[$Factor] = $this->processScale($XMin,$XMax,$MaxDivs,array($Factor),$AxisID); + + /* Remove scales that are creating to much decimals */ + $GoodScaleFactors = ""; + foreach ($Results as $Key => $Result) + { + $Decimals = preg_split("/\./",$Result["RowHeight"]); + if ( (!isset($Decimals[1])) || (strlen($Decimals[1]) < 6) ) { $GoodScaleFactors[] = $Key; } + } + + /* Found no correct scale, shame,... returns the 1st one as default */ + if ( $GoodScaleFactors == "" ) { return($Results[$Factors[0]]); } + + /* Find the factor that cause the maximum number of Rows */ + $MaxRows = 0; $BestFactor = 0; + foreach($GoodScaleFactors as $Key => $Factor) + { if ( $Results[$Factor]["Rows"] > $MaxRows ) { $MaxRows = $Results[$Factor]["Rows"]; $BestFactor = $Factor; } } + + /* Return the best visual scale */ + return($Results[$BestFactor]); + } + + /* Compute the best matching scale based on size & factors */ + function processScale($XMin,$XMax,$MaxDivs,$Factors,$AxisID) + { + $ScaleHeight = abs(ceil($XMax)-floor($XMin)); + + if ( isset($this->DataSet->Data["Axis"][$AxisID]["Format"]) ) + $Format = $this->DataSet->Data["Axis"][$AxisID]["Format"]; + else + $Format = NULL; + + if ( isset($this->DataSet->Data["Axis"][$AxisID]["Display"]) ) + $Mode = $this->DataSet->Data["Axis"][$AxisID]["Display"]; + else + $Mode = AXIS_FORMAT_DEFAULT; + + $Scale = ""; + if ( $XMin != $XMax ) + { + $Found = FALSE; $Rescaled = FALSE; $Scaled10Factor = .0001; $Result = 0; + while(!$Found) + { + foreach($Factors as $Key => $Factor) + { + if ( !$Found ) + { + if ( !($this->modulo($XMin,$Factor*$Scaled10Factor) == 0) || ($XMin != floor($XMin))) { $XMinRescaled = floor($XMin/($Factor*$Scaled10Factor))*$Factor*$Scaled10Factor; } else { $XMinRescaled = $XMin; } + if ( !($this->modulo($XMax,$Factor*$Scaled10Factor) == 0) || ($XMax != floor($XMax))) { $XMaxRescaled = floor($XMax/($Factor*$Scaled10Factor))*$Factor*$Scaled10Factor+($Factor*$Scaled10Factor); } else { $XMaxRescaled = $XMax; } + $ScaleHeightRescaled = abs($XMaxRescaled-$XMinRescaled); + + if ( !$Found && floor($ScaleHeightRescaled/($Factor*$Scaled10Factor)) <= $MaxDivs ) { $Found = TRUE; $Rescaled = TRUE; $Result = $Factor * $Scaled10Factor; } + } + } + $Scaled10Factor = $Scaled10Factor * 10; + } + + /* ReCall Min / Max / Height */ + if ( $Rescaled ) { $XMin = $XMinRescaled; $XMax = $XMaxRescaled; $ScaleHeight = $ScaleHeightRescaled; } + + /* Compute rows size */ + $Rows = floor($ScaleHeight / $Result); if ( $Rows == 0 ) { $Rows = 1; } + $RowHeight = $ScaleHeight / $Rows; + + /* Return the results */ + $Scale["Rows"] = $Rows; $Scale["RowHeight"] = $RowHeight; $Scale["XMin"] = $XMin; $Scale["XMax"] = $XMax; + + /* Compute the needed decimals for the metric view to avoid repetition of the same X Axis labels */ + if ( $Mode == AXIS_FORMAT_METRIC && $Format == NULL ) + { + $Done = FALSE; $GoodDecimals = 0; + for($Decimals=0;$Decimals<=10;$Decimals++) + { + if ( !$Done ) + { + $LastLabel = "zob"; $ScaleOK = TRUE; + for($i=0;$i<=$Rows;$i++) + { + $Value = $XMin + $i*$RowHeight; + $Label = $this->scaleFormat($Value,AXIS_FORMAT_METRIC,$Decimals); + + if ( $LastLabel == $Label ) { $ScaleOK = FALSE; } + $LastLabel = $Label; + } + if ( $ScaleOK ) { $Done = TRUE; $GoodDecimals = $Decimals; } + } + } + + $Scale["Format"] = $GoodDecimals; + } + } + else + { + /* If all values are the same we keep a +1/-1 scale */ + $Rows = 2; $XMin = $XMax-1; $XMax = $XMax+1; $RowHeight = 1; + + /* Return the results */ + $Scale["Rows"] = $Rows; $Scale["RowHeight"] = $RowHeight; $Scale["XMin"] = $XMin; $Scale["XMax"] = $XMax; + } + + return($Scale); + } + + function modulo($Value1,$Value2) + { + if (floor($Value2) == 0) { return(0); } + if (floor($Value2) != 0) { return($Value1 % $Value2); } + + $MinValue = min($Value1,$Value2); $Factor = 10; + while ( floor($MinValue*$Factor) == 0 ) + { $Factor = $Factor * 10; } + + return(($Value1*$Factor) % ($Value2*$Factor)); + } + + /* Draw an X threshold */ + function drawXThreshold($Value,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 255; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 50; + $Weight = isset($Format["Weight"]) ? $Format["Weight"] : NULL; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : 6; + $Wide = isset($Format["Wide"]) ? $Format["Wide"] : FALSE; + $WideFactor = isset($Format["WideFactor"]) ? $Format["WideFactor"] : 5; + $WriteCaption = isset($Format["WriteCaption"]) ? $Format["WriteCaption"] : FALSE; + $Caption = isset($Format["Caption"]) ? $Format["Caption"] : NULL; + $CaptionAlign = isset($Format["CaptionAlign"]) ? $Format["CaptionAlign"] : CAPTION_LEFT_TOP; + $CaptionOffset = isset($Format["CaptionOffset"]) ? $Format["CaptionOffset"] : 5; + $CaptionR = isset($Format["CaptionR"]) ? $Format["CaptionR"] : 255; + $CaptionG = isset($Format["CaptionG"]) ? $Format["CaptionG"] : 255; + $CaptionB = isset($Format["CaptionB"]) ? $Format["CaptionB"] : 255; + $CaptionAlpha = isset($Format["CaptionAlpha"]) ? $Format["CaptionAlpha"] : 100; + $DrawBox = isset($Format["DrawBox"]) ? $Format["DrawBox"] : TRUE; + $DrawBoxBorder = isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : FALSE; + $BorderOffset = isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 3; + $BoxRounded = isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : TRUE; + $RoundedRadius = isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 3; + $BoxR = isset($Format["BoxR"]) ? $Format["BoxR"] : 0; + $BoxG = isset($Format["BoxG"]) ? $Format["BoxG"] : 0; + $BoxB = isset($Format["BoxB"]) ? $Format["BoxB"] : 0; + $BoxAlpha = isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 30; + $BoxSurrounding = isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : ""; + $BoxBorderR = isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 255; + $BoxBorderG = isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 255; + $BoxBorderB = isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 255; + $BoxBorderAlpha = isset($Format["BoxBorderAlpha"]) ? $Format["BoxBorderAlpha"] : 100; + $ValueIsLabel = isset($Format["ValueIsLabel"]) ? $Format["ValueIsLabel"] : FALSE; + + $Data = $this->DataSet->getData(); + $AbscissaMargin = $this->getAbscissaMargin($Data); + $XScale = $this->scaleGetXSettings(); + + if ( is_array($Value) ) { foreach ($Value as $Key => $ID) { $this->drawXThreshold($ID,$Format); } return(0); } + + if ( $ValueIsLabel ) + { + $Format["ValueIsLabel"] = FALSE; + foreach($Data["Series"][$Data["Abscissa"]]["Data"] as $Key => $SerieValue) + { if ( $SerieValue == $Value ) { $this->drawXThreshold($Key,$Format); } } + + return(0); + } + + $CaptionSettings = array("DrawBox"=>$DrawBox,"DrawBoxBorder"=>$DrawBoxBorder,"BorderOffset"=>$BorderOffset,"BoxRounded"=>$BoxRounded,"RoundedRadius"=>$RoundedRadius, + "BoxR"=>$BoxR,"BoxG"=>$BoxG,"BoxB"=>$BoxB,"BoxAlpha"=>$BoxAlpha,"BoxSurrounding"=>$BoxSurrounding, + "BoxBorderR"=>$BoxBorderR,"BoxBorderG"=>$BoxBorderG,"BoxBorderB"=>$BoxBorderB,"BoxBorderAlpha"=>$BoxBorderAlpha, + "R"=>$CaptionR,"G"=>$CaptionG,"B"=>$CaptionB,"Alpha"=>$CaptionAlpha); + + if ( $Caption == NULL ) + { + if ( isset($Data["Abscissa"]) ) + { + if ( isset($Data["Series"][$Data["Abscissa"]]["Data"][$Value]) ) + $Caption = $Data["Series"][$Data["Abscissa"]]["Data"][$Value]; + else + $Caption = $Value; + } + else + $Caption = $Value; + } + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + $XStep = (($this->GraphAreaX2 - $this->GraphAreaX1) - $XScale[0] *2 ) / $XScale[1]; + $XPos = $this->GraphAreaX1 + $XScale[0] + $XStep * $Value; + $YPos1 = $this->GraphAreaY1 + $Data["YMargin"]; + $YPos2 = $this->GraphAreaY2 - $Data["YMargin"]; + + if ( $XPos >= $this->GraphAreaX1 + $AbscissaMargin && $XPos <= $this->GraphAreaX2 - $AbscissaMargin ) + { + $this->drawLine($XPos,$YPos1,$XPos,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + + if ( $Wide ) + { + $this->drawLine($XPos-1,$YPos1,$XPos-1,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + $this->drawLine($XPos+1,$YPos1,$XPos+1,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + } + + if ( $WriteCaption ) + { + if ( $CaptionAlign == CAPTION_LEFT_TOP ) + { $Y = $YPos1 + $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE; } + else + { $Y = $YPos2 - $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_BOTTOMMIDDLE; } + + $this->drawText($XPos,$Y,$Caption,$CaptionSettings); + } + + return(array("X"=>$XPos)); + } + } + elseif( $Data["Orientation"] == SCALE_POS_TOPBOTTOM ) + { + $XStep = (($this->GraphAreaY2 - $this->GraphAreaY1) - $XScale[0] *2 ) / $XScale[1]; + $XPos = $this->GraphAreaY1 + $XScale[0] + $XStep * $Value; + $YPos1 = $this->GraphAreaX1 + $Data["YMargin"]; + $YPos2 = $this->GraphAreaX2 - $Data["YMargin"]; + + if ( $XPos >= $this->GraphAreaY1 + $AbscissaMargin && $XPos <= $this->GraphAreaY2 - $AbscissaMargin ) + { + $this->drawLine($YPos1,$XPos,$YPos2,$XPos,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + + if ( $Wide ) + { + $this->drawLine($YPos1,$XPos-1,$YPos2,$XPos-1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + $this->drawLine($YPos1,$XPos+1,$YPos2,$XPos+1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + } + + if ( $WriteCaption ) + { + if ( $CaptionAlign == CAPTION_LEFT_TOP ) + { $Y = $YPos1 + $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLELEFT; } + else + { $Y = $YPos2 - $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLERIGHT; } + + $this->drawText($Y,$XPos,$Caption,$CaptionSettings); + } + + return(array("X"=>$XPos)); + } + } + } + + /* Draw an X threshold area */ + function drawXThresholdArea($Value1,$Value2,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 255; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 20; + $Border = isset($Format["Border"]) ? $Format["Border"] : TRUE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha + 20; + $BorderTicks = isset($Format["BorderTicks"]) ? $Format["BorderTicks"] : 2; + $AreaName = isset($Format["AreaName"]) ? $Format["AreaName"] : NULL; + $NameAngle = isset($Format["NameAngle"]) ? $Format["NameAngle"] : ZONE_NAME_ANGLE_AUTO; + $NameR = isset($Format["NameR"]) ? $Format["NameR"] : 255; + $NameG = isset($Format["NameG"]) ? $Format["NameG"] : 255; + $NameB = isset($Format["NameB"]) ? $Format["NameB"] : 255; + $NameAlpha = isset($Format["NameAlpha"]) ? $Format["NameAlpha"] : 100; + $DisableShadowOnArea = isset($Format["DisableShadowOnArea"]) ? $Format["DisableShadowOnArea"] : TRUE; + + $RestoreShadow = $this->Shadow; + if ( $DisableShadowOnArea && $this->Shadow ) { $this->Shadow = FALSE; } + + if ($BorderAlpha >100) { $BorderAlpha = 100;} + + $Data = $this->DataSet->getData(); + $XScale = $this->scaleGetXSettings(); + $AbscissaMargin = $this->getAbscissaMargin($Data); + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + $XStep = (($this->GraphAreaX2 - $this->GraphAreaX1) - $XScale[0] *2 ) / $XScale[1]; + $XPos1 = $this->GraphAreaX1 + $XScale[0] + $XStep * $Value1; + $XPos2 = $this->GraphAreaX1 + $XScale[0] + $XStep * $Value2; + $YPos1 = $this->GraphAreaY1 + $Data["YMargin"]; + $YPos2 = $this->GraphAreaY2 - $Data["YMargin"]; + + if ( $XPos1 < $this->GraphAreaX1 + $XScale[0] ) { $XPos1 = $this->GraphAreaX1 + $XScale[0]; } + if ( $XPos1 > $this->GraphAreaX2 - $XScale[0] ) { $XPos1 = $this->GraphAreaX2 - $XScale[0]; } + if ( $XPos2 < $this->GraphAreaX1 + $XScale[0] ) { $XPos2 = $this->GraphAreaX1 + $XScale[0]; } + if ( $XPos2 > $this->GraphAreaX2 - $XScale[0] ) { $XPos2 = $this->GraphAreaX2 - $XScale[0]; } + + $this->drawFilledRectangle($XPos1,$YPos1,$XPos2,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + if ( $Border ) + { + $this->drawLine($XPos1,$YPos1,$XPos1,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + $this->drawLine($XPos2,$YPos1,$XPos2,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + } + + if ( $AreaName != NULL ) + { + $XPos = ($XPos2-$XPos1)/2 + $XPos1; + $YPos = ($YPos2-$YPos1)/2 + $YPos1; + + if ( $NameAngle == ZONE_NAME_ANGLE_AUTO ) + { + $TxtPos = $this->getTextBox($XPos,$YPos,$this->FontName,$this->FontSize,0,$AreaName); + $TxtWidth = $TxtPos[1]["X"] - $TxtPos[0]["X"]; + if ( abs($XPos2 - $XPos1) > $TxtWidth ) { $NameAngle = 0; } else { $NameAngle = 90; } + } + $this->Shadow = $RestoreShadow; + $this->drawText($XPos,$YPos,$AreaName,array("R"=>$NameR,"G"=>$NameG,"B"=>$NameB,"Alpha"=>$NameAlpha,"Angle"=>$NameAngle,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE)); + if ( $DisableShadowOnArea ) { $this->Shadow = FALSE; } + } + + $this->Shadow = $RestoreShadow; + return(array("X1"=>$XPos1,"X2"=>$XPos2)); + } + elseif ( $Data["Orientation"] == SCALE_POS_TOPBOTTOM ) + { + $XStep = (($this->GraphAreaY2 - $this->GraphAreaY1) - $XScale[0] *2 ) / $XScale[1]; + $XPos1 = $this->GraphAreaY1 + $XScale[0] + $XStep * $Value1; + $XPos2 = $this->GraphAreaY1 + $XScale[0] + $XStep * $Value2; + $YPos1 = $this->GraphAreaX1 + $Data["YMargin"]; + $YPos2 = $this->GraphAreaX2 - $Data["YMargin"]; + + if ( $XPos1 < $this->GraphAreaY1 + $XScale[0] ) { $XPos1 = $this->GraphAreaY1 + $XScale[0]; } + if ( $XPos1 > $this->GraphAreaY2 - $XScale[0] ) { $XPos1 = $this->GraphAreaY2 - $XScale[0]; } + if ( $XPos2 < $this->GraphAreaY1 + $XScale[0] ) { $XPos2 = $this->GraphAreaY1 + $XScale[0]; } + if ( $XPos2 > $this->GraphAreaY2 - $XScale[0] ) { $XPos2 = $this->GraphAreaY2 - $XScale[0]; } + + $this->drawFilledRectangle($YPos1,$XPos1,$YPos2,$XPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + if ( $Border ) + { + $this->drawLine($YPos1,$XPos1,$YPos2,$XPos1,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + $this->drawLine($YPos1,$XPos2,$YPos2,$XPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + } + + if ( $AreaName != NULL ) + { + $XPos = ($XPos2-$XPos1)/2 + $XPos1; + $YPos = ($YPos2-$YPos1)/2 + $YPos1; + + $this->Shadow = $RestoreShadow; + $this->drawText($YPos,$XPos,$AreaName,array("R"=>$NameR,"G"=>$NameG,"B"=>$NameB,"Alpha"=>$NameAlpha,"Angle"=>0,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE)); + if ( $DisableShadowOnArea ) { $this->Shadow = FALSE; } + } + + $this->Shadow = $RestoreShadow; + return(array("X1"=>$XPos1,"X2"=>$XPos2)); + } + } + + /* Draw an Y threshold with the computed scale */ + function drawThreshold($Value,$Format="") + { + $AxisID = isset($Format["AxisID"]) ? $Format["AxisID"] : 0; + $R = isset($Format["R"]) ? $Format["R"] : 255; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 50; + $Weight = isset($Format["Weight"]) ? $Format["Weight"] : NULL; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : 6; + $Wide = isset($Format["Wide"]) ? $Format["Wide"] : FALSE; + $WideFactor = isset($Format["WideFactor"]) ? $Format["WideFactor"] : 5; + $WriteCaption = isset($Format["WriteCaption"]) ? $Format["WriteCaption"] : FALSE; + $Caption = isset($Format["Caption"]) ? $Format["Caption"] : NULL; + $CaptionAlign = isset($Format["CaptionAlign"]) ? $Format["CaptionAlign"] : CAPTION_LEFT_TOP; + $CaptionOffset = isset($Format["CaptionOffset"]) ? $Format["CaptionOffset"] : 10; + $CaptionR = isset($Format["CaptionR"]) ? $Format["CaptionR"] : 255; + $CaptionG = isset($Format["CaptionG"]) ? $Format["CaptionG"] : 255; + $CaptionB = isset($Format["CaptionB"]) ? $Format["CaptionB"] : 255; + $CaptionAlpha = isset($Format["CaptionAlpha"]) ? $Format["CaptionAlpha"] : 100; + $DrawBox = isset($Format["DrawBox"]) ? $Format["DrawBox"] : TRUE; + $DrawBoxBorder = isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : FALSE; + $BorderOffset = isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 5; + $BoxRounded = isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : TRUE; + $RoundedRadius = isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 3; + $BoxR = isset($Format["BoxR"]) ? $Format["BoxR"] : 0; + $BoxG = isset($Format["BoxG"]) ? $Format["BoxG"] : 0; + $BoxB = isset($Format["BoxB"]) ? $Format["BoxB"] : 0; + $BoxAlpha = isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 20; + $BoxSurrounding = isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : ""; + $BoxBorderR = isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 255; + $BoxBorderG = isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 255; + $BoxBorderB = isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 255; + $BoxBorderAlpha = isset($Format["BoxBorderAlpha"]) ? $Format["BoxBorderAlpha"] : 100; + $NoMargin = isset($Format["NoMargin"]) ? $Format["NoMargin"] : FALSE; + + if ( is_array($Value) ) { foreach ($Value as $Key => $ID) { $this->drawThreshold($ID,$Format); } return(0); } + + $CaptionSettings = array("DrawBox"=>$DrawBox,"DrawBoxBorder"=>$DrawBoxBorder,"BorderOffset"=>$BorderOffset,"BoxRounded"=>$BoxRounded,"RoundedRadius"=>$RoundedRadius, + "BoxR"=>$BoxR,"BoxG"=>$BoxG,"BoxB"=>$BoxB,"BoxAlpha"=>$BoxAlpha,"BoxSurrounding"=>$BoxSurrounding, + "BoxBorderR"=>$BoxBorderR,"BoxBorderG"=>$BoxBorderG,"BoxBorderB"=>$BoxBorderB,"BoxBorderAlpha"=>$BoxBorderAlpha, + "R"=>$CaptionR,"G"=>$CaptionG,"B"=>$CaptionB,"Alpha"=>$CaptionAlpha); + + $Data = $this->DataSet->getData(); + $AbscissaMargin = $this->getAbscissaMargin($Data); + + if ( $NoMargin ) { $AbscissaMargin = 0; } + if ( !isset($Data["Axis"][$AxisID]) ) { return(-1); } + if ( $Caption == NULL ) { $Caption = $Value; } + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + $YPos = $this->scaleComputeY($Value,array("AxisID"=>$AxisID)); + if ( $YPos >= $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"] && $YPos <= $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"] ) + { + $X1 = $this->GraphAreaX1 + $AbscissaMargin; + $X2 = $this->GraphAreaX2 - $AbscissaMargin; + + $this->drawLine($X1,$YPos,$X2,$YPos,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + + if ( $Wide ) + { + $this->drawLine($X1,$YPos-1,$X2,$YPos-1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + $this->drawLine($X1,$YPos+1,$X2,$YPos+1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + } + + if ( $WriteCaption ) + { + if ( $CaptionAlign == CAPTION_LEFT_TOP ) + { $X = $X1 + $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLELEFT; } + else + { $X = $X2 - $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLERIGHT; } + + $this->drawText($X,$YPos,$Caption,$CaptionSettings); + } + } + + return(array("Y"=>$YPos)); + } + + if ( $Data["Orientation"] == SCALE_POS_TOPBOTTOM ) + { + $XPos = $this->scaleComputeY($Value,array("AxisID"=>$AxisID)); + if ( $XPos >= $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"] && $XPos <= $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"] ) + { + $Y1 = $this->GraphAreaY1 + $AbscissaMargin; + $Y2 = $this->GraphAreaY2 - $AbscissaMargin; + + $this->drawLine($XPos,$Y1,$XPos,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + + if ( $Wide ) + { + $this->drawLine($XPos-1,$Y1,$XPos-1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + $this->drawLine($XPos+1,$Y1,$XPos+1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + } + + if ( $WriteCaption ) + { + if ( $CaptionAlign == CAPTION_LEFT_TOP ) + { $Y = $Y1 + $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE; } + else + { $Y = $Y2 - $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_BOTTOMMIDDLE; } + + $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE; + $this->drawText($XPos,$Y,$Caption,$CaptionSettings); + } + } + + return(array("Y"=>$XPos)); + } + } + + /* Draw a threshold with the computed scale */ + function drawThresholdArea($Value1,$Value2,$Format="") + { + $AxisID = isset($Format["AxisID"]) ? $Format["AxisID"] : 0; + $R = isset($Format["R"]) ? $Format["R"] : 255; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 20; + $Border = isset($Format["Border"]) ? $Format["Border"] : TRUE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha + 20; + $BorderTicks = isset($Format["BorderTicks"]) ? $Format["BorderTicks"] : 2; + $AreaName = isset($Format["AreaName"]) ? $Format["AreaName"] : NULL; + $NameAngle = isset($Format["NameAngle"]) ? $Format["NameAngle"] : ZONE_NAME_ANGLE_AUTO; + $NameR = isset($Format["NameR"]) ? $Format["NameR"] : 255; + $NameG = isset($Format["NameG"]) ? $Format["NameG"] : 255; + $NameB = isset($Format["NameB"]) ? $Format["NameB"] : 255; + $NameAlpha = isset($Format["NameAlpha"]) ? $Format["NameAlpha"] : 100; + $DisableShadowOnArea = isset($Format["DisableShadowOnArea"]) ? $Format["DisableShadowOnArea"] : TRUE; + $NoMargin = isset($Format["NoMargin"]) ? $Format["NoMargin"] : FALSE; + + if ($Value1 > $Value2) { list($Value1, $Value2) = array($Value2, $Value1); } + + $RestoreShadow = $this->Shadow; + if ( $DisableShadowOnArea && $this->Shadow ) { $this->Shadow = FALSE; } + + if ($BorderAlpha >100) { $BorderAlpha = 100;} + + $Data = $this->DataSet->getData(); + $AbscissaMargin = $this->getAbscissaMargin($Data); + + if ( $NoMargin ) { $AbscissaMargin = 0; } + if ( !isset($Data["Axis"][$AxisID]) ) { return(-1); } + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + $XPos1 = $this->GraphAreaX1 + $AbscissaMargin; + $XPos2 = $this->GraphAreaX2 - $AbscissaMargin; + $YPos1 = $this->scaleComputeY($Value1,array("AxisID"=>$AxisID)); + $YPos2 = $this->scaleComputeY($Value2,array("AxisID"=>$AxisID)); + + if ( $YPos1 < $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"] ) { $YPos1 = $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"]; } + if ( $YPos1 > $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"] ) { $YPos1 = $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"]; } + if ( $YPos2 < $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"] ) { $YPos2 = $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"]; } + if ( $YPos2 > $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"] ) { $YPos2 = $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"]; } + + $this->drawFilledRectangle($XPos1,$YPos1,$XPos2,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + if ( $Border ) + { + $this->drawLine($XPos1,$YPos1,$XPos2,$YPos1,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + $this->drawLine($XPos1,$YPos2,$XPos2,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + } + + if ( $AreaName != NULL ) + { + $XPos = ($XPos2-$XPos1)/2 + $XPos1; + $YPos = ($YPos2-$YPos1)/2 + $YPos1; + $this->Shadow = $RestoreShadow; + $this->drawText($XPos,$YPos,$AreaName,array("R"=>$NameR,"G"=>$NameG,"B"=>$NameB,"Alpha"=>$NameAlpha,"Angle"=>0,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE)); + if ( $DisableShadowOnArea ) { $this->Shadow = FALSE; } + } + + $this->Shadow = $RestoreShadow; + return(array("Y1"=>$YPos1,"Y2"=>$YPos2)); + } + elseif ( $Data["Orientation"] == SCALE_POS_TOPBOTTOM ) + { + $YPos1 = $this->GraphAreaY1 + $AbscissaMargin; + $YPos2 = $this->GraphAreaY2 - $AbscissaMargin; + $XPos1 = $this->scaleComputeY($Value1,array("AxisID"=>$AxisID)); + $XPos2 = $this->scaleComputeY($Value2,array("AxisID"=>$AxisID)); + + if ( $XPos1 < $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"] ) { $XPos1 = $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"]; } + if ( $XPos1 > $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"] ) { $XPos1 = $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"]; } + if ( $XPos2 < $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"] ) { $XPos2 = $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"]; } + if ( $XPos2 > $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"] ) { $XPos2 = $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"]; } + + $this->drawFilledRectangle($XPos1,$YPos1,$XPos2,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + if ( $Border ) + { + $this->drawLine($XPos1,$YPos1,$XPos1,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + $this->drawLine($XPos2,$YPos1,$XPos2,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + } + + if ( $AreaName != NULL ) + { + $XPos = ($YPos2-$YPos1)/2 + $YPos1; + $YPos = ($XPos2-$XPos1)/2 + $XPos1; + + if ( $NameAngle == ZONE_NAME_ANGLE_AUTO ) + { + $TxtPos = $this->getTextBox($XPos,$YPos,$this->FontName,$this->FontSize,0,$AreaName); + $TxtWidth = $TxtPos[1]["X"] - $TxtPos[0]["X"]; + if ( abs($XPos2 - $XPos1) > $TxtWidth ) { $NameAngle = 0; } else { $NameAngle = 90; } + } + $this->Shadow = $RestoreShadow; + $this->drawText($YPos,$XPos,$AreaName,array("R"=>$NameR,"G"=>$NameG,"B"=>$NameB,"Alpha"=>$NameAlpha,"Angle"=>$NameAngle,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE)); + if ( $DisableShadowOnArea ) { $this->Shadow = FALSE; } + } + + $this->Shadow = $RestoreShadow; + return(array("Y1"=>$XPos1,"Y2"=>$XPos2)); + } + } + + function scaleGetXSettings() + { + $Data = $this->DataSet->getData(); + foreach($Data["Axis"] as $AxisID => $Settings) + { + if ( $Settings["Identity"] == AXIS_X ) + { + $Rows = $Settings["Rows"]; + + return(array($Settings["Margin"],$Rows)); + } + } + } + + function scaleComputeY($Values,$Option="",$ReturnOnly0Height=FALSE) + { + $AxisID = isset($Option["AxisID"]) ? $Option["AxisID"] : 0; + $SerieName = isset($Option["SerieName"]) ? $Option["SerieName"] : NULL; + + $Data = $this->DataSet->getData(); + if ( !isset($Data["Axis"][$AxisID]) ) { return(-1); } + + if ( $SerieName != NULL ) { $AxisID = $Data["Series"][$SerieName]["Axis"]; } + if ( !is_array($Values) ) { $tmp = $Values; $Values = ""; $Values[0] = $tmp; } + + $Result = ""; + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + $Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Data["Axis"][$AxisID]["Margin"]*2; + $ScaleHeight = $Data["Axis"][$AxisID]["ScaleMax"] - $Data["Axis"][$AxisID]["ScaleMin"]; + $Step = $Height / $ScaleHeight; + + if ( $ReturnOnly0Height ) + { foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $Step * $Value; } } } + else + { foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $this->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"] - ($Step * ($Value-$Data["Axis"][$AxisID]["ScaleMin"])); } } } + } + else + { + $Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Data["Axis"][$AxisID]["Margin"]*2; + $ScaleWidth = $Data["Axis"][$AxisID]["ScaleMax"] - $Data["Axis"][$AxisID]["ScaleMin"]; + $Step = $Width / $ScaleWidth; + + if ( $ReturnOnly0Height ) + { foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $Step * $Value; } } } + else + { foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $this->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"] + ($Step * ($Value-$Data["Axis"][$AxisID]["ScaleMin"])); } } } + } + + if ( count($Result) == 1 ) + return($Result[0]); + else + return($Result); + } + + /* Format the axis values */ + function scaleFormat($Value,$Mode=NULL,$Format=NULL,$Unit=NULL) + { + if ( $Value == VOID ) { return(""); } + + if ( $Mode == AXIS_FORMAT_CUSTOM ) + { if ( function_exists($Format) ) { return(call_user_func($Format,$Value)); } } + + if ( $Mode == AXIS_FORMAT_DATE ) + { if ( $Format == NULL ) { $Pattern = "d/m/Y"; } else { $Pattern = $Format; } return(date($Pattern,$Value)); } + + if ( $Mode == AXIS_FORMAT_TIME ) + { if ( $Format == NULL ) { $Pattern = "H:i:s"; } else { $Pattern = $Format; } return(date($Pattern,$Value)); } + + if ( $Mode == AXIS_FORMAT_CURRENCY ) + { return($Format.number_format($Value,2)); } + + if ( $Mode == AXIS_FORMAT_METRIC ) + { + if (abs($Value) > 1000000000) + return(round($Value/1000000000,$Format)."g".$Unit); + if (abs($Value) > 1000000) + return(round($Value/1000000,$Format)."m".$Unit); + elseif (abs($Value) >= 1000) + return(round($Value/1000,$Format)."k".$Unit); + + } + return($Value.$Unit); + } + + /* Write Max value on a chart */ + function writeBounds($Type=BOUND_BOTH,$Format=NULL) + { + $MaxLabelTxt = isset($Format["MaxLabelTxt"]) ? $Format["MaxLabelTxt"] : "max="; + $MinLabelTxt = isset($Format["MinLabelTxt"]) ? $Format["MinLabelTxt"] : "min="; + $Decimals = isset($Format["Decimals"]) ? $Format["Decimals"] : 1; + $ExcludedSeries = isset($Format["ExcludedSeries"]) ? $Format["ExcludedSeries"] : ""; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 4; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $MaxDisplayR = isset($Format["MaxDisplayR"]) ? $Format["MaxDisplayR"] : 0; + $MaxDisplayG = isset($Format["MaxDisplayG"]) ? $Format["MaxDisplayG"] : 0; + $MaxDisplayB = isset($Format["MaxDisplayB"]) ? $Format["MaxDisplayB"] : 0; + $MinDisplayR = isset($Format["MinDisplayR"]) ? $Format["MinDisplayR"] : 255; + $MinDisplayG = isset($Format["MinDisplayG"]) ? $Format["MinDisplayG"] : 255; + $MinDisplayB = isset($Format["MinDisplayB"]) ? $Format["MinDisplayB"] : 255; + $MinLabelPos = isset($Format["MinLabelPos"]) ? $Format["MinLabelPos"] : BOUND_LABEL_POS_AUTO; + $MaxLabelPos = isset($Format["MaxLabelPos"]) ? $Format["MaxLabelPos"] : BOUND_LABEL_POS_AUTO; + $DrawBox = isset($Format["DrawBox"]) ? $Format["DrawBox"] : TRUE; + $DrawBoxBorder = isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : FALSE; + $BorderOffset = isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 5; + $BoxRounded = isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : TRUE; + $RoundedRadius = isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 3; + $BoxR = isset($Format["BoxR"]) ? $Format["BoxR"] : 0; + $BoxG = isset($Format["BoxG"]) ? $Format["BoxG"] : 0; + $BoxB = isset($Format["BoxB"]) ? $Format["BoxB"] : 0; + $BoxAlpha = isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 20; + $BoxSurrounding = isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : ""; + $BoxBorderR = isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 255; + $BoxBorderG = isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 255; + $BoxBorderB = isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 255; + $BoxBorderAlpha = isset($Format["BoxBorderAlpha"]) ? $Format["BoxBorderAlpha"] : 100; + + $CaptionSettings = array("DrawBox"=>$DrawBox,"DrawBoxBorder"=>$DrawBoxBorder,"BorderOffset"=>$BorderOffset,"BoxRounded"=>$BoxRounded,"RoundedRadius"=>$RoundedRadius, + "BoxR"=>$BoxR,"BoxG"=>$BoxG,"BoxB"=>$BoxB,"BoxAlpha"=>$BoxAlpha,"BoxSurrounding"=>$BoxSurrounding, + "BoxBorderR"=>$BoxBorderR,"BoxBorderG"=>$BoxBorderG,"BoxBorderB"=>$BoxBorderB,"BoxBorderAlpha"=>$BoxBorderAlpha); + + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + $Data = $this->DataSet->getData(); + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] && !isset($ExcludedSeries[$SerieName])) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $MinValue = $this->DataSet->getMin($SerieName); + $MaxValue = $this->DataSet->getMax($SerieName); + + $MinPos = VOID; $MaxPos = VOID; + foreach($Serie["Data"] as $Key => $Value) + { + if ( $Value == $MinValue && $MinPos == VOID ) { $MinPos = $Key; } + if ( $Value == $MaxValue ) { $MaxPos = $Key; } + } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; + $X = $this->GraphAreaX1 + $XMargin; + $SerieOffset = isset($Serie["XOffset"]) ? $Serie["XOffset"] : 0; + + if ( $Type == BOUND_MAX || $Type == BOUND_BOTH ) + { + if ( $MaxLabelPos == BOUND_LABEL_POS_TOP || ( $MaxLabelPos == BOUND_LABEL_POS_AUTO && $MaxValue >= 0) ) { $YPos = $PosArray[$MaxPos] - $DisplayOffset + 2; $Align = TEXT_ALIGN_BOTTOMMIDDLE; } + if ( $MaxLabelPos == BOUND_LABEL_POS_BOTTOM || ( $MaxLabelPos == BOUND_LABEL_POS_AUTO && $MaxValue < 0) ) { $YPos = $PosArray[$MaxPos] + $DisplayOffset + 2; $Align = TEXT_ALIGN_TOPMIDDLE; } + + $XPos = $X + $MaxPos*$XStep + $SerieOffset; + $Label = $MaxLabelTxt.$this->scaleFormat(round($MaxValue,$Decimals),$Mode,$Format,$Unit); + + $TxtPos = $this->getTextBox($XPos,$YPos,$this->FontName,$this->FontSize,0,$Label); + $XOffset = 0; $YOffset = 0; + if ( $TxtPos[0]["X"] < $this->GraphAreaX1 ) { $XOffset = (($this->GraphAreaX1 - $TxtPos[0]["X"])/2); } + if ( $TxtPos[1]["X"] > $this->GraphAreaX2 ) { $XOffset = -(($TxtPos[1]["X"] - $this->GraphAreaX2)/2); } + if ( $TxtPos[2]["Y"] < $this->GraphAreaY1 ) { $YOffset = $this->GraphAreaY1 - $TxtPos[2]["Y"]; } + if ( $TxtPos[0]["Y"] > $this->GraphAreaY2 ) { $YOffset = -($TxtPos[0]["Y"] - $this->GraphAreaY2); } + + $CaptionSettings["R"] = $MaxDisplayR; $CaptionSettings["G"] = $MaxDisplayG; + $CaptionSettings["B"] = $MaxDisplayB; $CaptionSettings["Align"] = $Align; + + $this->drawText($XPos+$XOffset,$YPos+$YOffset,$Label,$CaptionSettings); + } + + if ( $Type == BOUND_MIN || $Type == BOUND_BOTH ) + { + if ( $MinLabelPos == BOUND_LABEL_POS_TOP || ( $MinLabelPos == BOUND_LABEL_POS_AUTO && $MinValue >= 0) ) { $YPos = $PosArray[$MinPos] - $DisplayOffset + 2; $Align = TEXT_ALIGN_BOTTOMMIDDLE; } + if ( $MinLabelPos == BOUND_LABEL_POS_BOTTOM || ( $MinLabelPos == BOUND_LABEL_POS_AUTO && $MinValue < 0) ) { $YPos = $PosArray[$MinPos] + $DisplayOffset + 2; $Align = TEXT_ALIGN_TOPMIDDLE; } + + $XPos = $X + $MinPos*$XStep + $SerieOffset; + $Label = $MinLabelTxt.$this->scaleFormat(round($MinValue,$Decimals),$Mode,$Format,$Unit); + + $TxtPos = $this->getTextBox($XPos,$YPos,$this->FontName,$this->FontSize,0,$Label); + $XOffset = 0; $YOffset = 0; + if ( $TxtPos[0]["X"] < $this->GraphAreaX1 ) { $XOffset = (($this->GraphAreaX1 - $TxtPos[0]["X"])/2); } + if ( $TxtPos[1]["X"] > $this->GraphAreaX2 ) { $XOffset = -(($TxtPos[1]["X"] - $this->GraphAreaX2)/2); } + if ( $TxtPos[2]["Y"] < $this->GraphAreaY1 ) { $YOffset = $this->GraphAreaY1 - $TxtPos[2]["Y"]; } + if ( $TxtPos[0]["Y"] > $this->GraphAreaY2 ) { $YOffset = -($TxtPos[0]["Y"] - $this->GraphAreaY2); } + + $CaptionSettings["R"] = $MinDisplayR; $CaptionSettings["G"] = $MinDisplayG; + $CaptionSettings["B"] = $MinDisplayB; $CaptionSettings["Align"] = $Align; + + $this->drawText($XPos+$XOffset,$YPos-$DisplayOffset+$YOffset,$Label,$CaptionSettings); + } + } + else + { + $XStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; + $X = $this->GraphAreaY1 + $XMargin; + $SerieOffset = isset($Serie["XOffset"]) ? $Serie["XOffset"] : 0; + + if ( $Type == BOUND_MAX || $Type == BOUND_BOTH ) + { + if ( $MaxLabelPos == BOUND_LABEL_POS_TOP || ( $MaxLabelPos == BOUND_LABEL_POS_AUTO && $MaxValue >= 0) ) { $YPos = $PosArray[$MaxPos] + $DisplayOffset + 2; $Align = TEXT_ALIGN_MIDDLELEFT; } + if ( $MaxLabelPos == BOUND_LABEL_POS_BOTTOM || ( $MaxLabelPos == BOUND_LABEL_POS_AUTO && $MaxValue < 0) ) { $YPos = $PosArray[$MaxPos] - $DisplayOffset + 2; $Align = TEXT_ALIGN_MIDDLERIGHT; } + + $XPos = $X + $MaxPos*$XStep + $SerieOffset; + $Label = $MaxLabelTxt.$this->scaleFormat($MaxValue,$Mode,$Format,$Unit); + + $TxtPos = $this->getTextBox($YPos,$XPos,$this->FontName,$this->FontSize,0,$Label); + $XOffset = 0; $YOffset = 0; + if ( $TxtPos[0]["X"] < $this->GraphAreaX1 ) { $XOffset = $this->GraphAreaX1 - $TxtPos[0]["X"]; } + if ( $TxtPos[1]["X"] > $this->GraphAreaX2 ) { $XOffset = -($TxtPos[1]["X"] - $this->GraphAreaX2); } + if ( $TxtPos[2]["Y"] < $this->GraphAreaY1 ) { $YOffset = ($this->GraphAreaY1 - $TxtPos[2]["Y"])/2; } + if ( $TxtPos[0]["Y"] > $this->GraphAreaY2 ) { $YOffset = -(($TxtPos[0]["Y"] - $this->GraphAreaY2)/2);} + + $CaptionSettings["R"] = $MaxDisplayR; $CaptionSettings["G"] = $MaxDisplayG; + $CaptionSettings["B"] = $MaxDisplayB; $CaptionSettings["Align"] = $Align; + + $this->drawText($YPos+$XOffset,$XPos+$YOffset,$Label,$CaptionSettings); + } + + if ( $Type == BOUND_MIN || $Type == BOUND_BOTH ) + { + if ( $MinLabelPos == BOUND_LABEL_POS_TOP || ( $MinLabelPos == BOUND_LABEL_POS_AUTO && $MinValue >= 0) ) { $YPos = $PosArray[$MinPos] + $DisplayOffset + 2; $Align = TEXT_ALIGN_MIDDLELEFT; } + if ( $MinLabelPos == BOUND_LABEL_POS_BOTTOM || ( $MinLabelPos == BOUND_LABEL_POS_AUTO && $MinValue < 0) ) { $YPos = $PosArray[$MinPos] - $DisplayOffset + 2; $Align = TEXT_ALIGN_MIDDLERIGHT; } + + $XPos = $X + $MinPos*$XStep + $SerieOffset; + $Label = $MinLabelTxt.$this->scaleFormat($MinValue,$Mode,$Format,$Unit); + + $TxtPos = $this->getTextBox($YPos,$XPos,$this->FontName,$this->FontSize,0,$Label); + $XOffset = 0; $YOffset = 0; + if ( $TxtPos[0]["X"] < $this->GraphAreaX1 ) { $XOffset = $this->GraphAreaX1 - $TxtPos[0]["X"]; } + if ( $TxtPos[1]["X"] > $this->GraphAreaX2 ) { $XOffset = -($TxtPos[1]["X"] - $this->GraphAreaX2); } + if ( $TxtPos[2]["Y"] < $this->GraphAreaY1 ) { $YOffset = ($this->GraphAreaY1 - $TxtPos[2]["Y"])/2; } + if ( $TxtPos[0]["Y"] > $this->GraphAreaY2 ) { $YOffset = -(($TxtPos[0]["Y"] - $this->GraphAreaY2)/2);} + + $CaptionSettings["R"] = $MinDisplayR; $CaptionSettings["G"] = $MinDisplayG; + $CaptionSettings["B"] = $MinDisplayB; $CaptionSettings["Align"] = $Align; + + $this->drawText($YPos+$XOffset,$XPos+$YOffset,$Label,$CaptionSettings); + } + } + } + } + } + + /* Draw a plot chart */ + function drawPlotChart($Format=NULL) + { + $PlotSize = isset($Format["PlotSize"]) ? $Format["PlotSize"] : NULL; + $PlotBorder = isset($Format["PlotBorder"]) ? $Format["PlotBorder"] : FALSE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 50; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 50; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 50; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : 30; + $BorderSize = isset($Format["BorderSize"]) ? $Format["BorderSize"] : 2; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 4; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + if ( isset($Serie["Weight"]) ) { $SerieWeight = $Serie["Weight"] + 2; } else { $SerieWeight = 2; } + if ( $PlotSize != NULL ) { $SerieWeight = $PlotSize; } + + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; + if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; } + if ( isset($Serie["Picture"]) ) + { $Picture = $Serie["Picture"]; list($PicWidth,$PicHeight,$PicType) = $this->getPicInfo($Picture); } + else { $Picture = NULL; $PicOffset = 0; } + + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $AxisID = $Serie["Axis"]; + $Shape = $Serie["Shape"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; } + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + if ( $Picture != NULL ) { $PicOffset = $PicHeight / 2; $SerieWeight = 0; } + $X = $this->GraphAreaX1 + $XMargin; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $Y) + { + if ( $DisplayValues ) + $this->drawText($X,$Y-$DisplayOffset-$SerieWeight-$BorderSize-$PicOffset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + + if ( $Y != VOID ) + { + if ( $RecordImageMap ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$SerieWeight,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Picture != NULL ) + { $this->drawFromPicture($PicType,$Picture,$X-$PicWidth/2,$Y-$PicHeight/2); } + else + { $this->drawShape($X,$Y,$Shape,$SerieWeight,$PlotBorder,$BorderSize,$R,$G,$B,$Alpha,$BorderR,$BorderG,$BorderB,$BorderAlpha); } + } + $X = $X + $XStep; + } + } + else + { + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + if ( $Picture != NULL ) { $PicOffset = $PicWidth / 2; $SerieWeight = 0; } + $Y = $this->GraphAreaY1 + $XMargin; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $X) + { + if ( $DisplayValues ) + $this->drawText($X+$DisplayOffset+$SerieWeight+$BorderSize+$PicOffset,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + + if ( $X != VOID ) + { + if ( $RecordImageMap ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$SerieWeight,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Picture != NULL ) + { $this->drawFromPicture($PicType,$Picture,$X-$PicWidth/2,$Y-$PicHeight/2); } + else + { $this->drawShape($X,$Y,$Shape,$SerieWeight,$PlotBorder,$BorderSize,$R,$G,$B,$Alpha,$BorderR,$BorderG,$BorderB,$BorderAlpha); } + } + $Y = $Y + $YStep; + } + } + } + } + } + + /* Draw a spline chart */ + function drawSplineChart($Format=NULL) + { + $BreakVoid = isset($Format["BreakVoid"]) ? $Format["BreakVoid"] : TRUE; + $VoidTicks = isset($Format["VoidTicks"]) ? $Format["VoidTicks"] : 4; + $BreakR = isset($Format["BreakR"]) ? $Format["BreakR"] : NULL; // 234 + $BreakG = isset($Format["BreakG"]) ? $Format["BreakG"] : NULL; // 55 + $BreakB = isset($Format["BreakB"]) ? $Format["BreakB"] : NULL; // 26 + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + $ImageMapPlotSize = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 5; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"]; + + if ( $BreakR == NULL ) + $BreakSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks); + else + $BreakSettings = array("R"=>$BreakR,"G"=>$BreakG,"B"=>$BreakB,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight); + + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; } + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; $WayPoints = ""; + $Force = $XStep / 5; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; $LastX = 1; $LastY = 1; + foreach($PosArray as $Key => $Y) + { + if ( $DisplayValues ) + $this->drawText($X,$Y-$DisplayOffset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + + if ( $RecordImageMap && $Y != VOID ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$ImageMapPlotSize,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Y == VOID && $LastY != NULL ) + { $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); $WayPoints = ""; } + + if ( $Y != VOID && $LastY == NULL && $LastGoodY != NULL && !$BreakVoid ) + { $this->drawLine($LastGoodX,$LastGoodY,$X,$Y,$BreakSettings); } + + if ( $Y != VOID ) + $WayPoints[] = array($X,$Y); + + if ( $Y != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; } + if ( $Y == VOID ) { $Y = NULL; } + + $LastX = $X; $LastY = $Y; + $X = $X + $XStep; + } + $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + } + else + { + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; $WayPoints = ""; + $Force = $YStep / 5; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; $LastX = 1; $LastY = 1; + foreach($PosArray as $Key => $X) + { + if ( $DisplayValues ) + $this->drawText($X+$DisplayOffset,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + + if ( $RecordImageMap && $X != VOID ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$ImageMapPlotSize,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $X == VOID && $LastX != NULL ) + { $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); $WayPoints = ""; } + + if ( $X != VOID && $LastX == NULL && $LastGoodX != NULL && !$BreakVoid ) + { $this->drawLine($LastGoodX,$LastGoodY,$X,$Y,$BreakSettings); } + + if ( $X != VOID ) + $WayPoints[] = array($X,$Y); + + if ( $X != VOID ) { $LastGoodX = $X; $LastGoodY = $Y; } + if ( $X == VOID ) { $X = NULL; } + + $LastX = $X; $LastY = $Y; + $Y = $Y + $YStep; + } + $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + } + } + } + } + + /* Draw a filled spline chart */ + function drawFilledSplineChart($Format=NULL) + { + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $AroundZero = isset($Format["AroundZero"]) ? $Format["AroundZero"] : TRUE; + $Threshold = isset($Format["Threshold"]) ? $Format["Threshold"] : NULL; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + if ( $AroundZero ) { $YZero = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"])); } + + if ( $Threshold != NULL ) + { + foreach($Threshold as $Key => $Params) + { + $Threshold[$Key]["MinX"] = $this->scaleComputeY($Params["Min"],array("AxisID"=>$Serie["Axis"])); + $Threshold[$Key]["MaxX"] = $this->scaleComputeY($Params["Max"],array("AxisID"=>$Serie["Axis"])); + } + } + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; $WayPoints = ""; + $Force = $XStep / 5; + + if ( !$AroundZero ) { $YZero = $this->GraphAreaY2-1; } + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; } + + $LastX = ""; $LastY = ""; + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $Y) + { + if ( $DisplayValues ) + $this->drawText($X,$Y-$DisplayOffset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + + if ( $Y == VOID ) + { + $Area = $this->drawSpline($WayPoints,array("Force"=>$Force,"PathOnly"=>TRUE)); + + if ( $Area != "" ) + { + foreach ($Area as $key => $Points) + { + $Corners = ""; $Corners[] = $Area[$key][0]["X"]; $Corners[] = $YZero; + foreach($Points as $subKey => $Point) + { + if ( $subKey == count($Points)-1) { $Corners[] = $Point["X"]-1; } else { $Corners[] = $Point["X"]; } + $Corners[] = $Point["Y"]+1; + } + $Corners[] = $Points[$subKey]["X"]-1; $Corners[] = $YZero; + + $this->drawPolygonChart($Corners,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/2,"NoBorder"=>TRUE,"Threshold"=>$Threshold)); + } + $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + } + + $WayPoints = ""; + } + else + $WayPoints[] = array($X,$Y-.5); /* -.5 for AA visual fix */ + + $X = $X + $XStep; + } + $Area = $this->drawSpline($WayPoints,array("Force"=>$Force,"PathOnly"=>TRUE)); + + if ( $Area != "" ) + { + foreach ($Area as $key => $Points) + { + $Corners = ""; $Corners[] = $Area[$key][0]["X"]; $Corners[] = $YZero; + foreach($Points as $subKey => $Point) + { + if ( $subKey == count($Points)-1) { $Corners[] = $Point["X"]-1; } else { $Corners[] = $Point["X"]; } + $Corners[] = $Point["Y"]+1; + } + $Corners[] = $Points[$subKey]["X"]-1; $Corners[] = $YZero; + + $this->drawPolygonChart($Corners,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/2,"NoBorder"=>TRUE,"Threshold"=>$Threshold)); + } + $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + } + } + else + { + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; $WayPoints = ""; + $Force = $YStep / 5; + + if ( !$AroundZero ) { $YZero = $this->GraphAreaX1+1; } + if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; } + if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; } + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $X) + { + if ( $DisplayValues ) + $this->drawText($X+$DisplayOffset,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + + if ( $X == VOID ) + { + $Area = $this->drawSpline($WayPoints,array("Force"=>$Force,"PathOnly"=>TRUE)); + + if ( $Area != "" ) + { + foreach ($Area as $key => $Points) + { + $Corners = ""; $Corners[] = $YZero; $Corners[] = $Area[$key][0]["Y"]; + foreach($Points as $subKey => $Point) + { + if ( $subKey == count($Points)-1) { $Corners[] = $Point["X"]-1; } else { $Corners[] = $Point["X"]; } + $Corners[] = $Point["Y"]; + } + $Corners[] = $YZero; $Corners[] = $Points[$subKey]["Y"]-1; + + $this->drawPolygonChart($Corners,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/2,"NoBorder"=>TRUE,"Threshold"=>$Threshold)); + } + $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + } + + $WayPoints = ""; + } + else + $WayPoints[] = array($X,$Y); + + $Y = $Y + $YStep; + } + $Area = $this->drawSpline($WayPoints,array("Force"=>$Force,"PathOnly"=>TRUE)); + + if ( $Area != "" ) + { + foreach ($Area as $key => $Points) + { + $Corners = ""; $Corners[] = $YZero; $Corners[] = $Area[$key][0]["Y"]; + foreach($Points as $subKey => $Point) + { + if ( $subKey == count($Points)-1) { $Corners[] = $Point["X"]-1; } else { $Corners[] = $Point["X"]; } + $Corners[] = $Point["Y"]; + } + $Corners[] = $YZero; $Corners[] = $Points[$subKey]["Y"]-1; + + $this->drawPolygonChart($Corners,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/2,"NoBorder"=>TRUE,"Threshold"=>$Threshold)); + } + $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks)); + } + + } + } + } + } + + /* Draw a line chart */ + function drawLineChart($Format=NULL) + { + $BreakVoid = isset($Format["BreakVoid"]) ? $Format["BreakVoid"] : TRUE; + $VoidTicks = isset($Format["VoidTicks"]) ? $Format["VoidTicks"] : 4; + $BreakR = isset($Format["BreakR"]) ? $Format["BreakR"] : NULL; + $BreakG = isset($Format["BreakG"]) ? $Format["BreakG"] : NULL; + $BreakB = isset($Format["BreakB"]) ? $Format["BreakB"] : NULL; + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + $ImageMapPlotSize = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 5; + $ForceColor = isset($Format["ForceColor"]) ? $Format["ForceColor"] : FALSE; + $ForceR = isset($Format["ForceR"]) ? $Format["ForceR"] : 0; + $ForceG = isset($Format["ForceG"]) ? $Format["ForceG"] : 0; + $ForceB = isset($Format["ForceB"]) ? $Format["ForceB"] : 0; + $ForceAlpha = isset($Format["ForceAlpha"]) ? $Format["ForceAlpha"] : 100; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"]; + + if ( $ForceColor ) + { $R = $ForceR; $G = $ForceG; $B = $ForceB; $Alpha = $ForceAlpha; } + + if ( $BreakR == NULL ) + $BreakSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight); + else + $BreakSettings = array("R"=>$BreakR,"G"=>$BreakG,"B"=>$BreakB,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight); + + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; } + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; + foreach($PosArray as $Key => $Y) + { + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { + if ( $Serie["Data"][$Key] > 0 ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; } + $this->drawText($X,$Y-$Offset-$Weight,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align)); + } + + if ( $RecordImageMap && $Y != VOID ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$ImageMapPlotSize,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Y != VOID && $LastX != NULL && $LastY != NULL ) + $this->drawLine($LastX,$LastY,$X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + + if ( $Y != VOID && $LastY == NULL && $LastGoodY != NULL && !$BreakVoid ) + { $this->drawLine($LastGoodX,$LastGoodY,$X,$Y,$BreakSettings); $LastGoodY = NULL; } + + if ( $Y != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; } + if ( $Y == VOID ) { $Y = NULL; } + + $LastX = $X; $LastY = $Y; + $X = $X + $XStep; + } + } + else + { + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; + foreach($PosArray as $Key => $X) + { + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { $this->drawText($X+$DisplayOffset+$Weight,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); } + + if ( $RecordImageMap && $X != VOID ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$ImageMapPlotSize,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $X != VOID && $LastX != NULL && $LastY != NULL ) + $this->drawLine($LastX,$LastY,$X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + + if ( $X != VOID && $LastX == NULL && $LastGoodY != NULL && !$BreakVoid ) + { $this->drawLine($LastGoodX,$LastGoodY,$X,$Y,$BreakSettings); $LastGoodY = NULL; } + + if ( $X != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; } + if ( $X == VOID ) { $X = NULL; } + + $LastX = $X; $LastY = $Y; + $Y = $Y + $YStep; + } + } + } + } + } + + /* Draw a line chart */ + function drawZoneChart($SerieA,$SerieB,$Format=NULL) + { + $AxisID = isset($Format["AxisID"]) ? $Format["AxisID"] : 0; + $LineR = isset($Format["LineR"]) ? $Format["LineR"] : 150; + $LineG = isset($Format["LineG"]) ? $Format["LineG"] : 150; + $LineB = isset($Format["LineB"]) ? $Format["LineB"] : 150; + $LineAlpha = isset($Format["LineAlpha"]) ? $Format["LineAlpha"] : 50; + $LineTicks = isset($Format["LineTicks"]) ? $Format["LineTicks"] : 1; + $AreaR = isset($Format["AreaR"]) ? $Format["AreaR"] : 150; + $AreaG = isset($Format["AreaG"]) ? $Format["AreaG"] : 150; + $AreaB = isset($Format["AreaB"]) ? $Format["AreaB"] : 150; + $AreaAlpha = isset($Format["AreaAlpha"]) ? $Format["AreaAlpha"] : 5; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + if ( !isset($Data["Series"][$SerieA]["Data"]) || !isset($Data["Series"][$SerieB]["Data"]) ) { return(0); } + $SerieAData = $Data["Series"][$SerieA]["Data"]; + $SerieBData = $Data["Series"][$SerieB]["Data"]; + + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + $PosArrayA = $this->scaleComputeY($SerieAData,array("AxisID"=>$AxisID)); + $PosArrayB = $this->scaleComputeY($SerieBData,array("AxisID"=>$AxisID)); + if ( count($PosArrayA) != count($PosArrayB) ) { return(0); } + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL; + + $LastX = NULL; $LastY1 = NULL; $LastY2 = NULL; + $BoundsA = ""; $BoundsB = ""; + foreach($PosArrayA as $Key => $Y1) + { + $Y2 = $PosArrayB[$Key]; + + $BoundsA[] = $X; $BoundsA[] = $Y1; + $BoundsB[] = $X; $BoundsB[] = $Y2; + + $LastX = $X; + $LastY1 = $Y1; $LastY2 = $Y2; + + $X = $X + $XStep; + } + $Bounds = array_merge($BoundsA,$this->reversePlots($BoundsB)); + $this->drawPolygonChart($Bounds,array("R"=>$AreaR,"G"=>$AreaG,"B"=>$AreaB,"Alpha"=>$AreaAlpha)); + + for($i=0;$i<=count($BoundsA)-4;$i=$i+2) + { + $this->drawLine($BoundsA[$i],$BoundsA[$i+1],$BoundsA[$i+2],$BoundsA[$i+3],array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha,"Ticks"=>$LineTicks)); + $this->drawLine($BoundsB[$i],$BoundsB[$i+1],$BoundsB[$i+2],$BoundsB[$i+3],array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha,"Ticks"=>$LineTicks)); + } + } + else + { + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL; + + $LastY = NULL; $LastX1 = NULL; $LastX2 = NULL; + $BoundsA = ""; $BoundsB = ""; + foreach($PosArrayA as $Key => $X1) + { + $X2 = $PosArrayB[$Key]; + + $BoundsA[] = $X1; $BoundsA[] = $Y; + $BoundsB[] = $X2; $BoundsB[] = $Y; + + $LastY = $Y; + $LastX1 = $X1; $LastX2 = $X2; + + $Y = $Y + $YStep; + } + $Bounds = array_merge($BoundsA,$this->reversePlots($BoundsB)); + $this->drawPolygonChart($Bounds,array("R"=>$AreaR,"G"=>$AreaG,"B"=>$AreaB,"Alpha"=>$AreaAlpha)); + + for($i=0;$i<=count($BoundsA)-4;$i=$i+2) + { + $this->drawLine($BoundsA[$i],$BoundsA[$i+1],$BoundsA[$i+2],$BoundsA[$i+3],array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha,"Ticks"=>$LineTicks)); + $this->drawLine($BoundsB[$i],$BoundsB[$i+1],$BoundsB[$i+2],$BoundsB[$i+3],array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha,"Ticks"=>$LineTicks)); + } + } + } + + /* Draw a step chart */ + function drawStepChart($Format=NULL) + { + $BreakVoid = isset($Format["BreakVoid"]) ? $Format["BreakVoid"] : FALSE; + $ReCenter = isset($Format["ReCenter"]) ? $Format["ReCenter"] : TRUE; + $VoidTicks = isset($Format["VoidTicks"]) ? $Format["VoidTicks"] : 4; + $BreakR = isset($Format["BreakR"]) ? $Format["BreakR"] : NULL; + $BreakG = isset($Format["BreakG"]) ? $Format["BreakG"] : NULL; + $BreakB = isset($Format["BreakB"]) ? $Format["BreakB"] : NULL; + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] :FALSE; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + $ImageMapPlotSize = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 5; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"]; + + if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; } + + if ( $BreakR == NULL ) + $BreakSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight); + else + $BreakSettings = array("R"=>$BreakR,"G"=>$BreakG,"B"=>$BreakB,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight); + + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight); + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; $Init = FALSE; + foreach($PosArray as $Key => $Y) + { + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { + if ( $Y <= $LastY ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; } + $this->drawText($X,$Y-$Offset-$Weight,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align)); + } + + if ( $Y != VOID && $LastX != NULL && $LastY != NULL ) + { + $this->drawLine($LastX,$LastY,$X,$LastY,$Color); + $this->drawLine($X,$LastY,$X,$Y,$Color); + if ( $ReCenter && $X+$XStep < $this->GraphAreaX2 - $XMargin ) + { + $this->drawLine($X,$Y,$X+$XStep,$Y,$Color); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X-$ImageMapPlotSize).",".floor($Y-$ImageMapPlotSize).",".floor($X+$XStep+$ImageMapPlotSize).",".floor($Y+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + else + { if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastX-$ImageMapPlotSize).",".floor($LastY-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($LastY+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } } + } + + if ( $Y != VOID && $LastY == NULL && $LastGoodY != NULL && !$BreakVoid ) + { + if ( $ReCenter ) + { + $this->drawLine($LastGoodX+$XStep,$LastGoodY,$X,$LastGoodY,$BreakSettings); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastGoodX+$XStep-$ImageMapPlotSize).",".floor($LastGoodY-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($LastGoodY+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + else + { + $this->drawLine($LastGoodX,$LastGoodY,$X,$LastGoodY,$BreakSettings); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastGoodX-$ImageMapPlotSize).",".floor($LastGoodY-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($LastGoodY+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + + $this->drawLine($X,$LastGoodY,$X,$Y,$BreakSettings); + $LastGoodY = NULL; + } + elseif( !$BreakVoid && $LastGoodY == NULL && $Y != VOID ) + { + $this->drawLine($this->GraphAreaX1 + $XMargin,$Y,$X,$Y,$BreakSettings); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($this->GraphAreaX1+$XMargin-$ImageMapPlotSize).",".floor($Y-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($Y+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + + if ( $Y != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; } + if ( $Y == VOID ) { $Y = NULL; } + + if ( !$Init && $ReCenter ) { $X = $X - $XStep/2; $Init = TRUE; } + $LastX = $X; $LastY = $Y; + if ( $LastX < $this->GraphAreaX1 + $XMargin ) { $LastX = $this->GraphAreaX1 + $XMargin; } + $X = $X + $XStep; + } + if ( $ReCenter ) + { + $this->drawLine($LastX,$LastY,$this->GraphAreaX2 - $XMargin,$LastY,$Color); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastX-$ImageMapPlotSize).",".floor($LastY-$ImageMapPlotSize).",".floor($this->GraphAreaX2-$XMargin+$ImageMapPlotSize).",".floor($LastY+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + } + else + { + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; $Init = FALSE; + foreach($PosArray as $Key => $X) + { + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { + if ( $X >= $LastX ) { $Align = TEXT_ALIGN_MIDDLELEFT; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_MIDDLERIGHT; $Offset = -$DisplayOffset; } + $this->drawText($X+$Offset+$Weight,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align)); + } + + if ( $X != VOID && $LastX != NULL && $LastY != NULL ) + { + $this->drawLine($LastX,$LastY,$LastX,$Y,$Color); + $this->drawLine($LastX,$Y,$X,$Y,$Color); + + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastX-$ImageMapPlotSize).",".floor($LastY-$ImageMapPlotSize).",".floor($LastX+$XStep+$ImageMapPlotSize).",".floor($Y+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + + if ( $X != VOID && $LastX == NULL && $LastGoodY != NULL && !$BreakVoid ) + { + $this->drawLine($LastGoodX,$LastGoodY,$LastGoodX,$LastGoodY+$YStep,$Color); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastGoodX-$ImageMapPlotSize).",".floor($LastGoodY-$ImageMapPlotSize).",".floor($LastGoodX+$ImageMapPlotSize).",".floor($LastGoodY+$YStep+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + $this->drawLine($LastGoodX,$LastGoodY+$YStep,$LastGoodX,$Y,$BreakSettings); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastGoodX-$ImageMapPlotSize).",".floor($LastGoodY+$YStep-$ImageMapPlotSize).",".floor($LastGoodX+$ImageMapPlotSize).",".floor($YStep+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + $this->drawLine($LastGoodX,$Y,$X,$Y,$BreakSettings); + $LastGoodY = NULL; + } + elseif ( $X != VOID && $LastGoodY == NULL && !$BreakVoid ) + { + $this->drawLine($X,$this->GraphAreaY1 + $XMargin,$X,$Y,$BreakSettings); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X-$ImageMapPlotSize).",".floor($this->GraphAreaY1+$XMargin-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($Y+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + + if ( $X != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; } + if ( $X == VOID ) { $X = NULL; } + + if ( !$Init && $ReCenter ) { $Y = $Y - $YStep/2; $Init = TRUE; } + $LastX = $X; $LastY = $Y; + if ( $LastY < $this->GraphAreaY1 + $XMargin ) { $LastY = $this->GraphAreaY1 + $XMargin; } + $Y = $Y + $YStep; + } + if ( $ReCenter ) + { + $this->drawLine($LastX,$LastY,$LastX,$this->GraphAreaY2 - $XMargin,$Color); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastX-$ImageMapPlotSize).",".floor($LastY-$ImageMapPlotSize).",".floor($LastX+$ImageMapPlotSize).",".floor($this->GraphAreaY2-$XMargin+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + } + } + } + } + + /* Draw a step chart */ + function drawFilledStepChart($Format=NULL) + { + $ReCenter = isset($Format["ReCenter"]) ? $Format["ReCenter"] : TRUE; + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] :FALSE; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $ForceTransparency = isset($Format["ForceTransparency"]) ? $Format["ForceTransparency"] : NULL; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $AroundZero = isset($Format["AroundZero"]) ? $Format["AroundZero"] : TRUE; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"]; + + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B); + if ( $ForceTransparency != NULL ) { $Color["Alpha"] = $ForceTransparency; } else { $Color["Alpha"] = $Alpha; } + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + $YZero = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"])); + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; } + + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !$AroundZero ) { $YZero = $this->GraphAreaY2-1; } + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; $Points = ""; $Init = FALSE; + foreach($PosArray as $Key => $Y) + { + if ( $Y == VOID && $LastX != NULL && $LastY != NULL && $Points !="" ) + { + $Points[] = $LastX; $Points[] = $LastY; + $Points[] = $X; $Points[] = $LastY; + $Points[] = $X; $Points[] = $YZero; + $this->drawPolygon($Points,$Color); + $Points = ""; + } + + if ( $Y != VOID && $LastX != NULL && $LastY != NULL ) + { + if ( $Points == "") { $Points[] = $LastX; $Points[] = $YZero; } + $Points[] = $LastX; $Points[] = $LastY; + $Points[] = $X; $Points[] = $LastY; + $Points[] = $X; $Points[] = $Y; + } + + if ( $Y != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; } + if ( $Y == VOID ) { $Y = NULL; } + + if ( !$Init && $ReCenter ) { $X = $X - $XStep/2; $Init = TRUE; } + $LastX = $X; $LastY = $Y; + if ( $LastX < $this->GraphAreaX1 + $XMargin ) { $LastX = $this->GraphAreaX1 + $XMargin; } + $X = $X + $XStep; + } + + if ( $ReCenter ) + { + $Points[] = $LastX+$XStep/2; $Points[] = $LastY; + $Points[] = $LastX+$XStep/2; $Points[] = $YZero; + } + else + { $Points[] = $LastX; $Points[] = $YZero; } + + $this->drawPolygon($Points,$Color); + } + else + { + if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; } + if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; } + + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $LastGoodY = NULL; $LastGoodX = NULL; $Points = ""; + foreach($PosArray as $Key => $X) + { + if ( $X == VOID && $LastX != NULL && $LastY != NULL && $Points !="" ) + { + $Points[] = $LastX; $Points[] = $LastY; + $Points[] = $LastX; $Points[] = $Y; + $Points[] = $YZero; $Points[] = $Y; + $this->drawPolygon($Points,$Color); + $Points = ""; + } + + if ( $X != VOID && $LastX != NULL && $LastY != NULL ) + { + if ( $Points == "") { $Points[] = $YZero; $Points[] = $LastY; } + $Points[] = $LastX; $Points[] = $LastY; + $Points[] = $LastX; $Points[] = $Y; + $Points[] = $X; $Points[] = $Y; + } + + if ( $X != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; } + if ( $X == VOID ) { $X = NULL; } + + if ( $LastX == NULL && $ReCenter ) { $Y = $Y - $YStep/2; } + $LastX = $X; $LastY = $Y; + if ( $LastY < $this->GraphAreaY1 + $XMargin ) { $LastY = $this->GraphAreaY1 + $XMargin; } + $Y = $Y + $YStep; + } + + if ( $ReCenter ) + { + $Points[] = $LastX; $Points[] = $LastY+$YStep/2; + $Points[] = $YZero; $Points[] = $LastY+$YStep/2; + } + else + { $Points[] = $YZero; $Points[] = $LastY; } + + $this->drawPolygon($Points,$Color); + } + } + } + } + + /* Draw an area chart */ + function drawAreaChart($Format=NULL) + { + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $ForceTransparency = isset($Format["ForceTransparency"]) ? $Format["ForceTransparency"] : 25; + $AroundZero = isset($Format["AroundZero"]) ? $Format["AroundZero"] : TRUE; + $Threshold = isset($Format["Threshold"]) ? $Format["Threshold"] : NULL; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + $YZero = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"])); + + if ( $Threshold != NULL ) + { + foreach($Threshold as $Key => $Params) + { + $Threshold[$Key]["MinX"] = $this->scaleComputeY($Params["Min"],array("AxisID"=>$Serie["Axis"])); + $Threshold[$Key]["MaxX"] = $this->scaleComputeY($Params["Max"],array("AxisID"=>$Serie["Axis"])); + } + } + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + + $Areas = ""; $AreaID = 0; + $Areas[$AreaID][] = $this->GraphAreaX1 + $XMargin; + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaY2-1; } + + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $Y) + { + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { + if ( $Serie["Data"][$Key] > 0 ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; } + $this->drawText($X,$Y-$Offset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align)); + } + + if ( $Y == VOID && isset($Areas[$AreaID]) ) + { + if($LastX == NULL) + { $Areas[$AreaID][] = $X; } + else + { $Areas[$AreaID][] = $LastX; } + + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaY2-1; } + $AreaID++; + } + elseif ($Y != VOID) + { + if ( !isset($Areas[$AreaID]) ) + { + $Areas[$AreaID][] = $X; + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaY2-1; } + } + + $Areas[$AreaID][] = $X; + $Areas[$AreaID][] = $Y; + } + + $LastX = $X; + $X = $X + $XStep; + } + $Areas[$AreaID][] = $LastX; + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaY2-1; } + + /* Handle shadows in the areas */ + if ( $this->Shadow ) + { + $ShadowArea = ""; + foreach($Areas as $Key => $Points) + { + $ShadowArea[$Key] = ""; + foreach($Points as $Key2 => $Value) + { + if ( $Key2 % 2 == 0 ) + { $ShadowArea[$Key][] = $Value + $this->ShadowX; } + else + { $ShadowArea[$Key][] = $Value + $this->ShadowY; } + } + } + + foreach($ShadowArea as $Key => $Points) + $this->drawPolygonChart($Points,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa)); + } + + $Alpha = $ForceTransparency != NULL ? $ForceTransparency : $Alpha; + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Threshold"=>$Threshold); + + foreach($Areas as $Key => $Points) + $this->drawPolygonChart($Points,$Color); + } + else + { + if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; } + if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; } + + $Areas = ""; $AreaID = 0; + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaX1+1; } + $Areas[$AreaID][] = $this->GraphAreaY1 + $XMargin; + + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $X) + { + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { + if ( $Serie["Data"][$Key] > 0 ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; } + $this->drawText($X+$Offset,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align)); + } + + if ( $X == VOID && isset($Areas[$AreaID]) ) + { + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaX1+1; } + + if($LastY == NULL) + { $Areas[$AreaID][] = $Y; } + else + { $Areas[$AreaID][] = $LastY; } + + $AreaID++; + } + elseif ($X != VOID) + { + if ( !isset($Areas[$AreaID]) ) + { + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaX1+1; } + $Areas[$AreaID][] = $Y; + } + + $Areas[$AreaID][] = $X; + $Areas[$AreaID][] = $Y; + } + + $LastX = $X; $LastY = $Y; + $Y = $Y + $YStep; + } + if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaX1+1; } + $Areas[$AreaID][] = $LastY; + + /* Handle shadows in the areas */ + if ( $this->Shadow ) + { + $ShadowArea = ""; + foreach($Areas as $Key => $Points) + { + $ShadowArea[$Key] = ""; + foreach($Points as $Key2 => $Value) + { + if ( $Key2 % 2 == 0 ) + { $ShadowArea[$Key][] = $Value + $this->ShadowX; } + else + { $ShadowArea[$Key][] = $Value + $this->ShadowY; } + } + } + + foreach($ShadowArea as $Key => $Points) + $this->drawPolygonChart($Points,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa)); + } + + $Alpha = $ForceTransparency != NULL ? $ForceTransparency : $Alpha; + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Threshold"=>$Threshold); + + foreach($Areas as $Key => $Points) + $this->drawPolygonChart($Points,$Color); + } + } + } + } + + + /* Draw a bar chart */ + function drawBarChart($Format=NULL) + { + $Floating0Serie = isset($Format["Floating0Serie"]) ? $Format["Floating0Serie"] : NULL; + $Floating0Value = isset($Format["Floating0Value"]) ? $Format["Floating0Value"] : NULL; + $Draw0Line = isset($Format["Draw0Line"]) ? $Format["Draw0Line"] : FALSE; + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE; + $DisplayOrientation = isset($Format["DisplayOrientation"]) ? $Format["DisplayOrientation"] : ORIENTATION_HORIZONTAL; + $DisplayOffset = isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayFont = isset($Format["DisplaySize"]) ? $Format["DisplaySize"] : $this->FontName; + $DisplaySize = isset($Format["DisplaySize"]) ? $Format["DisplaySize"] : $this->FontSize; + $DisplayPos = isset($Format["DisplayPos"]) ? $Format["DisplayPos"] : LABEL_POS_OUTSIDE; + $DisplayShadow = isset($Format["DisplayShadow"]) ? $Format["DisplayShadow"] : TRUE; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $AroundZero = isset($Format["AroundZero"]) ? $Format["AroundZero"] : TRUE; + $Interleave = isset($Format["Interleave"]) ? $Format["Interleave"] : .5; + $Rounded = isset($Format["Rounded"]) ? $Format["Rounded"] : FALSE; + $RoundRadius = isset($Format["RoundRadius"]) ? $Format["RoundRadius"] : 4; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1; + $Gradient = isset($Format["Gradient"]) ? $Format["Gradient"] : FALSE; + $GradientMode = isset($Format["GradientMode"]) ? $Format["GradientMode"] : GRADIENT_SIMPLE; + $GradientAlpha = isset($Format["GradientAlpha"]) ? $Format["GradientAlpha"] : 20; + $GradientStartR = isset($Format["GradientStartR"]) ? $Format["GradientStartR"] : 255; + $GradientStartG = isset($Format["GradientStartG"]) ? $Format["GradientStartG"] : 255; + $GradientStartB = isset($Format["GradientStartB"]) ? $Format["GradientStartB"] : 255; + $GradientEndR = isset($Format["GradientEndR"]) ? $Format["GradientEndR"] : 0; + $GradientEndG = isset($Format["GradientEndG"]) ? $Format["GradientEndG"] : 0; + $GradientEndB = isset($Format["GradientEndB"]) ? $Format["GradientEndB"] : 0; + $TxtMargin = isset($Format["TxtMargin"]) ? $Format["TxtMargin"] : 6; + $OverrideColors = isset($Format["OverrideColors"]) ? $Format["OverrideColors"] : NULL; + $OverrideSurrounding = isset($Format["OverrideSurrounding"]) ? $Format["OverrideSurrounding"] : 30; + $InnerSurrounding = isset($Format["InnerSurrounding"]) ? $Format["InnerSurrounding"] : NULL; + $InnerBorderR = isset($Format["InnerBorderR"]) ? $Format["InnerBorderR"] : -1; + $InnerBorderG = isset($Format["InnerBorderG"]) ? $Format["InnerBorderG"] : -1; + $InnerBorderB = isset($Format["InnerBorderB"]) ? $Format["InnerBorderB"] : -1; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + + $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + if ( $OverrideColors != NULL ) + { + $OverrideColors = $this->validatePalette($OverrideColors,$OverrideSurrounding); + $this->DataSet->saveExtendedData("Palette",$OverrideColors); + } + + $RestoreShadow = $this->Shadow; + + $SeriesCount = $this->countDrawableSeries(); + $CurrentSerie = 0; + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; } + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + if ( $InnerSurrounding != NULL ) { $InnerBorderR = $R+$InnerSurrounding; $InnerBorderG = $G+$InnerSurrounding; $InnerBorderB = $B+$InnerSurrounding; } + if ( $InnerBorderR == -1 ) { $InnerColor = NULL; } else { $InnerColor = array("R"=>$InnerBorderR,"G"=>$InnerBorderG,"B"=>$InnerBorderB); } + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB); + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; } + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + if ( $Floating0Value != NULL ) + { $YZero = $this->scaleComputeY($Floating0Value,array("AxisID"=>$Serie["Axis"])); } + else + { $YZero = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"])); } + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; } + + if ( $XDivs == 0 ) { $XStep = 0; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; + + if ( $AroundZero ) { $Y1 = $YZero; } else { $Y1 = $this->GraphAreaY2-1; } + if ( $XDivs == 0 ) { $XSize = ($this->GraphAreaX2-$this->GraphAreaX1)/($SeriesCount+$Interleave); } else { $XSize = ($XStep / ($SeriesCount+$Interleave) ); } + + $XOffset = -($XSize*$SeriesCount)/2 + $CurrentSerie * $XSize; + if ( $X + $XOffset <= $this->GraphAreaX1 ) { $XOffset = $this->GraphAreaX1 - $X + 1 ; } + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = $XOffset + $XSize / 2; + + if ( $Rounded || $BorderR != -1) { $XSpace = 1; } else { $XSpace = 0; } + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + + $ID = 0; + foreach($PosArray as $Key => $Y2) + { + if ( $Floating0Serie != NULL ) + { + if ( isset($Data["Series"][$Floating0Serie]["Data"][$Key]) ) + { $Value = $Data["Series"][$Floating0Serie]["Data"][$Key]; } + else + { $Value = 0; } + + $YZero = $this->scaleComputeY($Value,array("AxisID"=>$Serie["Axis"])); + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; } + + if ( $AroundZero ) { $Y1 = $YZero; } else { $Y1 = $this->GraphAreaY2-1; } + } + + if ( $OverrideColors != NULL ) + { if ( isset($OverrideColors[$ID]) ) { $Color = array("R"=>$OverrideColors[$ID]["R"],"G"=>$OverrideColors[$ID]["G"],"B"=>$OverrideColors[$ID]["B"],"Alpha"=>$OverrideColors[$ID]["Alpha"],"BorderR"=>$OverrideColors[$ID]["BorderR"],"BorderG"=>$OverrideColors[$ID]["BorderG"],"BorderB"=>$OverrideColors[$ID]["BorderB"]); } else { $Color = $this->getRandomColor(); } } + + if ( $Y2 != VOID ) + { + $BarHeight = $Y1 - $Y2; + + if ( $Serie["Data"][$Key] == 0 ) + { + $this->drawLine($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y1,$Color); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X+$XOffset+$XSpace).",".floor($Y1-1).",".floor($X+$XOffset+$XSize-$XSpace).",".floor($Y1+1),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + else + { + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X+$XOffset+$XSpace).",".floor($Y1).",".floor($X+$XOffset+$XSize-$XSpace).",".floor($Y2),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Rounded ) + $this->drawRoundedFilledRectangle($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y2,$RoundRadius,$Color); + else + { + $this->drawFilledRectangle($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y2,$Color); + + if ( $InnerColor != NULL ) { $this->drawRectangle($X+$XOffset+$XSpace+1,min($Y1,$Y2)+1,$X+$XOffset+$XSize-$XSpace-1,max($Y1,$Y2)-1,$InnerColor); } + + if ( $Gradient ) + { + $this->Shadow = FALSE; + + if ( $GradientMode == GRADIENT_SIMPLE ) + { + if ( $Serie["Data"][$Key] >= 0 ) + $GradienColor = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + else + $GradienColor = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha); + + $this->drawGradientArea($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y2,DIRECTION_VERTICAL,$GradienColor); + } + elseif ( $GradientMode == GRADIENT_EFFECT_CAN ) + { + $GradienColor1 = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha); + $GradienColor2 = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + $XSpan = floor($XSize / 3); + + $this->drawGradientArea($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSpan-$XSpace,$Y2,DIRECTION_HORIZONTAL,$GradienColor1); + $this->drawGradientArea($X+$XOffset+$XSpan+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y2,DIRECTION_HORIZONTAL,$GradienColor2); + } + $this->Shadow = $RestoreShadow; + } + } + + if ( $Draw0Line ) + { + $Line0Color = array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20); + + if ( abs($Y1 - $Y2) > 3 ) { $Line0Width = 3; } else { $Line0Width = 1; } + if ( $Y1 - $Y2 < 0 ) { $Line0Width = -$Line0Width; } + + $this->drawFilledRectangle($X+$XOffset+$XSpace,floor($Y1),$X+$XOffset+$XSize-$XSpace,floor($Y1)-$Line0Width,$Line0Color); + $this->drawLine($X+$XOffset+$XSpace,floor($Y1),$X+$XOffset+$XSize-$XSpace,floor($Y1),$Line0Color); + } + } + + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { + if ( $DisplayShadow ) { $this->Shadow = TRUE; } + + $Caption = $this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit); + $TxtPos = $this->getTextBox(0,0,$DisplayFont,$DisplaySize,90,$Caption); + $TxtHeight = $TxtPos[0]["Y"] - $TxtPos[1]["Y"] + $TxtMargin; + + if ( $DisplayPos == LABEL_POS_INSIDE && abs($TxtHeight) < abs($BarHeight) ) + { + $CenterX = (($X+$XOffset+$XSize-$XSpace)-($X+$XOffset+$XSpace))/2 + $X+$XOffset+$XSpace; + $CenterY = ($Y2-$Y1)/2 + $Y1; + + $this->drawText($CenterX,$CenterY,$Caption,array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"Angle"=>90)); + } + else + { + if ( $Serie["Data"][$Key] >= 0 ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; } + $this->drawText($X+$XOffset+$XSize/2,$Y2-$Offset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align,"FontSize"=>$DisplaySize)); + } + + $this->Shadow = $RestoreShadow; + } + } + + $X = $X + $XStep; + $ID++; + } + } + else + { + if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; } + if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; } + + if ( $XDivs == 0 ) { $YStep = 0; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + + $Y = $this->GraphAreaY1 + $XMargin; + + if ( $AroundZero ) { $X1 = $YZero; } else { $X1 = $this->GraphAreaX1+1; } + if ( $XDivs == 0 ) { $YSize = ($this->GraphAreaY2-$this->GraphAreaY1)/($SeriesCount+$Interleave); } else { $YSize = ($YStep / ($SeriesCount+$Interleave) ); } + + $YOffset = -($YSize*$SeriesCount)/2 + $CurrentSerie * $YSize; + if ( $Y + $YOffset <= $this->GraphAreaY1 ) { $YOffset = $this->GraphAreaY1 - $Y + 1 ; } + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = $YOffset + $YSize / 2; + + if ( $Rounded || $BorderR != -1 ) { $YSpace = 1; } else { $YSpace = 0; } + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + + $ID = 0 ; + foreach($PosArray as $Key => $X2) + { + if ( $Floating0Serie != NULL ) + { + if ( isset($Data["Series"][$Floating0Serie]["Data"][$Key]) ) + $Value = $Data["Series"][$Floating0Serie]["Data"][$Key]; + else { $Value = 0; } + + $YZero = $this->scaleComputeY($Value,array("AxisID"=>$Serie["Axis"])); + if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; } + if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; } + if ( $AroundZero ) { $X1 = $YZero; } else { $X1 = $this->GraphAreaX1+1; } + } + + if ( $OverrideColors != NULL ) + { if ( isset($OverrideColors[$ID]) ) { $Color = array("R"=>$OverrideColors[$ID]["R"],"G"=>$OverrideColors[$ID]["G"],"B"=>$OverrideColors[$ID]["B"],"Alpha"=>$OverrideColors[$ID]["Alpha"],"BorderR"=>$OverrideColors[$ID]["BorderR"],"BorderG"=>$OverrideColors[$ID]["BorderG"],"BorderB"=>$OverrideColors[$ID]["BorderB"]); } else { $Color = $this->getRandomColor(); } } + + if ( $X2 != VOID ) + { + $BarWidth = $X2 - $X1; + + if ( $Serie["Data"][$Key] == 0 ) + { + $this->drawLine($X1,$Y+$YOffset+$YSpace,$X1,$Y+$YOffset+$YSize-$YSpace,$Color); + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X1-1).",".floor($Y+$YOffset+$YSpace).",".floor($X1+1).",".floor($Y+$YOffset+$YSize-$YSpace),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + } + else + { + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X1).",".floor($Y+$YOffset+$YSpace).",".floor($X2).",".floor($Y+$YOffset+$YSize-$YSpace),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Rounded ) + $this->drawRoundedFilledRectangle($X1+1,$Y+$YOffset+$YSpace,$X2,$Y+$YOffset+$YSize-$YSpace,$RoundRadius,$Color); + else + { + $this->drawFilledRectangle($X1,$Y+$YOffset+$YSpace,$X2,$Y+$YOffset+$YSize-$YSpace,$Color); + + if ( $InnerColor != NULL ) { $this->drawRectangle(min($X1,$X2)+1,$Y+$YOffset+$YSpace+1,max($X1,$X2)-1,$Y+$YOffset+$YSize-$YSpace-1,$InnerColor); } + + if ( $Gradient ) + { + $this->Shadow = FALSE; + + if ( $GradientMode == GRADIENT_SIMPLE ) + { + if ( $Serie["Data"][$Key] >= 0 ) + $GradienColor = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + else + $GradienColor = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha); + + $this->drawGradientArea($X1,$Y+$YOffset+$YSpace,$X2,$Y+$YOffset+$YSize-$YSpace,DIRECTION_HORIZONTAL,$GradienColor); + } + elseif ( $GradientMode == GRADIENT_EFFECT_CAN ) + { + $GradienColor1 = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha); + $GradienColor2 = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + $YSpan = floor($YSize / 3); + + $this->drawGradientArea($X1,$Y+$YOffset+$YSpace,$X2,$Y+$YOffset+$YSpan-$YSpace,DIRECTION_VERTICAL,$GradienColor1); + $this->drawGradientArea($X1,$Y+$YOffset+$YSpan,$X2,$Y+$YOffset+$YSize-$YSpace,DIRECTION_VERTICAL,$GradienColor2); + } + $this->Shadow = $RestoreShadow; + } + } + + if ( $Draw0Line ) + { + $Line0Color = array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20); + + if ( abs($X1 - $X2) > 3 ) { $Line0Width = 3; } else { $Line0Width = 1; } + if ( $X2 - $X1 < 0 ) { $Line0Width = -$Line0Width; } + + $this->drawFilledRectangle(floor($X1),$Y+$YOffset+$YSpace,floor($X1)+$Line0Width,$Y+$YOffset+$YSize-$YSpace,$Line0Color); + $this->drawLine(floor($X1),$Y+$YOffset+$YSpace,floor($X1),$Y+$YOffset+$YSize-$YSpace,$Line0Color); + } + } + + if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) + { + if ( $DisplayShadow ) { $this->Shadow = TRUE; } + + $Caption = $this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit); + $TxtPos = $this->getTextBox(0,0,$DisplayFont,$DisplaySize,0,$Caption); + $TxtWidth = $TxtPos[1]["X"] - $TxtPos[0]["X"] + $TxtMargin; + + if ( $DisplayPos == LABEL_POS_INSIDE && abs($TxtWidth) < abs($BarWidth) ) + { + $CenterX = ($X2-$X1)/2 + $X1; + $CenterY = (($Y+$YOffset+$YSize-$YSpace)-($Y+$YOffset+$YSpace))/2 + ($Y+$YOffset+$YSpace); + + $this->drawText($CenterX,$CenterY,$Caption,array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize)); + } + else + { + if ( $Serie["Data"][$Key] >= 0 ) { $Align = TEXT_ALIGN_MIDDLELEFT; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_MIDDLERIGHT; $Offset = -$DisplayOffset; } + $this->drawText($X2+$Offset,$Y+$YOffset+$YSize/2,$Caption,array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align,"FontSize"=>$DisplaySize)); + } + + $this->Shadow = $RestoreShadow; + } + } + $Y = $Y + $YStep; + $ID++; + } + } + $CurrentSerie++; + } + } + } + + /* Draw a bar chart */ + function drawStackedBarChart($Format=NULL) + { + $DisplayValues = isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE; + $DisplayOrientation = isset($Format["DisplayOrientation"]) ? $Format["DisplayOrientation"] : ORIENTATION_AUTO; + $DisplayRound = isset($Format["DisplayRound"]) ? $Format["DisplayRound"] : 0; + $DisplayColor = isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL; + $DisplayFont = isset($Format["DisplayFont"]) ? $Format["DisplayFont"] : $this->FontName; + $DisplaySize = isset($Format["DisplaySize"]) ? $Format["DisplaySize"] : $this->FontSize; + $DisplayR = isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0; + $DisplayG = isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0; + $DisplayB = isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0; + $Interleave = isset($Format["Interleave"]) ? $Format["Interleave"] : .5; + $Rounded = isset($Format["Rounded"]) ? $Format["Rounded"] : FALSE; + $RoundRadius = isset($Format["RoundRadius"]) ? $Format["RoundRadius"] : 4; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : -1; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : -1; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : -1; + $Gradient = isset($Format["Gradient"]) ? $Format["Gradient"] : FALSE; + $GradientMode = isset($Format["GradientMode"]) ? $Format["GradientMode"] : GRADIENT_SIMPLE; + $GradientAlpha = isset($Format["GradientAlpha"]) ? $Format["GradientAlpha"] : 20; + $GradientStartR = isset($Format["GradientStartR"]) ? $Format["GradientStartR"] : 255; + $GradientStartG = isset($Format["GradientStartG"]) ? $Format["GradientStartG"] : 255; + $GradientStartB = isset($Format["GradientStartB"]) ? $Format["GradientStartB"] : 255; + $GradientEndR = isset($Format["GradientEndR"]) ? $Format["GradientEndR"] : 0; + $GradientEndG = isset($Format["GradientEndG"]) ? $Format["GradientEndG"] : 0; + $GradientEndB = isset($Format["GradientEndB"]) ? $Format["GradientEndB"] : 0; + $InnerSurrounding = isset($Format["InnerSurrounding"]) ? $Format["InnerSurrounding"] : NULL; + $InnerBorderR = isset($Format["InnerBorderR"]) ? $Format["InnerBorderR"] : -1; + $InnerBorderG = isset($Format["InnerBorderG"]) ? $Format["InnerBorderG"] : -1; + $InnerBorderB = isset($Format["InnerBorderB"]) ? $Format["InnerBorderB"] : -1; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + $FontFactor = isset($Format["FontFactor"]) ? $Format["FontFactor"] : 8; + + $this->LastChartLayout = CHART_LAST_LAYOUT_STACKED; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + $RestoreShadow = $this->Shadow; + + $LastX = ""; $LastY = ""; + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; + if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = 255; $DisplayG = 255; $DisplayB = 255; } + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + if ( $InnerSurrounding != NULL ) { $InnerBorderR = $R+$InnerSurrounding; $InnerBorderG = $G+$InnerSurrounding; $InnerBorderB = $B+$InnerSurrounding; } + if ( $InnerBorderR == -1 ) { $InnerColor = NULL; } else { $InnerColor = array("R"=>$InnerBorderR,"G"=>$InnerBorderG,"B"=>$InnerBorderB); } + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; } + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]),TRUE); + $YZero = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"])); + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + $Color = array("TransCorner"=>TRUE,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB); + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; + + $XSize = ($XStep / (1+$Interleave) ); + $XOffset = -($XSize/2); + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $Height) + { + if ( $Height != VOID && $Serie["Data"][$Key] != 0 ) + { + if ( $Serie["Data"][$Key] > 0 ) { $Pos = "+"; } else { $Pos = "-"; } + + if ( !isset($LastY[$Key] ) ) { $LastY[$Key] = ""; } + if ( !isset($LastY[$Key][$Pos] ) ) { $LastY[$Key][$Pos] = $YZero; } + + $Y1 = $LastY[$Key][$Pos]; + $Y2 = $Y1 - $Height; + + if ( ($Rounded || $BorderR != -1) && ($Pos == "+" && $Y1 != $YZero) ) { $YSpaceUp = 1; } else { $YSpaceUp = 0; } + if ( ($Rounded || $BorderR != -1) && ($Pos == "-" && $Y1 != $YZero) ) { $YSpaceDown = 1; } else { $YSpaceDown = 0; } + + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X+$XOffset).",".floor($Y1-$YSpaceUp+$YSpaceDown).",".floor($X+$XOffset+$XSize).",".floor($Y2),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Rounded ) + $this->drawRoundedFilledRectangle($X+$XOffset,$Y1-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSize,$Y2,$RoundRadius,$Color); + else + { + $this->drawFilledRectangle($X+$XOffset,$Y1-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSize,$Y2,$Color); + + if ( $InnerColor != NULL ) { $RestoreShadow = $this->Shadow; $this->Shadow = FALSE; $this->drawRectangle(min($X+$XOffset+1,$X+$XOffset+$XSize),min($Y1-$YSpaceUp+$YSpaceDown,$Y2)+1,max($X+$XOffset+1,$X+$XOffset+$XSize)-1,max($Y1-$YSpaceUp+$YSpaceDown,$Y2)-1,$InnerColor); $this->Shadow = $RestoreShadow;} + + if ( $Gradient ) + { + $this->Shadow = FALSE; + + if ( $GradientMode == GRADIENT_SIMPLE ) + { + $GradientColor = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + $this->drawGradientArea($X+$XOffset,$Y1-1-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSize,$Y2+1,DIRECTION_VERTICAL,$GradientColor); + } + elseif ( $GradientMode == GRADIENT_EFFECT_CAN ) + { + $GradientColor1 = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha); + $GradientColor2 = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + $XSpan = floor($XSize / 3); + + $this->drawGradientArea($X+$XOffset-.5,$Y1-.5-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSpan,$Y2+.5,DIRECTION_HORIZONTAL,$GradientColor1); + $this->drawGradientArea($X+$XSpan+$XOffset-.5,$Y1-.5-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSize,$Y2+.5,DIRECTION_HORIZONTAL,$GradientColor2); + } + $this->Shadow = $RestoreShadow; + } + } + + if ( $DisplayValues ) + { + $BarHeight = abs($Y2-$Y1)-2; + $BarWidth = $XSize+($XOffset/2)-$FontFactor; + + $Caption = $this->scaleFormat(round($Serie["Data"][$Key],$DisplayRound),$Mode,$Format,$Unit); + $TxtPos = $this->getTextBox(0,0,$DisplayFont,$DisplaySize,0,$Caption); + $TxtHeight = abs($TxtPos[2]["Y"] - $TxtPos[0]["Y"]); + $TxtWidth = abs($TxtPos[1]["X"] - $TxtPos[0]["X"]); + + $XCenter = ( ($X+$XOffset+$XSize) - ($X+$XOffset) ) / 2 + $X+$XOffset; + $YCenter = ( ($Y2) - ($Y1-$YSpaceUp+$YSpaceDown) ) / 2 + $Y1-$YSpaceUp+$YSpaceDown; + + $Done = FALSE; + if ( $DisplayOrientation == ORIENTATION_HORIZONTAL || $DisplayOrientation == ORIENTATION_AUTO ) + { + if ( $TxtHeight < $BarHeight && $TxtWidth < $BarWidth ) + { + $this->drawText($XCenter,$YCenter,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"FontName"=>$DisplayFont)); + $Done = TRUE; + } + } + + if ( $DisplayOrientation == ORIENTATION_VERTICAL || ( $DisplayOrientation == ORIENTATION_AUTO && !$Done) ) + { + if ( $TxtHeight < $BarWidth && $TxtWidth < $BarHeight ) + $this->drawText($XCenter,$YCenter,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Angle"=>90,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"FontName"=>$DisplayFont)); + } + } + + $LastY[$Key][$Pos] = $Y2; + } + + $X = $X + $XStep; + } + } + else + { + if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; } + if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; } + + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; + + $YSize = $YStep / (1+$Interleave); + $YOffset = -($YSize/2); + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + foreach($PosArray as $Key => $Width) + { + if ( $Width != VOID && $Serie["Data"][$Key] != 0 ) + { + if ( $Serie["Data"][$Key] > 0 ) { $Pos = "+"; } else { $Pos = "-"; } + + if ( !isset($LastX[$Key] ) ) { $LastX[$Key] = ""; } + if ( !isset($LastX[$Key][$Pos] ) ) { $LastX[$Key][$Pos] = $YZero; } + + $X1 = $LastX[$Key][$Pos]; + $X2 = $X1 + $Width; + + if ( ($Rounded || $BorderR != -1) && ($Pos == "+" && $X1 != $YZero) ) { $XSpaceLeft = 2; } else { $XSpaceLeft = 0; } + if ( ($Rounded || $BorderR != -1) && ($Pos == "-" && $X1 != $YZero) ) { $XSpaceRight = 2; } else { $XSpaceRight = 0; } + + if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X1+$XSpaceLeft).",".floor($Y+$YOffset).",".floor($X2-$XSpaceRight).",".floor($Y+$YOffset+$YSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } + + if ( $Rounded ) + $this->drawRoundedFilledRectangle($X1+$XSpaceLeft,$Y+$YOffset,$X2-$XSpaceRight,$Y+$YOffset+$YSize,$RoundRadius,$Color); + else + { + $this->drawFilledRectangle($X1+$XSpaceLeft,$Y+$YOffset,$X2-$XSpaceRight,$Y+$YOffset+$YSize,$Color); + + if ( $InnerColor != NULL ) { $RestoreShadow = $this->Shadow; $this->Shadow = FALSE; $this->drawRectangle(min($X1+$XSpaceLeft,$X2-$XSpaceRight)+1,min($Y+$YOffset,$Y+$YOffset+$YSize)+1,max($X1+$XSpaceLeft,$X2-$XSpaceRight)-1,max($Y+$YOffset,$Y+$YOffset+$YSize)-1,$InnerColor); $this->Shadow = $RestoreShadow;} + + if ( $Gradient ) + { + $this->Shadow = FALSE; + + if ( $GradientMode == GRADIENT_SIMPLE ) + { + $GradientColor = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + $this->drawGradientArea($X1+$XSpaceLeft,$Y+$YOffset,$X2-$XSpaceRight,$Y+$YOffset+$YSize,DIRECTION_HORIZONTAL,$GradientColor); + } + elseif ( $GradientMode == GRADIENT_EFFECT_CAN ) + { + $GradientColor1 = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha); + $GradientColor2 = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha); + $YSpan = floor($YSize / 3); + + $this->drawGradientArea($X1+$XSpaceLeft,$Y+$YOffset,$X2-$XSpaceRight,$Y+$YOffset+$YSpan,DIRECTION_VERTICAL,$GradientColor1); + $this->drawGradientArea($X1+$XSpaceLeft,$Y+$YOffset+$YSpan,$X2-$XSpaceRight,$Y+$YOffset+$YSize,DIRECTION_VERTICAL,$GradientColor2); + } + $this->Shadow = $RestoreShadow; + } + } + + if ( $DisplayValues ) + { + $BarWidth = abs($X2-$X1)-$FontFactor; + $BarHeight = $YSize+($YOffset/2)-$FontFactor/2; + $Caption = $this->scaleFormat(round($Serie["Data"][$Key],$DisplayRound),$Mode,$Format,$Unit); + $TxtPos = $this->getTextBox(0,0,$DisplayFont,$DisplaySize,0,$Caption); + $TxtHeight = abs($TxtPos[2]["Y"] - $TxtPos[0]["Y"]); + $TxtWidth = abs($TxtPos[1]["X"] - $TxtPos[0]["X"]); + + $XCenter = ( $X2 - $X1 ) / 2 + $X1; + $YCenter = ( ($Y+$YOffset+$YSize) - ($Y+$YOffset) ) / 2 + $Y+$YOffset; + + $Done = FALSE; + if ( $DisplayOrientation == ORIENTATION_HORIZONTAL || $DisplayOrientation == ORIENTATION_AUTO ) + { + if ( $TxtHeight < $BarHeight && $TxtWidth < $BarWidth ) + { + $this->drawText($XCenter,$YCenter,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"FontName"=>$DisplayFont)); + $Done = TRUE; + } + } + + if ( $DisplayOrientation == ORIENTATION_VERTICAL || ( $DisplayOrientation == ORIENTATION_AUTO && !$Done) ) + { + if ( $TxtHeight < $BarWidth && $TxtWidth < $BarHeight ) + $this->drawText($XCenter,$YCenter,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Angle"=>90,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"FontName"=>$DisplayFont)); + } + } + + $LastX[$Key][$Pos] = $X2; + } + + $Y = $Y + $YStep; + } + } + } + } + } + + /* Draw a stacked area chart */ + function drawStackedAreaChart($Format=NULL) + { + $DrawLine = isset($Format["DrawLine"]) ? $Format["DrawLine"] : FALSE; + $LineSurrounding = isset($Format["LineSurrounding"]) ? $Format["LineSurrounding"] : NULL; + $LineR = isset($Format["LineR"]) ? $Format["LineR"] : VOID; + $LineG = isset($Format["LineG"]) ? $Format["LineG"] : VOID; + $LineB = isset($Format["LineB"]) ? $Format["LineB"] : VOID; + $LineAlpha = isset($Format["LineAlpha"]) ? $Format["LineAlpha"] : 100; + $DrawPlot = isset($Format["DrawPlot"]) ? $Format["DrawPlot"] : FALSE; + $PlotRadius = isset($Format["PlotRadius"]) ? $Format["PlotRadius"] : 2; + $PlotBorder = isset($Format["PlotBorder"]) ? $Format["PlotBorder"] : 1; + $PlotBorderSurrounding = isset($Format["PlotBorderSurrounding"]) ? $Format["PlotBorderSurrounding"] : NULL; + $PlotBorderR = isset($Format["PlotBorderR"]) ? $Format["PlotBorderR"] : 0; + $PlotBorderG = isset($Format["PlotBorderG"]) ? $Format["PlotBorderG"] : 0; + $PlotBorderB = isset($Format["PlotBorderB"]) ? $Format["PlotBorderB"] : 0; + $PlotBorderAlpha = isset($Format["PlotBorderAlpha"]) ? $Format["PlotBorderAlpha"] : 50; + $ForceTransparency = isset($Format["ForceTransparency"]) ? $Format["ForceTransparency"] : NULL; + + $this->LastChartLayout = CHART_LAST_LAYOUT_STACKED; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + $RestoreShadow = $this->Shadow; + $this->Shadow = FALSE; + + /* Build the offset data series */ + $OffsetData = ""; + $OverallOffset = ""; + $SerieOrder = ""; + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $SerieOrder[] = $SerieName; + + foreach($Serie["Data"] as $Key => $Value) + { + if ( $Value == VOID ) { $Value = 0; } + if ($Value >= 0) { $Sign = "+"; } else { $Sign = "-"; } + if ( !isset($OverallOffset[$Key]) || !isset($OverallOffset[$Key][$Sign]) ) { $OverallOffset[$Key][$Sign] = 0; } + + if ( $Sign == "+" ) + { $Data["Series"][$SerieName]["Data"][$Key] = $Value + $OverallOffset[$Key][$Sign]; } + else + { $Data["Series"][$SerieName]["Data"][$Key] = $Value - $OverallOffset[$Key][$Sign]; } + + $OverallOffset[$Key][$Sign] = $OverallOffset[$Key][$Sign] + abs($Value); + } + } + } + $SerieOrder = array_reverse($SerieOrder); + + $LastX = ""; $LastY = ""; + foreach($SerieOrder as $Key => $SerieName) + { + $Serie = $Data["Series"][$SerieName]; + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; + if ( $ForceTransparency != NULL ) { $Alpha = $ForceTransparency; } + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + + if ( $LineSurrounding != NULL ) + $LineColor = array("R"=>$R+$LineSurrounding,"G"=>$G+$LineSurrounding,"B"=>$B+$LineSurrounding,"Alpha"=>$Alpha); + elseif ( $LineR != VOID ) + $LineColor = array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha); + else + $LineColor = $Color; + + if ( $PlotBorderSurrounding != NULL ) + $PlotBorderColor = array("R"=>$R+$PlotBorderSurrounding,"G"=>$G+$PlotBorderSurrounding,"B"=>$B+$PlotBorderSurrounding,"Alpha"=>$PlotBorderAlpha); + else + $PlotBorderColor = array("R"=>$PlotBorderR,"G"=>$PlotBorderG,"B"=>$PlotBorderB,"Alpha"=>$PlotBorderAlpha); + + $AxisID = $Serie["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]),TRUE); + $YZero = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"])); + + $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; } + if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; } + + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + + $Plots = ""; $Plots[] = $X; $Plots[] = $YZero; + foreach($PosArray as $Key => $Height) + { + if ( $Height != VOID ) { $Plots[] = $X; $Plots[] = $YZero-$Height; } + $X = $X + $XStep; + } + $Plots[] = $X-$XStep; $Plots[] = $YZero; + + $this->drawPolygon($Plots,$Color); + + $this->Shadow = $RestoreShadow; + if ( $DrawLine ) { for($i=2; $i<=count($Plots)-6; $i=$i+2) { $this->drawLine($Plots[$i],$Plots[$i+1],$Plots[$i+2],$Plots[$i+3],$LineColor); } } + if ( $DrawPlot ) + { + for($i=2; $i<=count($Plots)-4; $i=$i+2) + { + if ( $PlotBorder != 0 ) + { $this->drawFilledCircle($Plots[$i],$Plots[$i+1],$PlotRadius+$PlotBorder,$PlotBorderColor); } + + $this->drawFilledCircle($Plots[$i],$Plots[$i+1],$PlotRadius,$Color); + } + } + $this->Shadow = FALSE; + } + elseif ( $Data["Orientation"] == SCALE_POS_TOPBOTTOM ) + { + if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; } + if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; } + + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + + $Plots = ""; $Plots[] = $YZero; $Plots[] = $Y; + foreach($PosArray as $Key => $Height) + { + if ( $Height != VOID ) { $Plots[] = $YZero+$Height; $Plots[] = $Y; } + $Y = $Y + $YStep; + } + $Plots[] = $YZero; $Plots[] = $Y-$YStep; + + $this->drawPolygon($Plots,$Color); + + $this->Shadow = $RestoreShadow; + if ( $DrawLine ) { for($i=2; $i<=count($Plots)-6; $i=$i+2) { $this->drawLine($Plots[$i],$Plots[$i+1],$Plots[$i+2],$Plots[$i+3],$LineColor); } } + if ( $DrawPlot ) + { + for($i=2; $i<=count($Plots)-4; $i=$i+2) + { + if ( $PlotBorder != 0 ) + { $this->drawFilledCircle($Plots[$i],$Plots[$i+1],$PlotRadius+$PlotBorder,$PlotBorderColor); } + + $this->drawFilledCircle($Plots[$i],$Plots[$i+1],$PlotRadius,$Color); + } + } + $this->Shadow = FALSE; + } + } + } + $this->Shadow = $RestoreShadow; + } + + /* Returns a random color */ + function getRandomColor($Alpha=100) + { return(array("R"=>rand(0,255),"G"=>rand(0,255),"B"=>rand(0,255),"Alpha"=>$Alpha)); } + + /* Validate a palette */ + function validatePalette($Colors,$Surrounding=NULL) + { + $Result = ""; + + if ( !is_array($Colors) ) { return($this->getRandomColor()); } + + foreach($Colors as $Key => $Values) + { + if ( isset($Values["R"]) ) { $Result[$Key]["R"] = $Values["R"]; } else { $Result[$Key]["R"] = rand(0,255); } + if ( isset($Values["G"]) ) { $Result[$Key]["G"] = $Values["G"]; } else { $Result[$Key]["G"] = rand(0,255); } + if ( isset($Values["B"]) ) { $Result[$Key]["B"] = $Values["B"]; } else { $Result[$Key]["B"] = rand(0,255); } + if ( isset($Values["Alpha"]) ) { $Result[$Key]["Alpha"] = $Values["Alpha"]; } else { $Result[$Key]["Alpha"] = 100; } + + if ( $Surrounding != NULL ) + { + $Result[$Key]["BorderR"] = $Result[$Key]["R"] + $Surrounding; + $Result[$Key]["BorderG"] = $Result[$Key]["G"] + $Surrounding; + $Result[$Key]["BorderB"] = $Result[$Key]["B"] + $Surrounding; + } + else + { + if ( isset($Values["BorderR"]) ) { $Result[$Key]["BorderR"] = $Values["BorderR"]; } else { $Result[$Key]["BorderR"] = $Result[$Key]["R"]; } + if ( isset($Values["BorderG"]) ) { $Result[$Key]["BorderG"] = $Values["BorderG"]; } else { $Result[$Key]["BorderG"] = $Result[$Key]["G"]; } + if ( isset($Values["BorderB"]) ) { $Result[$Key]["BorderB"] = $Values["BorderB"]; } else { $Result[$Key]["BorderB"] = $Result[$Key]["B"]; } + if ( isset($Values["BorderAlpha"]) ) { $Result[$Key]["BorderAlpha"] = $Values["BorderAlpha"]; } else { $Result[$Key]["BorderAlpha"] = $Result[$Key]["Alpha"]; } + } + } + + return($Result); + } + + /* Draw the derivative chart associated to the data series */ + function drawDerivative($Format=NULL) + { + $Offset = isset($Format["Offset"]) ? $Format["Offset"] : 10; + $SerieSpacing = isset($Format["SerieSpacing"]) ? $Format["SerieSpacing"] : 3; + $DerivativeHeight = isset($Format["DerivativeHeight"]) ? $Format["DerivativeHeight"] : 4; + $ShadedSlopeBox = isset($Format["ShadedSlopeBox"]) ? $Format["ShadedSlopeBox"] : FALSE; + $DrawBackground = isset($Format["DrawBackground"]) ? $Format["DrawBackground"] : TRUE; + $BackgroundR = isset($Format["BackgroundR"]) ? $Format["BackgroundR"] : 255; + $BackgroundG = isset($Format["BackgroundG"]) ? $Format["BackgroundG"] : 255; + $BackgroundB = isset($Format["BackgroundB"]) ? $Format["BackgroundB"] : 255; + $BackgroundAlpha = isset($Format["BackgroundAlpha"]) ? $Format["BackgroundAlpha"] : 20; + $DrawBorder = isset($Format["DrawBorder"]) ? $Format["DrawBorder"] : TRUE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 0; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 0; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 0; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : 100; + $Caption = isset($Format["Caption"]) ? $Format["Caption"] : TRUE; + $CaptionHeight = isset($Format["CaptionHeight"]) ? $Format["CaptionHeight"] : 10; + $CaptionWidth = isset($Format["CaptionWidth"]) ? $Format["CaptionWidth"] : 20; + $CaptionMargin = isset($Format["CaptionMargin"]) ? $Format["CaptionMargin"] : 4; + $CaptionLine = isset($Format["CaptionLine"]) ? $Format["CaptionLine"] : FALSE; + $CaptionBox = isset($Format["CaptionBox"]) ? $Format["CaptionBox"] : FALSE; + $CaptionBorderR = isset($Format["CaptionBorderR"]) ? $Format["CaptionBorderR"] : 0; + $CaptionBorderG = isset($Format["CaptionBorderG"]) ? $Format["CaptionBorderG"] : 0; + $CaptionBorderB = isset($Format["CaptionBorderB"]) ? $Format["CaptionBorderB"] : 0; + $CaptionFillR = isset($Format["CaptionFillR"]) ? $Format["CaptionFillR"] : 255; + $CaptionFillG = isset($Format["CaptionFillG"]) ? $Format["CaptionFillG"] : 255; + $CaptionFillB = isset($Format["CaptionFillB"]) ? $Format["CaptionFillB"] : 255; + $CaptionFillAlpha = isset($Format["CaptionFillAlpha"]) ? $Format["CaptionFillAlpha"] : 80; + $PositiveSlopeStartR = isset($Format["PositiveSlopeStartR"]) ? $Format["PositiveSlopeStartR"] : 184; + $PositiveSlopeStartG = isset($Format["PositiveSlopeStartG"]) ? $Format["PositiveSlopeStartG"] : 234; + $PositiveSlopeStartB = isset($Format["PositiveSlopeStartB"]) ? $Format["PositiveSlopeStartB"] : 88; + $PositiveSlopeEndR = isset($Format["PositiveSlopeStartR"]) ? $Format["PositiveSlopeStartR"] : 239; + $PositiveSlopeEndG = isset($Format["PositiveSlopeStartG"]) ? $Format["PositiveSlopeStartG"] : 31; + $PositiveSlopeEndB = isset($Format["PositiveSlopeStartB"]) ? $Format["PositiveSlopeStartB"] : 36; + $NegativeSlopeStartR = isset($Format["NegativeSlopeStartR"]) ? $Format["NegativeSlopeStartR"] : 184; + $NegativeSlopeStartG = isset($Format["NegativeSlopeStartG"]) ? $Format["NegativeSlopeStartG"] : 234; + $NegativeSlopeStartB = isset($Format["NegativeSlopeStartB"]) ? $Format["NegativeSlopeStartB"] : 88; + $NegativeSlopeEndR = isset($Format["NegativeSlopeStartR"]) ? $Format["NegativeSlopeStartR"] : 67; + $NegativeSlopeEndG = isset($Format["NegativeSlopeStartG"]) ? $Format["NegativeSlopeStartG"] : 124; + $NegativeSlopeEndB = isset($Format["NegativeSlopeStartB"]) ? $Format["NegativeSlopeStartB"] : 227; + + $Data = $this->DataSet->getData(); + + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + $YPos = $this->DataSet->Data["GraphArea"]["Y2"] + $Offset; + else + $XPos = $this->DataSet->Data["GraphArea"]["X2"] + $Offset; + + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"]; + + $AxisID = $Serie["Axis"]; + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $Caption ) + { + if ( $CaptionLine ) + { + $StartX = floor($this->GraphAreaX1-$CaptionWidth+$XMargin-$CaptionMargin); + $EndX = floor($this->GraphAreaX1-$CaptionMargin+$XMargin); + + $CaptionSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight); + if ( $CaptionBox ) { $this->drawFilledRectangle($StartX,$YPos,$EndX,$YPos+$CaptionHeight,array("R"=>$CaptionFillR,"G"=>$CaptionFillG,"B"=>$CaptionFillB,"BorderR"=>$CaptionBorderR,"BorderG"=>$CaptionBorderG,"BorderB"=>$CaptionBorderB,"Alpha"=>$CaptionFillAlpha)); } + $this->drawLine($StartX+2,$YPos+($CaptionHeight/2),$EndX-2,$YPos+($CaptionHeight/2),$CaptionSettings); + } + else + $this->drawFilledRectangle($this->GraphAreaX1-$CaptionWidth+$XMargin-$CaptionMargin,$YPos,$this->GraphAreaX1-$CaptionMargin+$XMargin,$YPos+$CaptionHeight,array("R"=>$R,"G"=>$G,"B"=>$B,"BorderR"=>$CaptionBorderR,"BorderG"=>$CaptionBorderG,"BorderB"=>$CaptionBorderB)); + } + + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; + + $TopY = $YPos + ($CaptionHeight/2) - ($DerivativeHeight/2); + $BottomY = $YPos + ($CaptionHeight/2) + ($DerivativeHeight/2); + + $StartX = floor($this->GraphAreaX1+$XMargin); + $EndX = floor($this->GraphAreaX2-$XMargin); + + if ( $DrawBackground ) { $this->drawFilledRectangle($StartX-1,$TopY-1,$EndX+1,$BottomY+1,array("R"=>$BackgroundR,"G"=>$BackgroundG,"B"=>$BackgroundB,"Alpha"=>$BackgroundAlpha)); } + if ( $DrawBorder ) { $this->drawRectangle($StartX-1,$TopY-1,$EndX+1,$BottomY+1,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); } + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + + $RestoreShadow = $this->Shadow; + $this->Shadow = FALSE; + + /* Determine the Max slope index */ + $LastX = NULL; $LastY = NULL; $MinSlope = 0; $MaxSlope = 1; + foreach($PosArray as $Key => $Y) + { + if ( $Y != VOID && $LastX != NULL ) + { $Slope = ($LastY - $Y); if ( $Slope > $MaxSlope ) { $MaxSlope = $Slope; } if ( $Slope < $MinSlope ) { $MinSlope = $Slope; } } + + if ( $Y == VOID ) + { $LastX = NULL; $LastY = NULL; } + else + { $LastX = $X; $LastY = $Y; } + } + + $LastX = NULL; $LastY = NULL; $LastColor = NULL; + foreach($PosArray as $Key => $Y) + { + if ( $Y != VOID && $LastY != NULL ) + { + $Slope = ($LastY - $Y); + + if ( $Slope >= 0 ) + { + $SlopeIndex = (100 / $MaxSlope) * $Slope; + $R = (($PositiveSlopeEndR - $PositiveSlopeStartR)/100)*$SlopeIndex+$PositiveSlopeStartR; + $G = (($PositiveSlopeEndG - $PositiveSlopeStartG)/100)*$SlopeIndex+$PositiveSlopeStartG; + $B = (($PositiveSlopeEndB - $PositiveSlopeStartB)/100)*$SlopeIndex+$PositiveSlopeStartB; + } + elseif ( $Slope < 0 ) + { + $SlopeIndex = (100 / abs($MinSlope)) * abs($Slope); + $R = (($NegativeSlopeEndR - $NegativeSlopeStartR)/100)*$SlopeIndex+$NegativeSlopeStartR; + $G = (($NegativeSlopeEndG - $NegativeSlopeStartG)/100)*$SlopeIndex+$NegativeSlopeStartG; + $B = (($NegativeSlopeEndB - $NegativeSlopeStartB)/100)*$SlopeIndex+$NegativeSlopeStartB; + } + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B); + + if ( $ShadedSlopeBox && $LastColor != NULL ) // && $Slope != 0 + { + $GradientSettings = array("StartR"=>$LastColor["R"],"StartG"=>$LastColor["G"],"StartB"=>$LastColor["B"],"EndR"=>$R,"EndG"=>$G,"EndB"=>$B); + $this->drawGradientArea($LastX,$TopY,$X,$BottomY,DIRECTION_HORIZONTAL,$GradientSettings); + } + elseif ( !$ShadedSlopeBox || $LastColor == NULL ) // || $Slope == 0 + $this->drawFilledRectangle(floor($LastX),$TopY,floor($X),$BottomY,$Color); + + $LastColor = $Color; + } + + if ( $Y == VOID ) + { $LastY = NULL; } + else + { $LastX = $X; $LastY = $Y; } + + $X = $X + $XStep; + } + + $YPos = $YPos + $CaptionHeight + $SerieSpacing; + } + else + { + if ( $Caption ) + { + $StartY = floor($this->GraphAreaY1-$CaptionWidth+$XMargin-$CaptionMargin); + $EndY = floor($this->GraphAreaY1-$CaptionMargin+$XMargin); + if ( $CaptionLine ) + { + $CaptionSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight); + if ( $CaptionBox ) { $this->drawFilledRectangle($XPos,$StartY,$XPos+$CaptionHeight,$EndY,array("R"=>$CaptionFillR,"G"=>$CaptionFillG,"B"=>$CaptionFillB,"BorderR"=>$CaptionBorderR,"BorderG"=>$CaptionBorderG,"BorderB"=>$CaptionBorderB,"Alpha"=>$CaptionFillAlpha)); } + $this->drawLine($XPos+($CaptionHeight/2),$StartY+2,$XPos+($CaptionHeight/2),$EndY-2,$CaptionSettings); + } + else + $this->drawFilledRectangle($XPos,$StartY,$XPos+$CaptionHeight,$EndY,array("R"=>$R,"G"=>$G,"B"=>$B,"BorderR"=>$CaptionBorderR,"BorderG"=>$CaptionBorderG,"BorderB"=>$CaptionBorderB)); + } + + + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $XStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; + + $TopX = $XPos + ($CaptionHeight/2) - ($DerivativeHeight/2); + $BottomX = $XPos + ($CaptionHeight/2) + ($DerivativeHeight/2); + + $StartY = floor($this->GraphAreaY1+$XMargin); + $EndY = floor($this->GraphAreaY2-$XMargin); + + if ( $DrawBackground ) { $this->drawFilledRectangle($TopX-1,$StartY-1,$BottomX+1,$EndY+1,array("R"=>$BackgroundR,"G"=>$BackgroundG,"B"=>$BackgroundB,"Alpha"=>$BackgroundAlpha)); } + if ( $DrawBorder ) { $this->drawRectangle($TopX-1,$StartY-1,$BottomX+1,$EndY+1,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); } + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + + $RestoreShadow = $this->Shadow; + $this->Shadow = FALSE; + + /* Determine the Max slope index */ + $LastX = NULL; $LastY = NULL; $MinSlope = 0; $MaxSlope = 1; + foreach($PosArray as $Key => $X) + { + if ( $X != VOID && $LastX != NULL ) + { $Slope = ($X - $LastX); if ( $Slope > $MaxSlope ) { $MaxSlope = $Slope; } if ( $Slope < $MinSlope ) { $MinSlope = $Slope; } } + + if ( $X == VOID ) + { $LastX = NULL; } + else + { $LastX = $X; } + } + + $LastX = NULL; $LastY = NULL; $LastColor = NULL; + foreach($PosArray as $Key => $X) + { + if ( $X != VOID && $LastX != NULL ) + { + $Slope = ($X - $LastX); + + if ( $Slope >= 0 ) + { + $SlopeIndex = (100 / $MaxSlope) * $Slope; + $R = (($PositiveSlopeEndR - $PositiveSlopeStartR)/100)*$SlopeIndex+$PositiveSlopeStartR; + $G = (($PositiveSlopeEndG - $PositiveSlopeStartG)/100)*$SlopeIndex+$PositiveSlopeStartG; + $B = (($PositiveSlopeEndB - $PositiveSlopeStartB)/100)*$SlopeIndex+$PositiveSlopeStartB; + } + elseif ( $Slope < 0 ) + { + $SlopeIndex = (100 / abs($MinSlope)) * abs($Slope); + $R = (($NegativeSlopeEndR - $NegativeSlopeStartR)/100)*$SlopeIndex+$NegativeSlopeStartR; + $G = (($NegativeSlopeEndG - $NegativeSlopeStartG)/100)*$SlopeIndex+$NegativeSlopeStartG; + $B = (($NegativeSlopeEndB - $NegativeSlopeStartB)/100)*$SlopeIndex+$NegativeSlopeStartB; + } + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B); + + if ( $ShadedSlopeBox && $LastColor != NULL ) + { + $GradientSettings = array("StartR"=>$LastColor["R"],"StartG"=>$LastColor["G"],"StartB"=>$LastColor["B"],"EndR"=>$R,"EndG"=>$G,"EndB"=>$B); + + $this->drawGradientArea($TopX,$LastY,$BottomX,$Y,DIRECTION_VERTICAL,$GradientSettings); + } + elseif ( !$ShadedSlopeBox || $LastColor == NULL ) + $this->drawFilledRectangle($TopX,floor($LastY),$BottomX,floor($Y),$Color); + + $LastColor = $Color; + } + + if ( $X == VOID ) + { $LastX = NULL; } + else + { $LastX = $X; $LastY = $Y; } + + $Y = $Y + $XStep; + } + + $XPos = $XPos + $CaptionHeight + $SerieSpacing; + } + + $this->Shadow = $RestoreShadow; + } + } + } + + /* Draw the line of best fit */ + function drawBestFit($Format="") + { + $OverrideTicks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL; + $OverrideR = isset($Format["R"]) ? $Format["R"] : VOID; + $OverrideG = isset($Format["G"]) ? $Format["G"] : VOID; + $OverrideB = isset($Format["B"]) ? $Format["B"] : VOID; + $OverrideAlpha = isset($Format["Alpha"]) ? $Format["Alpha"] : VOID; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + foreach($Data["Series"] as $SerieName => $Serie) + { + if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) + { + if ( $OverrideR != VOID && $OverrideG != VOID && $OverrideB != VOID ) { $R = $OverrideR; $G = $OverrideG; $B = $OverrideB; } else { $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; } + if ( $OverrideTicks == NULL ) { $Ticks = $Serie["Ticks"]; } else { $Ticks = $OverrideTicks; } + if ( $OverrideAlpha == VOID ) { $Alpha = $Serie["Color"]["Alpha"]; } else { $Alpha = $OverrideAlpha; } + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks); + + $AxisID = $Serie["Axis"]; + $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"])); + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $Sxy = 0; $Sx = 0; $Sy = 0; $Sxx = 0; + foreach($PosArray as $Key => $Y) + { + if ( $Y != VOID ) + { + $Sxy = $Sxy + $X*$Y; + $Sx = $Sx + $X; + $Sy = $Sy + $Y; + $Sxx = $Sxx + $X*$X; + } + + $X = $X + $XStep; + } + $n = count($this->DataSet->stripVOID($PosArray)); //$n = count($PosArray); + $M = (($n*$Sxy)-($Sx*$Sy)) / (($n*$Sxx)-($Sx*$Sx)); + $B = (($Sy)-($M*$Sx))/($n); + + $X1 = $this->GraphAreaX1 + $XMargin; + $Y1 = $M * $X1 + $B; + $X2 = $this->GraphAreaX2 - $XMargin; + $Y2 = $M * $X2 + $B; + + if ( $Y1 < $this->GraphAreaY1 ) { $X1 = $X1 + ($this->GraphAreaY1-$Y1); $Y1 = $this->GraphAreaY1; } + if ( $Y1 > $this->GraphAreaY2 ) { $X1 = $X1 + ($Y1-$this->GraphAreaY2); $Y1 = $this->GraphAreaY2; } + if ( $Y2 < $this->GraphAreaY1 ) { $X2 = $X2 - ($this->GraphAreaY1-$Y2); $Y2 = $this->GraphAreaY1; } + if ( $Y2 > $this->GraphAreaY2 ) { $X2 = $X2 - ($Y2-$this->GraphAreaY2); $Y2 = $this->GraphAreaY2; } + + $this->drawLine($X1,$Y1,$X2,$Y2,$Color); + } + else + { + if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin; + + if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; } + $Sxy = 0; $Sx = 0; $Sy = 0; $Sxx = 0; + foreach($PosArray as $Key => $X) + { + if ( $X != VOID ) + { + $Sxy = $Sxy + $X*$Y; + $Sx = $Sx + $Y; + $Sy = $Sy + $X; + $Sxx = $Sxx + $Y*$Y; + } + + $Y = $Y + $YStep; + } + $n = count($this->DataSet->stripVOID($PosArray)); //$n = count($PosArray); + $M = (($n*$Sxy)-($Sx*$Sy)) / (($n*$Sxx)-($Sx*$Sx)); + $B = (($Sy)-($M*$Sx))/($n); + + $Y1 = $this->GraphAreaY1 + $XMargin; + $X1 = $M * $Y1 + $B; + $Y2 = $this->GraphAreaY2 - $XMargin; + $X2 = $M * $Y2 + $B; + + if ( $X1 < $this->GraphAreaX1 ) { $Y1 = $Y1 + ($this->GraphAreaX1-$X1); $X1 = $this->GraphAreaX1; } + if ( $X1 > $this->GraphAreaX2 ) { $Y1 = $Y1 + ($X1-$this->GraphAreaX2); $X1 = $this->GraphAreaX2; } + if ( $X2 < $this->GraphAreaX1 ) { $Y2 = $Y2 - ($this->GraphAreaY1-$X2); $X2 = $this->GraphAreaX1; } + if ( $X2 > $this->GraphAreaX2 ) { $Y2 = $Y2 - ($X2-$this->GraphAreaX2); $X2 = $this->GraphAreaX2; } + + $this->drawLine($X1,$Y1,$X2,$Y2,$Color); + } + } + } + } + + /* Write labels */ + function writeLabel($SeriesName,$Indexes,$Format="") + { + $OverrideTitle = isset($Format["OverrideTitle"]) ? $Format["OverrideTitle"] : NULL; + $ForceLabels = isset($Format["ForceLabels"]) ? $Format["ForceLabels"] : NULL; + $DrawPoint = isset($Format["DrawPoint"]) ? $Format["DrawPoint"] : LABEL_POINT_BOX; + $DrawVerticalLine = isset($Format["DrawVerticalLine"]) ? $Format["DrawVerticalLine"] : FALSE; + $VerticalLineR = isset($Format["VerticalLineR"]) ? $Format["VerticalLineR"] : 0; + $VerticalLineG = isset($Format["VerticalLineG"]) ? $Format["VerticalLineG"] : 0; + $VerticalLineB = isset($Format["VerticalLineB"]) ? $Format["VerticalLineB"] : 0; + $VerticalLineAlpha = isset($Format["VerticalLineAlpha"]) ? $Format["VerticalLineAlpha"] : 40; + $VerticalLineTicks = isset($Format["VerticalLineTicks"]) ? $Format["VerticalLineTicks"] : 2; + + $Data = $this->DataSet->getData(); + list($XMargin,$XDivs) = $this->scaleGetXSettings(); + + if ( !is_array($Indexes) ) { $Index = $Indexes; $Indexes = ""; $Indexes[] = $Index; } + if ( !is_array($SeriesName) ) { $SerieName = $SeriesName; $SeriesName = ""; $SeriesName[] = $SerieName; } + if ( $ForceLabels != NULL && !is_array($ForceLabels) ) { $ForceLabel = $ForceLabels; $ForceLabels = ""; $ForceLabels[] = $ForceLabel; } + + foreach ($Indexes as $Key => $Index) + { + $Series = ""; + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; } + $X = $this->GraphAreaX1 + $XMargin + $Index * $XStep; + + if ( $DrawVerticalLine ) { $this->drawLine($X,$this->GraphAreaY1+$Data["YMargin"],$X,$this->GraphAreaY2-$Data["YMargin"],array("R"=>$VerticalLineR,"G"=>$VerticalLineG,"B"=>$VerticalLineB,"Alpha"=>$VerticalLineAlpha,"Ticks"=>$VerticalLineTicks)); } + + $MinY = $this->GraphAreaY2; + foreach ($SeriesName as $iKey => $SerieName) + { + if ( isset($Data["Series"][$SerieName]["Data"][$Index]) ) + { + $AxisID = $Data["Series"][$SerieName]["Axis"]; + + if ( $OverrideTitle != NULL) + $Description = $OverrideTitle; + elseif ( count($SeriesName) == 1 ) + { + if ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Index]) ) + $Description = $Data["Series"][$SerieName]["Description"]." - ".$Data["Series"][$Data["Abscissa"]]["Data"][$Index]; + else + $Description = $Data["Series"][$SerieName]["Description"]; + } + elseif ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Index]) ) + $Description = $Data["Series"][$Data["Abscissa"]]["Data"][$Index]; + + $AxisMode = $Data["Axis"][$AxisID]["Display"]; + $AxisFormat = $Data["Axis"][$AxisID]["Format"]; + $AxisUnit = $Data["Axis"][$AxisID]["Unit"]; + + $Serie = ""; + $Serie["R"] = $Data["Series"][$SerieName]["Color"]["R"]; + $Serie["G"] = $Data["Series"][$SerieName]["Color"]["G"]; + $Serie["B"] = $Data["Series"][$SerieName]["Color"]["B"]; + $Serie["Alpha"] = $Data["Series"][$SerieName]["Color"]["Alpha"]; + + if ( count($SeriesName) == 1 && isset($Data["Series"][$SerieName]["XOffset"]) ) + $SerieOffset = $Data["Series"][$SerieName]["XOffset"]; + else + $SerieOffset = 0; + + $Value = $Data["Series"][$SerieName]["Data"][$Index]; + if ( $Value == VOID ) { $Value = "NaN"; } + + if ( $ForceLabels != NULL ) + $Caption = isset($ForceLabels[$Key]) ? $ForceLabels[$Key] : "Not set"; + else + $Caption = $this->scaleFormat($Value,$AxisMode,$AxisFormat,$AxisUnit); + + if ( $this->LastChartLayout == CHART_LAST_LAYOUT_STACKED ) + { + if ( $Value >=0 ) { $LookFor = "+"; } else { $LookFor = "-"; } + + $Value = 0; $Done = FALSE; + foreach($Data["Series"] as $Name => $SerieLookup) + { + if ( $SerieLookup["isDrawable"] == TRUE && $Name != $Data["Abscissa"] && !$Done ) + { + if ( isset($Data["Series"][$Name]["Data"][$Index]) && $Data["Series"][$Name]["Data"][$Index] != VOID ) + { + if ($Data["Series"][$Name]["Data"][$Index] >= 0 && $LookFor == "+" ) { $Value = $Value + $Data["Series"][$Name]["Data"][$Index]; } + if ($Data["Series"][$Name]["Data"][$Index] < 0 && $LookFor == "-" ) { $Value = $Value - $Data["Series"][$Name]["Data"][$Index]; } + if ($Name == $SerieName ) { $Done = TRUE; } + } + } + } + } + + $X = floor($this->GraphAreaX1 + $XMargin + $Index * $XStep + $SerieOffset); + $Y = floor($this->scaleComputeY($Value,array("AxisID"=>$AxisID))); + + if ($Y < $MinY) { $MinY = $Y; } + + if ( $DrawPoint == LABEL_POINT_CIRCLE ) + $this->drawFilledCircle($X,$Y,3,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0)); + elseif ( $DrawPoint == LABEL_POINT_BOX ) + $this->drawFilledRectangle($X-2,$Y-2,$X+2,$Y+2,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0)); + + $Series[] = array("Format"=>$Serie,"Caption"=>$Caption); + } + } + $this->drawLabelBox($X,$MinY-3,$Description,$Series,$Format); + + } + else + { + if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $XStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; } + $Y = $this->GraphAreaY1 + $XMargin + $Index * $XStep; + + if ( $DrawVerticalLine ) { $this->drawLine($this->GraphAreaX1+$Data["YMargin"],$Y,$this->GraphAreaX2-$Data["YMargin"],$Y,array("R"=>$VerticalLineR,"G"=>$VerticalLineG,"B"=>$VerticalLineB,"Alpha"=>$VerticalLineAlpha,"Ticks"=>$VerticalLineTicks)); } + + $MinX = $this->GraphAreaX2; + foreach ($SeriesName as $Key => $SerieName) + { + if ( isset($Data["Series"][$SerieName]["Data"][$Index]) ) + { + $AxisID = $Data["Series"][$SerieName]["Axis"]; + + if ( $OverrideTitle != NULL) + $Description = $OverrideTitle; + elseif ( count($SeriesName) == 1 ) + { + if ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Index]) ) + $Description = $Data["Series"][$SerieName]["Description"]." - ".$Data["Series"][$Data["Abscissa"]]["Data"][$Index]; + else + $Description = $Data["Series"][$SerieName]["Description"]; + } + elseif ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Index]) ) + $Description = $Data["Series"][$Data["Abscissa"]]["Data"][$Index]; + + $AxisMode = $Data["Axis"][$AxisID]["Display"]; + $AxisFormat = $Data["Axis"][$AxisID]["Format"]; + $AxisUnit = $Data["Axis"][$AxisID]["Unit"]; + + $Serie = ""; + if ( isset($Data["Extended"]["Palette"][$Index] ) ) + { + $Serie["R"] = $Data["Extended"]["Palette"][$Index]["R"]; + $Serie["G"] = $Data["Extended"]["Palette"][$Index]["G"]; + $Serie["B"] = $Data["Extended"]["Palette"][$Index]["B"]; + $Serie["Alpha"] = $Data["Extended"]["Palette"][$Index]["Alpha"]; + } + else + { + $Serie["R"] = $Data["Series"][$SerieName]["Color"]["R"]; + $Serie["G"] = $Data["Series"][$SerieName]["Color"]["G"]; + $Serie["B"] = $Data["Series"][$SerieName]["Color"]["B"]; + $Serie["Alpha"] = $Data["Series"][$SerieName]["Color"]["Alpha"]; + } + + if ( count($SeriesName) == 1 && isset($Data["Series"][$SerieName]["XOffset"]) ) + $SerieOffset = $Data["Series"][$SerieName]["XOffset"]; + else + $SerieOffset = 0; + + $Value = $Data["Series"][$SerieName]["Data"][$Index]; + if ( $ForceLabels != NULL ) + $Caption = isset($ForceLabels[$Key]) ? $ForceLabels[$Key] : "Not set"; + else + $Caption = $this->scaleFormat($Value,$AxisMode,$AxisFormat,$AxisUnit); + if ( $Value == VOID ) { $Value = "NaN"; } + + if ( $this->LastChartLayout == CHART_LAST_LAYOUT_STACKED ) + { + if ( $Value >=0 ) { $LookFor = "+"; } else { $LookFor = "-"; } + + $Value = 0; $Done = FALSE; + foreach($Data["Series"] as $Name => $SerieLookup) + { + if ( $SerieLookup["isDrawable"] == TRUE && $Name != $Data["Abscissa"] && !$Done ) + { + if ( isset($Data["Series"][$Name]["Data"][$Index]) && $Data["Series"][$Name]["Data"][$Index] != VOID ) + { + if ($Data["Series"][$Name]["Data"][$Index] >= 0 && $LookFor == "+" ) { $Value = $Value + $Data["Series"][$Name]["Data"][$Index]; } + if ($Data["Series"][$Name]["Data"][$Index] < 0 && $LookFor == "-" ) { $Value = $Value - $Data["Series"][$Name]["Data"][$Index]; } + if ($Name == $SerieName ) { $Done = TRUE; } + } + } + } + } + + $X = floor($this->scaleComputeY($Value,array("AxisID"=>$AxisID))); + $Y = floor($this->GraphAreaY1 + $XMargin + $Index * $XStep + $SerieOffset); + + if ($X < $MinX) { $MinX = $X; } + + if ( $DrawPoint == LABEL_POINT_CIRCLE ) + $this->drawFilledCircle($X,$Y,3,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0)); + elseif ( $DrawPoint == LABEL_POINT_BOX ) + $this->drawFilledRectangle($X-2,$Y-2,$X+2,$Y+2,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0)); + + $Series[] = array("Format"=>$Serie,"Caption"=>$Caption); + } + } + $this->drawLabelBox($MinX,$Y-3,$Description,$Series,$Format); + + } + } + } + + /* Draw a label box */ + function drawLabelBox($X,$Y,$Title,$Captions,$Format="") + { + $NoTitle = isset($Format["NoTitle"]) ? $Format["NoTitle"] : NULL; + $BoxWidth = isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 50; + $DrawSerieColor = isset($Format["DrawSerieColor"]) ? $Format["DrawSerieColor"] : TRUE; + $SerieR = isset($Format["SerieR"]) ? $Format["SerieR"] : NULL; + $SerieG = isset($Format["SerieG"]) ? $Format["SerieG"] : NULL; + $SerieB = isset($Format["SerieB"]) ? $Format["SerieB"] : NULL; + $SerieAlpha = isset($Format["SerieAlpha"]) ? $Format["SerieAlpha"] : NULL; + $SerieBoxSize = isset($Format["SerieBoxSize"]) ? $Format["SerieBoxSize"] : 6; + $SerieBoxSpacing = isset($Format["SerieBoxSpacing"]) ? $Format["SerieBoxSpacing"] : 4; + $VerticalMargin = isset($Format["VerticalMargin"]) ? $Format["VerticalMargin"] : 10; + $HorizontalMargin = isset($Format["HorizontalMargin"]) ? $Format["HorizontalMargin"] : 8; + $R = isset($Format["R"]) ? $Format["R"] : $this->FontColorR; + $G = isset($Format["G"]) ? $Format["G"] : $this->FontColorG; + $B = isset($Format["B"]) ? $Format["B"] : $this->FontColorB; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : $this->FontColorA; + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize; + $TitleMode = isset($Format["TitleMode"]) ? $Format["TitleMode"] : LABEL_TITLE_NOBACKGROUND; + $TitleR = isset($Format["TitleR"]) ? $Format["TitleR"] : $R; + $TitleG = isset($Format["TitleG"]) ? $Format["TitleG"] : $G; + $TitleB = isset($Format["TitleB"]) ? $Format["TitleB"] : $B; + $TitleBackgroundR = isset($Format["TitleBackgroundR"]) ? $Format["TitleBackgroundR"] : 0; + $TitleBackgroundG = isset($Format["TitleBackgroundG"]) ? $Format["TitleBackgroundG"] : 0; + $TitleBackgroundB = isset($Format["TitleBackgroundB"]) ? $Format["TitleBackgroundB"] : 0; + $GradientStartR = isset($Format["GradientStartR"]) ? $Format["GradientStartR"] : 255; + $GradientStartG = isset($Format["GradientStartG"]) ? $Format["GradientStartG"] : 255; + $GradientStartB = isset($Format["GradientStartB"]) ? $Format["GradientStartB"] : 255; + $GradientEndR = isset($Format["GradientEndR"]) ? $Format["GradientEndR"] : 220; + $GradientEndG = isset($Format["GradientEndG"]) ? $Format["GradientEndG"] : 220; + $GradientEndB = isset($Format["GradientEndB"]) ? $Format["GradientEndB"] : 220; + + if ( !$DrawSerieColor ) { $SerieBoxSize = 0; $SerieBoxSpacing = 0; } + + $TxtPos = $this->getTextBox($X,$Y,$FontName,$FontSize,0,$Title); + $TitleWidth = ($TxtPos[1]["X"] - $TxtPos[0]["X"])+$VerticalMargin*2; + $TitleHeight = ($TxtPos[0]["Y"] - $TxtPos[2]["Y"]); + + if ( $NoTitle ) { $TitleWidth = 0; $TitleHeight = 0; } + + $CaptionWidth = 0; $CaptionHeight = -$HorizontalMargin; + foreach($Captions as $Key =>$Caption) + { + $TxtPos = $this->getTextBox($X,$Y,$FontName,$FontSize,0,$Caption["Caption"]); + $CaptionWidth = max($CaptionWidth,($TxtPos[1]["X"] - $TxtPos[0]["X"])+$VerticalMargin*2); + $CaptionHeight = $CaptionHeight + max(($TxtPos[0]["Y"] - $TxtPos[2]["Y"]),($SerieBoxSize+2)) + $HorizontalMargin; + } + + if ( $CaptionHeight <= 5 ) { $CaptionHeight = $CaptionHeight + $HorizontalMargin/2; } + + if ( $DrawSerieColor ) { $CaptionWidth = $CaptionWidth + $SerieBoxSize + $SerieBoxSpacing; } + + $BoxWidth = max($BoxWidth,$TitleWidth,$CaptionWidth); + + $XMin = $X - 5 - floor(($BoxWidth-10) / 2); + $XMax = $X + 5 + floor(($BoxWidth-10) / 2); + + $RestoreShadow = $this->Shadow; + if ( $this->Shadow == TRUE ) + { + $this->Shadow = FALSE; + + $Poly = ""; + $Poly[] = $X+$this->ShadowX; $Poly[] = $Y+$this->ShadowX; + $Poly[] = $X+5+$this->ShadowX; $Poly[] = $Y-5+$this->ShadowX; + $Poly[] = $XMax+$this->ShadowX; $Poly[] = $Y-5+$this->ShadowX; + + if ( $NoTitle ) + { + $Poly[] = $XMax+$this->ShadowX; $Poly[] = $Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2+$this->ShadowX; + $Poly[] = $XMin+$this->ShadowX; $Poly[] = $Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2+$this->ShadowX; + } + else + { + $Poly[] = $XMax+$this->ShadowX; $Poly[] = $Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3+$this->ShadowX; + $Poly[] = $XMin+$this->ShadowX; $Poly[] = $Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3+$this->ShadowX; + } + + $Poly[] = $XMin+$this->ShadowX; $Poly[] = $Y-5+$this->ShadowX; + $Poly[] = $X-5+$this->ShadowX; $Poly[] = $Y-5+$this->ShadowX; + $this->drawPolygon($Poly,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa)); + } + + /* Draw the background */ + $GradientSettings = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB); + if ( $NoTitle ) + $this->drawGradientArea($XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax,$Y-6,DIRECTION_VERTICAL,$GradientSettings); + else + $this->drawGradientArea($XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax,$Y-6,DIRECTION_VERTICAL,$GradientSettings); + $Poly = ""; $Poly[] = $X; $Poly[] = $Y; $Poly[] = $X-5; $Poly[] = $Y-5; $Poly[] = $X+5; $Poly[] = $Y-5; + $this->drawPolygon($Poly,array("R"=>$GradientEndR,"G"=>$GradientEndG,"B"=>$GradientEndB,"NoBorder"=>TRUE)); + + /* Outer border */ + $OuterBorderColor = $this->allocateColor($this->Picture,100,100,100,100); + imageline($this->Picture,$XMin,$Y-5,$X-5,$Y-5,$OuterBorderColor); + imageline($this->Picture,$X,$Y,$X-5,$Y-5,$OuterBorderColor); + imageline($this->Picture,$X,$Y,$X+5,$Y-5,$OuterBorderColor); + imageline($this->Picture,$X+5,$Y-5,$XMax,$Y-5,$OuterBorderColor); + if ( $NoTitle ) + { + imageline($this->Picture,$XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMin,$Y-5,$OuterBorderColor); + imageline($this->Picture,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax,$Y-5,$OuterBorderColor); + imageline($this->Picture,$XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$OuterBorderColor); + } + else + { + imageline($this->Picture,$XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMin,$Y-5,$OuterBorderColor); + imageline($this->Picture,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax,$Y-5,$OuterBorderColor); + imageline($this->Picture,$XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$OuterBorderColor); + } + + /* Inner border */ + $InnerBorderColor = $this->allocateColor($this->Picture,255,255,255,100); + imageline($this->Picture,$XMin+1,$Y-6,$X-5,$Y-6,$InnerBorderColor); + imageline($this->Picture,$X,$Y-1,$X-5,$Y-6,$InnerBorderColor); + imageline($this->Picture,$X,$Y-1,$X+5,$Y-6,$InnerBorderColor); + imageline($this->Picture,$X+5,$Y-6,$XMax-1,$Y-6,$InnerBorderColor); + if ( $NoTitle ) + { + imageline($this->Picture,$XMin+1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMin+1,$Y-6,$InnerBorderColor); + imageline($this->Picture,$XMax-1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax-1,$Y-6,$InnerBorderColor); + imageline($this->Picture,$XMin+1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax-1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$InnerBorderColor); + } + else + { + imageline($this->Picture,$XMin+1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMin+1,$Y-6,$InnerBorderColor); + imageline($this->Picture,$XMax-1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax-1,$Y-6,$InnerBorderColor); + imageline($this->Picture,$XMin+1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax-1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$InnerBorderColor); + } + + /* Draw the separator line */ + if ( $TitleMode == LABEL_TITLE_NOBACKGROUND && !$NoTitle ) + { + $YPos = $Y-7-$CaptionHeight-$HorizontalMargin-$HorizontalMargin/2; + $XMargin = $VerticalMargin / 2; + $this->drawLine($XMin+$XMargin,$YPos+1,$XMax-$XMargin,$YPos+1,array("R"=>$GradientEndR,"G"=>$GradientEndG,"B"=>$GradientEndB)); + $this->drawLine($XMin+$XMargin,$YPos,$XMax-$XMargin,$YPos,array("R"=>$GradientStartR,"G"=>$GradientStartG,"B"=>$GradientStartB)); + } + elseif ( $TitleMode == LABEL_TITLE_BACKGROUND ) + { + $this->drawFilledRectangle($XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin+$HorizontalMargin/2,array("R"=>$TitleBackgroundR,"G"=>$TitleBackgroundG,"B"=>$TitleBackgroundB)); + imageline($this->Picture,$XMin+1,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin+$HorizontalMargin/2+1,$XMax-1,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin+$HorizontalMargin/2+1,$InnerBorderColor); + } + + /* Write the description */ + if ( !$NoTitle ) + $this->drawText($XMin+$VerticalMargin,$Y-7-$CaptionHeight-$HorizontalMargin*2,$Title,array("Align"=>TEXT_ALIGN_BOTTOMLEFT,"R"=>$TitleR,"G"=>$TitleG,"B"=>$TitleB)); + + /* Write the value */ + $YPos = $Y-5-$HorizontalMargin; $XPos = $XMin+$VerticalMargin+$SerieBoxSize+$SerieBoxSpacing; + foreach($Captions as $Key => $Caption) + { + $CaptionTxt = $Caption["Caption"]; + $TxtPos = $this->getTextBox($XPos,$YPos,$FontName,$FontSize,0,$CaptionTxt); + $CaptionHeight = ($TxtPos[0]["Y"] - $TxtPos[2]["Y"]); + + /* Write the serie color if needed */ + if ( $DrawSerieColor ) + { + $BoxSettings = array("R"=>$Caption["Format"]["R"],"G"=>$Caption["Format"]["G"],"B"=>$Caption["Format"]["B"],"Alpha"=>$Caption["Format"]["Alpha"],"BorderR"=>0,"BorderG"=>0,"BorderB"=>0); + $this->drawFilledRectangle($XMin+$VerticalMargin,$YPos-$SerieBoxSize,$XMin+$VerticalMargin+$SerieBoxSize,$YPos,$BoxSettings); + } + + $this->drawText($XPos,$YPos,$CaptionTxt,array("Align"=>TEXT_ALIGN_BOTTOMLEFT)); + + $YPos = $YPos - $CaptionHeight - $HorizontalMargin; + } + + $this->Shadow = $RestoreShadow; + } + + /* Draw a basic shape */ + function drawShape($X,$Y,$Shape,$PlotSize,$PlotBorder,$BorderSize,$R,$G,$B,$Alpha,$BorderR,$BorderG,$BorderB,$BorderAlpha) + { + if ( $Shape == SERIE_SHAPE_FILLEDCIRCLE ) + { + if ( $PlotBorder ) { $this->drawFilledCircle($X,$Y,$PlotSize+$BorderSize,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); } + $this->drawFilledCircle($X,$Y,$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + } + elseif ( $Shape == SERIE_SHAPE_FILLEDSQUARE ) + { + if ( $PlotBorder ) { $this->drawFilledRectangle($X-$PlotSize-$BorderSize,$Y-$PlotSize-$BorderSize,$X+$PlotSize+$BorderSize,$Y+$PlotSize+$BorderSize,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); } + $this->drawFilledRectangle($X-$PlotSize,$Y-$PlotSize,$X+$PlotSize,$Y+$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + } + elseif ( $Shape == SERIE_SHAPE_FILLEDTRIANGLE ) + { + if ( $PlotBorder ) + { + $Pos = ""; $Pos[]=$X; $Pos[]=$Y-$PlotSize-$BorderSize; $Pos[]=$X-$PlotSize-$BorderSize; $Pos[]=$Y+$PlotSize+$BorderSize; $Pos[]=$X+$PlotSize+$BorderSize; $Pos[]=$Y+$PlotSize+$BorderSize; + $this->drawPolygon($Pos,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); + } + + $Pos = ""; $Pos[]=$X; $Pos[]=$Y-$PlotSize; $Pos[]=$X-$PlotSize; $Pos[]=$Y+$PlotSize; $Pos[]=$X+$PlotSize; $Pos[]=$Y+$PlotSize; + $this->drawPolygon($Pos,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + } + elseif ( $Shape == SERIE_SHAPE_TRIANGLE ) + { + $this->drawLine($X,$Y-$PlotSize,$X-$PlotSize,$Y+$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + $this->drawLine($X-$PlotSize,$Y+$PlotSize,$X+$PlotSize,$Y+$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + $this->drawLine($X+$PlotSize,$Y+$PlotSize,$X,$Y-$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + } + elseif ( $Shape == SERIE_SHAPE_SQUARE ) + $this->drawRectangle($X-$PlotSize,$Y-$PlotSize,$X+$PlotSize,$Y+$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + elseif ( $Shape == SERIE_SHAPE_CIRCLE ) + $this->drawCircle($X,$Y,$PlotSize,$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + elseif ( $Shape == SERIE_SHAPE_DIAMOND ) + { + $Pos = ""; $Pos[]=$X-$PlotSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y-$PlotSize; $Pos[]=$X+$PlotSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y+$PlotSize; + $this->drawPolygon($Pos,array("NoFill"=>TRUE,"BorderR"=>$R,"BorderG"=>$G,"BorderB"=>$B,"BorderAlpha"=>$Alpha)); + } + elseif ( $Shape == SERIE_SHAPE_FILLEDDIAMOND ) + { + if ( $PlotBorder ) + { + $Pos = ""; $Pos[]=$X-$PlotSize-$BorderSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y-$PlotSize-$BorderSize; $Pos[]=$X+$PlotSize+$BorderSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y+$PlotSize+$BorderSize; + $this->drawPolygon($Pos,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); + } + + $Pos = ""; $Pos[]=$X-$PlotSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y-$PlotSize; $Pos[]=$X+$PlotSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y+$PlotSize; + $this->drawPolygon($Pos,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + } + } + + function drawPolygonChart($Points,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $NoFill = isset($Format["NoFill"]) ? $Format["NoFill"] : FALSE; + $NoBorder = isset($Format["NoBorder"]) ? $Format["NoBorder"] : FALSE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha / 2; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $Threshold = isset($Format["Threshold"]) ? $Format["Threshold"] : NULL; + + if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; } + + $RestoreShadow = $this->Shadow; + $this->Shadow = FALSE; + + $AllIntegers = TRUE; + for($i=0;$i<=count($Points)-2;$i=$i+2) + { if ( $this->getFirstDecimal($Points[$i+1]) != 0 ) { $AllIntegers = FALSE; } } + + /* Convert polygon to segments */ + $Segments = ""; + for($i=2;$i<=count($Points)-2;$i=$i+2) + { $Segments[] = array("X1"=>$Points[$i-2],"Y1"=>$Points[$i-1],"X2"=>$Points[$i],"Y2"=>$Points[$i+1]); } + $Segments[] = array("X1"=>$Points[$i-2],"Y1"=>$Points[$i-1],"X2"=>$Points[0],"Y2"=>$Points[1]); + + /* Simplify straight lines */ + $Result = ""; $inHorizon = FALSE; $LastX = VOID; + foreach($Segments as $Key => $Pos) + { + if ( $Pos["Y1"] != $Pos["Y2"] ) + { + if ( $inHorizon ) { $inHorizon = FALSE; $Result[] = array("X1"=>$LastX,"Y1"=>$Pos["Y1"],"X2"=>$Pos["X1"],"Y2"=>$Pos["Y1"]); } + + $Result[] = array("X1"=>$Pos["X1"],"Y1"=>$Pos["Y1"],"X2"=>$Pos["X2"],"Y2"=>$Pos["Y2"]); + } + else { if ( !$inHorizon ) { $inHorizon = TRUE; $LastX = $Pos["X1"];} } + } + $Segments = $Result; + + /* Do we have something to draw */ + if ( $Segments == "" ) { return(0); } + + /* For segments debugging purpose */ + //foreach($Segments as $Key => $Pos) + // echo $Pos["X1"].",".$Pos["Y1"].",".$Pos["X2"].",".$Pos["Y2"]."\r\n"; + + /* Find out the min & max Y boundaries */ + $MinY = OUT_OF_SIGHT; $MaxY = OUT_OF_SIGHT; + foreach($Segments as $Key => $Coords) + { + if ( $MinY == OUT_OF_SIGHT || $MinY > min($Coords["Y1"],$Coords["Y2"]) ) { $MinY = min($Coords["Y1"],$Coords["Y2"]); } + if ( $MaxY == OUT_OF_SIGHT || $MaxY < max($Coords["Y1"],$Coords["Y2"]) ) { $MaxY = max($Coords["Y1"],$Coords["Y2"]); } + } + + if ( $AllIntegers ) { $YStep = 1; } else { $YStep = .5; } + + $MinY = floor($MinY); $MaxY = floor($MaxY); + + /* Scan each Y lines */ + $DefaultColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + $DebugLine = 0; $DebugColor = $this->allocateColor($this->Picture,255,0,0,100); + + $MinY = floor($MinY); $MaxY = floor($MaxY); $YStep = 1; + + if ( !$NoFill ) + { + //if ( $DebugLine ) { $MinY = $DebugLine; $MaxY = $DebugLine; } + for($Y=$MinY;$Y<=$MaxY;$Y=$Y+$YStep) + { + $Intersections = ""; $LastSlope = NULL; $RestoreLast = "-"; + foreach($Segments as $Key => $Coords) + { + $X1 = $Coords["X1"]; $X2 = $Coords["X2"]; $Y1 = $Coords["Y1"]; $Y2 = $Coords["Y2"]; + + if ( min($Y1,$Y2) <= $Y && max($Y1,$Y2) >= $Y ) + { + if ( $Y1 == $Y2 ) + { $X = $X1; } + else + { $X = $X1 + ( ($Y-$Y1)*$X2 - ($Y-$Y1)*$X1 ) / ($Y2-$Y1); } + + $X = floor($X); + + if ( $X2 == $X1 ) + { $Slope = "!"; } + else + { + $SlopeC = ($Y2 - $Y1) / ($X2 - $X1); + if( $SlopeC == 0 ) + { $Slope = "="; } + elseif( $SlopeC > 0 ) + { $Slope = "+"; } + elseif ( $SlopeC < 0 ) + { $Slope = "-"; } + } + + if ( !is_array($Intersections) ) + { $Intersections[] = $X; } + elseif( !in_array($X,$Intersections) ) + { $Intersections[] = $X; } + elseif( in_array($X,$Intersections) ) + { + if ($Y == $DebugLine) { echo $Slope."/".$LastSlope."(".$X.") "; } + + if ( $Slope == "=" && $LastSlope == "-" ) { $Intersections[] = $X; } + if ( $Slope != $LastSlope && $LastSlope != "!" && $LastSlope != "=" ) { $Intersections[] = $X; } + if ( $Slope != $LastSlope && $LastSlope == "!" && $Slope == "+" ) { $Intersections[] = $X; } + } + + if ( is_array($Intersections) && in_array($X,$Intersections) && $LastSlope == "=" && ($Slope == "-" )) { $Intersections[] = $X; } + + $LastSlope = $Slope; + } + } + if ( $RestoreLast != "-" ) { $Intersections[] = $RestoreLast; echo "@".$Y."\r\n"; } + + if ( is_array($Intersections) ) + { + sort($Intersections); + + if ($Y == $DebugLine) { print_r($Intersections); } + + /* Remove NULL plots */ + $Result = ""; + for($i=0;$i<=count($Intersections)-1;$i=$i+2) + { + if ( isset($Intersections[$i+1]) ) + { if ( $Intersections[$i] != $Intersections[$i+1] ) { $Result[] = $Intersections[$i]; $Result[] = $Intersections[$i+1]; } } + } + + if ( is_array($Result) ) + { + $Intersections = $Result; + + $LastX = OUT_OF_SIGHT; + foreach($Intersections as $Key => $X) + { + if ( $LastX == OUT_OF_SIGHT ) + $LastX = $X; + elseif ( $LastX != OUT_OF_SIGHT ) + { + if ( $this->getFirstDecimal($LastX) > 1 ) { $LastX++; } + + $Color = $DefaultColor; + if ( $Threshold != NULL ) + { + foreach($Threshold as $Key => $Parameters) + { + if ( $Y <= $Parameters["MinX"] && $Y >= $Parameters["MaxX"]) + { + if ( isset($Parameters["R"]) ) { $R = $Parameters["R"]; } else { $R = 0; } + if ( isset($Parameters["G"]) ) { $G = $Parameters["G"]; } else { $G = 0; } + if ( isset($Parameters["B"]) ) { $B = $Parameters["B"]; } else { $B = 0; } + if ( isset($Parameters["Alpha"]) ) { $Alpha = $Parameters["Alpha"]; } else { $Alpha = 100; } + $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha); + } + } + } + + imageline($this->Picture,$LastX,$Y,$X,$Y,$Color); + + if ( $Y == $DebugLine) { imageline($this->Picture,$LastX,$Y,$X,$Y,$DebugColor); } + + $LastX = OUT_OF_SIGHT; + } + } + } + } + } + } + + /* Draw the polygon border, if required */ + if ( !$NoBorder) + { + foreach($Segments as $Key => $Coords) + $this->drawLine($Coords["X1"],$Coords["Y1"],$Coords["X2"],$Coords["Y2"],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Threshold"=>$Threshold)); + } + + $this->Shadow = $RestoreShadow; + } + + /* Return the abscissa margin */ + function getAbscissaMargin($Data) + { + foreach($Data["Axis"] as $AxisID => $Values) { if ( $Values["Identity"] == AXIS_X ) { return($Values["Margin"]); } } + return(0); + } + + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/class/pImage.class.php b/trunk/includes/pChart/class/pImage.class.php new file mode 100644 index 0000000..27b262e --- /dev/null +++ b/trunk/includes/pChart/class/pImage.class.php @@ -0,0 +1,472 @@ +TransparentBackground = $TransparentBackground; + + if ( $DataSet != NULL ) { $this->DataSet = $DataSet; } + + $this->XSize = $XSize; + $this->YSize = $YSize; + $this->Picture = imagecreatetruecolor($XSize,$YSize); + + if ( $this->TransparentBackground ) + { + imagealphablending($this->Picture,FALSE); + imagefilledrectangle($this->Picture, 0,0,$XSize, $YSize, imagecolorallocatealpha($this->Picture, 255, 255, 255, 127)); + imagealphablending($this->Picture,TRUE); + imagesavealpha($this->Picture,true); + } + else + { + $C_White = $this->AllocateColor($this->Picture,255,255,255); + imagefilledrectangle($this->Picture,0,0,$XSize,$YSize,$C_White); + } + } + + /* Enable / Disable and set shadow properties */ + function setShadow($Enabled=TRUE,$Format="") + { + $X = isset($Format["X"]) ? $Format["X"] : 2; + $Y = isset($Format["Y"]) ? $Format["Y"] : 2; + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 10; + + $this->Shadow = $Enabled; + $this->ShadowX = $X; + $this->ShadowY = $Y; + $this->ShadowR = $R; + $this->ShadowG = $G; + $this->ShadowB = $B; + $this->Shadowa = $Alpha; + } + + /* Set the graph area position */ + function setGraphArea($X1,$Y1,$X2,$Y2) + { + if ( $X2 < $X1 || $X1 == $X2 || $Y2 < $Y1 || $Y1 == $Y2 ) { return(-1); } + + $this->GraphAreaX1 = $X1; $this->DataSet->Data["GraphArea"]["X1"] = $X1; + $this->GraphAreaY1 = $Y1; $this->DataSet->Data["GraphArea"]["Y1"] = $Y1; + $this->GraphAreaX2 = $X2; $this->DataSet->Data["GraphArea"]["X2"] = $X2; + $this->GraphAreaY2 = $Y2; $this->DataSet->Data["GraphArea"]["Y2"] = $Y2; + } + + /* Return the width of the picture */ + function getWidth() + { return($this->XSize); } + + /* Return the heigth of the picture */ + function getHeight() + { return($this->YSize); } + + /* Render the picture to a file */ + function render($FileName) + { + if ( $this->TransparentBackground ) { imagealphablending($this->Picture,false); imagesavealpha($this->Picture,true); } + imagepng($this->Picture,$FileName); + } + + /* Render the picture to a web browser stream */ + function stroke($BrowserExpire=FALSE) + { + if ( $this->TransparentBackground ) { imagealphablending($this->Picture,false); imagesavealpha($this->Picture,true); } + + if ( $BrowserExpire ) + { + header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); + header("Cache-Control: no-cache"); + header("Pragma: no-cache"); + } + + header('Content-type: image/png'); + imagepng($this->Picture); + } + + /* Automatic output method based on the calling interface */ + function autoOutput($FileName="output.png") + { + if (php_sapi_name() == "cli") + $this->Render($FileName); + else + $this->Stroke(); + } + + /* Return the length between two points */ + function getLength($X1,$Y1,$X2,$Y2) + { return(sqrt(pow(max($X1,$X2)-min($X1,$X2),2)+pow(max($Y1,$Y2)-min($Y1,$Y2),2))); } + + /* Return the orientation of a line */ + function getAngle($X1,$Y1,$X2,$Y2) + { + $Opposite = $Y2 - $Y1; $Adjacent = $X2 - $X1;$Angle = rad2deg(atan2($Opposite,$Adjacent)); + if ($Angle > 0) { return($Angle); } else { return(360-abs($Angle)); } + } + + /* Return the surrounding box of text area */ + function getTextBox_deprecated($X,$Y,$FontName,$FontSize,$Angle,$Text) + { + $Size = imagettfbbox($FontSize,$Angle,$FontName,$Text); + $Width = $this->getLength($Size[0],$Size[1],$Size[2],$Size[3])+1; + $Height = $this->getLength($Size[2],$Size[3],$Size[4],$Size[5])+1; + + $RealPos[0]["X"] = $X; $RealPos[0]["Y"] = $Y; + $RealPos[1]["X"] = cos((360-$Angle)*PI/180)*$Width + $RealPos[0]["X"]; $RealPos[1]["Y"] = sin((360-$Angle)*PI/180)*$Width + $RealPos[0]["Y"]; + $RealPos[2]["X"] = cos((270-$Angle)*PI/180)*$Height + $RealPos[1]["X"]; $RealPos[2]["Y"] = sin((270-$Angle)*PI/180)*$Height + $RealPos[1]["Y"]; + $RealPos[3]["X"] = cos((180-$Angle)*PI/180)*$Width + $RealPos[2]["X"]; $RealPos[3]["Y"] = sin((180-$Angle)*PI/180)*$Width + $RealPos[2]["Y"]; + + $RealPos[TEXT_ALIGN_BOTTOMLEFT]["X"] = $RealPos[0]["X"]; $RealPos[TEXT_ALIGN_BOTTOMLEFT]["Y"] = $RealPos[0]["Y"]; + $RealPos[TEXT_ALIGN_BOTTOMRIGHT]["X"] = $RealPos[1]["X"]; $RealPos[TEXT_ALIGN_BOTTOMRIGHT]["Y"] = $RealPos[1]["Y"]; + + return($RealPos); + } + + /* Return the surrounding box of text area */ + function getTextBox($X,$Y,$FontName,$FontSize,$Angle,$Text) + { + $coords = imagettfbbox($FontSize, 0, $FontName, $Text); + + $a = deg2rad($Angle); $ca = cos($a); $sa = sin($a); $RealPos = array(); + for($i = 0; $i < 7; $i += 2) + { + $RealPos[$i/2]["X"] = $X + round($coords[$i] * $ca + $coords[$i+1] * $sa); + $RealPos[$i/2]["Y"] = $Y + round($coords[$i+1] * $ca - $coords[$i] * $sa); + } + + $RealPos[TEXT_ALIGN_BOTTOMLEFT]["X"] = $RealPos[0]["X"]; $RealPos[TEXT_ALIGN_BOTTOMLEFT]["Y"] = $RealPos[0]["Y"]; + $RealPos[TEXT_ALIGN_BOTTOMRIGHT]["X"] = $RealPos[1]["X"]; $RealPos[TEXT_ALIGN_BOTTOMRIGHT]["Y"] = $RealPos[1]["Y"]; + $RealPos[TEXT_ALIGN_TOPLEFT]["X"] = $RealPos[3]["X"]; $RealPos[TEXT_ALIGN_TOPLEFT]["Y"] = $RealPos[3]["Y"]; + $RealPos[TEXT_ALIGN_TOPRIGHT]["X"] = $RealPos[2]["X"]; $RealPos[TEXT_ALIGN_TOPRIGHT]["Y"] = $RealPos[2]["Y"]; + $RealPos[TEXT_ALIGN_BOTTOMMIDDLE]["X"] = ($RealPos[1]["X"]-$RealPos[0]["X"])/2+$RealPos[0]["X"]; $RealPos[TEXT_ALIGN_BOTTOMMIDDLE]["Y"] = ($RealPos[0]["Y"]-$RealPos[1]["Y"])/2+$RealPos[1]["Y"]; + $RealPos[TEXT_ALIGN_TOPMIDDLE]["X"] = ($RealPos[2]["X"]-$RealPos[3]["X"])/2+$RealPos[3]["X"]; $RealPos[TEXT_ALIGN_TOPMIDDLE]["Y"] = ($RealPos[3]["Y"]-$RealPos[2]["Y"])/2+$RealPos[2]["Y"]; + $RealPos[TEXT_ALIGN_MIDDLELEFT]["X"] = ($RealPos[0]["X"]-$RealPos[3]["X"])/2+$RealPos[3]["X"]; $RealPos[TEXT_ALIGN_MIDDLELEFT]["Y"] = ($RealPos[0]["Y"]-$RealPos[3]["Y"])/2+$RealPos[3]["Y"]; + $RealPos[TEXT_ALIGN_MIDDLERIGHT]["X"] = ($RealPos[1]["X"]-$RealPos[2]["X"])/2+$RealPos[2]["X"]; $RealPos[TEXT_ALIGN_MIDDLERIGHT]["Y"] = ($RealPos[1]["Y"]-$RealPos[2]["Y"])/2+$RealPos[2]["Y"]; + $RealPos[TEXT_ALIGN_MIDDLEMIDDLE]["X"] = ($RealPos[1]["X"]-$RealPos[3]["X"])/2+$RealPos[3]["X"]; $RealPos[TEXT_ALIGN_MIDDLEMIDDLE]["Y"] = ($RealPos[0]["Y"]-$RealPos[2]["Y"])/2+$RealPos[2]["Y"]; + + return($RealPos); + } + + /* Set current font properties */ + function setFontProperties($Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : -1; + $G = isset($Format["G"]) ? $Format["G"] : -1; + $B = isset($Format["B"]) ? $Format["B"] : -1; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : NULL; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : NULL; + + if ( $R != -1) { $this->FontColorR = $R; } + if ( $G != -1) { $this->FontColorG = $G; } + if ( $B != -1) { $this->FontColorB = $B; } + if ( $Alpha != NULL) { $this->FontColorA = $Alpha; } + + if ( $FontName != NULL ) + $this->FontName = $FontName; + + if ( $FontSize != NULL ) + $this->FontSize = $FontSize; + } + + /* Returns the 1st decimal values (used to correct AA bugs) */ + function getFirstDecimal($Value) + { + $Values = preg_split("/\./",$Value); + if ( isset($Values[1]) ) { return(substr($Values[1],0,1)); } else { return(0); } + } + + /* Attach a dataset to your pChart Object */ + function setDataSet(&$DataSet) + { $this->DataSet = $DataSet; } + + /* Print attached dataset contents to STDOUT */ + function printDataSet() + { print_r($this->DataSet); } + + /* Initialise the image map methods */ + function initialiseImageMap($Name="pChart",$StorageMode=IMAGE_MAP_STORAGE_SESSION,$UniqueID="imageMap",$StorageFolder="tmp") + { + $this->ImageMapIndex = $Name; + $this->ImageMapStorageMode = $StorageMode; + + if ($StorageMode == IMAGE_MAP_STORAGE_SESSION) + { + if(!isset($_SESSION)) { session_start(); } + $_SESSION[$this->ImageMapIndex] = NULL; + } + elseif($StorageMode == IMAGE_MAP_STORAGE_FILE) + { + $this->ImageMapFileName = $UniqueID; + $this->ImageMapStorageFolder = $StorageFolder; + + if (file_exists($StorageFolder."/".$UniqueID.".map")) { unlink($StorageFolder."/".$UniqueID.".map"); } + } + } + + /* Add a zone to the image map */ + function addToImageMap($Type,$Plots,$Color=NULL,$Title=NULL,$Message=NULL,$HTMLEncode=FALSE) + { + if ( $this->ImageMapStorageMode == NULL ) { $this->initialiseImageMap(); } + + /* Encode the characters in the imagemap in HTML standards */ + $Title = str_replace("€","\u20AC",$Title); + $Title = htmlentities($Title,ENT_QUOTES,"ISO-8859-15"); + if ( $HTMLEncode ) + { + $Message = htmlentities($Message,ENT_QUOTES,"ISO-8859-15"); + $Message = str_replace("<","<",$Message); + $Message = str_replace(">",">",$Message); + } + + if ( $this->ImageMapStorageMode == IMAGE_MAP_STORAGE_SESSION ) + { + if(!isset($_SESSION)) { $this->initialiseImageMap(); } + $_SESSION[$this->ImageMapIndex][] = array($Type,$Plots,$Color,$Title,$Message); + } + elseif($this->ImageMapStorageMode == IMAGE_MAP_STORAGE_FILE) + { + $Handle = fopen($this->ImageMapStorageFolder."/".$this->ImageMapFileName.".map", 'a'); + fwrite($Handle, $Type.IMAGE_MAP_DELIMITER.$Plots.IMAGE_MAP_DELIMITER.$Color.IMAGE_MAP_DELIMITER.$Title.IMAGE_MAP_DELIMITER.$Message."\r\n"); + fclose($Handle); + } + } + + /* Remove VOID values from an imagemap custom values array */ + function removeVOIDFromArray($SerieName, $Values) + { + if ( !isset($this->DataSet->Data["Series"][$SerieName]) ) { return(-1); } + + $Result = ""; + foreach($this->DataSet->Data["Series"][$SerieName]["Data"] as $Key => $Value) + { if ( $Value != VOID && isset($Values[$Key]) ) { $Result[] = $Values[$Key]; } } + return($Result); + } + + /* Replace the title of one image map serie */ + function replaceImageMapTitle($OldTitle, $NewTitle) + { + if ( $this->ImageMapStorageMode == NULL ) { return(-1); } + + if ( is_array($NewTitle) ) { $NewTitle = $this->removeVOIDFromArray($OldTitle, $NewTitle); } + + if ( $this->ImageMapStorageMode == IMAGE_MAP_STORAGE_SESSION ) + { + if(!isset($_SESSION)) { return(-1); } + if ( is_array($NewTitle) ) + { $ID = 0; foreach($_SESSION[$this->ImageMapIndex] as $Key => $Settings) { if ( $Settings[3] == $OldTitle && isset($NewTitle[$ID])) { $_SESSION[$this->ImageMapIndex][$Key][3] = $NewTitle[$ID]; $ID++; } } } + else + { foreach($_SESSION[$this->ImageMapIndex] as $Key => $Settings) { if ( $Settings[3] == $OldTitle ) { $_SESSION[$this->ImageMapIndex][$Key][3] = $NewTitle; } } } + } + elseif( $this->ImageMapStorageMode == IMAGE_MAP_STORAGE_FILE ) + { + $TempArray = ""; + $Handle = @fopen($this->ImageMapStorageFolder."/".$this->ImageMapFileName.".map", "r"); + if ($Handle) + { + while (($Buffer = fgets($Handle, 4096)) !== false) + { + $Fields = split(IMAGE_MAP_DELIMITER,str_replace(array(chr(10),chr(13)),"",$Buffer)); + $TempArray[] = array($Fields[0],$Fields[1],$Fields[2],$Fields[3],$Fields[4]); + } + fclose($Handle); + + if ( is_array($NewTitle) ) + { $ID = 0; foreach($TempArray as $Key => $Settings) { if ( $Settings[3] == $OldTitle && isset($NewTitle[$ID]) ) { $TempArray[$Key][3] = $NewTitle[$ID]; $ID++; } } } + else + { foreach($TempArray as $Key => $Settings) { if ( $Settings[3] == $OldTitle ) { $TempArray[$Key][3] = $NewTitle; } } } + + $Handle = fopen($this->ImageMapStorageFolder."/".$this->ImageMapFileName.".map", 'w'); + foreach($TempArray as $Key => $Settings) + { fwrite($Handle, $Settings[0].IMAGE_MAP_DELIMITER.$Settings[1].IMAGE_MAP_DELIMITER.$Settings[2].IMAGE_MAP_DELIMITER.$Settings[3].IMAGE_MAP_DELIMITER.$Settings[4]."\r\n"); } + fclose($Handle); + } + } + } + + /* Replace the values of the image map contents */ + function replaceImageMapValues($Title, $Values) + { + if ( $this->ImageMapStorageMode == NULL ) { return(-1); } + + $Values = $this->removeVOIDFromArray($Title, $Values); + $ID = 0; + if ( $this->ImageMapStorageMode == IMAGE_MAP_STORAGE_SESSION ) + { + if(!isset($_SESSION)) { return(-1); } + foreach($_SESSION[$this->ImageMapIndex] as $Key => $Settings) { if ( $Settings[3] == $Title ) { if ( isset($Values[$ID]) ) { $_SESSION[$this->ImageMapIndex][$Key][4] = $Values[$ID]; } $ID++; } } + } + elseif( $this->ImageMapStorageMode == IMAGE_MAP_STORAGE_FILE ) + { + $TempArray = ""; + $Handle = @fopen($this->ImageMapStorageFolder."/".$this->ImageMapFileName.".map", "r"); + if ($Handle) + { + while (($Buffer = fgets($Handle, 4096)) !== false) + { + $Fields = split(IMAGE_MAP_DELIMITER,str_replace(array(chr(10),chr(13)),"",$Buffer)); + $TempArray[] = array($Fields[0],$Fields[1],$Fields[2],$Fields[3],$Fields[4]); + } + fclose($Handle); + + foreach($TempArray as $Key => $Settings) { if ( $Settings[3] == $Title ) { if ( isset($Values[$ID]) ) { $TempArray[$Key][4] = $Values[$ID]; } $ID++; } } + + $Handle = fopen($this->ImageMapStorageFolder."/".$this->ImageMapFileName.".map", 'w'); + foreach($TempArray as $Key => $Settings) + { fwrite($Handle, $Settings[0].IMAGE_MAP_DELIMITER.$Settings[1].IMAGE_MAP_DELIMITER.$Settings[2].IMAGE_MAP_DELIMITER.$Settings[3].IMAGE_MAP_DELIMITER.$Settings[4]."\r\n"); } + fclose($Handle); + } + } + } + + /* Dump the image map */ + function dumpImageMap($Name="pChart",$StorageMode=IMAGE_MAP_STORAGE_SESSION,$UniqueID="imageMap",$StorageFolder="tmp") + { + $this->ImageMapIndex = $Name; + $this->ImageMapStorageMode = $StorageMode; + + if ( $this->ImageMapStorageMode == IMAGE_MAP_STORAGE_SESSION ) + { + if(!isset($_SESSION)) { session_start(); } + if ( $_SESSION[$Name] != NULL ) + { + foreach($_SESSION[$Name] as $Key => $Params) + { echo $Params[0].IMAGE_MAP_DELIMITER.$Params[1].IMAGE_MAP_DELIMITER.$Params[2].IMAGE_MAP_DELIMITER.$Params[3].IMAGE_MAP_DELIMITER.$Params[4]."\r\n"; } + } + } + elseif( $this->ImageMapStorageMode == IMAGE_MAP_STORAGE_FILE ) + { + if (file_exists($StorageFolder."/".$UniqueID.".map")) + { + $Handle = @fopen($StorageFolder."/".$UniqueID.".map", "r"); + if ($Handle) { while (($Buffer = fgets($Handle, 4096)) !== false) { echo $Buffer; } } + fclose($Handle); + + if ( $this->ImageMapAutoDelete ) { unlink($StorageFolder."/".$UniqueID.".map"); } + } + } + + /* When the image map is returned to the client, the script ends */ + exit(); + } + + /* Return the HTML converted color from the RGB composite values */ + function toHTMLColor($R,$G,$B) + { + $R=intval($R); $G=intval($G); $B=intval($B); + $R=dechex($R<0?0:($R>255?255:$R)); $G=dechex($G<0?0:($G>255?255:$G));$B=dechex($B<0?0:($B>255?255:$B)); + $Color="#".(strlen($R) < 2?'0':'').$R; $Color.=(strlen($G) < 2?'0':'').$G; $Color.= (strlen($B) < 2?'0':'').$B; + return($Color); + } + + /* Reverse an array of points */ + function reversePlots($Plots) + { + $Result = ""; + for($i=count($Plots)-2;$i>=0;$i=$i-2) { $Result[] = $Plots[$i]; $Result[] = $Plots[$i+1]; } + return($Result); + } + + /* Mirror Effect */ + function drawAreaMirror($X,$Y,$Width,$Height,$Format="") + { + $StartAlpha = isset($Format["StartAlpha"]) ? $Format["StartAlpha"] : 80; + $EndAlpha = isset($Format["EndAlpha"]) ? $Format["EndAlpha"] : 0; + + $AlphaStep = ($StartAlpha-$EndAlpha)/$Height; + + $Picture = imagecreatetruecolor($this->XSize,$this->YSize); + imagecopy($Picture,$this->Picture,0,0,0,0,$this->XSize,$this->YSize); + + for($i=1;$i<=$Height;$i++) + { + if ( $Y+($i-1) < $this->YSize && $Y-$i > 0 ) { imagecopymerge($Picture,$this->Picture,$X,$Y+($i-1),$X,$Y-$i,$Width,1,$StartAlpha-$AlphaStep*$i); } + } + + imagecopy($this->Picture,$Picture,0,0,0,0,$this->XSize,$this->YSize); + } + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/class/pIndicator.class.php b/trunk/includes/pChart/class/pIndicator.class.php new file mode 100644 index 0000000..1e4c7c3 --- /dev/null +++ b/trunk/includes/pChart/class/pIndicator.class.php @@ -0,0 +1,241 @@ +pChartObject = $pChartObject; + } + + /* Draw an indicator */ + function draw($X,$Y,$Width,$Height,$Format="") + { + $Values = isset($Format["Values"]) ? $Format["Values"] : VOID; + $IndicatorSections = isset($Format["IndicatorSections"]) ? $Format["IndicatorSections"] : NULL; + $ValueDisplay = isset($Format["ValueDisplay"]) ? $Format["ValueDisplay"] : INDICATOR_VALUE_BUBBLE; + $SectionsMargin = isset($Format["SectionsMargin"]) ? $Format["SectionsMargin"] : 4; + $DrawLeftHead = isset($Format["DrawLeftHead"]) ? $Format["DrawLeftHead"] : TRUE; + $DrawRightHead = isset($Format["DrawRightHead"]) ? $Format["DrawRightHead"] : TRUE; + $HeadSize = isset($Format["HeadSize"]) ? $Format["HeadSize"] : floor($Height/4); + $TextPadding = isset($Format["TextPadding"]) ? $Format["TextPadding"] : 4; + $CaptionLayout = isset($Format["CaptionLayout"]) ? $Format["CaptionLayout"] : INDICATOR_CAPTION_EXTENDED; + $CaptionPosition = isset($Format["CaptionPosition"]) ? $Format["CaptionPosition"] : INDICATOR_CAPTION_INSIDE; + $CaptionColorFactor = isset($Format["CaptionColorFactor"]) ? $Format["CaptionColorFactor"] : NULL; + $CaptionR = isset($Format["CaptionR"]) ? $Format["CaptionR"] : 255; + $CaptionG = isset($Format["CaptionG"]) ? $Format["CaptionG"] : 255; + $CaptionB = isset($Format["CaptionB"]) ? $Format["CaptionB"] : 255; + $CaptionAlpha = isset($Format["CaptionAlpha"]) ? $Format["CaptionAlpha"] : 100; + $SubCaptionColorFactor = isset($Format["SubCaptionColorFactor"]) ? $Format["SubCaptionColorFactor"] : NULL; + $SubCaptionR = isset($Format["SubCaptionR"]) ? $Format["SubCaptionR"] : 50; + $SubCaptionG = isset($Format["SubCaptionG"]) ? $Format["SubCaptionG"] : 50; + $SubCaptionB = isset($Format["SubCaptionB"]) ? $Format["SubCaptionB"] : 50; + $SubCaptionAlpha = isset($Format["SubCaptionAlpha"]) ? $Format["SubCaptionAlpha"] : 100; + $ValueFontName = isset($Format["ValueFontName"]) ? $Format["ValueFontName"] : $this->pChartObject->FontName; + $ValueFontSize = isset($Format["ValueFontSize"]) ? $Format["ValueFontSize"] : $this->pChartObject->FontSize; + $CaptionFontName = isset($Format["CaptionFontName"]) ? $Format["CaptionFontName"] : $this->pChartObject->FontName; + $CaptionFontSize = isset($Format["CaptionFontSize"]) ? $Format["CaptionFontSize"] : $this->pChartObject->FontSize; + $Unit = isset($Format["Unit"]) ? $Format["Unit"] : ""; + + /* Convert the Values to display to an array if needed */ + if ( !is_array($Values) ) { $Value = $Values; $Values = ""; $Values[] = $Value; } + + /* No section, let's die */ + if ( $IndicatorSections == NULL ) { return(0); } + + /* Determine indicator visual configuration */ + $OverallMin = $IndicatorSections[0]["End"]; $OverallMax = $IndicatorSections[0]["Start"]; + foreach ($IndicatorSections as $Key => $Settings) + { + if ( $Settings["End"] > $OverallMax ) { $OverallMax = $Settings["End"]; } + if ( $Settings["Start"] < $OverallMin ) { $OverallMin = $Settings["Start"]; } + } + $RealWidth = $Width - (count($IndicatorSections)-1)*$SectionsMargin; + $XScale = $RealWidth / ($OverallMax-$OverallMin); + + $X1 = $X; $ValuesPos = ""; + foreach ($IndicatorSections as $Key => $Settings) + { + $Color = array("R"=>$Settings["R"],"G"=>$Settings["G"],"B"=>$Settings["B"]); + $Caption = $Settings["Caption"]; + $SubCaption = $Settings["Start"]." - ".$Settings["End"]; + + $X2 = $X1 + ($Settings["End"] - $Settings["Start"]) * $XScale; + + if ( $Key == 0 && $DrawLeftHead ) + { + $Poly = ""; $Poly[] = $X1-1; $Poly[] = $Y; $Poly[] = $X1-1; $Poly[] = $Y+$Height; $Poly[] = $X1-1-$HeadSize; $Poly[] = $Y+($Height/2); + $this->pChartObject->drawPolygon($Poly,$Color); + $this->pChartObject->drawLine($X1-2,$Y,$X1-2-$HeadSize,$Y+($Height/2),$Color); + $this->pChartObject->drawLine($X1-2,$Y+$Height,$X1-2-$HeadSize,$Y+($Height/2),$Color); + } + + /* Determine the position of the breaks */ + $Break = ""; + foreach($Values as $iKey => $Value) + { + if ( $Value >= $Settings["Start"] && $Value <= $Settings["End"] ) + { + $XBreak = $X1 + ($Value - $Settings["Start"]) * $XScale; + $ValuesPos[$Value] = $XBreak; + $Break[] = floor($XBreak); + } + } + + if ( $ValueDisplay == INDICATOR_VALUE_LABEL ) + { + if ( $Break == "" ) + $this->pChartObject->drawFilledRectangle($X1,$Y,$X2,$Y+$Height,$Color); + else + { + sort($Break); + $Poly = ""; $Poly[] = $X1; $Poly[] = $Y; $LastPointWritten = FALSE; + foreach($Break as $iKey => $Value) + { + if ( $Value-5 >= $X1 ) + { $Poly[] = $Value-5; $Poly[] = $Y; } + elseif ($X1 - ($Value-5) > 0 ) + { + $Offset = $X1 - ($Value-5); + $Poly = ""; $Poly[] = $X1; $Poly[] = $Y + $Offset; + } + + $Poly[] = $Value; $Poly[] = $Y+5; + + if ( $Value+5 <= $X2 ) + { $Poly[] = $Value+5; $Poly[] = $Y; } + elseif (($Value+5) > $X2 ) + { + $Offset = ($Value+5) - $X2; + $Poly[] = $X2; $Poly[] = $Y + $Offset; + $LastPointWritten = TRUE; + } + + } + if ( !$LastPointWritten ) { $Poly[] = $X2; $Poly[] = $Y; } + $Poly[] = $X2; $Poly[] = $Y+$Height; + $Poly[] = $X1; $Poly[] = $Y+$Height; + + $this->pChartObject->drawPolygon($Poly,$Color); + } + } + else + $this->pChartObject->drawFilledRectangle($X1,$Y,$X2,$Y+$Height,$Color); + + if ( $Key == count($IndicatorSections)-1 && $DrawRightHead ) + { + $Poly = ""; $Poly[] = $X2+1; $Poly[] = $Y; $Poly[] = $X2+1; $Poly[] = $Y+$Height; $Poly[] = $X2+1+$HeadSize; $Poly[] = $Y+($Height/2); + $this->pChartObject->drawPolygon($Poly,$Color); + $this->pChartObject->drawLine($X2+1,$Y,$X2+1+$HeadSize,$Y+($Height/2),$Color); + $this->pChartObject->drawLine($X2+1,$Y+$Height,$X2+1+$HeadSize,$Y+($Height/2),$Color); + } + + if ( $CaptionPosition == INDICATOR_CAPTION_INSIDE ) + { + $TxtPos = $this->pChartObject->getTextBox($X1,$Y+$Height+$TextPadding,$CaptionFontName,$CaptionFontSize,0,$Caption); + $YOffset = ($TxtPos[0]["Y"] - $TxtPos[2]["Y"]) + $TextPadding; + + if ( $CaptionLayout == INDICATOR_CAPTION_EXTENDED ) + { + $TxtPos = $this->pChartObject->getTextBox($X1,$Y+$Height+$TextPadding,$CaptionFontName,$CaptionFontSize,0,$SubCaption); + $YOffset = $YOffset + ($TxtPos[0]["Y"] - $TxtPos[2]["Y"]) + $TextPadding*2; + } + + $XOffset = $TextPadding; + } + else + { $YOffset = 0; $XOffset = 0; } + + if ( $CaptionColorFactor == NULL ) + { $CaptionColor = array("Align"=>TEXT_ALIGN_TOPLEFT,"FontName"=>$CaptionFontName,"FontSize"=>$CaptionFontSize,"R"=>$CaptionR,"G"=>$CaptionG,"B"=>$CaptionB,"Alpha"=>$CaptionAlpha); } + else + { $CaptionColor = array("Align"=>TEXT_ALIGN_TOPLEFT,"FontName"=>$CaptionFontName,"FontSize"=>$CaptionFontSize,"R"=>$Settings["R"]+$CaptionColorFactor,"G"=>$Settings["G"]+$CaptionColorFactor,"B"=>$Settings["B"]+$CaptionColorFactor); } + + if ( $SubCaptionColorFactor == NULL ) + $SubCaptionColor = array("Align"=>TEXT_ALIGN_TOPLEFT,"FontName"=>$CaptionFontName,"FontSize"=>$CaptionFontSize,"R"=>$SubCaptionR,"G"=>$SubCaptionG,"B"=>$SubCaptionB,"Alpha"=>$SubCaptionAlpha); + else + $SubCaptionColor = array("Align"=>TEXT_ALIGN_TOPLEFT,"FontName"=>$CaptionFontName,"FontSize"=>$CaptionFontSize,"R"=>$Settings["R"]+$SubCaptionColorFactor,"G"=>$Settings["G"]+$SubCaptionColorFactor,"B"=>$Settings["B"]+$SubCaptionColorFactor); + + $RestoreShadow = $this->pChartObject->Shadow; + $this->pChartObject->Shadow = FALSE; + + if ( $CaptionLayout == INDICATOR_CAPTION_DEFAULT ) + $this->pChartObject->drawText($X1,$Y+$Height+$TextPadding,$Caption,$CaptionColor); + elseif ( $CaptionLayout == INDICATOR_CAPTION_EXTENDED ) + { + $TxtPos = $this->pChartObject->getTextBox($X1,$Y+$Height+$TextPadding,$CaptionFontName,$CaptionFontSize,0,$Caption); + $CaptionHeight = $TxtPos[0]["Y"] - $TxtPos[2]["Y"]; + + $this->pChartObject->drawText($X1+$XOffset,$Y+$Height-$YOffset+$TextPadding,$Caption,$CaptionColor); + $this->pChartObject->drawText($X1+$XOffset,$Y+$Height-$YOffset+$CaptionHeight+$TextPadding*2,$SubCaption,$SubCaptionColor); + } + + $this->pChartObject->Shadow = $RestoreShadow; + + $X1 = $X2 + $SectionsMargin; + } + + $RestoreShadow = $this->pChartObject->Shadow; + $this->pChartObject->Shadow = FALSE; + + foreach($Values as $Key => $Value) + { + if ( $Value >= $OverallMin && $Value <= $OverallMax ) + { + foreach ($IndicatorSections as $Key => $Settings) + { + if ( $Value >= $Settings["Start"] && $Value <= $Settings["End"] ) + { + $X1 = $ValuesPos[$Value]; //$X + $Key*$SectionsMargin + ($Value - $OverallMin) * $XScale; + + if ( $ValueDisplay == INDICATOR_VALUE_BUBBLE ) + { + $TxtPos = $this->pChartObject->getTextBox($X1,$Y,$ValueFontName,$ValueFontSize,0,$Value.$Unit); + $Radius = floor(($TxtPos[1]["X"] - $TxtPos[0]["X"] + $TextPadding*4)/2); + + $this->pChartObject->drawFilledCircle($X1,$Y,$Radius+4,array("R"=>$Settings["R"]+20,"G"=>$Settings["G"]+20,"B"=>$Settings["B"]+20)); + $this->pChartObject->drawFilledCircle($X1,$Y,$Radius,array("R"=>255,"G"=>255,"B"=>255)); + + $TextSettings = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontName"=>$ValueFontName,"FontSize"=>$ValueFontSize); + $this->pChartObject->drawText($X1-1,$Y-1,$Value.$Unit,$TextSettings); + } + elseif( $ValueDisplay == INDICATOR_VALUE_LABEL ) + { + $Caption = ""; + $Caption[] = array("Format"=>array("R"=>$Settings["R"],"G"=>$Settings["G"],"B"=>$Settings["B"],"Alpha"=>100),"Caption"=>$Value.$Unit); + $this->pChartObject->drawLabelBox(floor($X1),floor($Y)+2,"Value - ".$Settings["Caption"],$Caption); + } + } + $X1 = $X2 + $SectionsMargin; + } + } + } + $this->pChartObject->Shadow = $RestoreShadow; + } + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/class/pPie.class.php b/trunk/includes/pChart/class/pPie.class.php new file mode 100644 index 0000000..06db3cf --- /dev/null +++ b/trunk/includes/pChart/class/pPie.class.php @@ -0,0 +1,1500 @@ +pChartObject = $Object; + + /* Cache the pData object reference */ + $this->pDataObject = $pDataObject; + } + + /* Draw a pie chart */ + function draw2DPie($X,$Y,$Format="") + { + $Radius = isset($Format["Radius"]) ? $Format["Radius"] : 60; + $Precision = isset($Format["Precision"]) ? $Format["Precision"] : 0; + $DataGapAngle = isset($Format["DataGapAngle"]) ? $Format["DataGapAngle"] : 0; + $DataGapRadius = isset($Format["DataGapRadius"]) ? $Format["DataGapRadius"] : 0; + $SecondPass = isset($Format["SecondPass"]) ? $Format["SecondPass"] : TRUE; + $Border = isset($Format["Border"]) ? $Format["Border"] : FALSE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255; + $Shadow = isset($Format["Shadow"]) ? $Format["Shadow"] : FALSE; + $DrawLabels = isset($Format["DrawLabels"]) ? $Format["DrawLabels"] : FALSE; + $LabelStacked = isset($Format["LabelStacked"]) ? $Format["LabelStacked"] : FALSE; + $LabelColor = isset($Format["LabelColor"]) ? $Format["LabelColor"] : PIE_LABEL_COLOR_MANUAL; + $LabelR = isset($Format["LabelR"]) ? $Format["LabelR"] : 0; + $LabelG = isset($Format["LabelG"]) ? $Format["LabelG"] : 0; + $LabelB = isset($Format["LabelB"]) ? $Format["LabelB"] : 0; + $LabelAlpha = isset($Format["LabelAlpha"]) ? $Format["LabelAlpha"] : 100; + $WriteValues = isset($Format["WriteValues"]) ? $Format["WriteValues"] : NULL; + $ValuePosition = isset($Format["ValuePosition"]) ? $Format["ValuePosition"] : PIE_VALUE_OUTSIDE; + $ValuePadding = isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : 15; + $ValueSuffix = isset($Format["ValueSuffix"]) ? $Format["ValueSuffix"] : ""; + $ValueR = isset($Format["ValueR"]) ? $Format["ValueR"] : 255; + $ValueG = isset($Format["ValueG"]) ? $Format["ValueG"] : 255; + $ValueB = isset($Format["ValueB"]) ? $Format["ValueB"] : 255; + $ValueAlpha = isset($Format["ValueAlpha"]) ? $Format["ValueAlpha"] : 100; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + + /* Data Processing */ + $Data = $this->pDataObject->getData(); + $Palette = $this->pDataObject->getPalette(); + + /* Do we have an abscissa serie defined? */ + if ( $Data["Abscissa"] == "" ) { return(PIE_NO_ABSCISSA); } + + /* Try to find the data serie */ + $DataSerie = ""; + foreach ($Data["Series"] as $SerieName => $SerieData) + { if ( $SerieName != $Data["Abscissa"]) { $DataSerie = $SerieName; } } + + /* Do we have data to compute? */ + if ( $DataSerie == "" ) { return(PIE_NO_DATASERIE); } + + /* Remove unused data */ + list($Data,$Palette) = $this->clean0Values($Data,$Palette,$DataSerie,$Data["Abscissa"]); + + /* Compute the pie sum */ + $SerieSum = $this->pDataObject->getSum($DataSerie); + + /* Do we have data to draw? */ + if ( $SerieSum == 0 ) { return(PIE_SUMISNULL); } + + /* Dump the real number of data to draw */ + $Values = ""; + foreach ($Data["Series"][$DataSerie]["Data"] as $Key => $Value) + { if ($Value != 0) { $Values[] = $Value; } } + + /* Compute the wasted angular space between series */ + if (count($Values)==1) { $WastedAngular = 0; } else { $WastedAngular = count($Values) * $DataGapAngle; } + + /* Compute the scale */ + $ScaleFactor = (360 - $WastedAngular) / $SerieSum; + + $RestoreShadow = $this->pChartObject->Shadow; + if ( $this->pChartObject->Shadow ) + { + $this->pChartObject->Shadow = FALSE; + + $ShadowFormat = $Format; $ShadowFormat["Shadow"] = TRUE; + $this->draw2DPie($X+$this->pChartObject->ShadowX,$Y+$this->pChartObject->ShadowY,$ShadowFormat); + } + + /* Draw the polygon pie elements */ + $Step = 360 / (2 * PI * $Radius); + $Offset = 0; $ID = 0; + foreach($Values as $Key => $Value) + { + if ( $Shadow ) + $Settings = array("R"=>$this->pChartObject->ShadowR,"G"=>$this->pChartObject->ShadowG,"B"=>$this->pChartObject->ShadowB,"Alpha"=>$this->pChartObject->Shadowa); + else + { + if ( !isset($Palette[$ID]["R"]) ) { $Color = $this->pChartObject->getRandomColor(); $Palette[$ID] = $Color; $this->pDataObject->savePalette($ID,$Color); } + $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]); + } + + if ( !$SecondPass && !$Shadow ) + { + if ( !$Border ) + $Settings["Surrounding"] = 10; + else + { $Settings["BorderR"] = $BorderR; $Settings["BorderG"] = $BorderG; $Settings["BorderB"] = $BorderB; } + } + + $Plots = ""; + $EndAngle = $Offset+($Value*$ScaleFactor); if ( $EndAngle > 360 ) { $EndAngle = 360; } + + $Angle = ($EndAngle - $Offset)/2 + $Offset; + if ($DataGapAngle == 0) + { $X0 = $X; $Y0 = $Y; } + else + { + $X0 = cos(($Angle-90)*PI/180) * $DataGapRadius + $X; + $Y0 = sin(($Angle-90)*PI/180) * $DataGapRadius + $Y; + } + + $Plots[] = $X0; $Plots[] = $Y0; + + + for($i=$Offset;$i<=$EndAngle;$i=$i+$Step) + { + $Xc = cos(($i-90)*PI/180) * $Radius + $X; + $Yc = sin(($i-90)*PI/180) * $Radius + $Y; + + if ( $SecondPass && ( $i<90 )) { $Yc++; } + if ( $SecondPass && ( $i>180 && $i<270 )) { $Xc++; } + if ( $SecondPass && ( $i>=270 )) { $Xc++; $Yc++; } + + $Plots[] = $Xc; $Plots[] = $Yc; + } + + $this->pChartObject->drawPolygon($Plots,$Settings); + if ( $RecordImageMap && !$Shadow ) { $this->pChartObject->addToImageMap("POLY",$this->arraySerialize($Plots),$this->pChartObject->toHTMLColor($Palette[$ID]["R"],$Palette[$ID]["G"],$Palette[$ID]["B"]),$Data["Series"][$Data["Abscissa"]]["Data"][$Key],$Value); } + + if ( $DrawLabels && !$Shadow && !$SecondPass ) + { + if ( $LabelColor == PIE_LABEL_COLOR_AUTO ) + { $Settings = array("FillR"=>$Palette[$ID]["R"],"FillG"=>$Palette[$ID]["G"],"FillB"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);} + else + { $Settings = array("FillR"=>$LabelR,"FillG"=>$LabelG,"FillB"=>$LabelB,"Alpha"=>$LabelAlpha); } + + $Angle = ($EndAngle - $Offset)/2 + $Offset; + $Xc = cos(($Angle-90)*PI/180) * $Radius + $X; + $Yc = sin(($Angle-90)*PI/180) * $Radius + $Y; + + $Label = $Data["Series"][$Data["Abscissa"]]["Data"][$Key]; + + if ( $LabelStacked ) + $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,TRUE,$X,$Y,$Radius); + else + $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,FALSE); + } + + $Offset = $i + $DataGapAngle; $ID++; + } + + /* Second pass to smooth the angles */ + if ( $SecondPass ) + { + $Step = 360 / (2 * PI * $Radius); + $Offset = 0; $ID = 0; + foreach($Values as $Key => $Value) + { + $FirstPoint = TRUE; + if ( $Shadow ) + $Settings = array("R"=>$this->pChartObject->ShadowR,"G"=>$this->pChartObject->ShadowG,"B"=>$this->pChartObject->ShadowB,"Alpha"=>$this->pChartObject->Shadowa); + else + { + if ( $Border ) + $Settings = array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB); + else + $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]); + } + + $EndAngle = $Offset+($Value*$ScaleFactor); if ( $EndAngle > 360 ) { $EndAngle = 360; } + + if ($DataGapAngle == 0) + { $X0 = $X; $Y0 = $Y; } + else + { + $Angle = ($EndAngle - $Offset)/2 + $Offset; + $X0 = cos(($Angle-90)*PI/180) * $DataGapRadius + $X; + $Y0 = sin(($Angle-90)*PI/180) * $DataGapRadius + $Y; + } + $Plots[] = $X0; $Plots[] = $Y0; + + for($i=$Offset;$i<=$EndAngle;$i=$i+$Step) + { + $Xc = cos(($i-90)*PI/180) * $Radius + $X; + $Yc = sin(($i-90)*PI/180) * $Radius + $Y; + + if ( $FirstPoint ) { $this->pChartObject->drawLine($Xc,$Yc,$X0,$Y0,$Settings); } { $FirstPoint = FALSE; } + + $this->pChartObject->drawAntialiasPixel($Xc,$Yc,$Settings); + } + $this->pChartObject->drawLine($Xc,$Yc,$X0,$Y0,$Settings); + + if ( $DrawLabels && !$Shadow ) + { + if ( $LabelColor == PIE_LABEL_COLOR_AUTO ) + { $Settings = array("FillR"=>$Palette[$ID]["R"],"FillG"=>$Palette[$ID]["G"],"FillB"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);} + else + { $Settings = array("FillR"=>$LabelR,"FillG"=>$LabelG,"FillB"=>$LabelB,"Alpha"=>$LabelAlpha); } + + $Angle = ($EndAngle - $Offset)/2 + $Offset; + $Xc = cos(($Angle-90)*PI/180) * $Radius + $X; + $Yc = sin(($Angle-90)*PI/180) * $Radius + $Y; + + $Label = $Data["Series"][$Data["Abscissa"]]["Data"][$Key]; + + if ( $LabelStacked ) + $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,TRUE,$X,$Y,$Radius); + else + $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,FALSE); + } + + $Offset = $i + $DataGapAngle; $ID++; + } + } + + if ( $WriteValues != NULL && !$Shadow ) + { + $Step = 360 / (2 * PI * $Radius); + $Offset = 0; $ID = count($Values)-1; + $Settings = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"R"=>$ValueR,"G"=>$ValueG,"B"=>$ValueB,"Alpha"=>$ValueAlpha); + foreach($Values as $Key => $Value) + { + $EndAngle = ($Value*$ScaleFactor) + $Offset; if ( $EndAngle > 360 ) { $EndAngle = 0; } + $Angle = ($EndAngle - $Offset)/2 + $Offset; + + if ( $ValuePosition == PIE_VALUE_OUTSIDE ) + { + $Xc = cos(($Angle-90)*PI/180) * ($Radius+$ValuePadding) + $X; + $Yc = sin(($Angle-90)*PI/180) * ($Radius+$ValuePadding) + $Y; + } + else + { + $Xc = cos(($Angle-90)*PI/180) * ($Radius)/2 + $X; + $Yc = sin(($Angle-90)*PI/180) * ($Radius)/2 + $Y; + } + + if ( $WriteValues == PIE_VALUE_PERCENTAGE ) + $Display = round(( 100 / $SerieSum ) * $Value,$Precision)."%"; + elseif ( $WriteValues == PIE_VALUE_NATURAL ) + $Display = $Value.$ValueSuffix; + + $this->pChartObject->drawText($Xc,$Yc,$Display,$Settings); + + $Offset = $EndAngle + $DataGapAngle; $ID--; + } + } + + if ( $DrawLabels && $LabelStacked ) { $this->writeShiftedLabels(); } + + $this->pChartObject->Shadow = $RestoreShadow; + + return(PIE_RENDERED); + } + + /* Draw a 3D pie chart */ + function draw3DPie($X,$Y,$Format="") + { + /* Rendering layout */ + $Radius = isset($Format["Radius"]) ? $Format["Radius"] : 80; + $Precision = isset($Format["Precision"]) ? $Format["Precision"] : 0; + $SkewFactor = isset($Format["SkewFactor"]) ? $Format["SkewFactor"] : .5; + $SliceHeight = isset($Format["SliceHeight"]) ? $Format["SliceHeight"] : 20; + $DataGapAngle = isset($Format["DataGapAngle"]) ? $Format["DataGapAngle"] : 0; + $DataGapRadius = isset($Format["DataGapRadius"]) ? $Format["DataGapRadius"] : 0; + $SecondPass = isset($Format["SecondPass"]) ? $Format["SecondPass"] : TRUE; + $Border = isset($Format["Border"]) ? $Format["Border"] : FALSE; + $Shadow = isset($Format["Shadow"]) ? $Format["Shadow"] : FALSE; + $DrawLabels = isset($Format["DrawLabels"]) ? $Format["DrawLabels"] : FALSE; + $LabelStacked = isset($Format["LabelStacked"]) ? $Format["LabelStacked"] : FALSE; + $LabelColor = isset($Format["LabelColor"]) ? $Format["LabelColor"] : PIE_LABEL_COLOR_MANUAL; + $LabelR = isset($Format["LabelR"]) ? $Format["LabelR"] : 0; + $LabelG = isset($Format["LabelG"]) ? $Format["LabelG"] : 0; + $LabelB = isset($Format["LabelB"]) ? $Format["LabelB"] : 0; + $LabelAlpha = isset($Format["LabelAlpha"]) ? $Format["LabelAlpha"] : 100; + $WriteValues = isset($Format["WriteValues"]) ? $Format["WriteValues"] : NULL; //PIE_VALUE_PERCENTAGE + $ValuePosition = isset($Format["ValuePosition"]) ? $Format["ValuePosition"] : PIE_VALUE_INSIDE; + $ValuePadding = isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : 15; + $ValueSuffix = isset($Format["ValueSuffix"]) ? $Format["ValueSuffix"] : ""; + $ValueR = isset($Format["ValueR"]) ? $Format["ValueR"] : 255; + $ValueG = isset($Format["ValueG"]) ? $Format["ValueG"] : 255; + $ValueB = isset($Format["ValueB"]) ? $Format["ValueB"] : 255; + $ValueAlpha = isset($Format["ValueAlpha"]) ? $Format["ValueAlpha"] : 100; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + + /* Error correction for overlaying rounded corners */ + if ( $SkewFactor < .5 ) { $SkewFactor = .5; } + + /* Data Processing */ + $Data = $this->pDataObject->getData(); + $Palette = $this->pDataObject->getPalette(); + + /* Do we have an abscissa serie defined? */ + if ( $Data["Abscissa"] == "" ) { return(PIE_NO_ABSCISSA); } + + /* Try to find the data serie */ + $DataSerie = ""; + foreach ($Data["Series"] as $SerieName => $SerieData) + { if ( $SerieName != $Data["Abscissa"]) { $DataSerie = $SerieName; } } + + /* Do we have data to compute? */ + if ( $DataSerie == "" ) { return(PIE_NO_DATASERIE); } + + /* Remove unused data */ + list($Data,$Palette) = $this->clean0Values($Data,$Palette,$DataSerie,$Data["Abscissa"]); + + /* Compute the pie sum */ + $SerieSum = $this->pDataObject->getSum($DataSerie); + + /* Do we have data to draw? */ + if ( $SerieSum == 0 ) { return(PIE_SUMISNULL); } + + /* Dump the real number of data to draw */ + $Values = ""; + foreach ($Data["Series"][$DataSerie]["Data"] as $Key => $Value) + { if ($Value != 0) { $Values[] = $Value; } } + + /* Compute the wasted angular space between series */ + if (count($Values)==1) { $WastedAngular = 0; } else { $WastedAngular = count($Values) * $DataGapAngle; } + + /* Compute the scale */ + $ScaleFactor = (360 - $WastedAngular) / $SerieSum; + + $RestoreShadow = $this->pChartObject->Shadow; + if ( $this->pChartObject->Shadow ) { $this->pChartObject->Shadow = FALSE; } + + /* Draw the polygon pie elements */ + $Step = 360 / (2 * PI * $Radius); + $Offset = 360; $ID = count($Values)-1; + $Values = array_reverse($Values); + $Slice = 0; $Slices = ""; $SliceColors = ""; $Visible = ""; $SliceAngle = ""; + foreach($Values as $Key => $Value) + { + if ( !isset($Palette[$ID]["R"]) ) { $Color = $this->pChartObject->getRandomColor(); $Palette[$ID] = $Color; $this->pDataObject->savePalette($ID,$Color); } + $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]); + + $SliceColors[$Slice] = $Settings; + + $StartAngle = $Offset; + $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; } + + if ( $StartAngle > 180 ) { $Visible[$Slice]["Start"] = TRUE; } else { $Visible[$Slice]["Start"] = TRUE; } + if ( $EndAngle < 180 ) { $Visible[$Slice]["End"] = FALSE; } else { $Visible[$Slice]["End"] = TRUE; } + + if ($DataGapAngle == 0) + { $X0 = $X; $Y0 = $Y; } + else + { + $Angle = ($EndAngle - $Offset)/2 + $Offset; + $X0 = cos(($Angle-90)*PI/180) * $DataGapRadius + $X; + $Y0 = sin(($Angle-90)*PI/180) * $DataGapRadius*$SkewFactor + $Y; + } + $Slices[$Slice][] = $X0; $Slices[$Slice][] = $Y0; $SliceAngle[$Slice][] = 0; + + for($i=$Offset;$i>=$EndAngle;$i=$i-$Step) + { + $Xc = cos(($i-90)*PI/180) * $Radius + $X; + $Yc = sin(($i-90)*PI/180) * $Radius*$SkewFactor + $Y; + + if ( ($SecondPass || $RestoreShadow ) && ( $i<90 )) { $Yc++; } + if ( ($SecondPass || $RestoreShadow ) && ( $i>90 && $i<180 )) { $Xc++; } + if ( ($SecondPass || $RestoreShadow ) && ( $i>180 && $i<270 )) { $Xc++; } + if ( ($SecondPass || $RestoreShadow ) && ( $i>=270 )) { $Xc++; $Yc++; } + + $Slices[$Slice][] = $Xc; $Slices[$Slice][] = $Yc; $SliceAngle[$Slice][] = $i; + } + + $Offset = $i - $DataGapAngle; $ID--; $Slice++; + } + + /* Draw the bottom shadow if needed */ + if ( $RestoreShadow && ($this->pChartObject->ShadowX != 0 || $this->pChartObject->ShadowY !=0 )) + { + foreach($Slices as $SliceID => $Plots) + { + $ShadowPie = ""; + for($i=0;$ipChartObject->ShadowX; $ShadowPie[] = $Plots[$i+1]+$this->pChartObject->ShadowY; } + + $Settings = array("R"=>$this->pChartObject->ShadowR,"G"=>$this->pChartObject->ShadowG,"B"=>$this->pChartObject->ShadowB,"Alpha"=>$this->pChartObject->Shadowa,"NoBorder"=>TRUE); + $this->pChartObject->drawPolygon($ShadowPie,$Settings); + } + + $Step = 360 / (2 * PI * $Radius); + $Offset = 360; + foreach($Values as $Key => $Value) + { + $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; } + + for($i=$Offset;$i>=$EndAngle;$i=$i-$Step) + { + $Xc = cos(($i-90)*PI/180) * $Radius + $X + $this->pChartObject->ShadowX; + $Yc = sin(($i-90)*PI/180) * $Radius*$SkewFactor + $Y + $this->pChartObject->ShadowY; + + $this->pChartObject->drawAntialiasPixel($Xc,$Yc,$Settings); + } + + $Offset = $i - $DataGapAngle; $ID--; + } + } + + /* Draw the bottom pie splice */ + foreach($Slices as $SliceID => $Plots) + { + $Settings = $SliceColors[$SliceID]; $Settings["NoBorder"] = TRUE; + $this->pChartObject->drawPolygon($Plots,$Settings); + + if ( $SecondPass ) + { + $Settings = $SliceColors[$SliceID]; + if ( $Border ) + { $Settings["R"]+= 30; $Settings["G"]+= 30; $Settings["B"]+= 30;; } + + if ( isset($SliceAngle[$SliceID][1]) ) /* Empty error handling */ + { + $Angle = $SliceAngle[$SliceID][1]; + $Xc = cos(($Angle-90)*PI/180) * $Radius + $X; + $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y; + $this->pChartObject->drawLine($Plots[0],$Plots[1],$Xc,$Yc,$Settings); + + $Angle = $SliceAngle[$SliceID][count($SliceAngle[$SliceID])-1]; + $Xc = cos(($Angle-90)*PI/180) * $Radius + $X; + $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y; + $this->pChartObject->drawLine($Plots[0],$Plots[1],$Xc,$Yc,$Settings); + } + } + } + + /* Draw the two vertical edges */ + $Slices = array_reverse($Slices); + $SliceColors = array_reverse($SliceColors); + foreach($Slices as $SliceID => $Plots) + { + $Settings = $SliceColors[$SliceID]; + $Settings["R"]+= 10; $Settings["G"]+= 10; $Settings["B"]+= 10; $Settings["NoBorder"] = TRUE; + + if ( $Visible[$SliceID]["Start"] && isset($Plots[2])) /* Empty error handling */ + { + $this->pChartObject->drawLine($Plots[2],$Plots[3],$Plots[2],$Plots[3]- $SliceHeight,array("R"=>$Settings["R"],"G"=>$Settings["G"],"B"=>$Settings["B"])); + $Border = ""; + $Border[] = $Plots[0]; $Border[] = $Plots[1]; $Border[] = $Plots[0]; $Border[] = $Plots[1] - $SliceHeight; + $Border[] = $Plots[2]; $Border[] = $Plots[3] - $SliceHeight; $Border[] = $Plots[2]; $Border[] = $Plots[3]; + $this->pChartObject->drawPolygon($Border,$Settings); + } + } + + $Slices = array_reverse($Slices); + $SliceColors = array_reverse($SliceColors); + foreach($Slices as $SliceID => $Plots) + { + $Settings = $SliceColors[$SliceID]; + $Settings["R"]+= 10; $Settings["G"]+= 10; $Settings["B"]+= 10; $Settings["NoBorder"] = TRUE; + if ( $Visible[$SliceID]["End"] ) + { + $this->pChartObject->drawLine($Plots[count($Plots)-2],$Plots[count($Plots)-1],$Plots[count($Plots)-2],$Plots[count($Plots)-1]- $SliceHeight,array("R"=>$Settings["R"],"G"=>$Settings["G"],"B"=>$Settings["B"])); + + $Border = ""; + $Border[] = $Plots[0]; $Border[] = $Plots[1]; $Border[] = $Plots[0]; $Border[] = $Plots[1] - $SliceHeight; + $Border[] = $Plots[count($Plots)-2]; $Border[] = $Plots[count($Plots)-1] - $SliceHeight; $Border[] = $Plots[count($Plots)-2]; $Border[] = $Plots[count($Plots)-1]; + $this->pChartObject->drawPolygon($Border,$Settings); + } + } + + /* Draw the rounded edges */ + foreach($Slices as $SliceID => $Plots) + { + $Settings = $SliceColors[$SliceID]; + $Settings["R"]+= 10; $Settings["G"]+= 10; $Settings["B"]+= 10; $Settings["NoBorder"] = TRUE; + + for ($j=2;$j 90 ) + { + $Border = ""; + $Border[] = $Plots[$j]; $Border[] = $Plots[$j+1]; + $Border[] = $Plots[$j+2]; $Border[] = $Plots[$j+3]; + $Border[] = $Plots[$j+2]; $Border[] = $Plots[$j+3] - $SliceHeight; + $Border[] = $Plots[$j]; $Border[] = $Plots[$j+1] - $SliceHeight; + $this->pChartObject->drawPolygon($Border,$Settings); + } + } + + if ( $SecondPass ) + { + $Settings = $SliceColors[$SliceID]; + if ( $Border ) + { $Settings["R"]+= 30; $Settings["G"]+= 30; $Settings["B"]+= 30; } + + if ( isset($SliceAngle[$SliceID][1]) ) /* Empty error handling */ + { + $Angle = $SliceAngle[$SliceID][1]; + if ( $Angle < 270 && $Angle > 90 ) + { + $Xc = cos(($Angle-90)*PI/180) * $Radius + $X; + $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y; + $this->pChartObject->drawLine($Xc,$Yc,$Xc,$Yc-$SliceHeight,$Settings); + } + } + + $Angle = $SliceAngle[$SliceID][count($SliceAngle[$SliceID])-1]; + if ( $Angle < 270 && $Angle > 90 ) + { + $Xc = cos(($Angle-90)*PI/180) * $Radius + $X; + $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y; + $this->pChartObject->drawLine($Xc,$Yc,$Xc,$Yc-$SliceHeight,$Settings); + } + + if ( isset($SliceAngle[$SliceID][1]) && $SliceAngle[$SliceID][1] > 270 && $SliceAngle[$SliceID][count($SliceAngle[$SliceID])-1] < 270 ) + { + $Xc = cos((270-90)*PI/180) * $Radius + $X; + $Yc = sin((270-90)*PI/180) * $Radius*$SkewFactor + $Y; + $this->pChartObject->drawLine($Xc,$Yc,$Xc,$Yc-$SliceHeight,$Settings); + } + + if ( isset($SliceAngle[$SliceID][1]) && $SliceAngle[$SliceID][1] > 90 && $SliceAngle[$SliceID][count($SliceAngle[$SliceID])-1] < 90 ) + { + $Xc = cos((0)*PI/180) * $Radius + $X; + $Yc = sin((0)*PI/180) * $Radius*$SkewFactor + $Y; + $this->pChartObject->drawLine($Xc,$Yc,$Xc,$Yc-$SliceHeight,$Settings); + } + + } + } + + /* Draw the top splice */ + foreach($Slices as $SliceID => $Plots) + { + $Settings = $SliceColors[$SliceID]; + $Settings["R"]+= 20; $Settings["G"]+= 20; $Settings["B"]+= 20; + + $Top = ""; + for($j=0;$jpChartObject->drawPolygon($Top,$Settings); + + if ( $RecordImageMap && !$Shadow ) { $this->pChartObject->addToImageMap("POLY",$this->arraySerialize($Top),$this->pChartObject->toHTMLColor($Settings["R"],$Settings["G"],$Settings["B"]),$Data["Series"][$Data["Abscissa"]]["Data"][count($Slices)-$SliceID-1],$Values[$SliceID]); } + } + + + /* Second pass to smooth the angles */ + if ( $SecondPass ) + { + $Step = 360 / (2 * PI * $Radius); + $Offset = 360; $ID = count($Values)-1; + foreach($Values as $Key => $Value) + { + $FirstPoint = TRUE; + if ( $Shadow ) + $Settings = array("R"=>$this->pChartObject->ShadowR,"G"=>$this->pChartObject->ShadowG,"B"=>$this->pChartObject->ShadowB,"Alpha"=>$this->pChartObject->Shadowa); + else + { + if ( $Border ) + { $Settings = array("R"=>$Palette[$ID]["R"]+30,"G"=>$Palette[$ID]["G"]+30,"B"=>$Palette[$ID]["B"]+30,"Alpha"=>$Palette[$ID]["Alpha"]); } + else + $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]); + } + + $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; } + + if ($DataGapAngle == 0) + { $X0 = $X; $Y0 = $Y- $SliceHeight; } + else + { + $Angle = ($EndAngle - $Offset)/2 + $Offset; + $X0 = cos(($Angle-90)*PI/180) * $DataGapRadius + $X; + $Y0 = sin(($Angle-90)*PI/180) * $DataGapRadius*$SkewFactor + $Y - $SliceHeight; + } + $Plots[] = $X0; $Plots[] = $Y0; + + for($i=$Offset;$i>=$EndAngle;$i=$i-$Step) + { + $Xc = cos(($i-90)*PI/180) * $Radius + $X; + $Yc = sin(($i-90)*PI/180) * $Radius*$SkewFactor + $Y - $SliceHeight; + + if ( $FirstPoint ) { $this->pChartObject->drawLine($Xc,$Yc,$X0,$Y0,$Settings); } { $FirstPoint = FALSE; } + + $this->pChartObject->drawAntialiasPixel($Xc,$Yc,$Settings); + if ($i < 270 && $i > 90 ) { $this->pChartObject->drawAntialiasPixel($Xc,$Yc+$SliceHeight,$Settings); } + } + $this->pChartObject->drawLine($Xc,$Yc,$X0,$Y0,$Settings); + + $Offset = $i - $DataGapAngle; $ID--; + } + } + + if ( $WriteValues != NULL ) + { + $Step = 360 / (2 * PI * $Radius); + $Offset = 360; $ID = count($Values)-1; + $Settings = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"R"=>$ValueR,"G"=>$ValueG,"B"=>$ValueB,"Alpha"=>$ValueAlpha); + foreach($Values as $Key => $Value) + { + $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; } + + $Angle = ($EndAngle - $Offset)/2 + $Offset; + + if ( $ValuePosition == PIE_VALUE_OUTSIDE ) + { + $Xc = cos(($Angle-90)*PI/180) * ($Radius+$ValuePadding) + $X; + $Yc = sin(($Angle-90)*PI/180) * (($Radius*$SkewFactor)+$ValuePadding) + $Y - $SliceHeight; + } + else + { + $Xc = cos(($Angle-90)*PI/180) * ($Radius)/2 + $X; + $Yc = sin(($Angle-90)*PI/180) * ($Radius*$SkewFactor)/2 + $Y - $SliceHeight; + } + + if ( $WriteValues == PIE_VALUE_PERCENTAGE ) + $Display = round(( 100 / $SerieSum ) * $Value,$Precision)."%"; + elseif ( $WriteValues == PIE_VALUE_NATURAL ) + $Display = $Value.$ValueSuffix; + + $this->pChartObject->drawText($Xc,$Yc,$Display,$Settings); + + $Offset = $EndAngle - $DataGapAngle; $ID--; + } + } + + if ( $DrawLabels ) + { + $Step = 360 / (2 * PI * $Radius); + $Offset = 360; $ID = count($Values)-1; + foreach($Values as $Key => $Value) + { + if ( $LabelColor == PIE_LABEL_COLOR_AUTO ) + { $Settings = array("FillR"=>$Palette[$ID]["R"],"FillG"=>$Palette[$ID]["G"],"FillB"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);} + else + { $Settings = array("FillR"=>$LabelR,"FillG"=>$LabelG,"FillB"=>$LabelB,"Alpha"=>$LabelAlpha); } + + $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; } + + $Angle = ($EndAngle - $Offset)/2 + $Offset; + $Xc = cos(($Angle-90)*PI/180) * $Radius + $X; + $Yc = sin(($Angle-90)*PI/180) * $Radius*$SkewFactor + $Y - $SliceHeight; + + if ( isset($Data["Series"][$Data["Abscissa"]]["Data"][$ID]) ) + { + $Label = $Data["Series"][$Data["Abscissa"]]["Data"][$ID]; + + if ( $LabelStacked ) + $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,TRUE,$X,$Y,$Radius,TRUE); + else + $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,FALSE); + } + + $Offset = $EndAngle - $DataGapAngle; $ID--; + } + } + + if ( $DrawLabels && $LabelStacked ) { $this->writeShiftedLabels(); } + + $this->pChartObject->Shadow = $RestoreShadow; + + return(PIE_RENDERED); + } + + /* Draw the legend of pie chart */ + function drawPieLegend($X,$Y,$Format="") + { + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->pChartObject->FontName; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->pChartObject->FontSize; + $FontR = isset($Format["FontR"]) ? $Format["FontR"] : $this->pChartObject->FontColorR; + $FontG = isset($Format["FontG"]) ? $Format["FontG"] : $this->pChartObject->FontColorG; + $FontB = isset($Format["FontB"]) ? $Format["FontB"] : $this->pChartObject->FontColorB; + $BoxSize = isset($Format["BoxSize"]) ? $Format["BoxSize"] : 5; + $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5; + $R = isset($Format["R"]) ? $Format["R"] : 200; + $G = isset($Format["G"]) ? $Format["G"] : 200; + $B = isset($Format["B"]) ? $Format["B"] : 200; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $Style = isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND; + $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL; + + if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; } + + $YStep = max($this->pChartObject->FontSize,$BoxSize) + 5; + $XStep = $BoxSize + 5; + + /* Data Processing */ + $Data = $this->pDataObject->getData(); + $Palette = $this->pDataObject->getPalette(); + + /* Do we have an abscissa serie defined? */ + if ( $Data["Abscissa"] == "" ) { return(PIE_NO_ABSCISSA); } + + $Boundaries = ""; $Boundaries["L"] = $X; $Boundaries["T"] = $Y; $Boundaries["R"] = 0; $Boundaries["B"] = 0; $vY = $Y; $vX = $X; + foreach($Data["Series"][$Data["Abscissa"]]["Data"] as $Key => $Value) + { + $BoxArray = $this->pChartObject->getTextBox($vX+$BoxSize+4,$vY+$BoxSize/2,$FontName,$FontSize,0,$Value); + + if ( $Mode == LEGEND_VERTICAL ) + { + if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$BoxSize/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$BoxSize/2; } + if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } + if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$BoxSize/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$BoxSize/2; } + $vY=$vY+$YStep; + } + elseif ( $Mode == LEGEND_HORIZONTAL ) + { + if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$BoxSize/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$BoxSize/2; } + if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } + if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$BoxSize/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$BoxSize/2; } + $vX=$Boundaries["R"]+$XStep; + } + } + $vY=$vY-$YStep; $vX=$vX-$XStep; + + $TopOffset = $Y - $Boundaries["T"]; + if ( $Boundaries["B"]-($vY+$BoxSize) < $TopOffset ) { $Boundaries["B"] = $vY+$BoxSize+$TopOffset; } + + if ( $Style == LEGEND_ROUND ) + $this->pChartObject->drawRoundedFilledRectangle($Boundaries["L"]-$Margin,$Boundaries["T"]-$Margin,$Boundaries["R"]+$Margin,$Boundaries["B"]+$Margin,$Margin,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB)); + elseif ( $Style == LEGEND_BOX ) + $this->pChartObject->drawFilledRectangle($Boundaries["L"]-$Margin,$Boundaries["T"]-$Margin,$Boundaries["R"]+$Margin,$Boundaries["B"]+$Margin,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB)); + + $RestoreShadow = $this->pChartObject->Shadow; $this->pChartObject->Shadow = FALSE; + foreach($Data["Series"][$Data["Abscissa"]]["Data"] as $Key => $Value) + { + $R = $Palette[$Key]["R"]; $G = $Palette[$Key]["G"]; $B = $Palette[$Key]["B"]; + + $this->pChartObject->drawFilledRectangle($X+1,$Y+1,$X+$BoxSize+1,$Y+$BoxSize+1,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20)); + $this->pChartObject->drawFilledRectangle($X,$Y,$X+$BoxSize,$Y+$BoxSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Surrounding"=>20)); + if ( $Mode == LEGEND_VERTICAL ) + { + $this->pChartObject->drawText($X+$BoxSize+4,$Y+$BoxSize/2,$Value,array("R"=>$FontR,"G"=>$FontG,"B"=>$FontB,"Align"=>TEXT_ALIGN_MIDDLELEFT,"FontName"=>$FontName,"FontSize"=>$FontSize)); + $Y=$Y+$YStep; + } + elseif ( $Mode == LEGEND_HORIZONTAL ) + { + $BoxArray = $this->pChartObject->drawText($X+$BoxSize+4,$Y+$BoxSize/2,$Value,array("R"=>$FontR,"G"=>$FontG,"B"=>$FontB,"Align"=>TEXT_ALIGN_MIDDLELEFT,"FontName"=>$FontName,"FontSize"=>$FontSize)); + $X=$BoxArray[1]["X"]+2+$XStep; + } + } + + $this->Shadow = $RestoreShadow; + } + + /* Set the color of the specified slice */ + function setSliceColor($SliceID,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + + $this->pDataObject->Palette[$SliceID]["R"] = $R; + $this->pDataObject->Palette[$SliceID]["G"] = $G; + $this->pDataObject->Palette[$SliceID]["B"] = $B; + $this->pDataObject->Palette[$SliceID]["Alpha"] = $Alpha; + } + + /* Internally used compute the label positions */ + function writePieLabel($X,$Y,$Label,$Angle,$Settings,$Stacked,$Xc=0,$Yc=0,$Radius=0,$Reversed=FALSE) + { + $LabelOffset = 30; + $FontName = $this->pChartObject->FontName; + $FontSize = $this->pChartObject->FontSize; + + if ( !$Stacked ) + { + $Settings["Angle"] = 360-$Angle; + $Settings["Length"] = 25; + $Settings["Size"] = 8; + + $this->pChartObject->drawArrowLabel($X,$Y," ".$Label." ",$Settings); + } + else + { + $X2 = cos(deg2rad($Angle-90))*20+$X; + $Y2 = sin(deg2rad($Angle-90))*20+$Y; + + $TxtPos = $this->pChartObject->getTextBox($X,$Y,$FontName,$FontSize,0,$Label); + $Height = $TxtPos[0]["Y"] - $TxtPos[2]["Y"]; + $YTop = $Y2 - $Height/2 - 2; + $YBottom = $Y2 + $Height/2 + 2; + + if ( $this->LabelPos != "" ) + { + $Done = FALSE; + foreach($this->LabelPos as $Key => $Settings) + { + if ( !$Done ) + { + if ( $Angle <= 90 && (($YTop >= $Settings["YTop"] && $YTop <= $Settings["YBottom"]) || ($YBottom >= $Settings["YTop"] && $YBottom <= $Settings["YBottom"]))) + { $this->shift(0,180,-($Height+2),$Reversed); $Done = TRUE; } + if ( $Angle > 90 && $Angle <= 180 && (($YTop >= $Settings["YTop"] && $YTop <= $Settings["YBottom"]) || ($YBottom >= $Settings["YTop"] && $YBottom <= $Settings["YBottom"]))) + { $this->shift(0,180,-($Height+2),$Reversed); $Done = TRUE; } + if ( $Angle > 180 && $Angle <= 270 && (($YTop >= $Settings["YTop"] && $YTop <= $Settings["YBottom"]) || ($YBottom >= $Settings["YTop"] && $YBottom <= $Settings["YBottom"]))) + { $this->shift(180,360,($Height+2),$Reversed); $Done = TRUE; } + if ( $Angle > 270 && $Angle <= 360 && (($YTop >= $Settings["YTop"] && $YTop <= $Settings["YBottom"]) || ($YBottom >= $Settings["YTop"] && $YBottom <= $Settings["YBottom"]))) + { $this->shift(180,360,($Height+2),$Reversed); $Done = TRUE; } + } + } + } + + $LabelSettings = array("YTop"=>$YTop,"YBottom"=>$YBottom,"Label"=>$Label,"Angle"=>$Angle,"X1"=>$X,"Y1"=>$Y,"X2"=>$X2,"Y2"=>$Y2); + if ( $Angle <= 180 ) { $LabelSettings["X3"] = $Xc+$Radius+$LabelOffset; } + if ( $Angle > 180 ) { $LabelSettings["X3"] = $Xc-$Radius-$LabelOffset; } + $this->LabelPos[] = $LabelSettings; + } + } + + /* Internally used to shift label positions */ + function shift($StartAngle,$EndAngle,$Offset,$Reversed) + { + if ( $Reversed ) { $Offset = -$Offset; } + foreach($this->LabelPos as $Key => $Settings) + { + if ( $Settings["Angle"] > $StartAngle && $Settings["Angle"] <= $EndAngle ) { $this->LabelPos[$Key]["YTop"] = $Settings["YTop"] + $Offset; $this->LabelPos[$Key]["YBottom"] = $Settings["YBottom"] + $Offset; $this->LabelPos[$Key]["Y2"] = $Settings["Y2"] + $Offset; } + } + } + + /* Internally used to write the re-computed labels */ + function writeShiftedLabels() + { + if ( $this->LabelPos == "" ) { return(0); } + foreach($this->LabelPos as $Key => $Settings) + { + $X1 = $Settings["X1"]; $Y1 = $Settings["Y1"]; + $X2 = $Settings["X2"]; $Y2 = $Settings["Y2"]; + $X3 = $Settings["X3"]; + $Angle = $Settings["Angle"]; + $Label = $Settings["Label"]; + + $this->pChartObject->drawArrow($X2,$Y2,$X1,$Y1,array("Size"=>8)); + if ( $Angle <= 180 ) + { + $this->pChartObject->drawLine($X2,$Y2,$X3,$Y2); + $this->pChartObject->drawText($X3+2,$Y2,$Label,array("Align"=>TEXT_ALIGN_MIDDLELEFT)); + } + else + { + $this->pChartObject->drawLine($X2,$Y2,$X3,$Y2); + $this->pChartObject->drawText($X3-2,$Y2,$Label,array("Align"=>TEXT_ALIGN_MIDDLERIGHT)); + } + } + } + + /* Draw a ring chart */ + function draw2DRing($X,$Y,$Format="") + { + $OuterRadius = isset($Format["Radius"]) ? $Format["Radius"] : 60; + $Precision = isset($Format["Precision"]) ? $Format["Precision"] : 0; + $InnerRadius = isset($Format["Radius"]) ? $Format["Radius"] : 30; + $Border = isset($Format["Border"]) ? $Format["Border"] : FALSE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : 100; + $Shadow = isset($Format["Shadow"]) ? $Format["Shadow"] : FALSE; + $DrawLabels = isset($Format["DrawLabels"]) ? $Format["DrawLabels"] : FALSE; + $LabelStacked = isset($Format["LabelStacked"]) ? $Format["LabelStacked"] : FALSE; + $LabelColor = isset($Format["LabelColor"]) ? $Format["LabelColor"] : PIE_LABEL_COLOR_MANUAL; + $LabelR = isset($Format["LabelR"]) ? $Format["LabelR"] : 0; + $LabelG = isset($Format["LabelG"]) ? $Format["LabelG"] : 0; + $LabelB = isset($Format["LabelB"]) ? $Format["LabelB"] : 0; + $LabelAlpha = isset($Format["LabelAlpha"]) ? $Format["LabelAlpha"] : 100; + $WriteValues = isset($Format["WriteValues"]) ? $Format["WriteValues"] : NULL; //PIE_VALUE_PERCENTAGE + $ValuePadding = isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : 5; + $ValuePosition = isset($Format["ValuePosition"]) ? $Format["ValuePosition"] : PIE_VALUE_OUTSIDE; + $ValueSuffix = isset($Format["ValueSuffix"]) ? $Format["ValueSuffix"] : ""; + $ValueR = isset($Format["ValueR"]) ? $Format["ValueR"] : 255; + $ValueG = isset($Format["ValueG"]) ? $Format["ValueG"] : 255; + $ValueB = isset($Format["ValueB"]) ? $Format["ValueB"] : 255; + $ValueAlpha = isset($Format["ValueAlpha"]) ? $Format["ValueAlpha"] : 100; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + + /* Data Processing */ + $Data = $this->pDataObject->getData(); + $Palette = $this->pDataObject->getPalette(); + + /* Do we have an abscissa serie defined? */ + if ( $Data["Abscissa"] == "" ) { return(PIE_NO_ABSCISSA); } + + /* Try to find the data serie */ + $DataSerie = ""; + foreach ($Data["Series"] as $SerieName => $SerieData) + { if ( $SerieName != $Data["Abscissa"]) { $DataSerie = $SerieName; } } + + /* Do we have data to compute? */ + if ( $DataSerie == "" ) { return(PIE_NO_DATASERIE); } + + /* Remove unused data */ + list($Data,$Palette) = $this->clean0Values($Data,$Palette,$DataSerie,$Data["Abscissa"]); + + /* Compute the pie sum */ + $SerieSum = $this->pDataObject->getSum($DataSerie); + + /* Do we have data to draw? */ + if ( $SerieSum == 0 ) { return(PIE_SUMISNULL); } + + /* Dump the real number of data to draw */ + $Values = ""; + foreach ($Data["Series"][$DataSerie]["Data"] as $Key => $Value) + { if ($Value != 0) { $Values[] = $Value; } } + + /* Compute the wasted angular space between series */ + if (count($Values)==1) { $WastedAngular = 0; } else { $WastedAngular = 0; } // count($Values) + + /* Compute the scale */ + $ScaleFactor = (360 - $WastedAngular) / $SerieSum; + + $RestoreShadow = $this->pChartObject->Shadow; + if ( $this->pChartObject->Shadow ) + { + $this->pChartObject->Shadow = FALSE; + + $ShadowFormat = $Format; $ShadowFormat["Shadow"] = TRUE; + $this->draw2DRing($X+$this->pChartObject->ShadowX,$Y+$this->pChartObject->ShadowY,$ShadowFormat); + } + + /* Draw the polygon pie elements */ + $Step = 360 / (2 * PI * $OuterRadius); + $Offset = 0; $ID = 0; + foreach($Values as $Key => $Value) + { + if ( $Shadow ) + { + $Settings = array("R"=>$this->pChartObject->ShadowR,"G"=>$this->pChartObject->ShadowG,"B"=>$this->pChartObject->ShadowB,"Alpha"=>$this->pChartObject->Shadowa); + $BorderColor = $Settings; + } + else + { + if ( !isset($Palette[$ID]["R"]) ) { $Color = $this->pChartObject->getRandomColor(); $Palette[$ID] = $Color; $this->pDataObject->savePalette($ID,$Color); } + $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]); + + if ( $Border ) + $BorderColor = array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha); + else + $BorderColor = $Settings; + } + + $Plots = ""; $Boundaries = ""; $AAPixels = ""; + $EndAngle = $Offset+($Value*$ScaleFactor); if ( $EndAngle > 360 ) { $EndAngle = 360; } + for($i=$Offset;$i<=$EndAngle;$i=$i+$Step) + { + $Xc = cos(($i-90)*PI/180) * $OuterRadius + $X; + $Yc = sin(($i-90)*PI/180) * $OuterRadius + $Y; + + if ( !isset($Boundaries[0]["X1"]) ) { $Boundaries[0]["X1"] = $Xc; $Boundaries[0]["Y1"] = $Yc; } + $AAPixels[] = array($Xc,$Yc); + + if ( $i<90 ) { $Yc++; } + if ( $i>180 && $i<270 ) { $Xc++; } + if ( $i>=270 ) { $Xc++; $Yc++; } + + $Plots[] = $Xc; $Plots[] = $Yc; + } + $Boundaries[1]["X1"] = $Xc; $Boundaries[1]["Y1"] = $Yc; + $Lasti = $EndAngle; + + for($i=$EndAngle;$i>=$Offset;$i=$i-$Step) + { + $Xc = cos(($i-90)*PI/180) * ($InnerRadius-1) + $X; + $Yc = sin(($i-90)*PI/180) * ($InnerRadius-1) + $Y; + + if ( !isset($Boundaries[1]["X2"]) ) { $Boundaries[1]["X2"] = $Xc; $Boundaries[1]["Y2"] = $Yc; } + $AAPixels[] = array($Xc,$Yc); + + $Xc = cos(($i-90)*PI/180) * $InnerRadius + $X; + $Yc = sin(($i-90)*PI/180) * $InnerRadius + $Y; + + if ( $i<90 ) { $Yc++; } + if ( $i>180 && $i<270 ) { $Xc++; } + if ( $i>=270 ) { $Xc++; $Yc++; } + + $Plots[] = $Xc; $Plots[] = $Yc; + } + $Boundaries[0]["X2"] = $Xc; $Boundaries[0]["Y2"] = $Yc; + + /* Draw the polygon */ + $this->pChartObject->drawPolygon($Plots,$Settings); + if ( $RecordImageMap && !$Shadow ) { $this->pChartObject->addToImageMap("POLY",$this->arraySerialize($Plots),$this->pChartObject->toHTMLColor($Palette[$ID]["R"],$Palette[$ID]["G"],$Palette[$ID]["B"]),$Data["Series"][$Data["Abscissa"]]["Data"][$Key],$Value); } + + /* Smooth the edges using AA */ + foreach($AAPixels as $iKey => $Pos ) { $this->pChartObject->drawAntialiasPixel($Pos[0],$Pos[1],$BorderColor); } + $this->pChartObject->drawLine($Boundaries[0]["X1"],$Boundaries[0]["Y1"],$Boundaries[0]["X2"],$Boundaries[0]["Y2"],$BorderColor); + $this->pChartObject->drawLine($Boundaries[1]["X1"],$Boundaries[1]["Y1"],$Boundaries[1]["X2"],$Boundaries[1]["Y2"],$BorderColor); + + if ( $DrawLabels && !$Shadow ) + { + if ( $LabelColor == PIE_LABEL_COLOR_AUTO ) + { $Settings = array("FillR"=>$Palette[$ID]["R"],"FillG"=>$Palette[$ID]["G"],"FillB"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);} + else + { $Settings = array("FillR"=>$LabelR,"FillG"=>$LabelG,"FillB"=>$LabelB,"Alpha"=>$LabelAlpha); } + + $Angle = ($EndAngle - $Offset)/2 + $Offset; + $Xc = cos(($Angle-90)*PI/180) * $OuterRadius + $X; + $Yc = sin(($Angle-90)*PI/180) * $OuterRadius + $Y; + + $Label = $Data["Series"][$Data["Abscissa"]]["Data"][$Key]; + + if ( $LabelStacked ) + $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,TRUE,$X,$Y,$OuterRadius); + else + $this->writePieLabel($Xc,$Yc,$Label,$Angle,$Settings,FALSE); + } + + $Offset = $Lasti; $ID++; + } + + if ( $DrawLabels && $LabelStacked ) { $this->writeShiftedLabels(); } + + if ( $WriteValues && !$Shadow ) + { + $Step = 360 / (2 * PI * $OuterRadius); + $Offset = 0; + foreach($Values as $Key => $Value) + { + $EndAngle = $Offset+($Value*$ScaleFactor); + if ( $EndAngle > 360 ) { $EndAngle = 360; } + + $Angle = $Offset+($Value*$ScaleFactor)/2; + if ( $ValuePosition == PIE_VALUE_OUTSIDE ) + { + $Xc = cos(($Angle-90)*PI/180) * ($OuterRadius+$ValuePadding) + $X; + $Yc = sin(($Angle-90)*PI/180) * ($OuterRadius+$ValuePadding) + $Y; + if ( $Angle >=0 && $Angle <= 90 ) { $Align = TEXT_ALIGN_BOTTOMLEFT; } + if ( $Angle > 90 && $Angle <= 180 ) { $Align = TEXT_ALIGN_TOPLEFT; } + if ( $Angle > 180 && $Angle <= 270 ) { $Align = TEXT_ALIGN_TOPRIGHT; } + if ( $Angle > 270 ) { $Align = TEXT_ALIGN_BOTTOMRIGHT; } + } + else + { + $Xc = cos(($Angle-90)*PI/180) * (($OuterRadius-$InnerRadius)/2+$InnerRadius) + $X; + $Yc = sin(($Angle-90)*PI/180) * (($OuterRadius-$InnerRadius)/2+$InnerRadius) + $Y; + $Align = TEXT_ALIGN_MIDDLEMIDDLE; + } + + if ( $WriteValues == PIE_VALUE_PERCENTAGE ) + $Display = round(( 100 / $SerieSum ) * $Value,$Precision)."%"; + elseif ( $WriteValues == PIE_VALUE_NATURAL ) + $Display = $Value.$ValueSuffix; + else + $Label = ""; + + $this->pChartObject->drawText($Xc,$Yc,$Display,array("Align"=>$Align,"R"=>$ValueR,"G"=>$ValueG,"B"=>$ValueB)); + $Offset = $EndAngle; + } + } + + $this->pChartObject->Shadow = $RestoreShadow; + + return(PIE_RENDERED); + } + + /* Draw a 3D ring chart */ + function draw3DRing($X,$Y,$Format="") + { + $OuterRadius = isset($Format["OuterRadius"]) ? $Format["OuterRadius"] : 100; + $Precision = isset($Format["Precision"]) ? $Format["Precision"] : 0; + $InnerRadius = isset($Format["InnerRadius"]) ? $Format["InnerRadius"] : 30; + $SkewFactor = isset($Format["SkewFactor"]) ? $Format["SkewFactor"] : .6; + $SliceHeight = isset($Format["SliceHeight"]) ? $Format["SliceHeight"] : 10; + $DataGapAngle = isset($Format["DataGapAngle"]) ? $Format["DataGapAngle"] : 10; + $DataGapRadius = isset($Format["DataGapRadius"]) ? $Format["DataGapRadius"] : 10; + $Border = isset($Format["Border"]) ? $Format["Border"] : FALSE; + $Shadow = isset($Format["Shadow"]) ? $Format["Shadow"] : FALSE; + $DrawLabels = isset($Format["DrawLabels"]) ? $Format["DrawLabels"] : FALSE; + $LabelStacked = isset($Format["LabelStacked"]) ? $Format["LabelStacked"] : FALSE; + $LabelColor = isset($Format["LabelColor"]) ? $Format["LabelColor"] : PIE_LABEL_COLOR_MANUAL; + $LabelR = isset($Format["LabelR"]) ? $Format["LabelR"] : 0; + $LabelG = isset($Format["LabelG"]) ? $Format["LabelG"] : 0; + $LabelB = isset($Format["LabelB"]) ? $Format["LabelB"] : 0; + $LabelAlpha = isset($Format["LabelAlpha"]) ? $Format["LabelAlpha"] : 100; + $Cf = isset($Format["Cf"]) ? $Format["Cf"] : 20; + $WriteValues = isset($Format["WriteValues"]) ? $Format["WriteValues"] : PIE_VALUE_NATURAL; + $ValuePadding = isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : $SliceHeight + 15; + $ValuePosition = isset($Format["ValuePosition"]) ? $Format["ValuePosition"] : PIE_VALUE_OUTSIDE; + $ValueSuffix = isset($Format["ValueSuffix"]) ? $Format["ValueSuffix"] : ""; + $ValueR = isset($Format["ValueR"]) ? $Format["ValueR"] : 255; + $ValueG = isset($Format["ValueG"]) ? $Format["ValueG"] : 255; + $ValueB = isset($Format["ValueB"]) ? $Format["ValueB"] : 255; + $ValueAlpha = isset($Format["ValueAlpha"]) ? $Format["ValueAlpha"] : 100; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + + /* Error correction for overlaying rounded corners */ + if ( $SkewFactor < .5 ) { $SkewFactor = .5; } + + /* Data Processing */ + $Data = $this->pDataObject->getData(); + $Palette = $this->pDataObject->getPalette(); + + /* Do we have an abscissa serie defined? */ + if ( $Data["Abscissa"] == "" ) { return(PIE_NO_ABSCISSA); } + + /* Try to find the data serie */ + $DataSerie = ""; + foreach ($Data["Series"] as $SerieName => $SerieData) + { if ( $SerieName != $Data["Abscissa"]) { $DataSerie = $SerieName; } } + + /* Do we have data to compute? */ + if ( $DataSerie == "" ) { return(PIE_NO_DATASERIE); } + + /* Remove unused data */ + list($Data,$Palette) = $this->clean0Values($Data,$Palette,$DataSerie,$Data["Abscissa"]); + + /* Compute the pie sum */ + $SerieSum = $this->pDataObject->getSum($DataSerie); + + /* Do we have data to draw? */ + if ( $SerieSum == 0 ) { return(PIE_SUMISNULL); } + + /* Dump the real number of data to draw */ + $Values = ""; + foreach ($Data["Series"][$DataSerie]["Data"] as $Key => $Value) + { if ($Value != 0) { $Values[] = $Value; } } + + /* Compute the wasted angular space between series */ + if (count($Values)==1) { $WastedAngular = 0; } else { $WastedAngular = count($Values) * $DataGapAngle; } + + /* Compute the scale */ + $ScaleFactor = (360 - $WastedAngular) / $SerieSum; + + $RestoreShadow = $this->pChartObject->Shadow; + if ( $this->pChartObject->Shadow ) { $this->pChartObject->Shadow = FALSE; } + + /* Draw the polygon ring elements */ + $Offset = 360; $ID = count($Values)-1; + $Values = array_reverse($Values); + $Slice = 0; $Slices = ""; $SliceColors = ""; $Visible = ""; $SliceAngle = ""; + foreach($Values as $Key => $Value) + { + if ( !isset($Palette[$ID]["R"]) ) { $Color = $this->pChartObject->getRandomColor(); $Palette[$ID] = $Color; $this->pDataObject->savePalette($ID,$Color); } + $Settings = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]); + + $SliceColors[$Slice] = $Settings; + + $StartAngle = $Offset; + $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; } + + if ( $StartAngle > 180 ) { $Visible[$Slice]["Start"] = TRUE; } else { $Visible[$Slice]["Start"] = TRUE; } + if ( $EndAngle < 180 ) { $Visible[$Slice]["End"] = FALSE; } else { $Visible[$Slice]["End"] = TRUE; } + + $Step = (360 / (2 * PI * $OuterRadius))/2; + $OutX1 = VOID; $OutY1 = VOID; + for($i=$Offset;$i>=$EndAngle;$i=$i-$Step) + { + $Xc = cos(($i-90)*PI/180) * ($OuterRadius+$DataGapRadius-2) + $X; + $Yc = sin(($i-90)*PI/180) * ($OuterRadius+$DataGapRadius-2)*$SkewFactor + $Y; + $Slices[$Slice]["AA"][] = array($Xc,$Yc); + + $Xc = cos(($i-90)*PI/180) * ($OuterRadius+$DataGapRadius-1) + $X; + $Yc = sin(($i-90)*PI/180) * ($OuterRadius+$DataGapRadius-1)*$SkewFactor + $Y; + $Slices[$Slice]["AA"][] = array($Xc,$Yc); + + $Xc = cos(($i-90)*PI/180) * ($OuterRadius+$DataGapRadius) + $X; + $Yc = sin(($i-90)*PI/180) * ($OuterRadius+$DataGapRadius)*$SkewFactor + $Y; + $this->pChartObject->drawAntialiasPixel($Xc,$Yc,$Settings); + + if ( $OutX1 == VOID ) { $OutX1 = $Xc; $OutY1 = $Yc; } + + if ( $i<90 ) { $Yc++; } + if ( $i>90 && $i<180 ) { $Xc++; } + if ( $i>180 && $i<270 ) { $Xc++; } + if ( $i>=270 ) { $Xc++; $Yc++; } + + $Slices[$Slice]["BottomPoly"][] = floor($Xc); $Slices[$Slice]["BottomPoly"][] = floor($Yc); + $Slices[$Slice]["TopPoly"][] = floor($Xc); $Slices[$Slice]["TopPoly"][] = floor($Yc)-$SliceHeight; + $Slices[$Slice]["Angle"][] = $i; + } + $OutX2 = $Xc; $OutY2 = $Yc; + + $Slices[$Slice]["Angle"][] = VOID; + $Lasti = $i; + + $Step = (360 / (2 * PI * $InnerRadius))/2; + $InX1 = VOID; $InY1 = VOID; + for($i=$EndAngle;$i<=$Offset;$i=$i+$Step) + { + $Xc = cos(($i-90)*PI/180) * ($InnerRadius+$DataGapRadius-1) + $X; + $Yc = sin(($i-90)*PI/180) * ($InnerRadius+$DataGapRadius-1)*$SkewFactor + $Y; + $Slices[$Slice]["AA"][] = array($Xc,$Yc); + + $Xc = cos(($i-90)*PI/180) * ($InnerRadius+$DataGapRadius) + $X; + $Yc = sin(($i-90)*PI/180) * ($InnerRadius+$DataGapRadius)*$SkewFactor + $Y; + $Slices[$Slice]["AA"][] = array($Xc,$Yc); + + if ( $InX1 == VOID ) { $InX1 = $Xc; $InY1 = $Yc; } + + if ( $i<90 ) { $Yc++; } + if ( $i>90 && $i<180 ) { $Xc++; } + if ( $i>180 && $i<270 ) { $Xc++; } + if ( $i>=270 ) { $Xc++; $Yc++; } + + $Slices[$Slice]["BottomPoly"][] = floor($Xc); $Slices[$Slice]["BottomPoly"][] = floor($Yc); + $Slices[$Slice]["TopPoly"][] = floor($Xc); $Slices[$Slice]["TopPoly"][] = floor($Yc)-$SliceHeight; + $Slices[$Slice]["Angle"][] = $i; + } + $InX2 = $Xc; $InY2 = $Yc; + + $Slices[$Slice]["InX1"] = $InX1; $Slices[$Slice]["InY1"] = $InY1; + $Slices[$Slice]["InX2"] = $InX2; $Slices[$Slice]["InY2"] = $InY2; + $Slices[$Slice]["OutX1"] = $OutX1; $Slices[$Slice]["OutY1"] = $OutY1; + $Slices[$Slice]["OutX2"] = $OutX2; $Slices[$Slice]["OutY2"] = $OutY2; + + $Offset = $Lasti - $DataGapAngle; $ID--; $Slice++; + } + + /* Draw the bottom pie splice */ + foreach($Slices as $SliceID => $Plots) + { + $Settings = $SliceColors[$SliceID]; $Settings["NoBorder"] = TRUE; + $this->pChartObject->drawPolygon($Plots["BottomPoly"],$Settings); + + foreach($Plots["AA"] as $Key => $Pos) + $this->pChartObject->drawAntialiasPixel($Pos[0],$Pos[1],$Settings); + + $this->pChartObject->drawLine($Plots["InX1"],$Plots["InY1"],$Plots["OutX2"],$Plots["OutY2"],$Settings); + $this->pChartObject->drawLine($Plots["InX2"],$Plots["InY2"],$Plots["OutX1"],$Plots["OutY1"],$Settings); + } + + $Slices = array_reverse($Slices); + $SliceColors = array_reverse($SliceColors); + + /* Draw the vertical edges (semi-visible) */ + foreach($Slices as $SliceID => $Plots) + { + $Settings = $SliceColors[$SliceID]; $Settings["NoBorder"] = TRUE; + $Settings["R"] = $Settings["R"]+$Cf; $Settings["G"] = $Settings["G"]+$Cf; $Settings["B"] = $Settings["B"]+$Cf; + + $StartAngle = $Plots["Angle"][0]; + foreach($Plots["Angle"] as $Key =>$Angle) { if ($Angle == VOID) { $EndAngle = $Plots["Angle"][$Key-1]; } } + + if ( $StartAngle >= 270 || $StartAngle <= 90 ) + $this->pChartObject->drawLine($Plots["OutX1"],$Plots["OutY1"],$Plots["OutX1"],$Plots["OutY1"]-$SliceHeight,$Settings); + if ( $StartAngle >= 270 || $StartAngle <= 90 ) + $this->pChartObject->drawLine($Plots["OutX2"],$Plots["OutY2"],$Plots["OutX2"],$Plots["OutY2"]-$SliceHeight,$Settings); + + $this->pChartObject->drawLine($Plots["InX1"],$Plots["InY1"],$Plots["InX1"],$Plots["InY1"]-$SliceHeight,$Settings); + $this->pChartObject->drawLine($Plots["InX2"],$Plots["InY2"],$Plots["InX2"],$Plots["InY2"]-$SliceHeight,$Settings); + } + + /* Draw the inner vertical slices */ + foreach($Slices as $SliceID => $Plots) + { + $Settings = $SliceColors[$SliceID]; $Settings["NoBorder"] = TRUE; + $Settings["R"] = $Settings["R"]+$Cf; $Settings["G"] = $Settings["G"]+$Cf; $Settings["B"] = $Settings["B"]+$Cf; + + $Outer = TRUE; $Inner = FALSE; + $InnerPlotsA = ""; $InnerPlotsB = ""; + foreach($Plots["Angle"] as $ID => $Angle) + { + if ( $Angle == VOID ) + { $Outer = FALSE; $Inner = TRUE; } + elseif( $Inner ) + { + if (( $Angle < 90 || $Angle > 270 ) && isset($Plots["BottomPoly"][$ID*2]) ) + { + $Xo = $Plots["BottomPoly"][$ID*2]; + $Yo = $Plots["BottomPoly"][$ID*2+1]; + + $InnerPlotsA[] = $Xo; $InnerPlotsA[] = $Yo; + $InnerPlotsB[] = $Xo; $InnerPlotsB[] = $Yo-$SliceHeight; + } + } + } + + if ( $InnerPlotsA != "" ) + { $InnerPlots = array_merge($InnerPlotsA,$this->arrayReverse($InnerPlotsB)); $this->pChartObject->drawPolygon($InnerPlots,$Settings); } + } + + /* Draw the splice top and left poly */ + foreach($Slices as $SliceID => $Plots) + { + $Settings = $SliceColors[$SliceID]; $Settings["NoBorder"] = TRUE; + $Settings["R"] = $Settings["R"]+$Cf*1.5; $Settings["G"] = $Settings["G"]+$Cf*1.5; $Settings["B"] = $Settings["B"]+$Cf*1.5; + + $StartAngle = $Plots["Angle"][0]; + foreach($Plots["Angle"] as $Key =>$Angle) { if ($Angle == VOID) { $EndAngle = $Plots["Angle"][$Key-1]; } } + + if ( $StartAngle < 180 ) + { + $Points = ""; + $Points[] = $Plots["InX2"]; + $Points[] = $Plots["InY2"]; + $Points[] = $Plots["InX2"]; + $Points[] = $Plots["InY2"]-$SliceHeight; + $Points[] = $Plots["OutX1"]; + $Points[] = $Plots["OutY1"]-$SliceHeight; + $Points[] = $Plots["OutX1"]; + $Points[] = $Plots["OutY1"]; + + $this->pChartObject->drawPolygon($Points,$Settings); + } + + if ( $EndAngle > 180 ) + { + $Points = ""; + $Points[] = $Plots["InX1"]; + $Points[] = $Plots["InY1"]; + $Points[] = $Plots["InX1"]; + $Points[] = $Plots["InY1"]-$SliceHeight; + $Points[] = $Plots["OutX2"]; + $Points[] = $Plots["OutY2"]-$SliceHeight; + $Points[] = $Plots["OutX2"]; + $Points[] = $Plots["OutY2"]; + + $this->pChartObject->drawPolygon($Points,$Settings); + } + } + + + /* Draw the vertical edges (visible) */ + foreach($Slices as $SliceID => $Plots) + { + $Settings = $SliceColors[$SliceID]; $Settings["NoBorder"] = TRUE; + $Settings["R"] = $Settings["R"]+$Cf; $Settings["G"] = $Settings["G"]+$Cf; $Settings["B"] = $Settings["B"]+$Cf; + + $StartAngle = $Plots["Angle"][0]; + foreach($Plots["Angle"] as $Key =>$Angle) { if ($Angle == VOID) { $EndAngle = $Plots["Angle"][$Key-1]; } } + + if ( $StartAngle <= 270 && $StartAngle >= 90 ) + $this->pChartObject->drawLine($Plots["OutX1"],$Plots["OutY1"],$Plots["OutX1"],$Plots["OutY1"]-$SliceHeight,$Settings); + if ( $EndAngle <= 270 && $EndAngle >= 90 ) + $this->pChartObject->drawLine($Plots["OutX2"],$Plots["OutY2"],$Plots["OutX2"],$Plots["OutY2"]-$SliceHeight,$Settings); + } + + + /* Draw the outer vertical slices */ + foreach($Slices as $SliceID => $Plots) + { + $Settings = $SliceColors[$SliceID]; $Settings["NoBorder"] = TRUE; + $Settings["R"] = $Settings["R"]+$Cf; $Settings["G"] = $Settings["G"]+$Cf; $Settings["B"] = $Settings["B"]+$Cf; + + $Outer = TRUE; $Inner = FALSE; + $OuterPlotsA = ""; $OuterPlotsB = ""; $InnerPlotsA = ""; $InnerPlotsB = ""; + foreach($Plots["Angle"] as $ID => $Angle) + { + if ( $Angle == VOID ) + { $Outer = FALSE; $Inner = TRUE; } + elseif( $Outer ) + { + if ( ( $Angle > 90 && $Angle < 270 ) && isset($Plots["BottomPoly"][$ID*2]) ) + { + $Xo = $Plots["BottomPoly"][$ID*2]; + $Yo = $Plots["BottomPoly"][$ID*2+1]; + + $OuterPlotsA[] = $Xo; $OuterPlotsA[] = $Yo; + $OuterPlotsB[] = $Xo; $OuterPlotsB[] = $Yo-$SliceHeight; + } + } + } + if ( $OuterPlotsA != "" ) + { $OuterPlots = array_merge($OuterPlotsA,$this->arrayReverse($OuterPlotsB)); $this->pChartObject->drawPolygon($OuterPlots,$Settings); } + } + + $Slices = array_reverse($Slices); + $SliceColors = array_reverse($SliceColors); + + + /* Draw the top pie splice */ + foreach($Slices as $SliceID => $Plots) + { + $Settings = $SliceColors[$SliceID]; $Settings["NoBorder"] = TRUE; + $Settings["R"] = $Settings["R"]+$Cf*2; $Settings["G"] = $Settings["G"]+$Cf*2; $Settings["B"] = $Settings["B"]+$Cf*2; + + $this->pChartObject->drawPolygon($Plots["TopPoly"],$Settings); + + if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("POLY",$this->arraySerialize($Plots["TopPoly"]),$this->pChartObject->toHTMLColor($Settings["R"],$Settings["G"],$Settings["B"]),$Data["Series"][$Data["Abscissa"]]["Data"][$SliceID],$Data["Series"][$DataSerie]["Data"][count($Slices)-$SliceID-1]); } + + foreach($Plots["AA"] as $Key => $Pos) + $this->pChartObject->drawAntialiasPixel($Pos[0],$Pos[1]-$SliceHeight,$Settings); + + $this->pChartObject->drawLine($Plots["InX1"],$Plots["InY1"]-$SliceHeight,$Plots["OutX2"],$Plots["OutY2"]-$SliceHeight,$Settings); + $this->pChartObject->drawLine($Plots["InX2"],$Plots["InY2"]-$SliceHeight,$Plots["OutX1"],$Plots["OutY1"]-$SliceHeight,$Settings); + } + + if ( $DrawLabels ) + { + $Offset = 360; + foreach($Values as $Key => $Value) + { + $StartAngle = $Offset; + $EndAngle = $Offset-($Value*$ScaleFactor); if ( $EndAngle < 0 ) { $EndAngle = 0; } + + if ( $LabelColor == PIE_LABEL_COLOR_AUTO ) + { $Settings = array("FillR"=>$Palette[$ID]["R"],"FillG"=>$Palette[$ID]["G"],"FillB"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"]);} + else + { $Settings = array("FillR"=>$LabelR,"FillG"=>$LabelG,"FillB"=>$LabelB,"Alpha"=>$LabelAlpha); } + + $Angle = ($EndAngle - $Offset)/2 + $Offset; + $Xc = cos(($Angle-90)*PI/180) * ($OuterRadius+$DataGapRadius) + $X; + $Yc = sin(($Angle-90)*PI/180) * ($OuterRadius+$DataGapRadius)*$SkewFactor + $Y; + + if ( $WriteValues == PIE_VALUE_PERCENTAGE ) + $Label = $Display = round(( 100 / $SerieSum ) * $Value,$Precision)."%"; + elseif ( $WriteValues == PIE_VALUE_NATURAL ) + $Label = $Data["Series"][$Data["Abscissa"]]["Data"][$Key]; + else + $Label = ""; + + if ( $LabelStacked ) + $this->writePieLabel($Xc,$Yc-$SliceHeight,$Label,$Angle,$Settings,TRUE,$X,$Y,$OuterRadius); + else + $this->writePieLabel($Xc,$Yc-$SliceHeight,$Label,$Angle,$Settings,FALSE); + + $Offset = $EndAngle - $DataGapAngle; $ID--; $Slice++; + } + } + if ( $DrawLabels && $LabelStacked ) { $this->writeShiftedLabels(); } + + $this->pChartObject->Shadow = $RestoreShadow; + + return(PIE_RENDERED); + } + + /* Serialize an array */ + function arraySerialize($Data) + { + $Result = ""; + foreach($Data as $Key => $Value) + { if ($Result == "") { $Result = floor($Value); } else { $Result = $Result.",".floor($Value); } } + + return($Result); + } + + /* Reverse an array */ + function arrayReverse($Plots) + { + $Result = ""; + + for($i=count($Plots)-1;$i>=0;$i=$i-2) + { $Result[] = $Plots[$i-1]; $Result[] = $Plots[$i]; } + + return($Result); + } + + /* Remove unused series & values */ + function clean0Values($Data,$Palette,$DataSerie,$AbscissaSerie) + { + $NewPalette = ""; $NewData = ""; $NewAbscissa = ""; + + /* Remove unused series */ + foreach($Data["Series"] as $SerieName => $SerieSettings) + { if ( $SerieName != $DataSerie && $SerieName != $AbscissaSerie ) { unset($Data["Series"][$SerieName]); } } + + /* Remove NULL values */ + foreach($Data["Series"][$DataSerie]["Data"] as $Key => $Value) + { + if ($Value != 0 ) + { + $NewData[] = $Value; + $NewAbscissa[] = $Data["Series"][$AbscissaSerie]["Data"][$Key]; + if ( isset($Palette[$Key]) ) { $NewPalette[] = $Palette[$Key]; } + } + } + $Data["Series"][$DataSerie]["Data"] = $NewData; + $Data["Series"][$AbscissaSerie]["Data"] = $NewAbscissa; + + return(array($Data,$NewPalette)); + } + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/class/pRadar.class.php b/trunk/includes/pChart/class/pRadar.class.php new file mode 100644 index 0000000..af15bbf --- /dev/null +++ b/trunk/includes/pChart/class/pRadar.class.php @@ -0,0 +1,681 @@ +pChartObject = $Object; + + $FixedMax = isset($Format["FixedMax"]) ? $Format["FixedMax"] : VOID; + $AxisR = isset($Format["AxisR"]) ? $Format["AxisR"] : 60; + $AxisG = isset($Format["AxisG"]) ? $Format["AxisG"] : 60; + $AxisB = isset($Format["AxisB"]) ? $Format["AxisB"] : 60; + $AxisAlpha = isset($Format["AxisAlpha"]) ? $Format["AxisAlpha"] : 50; + $AxisRotation = isset($Format["AxisRotation"]) ? $Format["AxisRotation"] : 0; + $DrawTicks = isset($Format["DrawTicks"]) ? $Format["DrawTicks"] : TRUE; + $TicksLength = isset($Format["TicksLength"]) ? $Format["TicksLength"] : 2; + $DrawAxisValues = isset($Format["DrawAxisValues"]) ? $Format["DrawAxisValues"] : TRUE; + $AxisBoxRounded = isset($Format["AxisBoxRounded"]) ? $Format["AxisBoxRounded"] : TRUE; + $AxisFontName = isset($Format["AxisFontName"]) ? $Format["AxisFontName"] : $this->pChartObject->FontName; + $AxisFontSize = isset($Format["AxisFontSize"]) ? $Format["AxisFontSize"] : $this->pChartObject->FontSize; + $WriteValues = isset($Format["WriteValues"]) ? $Format["WriteValues"] : FALSE; + $WriteValuesInBubble = isset($Format["WriteValuesInBubble"]) ? $Format["WriteValuesInBubble"] : TRUE; + $ValueFontName = isset($Format["ValueFontName"]) ? $Format["ValueFontName"] : $this->pChartObject->FontName; + $ValueFontSize = isset($Format["ValueFontSize"]) ? $Format["ValueFontSize"] : $this->pChartObject->FontSize; + $ValuePadding = isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : 4; + $OuterBubbleRadius = isset($Format["OuterBubbleRadius"]) ? $Format["OuterBubbleRadius"] : 2; + $OuterBubbleR = isset($Format["OuterBubbleR"]) ? $Format["OuterBubbleR"] : VOID; + $OuterBubbleG = isset($Format["OuterBubbleG"]) ? $Format["OuterBubbleG"] : VOID; + $OuterBubbleB = isset($Format["OuterBubbleB"]) ? $Format["OuterBubbleB"] : VOID; + $OuterBubbleAlpha = isset($Format["OuterBubbleAlpha"]) ? $Format["OuterBubbleAlpha"] : 100; + $InnerBubbleR = isset($Format["InnerBubbleR"]) ? $Format["InnerBubbleR"] : 255; + $InnerBubbleG = isset($Format["InnerBubbleG"]) ? $Format["InnerBubbleG"] : 255; + $InnerBubbleB = isset($Format["InnerBubbleB"]) ? $Format["InnerBubbleB"] : 255; + $InnerBubbleAlpha = isset($Format["InnerBubbleAlpha"]) ? $Format["InnerBubbleAlpha"] : 100; + $DrawBackground = isset($Format["DrawBackground"]) ? $Format["DrawBackground"] : TRUE; + $BackgroundR = isset($Format["BackgroundR"]) ? $Format["BackgroundR"] : 255; + $BackgroundG = isset($Format["BackgroundG"]) ? $Format["BackgroundG"] : 255; + $BackgroundB = isset($Format["BackgroundB"]) ? $Format["BackgroundB"] : 255; + $BackgroundAlpha = isset($Format["BackgroundAlpha"]) ? $Format["BackgroundAlpha"] : 50; + $BackgroundGradient= isset($Format["BackgroundGradient"]) ? $Format["BackgroundGradient"] : NULL; + $Layout = isset($Format["Layout"]) ? $Format["Layout"] : RADAR_LAYOUT_STAR; + $SegmentHeight = isset($Format["SegmentHeight"]) ? $Format["SegmentHeight"] : SEGMENT_HEIGHT_AUTO; + $Segments = isset($Format["Segments"]) ? $Format["Segments"] : 4; + $WriteLabels = isset($Format["WriteLabels"]) ? $Format["WriteLabels"] : TRUE; + $SkipLabels = isset($Format["SkipLabels"]) ? $Format["SkipLabels"] : 1; + $LabelMiddle = isset($Format["LabelMiddle"]) ? $Format["LabelMiddle"] : FALSE; + $LabelsBackground = isset($Format["LabelsBackground"]) ? $Format["LabelsBackground"] : TRUE; + $LabelsBGR = isset($Format["LabelsBGR"]) ? $Format["LabelsBGR"] : 255; + $LabelsBGG = isset($Format["LabelsBGR"]) ? $Format["LabelsBGG"] : 255; + $LabelsBGB = isset($Format["LabelsBGR"]) ? $Format["LabelsBGB"] : 255; + $LabelsBGAlpha = isset($Format["LabelsBGAlpha"]) ? $Format["LabelsBGAlpha"] : 50; + $LabelPos = isset($Format["LabelPos"]) ? $Format["LabelPos"] : RADAR_LABELS_ROTATED; + $LabelPadding = isset($Format["LabelPadding"]) ? $Format["LabelPadding"] : 4; + $DrawPoints = isset($Format["DrawPoints"]) ? $Format["DrawPoints"] : TRUE; + $PointRadius = isset($Format["PointRadius"]) ? $Format["PointRadius"] : 4; + $PointSurrounding = isset($Format["PointRadius"]) ? $Format["PointRadius"] : -30; + $DrawLines = isset($Format["DrawLines"]) ? $Format["DrawLines"] : TRUE; + $LineLoopStart = isset($Format["LineLoopStart"]) ? $Format["LineLoopStart"] : TRUE; + $DrawPoly = isset($Format["DrawPoly"]) ? $Format["DrawPoly"] : FALSE; + $PolyAlpha = isset($Format["PolyAlpha"]) ? $Format["PolyAlpha"] : 40; + $FontSize = $Object->FontSize; + $X1 = $Object->GraphAreaX1; + $Y1 = $Object->GraphAreaY1; + $X2 = $Object->GraphAreaX2; + $Y2 = $Object->GraphAreaY2; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + + /* Cancel default tick length if ticks not enabled */ + if ( $DrawTicks == FALSE ) { $TicksLength = 0; } + + /* Data Processing */ + $Data = $Values->getData(); + $Palette = $Values->getPalette(); + + /* Catch the number of required axis */ + $LabelSerie = $Data["Abscissa"]; + if ( $LabelSerie != "" ) + { $Points = count($Data["Series"][$LabelSerie]["Data"]); } + else + { + $Points = 0; + foreach($Data["Series"] as $SerieName => $DataArray) + { if ( count($DataArray["Data"]) > $Points ) { $Points = count($DataArray["Data"]); } } + } + + /* Draw the axis */ + $CenterX = ($X2-$X1)/2 + $X1; + $CenterY = ($Y2-$Y1)/2 + $Y1; + + $EdgeHeight = min(($X2-$X1)/2,($Y2-$Y1)/2); + if ( $WriteLabels ) + $EdgeHeight = $EdgeHeight - $FontSize - $LabelPadding - $TicksLength; + + /* Determine the scale if set to automatic */ + if ( $SegmentHeight == SEGMENT_HEIGHT_AUTO) + { + if ( $FixedMax != VOID ) + $Max = $FixedMax; + else + { + $Max = 0; + foreach($Data["Series"] as $SerieName => $DataArray) + { + if ( $SerieName != $LabelSerie ) + { + if ( max($DataArray["Data"]) > $Max ) { $Max = max($DataArray["Data"]); } + } + } + } + $MaxSegments = $EdgeHeight/20; + $Scale = $Object->computeScale(0,$Max,$MaxSegments,array(1,2,5)); + + $Segments = $Scale["Rows"]; + $SegmentHeight = $Scale["RowHeight"]; + } + + if ( $LabelMiddle && $SkipLabels == 1 ) + { $Axisoffset = (360/$Points)/2; } + elseif ( $LabelMiddle && $SkipLabels != 1 ) + { $Axisoffset = (360/($Points/$SkipLabels))/2; } + elseif ( !$LabelMiddle ) + { $Axisoffset = 0; } + + /* Background processing */ + if ( $DrawBackground ) + { + $RestoreShadow = $Object->Shadow; + $Object->Shadow = FALSE; + + if ($BackgroundGradient == NULL) + { + if ( $Layout == RADAR_LAYOUT_STAR ) + { + $Color = array("R"=>$BackgroundR,"G"=>$BackgroundG,"B"=>$BackgroundB,"Alpha"=>$BackgroundAlpha); + $PointArray = ""; + for($i=0;$i<=360;$i=$i+(360/$Points)) + { + $PointArray[] = cos(deg2rad($i+$AxisRotation)) * $EdgeHeight + $CenterX; + $PointArray[] = sin(deg2rad($i+$AxisRotation)) * $EdgeHeight + $CenterY; + } + $Object->drawPolygon($PointArray,$Color); + } + elseif ( $Layout == RADAR_LAYOUT_CIRCLE ) + { + $Color = array("R"=>$BackgroundR,"G"=>$BackgroundG,"B"=>$BackgroundB,"Alpha"=>$BackgroundAlpha); + $Object->drawFilledCircle($CenterX,$CenterY,$EdgeHeight,$Color); + } + } + else + { + $GradientROffset = ($BackgroundGradient["EndR"] - $BackgroundGradient["StartR"]) / $Segments; + $GradientGOffset = ($BackgroundGradient["EndG"] - $BackgroundGradient["StartG"]) / $Segments; + $GradientBOffset = ($BackgroundGradient["EndB"] - $BackgroundGradient["StartB"]) / $Segments; + $GradientAlphaOffset = ($BackgroundGradient["EndAlpha"] - $BackgroundGradient["StartAlpha"]) / $Segments; + + if ( $Layout == RADAR_LAYOUT_STAR ) + { + for($j=$Segments;$j>=1;$j--) + { + $Color = array("R"=>$BackgroundGradient["StartR"]+$GradientROffset*$j,"G"=>$BackgroundGradient["StartG"]+$GradientGOffset*$j,"B"=>$BackgroundGradient["StartB"]+$GradientBOffset*$j,"Alpha"=>$BackgroundGradient["StartAlpha"]+$GradientAlphaOffset*$j); + $PointArray = ""; + + for($i=0;$i<=360;$i=$i+(360/$Points)) + { + $PointArray[] = cos(deg2rad($i+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterX; + $PointArray[] = sin(deg2rad($i+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterY; + } + $Object->drawPolygon($PointArray,$Color); + } + } + elseif ( $Layout == RADAR_LAYOUT_CIRCLE ) + { + for($j=$Segments;$j>=1;$j--) + { + $Color = array("R"=>$BackgroundGradient["StartR"]+$GradientROffset*$j,"G"=>$BackgroundGradient["StartG"]+$GradientGOffset*$j,"B"=>$BackgroundGradient["StartB"]+$GradientBOffset*$j,"Alpha"=>$BackgroundGradient["StartAlpha"]+$GradientAlphaOffset*$j); + $Object->drawFilledCircle($CenterX,$CenterY,($EdgeHeight/$Segments)*$j,$Color); + } + } + } + $Object->Shadow = $RestoreShadow; + } + + /* Axis to axis lines */ + $Color = array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha); + $ColorDotted = array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha*.8, "Ticks"=>2); + if ( $Layout == RADAR_LAYOUT_STAR ) + { + for($j=1;$j<=$Segments;$j++) + { + for($i=0;$i<360;$i=$i+(360/$Points)) + { + $EdgeX1 = cos(deg2rad($i+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterX; + $EdgeY1 = sin(deg2rad($i+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterY; + $EdgeX2 = cos(deg2rad($i+$AxisRotation+(360/$Points))) * ($EdgeHeight/$Segments)*$j + $CenterX; + $EdgeY2 = sin(deg2rad($i+$AxisRotation+(360/$Points))) * ($EdgeHeight/$Segments)*$j + $CenterY; + + $Object->drawLine($EdgeX1,$EdgeY1,$EdgeX2,$EdgeY2,$Color); + } + } + } + elseif ( $Layout == RADAR_LAYOUT_CIRCLE ) + { + for($j=1;$j<=$Segments;$j++) + { + $Radius = ($EdgeHeight/$Segments)*$j; + $Object->drawCircle($CenterX,$CenterY,$Radius,$Radius,$Color); + } + } + + if ( $DrawAxisValues ) + { + if ( $LabelsBackground ) + $Options = array("DrawBox"=>TRUE, "Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"BoxR"=>$LabelsBGR,"BoxG"=>$LabelsBGG,"BoxB"=>$LabelsBGB,"BoxAlpha"=>$LabelsBGAlpha); + else + $Options = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE); + + if ( $AxisBoxRounded ) { $Options["BoxRounded"] = TRUE; } + + $Options["FontName"] = $AxisFontName; + $Options["FontSize"] = $AxisFontSize; + + $Angle = 360 / ($Points*2); + for($j=1;$j<=$Segments;$j++) + { + $Label = $j * $SegmentHeight; + + if ( $Layout == RADAR_LAYOUT_CIRCLE ) + { + $EdgeX1 = cos(deg2rad($Angle+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterX; + $EdgeY1 = sin(deg2rad($Angle+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterY; + } + elseif ( $Layout == RADAR_LAYOUT_STAR ) + { + $EdgeX1 = cos(deg2rad($AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterX; + $EdgeY1 = sin(deg2rad($AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterY; + $EdgeX2 = cos(deg2rad((360 / $Points) + $AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterX; + $EdgeY2 = sin(deg2rad((360 / $Points) + $AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterY; + + $EdgeX1 = ($EdgeX2 - $EdgeX1)/2 + $EdgeX1; + $EdgeY1 = ($EdgeY2 - $EdgeY1)/2 + $EdgeY1; + } + + $Object->drawText($EdgeX1,$EdgeY1,$Label,$Options); + } + } + + /* Axis lines */ + $ID = 0; + for($i=0;$i<360;$i=$i+(360/$Points)) + { + $EdgeX = cos(deg2rad($i+$AxisRotation)) * ($EdgeHeight+$TicksLength) + $CenterX; + $EdgeY = sin(deg2rad($i+$AxisRotation)) * ($EdgeHeight+$TicksLength) + $CenterY; + + if ($ID % $SkipLabels == 0) + { $Object->drawLine($CenterX,$CenterY,$EdgeX,$EdgeY,$Color); } + else + { $Object->drawLine($CenterX,$CenterY,$EdgeX,$EdgeY,$ColorDotted); } + + if ( $WriteLabels ) + { + $LabelX = cos(deg2rad($i+$AxisRotation+$Axisoffset)) * ($EdgeHeight+$LabelPadding+$TicksLength) + $CenterX; + $LabelY = sin(deg2rad($i+$AxisRotation+$Axisoffset)) * ($EdgeHeight+$LabelPadding+$TicksLength) + $CenterY; + + if ( $LabelSerie != "" ) + { $Label = isset($Data["Series"][$LabelSerie]["Data"][$ID]) ? $Data["Series"][$LabelSerie]["Data"][$ID] : ""; } + else + $Label = $ID; + + if ($ID % $SkipLabels == 0) + { + if ( $LabelPos == RADAR_LABELS_ROTATED ) + $Object->drawText($LabelX,$LabelY,$Label,array("Angle"=>(360-($i+$AxisRotation+$Axisoffset))-90,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + else + { + if ( (floor($LabelX) == floor($CenterX)) && (floor($LabelY) < floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); } + if ( (floor($LabelX) > floor($CenterX)) && (floor($LabelY) < floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_BOTTOMLEFT)); } + if ( (floor($LabelX) > floor($CenterX)) && (floor($LabelY) == floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_MIDDLELEFT)); } + if ( (floor($LabelX) > floor($CenterX)) && (floor($LabelY) > floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_TOPLEFT)); } + if ( (floor($LabelX) < floor($CenterX)) && (floor($LabelY) < floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_BOTTOMRIGHT)); } + if ( (floor($LabelX) < floor($CenterX)) && (floor($LabelY) == floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_MIDDLERIGHT)); } + if ( (floor($LabelX) < floor($CenterX)) && (floor($LabelY) > floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_TOPRIGHT)); } + if ( (floor($LabelX) == floor($CenterX)) && (floor($LabelY) > floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_TOPMIDDLE)); } + } + } + } + $ID++; + } + + /* Compute the plots position */ + $ID = 0; $Plot = ""; + foreach($Data["Series"] as $SerieName => $DataS) + { + if ( $SerieName != $LabelSerie ) + { + $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"],"Surrounding"=>$PointSurrounding); + foreach($DataS["Data"] as $Key => $Value) + { + $Angle = (360/$Points) * $Key; + $Length = ($EdgeHeight/($Segments*$SegmentHeight))*$Value; + + $X = cos(deg2rad($Angle+$AxisRotation)) * $Length + $CenterX; + $Y = sin(deg2rad($Angle+$AxisRotation)) * $Length + $CenterY; + + $Plot[$ID][] = array($X,$Y,$Value); + + if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".floor($PointRadius),$this->pChartObject->toHTMLColor($Palette[$ID]["R"],$Palette[$ID]["G"],$Palette[$ID]["B"]),$DataS["Description"],$Data["Series"][$LabelSerie]["Data"][$Key]." = ".$Value); } + } + $ID++; + } + } + + /* Draw all that stuff! */ + foreach($Plot as $ID => $Points) + { + $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"],"Surrounding"=>$PointSurrounding); + + /* Draw the polygons */ + if ( $DrawPoly ) + { + if ($PolyAlpha != NULL) + $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$PolyAlpha,"Surrounding"=>$PointSurrounding); + + $PointsArray = ""; + for($i=0; $idrawPolygon($PointsArray,$Color); + } + + $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"],"Surrounding"=>$PointSurrounding); + + /* Bubble and labels settings */ + $TextSettings = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontName"=>$ValueFontName,"FontSize"=>$ValueFontSize,"R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"]); + $InnerColor = array("R"=>$InnerBubbleR,"G"=>$InnerBubbleG,"B"=>$InnerBubbleB,"Alpha"=>$InnerBubbleAlpha); + if ( $OuterBubbleR != VOID ) + $OuterColor = array("R"=>$OuterBubbleR,"G"=>$OuterBubbleG,"B"=>$OuterBubbleB,"Alpha"=>$OuterBubbleAlpha); + else + $OuterColor = array("R"=>$Palette[$ID]["R"]+20,"G"=>$Palette[$ID]["G"]+20,"B"=>$Palette[$ID]["B"]+20,"Alpha"=>$Palette[$ID]["Alpha"]); + + /* Loop to the starting points if asked */ + if ( $LineLoopStart && $DrawLines ) + $Object->drawLine($Points[count($Points)-1][0],$Points[count($Points)-1][1],$Points[0][0],$Points[0][1],$Color); + + /* Draw the lines & points */ + for($i=0; $idrawLine($Points[$i][0],$Points[$i][1],$Points[$i+1][0],$Points[$i+1][1],$Color); + + if ( $DrawPoints ) + $Object->drawFilledCircle($Points[$i][0],$Points[$i][1],$PointRadius,$Color); + + if ( $WriteValuesInBubble && $WriteValues ) + { + $TxtPos = $this->pChartObject->getTextBox($Points[$i][0],$Points[$i][1],$ValueFontName,$ValueFontSize,0,$Points[$i][2]); + $Radius = floor(($TxtPos[1]["X"] - $TxtPos[0]["X"] + $ValuePadding*2)/2); + + $this->pChartObject->drawFilledCircle($Points[$i][0],$Points[$i][1],$Radius+$OuterBubbleRadius,$OuterColor); + $this->pChartObject->drawFilledCircle($Points[$i][0],$Points[$i][1],$Radius,$InnerColor); + } + + if ( $WriteValues ) + $this->pChartObject->drawText($Points[$i][0]-1,$Points[$i][1]-1,$Points[$i][2],$TextSettings); + } + } + } + + + + /* Draw a radar chart */ + function drawPolar($Object,$Values,$Format="") + { + $this->pChartObject = $Object; + + $FixedMax = isset($Format["FixedMax"]) ? $Format["FixedMax"] : VOID; + $AxisR = isset($Format["AxisR"]) ? $Format["AxisR"] : 60; + $AxisG = isset($Format["AxisG"]) ? $Format["AxisG"] : 60; + $AxisB = isset($Format["AxisB"]) ? $Format["AxisB"] : 60; + $AxisAlpha = isset($Format["AxisAlpha"]) ? $Format["AxisAlpha"] : 50; + $AxisRotation = isset($Format["AxisRotation"]) ? $Format["AxisRotation"] : -90; + $DrawTicks = isset($Format["DrawTicks"]) ? $Format["DrawTicks"] : TRUE; + $TicksLength = isset($Format["TicksLength"]) ? $Format["TicksLength"] : 2; + $DrawAxisValues = isset($Format["DrawAxisValues"]) ? $Format["DrawAxisValues"] : TRUE; + $AxisBoxRounded = isset($Format["AxisBoxRounded"]) ? $Format["AxisBoxRounded"] : TRUE; + $AxisFontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->pChartObject->FontName; + $AxisFontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->pChartObject->FontSize; + $WriteValues = isset($Format["WriteValues"]) ? $Format["WriteValues"] : FALSE; + $WriteValuesInBubble = isset($Format["WriteValuesInBubble"]) ? $Format["WriteValuesInBubble"] : TRUE; + $ValueFontName = isset($Format["ValueFontName"]) ? $Format["ValueFontName"] : $this->pChartObject->FontName; + $ValueFontSize = isset($Format["ValueFontSize"]) ? $Format["ValueFontSize"] : $this->pChartObject->FontSize; + $ValuePadding = isset($Format["ValuePadding"]) ? $Format["ValuePadding"] : 4; + $OuterBubbleRadius = isset($Format["OuterBubbleRadius"]) ? $Format["OuterBubbleRadius"] : 2; + $OuterBubbleR = isset($Format["OuterBubbleR"]) ? $Format["OuterBubbleR"] : VOID; + $OuterBubbleG = isset($Format["OuterBubbleG"]) ? $Format["OuterBubbleG"] : VOID; + $OuterBubbleB = isset($Format["OuterBubbleB"]) ? $Format["OuterBubbleB"] : VOID; + $OuterBubbleAlpha = isset($Format["OuterBubbleAlpha"]) ? $Format["OuterBubbleAlpha"] : 100; + $InnerBubbleR = isset($Format["InnerBubbleR"]) ? $Format["InnerBubbleR"] : 255; + $InnerBubbleG = isset($Format["InnerBubbleG"]) ? $Format["InnerBubbleG"] : 255; + $InnerBubbleB = isset($Format["InnerBubbleB"]) ? $Format["InnerBubbleB"] : 255; + $InnerBubbleAlpha = isset($Format["InnerBubbleAlpha"]) ? $Format["InnerBubbleAlpha"] : 100; + $DrawBackground = isset($Format["DrawBackground"]) ? $Format["DrawBackground"] : TRUE; + $BackgroundR = isset($Format["BackgroundR"]) ? $Format["BackgroundR"] : 255; + $BackgroundG = isset($Format["BackgroundG"]) ? $Format["BackgroundG"] : 255; + $BackgroundB = isset($Format["BackgroundB"]) ? $Format["BackgroundB"] : 255; + $BackgroundAlpha = isset($Format["BackgroundAlpha"]) ? $Format["BackgroundAlpha"] : 50; + $BackgroundGradient= isset($Format["BackgroundGradient"]) ? $Format["BackgroundGradient"] : NULL; + $AxisSteps = isset($Format["AxisSteps"]) ? $Format["AxisSteps"] : 20; + $SegmentHeight = isset($Format["SegmentHeight"]) ? $Format["SegmentHeight"] : SEGMENT_HEIGHT_AUTO; + $Segments = isset($Format["Segments"]) ? $Format["Segments"] : 4; + $WriteLabels = isset($Format["WriteLabels"]) ? $Format["WriteLabels"] : TRUE; + $LabelsBackground = isset($Format["LabelsBackground"]) ? $Format["LabelsBackground"] : TRUE; + $LabelsBGR = isset($Format["LabelsBGR"]) ? $Format["LabelsBGR"] : 255; + $LabelsBGG = isset($Format["LabelsBGR"]) ? $Format["LabelsBGG"] : 255; + $LabelsBGB = isset($Format["LabelsBGR"]) ? $Format["LabelsBGB"] : 255; + $LabelsBGAlpha = isset($Format["LabelsBGAlpha"]) ? $Format["LabelsBGAlpha"] : 50; + $LabelPos = isset($Format["LabelPos"]) ? $Format["LabelPos"] : RADAR_LABELS_ROTATED; + $LabelPadding = isset($Format["LabelPadding"]) ? $Format["LabelPadding"] : 4; + $DrawPoints = isset($Format["DrawPoints"]) ? $Format["DrawPoints"] : TRUE; + $PointRadius = isset($Format["PointRadius"]) ? $Format["PointRadius"] : 4; + $PointSurrounding = isset($Format["PointRadius"]) ? $Format["PointRadius"] : -30; + $DrawLines = isset($Format["DrawLines"]) ? $Format["DrawLines"] : TRUE; + $LineLoopStart = isset($Format["LineLoopStart"]) ? $Format["LineLoopStart"] : FALSE; + $DrawPoly = isset($Format["DrawPoly"]) ? $Format["DrawPoly"] : FALSE; + $PolyAlpha = isset($Format["PolyAlpha"]) ? $Format["PolyAlpha"] : NULL; + $FontSize = $Object->FontSize; + $X1 = $Object->GraphAreaX1; + $Y1 = $Object->GraphAreaY1; + $X2 = $Object->GraphAreaX2; + $Y2 = $Object->GraphAreaY2; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + + if ( $AxisBoxRounded ) { $DrawAxisValues = TRUE; } + + /* Cancel default tick length if ticks not enabled */ + if ( $DrawTicks == FALSE ) { $TicksLength = 0; } + + /* Data Processing */ + $Data = $Values->getData(); + $Palette = $Values->getPalette(); + + /* Catch the number of required axis */ + $LabelSerie = $Data["Abscissa"]; + if ( $LabelSerie != "" ) + { $Points = count($Data["Series"][$LabelSerie]["Data"]); } + else + { + $Points = 0; + foreach($Data["Series"] as $SerieName => $DataArray) + { if ( count($DataArray["Data"]) > $Points ) { $Points = count($DataArray["Data"]); } } + } + + /* Draw the axis */ + $CenterX = ($X2-$X1)/2 + $X1; + $CenterY = ($Y2-$Y1)/2 + $Y1; + + $EdgeHeight = min(($X2-$X1)/2,($Y2-$Y1)/2); + if ( $WriteLabels ) + $EdgeHeight = $EdgeHeight - $FontSize - $LabelPadding - $TicksLength; + + /* Determine the scale if set to automatic */ + if ( $SegmentHeight == SEGMENT_HEIGHT_AUTO) + { + if ( $FixedMax != VOID ) + $Max = $FixedMax; + else + { + $Max = 0; + foreach($Data["Series"] as $SerieName => $DataArray) + { + if ( $SerieName != $LabelSerie ) + { + if ( max($DataArray["Data"]) > $Max ) { $Max = max($DataArray["Data"]); } + } + } + } + $MaxSegments = $EdgeHeight/20; + $Scale = $Object->computeScale(0,$Max,$MaxSegments,array(1,2,5)); + + $Segments = $Scale["Rows"]; + $SegmentHeight = $Scale["RowHeight"]; + } + + + /* Background processing */ + if ( $DrawBackground ) + { + $RestoreShadow = $Object->Shadow; + $Object->Shadow = FALSE; + + if ($BackgroundGradient == NULL) + { + $Color = array("R"=>$BackgroundR,"G"=>$BackgroundG,"B"=>$BackgroundB,"Alpha"=>$BackgroundAlpha); + $Object->drawFilledCircle($CenterX,$CenterY,$EdgeHeight,$Color); + } + else + { + $GradientROffset = ($BackgroundGradient["EndR"] - $BackgroundGradient["StartR"]) / $Segments; + $GradientGOffset = ($BackgroundGradient["EndG"] - $BackgroundGradient["StartG"]) / $Segments; + $GradientBOffset = ($BackgroundGradient["EndB"] - $BackgroundGradient["StartB"]) / $Segments; + $GradientAlphaOffset = ($BackgroundGradient["EndAlpha"] - $BackgroundGradient["StartAlpha"]) / $Segments; + + for($j=$Segments;$j>=1;$j--) + { + $Color = array("R"=>$BackgroundGradient["StartR"]+$GradientROffset*$j,"G"=>$BackgroundGradient["StartG"]+$GradientGOffset*$j,"B"=>$BackgroundGradient["StartB"]+$GradientBOffset*$j,"Alpha"=>$BackgroundGradient["StartAlpha"]+$GradientAlphaOffset*$j); + $Object->drawFilledCircle($CenterX,$CenterY,($EdgeHeight/$Segments)*$j,$Color); + } + } + $Object->Shadow = $RestoreShadow; + } + + /* Axis to axis lines */ + $Color = array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha); + for($j=1;$j<=$Segments;$j++) + { + $Radius = ($EdgeHeight/$Segments)*$j; + $Object->drawCircle($CenterX,$CenterY,$Radius,$Radius,$Color); + } + + if ( $DrawAxisValues ) + { + if ( $LabelsBackground ) + $Options = array("DrawBox"=>TRUE, "Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"BoxR"=>$LabelsBGR,"BoxG"=>$LabelsBGG,"BoxB"=>$LabelsBGB,"BoxAlpha"=>$LabelsBGAlpha); + else + $Options = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE); + + if ( $AxisBoxRounded ) { $Options["BoxRounded"] = TRUE; } + + $Options["FontName"] = $AxisFontName; + $Options["FontSize"] = $AxisFontSize; + + $Angle = 360 / ($Points*2); + for($j=1;$j<=$Segments;$j++) + { + $EdgeX1 = cos(deg2rad($Angle+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterX; + $EdgeY1 = sin(deg2rad($Angle+$AxisRotation)) * ($EdgeHeight/$Segments)*$j + $CenterY; + $Label = $j*$SegmentHeight; + + $Object->drawText($EdgeX1,$EdgeY1,$Label,$Options); + } + } + + /* Axis lines */ + $ID = 0; + for($i=0;$i<=359;$i=$i+$AxisSteps) + { + $EdgeX = cos(deg2rad($i+$AxisRotation)) * ($EdgeHeight+$TicksLength) + $CenterX; + $EdgeY = sin(deg2rad($i+$AxisRotation)) * ($EdgeHeight+$TicksLength) + $CenterY; + + $Object->drawLine($CenterX,$CenterY,$EdgeX,$EdgeY,$Color); + + if ( $WriteLabels ) + { + $LabelX = cos(deg2rad($i+$AxisRotation)) * ($EdgeHeight+$LabelPadding+$TicksLength) + $CenterX; + $LabelY = sin(deg2rad($i+$AxisRotation)) * ($EdgeHeight+$LabelPadding+$TicksLength) + $CenterY; + $Label = $i."°"; + + if ( $LabelPos == RADAR_LABELS_ROTATED ) + $Object->drawText($LabelX,$LabelY,$Label,array("Angle"=>(360-$i),"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + else + { + if ( (floor($LabelX) == floor($CenterX)) && (floor($LabelY) < floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); } + if ( (floor($LabelX) > floor($CenterX)) && (floor($LabelY) < floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_BOTTOMLEFT)); } + if ( (floor($LabelX) > floor($CenterX)) && (floor($LabelY) == floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_MIDDLELEFT)); } + if ( (floor($LabelX) > floor($CenterX)) && (floor($LabelY) > floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_TOPLEFT)); } + if ( (floor($LabelX) < floor($CenterX)) && (floor($LabelY) < floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_BOTTOMRIGHT)); } + if ( (floor($LabelX) < floor($CenterX)) && (floor($LabelY) == floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_MIDDLERIGHT)); } + if ( (floor($LabelX) < floor($CenterX)) && (floor($LabelY) > floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_TOPRIGHT)); } + if ( (floor($LabelX) == floor($CenterX)) && (floor($LabelY) > floor($CenterY)) ) { $Object->drawText($LabelX,$LabelY,$Label,array("Align"=>TEXT_ALIGN_TOPMIDDLE)); } + } + } + $ID++; + } + + /* Compute the plots position */ + $ID = 0; $Plot = ""; + foreach($Data["Series"] as $SerieName => $DataSet) + { + if ( $SerieName != $LabelSerie ) + { + $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"],"Surrounding"=>$PointSurrounding); + foreach($DataSet["Data"] as $Key => $Value) + { + $Angle = $Data["Series"][$LabelSerie]["Data"][$Key]; + $Length = ($EdgeHeight/($Segments*$SegmentHeight))*$Value; + + $X = cos(deg2rad($Angle+$AxisRotation)) * $Length + $CenterX; + $Y = sin(deg2rad($Angle+$AxisRotation)) * $Length + $CenterY; + + if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".floor($PointRadius),$this->pChartObject->toHTMLColor($Palette[$ID]["R"],$Palette[$ID]["G"],$Palette[$ID]["B"]),$DataSet["Description"],$Data["Series"][$LabelSerie]["Data"][$Key]."° = ".$Value); } + + $Plot[$ID][] = array($X,$Y,$Value); + } + $ID++; + } + } + + /* Draw all that stuff! */ + foreach($Plot as $ID => $Points) + { + $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"],"Surrounding"=>$PointSurrounding); + + /* Draw the polygons */ + if ( $DrawPoly ) + { + if ($PolyAlpha != NULL) + $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$PolyAlpha,"Surrounding"=>$PointSurrounding); + + $PointsArray = ""; + for($i=0; $idrawPolygon($PointsArray,$Color); + } + + $Color = array("R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"],"Alpha"=>$Palette[$ID]["Alpha"],"Surrounding"=>$PointSurrounding); + + /* Bubble and labels settings */ + $TextSettings = array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontName"=>$ValueFontName,"FontSize"=>$ValueFontSize,"R"=>$Palette[$ID]["R"],"G"=>$Palette[$ID]["G"],"B"=>$Palette[$ID]["B"]); + $InnerColor = array("R"=>$InnerBubbleR,"G"=>$InnerBubbleG,"B"=>$InnerBubbleB,"Alpha"=>$InnerBubbleAlpha); + if ( $OuterBubbleR != VOID ) + $OuterColor = array("R"=>$OuterBubbleR,"G"=>$OuterBubbleG,"B"=>$OuterBubbleB,"Alpha"=>$OuterBubbleAlpha); + else + $OuterColor = array("R"=>$Palette[$ID]["R"]+20,"G"=>$Palette[$ID]["G"]+20,"B"=>$Palette[$ID]["B"]+20,"Alpha"=>$Palette[$ID]["Alpha"]); + + /* Loop to the starting points if asked */ + if ( $LineLoopStart && $DrawLines ) + $Object->drawLine($Points[count($Points)-1][0],$Points[count($Points)-1][1],$Points[0][0],$Points[0][1],$Color); + + /* Draw the lines & points */ + for($i=0; $idrawLine($Points[$i][0],$Points[$i][1],$Points[$i+1][0],$Points[$i+1][1],$Color); + + if ( $DrawPoints ) + $Object->drawFilledCircle($Points[$i][0],$Points[$i][1],$PointRadius,$Color); + + if ( $WriteValuesInBubble && $WriteValues ) + { + $TxtPos = $this->pChartObject->getTextBox($Points[$i][0],$Points[$i][1],$ValueFontName,$ValueFontSize,0,$Points[$i][2]); + $Radius = floor(($TxtPos[1]["X"] - $TxtPos[0]["X"] + $ValuePadding*2)/2); + + $this->pChartObject->drawFilledCircle($Points[$i][0],$Points[$i][1],$Radius+$OuterBubbleRadius,$OuterColor); + $this->pChartObject->drawFilledCircle($Points[$i][0],$Points[$i][1],$Radius,$InnerColor); + } + + if ( $WriteValues ) + $this->pChartObject->drawText($Points[$i][0]-1,$Points[$i][1]-1,$Points[$i][2],$TextSettings); + } + } + } + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/class/pScatter.class.php b/trunk/includes/pChart/class/pScatter.class.php new file mode 100644 index 0000000..a83ce39 --- /dev/null +++ b/trunk/includes/pChart/class/pScatter.class.php @@ -0,0 +1,1158 @@ +pChartObject = $pChartObject; + $this->pDataObject = $pDataObject; + } + + /* Prepare the scale */ + function drawScatterScale($Format="") + { + $Mode = isset($Format["Mode"]) ? $Format["Mode"] : SCALE_MODE_FLOATING; + $Floating = isset($Format["Floating"]) ? $Format["Floating"] : FALSE; + $XLabelsRotation = isset($Format["XLabelsRotation"]) ? $Format["XLabelsRotation"] : 90; + $MinDivHeight = isset($Format["MinDivHeight"]) ? $Format["MinDivHeight"] : 20; + $Factors = isset($Format["Factors"]) ? $Format["Factors"] : array(1,2,5); + $ManualScale = isset($Format["ManualScale"]) ? $Format["ManualScale"] : array("0"=>array("Min"=>-100,"Max"=>100)); + $XMargin = isset($Format["XMargin"]) ? $Format["XMargin"] : 0; + $YMargin = isset($Format["YMargin"]) ? $Format["YMargin"] : 0; + $ScaleSpacing = isset($Format["ScaleSpacing"]) ? $Format["ScaleSpacing"] : 15; + $InnerTickWidth = isset($Format["InnerTickWidth"]) ? $Format["InnerTickWidth"] : 2; + $OuterTickWidth = isset($Format["OuterTickWidth"]) ? $Format["OuterTickWidth"] : 2; + $DrawXLines = isset($Format["DrawXLines"]) ? $Format["DrawXLines"] : ALL; + $DrawYLines = isset($Format["DrawYLines"]) ? $Format["DrawYLines"] : ALL; + $GridTicks = isset($Format["GridTicks"]) ? $Format["GridTicks"] : 4; + $GridR = isset($Format["GridR"]) ? $Format["GridR"] : 255; + $GridG = isset($Format["GridG"]) ? $Format["GridG"] : 255; + $GridB = isset($Format["GridB"]) ? $Format["GridB"] : 255; + $GridAlpha = isset($Format["GridAlpha"]) ? $Format["GridAlpha"] : 40; + $AxisRo = isset($Format["AxisR"]) ? $Format["AxisR"] : 0; + $AxisGo = isset($Format["AxisG"]) ? $Format["AxisG"] : 0; + $AxisBo = isset($Format["AxisB"]) ? $Format["AxisB"] : 0; + $AxisAlpha = isset($Format["AxisAlpha"]) ? $Format["AxisAlpha"] : 100; + $TickRo = isset($Format["TickR"]) ? $Format["TickR"] : 0; + $TickGo = isset($Format["TickG"]) ? $Format["TickG"] : 0; + $TickBo = isset($Format["TickB"]) ? $Format["TickB"] : 0; + $TickAlpha = isset($Format["TickAlpha"]) ? $Format["TickAlpha"] : 100; + $DrawSubTicks = isset($Format["DrawSubTicks"]) ? $Format["DrawSubTicks"] : FALSE; + $InnerSubTickWidth = isset($Format["InnerSubTickWidth"]) ? $Format["InnerSubTickWidth"] : 0; + $OuterSubTickWidth = isset($Format["OuterSubTickWidth"]) ? $Format["OuterSubTickWidth"] : 2; + $SubTickR = isset($Format["SubTickR"]) ? $Format["SubTickR"] : 255; + $SubTickG = isset($Format["SubTickG"]) ? $Format["SubTickG"] : 0; + $SubTickB = isset($Format["SubTickB"]) ? $Format["SubTickB"] : 0; + $SubTickAlpha = isset($Format["SubTickAlpha"]) ? $Format["SubTickAlpha"] : 100; + $XReleasePercent = isset($Format["XReleasePercent"]) ? $Format["XReleasePercent"] : 1; + $DrawArrows = isset($Format["DrawArrows"]) ? $Format["DrawArrows"] : FALSE; + $ArrowSize = isset($Format["ArrowSize"]) ? $Format["ArrowSize"] : 8; + $CycleBackground = isset($Format["CycleBackground"]) ? $Format["CycleBackground"] : FALSE; + $BackgroundR1 = isset($Format["BackgroundR1"]) ? $Format["BackgroundR1"] : 255; + $BackgroundG1 = isset($Format["BackgroundG1"]) ? $Format["BackgroundG1"] : 255; + $BackgroundB1 = isset($Format["BackgroundB1"]) ? $Format["BackgroundB1"] : 255; + $BackgroundAlpha1 = isset($Format["BackgroundAlpha1"]) ? $Format["BackgroundAlpha1"] : 10; + $BackgroundR2 = isset($Format["BackgroundR2"]) ? $Format["BackgroundR2"] : 230; + $BackgroundG2 = isset($Format["BackgroundG2"]) ? $Format["BackgroundG2"] : 230; + $BackgroundB2 = isset($Format["BackgroundB2"]) ? $Format["BackgroundB2"] : 230; + $BackgroundAlpha2 = isset($Format["BackgroundAlpha2"]) ? $Format["BackgroundAlpha2"] : 10; + + /* Check if we have at least both one X and Y axis */ + $GotXAxis = FALSE; $GotYAxis = FALSE; + foreach($this->pDataObject->Data["Axis"] as $AxisID => $AxisSettings) + { + if ( $AxisSettings["Identity"] == AXIS_X ) { $GotXAxis = TRUE; } + if ( $AxisSettings["Identity"] == AXIS_Y ) { $GotYAxis = TRUE; } + } + if ( !$GotXAxis ) { return(SCATTER_MISSING_X_SERIE); } + if ( !$GotYAxis ) { return(SCATTER_MISSING_Y_SERIE); } + + /* Skip a NOTICE event in case of an empty array */ + if ( $DrawYLines == NONE ) { $DrawYLines = array("zarma"=>"31"); } + + $Data = $this->pDataObject->getData(); + + foreach($Data["Axis"] as $AxisID => $AxisSettings) + { + if ( $AxisSettings["Identity"] == AXIS_X) + { $Width = $this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1 - $XMargin*2; } + else + { $Width = $this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1 - $YMargin*2; } + + $AxisMin = ABSOLUTE_MAX; $AxisMax = OUT_OF_SIGHT; + if ( $Mode == SCALE_MODE_FLOATING ) + { + foreach($Data["Series"] as $SerieID => $SerieParameter) + { + if ( $SerieParameter["Axis"] == $AxisID && $Data["Series"][$SerieID]["isDrawable"] ) + { + $AxisMax = max($AxisMax,$Data["Series"][$SerieID]["Max"]); + $AxisMin = min($AxisMin,$Data["Series"][$SerieID]["Min"]); + } + } + $AutoMargin = (($AxisMax-$AxisMin)/100)*$XReleasePercent; + + $Data["Axis"][$AxisID]["Min"] = $AxisMin-$AutoMargin; $Data["Axis"][$AxisID]["Max"] = $AxisMax+$AutoMargin; + } + elseif ( $Mode == SCALE_MODE_MANUAL ) + { + if ( isset($ManualScale[$AxisID]["Min"]) && isset($ManualScale[$AxisID]["Max"]) ) + { + $Data["Axis"][$AxisID]["Min"] = $ManualScale[$AxisID]["Min"]; + $Data["Axis"][$AxisID]["Max"] = $ManualScale[$AxisID]["Max"]; + } + else + { echo "Manual scale boundaries not set."; exit(); } + } + + /* Full manual scale */ + if ( isset($ManualScale[$AxisID]["Rows"]) && isset($ManualScale[$AxisID]["RowHeight"]) ) + $Scale = array("Rows"=>$ManualScale[$AxisID]["Rows"],"RowHeight"=>$ManualScale[$AxisID]["RowHeight"],"XMin"=>$ManualScale[$AxisID]["Min"],"XMax"=>$ManualScale[$AxisID]["Max"]); + else + { + $MaxDivs = floor($Width/$MinDivHeight); + $Scale = $this->pChartObject->computeScale($Data["Axis"][$AxisID]["Min"],$Data["Axis"][$AxisID]["Max"],$MaxDivs,$Factors,$AxisID); + } + + $Data["Axis"][$AxisID]["Margin"] = $AxisSettings["Identity"] == AXIS_X ? $XMargin : $YMargin; + $Data["Axis"][$AxisID]["ScaleMin"] = $Scale["XMin"]; + $Data["Axis"][$AxisID]["ScaleMax"] = $Scale["XMax"]; + $Data["Axis"][$AxisID]["Rows"] = $Scale["Rows"]; + $Data["Axis"][$AxisID]["RowHeight"] = $Scale["RowHeight"]; + + if ( isset($Scale["Format"]) ) { $Data["Axis"][$AxisID]["Format"] = $Scale["Format"]; } + + if ( !isset($Data["Axis"][$AxisID]["Display"]) ) { $Data["Axis"][$AxisID]["Display"] = NULL; } + if ( !isset($Data["Axis"][$AxisID]["Format"]) ) { $Data["Axis"][$AxisID]["Format"] = NULL; } + if ( !isset($Data["Axis"][$AxisID]["Unit"]) ) { $Data["Axis"][$AxisID]["Unit"] = NULL; } + } + + /* Get the default font color */ + $FontColorRo = $this->pChartObject->FontColorR; $FontColorGo = $this->pChartObject->FontColorG; $FontColorBo = $this->pChartObject->FontColorB; + + /* Set the original boundaries */ + $AxisPos["L"] = $this->pChartObject->GraphAreaX1; $AxisPos["R"] = $this->pChartObject->GraphAreaX2; $AxisPos["T"] = $this->pChartObject->GraphAreaY1; $AxisPos["B"] = $this->pChartObject->GraphAreaY2; + + foreach($Data["Axis"] as $AxisID => $AxisSettings) + { + if ( isset($AxisSettings["Color"]) ) + { + $AxisR = $AxisSettings["Color"]["R"]; $AxisG = $AxisSettings["Color"]["G"]; $AxisB = $AxisSettings["Color"]["B"]; + $TickR = $AxisSettings["Color"]["R"]; $TickG = $AxisSettings["Color"]["G"]; $TickB = $AxisSettings["Color"]["B"]; + $this->pChartObject->setFontProperties(array("R"=>$AxisSettings["Color"]["R"],"G"=>$AxisSettings["Color"]["G"],"B"=>$AxisSettings["Color"]["B"])); + } + else + { + $AxisR = $AxisRo; $AxisG = $AxisGo; $AxisB = $AxisBo; + $TickR = $TickRo; $TickG = $TickGo; $TickB = $TickBo; + $this->pChartObject->setFontProperties(array("R"=>$FontColorRo,"G"=>$FontColorGo,"B"=>$FontColorBo)); + } + + $LastValue = "w00t"; $ID = 1; + if ( $AxisSettings["Identity"] == AXIS_X ) + { + if ( $AxisSettings["Position"] == AXIS_POSITION_BOTTOM ) + { + if ( $XLabelsRotation == 0 ) { $LabelAlign = TEXT_ALIGN_TOPMIDDLE; $LabelOffset = 2; } + if ( $XLabelsRotation > 0 && $XLabelsRotation < 190 ) { $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $LabelOffset = 5; } + if ( $XLabelsRotation == 180 ) { $LabelAlign = TEXT_ALIGN_BOTTOMMIDDLE; $LabelOffset = 5; } + if ( $XLabelsRotation > 180 && $XLabelsRotation < 360 ) { $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $LabelOffset = 2; } + + if ( $Floating ) + { $FloatingOffset = $YMargin; $this->pChartObject->drawLine($this->pChartObject->GraphAreaX1+$AxisSettings["Margin"],$AxisPos["B"],$this->pChartObject->GraphAreaX2-$AxisSettings["Margin"],$AxisPos["B"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->pChartObject->drawLine($this->pChartObject->GraphAreaX1,$AxisPos["B"],$this->pChartObject->GraphAreaX2,$AxisPos["B"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->pChartObject->drawArrow($this->pChartObject->GraphAreaX2-$AxisSettings["Margin"],$AxisPos["B"],$this->pChartObject->GraphAreaX2+($ArrowSize*2),$AxisPos["B"],array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + + $Width = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1) - $AxisSettings["Margin"]*2; + $Step = $Width / $AxisSettings["Rows"]; $SubTicksSize = $Step /2; $MaxBottom = $AxisPos["B"]; + $LastX = NULL; + for($i=0;$i<=$AxisSettings["Rows"];$i++) + { + $XPos = $this->pChartObject->GraphAreaX1 + $AxisSettings["Margin"] + $Step*$i; + $YPos = $AxisPos["B"]; + $Value = $this->pChartObject->scaleFormat($AxisSettings["ScaleMin"] + $AxisSettings["RowHeight"]*$i,$AxisSettings["Display"],$AxisSettings["Format"],$AxisSettings["Unit"]); + + if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); } + if ( $LastX != NULL && $CycleBackground && ( $DrawXLines == ALL || in_array($AxisID,$DrawXLines) )) { $this->pChartObject->drawFilledRectangle($LastX,$this->pChartObject->GraphAreaY1+$FloatingOffset,$XPos,$this->pChartObject->GraphAreaY2-$FloatingOffset,$BGColor); } + + if ( $DrawXLines == ALL || in_array($AxisID,$DrawXLines) ) { $this->pChartObject->drawLine($XPos,$this->pChartObject->GraphAreaY1+$FloatingOffset,$XPos,$this->pChartObject->GraphAreaY2-$FloatingOffset,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + if ( $DrawSubTicks && $i != $AxisSettings["Rows"] ) + $this->pChartObject->drawLine($XPos+$SubTicksSize,$YPos-$InnerSubTickWidth,$XPos+$SubTicksSize,$YPos+$OuterSubTickWidth,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha)); + + $this->pChartObject->drawLine($XPos,$YPos-$InnerTickWidth,$XPos,$YPos+$OuterTickWidth,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); + $Bounds = $this->pChartObject->drawText($XPos,$YPos+$OuterTickWidth+$LabelOffset,$Value,array("Angle"=>$XLabelsRotation,"Align"=>$LabelAlign)); + $TxtBottom = $YPos+2+$OuterTickWidth+2+($Bounds[0]["Y"]-$Bounds[2]["Y"]); + $MaxBottom = max($MaxBottom,$TxtBottom); + + $LastX = $XPos; + } + + if ( isset($AxisSettings["Name"]) ) + { + $YPos = $MaxBottom+2; + $XPos = $this->pChartObject->GraphAreaX1+($this->pChartObject->GraphAreaX2-$this->pChartObject->GraphAreaX1)/2; + $Bounds = $this->pChartObject->drawText($XPos,$YPos,$AxisSettings["Name"],array("Align"=>TEXT_ALIGN_TOPMIDDLE)); + $MaxBottom = $Bounds[0]["Y"]; + + $this->pDataObject->Data["GraphArea"]["Y2"] = $MaxBottom + $this->pChartObject->FontSize; + } + + $AxisPos["B"] = $MaxBottom + $ScaleSpacing; + } + elseif ( $AxisSettings["Position"] == AXIS_POSITION_TOP ) + { + if ( $XLabelsRotation == 0 ) { $LabelAlign = TEXT_ALIGN_BOTTOMMIDDLE; $LabelOffset = 2; } + if ( $XLabelsRotation > 0 && $XLabelsRotation < 190 ) { $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $LabelOffset = 2; } + if ( $XLabelsRotation == 180 ) { $LabelAlign = TEXT_ALIGN_TOPMIDDLE; $LabelOffset = 5; } + if ( $XLabelsRotation > 180 && $SLabelxRotation < 360 ) { $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $LabelOffset = 5; } + + if ( $Floating ) + { $FloatingOffset = $YMargin; $this->pChartObject->drawLine($this->pChartObject->GraphAreaX1+$AxisSettings["Margin"],$AxisPos["T"],$this->pChartObject->GraphAreaX2-$AxisSettings["Margin"],$AxisPos["T"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->pChartObject->drawLine($this->pChartObject->GraphAreaX1,$AxisPos["T"],$this->pChartObject->GraphAreaX2,$AxisPos["T"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->pChartObject->drawArrow($this->pChartObject->GraphAreaX2-$AxisSettings["Margin"],$AxisPos["T"],$this->pChartObject->GraphAreaX2+($ArrowSize*2),$AxisPos["T"],array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + + $Width = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1) - $AxisSettings["Margin"]*2; + $Step = $Width / $AxisSettings["Rows"]; $SubTicksSize = $Step /2; $MinTop = $AxisPos["T"]; + $LastX = NULL; + for($i=0;$i<=$AxisSettings["Rows"];$i++) + { + $XPos = $this->pChartObject->GraphAreaX1 + $AxisSettings["Margin"] + $Step*$i; + $YPos = $AxisPos["T"]; + $Value = $this->pChartObject->scaleFormat($AxisSettings["ScaleMin"] + $AxisSettings["RowHeight"]*$i,$AxisSettings["Display"],$AxisSettings["Format"],$AxisSettings["Unit"]); + + if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); } + if ( $LastX != NULL && $CycleBackground && ( $DrawXLines == ALL || in_array($AxisID,$DrawXLines) )) { $this->pChartObject->drawFilledRectangle($LastX,$this->pChartObject->GraphAreaY1+$FloatingOffset,$XPos,$this->pChartObject->GraphAreaY2-$FloatingOffset,$BGColor); } + + if ( $DrawXLines == ALL || in_array($AxisID,$DrawXLines) ) { $this->pChartObject->drawLine($XPos,$this->pChartObject->GraphAreaY1+$FloatingOffset,$XPos,$this->pChartObject->GraphAreaY2-$FloatingOffset,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + + if ( $DrawSubTicks && $i != $AxisSettings["Rows"] ) + $this->pChartObject->drawLine($XPos+$SubTicksSize,$YPos-$OuterSubTickWidth,$XPos+$SubTicksSize,$YPos+$InnerSubTickWidth,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha)); + + $this->pChartObject->drawLine($XPos,$YPos-$OuterTickWidth,$XPos,$YPos+$InnerTickWidth,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); + $Bounds = $this->pChartObject->drawText($XPos,$YPos-$OuterTickWidth-$LabelOffset,$Value,array("Angle"=>$XLabelsRotation,"Align"=>$LabelAlign)); + $TxtBox = $YPos-$OuterTickWidth-4-($Bounds[0]["Y"]-$Bounds[2]["Y"]); + $MinTop = min($MinTop,$TxtBox); + + $LastX = $XPos; + } + + if ( isset($AxisSettings["Name"]) ) + { + $YPos = $MinTop-2; + $XPos = $this->pChartObject->GraphAreaX1+($this->pChartObject->GraphAreaX2-$this->pChartObject->GraphAreaX1)/2; + $Bounds = $this->pChartObject->drawText($XPos,$YPos,$AxisSettings["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); + $MinTop = $Bounds[2]["Y"]; + + $this->pDataObject->Data["GraphArea"]["Y1"] = $MinTop; + } + + $AxisPos["T"] = $MinTop - $ScaleSpacing; + } + } + elseif ( $AxisSettings["Identity"] == AXIS_Y ) + { + if ( $AxisSettings["Position"] == AXIS_POSITION_LEFT ) + { + + if ( $Floating ) + { $FloatingOffset = $XMargin; $this->pChartObject->drawLine($AxisPos["L"],$this->pChartObject->GraphAreaY1+$AxisSettings["Margin"],$AxisPos["L"],$this->pChartObject->GraphAreaY2-$AxisSettings["Margin"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->pChartObject->drawLine($AxisPos["L"],$this->pChartObject->GraphAreaY1,$AxisPos["L"],$this->pChartObject->GraphAreaY2,array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->pChartObject->drawArrow($AxisPos["L"],$this->pChartObject->GraphAreaY1+$AxisSettings["Margin"],$AxisPos["L"],$this->pChartObject->GraphAreaY1-($ArrowSize*2),array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + + $Height = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1) - $AxisSettings["Margin"]*2; + $Step = $Height / $AxisSettings["Rows"]; $SubTicksSize = $Step /2; $MinLeft = $AxisPos["L"]; + $LastY = NULL; + for($i=0;$i<=$AxisSettings["Rows"];$i++) + { + $YPos = $this->pChartObject->GraphAreaY2 - $AxisSettings["Margin"] - $Step*$i; + $XPos = $AxisPos["L"]; + $Value = $this->pChartObject->scaleFormat($AxisSettings["ScaleMin"] + $AxisSettings["RowHeight"]*$i,$AxisSettings["Display"],$AxisSettings["Format"],$AxisSettings["Unit"]); + + if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); } + if ( $LastY != NULL && $CycleBackground && ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->pChartObject->drawFilledRectangle($this->pChartObject->GraphAreaX1+$FloatingOffset,$LastY,$this->pChartObject->GraphAreaX2-$FloatingOffset,$YPos,$BGColor); } + + if ( ($YPos != $this->pChartObject->GraphAreaY1 && $YPos != $this->pChartObject->GraphAreaY2) && ($DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->pChartObject->drawLine($this->pChartObject->GraphAreaX1+$FloatingOffset,$YPos,$this->pChartObject->GraphAreaX2-$FloatingOffset,$YPos,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + + if ( $DrawSubTicks && $i != $AxisSettings["Rows"] ) + $this->pChartObject->drawLine($XPos-$OuterSubTickWidth,$YPos-$SubTicksSize,$XPos+$InnerSubTickWidth,$YPos-$SubTicksSize,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha)); + + $this->pChartObject->drawLine($XPos-$OuterTickWidth,$YPos,$XPos+$InnerTickWidth,$YPos,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); + $Bounds = $this->pChartObject->drawText($XPos-$OuterTickWidth-2,$YPos,$Value,array("Align"=>TEXT_ALIGN_MIDDLERIGHT)); + $TxtLeft = $XPos-$OuterTickWidth-2-($Bounds[1]["X"]-$Bounds[0]["X"]); + $MinLeft = min($MinLeft,$TxtLeft); + + $LastY = $YPos; + } + + if ( isset($AxisSettings["Name"]) ) + { + $XPos = $MinLeft-2; + $YPos = $this->pChartObject->GraphAreaY1+($this->pChartObject->GraphAreaY2-$this->pChartObject->GraphAreaY1)/2; + $Bounds = $this->pChartObject->drawText($XPos,$YPos,$AxisSettings["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE,"Angle"=>90)); + $MinLeft = $Bounds[2]["X"]; + + $this->pDataObject->Data["GraphArea"]["X1"] = $MinLeft; + } + + $AxisPos["L"] = $MinLeft - $ScaleSpacing; + } + elseif ( $AxisSettings["Position"] == AXIS_POSITION_RIGHT ) + { + + if ( $Floating ) + { $FloatingOffset = $XMargin; $this->pChartObject->drawLine($AxisPos["R"],$this->pChartObject->GraphAreaY1+$AxisSettings["Margin"],$AxisPos["R"],$this->pChartObject->GraphAreaY2-$AxisSettings["Margin"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + else + { $FloatingOffset = 0; $this->pChartObject->drawLine($AxisPos["R"],$this->pChartObject->GraphAreaY1,$AxisPos["R"],$this->pChartObject->GraphAreaY2,array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); } + + if ( $DrawArrows ) { $this->pChartObject->drawArrow($AxisPos["R"],$this->pChartObject->GraphAreaY1+$AxisSettings["Margin"],$AxisPos["R"],$this->pChartObject->GraphAreaY1-($ArrowSize*2),array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); } + + $Height = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1) - $AxisSettings["Margin"]*2; + $Step = $Height / $AxisSettings["Rows"]; $SubTicksSize = $Step /2; $MaxLeft = $AxisPos["R"]; + $LastY = NULL; + for($i=0;$i<=$AxisSettings["Rows"];$i++) + { + $YPos = $this->pChartObject->GraphAreaY2 - $AxisSettings["Margin"] - $Step*$i; + $XPos = $AxisPos["R"]; + $Value = $this->pChartObject->scaleFormat($AxisSettings["ScaleMin"] + $AxisSettings["RowHeight"]*$i,$AxisSettings["Display"],$AxisSettings["Format"],$AxisSettings["Unit"]); + + if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); } + if ( $LastY != NULL && $CycleBackground && ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->pChartObject->drawFilledRectangle($this->pChartObject->GraphAreaX1+$FloatingOffset,$LastY,$this->pChartObject->GraphAreaX2-$FloatingOffset,$YPos,$BGColor); } + + if ( ($YPos != $this->pChartObject->GraphAreaY1 && $YPos != $this->pChartObject->GraphAreaY2) && ($DrawYLines == ALL || in_array($AxisID,$DrawYLines)) ) { $this->pChartObject->drawLine($this->pChartObject->GraphAreaX1+$FloatingOffset,$YPos,$this->pChartObject->GraphAreaX2-$FloatingOffset,$YPos,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); } + + if ( $DrawSubTicks && $i != $AxisSettings["Rows"] ) + $this->pChartObject->drawLine($XPos-$InnerSubTickWidth,$YPos-$SubTicksSize,$XPos+$OuterSubTickWidth,$YPos-$SubTicksSize,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha)); + + $this->pChartObject->drawLine($XPos-$InnerTickWidth,$YPos,$XPos+$OuterTickWidth,$YPos,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); + $Bounds = $this->pChartObject->drawText($XPos+$OuterTickWidth+2,$YPos,$Value,array("Align"=>TEXT_ALIGN_MIDDLELEFT)); + $TxtLeft = $XPos+$OuterTickWidth+2+($Bounds[1]["X"]-$Bounds[0]["X"]); + $MaxLeft = max($MaxLeft,$TxtLeft); + + $LastY = $YPos; + } + + if ( isset($AxisSettings["Name"]) ) + { + $XPos = $MaxLeft+6; + $YPos = $this->pChartObject->GraphAreaY1+($this->pChartObject->GraphAreaY2-$this->pChartObject->GraphAreaY1)/2; + $Bounds = $this->pChartObject->drawText($XPos,$YPos,$AxisSettings["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE,"Angle"=>270)); + $MaxLeft = $Bounds[2]["X"]; + + $this->pDataObject->Data["GraphArea"]["X2"] = $MaxLeft + $this->pChartObject->FontSize; + } + + $AxisPos["R"] = $MaxLeft + $ScaleSpacing; + } + } + } + + $this->pDataObject->saveAxisConfig($Data["Axis"]); + } + + /* Draw a scatter plot chart */ + function drawScatterPlotChart($Format=NULL) + { + $PlotSize = isset($Format["PlotSize"]) ? $Format["PlotSize"] : 3; + $PlotBorder = isset($Format["PlotBorder"]) ? $Format["PlotBorder"] : FALSE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 250; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 250; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 250; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : 30; + $BorderSize = isset($Format["BorderSize"]) ? $Format["BorderSize"] : 1; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + $ImageMapTitle = isset($Format["ImageMapTitle"]) ? $Format["ImageMapTitle"] : NULL; + $ImageMapPrecision = isset($Format["ImageMapPrecision"]) ? $Format["ImageMapPrecision"] : 2; + + $Data = $this->pDataObject->getData(); + $Palette = $this->pDataObject->getPalette(); + + $BorderColor = array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha); + + foreach($Data["ScatterSeries"] as $Key => $Series) + { + if ( $Series["isDrawable"] == TRUE ) + { + $SerieX = $Series["X"]; $SerieValuesX = $Data["Series"][$SerieX]["Data"]; $SerieXAxis = $Data["Series"][$SerieX]["Axis"]; + $SerieY = $Series["Y"]; $SerieValuesY = $Data["Series"][$SerieY]["Data"]; $SerieYAxis = $Data["Series"][$SerieY]["Axis"]; + + if ( $ImageMapTitle == NULL ) { $Description = $Data["Series"][$Series["X"]]["Description"]." / ".$Data["Series"][$Series["Y"]]["Description"]; } else { $Description = $ImageMapTitle; } + + if ( isset($Series["Picture"]) && $Series["Picture"] != "" ) + { $Picture = $Series["Picture"]; list($PicWidth,$PicHeight,$PicType) = $this->pChartObject->getPicInfo($Picture); } + else + { $Picture = NULL; } + + $PosArrayX = $this->getPosArray($SerieValuesX,$SerieXAxis); + if ( !is_array($PosArrayX) ) { $Value = $PosArrayX; $PosArrayX = ""; $PosArrayX[0] = $Value; } + $PosArrayY = $this->getPosArray($SerieValuesY,$SerieYAxis); + if ( !is_array($PosArrayY) ) { $Value = $PosArrayY; $PosArrayY = ""; $PosArrayY[0] = $Value; } + + $Color = array("R"=>$Series["Color"]["R"],"G"=>$Series["Color"]["G"],"B"=>$Series["Color"]["B"],"Alpha"=>$Series["Color"]["Alpha"]); + + foreach($PosArrayX as $Key => $Value) + { + $X = $Value; $Y = $PosArrayY[$Key]; + + if ( $X != VOID && $Y != VOID ) + { + $RealValue = round($Data["Series"][$Series["X"]]["Data"][$Key],2)." / ".round($Data["Series"][$Series["Y"]]["Data"][$Key],2); + if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".floor($PlotSize+$BorderSize),$this->pChartObject->toHTMLColor($Series["Color"]["R"],$Series["Color"]["G"],$Series["Color"]["B"]),$Description,$RealValue); } + + if( isset($Series["Shape"]) ) + { $this->pChartObject->drawShape($X,$Y,$Series["Shape"],$PlotSize,$PlotBorder,$BorderSize,$Series["Color"]["R"],$Series["Color"]["G"],$Series["Color"]["B"],$Series["Color"]["Alpha"],$BorderR,$BorderG,$BorderB,$BorderAlpha); } + elseif ( $Picture == NULL ) + { + if ( $PlotBorder ) { $this->pChartObject->drawFilledCircle($X,$Y,$PlotSize+$BorderSize,$BorderColor); } + $this->pChartObject->drawFilledCircle($X,$Y,$PlotSize,$Color); + } + else + { $this->pChartObject->drawFromPicture($PicType,$Picture,$X-$PicWidth/2,$Y-$PicHeight/2); } + } + } + } + } + } + + /* Draw a scatter line chart */ + function drawScatterLineChart($Format=NULL) + { + $Data = $this->pDataObject->getData(); + $Palette = $this->pDataObject->getPalette(); + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + $ImageMapTitle = isset($Format["ImageMapTitle"]) ? $Format["ImageMapTitle"] : NULL; + $ImageMapPlotSize = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 10; + $ImageMapPrecision = isset($Format["ImageMapPrecision"]) ? $Format["ImageMapPrecision"] : 2; + + /* Parse all the series to draw */ + foreach($Data["ScatterSeries"] as $Key => $Series) + { + if ( $Series["isDrawable"] == TRUE ) + { + $SerieX = $Series["X"]; $SerieValuesX = $Data["Series"][$SerieX]["Data"]; $SerieXAxis = $Data["Series"][$SerieX]["Axis"]; + $SerieY = $Series["Y"]; $SerieValuesY = $Data["Series"][$SerieY]["Data"]; $SerieYAxis = $Data["Series"][$SerieY]["Axis"]; + $Ticks = $Series["Ticks"]; + $Weight = $Series["Weight"]; + + if ( $ImageMapTitle == NULL ) { $Description = $Data["Series"][$Series["X"]]["Description"]." / ".$Data["Series"][$Series["Y"]]["Description"]; } else { $Description = $ImageMapTitle; } + + $PosArrayX = $this->getPosArray($SerieValuesX,$SerieXAxis); + if ( !is_array($PosArrayX) ) { $Value = $PosArrayX; $PosArrayX = ""; $PosArrayX[0] = $Value; } + $PosArrayY = $this->getPosArray($SerieValuesY,$SerieYAxis); + if ( !is_array($PosArrayY) ) { $Value = $PosArrayY; $PosArrayY = ""; $PosArrayY[0] = $Value; } + + $Color = array("R"=>$Series["Color"]["R"],"G"=>$Series["Color"]["G"],"B"=>$Series["Color"]["B"],"Alpha"=>$Series["Color"]["Alpha"]); + if ( $Ticks != 0 ) { $Color["Ticks"] = $Ticks; } + if ( $Weight != 0 ) { $Color["Weight"] = $Weight; } + + $LastX = VOID; $LastY = VOID; + foreach($PosArrayX as $Key => $Value) + { + $X = $Value; $Y = $PosArrayY[$Key]; + + if ( $X != VOID && $Y != VOID ) + { + $RealValue = round($Data["Series"][$Series["X"]]["Data"][$Key],2)." / ".round($Data["Series"][$Series["Y"]]["Data"][$Key],2); + if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$ImageMapPlotSize,$this->pChartObject->toHTMLColor($Series["Color"]["R"],$Series["Color"]["G"],$Series["Color"]["B"]),$Description,$RealValue); } + } + + if ( $X != VOID && $Y != VOID && $LastX != VOID && $LastY != VOID) + $this->pChartObject->drawLine($LastX,$LastY,$X,$Y,$Color); + + $LastX = $X; $LastY = $Y; + } + } + } + } + + /* Draw a scatter spline chart */ + function drawScatterSplineChart($Format=NULL) + { + $Data = $this->pDataObject->getData(); + $Palette = $this->pDataObject->getPalette(); + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + $ImageMapTitle = isset($Format["ImageMapTitle"]) ? $Format["ImageMapTitle"] : NULL; + $ImageMapPlotSize = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 10; + $ImageMapPrecision = isset($Format["ImageMapPrecision"]) ? $Format["ImageMapPrecision"] : 2; + + foreach($Data["ScatterSeries"] as $Key => $Series) + { + if ( $Series["isDrawable"] == TRUE ) + { + $SerieX = $Series["X"]; $SerieValuesX = $Data["Series"][$SerieX]["Data"]; $SerieXAxis = $Data["Series"][$SerieX]["Axis"]; + $SerieY = $Series["Y"]; $SerieValuesY = $Data["Series"][$SerieY]["Data"]; $SerieYAxis = $Data["Series"][$SerieY]["Axis"]; + $Ticks = $Series["Ticks"]; + $Weight = $Series["Weight"]; + + if ( $ImageMapTitle == NULL ) { $Description = $Data["Series"][$Series["X"]]["Description"]." / ".$Data["Series"][$Series["Y"]]["Description"]; } else { $Description = $ImageMapTitle; } + + $PosArrayX = $this->getPosArray($SerieValuesX,$SerieXAxis); + if ( !is_array($PosArrayX) ) { $Value = $PosArrayX; $PosArrayX = ""; $PosArrayX[0] = $Value; } + $PosArrayY = $this->getPosArray($SerieValuesY,$SerieYAxis); + if ( !is_array($PosArrayY) ) { $Value = $PosArrayY; $PosArrayY = ""; $PosArrayY[0] = $Value; } + + $SplineSettings = array("R"=>$Series["Color"]["R"],"G"=>$Series["Color"]["G"],"B"=>$Series["Color"]["B"],"Alpha"=>$Series["Color"]["Alpha"]); + if ( $Ticks != 0 ) { $SplineSettings["Ticks"] = $Ticks; } + if ( $Weight != 0 ) { $SplineSettings["Weight"] = $Weight; } + + $LastX = VOID; $LastY = VOID; $WayPoints = ""; $Forces = ""; + foreach($PosArrayX as $Key => $Value) + { + $X = $Value; $Y = $PosArrayY[$Key]; + $Force = $this->pChartObject->getLength($LastX,$LastY,$X,$Y)/5; + + if ( $X != VOID && $Y != VOID ) + { + $RealValue = round($Data["Series"][$Series["X"]]["Data"][$Key],2)." / ".round($Data["Series"][$Series["Y"]]["Data"][$Key],2); + if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$ImageMapPlotSize,$this->pChartObject->toHTMLColor($Series["Color"]["R"],$Series["Color"]["G"],$Series["Color"]["B"]),$Description,$RealValue); } + } + + if ( $X != VOID && $Y != VOID ) + { $WayPoints[] = array($X,$Y); $Forces[] = $Force; } + + if ( $Y == VOID || $X == VOID ) + { $SplineSettings["Forces"] = $Forces; $this->pChartObject->drawSpline($WayPoints,$SplineSettings); $WayPoints = ""; $Forces = "";} + + $LastX = $X; $LastY = $Y; + } + $SplineSettings["Forces"] = $Forces; + $this->pChartObject->drawSpline($WayPoints,$SplineSettings); + } + } + } + + /* Return the scaled plot position */ + function getPosArray($Values,$AxisID) + { + $Data = $this->pDataObject->getData(); + + if ( !is_array($Values) ) { $Values = array($Values); } + + if ( $Data["Axis"][$AxisID]["Identity"] == AXIS_X ) + { + $Height = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1) - $Data["Axis"][$AxisID]["Margin"]*2; + $ScaleHeight = $Data["Axis"][$AxisID]["ScaleMax"] - $Data["Axis"][$AxisID]["ScaleMin"]; + $Step = $Height / $ScaleHeight; + + $Result = ""; + foreach($Values as $Key => $Value) + { + if ( $Value == VOID ) + $Result[] = VOID; + else + $Result[] = $this->pChartObject->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"] + ($Step * ($Value-$Data["Axis"][$AxisID]["ScaleMin"])); + } + + if ( count($Result) == 1 ) { return($Result[0]); } else { return($Result); } + } + else + { + $Height = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1) - $Data["Axis"][$AxisID]["Margin"]*2; + $ScaleHeight = $Data["Axis"][$AxisID]["ScaleMax"] - $Data["Axis"][$AxisID]["ScaleMin"]; + $Step = $Height / $ScaleHeight; + + $Result = ""; + foreach($Values as $Key => $Value) + { + if ( $Value == VOID ) + $Result[] = VOID; + else + $Result[] = $this->pChartObject->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"] - ($Step * ($Value-$Data["Axis"][$AxisID]["ScaleMin"])); + } + + if ( count($Result) == 1 ) { return($Result[0]); } else { return($Result); } + } + } + + /* Draw the legend of the active series */ + function drawScatterLegend($X,$Y,$Format="") + { + $Family = isset($Format["Family"]) ? $Format["Family"] : LEGEND_FAMILY_BOX; + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->pChartObject->FontName; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->pChartObject->FontSize; + $FontR = isset($Format["FontR"]) ? $Format["FontR"] : $this->pChartObject->FontColorR; + $FontG = isset($Format["FontG"]) ? $Format["FontG"] : $this->pChartObject->FontColorG; + $FontB = isset($Format["FontB"]) ? $Format["FontB"] : $this->pChartObject->FontColorB; + $BoxWidth = isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 5; + $BoxHeight = isset($Format["BoxHeight"]) ? $Format["BoxHeight"] : 5; + $IconAreaWidth = isset($Format["IconAreaWidth"]) ? $Format["IconAreaWidth"] : $BoxWidth; + $IconAreaHeight = isset($Format["IconAreaHeight"]) ? $Format["IconAreaHeight"] : $BoxHeight; + $XSpacing = isset($Format["XSpacing"]) ? $Format["XSpacing"] : 5; + $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5; + $R = isset($Format["R"]) ? $Format["R"] : 200; + $G = isset($Format["G"]) ? $Format["G"] : 200; + $B = isset($Format["B"]) ? $Format["B"] : 200; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 255; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 255; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 255; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $Style = isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND; + $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL; + + if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; } + + $Data = $this->pDataObject->getData(); + + foreach($Data["ScatterSeries"] as $Key => $Series) + { + if ( $Series["isDrawable"] == TRUE && isset($Series["Picture"])) + { + list($PicWidth,$PicHeight) = $this->pChartObject->getPicInfo($Series["Picture"]); + if ( $IconAreaWidth < $PicWidth ) { $IconAreaWidth = $PicWidth; } + if ( $IconAreaHeight < $PicHeight ) { $IconAreaHeight = $PicHeight; } + } + } + + $YStep = max($this->pChartObject->FontSize,$IconAreaHeight) + 5; + $XStep = $IconAreaWidth + 5; + $XStep = $XSpacing; + + $Boundaries = ""; $Boundaries["L"] = $X; $Boundaries["T"] = $Y; $Boundaries["R"] = 0; $Boundaries["B"] = 0; $vY = $Y; $vX = $X; + foreach($Data["ScatterSeries"] as $Key => $Series) + { + if ( $Series["isDrawable"] == TRUE ) + { + if ( $Mode == LEGEND_VERTICAL ) + { + $BoxArray = $this->pChartObject->getTextBox($vX+$IconAreaWidth+4,$vY+$IconAreaHeight/2,$FontName,$FontSize,0,$Series["Description"]); + + if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; } + if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } + if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; } + + $Lines = preg_split("/\n/",$Series["Description"]); + $vY = $vY + max($this->pChartObject->FontSize*count($Lines),$IconAreaHeight) + 5; + } + elseif ( $Mode == LEGEND_HORIZONTAL ) + { + $Lines = preg_split("/\n/",$Series["Description"]); + $Width = ""; + foreach($Lines as $Key => $Value) + { + $BoxArray = $this->pChartObject->getTextBox($vX+$IconAreaWidth+6,$Y+$IconAreaHeight/2+(($this->pChartObject->FontSize+3)*$Key),$FontName,$FontSize,0,$Value); + + if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; } + if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } + if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; } + + $Width[] = $BoxArray[1]["X"]; + } + + $vX=max($Width)+$XStep; + } + } + } + $vY=$vY-$YStep; $vX=$vX-$XStep; + + $TopOffset = $Y - $Boundaries["T"]; + if ( $Boundaries["B"]-($vY+$IconAreaHeight) < $TopOffset ) { $Boundaries["B"] = $vY+$IconAreaHeight+$TopOffset; } + + if ( $Style == LEGEND_ROUND ) + $this->pChartObject->drawRoundedFilledRectangle($Boundaries["L"]-$Margin,$Boundaries["T"]-$Margin,$Boundaries["R"]+$Margin,$Boundaries["B"]+$Margin,$Margin,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB)); + elseif ( $Style == LEGEND_BOX ) + $this->pChartObject->drawFilledRectangle($Boundaries["L"]-$Margin,$Boundaries["T"]-$Margin,$Boundaries["R"]+$Margin,$Boundaries["B"]+$Margin,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB)); + + $RestoreShadow = $this->pChartObject->Shadow; $this->Shadow = FALSE; + foreach($Data["ScatterSeries"] as $Key => $Series) + { + if ( $Series["isDrawable"] == TRUE ) + { + $R = $Series["Color"]["R"]; $G = $Series["Color"]["G"]; $B = $Series["Color"]["B"]; + $Ticks = $Series["Ticks"]; $Weight = $Series["Weight"]; + + if ( isset($Series["Picture"]) ) + { + $Picture = $Series["Picture"]; + list($PicWidth,$PicHeight) = $this->pChartObject->getPicInfo($Picture); + $PicX = $X+$IconAreaWidth/2; $PicY = $Y+$IconAreaHeight/2; + + $this->pChartObject->drawFromPNG($PicX-$PicWidth/2,$PicY-$PicHeight/2,$Picture); + } + else + { + if ( $Family == LEGEND_FAMILY_BOX ) + { + if ( $BoxWidth != $IconAreaWidth ) { $XOffset = floor(($IconAreaWidth-$BoxWidth)/2); } else { $XOffset = 0; } + if ( $BoxHeight != $IconAreaHeight ) { $YOffset = floor(($IconAreaHeight-$BoxHeight)/2); } else { $YOffset = 0; } + + $this->pChartObject->drawFilledRectangle($X+1+$XOffset,$Y+1+$YOffset,$X+$BoxWidth+$XOffset+1,$Y+$BoxHeight+1+$YOffset,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20)); + $this->pChartObject->drawFilledRectangle($X+$XOffset,$Y+$YOffset,$X+$BoxWidth+$XOffset,$Y+$BoxHeight+$YOffset,array("R"=>$R,"G"=>$G,"B"=>$B,"Surrounding"=>20)); + } + elseif ( $Family == LEGEND_FAMILY_CIRCLE ) + { + $this->pChartObject->drawFilledCircle($X+1+$IconAreaWidth/2,$Y+1+$IconAreaHeight/2,min($IconAreaHeight/2,$IconAreaWidth/2),array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20)); + $this->pChartObject->drawFilledCircle($X+$IconAreaWidth/2,$Y+$IconAreaHeight/2,min($IconAreaHeight/2,$IconAreaWidth/2),array("R"=>$R,"G"=>$G,"B"=>$B,"Surrounding"=>20)); + } + elseif ( $Family == LEGEND_FAMILY_LINE ) + { + $this->pChartObject->drawLine($X+1,$Y+1+$IconAreaHeight/2,$X+1+$IconAreaWidth,$Y+1+$IconAreaHeight/2,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20,"Ticks"=>$Ticks,"Weight"=>$Weight)); + $this->pChartObject->drawLine($X,$Y+$IconAreaHeight/2,$X+$IconAreaWidth,$Y+$IconAreaHeight/2,array("R"=>$R,"G"=>$G,"B"=>$B,"Ticks"=>$Ticks,"Weight"=>$Weight)); + } + } + + if ( $Mode == LEGEND_VERTICAL ) + { + $Lines = preg_split("/\n/",$Series["Description"]); + foreach($Lines as $Key => $Value) + $this->pChartObject->drawText($X+$IconAreaWidth+4,$Y+$IconAreaHeight/2+(($this->pChartObject->FontSize+3)*$Key),$Value,array("R"=>$FontR,"G"=>$FontG,"B"=>$FontB,"Align"=>TEXT_ALIGN_MIDDLELEFT)); + + $Y=$Y+max($this->pChartObject->FontSize*count($Lines),$IconAreaHeight) + 5; + } + elseif ( $Mode == LEGEND_HORIZONTAL ) + { + $Lines = preg_split("/\n/",$Series["Description"]); + $Width = ""; + foreach($Lines as $Key => $Value) + { + $BoxArray = $this->pChartObject->drawText($X+$IconAreaWidth+4,$Y+$IconAreaHeight/2+(($this->pChartObject->FontSize+3)*$Key),$Value,array("R"=>$FontR,"G"=>$FontG,"B"=>$FontB,"Align"=>TEXT_ALIGN_MIDDLELEFT)); + $Width[] = $BoxArray[1]["X"]; + } + $X=max($Width)+2+$XStep; + } + } + } + + $this->Shadow = $RestoreShadow; + } + + /* Get the legend box size */ + function getScatterLegendSize($Format="") + { + $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->pChartObject->FontName; + $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->pChartObject->FontSize; + $BoxSize = isset($Format["BoxSize"]) ? $Format["BoxSize"] : 5; + $Margin = isset($Format["Margin"]) ? $Format["Margin"] : 5; + $Style = isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND; + $Mode = isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL; + + $YStep = max($this->pChartObject->FontSize,$BoxSize) + 5; + $XStep = $BoxSize + 5; + + $X=100; $Y=100; + + $Data = $this->pDataObject->getData(); + + foreach($Data["ScatterSeries"] as $Key => $Series) + { + if ( $Series["isDrawable"] == TRUE && isset($Series["Picture"])) + { + list($PicWidth,$PicHeight) = $this->pChartObject->getPicInfo($Series["Picture"]); + if ( $IconAreaWidth < $PicWidth ) { $IconAreaWidth = $PicWidth; } + if ( $IconAreaHeight < $PicHeight ) { $IconAreaHeight = $PicHeight; } + } + } + + $YStep = max($this->pChartObject->FontSize,$IconAreaHeight) + 5; + $XStep = $IconAreaWidth + 5; + $XStep = $XSpacing; + + $Boundaries = ""; $Boundaries["L"] = $X; $Boundaries["T"] = $Y; $Boundaries["R"] = 0; $Boundaries["B"] = 0; $vY = $Y; $vX = $X; + foreach($Data["ScatterSeries"] as $Key => $Series) + { + if ( $Series["isDrawable"] == TRUE ) + { + if ( $Mode == LEGEND_VERTICAL ) + { + $BoxArray = $this->pChartObject->getTextBox($vX+$IconAreaWidth+4,$vY+$IconAreaHeight/2,$FontName,$FontSize,0,$Series["Description"]); + + if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; } + if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } + if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; } + + $Lines = preg_split("/\n/",$Series["Description"]); + $vY = $vY + max($this->pChartObject->FontSize*count($Lines),$IconAreaHeight) + 5; + } + elseif ( $Mode == LEGEND_HORIZONTAL ) + { + $Lines = preg_split("/\n/",$Series["Description"]); + $Width = ""; + foreach($Lines as $Key => $Value) + { + $BoxArray = $this->pChartObject->getTextBox($vX+$IconAreaWidth+6,$Y+$IconAreaHeight/2+(($this->pChartObject->FontSize+3)*$Key),$FontName,$FontSize,0,$Value); + + if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; } + if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; } + if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; } + + $Width[] = $BoxArray[1]["X"]; + } + + $vX=max($Width)+$XStep; + } + } + } + $vY=$vY-$YStep; $vX=$vX-$XStep; + + $TopOffset = $Y - $Boundaries["T"]; + if ( $Boundaries["B"]-($vY+$BoxSize) < $TopOffset ) { $Boundaries["B"] = $vY+$BoxSize+$TopOffset; } + + $Width = ($Boundaries["R"]+$Margin) - ($Boundaries["L"]-$Margin); + $Height = ($Boundaries["B"]+$Margin) - ($Boundaries["T"]-$Margin); + + return(array("Width"=>$Width,"Height"=>$Height)); + } + + /* Draw the line of best fit */ + function drawScatterBestFit($Format="") + { + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : 0; + + $Data = $this->pDataObject->getData(); + + foreach($Data["ScatterSeries"] as $Key => $Series) + { + if ( $Series["isDrawable"] == TRUE ) + { + $SerieX = $Series["X"]; $SerieValuesX = $Data["Series"][$SerieX]["Data"]; $SerieXAxis = $Data["Series"][$SerieX]["Axis"]; + $SerieY = $Series["Y"]; $SerieValuesY = $Data["Series"][$SerieY]["Data"]; $SerieYAxis = $Data["Series"][$SerieY]["Axis"]; + + $Color = array("R"=>$Series["Color"]["R"],"G"=>$Series["Color"]["G"],"B"=>$Series["Color"]["B"],"Alpha"=>$Series["Color"]["Alpha"]); + $Color["Ticks"] = $Ticks; + + $PosArrayX = $Data["Series"][$Series["X"]]["Data"]; + $PosArrayY = $Data["Series"][$Series["Y"]]["Data"]; + + $Sxy = 0; $Sx = 0; $Sy = 0; $Sxx = 0; + foreach($PosArrayX as $Key => $Value) + { + $X = $Value; $Y = $PosArrayY[$Key]; + + $Sxy = $Sxy + $X*$Y; + $Sx = $Sx + $X; + $Sy = $Sy + $Y; + $Sxx = $Sxx + $X*$X; + } + + $n = count($PosArrayX); + + if ((($n*$Sxx) == ($Sx*$Sx))) + { + $X1 = $this->getPosArray($Data["Axis"][$SerieXAxis]["ScaleMin"],$SerieXAxis); + $X2 = $X1; + $Y1 = $this->pChartObject->GraphAreaY1; + $Y2 = $this->pChartObject->GraphAreaY2; + } + else + { + $M = (($n*$Sxy)-($Sx*$Sy)) / (($n*$Sxx)-($Sx*$Sx)); + $B = (($Sy)-($M*$Sx))/($n); + + $X1 = $this->getPosArray($Data["Axis"][$SerieXAxis]["ScaleMin"],$SerieXAxis); + $Y1 = $this->getPosArray($M * $Data["Axis"][$SerieXAxis]["ScaleMin"] + $B,$SerieYAxis); + $X2 = $this->getPosArray($Data["Axis"][$SerieXAxis]["ScaleMax"],$SerieXAxis); + $Y2 = $this->getPosArray($M * $Data["Axis"][$SerieXAxis]["ScaleMax"] + $B,$SerieYAxis); + + $RealM = -($Y2-$Y1)/($X2-$X1); + + if ( $Y1 < $this->pChartObject->GraphAreaY1 ) { $X1 = $X1 + ($this->pChartObject->GraphAreaY1-$Y1/$RealM); $Y1 = $this->pChartObject->GraphAreaY1; } + if ( $Y1 > $this->pChartObject->GraphAreaY2 ) { $X1 = $X1 + ($Y1-$this->pChartObject->GraphAreaY2)/$RealM; $Y1 = $this->pChartObject->GraphAreaY2; } + if ( $Y2 < $this->pChartObject->GraphAreaY1 ) { $X2 = $X2 - ($this->pChartObject->GraphAreaY1-$Y2)/$RealM; $Y2 = $this->pChartObject->GraphAreaY1; } + if ( $Y2 > $this->pChartObject->GraphAreaY2 ) { $X2 = $X2 - ($Y2-$this->pChartObject->GraphAreaY2)/$RealM; $Y2 = $this->pChartObject->GraphAreaY2; } + } + + $this->pChartObject->drawLine($X1,$Y1,$X2,$Y2,$Color); + } + } + } + + function writeScatterLabel($ScatterSerieID,$Points,$Format="") + { + $OverrideTitle = isset($Format["OverrideTitle"]) ? $Format["OverrideTitle"] : NULL; + $DrawPoint = isset($Format["DrawPoint"]) ? $Format["DrawPoint"] : LABEL_POINT_BOX; + $Decimals = isset($Format["Decimals"]) ? $Format["Decimals"] : NULL; + + $Data = $this->pDataObject->getData(); + $Palette = $this->pDataObject->getPalette(); + + if ( !is_array($Points) ) { $Point = $Points; $Points = ""; $Points[0] = $Point; } + + if ( !isset($Data["ScatterSeries"][$ScatterSerieID]) ) + return(0); + + $Series = $Data["ScatterSeries"][$ScatterSerieID]; + $SerieX = $Series["X"]; $SerieValuesX = $Data["Series"][$SerieX]["Data"]; $SerieXAxis = $Data["Series"][$SerieX]["Axis"]; + $SerieY = $Series["Y"]; $SerieValuesY = $Data["Series"][$SerieY]["Data"]; $SerieYAxis = $Data["Series"][$SerieY]["Axis"]; + + $PosArrayX = $this->getPosArray($SerieValuesX,$SerieXAxis); + if ( !is_array($PosArrayX) ) { $Value = $PosArrayX; $PosArrayX = ""; $PosArrayX[0] = $Value; } + $PosArrayY = $this->getPosArray($SerieValuesY,$SerieYAxis); + if ( !is_array($PosArrayY) ) { $Value = $PosArrayY; $PosArrayY = ""; $PosArrayY[0] = $Value; } + + foreach($Points as $Key => $Point) + { + if ( isset($PosArrayX[$Point]) && isset($PosArrayY[$Point]) ) + { + $X = floor($PosArrayX[$Point]); + $Y = floor($PosArrayY[$Point]); + + if ( $DrawPoint == LABEL_POINT_CIRCLE ) + $this->pChartObject->drawFilledCircle($X,$Y,3,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0)); + elseif ( $DrawPoint == LABEL_POINT_BOX ) + $this->pChartObject->drawFilledRectangle($X-2,$Y-2,$X+2,$Y+2,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0)); + + $Serie = ""; + $Serie["R"] = $Series["Color"]["R"]; + $Serie["G"] = $Series["Color"]["G"]; + $Serie["B"] = $Series["Color"]["B"]; + $Serie["Alpha"] = $Series["Color"]["Alpha"]; + + $XAxisMode = $Data["Axis"][$SerieXAxis]["Display"]; + $XAxisFormat = $Data["Axis"][$SerieXAxis]["Format"]; + $XAxisUnit = $Data["Axis"][$SerieXAxis]["Unit"]; + if ( $Decimals == NULL ) { $XValue = $SerieValuesX[$Point]; } else { $XValue = round($SerieValuesX[$Point],$Decimals); } + $XValue = $this->pChartObject->scaleFormat($XValue,$XAxisMode,$XAxisFormat,$XAxisUnit); + + $YAxisMode = $Data["Axis"][$SerieYAxis]["Display"]; + $YAxisFormat = $Data["Axis"][$SerieYAxis]["Format"]; + $YAxisUnit = $Data["Axis"][$SerieYAxis]["Unit"]; + if ( $Decimals == NULL ) { $YValue = $SerieValuesY[$Point]; } else { $YValue = round($SerieValuesY[$Point],$Decimals); } + $YValue = $this->pChartObject->scaleFormat($YValue,$YAxisMode,$YAxisFormat,$YAxisUnit); + + $Caption = $XValue." / ".$YValue; + + if ( isset($Series["Description"]) ) + $Description = $Series["Description"]; + else + $Description = "No description"; + + $Series = ""; + $Series[] = array("Format"=>$Serie,"Caption"=>$Caption); + + $this->pChartObject->drawLabelBox($X,$Y-3,$Description,$Series,$Format); + } + } + } + + /* Draw a Scatter threshold */ + function drawScatterThreshold($Value,$Format="") + { + $AxisID = isset($Format["AxisID"]) ? $Format["AxisID"] : 0; + $R = isset($Format["R"]) ? $Format["R"] : 255; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 50; + $Weight = isset($Format["Weight"]) ? $Format["Weight"] : NULL; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : 3; + $Wide = isset($Format["Wide"]) ? $Format["Wide"] : FALSE; + $WideFactor = isset($Format["WideFactor"]) ? $Format["WideFactor"] : 5; + $WriteCaption = isset($Format["WriteCaption"]) ? $Format["WriteCaption"] : FALSE; + $Caption = isset($Format["Caption"]) ? $Format["Caption"] : NULL; + $CaptionAlign = isset($Format["CaptionAlign"]) ? $Format["CaptionAlign"] : CAPTION_LEFT_TOP; + $CaptionOffset = isset($Format["CaptionOffset"]) ? $Format["CaptionOffset"] : 10; + $CaptionR = isset($Format["CaptionR"]) ? $Format["CaptionR"] : 255; + $CaptionG = isset($Format["CaptionG"]) ? $Format["CaptionG"] : 255; + $CaptionB = isset($Format["CaptionB"]) ? $Format["CaptionB"] : 255; + $CaptionAlpha = isset($Format["CaptionAlpha"]) ? $Format["CaptionAlpha"] : 100; + $DrawBox = isset($Format["DrawBox"]) ? $Format["DrawBox"] : TRUE; + $DrawBoxBorder = isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : FALSE; + $BorderOffset = isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 5; + $BoxRounded = isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : TRUE; + $RoundedRadius = isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 3; + $BoxR = isset($Format["BoxR"]) ? $Format["BoxR"] : 0; + $BoxG = isset($Format["BoxG"]) ? $Format["BoxG"] : 0; + $BoxB = isset($Format["BoxB"]) ? $Format["BoxB"] : 0; + $BoxAlpha = isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 20; + $BoxSurrounding = isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : ""; + $BoxBorderR = isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 255; + $BoxBorderG = isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 255; + $BoxBorderB = isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 255; + $BoxBorderAlpha = isset($Format["BoxBorderAlpha"]) ? $Format["BoxBorderAlpha"] : 100; + + $CaptionSettings = array("DrawBox"=>$DrawBox,"DrawBoxBorder"=>$DrawBoxBorder,"BorderOffset"=>$BorderOffset,"BoxRounded"=>$BoxRounded,"RoundedRadius"=>$RoundedRadius, + "BoxR"=>$BoxR,"BoxG"=>$BoxG,"BoxB"=>$BoxB,"BoxAlpha"=>$BoxAlpha,"BoxSurrounding"=>$BoxSurrounding, + "BoxBorderR"=>$BoxBorderR,"BoxBorderG"=>$BoxBorderG,"BoxBorderB"=>$BoxBorderB,"BoxBorderAlpha"=>$BoxBorderAlpha, + "R"=>$CaptionR,"G"=>$CaptionG,"B"=>$CaptionB,"Alpha"=>$CaptionAlpha); + + if ( $Caption == NULL ) { $Caption = $Value; } + + $Data = $this->pDataObject->getData(); + + if ( !isset($Data["Axis"][$AxisID]) ) { return(-1); } + + if ( $Data["Axis"][$AxisID]["Identity"] == AXIS_Y ) + { + $X1 = $this->pChartObject->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"]; + $X2 = $this->pChartObject->GraphAreaX2 - $Data["Axis"][$AxisID]["Margin"]; + $Y = $this->getPosArray($Value,$AxisID); + + $this->pChartObject->drawLine($X1,$Y,$X2,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + + if ( $Wide ) + { + $this->pChartObject->drawLine($X1,$Y-1,$X2,$Y-1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + $this->pChartObject->drawLine($X1,$Y+1,$X2,$Y+1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + } + + if ( $WriteCaption ) + { + if ( $CaptionAlign == CAPTION_LEFT_TOP ) + { $X = $this->pChartObject->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"] + $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLELEFT; } + else + { $X = $this->pChartObject->GraphAreaX2 - $Data["Axis"][$AxisID]["Margin"] - $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLERIGHT; } + + $this->pChartObject->drawText($X,$Y,$Caption,$CaptionSettings); + } + + return(array("Y"=>$Y)); + } + elseif ( $Data["Axis"][$AxisID]["Identity"] == AXIS_X ) + { + $X = $this->getPosArray($Value,$AxisID); + $Y1 = $this->pChartObject->GraphAreaY1 + $Data["Axis"][$AxisID]["Margin"]; + $Y2 = $this->pChartObject->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"]; + + $this->pChartObject->drawLine($X,$Y1,$X,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); + + if ( $Wide ) + { + $this->pChartObject->drawLine($X-1,$Y1,$X-1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + $this->pChartObject->drawLine($X+1,$Y1,$X+1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks)); + } + + if ( $WriteCaption ) + { + if ( $CaptionAlign == CAPTION_LEFT_TOP ) + { $Y = $this->pChartObject->GraphAreaY1 + $Data["Axis"][$AxisID]["Margin"] + $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE; } + else + { $Y = $this->pChartObject->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"] - $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_BOTTOMMIDDLE; } + + $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE; + $this->pChartObject->drawText($X,$Y,$Caption,$CaptionSettings); + } + + return(array("X"=>$X)); + } + } + + /* Draw a Scatter threshold area */ + function drawScatterThresholdArea($Value1,$Value2,$Format="") + { + $AxisID = isset($Format["AxisID"]) ? $Format["AxisID"] : 0; + $R = isset($Format["R"]) ? $Format["R"] : 255; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 20; + $Border = isset($Format["Border"]) ? $Format["Border"] : TRUE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : $R; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : $G; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : $B; + $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha + 20; + $BorderTicks = isset($Format["BorderTicks"]) ? $Format["BorderTicks"] : 2; + $AreaName = isset($Format["AreaName"]) ? $Format["AreaName"] : "La ouate de phoque"; //NULL; + $NameAngle = isset($Format["NameAngle"]) ? $Format["NameAngle"] : ZONE_NAME_ANGLE_AUTO; + $NameR = isset($Format["NameR"]) ? $Format["NameR"] : 255; + $NameG = isset($Format["NameG"]) ? $Format["NameG"] : 255; + $NameB = isset($Format["NameB"]) ? $Format["NameB"] : 255; + $NameAlpha = isset($Format["NameAlpha"]) ? $Format["NameAlpha"] : 100; + $DisableShadowOnArea = isset($Format["DisableShadowOnArea"]) ? $Format["DisableShadowOnArea"] : TRUE; + + if ($Value1 > $Value2) { list($Value1, $Value2) = array($Value2, $Value1); } + + $RestoreShadow = $this->pChartObject->Shadow; + if ( $DisableShadowOnArea && $this->pChartObject->Shadow ) { $this->pChartObject->Shadow = FALSE; } + + if ($BorderAlpha >100) { $BorderAlpha = 100;} + + $Data = $this->pDataObject->getData(); + + if ( !isset($Data["Axis"][$AxisID]) ) { return(-1); } + + if ( $Data["Axis"][$AxisID]["Identity"] == AXIS_X ) + { + $Y1 = $this->pChartObject->GraphAreaY1 + $Data["Axis"][$AxisID]["Margin"]; + $Y2 = $this->pChartObject->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"]; + $X1 = $this->getPosArray($Value1,$AxisID); + $X2 = $this->getPosArray($Value2,$AxisID); + + if ( $X1 <= $this->pChartObject->GraphAreaX1 ) { $X1 = $this->pChartObject->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"]; } + if ( $X2 >= $this->pChartObject->GraphAreaX2 ) { $X2 = $this->pChartObject->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"]; } + + $this->pChartObject->drawFilledRectangle($X1,$Y1,$X2,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + if ( $Border ) + { + $this->pChartObject->drawLine($X1,$Y1,$X1,$Y2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + $this->pChartObject->drawLine($X2,$Y1,$X2,$Y2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + } + + if ( $AreaName != NULL ) + { + $XPos = ($X2-$X1)/2 + $X1; + $YPos = ($Y2-$Y1)/2 + $Y1; + + if ( $NameAngle == ZONE_NAME_ANGLE_AUTO ) + { + $TxtPos = $this->pChartObject->getTextBox($XPos,$YPos,$this->pChartObject->FontName,$this->pChartObject->FontSize,0,$AreaName); + $TxtWidth = $TxtPos[1]["X"] - $TxtPos[0]["X"]; + if ( abs($X2 - $X1) > $TxtWidth ) { $NameAngle = 0; } else { $NameAngle = 90; } + } + $this->pChartObject->Shadow = $RestoreShadow; + $this->pChartObject->drawText($XPos,$YPos,$AreaName,array("R"=>$NameR,"G"=>$NameG,"B"=>$NameB,"Alpha"=>$NameAlpha,"Angle"=>$NameAngle,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE)); + if ( $DisableShadowOnArea ) { $this->pChartObject->Shadow = FALSE; } + } + + $this->pChartObject->Shadow = $RestoreShadow; + return(array("X1"=>$X1,"X2"=>$X2)); + } + elseif ( $Data["Axis"][$AxisID]["Identity"] == AXIS_Y ) + { + $X1 = $this->pChartObject->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"]; + $X2 = $this->pChartObject->GraphAreaX2 - $Data["Axis"][$AxisID]["Margin"]; + $Y1 = $this->getPosArray($Value1,$AxisID); + $Y2 = $this->getPosArray($Value2,$AxisID); + + if ( $Y1 >= $this->pChartObject->GraphAreaY2 ) { $Y1 = $this->pChartObject->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"]; } + if ( $Y2 <= $this->pChartObject->GraphAreaY1 ) { $Y2 = $this->pChartObject->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"]; } + + $this->pChartObject->drawFilledRectangle($X1,$Y1,$X2,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha)); + + if ( $Border ) + { + $this->pChartObject->drawLine($X1,$Y1,$X2,$Y1,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + $this->pChartObject->drawLine($X1,$Y2,$X2,$Y2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks)); + } + + if ( $AreaName != NULL ) + { + $XPos = ($X2-$X1)/2 + $X1; + $YPos = ($Y2-$Y1)/2 + $Y1; + + $this->pChartObject->Shadow = $RestoreShadow; + $this->pChartObject->drawText($YPos,$XPos,$AreaName,array("R"=>$NameR,"G"=>$NameG,"B"=>$NameB,"Alpha"=>$NameAlpha,"Angle"=>0,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE)); + if ( $DisableShadowOnArea ) { $this->Shadow = FALSE; } + } + + $this->pChartObject->Shadow = $RestoreShadow; + return(array("Y1"=>$Y1,"Y2"=>$Y2)); + } + } + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/class/pSplit.class.php b/trunk/includes/pChart/class/pSplit.class.php new file mode 100644 index 0000000..248ffea --- /dev/null +++ b/trunk/includes/pChart/class/pSplit.class.php @@ -0,0 +1,131 @@ +pChartObject = $Object; + + $Spacing = isset($Format["Spacing"]) ? $Format["Spacing"] : 20; + $TextPadding = isset($Format["TextPadding"]) ? $Format["TextPadding"] : 2; + $TextPos = isset($Format["TextPos"]) ? $Format["TextPos"] : TEXT_POS_TOP; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL; + $Force = isset($Format["Force"]) ? $Format["Force"] : 70; + $Segments = isset($Format["Segments"]) ? $Format["Segments"] : 15; + $FontSize = $Object->FontSize; + $X1 = $Object->GraphAreaX1; + $Y1 = $Object->GraphAreaY1; + $X2 = $Object->GraphAreaX2; + $Y2 = $Object->GraphAreaY2; + + /* Data Processing */ + $Data = $Values->getData(); + $Palette = $Values->getPalette(); + + $LabelSerie = $Data["Abscissa"]; + $DataSerie = ""; + + foreach($Data["Series"] as $SerieName => $Value) + { if ( $SerieName != $LabelSerie && $DataSerie == "" ) { $DataSerie = $SerieName; } } + + $DataSerieSum = array_sum($Data["Series"][$DataSerie]["Data"]); + $DataSerieCount = count($Data["Series"][$DataSerie]["Data"]); + + /* Scale Processing */ + if ( $TextPos == TEXT_POS_RIGHT ) + $YScale = (($Y2-$Y1) - (($DataSerieCount+1)*$Spacing)) / $DataSerieSum; + else + $YScale = (($Y2-$Y1) - ($DataSerieCount*$Spacing)) / $DataSerieSum; + $LeftHeight = $DataSerieSum * $YScale; + + /* Re-compute graph width depending of the text mode choosen */ + if ( $TextPos == TEXT_POS_RIGHT ) + { + $MaxWidth = 0; + foreach($Data["Series"][$LabelSerie]["Data"] as $Key => $Label) + { + $Boundardies = $Object->getTextBox(0,0,$Object->FontName,$Object->FontSize,0,$Label); + if ( $Boundardies[1]["X"] > $MaxWidth ) { $MaxWidth = $Boundardies[1]["X"] + $TextPadding*2; } + } + $X2 = $X2 - $MaxWidth; + } + + /* Drawing */ + $LeftY = ((($Y2-$Y1) / 2) + $Y1) - ($LeftHeight/2); + $RightY = $Y1; + $VectorX = (($X2-$X1) / 2); + + foreach($Data["Series"][$DataSerie]["Data"] as $Key => $Value) + { + if ( isset($Data["Series"][$LabelSerie]["Data"][$Key]) ) + $Label = $Data["Series"][$LabelSerie]["Data"][$Key]; + else + $Label = "-"; + + $LeftY1 = $LeftY; + $LeftY2 = $LeftY + $Value * $YScale; + + $RightY1 = $RightY + $Spacing; + $RightY2 = $RightY + $Spacing + $Value * $YScale;; + + $Settings = array("R"=>$Palette[$Key]["R"],"G"=>$Palette[$Key]["G"],"B"=>$Palette[$Key]["B"],"Alpha"=>$Palette[$Key]["Alpha"],"NoDraw"=>TRUE,"Segments"=>$Segments,"Surrounding"=>$Surrounding); + + $PolyGon = ""; + + $Angle = $Object->getAngle($X2,$RightY1,$X1,$LeftY1); + $VectorX1 = cos(deg2rad($Angle+90)) * $Force + ($X2-$X1)/2 + $X1; + $VectorY1 = sin(deg2rad($Angle+90)) * $Force + ($RightY1-$LeftY1)/2 + $LeftY1; + $VectorX2 = cos(deg2rad($Angle-90)) * $Force + ($X2-$X1)/2 + $X1; + $VectorY2 = sin(deg2rad($Angle-90)) * $Force + ($RightY1-$LeftY1)/2 + $LeftY1; + + $Points = $Object->drawBezier($X1,$LeftY1,$X2,$RightY1,$VectorX1,$VectorY1,$VectorX2,$VectorY2,$Settings); + foreach($Points as $Key => $Pos) { $PolyGon[] = $Pos["X"]; $PolyGon[] = $Pos["Y"]; } + + + $Angle = $Object->getAngle($X2,$RightY2,$X1,$LeftY2); + $VectorX1 = cos(deg2rad($Angle+90)) * $Force + ($X2-$X1)/2 +$X1; + $VectorY1 = sin(deg2rad($Angle+90)) * $Force + ($RightY2-$LeftY2)/2 + $LeftY2; + $VectorX2 = cos(deg2rad($Angle-90)) * $Force + ($X2-$X1)/2 +$X1; + $VectorY2 = sin(deg2rad($Angle-90)) * $Force + ($RightY2-$LeftY2)/2 + $LeftY2; + + $Points = $Object->drawBezier($X1,$LeftY2,$X2,$RightY2,$VectorX1,$VectorY1,$VectorX2,$VectorY2,$Settings); + $Points = array_reverse($Points); + foreach($Points as $Key => $Pos) { $PolyGon[] = $Pos["X"]; $PolyGon[] = $Pos["Y"]; } + + $Object->drawPolygon($PolyGon,$Settings); + + if ( $TextPos == TEXT_POS_RIGHT ) + $Object->drawText($X2+$TextPadding,($RightY2-$RightY1)/2+$RightY1,$Label,array("Align"=>TEXT_ALIGN_MIDDLELEFT)); + else + $Object->drawText($X2,$RightY1-$TextPadding,$Label,array("Align"=>TEXT_ALIGN_BOTTOMRIGHT)); + + $LeftY = $LeftY2; + $RightY = $RightY2; + } + } + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/class/pSpring.class.php b/trunk/includes/pChart/class/pSpring.class.php new file mode 100644 index 0000000..30ea1a6 --- /dev/null +++ b/trunk/includes/pChart/class/pSpring.class.php @@ -0,0 +1,868 @@ +Data = ""; + $this->Links = ""; + + /* Set nodes defaults */ + $this->Default["R"] = 255; + $this->Default["G"] = 255; + $this->Default["B"] = 255; + $this->Default["Alpha"] = 100; + $this->Default["BorderR"] = 0; + $this->Default["BorderG"] = 0; + $this->Default["BorderB"] = 0; + $this->Default["BorderAlpha"] = 100; + $this->Default["Surrounding"] = NULL; + $this->Default["BackgroundR"] = 255; + $this->Default["BackgroundG"] = 255; + $this->Default["BackgroundB"] = 255; + $this->Default["BackgroundAlpha"] = 0; + $this->Default["Force"] = 1; + $this->Default["NodeType"] = NODE_TYPE_FREE; + $this->Default["Size"] = 5; + $this->Default["Shape"] = NODE_SHAPE_CIRCLE; + $this->Default["FreeZone"] = 40; + $this->Default["LinkR"] = 0; + $this->Default["LinkG"] = 0; + $this->Default["LinkB"] = 0; + $this->Default["LinkAlpha"] = 0; + + $this->Labels["Type"] = LABEL_CLASSIC; + $this->Labels["R"] = 0; + $this->Labels["G"] = 0; + $this->Labels["B"] = 0; + $this->Labels["Alpha"] = 100; + + $this->AutoComputeFreeZone = FALSE; + } + + /* Set default links options */ + function setLinkDefaults($Settings="") + { + if ( isset($Settings["R"]) ) { $this->Default["LinkR"] = $Settings["R"]; } + if ( isset($Settings["G"]) ) { $this->Default["LinkG"] = $Settings["G"]; } + if ( isset($Settings["B"]) ) { $this->Default["LinkB"] = $Settings["B"]; } + if ( isset($Settings["Alpha"]) ) { $this->Default["LinkAlpha"] = $Settings["Alpha"]; } + } + + /* Set default links options */ + function setLabelsSettings($Settings="") + { + if ( isset($Settings["Type"]) ) { $this->Labels["Type"] = $Settings["Type"]; } + if ( isset($Settings["R"]) ) { $this->Labels["R"] = $Settings["R"]; } + if ( isset($Settings["G"]) ) { $this->Labels["G"] = $Settings["G"]; } + if ( isset($Settings["B"]) ) { $this->Labels["B"] = $Settings["B"]; } + if ( isset($Settings["Alpha"]) ) { $this->Labels["Alpha"] = $Settings["Alpha"]; } + } + + /* Auto compute the FreeZone size based on the number of connections */ + function autoFreeZone() + { + /* Check connections reciprocity */ + foreach($this->Data as $Key => $Settings) + { + if ( isset($Settings["Connections"]) ) + { $this->Data[$Key]["FreeZone"] = count($Settings["Connections"])*10 + 20; } + else + { $this->Data[$Key]["FreeZone"] = 20; } + } + + } + + /* Set link properties */ + function linkProperties($FromNode,$ToNode,$Settings) + { + if ( !isset($this->Data[$FromNode]) ) { return(0); } + if ( !isset($this->Data[$ToNode]) ) { return(0); } + + $R = isset($Settings["R"]) ? $Settings["R"] : 0; + $G = isset($Settings["G"]) ? $Settings["G"] : 0; + $B = isset($Settings["B"]) ? $Settings["B"] : 0; + $Alpha = isset($Settings["Alpha"]) ? $Settings["Alpha"] : 100; + $Name = isset($Settings["Name"]) ? $Settings["Name"] : NULL; + $Ticks = isset($Settings["Ticks"]) ? $Settings["Ticks"] : NULL; + + $this->Links[$FromNode][$ToNode]["R"] = $R; $this->Links[$ToNode][$FromNode]["R"] = $R; + $this->Links[$FromNode][$ToNode]["G"] = $G; $this->Links[$ToNode][$FromNode]["G"] = $G; + $this->Links[$FromNode][$ToNode]["B"] = $B; $this->Links[$ToNode][$FromNode]["B"] = $B; + $this->Links[$FromNode][$ToNode]["Alpha"] = $Alpha; $this->Links[$ToNode][$FromNode]["Alpha"] = $Alpha; + $this->Links[$FromNode][$ToNode]["Name"] = $Name; $this->Links[$ToNode][$FromNode]["Name"] = $Name; + $this->Links[$FromNode][$ToNode]["Ticks"] = $Ticks; $this->Links[$ToNode][$FromNode]["Ticks"] = $Ticks; + } + + function setNodeDefaults($Settings="") + { + if ( isset($Settings["R"]) ) { $this->Default["R"] = $Settings["R"]; } + if ( isset($Settings["G"]) ) { $this->Default["G"] = $Settings["G"]; } + if ( isset($Settings["B"]) ) { $this->Default["B"] = $Settings["B"]; } + if ( isset($Settings["Alpha"]) ) { $this->Default["Alpha"] = $Settings["Alpha"]; } + if ( isset($Settings["BorderR"]) ) { $this->Default["BorderR"] = $Settings["BorderR"]; } + if ( isset($Settings["BorderG"]) ) { $this->Default["BorderG"] = $Settings["BorderG"]; } + if ( isset($Settings["BorderB"]) ) { $this->Default["BorderB"] = $Settings["BorderB"]; } + if ( isset($Settings["BorderAlpha"]) ) { $this->Default["BorderAlpha"] = $Settings["BorderAlpha"]; } + if ( isset($Settings["Surrounding"]) ) { $this->Default["Surrounding"] = $Settings["Surrounding"]; } + if ( isset($Settings["BackgroundR"]) ) { $this->Default["BackgroundR"] = $Settings["BackgroundR"]; } + if ( isset($Settings["BackgroundG"]) ) { $this->Default["BackgroundG"] = $Settings["BackgroundG"]; } + if ( isset($Settings["BackgroundB"]) ) { $this->Default["BackgroundB"] = $Settings["BackgroundB"]; } + if ( isset($Settings["BackgroundAlpha"]) ) { $this->Default["BackgroundAlpha"] = $Settings["BackgroundAlpha"]; } + if ( isset($Settings["NodeType"]) ) { $this->Default["NodeType"] = $Settings["NodeType"]; } + if ( isset($Settings["Size"]) ) { $this->Default["Size"] = $Settings["Size"]; } + if ( isset($Settings["Shape"]) ) { $this->Default["Shape"] = $Settings["Shape"]; } + if ( isset($Settings["FreeZone"]) ) { $this->Default["FreeZone"] = $Settings["FreeZone"]; } + } + + /* Add a node */ + function addNode($NodeID,$Settings="") + { + /* if the node already exists, ignore */ + if (isset($this->Data[$NodeID])) { return(0); } + + $Name = isset($Settings["Name"]) ? $Settings["Name"] : "Node ".$NodeID; + $Connections = isset($Settings["Connections"]) ? $Settings["Connections"] : NULL; + + $R = isset($Settings["R"]) ? $Settings["R"] : $this->Default["R"]; + $G = isset($Settings["G"]) ? $Settings["G"] : $this->Default["G"]; + $B = isset($Settings["B"]) ? $Settings["B"] : $this->Default["B"]; + $Alpha = isset($Settings["Alpha"]) ? $Settings["Alpha"] : $this->Default["Alpha"]; + $BorderR = isset($Settings["BorderR"]) ? $Settings["BorderR"] : $this->Default["BorderR"]; + $BorderG = isset($Settings["BorderG"]) ? $Settings["BorderG"] : $this->Default["BorderG"]; + $BorderB = isset($Settings["BorderB"]) ? $Settings["BorderB"] : $this->Default["BorderB"]; + $BorderAlpha = isset($Settings["BorderAlpha"]) ? $Settings["BorderAlpha"] : $this->Default["BorderAlpha"]; + $Surrounding = isset($Settings["Surrounding"]) ? $Settings["Surrounding"] : $this->Default["Surrounding"]; + $BackgroundR = isset($Settings["BackgroundR"]) ? $Settings["BackgroundR"] : $this->Default["BackgroundR"]; + $BackgroundG = isset($Settings["BackgroundG"]) ? $Settings["BackgroundG"] : $this->Default["BackgroundG"]; + $BackgroundB = isset($Settings["BackgroundB"]) ? $Settings["BackgroundB"] : $this->Default["BackgroundB"]; + $BackgroundAlpha = isset($Settings["BackgroundAlpha"]) ? $Settings["BackgroundAlpha"] : $this->Default["BackgroundAlpha"]; + $Force = isset($Settings["Force"]) ? $Settings["Force"] : $this->Default["Force"]; + $NodeType = isset($Settings["NodeType"]) ? $Settings["NodeType"] : $this->Default["NodeType"]; + $Size = isset($Settings["Size"]) ? $Settings["Size"] : $this->Default["Size"]; + $Shape = isset($Settings["Shape"]) ? $Settings["Shape"] : $this->Default["Shape"]; + $FreeZone = isset($Settings["FreeZone"]) ? $Settings["FreeZone"] : $this->Default["FreeZone"]; + + if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; } + + $this->Data[$NodeID]["R"] = $R; $this->Data[$NodeID]["G"] = $G; $this->Data[$NodeID]["B"] = $B; $this->Data[$NodeID]["Alpha"] = $Alpha; + $this->Data[$NodeID]["BorderR"] = $BorderR; $this->Data[$NodeID]["BorderG"] = $BorderG; $this->Data[$NodeID]["BorderB"] = $BorderB; $this->Data[$NodeID]["BorderAlpha"] = $BorderAlpha; + $this->Data[$NodeID]["BackgroundR"] = $BackgroundR; $this->Data[$NodeID]["BackgroundG"] = $BackgroundG; $this->Data[$NodeID]["BackgroundB"] = $BackgroundB; $this->Data[$NodeID]["BackgroundAlpha"] = $BackgroundAlpha; + $this->Data[$NodeID]["Name"] = $Name; + $this->Data[$NodeID]["Force"] = $Force; + $this->Data[$NodeID]["Type"] = $NodeType; + $this->Data[$NodeID]["Size"] = $Size; + $this->Data[$NodeID]["Shape"] = $Shape; + $this->Data[$NodeID]["FreeZone"] = $FreeZone; + if ( $Connections != NULL ) + { + if ( is_array($Connections ) ) + { + foreach($Connections as $Key => $Value) + $this->Data[$NodeID]["Connections"][] = $Value; + } + else + $this->Data[$NodeID]["Connections"][] = $Connections; + } + } + + /* Set color attribute for a list of nodes */ + function setNodesColor($Nodes,$Settings="") + { + if ( is_array($Nodes) ) + { + foreach ($Nodes as $Key => $NodeID) + { + if (isset($this->Data[$NodeID]) ) + { + if ( isset($Settings["R"]) ) { $this->Data[$NodeID]["R"] = $Settings["R"]; } + if ( isset($Settings["G"]) ) { $this->Data[$NodeID]["G"] = $Settings["G"]; } + if ( isset($Settings["B"]) ) { $this->Data[$NodeID]["B"] = $Settings["B"]; } + if ( isset($Settings["Alpha"]) ) { $this->Data[$NodeID]["Alpha"] = $Settings["Alpha"]; } + if ( isset($Settings["BorderR"]) ) { $this->Data[$NodeID]["BorderR"] = $Settings["BorderR"]; } + if ( isset($Settings["BorderG"]) ) { $this->Data[$NodeID]["BorderG"] = $Settings["BorderG"]; } + if ( isset($Settings["BorderB"]) ) { $this->Data[$NodeID]["BorderB"] = $Settings["BorderB"]; } + if ( isset($Settings["BorderAlpha"]) ) { $this->Data[$NodeID]["BorderAlpha"] = $Settings["BorderAlpha"]; } + if ( isset($Settings["Surrounding"]) ) { $this->Data[$NodeID]["BorderR"] = $this->Data[$NodeID]["R"] + $Settings["Surrounding"]; $this->Data[$NodeID]["BorderG"] = $this->Data[$NodeID]["G"] + $Settings["Surrounding"]; $this->Data[$NodeID]["BorderB"] = $this->Data[$NodeID]["B"] + $Settings["Surrounding"]; } + } + } + } + else + { + if ( isset($Settings["R"]) ) { $this->Data[$Nodes]["R"] = $Settings["R"]; } + if ( isset($Settings["G"]) ) { $this->Data[$Nodes]["G"] = $Settings["G"]; } + if ( isset($Settings["B"]) ) { $this->Data[$Nodes]["B"] = $Settings["B"]; } + if ( isset($Settings["Alpha"]) ) { $this->Data[$Nodes]["Alpha"] = $Settings["Alpha"]; } + if ( isset($Settings["BorderR"]) ) { $this->Data[$Nodes]["BorderR"] = $Settings["BorderR"]; } + if ( isset($Settings["BorderG"]) ) { $this->Data[$Nodes]["BorderG"] = $Settings["BorderG"]; } + if ( isset($Settings["BorderB"]) ) { $this->Data[$Nodes]["BorderB"] = $Settings["BorderB"]; } + if ( isset($Settings["BorderAlpha"]) ) { $this->Data[$Nodes]["BorderAlpha"] = $Settings["BorderAlpha"]; } + if ( isset($Settings["Surrounding"]) ) { $this->Data[$Nodes]["BorderR"] = $this->Data[$NodeID]["R"] + $Settings["Surrounding"]; $this->Data[$NodeID]["BorderG"] = $this->Data[$NodeID]["G"] + $Settings["Surrounding"]; $this->Data[$NodeID]["BorderB"] = $this->Data[$NodeID]["B"] + $Settings["Surrounding"]; } + } + } + + /* Returns all the nodes details */ + function dumpNodes() + { return($this->Data); } + + /* Check if a connection exists and create it if required */ + function checkConnection($SourceID, $TargetID) + { + if ( isset($this->Data[$SourceID]["Connections"]) ) + { + foreach ($this->Data[$SourceID]["Connections"] as $Key => $ConnectionID) + { if ( $TargetID == $ConnectionID ) { return(TRUE); } } + } + $this->Data[$SourceID]["Connections"][] = $TargetID; + } + /* Get the median linked nodes position */ + function getMedianOffset($Key,$X,$Y) + { + $Cpt = 1; + if ( isset($this->Data[$Key]["Connections"]) ) + { + foreach($this->Data[$Key]["Connections"] as $ID => $NodeID) + { + if ( isset($this->Data[$NodeID]["X"]) && isset($this->Data[$NodeID]["Y"]) ) + { + $X = $X + $this->Data[$NodeID]["X"]; + $Y = $Y + $this->Data[$NodeID]["Y"]; + $Cpt++; + } + } + } + return(array("X"=>$X/$Cpt,"Y"=>$Y/$Cpt)); + } + + /* Return the ID of the attached partner with the biggest weight */ + function getBiggestPartner($Key) + { + if ( !isset($this->Data[$Key]["Connections"]) ) { return(""); } + + $MaxWeight = 0; $Result = ""; + foreach($this->Data[$Key]["Connections"] as $Key => $PeerID) + { + if ( $this->Data[$PeerID]["Weight"] > $MaxWeight ) + { $MaxWeight = $this->Data[$PeerID]["Weight"]; $Result = $PeerID; } + } + return($Result); + } + + /* Do the initial node positions computing pass */ + function firstPass($Algorithm) + { + $CenterX = ($this->X2 - $this->X1) / 2 + $this->X1; + $CenterY = ($this->Y2 - $this->Y1) / 2 + $this->Y1; + + /* Check connections reciprocity */ + foreach($this->Data as $Key => $Settings) + { + if ( isset($Settings["Connections"]) ) + { + foreach($Settings["Connections"] as $ID => $ConnectionID) + $this->checkConnection($ConnectionID,$Key); + } + } + + if ( $this->AutoComputeFreeZone ) { $this->autoFreeZone(); } + + /* Get the max number of connections */ + $MaxConnections = 0; + foreach($this->Data as $Key => $Settings) + { if ( isset($Settings["Connections"]) ) { if ( $MaxConnections < count($Settings["Connections"] ) ) { $MaxConnections = count($Settings["Connections"]); } } } + + if ( $Algorithm == ALGORITHM_WEIGHTED ) + { + foreach($this->Data as $Key => $Settings) + { + if ( $Settings["Type"] == NODE_TYPE_CENTRAL ) { $this->Data[$Key]["X"] = $CenterX; $this->Data[$Key]["Y"] = $CenterY; } + if ( $Settings["Type"] == NODE_TYPE_FREE ) + { + if ( isset($Settings["Connections"]) ) + { $Connections = count($Settings["Connections"]); } + else + { $Connections = 0; } + + $Ring = $MaxConnections - $Connections; + $Angle = rand(0,360); + + $this->Data[$Key]["X"] = cos(deg2rad($Angle)) * ($Ring*$this->RingSize) + $CenterX; + $this->Data[$Key]["Y"] = sin(deg2rad($Angle)) * ($Ring*$this->RingSize) + $CenterY; + } + } + } + elseif ( $Algorithm == ALGORITHM_CENTRAL ) + { + /* Put a weight on each nodes */ + foreach($this->Data as $Key => $Settings) + { + if ( isset($Settings["Connections"]) ) + $this->Data[$Key]["Weight"] = count($Settings["Connections"]); + else + $this->Data[$Key]["Weight"] = 0; + } + + $MaxConnections = $MaxConnections + 1; + for($i=$MaxConnections;$i>=0;$i--) + { + foreach($this->Data as $Key => $Settings) + { + if ( $Settings["Type"] == NODE_TYPE_CENTRAL ) { $this->Data[$Key]["X"] = $CenterX; $this->Data[$Key]["Y"] = $CenterY; } + if ( $Settings["Type"] == NODE_TYPE_FREE ) + { + if ( isset($Settings["Connections"]) ) + { $Connections = count($Settings["Connections"]); } + else + { $Connections = 0; } + + if ( $Connections == $i ) + { + $BiggestPartner = $this->getBiggestPartner($Key); + if ( $BiggestPartner != "" ) + { + $Ring = $this->Data[$BiggestPartner]["FreeZone"]; + $Weight = $this->Data[$BiggestPartner]["Weight"]; + $AngleDivision = 360 / $this->Data[$BiggestPartner]["Weight"]; + $Done = FALSE; $Tries = 0; + while (!$Done && $Tries <= $Weight*2) + { + $Tries++; + $Angle = floor(rand(0,$Weight)*$AngleDivision); + if ( !isset($this->Data[$BiggestPartner]["Angular"][$Angle]) || !isset($this->Data[$BiggestPartner]["Angular"]) ) + { + $this->Data[$BiggestPartner]["Angular"][$Angle] = $Angle; + $Done = TRUE; + } + } + if ( !$Done ) + { $Angle = rand(0,360); $this->Data[$BiggestPartner]["Angular"][$Angle] = $Angle; } + + $X = cos(deg2rad($Angle)) * ($Ring) + $this->Data[$BiggestPartner]["X"]; + $Y = sin(deg2rad($Angle)) * ($Ring) + $this->Data[$BiggestPartner]["Y"]; + + $this->Data[$Key]["X"] = $X; + $this->Data[$Key]["Y"] = $Y; + } + } + } + } + } + } + elseif ( $Algorithm == ALGORITHM_CIRCULAR ) + { + $MaxConnections = $MaxConnections + 1; + for($i=$MaxConnections;$i>=0;$i--) + { + foreach($this->Data as $Key => $Settings) + { + if ( $Settings["Type"] == NODE_TYPE_CENTRAL ) { $this->Data[$Key]["X"] = $CenterX; $this->Data[$Key]["Y"] = $CenterY; } + if ( $Settings["Type"] == NODE_TYPE_FREE ) + { + if ( isset($Settings["Connections"]) ) + { $Connections = count($Settings["Connections"]); } + else + { $Connections = 0; } + + if ( $Connections == $i ) + { + $Ring = $MaxConnections - $Connections; + $Angle = rand(0,360); + + $X = cos(deg2rad($Angle)) * ($Ring*$this->RingSize) + $CenterX; + $Y = sin(deg2rad($Angle)) * ($Ring*$this->RingSize) + $CenterY; + + $MedianOffset = $this->getMedianOffset($Key,$X,$Y); + + $this->Data[$Key]["X"] = $MedianOffset["X"]; + $this->Data[$Key]["Y"] = $MedianOffset["Y"]; + } + } + } + } + } + elseif ( $Algorithm == ALGORITHM_RANDOM ) + { + foreach($this->Data as $Key => $Settings) + { + if ( $Settings["Type"] == NODE_TYPE_FREE ) + { + $this->Data[$Key]["X"] = $CenterX + rand(-20,20); + $this->Data[$Key]["Y"] = $CenterY + rand(-20,20); + } + if ( $Settings["Type"] == NODE_TYPE_CENTRAL ) { $this->Data[$Key]["X"] = $CenterX; $this->Data[$Key]["Y"] = $CenterY; } + } + } + } + + /* Compute one pass */ + function doPass() + { + /* Compute vectors */ + foreach($this->Data as $Key => $Settings) + { + if ( $Settings["Type"] != NODE_TYPE_CENTRAL ) + { + unset($this->Data[$Key]["Vectors"]); + + $X1 = $Settings["X"]; + $Y1 = $Settings["Y"]; + + /* Repulsion vectors */ + foreach($this->Data as $Key2 => $Settings2) + { + if ( $Key != $Key2 ) + { + $X2 = $this->Data[$Key2]["X"]; + $Y2 = $this->Data[$Key2]["Y"]; + $FreeZone = $this->Data[$Key2]["FreeZone"]; + + $Distance = $this->getDistance($X1,$Y1,$X2,$Y2); + $Angle = $this->getAngle($X1,$Y1,$X2,$Y2) + 180; + + /* Nodes too close, repulsion occurs */ + if ( $Distance < $FreeZone ) + { + $Force = log(pow(2,$FreeZone-$Distance)); + if ( $Force > 1 ) + { $this->Data[$Key]["Vectors"][] = array("Type"=>"R","Angle"=>$Angle % 360,"Force"=>$Force); } + } + } + } + + /* Attraction vectors */ + if ( isset($Settings["Connections"]) ) + { + foreach($Settings["Connections"] as $ID => $NodeID) + { + if ( isset($this->Data[$NodeID]) ) + { + $X2 = $this->Data[$NodeID]["X"]; + $Y2 = $this->Data[$NodeID]["Y"]; + $FreeZone = $this->Data[$Key2]["FreeZone"]; + + $Distance = $this->getDistance($X1,$Y1,$X2,$Y2); + $Angle = $this->getAngle($X1,$Y1,$X2,$Y2); + + if ( $Distance > $FreeZone ) + $Force = log(($Distance-$FreeZone)+1); + else + { $Force = log(($FreeZone-$Distance)+1); ($Angle = $Angle + 180); } + + if ( $Force > 1 ) + $this->Data[$Key]["Vectors"][] = array("Type"=>"A","Angle"=>$Angle % 360,"Force"=>$Force); + } + } + } + } + } + + /* Move the nodes accoding to the vectors */ + foreach($this->Data as $Key => $Settings) + { + $X = $Settings["X"]; + $Y = $Settings["Y"]; + + if ( isset($Settings["Vectors"]) && $Settings["Type"] != NODE_TYPE_CENTRAL ) + { + foreach($Settings["Vectors"] as $ID => $Vector) + { + $Type = $Vector["Type"]; + $Force = $Vector["Force"]; + $Angle = $Vector["Angle"]; + $Factor = $Type == "A" ? $this->MagneticForceA : $this->MagneticForceR; + + $X = cos(deg2rad($Angle)) * $Force * $Factor + $X; + $Y = sin(deg2rad($Angle)) * $Force * $Factor + $Y; + } + } + + $this->Data[$Key]["X"] = $X; + $this->Data[$Key]["Y"] = $Y; + } + } + + function lastPass() + { + /* Put everything inside the graph area */ + foreach($this->Data as $Key => $Settings) + { + $X = $Settings["X"]; + $Y = $Settings["Y"]; + + if ( $X < $this->X1 ) { $X = $this->X1; } + if ( $X > $this->X2 ) { $X = $this->X2; } + if ( $Y < $this->Y1 ) { $Y = $this->Y1; } + if ( $Y > $this->Y2 ) { $Y = $this->Y2; } + + $this->Data[$Key]["X"] = $X; + $this->Data[$Key]["Y"] = $Y; + } + + /* Dump all links */ + $Links = ""; + foreach($this->Data as $Key => $Settings) + { + $X1 = $Settings["X"]; + $Y1 = $Settings["Y"]; + + if ( isset($Settings["Connections"]) ) + { + foreach ($Settings["Connections"] as $ID => $NodeID) + { + if ( isset($this->Data[$NodeID]) ) + { + $X2 = $this->Data[$NodeID]["X"]; + $Y2 = $this->Data[$NodeID]["Y"]; + + $Links[] = array("X1"=>$X1,"Y1"=>$Y1,"X2"=>$X2,"Y2"=>$Y2,"Source"=>$Settings["Name"],"Destination"=>$this->Data[$NodeID]["Name"]); + } + } + } + } + + /* Check collisions */ + $Conflicts = 0; + foreach($this->Data as $Key => $Settings) + { + $X1 = $Settings["X"]; + $Y1 = $Settings["Y"]; + + if ( isset($Settings["Connections"]) ) + { + foreach ($Settings["Connections"] as $ID => $NodeID) + { + if ( isset($this->Data[$NodeID]) ) + { + $X2 = $this->Data[$NodeID]["X"]; + $Y2 = $this->Data[$NodeID]["Y"]; + + foreach($Links as $IDLinks => $Link) + { + $X3 = $Link["X1"]; $Y3 = $Link["Y1"]; $X4 = $Link["X2"]; $Y4 = $Link["Y2"]; + + if ( !($X1 == $X3 && $X2 == $X4 && $Y1 == $Y3 && $Y2 == $Y4 ) ) + { + if ( $this->intersect($X1,$Y1,$X2,$Y2,$X3,$Y3,$X4,$Y4) ) + { + if ( $Link["Source"] != $Settings["Name"] && $Link["Source"] != $this->Data[$NodeID]["Name"] && $Link["Destination"] != $Settings["Name"] && $Link["Destination"] != $this->Data[$NodeID]["Name"] ) + { $Conflicts++; } + } + } + } + } + } + } + } + return($Conflicts/2); + } + + /* Center the graph */ + function center() + { + /* Determine the real center */ + $TargetCenterX = ($this->X2 - $this->X1) / 2 + $this->X1; + $TargetCenterY = ($this->Y2 - $this->Y1) / 2 + $this->Y1; + + /* Get current boundaries */ + $XMin = $this->X2; $XMax = $this->X1; + $YMin = $this->Y2; $YMax = $this->Y1; + foreach($this->Data as $Key => $Settings) + { + $X = $Settings["X"]; + $Y = $Settings["Y"]; + + if ( $X < $XMin) { $XMin = $X; } + if ( $X > $XMax) { $XMax = $X; } + if ( $Y < $YMin) { $YMin = $Y; } + if ( $Y > $YMax) { $YMax = $Y; } + } + $CurrentCenterX = ($XMax - $XMin) / 2 + $XMin; + $CurrentCenterY = ($YMax - $YMin) / 2 + $YMin; + + /* Compute the offset to apply */ + $XOffset = $TargetCenterX - $CurrentCenterX; + $YOffset = $TargetCenterY - $CurrentCenterY; + + /* Correct the points position */ + foreach($this->Data as $Key => $Settings) + { + $this->Data[$Key]["X"] = $Settings["X"] + $XOffset; + $this->Data[$Key]["Y"] = $Settings["Y"] + $YOffset; + } + } + + /* Create the encoded string */ + function drawSpring($Object,$Settings="") + { + $this->pChartObject = $Object; + + $Pass = isset($Settings["Pass"]) ? $Settings["Pass"] : 50; + $Retries = isset($Settings["Retry"]) ? $Settings["Retry"] : 10; + $this->MagneticForceA = isset($Settings["MagneticForceA"]) ? $Settings["MagneticForceA"] : 1.5; + $this->MagneticForceR = isset($Settings["MagneticForceR"]) ? $Settings["MagneticForceR"] : 2; + $this->RingSize = isset($Settings["RingSize"]) ? $Settings["RingSize"] : 40; + $DrawVectors = isset($Settings["DrawVectors"]) ? $Settings["DrawVectors"] : FALSE; + $DrawQuietZone = isset($Settings["DrawQuietZone"]) ? $Settings["DrawQuietZone"] : FALSE; + $CenterGraph = isset($Settings["CenterGraph"]) ? $Settings["CenterGraph"] : TRUE; + $TextPadding = isset($Settings["TextPadding"]) ? $Settings["TextPadding"] : 4; + $Algorithm = isset($Settings["Algorithm"]) ? $Settings["Algorithm"] : ALGORITHM_WEIGHTED; + + $FontSize = $Object->FontSize; + $this->X1 = $Object->GraphAreaX1; + $this->Y1 = $Object->GraphAreaY1; + $this->X2 = $Object->GraphAreaX2; + $this->Y2 = $Object->GraphAreaY2; + + $Conflicts = 1; $Jobs = 0; $this->History["MinimumConflicts"] = -1; + while ($Conflicts != 0 && $Jobs < $Retries ) + { + $Jobs++; + + /* Compute the initial settings */ + $this->firstPass($Algorithm); + + /* Apply the vectors */ + if ( $Pass > 0 ) + { + for ($i=0; $i<=$Pass; $i++) { $this->doPass(); } + } + + $Conflicts = $this->lastPass(); + if ( $this->History["MinimumConflicts"] == -1 || $Conflicts < $this->History["MinimumConflicts"] ) + { $this->History["MinimumConflicts"] = $Conflicts; $this->History["Result"] = $this->Data; } + } + + $Conflicts = $this->History["MinimumConflicts"]; + $this->Data = $this->History["Result"]; + + if ( $CenterGraph ) { $this->center(); } + + /* Draw the connections */ + $Drawn = ""; + foreach($this->Data as $Key => $Settings) + { + $X = $Settings["X"]; + $Y = $Settings["Y"]; + + if ( isset($Settings["Connections"]) ) + { + foreach ($Settings["Connections"] as $ID => $NodeID) + { + if ( !isset($Drawn[$Key]) ) { $Drawn[$Key] = ""; } + if ( !isset($Drawn[$NodeID]) ) { $Drawn[$NodeID] = ""; } + + if ( isset($this->Data[$NodeID]) && !isset($Drawn[$Key][$NodeID]) && !isset($Drawn[$NodeID][$Key]) ) + { + $Color = array("R"=>$this->Default["LinkR"],"G"=>$this->Default["LinkG"],"B"=>$this->Default["LinkB"],"Alpha"=>$this->Default["Alpha"]); + + if ( $this->Links != "" ) + { + if ( isset($this->Links[$Key][$NodeID]["R"]) ) + { $Color = array("R"=>$this->Links[$Key][$NodeID]["R"],"G"=>$this->Links[$Key][$NodeID]["G"],"B"=>$this->Links[$Key][$NodeID]["B"],"Alpha"=>$this->Links[$Key][$NodeID]["Alpha"]); } + + if ( isset($this->Links[$Key][$NodeID]["Ticks"]) ) + { $Color["Ticks"] = $this->Links[$Key][$NodeID]["Ticks"]; } + } + + $X2 = $this->Data[$NodeID]["X"]; + $Y2 = $this->Data[$NodeID]["Y"]; + $this->pChartObject->drawLine($X,$Y,$X2,$Y2,$Color); + $Drawn[$Key][$NodeID] = TRUE; + + if ( isset($this->Links) && $this->Links != "" ) + { + if ( isset($this->Links[$Key][$NodeID]["Name"]) || isset($this->Links[$NodeID][$Key]["Name"]) ) + { + $Name = isset($this->Links[$Key][$NodeID]["Name"]) ? $this->Links[$Key][$NodeID]["Name"] : $this->Links[$NodeID][$Key]["Name"]; + $TxtX = ($X2 - $X)/2 + $X; + $TxtY = ($Y2 - $Y)/2 + $Y; + + if ( $X <= $X2 ) + $Angle = (360-$this->getAngle($X,$Y,$X2,$Y2)) % 360; + else + $Angle = (360-$this->getAngle($X2,$Y2,$X,$Y)) % 360; + + $Settings = $Color; + $Settings["Angle"] = $Angle; + $Settings["Align"] = TEXT_ALIGN_BOTTOMMIDDLE; + $this->pChartObject->drawText($TxtX,$TxtY,$Name,$Settings); + } + } + } + } + } + } + + /* Draw the quiet zones */ + if ( $DrawQuietZone ) + { + foreach($this->Data as $Key => $Settings) + { + $X = $Settings["X"]; + $Y = $Settings["Y"]; + $FreeZone = $Settings["FreeZone"]; + + $this->pChartObject->drawFilledCircle($X,$Y,$FreeZone,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>2)); + } + } + + + /* Draw the nodes */ + foreach($this->Data as $Key => $Settings) + { + $X = $Settings["X"]; + $Y = $Settings["Y"]; + $Name = $Settings["Name"]; + $FreeZone = $Settings["FreeZone"]; + $Shape = $Settings["Shape"]; + $Size = $Settings["Size"]; + + $Color = array("R"=>$Settings["R"],"G"=>$Settings["G"],"B"=>$Settings["B"],"Alpha"=>$Settings["Alpha"],"BorderR"=>$Settings["BorderR"],"BorderG"=>$Settings["BorderG"],"BorderB"=>$Settings["BorderB"],"BorderApha"=>$Settings["BorderAlpha"]); + + if ( $Shape == NODE_SHAPE_CIRCLE ) + { + $this->pChartObject->drawFilledCircle($X,$Y,$Size,$Color); + } + elseif ( $Shape == NODE_SHAPE_TRIANGLE ) + { + $Points = ""; + $Points[] = cos(deg2rad(270)) * $Size + $X; $Points[] = sin(deg2rad(270)) * $Size + $Y; + $Points[] = cos(deg2rad(45)) * $Size + $X; $Points[] = sin(deg2rad(45)) * $Size + $Y; + $Points[] = cos(deg2rad(135)) * $Size + $X; $Points[] = sin(deg2rad(135)) * $Size + $Y; + $this->pChartObject->drawPolygon($Points,$Color); + } + elseif ( $Shape == NODE_SHAPE_SQUARE ) + { + $Offset = $Size/2; $Size = $Size / 2; + $this->pChartObject->drawFilledRectangle($X-$Offset,$Y-$Offset,$X+$Offset,$Y+$Offset,$Color); + } + + if ( $Name != "" ) + { + $LabelOptions = array("R"=>$this->Labels["R"],"G"=>$this->Labels["G"],"B"=>$this->Labels["B"],"Alpha"=>$this->Labels["Alpha"]); + + if ( $this->Labels["Type"] == LABEL_LIGHT ) + { + $LabelOptions["Align"] = TEXT_ALIGN_BOTTOMLEFT; + $this->pChartObject->drawText($X,$Y,$Name,$LabelOptions); + } + elseif ( $this->Labels["Type"] == LABEL_CLASSIC ) + { + $LabelOptions["Align"] = TEXT_ALIGN_TOPMIDDLE; + $LabelOptions["DrawBox"] = TRUE; + $LabelOptions["BoxAlpha"] = 50; + $LabelOptions["BorderOffset"] = 4; + $LabelOptions["RoundedRadius"] = 3; + $LabelOptions["BoxRounded"] = TRUE; + $LabelOptions["NoShadow"] = TRUE; + + $this->pChartObject->drawText($X,$Y+$Size+$TextPadding,$Name,$LabelOptions); + } + } + } + + /* Draw the vectors */ + if ( $DrawVectors ) + { + foreach($this->Data as $Key => $Settings) + { + $X1 = $Settings["X"]; + $Y1 = $Settings["Y"]; + + if ( isset($Settings["Vectors"]) && $Settings["Type"] != NODE_TYPE_CENTRAL ) + { + foreach($Settings["Vectors"] as $ID => $Vector) + { + $Type = $Vector["Type"]; + $Force = $Vector["Force"]; + $Angle = $Vector["Angle"]; + $Factor = $Type == "A" ? $this->MagneticForceA : $this->MagneticForceR; + $Color = $Type == "A" ? array("FillR"=>255,"FillG"=>0,"FillB"=>0) : array("FillR"=>0,"FillG"=>255,"FillB"=>0); + + $X2 = cos(deg2rad($Angle)) * $Force * $Factor + $X1; + $Y2 = sin(deg2rad($Angle)) * $Force * $Factor + $Y1; + + $this->pChartObject->drawArrow($X1,$Y1,$X2,$Y2,$Color); + } + } + } + } + + return(array("Pass"=>$Jobs,"Conflicts"=>$Conflicts)); + } + + /* Return the distance between two points */ + function getDistance($X1,$Y1,$X2,$Y2) + { return (sqrt(($X2-$X1)*($X2-$X1)+($Y2-$Y1)*($Y2-$Y1))); } + + /* Return the angle made by a line and the X axis */ + function getAngle($X1,$Y1,$X2,$Y2) + { + $Opposite = $Y2 - $Y1; $Adjacent = $X2 - $X1;$Angle = rad2deg(atan2($Opposite,$Adjacent)); + if ($Angle > 0) { return($Angle); } else { return(360-abs($Angle)); } + } + + function intersect($X1,$Y1,$X2,$Y2,$X3,$Y3,$X4,$Y4) + { + $A = (($X3 * $Y4 - $X4 * $Y3) * ($X1 - $X2) - ($X1 * $Y2 - $X2 * $Y1) * ($X3 - $X4)); + $B = (($Y1 - $Y2) * ($X3 - $X4) - ($Y3 - $Y4) * ($X1 - $X2)); + + if ( $B == 0 ) { return(FALSE); } + $Xi = $A / $B; + + $C = ($X1 - $X2); + if ( $C == 0 ) { return(FALSE); } + $Yi = $Xi * (($Y1 - $Y2)/$C) + (($X1 * $Y2 - $X2 * $Y1)/$C); + + if ( $Xi >= min($X1,$X2) && $Xi >= min($X3,$X4) && $Xi <= max($X1,$X2) && $Xi <= max($X3,$X4)) + { + if ( $Yi >= min($Y1,$Y2) && $Yi >= min($Y3,$Y4) && $Yi <= max($Y1,$Y2) && $Yi <= max($Y3,$Y4)) + { return(TRUE); } + } + + return(FALSE); + } + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/class/pStock.class.php b/trunk/includes/pChart/class/pStock.class.php new file mode 100644 index 0000000..9b59488 --- /dev/null +++ b/trunk/includes/pChart/class/pStock.class.php @@ -0,0 +1,216 @@ +pChartObject = $pChartObject; + $this->pDataObject = $pDataObject; + } + + /* Draw a stock chart */ + function drawStockChart($Format="") + { + $SerieOpen = isset($Format["SerieOpen"]) ? $Format["SerieOpen"] : "Open"; + $SerieClose = isset($Format["SerieClose"]) ? $Format["SerieClose"] : "Close"; + $SerieMin = isset($Format["SerieMin"]) ? $Format["SerieMin"] : "Min"; + $SerieMax = isset($Format["SerieMax"]) ? $Format["SerieMax"] : "Max"; + $SerieMedian = isset($Format["SerieMedian"]) ? $Format["SerieMedian"] : NULL; + $LineWidth = isset($Format["LineWidth"]) ? $Format["LineWidth"] : 1; + $LineR = isset($Format["LineR"]) ? $Format["LineR"] : 0; + $LineG = isset($Format["LineG"]) ? $Format["LineG"] : 0; + $LineB = isset($Format["LineB"]) ? $Format["LineB"] : 0; + $LineAlpha = isset($Format["LineAlpha"]) ? $Format["LineAlpha"] : 100; + $ExtremityWidth = isset($Format["ExtremityWidth"]) ? $Format["ExtremityWidth"] : 1; + $ExtremityLength = isset($Format["ExtremityLength"]) ? $Format["ExtremityLength"] : 3; + $ExtremityR = isset($Format["ExtremityR"]) ? $Format["ExtremityR"] : 0; + $ExtremityG = isset($Format["ExtremityG"]) ? $Format["ExtremityG"] : 0; + $ExtremityB = isset($Format["ExtremityB"]) ? $Format["ExtremityB"] : 0; + $ExtremityAlpha = isset($Format["ExtremityAlpha"]) ? $Format["ExtremityAlpha"] : 100; + $BoxWidth = isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 8; + $BoxUpR = isset($Format["BoxUpR"]) ? $Format["BoxUpR"] : 188; + $BoxUpG = isset($Format["BoxUpG"]) ? $Format["BoxUpG"] : 224; + $BoxUpB = isset($Format["BoxUpB"]) ? $Format["BoxUpB"] : 46; + $BoxUpAlpha = isset($Format["BoxUpAlpha"]) ? $Format["BoxUpAlpha"] : 100; + $BoxUpSurrounding = isset($Format["BoxUpSurrounding"]) ? $Format["BoxUpSurrounding"] : NULL; + $BoxUpBorderR = isset($Format["BoxUpBorderR"]) ? $Format["BoxUpBorderR"] : $BoxUpR-20; + $BoxUpBorderG = isset($Format["BoxUpBorderG"]) ? $Format["BoxUpBorderG"] : $BoxUpG-20; + $BoxUpBorderB = isset($Format["BoxUpBorderB"]) ? $Format["BoxUpBorderB"] : $BoxUpB-20; + $BoxUpBorderAlpha = isset($Format["BoxUpBorderAlpha"]) ? $Format["BoxUpBorderAlpha"] : 100; + $BoxDownR = isset($Format["BoxDownR"]) ? $Format["BoxDownR"] : 224; + $BoxDownG = isset($Format["BoxDownG"]) ? $Format["BoxDownG"] : 100; + $BoxDownB = isset($Format["BoxDownB"]) ? $Format["BoxDownB"] : 46; + $BoxDownAlpha = isset($Format["BoxDownAlpha"]) ? $Format["BoxDownAlpha"] : 100; + $BoxDownSurrounding= isset($Format["BoxDownSurrounding"]) ? $Format["BoxDownSurrounding"] : NULL; + $BoxDownBorderR = isset($Format["BoxDownBorderR"]) ? $Format["BoxDownBorderR"] : $BoxDownR-20; + $BoxDownBorderG = isset($Format["BoxDownBorderG"]) ? $Format["BoxDownBorderG"] : $BoxDownG-20; + $BoxDownBorderB = isset($Format["BoxDownBorderB"]) ? $Format["BoxDownBorderB"] : $BoxDownB-20; + $BoxDownBorderAlpha= isset($Format["BoxDownBorderAlpha"]) ? $Format["BoxDownBorderAlpha"] : 100; + $ShadowOnBoxesOnly = isset($Format["ShadowOnBoxesOnly"]) ? $Format["ShadowOnBoxesOnly"] : TRUE; + $MedianR = isset($Format["MedianR"]) ? $Format["MedianR"] : 255; + $MedianG = isset($Format["MedianG"]) ? $Format["MedianG"] : 0; + $MedianB = isset($Format["MedianB"]) ? $Format["MedianB"] : 0; + $MedianAlpha = isset($Format["MedianAlpha"]) ? $Format["MedianAlpha"] : 100; + $RecordImageMap = isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE; + $ImageMapTitle = isset($Format["ImageMapTitle"]) ? $Format["ImageMapTitle"] : "Stock Chart"; + + + /* Data Processing */ + $Data = $this->pDataObject->getData(); + $Palette = $this->pDataObject->getPalette(); + + if ( $BoxUpSurrounding != NULL ) { $BoxUpBorderR = $BoxUpR + $BoxUpSurrounding; $BoxUpBorderG = $BoxUpG + $BoxUpSurrounding; $BoxUpBorderB = $BoxUpB + $BoxUpSurrounding; } + if ( $BoxDownSurrounding != NULL ) { $BoxDownBorderR = $BoxDownR + $BoxDownSurrounding; $BoxDownBorderG = $BoxDownG + $BoxDownSurrounding; $BoxDownBorderB = $BoxDownB + $BoxDownSurrounding; } + + if ( $LineWidth != 1 ) { $LineOffset = $LineWidth / 2; } + $BoxOffset = $BoxWidth / 2; + + $Data = $this->pChartObject->DataSet->getData(); + list($XMargin,$XDivs) = $this->pChartObject->scaleGetXSettings(); + + if ( !isset($Data["Series"][$SerieOpen]) || !isset($Data["Series"][$SerieClose]) || !isset($Data["Series"][$SerieMin]) || !isset($Data["Series"][$SerieMax]) ) + return(STOCK_MISSING_SERIE); + + $Plots = ""; + foreach($Data["Series"][$SerieOpen]["Data"] as $Key => $Value) + { + $Point = ""; + if ( isset($Data["Series"][$SerieClose]["Data"][$Key]) || isset($Data["Series"][$SerieMin]["Data"][$Key]) || isset($Data["Series"][$SerieMax]["Data"][$Key]) ) + $Point = array($Value,$Data["Series"][$SerieClose]["Data"][$Key],$Data["Series"][$SerieMin]["Data"][$Key],$Data["Series"][$SerieMax]["Data"][$Key]); + if ( $SerieMedian != NULL && isset($Data["Series"][$SerieMedian]["Data"][$Key]) ) + $Point[] = $Data["Series"][$SerieMedian]["Data"][$Key]; + + $Plots[] = $Point; + } + + $AxisID = $Data["Series"][$SerieOpen]["Axis"]; + $Mode = $Data["Axis"][$AxisID]["Display"]; + $Format = $Data["Axis"][$AxisID]["Format"]; + $Unit = $Data["Axis"][$AxisID]["Unit"]; + + $YZero = $this->pChartObject->scaleComputeY(0,array("AxisID"=>$AxisID)); + $XStep = ($this->pChartObject->GraphAreaX2-$this->pChartObject->GraphAreaX1-$XMargin*2)/$XDivs; + + $X = $this->pChartObject->GraphAreaX1 + $XMargin; + $Y = $this->pChartObject->GraphAreaY1 + $XMargin; + + $LineSettings = array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha); + $ExtremitySettings = array("R"=>$ExtremityR,"G"=>$ExtremityG,"B"=>$ExtremityB,"Alpha"=>$ExtremityAlpha); + $BoxUpSettings = array("R"=>$BoxUpR,"G"=>$BoxUpG,"B"=>$BoxUpB,"Alpha"=>$BoxUpAlpha,"BorderR"=>$BoxUpBorderR,"BorderG"=>$BoxUpBorderG,"BorderB"=>$BoxUpBorderB,"BorderAlpha"=>$BoxUpBorderAlpha); + $BoxDownSettings = array("R"=>$BoxDownR,"G"=>$BoxDownG,"B"=>$BoxDownB,"Alpha"=>$BoxDownAlpha,"BorderR"=>$BoxDownBorderR,"BorderG"=>$BoxDownBorderG,"BorderB"=>$BoxDownBorderB,"BorderAlpha"=>$BoxDownBorderAlpha); + $MedianSettings = array("R"=>$MedianR,"G"=>$MedianG,"B"=>$MedianB,"Alpha"=>$MedianAlpha); + + foreach($Plots as $Key =>$Points) + { + $PosArray = $this->pChartObject->scaleComputeY($Points,array("AxisID"=>$AxisID)); + + $Values = "Open :".$Data["Series"][$SerieOpen]["Data"][$Key]."
Close : ".$Data["Series"][$SerieClose]["Data"][$Key]."
Min : ".$Data["Series"][$SerieMin]["Data"][$Key]."
Max : ".$Data["Series"][$SerieMax]["Data"][$Key]."
"; + if ( $SerieMedian != NULL ) { $Values = $Values."Median : ".$Data["Series"][$SerieMedian]["Data"][$Key]."
"; } + if ( $PosArray[0] > $PosArray[1] ) { $ImageMapColor = $this->pChartObject->toHTMLColor($BoxUpR,$BoxUpG,$BoxUpB); } else { $ImageMapColor = $this->pChartObject->toHTMLColor($BoxDownR,$BoxDownG,$BoxDownB); } + + if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT ) + { + if ( $YZero > $this->pChartObject->GraphAreaY2-1 ) { $YZero = $this->pChartObject->GraphAreaY2-1; } + if ( $YZero < $this->pChartObject->GraphAreaY1+1 ) { $YZero = $this->pChartObject->GraphAreaY1+1; } + + if ( $XDivs == 0 ) { $XStep = 0; } else { $XStep = ($this->pChartObject->GraphAreaX2-$this->pChartObject->GraphAreaX1-$XMargin*2)/$XDivs; } + + if ( $ShadowOnBoxesOnly ) { $RestoreShadow = $this->pChartObject->Shadow; $this->pChartObject->Shadow = FALSE; } + + if ( $LineWidth == 1 ) + $this->pChartObject->drawLine($X,$PosArray[2],$X,$PosArray[3],$LineSettings); + else + $this->pChartObject->drawFilledRectangle($X-$LineOffset,$PosArray[2],$X+$LineOffset,$PosArray[3],$LineSettings); + + if ( $ExtremityWidth == 1 ) + { + $this->pChartObject->drawLine($X-$ExtremityLength,$PosArray[2],$X+$ExtremityLength,$PosArray[2],$ExtremitySettings); + $this->pChartObject->drawLine($X-$ExtremityLength,$PosArray[3],$X+$ExtremityLength,$PosArray[3],$ExtremitySettings); + + if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("RECT",floor($X-$ExtremityLength).",".floor($PosArray[2]).",".floor($X+$ExtremityLength).",".floor($PosArray[3]),$ImageMapColor,$ImageMapTitle,$Values); } + } + else + { + $this->pChartObject->drawFilledRectangle($X-$ExtremityLength,$PosArray[2],$X+$ExtremityLength,$PosArray[2]-$ExtremityWidth,$ExtremitySettings); + $this->pChartObject->drawFilledRectangle($X-$ExtremityLength,$PosArray[3],$X+$ExtremityLength,$PosArray[3]+$ExtremityWidth,$ExtremitySettings); + + if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("RECT",floor($X-$ExtremityLength).",".floor($PosArray[2]-$ExtremityWidth).",".floor($X+$ExtremityLength).",".floor($PosArray[3]+$ExtremityWidth),$ImageMapColor,$ImageMapTitle,$Values); } + } + + if ( $ShadowOnBoxesOnly ) { $this->pChartObject->Shadow = $RestoreShadow; } + + if ( $PosArray[0] > $PosArray[1] ) + $this->pChartObject->drawFilledRectangle($X-$BoxOffset,$PosArray[0],$X+$BoxOffset,$PosArray[1],$BoxUpSettings); + else + $this->pChartObject->drawFilledRectangle($X-$BoxOffset,$PosArray[0],$X+$BoxOffset,$PosArray[1],$BoxDownSettings); + + if ( isset($PosArray[4]) ) + $this->pChartObject->drawLine($X-$ExtremityLength,$PosArray[4],$X+$ExtremityLength,$PosArray[4],$MedianSettings); + + $X = $X + $XStep; + } + elseif ( $Data["Orientation"] == SCALE_POS_TOPBOTTOM ) + { + if ( $YZero > $this->pChartObject->GraphAreaX2-1 ) { $YZero = $this->pChartObject->GraphAreaX2-1; } + if ( $YZero < $this->pChartObject->GraphAreaX1+1 ) { $YZero = $this->pChartObject->GraphAreaX1+1; } + + if ( $XDivs == 0 ) { $XStep = 0; } else { $XStep = ($this->pChartObject->GraphAreaY2-$this->pChartObject->GraphAreaY1-$XMargin*2)/$XDivs; } + + if ( $LineWidth == 1 ) + $this->pChartObject->drawLine($PosArray[2],$Y,$PosArray[3],$Y,$LineSettings); + else + $this->pChartObject->drawFilledRectangle($PosArray[2],$Y-$LineOffset,$PosArray[3],$Y+$LineOffset,$LineSettings); + + if ( $ShadowOnBoxesOnly ) { $RestoreShadow = $this->pChartObject->Shadow; $this->pChartObject->Shadow = FALSE; } + + if ( $ExtremityWidth == 1 ) + { + $this->pChartObject->drawLine($PosArray[2],$Y-$ExtremityLength,$PosArray[2],$Y+$ExtremityLength,$ExtremitySettings); + $this->pChartObject->drawLine($PosArray[3],$Y-$ExtremityLength,$PosArray[3],$Y+$ExtremityLength,$ExtremitySettings); + + if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("RECT",floor($PosArray[2]).",".floor($Y-$ExtremityLength).",".floor($PosArray[3]).",".floor($Y+$ExtremityLength),$ImageMapColor,$ImageMapTitle,$Values); } + } + else + { + $this->pChartObject->drawFilledRectangle($PosArray[2],$Y-$ExtremityLength,$PosArray[2]-$ExtremityWidth,$Y+$ExtremityLength,$ExtremitySettings); + $this->pChartObject->drawFilledRectangle($PosArray[3],$Y-$ExtremityLength,$PosArray[3]+$ExtremityWidth,$Y+$ExtremityLength,$ExtremitySettings); + + if ( $RecordImageMap ) { $this->pChartObject->addToImageMap("RECT",floor($PosArray[2]-$ExtremityWidth).",".floor($Y-$ExtremityLength).",".floor($PosArray[3]+$ExtremityWidth).",".floor($Y+$ExtremityLength),$ImageMapColor,$ImageMapTitle,$Values); } + } + + if ( $ShadowOnBoxesOnly ) { $this->pChartObject->Shadow = $RestoreShadow; } + + if ( $PosArray[0] < $PosArray[1] ) + $this->pChartObject->drawFilledRectangle($PosArray[0],$Y-$BoxOffset,$PosArray[1],$Y+$BoxOffset,$BoxUpSettings); + else + $this->pChartObject->drawFilledRectangle($PosArray[0],$Y-$BoxOffset,$PosArray[1],$Y+$BoxOffset,$BoxDownSettings); + + if ( isset($PosArray[4]) ) + $this->pChartObject->drawLine($PosArray[4],$Y-$ExtremityLength,$PosArray[4],$Y+$ExtremityLength,$MedianSettings); + + $Y = $Y + $XStep; + } + } + } + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/class/pSurface.class.php b/trunk/includes/pChart/class/pSurface.class.php new file mode 100644 index 0000000..0aeb9b9 --- /dev/null +++ b/trunk/includes/pChart/class/pSurface.class.php @@ -0,0 +1,315 @@ +pChartObject = $pChartObject; + $this->GridSize = 10; + $this->Points = ""; + } + + /* Define the grid size and initialise the 2D matrix */ + function setGrid($XSize=10,$YSize=10) + { + for($X=0; $X<=$XSize; $X++) { for($Y=0; $Y<=$YSize; $Y++) { $this->Points[$X][$Y]=UNKNOWN; } } + + $this->GridSizeX = $XSize; + $this->GridSizeY = $YSize; + } + + /* Add a point on the grid */ + function addPoint($X,$Y,$Value,$Force=TRUE) + { + if ( $X < 0 || $X >$this->GridSizeX ) { return(0); } + if ( $Y < 0 || $Y >$this->GridSizeY ) { return(0); } + + if ( $this->Points[$X][$Y] == UNKNOWN || $Force ) + $this->Points[$X][$Y] = $Value; + elseif ( $this->Points[$X][$Y] == UNKNOWN ) + $this->Points[$X][$Y] = $Value; + else + $this->Points[$X][$Y] = ($this->Points[$X][$Y] + $Value)/2; + } + + /* Write the X labels */ + function writeXLabels($Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : $this->pChartObject->FontColorR; + $G = isset($Format["G"]) ? $Format["G"] : $this->pChartObject->FontColorG; + $B = isset($Format["B"]) ? $Format["B"] : $this->pChartObject->FontColorB; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : $this->pChartObject->FontColorA; + $Angle = isset($Format["Angle"]) ? $Format["Angle"] : 0; + $Padding = isset($Format["Padding"]) ? $Format["Padding"] : 5; + $Position = isset($Format["Position"]) ? $Format["Position"] : LABEL_POSITION_TOP; + $Labels = isset($Format["Labels"]) ? $Format["Labels"] : NULL; + $CountOffset = isset($Format["CountOffset"]) ? $Format["CountOffset"] : 0; + + if ( $Labels != NULL && !is_array($Labels) ) { $Label = $Labels; $Labels = ""; $Labels[] = $Label; } + + $X0 = $this->pChartObject->GraphAreaX1; + $XSize = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1) / ($this->GridSizeX+1); + + $Settings = array("Angle"=>$Angle,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + if ( $Position == LABEL_POSITION_TOP ) + { + $YPos = $this->pChartObject->GraphAreaY1 - $Padding; + if ($Angle == 0 ) { $Settings["Align"] = TEXT_ALIGN_BOTTOMMIDDLE; } + if ($Angle != 0 ) { $Settings["Align"] = TEXT_ALIGN_MIDDLELEFT; } + } + elseif ( $Position == LABEL_POSITION_BOTTOM ) + { + $YPos = $this->pChartObject->GraphAreaY2 + $Padding; + if ($Angle == 0 ) { $Settings["Align"] = TEXT_ALIGN_TOPMIDDLE; } + if ($Angle != 0 ) { $Settings["Align"] = TEXT_ALIGN_MIDDLERIGHT; } + } + else + return(-1); + + for($X=0;$X<=$this->GridSizeX;$X++) + { + $XPos = floor($X0+$X*$XSize + $XSize/2); + + if( $Labels == NULL || !isset($Labels[$X]) ) + $Value = $X+$CountOffset; + else + $Value = $Labels[$X]; + + $this->pChartObject->drawText($XPos,$YPos,$Value,$Settings); + } + } + + /* Write the Y labels */ + function writeYLabels($Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : $this->pChartObject->FontColorR; + $G = isset($Format["G"]) ? $Format["G"] : $this->pChartObject->FontColorG; + $B = isset($Format["B"]) ? $Format["B"] : $this->pChartObject->FontColorB; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : $this->pChartObject->FontColorA; + $Angle = isset($Format["Angle"]) ? $Format["Angle"] : 0; + $Padding = isset($Format["Padding"]) ? $Format["Padding"] : 5; + $Position = isset($Format["Position"]) ? $Format["Position"] : LABEL_POSITION_LEFT; + $Labels = isset($Format["Labels"]) ? $Format["Labels"] : NULL; + $CountOffset = isset($Format["CountOffset"]) ? $Format["CountOffset"] : 0; + + if ( $Labels != NULL && !is_array($Labels) ) { $Label = $Labels; $Labels = ""; $Labels[] = $Label; } + + $Y0 = $this->pChartObject->GraphAreaY1; + $YSize = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1) / ($this->GridSizeY+1); + + $Settings = array("Angle"=>$Angle,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + if ( $Position == LABEL_POSITION_LEFT ) + { $XPos = $this->pChartObject->GraphAreaX1 - $Padding; $Settings["Align"] = TEXT_ALIGN_MIDDLERIGHT; } + elseif ( $Position == LABEL_POSITION_RIGHT ) + { $XPos = $this->pChartObject->GraphAreaX2 + $Padding; $Settings["Align"] = TEXT_ALIGN_MIDDLELEFT; } + else + return(-1); + + for($Y=0;$Y<=$this->GridSizeY;$Y++) + { + $YPos = floor($Y0+$Y*$YSize + $YSize/2); + + if( $Labels == NULL || !isset($Labels[$Y]) ) + $Value = $Y+$CountOffset; + else + $Value = $Labels[$Y]; + + $this->pChartObject->drawText($XPos,$YPos,$Value,$Settings); + } + } + + /* Draw the area arround the specified Threshold */ + function drawContour($Threshold,$Format="") + { + $R = isset($Format["R"]) ? $Format["R"] : 0; + $G = isset($Format["G"]) ? $Format["G"] : 0; + $B = isset($Format["B"]) ? $Format["B"] : 0; + $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100; + $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : 3; + $Padding = isset($Format["Padding"]) ? $Format["Padding"] : 0; + + $X0 = $this->pChartObject->GraphAreaX1; + $Y0 = $this->pChartObject->GraphAreaY1; + $XSize = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1) / ($this->GridSizeX+1); + $YSize = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1) / ($this->GridSizeY+1); + + $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks); + + for($X=0;$X<=$this->GridSizeX;$X++) + { + for($Y=0;$Y<=$this->GridSizeY;$Y++) + { + $Value = $this->Points[$X][$Y]; + + if ( $Value != UNKNOWN && $Value != IGNORED && $Value >= $Threshold) + { + $X1 = floor($X0+$X*$XSize)+$Padding; + $Y1 = floor($Y0+$Y*$YSize)+$Padding; + $X2 = floor($X0+$X*$XSize+$XSize); + $Y2 = floor($Y0+$Y*$YSize+$YSize); + + if ( $X > 0 && $this->Points[$X-1][$Y] != UNKNOWN && $this->Points[$X-1][$Y] != IGNORED && $this->Points[$X-1][$Y] < $Threshold) + $this->pChartObject->drawLine($X1,$Y1,$X1,$Y2,$Color); + if ( $Y > 0 && $this->Points[$X][$Y-1] != UNKNOWN && $this->Points[$X][$Y-1] != IGNORED && $this->Points[$X][$Y-1] < $Threshold) + $this->pChartObject->drawLine($X1,$Y1,$X2,$Y1,$Color); + if ( $X < $this->GridSizeX && $this->Points[$X+1][$Y] != UNKNOWN && $this->Points[$X+1][$Y] != IGNORED && $this->Points[$X+1][$Y] < $Threshold) + $this->pChartObject->drawLine($X2,$Y1,$X2,$Y2,$Color); + if ( $Y < $this->GridSizeY && $this->Points[$X][$Y+1] != UNKNOWN && $this->Points[$X][$Y+1] != IGNORED && $this->Points[$X][$Y+1] < $Threshold) + $this->pChartObject->drawLine($X1,$Y2,$X2,$Y2,$Color); + } + } + } + } + + /* Draw the surface chart */ + function drawSurface($Format="") + { + $Palette = isset($Format["Palette"]) ? $Format["Palette"] : NULL; + $ShadeR1 = isset($Format["ShadeR1"]) ? $Format["ShadeR1"] : 77; + $ShadeG1 = isset($Format["ShadeG1"]) ? $Format["ShadeG1"] : 205; + $ShadeB1 = isset($Format["ShadeB1"]) ? $Format["ShadeB1"] : 21; + $ShadeA1 = isset($Format["ShadeA1"]) ? $Format["ShadeA1"] : 40; + $ShadeR2 = isset($Format["ShadeR2"]) ? $Format["ShadeR2"] : 227; + $ShadeG2 = isset($Format["ShadeG2"]) ? $Format["ShadeG2"] : 135; + $ShadeB2 = isset($Format["ShadeB2"]) ? $Format["ShadeB2"] : 61; + $ShadeA2 = isset($Format["ShadeA2"]) ? $Format["ShadeA2"] : 100; + $Border = isset($Format["Border"]) ? $Format["Border"] : FALSE; + $BorderR = isset($Format["BorderR"]) ? $Format["BorderR"] : 0; + $BorderG = isset($Format["BorderG"]) ? $Format["BorderG"] : 0; + $BorderB = isset($Format["BorderB"]) ? $Format["BorderB"] : 0; + $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : -1; + $Padding = isset($Format["Padding"]) ? $Format["Padding"] : 1; + + $X0 = $this->pChartObject->GraphAreaX1; + $Y0 = $this->pChartObject->GraphAreaY1; + $XSize = ($this->pChartObject->GraphAreaX2 - $this->pChartObject->GraphAreaX1) / ($this->GridSizeX+1); + $YSize = ($this->pChartObject->GraphAreaY2 - $this->pChartObject->GraphAreaY1) / ($this->GridSizeY+1); + + for($X=0;$X<=$this->GridSizeX;$X++) + { + for($Y=0;$Y<=$this->GridSizeY;$Y++) + { + $Value = $this->Points[$X][$Y]; + + if ( $Value != UNKNOWN && $Value != IGNORED ) + { + $X1 = floor($X0+$X*$XSize)+$Padding; + $Y1 = floor($Y0+$Y*$YSize)+$Padding; + $X2 = floor($X0+$X*$XSize+$XSize); + $Y2 = floor($Y0+$Y*$YSize+$YSize); + + if ( $Palette != NULL ) + { + if ( isset($Palette[$Value]) && isset($Palette[$Value]["R"]) ) { $R = $Palette[$Value]["R"]; } else { $R = 0; } + if ( isset($Palette[$Value]) && isset($Palette[$Value]["G"]) ) { $G = $Palette[$Value]["G"]; } else { $G = 0; } + if ( isset($Palette[$Value]) && isset($Palette[$Value]["B"]) ) { $B = $Palette[$Value]["B"]; } else { $B = 0; } + if ( isset($Palette[$Value]) && isset($Palette[$Value]["Alpha"]) ) { $Alpha = $Palette[$Value]["Alpha"]; } else { $Alpha = 1000; } + } + else + { + $R = (($ShadeR2-$ShadeR1)/100)*$Value + $ShadeR1; + $G = (($ShadeG2-$ShadeG1)/100)*$Value + $ShadeG1; + $B = (($ShadeB2-$ShadeB1)/100)*$Value + $ShadeB1; + $Alpha = (($ShadeA2-$ShadeA1)/100)*$Value + $ShadeA1; + } + + $Settings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha); + if ( $Border ) { $Settings["BorderR"] = $BorderR; $Settings["BorderG"] = $BorderG; $Settings["BorderB"] = $BorderB; } + if ( $Surrounding != -1 ) { $Settings["BorderR"] = $R+$Surrounding; $Settings["BorderG"] = $G+$Surrounding; $Settings["BorderB"] = $B+$Surrounding; } + + $this->pChartObject->drawFilledRectangle($X1,$Y1,$X2-1,$Y2-1,$Settings); + } + } + } + } + + /* Compute the missing points */ + function computeMissing() + { + $Missing = ""; + for($X=0;$X<=$this->GridSizeX;$X++) + { + for($Y=0;$Y<=$this->GridSizeY;$Y++) + { + if ( $this->Points[$X][$Y] == UNKNOWN ) + $Missing[] = $X.",".$Y; + } + } + shuffle($Missing); + + foreach($Missing as $Key => $Pos) + { + $Pos = preg_split("/,/",$Pos); + $X = $Pos[0]; + $Y = $Pos[1]; + + if ( $this->Points[$X][$Y] == UNKNOWN ) + { + $NearestNeighbor = $this->getNearestNeighbor($X,$Y); + + $Value = 0; $Points = 0; + for($Xi=$X-$NearestNeighbor;$Xi<=$X+$NearestNeighbor;$Xi++) + { + for($Yi=$Y-$NearestNeighbor;$Yi<=$Y+$NearestNeighbor;$Yi++) + { + if ($Xi >=0 && $Yi >= 0 && $Xi <= $this->GridSizeX && $Yi <= $this->GridSizeY && $this->Points[$Xi][$Yi] != UNKNOWN && $this->Points[$Xi][$Yi] != IGNORED) + { + $Value = $Value + $this->Points[$Xi][$Yi]; $Points++; + } + } + } + + if ( $Points != 0 ) { $this->Points[$X][$Y] = $Value / $Points; } + } + } + } + + /* Return the nearest Neighbor distance of a point */ + function getNearestNeighbor($Xp,$Yp) + { + $Nearest = UNKNOWN; + for($X=0;$X<=$this->GridSizeX;$X++) + { + for($Y=0;$Y<=$this->GridSizeY;$Y++) + { + if ( $this->Points[$X][$Y] != UNKNOWN && $this->Points[$X][$Y] != IGNORED ) + { + $DistanceX = max($Xp,$X)-min($Xp,$X); + $DistanceY = max($Yp,$Y)-min($Yp,$Y); + $Distance = max($DistanceX,$DistanceY); + if ( $Distance < $Nearest || $Nearest == UNKNOWN ) { $Nearest = $Distance; } + } + } + } + return($Nearest); + } + } +?> \ No newline at end of file diff --git a/trunk/includes/pChart/data/128B.db b/trunk/includes/pChart/data/128B.db new file mode 100644 index 0000000..20de3c9 --- /dev/null +++ b/trunk/includes/pChart/data/128B.db @@ -0,0 +1,107 @@ +0;32;11011001100 +1;33;11001101100 +2;34;11001100110 +3;35;10010011000 +4;36;10010001100 +5;37;10001001100 +6;38;10011001000 +7;39;10011000100 +8;40;10001100100 +9;41;11001001000 +10;42;11001000100 +11;43;11000100100 +12;44;10110011100 +13;45;10011011100 +14;46;10011001110 +15;47;10111001100 +16;48;10011101100 +17;49;10011100110 +18;50;11001110010 +19;51;11001011100 +20;52;11001001110 +21;53;11011100100 +22;54;11001110100 +23;55;11101101110 +24;56;11101001100 +25;57;11100101100 +26;58;11100100110 +27;59;11101100100 +28;60;11100110100 +29;61;11100110010 +30;62;11011011000 +31;63;11011000110 +32;64;11000110110 +33;65;10100011000 +34;66;10001011000 +35;67;10001000110 +36;68;10110001000 +37;69;10001101000 +38;70;10001100010 +39;71;11010001000 +40;72;11000101000 +41;73;11000100010 +42;74;10110111000 +43;75;10110001110 +44;76;10001101110 +45;77;10111011000 +46;78;10111000110 +47;79;10001110110 +48;80;11101110110 +49;81;11010001110 +50;82;11000101110 +51;83;11011101000 +52;84;11011100010 +53;85;11011101110 +54;86;11101011000 +55;87;11101000110 +56;88;11100010110 +57;89;11101101000 +58;90;11101100010 +59;91;11100011010 +60;92;11101111010 +61;93;11001000010 +62;94;11110001010 +63;95;10100110000 +64;96;10100001100 +65;97;10010110000 +66;98;10010000110 +67;99;10000101100 +68;100;10000100110 +69;101;10110010000 +70;102;10110000100 +71;103;10011010000 +72;104;10011000010 +73;105;10000110100 +74;106;10000110010 +75;107;11000010010 +76;108;11001010000 +77;109;11110111010 +78;110;11000010100 +79;111;10001111010 +80;112;10100111100 +81;113;10010111100 +82;114;10010011110 +83;115;10111100100 +84;116;10011110100 +85;117;10011110010 +86;118;11110100100 +87;119;11110010100 +88;120;11110010010 +89;121;11011011110 +90;122;11011110110 +91;123;11110110110 +92;124;10101111000 +93;125;10100011110 +94;126;10001011110 +95;200;10111101000 +96;201;10111100010 +97;202;11110101000 +98;203;11110100010 +99;204;10111011110 +100;205;10111101110 +101;206;11101011110 +102;207;11110101110 +103;208;11010000100 +104;209;11010010000 +105;210;11010011100 +106;211;1100011101011 \ No newline at end of file diff --git a/trunk/includes/pChart/data/39.db b/trunk/includes/pChart/data/39.db new file mode 100644 index 0000000..b1a74d6 --- /dev/null +++ b/trunk/includes/pChart/data/39.db @@ -0,0 +1,44 @@ +0;101001101101 +1;110100101011 +2;101100101011 +3;110110010101 +4;101001101011 +5;110100110101 +6;101100110101 +7;101001011011 +8;110100101101 +9;101100101101 +A;110101001011 +B;101101001011 +C;110110100101 +D;101011001011 +E;110101100101 +F;101101100101 +G;101010011011 +H;110101001101 +I;101101001101 +J;101011001101 +K;110101010011 +L;101101010011 +M;110110101001 +N;101011010011 +O;110101101001 +P;101101101001 +Q;101010110011 +R;110101011001 +S;101101011001 +T;101011011001 +U;110010101011 +V;100110101011 +W;110011010101 +X;100101101011 +Y;110010110101 +Z;100110110101 +-;100101011011 +.;110010101101 + ;100110101101 +$;100100100101 +/;100100101001 ++;100101001001 +%;101001001001 +*;100101101101 \ No newline at end of file diff --git a/trunk/includes/pChart/fonts/Bedizen.ttf b/trunk/includes/pChart/fonts/Bedizen.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d115733305c5cfd7772b20a911692b39ab376add GIT binary patch literal 42912 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%0Dj|rDgUqq!3r&C+Tmv5%q+6R|$8M=}Dj@(br z#wzQ|+4XroiZBIFUZS<695AcbvhL?`hKRPM?OI?hqDu>F$t{Qq@*-NPnrn6va@|Q1 zbPO*sc-%I{==B&iCl6#RDXDiLv65VkXea$3@MLf^9(Px>7YM)2UqR#J1G_*o2}m6uhOZ)%%2@0(=NalYrSf1&molp) zXp{uS|B1sq{cv07s#Tq>t*mStuMBr}LabnArC?e+vIru@8dk39sc(fq(alP<6!ES= zj{dGZVKo>_lHz|?o=`fosZPIx@;Ca_t5;s}^CwwRjJ(}d48WCGOqp;C=1T;E=0zm% z1G$Z~vN9KxknIlEHcP;xCMiIOhKk!VuU3;A`EwkANX;h6F8O`%kTBS+Sd>uIfk^o5 zq75z+&;h-Ovx2uDG+In{F?$=VbbMVFw+^=V^Ha7^wfWcHxgN+l;0zP=kV-whRE51LYhYxBOf^sTA-d0%~Ks4hRm2!`IIK}pk-s*Y(ioTK3`s+ML)w&XY-&n1HZ~a*pA@zm z!gVQ#L-B+{gNmyur5lFE686W3LEWvm1jKeMt>@aistL~-f=1G;AA;u65X|1qU~AJQ zf5C>9#fGL1jc^?wm-DT|Kj>_4@2aZ~x_xw^)R5}#OVz78oRHtgmlp@!ruSjDtB=KM z{lT!!QJIa_L=!!Y3GaLlji9dL0))({($nuTip|iW`^h7@39iAm^kut}iTHnA1b2r`$*#{S+Ov0LfLw2Cc8#SvBN>csXoji@wM z&xwlVzEg<_L&>*Mm9p4nz73Ryw+Jw(<67KZEoIbVMp!_&;Ov6X08fz>{+$gLG?-Fp zFy5(PV7zPT+ka}V&$3OoF;wNPY_$z^vOO2hzD=~W=WePWp$~vS4@{~UXa0S46AqQ% zgY#)lw;)z<5^rHY{W?eZnqaT0<+N&T3R$bINLm?-Mq|*BYbAG3ssY&7AUjMB>Yl;- zR8x3s!c$Ft;TK!-SvDP9dfYzOiW zUzF>nZgy`0kDh?jyH97=DJ9xGA|Vo|r4_XNPq*Em(x z!3xEw>RL`Eaa?~@z5eg)`cd*6zYa)%{z7C_Rreo^PM%oH=%gA~f61w*4ps_K&mg?*Q-QZpb&PCeLGCf%w^Qr`mh6<8+#rXEuFe0t!R7PYgvaP`S{@fxqPGMjWyZPv~E9%UA zg3rL*>qp6Jy6bFa)bBq*F6Y--Z1_H2dplry)V`Y4&Jd0Rd}Q0LtoA(w;4fB0l&lmK zp%=3I7jx@oTUMD>51~r$02*{Wv8%F#qKz|XQ1q!s7 z;^IN*d3p0{G3JGf0UYr!q5U(GaXB+9oYx>2BjF=F*94{QvB%i|Z$H-d=;iI-`F7i5 zkG6g5v9^C^GEU)XL_X%Z|8AOmIG0oP)O2+`gtcx=qfc?TCnLP4x>|92jL3lO_4?{1 zTM$_(WGN}Tpjs$y5sq0DTujSh3`YYds%rdTRxlPK^N^p#h;nB4E%G$m-&Aa2G}dKT zMfzcI2%tV9--<=%oXId~fkmxWRa+)}i|do)Yd=^MHcfgLr4kdXZnWFCcDLT?so0Wj zTE`<;<@yy}6YHn2@=f7|U0c^}yK!xv3Om-&3k|#1?)>l?Mi-1)nmN_Mb&B%?7~IQT zKT2NKU1wCszK?Z#jD5QWwe)l9>W0@U_`xK*$|8;z@Vfi4$1tAqB7Or@21Q7C4Qw~W zy_i@OC#kFqAh6%Sf@s~y;0EI&A~+p(+ng9$wpwv$fLcknvy^dmXBZk6XyQQ0vRJmI zDBAYyAnYZs_^SScp5<;~`?l|I8bZWgqV4-b7b1-IOf`%aIypU0i=%y&3QMqFVugo* zD7}jQA1Qhzx?@qvQ5lfjAtJdgaCzrR3KZm>i$)+#$p-ijAv2!dX3q#mwOFXip!$iy zOd2DS%ek7dq$O})Dg~jc{z8CtI6tbz33oO7%5cZS+XY&+<=m>8&W@VUP~Vm<2SSTi zbuXBYbS8p7(@m$dVv=VuvGJTH*^VuWcUg91qB_FnEeN0fc5xH>IQnOmCXN?2<9ao& zcc|Bk^LdJ2SHHiY^!+Eunf!VH-)|LHu>(@p^$5P-EndT} zgD)!NS@J-k3oAHLct<=B5iDu!+hgP;R`C4!xdkK<^&mNKM`N0~;YX!JBF;R+yE;9h zdr+$CXoO?_2t4z9TjiQ~Oi0xT?h5J$oK;oiNX&~;6-A2DNNG#p`#M9TirPqV?N*Wb z`rUm#+uf6M9rppu&JKaWN><$hORoG-R#jh2Zd77(CZ3nS-lqEYPx*QV*2J6YeUsF= zI=y#naBytzx)HjLy4R%kjSX&7VzqsJsi?B6wtk=#G^2X{uj%XwRYgW;VrQ0bh&Ikd z0kqEwqX8{f6^40~NjsN@GMQWlX-~u*Bu?O9W%L@10YAW}v{c<9TV0AZB}c3gfmUnM z5MzC1g&_^Zt0o!!cxCu_{pYgJ=}{?`V~c0YK9l{~p|QQp`AyET7!^2$HZGFxTYShE zoP*Si*fy@(2`|xN*a||3IvW^`gVyMuIV~^bv^J0I&}eYh^`qn`{CX7Me_v!YzL4|D zC&&c9?#K1_I4v)HkI`(AmJ9D=b2ae#zvsPH2HKDZ`bp;hwj$+R=W_NWv-`TUu=nGc1jC4Q>hd|>~wRk!cjnWGh-+>sti#(Vn47G4}Xax+gZ znMI<>g-B*t*m`~{wEyJ%h5L5hv}_XclrmMyR7^Z z8=2=I-7_u)Zb7H{2(J>^^?76~zg~&!zgMsG?;j=4^XuSV^gsB>uj1V939^A-XE9js z^7>a{GFkm8ew|YSpOICZ684Z)m=O`^ZJl6-KNqt#R3TC^LaVEDA$U#NtUei7E_BjL z*$syeo7D|Z2~Cb*N<~qMzzHAwlBiIvANguN@;U>q8;R}|-DkR5OHlYVmig{$+9&#c z5lGFyMJL|VKvlH37V)Eb;VPhEA;{QYg8xG@nX45OzOdhFp(FvDpCxScQ9mL6;s=%h z++_B6jb7M2+4Y!Yua?9B(m==+UIM>rGu?B^sc0z6`b9r-=7Pbh@)Er#abDlNeQu9)B6tiZPFFB8VHrt9 zPK>6at-@88uDa{+x@}U=mesc(UNeHNV*7MzJ z9$CxjpaIvPQLq1%(Z^BpEWgga|5Hv+>i3@@EBN&`T>m#tH|sfF?jhs+x*L9gDyP`Y z>Fg+Zi?49ii~aREUhKx2YPha5FLoCDqq(qKE#e$6b~RsDG5&{H*-NICzw5=Wq+A)q zf0RTe45Cs^nX<}73(bpNn4F|)be-nKUJS0|0gl{>UHoYNcX}`OtfRFJk#&ssI?!Xv zM`Cl4XD&pK;m3#d^fdN)UG5`ztO8n4n75|Rcb2;dmD~o)MNYE-6Bf$!^bj&S(O0yn zAnv&YZ(ZiObbW3_^;|-p7QtmgR%0s^8hI?NK^n{S;X>7ikjb^ zgEcIsX!fvj5D|UB|6&igc1CB}=E@p76%04pkCav{n^u+{JbQwka}FY8&Zg^A`R`L_ z-9$a5to6TOhJEnre-$6W{>8E%Uzr;y#*NB;9{{DeWP?GQsqR&Hj0`dd0aXfCGE^xg zo1hhVYh;(t>k>`OMXAI{;riXr8L3(@w#ui3nZ#ytikEn6nebAc1a4M*DZ)!tlxeQK z_DC^DT;y1{n)0mgtT58F-A(D{{9p@DBBUl1;waRPwlOuE&}im7piyh|8HMp7jAflEc+?a8gsqlh9<@{>G5IVXkZS|AFgT3{PQbG~^am#{gCl z>S&p{%Ies{_o^omJIz*_8PTA(gKj+J*4%vl!~s0rftkc%^8oeR-8|cc3}Qh>3uNy= znh)(S$gp5EAO!-HDrsZ@l>Y1s5?HT};vK z;+5E~hmmtm%|B3l+6h~{r8Ko5dd?NK0WJH41_Kf-Y|nq4&KK)o!bI(Uv4=K^--ZM* zkgHJbs#ZyID@Hpq0Ti z5sxHW@mM=WbSfqUftF0wnod*duT1{F7&g~4hYBnD2bM1%=wGqi;S7gdcDpMShQS?s zC|xtOB$tVo^%sRg9!&1_U?wu{-&yELv}~x2o80y0gxPe7t-c|#H5Ii5W4#vEiijAX zj{-HU=APc6P%bP~Tg?VX&>#d9gHfp(DmH-39QN~8*X_#=t9-d!FRwE{?odnod)6V>2ri@ zsChA5vPrFACSMTV06j9Ez@oTK0OSyHWp#_C2vnAS3N>r9Z!bfINFmGc4ep#4kFm#& zb!G1=B`A-FTus9F`O|0=rl_n)EJpGUMu{oGN$!I`vWMSa_cR=06EzPH7W1sXf4Rru zxXYzVZ!I-|Wk?sCYGU+a3lb>@c3Kus@_+d}9{AS@W@Ou8Gmt_q;ULe|XG#SS#=xc_ zB*h}u6y_qP;aF;vKv8$srX*G_UtgIiVG!xuX`;(Y!^Gz4bF)63K5MfEkx!$*W|1!A zvslmjz#>&0LFAl)@F6)8QVnw5VLogAZXasOgr=6AR;AorpDHz*&Gq+YeJV5a(yVT% zv>-5AfU`P#Hd8(F^i=YQ+gbgH*$@y>>;}VibufxH73I27_F+wByYa%TCpbMj>(lAa zb1L>?&J&(0$%}L=xPt}p&`3hVpLJzsd9*Ma3LcIE1&5eeVr6VMr65JMHxQ$lD9zaj zE7+?j$CS;aoI-%P(&@MQ2Q6}w z55m`$XO?4bIEXPdBkd?_7z@~jzb`lLNqA7D15bHVkPXXD#R{gf>7K`>wiL<>6Fu3X zHdEDFis!T1T_$}TczqV_W(RA#H-+}^x!O13KXI*i{mI~j_o}PuHFTTz_S z;~x*;B!Ipo$?bSJ%_+SE!=jdTLIsFIBZhMRZ+brix_bT4;D!x@L+feJ(1s1{oMoR% z7v2-i{8?Il;Ik}a6ptke7{V10+pUI*sMl15$N(DFRura<5#!INoj)(#JX|I@dQt}= z>Ei?R=b~8ylkzW|ex^N;D^$dmw0EYpz#JqpZqEGF)F(i$COgQDxluYbmD@>Tkw`oe zHAQ3bcqA5!8x8$S41vvt#ttZ%hS4>K#AJ>|6s%~qD(kx!D%J6bSS`XQoB0!HVIc4) zU=9V0O1Vj%uRtcEuzy^Qh3>)R?;_a-$dq1GnPQ@f_LLvZ-FmM3b-Cw6`sXNxr#&Zf z&fmrRm=klI`rOFa^uc&)pg$Fl@+U^pj{M*R{q{BbZ@jH{bDln^|1|rNl6TE|ex%MF z`t-+34%f^)P?COA=Pf<^QIm|On<;|)xMowKdN*QKf;oT|XM`6nU0`KtLtE}SAjzVu zzohf>=MpFUrV3^6fDrSNUh`kM1J*3_0W9d;{-FKkp(jUpT+>QCrMH-0jkVsyupI(B zHN>#FQB7sYrCgXMbCwb!{K22aP)&g}(aVJkkmb~hz2Y;uHL6x!%n)tTGDNdStC$du zY(bV+3qtDM6;>zr5``0?A|w5x3&}K@Qz7(mo;6yb9yiiP;~AHwJT;JDRW8RBK2G)^ zeU92_&DY)`Hey;!wo=J z)YpZ0(;XB>8+tX%qDqJ~2pH~qfHNP$@mnxQgbyijpE3TF5YrTnH}DMmejJ}7!~!P` z%U6*m7xp3>Kp`8TVf(FwI5raEg#U>1K|)-x4OM)C5O*^U)Ztl&<2gdS1Q$1jh@6gl{6G2JRv?PZJW^Mc@^M<4Hnd*Ao&) zy@^pAj}nqxj{_^K_8me}_-x1RD3L(AtU0)0b z{?>mbAp^L_Aig_z7a>Cl9H?^$ZOeU*kl{f>MtnG4BV^v|gp6(`WDM z$U@w2;jai8_uzPhkj3ctk}wX`v2==%WvFu*?z23I<7PrujNridtbB!#)ws6iIzrZ> zjE$p4-v4?XTl_pO76DI2v%Ej-3LI zAdYq%<2bhCIG>PRxYsV+Yu714c7KYHJ?jbCJB0&(+xsCLpT+SAj+Y48_YFe!hjHMZ z`(GjC0O~mKI3Wk|e(+5~4qZ*i;a(gc#qoPWjvU2-zMXlDkfUhxSp>&-2|0#)oQ=Mo zjqe}N5pvF-2sw8nj)w?25A8i4_qd>ezDvNKu<~GNVF!7f`00m94?Lay!Z?mQNR99j zNF+bR(}XvX06jvINCR|CNW(YfHzZAe22}bjy!Rtd^u?VY3 zy|9P`a8wCfQP)0v|NHQCe-3{6|4yRFTUSkgjC#LIyuy1VF6_kn3fyBQ@d$VT5`B|| z=?kP%xEkMWg9Z0t$isgoF|?tI-a?#+CTv60eH&||(24f4_f`1)7;)2o!Pd1Ow#Gi< z6sypN3-CnvKNBOgW*^;#Hs^?w-iW@olL-3bqT~4886+&YNge$Y+KXp#3pFG}n@9-t zMd=^Gyc^(HLF z=OFQ--w}3y@;vF~_rDJ3d5$L3(3gmrwUL}6J@{UT<_m8L?~*wEXS6wwdrY7|?DIB! zzZv890YpSyis+*8!Yg>@eFyn1X(Trgg+?HiJdQE`9meVlxbJfqm;2DB=PBpt$K zI4;I<1&#|yTDXREh&SUqiwV*pp&wvo0wNp*1LnsLk1%*A(q!RvT2VM9+>F0(Bdx;6 zQSV6{H{kdP=I2KICW`luqMl87XUBRRyTQgzSxK{%6Qz`gRj~BlS;rm|D zL>=Pp{y^$6UJdwOJ?d-|YBBycd_M;H8c|s2mzmx~qT&XAuoId{kR8pW5C&~!1U*Guh(%A5i*d< zBt&!~e=umogzN$qNKq^|x&u~q=AP@u?_qI9jRDMB5IAl%Y}R3{;0TFg-Nmtfl4xrR zQKR)(i)qkH6XeSl_*%A+c075$19>F7NEYMWLwZRcyiy0qAh<-143iP~2#k_3GM_Af zcgG?!P8O3TWGPujmXj5Da@i`fnyevf$vScd82JXWk!&KHVNuyiCdee&M(!k6kPpJ! z`b}~rxt?50K1uE&caanD$NVs6U z=|g0SJVSP34xR=dd6s++oa8OC3v1~V`2qPN*^LORf52?KKwgB0$#2NNl55C5vX|^9 z2gw0)h}=dFlQYQ?*r3lMXOm;(I5~&BP0l6flk><0 z-Ic#iVK#rl&(6Y}zJU3D2^7KRR+Uiafm)sbojnDbdj?cRKzC>J?|%<;_yd0S_lnE$ z$9<(QJVHJ~9tG9SyzVTXev`j{3)Dl%CqUDCL9quxvxh;iXL4FS4|K|?^kPsbqtDCu zdb$#Hb~Why1Xk2_SVPxi2e=Wd;6qqdH(|AXjNFWvz*`X&@ky+!f5aNN9jodtayRJs zGvu>agP#MP-ivj1A6C$p@Pu_n%U|Kt{2=){R=~rc-*1DSzXR(2XRN!|K>ZNYg$Ge~ zlL&ZH0ByPxbrfhD9igiL`=3iMrXLcX5S|i#CVnI0jCdl!NH`LU)J9q(y^+z#z0p{# z682bv-`|e5+=pKdzDZPfBQwz;&;iPs7ybL zf1ks@d-3l+{QDCAJ;?t(L?5A#(eLtqPa^j|{-LF_SJMCAc(1w&c7m>UgNFBlBKLFp zda6WWM=`T!fzHn6T=86RL`H2F&Z4)={|glNky$kNiCI*4=YN6j9+*RU-{c(hQ5^+- z7whrK;(Ao~fbV1fV>`ePu@f-f{}NU)Th$tmeg*6Q7ob~6$#{V?ny&{s^C)&bqj?2( zRA>G|lr{NdC?ok3C`a-iL3tp55z5Q?^;7wCaQ*}S*B|9C!1+(}A3*ssKYumPa%cIHP=j^sC@JdmG<@>ISb!!awz`~D39ciqdXILcaj(Lhf%(S7CKS?F_bUoV<=zC zMq#2hbT`?e+A_ark_Ch zBESAp{zjbtD1RNwm!}_uL@|s5;CCBoRbTN86Q2qe@O`*-7L+L8q zgYx;p%P3z$Sx+2!R=Q9&!_V*wC^rEdOga3jt~@*hJvTKEadg}8eLcYGe@y25KH z&&FfdGvo#S{U7o2Wt3Uee+Nou;ck>JejX}(66fK<$5AEG3tz(dW{gHRYJLQztMF}y1*`*D}gpz^y4V& zrk_MvKm9$F>FEbhHu9QV`FR^JGra!J>2Kq&+39~lIgnq8a(Ma$l#8doj&cboe}t@< z{sPLi(~qFsfORoKHs-rgZsK>@l3#%HiRpV$Zkv7>t<+=Y)Q)d?{*Hy*w$;_PZz0Wx_H@PWNG=3DpQY=zb z#0T%#rlp#oH;G>qnxLUtuIY_QOe}4TZCbEJEln!oMd^b+_-aL=4H5caMG7re~kE>)XJe&0YsD&aQ!5rstn#WAcBU z{S6$>{sNASb%ie)FzPRWZ`MzN*XlFib;jVJwLN>4XZ5S}^ZV$@XLxGAN|!29VThmcZ%4^s0XWc>>~Nd6nt@HRLGzex?}z#jN5@-Kru@FDU~ zg1z}u{Gu3O@gw+$1RT}3gOmC!IGvqjh8xst;G}*ToYo&_#v9bD%z8nsUjv>N<~IS} zcmrR03Oru_2(0Yt7;m#d8~%p*v8=bi57oZ{HwdM8j2YntaEJwuQU9;ODY(g<&wzva zx8O$oEI6#sfg^0R$(`rHDR`Va&w&H#JkFgz0f+VD;0W6tHx|da^DIw_gL*$WVJ14w znR|FP9njm)Q^O{>Q9lo!tdD}j`VnwMJr`-2|MA3EP-+X`B^=fEBv zCwbZ%%-&@N4eIZLepZ2dW`6(&%mPDN>3MJyi9=fH6j<4v;~Krujkci8UjVmfKW83R zJtM1UWc7@!o{`lvvU)~V&&cW-(T8Df^^B+|BfmYnm)ZPd^E<&$&}XjTy>Ec`7=8x- z!!L{Z?cm<|C&ByYE8qk3yTAvTl2`!C@SnFi4%HG#mIdc)DuP3dIu?EG<*WwO|KZE;kQ9)h(D+=f_gp~ zQ`;suq{oh_?Wf>`J}|cDlQFd^{|-HHf?Xa1eSIfba{q+d&Vy_8#!2f4mYuX7rG^PL zKMWqLUj#SNbAr8|08iNY)0Q7%wFwecL&ezPmlOVnCog*b1Ye~4uft`+bI1vv#|E5# z6WyKzr_AzrIC}my<9>}ZkMO(})IR_R=y07nPl97=xXwLiz$r|pcF&aF^)~sEaXqDv zy#lVyE`dj8-v=M9``|{+$cM#C;3n-bg~eI$1Y==}*Znj&oayRl_EE4x`qU&&VWG0u z>cil5T4qY0+|REKFcyrs?a zORR}Q9EGf3<}l=~SfCAP0lQg+JKZ)Ltm+I$Z1rYVnt<6V#M;+Av8=(!&TosD*?mhEW)%DevgGM6h92 zcyR~I%n9Xhk^o3i0lQU8pdIQ?{^=GrmV*R(Qh)@CV@wH_*TT`R(|l?I_MKCV|JV}|@P`KNnYNe(4Mu|u?RC$MQ-KB`J5~%r{R8hB5pF)g` zr=CMfGZ@9O=l!zIr7=ri)qlisDI3}f6&t3K+i;9@Cvk4L1&;J8<7h2{h3U8*){A2< z80$Lwu))!k!5UGV+8|{!K{Y{=EI7KRJZ;Rji6~+MM73cYJL75`7p#|m6oaQ}a^uK& zLB>sve8$1fg-M=A?8@9>!^Vaq3h~*x+E|Gup-Dq_XOuuzJ)tgNHt8xy8TQ5Z(B-6K zyx^G0&f*voOFTjs`$W6OWul@*>+@S4IL5W;-Xe)1mAl6KC3>QcayW>?=PK zv*wGWm0#G=kxify#}3(W)CQO+LywFTIMU#mMrlM`5Ah`BR$d$l!mcC%B$-qxH?DTw za<>3|il)icUl}QqL8n)Lh9e)c#3>Px8;&j^nu9uXH|_?KogfC<9hx*^g#^SRw%0~o z$2V$lan?uCHh#@&81lYW7+_Y-6+#2!;eEg^*Ev^ zbZ~^TbK*%VoAUU7s#aQXG#!9a)hAF4tVh{V1L#BHh9e)p!!gO|pc);dykwQHbA3Ls z!qY{0<{V>$5dBG4yQwaO$^XW2ZgSZISsb}DRoGGEh*!rJL}(N*ag5=JRyfgwHh_LN zau_%vG)0d5Jj5jtKp0PyuoE{tGye5Vb$LP#ln|gqMfSI6=Ctd|DTyNF(1*fma!d(F z#JrDV(PJ8LZiW5HCJL9%bUl$id76PcTMsRC&$pY$ru5ZkHkewnmUlUzfQ~ z8(8iZpie(bIooh#K|M0ej`B-opE<$%ohuE;!Yw!kDSO?kjV&<(AV&;v+BWgVkvm!H zq^2(E;Kni1r=?lwQkF>uC0POm5h{o%Y%E8Oy>Wyx@{35$HkY?e^E^+yrM{`Y;HWba zKoU=-6*H$eYDifUO)_v~Jry@%Ry;4eMW()>&uh5Gac>2VdA@6BW_B!Hp3B|S=mCS% zn-FMs)kvj|aDPq%qVxojlgUXOHI85!glW(x>*lKV7-d|Kq0);zoeGZ3jwQ?A3QN1JydKVo zjjtr8BqNGx*(48}iX#KXC>kOMeO5jDz%ilmpu()orf@wtieZwhtVWS5%iDGv$F!f9 zCBDx4kYI8JvLyr41`cw49cldWSy9^O1HY2PA}89ZXFd`~#Q7+9;C%BzteQa=92?V$DLH(=ZnHXOg=2!4 zqEDX|!!+Tup~&@0-f6tTniBnpywrY8vs z`S3@&2j*+M+&jQqYkN~-mv^*y;mBc!)hw;Ut@eBEQ-h=5`QGD4kL_6|Vl&M747?uP zcklY$cU!5ZJZ1k`zwz3`#pmB+eIIL>TCG37`}f1kzw_7UYn{u;)9UT^;(a$|(Bre5 odV}lFb}lc@t5B0}*qIx=*;V8Mb~$E6#20u2(`sGX@nzNXe<5)(*#H0l literal 0 HcmV?d00001 diff --git a/trunk/includes/pChart/fonts/Forgotte.ttf b/trunk/includes/pChart/fonts/Forgotte.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a2f7f4ab11f041a6d72e99a8f95c6b6b00a1b27d GIT binary patch literal 42148 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 literal 0 HcmV?d00001 diff --git a/trunk/includes/pChart/fonts/GeosansLight.ttf b/trunk/includes/pChart/fonts/GeosansLight.ttf new file mode 100644 index 0000000000000000000000000000000000000000..055932aac8de6861ab4e3a8f54e54d1f170101de GIT binary patch literal 60072 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 literal 0 HcmV?d00001 diff --git a/trunk/includes/pChart/fonts/Silkscreen.ttf b/trunk/includes/pChart/fonts/Silkscreen.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ae4425ddabf65d729318736cab2435f47ebe45fa GIT binary patch literal 16172 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 literal 0 HcmV?d00001 diff --git a/trunk/includes/pChart/fonts/advent_light.ttf b/trunk/includes/pChart/fonts/advent_light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..514030a885ddddf504fac6b4db1aa50be7c3ce70 GIT binary patch literal 45768 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 LFm?nPa}xgpDq>tJ literal 0 HcmV?d00001 diff --git a/trunk/includes/pChart/fonts/calibri.ttf b/trunk/includes/pChart/fonts/calibri.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8b6e3c9743151d253ef32fe27e386ed6707312cd GIT binary patch literal 811052 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�T#SJf@* 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ෳ-FYGPZ>(~o*P`QhbM6_ga9XN2qAT85q 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 Wa%z020eM!EKP7!_1CK~} diff --git a/trunk/includes/pChart/palettes/autumn.color b/trunk/includes/pChart/palettes/autumn.color new file mode 100644 index 0000000..80ffbc0 --- /dev/null +++ b/trunk/includes/pChart/palettes/autumn.color @@ -0,0 +1,6 @@ +185,106,154,100 +216,137,184,100 +156,192,137,100 +216,243,201,100 +253,232,215,100 +255,255,255,100 diff --git a/trunk/includes/pChart/palettes/blind.color b/trunk/includes/pChart/palettes/blind.color new file mode 100644 index 0000000..9d62238 --- /dev/null +++ b/trunk/includes/pChart/palettes/blind.color @@ -0,0 +1,6 @@ +109,152,171,100 +0,39,94,100 +254,183,41,100 +168,177,184,100 +255,255,255,100 +0,0,0,100 diff --git a/trunk/includes/pChart/palettes/evening.color b/trunk/includes/pChart/palettes/evening.color new file mode 100644 index 0000000..5d0c1a5 --- /dev/null +++ b/trunk/includes/pChart/palettes/evening.color @@ -0,0 +1,6 @@ +242,245,237,100 +255,194,0,100 +255,91,0,100 +184,0,40,100 +132,0,46,100 +74,192,242,100 diff --git a/trunk/includes/pChart/palettes/kitchen.color b/trunk/includes/pChart/palettes/kitchen.color new file mode 100644 index 0000000..b0eeb33 --- /dev/null +++ b/trunk/includes/pChart/palettes/kitchen.color @@ -0,0 +1,6 @@ +155,225,251,100 +197,239,253,100 +189,32,49,100 +35,31,32,100 +255,255,255,100 +0,98,149,100 diff --git a/trunk/includes/pChart/palettes/light.color b/trunk/includes/pChart/palettes/light.color new file mode 100644 index 0000000..d0657db --- /dev/null +++ b/trunk/includes/pChart/palettes/light.color @@ -0,0 +1,7 @@ +239,210,121,100 +149,203,233,100 +2,71,105,100 +175,215,117,100 +44,87,0,100 +222,157,127,100 + diff --git a/trunk/includes/pChart/palettes/navy.color b/trunk/includes/pChart/palettes/navy.color new file mode 100644 index 0000000..3b6df5e --- /dev/null +++ b/trunk/includes/pChart/palettes/navy.color @@ -0,0 +1,6 @@ +25,78,132,100 +59,107,156,100 +31,36,42,100 +55,65,74,100 +96,187,34,100 +242,186,187,100 diff --git a/trunk/includes/pChart/palettes/shade.color b/trunk/includes/pChart/palettes/shade.color new file mode 100644 index 0000000..0e43a1d --- /dev/null +++ b/trunk/includes/pChart/palettes/shade.color @@ -0,0 +1,6 @@ +117,113,22,100 +174,188,33,100 +217,219,86,100 +0,71,127,100 +76,136,190,100 +141,195,233,100 diff --git a/trunk/includes/pChart/palettes/spring.color b/trunk/includes/pChart/palettes/spring.color new file mode 100644 index 0000000..386cbc4 --- /dev/null +++ b/trunk/includes/pChart/palettes/spring.color @@ -0,0 +1,6 @@ +146,123,81,100 +168,145,102,100 +128,195,28,100 +188,221,90,100 +255,121,0,100 +251,179,107,100 diff --git a/trunk/includes/pChart/palettes/summer.color b/trunk/includes/pChart/palettes/summer.color new file mode 100644 index 0000000..1609534 --- /dev/null +++ b/trunk/includes/pChart/palettes/summer.color @@ -0,0 +1,6 @@ +253,184,19,100 +246,139,31,100 +241,112,34,100 +98,194,204,100 +228,246,248,100 +238,246,108,100 diff --git a/trunk/includes/pChart/readme.txt b/trunk/includes/pChart/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..1c3e21f5a787358103e8935e8795dc457b06c62f GIT binary patch literal 11944 zcmd6tOK)4p8HNYmrRy%cU<(L#P}_==7HG05Y)O_COAam3bzPt^bT_LDS(37%{P?!- zGcUi+nIn>wQrj^Il85KaeE0kC-~akm>ZIOM_cMLHUV^@tOC5cFj<1&$eZ#bp-lg3% zN)u80K<{0>yXl$UoyN0%I#0*CbDH{TPpjE+rQaX^Rnzz3;s3u7Yx@3@4kd}Pq%x3% z3heK6{dIbn9_jr}<9=E3v948(b$pJn)-si?{$AyR6j_o`aTm6hna_N`XR0B zy{UIkuZ<5%e@)+}FpsnCy-Gt-x~prbg}$%Sw`qC$`L(_u>GiRsR^Zn3mHVH|mFfH2 zXBz#wOMh2-&wqU!_0mDlL87 zmnk$gCHnPciFN!t%8~9&7I`WE9;FjKpX7K+w7itZoa)ulokM*Ob#i9^mVYRlXI)SM1zFQEz z_VnG!I7aEcevcH3kg_S<7k)=9II`yheJre}dPcPHlg;QxxnZFnCUW z7>EM68>RcY!6p7)#)q2pTzQRhBZ&JcRywqTE`$o|lj)5ye6bU|9SMr1bXg?AzavwWwUy%o~GjtSjpev7GNze7Up4Rki zMV|gb5nwHU?&!|P_4j$up^x|dToc{NpTAM;=_v2uANb{A`XaxItsO}gr`ZPZG~3^W z#Lt>2XuqG9jqn=G3dvI3a*L4jC4ODvA%_0h{OQQ3+U=6dqMh+{P3T+20Te5AbV6rW=F|DN^MFCu5 zRb;=gnt6Q9vzCnvgA55B*m;d>k$r-TY*+Tq$ATn|MQaTmt%Yy>Tn@TfSJ&ar_bVy_ zdvmE6W?S1%&JSdR+rW4Bca|PzxxSNziq_{z32fvZy2RV!i+wl4V~t@!ZGG2%)Q(8w zsjj{AX1IW{ud45M9L26hIDVb8%rNc9yGE)A@a$O@Hs2D))y~6T$+iCI|Y<$;^xY03{d&?UR- zx_yQo%a*7V%XFm;vF2`;Jc*cC#Ff4e)SnM@&Am~U?`rjw8m>HtW4aOIIrUnNyT)vb zp)PjZ+tT+iW7zobJy-8^JU54HeT@Z;*t;j{ew^AxSJ!kbcmmZCny131j>Ma&w@Qsc zcIzw7P~p1Yq7IuCqni4oYNKYlz2>OS$@S+MM^x}kMxN?Pfg4h6VkL&UN+<3F?j79? zOQOrG*8r2gsF}qJO!G;cC0?N8de zrKSXZMb3WiAbz>-!Ci$Z)I@r2FB+XFy`KBBcAtjM=-JU6GX^FL=%U1mKc?U7SKVci zi|N_$=Q4{x_QaY34?WI;`3K#_uGt@&M?bF2N>=`-)&LcnqHn*_PArDL@KQUDMY&@U z6`ehNF;prIjWT=Kp&qfN~b8R(42iKNhZ(|@+*H81q)>%FdLJQndP zvo&fd5uKRu470wltl}B%9EQg3$!@6Fkdt*3vzxH*W!zy!8#9^^i=25Jp4#Kyf30s6ROQt!4 zFnz?1CI!JU{rg$Y+tBHm5K|pX=DnVtG_W{F421`JOaq+SDv>Hxcj)YgY{lpV*q-@y zG~3z9Q$P4&mT@8Mg^!SJQvz|`w3pX0DR2*q4f6|X;bWAq%j}bT=Q&#*3k&Pu5L}i? z$bk71_6|I}{Jqwosq>tNkTbE>cuVgc6o$u{nuxC05p!7LC-hl6Ts_e}GT4Ezl6&bM z&N5}xu@n7zH>EG~e4XhwwR=T=`9gAB6TErTt51DDwB8f_=D3c+?b#EWz$@(~o+!qY z3|}aIgY3wDtfebI(#tW>y0O(#qY#B%7qNCj>-er?Fx4tmdUW@3HfL&>2cvI1)K-Oe zfUQ(6SOy&4)8}zMi!ugRy(jq@a6HjtEqT$CKU*QVCW6UnDHdY;w^b59BF?~3v7B}3 z{FQz;>nigRoI}&P@PU(zOP$pf2Buf;nKtuxtOrk#M@SA0S{gNU)8`x)-W;4e0y)Bv zMI%F_A*2K~_5{4HKyRKFBZZ=^CS{J<*3>vh56?=m1!QYaHhp+KS&sdVX|rX{3S^C* zjoDTFfoON6ATrb6J3iZ1eQH1+apd*yu&{YF+t!QxT!HyKrD+GoTe6t>3XQkzoGjk< zx<$5uRGR%*SbpR#R}170dtb<Mqh;9>uZNXyyet{}IO;7bXt!H+@ z#4YimRKM6WD^TD(NJ<;9b0X@kRYO!&;yy)-TwYWNpDiRrm{ntK%L_)GqX*;F{ z#w+OGoBqeYZzAi&*&sR8b3y1tuaopPTk&zWd-BFaR^d~Tp<)_7>1Q3;F@8wAv~4^W zht56d%Q6c1Pjm;L{V8Kv47aB>oQS~RR+c7upk8>Ie=+T=p%bYhQ}ji}BC59pnVIPz z+XFeGh6Rq1c%+`hE*C@F7G@~h%sL{T(&N++sqDZ;t{H1(NN_P^{E05eRZvIg?9?|z zy&AgLohW)3{_UX7hdUJRx0x$)$y@#EXB$}z|BWn?$ZBtVuAOv=SNR+I+OlEZcdFI) zM8}rJ81P+tG8TwT*bQuK5q_*WCqPJ4{ERbTDq*5w-S4^PbrnVIB~ue+VopfyK@@Pjh#2+{L8gNz z0=&_#3r(_INuht{1;%HM&h%bueIi`^n0pnR(Sdy{R)#8s!(?V zo+x4q)Tifq;(Xy~6!3|zWP`wJdx+Vf>s8ZNS9h+jnMIU1Z93Zj1S7kZv%Tx{N5^-p zwA3pRshf36=?`k%lz%i?DoBRc?dlZsxGF6%=Lm_RkLWDuWSAe#hU{mvYaqkk5nQ@; zA}Ly;HyLGILGe7Q7r|a`z`@eN^&r2vx+iYF)PGCjAEmeXA1wcnex!2{ru5_ybV1(r LSxZzPWS##2h&UWh literal 0 HcmV?d00001 diff --git a/trunk/semmelstatzR-database.php b/trunk/semmelstatzR-database.php index 5606278..b8007a6 100644 --- a/trunk/semmelstatzR-database.php +++ b/trunk/semmelstatzR-database.php @@ -2,22 +2,49 @@ /** * file semmelstatzR_database.php * - * @package SemmelstatzR - * @version $Rev$ - * @author Ortwin Pinke - * @author Andreas 'Redunzl' Mueller - * @copyright (c)2011 PHP-Backoffice - * @copyright (c)2005-2009 kopfhoch-studio - * @link http://sourceforge.net/projects/semmelstatz/ - * @license http://www.gnu.org/licenses/gpl-2.0.html + * @package SemmelstatzR + * @version $Rev$ + * @since 1.0.0 Beta + * @author SEM-Team + * @copyright (c)2011 SEM-Team + * @link http://sourceforge.net/projects/semmelstatz/ + * @license http://www.gnu.org/licenses/gpl-3.0.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * * $Id$ + * */ +/** + * based upon semmelstatz + * Copyright (c) 2005-2009 Andreas 'Redunzl' Mueller (redunzl@gmx.de) + * + * @license http://www.gnu.org/licenses/gpl-2.0.html + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ -define('SEMMELSTATZR_VERSION', '1.0.0 Beta'); -define('SEMMELSTATZR_SRVPATH', dirname(__FILE__)); -define('SEMMELSTATZR_HTML_RELPATH', WP_PLUGIN_URL.'/'.str_replace(basename( __FILE__),"",plugin_basename(__FILE__))); - if(current_user_can('manage_statz')) { global $wpdb; @@ -39,34 +66,39 @@ if(current_user_can('manage_statz')) { print "Index"; print "Daten & Index"; print "Überhang"; - + + $row_usage = 0; + $data_usage = 0; + $index_usage = 0; + $total_usage = 0; + $overhead_usage = 0; foreach($tablesstatus as $key=>$tablestatus) { - if(substr($tablestatus->Name,0,$lenpre) != $pre) continue; + if(substr($tablestatus->Name,0,$lenpre) != $pre) continue; - print ""; - print "".($key+1).""; - print "".$tablestatus->Name.""; - print "".number_format($tablestatus->Rows,0,',','.').""; - print "".number_format($tablestatus->Data_length/1024,0,',','.')." kb"; - print "".number_format($tablestatus->Index_length/1024,0,',','.')." kb"; - print "".number_format(($tablestatus->Data_length + $tablestatus->Index_length)/1024,0,',','.')." kb"; + print ""; + print "".($key+1).""; + print "".$tablestatus->Name.""; + print "".number_format($tablestatus->Rows,0,',','.').""; + print "".number_format($tablestatus->Data_length/1024,0,',','.')." kb"; + print "".number_format($tablestatus->Index_length/1024,0,',','.')." kb"; + print "".number_format(($tablestatus->Data_length + $tablestatus->Index_length)/1024,0,',','.')." kb"; - if($tablestatus->Data_free > 0) { - print ""; - print " ".number_format($tablestatus->Data_free/1024,2,',','.')." kb"; - print ""; - } - else { - print "--"; - } + if($tablestatus->Data_free > 0) { + print ""; + print " ".number_format($tablestatus->Data_free/1024,2,',','.')." kb"; + print ""; + } + else { + print "--"; + } - $row_usage += $tablestatus->Rows; - $data_usage += $tablestatus->Data_length; - $index_usage += $tablestatus->Index_length; - $total_usage += $tablestatus->Data_length + $tablestatus->Index_length; - $overhead_usage += $tablestatus->Data_free; - echo ''; + $row_usage += $tablestatus->Rows; + $data_usage += $tablestatus->Data_length; + $index_usage += $tablestatus->Index_length; + $total_usage += $tablestatus->Data_length + $tablestatus->Index_length; + $overhead_usage += $tablestatus->Data_free; + echo ''; } print ""; diff --git a/trunk/semmelstatzR-history.php b/trunk/semmelstatzR-history.php index 4cedc8f..ec6282b 100644 --- a/trunk/semmelstatzR-history.php +++ b/trunk/semmelstatzR-history.php @@ -2,53 +2,109 @@ /** * file semmelstatzR_history.php * - * @package SemmelstatzR - * @version $Rev$ - * @author Ortwin Pinke - * @author Andreas 'Redunzl' Mueller - * @copyright (c)2011 PHP-Backoffice - * @copyright (c)2005-2009 kopfhoch-studio - * @link http://www.php-backoffice.de/projects/semmelstatzR - * @link http://sourceforge.net/projects/semmelstatz/ - * @license http://www.gnu.org/licenses/gpl-2.0.html + * @package SemmelstatzR + * @version $Rev$ + * @since 1.0.0 Beta + * @author SEM-Team + * @copyright (c)2011 SEM-Team + * @link http://sourceforge.net/projects/semmelstatz/ + * @license http://www.gnu.org/licenses/gpl-3.0.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * * $Id$ + * */ +/** + * based upon semmelstatz + * Copyright (c) 2005-2009 Andreas 'Redunzl' Mueller (redunzl@gmx.de) + * + * @license http://www.gnu.org/licenses/gpl-2.0.html + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ if(!current_user_can('manage_statz')) { die('Zugriff verweigert'); } - - function sem_drawLast30DaysGoo() { - global $wpdb; - - $sql = $wpdb->get_results("ALTER TABLE ".$wpdb->statzhist." ORDER BY date ASC"); - $results = $wpdb->get_results("SELECT DAY(date) as days, visitors FROM ".$wpdb->statzhist." WHERE date >= NOW() - INTERVAL 31 DAY"); - - print "

"; - print "
"; - - if (empty($results)) { - print "... noch keine Einträge
"; - return; - } - - foreach ($results as $result) { - $visitors[] = $result->visitors; - $days[] = $result->days; - } - - $maxvalue = max($visitors); - $daylabels = implode('|', $days); - - print "
"; - - print ""; - - print "
"; - - print ""; - print "
"; + +include_once plugin_dir_path(__FILE__).'includes/pChart/class/pData.class.php'; +include_once plugin_dir_path(__FILE__).'includes/pChart/class/pDraw.class.php'; +include_once plugin_dir_path(__FILE__).'includes/pChart/class/pImage.class.php'; + +function sem_drawLast30DaysGoo() { + global $wpdb; + + //$sql = $wpdb->get_results("ALTER TABLE ".$wpdb->statzhist." ORDER BY date ASC"); + $results = $wpdb->get_results("SELECT DAY(date) as days, visitors FROM ".$wpdb->statzhist." WHERE date >= NOW() - INTERVAL 31 DAY ORDER BY date ASC"); + + print "
Besucher: Die letzten 30 Tage
"; + print "
"; + + if (empty($results)) { + print "... noch keine Einträge
"; + return; + } + + foreach ($results as $result) { + $visitors[] = $result->visitors; + $days[] = $result->days; + } + + $maxvalue = max($visitors); + $daylabels = implode('|', $days); + + $MyData = new pData(); + $MyData->addPoints($visitors,"Visitors"); + $MyData->setAxisName(0,"Hits"); + $MyData->addPoints($days,"Days"); + $MyData->setAbscissa("Days"); + + $myPicture = new pImage(780,150,$MyData); + $myPicture->Antialias = FALSE; + $myPicture->drawRectangle(0,0,779,149,array("R"=>0,"G"=>0,"B"=>0)); + $myPicture->setFontProperties(array("FontName"=>plugin_dir_path(__FILE__)."includes/pChart/fonts/Bedizen.ttf","FontSize"=>8)); + $myPicture->setGraphArea(30,20,760,130); + $scaleSettings = array("GridR"=>200,"GridG"=>200,"GridB"=>200); + $myPicture->drawScale($scaleSettings); + $myPicture->drawBarChart(); + @$myPicture->Render(WP_CONTENT_DIR."/cache/Last30DaysGoo.png"); + + print "
"; + + //print ""; + if(is_readable(WP_CONTENT_DIR."/cache/Last30DaysGoo.png")) { + print ''; + } else if(!is_dir(WP_CONTENT_DIR."/cache")) { + print semr_i18n('No Chart: Cannot find cache-folder!'); + } else if(!is_writable(WP_CONTENT_DIR."/cache")) { + print semr_i18n('No Chart: Missing rights for cache-folder!'); + } + print "
"; + + print ""; + print "
"; } ### HISTORY Monatsgrafik GOOGLE-API @@ -72,14 +128,35 @@ $months[] = $result->months; } - $maxvalue = max($visitors); - + $maxvalue = max($visitors); $monthlabels = implode('|', $months); + + $MyData = new pData(); + $MyData->addPoints($visitors,"Visitors"); + $MyData->setAxisName(0,"Hits"); + $MyData->addPoints($months,"Month"); + $MyData->setAbscissa("Month"); + + $myPicture = new pImage(780,150,$MyData); + $myPicture->Antialias = FALSE; + $myPicture->drawRectangle(0,0,779,149,array("R"=>0,"G"=>0,"B"=>0)); + $myPicture->setFontProperties(array("FontName"=>plugin_dir_path(__FILE__)."includes/pChart/fonts/Bedizen.ttf","FontSize"=>8)); + $myPicture->setGraphArea(30,20,760,130); + $scaleSettings = array("GridR"=>200,"GridG"=>200,"GridB"=>200); + $myPicture->drawScale($scaleSettings); + $myPicture->drawBarChart(); + @$myPicture->Render(WP_CONTENT_DIR."/cache/AllMonthGoo.png"); print "
"; - print ""; - + //print ""; + if(is_readable(WP_CONTENT_DIR."/cache/AllMonthGoo.png")) { + print ''; + } else if(!is_dir(WP_CONTENT_DIR."/cache")) { + print semr_i18n('No Chart: Cannot find cache-folder!'); + } else if(!is_writable(WP_CONTENT_DIR."/cache")) { + print semr_i18n('No Chart: Missing rights for cache-folder!'); + } print "
"; print ""; @@ -88,40 +165,62 @@ ### HISTORY ALLE historischen Tage - function sem_drawAllDaysGoo() { - global $wpdb; - - $numdays = $wpdb->get_var("SELECT COUNT(date) FROM ".$wpdb->statzhist); - - $results = $wpdb->get_results("SELECT referers, visitors, hits, substring(date,1,10) AS date - FROM ".$wpdb->statzhist." GROUP BY date ORDER BY date ASC"); - $visitors=$totaldays->visitors; - - print "
Besucher: ".$numdays." Tage zurück
"; - print "
"; - - if (empty($results)) { - print "... noch keine Einträge
"; - return; - } - - foreach($results as $result) { - $visitors[] = $result->visitors; - $hits[] = $result->hits; - $referers[] = $result->referers; - } - - $maxvalue = max($visitors); - - print "
"; - - print ""; - - print "
"; - - print ""; - print "
"; - } +function sem_drawAllDaysGoo() { + /* @var $wpdb wpdb */ + global $wpdb; + + $numdays = $wpdb->get_var("SELECT COUNT(date) FROM ".$wpdb->statzhist); + + $results = $wpdb->get_results("SELECT referers, visitors, hits, substring(date,1,10) AS date + FROM ".$wpdb->statzhist." GROUP BY date ORDER BY date ASC"); + + + print "
Besucher: ".$numdays." Tage zurück
"; + print "
"; + + if (empty($results)) { + print "... noch keine Einträge
"; + return; + } + + foreach($results as $result) { + $visitors[] = $result->visitors; + $hits[] = $result->hits; + $referers[] = $result->referers; + } + + $maxvalue = max($visitors); + + $MyData = new pData(); + $MyData->addPoints($visitors,"Visitors"); + $MyData->setAxisName(0,"Hits"); + $MyData->addPoints($hits,"Hits"); + $MyData->setAbscissa("Hits"); + + $myPicture = new pImage(780,150,$MyData); + $myPicture->Antialias = FALSE; + $myPicture->drawRectangle(0,0,779,149,array("R"=>0,"G"=>0,"B"=>0)); + $myPicture->setFontProperties(array("FontName"=>plugin_dir_path(__FILE__)."includes/pChart/fonts/Bedizen.ttf","FontSize"=>8)); + $myPicture->setGraphArea(30,20,760,130); + $scaleSettings = array("GridR"=>200,"GridG"=>200,"GridB"=>200); + $myPicture->drawScale($scaleSettings); + $myPicture->drawBarChart(); + @$myPicture->Render(WP_CONTENT_DIR."/cache/AllDaysGoo.png"); + + print "
"; + //print ""; + if(is_readable(WP_CONTENT_DIR."/cache/AllDaysGoo.png")) { + print ''; + } else if(!is_dir(WP_CONTENT_DIR."/cache")) { + print semr_i18n('No Chart: Cannot find cache-folder!'); + } else if(!is_writable(WP_CONTENT_DIR."/cache")) { + print semr_i18n('No Chart: Missing rights for cache-folder!'); + } + print "
"; + + print ""; + print "
"; +} function sem_showAllDaysInNumbers() { global $wpdb; @@ -147,11 +246,17 @@ print ""; print ""; print ""; + $sum_visitors = 0; + $sum_hits = 0; + $sum_referers = 0; foreach($results as $key=>$result) { $date = mysql2date('d.m.Y',$result->date); - $visitors = $result->visitors; $sum_visitors += $visitors; - $hits = $result->hits; $sum_hits += $hits; - $referers = $result->referers; $sum_referers += $referers; + $visitors = $result->visitors; + $sum_visitors += $visitors; + $hits = $result->hits; + $sum_hits += $hits; + $referers = $result->referers; + $sum_referers += $referers; print ""; print "".$date.""; print "".$visitors.""; diff --git a/trunk/semmelstatzR-log.php b/trunk/semmelstatzR-log.php index 46e7cae..6a2b819 100644 --- a/trunk/semmelstatzR-log.php +++ b/trunk/semmelstatzR-log.php @@ -2,18 +2,48 @@ /** * file semmelstatzR_log.php * - * @package SemmelstatzR - * @version $Rev$ - * @author Ortwin Pinke - * @author Andreas 'Redunzl' Mueller - * @copyright (c)2011 PHP-Backoffice - * @copyright (c)2005-2009 kopfhoch-studio - * @link http://www.php-backoffice.de/projects/semmelstatzR - * @link http://sourceforge.net/projects/semmelstatz/ - * @license http://www.gnu.org/licenses/gpl-2.0.html + * @package SemmelstatzR + * @version $Rev$ + * @since 1.0.0 Beta + * @author SEM-Team + * @copyright (c)2011 SEM-Team + * @link http://sourceforge.net/projects/semmelstatz/ + * @license http://www.gnu.org/licenses/gpl-3.0.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * * $Id$ + * */ +/** + * based upon semmelstatz + * Copyright (c) 2005-2009 Andreas 'Redunzl' Mueller (redunzl@gmx.de) + * + * @license http://www.gnu.org/licenses/gpl-2.0.html + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ if(!current_user_can('manage_statz')) { die('Zugriff verweigert'); diff --git a/trunk/semmelstatzR-options.php b/trunk/semmelstatzR-options.php index 6c6b07f..2035000 100644 --- a/trunk/semmelstatzR-options.php +++ b/trunk/semmelstatzR-options.php @@ -2,18 +2,48 @@ /** * file semmelstatzR_options.php * - * @package SemmelstatzR - * @version $Rev$ - * @author Ortwin Pinke - * @author Andreas 'Redunzl' Mueller - * @copyright (c)2011 PHP-Backoffice - * @copyright (c)2005-2009 kopfhoch-studio - * @link http://www.php-backoffice.de/projects/semmelstatzR - * @link http://sourceforge.net/projects/semmelstatz/ - * @license http://www.gnu.org/licenses/gpl-2.0.html + * @package SemmelstatzR + * @version $Rev$ + * @since 1.0.0 Beta + * @author SEM-Team + * @copyright (c)2011 SEM-Team + * @link http://sourceforge.net/projects/semmelstatz/ + * @license http://www.gnu.org/licenses/gpl-3.0.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * * $Id$ + * */ +/** + * based upon semmelstatz + * Copyright (c) 2005-2009 Andreas 'Redunzl' Mueller (redunzl@gmx.de) + * + * @license http://www.gnu.org/licenses/gpl-2.0.html + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ if(!current_user_can('manage_statz')) { die('Zugriff verweigert'); @@ -45,12 +75,12 @@ if(!current_user_can('manage_statz')) { $sem_options['statz_use_img'] = $_POST['statz_use_img']; update_option("semmelstatzR_options", $sem_options); - echo '

'.semr_e('Options saved').'

'; + echo '

'.semr_i18n('Options saved').'

'; } if(isset($_POST['trunc_save'])) { - if ($result == sem_truncateStatzTable()) { - echo "

".semr_e('statz-table emptied succesfully.')."

"; + if (sem_truncateStatzTable()) { + echo "

".semr_i18n('statz-table emptied succesfully.')."

"; } } @@ -93,18 +123,18 @@ if(!current_user_can('manage_statz')) {

-

SemmelstatzR ›

+

SemmelstatzR ›

-

+

- + - + diff --git a/trunk/semmelstatzR-statz.php b/trunk/semmelstatzR-statz.php index eb0e158..9191b6f 100644 --- a/trunk/semmelstatzR-statz.php +++ b/trunk/semmelstatzR-statz.php @@ -2,23 +2,56 @@ /** * file semmelstatzR_statz.php * - * @package SemmelstatzR - * @version $Rev$ - * @author Ortwin Pinke - * @author Andreas 'Redunzl' Mueller - * @copyright (c)2011 PHP-Backoffice - * @copyright (c)2005-2009 kopfhoch-studio - * @link http://www.php-backoffice.de/projects/semmelstatzR - * @link http://sourceforge.net/projects/semmelstatz/ - * @license http://www.gnu.org/licenses/gpl-2.0.html + * @package SemmelstatzR + * @version $Rev$ + * @since 1.0.0 Beta + * @author SEM-Team + * @copyright (c)2011 SEM-Team + * @link http://sourceforge.net/projects/semmelstatz/ + * @license http://www.gnu.org/licenses/gpl-3.0.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * * $Id$ + * */ +/** + * based upon semmelstatz + * Copyright (c) 2005-2009 Andreas 'Redunzl' Mueller (redunzl@gmx.de) + * + * @license http://www.gnu.org/licenses/gpl-2.0.html + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ if(!current_user_can('manage_statz')) { die('Zugriff verweigert'); } - + +include_once plugin_dir_path(__FILE__).'includes/pChart/class/pData.class.php'; +include_once plugin_dir_path(__FILE__).'includes/pChart/class/pDraw.class.php'; +include_once plugin_dir_path(__FILE__).'includes/pChart/class/pImage.class.php'; ### AKTUELL - Funktionen function sem_showWhoIsOnline() { @@ -96,37 +129,40 @@ if(!current_user_can('manage_statz')) { return; } - foreach ($results as $result) { - $visitors[] = $result->visitors; - $hours[] = mysql2date('H', $result->hours); - } - - $maxvalue = max($visitors); - $visitors = implode(',', $visitors); - $hours = "|".implode('|', $hours)."|"; - - $charturl = "http://chart.apis.google.com/chart?"; - $chartsize = "chs=600x150&"; - $charttype = "cht=bvs&"; - $chartgrid = "chg=25,25&"; - $chartdata = "chd=t:".$visitors."&"; - $chartminmax = "chds=0,".$maxvalue."&"; - $barsize = "chbh=a&"; - $axis = "chxt=x,y&"; - $axisdataX = "chxl=0:".$hours; - $axisdataY = "1:|0|".$maxvalue."&"; - $datalabels = "chm=N,000000,0,-1,10"; - - $chart = $charturl.$chartsize.$charttype.$chartgrid.$chartdata.$chartminmax.$barsize.$axis.$axisdataX.$axisdataY.$datalabels; - - print "
"; - - print "Chart nicht verfügbar"; - - print "
"; - print ""; - print "
"; - } + foreach ($results as $result) { + $visitors[] = $result->visitors; + $hours[] = mysql2date('H', $result->hours); + } + + $MyData = new pData(); + $MyData->addPoints($visitors,"Visitors"); + $MyData->setAxisName(0,"Visitors"); + $MyData->addPoints($hours,"Hours"); + $MyData->setAbscissa("Hours"); + + $myPicture = new pImage(780,150,$MyData); + $myPicture->Antialias = FALSE; + $myPicture->drawRectangle(0,0,779,149,array("R"=>0,"G"=>0,"B"=>0)); + $myPicture->setFontProperties(array("FontName"=>plugin_dir_path(__FILE__)."includes/pChart/fonts/Bedizen.ttf","FontSize"=>8)); + $myPicture->setGraphArea(30,20,760,130); + $scaleSettings = array("GridR"=>200,"GridG"=>200,"GridB"=>200); + $myPicture->drawScale($scaleSettings); + $myPicture->drawBarChart(); + @$myPicture->Render(WP_CONTENT_DIR."/cache/24HourGoo.png"); + + print "
"; + + if(is_readable(WP_CONTENT_DIR."/cache/24HourGoo.png")) { + print ''; + } else if(!is_dir(WP_CONTENT_DIR."/cache")) { + print semr_i18n('No Chart: Cannot find cache-folder!'); + } else if(!is_writable(WP_CONTENT_DIR."/cache")) { + print semr_i18n('No Chart: Missing rights for cache-folder!'); + } + print "
"; + print ""; + print "
"; +} function sem_showDailyStatz() { global $wpdb; diff --git a/trunk/semmelstatzR-templates.php b/trunk/semmelstatzR-templates.php index 8097a63..5361a3a 100644 --- a/trunk/semmelstatzR-templates.php +++ b/trunk/semmelstatzR-templates.php @@ -2,18 +2,48 @@ /** * file semmelstatzR_templates.php * - * @package SemmelstatzR - * @version $Rev$ - * @author Ortwin Pinke - * @author Andreas 'Redunzl' Mueller - * @copyright (c)2011 PHP-Backoffice - * @copyright (c)2005-2009 kopfhoch-studio - * @link http://www.php-backoffice.de/projects/semmelstatzR - * @link http://sourceforge.net/projects/semmelstatz/ - * @license http://www.gnu.org/licenses/gpl-2.0.html + * @package SemmelstatzR + * @version $Rev$ + * @since 1.0.0 Beta + * @author SEM-Team + * @copyright (c)2011 SEM-Team + * @link http://sourceforge.net/projects/semmelstatz/ + * @license http://www.gnu.org/licenses/gpl-3.0.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * * $Id$ + * */ +/** + * based upon semmelstatz + * Copyright (c) 2005-2009 Andreas 'Redunzl' Mueller (redunzl@gmx.de) + * + * @license http://www.gnu.org/licenses/gpl-2.0.html + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ if(!current_user_can('manage_statz')) { die('Zugriff verweigert'); diff --git a/trunk/semmelstatzR.php b/trunk/semmelstatzR.php index 875f6ef..0c9bef0 100644 --- a/trunk/semmelstatzR.php +++ b/trunk/semmelstatzR.php @@ -12,14 +12,13 @@ License URI: http://www.gnu.org/licenses/gpl-3.0.html /** * file semmelstatzR.php * - * @package SemmelstatzR - * @version $Rev$ - * @author Ortwin Pinke - * @author Andreas 'Redunzl' Mueller - * @copyright (c)2011 SEM-Team - * @copyright (c)2005-2009 kopfhoch-studio - * @link http://sourceforge.net/projects/semmelstatz/ - * @license http://www.gnu.org/licenses/gpl-3.0.html + * @package SemmelstatzR + * @version $Rev$ + * @since 1.0.0 Beta + * @author SEM-Team + * @copyright (c)2011 SEM-Team + * @link http://sourceforge.net/projects/semmelstatz/ + * @license http://www.gnu.org/licenses/gpl-3.0.html * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/trunk/semmelstatzR_startup.php b/trunk/semmelstatzR_startup.php index 734e67b..e6ff8d3 100644 --- a/trunk/semmelstatzR_startup.php +++ b/trunk/semmelstatzR_startup.php @@ -2,17 +2,48 @@ /** * file semmelstatzR_startup.php * - * @package SemmelstatzR - * @version $Rev$ - * @author Ortwin Pinke - * @author Andreas 'Redunzl' Mueller - * @copyright (c)2011 PHP-Backoffice - * @copyright (c)2005-2009 kopfhoch-studio - * @link http://sourceforge.net/projects/semmelstatz/ - * @license http://www.gnu.org/licenses/gpl-2.0.html + * @package SemmelstatzR + * @version $Rev$ + * @since 1.0.0 Beta + * @author SEM-Team + * @copyright (c)2011 SEM-Team + * @link http://sourceforge.net/projects/semmelstatz/ + * @license http://www.gnu.org/licenses/gpl-3.0.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * * $Id$ + * */ +/** + * based upon semmelstatz + * Copyright (c) 2005-2009 Andreas 'Redunzl' Mueller (redunzl@gmx.de) + * + * @license http://www.gnu.org/licenses/gpl-2.0.html + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ ### constants define('SEMMELSTATZR_VERSION', '1.0.0 Beta'); define('SEMMELSTATZR_SRVPATH', dirname(__FILE__)); diff --git a/trunk/semr_image.php b/trunk/semr_image.php index a9372f5..39aa268 100644 --- a/trunk/semr_image.php +++ b/trunk/semr_image.php @@ -2,21 +2,35 @@ /** * file semr_image.php * - * @package SemmelstatzR - * @version $Rev$ - * @author Ortwin Pinke - * @author Andreas 'Redunzl' Mueller - * @copyright (c)2011 PHP-Backoffice - * @copyright (c)2005-2009 kopfhoch-studio - * @link http://www.php-backoffice.de/projects/semmelstatzR - * @link http://sourceforge.net/projects/semmelstatz/ - * @license http://www.gnu.org/licenses/gpl-2.0.html + * @package SemmelstatzR + * @version $Rev$ + * @since 1.0.0 Beta + * @author SEM-Team + * @copyright (c)2011 SEM-Team + * @link http://sourceforge.net/projects/semmelstatz/ + * @license http://www.gnu.org/licenses/gpl-3.0.html + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * * $Id$ - * + * + */ +/** + * based upon semmelstatz * Copyright (c) 2005-2009 Andreas 'Redunzl' Mueller (redunzl@gmx.de) - * Copyright (c) 2011- Ortwin Pinke (info@php-backoffice.de) - * + * + * @license http://www.gnu.org/licenses/gpl-2.0.html * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License (version 2) as * published by the Free Software Foundation. @@ -30,7 +44,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - /** * security fix */ diff --git a/trunk/test/agents.php b/trunk/test/agents.php new file mode 100644 index 0000000..ac913cb --- /dev/null +++ b/trunk/test/agents.php @@ -0,0 +1,5 @@ + \ No newline at end of file
checked="checked" />

K`* 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 literal 0 HcmV?d00001 diff --git a/trunk/includes/pChart/fonts/verdana.ttf b/trunk/includes/pChart/fonts/verdana.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5a059d23c476d9d68d190136ec8cfccd5221310d GIT binary patch literal 189144 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%0D`usD|`Qc4B$QCB_3T&hD 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