sort switches and position aggregations switches to fan out
diff --git a/web/ons-demo/README.txt b/web/ons-demo/README.txt
new file mode 100644
index 0000000..2807fec
--- /dev/null
+++ b/web/ons-demo/README.txt
@@ -0,0 +1,5 @@
+from main web directory
+
+	 python ./restapi2.py
+
+http://localhost:9000/ons-demo/index.html
\ No newline at end of file
diff --git a/web/ons-demo/RELEASE_NOTES.txt b/web/ons-demo/RELEASE_NOTES.txt
new file mode 100644
index 0000000..85df9bf
--- /dev/null
+++ b/web/ons-demo/RELEASE_NOTES.txt
@@ -0,0 +1,5 @@
+** March 19, 2013 **
+- aggregation switch sample data DPIDs do not match official switch config.
+	- switch config hacked 00:00:00:00:00:00:01:01 ==> 00:00:00:00:00:00:01:00 etc.
+- layout does not dynamically adjust when window is resized
+	- refresh browser window after resizing to fix layout
diff --git a/web/ons-demo/css/skin.default.css b/web/ons-demo/css/skin.default.css
index 951fbb1..14bfac8 100644
--- a/web/ons-demo/css/skin.default.css
+++ b/web/ons-demo/css/skin.default.css
@@ -66,7 +66,7 @@
 }
 
 path {
-	stroke: white;
+	stroke: rgba(255, 255, 255, .25);
 	stroke-width: 1px;
 }
 
diff --git a/web/ons-demo/data/configuration.json b/web/ons-demo/data/configuration.json
index 99b9041..bf5c855 100644
--- a/web/ons-demo/data/configuration.json
+++ b/web/ons-demo/data/configuration.json
@@ -8,13 +8,13 @@
 		"00:00:00:16:97:08:9a:46"
 	],
 	"aggregation": [
-		"00:00:00:00:00:00:01:01",
-		"00:00:00:00:00:00:02:01",
-		"00:00:00:00:00:00:03:01",
-		"00:00:00:00:00:00:04:01",
-		"00:00:00:00:00:00:05:01",
-		"00:00:00:00:00:00:06:01",
-		"00:00:00:00:00:00:07:01",
-		"00:00:00:00:00:00:08:01"
+		"00:00:00:00:00:00:01:00",
+		"00:00:00:00:00:00:02:00",
+		"00:00:00:00:00:00:03:00",
+		"00:00:00:00:00:00:04:00",
+		"00:00:00:00:00:00:05:00",
+		"00:00:00:00:00:00:06:00",
+		"00:00:00:00:00:00:07:00",
+		"00:00:00:00:00:00:08:00"
 	]
 }
\ No newline at end of file
diff --git a/web/ons-demo/js/app.js b/web/ons-demo/js/app.js
index ce5752c..7f2b159 100644
--- a/web/ons-demo/js/app.js
+++ b/web/ons-demo/js/app.js
@@ -42,27 +42,69 @@
 	// DRAW THE NODES
 	var rings = [{
 		radius: 3,
-		width: 4,
+		width: 6,
 		switches: model.edgeSwitches,
-		className: 'edge'
+		className: 'edge',
+		angles: []
 	}, {
 		radius: 2.25,
-		width: 8,
+		width: 12,
 		switches: model.aggregationSwitches,
-		className: 'aggregation'
+		className: 'aggregation',
+		angles: []
 	}, {
 		radius: .75,
-		width: 16,
+		width: 18,
 		switches: model.coreSwitches,
-		className: 'core'
+		className: 'core',
+		angles: []
 	}];
 
+
+	var aggRanges = {};
+
+	// arrange edge switches at equal increments
+	var k = 360 / rings[0].switches.length;
+	rings[0].switches.forEach(function (s, i) {
+		var angle = k * i;
+
+		rings[0].angles[i] = angle;
+
+		// record the angle for the agg switch layout
+		var dpid = s.dpid.split(':');
+		dpid[7] = '00';
+		var aggdpid = dpid.join(':');
+		var aggRange = aggRanges[aggdpid];
+		if (!aggRange) {
+			aggRange = aggRanges[aggdpid] = {};
+			aggRange.min = aggRange.max = angle;
+		} else {
+			aggRange.max = angle;
+		}
+
+
+	});
+
+	// arrange aggregation switches to "fan out" to edge switches
+	k = 360 / rings[1].switches.length;
+	rings[1].switches.forEach(function (s, i) {
+//		rings[1].angles[i] = k * i;
+		var range = aggRanges[s.dpid];
+
+		rings[1].angles[i] = (range.min + range.max)/2;
+	});
+
+	// arrange core switches at equal increments
+	k = 360 / rings[2].switches.length;
+	rings[2].switches.forEach(function (s, i) {
+		rings[2].angles[i] = k * i;
+	});
+
 	function ringEnter(data, i) {
 		if (!data.switches.length) {
 			return;
 		}
 
-		var k = 360 / data.switches.length;
 
 		d3.select(this).selectAll("g")
 			.data(d3.range(data.switches.length).map(function() {
@@ -73,7 +115,7 @@
 				return data.switches[i].dpid;
 			})
 			.attr("transform", function(_, i) {
-				return "rotate(" + i * k + ")translate(" + data.radius * 150 + ")rotate(" + (-i * k) + ")";
+				return "rotate(" + data.angles[i]+ ")translate(" + data.radius * 150 + ")rotate(" + (-data.angles[i]) + ")";
 			})
 			.append("svg:circle")
 			.attr('class', data.className)
@@ -101,7 +143,7 @@
 	function zoom(data, index) {
 		svg.selectAll('.edge').data(model.edgeSwitches).transition().duration(100)
 			.attr("r", function (data, i) {
-				return rings[0].width * (index == i ? 2 : 1);
+				return rings[0].width * (index == i ? 3 : 1);
 			})
 	}
 
diff --git a/web/ons-demo/js/model.js b/web/ons-demo/js/model.js
index e16565c..354299f 100644
--- a/web/ons-demo/js/model.js
+++ b/web/ons-demo/js/model.js
@@ -10,6 +10,17 @@
 		links: results.links
 	}
 
+	// sort the switches
+	results.switches.sort(function (a, b) {
+		var aA = a.dpid.split(':');
+		var bB = b.dpid.split(':');
+		for (var i=0; i<aA.length; i+=1) {
+			if (aA[i] != bB[i]) {
+				return aA[i] - bB[i];
+			}
+		}
+		return 0;
+	});
 
 	// identify switch types
 	var coreSwitchDPIDs = {};
@@ -23,7 +34,7 @@
 	});
 
 	results.switches.forEach(function (s) {
-		s.controller = results.mapping[s.dpid][0].controllerId
+		s.controller = results.mapping[s.dpid][0].controllerId;
 
 		if (coreSwitchDPIDs[s.dpid]) {
 			model.coreSwitches.push(s);