display count of flows through core<->core links
diff --git a/web/ons-demo/css/skin.default.css b/web/ons-demo/css/skin.default.css
index f6086a3..9857bc6 100644
--- a/web/ons-demo/css/skin.default.css
+++ b/web/ons-demo/css/skin.default.css
@@ -437,3 +437,8 @@
 	stroke: black;
 }
 
+.flowCount {
+	font-size: 20px;
+	fill: rgba(255, 255, 255, .75);
+}
+
diff --git a/web/ons-demo/js/map.js b/web/ons-demo/js/map.js
index 7662aaf..3849b8d 100644
--- a/web/ons-demo/js/map.js
+++ b/web/ons-demo/js/map.js
@@ -120,6 +120,64 @@
 	});
 }
 
+function drawCoreFlowCounts() {
+	var links = {};
+	model.links.forEach(function (l) {
+		links[makeLinkKey(l)] = l;
+	});
+
+	var flowCounts = [];
+	countCoreLinkFlows().forEach(function (count) {
+		var l = links[count.key];
+		if (l) {
+			var src = d3.select(document.getElementById(l['src-switch']));
+			var dst = d3.select(document.getElementById(l['dst-switch']));
+
+			if (!src.empty() && !dst.empty()) {
+				var x1 = parseFloat(src.attr('x'));
+				var x2 = parseFloat(dst.attr('x'));
+				var y1 = parseFloat(src.attr('y'));
+				var y2 = parseFloat(dst.attr('y'));
+
+				var slope = (y2 - y1)/(x2 - x1);
+
+				var offset = 15;
+				var xOffset = offset;
+				var yOffset = slope*offset;
+
+				var d = Math.sqrt(xOffset*xOffset + yOffset*yOffset);
+				var scaler = offset/d;
+
+				count.pt = {
+					x: x1 + (x2 - x1)/2 + xOffset*scaler,
+					y: y1 + (y2 - y1)/2 + yOffset*scaler
+				}
+			}
+			flowCounts.push(count);
+		}
+	});
+
+
+	var counts = linksLayer.selectAll('.flowCount').data(flowCounts, function (d) {
+		return d.key;
+	});
+
+	counts.enter().append('svg:text')
+		.attr('class', 'flowCount')
+		.attr('x', function (d) {
+			return d.pt.x;
+		})
+		.attr('y', function (d) {
+			return d.pt.y;
+		});
+
+	counts.text(function (d) {
+		return d.value;
+	});
+
+	counts.exit().remove();
+}
+
 function drawLinkLines() {
 
 	// key on link dpids since these will come/go during demo
@@ -163,6 +221,7 @@
 	linkLines.exit().remove();
 }
 
+
 var fanOutAngles = {
 	aggregation: 100,
 	edge: 5
@@ -252,9 +311,13 @@
 		g.append('svg:text')
 			.classed('label', true)
 			.text(d.label)
-			.attr("text-anchor", "end")
-			.attr('x', d.x - width)
-			.attr('y', d.y - width);
+			.attr("text-anchor", function (d) {
+				return d.x > 500 ? "end" : "start";
+			})
+			.attr('x', function (d) {
+				return d.x > 500 ? d.x - width*.8 : d.x + width*.8;
+			})
+			.attr('y', d.y - width*.8);
 	}
 }
 
@@ -333,6 +396,8 @@
 
 	drawLinkLines();
 
+	drawCoreFlowCounts();
+
 	labelsEnter(switches);
 }
 
diff --git a/web/ons-demo/js/model.js b/web/ons-demo/js/model.js
index f251c87..df4a751 100644
--- a/web/ons-demo/js/model.js
+++ b/web/ons-demo/js/model.js
@@ -5,13 +5,20 @@
 		edgeSwitches: [],
 		aggregationSwitches: [],
 		coreSwitches: [],
-		flows: results.flows,
+		flows: [],
 		controllers: results.controllers,
 		activeControllers: results.activeControllers,
 		links: results.links,
 		configuration: results.configuration
 	};
 
+	// remove bad flows;
+	results.flows.forEach(function (f) {
+		if (f.dataPath && f.dataPath.flowEntries && f.dataPath.flowEntries.length > 1) {
+			model.flows.push(f);
+		}
+	})
+
 	// sort the switches
 	results.switches.sort(function (a, b) {
 		var aA = a.dpid.split(':');
diff --git a/web/ons-demo/js/utils.js b/web/ons-demo/js/utils.js
index be7cf53..65117f5 100644
--- a/web/ons-demo/js/utils.js
+++ b/web/ons-demo/js/utils.js
@@ -81,24 +81,27 @@
 function updateHeader() {
 	d3.select('#lastUpdate').text(new Date());
 
-	var count = 0;
+	var activeSwitchCount = 0;
 	model.edgeSwitches.forEach(function (s) {
 		if (s.state === 'ACTIVE') {
-			count += 1;
+			activeSwitchCount += 1;
 		}
 	});
 	model.aggregationSwitches.forEach(function (s) {
 		if (s.state === 'ACTIVE') {
-			count += 1;
+			activeSwitchCount += 1;
 		}
 	});
 	model.coreSwitches.forEach(function (s) {
 		if (s.state === 'ACTIVE') {
-			count += 1;
+			activeSwitchCount += 1;
 		}
 	});
 
-	d3.select('#activeSwitches').text(count);
+	d3.select('#activeSwitches').text(activeSwitchCount);
+
+
+
 	d3.select('#activeFlows').text(model.flows.length);
 }
 
@@ -153,4 +156,51 @@
 	return svg;
 }
 
+/***************************************************************************************************
+counts the number of flows which pass through each core<->core link
+***************************************************************************************************/
+function countCoreLinkFlows() {
+	var allCounts = {};
+	model.flows.forEach(function (f) {
+		if (f.dataPath && f.dataPath.flowEntries && f.dataPath.flowEntries.length > 1) {
+			var flowEntries = f.dataPath.flowEntries;
+			var i;
+
+			for (i = 0; i < flowEntries.length - 1; i += 1) {
+				var linkKey = flowEntries[i].dpid.value + '=>' + flowEntries[i+1].dpid.value;
+				if (!allCounts[linkKey]) {
+					allCounts[linkKey] = 1;
+				} else {
+					allCounts[linkKey] += 1;
+				}
+			}
+		}
+	});
+
+	var coreCounts = {};
+	var i, j;
+	for (i = 0; i < model.coreSwitches.length - 1; i += 1) {
+		for (j = i + 1; j < model.coreSwitches.length; j += 1) {
+			var si = model.coreSwitches[i];
+			var sj = model.coreSwitches[j];
+			var key1 =  si.dpid + '=>' + sj.dpid;
+			var key2 =  sj.dpid + '=>' + si.dpid;
+			var linkCount = 0;
+			if (allCounts[key1]) {
+				linkCount += allCounts[key1];
+			}
+			if (allCounts[key2]) {
+				linkCount += allCounts[key2];
+			}
+
+			coreCounts[key1] = linkCount;
+		}
+	}
+
+	return d3.entries(coreCounts);
+}
+
+
+
+