Skip to content

Commit 0fa51ca

Browse files
committed
Dijkstra example now working
1 parent 9858023 commit 0fa51ca

File tree

9 files changed

+320
-70
lines changed

9 files changed

+320
-70
lines changed

samples/dci/DCI.js

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,38 @@
1-
/*
2-
function A() {}
3-
(<Test> A).something = 123;
4-
5-
export var Context = {
6-
extend: function(callback): any {
7-
return function(...args : any[]) {
8-
var context = new callback();
9-
if (!context.bindRoles) throw new Error('bindRoles() method not found');
10-
11-
context.bindRoles.apply(callback, arguments);
12-
return context;
13-
}
14-
}
15-
};
16-
*/
171
var Context = (function () {
182
function Context() {
193
}
20-
Context.extend = //for plain JS version
4+
Context.extend = //For plain JS version
5+
//Returns a constructor function to instantiate a new context.
6+
//In the future it may also inherit some utility methods that are common to all contexts.
7+
//
8+
//It will check whether the passed callback function has a bindRoles() method, and if so,
9+
//any constructor arguments will be passed to bindRoles(). If the passed callback does not
10+
//have a bindRoles() method, then the roles should be bound at the top of the callback function.
11+
//
12+
//bindRoles() is useful for the case where you want to be able to re-bind the roles on an existing
13+
//context object.
14+
//
2115
function (callback) {
2216
return function () {
2317
var args = [];
2418
for (var _i = 0; _i < (arguments.length - 0); _i++) {
2519
args[_i] = arguments[_i + 0];
2620
}
27-
var context = new callback();
28-
if (!context.bindRoles)
29-
throw new Error('bindRoles() method not found');
21+
//We always pass the parameters to the passed function (callback) because
22+
//we can't check whether or not a bindRoles() method exists until after we've
23+
//instantiated the context object.
24+
//The ContextConstructor function is needed so that we can pass constructor arguments dynamically
25+
//(see http://stackoverflow.com/a/13931627/560114)
26+
var ContextConstructor = function () {
27+
return callback.apply(this, args);
28+
};
29+
ContextConstructor.prototype = callback.prototype;
30+
31+
var context = new ContextConstructor();
32+
context.constructor = callback;
3033

31-
context.bindRoles.apply(callback, arguments);
34+
if (context.bindRoles)
35+
context.bindRoles.apply(context, arguments);
3236
return context;
3337
};
3438
};
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import DCI = require('../../DCI');
2+
import HashMap = require('../../typescript/Dijkstra/HashMap');
3+
4+
export = CalculateShortestPath;
5+
6+
/**
7+
* Calculate the shortest path between two points using the Dijkstra algorithm.
8+
* This javascript version was based on an earlier (non-TypeScript) implementation by Egon Elbre.
9+
*/
10+
var CalculateShortestPath = DCI.Context.extend(function() {
11+
12+
this.bindRoles = function(initial, destination, graph) {
13+
Initial <- initial;
14+
Graph <- graph;
15+
Tentative <- new HashMap();
16+
Unvisited <- new HashMap();
17+
Path <- new HashMap(); // best path (to --> from)
18+
19+
this.destination = destination;
20+
}
21+
22+
//Run the use case
23+
this.run = function() {
24+
Graph.nodes.each(function(node) {
25+
Unvisited.add(node);
26+
Tentative.add(node, Infinity);
27+
});
28+
Tentative.add(Initial, 0);
29+
30+
Current = Initial;
31+
Current.markVisited();
32+
33+
while (!Unvisited.isEmpty()) {
34+
Current.relaxDistances();
35+
Current.markVisited();
36+
37+
if (!Unvisited.has(this.destination)) break;
38+
39+
Current = Unvisited.findNearest();
40+
if (Current === undefined) break;
41+
}
42+
return Path.to(this.destination);
43+
}
44+
45+
role Initial {}
46+
47+
role Neighbor {
48+
visited() {
49+
return !Unvisited.has(this);
50+
}
51+
}
52+
53+
role Current {
54+
markVisited() {
55+
Unvisited.remove(this);
56+
}
57+
58+
getNeighbors() {
59+
return Graph.neighbors(this);
60+
}
61+
62+
relaxDistances() {
63+
this.getNeighbors().each(function(node) {
64+
Neighbor <- node;
65+
if (Neighbor.visited()) return;
66+
67+
var alternate = Tentative.get(Current) + Current.distanceTo(Neighbor);
68+
if (alternate < Tentative.get(Neighbor)) {
69+
Tentative.add(Neighbor, alternate);
70+
Path.add(Neighbor, Current);
71+
}
72+
});
73+
}
74+
75+
distanceTo(other) {
76+
return Graph.distance(this, other);
77+
}
78+
}
79+
80+
role Graph {
81+
distance(from, to) {
82+
if(from === to) return 0;
83+
return this.nodes.get(from).get(to) || Infinity;
84+
}
85+
86+
neighbors(node) {
87+
return this.nodes.get(node);
88+
}
89+
}
90+
91+
role Tentative {}
92+
93+
role Unvisited {
94+
findNearest() {
95+
var nearest = undefined,
96+
distance = Infinity;
97+
this.each(function(node) {
98+
var dist = Tentative.get(node);
99+
if(dist < distance) {
100+
nearest = node;
101+
distance = dist;
102+
}
103+
})
104+
return nearest;
105+
}
106+
}
107+
108+
role Path {
109+
to(to) {
110+
var path = [to],
111+
cur = to;
112+
while (cur != Initial) {
113+
cur = this.get(cur);
114+
path.unshift(cur);
115+
if (cur === undefined) {
116+
return undefined;
117+
}
118+
}
119+
return path;
120+
}
121+
}
122+
});

samples/dci/js/Dijkstra/Graph.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import HashMap = require('../../typescript/Dijkstra/HashMap');
2+
export = Graph;
3+
4+
function Graph(edges) {
5+
this.nodes = new HashMap();
6+
7+
for (var i = 0; i < edges.length; i++) {
8+
var edge = edges[i],
9+
from = edge[0],
10+
to = edge[1],
11+
dist = edge[2];
12+
13+
forceMap(this.nodes, to);
14+
var cur = forceMap(this.nodes, from);
15+
cur.add(to, dist);
16+
}
17+
}
18+
19+
function forceMap(nodes, node) {
20+
var map = nodes.get(node);
21+
if (map === undefined) {
22+
map = new HashMap();
23+
nodes.add(node, map);
24+
}
25+
return map;
26+
}

samples/dci/js/Dijkstra/index.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import CalculateShortestPath = require('./CalculateShortestPath');
2+
import Graph = require('./Graph');
3+
4+
var a = {id:'a'},
5+
b = {id:'b'},
6+
c = {id:'c'},
7+
d = {id:'d'},
8+
e = {id:'e'},
9+
f = {id:'f'},
10+
g = {id:'g'},
11+
h = {id:'h'},
12+
i = {id:'i'};
13+
14+
var edges = [
15+
[a,b,2],
16+
[a,d,1],
17+
[b,c,3],
18+
[b,e,2],
19+
[c,f,1],
20+
[d,e,1],
21+
[d,g,2],
22+
[e,f,1],
23+
[f,i,4],
24+
[g,h,1],
25+
[h,i,2]
26+
];
27+
28+
var graph = new Graph(edges);
29+
var ctx = new CalculateShortestPath(a, i, graph);
30+
31+
//Run the use case
32+
var path = ctx.run();
33+
34+
var proper = [];
35+
36+
path.forEach(function(node) {
37+
proper.push(node.id);
38+
});
39+
40+
console.log(proper.join(" -> "));

samples/dci/js/TransferMoney/Account.js

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,8 @@ var DCI = require('../../DCI');
33

44

55

6-
var Account = DCI.Context.extend(function () {
6+
var Account = DCI.Context.extend(function (ledgers) {
77
var __context = this;
8-
//TypeScript doesn't support this syntax yet.
9-
//If it did, in ES5 environments, a native-like getter could be created:
10-
/*
11-
get balance() {
12-
return Ledgers.getBalance();
13-
}
14-
*/
158
this.__$Ledgers = { addEntry: function (message, amount) {
169
__context.Ledgers.push(new LedgerEntry(message, amount));
1710
}
@@ -23,11 +16,9 @@ this.__$Ledgers = { addEntry: function (message, amount) {
2316
return sum;
2417
}
2518
};
26-
this.bindRoles = function (ledgers) {
27-
if (!ledgers)
28-
ledgers = [];
29-
__context.Ledgers = ledgers;
30-
};
19+
if (!ledgers)
20+
ledgers = [];
21+
__context.Ledgers = ledgers;
3122
this.increaseBalance = function (amount) {
3223
__context.__$Ledgers.addEntry.call(__context.Ledgers, 'depositing', amount);
3324
};
@@ -38,7 +29,6 @@ this.__$Ledgers = { addEntry: function (message, amount) {
3829
return __context.__$Ledgers.getBalance.call(__context.Ledgers);
3930
};
4031

41-
4232
});
4333
function LedgerEntry(message, amount) {
4434
this.message = message;

samples/dci/js/TransferMoney/Account.ts

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,52 @@ import DCI = require('../../DCI');
22

33
export = Account;
44

5+
var Account = DCI.Context.extend(function(ledgers) {
6+
if (!ledgers) ledgers = [];
7+
Ledgers <- ledgers;
8+
9+
this.increaseBalance = function(amount) {
10+
Ledgers.addEntry('depositing', amount);
11+
};
12+
13+
this.decreaseBalance = function(amount) {
14+
Ledgers.addEntry('withdrawing', 0 - amount);
15+
};
16+
17+
this.getBalance = function() {
18+
return Ledgers.getBalance();
19+
}
20+
21+
role Ledgers {
22+
addEntry(message, amount) {
23+
Ledgers.push(new LedgerEntry(message, amount));
24+
}
25+
26+
getBalance() {
27+
var sum = 0;
28+
Ledgers.forEach(function(ledgerEntry) {
29+
sum += ledgerEntry.amount;
30+
});
31+
return sum;
32+
}
33+
}
34+
});
35+
36+
function LedgerEntry(message, amount) {
37+
this.message = message;
38+
this.amount = amount;
39+
}
40+
41+
//export the LedgerEntry constructor
42+
Account.LedgerEntry = LedgerEntry;
43+
44+
/*
45+
var Account: any = function(ledgers) {
46+
if (!ledgers) ledgers = [];
47+
Ledgers <- ledgers;
48+
}
49+
*/
50+
/*
551
var Account = DCI.Context.extend(function() {
652
753
this.bindRoles = function(ledgers) {
@@ -23,11 +69,9 @@ var Account = DCI.Context.extend(function() {
2369
2470
//TypeScript doesn't support this syntax yet.
2571
//If it did, in ES5 environments, a native-like getter could be created:
26-
/*
27-
get balance() {
28-
return Ledgers.getBalance();
29-
}
30-
*/
72+
//get balance() {
73+
// return Ledgers.getBalance();
74+
//}
3175
3276
role Ledgers {
3377
addEntry(message, amount) {
@@ -51,7 +95,7 @@ function LedgerEntry(message, amount) {
5195
5296
//export the LedgerEntry constructor
5397
Account.LedgerEntry = LedgerEntry;
54-
98+
*/
5599

56100
/*
57101
function Account(initialBalance) {

samples/dci/js/TransferMoney/TransferMoney.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ export = TransferMoney;
66
*
77
* @constructor
88
* @this {TransferMoney}
9-
* @param {Account} source
10-
* @param {Account} destination
9+
* @param {Account} sourceAcct
10+
* @param {Account} destinationAcct
1111
* @param {number} amount
1212
*/
1313
var TransferMoney = DCI.Context.extend(function() {
@@ -16,12 +16,14 @@ var TransferMoney = DCI.Context.extend(function() {
1616
DestinationAccount <- destinationAcct;
1717
Amount <- amount;
1818
}
19-
19+
20+
//Run the use case
2021
this.run = function() {
2122
SourceAccount.transferOut();
2223
}
2324

2425
role SourceAccount {
26+
//transfer out of this account and into the destination account
2527
transferOut() {
2628
this.withdraw();
2729
DestinationAccount.deposit();

0 commit comments

Comments
 (0)