<commit_before>function activateGoggles() {
  (function($){
      if (window.goggles && window.goggles.active) {
        window.goggles.stop(function(){}); window.goggles = null; return;
      }

      // Utility functions
      function bind(bindee, action) {
        return function() {
          return action.apply(bindee, Array.prototype.slice.call(arguments));
        };
      }
      function pointsFromEv(ev) {
        // given an event object, return the point's XY coordinates relative to
        // the screen
        if ('clientX' in ev) { // Firefox
          return [ev.clientX, ev.clientY];
        } else if ('offsetX' in ev) { // Opera
          return [ev.offsetX, ev.offsetY];
        }
      }
      function getUrl() {
        // return a unique URL for this page
        return document.location.protocol+"//"+document.location.host+"/"+document.location.pathname;
      }

      // Picker widget
      function hex2rgb(hex) {
        if (hex.length==4) {
          return {r: parseInt(hex.substr(1,1),16)*17,
                  g: parseInt(hex.substr(2,1),16)*17,
                  b: parseInt(hex.substr(3,1),16)*17};
        } else if (hex.length==7) {
          return {r: parseInt(hex.substr(1,2),16),
                  g: parseInt(hex.substr(3,2),16),
                  b: parseInt(hex.substr(5,2),16)};
        } else {
          return {r:0,g:0,b:0};
        }
      }
      function Picker(onPickColor) {
        var self = this;
        this.jq = $("<div>").css({
          position: "fixed",
          cursor: 'pointer',
          "z-index": "100001",
          border: "solid 1px #000",
          top: "0",
          left: "0"
        });
        var chosenColor = $();
        var colors = ["#000", "#fff", "#e50", "#fa0", "#1ba", "#e07", "#ab0"]
          .map(function(color) {
            var colorjq = $("<div>").css({"background-color": color,
                                          'color': (color=="#000"?"#fff":"#000"),
                                          'line-height': '64px',
                                          'font-size': '300%',
                                          'text-align': 'center',
                                          width: 32, height: 64});
            colorjq.click(function(){
                if (colorjq == chosenColor) { return; }
                onPickColor(hex2rgb(color));
                chosenColor.text("");
                chosenColor = colorjq;
                colorjq.html("•");
              });
            colorjq.appendTo(self.jq);
            return colorjq;
          });
        colors[0].click();
      }
      Picker.prototype.del = function() {
        this.jq.fadeOut('fast', bind(this,function(){this.jq.remove();}));
      };
      Picker.prototype.show = function() {
        this.jq.hide().appendTo($("body")).slideDown('medium');
      };

      // SHAPES
      function Shape(thickness, r,g,b,a, points) {
        // Takes a position, thickness, and rgba colors
        // Each shape looks like this:
        // {p: [ [x,y], [x,y], [x,y], ...], points
        //  t: 5                            thickness
        //  r: 250, g: 200, b: 125, a: 0.5  color
        // }
        this.t = thickness;
        this.r = r;
        this.g = g;
        this.b = b;
        this.a = a;
        this.p = points||[];
      }
      Shape.prototype.appendPoint = function(point) {
        // Append a point to this shape.
        this.p.push(
          [Math.round(point[0]*10)/10, Math.round(point[1]*10)/10]
        );
      };
      Shape.prototype.drawLast = function(ctx) {
        // Given a canvas, draw the last line of the shape
        if (this.p.length >= 2) {
          var a = this.p[this.p.length-2],
              b = this.p[this.p.length-1];
          // draws part of the shape
          ctx.strokeStyle = "rgba("+this.r+","+this.g+","+this.b+","+this.a+")";
          ctx.lineWidth = this.t;
          ctx.lineCap = "round";
          ctx.beginPath();
          ctx.moveTo.apply(ctx, a);
          ctx.lineTo.apply(ctx, b);
          ctx.stroke();
        }
      };
      Shape.prototype.draw = function(ctx) {
        // Draw a given shape if it is in view.
//      if ((p.x + shape.s) > 0 &&
//          (p.y + shape.s) > 0 &&
//          (p.x - shape.s) < canvas.width &&
//          (p.y - shape.s) < canvas.height) {
          ctx.strokeStyle = "rgba("+this.r+","+this.g+","+this.b+","+this.a+")";
          ctx.lineWidth = this.t;
          ctx.lineCap = "round";
          ctx.beginPath();
          ctx.moveTo.apply(ctx, this.p[0]);
          for (var i=0,l=this.p.length; i<l; i++) {
            ctx.lineTo.apply(ctx, this.p[i]);
          }
          ctx.stroke();
//       }
      };
      Shape.prototype.boundingBox = function() {
        // return the bounding box
        return {
          left: Math.min.apply(null, this.p.map(function(point){return point[0];})),
          right: Math.max.apply(null, this.p.map(function(point){return point[0];})),
          top: Math.min.apply(null, this.p.map(function(point){return point[1];})),
          bottom: Math.max.apply(null, this.p.map(function(point){return point[1];}))
        };
      };

      // GOGGLES
      function Goggles(ajaxroot) {
        // Here is our goggles object.

        this.canvas = $("<canvas>").css({
          position: "fixed",
          "z-index": "100000",
          top: "0",
          left: "0"
        }).appendTo(document.body)[0];

        this.url = getUrl();
        this.serverUrl = ajaxroot+"?callback=?";

        this.ctx = this.canvas.getContext('2d');

        this.shapes = null;
        // the list of shapes to draw.

        // used to find out whether we've stopped or not
        this.active = true;

        // so we know when to redraw
        this.lastUpdate = null;
        this.updateTimer = null;
        this.update(bind(this,function(){
            this.updateTimer = setInterval(bind(this, this.update), 10000);
            this.picker.show();
          }));

        // Center coordinate
        // Guess at where the text probably is
        this.centerCoord = 0;

        // Color picker
        this.curColor = {r:0,g:0,b:0};
        this.picker = new Picker(bind(this,function(color){
            this.curColor = color;
          }));

        // Events
        this.curshape = null;
        this.canvas.onmousedown = bind(this, function(ev) {
          if (this.shapes !== null) {
            this.curshape = new Shape(5, this.curColor.r,this.curColor.g,this.curColor.b,1);
          }
        });
        this.canvas.onmouseup = bind(this, function(ev) {
          if (this.curshape) {
            if (this.curshape.p.length) {
              this.shapes.push(this.curshape);
              this.sendShape(this.curshape);
            }
            this.curshape = null;
          }
        });
        this.canvas.onmousemove = bind(this, function(ev) {
          if (this.curshape) {
            this.curshape.appendPoint(
              this.untransform(pointsFromEv(ev)));
            this.curshape.drawLast(this.ctx);
          }
        });

        // Window resize and scroll handlers
        this.resizeTimer = null;
        window.onresize = bind(this, function() {
          // Resize later
          clearTimeout(this.resizeTimer);
          this.resizeTimer = setTimeout(bind(this, this.resizeCanvas), 100);
        });
        window.onscroll = bind(this, this.redraw);
        this.resizeCanvas();
        //this.update();
      }
      Goggles.prototype.stop = function(cb) {
        // Destroy a goggles object with optional callback
        this.active = false;
        this.picker.del();
        $(this.canvas).fadeOut('fast', bind(this, function() {
            window.onresize = null;
            window.onscroll = null;
            clearInterval(this.updateTimer);
            clearTimeout(this.resizeTimer);
            $(this.canvas).remove();
            cb();
          }));
      };
      Goggles.prototype.transform = function(p) {
        // Point transformation functions
        // Establish a new coordinate system. (0, 0) is at the top MIDDLE of
        // the page, +x is right and -x is left.
        // This accomodates pages that have fixed-width or centered layouts.
        // todo: actually I would really like this to be relative to either
        // the left of the content or the middle of the page.
        //
        // Given an absolute point in our new coordinate system, return the
        // point's position on the screen
        return [
          p[0]-window.scrollX + this.centerCoord,
          p[1]-window.scrollY
        ];
      };
      Goggles.prototype.untransform = function(p) {
        // Given an point wrt the screen, return the point's absolute position
        // wrt our coordinate system
        return [
          p[0]+window.scrollX - this.centerCoord,
          p[1]+window.scrollY
        ];
      };
      Goggles.prototype.recalculateCenter = function() {
        // this calculates what X-coordinate will be the 'focus' of our web
        // page.
        //
        // essentially, we want our x=0 coordinate to be the left edge of the
        // content. this works reasonably well in practice except for
        // dynamically generated things and line wrapping.

        this.centerCoord = (
          ($("#header").offset() || {left:0}).left ||
          ($(".header").offset() || {left:0}).left ||
          ($(".inner").offset()  || {left:0}).left ||
          ($(".content").offset()|| {left:0}).left ||

          // hackernews
          ($("body>center>table").offset()||{left: 0}).left ||
          // table-based layouts
          ($("body>table").offset()||{left: 0}).left ||

          // gogole results pages
          ($("#center_col").offset()||{left:0}).left ||

          (this.canvas.width/2)
        );
      };

      // Drawing functions
      Goggles.prototype.redraw = function() {
        // Redraw entire canvas
        if (this.shapes === null) {
          this.drawLoading();
        } else {
          var ctx = this.ctx;
          // clear
          this.resetCanvasXform();
          for (var i=0,l=this.shapes.length; i<l; i++) {
            var bb = this.shapes[i].boundingBox();
            // clip invisible shapes
            if (bb.right - window.scrollX + this.centerCoord > 0 &&
                bb.left - window.scrollX + this.centerCoord < this.canvas.width &&
                bb.bottom - window.scrollY > 0 &&
                bb.top - window.scrollY < this.canvas.height) {
              this.shapes[i].draw(ctx);
            }
          }
        }
      };
      Goggles.prototype.resetCanvasXform = function() {
        this.ctx.setTransform(1,0,
                              0,1,  0, 0);
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
        this.ctx.setTransform(1,0,
                              0,1,
          this.centerCoord-window.scrollX,
          -window.scrollY);
      };
      Goggles.prototype.resizeCanvas = function() {
        // Fix the canvas when resized
        this.canvas.width = window.innerWidth;
        this.canvas.height = window.innerHeight;
        this.recalculateCenter();
        this.redraw();
      };

      // Loading... screen
      Goggles.prototype.drawLoading = function() {
        this.ctx.setTransform(1,0,
                              0,1,  0, 0);
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
        this.ctx.fillStyle = "rgba(128,128,128,0.2)";
        this.ctx.fillRect(0,0, this.canvas.width, this.canvas.height);
      };

      // AJAX functions
      function unserializeShapeArray(shapes) {
        if (typeof shapes !== 'undefined') {
          return shapes.map(function(s){
              return new Shape(s.t, s.r,s.g,s.b,s.a, s.p);
            });
        }
      }
      function serializePoints(points){
        // return the points in a suitable format for the server
        return points.map(function(point){
            return point[0]+","+point[1];
          }).join(';');
      }
      Goggles.prototype.update = function(cb) {
        // update informations from the server
        cb = cb || function(){};
        var self = this;
        $.getJSON(this.serverUrl, {
            page: this.url
          }, function(json) {
            if (json.err) {
              alert(json.err);
              self.stop(function(){});
            } else {
              console.log(json);
              if (self.active && self.lastUpdate != json.lastUpdate) {
                self.lastUpdate = json.lastUpdate;
                if (!self.curshape) {
                  self.shapes = unserializeShapeArray(json.shapes);
                  self.redraw();
                }
                cb();
              }
            }
          });
      };
      Goggles.prototype.sendShape = function(shape) {
        var self = this;
        $.getJSON(this.serverUrl, {
            page: this.url, add: 't',
            r: shape.r, g:shape.g, b:shape.b, a:shape.a,t:shape.t,
            p:serializePoints(shape.p)},
          function(data){
            if (data && data.err) {
              alert("There was a problem sending the shapes to the server.");
              console.log(data);
              self.stop(function(){});
            }
          });
      };

      window.goggles = new Goggles(window.GOGGLE_SERVER);

  })(jQuery);
}

if (typeof jQuery == 'undefined') {
  var jQ = document.createElement('script');
  jQ.type = 'text/javascript';
  jQ.onload=activateGoggles;
  jQ.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js';
  document.body.appendChild(jQ);
} else {
  activateGoggles();
}
<commit_msg>the client no longer saves the shape they draw<commit_after>function activateGoggles() {
  (function($){
      if (window.goggles && window.goggles.active) {
        window.goggles.stop(function(){}); window.goggles = null; return;
      }

      // Utility functions
      function bind(bindee, action) {
        return function() {
          return action.apply(bindee, Array.prototype.slice.call(arguments));
        };
      }
      function pointsFromEv(ev) {
        // given an event object, return the point's XY coordinates relative to
        // the screen
        if ('clientX' in ev) { // Firefox
          return [ev.clientX, ev.clientY];
        } else if ('offsetX' in ev) { // Opera
          return [ev.offsetX, ev.offsetY];
        }
      }
      function getUrl() {
        // return a unique URL for this page
        return document.location.protocol+"//"+document.location.host+"/"+document.location.pathname;
      }

      // Picker widget
      function hex2rgb(hex) {
        if (hex.length==4) {
          return {r: parseInt(hex.substr(1,1),16)*17,
                  g: parseInt(hex.substr(2,1),16)*17,
                  b: parseInt(hex.substr(3,1),16)*17};
        } else if (hex.length==7) {
          return {r: parseInt(hex.substr(1,2),16),
                  g: parseInt(hex.substr(3,2),16),
                  b: parseInt(hex.substr(5,2),16)};
        } else {
          return {r:0,g:0,b:0};
        }
      }
      function Picker(onPickColor) {
        var self = this;
        this.jq = $("<div>").css({
          position: "fixed",
          cursor: 'pointer',
          "z-index": "100001",
          border: "solid 1px #000",
          top: "0",
          left: "0"
        });
        var chosenColor = $();
        var colors = ["#000", "#fff", "#e50", "#fa0", "#1ba", "#e07", "#ab0"]
          .map(function(color) {
            var colorjq = $("<div>").css({"background-color": color,
                                          'color': (color=="#000"?"#fff":"#000"),
                                          'line-height': '64px',
                                          'font-size': '300%',
                                          'text-align': 'center',
                                          width: 32, height: 64});
            colorjq.click(function(){
                if (colorjq == chosenColor) { return; }
                onPickColor(hex2rgb(color));
                chosenColor.text("");
                chosenColor = colorjq;
                colorjq.html("•");
              });
            colorjq.appendTo(self.jq);
            return colorjq;
          });
        colors[0].click();
      }
      Picker.prototype.del = function() {
        this.jq.fadeOut('fast', bind(this,function(){this.jq.remove();}));
      };
      Picker.prototype.show = function() {
        this.jq.hide().appendTo($("body")).slideDown('medium');
      };

      // SHAPES
      function Shape(thickness, r,g,b,a, points) {
        // Takes a position, thickness, and rgba colors
        // Each shape looks like this:
        // {p: [ [x,y], [x,y], [x,y], ...], points
        //  t: 5                            thickness
        //  r: 250, g: 200, b: 125, a: 0.5  color
        // }
        this.t = thickness;
        this.r = r;
        this.g = g;
        this.b = b;
        this.a = a;
        this.p = points||[];
      }
      Shape.prototype.appendPoint = function(point) {
        // Append a point to this shape.
        this.p.push(
          [Math.round(point[0]*10)/10, Math.round(point[1]*10)/10]
        );
      };
      Shape.prototype.drawLast = function(ctx) {
        // Given a canvas, draw the last line of the shape
        if (this.p.length >= 2) {
          var a = this.p[this.p.length-2],
              b = this.p[this.p.length-1];
          // draws part of the shape
          ctx.strokeStyle = "rgba("+this.r+","+this.g+","+this.b+","+this.a+")";
          ctx.lineWidth = this.t;
          ctx.lineCap = "round";
          ctx.beginPath();
          ctx.moveTo.apply(ctx, a);
          ctx.lineTo.apply(ctx, b);
          ctx.stroke();
        }
      };
      Shape.prototype.draw = function(ctx) {
        // Draw a given shape if it is in view.
//      if ((p.x + shape.s) > 0 &&
//          (p.y + shape.s) > 0 &&
//          (p.x - shape.s) < canvas.width &&
//          (p.y - shape.s) < canvas.height) {
          ctx.strokeStyle = "rgba("+this.r+","+this.g+","+this.b+","+this.a+")";
          ctx.lineWidth = this.t;
          ctx.lineCap = "round";
          ctx.beginPath();
          ctx.moveTo.apply(ctx, this.p[0]);
          for (var i=0,l=this.p.length; i<l; i++) {
            ctx.lineTo.apply(ctx, this.p[i]);
          }
          ctx.stroke();
//       }
      };
      Shape.prototype.boundingBox = function() {
        // return the bounding box
        return {
          left: Math.min.apply(null, this.p.map(function(point){return point[0];})),
          right: Math.max.apply(null, this.p.map(function(point){return point[0];})),
          top: Math.min.apply(null, this.p.map(function(point){return point[1];})),
          bottom: Math.max.apply(null, this.p.map(function(point){return point[1];}))
        };
      };

      // GOGGLES
      function Goggles(ajaxroot) {
        // Here is our goggles object.

        this.canvas = $("<canvas>").css({
          position: "fixed",
          "z-index": "100000",
          top: "0",
          left: "0"
        }).appendTo(document.body)[0];

        this.url = getUrl();
        this.serverUrl = ajaxroot+"?callback=?";

        this.ctx = this.canvas.getContext('2d');

        this.shapes = null;
        // the list of shapes to draw.

        // used to find out whether we've stopped or not
        this.active = true;

        // so we know when to redraw
        this.lastUpdate = null;
        this.updateTimer = null;
        this.update(bind(this,function(){
            this.updateTimer = setInterval(bind(this, this.update), 10000);
            this.picker.show();
          }));

        // Center coordinate
        // Guess at where the text probably is
        this.centerCoord = 0;

        // Color picker
        this.curColor = {r:0,g:0,b:0};
        this.picker = new Picker(bind(this,function(color){
            this.curColor = color;
          }));

        // Events
        this.curshape = null;
        this.canvas.onmousedown = bind(this, function(ev) {
          if (this.shapes !== null) {
            this.curshape = new Shape(5, this.curColor.r,this.curColor.g,this.curColor.b,1);
          }
        });
        this.canvas.onmouseup = bind(this, function(ev) {
          if (this.curshape) {
            if (this.curshape.p.length) {
              // todo: the server will send us the shape on its update
              //this.shapes.push(this.curshape);
              this.sendShape(this.curshape);
            }
            this.curshape = null;
          }
        });
        this.canvas.onmousemove = bind(this, function(ev) {
          if (this.curshape) {
            this.curshape.appendPoint(
              this.untransform(pointsFromEv(ev)));
            this.curshape.drawLast(this.ctx);
          }
        });

        // Window resize and scroll handlers
        this.resizeTimer = null;
        window.onresize = bind(this, function() {
          // Resize later
          clearTimeout(this.resizeTimer);
          this.resizeTimer = setTimeout(bind(this, this.resizeCanvas), 100);
        });
        window.onscroll = bind(this, this.redraw);
        this.resizeCanvas();
        //this.update();
      }
      Goggles.prototype.stop = function(cb) {
        // Destroy a goggles object with optional callback
        this.active = false;
        this.picker.del();
        $(this.canvas).fadeOut('fast', bind(this, function() {
            window.onresize = null;
            window.onscroll = null;
            clearInterval(this.updateTimer);
            clearTimeout(this.resizeTimer);
            $(this.canvas).remove();
            cb();
          }));
      };
      Goggles.prototype.transform = function(p) {
        // Point transformation functions
        // Establish a new coordinate system. (0, 0) is at the top MIDDLE of
        // the page, +x is right and -x is left.
        // This accomodates pages that have fixed-width or centered layouts.
        // todo: actually I would really like this to be relative to either
        // the left of the content or the middle of the page.
        //
        // Given an absolute point in our new coordinate system, return the
        // point's position on the screen
        return [
          p[0]-window.scrollX + this.centerCoord,
          p[1]-window.scrollY
        ];
      };
      Goggles.prototype.untransform = function(p) {
        // Given an point wrt the screen, return the point's absolute position
        // wrt our coordinate system
        return [
          p[0]+window.scrollX - this.centerCoord,
          p[1]+window.scrollY
        ];
      };
      Goggles.prototype.recalculateCenter = function() {
        // this calculates what X-coordinate will be the 'focus' of our web
        // page.
        //
        // essentially, we want our x=0 coordinate to be the left edge of the
        // content. this works reasonably well in practice except for
        // dynamically generated things and line wrapping.

        this.centerCoord = (
          ($("#header").offset() || {left:0}).left ||
          ($(".header").offset() || {left:0}).left ||
          ($(".inner").offset()  || {left:0}).left ||
          ($(".content").offset()|| {left:0}).left ||

          // hackernews
          ($("body>center>table").offset()||{left: 0}).left ||
          // table-based layouts
          ($("body>table").offset()||{left: 0}).left ||

          // gogole results pages
          ($("#center_col").offset()||{left:0}).left ||

          (this.canvas.width/2)
        );
      };

      // Drawing functions
      Goggles.prototype.redraw = function() {
        // Redraw entire canvas
        if (this.shapes === null) {
          this.drawLoading();
        } else {
          var ctx = this.ctx;
          // clear
          this.resetCanvasXform();
          for (var i=0,l=this.shapes.length; i<l; i++) {
            var bb = this.shapes[i].boundingBox();
            // clip invisible shapes
            if (bb.right - window.scrollX + this.centerCoord > 0 &&
                bb.left - window.scrollX + this.centerCoord < this.canvas.width &&
                bb.bottom - window.scrollY > 0 &&
                bb.top - window.scrollY < this.canvas.height) {
              this.shapes[i].draw(ctx);
            }
          }
        }
      };
      Goggles.prototype.resetCanvasXform = function() {
        this.ctx.setTransform(1,0,
                              0,1,  0, 0);
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
        this.ctx.setTransform(1,0,
                              0,1,
          this.centerCoord-window.scrollX,
          -window.scrollY);
      };
      Goggles.prototype.resizeCanvas = function() {
        // Fix the canvas when resized
        this.canvas.width = window.innerWidth;
        this.canvas.height = window.innerHeight;
        this.recalculateCenter();
        this.redraw();
      };

      // Loading... screen
      Goggles.prototype.drawLoading = function() {
        this.ctx.setTransform(1,0,
                              0,1,  0, 0);
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
        this.ctx.fillStyle = "rgba(128,128,128,0.2)";
        this.ctx.fillRect(0,0, this.canvas.width, this.canvas.height);
      };

      // AJAX functions
      function unserializeShapeArray(shapes) {
        if (typeof shapes !== 'undefined') {
          return shapes.map(function(s){
              return new Shape(s.t, s.r,s.g,s.b,s.a, s.p);
            });
        }
      }
      function serializePoints(points){
        // return the points in a suitable format for the server
        return points.map(function(point){
            return point[0]+","+point[1];
          }).join(';');
      }
      Goggles.prototype.update = function(cb) {
        // update informations from the server
        cb = cb || function(){};
        var self = this;
        $.getJSON(this.serverUrl, {
            page: this.url
          }, function(json) {
            if (json.err) {
              alert(json.err);
              self.stop(function(){});
            } else {
              console.log(json);
              if (self.active && self.lastUpdate != json.lastUpdate) {
                self.lastUpdate = json.lastUpdate;
                if (!self.curshape) {
                  self.shapes = unserializeShapeArray(json.shapes);
                  self.redraw();
                }
                cb();
              }
            }
          });
      };
      Goggles.prototype.sendShape = function(shape) {
        var self = this;
        $.getJSON(this.serverUrl, {
            page: this.url, add: 't',
            r: shape.r, g:shape.g, b:shape.b, a:shape.a,t:shape.t,
            p:serializePoints(shape.p)},
          function(data){
            if (data && data.err) {
              alert("There was a problem sending the shapes to the server.");
              console.log(data);
              self.stop(function(){});
            }
          });
      };

      window.goggles = new Goggles(window.GOGGLE_SERVER);

  })(jQuery);
}

if (typeof jQuery == 'undefined') {
  var jQ = document.createElement('script');
  jQ.type = 'text/javascript';
  jQ.onload=activateGoggles;
  jQ.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js';
  document.body.appendChild(jQ);
} else {
  activateGoggles();
}
<|endoftext|>


<commit_before>module.exports = grammar({
  name: 'ruby',

  extras: $ => [
    $.comment,
    $._line_break,
    /[ \t\r]/
  ],

  rules: {
    program: $ => sep($._statement, $._terminator),

  	_statement: $ => choice(
      $._declaration,
      seq($._call, "do", optional("|", $._block_variable, "|"), sep($._statement, $._terminator), "end"),
      seq("undef", $._function_name),
      seq("alias", $._function_name, $._function_name),
      seq($._statement, "if", $._expression),
      seq($._statement, "while", $._expression),
      seq($._statement, "unless", $._expression),
      seq($._statement, "until", $._expression),
      $._expression
    ),

    _declaration: $ => choice(
      $.method_declaration,
      $.class_declaration,
      $.module_declaration
    ),

    method_declaration: $ => seq(
      "def", $._function_name, choice(seq("(", optional($.argument_list), ")"), seq(optional($.argument_list), $._terminator)),
      sep($._statement, $._terminator),
      "end"
    ),

    argument_list: $ => commaSep1(seq(optional(choice("*", "&")), $.identifier)),

    class_declaration: $ => seq("class", $.identifier, optional(seq("<", sep1($.identifier, "::"))), sep($._statement, $._terminator), "end"),

    module_declaration: $ => seq("module", $.identifier, sep($._statement, $._terminator), "end"),

    _call: $ => choice($._function_call, $._command),

    _call_arguments: $ => choice(
      commaSep1($._argument),
      $._command
    ),

    _command: $ => choice(
      seq("super", $._call_arguments)
    ),
    _function_call: $ => choice("super"),

  	_expression: $ => choice($._argument),

  	_argument: $ => choice($._primary),

  	_primary: $ => choice(
      seq("(", sep1($._statement, $._terminator), ")"),
      $._variable
    ),

    _block_variable: $ => choice($._lhs, $._mlhs),
    _mlhs: $ => choice(
      seq($._mlhs_item, optional(seq($._mlhs_item, repeat(",", $._mlhs_item))), optional(seq("*", optional($._lhs)))),
      seq("*", $._lhs)
    ),
    _mlhs_item: $ => choice($._lhs, seq("(", $._mlhs, ")")),
    _lhs: $ => choice(
      $._variable,
      seq($._primary, "[", commaSep($._argument), "]"),
      seq($._primary, ".", $.identifier)
    ),
  	_variable: $ => choice($.identifier , 'nil', 'self'),

  	identifier: $ => token(seq(repeat(choice('@', '$')), /[a-zA-Z_][a-zA-Z0-9_]*/)),

  	comment: $ => token(choice(
      seq('#', /.*/),
      seq(
        '=begin\n',
        repeat(/.*\n/),
        '=end\n'
      )
    )),

    symbol: $ => token(seq(':', choice($._function_name, $._variable))),

    _function_name: $ => choice($.identifier, '..', '|'),

    _line_break: $ => '\n',
  	_terminator: $ => choice($._line_break, ';'),
  }
});

function sep1 (rule, separator) {
  return seq(rule, repeat(seq(separator, rule)));
}

function sep (rule, separator) {
  return optional(sep1(rule, separator));
}

function commaSep1 (rule) {
  return sep1(rule, ',')
}

function commaSep (rule) {
  return optional(commaSep1(rule));
}

function optionalParens (rule) {
  return choice(seq("(", rule, ")"), rule)
}
<commit_msg>Pull the body of identifiers out into a function.<commit_after>module.exports = grammar({
  name: 'ruby',

  extras: $ => [
    $.comment,
    $._line_break,
    /[ \t\r]/
  ],

  rules: {
    program: $ => sep($._statement, $._terminator),

  	_statement: $ => choice(
      $._declaration,
      seq($._call, "do", optional("|", $._block_variable, "|"), sep($._statement, $._terminator), "end"),
      seq("undef", $._function_name),
      seq("alias", $._function_name, $._function_name),
      seq($._statement, "if", $._expression),
      seq($._statement, "while", $._expression),
      seq($._statement, "unless", $._expression),
      seq($._statement, "until", $._expression),
      $._expression
    ),

    _declaration: $ => choice(
      $.method_declaration,
      $.class_declaration,
      $.module_declaration
    ),

    method_declaration: $ => seq(
      "def", $._function_name, choice(seq("(", optional($.argument_list), ")"), seq(optional($.argument_list), $._terminator)),
      sep($._statement, $._terminator),
      "end"
    ),

    argument_list: $ => commaSep1(seq(optional(choice("*", "&")), $.identifier)),

    class_declaration: $ => seq("class", $.identifier, optional(seq("<", sep1($.identifier, "::"))), sep($._statement, $._terminator), "end"),

    module_declaration: $ => seq("module", $.identifier, sep($._statement, $._terminator), "end"),

    _call: $ => choice($._function_call, $._command),

    _call_arguments: $ => choice(
      commaSep1($._argument),
      $._command
    ),

    _command: $ => choice(
      seq("super", $._call_arguments)
    ),
    _function_call: $ => choice("super"),

  	_expression: $ => choice($._argument),

  	_argument: $ => choice($._primary),

  	_primary: $ => choice(
      seq("(", sep1($._statement, $._terminator), ")"),
      $._variable
    ),

    _block_variable: $ => choice($._lhs, $._mlhs),
    _mlhs: $ => choice(
      seq($._mlhs_item, optional(seq($._mlhs_item, repeat(",", $._mlhs_item))), optional(seq("*", optional($._lhs)))),
      seq("*", $._lhs)
    ),
    _mlhs_item: $ => choice($._lhs, seq("(", $._mlhs, ")")),
    _lhs: $ => choice(
      $._variable,
      seq($._primary, "[", commaSep($._argument), "]"),
      seq($._primary, ".", $.identifier)
    ),
  	_variable: $ => choice($.identifier , 'nil', 'self'),

  	identifier: $ => token(seq(repeat(choice('@', '$')), identifierChars())),

  	comment: $ => token(choice(
      seq('#', /.*/),
      seq(
        '=begin\n',
        repeat(/.*\n/),
        '=end\n'
      )
    )),

    symbol: $ => token(seq(':', choice($._function_name, $._variable))),

    _function_name: $ => choice($.identifier, '..', '|'),

    _line_break: $ => '\n',
  	_terminator: $ => choice($._line_break, ';'),
  }
});

function identifierChars () {
  return /[a-zA-Z_][a-zA-Z0-9_]*/;
}

function sep1 (rule, separator) {
  return seq(rule, repeat(seq(separator, rule)));
}

function sep (rule, separator) {
  return optional(sep1(rule, separator));
}

function commaSep1 (rule) {
  return sep1(rule, ',')
}

function commaSep (rule) {
  return optional(commaSep1(rule));
}

function optionalParens (rule) {
  return choice(seq("(", rule, ")"), rule)
}
<|endoftext|>


<commit_before>module.exports = grammar({
  name: 'ruby',

  extras: $ => [
    $.comment,
    $._line_break,
    /[ \t\r]/
  ],

  rules: {
    program: $ => $._compound_statement,

    _compound_statement: $ => repeat(seq($._statement, optional($._terminator))),

  	_statement: $ => choice(
      $._expression
    ),
  	_expression: $ => choice($._argument),

    _arguments: $ => seq($._argument, repeat(seq(",", $._arguments))),
  	_argument: $ => choice($._primary),

  	_primary: $ => choice(
      seq("(", $._compound_statement, ")"),
      $._variable
    ),

  	_variable: $ => choice($.identifier , 'nil', 'self'),

  	identifier: $ => seq(repeat(choice('@', '$')), /[a-zA-Z_][a-zA-Z0-9_]*/),

  	comment: $ => token(choice(
      seq('#', /.*/),
      seq(
        '=begin\n',
        repeat(/.*\n/),
        '=end\n'
      )
    )),

    _line_break: $ => '\n',
  	_terminator: $ => choice($._line_break, ';'),
  }
});

function commaSep1 (rule) {
  return seq(rule, repeat(seq(',', rule)));
}
<commit_msg>Steal the commaSep function too.<commit_after>module.exports = grammar({
  name: 'ruby',

  extras: $ => [
    $.comment,
    $._line_break,
    /[ \t\r]/
  ],

  rules: {
    program: $ => $._compound_statement,

    _compound_statement: $ => repeat(seq($._statement, optional($._terminator))),

  	_statement: $ => choice(
      $._expression
    ),
  	_expression: $ => choice($._argument),

    _arguments: $ => seq($._argument, repeat(seq(",", $._arguments))),
  	_argument: $ => choice($._primary),

  	_primary: $ => choice(
      seq("(", $._compound_statement, ")"),
      $._variable
    ),

  	_variable: $ => choice($.identifier , 'nil', 'self'),

  	identifier: $ => seq(repeat(choice('@', '$')), /[a-zA-Z_][a-zA-Z0-9_]*/),

  	comment: $ => token(choice(
      seq('#', /.*/),
      seq(
        '=begin\n',
        repeat(/.*\n/),
        '=end\n'
      )
    )),

    _line_break: $ => '\n',
  	_terminator: $ => choice($._line_break, ';'),
  }
});

function commaSep1 (rule) {
  return seq(rule, repeat(seq(',', rule)));
}

function commaSep (rule) {
  return optional(commaSep1(rule));
}
<|endoftext|>


<commit_before>export function init() {
    $(document).ready(function() {
        let listElements = $('.listing-item');
        listElements.each(function () {
            let mediaCaption = $(this).find('.media-caption__source');
            if (mediaCaption.hasClass('media-caption__source--video') || mediaCaption.hasClass('media-caption__source--audio')) {
                $(this).find('.infoline').html(mediaCaption.html());
            } else {
                $(this).find('.infoline-source').html(mediaCaption.html());
            }
        });
    });
}
<commit_msg>make listmodule.js idempotent by marking & checking elements<commit_after>import { DOM_MUTATION_EVENTS } from './utils/fef-events';

export function init() {
    $(window).on(DOM_MUTATION_EVENTS, () => {
        let $listElements = $('.listing-item');

        $listElements.each(function () {
            // only initialize each list module once
            if ($(this).data('listmodule-initialized')) {
                return;
            }

            let $mediaCaption = $(this).find('.media-caption__source');

            if ($mediaCaption.hasClass('media-caption__source--video') || $mediaCaption.hasClass('media-caption__source--audio')) {
                $(this).find('.infoline').html($mediaCaption.html());
            } else {
                $(this).find('.infoline-source').html($mediaCaption.html());
            }

            // mark element, so that it won't be initialized again by this module
            $(this).data('listmodule-initialized', true);
        });
    });
}
<|endoftext|>


<commit_before>/**
 * AutoGrid - responsive, adaptive automatic layout that just works for you. Everything you have to
 * do is to create AutoGrid instance with argument of container element, and AutoGrid will align
 * the best layout for you.
 * NOTE. AutoGrid will turn container's position to relative and overflow to auto.
 * @author Nikita Savchenko aka ZitRo (zitros.lab@gmail.com)
 * @param {HTMLElement} container - Block that contains blocks to align.
 */
export function AutoGrid (container) {

    if (!(container instanceof HTMLElement))
        throw new Error(`container (${container}) is not HTML element.`);

    container.style.position = "relative";

    this.container = container;
    this.width = container.offsetWidth;
    this.columns = getColumnsNumber(this.width);

    /**
     * This array holds sorted grid elements. Container is a wrapper for the element.
     * @type {{ element: HTMLElement, container: HTMLElement }[]}
     */
    this.children = [

    ];

    let resizeTimer = 0; // not to perform resize too frequently
    this.windowResizeHandler = () => {
        if (resizeTimer) clearTimeout(resizeTimer);
        resizeTimer = setTimeout(() => this.updateSizes(), 200);
    };
    window.addEventListener("resize", this.windowResizeHandler);

}

function getColumnsNumber (width) {
    return Math.max(1, Math.round(width / 400));
}

/**
 * Removes all children.
 */
AutoGrid.prototype.clear = function () {
    this.children = this.children.filter(({ container }) => {
        if (container.parentNode)
            container.parentNode.removeChild(container);
        return false;
    });
};

/**
 * This function disables AutoGrid automatic layout.
 */
AutoGrid.prototype.disable = function () {

    if (!this.windowResizeHandler) return;

    window.removeEventListener("resize", this.windowResizeHandler);
    this.windowResizeHandler = null;
    this.container = null;

};

AutoGrid.prototype.childExists = function (element) {

    return !!this.children.filter((e) => element === e.element).length;

};

AutoGrid.prototype.applyChild = function (element) {

    if (this.childExists(element)) return;

    let container = document.createElement("div");
    container.className = "AutoGrid-container";
    container.style.position = "absolute";
    container.appendChild(element);
    this.children.push({
        element: element,
        container: container
    });

    this.updateGrid();

};

AutoGrid.prototype.updateGrid = function () {

    let i, columnWidth = Math.floor(this.width/this.columns),
        columnHeights = (() => {
            let arr = [], i;
            for (i = 0; i < this.columns; i++)
                arr.push(0);
            return arr;
        })();

    function getNextColumnIndex () {
        let i, minCol = 0, minHeight = columnHeights[0];
        for (i = 1; i < columnHeights.length; i++)
            if (columnHeights[i] < minHeight) {
                minCol = i;
                minHeight = columnHeights[minCol];
            }
        return minCol;
    }

    for (i = 0; i < this.children.length; i++) {

        let block = this.children[i];
        let colIndex = getNextColumnIndex(),
            left = colIndex * columnWidth + "px",
            top = columnHeights[colIndex] + "px";

        if (!block.container.parentNode) {
            block.container.style.left = left;
            block.container.style.top = top;
            block.container.style.width = columnWidth + "px";
            this.container.appendChild(block.container);
        } else {
            if (block.container.style.left !== left)
                block.container.style.left = left;
            if (block.container.style.top !== top)
                block.container.style.top = top;
            if (block.container.style.width !== columnWidth + "px")
                block.container.style.width = columnWidth + "px";
        }
        columnHeights[colIndex] += block.container.offsetHeight;
        // Adding/updating of nodes may cause scrollbar to appear. This changes the width of the
        // container. To prevent inset containers from flowing we need to recalculate sizes as
        // soon as we noticed size change. This won't take a lot of resources as not many cards
        // needed to trigger scrollbar appear.
        if (this.width !== this.container.offsetWidth) {
            this.updateSizes();
            return;
        }

    }

    this.container.style.height = columnHeights.reduce((a, b) => Math.max(a, b)) + "px";

    // Yet another check required in case the height of the block is reduced and scrollbar
    // disappears.
    if (this.width !== this.container.offsetWidth) {
        this.updateSizes();
    }

};

AutoGrid.prototype.updateSizes = function () {

    if (this.width === this.container.offsetWidth) return;

    this.width = this.container.offsetWidth;
    this.columns = getColumnsNumber(this.width);

    this.updateGrid();

};<commit_msg>AutoGrid manual width support<commit_after>/**
 * AutoGrid - responsive, adaptive automatic layout that just works for you. Everything you have to
 * do is to create AutoGrid instance with argument of container element, and AutoGrid will align
 * the best layout for you.
 * NOTE. AutoGrid will turn container's position to relative and overflow to auto.
 * @author Nikita Savchenko aka ZitRo (zitros.lab@gmail.com)
 * @param {HTMLElement} container - Block that contains blocks to align.
 */
export function AutoGrid (container) {

    if (!(container instanceof HTMLElement))
        throw new Error(`container (${container}) is not HTML element.`);

    container.style.position = "relative";

    this.container = container;
    this.width = container.offsetWidth;
    this.COLUMNS = getColumnsNumber(this.width);

    /**
     * This array holds sorted grid elements. Container is a wrapper for the element.
     * @type {{ element: HTMLElement, container: HTMLElement, [width]: number=1 }[]}
     */
    this.children = [];

    let resizeTimer = 0; // not to perform resize too frequently
    this.windowResizeHandler = () => {
        if (resizeTimer) clearTimeout(resizeTimer);
        resizeTimer = setTimeout(() => this.updateSizes(), 200);
    };
    window.addEventListener("resize", this.windowResizeHandler);

}

function getColumnsNumber (width) {
    return Math.max(1, Math.round(width / 400));
}

/**
 * Removes all children.
 */
AutoGrid.prototype.clear = function () {
    this.children = this.children.filter(({ container }) => {
        if (container.parentNode)
            container.parentNode.removeChild(container);
        return false;
    });
};

/**
 * This function disables AutoGrid automatic layout.
 */
AutoGrid.prototype.disable = function () {

    if (!this.windowResizeHandler) return;

    window.removeEventListener("resize", this.windowResizeHandler);
    this.windowResizeHandler = null;
    this.container = null;

};

AutoGrid.prototype.childExists = function (element) {

    return !!this.children.filter((e) => element === e.element).length;

};

/**
 * @param {HTMLElement} element
 * @param {*} [options] - Additional options like { width: 2 }.
 */
AutoGrid.prototype.applyChild = function (element, options) {

    if (this.childExists(element)) return;

    let container = document.createElement("div"),
        obj = {
            element: element,
            container: container,
            width: 1
        };

    container.className = "AutoGrid-container";
    container.style.position = "absolute";
    container.appendChild(element);
    Object.assign(obj, options || {});

    this.children.push(obj);

    this.updateGrid();

};

/**
 * @param {HTMLElement} element
 * @param {*} options - Additional options like { width: 2 }.
 * @returns {boolean} - Success of update (if the element is found).
 */
AutoGrid.prototype.updateChild = function (element, options) {

    let updated = null;

    this.children.forEach(c => {
        if (c !== element)
            return;
        updated = c;
    });

    if (updated) {
        Object.assign(updated, options);
        this.updateGrid();
    }

    return !!updated;

};

AutoGrid.prototype.updateGrid = function () {

    let i, columnWidth = Math.floor(this.width / this.COLUMNS),
        columnHeights = (() => {
            let arr = [], i;
            for (i = 0; i < this.COLUMNS; i++)
                arr.push(0);
            return arr;
        })();

    /**
     * WIDTH = 3
     * C1 C2 C3 C4 C5
     * ## ## ## ## ##
     * ## ##    ##
     * ##       ##
     * (______) ##
     *
     * This function returns sorted array of column indices to fill the grid.
     */
    function getNextColumnIndices (colSpan) {
        let iArr = Array.from({ length: columnHeights.length }, (v, k) => k).sort((i1, i2) => {
                if (columnHeights[i1] === columnHeights[i2])
                    return 0;
                return columnHeights[i1] > columnHeights[i2] ? 1 : -1;
            }), rArr;
        for (let i = colSpan; i <= iArr.length; i++) {
            rArr = iArr.slice(0, i).sort();
            let c = 1, u;
            for (u = 1; u < rArr.length; u++)
                if (rArr[u - 1] + 1 === rArr[u]) {
                    if (++c === colSpan) {
                        u++;
                        break;
                    }
                } else {
                    c = 1;
                }
            if (c === colSpan) {
                rArr = rArr.slice(u - colSpan, u);
                break;
            }
        }
        return rArr ? rArr : Array.from({ length: columnHeights.length }, (v, k) => k);
    }

    for (i = 0; i < this.children.length; i++) {

        let block = this.children[i];
        let colSpan = Math.min(block.width || 1, this.COLUMNS),
            colIndices = getNextColumnIndices(colSpan),
            minTop = Math.max.apply(Math, colIndices.map(i => columnHeights[i])),
            left = colIndices[0] * columnWidth + "px",
            top = minTop + "px";

        if (!block.container.parentNode) {
            block.container.style.left = left;
            block.container.style.top = top;
            block.container.style.width = columnWidth * colSpan + "px";
            this.container.appendChild(block.container);
        } else {
            if (block.container.style.left !== left)
                block.container.style.left = left;
            if (block.container.style.top !== top)
                block.container.style.top = top;
            if (block.container.style.width !== columnWidth + "px")
                block.container.style.width = columnWidth * colSpan + "px";
        }

        colIndices.forEach(index => {
            columnHeights[index] = minTop + block.container.offsetHeight;
        });

        // Adding/updating of nodes may cause scrollbar to appear. This changes the width of the
        // container. To prevent inset containers from flowing we need to recalculate sizes as
        // soon as we noticed size change. This won't take a lot of resources as not many cards
        // needed to trigger scrollbar appear.
        if (this.width !== this.container.offsetWidth) {
            this.updateSizes();
            return;
        }

    }

    this.container.style.height = columnHeights.reduce((a, b) => Math.max(a, b)) + "px";

    // Yet another check required in case the height of the block is reduced and scrollbar
    // disappears.
    if (this.width !== this.container.offsetWidth) {
        this.updateSizes();
    }

};

AutoGrid.prototype.updateSizes = function () {

    if (this.width === this.container.offsetWidth) return;

    this.width = this.container.offsetWidth;
    this.COLUMNS = getColumnsNumber(this.width);

    this.updateGrid();

};<|endoftext|>


<commit_before>import '/resources/polymer/@polymer/polymer/polymer-legacy.js';

import '/resources/components/postal-lib.js';

import { random } from '/resources/reflection/tg-numeric-utils.js';

export const TgSseBehavior = {

    properties: {

        /**
         * Event source class that is used to identify what process is sending the server event.
         */
        eventSourceClass: {
            type: String
        },

        /**
         * The identifier of sse job that uses the same eventSourceClass (for example file upload process).
         */
        jobUid: {
            type: String
        },

        /* A function that takes a single String arugment representing the push event data. */
        dataHandler: {
            type: Function
        },

        /* An optional function to react to SSE errors. Accepts error event as an argument. */
        errorHandler: {
            type: Function
        },

        /**postal subcription on sse message event */
        _messageSubscription: Object,

        /**postal subscription on sse error event */
        _errorSubscription: Object,

        /* A timer ID to delay reactions to SSE events in case a delay was requested. */
        _timerIdForDataHandling: {
            type: Number,
            value: null
        },

        /* Indicates the need to schedule dataHandler execution based on 'minDelay' and 'delay' properties of event data. */
        useTimerBasedScheduling: {
            type: Boolean,
            value: true
        }

    },

    observers: ['_sseAttributesChanged(eventSourceClass, jobUid)'],

    _sseAttributesChanged: function (eventSourceClass, jobUid) {
        this.unsubscribeFromSseEvents();
        if (eventSourceClass) {
            this.subscribeToSseEvent();
        }
    },

    attached: function () {
        if (this.eventSourceClass && !this._messageSubscription && !this._errorSubscription) {
            this.subscribeToSseEvent();
        }
    },

    detached: function () {
        this.unsubscribeFromSseEvents();
    },

    subscribeToSseEvent: function () {
        if (this._messageSubscription) {
            throw new Error("Unsubscribe from sse message event first in order to subscribe to the new one");
        }

        if (this._errorSubscription) {
            throw new Error("Unsubscribe from sse error event first in order to subscribe to the new one");
        }

        this._messageSubscription = postal.subscribe({
            channel: "sse-event",
            topic: `${this.eventSourceClass ? "/" + this.eventSourceClass : ""}${this.jobUid ? "/" + this.jobUid : ""}/message`,
            callback: (data, envelope) => {
                const msg = data.msg;
                if (this.useTimerBasedScheduling) {
                    // Ensures that if there is a pending data handling request then new requests are ignored
                    if (this._timerIdForDataHandling) {
                        return;
                    }
                    const minDelay = msg.minDelay ? msg.minDelay : 0;
                    const rndDelay = msg.delay ? random(msg.delay) + 1 : 1;
                    console.log("min delay: ", minDelay, " rnd delay: ", rndDelay);
                    this._execDataHandlerWithDelay(msg, minDelay + rndDelay);
                } else {
                    this.dataHandler(msg);
                }
            }
        });

        this._errorSubscription = postal.subscribe({
            channel: "sse-event",
            topic: "error",
            callback: (data, envelope) => {
                // invoke error handler if provided
                if (this.errorHandler) {
                    this.errorHandler(data.event, data.source);
                }
            }
        });
    },

    unsubscribeFromSseEvents: function () {
        this._messageSubscription && this._messageSubscription.unsubscribe();
        this._errorSubscription && this._errorSubscription.unsubscribe();
        delete this._messageSubscription;
        delete this._errorSubscription;
    },

    /** Executes dataHandler with delay. */
    _execDataHandlerWithDelay: function (msg, delay) {
        const self = this;
        self._timerIdForDataHandling = setTimeout(() => {
            try {
                self.dataHandler(msg);
            } finally {
                self._timerIdForDataHandling = null;
            }
        }, delay);
    }

}; // end of behaviour declaration<commit_msg>#1835 Refactored 'unsubscribeFromSseEvents' for clarity.<commit_after>import '/resources/polymer/@polymer/polymer/polymer-legacy.js';

import '/resources/components/postal-lib.js';

import { random } from '/resources/reflection/tg-numeric-utils.js';

export const TgSseBehavior = {

    properties: {

        /**
         * Event source class that is used to identify what process is sending the server event.
         */
        eventSourceClass: {
            type: String
        },

        /**
         * The identifier of sse job that uses the same eventSourceClass (for example file upload process).
         */
        jobUid: {
            type: String
        },

        /* A function that takes a single String arugment representing the push event data. */
        dataHandler: {
            type: Function
        },

        /* An optional function to react to SSE errors. Accepts error event as an argument. */
        errorHandler: {
            type: Function
        },

        /**postal subcription on sse message event */
        _messageSubscription: Object,

        /**postal subscription on sse error event */
        _errorSubscription: Object,

        /* A timer ID to delay reactions to SSE events in case a delay was requested. */
        _timerIdForDataHandling: {
            type: Number,
            value: null
        },

        /* Indicates the need to schedule dataHandler execution based on 'minDelay' and 'delay' properties of event data. */
        useTimerBasedScheduling: {
            type: Boolean,
            value: true
        }

    },

    observers: ['_sseAttributesChanged(eventSourceClass, jobUid)'],

    _sseAttributesChanged: function (eventSourceClass, jobUid) {
        this.unsubscribeFromSseEvents();
        if (eventSourceClass) {
            this.subscribeToSseEvent();
        }
    },

    attached: function () {
        if (this.eventSourceClass && !this._messageSubscription && !this._errorSubscription) {
            this.subscribeToSseEvent();
        }
    },

    detached: function () {
        this.unsubscribeFromSseEvents();
    },

    subscribeToSseEvent: function () {
        if (this._messageSubscription) {
            throw new Error("Unsubscribe from sse message event first in order to subscribe to the new one");
        }

        if (this._errorSubscription) {
            throw new Error("Unsubscribe from sse error event first in order to subscribe to the new one");
        }

        this._messageSubscription = postal.subscribe({
            channel: "sse-event",
            topic: `${this.eventSourceClass ? "/" + this.eventSourceClass : ""}${this.jobUid ? "/" + this.jobUid : ""}/message`,
            callback: (data, envelope) => {
                const msg = data.msg;
                if (this.useTimerBasedScheduling) {
                    // Ensures that if there is a pending data handling request then new requests are ignored
                    if (this._timerIdForDataHandling) {
                        return;
                    }
                    const minDelay = msg.minDelay ? msg.minDelay : 0;
                    const rndDelay = msg.delay ? random(msg.delay) + 1 : 1;
                    console.log("min delay: ", minDelay, " rnd delay: ", rndDelay);
                    this._execDataHandlerWithDelay(msg, minDelay + rndDelay);
                } else {
                    this.dataHandler(msg);
                }
            }
        });

        this._errorSubscription = postal.subscribe({
            channel: "sse-event",
            topic: "error",
            callback: (data, envelope) => {
                // invoke error handler if provided
                if (this.errorHandler) {
                    this.errorHandler(data.event, data.source);
                }
            }
        });
    },

    unsubscribeFromSseEvents: function () {
        if (this._messageSubscription) {
            this._messageSubscription.unsubscribe();
            delete this._messageSubscription;
        }
        if (this._errorSubscription) {
            this._errorSubscription.unsubscribe();
            delete this._errorSubscription;
        }
    },

    /** Executes dataHandler with delay. */
    _execDataHandlerWithDelay: function (msg, delay) {
        const self = this;
        self._timerIdForDataHandling = setTimeout(() => {
            try {
                self.dataHandler(msg);
            } finally {
                self._timerIdForDataHandling = null;
            }
        }, delay);
    }

}; // end of behaviour declaration<|endoftext|>


<commit_before>//Specify files to be included in the simulation
importScripts("simulation.js");
importScripts("simulationtools.js");
importScripts("person.js");
importScripts("hcv.js");
importScripts("lcgrand.js");

var Param={};
var PP=[];
self.onmessage = function (e) {
    lcg.setSeed();//note that this is an extremely important step to allow random numbers to be generated

	var seconds1 = new Date().getTime() / 1000;

	var SimNumber = e.data.SimNumber;
    var SimData = e.data.SimData;//creates a pointer

	IncrementSize=Math.round(SimData.NoPeople/100);//used to deliver progress rates back to the progress bar

	Year=2014.5;
	GenotypeValue=0;
	YearOfBirth=1985.1;
	Age=29;
	Sex=1;
	Alcohol=0;
	YearsToSimulate=40;

	HCVParam={};
	HCVParam.F0F1=0.117;
	HCVParam.F1F2=0.085;
	HCVParam.F2F3=0.12;
	HCVParam.F3F4=0.116;
	HCVParam.F4LF=0.0001;//not real
	HCVParam.F4HCC=0.4;//not real

	console.log("Starting to load Person object");

	for (i=0; i<SimData.NoPeople; i++){
		PP[i]=new PersonObject(YearOfBirth, Sex);
		if (i%IncrementSize==0){
			self.postMessage({ProgressBarValue: i/SimData.NoPeople});
		}
	}

	var seconds2 = new Date().getTime() / 1000;
    TotalTime=seconds2 -seconds1;
	console.log("Memory allocation stopped after "+TotalTime+" seconds");

	console.log("Starting to HCV progression");

	for (i=0; i<SimData.NoPeople; i++){
		PP[i].HCV.Infection(Year, GenotypeValue, Age, Sex, Alcohol, HCVParam );
		if (i%IncrementSize==0){
			self.postMessage({ProgressBarValue: i/SimData.NoPeople});
		}
	}

	//Determine fibrosis levels with year

	FibrosisMatrix=new ZeroMatrix(6, YearsToSimulate+1);

	console.log("Extracting results");
	YearCount=0;
	for (GraphYear=Year; GraphYear<Year+YearsToSimulate+1; GraphYear++){
		for (i=0; i<SimData.NoPeople; i++){
			FibrosisLevel=PP[i].HCV.Fibrosis.Get(GraphYear).Value;
			//self.postMessage({ConsoleMessage: "FibrosisLevel "+ FibrosisLevel+ " YearCount" + YearCount});
			FibrosisMatrix[FibrosisLevel][YearCount]=FibrosisMatrix[FibrosisLevel][YearCount]+1;;
		}
		YearCount++;
		self.postMessage({ProgressBarValue: (YearCount/(YearsToSimulate+1))});
	}

	seconds2 = new Date().getTime() / 1000;
    TotalTime=seconds2 -seconds1;

	console.log("Finished simulation in "+TotalTime+" seconds");
	var SimResult={};
	SimResult.HCVTestResult=FibrosisMatrix;

	//Saving simulation results into local storage

	self.postMessage({SimNumber: e.data.SimNumber, Result: SimResult});//All simulation will end with this line
};
<commit_msg>Leaving a message for future upgrades<commit_after>//Specify files to be included in the simulation
importScripts("simulation.js");
importScripts("simulationtools.js");
importScripts("person.js");
importScripts("hcv.js");
importScripts("lcgrand.js");

var Param={};
var PP=[];
self.onmessage = function (e) {
	//In this section will be a message handler that allows calls
	// Initialise (set data and parameters)
	// Optimise (find unknown parameters)
	// Initialise with optimised data
	// Extrapolate (with current settings)
	// Intervention (with changed settings)
	// Get data
	// Save

    lcg.setSeed();//note that this is an extremely important step to allow random numbers to be generated

	var seconds1 = new Date().getTime() / 1000;

	var SimNumber = e.data.SimNumber;
    var SimData = e.data.SimData;//creates a pointer

	IncrementSize=Math.round(SimData.NoPeople/100);//used to deliver progress rates back to the progress bar

	Year=2014.5;
	GenotypeValue=0;
	YearOfBirth=1985.1;
	Age=29;
	Sex=1;
	Alcohol=0;
	YearsToSimulate=40;

	HCVParam={};
	HCVParam.F0F1=0.117;
	HCVParam.F1F2=0.085;
	HCVParam.F2F3=0.12;
	HCVParam.F3F4=0.116;
	HCVParam.F4LF=0.0001;//not real
	HCVParam.F4HCC=0.4;//not real

	console.log("Starting to load Person object");

	for (i=0; i<SimData.NoPeople; i++){
		PP[i]=new PersonObject(YearOfBirth, Sex);
		if (i%IncrementSize==0){
			self.postMessage({ProgressBarValue: i/SimData.NoPeople});
		}
	}

	var seconds2 = new Date().getTime() / 1000;
    TotalTime=seconds2 -seconds1;
	console.log("Memory allocation stopped after "+TotalTime+" seconds");

	console.log("Starting to HCV progression");

	for (i=0; i<SimData.NoPeople; i++){
		PP[i].HCV.Infection(Year, GenotypeValue, Age, Sex, Alcohol, HCVParam );
		if (i%IncrementSize==0){
			self.postMessage({ProgressBarValue: i/SimData.NoPeople});
		}
	}

	//Determine fibrosis levels with year

	FibrosisMatrix=new ZeroMatrix(6, YearsToSimulate+1);

	console.log("Extracting results");
	YearCount=0;
	for (GraphYear=Year; GraphYear<Year+YearsToSimulate+1; GraphYear++){
		for (i=0; i<SimData.NoPeople; i++){
			FibrosisLevel=PP[i].HCV.Fibrosis.Get(GraphYear).Value;
			//self.postMessage({ConsoleMessage: "FibrosisLevel "+ FibrosisLevel+ " YearCount" + YearCount});
			FibrosisMatrix[FibrosisLevel][YearCount]=FibrosisMatrix[FibrosisLevel][YearCount]+1;;
		}
		YearCount++;
		self.postMessage({ProgressBarValue: (YearCount/(YearsToSimulate+1))});
	}

	seconds2 = new Date().getTime() / 1000;
    TotalTime=seconds2 -seconds1;

	console.log("Finished simulation in "+TotalTime+" seconds");
	var SimResult={};
	SimResult.HCVTestResult=FibrosisMatrix;

	//Saving simulation results into local storage

	self.postMessage({SimNumber: e.data.SimNumber, Result: SimResult});//All simulation will end with this line
};
<|endoftext|>


<commit_before>/**
 * states.js
 * Created by anonymous on 09/12/15 13:11.
 */

(function() {
    'use strict';

    angular
        .module('dashboard')
        .config(dashboardRouter);

    dashboardRouter.$inject = ['$stateProvider', '$urlRouterProvider', 'layoutProvider'];

    /* @ngInject */
    function dashboardRouter($stateProvider, $urlRouterProvider, layoutProvider) {
        $urlRouterProvider.otherwise('/');

        $stateProvider
            .state('dashboard', {
                abstract: true,
                url     : '/dashboard',
                views   : {
                    'layout@'         : {
                        templateUrl : layoutProvider.layout('themes.minimalist'),
                        controller  : 'DashboardController',
                        controllerAs: 'dashboard'
                    },
                    'header@dashboard': {
                        templateUrl : layoutProvider.view('dashboard.header'),
                        controller  : 'DashboardHeaderController',
                        controllerAs: 'header'
                    },
                    'sidenav@dashboard'  : {
                        templateUrl : layoutProvider.view('dashboard.sidenav'),
                        controller  : 'DashboardSidenavController',
                        controllerAs: 'sidenav'
                    },
                    'aside@dashboard' : {
                        templateUrl : layoutProvider.view('dashboard.aside'),
                        controller  : 'DashboardAsideController',
                        controllerAs: 'aside'
                    },
                    'footer@dashboard': {
                        templateUrl : layoutProvider.view('dashboard.footer'),
                        controller  : 'DashboardFooterController',
                        controllerAs: 'footer'
                    },
                    'main@dashboard'  : {}
                }
            })
            .state('dashboard.home', {
                url  : '/',
                data : {pageName: 'Overview'},
                views: {
                    'main@dashboard': {
                        templateUrl : layoutProvider.view('dashboard.home'),
                        controller  : 'DashboardHomeController',
                        controllerAs: 'home'
                    }
                }
            });

    }

})();

<commit_msg>Modified states<commit_after>/**
 * states.js
 * Created by anonymous on 09/12/15 13:11.
 */

(function() {
    'use strict';

    angular
        .module('dashboard')
        .config(dashboardRouter);

    dashboardRouter.$inject = ['$stateProvider', '$urlRouterProvider', 'layoutProvider'];

    /* @ngInject */
    function dashboardRouter($stateProvider, $urlRouterProvider, layoutProvider) {
        $urlRouterProvider.otherwise('/');

        $stateProvider
            .state('dashboard', {
                abstract: true,
                url     : '/dashboard',
                views   : {
                    'layout@'         : {
                        templateUrl : layoutProvider.layout('minimalist.theme'),
                        controller  : 'DashboardController',
                        controllerAs: 'dashboard'
                    },
                    'header@dashboard': {
                        templateUrl : layoutProvider.layout('minimalist.header'),
                        controller  : 'HeaderController',
                        controllerAs: 'header'
                    },
                    'sidenav@dashboard'  : {
                        templateUrl : layoutProvider.layout('minimalist.sidenav'),
                        controller  : 'SidenavController',
                        controllerAs: 'sidenav'
                    },
                    'aside@dashboard' : {
                        templateUrl : layoutProvider.layout('minimalist.aside'),
                        controller  : 'AsideController',
                        controllerAs: 'aside'
                    },
                    'footer@dashboard': {
                        templateUrl : layoutProvider.layout('minimalist.footer'),
                        controller  : 'FooterController',
                        controllerAs: 'footer'
                    },
                    'main@dashboard'  : {}
                }
            })
            .state('dashboard.home', {
                url  : '/',
                data : {pageName: 'Overview'},
                views: {
                    'main@dashboard': {
                        templateUrl : layoutProvider.view('dashboard.home'),
                        controller  : 'DashboardHomeController',
                        controllerAs: 'home'
                    }
                }
            });

    }

})();

<|endoftext|>


<commit_before>/**
 * @license
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
(function() {
  'use strict';

  /**
   * @appliesMixin Gerrit.RepoPluginConfigMixin
   */
  class GrRepoPluginConfig extends Polymer.mixinBehaviors( [
    Gerrit.RepoPluginConfig,
  ], Polymer.GestureEventListeners(
      Polymer.LegacyElementMixin(
          Polymer.Element))) {
    static get is() { return 'gr-repo-plugin-config'; }
    /**
     * Fired when the plugin config changes.
     *
     * @event plugin-config-changed
     */

    static get properties() {
      return {
      /** @type {?} */
        pluginData: Object,
        /** @type {Array} */
        _pluginConfigOptions: {
          type: Array,
          computed: '_computePluginConfigOptions(pluginData.*)',
        },
      };
    }

    _computePluginConfigOptions(dataRecord) {
      if (!dataRecord || !dataRecord.base || !dataRecord.base.config) {
        return [];
      }
      const {config} = dataRecord.base;
      return Object.keys(config).map(_key => ({_key, info: config[_key]}));
    }

    _isArray(type) {
      return type === this.ENTRY_TYPES.ARRAY;
    }

    _isBoolean(type) {
      return type === this.ENTRY_TYPES.BOOLEAN;
    }

    _isList(type) {
      return type === this.ENTRY_TYPES.LIST;
    }

    _isString(type) {
      // Treat numbers like strings for simplicity.
      return type === this.ENTRY_TYPES.STRING ||
          type === this.ENTRY_TYPES.INT ||
          type === this.ENTRY_TYPES.LONG;
    }

    _computeDisabled(editable) {
      return editable === 'false';
    }

    _computeChecked(value) {
      return JSON.parse(value);
    }

    _handleStringChange(e) {
      const el = Polymer.dom(e).localTarget;
      const _key = el.getAttribute('data-option-key');
      const configChangeInfo =
          this._buildConfigChangeInfo(el.value, _key);
      this._handleChange(configChangeInfo);
    }

    _handleListChange(e) {
      const el = Polymer.dom(e).localTarget;
      const _key = el.getAttribute('data-option-key');
      const configChangeInfo =
          this._buildConfigChangeInfo(el.value, _key);
      this._handleChange(configChangeInfo);
    }

    _handleBooleanChange(e) {
      const el = Polymer.dom(e).localTarget;
      const _key = el.getAttribute('data-option-key');
      const configChangeInfo =
          this._buildConfigChangeInfo(JSON.stringify(el.checked), _key);
      this._handleChange(configChangeInfo);
    }

    _buildConfigChangeInfo(value, _key) {
      const info = this.pluginData.config[_key];
      info.value = value;
      return {
        _key,
        info,
        notifyPath: `${_key}.value`,
      };
    }

    _handleArrayChange({detail}) {
      this._handleChange(detail);
    }

    _handleChange({_key, info, notifyPath}) {
      const {name, config} = this.pluginData;

      /** @type {Object} */
      const detail = {
        name,
        config: Object.assign(config, {[_key]: info}, {}),
        notifyPath: `${name}.${notifyPath}`,
      };

      this.dispatchEvent(new CustomEvent(
          this.PLUGIN_CONFIG_CHANGED, {detail, bubbles: true, composed: true}));
    }
  }

  customElements.define(GrRepoPluginConfig.is, GrRepoPluginConfig);
})();
<commit_msg>Fix parse error from repo settings page<commit_after>/**
 * @license
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
(function() {
  'use strict';

  /**
   * @appliesMixin Gerrit.RepoPluginConfigMixin
   */
  class GrRepoPluginConfig extends Polymer.mixinBehaviors( [
    Gerrit.RepoPluginConfig,
  ], Polymer.GestureEventListeners(
      Polymer.LegacyElementMixin(
          Polymer.Element))) {
    static get is() { return 'gr-repo-plugin-config'; }
    /**
     * Fired when the plugin config changes.
     *
     * @event plugin-config-changed
     */

    static get properties() {
      return {
      /** @type {?} */
        pluginData: Object,
        /** @type {Array} */
        _pluginConfigOptions: {
          type: Array,
          computed: '_computePluginConfigOptions(pluginData.*)',
        },
      };
    }

    _computePluginConfigOptions(dataRecord) {
      if (!dataRecord || !dataRecord.base || !dataRecord.base.config) {
        return [];
      }
      const {config} = dataRecord.base;
      return Object.keys(config).map(_key => ({_key, info: config[_key]}));
    }

    _isArray(type) {
      return type === this.ENTRY_TYPES.ARRAY;
    }

    _isBoolean(type) {
      return type === this.ENTRY_TYPES.BOOLEAN;
    }

    _isList(type) {
      return type === this.ENTRY_TYPES.LIST;
    }

    _isString(type) {
      // Treat numbers like strings for simplicity.
      return type === this.ENTRY_TYPES.STRING ||
          type === this.ENTRY_TYPES.INT ||
          type === this.ENTRY_TYPES.LONG;
    }

    _computeDisabled(editable) {
      return editable === 'false';
    }

    /**
     * @param {?boolean} value - fallback to false if undefined
     */
    _computeChecked(value = false) {
      return JSON.parse(value);
    }

    _handleStringChange(e) {
      const el = Polymer.dom(e).localTarget;
      const _key = el.getAttribute('data-option-key');
      const configChangeInfo =
          this._buildConfigChangeInfo(el.value, _key);
      this._handleChange(configChangeInfo);
    }

    _handleListChange(e) {
      const el = Polymer.dom(e).localTarget;
      const _key = el.getAttribute('data-option-key');
      const configChangeInfo =
          this._buildConfigChangeInfo(el.value, _key);
      this._handleChange(configChangeInfo);
    }

    _handleBooleanChange(e) {
      const el = Polymer.dom(e).localTarget;
      const _key = el.getAttribute('data-option-key');
      const configChangeInfo =
          this._buildConfigChangeInfo(JSON.stringify(el.checked), _key);
      this._handleChange(configChangeInfo);
    }

    _buildConfigChangeInfo(value, _key) {
      const info = this.pluginData.config[_key];
      info.value = value;
      return {
        _key,
        info,
        notifyPath: `${_key}.value`,
      };
    }

    _handleArrayChange({detail}) {
      this._handleChange(detail);
    }

    _handleChange({_key, info, notifyPath}) {
      const {name, config} = this.pluginData;

      /** @type {Object} */
      const detail = {
        name,
        config: Object.assign(config, {[_key]: info}, {}),
        notifyPath: `${name}.${notifyPath}`,
      };

      this.dispatchEvent(new CustomEvent(
          this.PLUGIN_CONFIG_CHANGED, {detail, bubbles: true, composed: true}));
    }
  }

  customElements.define(GrRepoPluginConfig.is, GrRepoPluginConfig);
})();
<|endoftext|>


<commit_before>define(['logManager'], function (logManager) {

  var Refresher = function (core, META, app_json) {
    this.core = core;
    this.META = META;
    this.app_json = app_json;
    this.logger = logManager.create('Refresher');
  };

  Refresher.prototype.update = function (node, component, callback) {
    var self = this;
    self.logger.info('update');
    self.deleteChildren(node, function () {
      self.updateComponent(node, component, function () {
        self.updateUPInterfaces(node, component, function () {
          self.updateWirings(node, component, function () {
            self.logger.info('update finished, calling callback');
            callback();
          });
        });
      });
    });
  };

  Refresher.prototype.updateWirings = function (node, component, next) {
    var self = this;
    self.logger.info('updateWirings');
    var wires = self.app_json.components[component].wiring;
    var counter = 0;
    var created = {};
    // if (wires.length > 0 ) wires = [wires[0]];
    if (wires.length < 1) next();
    wires.forEach(function (w) {
      self.findObject(node, component, w.from.component_base, function (fc) {
        self.logger.info('wiring from: ' + w.from.component_base + ' ' + (fc ? 'found' : fc));
        if (!fc) {
          counter++;
          if (counter == wires.length) {
            next();
          }
        } else {
          self.findObject(node, component, w.to.component_base, function (tc) {
            self.logger.info('wiring to: ' + w.to.component_base + ' ' + (tc ? 'found' : tc));
            if (!tc) {
              counter++;
              if (counter == wires.length) {
                next();
              }
            } else {
              self.logger.info('Both objects are found');
              var from_port_component = create_wiring_component(fc, w.from);
              var to_port_component = create_wiring_component(tc, w.to);

              // create wiring
              if (from_port_component && to_port_component) {
                getPort(from_port_component, w.from.interface, function (from_port) {
                  if (!from_port) {
                    counter++;
                    if (counter == wires.length) {
                      next();
                    }
                  }
                  self.logger.info('from port is found');
                  getPort(to_port_component, w.to.interface, function (to_port) {

                    var base_type = self.META.Link_Interface;
                    if (from_port_component == node || to_port_component == node)
                      base_type = self.META.Equate_Interface;

                    var wiring_node = self.core.createNode({
                      base: base_type,
                      parent: node,
                    });
                    self.core.setPointer(wiring_node, 'src', from_port);
                    self.core.setPointer(wiring_node, 'dst', to_port);

                    counter++;
                    if (counter == wires.length) {
                      next();
                    }
                  });
                });
              } else {
                counter++;
                if (counter == wires.length) {
                  next();
                }
              }

              function getPort (object, name, cb) {
                self.logger.info('getPort for');
                self.core.loadChildren(object, function (err, children) {
                  if (err) {
                    self.logger.error(err);
                    return;
                  }
                  self.logger.info('getPort children loaded');
                  for (var i = children.length - 1; i >= 0; i--) {
                    var n = self.core.getAttribute(children[i], 'name');
                    if (n == name) {
                      cb(children[i]);
                      return;
                    }
                  }
                  cb(null);
                });
              }

              function create_wiring_component (mc, port_information) {
                if (mc == node) return node;// self._cache[port_information.interface];
                if (created[port_information.component_base]) {
                  return created[port_information.component_base];
                }
                // Check if the component is a generic type
                if (self.app_json.instance_components[port_information.name]) {
                  var p = port_information.component_base + port_information.name + '_g';
                  if (created[p])
                    return created[p];
                  var new_port_obj_inst = self.core.createNode({
                    base: mc,
                    parent: node
                  });
                  var names = port_information.name.split('.');
                  var n = names[names.length - 1];
                  self.core.setAttribute(new_port_obj_inst, 'name', n);
                  created[port_information.component_base + '_g'] = new_port_obj_inst;
                  return new_port_obj_inst;
                }
                var new_port_obj = self.core.createNode({
                  base: mc,
                  parent: node
                });
                created[port_information.component_base] = new_port_obj;
                return new_port_obj;
              }

              function getWiringInterface(c, c_interface) {
                var c_ids = self.core.getChildrenRelids(c);
                var interface_node = null;
                for (var i = c_ids.length - 1; i >= 0; i--) {
                  var interf_child = self.core.getChild(c, c_ids[i]);
                  var interface_name = self.core.getAttribute(interf_child, 'name');
                  if (interface_name == c_interface) return interf_child;
                }
                return null;
              }

            }
          });
        }

      });
    });
  };

  Refresher.prototype.findObject = function (node, component, path, callback) {
    var self = this;
    self.logger.info('findObject' + ' -> ' + component + ' ' + path);
    if (self.app_json.components[component].file_path == path) {
      callback(node);
      return;
    }

    // First we check if the object is in the same folder with the node
    var parent = self.core.getParent(node);
    self.core.loadChildren(parent, function (err, children) {
      if (err) {
        self.logger.error('findObject > loadChildren for the node\'s siblings');
      } else {
        for (var i = children.length - 1; i >= 0; i--) {
          var nn = self.core.getAttribute(children[i], 'name');
          if (nn + '.nc' == path) {
            callback(children[i]);
            return;
          }
        }
      }
      // Then we try to find the object in its full path
      self.logger.info('findObject > looking for the full path')
      var root = self.core.getRoot(node);
      var paths = getPaths(path);
      if (!paths) {
        self.logger.error('findObject > can\'t resolve the path')
        callback(null);
        return;
      }
      var curr = root;
      findChild(0);

      function findChild(index) {
        if (index >= paths.length) {
          callback(curr);
        } else {
          self.core.loadChildren(curr, function (err, children) {
            if (err) {
              self.logger.error('in findObject > findChild > loadChildren');
              callback(null);
              return;
            }
            var getTheNextChild = false;
            for (var j = children.length - 1; j >= 0; j--) {
              var nn = self.core.getAttribute(children[j], 'name');
              if (nn == paths[index]) {
                curr = children[j];
                getTheNextChild = true;
                break;
              }
            }
            if (!getTheNextChild) {
              self.logger.info('findObject > findChild > no next child');
              callback(null);
              return;
            }
            findChild(index+1);
          });
        }
      }

    });

    function getPaths(path) {
      var paths;
      try {
        paths = path.split('.')[0].split('/');
      } catch (error) {
        return null;
      }
      return paths;
    }
  };

  Refresher.prototype.deleteChildren = function (node, next) {
    var self = this;
    self.logger.info('deleteChildren');
    self.core.loadChildren(node, function (err, children) {
      if (err) {
        throw new Error(err);
      } else {
        for (var i = children.length - 1; i >= 0; i--) {
          self.core.deleteNode(children[i]);
        };
        next();
      }
    });
  };

  Refresher.prototype.updateComponent = function (node, component, next) {
    var self = this;
    self.logger.info('updateComponent');
    var val = self.app_json.components[component].safe;
    self.core.setAttribute(node, 'safe', val);
    next();
  };

  Refresher.prototype.updateUPInterfaces = function (node, component, cb) {
    var self = this;
    self.logger.info('updateUPInterfaces');
    var interfaces = self.app_json.components[component].interface_types;
    var counter = 0;
    var messages = [];
    if (interfaces.length < 1) cb();
    for (var i = interfaces.length - 1; i >= 0; i--) {
      findObject(interfaces[i], function (error, obj, interf) {
        if (error) {
          var m = 'Cannot find the interface object';
          messages.push({m: error});
        } else {
          var base = self.META.Uses_Interface;
          if (interf.provided === 1)
            base = self.META.Provides_Interface;
          var int_node = self.core.createNode({
            base: base,
            parent: node
          });
          self.core.setAttribute(int_node, 'name', interf.as);
          self.core.setPointer(int_node, 'interface', obj);
          if (interf.argument_type) {
            self.core.setAttribute(int_node, 'type_arguments', interf.argument_type);
          }
        }
        counter++;
        if (counter==interfaces.length) {
          cb();
        }
      });
    }
    function findObject(interf, callback) {
      try {
        var name = interf.name;
        var interdef = self.app_json.interfacedefs[name];
        var fp = interdef.file_path;
        var root = self.core.getRoot(node);
        var paths = fp.split('.')[0].split('/');
        var curr = root;
        findChild(0);
        function findChild(index) {
          if (index >= paths.length) {
            callback(null, curr, interf);
          } else {
            self.core.loadChildren(curr, function (err, children) {
              if (err) {
                callback(err, null, interf);
                return;
              }
              for (var j = children.length - 1; j >= 0; j--) {
                var nn = self.core.getAttribute(children[j], 'name');
                if (nn == paths[index]) {
                  curr = children[j];
                  break;
                }
              }
              findChild(index+1);
            });
          }
        }
      } catch(error) {
        callback(error, null, interf);
      }

    }
  };

  return Refresher;

});
<commit_msg>Fix a bug. Update src_params & dst_params<commit_after>define(['logManager'], function (logManager) {

  var Refresher = function (core, META, app_json) {
    this.core = core;
    this.META = META;
    this.app_json = app_json;
    this.logger = logManager.create('Refresher');
  };

  Refresher.prototype.update = function (node, component, callback) {
    var self = this;
    self.logger.info('update');
    self.deleteChildren(node, function () {
      self.updateComponent(node, component, function () {
        self.updateUPInterfaces(node, component, function () {
          self.updateWirings(node, component, function () {
            self.logger.info('update finished, calling callback');
            callback();
          });
        });
      });
    });
  };

  Refresher.prototype.updateWirings = function (node, component, next) {
    var self = this;
    self.logger.info('updateWirings');
    var wires = self.app_json.components[component].wiring;
    var counter = 0;
    var created = {};
    // if (wires.length > 0 ) wires = [wires[0]];
    if (wires.length < 1) next();
    wires.forEach(function (w) {
      self.findObject(node, component, w.from.component_base, function (fc) {
        self.logger.info('wiring from: ' + w.from.component_base + ' ' + (fc ? 'found' : fc) + ' ' + w.from.interface);
        if (!fc) {
          counter++;
          if (counter == wires.length) {
            next();
          }
        } else {
          self.findObject(node, component, w.to.component_base, function (tc) {
            self.logger.info('wiring to: ' + w.to.component_base + ' ' + (tc ? 'found' : tc) + ' ' + w.to.interface);
            if (!tc) {
              counter++;
              if (counter == wires.length) {
                next();
              }
            } else {
              self.logger.info('Both objects are found');
              var from_port_component = create_wiring_component(fc, w.from);
              var to_port_component = create_wiring_component(tc, w.to);

              // create wiring
              if (from_port_component && to_port_component) {
                getPort(from_port_component, w.from.interface, function (from_port) {
                  if (!from_port) {
                    counter++;
                    if (counter == wires.length) {
                      next();
                    }
                  }
                  self.logger.info('from port is found');
                  getPort(to_port_component, w.to.interface, function (to_port) {

                    var base_type = self.META.Link_Interface;
                    if (from_port_component == node || to_port_component == node)
                      base_type = self.META.Equate_Interface;

                    var wiring_node = self.core.createNode({
                      base: base_type,
                      parent: node,
                    });
                    self.core.setPointer(wiring_node, 'src', from_port);
                    self.core.setPointer(wiring_node, 'dst', to_port);
                    if (w.from.cst !== null) {
                      self.core.setAttribute(wiring_node, 'src_params', w.from.cst);
                    }
                    if (w.to.cst !== null) {
                      self.core.setAttribute(wiring_node, 'dst_params', w.to.cst);
                    }

                    counter++;
                    if (counter == wires.length) {
                      next();
                    }
                  });
                });
              } else {
                counter++;
                if (counter == wires.length) {
                  next();
                }
              }

              function getPort (object, name, cb) {
                self.logger.info('getPort for');
                self.core.loadChildren(object, function (err, children) {
                  if (err) {
                    self.logger.error(err);
                    return;
                  }
                  self.logger.info('getPort children loaded');
                  for (var i = children.length - 1; i >= 0; i--) {
                    var n = self.core.getAttribute(children[i], 'name');
                    if (n == name) {
                      cb(children[i]);
                      return;
                    }
                  }
                  cb(null);
                });
              }

              function create_wiring_component (mc, port_information) {
                if (mc == node) return node;// self._cache[port_information.interface];
                if (created[port_information.component_base]) {
                  return created[port_information.component_base];
                }
                // Check if the component is a generic type
                if (self.app_json.instance_components[port_information.name]) {
                  var p = port_information.component_base + port_information.name + '_g';
                  if (created[p])
                    return created[p];
                  var new_port_obj_inst = self.core.createNode({
                    base: mc,
                    parent: node
                  });
                  var names = port_information.name.split('.');
                  var n = names[names.length - 1];
                  self.core.setAttribute(new_port_obj_inst, 'name', n);
                  created[p] = new_port_obj_inst;
                  return new_port_obj_inst;
                }
                var new_port_obj = self.core.createNode({
                  base: mc,
                  parent: node
                });
                created[port_information.component_base] = new_port_obj;
                return new_port_obj;
              }

              function getWiringInterface(c, c_interface) {
                var c_ids = self.core.getChildrenRelids(c);
                var interface_node = null;
                for (var i = c_ids.length - 1; i >= 0; i--) {
                  var interf_child = self.core.getChild(c, c_ids[i]);
                  var interface_name = self.core.getAttribute(interf_child, 'name');
                  if (interface_name == c_interface) return interf_child;
                }
                return null;
              }

            }
          });
        }

      });
    });
  };

  Refresher.prototype.findObject = function (node, component, path, callback) {
    var self = this;
    self.logger.info('findObject' + ' -> ' + component + ' ' + path);
    if (self.app_json.components[component].file_path == path) {
      callback(node);
      return;
    }

    // First we check if the object is in the same folder with the node
    var parent = self.core.getParent(node);
    self.core.loadChildren(parent, function (err, children) {
      if (err) {
        self.logger.error('findObject > loadChildren for the node\'s siblings');
      } else {
        for (var i = children.length - 1; i >= 0; i--) {
          var nn = self.core.getAttribute(children[i], 'name');
          if (nn + '.nc' == path) {
            callback(children[i]);
            return;
          }
        }
      }
      // Then we try to find the object in its full path
      self.logger.info('findObject > looking for the full path')
      var root = self.core.getRoot(node);
      var paths = getPaths(path);
      if (!paths) {
        self.logger.error('findObject > can\'t resolve the path')
        callback(null);
        return;
      }
      var curr = root;
      findChild(0);

      function findChild(index) {
        if (index >= paths.length) {
          callback(curr);
        } else {
          self.core.loadChildren(curr, function (err, children) {
            if (err) {
              self.logger.error('in findObject > findChild > loadChildren');
              callback(null);
              return;
            }
            var getTheNextChild = false;
            for (var j = children.length - 1; j >= 0; j--) {
              var nn = self.core.getAttribute(children[j], 'name');
              if (nn == paths[index]) {
                curr = children[j];
                getTheNextChild = true;
                break;
              }
            }
            if (!getTheNextChild) {
              self.logger.info('findObject > findChild > no next child');
              callback(null);
              return;
            }
            findChild(index+1);
          });
        }
      }

    });

    function getPaths(path) {
      var paths;
      try {
        paths = path.split('.')[0].split('/');
      } catch (error) {
        return null;
      }
      return paths;
    }
  };

  Refresher.prototype.deleteChildren = function (node, next) {
    var self = this;
    self.logger.info('deleteChildren');
    self.core.loadChildren(node, function (err, children) {
      if (err) {
        throw new Error(err);
      } else {
        for (var i = children.length - 1; i >= 0; i--) {
          self.core.deleteNode(children[i]);
        };
        next();
      }
    });
  };

  Refresher.prototype.updateComponent = function (node, component, next) {
    var self = this;
    self.logger.info('updateComponent');
    var val = self.app_json.components[component].safe;
    self.core.setAttribute(node, 'safe', val);
    next();
  };

  Refresher.prototype.updateUPInterfaces = function (node, component, cb) {
    var self = this;
    self.logger.info('updateUPInterfaces');
    var interfaces = self.app_json.components[component].interface_types;
    var counter = 0;
    var messages = [];
    if (interfaces.length < 1) cb();
    for (var i = interfaces.length - 1; i >= 0; i--) {
      findObject(interfaces[i], function (error, obj, interf) {
        if (error) {
          var m = 'Cannot find the interface object';
          messages.push({m: error});
        } else {
          var base = self.META.Uses_Interface;
          if (interf.provided === 1)
            base = self.META.Provides_Interface;
          var int_node = self.core.createNode({
            base: base,
            parent: node
          });
          self.core.setAttribute(int_node, 'name', interf.as);
          self.core.setPointer(int_node, 'interface', obj);
          if (interf.argument_type) {
            self.core.setAttribute(int_node, 'type_arguments', interf.argument_type);
          }
        }
        counter++;
        if (counter==interfaces.length) {
          cb();
        }
      });
    }
    function findObject(interf, callback) {
      try {
        var name = interf.name;
        var interdef = self.app_json.interfacedefs[name];
        var fp = interdef.file_path;
        var root = self.core.getRoot(node);
        var paths = fp.split('.')[0].split('/');
        var curr = root;
        findChild(0);
        function findChild(index) {
          if (index >= paths.length) {
            callback(null, curr, interf);
          } else {
            self.core.loadChildren(curr, function (err, children) {
              if (err) {
                callback(err, null, interf);
                return;
              }
              for (var j = children.length - 1; j >= 0; j--) {
                var nn = self.core.getAttribute(children[j], 'name');
                if (nn == paths[index]) {
                  curr = children[j];
                  break;
                }
              }
              findChild(index+1);
            });
          }
        }
      } catch(error) {
        callback(error, null, interf);
      }

    }
  };

  return Refresher;

});
<|endoftext|>