├── AUTHORS.txt ├── LICENSE.txt ├── README.md ├── data └── 2010-01-10.xml ├── mapgenerator ├── img │ ├── LICENSE.txt │ ├── bg.png │ ├── locked.png │ ├── locked.svg │ ├── marker-few-open.png │ ├── marker-few.png │ ├── marker-few.svg │ ├── marker-many-open.png │ ├── marker-many.png │ ├── marker-many.svg │ ├── marker-open.png │ ├── marker.png │ ├── marker.svg │ ├── wifi.png │ └── wifi.svg ├── mapgenerator.py └── scripts │ ├── MIT-LICENSE │ ├── bluff-min.js │ ├── bluff-src.js │ ├── excanvas.js │ └── js-class.js ├── results ├── bg.png ├── bluff-min.js ├── excanvas.js ├── index.html ├── js-class.js ├── locked.png ├── marker-few-open.png ├── marker-few.png ├── marker-many-open.png ├── marker-many.png ├── marker-open.png ├── marker.png └── wifi.png └── scanner ├── locked.png ├── unlocked.png ├── wifiScanner.py └── wnmc.glade /AUTHORS.txt: -------------------------------------------------------------------------------- 1 | Δόβα Φιλία (Dova Filia) 2 | Μίγδος Γεώργιος (Migdos George) 3 | 4 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WifiScanAndMap 2 | ============== 3 | 4 | A simple 802.11 mapping application for Linux written in Python. 5 | 6 | Url 7 | --- 8 | 9 | * [http://gmigdos.wordpress.com/2010/04/04/wifiscanandmap-a-wifi-mapping-application-for-linux/](http://gmigdos.wordpress.com/2010/04/04/wifiscanandmap-a-wifi-mapping-application-for-linux/) 10 | 11 | Authors 12 | ------- 13 | 14 | * Δόβα Φιλία (Dova Filia) 15 | * Μίγδος Γεώργιος (Migdos George) 16 | 17 | License 18 | ------- 19 | 20 | * The source code is available under the [Apache v2.0 license](http://www.apache.org/licenses/LICENSE-2.0.html). 21 | * The artwork is available under the [Creative Commons Attribution-Share Alike 3.0 Unported license](http://creativecommons.org/licenses/by-sa/3.0/). 22 | * The 3rd party [Bluff Javascript library](http://bluff.jcoglan.com/) is available under the [MIT license](http://www.opensource.org/licenses/mit-license.php). 23 | 24 | Description 25 | ----------- 26 | 27 | WiFiScanAndMap is a Python WiFi mapping application for Linux. 28 | 29 | You can use it to scan areas for wireless networks, collect information about them and then generate a web page displaying these information on a map. 30 | 31 | 32 | The application was created as an assignment for the “Wireless Networks And Mobile Communcations” course at the Computer Science Department of the Athens University Of Economics And Business, by: 33 | 34 | * Filia Dova 35 | * Georgios Migdos 36 | 37 | 38 | The application consists of two programs, the scanner and the map generator. 39 | 40 | The user runs the scanner on a mobile device (laptop/netbook) which collects information about the wireless networks within range. The program relies on `iwlist` output for the scanning process. After the user is done, they can save the collected information as an XML file. 41 | 42 | The scanner can be run as a GTK+ application or as a command line application (with the `–no-gui` parameter). 43 | 44 | This process can be repeated any number of times, resulting in a number of XML files. These XML files are used as the input of the map generator program which parses the XML files and produces an HTML web page. 45 | 46 | 47 | 48 | The map data used is obtained from OpenStreetMap and the tiles are from Yahoo! Maps. The graph is displayed using the Bluff Javascript library. 49 | 50 | 51 | 52 | Requirements 53 | ------------ 54 | 55 | To run the scanner you need: 56 | 57 | * A Linux system with wireless tools for Linux installed 58 | * Wireless card supporting scanning 59 | * GPS receiver 60 | * Python 2.6.4 61 | * gpsd (+python bindings) 62 | * PyGTK+ 2.16 (if you want to use the GUI) 63 | 64 | To display the map you need: 65 | 66 | * A web browser supporting CSS with Javascript enabled 67 | * An active internet connection 68 | 69 | 70 | Usage 71 | ----- 72 | 73 | You can run the scanner (GTK+ GUI) with the command : 74 | 75 | python scanner/scanner.py 76 | 77 | You can run the scanner (GTK+ GUI) with the command : 78 | 79 | python scanner/scanner.py –no-gui 80 | 81 | You can run the map generator with the command: 82 | 83 | python mapgenerator/mapgenerator.py 84 | 85 | where: 86 | 87 | * `` and `` are the geographic coordinates of the resulting map’s original center 88 | * `` is the directory where the result files will be saved 89 | * `` `` … `` are the XML files generated by the scanner. 90 | 91 | -------------------------------------------------------------------------------- /mapgenerator/img/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The artwork in this directory is available under the Creative Commons Attribution-Share Alike 3.0 Unported license (http://creativecommons.org/licenses/by-sa/3.0/). 2 | 3 | Copyright 2010 Georgios Migdos. 4 | -------------------------------------------------------------------------------- /mapgenerator/img/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/mapgenerator/img/bg.png -------------------------------------------------------------------------------- /mapgenerator/img/locked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/mapgenerator/img/locked.png -------------------------------------------------------------------------------- /mapgenerator/img/locked.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 23 | 27 | 31 | 35 | 39 | 40 | 42 | 46 | 50 | 54 | 55 | 62 | 71 | 72 | 91 | 93 | 94 | 96 | image/svg+xml 97 | 99 | 100 | 101 | 102 | 103 | 108 | 117 | 120 | 130 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /mapgenerator/img/marker-few-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/mapgenerator/img/marker-few-open.png -------------------------------------------------------------------------------- /mapgenerator/img/marker-few.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/mapgenerator/img/marker-few.png -------------------------------------------------------------------------------- /mapgenerator/img/marker-few.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 24 | 26 | 28 | 32 | 36 | 37 | 40 | 44 | 48 | 49 | 51 | 55 | 59 | 63 | 67 | 68 | 70 | 74 | 78 | 79 | 86 | 93 | 102 | 112 | 122 | 132 | 141 | 152 | 161 | 169 | 173 | 174 | 175 | 197 | 199 | 200 | 202 | image/svg+xml 203 | 205 | 206 | 207 | 208 | 209 | 214 | 220 | 230 | 246 | 247 | 248 | -------------------------------------------------------------------------------- /mapgenerator/img/marker-many-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/mapgenerator/img/marker-many-open.png -------------------------------------------------------------------------------- /mapgenerator/img/marker-many.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/mapgenerator/img/marker-many.png -------------------------------------------------------------------------------- /mapgenerator/img/marker-many.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 24 | 26 | 28 | 32 | 36 | 37 | 40 | 44 | 48 | 49 | 51 | 55 | 59 | 63 | 67 | 68 | 70 | 74 | 78 | 79 | 86 | 93 | 102 | 112 | 122 | 132 | 141 | 152 | 161 | 169 | 173 | 174 | 175 | 197 | 199 | 200 | 202 | image/svg+xml 203 | 205 | 206 | 207 | 208 | 209 | 214 | 220 | 230 | 246 | 247 | 248 | -------------------------------------------------------------------------------- /mapgenerator/img/marker-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/mapgenerator/img/marker-open.png -------------------------------------------------------------------------------- /mapgenerator/img/marker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/mapgenerator/img/marker.png -------------------------------------------------------------------------------- /mapgenerator/img/marker.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 24 | 26 | 28 | 32 | 36 | 37 | 40 | 44 | 48 | 49 | 51 | 55 | 59 | 63 | 67 | 68 | 70 | 74 | 78 | 79 | 86 | 93 | 102 | 112 | 122 | 132 | 141 | 152 | 161 | 169 | 173 | 174 | 175 | 197 | 199 | 200 | 202 | image/svg+xml 203 | 205 | 206 | 207 | 208 | 209 | 214 | 220 | 230 | 246 | 247 | 248 | -------------------------------------------------------------------------------- /mapgenerator/img/wifi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/mapgenerator/img/wifi.png -------------------------------------------------------------------------------- /mapgenerator/img/wifi.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 24 | 26 | 30 | 34 | 35 | 42 | 51 | 60 | 69 | 78 | 79 | 98 | 100 | 101 | 103 | image/svg+xml 104 | 106 | 107 | 108 | 109 | 110 | 115 | 120 | 130 | 135 | 140 | 145 | 150 | 156 | 161 | 166 | 171 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /mapgenerator/mapgenerator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -*- 3 | 4 | ''' 5 | Copyright 2010 Filia Dova, Georgios Migdos 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | ''' 19 | 20 | from xml.dom.minidom import parse 21 | import os 22 | import sys 23 | import shutil 24 | import math 25 | 26 | class MapGenerator: 27 | 28 | def parseXMLFile(self, XMLFilename, outputDictionary, referenceDictionary): 29 | dom = parse(XMLFilename) 30 | for network in dom.getElementsByTagName('network'): 31 | latitude = "" 32 | longtitude = "" 33 | essid = "" 34 | channel = "" 35 | quality = "" 36 | qualityNum = 0 37 | security = "" 38 | address = "" 39 | frequency = "" 40 | signal = "" 41 | noise = "" 42 | for lat in network.getElementsByTagName('latitude'): 43 | if(len(lat.childNodes)>0): 44 | latitude = lat.childNodes[0].nodeValue 45 | for lon in network.getElementsByTagName('longtitude'): 46 | if(len(lon.childNodes)>0): 47 | longtitude = lon.childNodes[0].nodeValue 48 | for ssid in network.getElementsByTagName('essid'): 49 | if(len(ssid.childNodes)>0): 50 | essid = ssid.childNodes[0].nodeValue 51 | for chan in network.getElementsByTagName('channel'): 52 | if(len(chan.childNodes)>0): 53 | channel = chan.childNodes[0].nodeValue 54 | for qual in network.getElementsByTagName('quality'): 55 | if(len(qual.childNodes)>0): 56 | qualityNum = eval(qual.childNodes[0].nodeValue)*100 57 | quality = str(qualityNum)+"%" 58 | for sec in network.getElementsByTagName('security'): 59 | if(len(sec.childNodes)>0): 60 | security = sec.childNodes[0].nodeValue 61 | for mac in network.getElementsByTagName('address'): 62 | if(len(mac.childNodes)>0): 63 | address = mac.childNodes[0].nodeValue 64 | for freq in network.getElementsByTagName('frequency'): 65 | if(len(freq.childNodes)>0): 66 | frequency = freq.childNodes[0].nodeValue 67 | for sig in network.getElementsByTagName('signal'): 68 | if(len(sig.childNodes)>0): 69 | signal = sig.childNodes[0].nodeValue 70 | for nois in network.getElementsByTagName('noise'): 71 | if(len(nois.childNodes)>0): 72 | noise = nois.childNodes[0].nodeValue 73 | 74 | referenceKey = essid+":"+address 75 | newReferenceEntry = [essid, address, qualityNum] 76 | key = latitude+","+longtitude 77 | entry = [essid, channel, quality, security, address, frequency, signal, noise] 78 | 79 | try: 80 | referenceEntry = referenceDictionary[referenceKey] 81 | if(referenceEntry[2] 151 | 152 | 153 | 154 | WNMC 155 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | \n\n''' 295 | outputFile.write(tempStr.encode('utf-8')) 296 | tempStr = ''' 297 | 298 | 299 |
\n\n''' 300 | outputFile.write(tempStr.encode('utf-8')) 301 | stats = Stats(50, inputXMLFilesList).getStats() 302 | tempStr = ''' 303 |
304 |
305 |
306 |
307 | marker 308 | : 1 WN 309 | marker-few 310 | : 2-4 WNs 311 | marker-many 312 | : >4 WNs 313 |
314 |
315 |
316 |
317 |
318 |
319 | Networks: '''+ str(stats[0]) + " - Open: "+ str(stats[2]) +''' 320 |
321 |
322 |
323 |
324 |
325 |
326 | Access Points / Channel 327 |
328 | 329 |
330 | 331 |
332 |
333 |
334 |
335 | 336 | 358 | ''' 359 | outputFile.write(tempStr.encode('utf-8')) 360 | 361 | tempStr = ''' 362 | ''' 363 | outputFile.write(tempStr.encode('utf-8')) 364 | outputFile.close() 365 | 366 | 367 | class Stats: 368 | 369 | def __init__(self, minDistance, XMLFilenames): 370 | self.clear() 371 | for fname in XMLFilenames: 372 | self.parseXMLFile(fname) 373 | self.runStats(minDistance) 374 | 375 | def clear(self): 376 | self.networks = [] 377 | self.total = 0 378 | self.totalOpen = 0 379 | self.channelsCounter = [0,0,0,0,0,0,0,0,0,0,0] 380 | 381 | def getStats(self): 382 | return self.total, self.channelsCounter, self.totalOpen 383 | 384 | def getNetworksList(self): 385 | return self.networks 386 | 387 | def parseXMLFile(self, XMLFilename): 388 | dom = parse(XMLFilename) 389 | for network in dom.getElementsByTagName('network'): 390 | latitude = "" 391 | longtitude = "" 392 | essid = "" 393 | channel = "" 394 | quality = "" 395 | security = "" 396 | address = "" 397 | frequency = "" 398 | signal = "" 399 | noise = "" 400 | for lat in network.getElementsByTagName('latitude'): 401 | if(len(lat.childNodes)>0): 402 | latitude = lat.childNodes[0].nodeValue 403 | for lon in network.getElementsByTagName('longtitude'): 404 | if(len(lon.childNodes)>0): 405 | longtitude = lon.childNodes[0].nodeValue 406 | for ssid in network.getElementsByTagName('essid'): 407 | if(len(ssid.childNodes)>0): 408 | essid = ssid.childNodes[0].nodeValue 409 | for chan in network.getElementsByTagName('channel'): 410 | if(len(chan.childNodes)>0): 411 | channel = chan.childNodes[0].nodeValue 412 | for qual in network.getElementsByTagName('quality'): 413 | if(len(qual.childNodes)>0): 414 | quality = str(eval(qual.childNodes[0].nodeValue)*100)+"%" 415 | for sec in network.getElementsByTagName('security'): 416 | if(len(sec.childNodes)>0): 417 | security = sec.childNodes[0].nodeValue 418 | for mac in network.getElementsByTagName('address'): 419 | if(len(mac.childNodes)>0): 420 | address = mac.childNodes[0].nodeValue 421 | for freq in network.getElementsByTagName('frequency'): 422 | if(len(freq.childNodes)>0): 423 | frequency = freq.childNodes[0].nodeValue 424 | for sig in network.getElementsByTagName('signal'): 425 | if(len(sig.childNodes)>0): 426 | signal = sig.childNodes[0].nodeValue 427 | for nois in network.getElementsByTagName('noise'): 428 | if(len(nois.childNodes)>0): 429 | noise = nois.childNodes[0].nodeValue 430 | 431 | entry = [essid, int(channel), quality, security, address, frequency, signal, noise, float(latitude), float(longtitude)] 432 | self.networks.append(entry) 433 | 434 | 435 | def runStats(self, minDistance): 436 | self.channelsCounter = [0,0,0,0,0,0,0,0,0,0,0,0,0,0] 437 | self.total = len(self.networks) 438 | for network in self.networks: 439 | chn = network[1] 440 | self.channelsCounter[chn-1] = self.channelsCounter[chn-1]+1 441 | if(network[3]!="on"): 442 | self.totalOpen += 1 443 | 444 | def calculate_distance(self, lat1, lon1, lat2, lon2): 445 | ''' 446 | * Calculates the distance between two points given their (lat, lon) co-ordinates. 447 | * It uses the Spherical Law Of Cosines (http://en.wikipedia.org/wiki/Spherical_law_of_cosines): 448 | * 449 | * cos(c) = cos(a) * cos(b) + sin(a) * sin(b) * cos(C) (1) 450 | * 451 | * In this case: 452 | * a = lat1 in radians, b = lat2 in radians, C = (lon2 - lon1) in radians 453 | * and because the latitude range is [-π/2, π/2] instead of [0, π] 454 | * and the longitude range is [-π, π] instead of [0, 2π] 455 | * (1) transforms into: 456 | * 457 | * x = cos(c) = sin(a) * sin(b) + cos(a) * cos(b) * cos(C) 458 | * 459 | * Finally the distance is arccos(x) 460 | ''' 461 | 462 | if ((lat1 == lat2) and (lon1 == lon2)): 463 | return 0 464 | 465 | try: 466 | delta = lon2 - lon1 467 | a = math.radians(lat1) 468 | b = math.radians(lat2) 469 | C = math.radians(delta) 470 | x = math.sin(a) * math.sin(b) + math.cos(a) * math.cos(b) * math.cos(C) 471 | distance = math.acos(x) # in radians 472 | distance = math.degrees(distance) # in degrees 473 | distance = distance * 60 # 60 nautical miles / lat degree 474 | distance = distance * 1852 # conversion to meters 475 | distance = round(distance) 476 | return distance; 477 | except: 478 | return 0 479 | 480 | 481 | if(len(sys.argv)<5): 482 | print "Usage:\n\tpython mapgenerator.py \n" 483 | print "\tlongtitude:\tThe longtitude of the default center of the map." 484 | print "\tlatitude:\tThe latitude of the default center of the map." 485 | print "\toutput_dir:\tThe location where the resulting html file and images will be saved." 486 | print "\tinput_files:\tThe XML files that were generated by the scanner application.\n" 487 | else: 488 | generator = MapGenerator() 489 | #lon="23.70823" 490 | #lat="37.97009" 491 | generator.generateOpenStreetMapsMap(sys.argv[3], sys.argv[4:], sys.argv[1], sys.argv[2]) 492 | 493 | -------------------------------------------------------------------------------- /mapgenerator/scripts/MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Bluff -- Beautiful graphs in JavaScript 2 | http://bluff.jcoglan.com 3 | 4 | Copyright (c) 2008-2009 James Coglan 5 | 6 | Original Ruby version (c) 2005-2009 Topfunky Corporation boss@topfunky.com 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /mapgenerator/scripts/bluff-min.js: -------------------------------------------------------------------------------- 1 | Bluff={VERSION:'0.3.6',array:function(c){if(c.length===undefined)return[c];var d=[],f=c.length;while(f--)d[f]=c[f];return d},array_new:function(c,d){var f=[];while(c--)f.push(d);return f},each:function(c,d,f){for(var g=0,h=c.length;gthis._5)?g.length:this._5;Bluff.each(g,function(c,d){if(c===undefined)return;if(this.maximum_value===null&&this.minimum_value===null)this.maximum_value=this.minimum_value=c;this.maximum_value=this._1f(c)?c:this.maximum_value;if(this.maximum_value>=0)this._a=true;this.minimum_value=this._1A(c)?c:this.minimum_value;if(this.minimum_value<0)this._a=true},this)},draw:function(){if(this.stacked)this._1B();this._1C();this._u(function(){this._0.rectangle(this.left_margin,this.top_margin,this._d-this.right_margin,this._L-this.bottom_margin);this._0.rectangle(this._1,this._7,this._l,this._g)})},clear:function(){this._X()},_1C:function(){if(!this._a)return this._1D();this._13();this._1E();if(this.sort)this._1F();this._1G();this._M();this._1H();this._1I()},_13:function(g){if(this._9===null||g===true){this._9=[];if(!this._a)return;this._1g();Bluff.each(this._2,function(d){var f=[];Bluff.each(d[this.klass.DATA_VALUES_INDEX],function(c){if(c===null||c===undefined)f.push(null);else f.push((c-this.minimum_value)/this._i)},this);this._9.push([d[this.klass.DATA_LABEL_INDEX],f,d[this.klass.DATA_COLOR_INDEX]])},this)}},_1g:function(){this._i=this.maximum_value-this.minimum_value;this._i=this._i>0?this._i:1;this._1h=100/Math.pow(10,Math.round(Math.LOG10E*Math.log(this._i)))},_1E:function(){this._N=this.hide_line_markers?0:this._D(this.marker_font_size);this._1i=this.hide_title?0:this._D(this.title_font_size);this._1j=this.hide_legend?0:this._D(this.legend_font_size);var c,d,f,g,h,i,j;if(this.hide_line_markers){this._1=this.left_margin;this._14=this.right_margin;this._1k=this.bottom_margin}else{d=0;if(this.has_left_labels){c='';for(j in this.labels){c=c.length>this.labels[j].length?c:this.labels[j]}d=this._O(this.marker_font_size,c)*1.25}else{d=this._O(this.marker_font_size,this._15(this.maximum_value))}f=this.hide_line_numbers&&!this.has_left_labels?0.0:d+this.klass.LABEL_MARGIN*2;this._1=this.left_margin+f+(this.y_axis_label===null?0.0:this._N+this.klass.LABEL_MARGIN*2);g=-Infinity;for(j in this.labels)g=g>Number(j)?g:Number(j);g=Math.round(g);h=(g>=(this._5-1)&&this.center_labels_over_point)?this._O(this.marker_font_size,this.labels[g])/2:0;this._14=this.right_margin+h;this._1k=this.bottom_margin+this._N+this.klass.LABEL_MARGIN}this._l=this._d-this._14;this._6=this._d-this._1-this._14;this._7=this.top_margin+(this.hide_title?this.title_margin:this._1i+this.title_margin)+(this.hide_legend?this.legend_margin:this._1j+this.legend_margin);i=(this.x_axis_label===null)?0.0:this._N+this.klass.LABEL_MARGIN;this._g=this._L-this._1k-i;this._3=this._g-this._7},_1H:function(){if(this.x_axis_label){var c=this._g+this.klass.LABEL_MARGIN*2+this._N;this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.pointsize=this._e(this.marker_font_size);this._0.gravity='north';this._0.annotate_scaled(this._d,1.0,0.0,c,this.x_axis_label,this._b);this._u(function(){this._0.line(0.0,c,this._d,c)})}},_M:function(){if(this.hide_line_markers)return;if(this.y_axis_increment===null){if(this.marker_count===null){Bluff.each([3,4,5,6,7],function(c){if(!this.marker_count&&this._i%c===0)this.marker_count=c},this);this.marker_count=this.marker_count||4}this._16=(this._i>0)?this._17(this._i/this.marker_count):1}else{this.maximum_value=Math.max(Math.ceil(this.maximum_value),this.y_axis_increment);this.minimum_value=Math.floor(this.minimum_value);this._1g();this._13(true);this.marker_count=Math.round(this._i/this.y_axis_increment);this._16=this.y_axis_increment}this._1J=this._3/(this._i/this._16);var d,f,g,h;for(d=0,f=this.marker_count;d<=f;d++){g=this._7+this._3-d*this._1J;this._0.stroke=this.marker_color;this._0.stroke_width=1;this._0.line(this._1,g,this._l,g);h=d*this._16+this.minimum_value;if(!this.hide_line_numbers){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.font_weight='normal';this._0.stroke='transparent';this._0.pointsize=this._e(this.marker_font_size);this._0.gravity='east';this._0.annotate_scaled(this._1-this.klass.LABEL_MARGIN,1.0,0.0,g,this._15(h),this._b)}}},_1l:function(c){return(this._d-c)/2},_1G:function(){if(this.hide_legend)return;this._P=Bluff.map(this._2,function(c){return c[this.klass.DATA_LABEL_INDEX]},this);var i=this.legend_box_size;if(this.font)this._0.font=this.font;this._0.pointsize=this.legend_font_size;var j=[[]];Bluff.each(this._P,function(c){var d=j.length-1;var f=this._0.get_type_metrics(c);var g=f.width+i*2.7;j[d].push(g);if(Bluff.sum(j[d])>(this._d*0.9))j.push([j[d].pop()])},this);var k=this._1l(Bluff.sum(j[0]));var l=this.hide_title?this.top_margin+this.title_margin:this.top_margin+this.title_margin+this._1i;this._u(function(){this._0.stroke_width=1;this._0.line(0,l,this._d,l)});Bluff.each(this._P,function(c,d){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._e(this.legend_font_size);this._0.stroke='transparent';this._0.font_weight='normal';this._0.gravity='west';this._0.annotate_scaled(this._d,1.0,k+(i*1.7),l,c,this._b);this._0.stroke='transparent';this._0.fill=this._2[d][this.klass.DATA_COLOR_INDEX];this._0.rectangle(k,l-i/2.0,k+i,l+i/2.0);this._0.pointsize=this.legend_font_size;var f=this._0.get_type_metrics(c);var g=f.width+(i*2.7),h;j[0].shift();if(j[0].length==0){this._u(function(){this._0.line(0.0,l,this._d,l)});j.shift();if(j.length>0)k=this._1l(Bluff.sum(j[0]));h=Math.max(this._1j,i)+this.legend_margin;if(j.length>0){l+=h;this._7+=h;this._3=this._g-this._7}}else{k+=g}},this);this._m=0},_1I:function(){if(this.hide_title||!this.title)return;this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._e(this.title_font_size);this._0.font_weight='bold';this._0.gravity='north';this._0.annotate_scaled(this._d,1.0,0,this.top_margin,this.title,this._b)},_c:function(c,d){if(this.hide_line_markers)return;var f;if(this.labels[d]&&!this._q[d]){f=this._g+this.klass.LABEL_MARGIN;this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.font_weight='normal';this._0.pointsize=this._e(this.marker_font_size);this._0.gravity='north';this._0.annotate_scaled(1.0,1.0,c,f,this.labels[d],this._b);this._q[d]=true;this._u(function(){this._0.stroke_width=1;this._0.line(0.0,f,this._d,f)})}},_E:function(c,d,f,g,h,i,j){if(!this.tooltips)return;this._0.tooltip(c,d,f,g,h,i,j)},_1D:function(){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.font_weight='normal';this._0.pointsize=this._e(80);this._0.gravity='center';this._0.annotate_scaled(this._d,this._L/2,0,10,this.no_data_message,this._b)},_X:function(){var c=this._k.background_colors;switch(true){case c instanceof Array:this._1K.apply(this,c);break;case typeof c==='string':this._1L(c);break;default:this._1M(this._k.background_image);break}},_1L:function(c){this._0.render_solid_background(this._j,this._y,c)},_1K:function(c,d){this._0.render_gradiated_background(this._j,this._y,c,d)},_1M:function(c){},_1e:function(){this._m=0;this._q={};this._k={};this._0.scale(this._b,this._b)},_2a:function(c){return this._b*c},_e:function(c){var d=c*this._b;return d},_Q:function(c,d){return(c>d)?d:c},_1f:function(c,d){return c>this.maximum_value},_1A:function(c,d){return c100){c/=10;d*=10}return Math.floor(c)*d},_1F:function(){var f=this._1N,g=this.klass.DATA_VALUES_INDEX;this._9.sort(function(c,d){return f(d[g])-f(c[g])});this._2.sort(function(c,d){return f(d[g])-f(c[g])})},_1N:function(d){var f=0;Bluff.each(d,function(c){f+=(c||0)});return f},_1B:function(){var g=[],h=this._5;while(h--)g[h]=0;Bluff.each(this._2,function(f){Bluff.each(f[this.klass.DATA_VALUES_INDEX],function(c,d){g[d]+=c},this);f[this.klass.DATA_VALUES_INDEX]=Bluff.array(g)},this)},_u:function(c){if(this.klass.DEBUG){this._0.fill='transparent';this._0.stroke='turquoise';c.call(this)}},_1z:function(){if(this._m0&&k>0){i.push(f);i.push(g)}else{i.push(this._1);i.push(this._g-1);i.push(f);i.push(g)}this._c(f,d);j=f;k=g},this);i.push(this._l);i.push(this._g-1);i.push(this._1);i.push(this._g-1);this._0.fill=h[this.klass.DATA_COLOR_INDEX];this._0.polyline(i)},this)}});Bluff.BarConversion=new JS.Class({mode:null,zero:null,graph_top:null,graph_height:null,minimum_value:null,spread:null,getLeftYRightYscaled:function(c,d){var f;switch(this.mode){case 1:d[0]=this.graph_top+this.graph_height*(1-c)+1;d[1]=this.graph_top+this.graph_height-1;break;case 2:d[0]=this.graph_top+1;d[1]=this.graph_top+this.graph_height*(1-c)-1;break;case 3:f=c-this.minimum_value/this.spread;if(c>=this.zero){d[0]=this.graph_top+this.graph_height*(1-(f-this.zero))+1;d[1]=this.graph_top+this.graph_height*(1-this.zero)-1}else{d[0]=this.graph_top+this.graph_height*(1-(f-this.zero))+1;d[1]=this.graph_top+this.graph_height*(1-this.zero)-1}break;default:d[0]=0.0;d[1]=0.0}}});Bluff.Bar=new JS.Class(Bluff.Base,{bar_spacing:0.9,draw:function(){this.center_labels_over_point=(Bluff.keys(this.labels).length>this._5);this.callSuper();if(!this._a)return;this._1O()},_1O:function(){this._8=this._6/(this._5*this._2.length);var n=(this._8*(1-this.bar_spacing))/2;this._0.stroke_opacity=0.0;var m=new Bluff.BarConversion();m.graph_height=this._3;m.graph_top=this._7;if(this.minimum_value>=0){m.mode=1}else{if(this.maximum_value<=0){m.mode=2}else{m.mode=3;m.spread=this._i;m.minimum_value=this.minimum_value;m.zero=-this.minimum_value/this._i}}Bluff.each(this._9,function(j,k){var l=this._2[k][this.klass.DATA_VALUES_INDEX];Bluff.each(j[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._8*(k+d+((this._2.length-1)*d)))+n;var g=f+this._8*this.bar_spacing;var h=[];m.getLeftYRightYscaled(c,h);this._0.fill=j[this.klass.DATA_COLOR_INDEX];this._0.rectangle(f,h[0],g,h[1]);this._E(f,h[0],g-f,h[1]-h[0],j[this.klass.DATA_LABEL_INDEX],j[this.klass.DATA_COLOR_INDEX],l[d]);var i=this._1+(this._2.length*this._8*d)+(this._2.length*this._8/2.0);this._c(i-(this.center_labels_over_point?this._8/2.0:0.0),d)},this)},this);if(this.center_labels_over_point)this._c(this._l,this._5)}});Bluff.Line=new JS.Class(Bluff.Base,{baseline_value:null,baseline_color:null,line_width:null,dot_radius:null,hide_dots:null,hide_lines:null,initialize:function(c){if(arguments.length>3)throw'Wrong number of arguments';if(arguments.length===1||(typeof arguments[1]!=='number'&&typeof arguments[1]!=='string'))this.callSuper(c,null);else this.callSuper();this.hide_dots=this.hide_lines=false;this.baseline_color='red';this.baseline_value=null},draw:function(){this.callSuper();if(!this._a)return;this.x_increment=(this._5>1)?(this._6/(this._5-1)):this._6;var m;if(this._S!==undefined){m=this._7+(this._3-this._S*this._3);this._0.push();this._0.stroke=this.baseline_color;this._0.fill_opacity=0.0;this._0.stroke_width=3.0;this._0.line(this._1,m,this._1+this._6,m);this._0.pop()}Bluff.each(this._9,function(i,j){var k=null,l=null;var n=this._2[j][this.klass.DATA_VALUES_INDEX];this._1P=this._1Q(i);Bluff.each(i[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this.x_increment*d);if(typeof c!=='number')return;this._c(f,d);var g=this._7+(this._3-c*this._3);this._0.stroke=i[this.klass.DATA_COLOR_INDEX];this._0.fill=i[this.klass.DATA_COLOR_INDEX];this._0.stroke_opacity=1.0;this._0.stroke_width=this.line_width||this._Q(this._j/(this._9[0][this.klass.DATA_VALUES_INDEX].length*6),3.0);var h=this.dot_radius||this._Q(this._j/(this._9[0][this.klass.DATA_VALUES_INDEX].length*2),7.0);if(!this.hide_lines&&k!==null&&l!==null){this._0.line(k,l,f,g)}else if(this._1P){this._0.circle(f,g,f-h,g)}if(!this.hide_dots)this._0.circle(f,g,f-h,g);this._E(f-h,g-h,2*h,2*h,i[this.klass.DATA_LABEL_INDEX],i[this.klass.DATA_COLOR_INDEX],n[d]);k=f;l=g},this)},this)},_13:function(){this.maximum_value=Math.max(this.maximum_value,this.baseline_value);this.callSuper();if(this.baseline_value!==null)this._S=this.baseline_value/this.maximum_value},_1Q:function(d){var f=0;Bluff.each(d[this.klass.DATA_VALUES_INDEX],function(c){if(c!==undefined)f+=1});return f===1}});Bluff.Dot=new JS.Class(Bluff.Base,{draw:function(){this.has_left_labels=true;this.callSuper();if(!this._a)return;var k=1.0;this._F=this._3/this._5;this._18=this._F*k/this._9.length;this._0.stroke_opacity=0.0;var l=Bluff.array_new(this._5,0),n=Bluff.array_new(this._5,this._1),m=(this._F*(1-k))/2;Bluff.each(this._9,function(i,j){Bluff.each(i[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(c*this._6)-Math.round(this._18/6.0);var g=this._7+(this._F*d)+m+Math.round(this._18/2.0);if(j===0){this._0.stroke=this.marker_color;this._0.stroke_width=1.0;this._0.opacity=0.1;this._0.line(this._1,g,this._1+this._6,g)}this._0.fill=i[this.klass.DATA_COLOR_INDEX];this._0.stroke='transparent';this._0.circle(f,g,f+Math.round(this._18/3.0),g);var h=this._7+(this._F*d+this._F/2)+m;this._c(h,d)},this)},this)},_M:function(){if(this.hide_line_markers)return;this._0.stroke_antialias=false;this._0.stroke_width=1;var c=5;var d=this._17(this.maximum_value/c);for(var f=0;f<=c;f++){var g=(this._l-this._1)/c,h=this._l-(g*f)-1,i=f-c,j=Math.abs(i)*d;this._0.stroke=this.marker_color;this._0.line(h,this._g,h,this._g+0.5*this.klass.LABEL_MARGIN);if(!this.hide_line_numbers){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.pointsize=this._e(this.marker_font_size);this._0.gravity='center';this._0.annotate_scaled(0,0,h,this._g+(this.klass.LABEL_MARGIN*2.0),j,this._b)}this._0.stroke_antialias=true}},_c:function(c,d){if(this.labels[d]&&!this._q[d]){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.font_weight='normal';this._0.pointsize=this._e(this.marker_font_size);this._0.gravity='east';this._0.annotate_scaled(1,1,this._1-this.klass.LABEL_MARGIN*2.0,c,this.labels[d],this._b);this._q[d]=true}}});Bluff.Net=new JS.Class(Bluff.Base,{hide_dots:null,line_width:null,dot_radius:null,initialize:function(){this.callSuper();this.hide_dots=false;this.hide_line_numbers=true},draw:function(){this.callSuper();if(!this._a)return;this._v=this._3/2.0;this._w=this._1+(this._6/2.0);this._x=this._7+(this._3/2.0)-10;this._R=this._6/(this._5-1);var s=this.dot_radius||this._Q(this._j/(this._9[0][this.klass.DATA_VALUES_INDEX].length*2.5),7.0);this._0.stroke_opacity=1.0;this._0.stroke_width=this.line_width||this._Q(this._j/(this._9[0][this.klass.DATA_VALUES_INDEX].length*4),3.0);var r;if(this._S!==undefined){r=this._7+(this._3-this._S*this._3);this._0.push();this._0.stroke_color=this.baseline_color;this._0.fill_opacity=0.0;this._0.stroke_width=5;this._0.line(this._1,r,this._1+this._6,r);this._0.pop()}Bluff.each(this._9,function(o){var p=null,q=null;Bluff.each(o[this.klass.DATA_VALUES_INDEX],function(c,d){if(c===undefined)return;var f=d*Math.PI*2/this._5,g=c*this._v,h=this._w+Math.sin(f)*g,i=this._x-Math.cos(f)*g,j=(d+10){this._0.fill=c[this.klass.DATA_COLOR_INDEX];var f=(c[this.klass.DATA_VALUES_INDEX][0]/o)*360;this._0.circle(n,m,n+k,m,p,p+f+0.5);var g=p+((p+f)-p)/2,h=Math.round((c[this.klass.DATA_VALUES_INDEX][0]/o)*100.0),i;if(h>=this.hide_labels_less_than){i=this._15(c[this.klass.DATA_VALUES_INDEX][0]);this._c(n,m,g,k+(k*this.klass.TEXT_OFFSET_PERCENTAGE),i)}p+=f}},this)},_c:function(c,d,f,g,h){var i=20.0,j=c,k=d,l=g+i,n=l*0.15,m=j+((l+n)*Math.cos(f*Math.PI/180)),o=k+(l*Math.sin(f*Math.PI/180));this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._e(this.marker_font_size);this._0.font_weight='bold';this._0.gravity='center';this._0.annotate_scaled(0,0,m,o,h,this._b)},_1R:function(){var d=0;Bluff.each(this._2,function(c){d+=c[this.klass.DATA_VALUES_INDEX][0]},this);return d}});Bluff.SideBar=new JS.Class(Bluff.Base,{bar_spacing:0.9,draw:function(){this.has_left_labels=true;this.callSuper();if(!this._a)return;this._G=this._3/this._5;this._8=this._G*this.bar_spacing/this._9.length;this._0.stroke_opacity=0.0;var q=Bluff.array_new(this._5,0),s=Bluff.array_new(this._5,this._1),r=(this._G*(1-this.bar_spacing))/2;Bluff.each(this._9,function(m,o){var p=this._2[o][this.klass.DATA_VALUES_INDEX];Bluff.each(m[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._6-c*this._6-q[d]),g=this._1+this._6-q[d],h=g-f,i=s[d]-1,j=this._7+(this._G*d)+(this._8*o)+r,k=i+h,l=j+this._8;q[d]+=(c*this._6);this._0.stroke='transparent';this._0.fill=m[this.klass.DATA_COLOR_INDEX];this._0.rectangle(i,j,k,l);this._E(i,j,k-i,l-j,m[this.klass.DATA_LABEL_INDEX],m[this.klass.DATA_COLOR_INDEX],p[d]);var n=this._7+(this._G*d+this._G/2);this._c(n,d)},this)},this)},_M:function(){if(this.hide_line_markers)return;this._0.stroke_antialias=false;this._0.stroke_width=1;var c=5;var d=this._17(this.maximum_value/c),f,g,h,i;for(var j=0;j<=c;j++){f=(this._l-this._1)/c;g=this._l-(f*j)-1;h=j-c;i=Math.abs(h)*d;this._0.stroke=this.marker_color;this._0.line(g,this._g,g,this._7);if(!this.hide_line_numbers){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.pointsize=this._e(this.marker_font_size);this._0.gravity='center';this._0.annotate_scaled(0,0,g,this._g+(this.klass.LABEL_MARGIN*2.0),i,this._b)}}},_c:function(c,d){if(this.labels[d]&&!this._q[d]){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.font_weight='normal';this._0.pointsize=this._e(this.marker_font_size);this._0.gravity='east';this._0.annotate_scaled(1,1,this._1-this.klass.LABEL_MARGIN*2.0,c,this.labels[d],this._b);this._q[d]=true}}});Bluff.Spider=new JS.Class(Bluff.Base,{hide_text:null,hide_axes:null,transparent_background:null,initialize:function(c,d,f){this.callSuper(c,f);this._1S=d;this.hide_legend=true},draw:function(){this.hide_line_markers=true;this.callSuper();if(!this._a)return;var c=this._3,d=this._3/2.0,f=this._1+(this._6-c)/2.0,g=this._1+(this._6/2.0),h=this._7+(this._3/2.0)-25;this._1T=d/this._1S;var i=this._1U(),j=0.0,k=(2*Math.PI)/this._2.length,l=0.0;if(!this.hide_axes)this._1V(g,h,d,k);this._1W(g,h,k)},_1n:function(c){return c*this._1T},_c:function(c,d,f,g,h){var i=50,j=c,k=d+0,l=j+((g+i)*Math.cos(f)),n=k+((g+i)*Math.sin(f));this._0.fill=this.marker_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._e(this.legend_font_size);this._0.stroke='transparent';this._0.font_weight='bold';this._0.gravity='center';this._0.annotate_scaled(0,0,l,n,h,this._b)},_1V:function(g,h,i,j,k){if(this.hide_axes)return;var l=0.0;Bluff.each(this._2,function(c){this._0.stroke=k||c[this.klass.DATA_COLOR_INDEX];this._0.stroke_width=5.0;var d=i*Math.cos(l);var f=i*Math.sin(l);this._0.line(g,h,g+d,h+f);if(!this.hide_text)this._c(g,h,l,i,c[this.klass.DATA_LABEL_INDEX]);l+=j},this)},_1W:function(d,f,g,h){var i=[],j=0.0;Bluff.each(this._2,function(c){i.push(d+this._1n(c[this.klass.DATA_VALUES_INDEX][0])*Math.cos(j));i.push(f+this._1n(c[this.klass.DATA_VALUES_INDEX][0])*Math.sin(j));j+=g},this);this._0.stroke_width=1.0;this._0.stroke=h||this.marker_color;this._0.fill=h||this.marker_color;this._0.fill_opacity=0.4;this._0.polyline(i)},_1U:function(){var d=0.0;Bluff.each(this._2,function(c){d+=c[this.klass.DATA_VALUES_INDEX][0]},this);return d}});Bluff.Base.StackedMixin=new JS.Module({_19:function(){var g={};Bluff.each(this._2,function(f){Bluff.each(f[this.klass.DATA_VALUES_INDEX],function(c,d){if(!g[d])g[d]=0.0;g[d]+=c},this)},this);for(var h in g){if(g[h]>this.maximum_value)this.maximum_value=g[h]}this.minimum_value=0}});Bluff.StackedArea=new JS.Class(Bluff.Base,{include:Bluff.Base.StackedMixin,last_series_goes_on_bottom:null,draw:function(){this._19();this.callSuper();if(!this._a)return;this._R=this._6/(this._5-1);this._0.stroke='transparent';var n=Bluff.array_new(this._5,0);var m=null;var o=this.last_series_goes_on_bottom?'reverse_each':'each';Bluff[o](this._9,function(h){var i=m;m=[];Bluff.each(h[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._R*d);var g=this._7+(this._3-c*this._3-n[d]);n[d]+=(c*this._3);m.push(f);m.push(g);this._c(f,d)},this);var j,k,l;if(i){j=Bluff.array(m);for(k=i.length/2-1;k>=0;k--){j.push(i[2*k]);j.push(i[2*k+1])}j.push(m[0]);j.push(m[1])}else{j=Bluff.array(m);j.push(this._l);j.push(this._g-1);j.push(this._1);j.push(this._g-1);j.push(m[0]);j.push(m[1])}this._0.fill=h[this.klass.DATA_COLOR_INDEX];this._0.polyline(j)},this)}});Bluff.StackedBar=new JS.Class(Bluff.Base,{include:Bluff.Base.StackedMixin,bar_spacing:0.9,draw:function(){this._19();this.callSuper();if(!this._a)return;this._8=this._6/this._5;var m=(this._8*(1-this.bar_spacing))/2;this._0.stroke_opacity=0.0;var o=Bluff.array_new(this._5,0);Bluff.each(this._9,function(k,l){var n=this._2[l][this.klass.DATA_VALUES_INDEX];Bluff.each(k[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._8*d)+(this._8*this.bar_spacing/2.0);this._c(f,d);if(c==0)return;var g=this._1+(this._8*d)+m;var h=this._7+(this._3-c*this._3-o[d])+1;var i=g+this._8*this.bar_spacing;var j=this._7+this._3-o[d]-1;o[d]+=(c*this._3);this._0.fill=k[this.klass.DATA_COLOR_INDEX];this._0.rectangle(g,h,i,j);this._E(g,h,i-g,j-h,k[this.klass.DATA_LABEL_INDEX],k[this.klass.DATA_COLOR_INDEX],n[d])},this)},this)}});Bluff.AccumulatorBar=new JS.Class(Bluff.StackedBar,{draw:function(){if(this._2.length!==1)throw'Incorrect number of datasets';var g=[],h=0,i=[];Bluff.each(this._2[0][this.klass.DATA_VALUES_INDEX],function(d){var f=-Infinity;Bluff.each(i,function(c){f=Math.max(f,c)});i.push((h>0)?(d+f):d);g.push(i[h]-d);h+=1},this);this.data("Accumulator",g);this.callSuper()}});Bluff.SideStackedBar=new JS.Class(Bluff.SideBar,{include:Bluff.Base.StackedMixin,bar_spacing:0.9,draw:function(){this.has_left_labels=true;this._19();this.callSuper();if(!this._a)return;this._8=this._3/this._5;var q=Bluff.array_new(this._5,0),s=Bluff.array_new(this._5,this._1),r=(this._8*(1-this.bar_spacing))/2;Bluff.each(this._9,function(m,o){this._0.fill=m[this.klass.DATA_COLOR_INDEX];var p=this._2[o][this.klass.DATA_VALUES_INDEX];Bluff.each(m[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._6-c*this._6-q[d])+1;var g=this._1+this._6-q[d]-1;var h=g-f;var i=s[d],j=this._7+(this._8*d)+r,k=i+h,l=j+this._8*this.bar_spacing;s[d]+=h;q[d]+=(c*this._6-2);this._0.rectangle(i,j,k,l);this._E(i,j,k-i,l-j,m[this.klass.DATA_LABEL_INDEX],m[this.klass.DATA_COLOR_INDEX],p[d]);var n=this._7+(this._8*d)+(this._8*this.bar_spacing/2.0);this._c(n,d)},this)},this)},_1f:function(c,d){d=d||0;return this._1m(c,d)>this.maximum_value},_1m:function(d,f){var g=0;Bluff.each(this._2,function(c){g+=c[this.klass.DATA_VALUES_INDEX][f]},this);return g}});Bluff.Mini.Legend=new JS.Module({hide_mini_legend:false,_1a:function(){if(this.hide_mini_legend)return;this._1X=this._L;this._y+=this._2.length*this._D(this._e(this.legend_font_size))*1.7;this._X()},_1b:function(){if(this.hide_mini_legend)return;this._P=Bluff.map(this._2,function(c){return c[this.klass.DATA_LABEL_INDEX]},this);var f=40.0,g=10.0,h=100.0,i=40.0;if(this.font)this._0.font=this.font;this._0.pointsize=this.legend_font_size;var j=h,k=this._1X+i;this._u(function(){this._0.line(0.0,k,this._d,k)});Bluff.each(this._P,function(c,d){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._e(this.legend_font_size);this._0.stroke='transparent';this._0.font_weight='normal';this._0.gravity='west';this._0.annotate_scaled(this._d,1.0,j+(f*1.7),k,this._1Y(c),this._b);this._0.stroke='transparent';this._0.fill=this._2[d][this.klass.DATA_COLOR_INDEX];this._0.rectangle(j,k-f/2.0,j+f,k+f/2.0);k+=this._D(this.legend_font_size)*1.7},this);this._m=0},_1Y:function(c){var d=String(c);while(this._O(this._e(this.legend_font_size),d)>(this._j-this.legend_left_margin-this.right_margin)&&(d.length>1))d=d.substr(0,d.length-1);return d+(d.length=1?(c*i):1;var k=(d*i)>=1?(d*i):1;var h=this._T(this.pointsize,h);h.style.color=this.fill;h.style.fontWeight=this.font_weight;h.style.textAlign='center';h.style.left=(this._f*f+this._1Z(h,j))+'px';h.style.top=(this._h*g+this._20(h,k))+'px'},tooltip:function(d,f,g,h,i,j,k){if(g<0)d+=g;if(h<0)f+=h;var l=this._n.parentNode,n=document.createElement('div');n.className=this.klass.TARGET_CLASS;n.style.position='absolute';n.style.left=(this._f*d-3)+'px';n.style.top=(this._h*f-3)+'px';n.style.width=(this._f*Math.abs(g)+5)+'px';n.style.height=(this._h*Math.abs(h)+5)+'px';n.style.fontSize=0;n.style.overflow='hidden';Bluff.Event.observe(n,'mouseover',function(c){Bluff.Tooltip.show(i,j,k)});Bluff.Event.observe(n,'mouseout',function(c){Bluff.Tooltip.hide()});l.appendChild(n)},circle:function(c,d,f,g,h,i){var j=Math.sqrt(Math.pow(f-c,2)+Math.pow(g-d,2));this._4.fillStyle=this.fill;this._4.beginPath();var k=(h||0)*Math.PI/180;var l=(i||360)*Math.PI/180;if(h!==undefined&&i!==undefined){this._4.moveTo(this._f*(c+j*Math.cos(l)),this._h*(d+j*Math.sin(l)));this._4.lineTo(this._f*c,this._h*d);this._4.lineTo(this._f*(c+j*Math.cos(k)),this._h*(d+j*Math.sin(k)))}this._4.arc(this._f*c,this._h*d,this._f*j,k,l,false);this._4.fill()},line:function(c,d,f,g){this._4.strokeStyle=this.stroke;this._4.lineWidth=this.stroke_width;this._4.beginPath();this._4.moveTo(this._f*c,this._h*d);this._4.lineTo(this._f*f,this._h*g);this._4.stroke()},polyline:function(c){this._4.fillStyle=this.fill;this._4.globalAlpha=this.fill_opacity||1;try{this._4.strokeStyle=this.stroke}catch(e){}var d=c.shift(),f=c.shift();this._4.beginPath();this._4.moveTo(this._f*d,this._h*f);while(c.length>0){d=c.shift();f=c.shift();this._4.lineTo(this._f*d,this._h*f)}this._4.fill()},rectangle:function(c,d,f,g){var h;if(c>f){h=c;c=f;f=h}if(d>g){h=d;d=g;g=h}try{this._4.fillStyle=this.fill;this._4.fillRect(this._f*c,this._h*d,this._f*(f-c),this._h*(g-d))}catch(e){}try{this._4.strokeStyle=this.stroke;if(this.stroke!=='transparent')this._4.strokeRect(this._f*c,this._h*d,this._f*(f-c),this._h*(g-d))}catch(e){}},_1Z:function(c,d){var f=this._H(c).width;switch(this.gravity){case'west':return 0;case'east':return d-f;case'north':case'south':case'center':return(d-f)/2}},_20:function(c,d){var f=this._H(c).height;switch(this.gravity){case'north':return 0;case'south':return d-f;case'west':case'east':case'center':return(d-f)/2}},_1o:function(){var c=this._n.parentNode;if(c.className===this.klass.WRAPPER_CLASS)return c;c=document.createElement('div');c.className=this.klass.WRAPPER_CLASS;c.style.position='relative';c.style.border='none';c.style.padding='0 0 0 0';this._n.parentNode.insertBefore(c,this._n);c.appendChild(this._n);return c},_T:function(c,d){var f=this._21(d);f.style.fontFamily=this.font;f.style.fontSize=(typeof c==='number')?c+'px':c;return f},_21:function(c){var d=document.createElement('div');d.className=this.klass.TEXT_CLASS;d.style.position='absolute';d.appendChild(document.createTextNode(c));this._1o().appendChild(d);return d},_U:function(c){c.parentNode.removeChild(c);if(c.className===this.klass.TARGET_CLASS)Bluff.Event.stopObserving(c)},_H:function(c){var d=c.style.display;return(d&&d!=='none')?{width:c.offsetWidth,height:c.offsetHeight}:{width:c.clientWidth,height:c.clientHeight}}});Bluff.Event={_V:[],_1p:(window.attachEvent&&navigator.userAgent.indexOf('Opera')===-1),observe:function(d,f,g,h){var i=Bluff.map(this._1q(d,f),function(c){return c._22});if(Bluff.index(i,g)!==-1)return;var j=function(c){g.call(h||null,d,Bluff.Event._23(c))};this._V.push({_W:d,_1c:f,_22:g,_1r:j});if(d.addEventListener)d.addEventListener(f,j,false);else d.attachEvent('on'+f,j)},stopObserving:function(d){var f=d?this._1q(d):this._V;Bluff.each(f,function(c){if(c._W.removeEventListener)c._W.removeEventListener(c._1c,c._1r,false);else c._W.detachEvent('on'+c._1c,c._1r)})},_1q:function(d,f){var g=[];Bluff.each(this._V,function(c){if(d&&c._W!==d)return;if(f&&c._1c!==f)return;g.push(c)});return g},_23:function(c){if(!this._1p)return c;if(!c)return false;if(c._24)return c;c._24=true;var d=this._25(c);c.target=c.srcElement;c.pageX=d.x;c.pageY=d.y;return c},_25:function(c){var d=document.documentElement,f=document.body||{scrollLeft:0,scrollTop:0};return{x:c.pageX||(c.clientX+(d.scrollLeft||f.scrollLeft)-(d.clientLeft||0)),y:c.pageY||(c.clientY+(d.scrollTop||f.scrollTop)-(d.clientTop||0))}}};if(Bluff.Event._1p)window.attachEvent('onunload',function(){Bluff.Event.stopObserving();Bluff.Event._V=null});if(navigator.userAgent.indexOf('AppleWebKit/')>-1)window.addEventListener('unload',function(){},false);Bluff.Tooltip=new JS.Singleton({LEFT_OFFSET:20,TOP_OFFSET:-6,DATA_LENGTH:8,CLASS_NAME:'bluff-tooltip',setup:function(){this._o=document.createElement('div');this._o.className=this.CLASS_NAME;this._o.style.position='absolute';this.hide();document.body.appendChild(this._o);Bluff.Event.observe(document.body,'mousemove',function(c,d){this._o.style.left=(d.pageX+this.LEFT_OFFSET)+'px';this._o.style.top=(d.pageY+this.TOP_OFFSET)+'px'},this)},show:function(c,d,f){f=Number(String(f).substr(0,this.DATA_LENGTH));this._o.innerHTML='  '+c+' '+f+'';this._o.style.display=''},hide:function(){this._o.style.display='none'}});Bluff.Event.observe(window,'load',Bluff.Tooltip.method('setup'));Bluff.TableReader=new JS.Class({NUMBER_FORMAT:/\-?(0|[1-9]\d*)(\.\d+)?(e[\+\-]?\d+)?/i,initialize:function(c,d){this._26=(typeof c==='string')?document.getElementById(c):c;this._1s=!!d},get_data:function(){if(!this._2)this._1t();return this._2},get_labels:function(){if(!this._1d)this._1t();return this._1d},get_title:function(){return this._27},get_series:function(c){if(this._2[c])return this._2[c];return this._2[c]={points:[]}},_1t:function(){this._I=this._p=0;this._J=this._K=0;this._2=[];this._1d={};this._s=[];this._t=[];this._1u(this._26);if((this._s.length>1&&this._t.length===1)||this._s.length]+>/gi,'')},extend:{Mixin:new JS.Module({data_from_table:function(d,f){var g=new Bluff.TableReader(d,f),h=g.get_data();Bluff.each(h,function(c){this.data(c.name,c.points)},this);this.labels=g.get_labels();this.title=g.get_title()||this.title}})}});Bluff.Base.include(Bluff.TableReader.Mixin); -------------------------------------------------------------------------------- /mapgenerator/scripts/excanvas.js: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | document.createElement("canvas").getContext||(function(){var s=Math,j=s.round,F=s.sin,G=s.cos,V=s.abs,W=s.sqrt,k=10,v=k/2;function X(){return this.context_||(this.context_=new H(this))}var L=Array.prototype.slice;function Y(b,a){var c=L.call(arguments,2);return function(){return b.apply(a,c.concat(L.call(arguments)))}}var M={init:function(b){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var a=b||document;a.createElement("canvas");a.attachEvent("onreadystatechange",Y(this.init_,this,a))}},init_:function(b){b.namespaces.g_vml_|| 15 | b.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML");b.namespaces.g_o_||b.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML");if(!b.styleSheets.ex_canvas_){var a=b.createStyleSheet();a.owningElement.id="ex_canvas_";a.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}g_vml_\\:*{behavior:url(#default#VML)}g_o_\\:*{behavior:url(#default#VML)}"}var c=b.getElementsByTagName("canvas"),d=0;for(;d','","");this.element_.insertAdjacentHTML("BeforeEnd",t.join(""))};i.stroke=function(b){var a=[],c=P(b?this.fillStyle:this.strokeStyle),d=c.color,f=c.alpha*this.globalAlpha;a.push("g.x)g.x=e.x;if(h.y==null||e.yg.y)g.y=e.y}}a.push(' ">');if(b)if(typeof this.fillStyle=="object"){var m=this.fillStyle,r=0,n={x:0,y:0},o=0,q=1;if(m.type_=="gradient"){var t=m.x1_/this.arcScaleX_,E=m.y1_/this.arcScaleY_,p=this.getCoords_(m.x0_/this.arcScaleX_,m.y0_/this.arcScaleY_), 30 | z=this.getCoords_(t,E);r=Math.atan2(z.x-p.x,z.y-p.y)*180/Math.PI;if(r<0)r+=360;if(r<1.0E-6)r=0}else{var p=this.getCoords_(m.x0_,m.y0_),w=g.x-h.x,x=g.y-h.y;n={x:(p.x-h.x)/w,y:(p.y-h.y)/x};w/=this.arcScaleX_*k;x/=this.arcScaleY_*k;var R=s.max(w,x);o=2*m.r0_/R;q=2*m.r1_/R-o}var u=m.colors_;u.sort(function(ba,ca){return ba.offset-ca.offset});var J=u.length,da=u[0].color,ea=u[J-1].color,fa=u[0].alpha*this.globalAlpha,ga=u[J-1].alpha*this.globalAlpha,S=[],l=0;for(;l')}else a.push('');else{var K=this.lineScale_*this.lineWidth;if(K<1)f*=K;a.push("')}a.push("");this.element_.insertAdjacentHTML("beforeEnd",a.join(""))};i.fill=function(){this.stroke(true)};i.closePath=function(){this.currentPath_.push({type:"close"})};i.getCoords_=function(b,a){var c=this.m_;return{x:k*(b*c[0][0]+a*c[1][0]+c[2][0])-v,y:k*(b*c[0][1]+a*c[1][1]+c[2][1])-v}};i.save=function(){var b={};O(this,b);this.aStack_.push(b);this.mStack_.push(this.m_);this.m_=y(I(),this.m_)};i.restore=function(){O(this.aStack_.pop(), 33 | this);this.m_=this.mStack_.pop()};function ha(b){var a=0;for(;a<3;a++){var c=0;for(;c<2;c++)if(!isFinite(b[a][c])||isNaN(b[a][c]))return false}return true}function A(b,a,c){if(!!ha(a)){b.m_=a;if(c)b.lineScale_=W(V(a[0][0]*a[1][1]-a[0][1]*a[1][0]))}}i.translate=function(b,a){A(this,y([[1,0,0],[0,1,0],[b,a,1]],this.m_),false)};i.rotate=function(b){var a=G(b),c=F(b);A(this,y([[a,c,0],[-c,a,0],[0,0,1]],this.m_),false)};i.scale=function(b,a){this.arcScaleX_*=b;this.arcScaleY_*=a;A(this,y([[b,0,0],[0,a, 34 | 0],[0,0,1]],this.m_),true)};i.transform=function(b,a,c,d,f,h){A(this,y([[b,a,0],[c,d,0],[f,h,1]],this.m_),true)};i.setTransform=function(b,a,c,d,f,h){A(this,[[b,a,0],[c,d,0],[f,h,1]],true)};i.clip=function(){};i.arcTo=function(){};i.createPattern=function(){return new U};function D(b){this.type_=b;this.r1_=this.y1_=this.x1_=this.r0_=this.y0_=this.x0_=0;this.colors_=[]}D.prototype.addColorStop=function(b,a){a=P(a);this.colors_.push({offset:b,color:a.color,alpha:a.alpha})};function U(){}G_vmlCanvasManager= 35 | M;CanvasRenderingContext2D=H;CanvasGradient=D;CanvasPattern=U})(); 36 | -------------------------------------------------------------------------------- /mapgenerator/scripts/js-class.js: -------------------------------------------------------------------------------- 1 | JS={extend:function(a,b){b=b||{};for(var c in b){if(a[c]===b[c])continue;a[c]=b[c]}return a},makeFunction:function(){return function(){return this.initialize?(this.initialize.apply(this,arguments)||this):this}},makeBridge:function(a){var b=function(){};b.prototype=a.prototype;return new b},bind:function(){var a=JS.array(arguments),b=a.shift(),c=a.shift()||null;return function(){return b.apply(c,a.concat(JS.array(arguments)))}},callsSuper:function(a){return a.SUPER===undefined?a.SUPER=/\bcallSuper\b/.test(a.toString()):a.SUPER},mask:function(a){var b=a.toString().replace(/callSuper/g,'super');a.toString=function(){return b};return a},array:function(a){if(!a)return[];if(a.toArray)return a.toArray();var b=a.length,c=[];while(b--)c[b]=a[b];return c},indexOf:function(a,b){for(var c=0,d=a.length;c':''),d=this.__meta__=new JS.Module(c?c+'.':'',{},{_1:this});d.include(this.klass.__mod__,false);return d},equals:function(a){return this===a},extend:function(a,b){return this.__eigen__().include(a,b,{_2:this})},hash:function(){return this.__hashcode__=this.__hashcode__||JS.Kernel.getHashCode()},isA:function(a){return this.__eigen__().includes(a)},method:function(a){var b=this,c=b.__mcache__=b.__mcache__||{};if((c[a]||{}).fn===b[a])return c[a].bd;return(c[a]={fn:b[a],bd:JS.bind(b[a],b)}).bd},methods:function(){return this.__eigen__().instanceMethods(true)},tap:function(a,b){a.call(b||null,this);return this}}),{__hashIndex__:0,getHashCode:function(){this.__hashIndex__+=1;return(Math.floor(new Date().getTime()/1000)+this.__hashIndex__).toString(16)}});JS.Module.include(JS.Kernel);JS.extend(JS.Module,JS.Kernel.__fns__);JS.Class.include(JS.Kernel);JS.extend(JS.Class,JS.Kernel.__fns__);JS.Interface=new JS.Class({initialize:function(d){this.test=function(a,b){var c=d.length;while(c--){if(!JS.isFn(a[d[c]]))return b?d[c]:false}return true}},extend:{ensure:function(){var a=JS.array(arguments),b=a.shift(),c,d;while(c=a.shift()){d=c.test(b,true);if(d!==true)throw new Error('object does not implement '+d+'()');}}}});JS.Singleton=new JS.Class({initialize:function(a,b,c){return new(new JS.Class(a,b,c))}}); -------------------------------------------------------------------------------- /results/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/results/bg.png -------------------------------------------------------------------------------- /results/bluff-min.js: -------------------------------------------------------------------------------- 1 | Bluff={VERSION:'0.3.6',array:function(c){if(c.length===undefined)return[c];var d=[],f=c.length;while(f--)d[f]=c[f];return d},array_new:function(c,d){var f=[];while(c--)f.push(d);return f},each:function(c,d,f){for(var g=0,h=c.length;gthis._5)?g.length:this._5;Bluff.each(g,function(c,d){if(c===undefined)return;if(this.maximum_value===null&&this.minimum_value===null)this.maximum_value=this.minimum_value=c;this.maximum_value=this._1f(c)?c:this.maximum_value;if(this.maximum_value>=0)this._a=true;this.minimum_value=this._1A(c)?c:this.minimum_value;if(this.minimum_value<0)this._a=true},this)},draw:function(){if(this.stacked)this._1B();this._1C();this._u(function(){this._0.rectangle(this.left_margin,this.top_margin,this._d-this.right_margin,this._L-this.bottom_margin);this._0.rectangle(this._1,this._7,this._l,this._g)})},clear:function(){this._X()},_1C:function(){if(!this._a)return this._1D();this._13();this._1E();if(this.sort)this._1F();this._1G();this._M();this._1H();this._1I()},_13:function(g){if(this._9===null||g===true){this._9=[];if(!this._a)return;this._1g();Bluff.each(this._2,function(d){var f=[];Bluff.each(d[this.klass.DATA_VALUES_INDEX],function(c){if(c===null||c===undefined)f.push(null);else f.push((c-this.minimum_value)/this._i)},this);this._9.push([d[this.klass.DATA_LABEL_INDEX],f,d[this.klass.DATA_COLOR_INDEX]])},this)}},_1g:function(){this._i=this.maximum_value-this.minimum_value;this._i=this._i>0?this._i:1;this._1h=100/Math.pow(10,Math.round(Math.LOG10E*Math.log(this._i)))},_1E:function(){this._N=this.hide_line_markers?0:this._D(this.marker_font_size);this._1i=this.hide_title?0:this._D(this.title_font_size);this._1j=this.hide_legend?0:this._D(this.legend_font_size);var c,d,f,g,h,i,j;if(this.hide_line_markers){this._1=this.left_margin;this._14=this.right_margin;this._1k=this.bottom_margin}else{d=0;if(this.has_left_labels){c='';for(j in this.labels){c=c.length>this.labels[j].length?c:this.labels[j]}d=this._O(this.marker_font_size,c)*1.25}else{d=this._O(this.marker_font_size,this._15(this.maximum_value))}f=this.hide_line_numbers&&!this.has_left_labels?0.0:d+this.klass.LABEL_MARGIN*2;this._1=this.left_margin+f+(this.y_axis_label===null?0.0:this._N+this.klass.LABEL_MARGIN*2);g=-Infinity;for(j in this.labels)g=g>Number(j)?g:Number(j);g=Math.round(g);h=(g>=(this._5-1)&&this.center_labels_over_point)?this._O(this.marker_font_size,this.labels[g])/2:0;this._14=this.right_margin+h;this._1k=this.bottom_margin+this._N+this.klass.LABEL_MARGIN}this._l=this._d-this._14;this._6=this._d-this._1-this._14;this._7=this.top_margin+(this.hide_title?this.title_margin:this._1i+this.title_margin)+(this.hide_legend?this.legend_margin:this._1j+this.legend_margin);i=(this.x_axis_label===null)?0.0:this._N+this.klass.LABEL_MARGIN;this._g=this._L-this._1k-i;this._3=this._g-this._7},_1H:function(){if(this.x_axis_label){var c=this._g+this.klass.LABEL_MARGIN*2+this._N;this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.pointsize=this._e(this.marker_font_size);this._0.gravity='north';this._0.annotate_scaled(this._d,1.0,0.0,c,this.x_axis_label,this._b);this._u(function(){this._0.line(0.0,c,this._d,c)})}},_M:function(){if(this.hide_line_markers)return;if(this.y_axis_increment===null){if(this.marker_count===null){Bluff.each([3,4,5,6,7],function(c){if(!this.marker_count&&this._i%c===0)this.marker_count=c},this);this.marker_count=this.marker_count||4}this._16=(this._i>0)?this._17(this._i/this.marker_count):1}else{this.maximum_value=Math.max(Math.ceil(this.maximum_value),this.y_axis_increment);this.minimum_value=Math.floor(this.minimum_value);this._1g();this._13(true);this.marker_count=Math.round(this._i/this.y_axis_increment);this._16=this.y_axis_increment}this._1J=this._3/(this._i/this._16);var d,f,g,h;for(d=0,f=this.marker_count;d<=f;d++){g=this._7+this._3-d*this._1J;this._0.stroke=this.marker_color;this._0.stroke_width=1;this._0.line(this._1,g,this._l,g);h=d*this._16+this.minimum_value;if(!this.hide_line_numbers){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.font_weight='normal';this._0.stroke='transparent';this._0.pointsize=this._e(this.marker_font_size);this._0.gravity='east';this._0.annotate_scaled(this._1-this.klass.LABEL_MARGIN,1.0,0.0,g,this._15(h),this._b)}}},_1l:function(c){return(this._d-c)/2},_1G:function(){if(this.hide_legend)return;this._P=Bluff.map(this._2,function(c){return c[this.klass.DATA_LABEL_INDEX]},this);var i=this.legend_box_size;if(this.font)this._0.font=this.font;this._0.pointsize=this.legend_font_size;var j=[[]];Bluff.each(this._P,function(c){var d=j.length-1;var f=this._0.get_type_metrics(c);var g=f.width+i*2.7;j[d].push(g);if(Bluff.sum(j[d])>(this._d*0.9))j.push([j[d].pop()])},this);var k=this._1l(Bluff.sum(j[0]));var l=this.hide_title?this.top_margin+this.title_margin:this.top_margin+this.title_margin+this._1i;this._u(function(){this._0.stroke_width=1;this._0.line(0,l,this._d,l)});Bluff.each(this._P,function(c,d){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._e(this.legend_font_size);this._0.stroke='transparent';this._0.font_weight='normal';this._0.gravity='west';this._0.annotate_scaled(this._d,1.0,k+(i*1.7),l,c,this._b);this._0.stroke='transparent';this._0.fill=this._2[d][this.klass.DATA_COLOR_INDEX];this._0.rectangle(k,l-i/2.0,k+i,l+i/2.0);this._0.pointsize=this.legend_font_size;var f=this._0.get_type_metrics(c);var g=f.width+(i*2.7),h;j[0].shift();if(j[0].length==0){this._u(function(){this._0.line(0.0,l,this._d,l)});j.shift();if(j.length>0)k=this._1l(Bluff.sum(j[0]));h=Math.max(this._1j,i)+this.legend_margin;if(j.length>0){l+=h;this._7+=h;this._3=this._g-this._7}}else{k+=g}},this);this._m=0},_1I:function(){if(this.hide_title||!this.title)return;this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._e(this.title_font_size);this._0.font_weight='bold';this._0.gravity='north';this._0.annotate_scaled(this._d,1.0,0,this.top_margin,this.title,this._b)},_c:function(c,d){if(this.hide_line_markers)return;var f;if(this.labels[d]&&!this._q[d]){f=this._g+this.klass.LABEL_MARGIN;this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.font_weight='normal';this._0.pointsize=this._e(this.marker_font_size);this._0.gravity='north';this._0.annotate_scaled(1.0,1.0,c,f,this.labels[d],this._b);this._q[d]=true;this._u(function(){this._0.stroke_width=1;this._0.line(0.0,f,this._d,f)})}},_E:function(c,d,f,g,h,i,j){if(!this.tooltips)return;this._0.tooltip(c,d,f,g,h,i,j)},_1D:function(){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.font_weight='normal';this._0.pointsize=this._e(80);this._0.gravity='center';this._0.annotate_scaled(this._d,this._L/2,0,10,this.no_data_message,this._b)},_X:function(){var c=this._k.background_colors;switch(true){case c instanceof Array:this._1K.apply(this,c);break;case typeof c==='string':this._1L(c);break;default:this._1M(this._k.background_image);break}},_1L:function(c){this._0.render_solid_background(this._j,this._y,c)},_1K:function(c,d){this._0.render_gradiated_background(this._j,this._y,c,d)},_1M:function(c){},_1e:function(){this._m=0;this._q={};this._k={};this._0.scale(this._b,this._b)},_2a:function(c){return this._b*c},_e:function(c){var d=c*this._b;return d},_Q:function(c,d){return(c>d)?d:c},_1f:function(c,d){return c>this.maximum_value},_1A:function(c,d){return c100){c/=10;d*=10}return Math.floor(c)*d},_1F:function(){var f=this._1N,g=this.klass.DATA_VALUES_INDEX;this._9.sort(function(c,d){return f(d[g])-f(c[g])});this._2.sort(function(c,d){return f(d[g])-f(c[g])})},_1N:function(d){var f=0;Bluff.each(d,function(c){f+=(c||0)});return f},_1B:function(){var g=[],h=this._5;while(h--)g[h]=0;Bluff.each(this._2,function(f){Bluff.each(f[this.klass.DATA_VALUES_INDEX],function(c,d){g[d]+=c},this);f[this.klass.DATA_VALUES_INDEX]=Bluff.array(g)},this)},_u:function(c){if(this.klass.DEBUG){this._0.fill='transparent';this._0.stroke='turquoise';c.call(this)}},_1z:function(){if(this._m0&&k>0){i.push(f);i.push(g)}else{i.push(this._1);i.push(this._g-1);i.push(f);i.push(g)}this._c(f,d);j=f;k=g},this);i.push(this._l);i.push(this._g-1);i.push(this._1);i.push(this._g-1);this._0.fill=h[this.klass.DATA_COLOR_INDEX];this._0.polyline(i)},this)}});Bluff.BarConversion=new JS.Class({mode:null,zero:null,graph_top:null,graph_height:null,minimum_value:null,spread:null,getLeftYRightYscaled:function(c,d){var f;switch(this.mode){case 1:d[0]=this.graph_top+this.graph_height*(1-c)+1;d[1]=this.graph_top+this.graph_height-1;break;case 2:d[0]=this.graph_top+1;d[1]=this.graph_top+this.graph_height*(1-c)-1;break;case 3:f=c-this.minimum_value/this.spread;if(c>=this.zero){d[0]=this.graph_top+this.graph_height*(1-(f-this.zero))+1;d[1]=this.graph_top+this.graph_height*(1-this.zero)-1}else{d[0]=this.graph_top+this.graph_height*(1-(f-this.zero))+1;d[1]=this.graph_top+this.graph_height*(1-this.zero)-1}break;default:d[0]=0.0;d[1]=0.0}}});Bluff.Bar=new JS.Class(Bluff.Base,{bar_spacing:0.9,draw:function(){this.center_labels_over_point=(Bluff.keys(this.labels).length>this._5);this.callSuper();if(!this._a)return;this._1O()},_1O:function(){this._8=this._6/(this._5*this._2.length);var n=(this._8*(1-this.bar_spacing))/2;this._0.stroke_opacity=0.0;var m=new Bluff.BarConversion();m.graph_height=this._3;m.graph_top=this._7;if(this.minimum_value>=0){m.mode=1}else{if(this.maximum_value<=0){m.mode=2}else{m.mode=3;m.spread=this._i;m.minimum_value=this.minimum_value;m.zero=-this.minimum_value/this._i}}Bluff.each(this._9,function(j,k){var l=this._2[k][this.klass.DATA_VALUES_INDEX];Bluff.each(j[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._8*(k+d+((this._2.length-1)*d)))+n;var g=f+this._8*this.bar_spacing;var h=[];m.getLeftYRightYscaled(c,h);this._0.fill=j[this.klass.DATA_COLOR_INDEX];this._0.rectangle(f,h[0],g,h[1]);this._E(f,h[0],g-f,h[1]-h[0],j[this.klass.DATA_LABEL_INDEX],j[this.klass.DATA_COLOR_INDEX],l[d]);var i=this._1+(this._2.length*this._8*d)+(this._2.length*this._8/2.0);this._c(i-(this.center_labels_over_point?this._8/2.0:0.0),d)},this)},this);if(this.center_labels_over_point)this._c(this._l,this._5)}});Bluff.Line=new JS.Class(Bluff.Base,{baseline_value:null,baseline_color:null,line_width:null,dot_radius:null,hide_dots:null,hide_lines:null,initialize:function(c){if(arguments.length>3)throw'Wrong number of arguments';if(arguments.length===1||(typeof arguments[1]!=='number'&&typeof arguments[1]!=='string'))this.callSuper(c,null);else this.callSuper();this.hide_dots=this.hide_lines=false;this.baseline_color='red';this.baseline_value=null},draw:function(){this.callSuper();if(!this._a)return;this.x_increment=(this._5>1)?(this._6/(this._5-1)):this._6;var m;if(this._S!==undefined){m=this._7+(this._3-this._S*this._3);this._0.push();this._0.stroke=this.baseline_color;this._0.fill_opacity=0.0;this._0.stroke_width=3.0;this._0.line(this._1,m,this._1+this._6,m);this._0.pop()}Bluff.each(this._9,function(i,j){var k=null,l=null;var n=this._2[j][this.klass.DATA_VALUES_INDEX];this._1P=this._1Q(i);Bluff.each(i[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this.x_increment*d);if(typeof c!=='number')return;this._c(f,d);var g=this._7+(this._3-c*this._3);this._0.stroke=i[this.klass.DATA_COLOR_INDEX];this._0.fill=i[this.klass.DATA_COLOR_INDEX];this._0.stroke_opacity=1.0;this._0.stroke_width=this.line_width||this._Q(this._j/(this._9[0][this.klass.DATA_VALUES_INDEX].length*6),3.0);var h=this.dot_radius||this._Q(this._j/(this._9[0][this.klass.DATA_VALUES_INDEX].length*2),7.0);if(!this.hide_lines&&k!==null&&l!==null){this._0.line(k,l,f,g)}else if(this._1P){this._0.circle(f,g,f-h,g)}if(!this.hide_dots)this._0.circle(f,g,f-h,g);this._E(f-h,g-h,2*h,2*h,i[this.klass.DATA_LABEL_INDEX],i[this.klass.DATA_COLOR_INDEX],n[d]);k=f;l=g},this)},this)},_13:function(){this.maximum_value=Math.max(this.maximum_value,this.baseline_value);this.callSuper();if(this.baseline_value!==null)this._S=this.baseline_value/this.maximum_value},_1Q:function(d){var f=0;Bluff.each(d[this.klass.DATA_VALUES_INDEX],function(c){if(c!==undefined)f+=1});return f===1}});Bluff.Dot=new JS.Class(Bluff.Base,{draw:function(){this.has_left_labels=true;this.callSuper();if(!this._a)return;var k=1.0;this._F=this._3/this._5;this._18=this._F*k/this._9.length;this._0.stroke_opacity=0.0;var l=Bluff.array_new(this._5,0),n=Bluff.array_new(this._5,this._1),m=(this._F*(1-k))/2;Bluff.each(this._9,function(i,j){Bluff.each(i[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(c*this._6)-Math.round(this._18/6.0);var g=this._7+(this._F*d)+m+Math.round(this._18/2.0);if(j===0){this._0.stroke=this.marker_color;this._0.stroke_width=1.0;this._0.opacity=0.1;this._0.line(this._1,g,this._1+this._6,g)}this._0.fill=i[this.klass.DATA_COLOR_INDEX];this._0.stroke='transparent';this._0.circle(f,g,f+Math.round(this._18/3.0),g);var h=this._7+(this._F*d+this._F/2)+m;this._c(h,d)},this)},this)},_M:function(){if(this.hide_line_markers)return;this._0.stroke_antialias=false;this._0.stroke_width=1;var c=5;var d=this._17(this.maximum_value/c);for(var f=0;f<=c;f++){var g=(this._l-this._1)/c,h=this._l-(g*f)-1,i=f-c,j=Math.abs(i)*d;this._0.stroke=this.marker_color;this._0.line(h,this._g,h,this._g+0.5*this.klass.LABEL_MARGIN);if(!this.hide_line_numbers){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.pointsize=this._e(this.marker_font_size);this._0.gravity='center';this._0.annotate_scaled(0,0,h,this._g+(this.klass.LABEL_MARGIN*2.0),j,this._b)}this._0.stroke_antialias=true}},_c:function(c,d){if(this.labels[d]&&!this._q[d]){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.font_weight='normal';this._0.pointsize=this._e(this.marker_font_size);this._0.gravity='east';this._0.annotate_scaled(1,1,this._1-this.klass.LABEL_MARGIN*2.0,c,this.labels[d],this._b);this._q[d]=true}}});Bluff.Net=new JS.Class(Bluff.Base,{hide_dots:null,line_width:null,dot_radius:null,initialize:function(){this.callSuper();this.hide_dots=false;this.hide_line_numbers=true},draw:function(){this.callSuper();if(!this._a)return;this._v=this._3/2.0;this._w=this._1+(this._6/2.0);this._x=this._7+(this._3/2.0)-10;this._R=this._6/(this._5-1);var s=this.dot_radius||this._Q(this._j/(this._9[0][this.klass.DATA_VALUES_INDEX].length*2.5),7.0);this._0.stroke_opacity=1.0;this._0.stroke_width=this.line_width||this._Q(this._j/(this._9[0][this.klass.DATA_VALUES_INDEX].length*4),3.0);var r;if(this._S!==undefined){r=this._7+(this._3-this._S*this._3);this._0.push();this._0.stroke_color=this.baseline_color;this._0.fill_opacity=0.0;this._0.stroke_width=5;this._0.line(this._1,r,this._1+this._6,r);this._0.pop()}Bluff.each(this._9,function(o){var p=null,q=null;Bluff.each(o[this.klass.DATA_VALUES_INDEX],function(c,d){if(c===undefined)return;var f=d*Math.PI*2/this._5,g=c*this._v,h=this._w+Math.sin(f)*g,i=this._x-Math.cos(f)*g,j=(d+10){this._0.fill=c[this.klass.DATA_COLOR_INDEX];var f=(c[this.klass.DATA_VALUES_INDEX][0]/o)*360;this._0.circle(n,m,n+k,m,p,p+f+0.5);var g=p+((p+f)-p)/2,h=Math.round((c[this.klass.DATA_VALUES_INDEX][0]/o)*100.0),i;if(h>=this.hide_labels_less_than){i=this._15(c[this.klass.DATA_VALUES_INDEX][0]);this._c(n,m,g,k+(k*this.klass.TEXT_OFFSET_PERCENTAGE),i)}p+=f}},this)},_c:function(c,d,f,g,h){var i=20.0,j=c,k=d,l=g+i,n=l*0.15,m=j+((l+n)*Math.cos(f*Math.PI/180)),o=k+(l*Math.sin(f*Math.PI/180));this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._e(this.marker_font_size);this._0.font_weight='bold';this._0.gravity='center';this._0.annotate_scaled(0,0,m,o,h,this._b)},_1R:function(){var d=0;Bluff.each(this._2,function(c){d+=c[this.klass.DATA_VALUES_INDEX][0]},this);return d}});Bluff.SideBar=new JS.Class(Bluff.Base,{bar_spacing:0.9,draw:function(){this.has_left_labels=true;this.callSuper();if(!this._a)return;this._G=this._3/this._5;this._8=this._G*this.bar_spacing/this._9.length;this._0.stroke_opacity=0.0;var q=Bluff.array_new(this._5,0),s=Bluff.array_new(this._5,this._1),r=(this._G*(1-this.bar_spacing))/2;Bluff.each(this._9,function(m,o){var p=this._2[o][this.klass.DATA_VALUES_INDEX];Bluff.each(m[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._6-c*this._6-q[d]),g=this._1+this._6-q[d],h=g-f,i=s[d]-1,j=this._7+(this._G*d)+(this._8*o)+r,k=i+h,l=j+this._8;q[d]+=(c*this._6);this._0.stroke='transparent';this._0.fill=m[this.klass.DATA_COLOR_INDEX];this._0.rectangle(i,j,k,l);this._E(i,j,k-i,l-j,m[this.klass.DATA_LABEL_INDEX],m[this.klass.DATA_COLOR_INDEX],p[d]);var n=this._7+(this._G*d+this._G/2);this._c(n,d)},this)},this)},_M:function(){if(this.hide_line_markers)return;this._0.stroke_antialias=false;this._0.stroke_width=1;var c=5;var d=this._17(this.maximum_value/c),f,g,h,i;for(var j=0;j<=c;j++){f=(this._l-this._1)/c;g=this._l-(f*j)-1;h=j-c;i=Math.abs(h)*d;this._0.stroke=this.marker_color;this._0.line(g,this._g,g,this._7);if(!this.hide_line_numbers){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.pointsize=this._e(this.marker_font_size);this._0.gravity='center';this._0.annotate_scaled(0,0,g,this._g+(this.klass.LABEL_MARGIN*2.0),i,this._b)}}},_c:function(c,d){if(this.labels[d]&&!this._q[d]){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.font_weight='normal';this._0.pointsize=this._e(this.marker_font_size);this._0.gravity='east';this._0.annotate_scaled(1,1,this._1-this.klass.LABEL_MARGIN*2.0,c,this.labels[d],this._b);this._q[d]=true}}});Bluff.Spider=new JS.Class(Bluff.Base,{hide_text:null,hide_axes:null,transparent_background:null,initialize:function(c,d,f){this.callSuper(c,f);this._1S=d;this.hide_legend=true},draw:function(){this.hide_line_markers=true;this.callSuper();if(!this._a)return;var c=this._3,d=this._3/2.0,f=this._1+(this._6-c)/2.0,g=this._1+(this._6/2.0),h=this._7+(this._3/2.0)-25;this._1T=d/this._1S;var i=this._1U(),j=0.0,k=(2*Math.PI)/this._2.length,l=0.0;if(!this.hide_axes)this._1V(g,h,d,k);this._1W(g,h,k)},_1n:function(c){return c*this._1T},_c:function(c,d,f,g,h){var i=50,j=c,k=d+0,l=j+((g+i)*Math.cos(f)),n=k+((g+i)*Math.sin(f));this._0.fill=this.marker_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._e(this.legend_font_size);this._0.stroke='transparent';this._0.font_weight='bold';this._0.gravity='center';this._0.annotate_scaled(0,0,l,n,h,this._b)},_1V:function(g,h,i,j,k){if(this.hide_axes)return;var l=0.0;Bluff.each(this._2,function(c){this._0.stroke=k||c[this.klass.DATA_COLOR_INDEX];this._0.stroke_width=5.0;var d=i*Math.cos(l);var f=i*Math.sin(l);this._0.line(g,h,g+d,h+f);if(!this.hide_text)this._c(g,h,l,i,c[this.klass.DATA_LABEL_INDEX]);l+=j},this)},_1W:function(d,f,g,h){var i=[],j=0.0;Bluff.each(this._2,function(c){i.push(d+this._1n(c[this.klass.DATA_VALUES_INDEX][0])*Math.cos(j));i.push(f+this._1n(c[this.klass.DATA_VALUES_INDEX][0])*Math.sin(j));j+=g},this);this._0.stroke_width=1.0;this._0.stroke=h||this.marker_color;this._0.fill=h||this.marker_color;this._0.fill_opacity=0.4;this._0.polyline(i)},_1U:function(){var d=0.0;Bluff.each(this._2,function(c){d+=c[this.klass.DATA_VALUES_INDEX][0]},this);return d}});Bluff.Base.StackedMixin=new JS.Module({_19:function(){var g={};Bluff.each(this._2,function(f){Bluff.each(f[this.klass.DATA_VALUES_INDEX],function(c,d){if(!g[d])g[d]=0.0;g[d]+=c},this)},this);for(var h in g){if(g[h]>this.maximum_value)this.maximum_value=g[h]}this.minimum_value=0}});Bluff.StackedArea=new JS.Class(Bluff.Base,{include:Bluff.Base.StackedMixin,last_series_goes_on_bottom:null,draw:function(){this._19();this.callSuper();if(!this._a)return;this._R=this._6/(this._5-1);this._0.stroke='transparent';var n=Bluff.array_new(this._5,0);var m=null;var o=this.last_series_goes_on_bottom?'reverse_each':'each';Bluff[o](this._9,function(h){var i=m;m=[];Bluff.each(h[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._R*d);var g=this._7+(this._3-c*this._3-n[d]);n[d]+=(c*this._3);m.push(f);m.push(g);this._c(f,d)},this);var j,k,l;if(i){j=Bluff.array(m);for(k=i.length/2-1;k>=0;k--){j.push(i[2*k]);j.push(i[2*k+1])}j.push(m[0]);j.push(m[1])}else{j=Bluff.array(m);j.push(this._l);j.push(this._g-1);j.push(this._1);j.push(this._g-1);j.push(m[0]);j.push(m[1])}this._0.fill=h[this.klass.DATA_COLOR_INDEX];this._0.polyline(j)},this)}});Bluff.StackedBar=new JS.Class(Bluff.Base,{include:Bluff.Base.StackedMixin,bar_spacing:0.9,draw:function(){this._19();this.callSuper();if(!this._a)return;this._8=this._6/this._5;var m=(this._8*(1-this.bar_spacing))/2;this._0.stroke_opacity=0.0;var o=Bluff.array_new(this._5,0);Bluff.each(this._9,function(k,l){var n=this._2[l][this.klass.DATA_VALUES_INDEX];Bluff.each(k[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._8*d)+(this._8*this.bar_spacing/2.0);this._c(f,d);if(c==0)return;var g=this._1+(this._8*d)+m;var h=this._7+(this._3-c*this._3-o[d])+1;var i=g+this._8*this.bar_spacing;var j=this._7+this._3-o[d]-1;o[d]+=(c*this._3);this._0.fill=k[this.klass.DATA_COLOR_INDEX];this._0.rectangle(g,h,i,j);this._E(g,h,i-g,j-h,k[this.klass.DATA_LABEL_INDEX],k[this.klass.DATA_COLOR_INDEX],n[d])},this)},this)}});Bluff.AccumulatorBar=new JS.Class(Bluff.StackedBar,{draw:function(){if(this._2.length!==1)throw'Incorrect number of datasets';var g=[],h=0,i=[];Bluff.each(this._2[0][this.klass.DATA_VALUES_INDEX],function(d){var f=-Infinity;Bluff.each(i,function(c){f=Math.max(f,c)});i.push((h>0)?(d+f):d);g.push(i[h]-d);h+=1},this);this.data("Accumulator",g);this.callSuper()}});Bluff.SideStackedBar=new JS.Class(Bluff.SideBar,{include:Bluff.Base.StackedMixin,bar_spacing:0.9,draw:function(){this.has_left_labels=true;this._19();this.callSuper();if(!this._a)return;this._8=this._3/this._5;var q=Bluff.array_new(this._5,0),s=Bluff.array_new(this._5,this._1),r=(this._8*(1-this.bar_spacing))/2;Bluff.each(this._9,function(m,o){this._0.fill=m[this.klass.DATA_COLOR_INDEX];var p=this._2[o][this.klass.DATA_VALUES_INDEX];Bluff.each(m[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._6-c*this._6-q[d])+1;var g=this._1+this._6-q[d]-1;var h=g-f;var i=s[d],j=this._7+(this._8*d)+r,k=i+h,l=j+this._8*this.bar_spacing;s[d]+=h;q[d]+=(c*this._6-2);this._0.rectangle(i,j,k,l);this._E(i,j,k-i,l-j,m[this.klass.DATA_LABEL_INDEX],m[this.klass.DATA_COLOR_INDEX],p[d]);var n=this._7+(this._8*d)+(this._8*this.bar_spacing/2.0);this._c(n,d)},this)},this)},_1f:function(c,d){d=d||0;return this._1m(c,d)>this.maximum_value},_1m:function(d,f){var g=0;Bluff.each(this._2,function(c){g+=c[this.klass.DATA_VALUES_INDEX][f]},this);return g}});Bluff.Mini.Legend=new JS.Module({hide_mini_legend:false,_1a:function(){if(this.hide_mini_legend)return;this._1X=this._L;this._y+=this._2.length*this._D(this._e(this.legend_font_size))*1.7;this._X()},_1b:function(){if(this.hide_mini_legend)return;this._P=Bluff.map(this._2,function(c){return c[this.klass.DATA_LABEL_INDEX]},this);var f=40.0,g=10.0,h=100.0,i=40.0;if(this.font)this._0.font=this.font;this._0.pointsize=this.legend_font_size;var j=h,k=this._1X+i;this._u(function(){this._0.line(0.0,k,this._d,k)});Bluff.each(this._P,function(c,d){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._e(this.legend_font_size);this._0.stroke='transparent';this._0.font_weight='normal';this._0.gravity='west';this._0.annotate_scaled(this._d,1.0,j+(f*1.7),k,this._1Y(c),this._b);this._0.stroke='transparent';this._0.fill=this._2[d][this.klass.DATA_COLOR_INDEX];this._0.rectangle(j,k-f/2.0,j+f,k+f/2.0);k+=this._D(this.legend_font_size)*1.7},this);this._m=0},_1Y:function(c){var d=String(c);while(this._O(this._e(this.legend_font_size),d)>(this._j-this.legend_left_margin-this.right_margin)&&(d.length>1))d=d.substr(0,d.length-1);return d+(d.length=1?(c*i):1;var k=(d*i)>=1?(d*i):1;var h=this._T(this.pointsize,h);h.style.color=this.fill;h.style.fontWeight=this.font_weight;h.style.textAlign='center';h.style.left=(this._f*f+this._1Z(h,j))+'px';h.style.top=(this._h*g+this._20(h,k))+'px'},tooltip:function(d,f,g,h,i,j,k){if(g<0)d+=g;if(h<0)f+=h;var l=this._n.parentNode,n=document.createElement('div');n.className=this.klass.TARGET_CLASS;n.style.position='absolute';n.style.left=(this._f*d-3)+'px';n.style.top=(this._h*f-3)+'px';n.style.width=(this._f*Math.abs(g)+5)+'px';n.style.height=(this._h*Math.abs(h)+5)+'px';n.style.fontSize=0;n.style.overflow='hidden';Bluff.Event.observe(n,'mouseover',function(c){Bluff.Tooltip.show(i,j,k)});Bluff.Event.observe(n,'mouseout',function(c){Bluff.Tooltip.hide()});l.appendChild(n)},circle:function(c,d,f,g,h,i){var j=Math.sqrt(Math.pow(f-c,2)+Math.pow(g-d,2));this._4.fillStyle=this.fill;this._4.beginPath();var k=(h||0)*Math.PI/180;var l=(i||360)*Math.PI/180;if(h!==undefined&&i!==undefined){this._4.moveTo(this._f*(c+j*Math.cos(l)),this._h*(d+j*Math.sin(l)));this._4.lineTo(this._f*c,this._h*d);this._4.lineTo(this._f*(c+j*Math.cos(k)),this._h*(d+j*Math.sin(k)))}this._4.arc(this._f*c,this._h*d,this._f*j,k,l,false);this._4.fill()},line:function(c,d,f,g){this._4.strokeStyle=this.stroke;this._4.lineWidth=this.stroke_width;this._4.beginPath();this._4.moveTo(this._f*c,this._h*d);this._4.lineTo(this._f*f,this._h*g);this._4.stroke()},polyline:function(c){this._4.fillStyle=this.fill;this._4.globalAlpha=this.fill_opacity||1;try{this._4.strokeStyle=this.stroke}catch(e){}var d=c.shift(),f=c.shift();this._4.beginPath();this._4.moveTo(this._f*d,this._h*f);while(c.length>0){d=c.shift();f=c.shift();this._4.lineTo(this._f*d,this._h*f)}this._4.fill()},rectangle:function(c,d,f,g){var h;if(c>f){h=c;c=f;f=h}if(d>g){h=d;d=g;g=h}try{this._4.fillStyle=this.fill;this._4.fillRect(this._f*c,this._h*d,this._f*(f-c),this._h*(g-d))}catch(e){}try{this._4.strokeStyle=this.stroke;if(this.stroke!=='transparent')this._4.strokeRect(this._f*c,this._h*d,this._f*(f-c),this._h*(g-d))}catch(e){}},_1Z:function(c,d){var f=this._H(c).width;switch(this.gravity){case'west':return 0;case'east':return d-f;case'north':case'south':case'center':return(d-f)/2}},_20:function(c,d){var f=this._H(c).height;switch(this.gravity){case'north':return 0;case'south':return d-f;case'west':case'east':case'center':return(d-f)/2}},_1o:function(){var c=this._n.parentNode;if(c.className===this.klass.WRAPPER_CLASS)return c;c=document.createElement('div');c.className=this.klass.WRAPPER_CLASS;c.style.position='relative';c.style.border='none';c.style.padding='0 0 0 0';this._n.parentNode.insertBefore(c,this._n);c.appendChild(this._n);return c},_T:function(c,d){var f=this._21(d);f.style.fontFamily=this.font;f.style.fontSize=(typeof c==='number')?c+'px':c;return f},_21:function(c){var d=document.createElement('div');d.className=this.klass.TEXT_CLASS;d.style.position='absolute';d.appendChild(document.createTextNode(c));this._1o().appendChild(d);return d},_U:function(c){c.parentNode.removeChild(c);if(c.className===this.klass.TARGET_CLASS)Bluff.Event.stopObserving(c)},_H:function(c){var d=c.style.display;return(d&&d!=='none')?{width:c.offsetWidth,height:c.offsetHeight}:{width:c.clientWidth,height:c.clientHeight}}});Bluff.Event={_V:[],_1p:(window.attachEvent&&navigator.userAgent.indexOf('Opera')===-1),observe:function(d,f,g,h){var i=Bluff.map(this._1q(d,f),function(c){return c._22});if(Bluff.index(i,g)!==-1)return;var j=function(c){g.call(h||null,d,Bluff.Event._23(c))};this._V.push({_W:d,_1c:f,_22:g,_1r:j});if(d.addEventListener)d.addEventListener(f,j,false);else d.attachEvent('on'+f,j)},stopObserving:function(d){var f=d?this._1q(d):this._V;Bluff.each(f,function(c){if(c._W.removeEventListener)c._W.removeEventListener(c._1c,c._1r,false);else c._W.detachEvent('on'+c._1c,c._1r)})},_1q:function(d,f){var g=[];Bluff.each(this._V,function(c){if(d&&c._W!==d)return;if(f&&c._1c!==f)return;g.push(c)});return g},_23:function(c){if(!this._1p)return c;if(!c)return false;if(c._24)return c;c._24=true;var d=this._25(c);c.target=c.srcElement;c.pageX=d.x;c.pageY=d.y;return c},_25:function(c){var d=document.documentElement,f=document.body||{scrollLeft:0,scrollTop:0};return{x:c.pageX||(c.clientX+(d.scrollLeft||f.scrollLeft)-(d.clientLeft||0)),y:c.pageY||(c.clientY+(d.scrollTop||f.scrollTop)-(d.clientTop||0))}}};if(Bluff.Event._1p)window.attachEvent('onunload',function(){Bluff.Event.stopObserving();Bluff.Event._V=null});if(navigator.userAgent.indexOf('AppleWebKit/')>-1)window.addEventListener('unload',function(){},false);Bluff.Tooltip=new JS.Singleton({LEFT_OFFSET:20,TOP_OFFSET:-6,DATA_LENGTH:8,CLASS_NAME:'bluff-tooltip',setup:function(){this._o=document.createElement('div');this._o.className=this.CLASS_NAME;this._o.style.position='absolute';this.hide();document.body.appendChild(this._o);Bluff.Event.observe(document.body,'mousemove',function(c,d){this._o.style.left=(d.pageX+this.LEFT_OFFSET)+'px';this._o.style.top=(d.pageY+this.TOP_OFFSET)+'px'},this)},show:function(c,d,f){f=Number(String(f).substr(0,this.DATA_LENGTH));this._o.innerHTML='  '+c+' '+f+'';this._o.style.display=''},hide:function(){this._o.style.display='none'}});Bluff.Event.observe(window,'load',Bluff.Tooltip.method('setup'));Bluff.TableReader=new JS.Class({NUMBER_FORMAT:/\-?(0|[1-9]\d*)(\.\d+)?(e[\+\-]?\d+)?/i,initialize:function(c,d){this._26=(typeof c==='string')?document.getElementById(c):c;this._1s=!!d},get_data:function(){if(!this._2)this._1t();return this._2},get_labels:function(){if(!this._1d)this._1t();return this._1d},get_title:function(){return this._27},get_series:function(c){if(this._2[c])return this._2[c];return this._2[c]={points:[]}},_1t:function(){this._I=this._p=0;this._J=this._K=0;this._2=[];this._1d={};this._s=[];this._t=[];this._1u(this._26);if((this._s.length>1&&this._t.length===1)||this._s.length]+>/gi,'')},extend:{Mixin:new JS.Module({data_from_table:function(d,f){var g=new Bluff.TableReader(d,f),h=g.get_data();Bluff.each(h,function(c){this.data(c.name,c.points)},this);this.labels=g.get_labels();this.title=g.get_title()||this.title}})}});Bluff.Base.include(Bluff.TableReader.Mixin); -------------------------------------------------------------------------------- /results/excanvas.js: -------------------------------------------------------------------------------- 1 | // Copyright 2006 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | document.createElement("canvas").getContext||(function(){var s=Math,j=s.round,F=s.sin,G=s.cos,V=s.abs,W=s.sqrt,k=10,v=k/2;function X(){return this.context_||(this.context_=new H(this))}var L=Array.prototype.slice;function Y(b,a){var c=L.call(arguments,2);return function(){return b.apply(a,c.concat(L.call(arguments)))}}var M={init:function(b){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var a=b||document;a.createElement("canvas");a.attachEvent("onreadystatechange",Y(this.init_,this,a))}},init_:function(b){b.namespaces.g_vml_|| 15 | b.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML");b.namespaces.g_o_||b.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML");if(!b.styleSheets.ex_canvas_){var a=b.createStyleSheet();a.owningElement.id="ex_canvas_";a.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}g_vml_\\:*{behavior:url(#default#VML)}g_o_\\:*{behavior:url(#default#VML)}"}var c=b.getElementsByTagName("canvas"),d=0;for(;d','","");this.element_.insertAdjacentHTML("BeforeEnd",t.join(""))};i.stroke=function(b){var a=[],c=P(b?this.fillStyle:this.strokeStyle),d=c.color,f=c.alpha*this.globalAlpha;a.push("g.x)g.x=e.x;if(h.y==null||e.yg.y)g.y=e.y}}a.push(' ">');if(b)if(typeof this.fillStyle=="object"){var m=this.fillStyle,r=0,n={x:0,y:0},o=0,q=1;if(m.type_=="gradient"){var t=m.x1_/this.arcScaleX_,E=m.y1_/this.arcScaleY_,p=this.getCoords_(m.x0_/this.arcScaleX_,m.y0_/this.arcScaleY_), 30 | z=this.getCoords_(t,E);r=Math.atan2(z.x-p.x,z.y-p.y)*180/Math.PI;if(r<0)r+=360;if(r<1.0E-6)r=0}else{var p=this.getCoords_(m.x0_,m.y0_),w=g.x-h.x,x=g.y-h.y;n={x:(p.x-h.x)/w,y:(p.y-h.y)/x};w/=this.arcScaleX_*k;x/=this.arcScaleY_*k;var R=s.max(w,x);o=2*m.r0_/R;q=2*m.r1_/R-o}var u=m.colors_;u.sort(function(ba,ca){return ba.offset-ca.offset});var J=u.length,da=u[0].color,ea=u[J-1].color,fa=u[0].alpha*this.globalAlpha,ga=u[J-1].alpha*this.globalAlpha,S=[],l=0;for(;l')}else a.push('');else{var K=this.lineScale_*this.lineWidth;if(K<1)f*=K;a.push("')}a.push("");this.element_.insertAdjacentHTML("beforeEnd",a.join(""))};i.fill=function(){this.stroke(true)};i.closePath=function(){this.currentPath_.push({type:"close"})};i.getCoords_=function(b,a){var c=this.m_;return{x:k*(b*c[0][0]+a*c[1][0]+c[2][0])-v,y:k*(b*c[0][1]+a*c[1][1]+c[2][1])-v}};i.save=function(){var b={};O(this,b);this.aStack_.push(b);this.mStack_.push(this.m_);this.m_=y(I(),this.m_)};i.restore=function(){O(this.aStack_.pop(), 33 | this);this.m_=this.mStack_.pop()};function ha(b){var a=0;for(;a<3;a++){var c=0;for(;c<2;c++)if(!isFinite(b[a][c])||isNaN(b[a][c]))return false}return true}function A(b,a,c){if(!!ha(a)){b.m_=a;if(c)b.lineScale_=W(V(a[0][0]*a[1][1]-a[0][1]*a[1][0]))}}i.translate=function(b,a){A(this,y([[1,0,0],[0,1,0],[b,a,1]],this.m_),false)};i.rotate=function(b){var a=G(b),c=F(b);A(this,y([[a,c,0],[-c,a,0],[0,0,1]],this.m_),false)};i.scale=function(b,a){this.arcScaleX_*=b;this.arcScaleY_*=a;A(this,y([[b,0,0],[0,a, 34 | 0],[0,0,1]],this.m_),true)};i.transform=function(b,a,c,d,f,h){A(this,y([[b,a,0],[c,d,0],[f,h,1]],this.m_),true)};i.setTransform=function(b,a,c,d,f,h){A(this,[[b,a,0],[c,d,0],[f,h,1]],true)};i.clip=function(){};i.arcTo=function(){};i.createPattern=function(){return new U};function D(b){this.type_=b;this.r1_=this.y1_=this.x1_=this.r0_=this.y0_=this.x0_=0;this.colors_=[]}D.prototype.addColorStop=function(b,a){a=P(a);this.colors_.push({offset:b,color:a.color,alpha:a.alpha})};function U(){}G_vmlCanvasManager= 35 | M;CanvasRenderingContext2D=H;CanvasGradient=D;CanvasPattern=U})(); 36 | -------------------------------------------------------------------------------- /results/js-class.js: -------------------------------------------------------------------------------- 1 | JS={extend:function(a,b){b=b||{};for(var c in b){if(a[c]===b[c])continue;a[c]=b[c]}return a},makeFunction:function(){return function(){return this.initialize?(this.initialize.apply(this,arguments)||this):this}},makeBridge:function(a){var b=function(){};b.prototype=a.prototype;return new b},bind:function(){var a=JS.array(arguments),b=a.shift(),c=a.shift()||null;return function(){return b.apply(c,a.concat(JS.array(arguments)))}},callsSuper:function(a){return a.SUPER===undefined?a.SUPER=/\bcallSuper\b/.test(a.toString()):a.SUPER},mask:function(a){var b=a.toString().replace(/callSuper/g,'super');a.toString=function(){return b};return a},array:function(a){if(!a)return[];if(a.toArray)return a.toArray();var b=a.length,c=[];while(b--)c[b]=a[b];return c},indexOf:function(a,b){for(var c=0,d=a.length;c':''),d=this.__meta__=new JS.Module(c?c+'.':'',{},{_1:this});d.include(this.klass.__mod__,false);return d},equals:function(a){return this===a},extend:function(a,b){return this.__eigen__().include(a,b,{_2:this})},hash:function(){return this.__hashcode__=this.__hashcode__||JS.Kernel.getHashCode()},isA:function(a){return this.__eigen__().includes(a)},method:function(a){var b=this,c=b.__mcache__=b.__mcache__||{};if((c[a]||{}).fn===b[a])return c[a].bd;return(c[a]={fn:b[a],bd:JS.bind(b[a],b)}).bd},methods:function(){return this.__eigen__().instanceMethods(true)},tap:function(a,b){a.call(b||null,this);return this}}),{__hashIndex__:0,getHashCode:function(){this.__hashIndex__+=1;return(Math.floor(new Date().getTime()/1000)+this.__hashIndex__).toString(16)}});JS.Module.include(JS.Kernel);JS.extend(JS.Module,JS.Kernel.__fns__);JS.Class.include(JS.Kernel);JS.extend(JS.Class,JS.Kernel.__fns__);JS.Interface=new JS.Class({initialize:function(d){this.test=function(a,b){var c=d.length;while(c--){if(!JS.isFn(a[d[c]]))return b?d[c]:false}return true}},extend:{ensure:function(){var a=JS.array(arguments),b=a.shift(),c,d;while(c=a.shift()){d=c.test(b,true);if(d!==true)throw new Error('object does not implement '+d+'()');}}}});JS.Singleton=new JS.Class({initialize:function(a,b,c){return new(new JS.Class(a,b,c))}}); -------------------------------------------------------------------------------- /results/locked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/results/locked.png -------------------------------------------------------------------------------- /results/marker-few-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/results/marker-few-open.png -------------------------------------------------------------------------------- /results/marker-few.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/results/marker-few.png -------------------------------------------------------------------------------- /results/marker-many-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/results/marker-many-open.png -------------------------------------------------------------------------------- /results/marker-many.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/results/marker-many.png -------------------------------------------------------------------------------- /results/marker-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/results/marker-open.png -------------------------------------------------------------------------------- /results/marker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/results/marker.png -------------------------------------------------------------------------------- /results/wifi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/results/wifi.png -------------------------------------------------------------------------------- /scanner/locked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/scanner/locked.png -------------------------------------------------------------------------------- /scanner/unlocked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cyberpython/WifiScanAndMap/789a95fb23d0dda4a50053194daa64a15b853cb6/scanner/unlocked.png -------------------------------------------------------------------------------- /scanner/wifiScanner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | Copyright 2010 Filia Dova, Georgios Migdos 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | ''' 18 | 19 | import subprocess 20 | import threading 21 | import time 22 | from gps import * 23 | import os 24 | import sys 25 | from os import path 26 | import commands 27 | 28 | 29 | #====================================================================================================================== 30 | 31 | #--- Simple helper class: 32 | #--- (method names are self-explanatory) 33 | 34 | class Utilities: 35 | def getWirelessInterfacesList(self): 36 | networkInterfaces=[] 37 | command = ["iwconfig"] 38 | process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 39 | process.wait() 40 | (stdoutdata, stderrdata) = process.communicate(); 41 | output = stdoutdata 42 | lines = output.splitlines() 43 | for line in lines: 44 | if(line.find("IEEE 802.11")!=-1): 45 | networkInterfaces.append(line.split()[0]) 46 | return networkInterfaces 47 | 48 | def checkIfGpsdIsRunning(self): 49 | output = commands.getoutput('ps -A') 50 | if 'gpsd' in output: 51 | return True 52 | else: 53 | return False 54 | 55 | 56 | #====================================================================================================================== 57 | 58 | #--- Class that calls iwlist periodically 59 | #--- and parses its output - also gets GPS data from gpsd: 60 | 61 | class wifiScanner(threading.Thread): 62 | 63 | def __init__(self, wifiNetworks, interval): 64 | self.stopThread = threading.Event() 65 | self.wifiNetworks = wifiNetworks 66 | self.interval = interval 67 | self.setWirelessInterface(None) 68 | self.session = gps(mode=WATCH_ENABLE) 69 | self.scanning = False 70 | threading.Thread.__init__(self) 71 | 72 | def run(self): 73 | self.stopThread.clear() 74 | self.scanning = True 75 | 76 | while( not self.stopThread.isSet() ): 77 | self.scanForWifiNetworks() 78 | time.sleep(self.interval) 79 | 80 | self.scanning = False 81 | 82 | 83 | def stop(self): 84 | self.stopThread.set() 85 | 86 | def isScanning(self): 87 | return self.scanning 88 | 89 | def getGPSData(self): 90 | # Get GPS data from gpsd 91 | # a = altitude, d = date/time, m=mode, 92 | # o=postion/fix, s=status, y=satellites 93 | #self.session.query('o') 94 | self.session.next() 95 | longtitude = self.session.fix.longitude 96 | latitude = self.session.fix.latitude 97 | return (longtitude, latitude) 98 | 99 | def getWifiNetworksList(self): 100 | result = [] 101 | for k,v in self.wifiNetworks.iteritems(): 102 | result.append(v) 103 | return result 104 | 105 | def setWirelessInterface(self, iface): 106 | self.wIface = iface 107 | 108 | def getWirelessInterface(self): 109 | return self.wIface 110 | 111 | 112 | def scanForWifiNetworks(self): 113 | networkInterface = self.wIface 114 | output = "" 115 | if(networkInterface!=None): 116 | command = ["iwlist", networkInterface, "scanning"] 117 | process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 118 | process.wait() 119 | (stdoutdata, stderrdata) = process.communicate(); 120 | output = stdoutdata 121 | self.parseIwlistOutput(output) 122 | 123 | 124 | def cutFrom(self, s, pattern): 125 | index = s.find(pattern) 126 | if(index>-1): 127 | return s[index+len(pattern):] 128 | else: 129 | return "" 130 | 131 | def cutTo(self, s, pattern): 132 | index = s.find(pattern) 133 | if(index>-1): 134 | return s[:index] 135 | else: 136 | return s 137 | 138 | def parseIwlistOutput(self, output): 139 | output = self.cutFrom(output, "Address:") 140 | while (output!=""): 141 | entry = self.cutTo(output, "Address:") 142 | 143 | address = "" 144 | essid = "" 145 | mode = "" 146 | channel = "" 147 | frequency = "" 148 | quality = "" 149 | signal = "" 150 | noise = "" 151 | encryption = "" 152 | 153 | address = entry[1:18] 154 | 155 | startIndex = entry.find("ESSID:\"") 156 | if(startIndex > -1): 157 | endIndex = entry.find("\"\n", startIndex) 158 | essid = entry[startIndex+7:endIndex] 159 | 160 | startIndex = entry.find("Mode:") 161 | if(startIndex > -1): 162 | endIndex = entry.find("\n", startIndex) 163 | mode = entry[startIndex+5:endIndex] 164 | 165 | startIndex = entry.find("Channel:") 166 | if(startIndex > -1): 167 | endIndex = entry.find("\n", startIndex) 168 | channel = entry[startIndex+8:endIndex] 169 | 170 | startIndex = entry.find("Frequency:") 171 | if(startIndex > -1): 172 | endIndex = entry.find("\n", startIndex) 173 | frequency = entry[startIndex+10:endIndex] 174 | 175 | startIndex = entry.find("Quality=") 176 | if(startIndex > -1): 177 | endIndex = entry.find("Signal", startIndex) -2 178 | qual = eval(entry[startIndex+8:endIndex]+".0") 179 | if(qual > 1.0): 180 | qual = 1.0 181 | quality = str(qual) 182 | 183 | startIndex = entry.find("Signal level:") 184 | if(startIndex > -1): 185 | endIndex = entry.find("dBm", startIndex) -1 186 | signal = entry[startIndex+13:endIndex] 187 | 188 | startIndex = entry.find("Noise level=") 189 | if(startIndex > -1): 190 | endIndex = entry.find("dBm", startIndex) -1 191 | noise = entry[startIndex+12:endIndex] 192 | 193 | startIndex = entry.find("Encryption key:") 194 | if(startIndex > -1): 195 | endIndex = entry.find("\n", startIndex) 196 | encryption = entry[startIndex+15:endIndex] 197 | 198 | longtitude, latitude = self.getGPSData() 199 | 200 | key = (address, essid) 201 | value = [address, essid, mode, channel, frequency, quality, signal, noise, encryption, str(latitude), str(longtitude)] 202 | try: 203 | oldValue = self.wifiNetworks[key] 204 | qualityN = eval(quality) 205 | oldQualityN = eval(oldValue[5]) 206 | oldLat = oldValue[9] 207 | oldLon = oldValue[10] 208 | if ( ( qualityN > oldQualityN) or ( (oldLat=="0.0") and (oldLon=="0.0") ) ): 209 | self.wifiNetworks[key] = value 210 | except KeyError: 211 | self.wifiNetworks[key] = value 212 | 213 | output = self.cutFrom(output, "Address:") 214 | 215 | 216 | 217 | def exportXML(self, filename): 218 | out = open(filename, 'w') 219 | out.write('\n') 220 | out.write("\n") 221 | 222 | lst = self.getWifiNetworksList() 223 | for l in lst: 224 | out.write("\t\n") 225 | 226 | out.write("\t\t
"+ l[0] +"
\n") 227 | out.write("\t\t"+ l[1] +"\n") 228 | out.write("\t\t"+ l[2] +"\n") 229 | out.write("\t\t"+ l[3] +"\n") 230 | out.write("\t\t"+ l[4] +"\n") 231 | out.write("\t\t"+ l[5] +"\n") 232 | out.write("\t\t"+ l[6] +"\n") 233 | out.write("\t\t"+ l[7] +"\n") 234 | out.write("\t\t"+ l[8] +"\n") 235 | out.write("\t\t"+ l[9] +"\n") 236 | out.write("\t\t"+ l[10] +"\n") 237 | 238 | out.write("\t
\n") 239 | 240 | out.write("
\n") 241 | out.close() 242 | 243 | 244 | 245 | #====================================================================================================================== 246 | 247 | #--- Class that is used to print 248 | #--- results to stdout 249 | 250 | class resultCLIPrinter(threading.Thread): 251 | 252 | def __init__(self, interval, scanner, msg): 253 | self.stopThread = threading.Event() 254 | self.scanner = scanner 255 | self.interval = interval 256 | self.msg = msg 257 | threading.Thread.__init__(self) 258 | 259 | def run(self): 260 | self.stopThread.clear() 261 | 262 | while( not self.stopThread.isSet() ): 263 | os.system("clear") 264 | lst = self.scanner.getWifiNetworksList() 265 | for l in lst: 266 | print l 267 | print "--------------------" 268 | print self.msg 269 | time.sleep(self.interval) 270 | 271 | 272 | def stop(self): 273 | self.stopThread.set() 274 | 275 | 276 | 277 | 278 | 279 | #====================================================================================================================== 280 | 281 | #--- Simple CLI application: 282 | 283 | class CLIApplication: 284 | 285 | def __init__(self): 286 | self.wifiNetworks={} 287 | self.SCANNER_INTERVAL = 5 288 | self.UPDATE_INTERVAL = 2 289 | self.checkForGpsd() 290 | self.scanner = wifiScanner(self.wifiNetworks, self.SCANNER_INTERVAL) 291 | self.resultsPrinter = resultCLIPrinter(self.UPDATE_INTERVAL, self.scanner, "Press enter key to stop scanning") 292 | 293 | def checkForGpsd(self): 294 | if( not Utilities().checkIfGpsdIsRunning()): 295 | print "gpsd is not running!" 296 | device = raw_input("Please enter which GPS device gpsd should use: ") 297 | while (not os.path.exists(device)): 298 | print "Invalid device!" 299 | device = raw_input("Please enter which GPS device gpsd should use: ") 300 | process = subprocess.Popen(["gpsd", device]) 301 | process.wait() 302 | 303 | def run(self): 304 | os.system("clear") 305 | print "Available wireless interfaces:" 306 | wifiInterfacesList = Utilities().getWirelessInterfacesList() 307 | if(len(wifiInterfacesList)==0): 308 | print "\tNone\n" 309 | print "Get a wireless card and try again! Bye, bye..." 310 | exit(1) 311 | else: 312 | for wi in wifiInterfacesList: 313 | print "\t- "+wi 314 | 315 | wifiInterfaceName = raw_input("Wireless interface to use: ") 316 | if( not (wifiInterfaceName in wifiInterfacesList) ): 317 | print "Error: Invalid wireless interface!" 318 | exit(1) 319 | 320 | self.scanner.setWirelessInterface(wifiInterfaceName) 321 | 322 | self.scanner.start() 323 | self.resultsPrinter.start() 324 | 325 | x=raw_input() 326 | 327 | self.resultsPrinter.stop() 328 | self.scanner.stop() 329 | 330 | answer = raw_input("Would you like to save the results as an XML file (y = yes)? ") 331 | if(answer == "y"): 332 | fname = raw_input("Filename: ") 333 | self.scanner.exportXML(fname) 334 | 335 | 336 | 337 | #====================================================================================================================== 338 | 339 | #--- GUI application: 340 | 341 | class GUIApplication: 342 | 343 | def __init__(self): 344 | 345 | self.checkForGpsd() 346 | 347 | self.initialize() 348 | self.associateGUIElements() 349 | self.createComboBox() 350 | self.createListview() 351 | self.bindEvents() 352 | 353 | self.updater = ListviewUpdater(self, self.discoveredLabel, self.UPDATE_INTERVAL) 354 | self.updater.start() 355 | 356 | self.window.show_all() 357 | 358 | 359 | def initialize(self): 360 | self.wifiNetworks = {} 361 | self.SCANNER_INTERVAL = 5 362 | self.UPDATE_INTERVAL = 2 363 | self.scanner = wifiScanner(self.wifiNetworks, self.SCANNER_INTERVAL) 364 | self.gladefile = path.join(path.dirname(__file__), "wnmc.glade") 365 | self.wTree = gtk.glade.XML(self.gladefile) 366 | 367 | def checkForGpsd(self): 368 | if( not Utilities().checkIfGpsdIsRunning()): 369 | device = self.showEnterGPSDeviceDialog('Please enter which GPS device to use:') 370 | while ( (device!=None) and (not os.path.exists(device)) ): 371 | device = self.showEnterGPSDeviceDialog('Invalid device!\nPlease enter which GPS device to use:') 372 | if(device==None): 373 | exit(0) 374 | process = subprocess.Popen(["gpsd", device]) 375 | process.wait() 376 | 377 | def on_quit(self, sender, arg=None): 378 | self.quit() 379 | 380 | def quit(self): 381 | if(self.updater!=None): 382 | self.updater.stop() 383 | if(self.scanner!=None): 384 | self.scanner.stop() 385 | gtk.main_quit() 386 | 387 | def run(self): 388 | gtk.main() 389 | 390 | def getScanner(self): 391 | return self.scanner 392 | 393 | def getListview(self): 394 | return self.listview 395 | 396 | def getNetworks(self): 397 | return self.wifiNetworks 398 | 399 | def getNumberOfNetworks(self): 400 | return len(self.wifiNetworks) 401 | 402 | # def setRGBAColorMap(self, widget): 403 | # screen = widget.get_screen() 404 | # rgba = screen.get_rgba_colormap() 405 | # widget.set_colormap(rgba) 406 | 407 | def associateGUIElements(self): 408 | self.window = self.wTree.get_widget("window1") 409 | #self.setRGBAColorMap(self.window) 410 | self.scrolledWindow1 = self.wTree.get_widget("scrolledwindow1") 411 | self.statusLabel = self.wTree.get_widget("label1") 412 | self.discoveredLabel = self.wTree.get_widget("label3") 413 | self.quitButton = self.wTree.get_widget("button1") 414 | self.startStopButton = self.wTree.get_widget("button2") 415 | self.exportXMLButton = self.wTree.get_widget("button3") 416 | 417 | 418 | # --- Network interface selection combobox: 419 | 420 | def createComboBox(self): 421 | self.comboBox1 = gtk.combo_box_new_text() 422 | self.wTree.get_widget("hbox1").pack_start(self.comboBox1, expand=False) 423 | self.updateComboBoxModel() 424 | 425 | def updateComboBoxModel(self): 426 | self.comboBox1.get_model().clear() 427 | items = Utilities().getWirelessInterfacesList() 428 | for item in items: 429 | self.comboBox1.append_text(item) 430 | if(len(items)>0): 431 | self.comboBox1.set_active(0) 432 | 433 | 434 | #--- Wifi networks listview: 435 | 436 | def createListview(self): 437 | self.listviewModel = self.createListviewModel() 438 | self.listview = gtk.TreeView(self.listviewModel) 439 | self.scrolledWindow1.add(self.listview) 440 | self.createListviewColumns(self.listview) 441 | self.listview.set_reorderable(False) 442 | 443 | 444 | def createListviewModel(self): 445 | networksList = [] 446 | listviewModel = gtk.ListStore(str, str, str, str, str, float, str, str, gtk.gdk.Pixbuf, str, str) 447 | return listviewModel 448 | 449 | def createListviewColumns(self, listview): 450 | rendererText = gtk.CellRendererText() 451 | column = gtk.TreeViewColumn("ESSID", rendererText, text=1) 452 | column.set_sort_column_id(-1) 453 | listview.append_column(column) 454 | 455 | rendererText = gtk.CellRendererText() 456 | column = gtk.TreeViewColumn("Address", rendererText, text=0) 457 | column.set_sort_column_id(-1) 458 | listview.append_column(column) 459 | 460 | rendererText = gtk.CellRendererText() 461 | column = gtk.TreeViewColumn("Mode", rendererText, text=2) 462 | column.set_sort_column_id(-1) 463 | listview.append_column(column) 464 | 465 | rendererText = gtk.CellRendererText() 466 | column = gtk.TreeViewColumn("Channel", rendererText, text=3) 467 | column.set_sort_column_id(-1) 468 | listview.append_column(column) 469 | 470 | rendererText = gtk.CellRendererText() 471 | column = gtk.TreeViewColumn("Frequency", rendererText, text=4) 472 | column.set_sort_column_id(-1) 473 | listview.append_column(column) 474 | 475 | rendererProgress = gtk.CellRendererProgress() 476 | column = gtk.TreeViewColumn("Quality", rendererProgress, value=5) 477 | column.set_sort_column_id(-1) 478 | listview.append_column(column) 479 | 480 | rendererText = gtk.CellRendererText() 481 | column = gtk.TreeViewColumn("Signal", rendererText, text=6) 482 | column.set_sort_column_id(-1) 483 | listview.append_column(column) 484 | 485 | rendererText = gtk.CellRendererText() 486 | column = gtk.TreeViewColumn("Noise", rendererText, text=7) 487 | column.set_sort_column_id(-1) 488 | listview.append_column(column) 489 | 490 | rendererPixbuf = gtk.CellRendererPixbuf() 491 | column = gtk.TreeViewColumn("Security", rendererPixbuf, pixbuf=8) 492 | column.set_sort_column_id(-1) 493 | listview.append_column(column) 494 | 495 | rendererText = gtk.CellRendererText() 496 | column = gtk.TreeViewColumn("Latitude", rendererText, text=9) 497 | column.set_sort_column_id(-1) 498 | listview.append_column(column) 499 | 500 | rendererText = gtk.CellRendererText() 501 | column = gtk.TreeViewColumn("Longtitude", rendererText, text=10) 502 | column.set_sort_column_id(-1) 503 | listview.append_column(column) 504 | 505 | #--- GUI Events: 506 | 507 | def bindEvents(self): 508 | self.startStopButton.connect("clicked", self.onStartStopButtonClicked) 509 | self.quitButton.connect("clicked", self.onQuitButtonClicked) 510 | self.exportXMLButton.connect("clicked", self.onExportXMLButtonClicked) 511 | 512 | if (self.window): 513 | self.window.connect("destroy", self.on_quit) 514 | 515 | 516 | def onStartStopButtonClicked(self, widget): 517 | if(self.scanner.isScanning()): 518 | self.stopScanning() 519 | self.updateComboBoxModel() 520 | else: 521 | self.startScanning() 522 | 523 | 524 | 525 | def onQuitButtonClicked(self, widget): 526 | self.quit() 527 | 528 | 529 | 530 | def onExportXMLButtonClicked(self, widget): 531 | self.exportXML() 532 | 533 | #--- Application methods: 534 | 535 | def startScanning(self): 536 | if(self.comboBox1.get_active()!=-1): 537 | self.scanner.stop() 538 | 539 | self.comboBox1.set_sensitive(False) 540 | self.exportXMLButton.set_sensitive(False) 541 | self.startStopButton.set_label("Stop scanning") 542 | self.statusLabel.set_text("Scanning for 802.11 networks in range...") 543 | 544 | iface = self.comboBox1.get_model().get_value(self.comboBox1.get_active_iter(), 0) 545 | self.scanner = wifiScanner(self.wifiNetworks, self.SCANNER_INTERVAL) 546 | self.scanner.setWirelessInterface(iface) 547 | self.scanner.start() 548 | 549 | def stopScanning(self): 550 | self.scanner.stop() 551 | self.startStopButton.set_label("Start scanning") 552 | self.startStopButton.set_sensitive(False) 553 | self.statusLabel.set_text("Stopping - Please wait...") 554 | while (self.scanner.isScanning()): 555 | time.sleep(1) 556 | self.statusLabel.set_text("Idle") 557 | self.startStopButton.set_sensitive(True) 558 | self.comboBox1.set_sensitive(True) 559 | self.exportXMLButton.set_sensitive(True) 560 | 561 | 562 | def exportXML(self): 563 | fname = self.getSaveTarget() 564 | if( fname!=None ): 565 | self.scanner.exportXML(fname) 566 | 567 | def getSaveTarget(self): 568 | filename = self.showSaveToXMLDialog() 569 | overwrite = False 570 | while( (filename!=None) and os.path.exists(filename) and (not overwrite) ): 571 | if(self.overwriteFile(filename)): 572 | overwrite = True 573 | else: 574 | filename = self.showSaveToXMLDialog() 575 | return filename 576 | 577 | def showSaveToXMLDialog(self): 578 | dialog = gtk.FileChooserDialog("Save..", self.window, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) 579 | #self.setRGBAColorMap(dialog) 580 | dialog.set_default_response(gtk.RESPONSE_OK) 581 | filter = gtk.FileFilter() 582 | filter.set_name("XML files") 583 | filter.add_mime_type("text/xml") 584 | filter.add_pattern("*.xml") 585 | dialog.add_filter(filter) 586 | response = dialog.run() 587 | if response == gtk.RESPONSE_OK: 588 | result = dialog.get_filename() 589 | elif response == gtk.RESPONSE_CANCEL: 590 | result = None 591 | dialog.destroy() 592 | return result 593 | 594 | def overwriteFile(self, filename): 595 | dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO, "The file: \n\n"+filename+"\n\nalready exists. Overwrite?") 596 | #self.setRGBAColorMap(dialog) 597 | response = dialog.run() 598 | dialog.destroy() 599 | if response == gtk.RESPONSE_YES: 600 | return True 601 | elif response == gtk.RESPONSE_NO: 602 | return False 603 | 604 | def showEnterGPSDeviceDialog(self, msg): 605 | dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, None) 606 | #self.setRGBAColorMap(dialog) 607 | dialog.set_markup(msg) 608 | entry = gtk.Entry() 609 | entry.connect("activate", self.responseToDialog, dialog, gtk.RESPONSE_OK) 610 | hbox = gtk.HBox() 611 | hbox.pack_start(gtk.Label("Device:"), False, 5, 5) 612 | hbox.pack_end(entry) 613 | dialog.vbox.pack_end(hbox, True, True, 0) 614 | dialog.show_all() 615 | response = dialog.run() 616 | device = entry.get_text() 617 | dialog.destroy() 618 | if response == gtk.RESPONSE_CANCEL: 619 | return None 620 | return device 621 | 622 | def responseToDialog(self, entry, dialog, response): 623 | dialog.response(response) 624 | 625 | 626 | #====================================================================================================================== 627 | 628 | #--- Helper class that updates the listview on regular intervals: 629 | 630 | class ListviewUpdater(threading.Thread): 631 | 632 | def __init__(self, parentApp, counterLabel, interval): 633 | self.stopThread = threading.Event() 634 | self.parentApp = parentApp 635 | self.interval = interval 636 | self.counterLabel = counterLabel 637 | self.lockedIcon = gtk.gdk.pixbuf_new_from_file(path.join(path.dirname(__file__), "locked.png")) 638 | self.unlockedIcon = gtk.gdk.pixbuf_new_from_file(path.join(path.dirname(__file__), "unlocked.png")) 639 | threading.Thread.__init__(self) 640 | 641 | def run(self): 642 | self.stopThread.clear() 643 | 644 | while( not self.stopThread.isSet() ): 645 | scanner = self.parentApp.getScanner() 646 | listview = self.parentApp.getListview() 647 | 648 | networksList = scanner.getWifiNetworksList() 649 | listviewModel = gtk.ListStore(str, str, str, str, str, float, str, str, gtk.gdk.Pixbuf, str, str) 650 | for l in networksList: 651 | listviewModel.append( [ l[0], l[1], l[2], l[3], l[4], eval(l[5])*100, l[6], l[7], self.securityStatusToPixbuf(l[8]), l[9], l[10] ] ) 652 | listviewModel.set_sort_column_id(5,gtk.SORT_DESCENDING) 653 | gtk.gdk.threads_enter() 654 | listview.set_model(listviewModel) 655 | self.counterLabel.set_markup("Networks found: "+str(self.parentApp.getNumberOfNetworks())+"") 656 | gtk.gdk.threads_leave() 657 | time.sleep(self.interval) 658 | 659 | 660 | def stop(self): 661 | self.stopThread.set() 662 | 663 | 664 | def securityStatusToBool(self, status): 665 | if(status=="on"): 666 | return True 667 | else: 668 | return False 669 | 670 | def securityStatusToPixbuf(self, status): 671 | if(status=="on"): 672 | return self.lockedIcon 673 | else: 674 | return self.unlockedIcon 675 | 676 | 677 | 678 | #====================================================================================================================== 679 | 680 | #--- Main loop: 681 | 682 | 683 | if "--no-gui" in sys.argv: 684 | import readline 685 | application = CLIApplication() 686 | else: 687 | import gtk 688 | import gtk.glade 689 | gtk.gdk.threads_init() 690 | application = GUIApplication() 691 | 692 | application.run() 693 | 694 | 695 | -------------------------------------------------------------------------------- /scanner/wnmc.glade: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 802.11 Wireless Network Scanner 7 | 640 8 | 480 9 | 10 | 11 | True 12 | vertical 13 | 14 | 15 | True 16 | 17 | 18 | True 19 | <b>Wireless Interface: </b> 20 | True 21 | 22 | 23 | False 24 | 5 25 | 0 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | False 37 | 0 38 | 39 | 40 | 41 | 42 | True 43 | 44 | 45 | True 46 | True 47 | automatic 48 | automatic 49 | in 50 | 51 | 52 | 53 | 54 | 55 | 5 56 | 0 57 | 58 | 59 | 60 | 61 | 1 62 | 63 | 64 | 65 | 66 | True 67 | 68 | 69 | True 70 | 71 | 72 | Start scanning 73 | True 74 | True 75 | True 76 | 77 | 78 | False 79 | False 80 | 0 81 | 82 | 83 | 84 | 85 | Export XML 86 | True 87 | True 88 | True 89 | 90 | 91 | False 92 | False 93 | 1 94 | 95 | 96 | 97 | 98 | False 99 | 5 100 | 0 101 | 102 | 103 | 104 | 105 | True 106 | Networks found: <b>0</b> 107 | True 108 | right 109 | 110 | 111 | False 112 | 5 113 | end 114 | 1 115 | 116 | 117 | 118 | 119 | False 120 | 2 121 | 122 | 123 | 124 | 125 | True 126 | 127 | 128 | False 129 | 5 130 | 3 131 | 132 | 133 | 134 | 135 | True 136 | 137 | 138 | True 139 | Idle 140 | 141 | 142 | False 143 | 5 144 | 0 145 | 146 | 147 | 148 | 149 | True 150 | 151 | 152 | 1 153 | 154 | 155 | 156 | 157 | True 158 | end 159 | 160 | 161 | gtk-quit 162 | True 163 | True 164 | True 165 | True 166 | 167 | 168 | False 169 | False 170 | 0 171 | 172 | 173 | 174 | 175 | False 176 | 5 177 | 2 178 | 179 | 180 | 181 | 182 | False 183 | 10 184 | 4 185 | 186 | 187 | 188 | 189 | 190 | 191 | --------------------------------------------------------------------------------