changeset 0:fb5784aa45e6 default tip

from monotone. problematic https vs v2 API
author Matt Johnston <matt@ucc.asn.au>
date Sun, 21 Oct 2012 23:03:51 +0800
parents
children
files bluedot.png conv.py freenet_data.js labeled_marker.js linkmap.html yellowdot.png
diffstat 6 files changed, 522 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
Binary file bluedot.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/conv.py	Sun Oct 21 23:03:51 2012 +0800
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+# This Python file uses the following encoding: utf-8
+
+import re
+import sys
+
+s = """
+PerthAP: 31°57'34.78"S 115°52'20.29"E
+WannerooAP: 31°47'26.03"S 115°49'12.34"E
+Belmont2: 31°57'34.19"S 115°55'42.52"E
+MitchLand: 31°47'17.81"S 115°46'10.70"E
+Mystic: 31°46'19.51"S 115°45'43.89"E
+NHE (Welvis): 31°46'29.52"S 115°49'7.87"E
+Doubleview: 31°53'41.14"S 115°46'50.86"E
+BelmontAP: 31°57'4.63"S 115°55'15.38"E
+Zaphod: 31°46'13.77"S 115°46'11.24"E
+TIC Hill: 31°49'32.77"S 116°3'51.87"E
+kaelnorr: 31°40'40.79"S 115°42'58.29"E
+"""
+
+l = s.split('\n')
+
+r = re.compile(r'(\d+)°(\d+)\'([\d\.]+)".')
+
+def coord_to_decimal(coord):
+		lparts = r.match(coord)
+		deg, min, sec = map(float, lparts.groups())
+		val = deg + min/60.0 + sec/(60.0**2)
+
+		return val
+
+for i in l:
+	try:
+		name, coords = i.split(':')
+
+		lat, long = coords.strip().split()
+
+		lat_dec = -coord_to_decimal(lat)
+		long_dec = coord_to_decimal(long)
+
+		print '"%s": [%f, %f, "%s", ""],' % (name.lower(), lat_dec, long_dec, name)
+		
+	except Exception, e:
+		print>>sys.stderr, "Error for line '%s': %s" % (i, e)
+		continue
+
+	
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/freenet_data.js	Sun Oct 21 23:03:51 2012 +0800
@@ -0,0 +1,62 @@
+// format is 
+// 'nodeid': [lat, long, "Name", "Description", "url"]
+// nodeid should be lowercase (for simplicity)
+// lat/long must be decimal coords.
+// Name and Description can be anything, valid HTML helps, so escape ampersands etc...
+// url is optional
+
+freenet_nodes = {
+
+	"perthap": [-31.959661, 115.872303, "PerthAP", ""],
+	"wannerooap": [-31.790564, 115.820094, "WannerooAP", ""],
+	"belmont2": [-31.959497, 115.928478, "Belmont2", ""],
+	"mitchland": [-31.788281, 115.769639, "MitchLand", ""],
+	"mystic": [-31.772086, 115.762192, "Mystic", ""],
+	"nhe": [-31.774867, 115.818853, "NHE (Welvis)", ""],
+	"doubleview": [-31.894761, 115.780794, "KodEBlaK", ""],
+	"belmontap": [-31.951286, 115.920939, "BelmontAP", ""],
+	"frogstar1": [-31.770429, 115.76983, "Frogstar 1", "15m", "http://www.wafreenet.org/node-Frogstar"],
+	"frogstar2": [-31.767973, 115.771309, "Frogstar 2", "22m", "http://www.wafreenet.org/node-Frogstar"],
+	"tichill": [-31.825769, 116.064408, "TIC Hill", ""],
+	"niak": [-32.101311, 115.943632, "niak", ""],
+	"msh": [-31.9285, 115.9085, "msh", ""],
+	"kaelnorr": [-31.6779966, 115.7161922, "kaelnorr", "", ""],
+	// the following are guessed from the map.
+	"duncraig": [-31.83017,115.772552, "Duncraig", "", "http://www.wafreenet.org/node-Duncraig"],
+	"spiked": [-31.812521,115.86113, "Spiked", "", "http://www.wafreenet.org/node-Spiked"],
+	"dericote": [-31.831774,115.803795, "Dericote", "", "http://www.wafreenet.org/node-Dericote"],
+	"vipernet": [-31.842566,115.801907, "Vipernet", "", "http://www.wafreenet.org/node-Vipernet"],
+	"bungknee": [-31.739263,115.801392, "Bungknee", "", ""],
+	"wirelesshill": [-32.030754,115.827302, "Wireless Hill", "", ""],
+	"jandakot": [-32.099736,115.870743, "Jandakot", "", "http://www.wafreenet.org/node-Jandakot"],
+	"armadale": [-32.128669,116.002235, "ArmadaleAP", "", "http://www.wafreenet.org/node-ArmadaleAP"],
+	"sgnet": [-32.132304,115.997772, "SGNet", "", "http://www.wafreenet.org/node-SGNet"]
+};
+
+// format is ['kind', 'node1', 'node2'].
+// Make sure that nodes are defined in the freenet_nodes list above.
+// Defined kinds are:
+// '2ghz', '5ghz', 'vpn'.
+
+freenet_links = [
+  [ '5ghz', 'perthap', 'tichill'],
+  [ '5ghz', 'niak', 'tichill'],
+  [ '5ghz', 'mitchland', 'mystic'],
+  [ '5ghz', 'nhe', 'mitchland'],
+  [ '5ghz', 'belmontap', 'belmont2'],
+  [ '5ghz', 'perthap', 'belmont2'],
+  [ '5ghz', 'msh', 'perthap'],
+  [ '5ghz', 'mystic', 'frogstar1'],
+  [ '5ghz', 'mitchland', 'frogstar1'],
+  [ 'vpn', 'mitchland', 'kaelnorr'],
+  [ '5ghz', 'mitchland', 'wannerooap'],
+  [ '5ghz', 'mystic', 'wannerooap'],
+  [ '5ghz', 'doubleview', 'wannerooap'],
+  [ '5ghz', 'doubleview', 'perthap'],
+  [ '5ghz', 'duncraig', 'nhe'],
+  [ '2ghz', 'mystic', 'spiked'],
+  [ '2ghz', 'mystic', 'dericote'],
+  [ '5ghz', 'mystic', 'vipernet'],
+  [ '2ghz', 'jandakot', 'armadale'],
+  [ '2ghz', 'sgnet', 'armadale']
+];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/labeled_marker.js	Sun Oct 21 23:03:51 2012 +0800
@@ -0,0 +1,106 @@
+/*
+* LabeledMarker Class
+*
+* Copyright 2007 Mike Purvis (http://uwmike.com)
+* 
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* 
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+* This class extends the Maps API's standard GMarker class with the ability
+* to support markers with textual labels. Please see articles here:
+*
+*       http://googlemapsbook.com/2007/01/22/extending-gmarker/
+*       http://googlemapsbook.com/2007/03/06/clickable-labeledmarker/
+*/
+
+/* Constructor */
+function LabeledMarker(latlng, options){
+    this.latlng = latlng;
+    this.labelText = options.labelText || "";
+    this.labelClass = options.labelClass || "markerLabel";
+    this.labelOffset = options.labelOffset || new GSize(0, 0);
+    
+    this.clickable = options.clickable || true;
+    
+    if (options.draggable) {
+    	// This version of LabeledMarker doesn't support dragging.
+    	options.draggable = false;
+    }
+    
+    GMarker.apply(this, arguments);
+}
+
+
+/* It's a limitation of JavaScript inheritance that we can't conveniently
+   extend GMarker without having to run its constructor. In order for the
+   constructor to run, it requires some dummy GLatLng. */
+LabeledMarker.prototype = new GMarker(new GLatLng(0, 0));
+
+
+// Creates the text div that goes over the marker.
+LabeledMarker.prototype.initialize = function(map) {
+	// Do the GMarker constructor first.
+	GMarker.prototype.initialize.apply(this, arguments);
+	
+	var div = document.createElement("div");
+	div.className = this.labelClass;
+	div.innerHTML = this.labelText;
+	div.style.position = "absolute";
+	map.getPane(G_MAP_MARKER_PANE).appendChild(div);
+
+	if (this.clickable) {
+		// Pass through events fired on the text div to the marker.
+		var eventPassthrus = ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout'];
+		for(var i = 0; i < eventPassthrus.length; i++) {
+			var name = eventPassthrus[i];
+			GEvent.addDomListener(div, name, newEventPassthru(this, name));
+		}
+
+		// Mouseover behaviour for the cursor.
+		div.style.cursor = "pointer";
+	}
+	
+	this.map = map;
+	this.div = div;
+}
+
+function newEventPassthru(obj, event) {
+	return function() { 
+		GEvent.trigger(obj, event);
+	};
+}
+
+// Redraw the rectangle based on the current projection and zoom level
+LabeledMarker.prototype.redraw = function(force) {
+	GMarker.prototype.redraw.apply(this, arguments);
+	
+	// We only need to do anything if the coordinate system has changed
+	if (!force) return;
+	
+	// Calculate the DIV coordinates of two opposite corners of our bounds to
+	// get the size and position of our rectangle
+	var p = this.map.fromLatLngToDivPixel(this.latlng);
+	var z = GOverlay.getZIndex(this.latlng.lat());
+	
+	// Now position our DIV based on the DIV coordinates of our bounds
+	this.div.style.left = (p.x + this.labelOffset.width) + "px";
+	this.div.style.top = (p.y + this.labelOffset.height) + "px";
+	this.div.style.zIndex = z + 1; // in front of the marker
+}
+
+// Remove the main DIV from the map pane, destroy event handlers
+LabeledMarker.prototype.remove = function() {
+	GEvent.clearInstanceListeners(this.div);
+	this.div.parentNode.removeChild(this.div);
+	this.div = null;
+	GMarker.prototype.remove.apply(this, arguments);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/linkmap.html	Sun Oct 21 23:03:51 2012 +0800
@@ -0,0 +1,307 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"> 
+  <head> 
+    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+    
+    <title>Link Map</title> 
+    
+    <style type="text/css"><!--
+    body{font-family: sans-serif; height:99%; margin:0; padding:0;}
+    html{height:99%; margin:0; padding:0;}
+    #error_log {
+        font-family: Courier, "Courier New", monospace, Fixed;
+        border: 3px solid red; 
+        padding: 0.5em; 
+        margin: 0.5em;
+        display: none;
+    }
+    #map_canvas {
+        height:99%; 
+        width: 100%; 
+        margin:0; 
+        padding:0;
+    }
+
+	#legend {
+		font-size: small;
+		background-color: #fff;
+		opacity: 0.7;
+		text-align: left;
+		padding: 0.5em;
+		border: 1px solid black;
+	}
+
+	#legend div {
+		vertical-align: middle;
+		display: inline-block;
+		margin-right: 1em;
+	}
+
+    .node_label_id {
+        font-size: smaller; 
+    }
+    .node_marker_label {
+        font-size: small; 
+        font-weight: bold;
+        color: #800;
+        opacity: 0.9; 
+    }
+    //-->
+    </style> 
+
+	<script>
+	// define some constants for colours etc:
+	LINKED_ICON = 'bluedot.png';
+	UNLINKED_ICON = 'yellowdot.png';
+	ICON_SIZE_W = 18;
+	ICON_SIZE_H = 18;
+
+	LINK_COLOUR_5GHZ = '#080';
+	LINK_COLOUR_2GHZ = '#00f';
+	LINK_COLOUR_VPN = '#777';
+	LINK_OPACITY = 0.7;
+	LINK_WIDTH = 4;
+
+	LEGEND_X_OFFSET = 7;
+	LEGEND_Y_OFFSET = 240;
+
+	CENTRE_COORDS_LAT = -31.9554;
+	CENTRE_COORDS_LNG = 115.85859;
+
+	// Note that these don't really help with privacy - people
+	// can always inspect the raw javascript. Manually alter coordinates
+	// if desired.
+	MAX_ZOOM = 13;
+	MIN_ZOOM = 3;
+	INIT_ZOOM = 10;
+
+	</script>
+    
+    <!-- load the nodes and links. -->
+    <script src="freenet_data.js"></script>
+
+    <script>
+
+	var key = {
+        'localhost': 'ABQIAAAAN6v4BE-QSU4eUIUlNyDwJBT2yXp_ZAY8_ufC3CFXhHIE1NvwkxQeuZtV4Gh5jn5-Mzkw8HaJ-hZUxQ',
+        'matt.ucc.asn.au': 'ABQIAAAAN6v4BE-QSU4eUIUlNyDwJBTcvFJ22Qq_4Wpg4VhVaFRl5W3cyxRmrAk6RVdmqxBPO7KK8gwSWsrFVg',
+        'www.wafreenet.org': 'ABQIAAAAN6v4BE-QSU4eUIUlNyDwJBRTyFF_GlE7_llDeWLTuKgydpOCLhQydqjQALO8ZGbbZw5VaoTB-DBcMw',
+      }[window.location.host]
+	if (!key) {
+		key =
+		'ABQIAAAAN6v4BE-QSU4eUIUlNyDwJBTR5ei7CukQRzAV2g5VZ7MlqVyAPxSs6pg6K2o24gSmaclijIuM-Q9KcA';
+	}
+    document.write([
+      '<script src="https://maps.google.com/maps?file=api&amp;v=2&amp;key=',
+	  key,
+      '" type="text/javascript"><\/script>'
+    ].join(''));
+    </script>
+
+    <!-- 3rd party labelled marker code -->
+    <script src="labeled_marker.js"></script>
+    
+    <script type="text/javascript"> 
+
+	// define a few constants after loading the gmaps API
+	ICON_SIZE = new GSize(ICON_SIZE_W, ICON_SIZE_H);
+	CENTRE_COORDS = new GLatLng(CENTRE_COORDS_LAT, CENTRE_COORDS_LNG);
+    
+    function add_node(map, nodeid, lat, lng, name, desc, url, is_linked) {
+        var latlng = GLatLng.fromUrlValue('')
+        var latlng = new GLatLng(lat, lng);
+
+        var icon = new GIcon(G_DEFAULT_ICON);
+        icon.shadow = "";
+        if (is_linked) {
+            icon.image = LINKED_ICON;
+        } else {
+            icon.image = UNLINKED_ICON;
+        }
+        var middle = new GPoint(ICON_SIZE.width / 2.0, ICON_SIZE.height / 2.0);
+        icon.iconAnchor = middle;
+        icon.infoWindowAnchor = middle;
+        icon.iconSize = ICON_SIZE;
+
+        var marker_opts = { 
+                            icon: icon,
+                            labelText: '<div class="node_marker_label">' + name + "</div>",
+                            labelOffset: new GSize(ICON_SIZE.width/2.0, 0),
+                            };
+
+        var marker = new LabeledMarker(latlng, marker_opts);
+        
+        var desc_text = '';
+        if (desc) {
+                desc_text = '<br/>' + desc;
+        }
+
+        var name_text = nodeid;
+        if (name) {
+            name_text = name;
+        }
+        if (url) {
+                name_text = '<a href="' + url + '">' + name_text + '</a>';
+        }
+        var myhtml =  '<div class="node_label"><b>' + name_text + "</b>" + desc_text + '<br/><div class="node_label_id">' + nodeid + "</div></div>";
+        GEvent.addListener(marker, "click", function() {
+                        map.openInfoWindowHtml(latlng, myhtml);
+                });
+        map.addOverlay(marker);
+    }
+    
+    function add_link(map, kind, lat1, lng1, lat2, lng2) {
+            var pos1 = new GLatLng(lat1, lng1);
+            var pos2 = new GLatLng(lat2, lng2);
+            var polyOptions = {geodesic:true};
+            
+            // line styling defined here.
+            var colour = null;
+            if (kind == '2ghz') {
+                colour = LINK_COLOUR_2GHZ;
+            } else if (kind == '5ghz') {
+                colour = LINK_COLOUR_5GHZ;
+            } else if (kind == 'vpn') {
+                colour = LINK_COLOUR_VPN;
+            }
+            else {
+                throw ("Link kind '" + kind + "' is not known.");
+            }
+
+            var line = new GPolyline([
+                    pos1, pos2,
+              ], colour, LINK_WIDTH, LINK_OPACITY, polyOptions);
+            map.addOverlay(line);
+    }
+
+    function make_legend(map, legend_html) {
+    // from
+    // http://code.google.com/apis/maps/documentation/examples/control-custom.html
+        function LegendControl() {
+        }
+
+        LegendControl.prototype = new GControl();
+
+        // Creates a one DIV for each of the buttons and places them in a container
+        // DIV which is returned as our control element. We add the control to
+        // to the map container and return the element for the map class to
+        // position properly.
+        LegendControl.prototype.initialize = function(map) {
+            var legendDiv = document.createElement("div");
+            legendDiv.id = "legend";
+            legendDiv.innerHTML = legend_html;
+
+            var container = document.createElement("div");
+            container.appendChild(legendDiv);
+            map.getContainer().appendChild(container);
+            return container;
+        }
+
+        // By default, the control will appear in the top left corner of the
+        // map with 7 pixels of padding.
+        LegendControl.prototype.getDefaultPosition = function() {
+            return new GControlPosition(G_ANCHOR_TOP_LEFT, 
+					new GSize(LEGEND_X_OFFSET, LEGEND_Y_OFFSET));
+        }
+
+        map.addControl(new LegendControl());
+    }
+
+    function limit_zoom(map, minMapScale, maxMapScale) {
+        // get array of map types 
+        var mapTypes = map.getMapTypes(); 
+        // overwrite the getMinimumResolution() and getMaximumResolution() methods
+        // for each map type 
+        for (var i=0; i<mapTypes.length; i++) { 
+            mapTypes[i].getMinimumResolution = function() {return minMapScale;} 
+            mapTypes[i].getMaximumResolution = function() {return maxMapScale;} 
+        }
+    }
+    
+    function initialize() {
+      if (GBrowserIsCompatible()) {
+        var map = new GMap2(document.getElementById("map_canvas"));
+        
+        // turn on the zoom and terrain/sat buttons
+        
+        var customUI = map.getDefaultUI();
+        customUI.maptypes.hybrid = false;
+        customUI.controls.scalecontrol = false;
+        map.setUI(customUI);
+
+        map.setMapType(G_PHYSICAL_MAP);
+        map.enableContinuousZoom();
+
+        limit_zoom(map, MIN_ZOOM, MAX_ZOOM);
+        
+        // centered kind of on perth city.
+        map.setCenter(CENTRE_COORDS, INIT_ZOOM);
+
+        var legend_html = '<div><img src="' + LINKED_ICON + '"/></div><div>Linked Node</div>'
+                        + '<br/><div><img src="' + UNLINKED_ICON + '"/></div><div>Unlinked Node</div>'
+                        + '<br/><div style="background-color: ' + LINK_COLOUR_5GHZ + '; width: 3em; height: ' + LINK_WIDTH + 'px"></div><div>5GHz Link</div>'
+                        + '<br/><div style="background-color: ' + LINK_COLOUR_2GHZ + '; width: 3em; height: ' + LINK_WIDTH + 'px"></div><div>2GHz Link</div>'
+                        + '<br/><div style="background-color: ' + LINK_COLOUR_VPN + '; width: 3em; height: ' + LINK_WIDTH + 'px"></div><div>VPN Link</div>'
+						;
+;
+        make_legend(map, legend_html);
+
+        var linked_nodes = {};
+        for (var i = 0; i < freenet_links.length; i++)
+        {
+            try {
+                var l = freenet_links[i];
+                var kind = l[0];
+                var nodeid1 = l[1];
+                var nodeid2 = l[2];
+
+                var node1 = freenet_nodes[nodeid1];
+                var node2 = freenet_nodes[nodeid2];
+
+                if (node1 == undefined) {
+                    throw "Node ID " + nodeid1 + " is not in the node list.";
+                }
+                if (node2 == undefined) {
+                    throw "Node ID " + nodeid2 + " is not in the node list.";
+                }
+
+                if (kind != 'vpn') {
+                    linked_nodes[nodeid1] = true;
+                    linked_nodes[nodeid2] = true;
+                }
+
+                var lat1 = node1[0];
+                var lng1 = node1[1];
+                var lat2 = node2[0];
+                var lng2 = node2[1];
+
+                add_link(map, kind, lat1, lng1, lat2, lng2);
+            } catch (e) {
+                var error_log = document.getElementById("error_log");
+                error_log.innerHTML += "Error adding node link '" +
+                    l + "': '" + String(e) + "'<br/>";
+                error_log.style.display = "block";
+            }
+        }
+ 
+        for (var nodeid in freenet_nodes) {
+            var n = freenet_nodes[nodeid];
+            var lat = n[0];
+            var lng = n[1];
+            var name = n[2];
+            var desc = n[3];
+            var url = n[4];
+            var is_linked = linked_nodes[nodeid];
+            add_node(map, nodeid, lat, lng, name, desc, url, is_linked);
+        }
+      }
+    }
+ 
+    </script> 
+  </head> 
+  <body onload="initialize()" onunload="GUnload()"> 
+    <div id="error_log"></div>
+    <div id="map_canvas"></div> 
+  </body> 
+</html>
Binary file yellowdot.png has changed