blob: e94d1aa125212fe774574f687984fd46d9ffb4d9 [file] [log] [blame]
Masayoshi Kobayashi274c07d2013-02-20 21:38:16 +00001function gui(data_source){
2 var width = 960,
3 height = 500;
4 var color = d3.scale.category20();
5
6 var svg = d3.select("body").append("svg:svg")
7 .attr("width", width)
8 .attr("height", height);
9
10 var force = d3.layout.force()
11 .charge(-500)
12 .linkDistance(100)
13 .size([width, height]);
14
15 var path = svg.selectAll("path");
16 var circle = svg.selectAll("circle");
17 var text = svg.selectAll("g");
18 var pathlen = 0;
19 var from;
20 var to;
21 var path_set = 0;
22
23
24 d3.json(data_source,init);
25
26 function init(json){
27 nodes = force.nodes();
28 links = force.links();
29
30 json.nodes.forEach(function(item) {
31 nodes.push(item);
32 });
33/*
34 nodes.sort(function(a,b) {
35 if (a.name > b.name) {return 1;}
36 else if (a.name < b.name) {return -1;}
37 else {return 0;}
38 });
39*/
40 json.links.forEach(function(item) {
41 links.push(item);
42 });
43 draw(nodes, links);
44 }
45
46 function update(json) {
47 Array.prototype.diff2 = function(arr) {
48 return this.filter(function(i) {
49 for (var j = 0; j < arr.length ; j++) {
50 if (arr[j].source === i.source.index &&
51 arr[j].target === i.target.index)
52 return false;
53 }
54 return true;
55 });
56 };
57
58 Array.prototype.diff = function(arr) {
59 return this.filter(function(i) {
60 for (var j = 0; j < arr.length ; j++) {
61 if (arr[j].source.index === i.source &&
62 arr[j].target.index === i.target)
63 return false;
64 }
65 return true;
66 });
67 };
68
69 Array.prototype.node_diff = function(arr) {
70 return this.filter(function(i) {
71 for (var j = 0; j < arr.length ; j++) {
72 if (arr[j].name === i.name)
73 return false;
74 }
75 return true;
76 });
77 };
78
79
80 links.sort(function(a,b) {
81 if (a.source > b.source) {return 1;}
82 else if (a.source < b.source) {return -1;}
83 else {
84 if (a.target > b.target) {return 1;}
85 if (a.target < b.target) {return -1;}
86 else {return 0;}
87 }
88 });
89
90// for (var i=0; i<links.length; i++) {
91// if (i != 0 &&
92// links[i].source == links[i-1].source &&
93// links[i].target == links[i-1].target) {
94// links[i].linknum = links[i-1].linknum + 1;
95// }
96// else {links[i].linknum = 1;};
97// };
98
99
100 function cdiff(topo) {
101 var changed = false;
102
103 var n_adds = topo.nodes.node_diff(nodes);
104 var n_rems = nodes.node_diff(topo.nodes);
105 for (var i = 0; i < n_adds.length; i++) {
106 nodes.push(n_adds[i]);
107 changed = true;
108 }
109 for (var i = 0; i < n_rems.length; i++) {
110 for (var j = 0; j < nodes.length; j++) {
111 if ( nodes[j].name == n_rems[i].name ){
112 nodes.splice(j,1);
113 changed = true;
114 break;
115 }
116 }
117 }
118
119 var l_adds = [];
120 var l_rems = [];
121 l_adds = added_links(topo, links, l_adds);
122 l_rems = gone_links(topo, links, l_rems);
123
124 for (var i = 0; i < l_rems.length ; i++) {
125 for (var j = 0; j < links.length; j++) {
126 if (links[j].source.name == l_rems[i].source.name &&
127 links[j].target.name == l_rems[i].target.name) {
128 links.splice(j,1);
129 changed = true;
130 break;
131 }
132 }
133 }
134 for (var i = 0; i < l_adds.length; i++) {
135 var s;
136 var t;
137 for (var j = 0; j < nodes.length; j++) {
138 if ( json.nodes[l_adds[i].source].name == nodes[j].name ){
139 s = j;
140 break;
141 }
142 }
143 for (var j = 0; j < nodes.length; j++) {
144 if ( json.nodes[l_adds[i].target].name == nodes[j].name ){
145 t = j;
146 break;
147 }
148 }
149 l_adds[i].source = s;
150 l_adds[i].target = t;
151 links.push(l_adds[i]);
152 changed = true;
153 }
154 return changed
155 }
156
157
158 var changed = cdiff(json);
159
160 for (var i = 0; i < json.nodes.length; i++) {
161 nodes[i].group = json.nodes[i].group
162 }
163 var rewrite = 0;
164 for (var i = 0; i < links.length; i++) {
165 for (var j = 0; j < json.links.length; j++) {
166 /*
167 console.log("link" + i);
168 console.log(links[i].source.name + "->" + links[i].target.name);
169 console.log("type " + links[i].type);
170 console.log("json link" + j);
171 console.log(json.nodes[json.links[j].source].name + "->" + json.nodes[json.links[j].target].name);
172 */
173 if (links[i].target.name == json.nodes[json.links[j].target].name &&
174 links[i].source.name == json.nodes[json.links[j].source].name ){
175 links[i].type = json.links[j].type;
176 rewrite ++;
177 }
178 }
179 }
180 console.log("changed?" + changed);
181 if (changed){
182 console.log(nodes);
183 console.log(links);
184 path = svg.selectAll("path").data(links)
185 circle = svg.selectAll("circle").data(nodes);
186 text = svg.selectAll("text").data(nodes);
187
188 force.stop();
189
190 path.enter().append("svg:path")
191 .attr("class", function(d) { return "link"; })
192 .attr("marker-end", function(d) {
193 if(d.type == 1){
194 return "url(#TriangleRed)";
195 } else {
196 return "url(#Triangle)";
197 }
198 });
199
200 circle.enter().append("svg:circle")
201 .attr("r", 8)
202/* .on("click", function(d,i) {
203 if ( path_set == 0 || path_set == 2 ){
204 fm = d.name;
205 path_set = 1;
206 alert("from set to " + d.name);
207 }else if ( path_set == 1 ){
208 to = d.name;
209 path_set = 2;
210 alert("to set to " + d.name);
211 }
212 }) */
213 .call(force.drag);
214
215/* text.enter().append("svg:text")
216 .attr("x", 8)
217 .attr("y", ".31em")
218 .attr("class", "shadow")
219 .text(function(d) { return d.name.split(":")[7]; }); */
220
221 text.enter().append("svg:text")
222 .attr("x", 8)
223 .attr("y", ".31em")
224 .text(function(d) { return d.name.split(":")[7]; });
225
226 circle.append("title")
227 .text(function(d) { return d.name; });
228
229 path.attr("stroke", function(d) {
230 if(d.type == 1){
231 return "red"
232 } else {
233 return "black"
234 }
235 })
236 .attr("stroke-width", function(d) {
237 if(d.type == 1){
238 return "4px";
239 } else {
240 return "1.5px";
241 }
242 });
243
244
245 path.exit().remove();
246 circle.exit().remove();
247 text.exit().remove();
248 force.on("tick", tick);
249 force.start();
250 }
251 }
252 function draw(nodes, links){
253 path = svg.append("svg:g").selectAll("path").data(links)
254 circle = svg.append("svg:g").selectAll("circle").data(nodes);
255 text = svg.append("svg:g").selectAll("text").data(nodes);
256
257 path.enter().append("svg:path")
258 .attr("class", function(d) { return "link"; })
259 .attr("marker-end", function(d) {
260 if(d.type == 1){
261 return "url(#TriangleRed)";
262 } else {
263 return "url(#Triangle)";
264 }
265 });
266
267 path.attr("stroke", function(d) {
268 if(d.type == 1){
269 return "red"
270 } else {
271 return "black"
272 }
273 }).attr("stroke-width", function(d) {
274 if(d.type == 1){
275 return "4px";
276 } else {
277 return "1.5px";
278 }
279 }).attr("marker-end", function(d) {
280 if(d.type == 1){
281 return "url(#TriangleRed)";
282 } else {
283 return "url(#Triangle)";
284 }
285 });
286
287
288 circle.enter().append("svg:circle")
289 .attr("r", 8)
290/* .on("click", function(d,i) {
291 if ( path_set == 0 || path_set == 2 ){
292 fm = d.name;
293 path_set = 1;
294 alert("from set to " + d.name);
295 }else if ( path_set == 1 ){
296 to = d.name;
297 path_set = 2;
298 alert("to set to " + d.name);
299 }
300 }) */
301 .call(force.drag);
302
303/* text.enter().append("svg:text")
304 .attr("x", 8)
305 .attr("y", ".31em")
306 .attr("class", "shadow")
307 .text(function(d) { return d.name.split(":")[7]; }); */
308
309 text.enter().append("svg:text")
310 .attr("x", 8)
311 .attr("y", ".31em")
312 .text(function(d) { return d.name.split(":")[7]; });
313
314 circle.append("title")
315 .text(function(d) { return d.name; });
316
317 circle.attr("fill", function(d) {
318 if (d.group == 1){return "red";}
319 else if (d.group == 2){return "blue";}
320 else if (d.group == 3){return "green";}
321 else{ return "gray"; }
322 });
323
324
325 force.on("tick", tick);
326 path.exit().remove();
327 circle.exit().remove();
328// text.exit().remove();
329
330 force.start();
331
332 setInterval(function() {
333 $.ajax({
334// url: 'http://onosnat.onlab.us:8080/topology',
335 url: data_source,
336 success: function(json) {
337 update(json)
338 },
339 dataType: "json"
340 });
341 }, 3000);
342 }
343 function tick() {
344 path.attr("d", function(d) {
345 var dx = d.target.x - d.source.x,
346 dy = d.target.y - d.source.y,
347 dr = 1/d.linknum; //linknum is defined above
348 dr = 300;
349 return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
350 });
351
352 path
353 .attr("stroke", function(d) {
354 if(d.type == 1){
355 return "red"
356 } else {
357 return "black"
358 }
359 }).attr("stroke-width", function(d) {
360 if(d.type == 1){
361 return "4px";
362 } else {
363 return "1.5px";
364 }
365 }).attr("marker-end", function(d) {
366 if(d.type == 1){
367 return "url(#TriangleRed)";
368 } else {
369 return "url(#Triangle)";
370 }
371 });
372
373
374// circle.attr("cx", function(d) { return d.x; }).attr("cy", function(d) { return d.y; });
375 circle.attr("transform", function(d) {
376 return "translate(" + d.x + "," + d.y + ")";
377 })
378 circle.attr("fill", function(d) {
379 if (d.group == 1){return "red";}
380 else if (d.group == 2){return "blue";}
381 else if (d.group == 3){return "green";}
382 else{ return "gray"; }
383 });
384// text.attr("x", function(d) { return d.x; }).attr("y", function(d) { return d.y; });
385// text.attr("x", function(d) { return d.x; }).attr("y", function(d) { return d.y; });
386 text.attr("transform", function(d) {
387 return "translate(" + d.x + "," + d.y + ")";
388 });
389 }
390}