add tabs for maps
[myslice.git] / plugins / senslabmap / static / js / map.js
index e80ee9e..6918e7c 100644 (file)
@@ -1,24 +1,38 @@
 var Senslab = {
   normalize: function(node) {
     var info;
-
+    
     if (node.component_name) { // wsn430-11.devlille.iot-lab.info
       info = node.component_name.split(".");
-    } else if (node.hrn) { // iotlab.a8-11\.devgrenoble\.iot-lab\.info
+    } /*else if (node.hrn) { // iotlab.a8-11\.devgrenoble\.iot-lab\.info
       var info = node.hrn.split("\\.");
       info[0] = info[0].split(".")[1];
-    }
+    }*/
 
     if (info && info[2] == "iot-lab" && info[3] == "info") {
       node.arch = info[0].split("-")[0];
-      node.id = info[0].split("-")[1];
+      node.id = parseInt(info[0].split("-")[1]);
       node.site = info[1];
-      return true;
-    } else {
-      console.warn("could not normalize node :");
-      console.warn(node);
-      return false;
+      node.normalized = true;
     }
+  },
+  notify: function(node) {
+    console.log("[Notify] node " + node.id + " is " + node.boot_state);
+  },
+  createMaps: function($container, sites, nodes) {
+    var maps = {};
+    var $menu = $("<ul id='sites-tabs' class='nav nav-tabs' data-tabs='sites-tabs'/>").appendTo($container);
+    var $maps = $("<div id='maps' class='tab-content' />").appendTo($container);
+    
+    $.each(sites, function(i, site) {
+      var entry = $("<li><a href='#" + site + "' data-toggle='tab'>" + site + "</a></li>").appendTo($menu);
+      var $tab = $("<div class='tab-pane' id='" + site + "' />").appendTo($maps);
+      maps[site] = new Senslab.Map($tab);
+      maps[site].addNodes(nodes[site]);
+    });
+    
+    $menu.find("li").eq(0).addClass("active");
+    $maps.find("div").eq(0).addClass("active");
   }
 };
 
@@ -29,14 +43,14 @@ Senslab.Map = function() {
     "Suspected": 0xFF3030,
     "Selected": 0x0099CC
   };
-  
+
   var archs = [
     "wsn430",
     "m3",
     "a8"
   ];
   
-  function Map($container) {
+  function Map($container, options) {
     this.width  = 600;
     this.height = 400;
     
@@ -62,16 +76,14 @@ Senslab.Map = function() {
     
     var self = this;
     
-    this.nodes = {};
     this.$nodeInputs = {};
     
     $.each(archs, function(i, arch) {
-      self.nodes[arch] = [];
       self.$nodeInputs[arch] = $("<input type='text' placeholder='" + arch + "'>")
       .appendTo($container)
       .change(function() {
-        self.nodes[arch] = expand($(this).val());
-        self.updateColor(arch);
+        self.updateSelected(arch, expand($(this).val()));
+        self.update();
       });
     });
     
@@ -100,11 +112,14 @@ Senslab.Map = function() {
         case 1:
           self.pointerDetectRay = self.projector.pickingRay(self.mouse2D.clone(), self.camera);
           var intersects = self.pointerDetectRay.intersectObjects(self.scene.children);
-          if (intersects.length > 0 && self.select(intersects[0].object)) {
-            var node = intersects[0].object;
-            var $nodeInput = self.$nodeInputs[node.arch];
-            $nodeInput.val(factorize(self.nodes[node.arch]));
-            self.update();
+          if (intersects.length > 0) {
+            var particle = intersects[0].object;
+            if (particle.data.boot_state != "Suspected") {
+              setState(particle, particle.data.boot_state == "Alive" ? "Selected" : "Alive");
+              var $nodeInput = self.$nodeInputs[particle.data.arch];
+              $nodeInput.val(factorize(self.getNodesId(particle.data.arch)));
+              self.update();
+            }
           }
           break;
         case 3:
@@ -132,41 +147,29 @@ Senslab.Map = function() {
     $container.append($canvas);
   }
   
-  function getCenter(nodes) {
-    var xmin = 0, ymin = 0, zmin = 0;
-    var xmax = 0, ymax = 0, zmax = 0;
-    
-    for (var i = 0; i < nodes.length; ++i) {
-      if (nodes[i].x > xmax) xmax = nodes[i].x;
-      if (nodes[i].x < xmin) xmin = nodes[i].x;
-      if (nodes[i].y > ymax) ymax = nodes[i].y;
-      if (nodes[i].y < ymin) ymin = nodes[i].y;
-      if (nodes[i].z > zmax) zmax = nodes[i].z;
-      if (nodes[i].z < zmin) zmin = nodes[i].z;
+  Map.prototype.getNodesId = function(arch) {
+    var particles = this.scene.children;
+    var nodes = [];
+    for (var i = 0; i < particles.length; ++i) {
+      if (particles[i].data && particles[i].data.arch == arch && particles[i].data.boot_state == "Selected") {
+        nodes.push(particles[i].id);
+      }
     }
-    return {x: (xmax + xmin) / 2, y: (ymax + ymin) / 2, z: (zmax + zmin) / 2};
-  }
-  
-  function setColor(node) {
-    node.material.color.setHex(colors[node.boot_state] || colors["Selected"]);
+    return nodes;
   }
   
   Map.prototype.addNodes = function(nodes) {
     var center = getCenter(nodes);
-    var program = function(context) {
-      context.beginPath();
-      context.arc(0, 0, 1, 0, Math.PI * 2, true);
-      context.closePath();
-      context.fill();
-    };
+
+    nodes.sort(function(a, b) {
+      return a.id - b.id;
+    });
     
     for(var i = 0; i < nodes.length; ++i) {
-      var material = new THREE.ParticleCanvasMaterial({program: program});
+      var material = new THREE.ParticleCanvasMaterial({program: circle});
       var particle = new THREE.Particle(material);
-      
-      particle.id = nodes[i].id;
-      particle.arch = nodes[i].arch;
-      particle.boot_state = nodes[i].boot_state;
+      particle.data = nodes[i];
+      particle.id = parseInt(nodes[i].id);
       particle.position.x = (nodes[i].x - center.x) * 10;
       particle.position.y = (nodes[i].y - center.y) * 10;
       particle.position.z = (nodes[i].z - center.z) * 10;
@@ -177,26 +180,61 @@ Senslab.Map = function() {
     this.update();
   };
   
-  Map.prototype.select = function(node) {
-    if (node.boot_state == "Suspected") {
-      return false;
-    } else if (node.boot_state == "Alive") {
-      var array = this.nodes[node.arch];
-      array.push(parseInt(node.id));
-      array.sort(nodeSort);
-      node.boot_state = "Selected";
-      setColor(node);
-      return true;
-    } else {
-      var array = this.nodes[node.arch];
-      var index = $.inArray(parseInt(node.id), array);
-      index > -1 && array.splice(index, 1);
-      node.boot_state = "Alive";
-      setColor(node);
-      return true;
+  Map.prototype.updateSelected = function(arch, selected) {
+    var particles = this.scene.children;
+    for (var i = 0; i < particles.length; ++i) {
+      if (particles[i].data && particles[i].data.arch == arch && particles[i].data.boot_state != "Suspected") {
+        var particle = particles[i];
+        var state = $.inArray(particle.id, selected) == -1 ? "Alive" : "Selected";
+        if (particle.data.boot_state != state) {
+          setState(particle, state);
+        }
+      }
     }
+  }
+  
+  Map.prototype.updatePosition = function() {
+    this.camera.position.x = this.distance
+      * Math.sin(this.theta * Math.PI / 360)
+      * Math.cos(this.phi * Math.PI / 360);
+    this.camera.position.y = this.distance * Math.sin(this.phi * Math.PI / 360);
+    this.camera.position.z = this.distance
+      * Math.cos(this.theta * Math.PI / 360)
+      * Math.cos(this.phi * Math.PI / 360);
+    this.camera.lookAt(this.scene.position);
+    this.camera.updateMatrix();
   };
   
+  Map.prototype.update = function() {
+    this.renderer.render(this.scene, this.camera);
+  };
+
+  function setState(particle, state) {
+    particle.data.boot_state = state;
+    setColor(particle);
+    Senslab.notify(particle.data);
+  }
+
+  function setColor(particle) {
+    var color = colors[particle.data.boot_state] || colors["Selected"];
+    particle.material.color.setHex(color);
+  }
+
+  function getCenter(nodes) {
+    var xmin = 0, ymin = 0, zmin = 0;
+    var xmax = 0, ymax = 0, zmax = 0;
+    
+    for (var i = 0; i < nodes.length; ++i) {
+      if (nodes[i].x > xmax) xmax = nodes[i].x;
+      if (nodes[i].x < xmin) xmin = nodes[i].x;
+      if (nodes[i].y > ymax) ymax = nodes[i].y;
+      if (nodes[i].y < ymin) ymin = nodes[i].y;
+      if (nodes[i].z > zmax) zmax = nodes[i].z;
+      if (nodes[i].z < zmin) zmin = nodes[i].z;
+    }
+    return {x: (xmax + xmin) / 2, y: (ymax + ymin) / 2, z: (zmax + zmin) / 2};
+  }
+
   function factorize(nodes) {
     var factorized = [];
     var prev = 0;
@@ -238,7 +276,11 @@ Senslab.Map = function() {
         expanded.push(parseInt(factorized[i]));
       }
     }
-    expanded.sort(nodeSort);
+    
+    expanded.sort(function(a, b) {
+      return a - b;
+    });
+    
     for (var i = 1; i < expanded.length; i++) {
       if (expanded[i] == expanded[i - 1]) {
         expanded.splice(i--, 1);
@@ -246,34 +288,12 @@ Senslab.Map = function() {
     }
     return expanded;
   }
-  
-  function nodeSort(a, b) {
-    return a - b;
-  }
-  
-  Map.prototype.updateColor = function(arch) {
-    var nodes = this.scene.children;
-    for (var i = 0; i < nodes.length; ++i) {
-      if (nodes[i].arch == arch && nodes[i].boot_state != "Suspected") {
-        var id = parseInt(nodes[i].id);
-        var array = this.nodes[arch];
-        nodes[i].boot_state = $.inArray(id, array) == -1 ? "Alive" : "Selected";
-        setColor(nodes[i]);
-      }
-    }
-    this.update();
-  }
-  
-  Map.prototype.updatePosition = function() {
-    this.camera.position.x = this.distance * Math.sin(this.theta * Math.PI / 360) * Math.cos(this.phi * Math.PI / 360);
-    this.camera.position.y = this.distance * Math.sin(this.phi * Math.PI / 360);
-    this.camera.position.z = this.distance * Math.cos(this.theta * Math.PI / 360) * Math.cos(this.phi * Math.PI / 360);
-    this.camera.lookAt(this.scene.position);
-    this.camera.updateMatrix();
-  };
-  
-  Map.prototype.update = function() {
-    this.renderer.render(this.scene, this.camera);
+
+  function circle(context) {
+    context.beginPath();
+    context.arc(0, 0, 1, 0, Math.PI * 2, true);
+    context.closePath();
+    context.fill();
   };
   
   return Map;