nutella_framework 0.4.27 → 0.4.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }