nutella_framework 0.4.27 → 0.4.28

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/VERSION +1 -1
  4. data/framework_components/order.json +2 -1
  5. data/framework_components/room-places-interface/.gitignore +3 -0
  6. data/framework_components/room-places-interface/LICENSE +21 -0
  7. data/framework_components/room-places-interface/Readme.md +0 -0
  8. data/framework_components/room-places-interface/bower.json +29 -0
  9. data/framework_components/room-places-interface/bower_components/bower-mqttws/.bower.json +23 -0
  10. data/framework_components/room-places-interface/bower_components/bower-mqttws/bower.json +14 -0
  11. data/framework_components/room-places-interface/bower_components/bower-mqttws/mqttws31.js +2081 -0
  12. data/framework_components/room-places-interface/bower_components/bower-mqttws/readme.md +4 -0
  13. data/framework_components/room-places-interface/bower_components/nutella_lib/.bower.json +37 -0
  14. data/framework_components/room-places-interface/bower_components/nutella_lib/LICENSE +21 -0
  15. data/framework_components/room-places-interface/bower_components/nutella_lib/README.md +15 -0
  16. data/framework_components/room-places-interface/bower_components/nutella_lib/bower.json +28 -0
  17. data/framework_components/room-places-interface/bower_components/nutella_lib/examples/browser/mqtt_client_hello_world.html +23 -0
  18. data/framework_components/room-places-interface/bower_components/nutella_lib/examples/browser/nutella_hello_world.html +52 -0
  19. data/framework_components/room-places-interface/bower_components/nutella_lib/examples/node/mqtt_client_hello_world.js +14 -0
  20. data/framework_components/room-places-interface/bower_components/nutella_lib/examples/node/nutella_hello_world.js +38 -0
  21. data/framework_components/room-places-interface/bower_components/nutella_lib/nutella_lib.js +789 -0
  22. data/framework_components/room-places-interface/bower_components/nutella_lib/package.json +30 -0
  23. data/framework_components/room-places-interface/css/animation.css +22 -0
  24. data/framework_components/room-places-interface/css/bootstrap.min.css +5 -0
  25. data/framework_components/room-places-interface/css/cursor.css +22 -0
  26. data/framework_components/room-places-interface/css/font-awesome/css/font-awesome.css +1801 -0
  27. data/framework_components/room-places-interface/css/font-awesome/css/font-awesome.min.css +4 -0
  28. data/framework_components/room-places-interface/css/font-awesome/fonts/FontAwesome.otf +0 -0
  29. data/framework_components/room-places-interface/css/font-awesome/fonts/fontawesome-webfont.eot +0 -0
  30. data/framework_components/room-places-interface/css/font-awesome/fonts/fontawesome-webfont.svg +565 -0
  31. data/framework_components/room-places-interface/css/font-awesome/fonts/fontawesome-webfont.ttf +0 -0
  32. data/framework_components/room-places-interface/css/font-awesome/fonts/fontawesome-webfont.woff +0 -0
  33. data/framework_components/room-places-interface/css/font-awesome/fonts/fontawesome-webfont.woff2 +0 -0
  34. data/framework_components/room-places-interface/css/font-awesome/less/animated.less +34 -0
  35. data/framework_components/room-places-interface/css/font-awesome/less/bordered-pulled.less +16 -0
  36. data/framework_components/room-places-interface/css/font-awesome/less/core.less +13 -0
  37. data/framework_components/room-places-interface/css/font-awesome/less/fixed-width.less +6 -0
  38. data/framework_components/room-places-interface/css/font-awesome/less/font-awesome.less +17 -0
  39. data/framework_components/room-places-interface/css/font-awesome/less/icons.less +596 -0
  40. data/framework_components/room-places-interface/css/font-awesome/less/larger.less +13 -0
  41. data/framework_components/room-places-interface/css/font-awesome/less/list.less +19 -0
  42. data/framework_components/room-places-interface/css/font-awesome/less/mixins.less +27 -0
  43. data/framework_components/room-places-interface/css/font-awesome/less/path.less +15 -0
  44. data/framework_components/room-places-interface/css/font-awesome/less/rotated-flipped.less +20 -0
  45. data/framework_components/room-places-interface/css/font-awesome/less/stacked.less +20 -0
  46. data/framework_components/room-places-interface/css/font-awesome/less/variables.less +606 -0
  47. data/framework_components/room-places-interface/css/font-awesome/scss/_animated.scss +34 -0
  48. data/framework_components/room-places-interface/css/font-awesome/scss/_bordered-pulled.scss +16 -0
  49. data/framework_components/room-places-interface/css/font-awesome/scss/_core.scss +13 -0
  50. data/framework_components/room-places-interface/css/font-awesome/scss/_fixed-width.scss +6 -0
  51. data/framework_components/room-places-interface/css/font-awesome/scss/_icons.scss +596 -0
  52. data/framework_components/room-places-interface/css/font-awesome/scss/_larger.scss +13 -0
  53. data/framework_components/room-places-interface/css/font-awesome/scss/_list.scss +19 -0
  54. data/framework_components/room-places-interface/css/font-awesome/scss/_mixins.scss +27 -0
  55. data/framework_components/room-places-interface/css/font-awesome/scss/_path.scss +15 -0
  56. data/framework_components/room-places-interface/css/font-awesome/scss/_rotated-flipped.scss +20 -0
  57. data/framework_components/room-places-interface/css/font-awesome/scss/_stacked.scss +20 -0
  58. data/framework_components/room-places-interface/css/font-awesome/scss/_variables.scss +606 -0
  59. data/framework_components/room-places-interface/css/font-awesome/scss/font-awesome.scss +17 -0
  60. data/framework_components/room-places-interface/css/icomoon.css +57 -0
  61. data/framework_components/room-places-interface/css/page_layout.css +82 -0
  62. data/framework_components/room-places-interface/fonts/icomoon.eot +0 -0
  63. data/framework_components/room-places-interface/fonts/icomoon.svg +17 -0
  64. data/framework_components/room-places-interface/fonts/icomoon.ttf +0 -0
  65. data/framework_components/room-places-interface/fonts/icomoon.woff +0 -0
  66. data/framework_components/room-places-interface/gulpfile.js +24 -0
  67. data/framework_components/room-places-interface/index.html +73 -0
  68. data/framework_components/room-places-interface/index2.html +1753 -0
  69. data/framework_components/room-places-interface/js/component.js +438 -0
  70. data/framework_components/room-places-interface/js/lib/JSXTransformer-0.12.2.js +15199 -0
  71. data/framework_components/room-places-interface/js/lib/bootstrap.min.js +7 -0
  72. data/framework_components/room-places-interface/js/lib/d3.v3.min.js +5 -0
  73. data/framework_components/room-places-interface/js/lib/jquery-1.10.0.min.js +6 -0
  74. data/framework_components/room-places-interface/js/lib/nutella_lib.js +4145 -0
  75. data/framework_components/room-places-interface/js/lib/react-with-addons-0.12.2.js +19822 -0
  76. data/framework_components/room-places-interface/js/lib/underscore.js +6 -0
  77. data/framework_components/room-places-interface/js/map.js +1593 -0
  78. data/framework_components/room-places-interface/js/position.js +6 -0
  79. data/framework_components/room-places-interface/js/react/dist/beacon.js +30 -0
  80. data/framework_components/room-places-interface/js/react/dist/discrete.js +282 -0
  81. data/framework_components/room-places-interface/js/react/dist/interactive-label.js +54 -0
  82. data/framework_components/room-places-interface/js/react/dist/resource-add.js +203 -0
  83. data/framework_components/room-places-interface/js/react/dist/resource-table.js +227 -0
  84. data/framework_components/room-places-interface/js/react/dist/resource.js +433 -0
  85. data/framework_components/room-places-interface/js/react/src/beacon.js +30 -0
  86. data/framework_components/room-places-interface/js/react/src/discrete.js +282 -0
  87. data/framework_components/room-places-interface/js/react/src/interactive-label.js +54 -0
  88. data/framework_components/room-places-interface/js/react/src/resource-add.js +203 -0
  89. data/framework_components/room-places-interface/js/react/src/resource-table.js +227 -0
  90. data/framework_components/room-places-interface/js/react/src/resource.js +433 -0
  91. data/framework_components/room-places-interface/js/room.js +65 -0
  92. data/framework_components/room-places-interface/nutella.json +6 -0
  93. data/nutella_framework.gemspec +93 -5
  94. metadata +91 -3
@@ -0,0 +1,1593 @@
1
+ var Map = function(mapId, room) {
2
+ var self = {};
3
+
4
+ // The size measure are in meters
5
+ self.size = {
6
+ margin_left: 1,
7
+ margin_right: 1,
8
+ margin_top: 1,
9
+ margin_bottom: 1
10
+ };
11
+
12
+ self._style = {
13
+ stroke: 0.01,
14
+ arrow_thick: 0.06,
15
+ _arrow_ratio: 2.0,
16
+ font: 0.12,
17
+ resource_name_font: 0.1,
18
+ discrete_symbol_font: 0.1,
19
+ discrete_symbol_font_offset: 0.1,
20
+ quotation_excess: 1.2,
21
+ _quotation_room_offset: 0.4,
22
+ discrete_tracking_dash_length: 0.02,
23
+ discrete_tracking_color: "#777777",
24
+ quotation_color: "#056CF2",
25
+ resource_radius: 0.06,
26
+ resource_radius_hover: 0.2,
27
+ resource_range_stroke: 0.05,
28
+ proximity_range_stroke: 0.01,
29
+ location_range_color: "rgba(216, 242, 242, 0.5)",
30
+ location_range_stroke_color: "#056CF2",
31
+ proximity_range_stroke_color: "#056CF2",
32
+ location_range_stroke_color_overlapped: "#c0392b",
33
+ location_range_color_overlapped: "rgba(231, 76, 60, 0.5)",
34
+ resource_name_offset: 0.07,
35
+ discrete_square_side: 0.07,
36
+ discrete_square_stroke: 0.01
37
+ };
38
+
39
+ self.constant = {
40
+ position: {
41
+ top_right: "position.top_right",
42
+ top_left: "position.top_left",
43
+ bottom_right: "position.bottom_right",
44
+ bottom_left: "position.bottom_left"
45
+ }
46
+ };
47
+
48
+ self.updateStyle = function(k) {
49
+ self.style = {};
50
+ for(var key in self._style) {
51
+ if(typeof self._style[key] == "string") {
52
+ self.style[key] = self._style[key];
53
+ }
54
+ else {
55
+ if(key[0] == "_")
56
+ self.style[key.slice(1)] = self._style[key];
57
+ else
58
+ self.style[key] = self._style[key] * k;
59
+ }
60
+
61
+ }
62
+ };
63
+
64
+ // Room model
65
+ self.roomManager = room;
66
+
67
+ // D3 group containing the room objects
68
+ self.room = null;
69
+
70
+ // Contains all the resources data indexed with the RID
71
+ self.resources = {};
72
+
73
+ // Contains the discrete tracking system or undefined if not enabled
74
+ self.discreteTracking = undefined;
75
+
76
+ // Contains all the graphical resources indexed with the RID
77
+ self.graphicResources = {};
78
+
79
+ // Tells if it is during dragging procedure
80
+ self.dragging = false;
81
+
82
+ // Render the resources and keep track of them
83
+ self.renderResources = function() {
84
+ self.renderResources();
85
+ };
86
+
87
+ // Private variables
88
+ var proximityResourceRangeGroup = undefined;
89
+ var proximityResourceRangeTextGroup = undefined;
90
+ var staticResourceLocationGroup = undefined;
91
+ var staticResourceLocationRangeGroup = undefined;
92
+ var staticResourceLocationRangeBackgroundGroup = undefined;
93
+ var resourceLocationNameGroup = undefined;
94
+ var resourceLocationNumberGroup = undefined;
95
+ var discreteTrackingSystemGroup = undefined;
96
+ var discreteTrackingSystemSquareGroup = undefined;
97
+
98
+ // Render the static resources with D3 and keep track of them
99
+ self.renderResources = function() {
100
+
101
+ // Check for possible overlap in ranges
102
+ self.checkOverlap();
103
+
104
+ var continuousResources = [];
105
+ var discreteResources = [];
106
+ var proximityResources = [];
107
+
108
+ for(var r in self.resources) {
109
+ if(self.resources[r].continuous != undefined) {
110
+ continuousResources.push(self.resources[r]);
111
+ }
112
+ else if(self.resources[r].discrete != undefined) {
113
+ if(self.discreteTracking != undefined) {
114
+ discreteResources.push(self.resources[r]);
115
+ }
116
+ }
117
+ else if(self.resources[r].proximity != undefined &&
118
+ self.resources[r].proximity.rid != undefined &&
119
+ self.resources[r].proximity.distance != undefined) {
120
+ if(self.resources[r].proximity.continuous != undefined) {
121
+ proximityResources.push(self.resources[r]);
122
+ }
123
+ else if(self.resources[r].proximity.discrete != undefined && self.discreteTracking != undefined) {
124
+ proximityResources.push(self.resources[r]);
125
+ }
126
+ }
127
+ }
128
+
129
+ // Drag & drop behavior for resources
130
+ var drag = d3.behavior.drag()
131
+ //.origin(function(d) { return d; })
132
+ .on("dragstart", function(d){
133
+ d3.select(this)
134
+ .classed({"dragged": true});
135
+
136
+ d.dragged = true;
137
+ self.dragging = true;
138
+
139
+ self.renderResources();
140
+ })
141
+ .on("drag", function(d) {
142
+
143
+ var x, y;
144
+
145
+ d3.select(this)
146
+ .attr("cx", x = d3.event.x)
147
+ .attr("cy", y = d3.event.y);
148
+
149
+ // Add quotations
150
+ if(d.quotation != undefined)
151
+ d.quotation.remove();
152
+
153
+ // X on the left
154
+ d.quotation = self.drawQuotation(
155
+ 0,
156
+ y,
157
+ x,
158
+ y,
159
+ Position.bottom,
160
+ 0,
161
+ x.toPrecision(3),
162
+ self.style.quotation_color);
163
+
164
+ // X on the right
165
+ d.quotation = self.drawQuotation(
166
+ x,
167
+ y,
168
+ self.roomManager.x,
169
+ y,
170
+ Position.bottom,
171
+ 0,
172
+ (self.roomManager.x-x).toPrecision(3),
173
+ self.style.quotation_color,
174
+ undefined,
175
+ d.quotation);
176
+
177
+ // Y on the top
178
+ d.quotation = self.drawQuotation(
179
+ x,
180
+ 0,
181
+ x,
182
+ y,
183
+ Position.left,
184
+ 0,
185
+ y.toPrecision(3),
186
+ self.style.quotation_color,
187
+ undefined,
188
+ d.quotation);
189
+
190
+ // Y on the bottom
191
+ d.quotation = self.drawQuotation(
192
+ x,
193
+ y,
194
+ x,
195
+ self.roomManager.y,
196
+ Position.left,
197
+ 0,
198
+ (self.roomManager.y-y).toPrecision(3),
199
+ self.style.quotation_color,
200
+ undefined,
201
+ d.quotation);
202
+
203
+ // Recalculate y
204
+ y = self.roomManager.y - y;
205
+
206
+
207
+ if(d.continuous != undefined) {
208
+ d.continuous = {x: x, y: y};
209
+ }
210
+ else if(d.discrete != undefined) {
211
+ d.discrete = self.continuousToDiscrete({x: x, y: y});
212
+ }
213
+
214
+ })
215
+ .on("dragend", function(d){
216
+ //var x = parseFloat(d3.select(this).attr("cx"));
217
+ //var y = self.roomManager.y - parseFloat(d3.select(this).attr("cy"));
218
+
219
+ d3.select(this)
220
+ .classed({"dragged": false});
221
+
222
+ //d.continuous.y = y;
223
+
224
+ //var continuous = {x: x, y: y};
225
+
226
+ d.dragged = false;
227
+ self.dragging = false;
228
+
229
+ // Remove quotation
230
+ if(d.quotation != undefined) {
231
+ d.quotation.remove();
232
+ }
233
+
234
+ // Rend all resources
235
+ self.renderResources();
236
+
237
+ if(d.continuous != undefined) {
238
+ // Update the resource on the server
239
+ nutella.net.publish("location/resource/update", {rid: d.rid, continuous: d.continuous});
240
+ }
241
+ else if(d.discrete != undefined) {
242
+ // Update the resource on the server
243
+ nutella.net.publish("location/resource/update", {rid: d.rid, discrete: d.discrete});
244
+ }
245
+ });
246
+
247
+ // Drag & drop behavior for proximity range
248
+ var dragRange = d3.behavior.drag()
249
+ .on("dragstart", function(d){
250
+ self.dragging = true;
251
+ })
252
+ .on("drag", function(d) {
253
+
254
+ var x = 0;
255
+ var y = 0;
256
+
257
+ if(d.continuous != undefined) {
258
+ x = d.continuous.x;
259
+ y = d.continuous.y;
260
+ }
261
+ else if(d.discrete != undefined) {
262
+ x = self.discreteToContinuous(d.discrete).x;
263
+ y = self.discreteToContinuous(d.discrete).y;
264
+ }
265
+
266
+ // Calculate the new range
267
+ if(d.proximity_range != undefined)
268
+ d.proximity_range = Math.sqrt(
269
+ Math.pow(d3.event.x - x, 2)+
270
+ Math.pow(d3.event.y - (self.roomManager.y - y), 2)
271
+ );
272
+
273
+ // Update graphically the range
274
+ d3.select(this)
275
+ .attr("r", function(d) {
276
+ if(d.proximity_range != null) {
277
+ if(d.dragged == true)
278
+ return 0;
279
+ else
280
+ return d.proximity_range;
281
+ }
282
+ else {
283
+ return 0;
284
+ }
285
+ });
286
+ })
287
+ .on("dragend", function(d) {
288
+
289
+ self.dragging = false;
290
+
291
+ if(d.proximity_range != undefined && d.continuous != undefined) {
292
+ nutella.net.publish("location/resource/update", {
293
+ rid: d.rid,
294
+ proximity_range: d.proximity_range,
295
+ continuous: d.continuous
296
+ });
297
+ }
298
+ else if(d.proximity_range != undefined && d.discrete != undefined) {
299
+ nutella.net.publish("location/resource/update", {
300
+ rid: d.rid,
301
+ proximity_range: d.proximity_range,
302
+ discrete: d.discrete
303
+ });
304
+ }
305
+ });
306
+
307
+ // Continuous resources
308
+
309
+ function rid(d) {
310
+ return d.rid;
311
+ }
312
+
313
+ // Resource D3 object
314
+ var resourceLocation = staticResourceLocationGroup.selectAll(".resource_location")
315
+ .data(continuousResources.concat(discreteResources), rid);
316
+
317
+ // Resource range D3 object
318
+ var resourceLocationRange = staticResourceLocationRangeGroup.selectAll(".resource_location_range")
319
+ .data(continuousResources.concat(discreteResources), rid);
320
+
321
+ // Resource range background D3 object
322
+ var resourceLocationRangeBackground = staticResourceLocationRangeBackgroundGroup.selectAll(".resource_location_range_background")
323
+ .data(continuousResources.concat(discreteResources), rid);
324
+
325
+ // Resource name (RID)
326
+ resourceLocationNameGroup.selectAll(".resource_location_name").remove();
327
+ var resourceLocationName = resourceLocationNameGroup.selectAll(".resource_location_name")
328
+ .data(continuousResources.concat(discreteResources), rid);
329
+
330
+ resourceLocationRangeBackground
331
+ .enter()
332
+ .append("circle")
333
+ .attr("class", "resource_location_range_background")
334
+ .attr("r", function(d) {
335
+ if(d.proximity_range != null) {
336
+ if(d.dragged == true)
337
+ return 0;
338
+ else
339
+ return d.proximity_range;
340
+ }
341
+ else {
342
+ return 0;
343
+ }
344
+ })
345
+ .attr("fill", self.style.location_range_color);
346
+
347
+ // Update resources that are already there
348
+ resourceLocationRangeBackground
349
+ .attr("cx", function(d) {
350
+ var x = 0;
351
+
352
+ if(d.continuous != undefined) {
353
+ x = d.continuous.x;
354
+ }
355
+ else if(d.discrete != undefined) {
356
+ x = self.discreteToContinuous(d.discrete).x;
357
+ }
358
+
359
+ return x;
360
+ })
361
+ .attr("cy", function(d) {
362
+ var y = 0;
363
+
364
+ if(d.continuous != undefined) {
365
+ y = d.continuous.y;
366
+ }
367
+ else if(d.discrete != undefined) {
368
+ y = self.discreteToContinuous(d.discrete).y;
369
+ }
370
+
371
+ return self.roomManager.y - y;
372
+ })
373
+ .attr("fill", function(d) {
374
+ if(d.overlapped == true) {
375
+ return self.style.location_range_color_overlapped;
376
+ }
377
+ else
378
+ return self.style.location_range_color;
379
+ })
380
+ .transition()
381
+ .attr("r", function(d) {
382
+ if(d.proximity_range != null) {
383
+ if(d.dragged == true)
384
+ return 0;
385
+ else
386
+ return d.proximity_range;
387
+ }
388
+ else {
389
+ return 0;
390
+ }
391
+ });
392
+
393
+ resourceLocationRangeBackground.exit().remove();
394
+
395
+
396
+ resourceLocationRange
397
+ .enter()
398
+ .append("circle")
399
+ .attr("class", "resource_location_range pointer")
400
+ .attr("r", function(d) {
401
+ if(d.proximity_range != null) {
402
+ if(d.dragged == true)
403
+ return 0;
404
+ else
405
+ return d.proximity_range;
406
+ }
407
+ else {
408
+ return 0;
409
+ }
410
+ })
411
+ .attr("fill", "none")
412
+ .attr("stroke", function() {
413
+ return self.style.location_range_stroke_color;
414
+ } )
415
+ .attr("stroke-width", self.style.resource_range_stroke)
416
+ .attr("cx", function(d) {
417
+ var x = 0;
418
+
419
+ if(d.continuous != undefined) {
420
+ x = d.continuous.x;
421
+ }
422
+ else if(d.discrete != undefined) {
423
+ x = self.discreteToContinuous(d.discrete).x;
424
+ }
425
+
426
+ return x;
427
+ })
428
+ .attr("cy", function(d) {
429
+ var y = 0;
430
+
431
+ if(d.continuous != undefined) {
432
+ y = d.continuous.y;
433
+ }
434
+ else if(d.discrete != undefined) {
435
+ y = self.discreteToContinuous(d.discrete).y;
436
+ }
437
+
438
+ return self.roomManager.y - y;
439
+ })
440
+ .call(dragRange);
441
+
442
+ // Update resources that are already there
443
+ resourceLocationRange
444
+ .attr("cx", function(d) {
445
+ var x = 0;
446
+
447
+ if(d.continuous != undefined) {
448
+ x = d.continuous.x;
449
+ }
450
+ else if(d.discrete != undefined) {
451
+ x = self.discreteToContinuous(d.discrete).x;
452
+ }
453
+
454
+ return x;
455
+ })
456
+ .attr("cy", function(d) {
457
+ var y = 0;
458
+
459
+ if(d.continuous != undefined) {
460
+ y = d.continuous.y;
461
+ }
462
+ else if(d.discrete != undefined) {
463
+ y = self.discreteToContinuous(d.discrete).y;
464
+ }
465
+
466
+ return self.roomManager.y - y;
467
+ })
468
+ .attr("stroke", function(d) {
469
+ if(d.overlapped == true) {
470
+ return self.style.location_range_stroke_color_overlapped;
471
+ }
472
+ else {
473
+ return self.style.location_range_stroke_color;
474
+ }
475
+ } )
476
+ .transition()
477
+ .attr("r", function(d) {
478
+ if(d.proximity_range != null) {
479
+ if(d.dragged == true)
480
+ return 0;
481
+ else
482
+ return d.proximity_range;
483
+ }
484
+ else {
485
+ return 0;
486
+ }
487
+ });
488
+
489
+ resourceLocationRange.exit().remove();
490
+
491
+ resourceLocationName
492
+ .enter()
493
+ .append("text")
494
+ .attr("x", function(d) {
495
+ var x = 0;
496
+
497
+ if(d.continuous != undefined) {
498
+ x = d.continuous.x;
499
+ }
500
+ else if(d.discrete != undefined) {
501
+ x = self.discreteToContinuous(d.discrete).x;
502
+ }
503
+
504
+ return x;
505
+ })
506
+ .attr("y", function(d) {
507
+ var y = 0;
508
+
509
+ if(d.continuous != undefined) {
510
+ y = d.continuous.y;
511
+ }
512
+ else if(d.discrete != undefined) {
513
+ y = self.discreteToContinuous(d.discrete).y;
514
+ }
515
+
516
+ return (self.roomManager.y - y)- self.style.resource_name_offset;
517
+ })
518
+ .attr("class", "resource_location_name no_interaction")
519
+ .attr("text-anchor", "middle")
520
+ .attr("fill", function(d) { if(d.dragged == true) return "none"; else return "black";})
521
+ .attr("font-size", self.style.resource_name_font)
522
+ .text(function(d) { return d.rid; });
523
+
524
+ resourceLocationName
525
+ .attr("x", function(d) {
526
+ var x = 0;
527
+
528
+ if(d.continuous != undefined) {
529
+ x = d.continuous.x;
530
+ }
531
+ else if(d.discrete != undefined) {
532
+ x = self.discreteToContinuous(d.discrete).x;
533
+ }
534
+
535
+ return x;
536
+ })
537
+ .attr("y", function(d) {
538
+ var y = 0;
539
+
540
+ if(d.continuous != undefined) {
541
+ y = d.continuous.y;
542
+ }
543
+ else if(d.discrete != undefined) {
544
+ y = self.discreteToContinuous(d.discrete).y;
545
+ }
546
+
547
+ return (self.roomManager.y - y)- self.style.resource_name_offset;
548
+ })
549
+ .attr("fill", function(d) { if(d.dragged == true) return "none"; else return "black";})
550
+ .text(function(d) { return d.rid; });
551
+
552
+ resourceLocationName.exit().remove();
553
+
554
+ //resourceLocationName.order();
555
+
556
+ resourceLocation
557
+ .enter()
558
+ .append("circle")
559
+ .attr("class", "resource_location pointer")
560
+ .attr("r", self.style.resource_radius)
561
+ .attr("fill", "black")
562
+ .attr("cx", function(d) {
563
+ var x = 0;
564
+
565
+ if(d.continuous != undefined) {
566
+ x = d.continuous.x;
567
+ }
568
+ else if(d.discrete != undefined) {
569
+ x = self.discreteToContinuous(d.discrete).x;
570
+ }
571
+
572
+ return x;
573
+ })
574
+ .attr("cy", function(d) {
575
+ var y = 0;
576
+
577
+ if(d.continuous != undefined) {
578
+ y = d.continuous.y;
579
+ }
580
+ else if(d.discrete != undefined) {
581
+ y = self.discreteToContinuous(d.discrete).y;
582
+ }
583
+
584
+ return self.roomManager.y - y;
585
+ })
586
+ .call(drag);
587
+
588
+ // Update resources that are already there
589
+ resourceLocation
590
+ .transition()
591
+ .attr("r", self.style.resource_radius)
592
+ .attr("cx", function(d) {
593
+ var x = 0;
594
+
595
+ if(d.continuous != undefined) {
596
+ x = d.continuous.x;
597
+ }
598
+ else if(d.discrete != undefined) {
599
+ x = self.discreteToContinuous(d.discrete).x;
600
+ }
601
+
602
+ return x;
603
+ })
604
+ .attr("cy", function(d) {
605
+ var y = 0;
606
+
607
+ if(d.continuous != undefined) {
608
+ y = d.continuous.y;
609
+ }
610
+ else if(d.discrete != undefined) {
611
+ y = self.discreteToContinuous(d.discrete).y;
612
+ }
613
+
614
+ return self.roomManager.y - y;
615
+ });
616
+
617
+ resourceLocation.exit().remove();
618
+
619
+ resourceLocation.order();
620
+
621
+ // Proximity resources
622
+
623
+ // Resource
624
+ var proximityResourceRange = proximityResourceRangeGroup.selectAll(".proximity_resource_range")
625
+ .data(proximityResources, rid);
626
+
627
+ proximityResourceRangeTextGroup.selectAll(".proximity_resource_text").remove();
628
+ var proximityResourceText = proximityResourceRangeTextGroup.selectAll(".proximity_resource_text")
629
+ .data(proximityResources, rid);
630
+
631
+ proximityResourceRange
632
+ .enter()
633
+ .append("circle")
634
+ .attr("class", "proximity_resource_range")
635
+ .attr("r", function(d) { return d.proximity.distance; })
636
+ .attr("fill", "none")
637
+ .attr("stroke", function() {
638
+ return self.style.proximity_range_stroke_color;
639
+ } )
640
+ .attr("stroke-width", self.style.proximity_range_stroke)
641
+ .attr("cx", function(d) {
642
+ if(d.proximity.continuous != undefined) {
643
+ return d.proximity.continuous.x;
644
+ }
645
+ else if(d.proximity.discrete != undefined) {
646
+ return self.discreteToContinuous(d.proximity.discrete).x;
647
+ }
648
+ })
649
+ .attr("cy", function(d) {
650
+ if(d.proximity.continuous != undefined) {
651
+ return self.roomManager.y - d.proximity.continuous.y;
652
+ }
653
+ else if(d.proximity.discrete != undefined) {
654
+ return self.roomManager.y - self.discreteToContinuous(d.proximity.discrete).y;
655
+ }
656
+ });
657
+
658
+ // Update resources that are already there
659
+ proximityResourceRange
660
+ .attr("cx", function(d) {
661
+ if(d.proximity.continuous != undefined) {
662
+ return d.proximity.continuous.x;
663
+ }
664
+ else if(d.proximity.discrete != undefined) {
665
+ return self.discreteToContinuous(d.proximity.discrete).x;
666
+ }
667
+ })
668
+ .attr("cy", function(d) {
669
+ if(d.proximity.continuous != undefined) {
670
+ return self.roomManager.y - d.proximity.continuous.y;
671
+ }
672
+ else if(d.proximity.discrete != undefined) {
673
+ return self.roomManager.y - self.discreteToContinuous(d.proximity.discrete).y;
674
+ }
675
+ })
676
+ .transition()
677
+ .attr("r", function(d) { return d.proximity.distance; });
678
+
679
+ proximityResourceRange.exit().remove();
680
+
681
+ proximityResourceText
682
+ .enter()
683
+ .append("text")
684
+ .attr("class", "proximity_resource_text")
685
+ .attr("x", function(d) {
686
+ if(d.proximity.continuous != undefined) {
687
+ return d.proximity.continuous.x;
688
+ }
689
+ else if(d.proximity.discrete != undefined) {
690
+ return self.discreteToContinuous(d.proximity.discrete).x;
691
+ }
692
+ })
693
+ .attr("y", function(d) {
694
+ if(d.proximity.continuous != undefined) {
695
+ return self.roomManager.y - d.proximity.continuous.y;
696
+ }
697
+ else if(d.proximity.discrete != undefined) {
698
+ return self.roomManager.y - self.discreteToContinuous(d.proximity.discrete).y;
699
+ }
700
+ })
701
+ .attr("text-anchor", "middle")
702
+ .attr("font-size", self.style.resource_name_font)
703
+ .attr("fill", "black")
704
+ .text(function(d) { return d.rid; });
705
+
706
+ // Update resources that are already there
707
+ proximityResourceText
708
+ //.transition()
709
+ .attr("x", function(d) {
710
+ if(d.proximity.continuous != undefined) {
711
+ return d.proximity.continuous.x;
712
+ }
713
+ else if(d.proximity.discrete != undefined) {
714
+ return self.discreteToContinuous(d.proximity.discrete).x;
715
+ }
716
+ })
717
+ .attr("y", function(d) {
718
+ if(d.proximity.continuous != undefined) {
719
+ return self.roomManager.y - d.proximity.continuous.y - d.proximity.distance;
720
+ }
721
+ else if(d.proximity.discrete != undefined) {
722
+ return self.roomManager.y - self.discreteToContinuous(d.proximity.discrete).y - d.proximity.distance;
723
+ }
724
+ })
725
+ .text(function(d) { return d.rid; });
726
+
727
+ proximityResourceText.exit().remove();
728
+
729
+ // Number of beacons tracked for every base station
730
+ resourceLocationNumberGroup.selectAll(".resource_location_number").remove();
731
+ var resourceLocationNumber = resourceLocationNumberGroup.selectAll(".resource_location_number")
732
+ .data(continuousResources.concat(discreteResources), rid);
733
+
734
+ resourceLocationNumber
735
+ .enter()
736
+ .append("text")
737
+ .attr("x", function(d) {
738
+ if(d.continuous != undefined) {
739
+ return d.continuous.x;
740
+ }
741
+ else if(d.discrete != undefined) {
742
+ return self.discreteToContinuous(d.discrete).x;
743
+ }
744
+ })
745
+ .attr("y", function(d) {
746
+ if(d.continuous != undefined) {
747
+ return self.roomManager.y - d.continuous.y + self.style.resource_name_font/3;
748
+ }
749
+ else if(d.discrete != undefined) {
750
+ return self.roomManager.y - self.discreteToContinuous(d.discrete).y + self.style.resource_name_font/3;
751
+ }
752
+ })
753
+ .attr("class", "resource_location_number no_interaction")
754
+ .attr("text-anchor", "middle")
755
+ .attr("fill", function(d) {
756
+ if(d.dragged == true ||
757
+ d.number_resources == undefined ||
758
+ d.number_resources == 0)
759
+ return "none";
760
+ else
761
+ return "white";})
762
+ .attr("font-size", self.style.resource_name_font);
763
+
764
+ // Update resources that are already there
765
+ resourceLocationNumber
766
+ .attr("x", function(d) {
767
+ if(d.continuous != undefined) {
768
+ return d.continuous.x;
769
+ }
770
+ else if(d.discrete != undefined) {
771
+ return self.discreteToContinuous(d.discrete).x;
772
+ }
773
+ })
774
+ .attr("y", function(d) {
775
+ if(d.continuous != undefined) {
776
+ return self.roomManager.y - d.continuous.y + self.style.resource_name_font/3;
777
+ }
778
+ else if(d.discrete != undefined) {
779
+ return self.roomManager.y - self.discreteToContinuous(d.discrete).y + self.style.resource_name_font/3;
780
+ }
781
+ })
782
+ .text(function(d) {return d.number_resources; })
783
+ .attr("fill", function(d) {
784
+ if(d.dragged == true ||
785
+ d.number_resources == undefined ||
786
+ d.number_resources == 0)
787
+ return "none";
788
+ else
789
+ return "white";})
790
+ //.attr("fill", function(d) { return d.number_resources > 0 ? "black" : "none" });
791
+
792
+ resourceLocationNumber.exit().remove();
793
+
794
+ };
795
+
796
+ self.renderDiscreteTrackingSystem = function() {
797
+
798
+ if (self.discreteTracking == undefined) {
799
+ discreteTrackingSystemGroup.selectAll(".discreteTrackingSystemGroup").remove();
800
+ return;
801
+ }
802
+
803
+ // Drag & drop behavior for discrete tracking system squares
804
+ var squareDrag = d3.behavior.drag()
805
+ .on("dragstart", function(d){
806
+ d3.select(this)
807
+ .classed({"dragged": true});
808
+
809
+ d.dragged = true;
810
+
811
+ self.renderResources();
812
+ })
813
+ .on("drag", function(d) {
814
+
815
+
816
+ // Add quotations
817
+ if(d.quotation != undefined)
818
+ d.quotation.remove();
819
+
820
+ // X on the left
821
+ d.quotation = self.drawQuotation(
822
+ 0,
823
+ d3.event.y,
824
+ d3.event.x,
825
+ d3.event.y,
826
+ Position.bottom,
827
+ 0,
828
+ d3.event.x.toPrecision(3),
829
+ self.style.quotation_color);
830
+
831
+ // X on the right
832
+ d.quotation = self.drawQuotation(
833
+ d3.event.x,
834
+ d3.event.y,
835
+ self.roomManager.x,
836
+ d3.event.y,
837
+ Position.bottom,
838
+ 0,
839
+ (self.roomManager.x-d3.event.x).toPrecision(3),
840
+ self.style.quotation_color,
841
+ undefined,
842
+ d.quotation);
843
+
844
+ // Y on the top
845
+ d.quotation = self.drawQuotation(
846
+ d3.event.x,
847
+ 0,
848
+ d3.event.x,
849
+ d3.event.y,
850
+ Position.left,
851
+ 0,
852
+ d3.event.y.toPrecision(3),
853
+ self.style.quotation_color,
854
+ undefined,
855
+ d.quotation);
856
+
857
+ // Y on the bottom
858
+ d.quotation = self.drawQuotation(
859
+ d3.event.x,
860
+ d3.event.y,
861
+ d3.event.x,
862
+ self.roomManager.y,
863
+ Position.left,
864
+ 0,
865
+ (self.roomManager.y - d3.event.y).toPrecision(3),
866
+ self.style.quotation_color,
867
+ undefined,
868
+ d.quotation);
869
+
870
+ switch(d.position) {
871
+ case self.constant.position.bottom_left:
872
+ self.discreteTracking.width += self.discreteTracking.x - d3.event.x;
873
+ self.discreteTracking.height += d3.event.y - (self.roomManager.y - self.discreteTracking.y);
874
+ self.discreteTracking.x = d3.event.x;
875
+ self.discreteTracking.y = self.roomManager.y - d3.event.y;
876
+ break;
877
+ case self.constant.position.bottom_right:
878
+ self.discreteTracking.width -= self.discreteTracking.x + self.discreteTracking.width - d3.event.x;
879
+ self.discreteTracking.height += d3.event.y - (self.roomManager.y - self.discreteTracking.y);
880
+ self.discreteTracking.y = self.roomManager.y - d3.event.y;
881
+ break;
882
+ case self.constant.position.top_left:
883
+ self.discreteTracking.width += self.discreteTracking.x - d3.event.x;
884
+ self.discreteTracking.height -= d3.event.y - (self.roomManager.y - (self.discreteTracking.y + self.discreteTracking.height));
885
+ self.discreteTracking.x = d3.event.x;
886
+ break;
887
+ case self.constant.position.top_right:
888
+ self.discreteTracking.width -= self.discreteTracking.x + self.discreteTracking.width - d3.event.x;
889
+ self.discreteTracking.height -= d3.event.y - (self.roomManager.y - (self.discreteTracking.y + self.discreteTracking.height));
890
+ break;
891
+ }
892
+
893
+ if(self.discreteTracking.width < 0){
894
+ self.discreteTracking.width = 0;
895
+ }
896
+
897
+ if(self.discreteTracking.height < 0){
898
+ self.discreteTracking.height = 0;
899
+ }
900
+
901
+ self.renderDiscreteTrackingSystem();
902
+
903
+ })
904
+ .on("dragend", function(d){
905
+ var x = parseFloat(d3.select(this).attr("x"));
906
+ var y = self.roomManager.y - parseFloat(d3.select(this).attr("y"));
907
+
908
+ d3.select(this)
909
+ .classed({"dragged": false});
910
+
911
+ self.dragging = false;
912
+
913
+ nutella.net.publish("location/tracking/discrete/update", {
914
+ tracking: self.discreteTracking
915
+ });
916
+
917
+ // Remove quotation
918
+ if(d.quotation != undefined) {
919
+ d.quotation.remove();
920
+ }
921
+
922
+ });
923
+
924
+ // Draw the lines of the discrete tracking system
925
+ var lines = [];
926
+ var squares = [];
927
+
928
+ // Calculate the coordinates for the horizontal lines
929
+ for (i = 0; i <= self.discreteTracking.n_y; i++) {
930
+ lines.push({
931
+ source: {
932
+ x: self.discreteTracking.x,
933
+ y: self.discreteTracking.y +
934
+ self.discreteTracking.height / self.discreteTracking.n_y * i
935
+ },
936
+ destination: {
937
+ x: self.discreteTracking.x + self.discreteTracking.width,
938
+ y: self.discreteTracking.y +
939
+ self.discreteTracking.height / self.discreteTracking.n_y * i
940
+ }
941
+ });
942
+ }
943
+
944
+ // Calculate the coordinates for the vertical lines
945
+ for (i = 0; i <= self.discreteTracking.n_x; i++) {
946
+ lines.push({
947
+ source: {
948
+ x: self.discreteTracking.x +
949
+ self.discreteTracking.width / self.discreteTracking.n_x * i,
950
+ y: self.discreteTracking.y
951
+ },
952
+ destination: {
953
+ x: self.discreteTracking.x +
954
+ self.discreteTracking.width / self.discreteTracking.n_x * i,
955
+ y: self.discreteTracking.y +
956
+ self.discreteTracking.height
957
+ }
958
+ });
959
+ }
960
+
961
+ // Calculate the coordinates for the corners
962
+ squares.push({
963
+ x: self.discreteTracking.x,
964
+ y: self.discreteTracking.y,
965
+ position: self.constant.position.bottom_left
966
+ });
967
+ squares.push({
968
+ x: self.discreteTracking.x + self.discreteTracking.width,
969
+ y: self.discreteTracking.y,
970
+ position: self.constant.position.bottom_right
971
+ });
972
+ squares.push({
973
+ x: self.discreteTracking.x,
974
+ y: self.discreteTracking.y + self.discreteTracking.height,
975
+ position: self.constant.position.top_left
976
+ });
977
+ squares.push({
978
+ x: self.discreteTracking.x + self.discreteTracking.width,
979
+ y: self.discreteTracking.y + self.discreteTracking.height,
980
+ position: self.constant.position.top_right
981
+ });
982
+
983
+ // Lines
984
+ var linesSelection = discreteTrackingSystemGroup.selectAll("line")
985
+ .data(lines);
986
+
987
+ linesSelection.enter()
988
+ .append("line")
989
+ .attr("x1", function (d) {
990
+ return d.source.x
991
+ })
992
+ .attr("y1", function (d) {
993
+ return self.roomManager.y - d.source.y
994
+ })
995
+ .attr("x2", function (d) {
996
+ return d.destination.x
997
+ })
998
+ .attr("y2", function (d) {
999
+ return self.roomManager.y - d.destination.y
1000
+ })
1001
+ .attr("class", "no_interaction")
1002
+ .style("stroke", self.style.discrete_tracking_color)
1003
+ .style("stroke-dasharray", ("" + self.style.discrete_tracking_dash_length + "," + self.style.discrete_tracking_dash_length))
1004
+ .style("stroke-width", self.style.stroke);
1005
+
1006
+ linesSelection
1007
+ .attr("x1", function (d) {
1008
+ return d.source.x
1009
+ })
1010
+ .attr("y1", function (d) {
1011
+ return self.roomManager.y - d.source.y
1012
+ })
1013
+ .attr("x2", function (d) {
1014
+ return d.destination.x
1015
+ })
1016
+ .attr("y2", function (d) {
1017
+ return self.roomManager.y - d.destination.y
1018
+ });
1019
+
1020
+ linesSelection
1021
+ .exit()
1022
+ .remove();
1023
+
1024
+ // Squares
1025
+ var squareSelection = discreteTrackingSystemSquareGroup.selectAll(".square")
1026
+ .data(squares);
1027
+
1028
+ squareSelection.enter()
1029
+ .append("rect")
1030
+ .classed({"square": true, "pointer": true})
1031
+ .attr("x", function (square) {
1032
+ return square.x - self.style.discrete_square_side / 2;
1033
+ })
1034
+ .attr("y", function (square) {
1035
+ return self.roomManager.y - (square.y + self.style.discrete_square_side / 2);
1036
+ })
1037
+ .attr("width", function (square) {
1038
+ return self.style.discrete_square_side;
1039
+ })
1040
+ .attr("height", function (square) {
1041
+ return self.style.discrete_square_side;
1042
+ })
1043
+ .attr("stroke-width", this.style.discrete_square_stroke)
1044
+ .attr("stroke", "#000")
1045
+ .attr("fill", "#fff")
1046
+ .call(squareDrag);
1047
+
1048
+ squareSelection
1049
+ .attr("x", function (square) {
1050
+ return square.x - self.style.discrete_square_side / 2;
1051
+ })
1052
+ .attr("y", function (square) {
1053
+ return self.roomManager.y - (square.y + self.style.discrete_square_side / 2);
1054
+ })
1055
+ .attr("width", function (square) {
1056
+ return self.style.discrete_square_side;
1057
+ })
1058
+ .attr("height", function (square) {
1059
+ return self.style.discrete_square_side;
1060
+ });
1061
+
1062
+ squareSelection.exit()
1063
+ .remove();
1064
+
1065
+ var symbols = [];
1066
+
1067
+ // Horizontal numbers or letters
1068
+ for(var i = 0; i < self.discreteTracking.n_x; i++) {
1069
+ symbol = {};
1070
+ symbol.x = self.discreteTracking.x +
1071
+ self.discreteTracking.width / self.discreteTracking.n_x * (i + 1/2);
1072
+ symbol.y = self.discreteTracking.y -
1073
+ self.style.discrete_symbol_font_offset;
1074
+
1075
+ switch(self.discreteTracking.t_x) {
1076
+ case "NUMBER":
1077
+ symbol.symbol = i;
1078
+ break;
1079
+ case "LETTER":
1080
+ symbol.symbol = String.fromCharCode(97 + i);
1081
+ break;
1082
+ }
1083
+
1084
+ symbols.push(symbol);
1085
+ }
1086
+
1087
+ // Vertical numbers or letters
1088
+ for(var i = 0; i < self.discreteTracking.n_y; i++) {
1089
+ symbol = {};
1090
+ symbol.x = self.discreteTracking.x -
1091
+ self.style.discrete_symbol_font_offset;
1092
+ symbol.y = self.discreteTracking.y +
1093
+ self.discreteTracking.height / self.discreteTracking.n_y * (i + 1/2);
1094
+ ;
1095
+
1096
+ switch(self.discreteTracking.t_y) {
1097
+ case "NUMBER":
1098
+ symbol.symbol = i;
1099
+ break;
1100
+ case "LETTER":
1101
+ symbol.symbol = String.fromCharCode(97 + i);
1102
+ break;
1103
+ }
1104
+
1105
+ symbols.push(symbol);
1106
+ }
1107
+
1108
+ // Symbols
1109
+ var symbolsSelection = discreteTrackingSystemGroup.selectAll(".symbol")
1110
+ .data(symbols);
1111
+
1112
+ symbolsSelection.enter()
1113
+ .append("text")
1114
+ .classed({"symbol": true, "no_interaction": true})
1115
+ .attr("x", function(symbol) {return symbol.x})
1116
+ .attr("y", function(symbol) {return self.roomManager.y - symbol.y})
1117
+ .attr("font-size", this.style.discrete_symbol_font)
1118
+ .text(function(symbol) { return symbol.symbol;});
1119
+
1120
+ symbolsSelection
1121
+ .transition()
1122
+ .attr("x", function(symbol) {return symbol.x})
1123
+ .attr("y", function(symbol) {return self.roomManager.y - symbol.y})
1124
+ .text(function(symbol) { return symbol.symbol;});
1125
+
1126
+ symbolsSelection.exit()
1127
+ .remove();
1128
+ };
1129
+
1130
+ // Render the map from the beginning
1131
+ self.render = function() {
1132
+
1133
+ var height = self.roomManager.y + self.size.margin_top + self.size.margin_bottom;
1134
+ var width = self.roomManager.x + self.size.margin_left + self.size.margin_right;
1135
+
1136
+ self.svg.attr("viewBox", "0 0 " + width + " " + height);
1137
+
1138
+ if(self.room != null) {
1139
+ self.room.remove();
1140
+ }
1141
+
1142
+ // Group that contains all the elements of the room
1143
+ self.room = self.svg.append("g")
1144
+ .attr("transform", "translate("+ self.size.margin_left +","+ self.size.margin_top +")");
1145
+
1146
+ // Clip path used in order to crop elements outside the room
1147
+ var defs = self.room.append("defs");
1148
+
1149
+ defs.append("rect")
1150
+ .attr("id", "rect")
1151
+ .attr("x", 0)
1152
+ .attr("y", 0)
1153
+ .attr("width", self.roomManager.x)
1154
+ .attr("height", self.roomManager.y)
1155
+ .attr("fill", "black")
1156
+ .attr("stroke", "blue");
1157
+
1158
+ defs.append("clipPath")
1159
+ .attr("id", "clip")
1160
+ .append("use")
1161
+ .attr({"xlink:href": "#rect"});
1162
+
1163
+ self.room.clip = self.room.append("g")
1164
+ .attr("clip-path", "url(#clip)");
1165
+
1166
+ self.room.unclip = self.room.append("g");
1167
+
1168
+ // Rectangle that represent the room
1169
+ self.rect = self.room.unclip.append("rect")
1170
+ .attr("x", 0)
1171
+ .attr("y", 0)
1172
+ .attr("width", self.roomManager.x)
1173
+ .attr("height", self.roomManager.y)
1174
+ .style("fill", "none")
1175
+ .attr("stroke", "black")
1176
+ .attr("stroke-width", self.style.stroke);
1177
+
1178
+ // Vertical room quotation
1179
+ self.drawQuotation(0, 0, 0, self.roomManager.y, Position.left, 0.5, self.roomManager.y, self.style.quotation_color, function() {
1180
+ var newHeight = prompt("Insert new height", self.roomManager.y);
1181
+ var y = parseFloat(newHeight);
1182
+
1183
+ if(newHeight != undefined) {
1184
+ self.roomManager.y = y;
1185
+ self.render();
1186
+ }
1187
+ });
1188
+
1189
+ // Horizontal room quotation
1190
+ self.drawQuotation(0, self.roomManager.y, self.roomManager.x, self.roomManager.y, Position.bottom, 0.5, self.roomManager.x, self.style.quotation_color, function() {
1191
+ var newWidth = prompt("Insert new width", self.roomManager.x);
1192
+ var x = parseFloat(newWidth);
1193
+
1194
+ if(newWidth != undefined) {
1195
+ self.roomManager.x = x;
1196
+ self.render();
1197
+ }
1198
+ });
1199
+
1200
+ // Create all the groups
1201
+ staticResourceLocationRangeBackgroundGroup = self.room.clip.append("g").attr("class", "staticResourceLocationRangeBackgroundGroup");
1202
+ resourceLocationNameGroup = self.room.unclip.append("g").attr("class", "resourceLocationNameGroup");
1203
+ proximityResourceRangeGroup = self.room.clip.append("g").attr("class", "proximityResourceRangeGroup");
1204
+ proximityResourceRangeTextGroup = self.room.clip.append("g").attr("class", "proximityResourceRangeTextGroup");
1205
+ discreteTrackingSystemGroup = self.room.unclip.append("g").attr("class", "discreteTrackingSystemGroup");
1206
+ staticResourceLocationRangeGroup = self.room.clip.append("g").attr("class", "staticResourceLocationRangeGroup");
1207
+ staticResourceLocationGroup = self.room.unclip.append("g").attr("class", "staticResourceLocationGroup");
1208
+ discreteTrackingSystemSquareGroup = self.room.unclip.append("g").attr("class", "discreteTrackingSystemSquareGroup");
1209
+ resourceLocationNumberGroup = self.room.unclip.append("g").attr("class", "resourceLocationNumberGroup");
1210
+
1211
+ self.renderDiscreteTrackingSystem();
1212
+ self.renderResources();
1213
+ };
1214
+
1215
+ self.drawArrow = function(x, y, color, position, element) {
1216
+
1217
+ if(element == null)
1218
+ element = self.svg;
1219
+
1220
+ var lineData = [
1221
+ { "x": 0.0, "y": 0.0},
1222
+ { "x": 1*self.style.arrow_thick/self.style.arrow_ratio, "y": 1*self.style.arrow_thick*self.style.arrow_ratio},
1223
+ { "x": -1*self.style.arrow_thick/self.style.arrow_ratio, "y": 1*self.style.arrow_thick*self.style.arrow_ratio}
1224
+ ];
1225
+
1226
+ var lineFunction = d3.svg.line()
1227
+ .x(function(d) { return d.x; })
1228
+ .y(function(d) { return d.y; })
1229
+ .interpolate("linear");
1230
+
1231
+ // calculate rotation
1232
+ var angle;
1233
+ switch(position) {
1234
+ case Position.top: angle = 0; break;
1235
+ case Position.bottom: angle = 180; break;
1236
+ case Position.right: angle = 90; break;
1237
+ case Position.left: angle = 270; break;
1238
+ default: angle = 0;
1239
+ }
1240
+
1241
+ var arrow = element.append("g")
1242
+ .attr("transform", "translate(" + x + "," + y + ")")
1243
+ .append("path")
1244
+ .attr("d", lineFunction(lineData))
1245
+ .attr("fill", color)
1246
+ .attr("transform", "rotate("+angle+")");
1247
+
1248
+ return arrow;
1249
+ };
1250
+
1251
+ self.drawQuotation = function(x1, y1, x2, y2, position, offset, quotationText, color, onClick, quotationObject) {
1252
+
1253
+ var quotation;
1254
+ if(quotationObject == undefined) {
1255
+ quotation = self.room.unclip.append("g");
1256
+ }
1257
+ else {
1258
+ quotation = quotationObject;
1259
+ }
1260
+
1261
+ // Calculate the offsets in two dimensions
1262
+ var ox, oy;
1263
+
1264
+ switch(position) {
1265
+ case Position.bottom:
1266
+ ox = 0;
1267
+ oy = offset;
1268
+
1269
+ break;
1270
+ case Position.top:
1271
+ ox = 0;
1272
+ oy = -offset;
1273
+
1274
+ break;
1275
+ case Position.left:
1276
+ ox = -offset;
1277
+ oy = 0;
1278
+
1279
+ break;
1280
+ case Position.right:
1281
+ ox = offset;
1282
+ oy = 0;
1283
+ break;
1284
+ }
1285
+
1286
+ var text = quotation.append("text")
1287
+ .text(quotationText)
1288
+ .attr("x", (x1+x2)/2 + ox)
1289
+ .attr("y", (y1+y2)/2 + oy + self.style.font / 3)
1290
+ .attr("font-size", self.style.font)
1291
+ .attr("text-anchor", "middle")
1292
+ .attr("fill", color);
1293
+
1294
+
1295
+ if(onClick != null) {
1296
+ text.on("click", onClick);
1297
+ text.classed("pointer",true);
1298
+ }
1299
+
1300
+ // Get the text length
1301
+ var textWidth = quotation.select("text").node().getBBox().width;
1302
+ var textHeight = quotation.select("text").node().getBBox().height;
1303
+
1304
+ var sx, sy;
1305
+
1306
+ switch(position) {
1307
+ case Position.bottom:
1308
+ case Position.top:
1309
+ sx = textWidth / 2;
1310
+ sy = 0;
1311
+
1312
+ quotation.append("line")
1313
+ .attr("x1", x1 + ox)
1314
+ .attr("x2", (x1+x2)/2 + ox - sx)
1315
+ .attr("y1", y1 + oy)
1316
+ .attr("y2", y2 + oy)
1317
+ .style("stroke", color)
1318
+ .style("stroke-width", self.style.stroke);
1319
+
1320
+ quotation.append("line")
1321
+ .attr("x1", (x1+x2)/2 + ox + sx)
1322
+ .attr("x2", x2 + ox)
1323
+ .attr("y1", y1 + oy)
1324
+ .attr("y2", y2 + oy)
1325
+ .style("stroke", color)
1326
+ .style("stroke-width", self.style.stroke);
1327
+
1328
+ self.drawArrow(x1+ox, y1+oy, color, Position.left, quotation);
1329
+ self.drawArrow(x2+ox, y2+oy, color, Position.right, quotation);
1330
+
1331
+ break;
1332
+
1333
+ case Position.left:
1334
+ case Position.right:
1335
+ sx = 0;
1336
+ sy = textHeight / 2;
1337
+
1338
+ quotation.append("line")
1339
+ .attr("x1", x1 + ox)
1340
+ .attr("x2", x2 + ox)
1341
+ .attr("y1", y1 + oy)
1342
+ .attr("y2", (y1+y2)/2 + oy - sy/2)
1343
+ .style("stroke", color)
1344
+ .style("stroke-width", self.style.stroke);
1345
+
1346
+ quotation.append("line")
1347
+ .attr("x1", x1 + ox)
1348
+ .attr("x2", x2 + ox)
1349
+ .attr("y1", (y1+y2)/2 + oy + sy/2)
1350
+ .attr("y2", y2 + oy)
1351
+ .style("stroke", color)
1352
+ .style("stroke-width", self.style.stroke);
1353
+
1354
+ self.drawArrow(x1+ox, y1+oy, color, Position.top, quotation);
1355
+ self.drawArrow(x2+ox, y2+oy, color, Position.bottom, quotation);
1356
+
1357
+ break;
1358
+ }
1359
+
1360
+
1361
+ quotation.append("line")
1362
+ .attr("x1", x1)
1363
+ .attr("x2", x1+ox*self.style.quotation_excess)
1364
+ .attr("y1", y1)
1365
+ .attr("y2", y1+oy*self.style.quotation_excess)
1366
+ .style("stroke", color)
1367
+ .style("stroke-width", self.style.stroke);
1368
+
1369
+ quotation.append("line")
1370
+ .attr("x1", x2)
1371
+ .attr("x2", x2+ox*self.style.quotation_excess)
1372
+ .attr("y1", y2)
1373
+ .attr("y2", y2+oy*self.style.quotation_excess)
1374
+ .style("stroke", color)
1375
+ .style("stroke-width", self.style.stroke);
1376
+
1377
+ return quotation;
1378
+ };
1379
+
1380
+ // Check if two static resources are overlapped and ser overlapped=true in case
1381
+ self.checkOverlap = function() {
1382
+ for(r1 in self.resources) {
1383
+ self.resources[r1].overlapped = false;
1384
+ for(r2 in self.resources) {
1385
+ if( r1 != r2 ) {
1386
+ var resource1 = self.resources[r1];
1387
+ var resource2 = self.resources[r2];
1388
+
1389
+ var continuous1, continuous2;
1390
+
1391
+ if(resource1.continuous != undefined) {
1392
+ continuous1 = resource1.continuous;
1393
+ }
1394
+ else if(resource1.discrete != undefined) {
1395
+ continuous1 = self.discreteToContinuous(resource1.discrete);
1396
+ }
1397
+
1398
+ if(resource2.continuous != undefined) {
1399
+ continuous2 = resource2.continuous;
1400
+ }
1401
+ else if(resource2.discrete != undefined) {
1402
+ continuous2 = self.discreteToContinuous(resource2.discrete);
1403
+ }
1404
+
1405
+ if(continuous1 != undefined &&
1406
+ continuous2 != undefined &&
1407
+ resource1.proximity_range != null &&
1408
+ resource2.proximity_range != null) {
1409
+
1410
+ // Check if the distance is less than the sum of proximity ranges
1411
+ var distance = Math.sqrt(
1412
+ Math.pow(continuous1.x - continuous2.x,2)
1413
+ + Math.pow(continuous1.y - continuous2.y,2));
1414
+
1415
+ var sumRange = parseFloat(resource1.proximity_range) + parseFloat(resource2.proximity_range);
1416
+
1417
+ if(distance < sumRange) {
1418
+ resource1.overlapped = true;
1419
+ }
1420
+ }
1421
+ }
1422
+ }
1423
+ }
1424
+ };
1425
+
1426
+ self.discreteToContinuous = function(discrete) {
1427
+
1428
+ if(self.discreteTracking == undefined) {
1429
+ return undefined;
1430
+ }
1431
+
1432
+ var x = discrete.x;
1433
+ var y = discrete.y;
1434
+
1435
+ var continuous = {x: undefined, y: undefined};
1436
+
1437
+ if(typeof discrete.x == "string") {
1438
+ x = x.charCodeAt(0) - "a".charCodeAt(0);
1439
+ }
1440
+ if(typeof discrete.y == "string") {
1441
+ y = y.charCodeAt(0) - "a".charCodeAt(0);
1442
+ }
1443
+
1444
+ continuous.x = self.discreteTracking.x +
1445
+ (self.discreteTracking.width / self.discreteTracking.n_x) * x +
1446
+ (self.discreteTracking.width / self.discreteTracking.n_x) / 2;
1447
+
1448
+ continuous.y = self.discreteTracking.y +
1449
+ (self.discreteTracking.height / self.discreteTracking.n_y) * y +
1450
+ (self.discreteTracking.height / self.discreteTracking.n_y) / 2;
1451
+
1452
+ return continuous;
1453
+
1454
+ };
1455
+
1456
+ self.continuousToDiscrete = function(continuous) {
1457
+
1458
+ if(self.discreteTracking == undefined) {
1459
+ return undefined;
1460
+ }
1461
+
1462
+ var x = continuous.x;
1463
+ var y = continuous.y;
1464
+
1465
+ var discrete = {x: undefined, y: undefined};
1466
+
1467
+ discrete.x = Math.floor(
1468
+ (continuous.x - self.discreteTracking.x) /
1469
+ (self.discreteTracking.width / self.discreteTracking.n_x)
1470
+ );
1471
+
1472
+ discrete.y = Math.floor(
1473
+ (continuous.y - self.discreteTracking.y) /
1474
+ (self.discreteTracking.height / self.discreteTracking.n_y)
1475
+ );
1476
+
1477
+ // Translate in letters if necessary
1478
+ if(self.discreteTracking.t_x == "LETTER") {
1479
+ discrete.x = String.fromCharCode("a".charCodeAt(0) + discrete.x);
1480
+ }
1481
+ if(self.discreteTracking.t_y == "LETTER") {
1482
+ discrete.y = String.fromCharCode("a".charCodeAt(0) + discrete.y);
1483
+ }
1484
+
1485
+
1486
+ return discrete;
1487
+ };
1488
+
1489
+
1490
+ self.init = function() {
1491
+
1492
+ self.svg = d3.select(mapId);
1493
+
1494
+ self.updateStyle(1);
1495
+
1496
+ self.render();
1497
+
1498
+ // Download all resources
1499
+ nutella.net.request("location/resources", {}, function(reply) {
1500
+ for(var r in reply.resources) {
1501
+ var resource = reply.resources[r];
1502
+ if(resource["continuous"] != null ||
1503
+ resource["discrete"] != null ||
1504
+ resource["proximity"] != null) {
1505
+ self.resources[resource.rid] = resource;
1506
+ }
1507
+ }
1508
+
1509
+ //self.renderResources();
1510
+ });
1511
+
1512
+ var updateResource = function(message) {
1513
+ var resources = message.resources;
1514
+ var changed = false;
1515
+
1516
+ for(var r in resources) {
1517
+ var resource = resources[r];
1518
+ if(resource["continuous"] != null ||
1519
+ resource["discrete"] != null ||
1520
+ resource["proximity"] != null) {
1521
+ self.resources[resource.rid] = resource;
1522
+ changed = true;
1523
+ }
1524
+ else {
1525
+ delete self.resources[resource.rid];
1526
+ changed = true;
1527
+ }
1528
+ }
1529
+
1530
+ if(changed) {
1531
+ //self.renderResources();
1532
+ }
1533
+ };
1534
+
1535
+ // Update resources
1536
+ nutella.net.subscribe("location/resources/updated", updateResource);
1537
+
1538
+ // Add resources
1539
+ nutella.net.subscribe("location/resources/added", updateResource);
1540
+
1541
+ // Delete resources
1542
+ nutella.net.subscribe("location/resources/removed", function(message) {
1543
+ var resources = message.resources;
1544
+
1545
+ for(var r in resources) {
1546
+ delete self.resources[resources[r].rid];
1547
+ }
1548
+
1549
+ //self.renderResources();
1550
+ });
1551
+
1552
+ // Update disctete tracking system
1553
+ nutella.net.subscribe("location/tracking/discrete/updated", function(message) {
1554
+ var tracking = message["tracking"];
1555
+ if(_.isEmpty(tracking)) {
1556
+ tracking = undefined;
1557
+ }
1558
+ self.discreteTracking = tracking;
1559
+ self.render();
1560
+ });
1561
+
1562
+
1563
+ // Download discrete tracking system if present
1564
+ nutella.net.request("location/tracking/discrete", {}, function(reply) {
1565
+ var tracking = reply["tracking"];
1566
+ if(_.isEmpty(tracking)){
1567
+ tracking = undefined;
1568
+ }
1569
+ self.discreteTracking = tracking;
1570
+ self.render();
1571
+ });
1572
+
1573
+ // Update the whole map
1574
+ room.observers.push(function() {
1575
+
1576
+ // Update the look and feel
1577
+ var d = Math.max(room.x, room.y);
1578
+ self.updateStyle(d/7.0);
1579
+
1580
+ self.render();
1581
+ });
1582
+
1583
+ // Update resources position once a second
1584
+ setInterval( function() {
1585
+ if(self.dragging == false) {
1586
+ self.renderResources();
1587
+ }
1588
+ }, 200);
1589
+
1590
+ }();
1591
+
1592
+ return self;
1593
+ }