<commit_before>/*
* @class
*/
OpenLayers.Util=new Object();

/**
* @class This class represents a screen coordinate, in x and y coordinates
*/
OpenLayers.Pixel = Class.create();
OpenLayers.Pixel.prototype = {

    /** @type float */
    x: 0.0,

    /** @type float */
    y: 0.0,

    /**
    * @constructor
    *
    * @param {float} x
    * @param {float} y
    */
    initialize: function(x, y) {
        this.x = x;
        this.y = y;
    },

    /**
    * @return string representation of Pixel. ex: "x=200.4,y=242.2"
    * @type str
    */
    toString:function() {
        return ("x=" + this.x + ",y=" + this.y);
    },

    /**
    * @type OpenLayers.Pixel
    */
    copyOf:function() {
        return new OpenLayers.Pixel(this.x, this.y);
    },

    /**
    * @param {OpenLayers.Pixel} px
    *
    * @return a Pixel object with the difference between the two pixels
    * @type OpenLayers.Pixel
    */
    diff:function(px) {
        return new OpenLayers.Pixel(this.x - px.x, this.y - px.y);
    },

    /**
    * @param {OpenLayers.Pixel} px
    *
    * @return a Pixel object with the absolute difference between the two pixels
    * @type OpenLayers.Pixel
    */
    diffABS:function(px) {
        return new OpenLayers.Pixel(Math.abs(this.x - px.x),
                                    Math.abs(this.y - px.y));
    },

    /**
    * @param {OpenLayers.Pixel} px
    *
    * @return whether or not the point passed in as parameter is equal to this
    * @type bool
    */
    equal:function(px) {
        var d = this.diff(px);
        return ((d.x == 0) && (d.y == 0));
    },

    /**
    * @param {int} x
    * @param {int} y
    *
    * @return a new Pixel with this pixel's x&y augmented by the int values passed in.
    * @type OpenLayers.Pixel
    */
    add:function(x, y) {
        return new OpenLayers.Pixel(this.x + x, this.y + y);
    },

    /** @type str */
    CLASS_NAME: "OpenLayers.Pixel"
};

OpenLayers.Size = Class.create();
OpenLayers.Size.prototype = {
    initialize: function(w,h) {
        this.w=w;
        this.h=h;
    },
    toString:function(){
        return ("w="+this.w+",h="+this.h);
    },
    copyOf:function(){
        return new OpenLayers.Size(this.w, this.h);
    },
    sameSize:function(pt){
        return (this.w==pt.w && this.h==pt.h);
    }
};

OpenLayers.LatLon = Class.create();
OpenLayers.LatLon.prototype = {
    initialize: function(lat,lon) {
        this.lat=lat;
        this.lon=lon;
    },
    toString:function(){
        return ("lat="+this.lat+",lon="+this.lon);
    },
    copyOf:function(){
        return new OpenLayers.LatLon(this.lat, this.lon);
    },
    toShortString:function(){
        return (this.lat+", "+this.lon);
    },
    diff:function(pt){          // subtract pt from this
        return new OpenLayers.LatLon(this.lat - pt.lat,this.lon - pt.lon);
    },
    samePT:function(pt){
        return (this.lat==pt.lat && this.lon==pt.lon);
    }
};
OpenLayers.LatLon.fromString=function(str){
    var pairs=str.split(",");
    return new OpenLayers.LatLon(pairs[1],pairs[0]);
};
OpenLayers.Bounds = Class.create();
OpenLayers.Bounds.prototype = {
    initialize: function(minlat,minlon,maxlat,maxlon){
        this.minlat=minlat;
        this.minlon=minlon;
        this.maxlat=maxlat;
        this.maxlon=maxlon;
        this.width = Math.abs(this.maxlon - this.minlon);
        this.height = Math.abs(this.maxlat - this.minlat);
    },
    toString:function(){
        return ("Min lat/lon=" + this.minlat +"/"+ this.minlon
                + " Max lat/lon=" + this.maxlat +"/"+ this.maxlon
                + " width:" + this.width + " height:" + this.height);
    },
    copyOf:function(){
        return new OpenLayers.Bounds(this.minlat, this.minlon,
                                    this.maxlat, this.maxlon);
    },
    toBBOX:function(){
        return (this.minlon+","+this.minlat+","+this.maxlon+","+this.maxlat);
    },
    contains:function(pt){
        return (pt.lon >=this.minlon && pt.lon <=this.maxlon
            && pt.lat >=this.minlat && pt.lat <= this.maxlat)
    }

};
/** Create bounds from coordinates in a string:-180.000000,-90.000000 180.000000,90.000000
*/
OpenLayers.Bounds.fromString=function(str){
    var pairs=str.split(" ");
    var min=pairs[0];
    var max=pairs[1];

    var latlon = min.split(",");
    var latlon2 = max.split(",");
    return new OpenLayers.Bounds(latlon[1],latlon[0],latlon2[1],latlon2[0]);
};

OpenLayers.Box = Class.create();
OpenLayers.Box.prototype = {
    initialize: function(x,y,w,h){
        this.xy=new OpenLayers.Pixel(x,y);
        this.sz=new OpenLayers.Size(w,h);
        this.c = new OpenLayers.Pixel(x+(w/2), y+(h/2));
        this.br = new OpenLayers.Pixel(x+w-1,y+h-1);
    },

    /* offset box by df
    * @df(OpenLayers.Size)
    */
    offset:function(df){
        this.xy=new OpenLayers.Pixel(this.xy.x+df.w,this.xy.y+df.h);
        this.c = new OpenLayers.Pixel(this.xy.x+(this.sz.w/2), this.xy.y+(this.sz.h/2));
        var x=this.xy.x;
        var y=this.xy.y;
        var w=this.sz.w;
        var h=this.sz.h;
        this.br = new OpenLayers.Pixel(x+w-1,y+h-1);
    },

    getOrigin:function(){return this.xy;},
    getSize:function(){return this.sz;},
    getCenter:function(){return this.c;},
    getBotRight:function(){return this.br;},
    getWidth:function(){return this.sz.w;},
    getHeight:function(){return this.sz.h;},
    getSize:function(){return this.sz;},

    toString:function(){
        return (this.xy.toString() + " " + this.sz.toString());
    },
    copyOf:function(){
        return new OpenLayers.Box(this.xy.x, this.xy.y, this.sz.w, this.sz.h);
    },
    toCoordsString:function(){
        var x1 = this.xy.x;
        var x2 = this.xy.x+this.sz.w-1;
        var y1 = this.xy.y;
        var y2 = this.xy.y+this.sz.h-1;
        return (x1+","+y1+","+x2+","+y2);
    },
    contains:function(pt){
        var returnVal = false;

        var lx=this.xy.x;
        var ly=this.xy.y;
        var rx=lx+this.sz.w-1;
        var ry=ly+this.sz.h-1;

        if (pt != null) {
            //upper left in
            returnVal =  (pt.x >=lx && pt.x <=rx && pt.y >=ly && pt.y <= ry);
        }
        return returnVal;
    },

    /**
    * @param {ol.Box} box
    * @param {bool} partial - if true, returns whether any part of the passed
    *                         in box is within the calling box. otherwise box
    *                         must contain entire box to return true.
    *
    * @return {bool}
    */
    containsBox:function(box, partial) {
        var contains = false;

        var mainTop = this.xy.y;
        var mainLeft = this.xy.x;
        var mainBottom = this.xy.y + this.sz.h;
        var mainRight = this.xy.x + this.sz.w;

        var top = box.xy.y;
        var left = box.xy.x;
        var bottom = box.xy.y + box.sz.h;
        var right = box.xy.x + box.sz.w;

        var inTop = (top >= mainTop) && (top <= mainBottom);
        var inLeft = (left >= mainLeft) && (left <= mainRight);
        var inBottom = (bottom >= mainTop) && (bottom <= mainBottom);
        var inRight= (right >= mainLeft) && (right <= mainRight);

        if (partial) {
            contains = (inTop || inBottom) && (inLeft || inRight );
        } else {
            contains = (inTop && inLeft && inBottom && inRight);
        }

        return contains;
    },

    // is this point the center of the box, +-2 pixels (@todo fix that number!)
    isCenter:function(pt){
        var size = this.c.absDiff(pt);
        return (size.w <= 2 && size.h <= 2);
    }
};

// Some other helpful things
String.prototype.startsWith = function(sStart){
    return (this.substr(0,sStart.length)==sStart);
};
String.prototype.trim = function() {
    var b=0,e=this.length -1;
    while(this.substr(b,1) == " ") {b++;}
    while(this.substr(e,1) == " ") {e--;}
    return this.substring(b,e+1);
};
Array.prototype.remove = function(rem) {
    for(var i=0; i<this.length; i++) {
        if(this[i]==rem) {
            this.splice(i,1);
			//break;more than once??
        }
    }
    return this;
}
Array.prototype.copy = function() {
  var copy = new Array();
  for (var i = 0; i < this.length; i++) {
      copy[i] = this[i];
  }
  return copy;
};

Array.prototype.prepend = function(the_item) {
    this.splice(0,0,the_item);
};
Array.prototype.append=function(the_item){
    this[this.length]=the_item;
};
Array.prototype.clear=function() {this.length=0;};

/** Create a child element (a div currently) that
* is a proper child of the supplied parent, is invisible,
* positioned as requested within the parent, etc
*
* zIndex is NOT set
*
* @param {str} id - HTML ID of new element, if empty something is made up
* @param {OpenLayers.Pixel} pt - x,y point if missing 0,0 is used
* @param {OpenLayers.Size} sz - size else size of parent is used
* @param {str} overflow - behavior of clipped/overflow content
* @param {str} img - background image url
* @param {str} position - relative or absolute?
*
* @return {DOM}
*/
OpenLayers.Util.createDiv = function(id, pt, sz, overflow, img, position) {
    var x,y,w,h;

    if (pt){
        x = pt.x;
        y = pt.y;
    } else {
        x = y = 0;
    }

    if (!position){
        position = "absolute";
    }

    if (!id){
        id = "OpenLayersDiv" + (Math.random()*10000%10000);
    }

    var dom = document.createElement('div');
    dom.id = id;
    if (overflow){
        dom.style.overflow = overflow;
    }
    if (sz) {
        dom.style.width = sz.w+"px";
        dom.style.height = sz.h+"px";
    }
    dom.style.position = position;
    dom.style.top = y;
    dom.style.left = x;
    dom.style.padding = "0";
    dom.style.margin = "0";
    dom.style.cursor = "inherit";

    if (img){
        dom.style.backgroundImage = 'url(' + img + ')';
    }

    return dom;
};

OpenLayers.Util.ImageHTML=function(img,sz,alt){
    return "<img src='" + img + "' padding='0' border='0' alt='" + alt + "' width=" + sz.w + "px height=" + sz.h + "px/>";
};

/**
* @param {str} img - src URL
* @param {OpenLayers.Size} sz
* @param {OpenLayers.Pixel} xy
* @param {str} position
* @param {str} id
* @param {int} border
*/
OpenLayers.Util.createImage = function(img, sz, xy, position, id, border) {
    image = document.createElement("img");
    if (id) {
        image.id = id;
        image.style.alt = id;
    }
    if (xy) {
        image.style.left = xy.x;
        image.style.top = xy.y;
    }
    if (sz) {
        image.style.width = sz.w;
        image.style.height = sz.h;
    }
    if (position) {
        image.style.position = position;
    } else {
        image.style.position = "relative";
    }
    if (border) {
        image.style.border = border + "px solid";
    } else {
        image.style.border = 0;
    }
    image.style.cursor = "inherit";
    image.src = img;
    return image;
};

/** returns a concatenation of the properties of an object in
*    http parameter notation. ex:
*
*    "key1=value1&key2=value2&key3=value3"
*
* @param {Object} params
*
* @return {str}
*/
OpenLayers.getParameterString = function(params) {
    paramsArray = new Array();

    for (var key in params) {
        var value = params[key];
        //skip functions
        if (typeof value == 'function') continue;

        paramsArray.push(key + "=" + value);
    }

    return paramsArray.join("&");
};

OpenLayers.Util.getImagesLocation = function () {
    return "img/";
};
<commit_msg>JSDOC / coding standards for Util.Size<commit_after>/*
* @class
*/
OpenLayers.Util=new Object();

/**
* @class This class represents a screen coordinate, in x and y coordinates
*/
OpenLayers.Pixel = Class.create();
OpenLayers.Pixel.prototype = {

    /** @type float */
    x: 0.0,

    /** @type float */
    y: 0.0,

    /**
    * @constructor
    *
    * @param {float} x
    * @param {float} y
    */
    initialize: function(x, y) {
        this.x = x;
        this.y = y;
    },

    /**
    * @return string representation of Pixel. ex: "x=200.4,y=242.2"
    * @type str
    */
    toString:function() {
        return ("x=" + this.x + ",y=" + this.y);
    },

    /**
    * @type OpenLayers.Pixel
    */
    copyOf:function() {
        return new OpenLayers.Pixel(this.x, this.y);
    },

    /**
    * @param {OpenLayers.Pixel} px
    *
    * @return a Pixel object with the difference between the two pixels
    * @type OpenLayers.Pixel
    */
    diff:function(px) {
        return new OpenLayers.Pixel(this.x - px.x, this.y - px.y);
    },

    /**
    * @param {OpenLayers.Pixel} px
    *
    * @return a Pixel object with the absolute difference between the two pixels
    * @type OpenLayers.Pixel
    */
    diffABS:function(px) {
        return new OpenLayers.Pixel(Math.abs(this.x - px.x),
                                    Math.abs(this.y - px.y));
    },

    /**
    * @param {OpenLayers.Pixel} px
    *
    * @return whether or not the point passed in as parameter is equal to this
    * @type bool
    */
    equal:function(px) {
        var d = this.diff(px);
        return ((d.x == 0) && (d.y == 0));
    },

    /**
    * @param {int} x
    * @param {int} y
    *
    * @return a new Pixel with this pixel's x&y augmented by the int values passed in.
    * @type OpenLayers.Pixel
    */
    add:function(x, y) {
        return new OpenLayers.Pixel(this.x + x, this.y + y);
    },

    /** @type str */
    CLASS_NAME: "OpenLayers.Pixel"
};

/**
* @class This class represents a width and height pair
*/
OpenLayers.Size = Class.create();
OpenLayers.Size.prototype = {

    /** @type float */
    w: 0.0,

    /** @type float */
    h: 0.0,

    /**
    * @param {float} w
    * @param {float} h
    */
    initialize: function(w, h) {
        this.w = w;
        this.h = h;
    },

    /**
    * @return String representation of OpenLayers.Size object. (ex. "w=55,h=66")
    * @type String
    */
    toString:function() {
        return ("w="+this.w+",h="+this.h);
    },

    /**
    * @return New OpenLayers.Size object with the same w and h values
    * @type OpenLayers.Size
    */
    copyOf:function() {
        return new OpenLayers.Size(this.w, this.h);
    },

    /**
    * @param {OpenLayers.Size} sz
    * @returns Boolean value indicating whether the passed-in OpenLayers.Size
    *          object has the same w and h components as this
    *
    * @type bool
    */
    equals:function(sz) {
        return ((this.w == sz.w) && /this.h == sz.h));
    }

    /** @type String */
    CLASS_NAME: "OpenLayers.Size"
};

OpenLayers.LatLon = Class.create();
OpenLayers.LatLon.prototype = {
    initialize: function(lat,lon) {
        this.lat=lat;
        this.lon=lon;
    },
    toString:function(){
        return ("lat="+this.lat+",lon="+this.lon);
    },
    copyOf:function(){
        return new OpenLayers.LatLon(this.lat, this.lon);
    },
    toShortString:function(){
        return (this.lat+", "+this.lon);
    },
    diff:function(pt){          // subtract pt from this
        return new OpenLayers.LatLon(this.lat - pt.lat,this.lon - pt.lon);
    },
    samePT:function(pt){
        return (this.lat==pt.lat && this.lon==pt.lon);
    }
};
OpenLayers.LatLon.fromString=function(str){
    var pairs=str.split(",");
    return new OpenLayers.LatLon(pairs[1],pairs[0]);
};
OpenLayers.Bounds = Class.create();
OpenLayers.Bounds.prototype = {
    initialize: function(minlat,minlon,maxlat,maxlon){
        this.minlat=minlat;
        this.minlon=minlon;
        this.maxlat=maxlat;
        this.maxlon=maxlon;
        this.width = Math.abs(this.maxlon - this.minlon);
        this.height = Math.abs(this.maxlat - this.minlat);
    },
    toString:function(){
        return ("Min lat/lon=" + this.minlat +"/"+ this.minlon
                + " Max lat/lon=" + this.maxlat +"/"+ this.maxlon
                + " width:" + this.width + " height:" + this.height);
    },
    copyOf:function(){
        return new OpenLayers.Bounds(this.minlat, this.minlon,
                                    this.maxlat, this.maxlon);
    },
    toBBOX:function(){
        return (this.minlon+","+this.minlat+","+this.maxlon+","+this.maxlat);
    },
    contains:function(pt){
        return (pt.lon >=this.minlon && pt.lon <=this.maxlon
            && pt.lat >=this.minlat && pt.lat <= this.maxlat)
    }

};
/** Create bounds from coordinates in a string:-180.000000,-90.000000 180.000000,90.000000
*/
OpenLayers.Bounds.fromString=function(str){
    var pairs=str.split(" ");
    var min=pairs[0];
    var max=pairs[1];

    var latlon = min.split(",");
    var latlon2 = max.split(",");
    return new OpenLayers.Bounds(latlon[1],latlon[0],latlon2[1],latlon2[0]);
};

OpenLayers.Box = Class.create();
OpenLayers.Box.prototype = {
    initialize: function(x,y,w,h){
        this.xy=new OpenLayers.Pixel(x,y);
        this.sz=new OpenLayers.Size(w,h);
        this.c = new OpenLayers.Pixel(x+(w/2), y+(h/2));
        this.br = new OpenLayers.Pixel(x+w-1,y+h-1);
    },

    /* offset box by df
    * @df(OpenLayers.Size)
    */
    offset:function(df){
        this.xy=new OpenLayers.Pixel(this.xy.x+df.w,this.xy.y+df.h);
        this.c = new OpenLayers.Pixel(this.xy.x+(this.sz.w/2), this.xy.y+(this.sz.h/2));
        var x=this.xy.x;
        var y=this.xy.y;
        var w=this.sz.w;
        var h=this.sz.h;
        this.br = new OpenLayers.Pixel(x+w-1,y+h-1);
    },

    getOrigin:function(){return this.xy;},
    getSize:function(){return this.sz;},
    getCenter:function(){return this.c;},
    getBotRight:function(){return this.br;},
    getWidth:function(){return this.sz.w;},
    getHeight:function(){return this.sz.h;},
    getSize:function(){return this.sz;},

    toString:function(){
        return (this.xy.toString() + " " + this.sz.toString());
    },
    copyOf:function(){
        return new OpenLayers.Box(this.xy.x, this.xy.y, this.sz.w, this.sz.h);
    },
    toCoordsString:function(){
        var x1 = this.xy.x;
        var x2 = this.xy.x+this.sz.w-1;
        var y1 = this.xy.y;
        var y2 = this.xy.y+this.sz.h-1;
        return (x1+","+y1+","+x2+","+y2);
    },
    contains:function(pt){
        var returnVal = false;

        var lx=this.xy.x;
        var ly=this.xy.y;
        var rx=lx+this.sz.w-1;
        var ry=ly+this.sz.h-1;

        if (pt != null) {
            //upper left in
            returnVal =  (pt.x >=lx && pt.x <=rx && pt.y >=ly && pt.y <= ry);
        }
        return returnVal;
    },

    /**
    * @param {ol.Box} box
    * @param {bool} partial - if true, returns whether any part of the passed
    *                         in box is within the calling box. otherwise box
    *                         must contain entire box to return true.
    *
    * @return {bool}
    */
    containsBox:function(box, partial) {
        var contains = false;

        var mainTop = this.xy.y;
        var mainLeft = this.xy.x;
        var mainBottom = this.xy.y + this.sz.h;
        var mainRight = this.xy.x + this.sz.w;

        var top = box.xy.y;
        var left = box.xy.x;
        var bottom = box.xy.y + box.sz.h;
        var right = box.xy.x + box.sz.w;

        var inTop = (top >= mainTop) && (top <= mainBottom);
        var inLeft = (left >= mainLeft) && (left <= mainRight);
        var inBottom = (bottom >= mainTop) && (bottom <= mainBottom);
        var inRight= (right >= mainLeft) && (right <= mainRight);

        if (partial) {
            contains = (inTop || inBottom) && (inLeft || inRight );
        } else {
            contains = (inTop && inLeft && inBottom && inRight);
        }

        return contains;
    },

    // is this point the center of the box, +-2 pixels (@todo fix that number!)
    isCenter:function(pt){
        var size = this.c.absDiff(pt);
        return (size.w <= 2 && size.h <= 2);
    }
};

// Some other helpful things
String.prototype.startsWith = function(sStart){
    return (this.substr(0,sStart.length)==sStart);
};
String.prototype.trim = function() {
    var b=0,e=this.length -1;
    while(this.substr(b,1) == " ") {b++;}
    while(this.substr(e,1) == " ") {e--;}
    return this.substring(b,e+1);
};
Array.prototype.remove = function(rem) {
    for(var i=0; i<this.length; i++) {
        if(this[i]==rem) {
            this.splice(i,1);
			//break;more than once??
        }
    }
    return this;
}
Array.prototype.copy = function() {
  var copy = new Array();
  for (var i = 0; i < this.length; i++) {
      copy[i] = this[i];
  }
  return copy;
};

Array.prototype.prepend = function(the_item) {
    this.splice(0,0,the_item);
};
Array.prototype.append=function(the_item){
    this[this.length]=the_item;
};
Array.prototype.clear=function() {this.length=0;};

/** Create a child element (a div currently) that
* is a proper child of the supplied parent, is invisible,
* positioned as requested within the parent, etc
*
* zIndex is NOT set
*
* @param {str} id - HTML ID of new element, if empty something is made up
* @param {OpenLayers.Pixel} pt - x,y point if missing 0,0 is used
* @param {OpenLayers.Size} sz - size else size of parent is used
* @param {str} overflow - behavior of clipped/overflow content
* @param {str} img - background image url
* @param {str} position - relative or absolute?
*
* @return {DOM}
*/
OpenLayers.Util.createDiv = function(id, pt, sz, overflow, img, position) {
    var x,y,w,h;

    if (pt){
        x = pt.x;
        y = pt.y;
    } else {
        x = y = 0;
    }

    if (!position){
        position = "absolute";
    }

    if (!id){
        id = "OpenLayersDiv" + (Math.random()*10000%10000);
    }

    var dom = document.createElement('div');
    dom.id = id;
    if (overflow){
        dom.style.overflow = overflow;
    }
    if (sz) {
        dom.style.width = sz.w+"px";
        dom.style.height = sz.h+"px";
    }
    dom.style.position = position;
    dom.style.top = y;
    dom.style.left = x;
    dom.style.padding = "0";
    dom.style.margin = "0";
    dom.style.cursor = "inherit";

    if (img){
        dom.style.backgroundImage = 'url(' + img + ')';
    }

    return dom;
};

OpenLayers.Util.ImageHTML=function(img,sz,alt){
    return "<img src='" + img + "' padding='0' border='0' alt='" + alt + "' width=" + sz.w + "px height=" + sz.h + "px/>";
};

/**
* @param {str} img - src URL
* @param {OpenLayers.Size} sz
* @param {OpenLayers.Pixel} xy
* @param {str} position
* @param {str} id
* @param {int} border
*/
OpenLayers.Util.createImage = function(img, sz, xy, position, id, border) {
    image = document.createElement("img");
    if (id) {
        image.id = id;
        image.style.alt = id;
    }
    if (xy) {
        image.style.left = xy.x;
        image.style.top = xy.y;
    }
    if (sz) {
        image.style.width = sz.w;
        image.style.height = sz.h;
    }
    if (position) {
        image.style.position = position;
    } else {
        image.style.position = "relative";
    }
    if (border) {
        image.style.border = border + "px solid";
    } else {
        image.style.border = 0;
    }
    image.style.cursor = "inherit";
    image.src = img;
    return image;
};

/** returns a concatenation of the properties of an object in
*    http parameter notation. ex:
*
*    "key1=value1&key2=value2&key3=value3"
*
* @param {Object} params
*
* @return {str}
*/
OpenLayers.getParameterString = function(params) {
    paramsArray = new Array();

    for (var key in params) {
        var value = params[key];
        //skip functions
        if (typeof value == 'function') continue;

        paramsArray.push(key + "=" + value);
    }

    return paramsArray.join("&");
};

OpenLayers.Util.getImagesLocation = function () {
    return "img/";
};
<|endoftext|>


<commit_before>'use strict';

const WorldstateObject = require('./WorldstateObject.js');
/**
 * Represents a persistent enemy
 * @extends {WorldstateObject}
 */
class PersistentEnemy extends WorldstateObject {
  /**
   * @param   {Object}             data            The persistent enemy data
   * @param   {Object}             deps            The dependencies object
   * @param   {MarkdownSettings}   deps.mdConfig   The markdown settings
   * @param   {Translator}         deps.translator The string translator
   */
  constructor(data, { mdConfig, translator, timeDate }) {
    super(data);

    /**
     * The markdown settings
     * @type {MarkdownSettings}
     * @private
     */
    this.mdConfig = mdConfig;
    Object.defineProperty(this, 'mdConfig', { enumerable: false, configurable: false });

    /**
     * The enemy's type
     * @type {string}
     */
    this.agentType = translator.languageString(data.AgentType);

    /**
     * The location tag
     * @type {string}
     */
    this.locationTag = translator.languageString(data.LocTag);

    /**
     * The enemy's rank
     * @type {number}
     */
    this.rank = data.Rank;

    /**
     * The enemy's remainaing health percentage
     * @type {number}
     */
    this.healthPercent = data.HealthPercent;

    /**
     * The percentual damage that the enemy takes when it's defeated
     * @type {number}
     */
    this.fleeDamage = data.FleeDamage;

    /**
     * The region where the enemy is located
     * @type {string}
     */
    this.region = translator.region(data.Region);

    /**
     * The last time the enemy was discovered
     * @type {Date}
     */
    this.lastDiscoveredTime = timeDate.parseDate(data.LastDiscoveredTime);

    /**
     * The node at which the enemy was last discovered
     * @type {string}
     */
    this.lastDiscoveredAt = translator.node(data.LastDiscoveredLocation);

    /**
     * Whether or not the enemy is currently available
     * @type {Boolean}
     */
    this.isDiscovered = data.Discovered;

    /**
     * Whether or not the enemy is using ticketing
     * @type {Boolean}
     */
    this.isUsingTicketing = data.UseTicketing;
  }

  /**
   * Returns a string representation of the persistent enemy
   * @returns {string}
   */
  toString() {
    const status = this.isDiscovered ? 'discovered' : 'not discovered';
    const lines = [
      `${this.agentType} last discovered at ${this.lastDiscoveredAt}.`,
      `It has ${this.healthPercent}% health remaining and is currently ${status}`,
    ];

    return lines.join(this.mdConfig.lineEnd);
  }
}

module.exports = PersistentEnemy;
<commit_msg>add fake id for easier discovery tracking<commit_after>'use strict';

const WorldstateObject = require('./WorldstateObject.js');
/**
 * Represents a persistent enemy
 * @extends {WorldstateObject}
 */
class PersistentEnemy extends WorldstateObject {
  /**
   * @param   {Object}             data            The persistent enemy data
   * @param   {Object}             deps            The dependencies object
   * @param   {MarkdownSettings}   deps.mdConfig   The markdown settings
   * @param   {Translator}         deps.translator The string translator
   */
  constructor(data, { mdConfig, translator, timeDate }) {
    super(data);

    /**
     * The markdown settings
     * @type {MarkdownSettings}
     * @private
     */
    this.mdConfig = mdConfig;
    Object.defineProperty(this, 'mdConfig', { enumerable: false, configurable: false });

    /**
     * The enemy's type
     * @type {string}
     */
    this.agentType = translator.languageString(data.AgentType);

    /**
     * The location tag
     * @type {string}
     */
    this.locationTag = translator.languageString(data.LocTag);

    /**
     * The enemy's rank
     * @type {number}
     */
    this.rank = data.Rank;

    /**
     * The enemy's remainaing health percentage
     * @type {number}
     */
    this.healthPercent = data.HealthPercent;

    /**
     * The percentual damage that the enemy takes when it's defeated
     * @type {number}
     */
    this.fleeDamage = data.FleeDamage;

    /**
     * The region where the enemy is located
     * @type {string}
     */
    this.region = translator.region(data.Region);

    /**
     * The last time the enemy was discovered
     * @type {Date}
     */
    this.lastDiscoveredTime = timeDate.parseDate(data.LastDiscoveredTime);

    /**
     * The node at which the enemy was last discovered
     * @type {string}
     */
    this.lastDiscoveredAt = translator.node(data.LastDiscoveredLocation);

    /**
     * Whether or not the enemy is currently available
     * @type {Boolean}
     */
    this.isDiscovered = data.Discovered;

    /**
     * Whether or not the enemy is using ticketing
     * @type {Boolean}
     */
    this.isUsingTicketing = data.UseTicketing;

    /**
     * Fake ID incorporating discovery
     * @type {string}
     */
    this.pid = `${this.id}${this.isDiscovered}`;
  }

  /**
   * Returns a string representation of the persistent enemy
   * @returns {string}
   */
  toString() {
    const status = this.isDiscovered ? 'discovered' : 'not discovered';
    const lines = [
      `${this.agentType} last discovered at ${this.lastDiscoveredAt}.`,
      `It has ${this.healthPercent}% health remaining and is currently ${status}`,
    ];

    return lines.join(this.mdConfig.lineEnd);
  }
}

module.exports = PersistentEnemy;
<|endoftext|>


<commit_before>describe("Console", function() {
  it ("should fail", function() {
    expect(false).toBeFalsy();
  });

  it ("should succeed", function() {
    expect(true).toBeTruthy();
  });

  it ("$.ajax exists", function() {
    expect(!!$.ajax).toBeTruthy();
  });

  it ("jQuery.ajax exists", function() {
    expect(!!jQuery.ajax).toBeTruthy();
  });

});<commit_msg>adding/adjusting tests.<commit_after>describe("Console", function() {
  it ("should fail", function() {
    expect(false).toBeFalsy();
  });

  it ("should succeed", function() {
    expect(true).toBeTruthy();
  });

  it ("jQuery exists", function() {
    expect(!!jQuery).toBeTruthy();
  });

});<|endoftext|>


<commit_before>var _ = require('lodash');
var on_client = require('on-client');
var ObsRouter = require('obs-router');
var scrollTo = require('../util/scrollTo');
var toggleTransitions = require('../util/toggleTransitions');
var cancellableNextTick = require('../util/cancellableNextTick');

var initialise = function(self, options, Super){
	// throw error if missing expected viewmodel data from server
	if (on_client && self.use_data_script){
		_.forEach(['_site_vm_data', '_page_vm_data'], function(str){
			var type = typeof window[str];
			if (type != 'object'){
				throw new Error('Expected to find "window.' + str + '" object. Instead found ' + type + '. \r\n' +
				'Be sure to include {{{data_script}}} in your document template before the script that initialises ' +
				'your ractive-isomorphic website.')
			}
		});
	}

	// expose pages
	self.pages = _.clone(options.pages || self.pages || {});
	// we set self.pages already; dont override it with the Super call
	delete options.pages;

	// collect routes from pages
	var routes = {};
	_.forIn(self.pages, function(Page, page_name){
		routes[page_name] = Page.prototype.url;
	});

	// create & expose router
	self.router = new ObsRouter({
		url: options.url,
		routes: routes
	});
	delete options.url;

	// abort early if on server and no matching route
	if (!on_client && !self.router.route){return;}

	// expose api
	//self.api = _.clone(options.api || self.api || {});
	//delete options.api;

	// add pages to components
	options.components = _.clone(options.components || {});
	_.forEach(self.pages, function(Page, page_name){
		options.components['rx-'+page_name] = Page;
	});

	// build 'content' partial exposing page components
	options.partials = _.assign({}, options.partials || {}, {
		content: _.map(self.pages, function(Page, page_name){
			return '{{#route=="'+page_name+'"}}<rx-'+page_name+' route="'+page_name+'" params="{{params}}" />{{/}}';
		}).join('')
	});

	// disable transitions
	toggleTransitions(false);

	// call super constructor
	Super.call(self, options);

	// throw error if no page mounted
	if (!self.page){throw new Error('No page was mounted. Did you forget to include {{>content}} somewhere in your body template?');}

	// throw error if user didnt call super method
	self._assertMethodsCalled();
	self.page._assertMethodsCalled();

	var true_ready = false;
	var delayed_ready = false;
	var cancelReady = null;
	var setReady = function(ready){
		true_ready = ready;
		if (cancelReady){
			cancelReady();
			cancelReady = null;
		}
		if (delayed_ready != ready){
			cancelReady = cancellableNextTick(function(){
				delayed_ready = ready;
				cancelReady = null;
				self.fire(delayed_ready?'ready':'waiting');
			});
		}
	};
	var trackRouteExecution = function(){
		var promises = [];
		if (self._promise){
			promises.push(self._promise);
			delete self._promise;
		}
		if (self.page._promise) {
			promises.push(self.page._promise);
			delete self.page._promise;
		}
		setReady(false);
		var always = function(){
			if ((self.get('route')==self.router.route) && (self.get('params')==self.router.params)){
				setReady(true);
			} else {
				executeRoute();
			}
		};
		Promise.all(promises).then(function(){
			always();
		}, function(error){
			console.error(error);
			always();
		});
	};
	var executeRoute = function(){
		if (!on_client){
			throw new Error('Something is terribly wrong... executeRoute() should not be called server-side.')
		}
		var page_changed = self.router.route != self.get('route');
		// by setting 'params', self._promise and/or/nor self.page._promise will be set
		self.set({
			title: self.constructor.prototype.data.title,
			'status-code': self.constructor.prototype.data['status-code'],
			route: self.router.route,
			params: self.router.params
		});
		if (page_changed){
			self.page._assertMethodsCalled();
		}
		trackRouteExecution();
	};

	// track initial route execution
	trackRouteExecution();

	// clean-up on teardown
	self.on('teardown', function(){
		var self = this;
		self.router.destroy();
		self.destroyed = true;
	});

	if (on_client){
		// track route changes
		self.router.on('route', function(route, params, old_route, old_params){
			if (true_ready){
				executeRoute();
			}
		});
		// enable transitions on client ('complete' event fires only on client anyway)
		self.on('complete', function(){
			toggleTransitions(true);
		});
		// bind vm title to browser title
		self.observe('title', function(title){
			window.document.title = title;
		});
		// handle internal link clicks
		var super_onclick = window.document.onclick;
		window.document.onclick = function(event){
			if ((event.srcElement.tagName.toLowerCase() == 'a')
				&& (event.srcElement.origin == window.document.location.origin)
				&& (self.router.fromUrl(event.srcElement.pathname + event.srcElement.search) != null)){
				self.router.pushUrl(event.srcElement.pathname + event.srcElement.search);
				scrollTo(window.document.body, 0, 400);
				event.preventDefault();
			} else if (typeof super_onclick=='function'){
				super_onclick.apply(this, arguments);
			}
		};
	} else {
		// [nce ready] set data_script for passing vm data from server to client
		if (self.use_data_script){
			self.once('ready', function(){
				var main_vm_data = getFilteredVmData(self);
				var page_vm_data = getFilteredVmData(self.page);
				var data_script = '';
				self.set('data_script', data_script);
			});
		}
	}
};

function getFilteredVmData(vm){
	var data = _.clone(vm.get(''));
	delete data.route;
	delete data.params;
	_.forEach(_.keys(data), function(key){
		if ( (typeof data[key]=='function') || (_.isEqual(vm.constructor.prototype.data[key], data[key])) ){
			delete data[key];
		}
	});
	return data;
}

module.exports = initialise;<commit_msg>handle indirect link clicks; add .ri-pages .ri-page.{{page/route name}} divs<commit_after>var _ = require('lodash');
var on_client = require('on-client');
var ObsRouter = require('obs-router');
var scrollTo = require('../util/scrollTo');
var toggleTransitions = require('../util/toggleTransitions');
var cancellableNextTick = require('../util/cancellableNextTick');

var initialise = function(self, options, Super){
	// throw error if missing expected viewmodel data from server
	if (on_client && self.use_data_script){
		_.forEach(['_site_vm_data', '_page_vm_data'], function(str){
			var type = typeof window[str];
			if (type != 'object'){
				throw new Error('Expected to find "window.' + str + '" object. Instead found ' + type + '. \r\n' +
				'Be sure to include {{{data_script}}} in your document template before the script that initialises ' +
				'your ractive-isomorphic website.')
			}
		});
	}

	// expose pages
	self.pages = _.clone(options.pages || self.pages || {});
	// we set self.pages already; dont override it with the Super call
	delete options.pages;

	// collect routes from pages
	var routes = {};
	_.forIn(self.pages, function(Page, page_name){
		routes[page_name] = Page.prototype.url;
	});

	// create & expose router
	self.router = new ObsRouter({
		url: options.url,
		routes: routes
	});
	delete options.url;

	// abort early if on server and no matching route
	if (!on_client && !self.router.route){return;}

	// expose api
	//self.api = _.clone(options.api || self.api || {});
	//delete options.api;

	// add pages to components
	options.components = _.clone(options.components || {});
	_.forEach(self.pages, function(Page, page_name){
		options.components['rx-'+page_name] = Page;
	});

	// build 'content' partial exposing page components
	options.partials = _.assign({}, options.partials || {}, {
		content: '
' + _.map(self.pages, function(Page, page_name){
			return '{{#route=="' + page_name + '"}}'
				+ '
'
				+ '<rx-'+page_name+' route="'+page_name+'" params="{{params}}" />'
				+ '
' +
				'{{/}}';
		}).join('') + '
'
	});

	// disable transitions
	toggleTransitions(false);

	// call super constructor
	Super.call(self, options);

	// throw error if no page mounted
	if (!self.page){throw new Error('No page was mounted. Did you forget to include {{>content}} somewhere in your body template?');}

	// throw error if user didnt call super method
	self._assertMethodsCalled();
	self.page._assertMethodsCalled();

	var true_ready = false;
	var delayed_ready = false;
	var cancelReady = null;
	var setReady = function(ready){
		true_ready = ready;
		if (cancelReady){
			cancelReady();
			cancelReady = null;
		}
		if (delayed_ready != ready){
			cancelReady = cancellableNextTick(function(){
				delayed_ready = ready;
				cancelReady = null;
				self.fire(delayed_ready?'ready':'waiting');
			});
		}
	};
	var trackRouteExecution = function(){
		var promises = [];
		if (self._promise){
			promises.push(self._promise);
			delete self._promise;
		}
		if (self.page._promise) {
			promises.push(self.page._promise);
			delete self.page._promise;
		}
		setReady(false);
		var always = function(){
			if ((self.get('route')==self.router.route) && (self.get('params')==self.router.params)){
				setReady(true);
			} else {
				executeRoute();
			}
		};
		Promise.all(promises).then(function(){
			always();
		}, function(error){
			console.error(error);
			always();
		});
	};
	var executeRoute = function(){
		if (!on_client){
			throw new Error('Something is terribly wrong... executeRoute() should not be called server-side.')
		}
		var page_changed = self.router.route != self.get('route');
		// by setting 'params', self._promise and/or/nor self.page._promise will be set
		self.set({
			title: self.constructor.prototype.data.title,
			'status-code': self.constructor.prototype.data['status-code'],
			route: self.router.route,
			params: self.router.params
		});
		if (page_changed){
			self.page._assertMethodsCalled();
		}
		trackRouteExecution();
	};

	// track initial route execution
	trackRouteExecution();

	// clean-up on teardown
	self.on('teardown', function(){
		var self = this;
		self.router.destroy();
		self.destroyed = true;
	});

	if (on_client){
		// track route changes
		self.router.on('route', function(route, params, old_route, old_params){
			if (true_ready){
				executeRoute();
			}
		});
		// enable transitions on client ('complete' event fires only on client anyway)
		self.on('complete', function(){
			toggleTransitions(true);
		});
		// bind vm title to browser title
		self.observe('title', function(title){
			window.document.title = title;
		});
		// handle internal link clicks
		var super_onclick = window.document.onclick;
		window.document.onclick = function(event){
			var link = getClosestVerticalLink(event.srcElement, 5);
			if (link && (link.origin == window.document.location.origin)
				&& (self.router.fromUrl(link.pathname + link.search) != null)){
				self.router.pushUrl(link.pathname + link.search);
				scrollTo(window.document.body, 0, 400);
				event.preventDefault();
			} else if (typeof super_onclick=='function'){
				super_onclick.apply(this, arguments);
			}
		};
	} else {
		// [nce ready] set data_script for passing vm data from server to client
		if (self.use_data_script){
			self.once('ready', function(){
				var main_vm_data = getFilteredVmData(self);
				var page_vm_data = getFilteredVmData(self.page);
				var data_script = '';
				self.set('data_script', data_script);
			});
		}
	}
};

function getFilteredVmData(vm){
	var data = _.clone(vm.get(''));
	delete data.route;
	delete data.params;
	_.forEach(_.keys(data), function(key){
		if ( (typeof data[key]=='function') || (_.isEqual(vm.constructor.prototype.data[key], data[key])) ){
			delete data[key];
		}
	});
	return data;
}

var isLink = function(el){return (typeof el=='object') && (el.tagName.toLowerCase() == 'a')};
var getClosestVerticalLink = function(element, deep){
	return isLink(element) && element
		|| element.parentElement && getClosestVerticalLink(element.parentElement, deep - 1);
};

module.exports = initialise;<|endoftext|>


<commit_before>const Native			= require("./Native");
const EventEmitter		= require('events').EventEmitter;
const SemanticSDP		= require("semantic-sdp");
const IncomingStreamTrack	= require("./IncomingStreamTrack");
const OutgoingStreamTrack	= require("./OutgoingStreamTrack");
const TrackInfo			= SemanticSDP.TrackInfo;

/**
 * Represent the connection between a local udp port and a remote one. It sends and/or receive plain RTP data.
 */
class StreamerSession
{
	/**
	 * @ignore
	 * @hideconstructor
	 * private constructor
	 */
	constructor(media,params)
	{
		this.session = new Native.RTPSessionFacade(media.getType().toLowerCase()==="audio" ? 0 : 1);

		//Set local params
		if (params && params.local && params.local.port)
			//Set it
			this.session.SetLocalPort(parseInt(params.local.port));

		//Set remote params
		if (params && params.remote && params.remote.ip && params.remote.port)
			//Set them
			this.session.SetRemotePort(params.remote.ip,params.remote.port);

		//Create new native properties object
		let properties = new Native.PropertiesFacade();

		//If we have got audio
		if (media)
		{
			let num = 0;
			//For each codec
			for (let codec of media.getCodecs().values())
			{
				//Item
				let item = "codecs."+num;
				//Put codec
				properties.SetProperty(item+".codec",codec.getCodec());
				properties.SetProperty(item+".pt",codec.getType());
				//If it has rtx
				if (codec.rtx)
					//Set rtx
					properties.SetProperty(item+".rtx",codec.getRTX());
				//one more
				num++;
			}
			//Set length
			properties.SetProperty("codecs.length", num);
		}

		//Init session
		this.session.Init(properties);

		//Create incoming and outgoing tracks
		this.incoming = new IncomingStreamTrack(media.getType(), media.getType() ,Native.SessionToReceiver(this.session), {'':this.session.GetIncomingSourceGroup()});
		this.outgoing = new OutgoingStreamTrack(media.getType(), media.getType(), Native.SessionToSender(this.session), this.session.GetOutgoingSourceGroup());

		//Stop listeners
		this.incoming.once("stopped",()=>{
			this.incoming = null;
		});
		this.outgoing.once("stopped",()=>{
			this.outgoing = null;
		});

		//Create event emitter
		this.emitter = new EventEmitter();
	}

	/**
	 * Returns the incoming stream track associated with this streaming session
	 * @returns {IncomingStreamTrack}
	 */
	getIncomingStreamTrack()
	{
		return this.incoming;
	}

	/**
	 * Returns the outgoing stream track associated with this streaming session
	 * @returns {OutgoingStreamTrack}
	 */
	getOutgoingStreamTrack()
	{
		return this.outgoing;
	}

	/**
	 * Add event listener
	 * @param {String} event	- Event name
	 * @param {function} listener	- Event listener
	 * @returns {StreamerSession}
	 */
	on()
	{
		//Delegate event listeners to event emitter
		this.emitter.on.apply(this.emitter, arguments);
		//Return object so it can be chained
		return this;
	}

	/**
	 * Add event listener once
	 * @param {String} event	- Event name
	 * @param {function} listener	- Event listener
	 * @returns {IncomingStream}
	 */
	once()
	{
		//Delegate event listeners to event emitter
		this.emitter.once.apply(this.emitter, arguments);
		//Return object so it can be chained
		return this;
	}

	/**
	 * Remove event listener
	 * @param {String} event	- Event name
	 * @param {function} listener	- Event listener
	 * @returns {StreamerSession}
	 */
	off()
	{
		//Delegate event listeners to event emitter
		this.emitter.removeListener.apply(this.emitter, arguments);
		//Return object so it can be chained
		return this;
	}

	/**
	 * Closes udp socket and frees resources
	 */
	stop()
	{
		//Don't call it twice
		if (!this.session) return;

		//Stop tracks
		this.incoming && this.incoming.stop();
		this.outgoing && this.outgoing.stop();

		//End
		this.session.End();

		/**
		* StreamerSession stopped event
		*
		* @name stopped
		* @memberof StreamerSession
		* @kind event
		* @argument {StreamerSession} session
		*/
		this.emitter.emit("stopped",this);

		//Remove transport reference, so destructor is called on GC
		this.session = null;
	}

}

module.exports = StreamerSession;<commit_msg>add getLocalPort<commit_after>const Native			= require("./Native");
const EventEmitter		= require('events').EventEmitter;
const SemanticSDP		= require("semantic-sdp");
const IncomingStreamTrack	= require("./IncomingStreamTrack");
const OutgoingStreamTrack	= require("./OutgoingStreamTrack");
const TrackInfo			= SemanticSDP.TrackInfo;

/**
 * Represent the connection between a local udp port and a remote one. It sends and/or receive plain RTP data.
 */
class StreamerSession
{
	/**
	 * @ignore
	 * @hideconstructor
	 * private constructor
	 */
	constructor(media,params)
	{
		this.session = new Native.RTPSessionFacade(media.getType().toLowerCase()==="audio" ? 0 : 1);

		//Set local params
		if (params && params.local && params.local.port)
			//Set it
			this.session.SetLocalPort(parseInt(params.local.port));

		//Set remote params
		if (params && params.remote && params.remote.ip && params.remote.port)
			//Set them
			this.session.SetRemotePort(params.remote.ip,params.remote.port);

		//Create new native properties object
		let properties = new Native.PropertiesFacade();

		//If we have got audio
		if (media)
		{
			let num = 0;
			//For each codec
			for (let codec of media.getCodecs().values())
			{
				//Item
				let item = "codecs."+num;
				//Put codec
				properties.SetProperty(item+".codec",codec.getCodec());
				properties.SetProperty(item+".pt",codec.getType());
				//If it has rtx
				if (codec.rtx)
					//Set rtx
					properties.SetProperty(item+".rtx",codec.getRTX());
				//one more
				num++;
			}
			//Set length
			properties.SetProperty("codecs.length", num);
		}

		//Init session
		this.session.Init(properties);

		//Create incoming and outgoing tracks
		this.incoming = new IncomingStreamTrack(media.getType(), media.getType() ,Native.SessionToReceiver(this.session), {'':this.session.GetIncomingSourceGroup()});
		this.outgoing = new OutgoingStreamTrack(media.getType(), media.getType(), Native.SessionToSender(this.session), this.session.GetOutgoingSourceGroup());

		//Stop listeners
		this.incoming.once("stopped",()=>{
			this.incoming = null;
		});
		this.outgoing.once("stopped",()=>{
			this.outgoing = null;
		});

		//Create event emitter
		this.emitter = new EventEmitter();
	}

	/**
	 * Get the local rtp/udp port
	 * @returns {Number} port number
	 */
	getLocalPort()
	{
		return this.session.GetLocalPort();
	}

	/**
	 * Returns the incoming stream track associated with this streaming session
	 * @returns {IncomingStreamTrack}
	 */
	getIncomingStreamTrack()
	{
		return this.incoming;
	}

	/**
	 * Returns the outgoing stream track associated with this streaming session
	 * @returns {OutgoingStreamTrack}
	 */
	getOutgoingStreamTrack()
	{
		return this.outgoing;
	}

	/**
	 * Add event listener
	 * @param {String} event	- Event name
	 * @param {function} listener	- Event listener
	 * @returns {StreamerSession}
	 */
	on()
	{
		//Delegate event listeners to event emitter
		this.emitter.on.apply(this.emitter, arguments);
		//Return object so it can be chained
		return this;
	}

	/**
	 * Add event listener once
	 * @param {String} event	- Event name
	 * @param {function} listener	- Event listener
	 * @returns {IncomingStream}
	 */
	once()
	{
		//Delegate event listeners to event emitter
		this.emitter.once.apply(this.emitter, arguments);
		//Return object so it can be chained
		return this;
	}

	/**
	 * Remove event listener
	 * @param {String} event	- Event name
	 * @param {function} listener	- Event listener
	 * @returns {StreamerSession}
	 */
	off()
	{
		//Delegate event listeners to event emitter
		this.emitter.removeListener.apply(this.emitter, arguments);
		//Return object so it can be chained
		return this;
	}

	/**
	 * Closes udp socket and frees resources
	 */
	stop()
	{
		//Don't call it twice
		if (!this.session) return;

		//Stop tracks
		this.incoming && this.incoming.stop();
		this.outgoing && this.outgoing.stop();

		//End
		this.session.End();

		/**
		* StreamerSession stopped event
		*
		* @name stopped
		* @memberof StreamerSession
		* @kind event
		* @argument {StreamerSession} session
		*/
		this.emitter.emit("stopped",this);

		//Remove transport reference, so destructor is called on GC
		this.session = null;
	}

}

module.exports = StreamerSession;
<|endoftext|>


<commit_before>import React, { useEffect, useState } from 'react';
import { c } from 'ttag';
import { SubTitle, Block, Alert, Loader, useFilters, useApiWithoutResult, useEventManager } from 'react-components';
import { arrayMove } from 'react-sortable-hoc';
import { updateFilterOrder } from 'proton-shared/lib/api/filters';

import FilterSortableList from './SortableList';
import ActionsFilterToolbar from './ActionsFilterToolbar';

function FiltersSection() {
    const { call } = useEventManager();
    const [filters, loading] = useFilters();
    const orderRequest = useApiWithoutResult(updateFilterOrder);

    const [list, setFilters] = useState(() => filters || []);

    useEffect(() => {
        if (!Array.isArray(filters)) {
            return;
        }
        setFilters(filters);
    }, [filters]);

    const getScrollContainer = () => document.querySelector('.main-area');
    const onSortEnd = async ({ oldIndex, newIndex }) => {
        try {
            const newList = arrayMove(list, oldIndex, newIndex);
            setFilters(newList);
            await orderRequest.request(newList.map(({ ID }) => ID));
            call();
        } catch (e) {
            setFilters(filters);
        }
    };

    return (
        <>
            <SubTitle>{c('FilterSettings').t`Custom Filters`}</SubTitle>
            <Alert type="info">
                {c('FilterSettings')
                    .t`Add a custom filter to perform actions suche as automatically labeling or archiving messages.`}
            </Alert>

            <Block>
                <ActionsFilterToolbar />
            </Block>

            {loading ? (
                <Loader />
            ) : list.length ? (
                <FilterSortableList getContainer={getScrollContainer} items={list} onSortEnd={onSortEnd} />
            ) : (
                <Alert>{c('FilterSettings').t`No filters available`}</Alert>
            )}
        </>
    );
}

export default FiltersSection;
<commit_msg>typo fixed on /containers/filters/FilterSection.js (#394)<commit_after>import React, { useEffect, useState } from 'react';
import { c } from 'ttag';
import { SubTitle, Block, Alert, Loader, useFilters, useApiWithoutResult, useEventManager } from 'react-components';
import { arrayMove } from 'react-sortable-hoc';
import { updateFilterOrder } from 'proton-shared/lib/api/filters';

import FilterSortableList from './SortableList';
import ActionsFilterToolbar from './ActionsFilterToolbar';

function FiltersSection() {
    const { call } = useEventManager();
    const [filters, loading] = useFilters();
    const orderRequest = useApiWithoutResult(updateFilterOrder);

    const [list, setFilters] = useState(() => filters || []);

    useEffect(() => {
        if (!Array.isArray(filters)) {
            return;
        }
        setFilters(filters);
    }, [filters]);

    const getScrollContainer = () => document.querySelector('.main-area');
    const onSortEnd = async ({ oldIndex, newIndex }) => {
        try {
            const newList = arrayMove(list, oldIndex, newIndex);
            setFilters(newList);
            await orderRequest.request(newList.map(({ ID }) => ID));
            call();
        } catch (e) {
            setFilters(filters);
        }
    };

    return (
        <>
            <SubTitle>{c('FilterSettings').t`Custom Filters`}</SubTitle>
            <Alert type="info">
                {c('FilterSettings')
                    .t`Add a custom filter to perform actions such as automatically labeling or archiving messages.`}
            </Alert>

            <Block>
                <ActionsFilterToolbar />
            </Block>

            {loading ? (
                <Loader />
            ) : list.length ? (
                <FilterSortableList getContainer={getScrollContainer} items={list} onSortEnd={onSortEnd} />
            ) : (
                <Alert>{c('FilterSettings').t`No filters available`}</Alert>
            )}
        </>
    );
}

export default FiltersSection;
<|endoftext|>


<commit_before>import dns from 'dns';

const DNS_SURVIVAL_TIME = 3600000;

export class DNSCache {

  _pool = {};

  static create() {
    return new DNSCache();
  }

  _now() {
    return (new Date()).getTime();
  }

  _lookup(hostname) {
    return new Promise((resolve, reject) => {
      dns.lookup(hostname, function (err, address) {
        if (err) {
          reject(err);
        } else {
          resolve(address);
        }
      });
    });
  }

  _put(hostname, address) {
    const expire = this._now() + DNS_SURVIVAL_TIME;
    this._pool[hostname] = [address, expire];
  }

  async get(hostname) {
    let address = null;
    try {
      if (typeof this._pool[hostname] === 'undefined') {
        address = await this._lookup(hostname);
        this._put(hostname, address);
      } else {
        const [addr, expire] = this._pool[hostname];
        if (this._now() >= expire) {
          delete this._pool[hostname];
        }
        address = addr;
      }
    } catch (err) {
      console.error(err);
      return null;
    }
    return address;
  }

}
<commit_msg>chore(DNSCache): use log4js to log<commit_after>import path from 'path';
import dns from 'dns';
import log4js from 'log4js';
import {Config} from '../Config';

const Logger = log4js.getLogger(path.basename(__filename, '.js'));
const DNS_SURVIVAL_TIME = 3600000;

export class DNSCache {

  _pool = {};

  constructor() {
    Logger.setLevel(Config.log_level);
  }

  static create() {
    return new DNSCache();
  }

  _now() {
    return (new Date()).getTime();
  }

  _lookup(hostname) {
    return new Promise((resolve, reject) => {
      dns.lookup(hostname, function (err, address) {
        if (err) {
          reject(err);
        } else {
          resolve(address);
        }
      });
    });
  }

  _put(hostname, address) {
    const expire = this._now() + DNS_SURVIVAL_TIME;
    this._pool[hostname] = [address, expire];
  }

  async get(hostname) {
    let address = null;
    try {
      if (typeof this._pool[hostname] === 'undefined') {
        address = await this._lookup(hostname);
        this._put(hostname, address);
      } else {
        const [addr, expire] = this._pool[hostname];
        if (this._now() >= expire) {
          delete this._pool[hostname];
        }
        address = addr;
      }
    } catch (err) {
      Logger.error(err);
      return null;
    }
    return address;
  }

}
<|endoftext|>


<commit_before>var ngSelectionProvider = function (grid, $scope, $parse) {
    var self = this;
    self.multi = grid.config.multiSelect;
    self.selectedItems = grid.config.selectedItems;
    self.selectedIndex = grid.config.selectedIndex;
    self.lastClickedRow = undefined;
    self.ignoreSelectedItemChanges = false; // flag to prevent circular event loops keeping single-select var in sync
    self.pKeyParser = $parse(grid.config.primaryKey);
    // function to manage the selection action of a data item (entity)
    self.ChangeSelection = function (rowItem, evt) {
        // ctrl-click + shift-click multi-selections
		// up/down key navigation in multi-selections
		var charCode = evt.which || evt.keyCode;
		var isUpDownKeyPress = (charCode === 40 || charCode === 38);
        if (evt && (!evt.keyCode || isUpDownKeyPress) && !evt.ctrlKey && !evt.shiftKey) {
            self.toggleSelectAll(false, true);
        }
        if (evt && evt.shiftKey && !evt.keyCode && self.multi && grid.config.enableRowSelection) {
            if (self.lastClickedRow) {
                var rowsArr;
                if ($scope.configGroups.length > 0) {
                    rowsArr = grid.rowFactory.parsedData.filter(function(row) {
                        return !row.isAggRow;
                    });
                } else {
                    rowsArr = grid.filteredRows;
                }
                var thisIndx = rowItem.rowIndex;
                var prevIndx = self.lastClickedRow.rowIndex;
                self.lastClickedRow = rowItem;
                if (thisIndx == prevIndx) {
                    return false;
                }
                if (thisIndx < prevIndx) {
                    thisIndx = thisIndx ^ prevIndx;
                    prevIndx = thisIndx ^ prevIndx;
                    thisIndx = thisIndx ^ prevIndx;
					thisIndx--;
                } else {
					prevIndx++;
				}
                var rows = [];
                for (; prevIndx <= thisIndx; prevIndx++) {
                    rows.push(rowsArr[prevIndx]);
                }
                if (rows[rows.length - 1].beforeSelectionChange(rows, evt)) {
                    for (var i = 0; i < rows.length; i++) {
                        var ri = rows[i];
                        var selectionState = ri.selected;
                        ri.selected = !selectionState;
                        if (ri.clone) {
                            ri.clone.selected = ri.selected;
                        }
                        var index = self.selectedItems.indexOf(ri.entity);
                        if (index === -1) {
                            self.selectedItems.push(ri.entity);
                        } else {
                            self.selectedItems.splice(index, 1);
                        }
                    }
                    rows[rows.length - 1].afterSelectionChange(rows, evt);
                }
                return true;
            }
        } else if (!self.multi) {
            if (self.lastClickedRow == rowItem) {
                self.setSelection(self.lastClickedRow, grid.config.keepLastSelected ? true : !rowItem.selected);
            } else {
                if (self.lastClickedRow) {
                    self.setSelection(self.lastClickedRow, false);
                }
                self.setSelection(rowItem, !rowItem.selected);
            }
        } else if (!evt.keyCode || isUpDownKeyPress) {
            self.setSelection(rowItem, !rowItem.selected);
        }
		self.lastClickedRow = rowItem;
        return true;
    };

    self.getSelection = function (entity) {
        var isSelected = false;
        if (grid.config.primaryKey) {
            var val = self.pKeyParser(entity);
            angular.forEach(self.selectedItems, function (c) {
                if (val == self.pkeyParser(c)) {
                    isSelected = true;
                }
            });
        } else {
            isSelected = self.selectedItems.indexOf(entity) !== -1;
        }
        return isSelected;
    };

    // just call this func and hand it the rowItem you want to select (or de-select)
    self.setSelection = function (rowItem, isSelected) {
		if(grid.config.enableRowSelection){
			if (!isSelected) {
				var indx = self.selectedItems.indexOf(rowItem.entity);
				if(indx != -1){
					self.selectedItems.splice(indx, 1);
				}
			} else {
				if (self.selectedItems.indexOf(rowItem.entity) === -1) {
					if(!self.multi && self.selectedItems.length > 0){
						self.toggleSelectAll(false, true);
					}
					self.selectedItems.push(rowItem.entity);
				}
			}
			rowItem.selected = isSelected;
			if (rowItem.orig) {
			    rowItem.orig.selected = isSelected;
			}
			rowItem.afterSelectionChange(rowItem);
		}
    };
    // @return - boolean indicating if all items are selected or not
    // @val - boolean indicating whether to select all/de-select all
    self.toggleSelectAll = function (checkAll, bypass) {
        if (bypass || grid.config.beforeSelectionChange(grid.filteredRows, checkAll)) {
            var selectedlength = self.selectedItems.length;
            if (selectedlength > 0) {
                self.selectedItems.length = 0;
            }
            for (var i = 0; i < grid.filteredRows.length; i++) {
                grid.filteredRows[i].selected = checkAll;
                if (grid.filteredRows[i].clone) {
                    grid.filteredRows[i].clone.selected = checkAll;
                }
                if (checkAll) {
                    self.selectedItems.push(grid.filteredRows[i].entity);
                }
            }
            if (!bypass) {
                grid.config.afterSelectionChange(grid.filteredRows, checkAll);
            }
        }
    };
};<commit_msg>Fixed capitalization of call to pKeyParser (pkeyParser -> pKeyParser)<commit_after>var ngSelectionProvider = function (grid, $scope, $parse) {
    var self = this;
    self.multi = grid.config.multiSelect;
    self.selectedItems = grid.config.selectedItems;
    self.selectedIndex = grid.config.selectedIndex;
    self.lastClickedRow = undefined;
    self.ignoreSelectedItemChanges = false; // flag to prevent circular event loops keeping single-select var in sync
    self.pKeyParser = $parse(grid.config.primaryKey);
    // function to manage the selection action of a data item (entity)
    self.ChangeSelection = function (rowItem, evt) {
        // ctrl-click + shift-click multi-selections
        if (evt && !evt.keyCode && !evt.ctrlKey && !evt.shiftKey) {
            self.toggleSelectAll(false, true);
        }
        if (evt && evt.shiftKey && !evt.keyCode && self.multi && grid.config.enableRowSelection) {
            if (self.lastClickedRow) {
                var rowsArr;
                if ($scope.configGroups.length > 0) {
                    rowsArr = grid.rowFactory.parsedData.filter(function(row) {
                        return !row.isAggRow;
                    });
                } else {
                    rowsArr = grid.filteredRows;
                }
                var thisIndx = rowItem.rowIndex;
                var prevIndx = self.lastClickedRow.rowIndex;
                self.lastClickedRow = rowItem;
                if (thisIndx == prevIndx) {
                    return false;
                }
                if (thisIndx < prevIndx) {
                    thisIndx = thisIndx ^ prevIndx;
                    prevIndx = thisIndx ^ prevIndx;
                    thisIndx = thisIndx ^ prevIndx;
					thisIndx--;
                } else {
					prevIndx++;
				}
                var rows = [];
                for (; prevIndx <= thisIndx; prevIndx++) {
                    rows.push(rowsArr[prevIndx]);
                }
                if (rows[rows.length - 1].beforeSelectionChange(rows, evt)) {
                    for (var i = 0; i < rows.length; i++) {
                        var ri = rows[i];
                        var selectionState = ri.selected;
                        ri.selected = !selectionState;
                        if (ri.clone) {
                            ri.clone.selected = ri.selected;
                        }
                        var index = self.selectedItems.indexOf(ri.entity);
                        if (index === -1) {
                            self.selectedItems.push(ri.entity);
                        } else {
                            self.selectedItems.splice(index, 1);
                        }
                    }
                    rows[rows.length - 1].afterSelectionChange(rows, evt);
                }
                return true;
            }
        } else if (!self.multi) {
            if (self.lastClickedRow == rowItem) {
                self.setSelection(self.lastClickedRow, grid.config.keepLastSelected ? true : !rowItem.selected);
            } else {
                if (self.lastClickedRow) {
                    self.setSelection(self.lastClickedRow, false);
                }
                self.setSelection(rowItem, !rowItem.selected);
            }
        } else if (!evt.keyCode) {
            self.setSelection(rowItem, !rowItem.selected);
        }
		self.lastClickedRow = rowItem;
        return true;
    };

    self.getSelection = function (entity) {
        var isSelected = false;
        if (grid.config.primaryKey) {
            var val = self.pKeyParser(entity);
            angular.forEach(self.selectedItems, function (c) {
                if (val == self.pKeyParser(c)) {
                    isSelected = true;
                }
            });
        } else {
            isSelected = self.selectedItems.indexOf(entity) !== -1;
        }
        return isSelected;
    };

    // just call this func and hand it the rowItem you want to select (or de-select)
    self.setSelection = function (rowItem, isSelected) {
		if(grid.config.enableRowSelection){
		    rowItem.selected = isSelected;
		    if (rowItem.clone) {
		        rowItem.clone.selected = isSelected;
		    }
			if (!isSelected) {
				var indx = self.selectedItems.indexOf(rowItem.entity);
				if(indx != -1){
					self.selectedItems.splice(indx, 1);
				}
			} else {
				if (self.selectedItems.indexOf(rowItem.entity) === -1) {
					if(!self.multi && self.selectedItems.length > 0){
						self.toggleSelectAll(false, true);
						rowItem.selected = isSelected;
						if (rowItem.clone) {
						    rowItem.clone.selected = isSelected;
						}
					}
					self.selectedItems.push(rowItem.entity);
				}
			}
			rowItem.afterSelectionChange(rowItem);
		}
    };
    // @return - boolean indicating if all items are selected or not
    // @val - boolean indicating whether to select all/de-select all
    self.toggleSelectAll = function (checkAll, bypass) {
        if (bypass || grid.config.beforeSelectionChange(grid.filteredRows)) {
            var selectedlength = self.selectedItems.length;
            if (selectedlength > 0) {
                self.selectedItems.length = 0;
            }
            for (var i = 0; i < grid.filteredRows.length; i++) {
                grid.filteredRows[i].selected = checkAll;
                if (grid.filteredRows[i].clone) {
                    grid.filteredRows[i].clone.selected = checkAll;
                }
                if (checkAll) {
                    self.selectedItems.push(grid.filteredRows[i].entity);
                }
            }
            if (!bypass) {
                grid.config.afterSelectionChange(grid.filteredRows);
            }
        }
    };
};<|endoftext|>


<commit_before>var get = Ember.get, set = Ember.set;

var View, view, parentBecameVisible, childBecameVisible, grandchildBecameVisible;
var parentBecameHidden, childBecameHidden, grandchildBecameHidden;

module("Ember.View#isVisible", {
  setup: function() {
    parentBecameVisible=0;
    childBecameVisible=0;
    grandchildBecameVisible=0;
    parentBecameHidden=0;
    childBecameHidden=0;
    grandchildBecameHidden=0;

    View = Ember.ContainerView.extend({
      childViews: ['child'],
      becameVisible: function() { parentBecameVisible++; },
      becameHidden: function() { parentBecameHidden++; },

      child: Ember.ContainerView.extend({
        childViews: ['grandchild'],
        becameVisible: function() { childBecameVisible++; },
        becameHidden: function() { childBecameHidden++; },

        grandchild: Ember.View.extend({
          template: function() { return "seems weird bro"; },
          becameVisible: function() { grandchildBecameVisible++; },
          becameHidden: function() { grandchildBecameHidden++; }
        })
      })
    });
  },

  teardown: function() {
    if (view) {
      Ember.run(function(){ view.destroy(); });
    }
  }
});

test("should hide views when isVisible is false", function() {
  var view = Ember.View.create({
    isVisible: false
  });

  Ember.run(function() {
    view.append();
  });

  ok(view.$().is(':hidden'), "the view is hidden");

  set(view, 'isVisible', true);
  ok(view.$().is(':visible'), "the view is visible");
  view.remove();
});

test("should hide element if isVisible is false before element is created", function() {
  var view = Ember.View.create({
    isVisible: false
  });

  ok(!get(view, 'isVisible'), "precond - view is not visible");

  set(view, 'template', function() { return "foo"; });

  Ember.run(function() {
    view.append();
  });

  ok(view.$().is(':hidden'), "should be hidden");

  view.remove();
  set(view, 'isVisible', true);

  Ember.run(function() {
    view.append();
  });

  ok(view.$().is(':visible'), "view should be visible");

  Ember.run(function() {
    view.remove();
  });
});

test("view should be notified after isVisible is set to false and the element has been hidden", function() {
  var view;
  Ember.run(function(){
    view = View.create({ isVisible: false });
    view.append();
  });

  ok(view.$().is(':hidden'), "precond - view is hidden when appended");

  Ember.run(function() {
    view.set('isVisible', true);
  });

  ok(view.$().is(':visible'), "precond - view is now visible");
  equal(parentBecameVisible, 1);
  equal(childBecameVisible, 1);
  equal(grandchildBecameVisible, 1);
});

test("view should be notified after isVisible is set to false and the element has been hidden", function() {
  view = View.create({ isVisible: true });
  var childView = view.get('childViews').objectAt(0);
  var grandchildView = childView.get('childViews').objectAt(0);

  Ember.run(function() {
    view.append();
  });

  ok(view.$().is(':visible'), "precond - view is visible when appended");

  Ember.run(function() {
    childView.set('isVisible', false);
  });

  ok(childView.$().is(':hidden'), "precond - view is now hidden");

  equal(childBecameHidden, 1);
  equal(grandchildBecameHidden, 1);
});

test("view should be notified after isVisible is set to true and the element has been shown", function() {
  view = View.create({ isVisible: false });
  var childView = view.get('childViews').objectAt(0);
  var grandchildView = childView.get('childViews').objectAt(0);

  Ember.run(function() {
    view.append();
  });

  ok(view.$().is(':hidden'), "precond - view is hidden when appended");

  Ember.run(function() {
    view.set('isVisible', true);
  });

  ok(view.$().is(':visible'), "precond - view is now visible");

  equal(parentBecameVisible, 1);
  equal(childBecameVisible, 1);
  equal(grandchildBecameVisible, 1);
});

test("if a view descends from a hidden view, making isVisible true should not trigger becameVisible", function() {
  view = View.create({ isVisible: true });
  var childView = view.get('childViews').objectAt(0);
  var grandchildView = childView.get('childViews').objectAt(0);

  Ember.run(function() {
    view.append();
  });

  ok(view.$().is(':visible'), "precond - view is visible when appended");

  Ember.run(function() {
    childView.set('isVisible', false);
  });

  Ember.run(function() {
    view.set('isVisible', false);
  });

  childBecameVisible = 0;
  grandchildBecameVisible = 0;

  Ember.run(function() {
    childView.set('isVisible', true);
  });

  equal(childBecameVisible, 0, "the child did not become visible");
  equal(grandchildBecameVisible, 0, "the grandchild did not become visible");
});

test("if a child view becomes visible while its parent is hidden, if its parent later becomes visible, it receives a becameVisible callback", function() {
  view = View.create({ isVisible: false });
  var childView = view.get('childViews').objectAt(0);
  var grandchildView = childView.get('childViews').objectAt(0);

  Ember.run(function() {
    view.append();
  });

  ok(view.$().is(':hidden'), "precond - view is hidden when appended");

  Ember.run(function() {
    childView.set('isVisible', true);
  });

  equal(childBecameVisible, 0, "child did not become visible since parent is hidden");
  equal(grandchildBecameVisible, 0, "grandchild did not become visible since parent is hidden");

  Ember.run(function() {
    view.set('isVisible', true);
  });

  equal(parentBecameVisible, 1);
  equal(childBecameVisible, 1);
  equal(grandchildBecameVisible, 1);
});
<commit_msg>Fix tests to use already declared global var<commit_after>var get = Ember.get, set = Ember.set;

var View, view, parentBecameVisible, childBecameVisible, grandchildBecameVisible;
var parentBecameHidden, childBecameHidden, grandchildBecameHidden;

module("Ember.View#isVisible", {
  setup: function() {
    parentBecameVisible=0;
    childBecameVisible=0;
    grandchildBecameVisible=0;
    parentBecameHidden=0;
    childBecameHidden=0;
    grandchildBecameHidden=0;

    View = Ember.ContainerView.extend({
      childViews: ['child'],
      becameVisible: function() { parentBecameVisible++; },
      becameHidden: function() { parentBecameHidden++; },

      child: Ember.ContainerView.extend({
        childViews: ['grandchild'],
        becameVisible: function() { childBecameVisible++; },
        becameHidden: function() { childBecameHidden++; },

        grandchild: Ember.View.extend({
          template: function() { return "seems weird bro"; },
          becameVisible: function() { grandchildBecameVisible++; },
          becameHidden: function() { grandchildBecameHidden++; }
        })
      })
    });
  },

  teardown: function() {
    if (view) {
      Ember.run(function(){ view.destroy(); });
    }
  }
});

test("should hide views when isVisible is false", function() {
  view = Ember.View.create({
    isVisible: false
  });

  Ember.run(function() {
    view.append();
  });

  ok(view.$().is(':hidden'), "the view is hidden");

  set(view, 'isVisible', true);
  ok(view.$().is(':visible'), "the view is visible");
  view.remove();
});

test("should hide element if isVisible is false before element is created", function() {
  view = Ember.View.create({
    isVisible: false
  });

  ok(!get(view, 'isVisible'), "precond - view is not visible");

  set(view, 'template', function() { return "foo"; });

  Ember.run(function() {
    view.append();
  });

  ok(view.$().is(':hidden'), "should be hidden");

  view.remove();
  set(view, 'isVisible', true);

  Ember.run(function() {
    view.append();
  });

  ok(view.$().is(':visible'), "view should be visible");

  Ember.run(function() {
    view.remove();
  });
});

test("view should be notified after isVisible is set to false and the element has been hidden", function() {
  Ember.run(function(){
    view = View.create({ isVisible: false });
    view.append();
  });

  ok(view.$().is(':hidden'), "precond - view is hidden when appended");

  Ember.run(function() {
    view.set('isVisible', true);
  });

  ok(view.$().is(':visible'), "precond - view is now visible");
  equal(parentBecameVisible, 1);
  equal(childBecameVisible, 1);
  equal(grandchildBecameVisible, 1);
});

test("view should be notified after isVisible is set to false and the element has been hidden", function() {
  view = View.create({ isVisible: true });
  var childView = view.get('childViews').objectAt(0);
  var grandchildView = childView.get('childViews').objectAt(0);

  Ember.run(function() {
    view.append();
  });

  ok(view.$().is(':visible'), "precond - view is visible when appended");

  Ember.run(function() {
    childView.set('isVisible', false);
  });

  ok(childView.$().is(':hidden'), "precond - view is now hidden");

  equal(childBecameHidden, 1);
  equal(grandchildBecameHidden, 1);
});

test("view should be notified after isVisible is set to true and the element has been shown", function() {
  view = View.create({ isVisible: false });
  var childView = view.get('childViews').objectAt(0);
  var grandchildView = childView.get('childViews').objectAt(0);

  Ember.run(function() {
    view.append();
  });

  ok(view.$().is(':hidden'), "precond - view is hidden when appended");

  Ember.run(function() {
    view.set('isVisible', true);
  });

  ok(view.$().is(':visible'), "precond - view is now visible");

  equal(parentBecameVisible, 1);
  equal(childBecameVisible, 1);
  equal(grandchildBecameVisible, 1);
});

test("if a view descends from a hidden view, making isVisible true should not trigger becameVisible", function() {
  view = View.create({ isVisible: true });
  var childView = view.get('childViews').objectAt(0);
  var grandchildView = childView.get('childViews').objectAt(0);

  Ember.run(function() {
    view.append();
  });

  ok(view.$().is(':visible'), "precond - view is visible when appended");

  Ember.run(function() {
    childView.set('isVisible', false);
  });

  Ember.run(function() {
    view.set('isVisible', false);
  });

  childBecameVisible = 0;
  grandchildBecameVisible = 0;

  Ember.run(function() {
    childView.set('isVisible', true);
  });

  equal(childBecameVisible, 0, "the child did not become visible");
  equal(grandchildBecameVisible, 0, "the grandchild did not become visible");
});

test("if a child view becomes visible while its parent is hidden, if its parent later becomes visible, it receives a becameVisible callback", function() {
  view = View.create({ isVisible: false });
  var childView = view.get('childViews').objectAt(0);
  var grandchildView = childView.get('childViews').objectAt(0);

  Ember.run(function() {
    view.append();
  });

  ok(view.$().is(':hidden'), "precond - view is hidden when appended");

  Ember.run(function() {
    childView.set('isVisible', true);
  });

  equal(childBecameVisible, 0, "child did not become visible since parent is hidden");
  equal(grandchildBecameVisible, 0, "grandchild did not become visible since parent is hidden");

  Ember.run(function() {
    view.set('isVisible', true);
  });

  equal(parentBecameVisible, 1);
  equal(childBecameVisible, 1);
  equal(grandchildBecameVisible, 1);
});
<|endoftext|>


<commit_before>/* */

import {describe, it} from 'mocha';
import {expect} from 'chai';
import {injectDeps, useDeps} from '../';
import {shallow} from 'enzyme';
import React from 'react';

describe('Depedancy Injection', () => {
  it('should inject context and allow to use them', () => {
    const context = {name: 'arunoda'};
    const Layout = ({children}) => children;
    const LayoutWithDeps = injectDeps(context)(Layout);

    const Comp = ({name}) => (
{name}
);
    const mapper = (context) => ({
      name: context.name
    });
    const CompWithDeps = useDeps(mapper)(Comp);

    const el = shallow((

        <LayoutWithDeps>
          <CompWithDeps />
        </LayoutWithDeps>

    ));

    expect(el.html()).to.match(/arunoda/);
  });

  it('should inject actions and allow to use them', () => {
    const context = {name: 'arunoda'};
    const actions = {
      default: {
        getFullName({name}, surname) {
          return `${name}-${surname}`;
        }
      }
    };
    const Layout = ({children}) => children;
    const LayoutWithDeps = injectDeps(context, actions)(Layout);

    const Comp = ({getName}) => (
{getName('susiripala')}
);
    const mapper = (context, actions) => ({
      getName: actions.default.getFullName
    });
    const CompWithDeps = useDeps(mapper)(Comp);

    const el = shallow((

        <LayoutWithDeps>
          <CompWithDeps />
        </LayoutWithDeps>

    ));

    expect(el.html()).to.match(/arunoda-susiripala/);
  });

  it('should use a default mapper if no mapper is provided', () => {
    const context = {name: 'arunoda'};
    const actions = {
      default: {
        getFullName({name}, surname) {
          return `${name}-${surname}`;
        }
      }
    };
    const Layout = ({children}) => children;
    const LayoutWithDeps = injectDeps(context, actions)(Layout);

    const Comp = ({context, actions}) => (
{
      actions().default.getFullName(context().name)
    }
);
    const CompWithDeps = useDeps()(Comp);

    const el = shallow((

        <LayoutWithDeps>
          <CompWithDeps />
        </LayoutWithDeps>

    ));

    expect(el.html()).to.match(/arunoda-arunoda/);
  });

  it('should preseve original props', () => {
    const context = {};
    const Layout = ({children}) => children;
    const LayoutWithDeps = injectDeps(context)(Layout);

    const Comp = ({name}) => (
{name}
);
    const CompWithDeps = useDeps()(Comp);

    const el = shallow((

        <LayoutWithDeps>
          <CompWithDeps name="arunoda"/>
        </LayoutWithDeps>

    ));

    expect(el.html()).to.match(/arunoda/);
  });
});

describe('Misc', () => {
  describe('static fields', () => {
    it('should preseve when injecting deps', () => {
      const Layout = () => (

);
      Layout.theme = 'light';

      const LayoutWithDeps = injectDeps({})(Layout);
      expect(LayoutWithDeps.theme).to.be.equal('light');
    });

    it('should preseve when using deps', () => {
      const Comp = () => (

);
      Comp.theme = 'light';

      const CompWithDeps = useDeps()(Comp);
      expect(CompWithDeps.theme).to.be.equal('light');
    });
  });

  describe('displayName', () => {
    it('should extend when injecting deps', () => {
      const Layout = () => (

);
      Layout.displayName = 'TheLayout';

      const LayoutWithDeps = injectDeps({})(Layout);
      expect(LayoutWithDeps.displayName).to.be.equal('WithDeps(TheLayout)');
    });

    it('should extend when using deps', () => {
      const Comp = () => (

);
      Comp.displayName = 'TheComp';

      const CompWithDeps = useDeps()(Comp);
      expect(CompWithDeps.displayName).to.be.equal('UseDeps(TheComp)');
    });
  });
});<commit_msg>Fix lint issues<commit_after>/* */

import {describe, it} from 'mocha';
import {expect} from 'chai';
import {injectDeps, useDeps} from '../';
import {shallow} from 'enzyme';
import React from 'react';

describe('Depedancy Injection', () => {
  it('should inject context and allow to use them', () => {
    const context = {name: 'arunoda'};
    const Layout = class extends React.Component {
      render() {
        return this.props.children;
      }
    };
    const LayoutWithDeps = injectDeps(context)(Layout);

    const Comp = ({name}) => (
{name}
);
    const mapper = c => ({
      name: c.name
    });
    const CompWithDeps = useDeps(mapper)(Comp);

    const el = shallow((

        <LayoutWithDeps>
          <CompWithDeps />
        </LayoutWithDeps>

    ));

    expect(el.html()).to.match(/arunoda/);
  });

  it('should inject actions and allow to use them', () => {
    const context = {name: 'arunoda'};
    const actions = {
      default: {
        getFullName({name}, surname) {
          return `${name}-${surname}`;
        }
      }
    };
    const Layout = ({children}) => children;
    const LayoutWithDeps = injectDeps(context, actions)(Layout);

    const Comp = ({getName}) => (
{getName('susiripala')}
);
    const mapper = (c, a) => ({
      getName: a.default.getFullName
    });
    const CompWithDeps = useDeps(mapper)(Comp);

    const el = shallow((

        <LayoutWithDeps>
          <CompWithDeps />
        </LayoutWithDeps>

    ));

    expect(el.html()).to.match(/arunoda-susiripala/);
  });

  it('should use a default mapper if no mapper is provided', () => {
    const context = {name: 'arunoda'};
    const actions = {
      default: {
        getFullName({name}, surname) {
          return `${name}-${surname}`;
        }
      }
    };
    const Layout = ({children}) => children;
    const LayoutWithDeps = injectDeps(context, actions)(Layout);

    const Comp = props => (
{
      props.actions().default.getFullName(props.context().name)
    }
);
    const CompWithDeps = useDeps()(Comp);

    const el = shallow((

        <LayoutWithDeps>
          <CompWithDeps />
        </LayoutWithDeps>

    ));

    expect(el.html()).to.match(/arunoda-arunoda/);
  });

  it('should preseve original props', () => {
    const context = {};
    const Layout = ({children}) => children;
    const LayoutWithDeps = injectDeps(context)(Layout);

    const Comp = ({name}) => (
{name}
);
    const CompWithDeps = useDeps()(Comp);

    const el = shallow((

        <LayoutWithDeps>
          <CompWithDeps name="arunoda"/>
        </LayoutWithDeps>

    ));

    expect(el.html()).to.match(/arunoda/);
  });
});

describe('Misc', () => {
  describe('static fields', () => {
    it('should preseve when injecting deps', () => {
      const Layout = () => (

);
      Layout.theme = 'light';

      const LayoutWithDeps = injectDeps({})(Layout);
      expect(LayoutWithDeps.theme).to.be.equal('light');
    });

    it('should preseve when using deps', () => {
      const Comp = () => (

);
      Comp.theme = 'light';

      const CompWithDeps = useDeps()(Comp);
      expect(CompWithDeps.theme).to.be.equal('light');
    });
  });

  describe('displayName', () => {
    it('should extend when injecting deps', () => {
      const Layout = () => (

);
      Layout.displayName = 'TheLayout';

      const LayoutWithDeps = injectDeps({})(Layout);
      expect(LayoutWithDeps.displayName).to.be.equal('WithDeps(TheLayout)');
    });

    it('should extend when using deps', () => {
      const Comp = () => (

);
      Comp.displayName = 'TheComp';

      const CompWithDeps = useDeps()(Comp);
      expect(CompWithDeps.displayName).to.be.equal('UseDeps(TheComp)');
    });
  });
});
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import React from 'react'
import EntityListApp from 'tocco-entity-list/src/main'

const SubGrid = props => {
  const formBase = `${props.detailFormName}_${props.gridName}`
  return (

      <EntityListApp
        id={`${props.appId}-subgrid-${formBase}`}
        keepStore={true}
        entityName={props.modelField.targetEntity}
        formBase={formBase}
        limit={props.limit}
        showSearchForm={props.showSearchForm}
        preselectedSearchFields={[{
          id: props.modelField.reverseRelationName,
          value: props.entityKey,
          hidden: true
        }]}
        onRowClick={e => {
          if (props.onRowClick) {
            props.onRowClick({
              id: e.id,
              gridName: props.gridName,
              relationName: props.relationName
            })
          }
        }}
        onNavigateToCreate={e => {
          props.onNavigateToCreate({
            gridName: props.gridName,
            relationName: props.relationName
          })
        }
        }
        showCreateButton={props.showSubGridsCreateButton}
        emitAction={action => { props.dispatchEmittedAction(action) }}
      />

  )
}

SubGrid.defaultProps = {
  limit: 5
}

SubGrid.propTypes = {
  entityKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  detailFormName: PropTypes.string.isRequired,
  gridName: PropTypes.string.isRequired,
  relationName: PropTypes.string.isRequired,
  modelField: PropTypes.shape({
    targetEntity: PropTypes.string,
    reverseRelationName: PropTypes.string
  }).isRequired,
  onRowClick: PropTypes.func,
  onNavigateToCreate: PropTypes.func.isRequired,
  dispatchEmittedAction: PropTypes.func.isRequired,
  showSubGridsCreateButton: PropTypes.bool,
  appId: PropTypes.string,
  showSearchForm: PropTypes.bool,
  limit: PropTypes.number
}

export default SubGrid
<commit_msg>refactor(entity-detail): adjust to new entity-list properties<commit_after>import PropTypes from 'prop-types'
import React from 'react'
import EntityListApp from 'tocco-entity-list/src/main'

const SubGrid = props => {
  const formBase = `${props.detailFormName}_${props.gridName}`
  return (

      <EntityListApp
        id={`${props.appId}-subgrid-${formBase}`}
        keepStore={true}
        entityName={props.modelField.targetEntity}
        formBase={formBase}
        limit={props.limit}
        showSearchForm={props.showSearchForm}
        onRowClick={e => {
          if (props.onRowClick) {
            props.onRowClick({
              id: e.id,
              gridName: props.gridName,
              relationName: props.relationName
            })
          }
        }}
        onNavigateToCreate={e => {
          props.onNavigateToCreate({
            gridName: props.gridName,
            relationName: props.relationName
          })
        }
        }
        showCreateButton={props.showSubGridsCreateButton}
        emitAction={action => { props.dispatchEmittedAction(action) }}
        parent={{
          key: props.entityKey,
          reverseRelationName: props.modelField.reverseRelationName
        }}
      />

  )
}

SubGrid.defaultProps = {
  limit: 5
}

SubGrid.propTypes = {
  entityKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  detailFormName: PropTypes.string.isRequired,
  gridName: PropTypes.string.isRequired,
  relationName: PropTypes.string.isRequired,
  modelField: PropTypes.shape({
    targetEntity: PropTypes.string,
    reverseRelationName: PropTypes.string
  }).isRequired,
  onRowClick: PropTypes.func,
  onNavigateToCreate: PropTypes.func.isRequired,
  dispatchEmittedAction: PropTypes.func.isRequired,
  showSubGridsCreateButton: PropTypes.bool,
  appId: PropTypes.string,
  showSearchForm: PropTypes.bool,
  limit: PropTypes.number
}

export default SubGrid
<|endoftext|>