diff --git a/draw_map.py b/draw_map.py
index 4f03fb9..73e52b2 100755
--- a/draw_map.py
+++ b/draw_map.py
@@ -36,7 +36,7 @@
m.zoom_to_box(mapnik.Envelope(-180.0,-90.0,180.0,83.623596))
### Write file
-mapnik.render_to_file(m,'output/world.png', 'png')
+mapnik.render_to_file(m,'/var/lib/banditvis/output/world.png', 'png')
##### Get Metadata
@@ -53,7 +53,7 @@
##### Insert Metadata
-im = Image.open('output/world.png')
+im = Image.open('/var/lib/banditvis/output/world.png')
draw = ImageDraw.Draw(im)
font = ImageFont.truetype('fonts/LinLibertine_Bd-4.1.5.otf', 20)
@@ -74,7 +74,6 @@
im.paste(im2, (27, 280), im2)
### Write file
-#im.save('output/world.png')
im.save('/var/lib/banditvis/output/world.png')
exit()
\ No newline at end of file
diff --git a/interactive/banditvis.css b/interactive/banditvis.css
index 9d8e852..6ae5e27 100644
--- a/interactive/banditvis.css
+++ b/interactive/banditvis.css
@@ -1,11 +1,37 @@
#map{
border: 1px solid black;
+ height: 100%;
+ width: 100%;
}
-.Popup{
- background-color:yellow;
+#legend {
border: 1px solid black;
+ position: absolute;
+ overflow: hidden;
+ z-index: 1000000;
+
+ top: 150px;
+ left: 15px;
+ width: 40px;
+ height: 70%;
+
+ text-align: center;
+
+ background-image: -ms-linear-gradient(top, hsl(0, 100%, 50%), hsl(120, 100%, 50%));
+ background-image: -moz-linear-gradient(top, red, yellow, green);
+ background-image: -o-linear-gradient(top, hsl(0,100%, 50%), hsl(120, 100%, 50%));
+ background-image: -webkit-linear-gradient(top, hsl(0, 100%, 50%), hsl(120, 100%, 50%));
+ background-image: linear-gradient(top, hsl(0, 100%, 50%), hsl(120, 100%, 50%));
}
-.PopupContent{
- overflow:visible;
+
+#legend_upper {
+ position:absolute;
+ top: 0px;
+ width: 100%
+}
+
+#legend_lower{
+ position:absolute;
+ bottom: 0px;
+ width: 100%
}
\ No newline at end of file
diff --git a/interactive/banditvis.js b/interactive/banditvis.js
index 5e59db3..9098670 100644
--- a/interactive/banditvis.js
+++ b/interactive/banditvis.js
@@ -1,56 +1,123 @@
- var map, dataLayers, debug;
-
+ Banditvis = new Object();
+ Banditvis.max_ocount = 0;
+
/* Called via map.html onload */
/* Does a lot... */
/* Returns nothing */
function init(){
- map = new OpenLayers.Map('map');
+ Banditvis.map = new OpenLayers.Map('map');
var osm = new OpenLayers.Layer.OSM("OpenStreetMaps");
- map.addLayer(osm);
+ osm.transitionEffect = "resize";
+ Banditvis.map.addLayer(osm);
- map.setCenter(
+ Banditvis.map.setCenter(
new OpenLayers.LonLat(10.75, 49.1).transform(
new OpenLayers.Projection("EPSG:4326"),
- map.getProjectionObject()
+ Banditvis.map.getProjectionObject()
), 2
);
- map.addControl(new OpenLayers.Control.LayerSwitcher());
+ Banditvis.map.addControl(new OpenLayers.Control.LayerSwitcher());
- debug = document.getElementById("debug");
+ Banditvis.legend = document.getElementById("legend");
+ Banditvis.legend.upper = document.getElementById("legend_upper");
+ Banditvis.legend.lower = document.getElementById("legend_lower");
loadData();
- addStyles();
- addClustering();
- addMouseOver();
+ Banditvis.map.events.on({ 'moveend': function(evt) {
+ Banditvis.min_ocount = null;
+ Banditvis.max_ocount = null;
+ for ( var i in Banditvis.dataLayers) {
+ updateMetadata(Banditvis.dataLayers[i]);
+ Banditvis.dataLayers[i].redraw();
+ }
+ } });
+ Banditvis.map.events.on({ 'zoomend': function(evt) {
+ redrawPopups();
+ } });
return;
}
/* Called by init() */
-/* Adds layers of data to the map */
+/* Loads the offences file */
/* Returns nothing */
function loadData() {
- dataLayers = new Array();
- dataLayers.push(new OpenLayers.Layer.GML("Server", "server.kml", {format: OpenLayers.Format.KML}));
- dataLayers.push(new OpenLayers.Layer.GML("ssh", "output/ssh.kml", {format: OpenLayers.Format.KML}));
-
+ var xmlHttpObject = false;
+ if (typeof XMLHttpRequest != 'undefined') {
+ xmlHttpObject = new XMLHttpRequest();
+ }
+ if (!xmlHttpObject) {
+ try {
+ xmlHttpObject = new ActiveXObject("Msxml2.XMLHTTP");
+ } catch(e) {
+ try {
+ xmlHttpObject = new ActiveXObject("Microsoft.XMLHTTP");
+ } catch(e) {
+ xmlHttpObject = null;
+ }
+ }
+ }
- map.addLayers(dataLayers);
- return;
+ // var wait = true;
+ // var waitTime = 10;
+ xmlHttpObject.open("GET", "output/offences.txt");
+ xmlHttpObject.onreadystatechange = function() {
+ if (xmlHttpObject.readyState == 4) {
+ loadKMLs(xmlHttpObject);
+ }
+ }
+ xmlHttpObject.send(null);
}
+/* Called by loadData() */
+/* Adds layers of data to the map */
+/* Returns nothing */
+function loadKMLs(xmlHttpObject) {
+ Banditvis.dataLayers = new Array();
+ Banditvis.dataLayers.push(new OpenLayers.Layer.GML("Server", "server.kml", {format: OpenLayers.Format.KML}));
+
+ var responseLines=xmlHttpObject.responseText.split("\n")
+ for (var i in responseLines) {
+ if (responseLines[i] != "") {
+ Banditvis.dataLayers.push(new OpenLayers.Layer.GML(responseLines[i], "output/"+responseLines[i]+".kml", {format: OpenLayers.Format.KML}));
+ }
+ }
+
+ for (var i in Banditvis.dataLayers) {
+ Banditvis.map.addLayer(Banditvis.dataLayers[i]);
+ Banditvis.dataLayers[i].strategies = new Array();
+
+ Banditvis.dataLayers[i].events.on({"loadend": function() {
+ addMetadata(Banditvis.dataLayers[i]);
+ updateMetadata(Banditvis.dataLayers[i]);
+ Banditvis.dataLayers[i].redraw();
+ } });
+
+ addStyles(Banditvis.dataLayers[i]);
+ addClustering(Banditvis.dataLayers[i]);
+ // addReloader(Banditvis.dataLayers[i]);
+ addMouseOver(Banditvis.dataLayers[i]);
+
+ }
+
+ return;
+}
-function addStyles(){
+/* Called by loadKMLs() */
+/* Adds the style to the datapoints */
+/* Returns nothing */
+function addStyles(layer){
var style = new OpenLayers.Style({
pointRadius: "${radius}",
- fillColor: "#ff5454",
+ fillColor: "${fillColor}",
fillOpacity: 0.8,
strokeColor: "#000000",
strokeWidth: "${width}",
- strokeOpacity: 0.8
+ strokeOpacity: 0.8,
+ label: "${label}"
}, {
context: {
width: function(feature) { return (feature.cluster) ? 3 : 1; },
@@ -61,11 +128,58 @@ function addStyles(){
var r = 5;
}
return r;
- }
+ },
+ fillColor: function(feature) {
+
+ if (!feature.attributes || !feature.attributes.ocount) {
+ return "#808080";
+ }
+ var ocount = parseInt(feature.attributes.ocount);
+
+ var r = 0;
+ var R;
+ var g = 0;
+ var G;
+
+ var p = (ocount - Banditvis.min_ocount) / (Banditvis.max_ocount - Banditvis.min_ocount) * 100;
+
+ if (p < 0 || p > 100 || isNaN(p))
+ { p = 50; }
+
+ if (p >= 50) r = 255;
+ if (p < 50) r = Math.round(p/50 * 255);
+
+ if (p >= 50) g = 255 - Math.round((p-50)/50 * 255);
+ if (p < 50) g = 255;
+
+ if (r < 16) R = "0"+r.toString(16);
+ else R = r.toString(16);
+
+ if (g < 16) G = "0"+g.toString(16);
+ else G = g.toString(16);
+
+ var color = "#"+R+G+"00";
+ if (color.length != 7) {
+ alert(color);
+ }
+ return color;
+
+ },
+ label: function(feature) {
+ if (feature.cluster) {
+ if (feature.attributes.count <= 3) {
+ return "";
+ }
+ return feature.attributes.count;
+ } else {
+ return "";
+ }
+ }
+
}
});
- dataLayers[1].styleMap = new OpenLayers.StyleMap({
+ layer.styleMap = new OpenLayers.StyleMap({
"default": style,
"select": {
fillColor: "#54ffff",
@@ -76,31 +190,123 @@ function addStyles(){
return;
}
-/* Called by init() */
+/* Called by loadKMLs() */
+/* Fills feature.data with metadata */
+/* Returns nothing */
+function addMetadata(layer) {
+ for (var i in layer.features) {
+ if ( layer.features[i].cluster) {
+ for (var j in layer.features[i].cluster) {
+ extractMetadata(layer.features[i].cluster[j]);
+ }
+ } else {
+ extractMetadata(layer.features[i]);
+ }
+ }
+ return;
+}
+
+function extractMetadata(feature) {
+ var match = feature.data.description.search("offence: (.*?), count: (.*?), first_seen: (.*?), last_seen: (.*)");
+ if (match != -1) {
+ feature.attributes.offence = RegExp.$1;
+ feature.attributes.ocount = RegExp.$2;
+ feature.attributes.first_time = RegExp.$3;
+ feature.attributes.last_time = RegExp.$4;
+ }
+ return;
+}
+
+function updateMetadata(layer) {
+for (var i in layer.features) {
+ if (layer.features[i].onScreen()){
+ if (layer.features[i].cluster) {
+ var count = 0;
+ for (var j in layer.features[i].cluster) {
+ if (layer.features[i].cluster[j].attributes.ocount) {
+ count = count + parseInt(layer.features[i].cluster[j].attributes.ocount);
+ }
+ }
+ layer.features[i].attributes.ocount = parseInt(count);
+ }
+ if (layer.features[i].attributes.ocount > Banditvis.max_ocount) {
+ Banditvis.max_ocount = parseInt(layer.features[i].attributes.ocount);
+ }
+ if (!Banditvis.min_ocount || layer.features[i].attributes.ocount < Banditvis.min_ocount) {
+ Banditvis.min_ocount = parseInt(layer.features[i].attributes.ocount);
+ }
+ }
+}
+ Banditvis.legend.upper.innerHTML = Banditvis.max_ocount;
+ Banditvis.legend.lower.innerHTML = Banditvis.min_ocount;
+ return;
+}
+
+/* Called by loadKMLs() */
/* Adds the clustering strategy to the dataLayer*/
/* Returns nothing */
-function addClustering() {
+function addClustering(layer) {
var clustering = new OpenLayers.Strategy.Cluster({distance: 25, threshold: 2});
- clustering.setLayer(dataLayers[1]);
- dataLayers[1].strategies = clustering;
- dataLayers[1].strategies.activate();
+ clustering.setLayer(layer);
+ clustering.activate();
+ layer.strategies.push(clustering);
return;
}
-/* Called by init() */
+/* Called by loadKMLs() */
/* Adds the Hover/Select-effect */
/* Returns nothing */
-function addMouseOver() {
- dataLayers[1].events.on({
+function addMouseOver(layer) {
+ layer.events.on({
//'hoverfeature': function(evt) { showPopup(evt.feature) },
//'outfeature': function(evt) { evt.feature.popup.destroy() },
- 'featureselected': function(evt) { showPopup(evt.feature) },
- 'featureunselected': function(evt) { evt.feature.popup.destroy() }
+ 'featureselected': function(evt) {
+ //alert("evt: sel: " +evt.feature.id);
+ showPopup(evt.feature);
+ if (evt.redraw != true) {
+ if (evt.feature.cluster == null) {
+ //alert("arrayAdd: "+arrayAdd(evt.feature));
+ } else {
+ for (var i in evt.feature.cluster) {
+ arrayAdd(evt.feature.cluster[i]);
+ }
+ }
+ }
+ },
+ 'featureunselected': function(evt) {
+ //alert("evt: usel: " +evt.feature.id);
+ //console.log(evt.feature.popup);
+ if (evt.feature.popup != null) {
+ evt.feature.popup.destroy();
+ }
+ if (evt.redraw != true) {
+ if (evt.feature.cluster == null) {
+ //alert("arrayRemove: "+arrayRemove(evt.feature));
+ } else {
+ for (var i in evt.feature.cluster) {
+ arrayRemove(evt.feature.cluster[i]);
+ }
+ }
+ }
+ }
});
+ Banditvis.hover = new OpenLayers.Control.SelectFeature(Banditvis.dataLayers, {/*hover: true, */multiple: true, toggle: true});
+ Banditvis.map.addControl(Banditvis.hover);
+ Banditvis.hover.activate(true);
- hover = new OpenLayers.Control.SelectFeature(dataLayers, {/*hover: true, */multiple: true, toggle: true});
- map.addControl(hover);
- hover.activate(true);
+ Banditvis.selectedFeatures = new Array();
+
+ return;
+}
+
+/* Called by loadKMLs() */
+/* Adds a reloading strategy */
+/* Returns nothing */
+function addReloader(layer) {
+ var reloader = new OpenLayers.Strategy.Refresh({interval: 1000, force: true});
+ reloader.setLayer(layer);
+ reloader.activate();
+ layer.strategies.push(reloader);
return;
}
@@ -108,15 +314,13 @@ function addMouseOver() {
/* Creates a Popup and shows it */
/* Returns nothing */
function showPopup(feature) {
- console.log(feature);
feature.popup = new OpenLayers.Popup(null, feature.geometry.getBounds().getCenterLonLat(), new OpenLayers.Size(270, 85), providePopupContent(feature), false, null);
feature.popup.autoSize = true;
feature.popup.displayClass = "Popup";
feature.popup.contentDisplayClass = "PopupContent";
feature.popup.setBorder("1px solid black");
feature.popup.setOpacity(0.8);
- //feature.popup.minSize = new OpenLayers.Size(300, 100);
- map.addPopup(feature.popup);
+ Banditvis.map.addPopup(feature.popup);
feature.popup.show();
return;
}
@@ -125,18 +329,89 @@ function showPopup(feature) {
/* Returns the features name and description as a formatted string */
function providePopupContent(feature) {
if (feature.cluster) {
- content = "Cluster of " + feature.attributes.count + " IPs:";
- for (i in feature.cluster) {
- content = content + "
" + feature.cluster[i].data.name;
+ content = "Cluster of " + feature.attributes.count + " IPs
Count: " + feature.attributes.ocount + "";
+ for (var i in feature.cluster) {
+ content = content + "
" + feature.cluster[i].attributes.name;
}
} else {
- match = feature.data.description.search("offence: (.*?), count: (.*?), last_seen: (.*)");
- if (match == -1) {
- console.log("Regex failed");
- content = "" + feature.data.name + "
" + feature.data.description;
+ if (feature.attributes.name && feature.attributes.offence && feature.attributes.ocount && feature.attributes.last_time) {
+ if (feature.attributes.first_time != feature.attributes.last_time) {
+ content = "" + feature.attributes.name +
+ "
Count: " + feature.attributes.ocount +
+ "
First time: " + feature.attributes.first_time +
+ "
Last time: " + feature.attributes.last_time;
+ } else {
+ content = "" + feature.attributes.name +
+ "
Count: " + feature.attributes.ocount +
+ "
Time: " + feature.attributes.last_time;
+ }
} else {
- content = "" + feature.data.name + "
Offence: " + RegExp.$1 + "
Count: " + RegExp.$2 + "
Last time seen: " + RegExp.$3;
+ content = "" + feature.data.name + "
" + feature.data.description;
}
}
return content;
}
+
+function redrawPopups() {
+
+ //alert("Destroying all popups");
+ for (var i in Banditvis.map.popups) {
+ Banditvis.map.popups[i].destroy();
+ }
+
+ var evt = { redraw: true, feature: null }
+ for (var i in Banditvis.selectedFeatures) {
+ for (var j in Banditvis.dataLayers) {
+ for (var k in Banditvis.dataLayers[j].features) {
+
+ if (Banditvis.dataLayers[j].features[k].id == Banditvis.selectedFeatures[i].id){
+ evt.feature = Banditvis.dataLayers[j].features[k];
+ //alert("usel: " +evt.feature.id);
+ Banditvis.dataLayers[j].events.triggerEvent('featureunselected', evt);
+ //alert("sel: " +evt.feature.id);
+ Banditvis.dataLayers[j].events.triggerEvent('featureselected', evt);
+
+ } else if (Banditvis.dataLayers[j].features[k].cluster != null) {
+ for (var l in Banditvis.dataLayers[j].features[k].cluster[l]) {
+ if(Banditvis.dataLayers[j].features[k].cluster[l].id == Banditvis.selectedFeatures[i].id) {
+
+ evt.feature = Banditvis.dataLayers[j].features[k].cluster[l];
+ Banditvis.dataLayers[j].events.triggerEvent('featureunselected', evt);
+ Banditvis.dataLayers[j].events.triggerEvent('featureselected', evt);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+function arrayAdd(feature) {
+ for (var i in Banditvis.selectedFeatures) {
+ if (Banditvis.selectedFeatures[i].id == feature.id) {
+ Banditvis.selectedFeatures.splice(i);
+ return false;
+ }
+ }
+ Banditvis.selectedFeatures.push(feature);
+ return true;
+}
+
+function arrayRemove(feature) {
+ for (var i in Banditvis.selectedFeatures) {
+ if (Banditvis.selectedFeatures[i].id == feature.id) {
+ Banditvis.selectedFeatures.splice(i);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
+
+
diff --git a/interactive/map.htm b/interactive/map.htm
index c01dde8..9217370 100644
--- a/interactive/map.htm
+++ b/interactive/map.htm
@@ -4,10 +4,10 @@
+
-
-
-
+