From f24d6f10ac5151fd31943290b876750baa67b145 Mon Sep 17 00:00:00 2001
From: "Selby, Nicholas Stearns" <nselby3@gatech.edu>
Date: Wed, 1 Nov 2017 16:13:59 -0400
Subject: [PATCH] Dijkstra

---
 sim/graph.js        | 144 ++++++++++++++++++++++++++++++++++++++++++++
 sim/index.html      |   1 +
 sim/manager_nick.js |  86 ++++++++++++++++++++++++++
 sim/sim_nick.js     |  55 +++++++++++++++++
 4 files changed, 286 insertions(+)
 create mode 100644 sim/graph.js
 create mode 100644 sim/manager_nick.js
 create mode 100644 sim/sim_nick.js

diff --git a/sim/graph.js b/sim/graph.js
new file mode 100644
index 0000000..22111e6
--- /dev/null
+++ b/sim/graph.js
@@ -0,0 +1,144 @@
+var Graph = (function (undefined) {
+
+	var extractKeys = function (obj) {
+		var keys = [], key;
+		for (key in obj) {
+		    Object.prototype.hasOwnProperty.call(obj,key) && keys.push(key);
+		}
+		return keys;
+	}
+
+	var sorter = function (a, b) {
+		return parseFloat (a) - parseFloat (b);
+	}
+
+	var findPaths = function (map, start, end, infinity) {
+		infinity = infinity || Infinity;
+
+		var costs = {},
+		    open = {'0': [start]},
+		    predecessors = {},
+		    keys;
+
+		var addToOpen = function (cost, vertex) {
+			var key = "" + cost;
+			if (!open[key]) open[key] = [];
+			open[key].push(vertex);
+		}
+
+		costs[start] = 0;
+
+		while (open) {
+			if(!(keys = extractKeys(open)).length) break;
+
+			keys.sort(sorter);
+
+			var key = keys[0],
+			    bucket = open[key],
+			    node = bucket.shift(),
+			    currentCost = parseFloat(key),
+			    adjacentNodes = map[node] || {};
+
+			if (!bucket.length) delete open[key];
+
+			for (var vertex in adjacentNodes) {
+			    if (Object.prototype.hasOwnProperty.call(adjacentNodes, vertex)) {
+					var cost = adjacentNodes[vertex],
+					    totalCost = cost + currentCost,
+					    vertexCost = costs[vertex];
+
+					if ((vertexCost === undefined) || (vertexCost > totalCost)) {
+						costs[vertex] = totalCost;
+						addToOpen(totalCost, vertex);
+						predecessors[vertex] = node;
+					}
+				}
+			}
+		}
+
+		if (costs[end] === undefined) {
+			return null;
+		} else {
+			return predecessors;
+		}
+
+	}
+
+	var extractShortest = function (predecessors, end) {
+		var nodes = [],
+		    u = end;
+
+		while (u !== undefined) {
+			nodes.push(u);
+			u = predecessors[u];
+		}
+
+		nodes.reverse();
+		return nodes;
+	}
+
+	var findShortestPath = function (map, nodes) {
+		var start = nodes.shift(),
+		    end,
+		    predecessors,
+		    path = [],
+		    shortest;
+
+		while (nodes.length) {
+			end = nodes.shift();
+			predecessors = findPaths(map, start, end);
+
+			if (predecessors) {
+				shortest = extractShortest(predecessors, end);
+				if (nodes.length) {
+					path.push.apply(path, shortest.slice(0, -1));
+				} else {
+					return path.concat(shortest);
+				}
+			} else {
+				return null;
+			}
+
+			start = end;
+		}
+	}
+
+	var toArray = function (list, offset) {
+		try {
+			return Array.prototype.slice.call(list, offset);
+		} catch (e) {
+			var a = [];
+			for (var i = offset || 0, l = list.length; i < l; ++i) {
+				a.push(list[i]);
+			}
+			return a;
+		}
+	}
+
+	var Graph = function (map) {
+		this.map = map;
+	}
+
+	Graph.prototype.findShortestPath = function (start, end) {
+		if (Object.prototype.toString.call(start) === '[object Array]') {
+			return findShortestPath(this.map, start);
+		} else if (arguments.length === 2) {
+			return findShortestPath(this.map, [start, end]);
+		} else {
+			return findShortestPath(this.map, toArray(arguments));
+		}
+	}
+
+	Graph.findShortestPath = function (map, start, end) {
+		if (Object.prototype.toString.call(start) === '[object Array]') {
+			return findShortestPath(map, start);
+		} else if (arguments.length === 3) {
+			return findShortestPath(map, [start, end]);
+		} else {
+			return findShortestPath(map, toArray(arguments, 1));
+		}
+	}
+
+	return Graph;
+
+})();
diff --git a/sim/index.html b/sim/index.html
index 75f5f54..5d1d21a 100755
--- a/sim/index.html
+++ b/sim/index.html
@@ -63,6 +63,7 @@
 		<script type="text/javascript" src="d3.v3.min.js"></script>
 		<script type="text/javascript" src="jquery.min.js"></script>
 		<script type="text/javascript" src="require.js"></script>
+		<script src="graph.js"></script>
 		<script src="goog/base.js"></script>
 		<script>
 		goog.require("goog.structs.PriorityQueue")
diff --git a/sim/manager_nick.js b/sim/manager_nick.js
new file mode 100644
index 0000000..a80623d
--- /dev/null
+++ b/sim/manager_nick.js
@@ -0,0 +1,86 @@
+function Manager(self) {
+	self.manager = this;
+
+	this.ports = [];
+	this.numports = 0;
+	var map = {0:{1:4,2:3},1:{0:4,3:1},2:{0:3,3:1},3:{1:1,2:1}};
+	var graph = new Graph(map);
+	const HOP_COUNT = 2;
+
+	this.setup = function(numports) {
+		this.numports = numports;
+		this.ports = new Array(numports).fill(-1);
+	};
+
+	this.connect = function(port, id) {
+
+		if (!(port < this.numports)) {
+			return;
+		}
+
+		if (self.id != id) {
+			var prevId = this.ports[port];
+			if (prevId >= 0) {
+				self.disconnect(prevId);
+			}
+
+			this.ports[port] = id;
+			self.connect(id);
+		}
+	};
+
+	this.disconnect = function(port) {
+		if (!(port < this.numports)) {
+			return;
+		}
+
+		var prevId = this.ports[port];
+		if (prevId >= 0) {
+			self.disconnect(prevId);
+		}
+
+		this.ports[port] = -1;
+	}
+
+	this.send = function(port, name, msg) {
+		if (port < this.numports && this.ports[port] >= 0) {
+			self.send(this.ports[port], 'message', {name: name, obj: msg});
+		}
+	};
+	
+	this.sendTo = function(id, msg) {
+		var path = graph.findShortestPath(self.id, id);
+		var nextNode = path[1];
+		for (var p = 0; p < this.numports; p++) {
+			if (this.ports[p] === parseInt(nextNode)) {
+				this.send(p, id, msg);
+				return;
+			}
+		}
+	}
+	
+	// Flood Packet: ['F' , HOP COUNT , ORIGINAL SENDER ID , COST 1 , RECIPIENT 1 , COST 2 , RECIPIENT 2 ...]
+	this.flood = function() {
+		for (var p = 0; p < this.numports; p++) {
+			this.send(this.ports[p], 'F', self.id);
+		}
+	}
+
+	this.onReceive = function(from, o) {
+		var port = this.ports.indexOf(from);
+		if (port == -1) {
+			return;
+		}
+
+		self.log(`got message '${o.name}' on port ${port}: '${o.obj}'`);
+		
+		if (o.name != self.id) {
+			this.sendTo(o.name,o.obj);
+		}
+	};
+
+	self.on('message', this.onReceive, this);
+	
+}
+
+module.exports = Manager;
diff --git a/sim/sim_nick.js b/sim/sim_nick.js
new file mode 100644
index 0000000..be1efd4
--- /dev/null
+++ b/sim/sim_nick.js
@@ -0,0 +1,55 @@
+var net = require("./network"),
+	manager = require('./manager');
+
+const numClients = 4;
+const startupDelay = 100;
+
+var clients = [];
+for (var i = 0; i < numClients; i++) {
+	c = new net.Client();
+	c.use(manager);
+	clients.push(c);
+}
+
+clients[0].init(function() {
+	this.delay(startupDelay, function() {
+		this.manager.setup(2);
+		this.manager.connect(0, 1);
+		this.manager.connect(1, 2);
+	});
+
+	this.delay(1000, function() {
+		//this.manager.send(0, 'Special Delivery', 'Surprise!!!');
+		this.manager.sendTo(3, 'Tell 3 I said I love her.');
+	});
+
+});
+
+clients[1].init(function() {
+	this.delay(startupDelay, function() {
+		this.manager.setup(2);
+		this.manager.connect(0, 0);
+		this.manager.connect(1, 3);
+	});
+});
+
+clients[2].init(function() {
+	this.delay(startupDelay, function() {
+		this.manager.setup(2);
+		this.manager.connect(0, 0);
+		this.manager.connect(1, 3);
+	});
+});
+
+clients[3].init(function() {
+	this.delay(startupDelay, function() {
+		this.manager.setup(2);
+		this.manager.connect(0, 1);
+		this.manager.connect(1, 2);
+	});
+});
+
+for (var i = 0; i < numClients; i++) {
+	net.add(1, clients[i]);
+}
+net.run(100 * 1000); // runs for 100 seconds
\ No newline at end of file
-- 
GitLab