<commit_before>define(["require", "exports", "module", "./Vec2D","./Line2D","./Circle","./Rect","../internals"], function(require, exports, module) {

var	internals = require('../internals'),
	MathUtils = require('../math/mathUtils'),
	Vec2D = require('./Vec2D'),
	Circle = require('./Circle'),
    Rect = require('./Rect'),
	Line2D = require('./Line2D');

/**
 * @class
 * @member toxi
 */
var Polygon2D = function(){
	this.vertices = [];
	var i,l;
	if(arguments.length > 1){ //comma-separated Vec2D's were passed in
		for(i=0, l = arguments.length;i<l;i++){
			this.add(arguments[i].copy());
		}
	} else if(arguments.length == 1){
		var arg = arguments[0];
		if( internals.is.Array( arg ) ){ // if it was an array of points
			for(i=0,l = arg.length;i<l;i++){
				this.add(arg[i].copy());
			}
		}
	} //otherwise no args were passed, and thats ok

};

Polygon2D.prototype = {
	constructor: Polygon2D,
	add: function(p){
		if(this.vertices.indexOf(p) < 0){
			this.vertices.push(p);
		}
	},
	/**
	 * centers the polygon so that its new centroid is at the given point
	 * @param {Vec2D} [origin]
	 * @return itself
	 */
	center: function( origin ){
		var centroid = this.getCentroid();
		var delta = origin !== undefined ? origin.sub( centroid ) : centroid.invert();
		for( var i=0, l = this.vertices.length; i<l; i++){
			this.vertices[i].addSelf( delta );
		}
		return this;
	},
	containsPoint: function(p){
		var num = this.vertices.length,
			i = 0,
			j = num-1,
			oddNodes = false,
			px = p.x,
			py = p.y;
		for(i=0;i<num;i++){
			var vi = this.vertices[i],
				vj = this.vertices[j];
			if (vi.y < py && vj.y >= py || vj.y < py && vi.y >= py) {
				if (vi.x + (py - vi.y) / (vj.y - vi.y) * (vj.x - vi.x) < px) {
					oddNodes = !oddNodes;
				}
			}
			j = i;
		}
		return oddNodes;
	},

	containsPolygon: function(poly) {
		for (var i=0,num=poly.vertices.length; i<num; i++) {
			if (!this.containsPoint(poly.vertices[i])) {
				return false;
			}
		}
		return true;
	},

	copy: function(){
		return new Polygon2D( this.vertices );
	},

	flipVertexOrder: function(){
		this.vertices.reverse();
		return this;
	},
	/**
	 * Returns the vertex at the given index. This function follows Python
	 * convention, in that if the index is negative, it is considered relative
	 * to the list end. Therefore the vertex at index -1 is the last vertex in
	 * the list.
	 * @param {Number} i index
	 * @return vertex
	 */
	get: function( i ){
		if( i < 0 ){
			i += this.vertices.length;
		}
		return this.vertices[i];
	},

	/**
	 * Computes the length of this polygon's apothem. This will only be valid if
	 * the polygon is regular. More info: http://en.wikipedia.org/wiki/Apothem
	 * @return apothem length
	 */
	getApothem: function() {
		return this.vertices[0]
			.interpolateTo(this.vertices[1], 0.5)
			.distanceTo( this.getCentroid() );
	},

	getArea: function(){
		var area = 0,
			numPoints = this.vertices.length;
		for(var i=0;i<numPoints;i++){
			var a = this.vertices[i],
				b = this.vertices[(i+1) % numPoints];
			area += a.x * b.y;
			area -= a.y * b.x;
		}
		area *= 0.5;
		return area;
	},

	getBoundingCircle: function() {
        var Circle = require('./Circle');
		return Circle.newBoundingCircle( this.vertices );
	},

    getBounds: function(){
        var Rect = require('./Rect');
        return Rect.getBoundingRect(this.vertices);
    },

	getCentroid: function(){
		var res = new Vec2D(),
			numPoints = this.vertices.length;
		for(var i=0;i<numPoints;i++){
			var a = this.vertices[i],
				b = this.vertices[(i+1) %numPoints],
				factor = a.x * b.y - b.x * a.y;
			res.x += (a.x + b.x) * factor;
			res.y += (a.y + b.y) * factor;
		}
		return res.scale(1 / (this.getArea() * 6));
	},

	getCircumference: function(){
		var circ = 0;
		for(var i=0,num=this.vertices.length;i<num;i++){
			circ += this.vertices[i].distanceTo(this.vertices[(i+1)%num]);
		}
		return circ;
	},

	getClosestPointTo: function( p ){
		var minD = Number.MAX_VALUE;
		var q, c, d;
		var edges = this.getEdges();
		for( var i=0, len = edges.length; i<len; i++ ){
			c = edges[i].closestPointTo( p );
			d = c.distanceToSquared( p );
			if( d < minD ){
				q = c;
				minD = d;
			}
		}
		return q;
	},

	getClosestVertexTo: function( p ){
		var minD = Number.MAX_VALUE;
		var q, d, i = 0, len = this.vertices.length;
		for( ; i<len; i++){
			d = this.vertices[i].distanceToSquared( p );
			if( d < minD ){
				q = this.vertices[i];
				minD = d;
			}
		}
		return q;
	},

	getEdges: function() {
		var num = this.vertices.length,
			edges = [];
		for (var i = 0; i < num; i++) {
			edges[i] = new Line2D(this.vertices[i], this.vertices[(i + 1) % num]);
		}
		return edges;
	},

	//@deprecated
	getNumPoints: function(){
		return this.getNumVertices();
	},

	getNumVertices: function(){
		return this.vertices.length;
	},

	getRandomPoint: function(){
		var edges = this.getEdges();
		var numEdges = edges.length;
		var ea = edges[MathUtils.random(numEdges)],
			eb;
		while( eb === undefined || eb.equals( ea ) ){
			eb = edges[ MathUtils.random(numEdges) ];
		}
		//pick a random point on edge A
		var p = ea.a.interpolateTo( ea.b, Math.random() );
		//then randomly interpolate to another point on b
		return p.interpolateToSelf(
			eb.a.interpolateTo( eb.b, Math.random() ),
			Math.random()
		);
	},
	/**
	 * Repeatedly inserts vertices as mid points of the longest edges until the
	 * new vertex count is reached.
	 * @param {Number} count new vertex count
	 * @return itself
	 */
	increaseVertexCount: function( count ){
		var num = this.vertices.length,
			longestID = 0,
			maxD = 0,
			i = 0,
			d,
			m;

		while( num < count ){
			//find longest edge
			longestID = 0;
			maxD = 0;
			for( i=0; i<num; i++ ){
				d = this.vertices[i].distanceToSquared( this.vertices[ (i+1) % num ] );
				if( d > maxD ){
					longestID = i;
					maxD = d;
				}
			}
			//insert mid point of longest segment
			m = this.vertices[longestID]
				.add(this.vertices[(longestID + 1) % num])
				.scaleSelf(0.5);
			//push this into the array inbetween the 2 points
			this.vertices.splice( longestID+1, 0, m );
			num++;
		}
		return this;
	},

	intersectsPolygon: function( poly ){
		var Type = Line2D.LineIntersection.Type;
		var edges = this.getEdges(), polyEdges = poly.getEdges();
		var i = 0, el = edges.length;
		var j = 0, pl = polyEdges.length;
		var ea, eb, isec;
		for( ; i<el; i++ ){
			ea = edges[i];
			for( j=0; j<pl; j++ ){
				eb = polyEdges[j];
				isec = ea.intersectLine(eb).getType();
				if( isec === Type.INTERSECTING || isec == Type.COINCIDENT ){
					return true;
				}
			}
		}
		return false;
	},

	isClockwise: function(){
		var isClockwise = function( a, b, c ){
			var determ = (b.x-a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
			return (determ < 0.0);
		};
		if(this.vertices.length > 2){
			return isClockwise(this.vertices[0],this.vertices[1],this.vertices[2]);
		}
		return false;
	},

	intersectsPoly: function(poly) {
		if (!this.containsPolygon(poly)) {
			var edges=this.getEdges();
			var pedges=poly.getEdges();
			for(var i=0, n=edges.length; i < n; i++) {
				for(var j=0, m = pedges.length, e = edges[i]; j < m; j++) {
					if (e.intersectLine(pedges[j]).getType() == Line2D.LineIntersection.Type.INTERSECTING) {
						return true;
					}
				}
			}
			return false;
		} else {
			return true;
		}
	},
	/**
     * Removes duplicate vertices from the polygon. Only successive points are
     * recognized as duplicates.
     * @param {Number} tolerance snap distance for finding duplicates
     * @return itself
     */
	removeDuplicates: function( tolerance ){
		//if tolerance is 0, it will be faster to just use 'equals' method
		var equals = tolerance ? 'equalsWithTolerance' : 'equals';
		var p, prev, i = 0, num = this.vertices.length;
		var last;
		for( ; i<num; i++ ){
			p = this.vertices[i];
			//if its the 'equals' method tolerance will just be ingored
			if( p[equals]( prev, tolerance ) ){
				//remove from array, step back counter
				this.vertices.splice( i, 1 );
				i--;
				num--;
			} else {
				prev = p;
			}
		}
		num = this.vertices.length;
		if( num >  0 ){
			last = this.vertices[num-1];
			if( last[equals]( this.vertices[0], tolerance ) ){
				this.vertices.splice( num-1, 1 );
			}
		}
		return this;
	},
	rotate: function(theta) {
		for (var i=0, num=this.vertices.length; i < num; i++) {
			this.vertices[i].rotate(theta);
		}
	},

	scale: function() {
		var x,y;
		if (arguments.length==1) {
			var arg = arguments[0];
			if( internals.has.XY( arg ) ){
				x=arg.x;
				y=arg.y;
			} else {
				// uniform scale
				x=arg;
				y=arg;
			}
		} else if (arguments.length==2) {
			x=arguments[0];
			y=arguments[1];
		} else {
			throw "Invalid argument(s) passed.";
		}
		for (var i=0, num=this.vertices.length; i < num; i++) {
			this.vertices[i].scaleSelf(x, y);
		}
		return this;
	},

	translate: function() {
		var x,y;
		if (arguments.length==1 && internals.has.XY( arguments[0] ) ){
			x=arguments[0].x;
			y=arguments[0].y;
		} else if (arguments.length==2) {
			x=arguments[0];
			y=arguments[1];
		} else {
			throw "Invalid argument(s) passed.";
		}
		for (var i=0, num=this.vertices.length; i < num; i++) {
			this.vertices[i].addSelf(x, y);
		}
		return this;
	},

	smooth: function(amount, baseWeight){
		var centroid = this.getCentroid();
		var num = this.vertices.length;
		var filtered = [];
		for(var i=0,j=num-1,k=1;i<num;i++){
			var a = this.vertices[i];
			var dir = this.vertices[j].sub(a).addSelf(this.vertices[k].sub(a))
				.addSelf(a.sub(centroid).scaleSelf(baseWeight));
			filtered.push(a.add(dir.scaleSelf(amount)));
			j++;
			if(j == num){
				j=0;
			}
			k++;
			if(k == num){
				k=0;
			}
		}
		this.vertices = filtered;
		return this;
	},

	toString: function(){
		var s = "";
		for(var i=0;i<this.vertices.length;i++){
			s += this.vertices[i];
			if(i<this.vertices.length-1){
				s+= ", ";
			}
		}
		return s;
	}

};

/**
 * Constructs a new regular polygon from the given base line/edge.
 * @param {Vec2D} baseA left point of the base edge
 * @param {Vec2D} baseB right point of the base edge
 * @param {Number} res number of polygon vertices
 * @return polygon
 */
Polygon2D.fromBaseEdge = function( baseA, baseB, res ){
	var theta = -( MathUtils.PI - (MathUtils.PI*(res-2) / res) ),
		dir = baseB.sub( baseA ),
		prev = baseB,
		poly = new Polygon2D( baseA, baseB ),
		p;
	for( var i=0; i< res-1; i++){
		p = prev.add( dir.getRotated(theta*i) );
		poly.add( p );
		prev = p;
	}
	return poly;
};

/**
 * Constructs a regular polygon from the given edge length and number of
 * vertices. This automatically computes the radius of the circle the
 * polygon is inscribed in.
 * More information: http://en.wikipedia.org/wiki/Regular_polygon#Radius
 *
 * @param {Number} len desired edge length
 * @param {Number} res number of vertices
 * @return polygon
 */
Polygon2D.fromEdgeLength = function( len, res ){
	return new Circle( Polygon2D.getRadiusForEdgeLength(len,res) ).toPolygon2D( res );
};

/**
 * Computes the radius of the circle the regular polygon with the desired
 * edge length is inscribed in
 * @param {Number} len edge length
 * @param {Number} res number of polygon vertices
 * @return radius
 */

Polygon2D.getRadiusForEdgeLength = function( len, res ){
	return len / ( 2 * MathUtils.sin(MathUtils.PI/res) );
};

module.exports = Polygon2D;
});
<commit_msg>convert Polygon2D to normal AMD spec<commit_after>define([
    '../math/mathUtils',
    './Vec2D',
    './Line2D',
    './Circle',
    './Rect',
    '../internals/has',
    '../internals/is'
], function( MathUtils, Vec2D, Line2D, Circle, Rect, has, is) {

    /**
    * @class
    * @member toxi
    */
    var Polygon2D = function(){
        this.vertices = [];
        var i,l;
        if(arguments.length > 1){ //comma-separated Vec2D's were passed in
            for(i=0, l = arguments.length;i<l;i++){
                this.add(arguments[i].copy());
            }
        } else if(arguments.length == 1){
            var arg = arguments[0];
            if( is.Array( arg ) ){ // if it was an array of points
                for(i=0,l = arg.length;i<l;i++){
                    this.add(arg[i].copy());
                }
            }
        } //otherwise no args were passed, and thats ok

    };

    Polygon2D.prototype = {
        constructor: Polygon2D,

        add: function(p){
            if(this.vertices.indexOf(p) < 0){
                this.vertices.push(p);
            }
        },

        /**
        * centers the polygon so that its new centroid is at the given point
        * @param {Vec2D} [origin]
        * @return itself
        */
        center: function( origin ){
            var centroid = this.getCentroid();
            var delta = origin !== undefined ? origin.sub( centroid ) : centroid.invert();
            for( var i=0, l = this.vertices.length; i<l; i++){
                this.vertices[i].addSelf( delta );
            }
            return this;
        },

        containsPoint: function(p){
            var num = this.vertices.length,
                i = 0,
                j = num-1,
                oddNodes = false,
                px = p.x,
                py = p.y;
            for(i=0;i<num;i++){
                var vi = this.vertices[i],
                    vj = this.vertices[j];
                if (vi.y < py && vj.y >= py || vj.y < py && vi.y >= py) {
                    if (vi.x + (py - vi.y) / (vj.y - vi.y) * (vj.x - vi.x) < px) {
                        oddNodes = !oddNodes;
                    }
                }
                j = i;
            }
            return oddNodes;
        },

        containsPolygon: function(poly) {
            for (var i=0,num=poly.vertices.length; i<num; i++) {
                if (!this.containsPoint(poly.vertices[i])) {
                    return false;
                }
            }
            return true;
        },

        copy: function(){
            return new Polygon2D( this.vertices );
        },

        flipVertexOrder: function(){
            this.vertices.reverse();
            return this;
        },

        /**
        * Returns the vertex at the given index. This function follows Python
        * convention, in that if the index is negative, it is considered relative
        * to the list end. Therefore the vertex at index -1 is the last vertex in
        * the list.
        * @param {Number} i index
        * @return vertex
        */
        get: function( i ){
            if( i < 0 ){
                i += this.vertices.length;
            }
            return this.vertices[i];
        },

        /**
        * Computes the length of this polygon's apothem. This will only be valid if
        * the polygon is regular. More info: http://en.wikipedia.org/wiki/Apothem
        * @return apothem length
        */
        getApothem: function() {
            return this.vertices[0]
                .interpolateTo(this.vertices[1], 0.5)
                .distanceTo( this.getCentroid() );
        },

        getArea: function(){
            var area = 0,
                numPoints = this.vertices.length;
            for(var i=0;i<numPoints;i++){
                var a = this.vertices[i],
                    b = this.vertices[(i+1) % numPoints];
                area += a.x * b.y;
                area -= a.y * b.x;
            }
            area *= 0.5;
            return area;
        },

        getBoundingCircle: function() {
            var Circle = require('./Circle');
            return Circle.newBoundingCircle( this.vertices );
        },

        getBounds: function(){
            var Rect = require('./Rect');
            return Rect.getBoundingRect(this.vertices);
        },

        getCentroid: function(){
            var res = new Vec2D(),
                numPoints = this.vertices.length;
            for(var i=0;i<numPoints;i++){
                var a = this.vertices[i],
                    b = this.vertices[(i+1) %numPoints],
                    factor = a.x * b.y - b.x * a.y;
                res.x += (a.x + b.x) * factor;
                res.y += (a.y + b.y) * factor;
            }
            return res.scale(1 / (this.getArea() * 6));
        },

        getCircumference: function(){
            var circ = 0;
            for(var i=0,num=this.vertices.length;i<num;i++){
                circ += this.vertices[i].distanceTo(this.vertices[(i+1)%num]);
            }
            return circ;
        },

        getClosestPointTo: function( p ){
            var minD = Number.MAX_VALUE;
            var q, c, d;
            var edges = this.getEdges();
            for( var i=0, len = edges.length; i<len; i++ ){
                c = edges[i].closestPointTo( p );
                d = c.distanceToSquared( p );
                if( d < minD ){
                    q = c;
                    minD = d;
                }
            }
            return q;
        },

        getClosestVertexTo: function( p ){
            var minD = Number.MAX_VALUE;
            var q, d, i = 0, len = this.vertices.length;
            for( ; i<len; i++){
                d = this.vertices[i].distanceToSquared( p );
                if( d < minD ){
                    q = this.vertices[i];
                    minD = d;
                }
            }
            return q;
        },

        getEdges: function() {
            var num = this.vertices.length,
                edges = [];
            for (var i = 0; i < num; i++) {
                edges[i] = new Line2D(this.vertices[i], this.vertices[(i + 1) % num]);
            }
            return edges;
        },

        //@deprecated
        getNumPoints: function(){
            return this.getNumVertices();
        },

        getNumVertices: function(){
            return this.vertices.length;
        },

        getRandomPoint: function(){
            var edges = this.getEdges();
            var numEdges = edges.length;
            var ea = edges[MathUtils.random(numEdges)],
                eb;
            while( eb === undefined || eb.equals( ea ) ){
                eb = edges[ MathUtils.random(numEdges) ];
            }
            //pick a random point on edge A
            var p = ea.a.interpolateTo( ea.b, Math.random() );
            //then randomly interpolate to another point on b
            return p.interpolateToSelf(
                eb.a.interpolateTo( eb.b, Math.random() ),
                Math.random()
            );
        },

        /**
        * Repeatedly inserts vertices as mid points of the longest edges until the
        * new vertex count is reached.
        * @param {Number} count new vertex count
        * @return itself
        */
        increaseVertexCount: function( count ){
            var num = this.vertices.length,
                longestID = 0,
                maxD = 0,
                i = 0,
                d,
                m;

            while( num < count ){
                //find longest edge
                longestID = 0;
                maxD = 0;
                for( i=0; i<num; i++ ){
                    d = this.vertices[i].distanceToSquared( this.vertices[ (i+1) % num ] );
                    if( d > maxD ){
                        longestID = i;
                        maxD = d;
                    }
                }
                //insert mid point of longest segment
                m = this.vertices[longestID]
                    .add(this.vertices[(longestID + 1) % num])
                    .scaleSelf(0.5);
                //push this into the array inbetween the 2 points
                this.vertices.splice( longestID+1, 0, m );
                num++;
            }
            return this;
        },

        intersectsPolygon: function( poly ){
            var Type = Line2D.LineIntersection.Type;
            var edges = this.getEdges(), polyEdges = poly.getEdges();
            var i = 0, el = edges.length;
            var j = 0, pl = polyEdges.length;
            var ea, eb, isec;
            for( ; i<el; i++ ){
                ea = edges[i];
                for( j=0; j<pl; j++ ){
                    eb = polyEdges[j];
                    isec = ea.intersectLine(eb).getType();
                    if( isec === Type.INTERSECTING || isec == Type.COINCIDENT ){
                        return true;
                    }
                }
            }
            return false;
        },

        isClockwise: function(){
            var isClockwise = function( a, b, c ){
                var determ = (b.x-a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
                return (determ < 0.0);
            };
            if(this.vertices.length > 2){
                return isClockwise(this.vertices[0],this.vertices[1],this.vertices[2]);
            }
            return false;
        },

        intersectsPoly: function(poly) {
            if (!this.containsPolygon(poly)) {
                var edges=this.getEdges();
                var pedges=poly.getEdges();
                for(var i=0, n=edges.length; i < n; i++) {
                    for(var j=0, m = pedges.length, e = edges[i]; j < m; j++) {
                        if (e.intersectLine(pedges[j]).getType() == Line2D.LineIntersection.Type.INTERSECTING) {
                            return true;
                        }
                    }
                }
                return false;
            } else {
                return true;
            }
        },

        /**
        * Removes duplicate vertices from the polygon. Only successive points are
        * recognized as duplicates.
        * @param {Number} tolerance snap distance for finding duplicates
        * @return itself
        */
        removeDuplicates: function( tolerance ){
            //if tolerance is 0, it will be faster to just use 'equals' method
            var equals = tolerance ? 'equalsWithTolerance' : 'equals';
            var p, prev, i = 0, num = this.vertices.length;
            var last;
            for( ; i<num; i++ ){
                p = this.vertices[i];
                //if its the 'equals' method tolerance will just be ingored
                if( p[equals]( prev, tolerance ) ){
                    //remove from array, step back counter
                    this.vertices.splice( i, 1 );
                    i--;
                    num--;
                } else {
                    prev = p;
                }
            }
            num = this.vertices.length;
            if( num >  0 ){
                last = this.vertices[num-1];
                if( last[equals]( this.vertices[0], tolerance ) ){
                    this.vertices.splice( num-1, 1 );
                }
            }
            return this;
        },

        rotate: function(theta) {
            for (var i=0, num=this.vertices.length; i < num; i++) {
                this.vertices[i].rotate(theta);
            }
        },

        scale: function() {
            var x,y;
            if (arguments.length==1) {
                var arg = arguments[0];
                if( has.XY( arg ) ){
                    x=arg.x;
                    y=arg.y;
                } else {
                    // uniform scale
                    x=arg;
                    y=arg;
                }
            } else if (arguments.length==2) {
                x=arguments[0];
                y=arguments[1];
            } else {
                throw "Invalid argument(s) passed.";
            }
            for (var i=0, num=this.vertices.length; i < num; i++) {
                this.vertices[i].scaleSelf(x, y);
            }
            return this;
        },

        translate: function() {
            var x,y;
            if (arguments.length==1 && has.XY( arguments[0] ) ){
                x=arguments[0].x;
                y=arguments[0].y;
            } else if (arguments.length==2) {
                x=arguments[0];
                y=arguments[1];
            } else {
                throw "Invalid argument(s) passed.";
            }
            for (var i=0, num=this.vertices.length; i < num; i++) {
                this.vertices[i].addSelf(x, y);
            }
            return this;
        },

        smooth: function(amount, baseWeight){
            var centroid = this.getCentroid();
            var num = this.vertices.length;
            var filtered = [];
            for(var i=0,j=num-1,k=1;i<num;i++){
                var a = this.vertices[i];
                var dir = this.vertices[j].sub(a).addSelf(this.vertices[k].sub(a))
                    .addSelf(a.sub(centroid).scaleSelf(baseWeight));
                filtered.push(a.add(dir.scaleSelf(amount)));
                j++;
                if(j == num){
                    j=0;
                }
                k++;
                if(k == num){
                    k=0;
                }
            }
            this.vertices = filtered;
            return this;
        },

        toString: function(){
            var s = "";
            for(var i=0;i<this.vertices.length;i++){
                s += this.vertices[i];
                if(i<this.vertices.length-1){
                    s+= ", ";
                }
            }
            return s;
        }

    };

    /**
    * Constructs a new regular polygon from the given base line/edge.
    * @param {Vec2D} baseA left point of the base edge
    * @param {Vec2D} baseB right point of the base edge
    * @param {Number} res number of polygon vertices
    * @return polygon
    */
    Polygon2D.fromBaseEdge = function( baseA, baseB, res ){
        var theta = -( MathUtils.PI - (MathUtils.PI*(res-2) / res) ),
            dir = baseB.sub( baseA ),
            prev = baseB,
            poly = new Polygon2D( baseA, baseB ),
            p;
        for( var i=0; i< res-1; i++){
            p = prev.add( dir.getRotated(theta*i) );
            poly.add( p );
            prev = p;
        }
        return poly;
    };

    /**
    * Constructs a regular polygon from the given edge length and number of
    * vertices. This automatically computes the radius of the circle the
    * polygon is inscribed in.
    * More information: http://en.wikipedia.org/wiki/Regular_polygon#Radius
    *
    * @param {Number} len desired edge length
    * @param {Number} res number of vertices
    * @return polygon
    */
    Polygon2D.fromEdgeLength = function( len, res ){
        var Circle = require('./Circle');
        return new Circle( Polygon2D.getRadiusForEdgeLength(len,res) ).toPolygon2D( res );
    };

    /**
    * Computes the radius of the circle the regular polygon with the desired
    * edge length is inscribed in
    * @param {Number} len edge length
    * @param {Number} res number of polygon vertices
    * @return radius
    */
    Polygon2D.getRadiusForEdgeLength = function( len, res ){
        return len / ( 2 * MathUtils.sin(MathUtils.PI/res) );
    };

    return Polygon2D;
});
<|endoftext|>


<commit_before>var conjectures = [];

function guessIncidences(el) {
    if (guessIncidences.hasOwnProperty(el.kind))
        guessIncidences[el.kind](el);
}

guessIncidences.P = function(p) {
    csgeo.lines.forEach(function(l) {
        var conjecture = incidentPL(p, l);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
    csgeo.conics.forEach(function(c) {
        var conjecture = incidentPC(p, c);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
};

guessIncidences.L = function(l) {
    csgeo.points.forEach(function(p) {
        var conjecture = incidentPL(p, l);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
};

guessIncidences.S = guessIncidences.L;

guessIncidences.C = function(c) {
    csgeo.points.forEach(function(p) {
        var conjecture = incidentPC(p, c);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
};

function applyIncidence(a, b) {
    return function() {
        a.incidences.push(b.name);
        b.incidences.push(a.name);
    };
}

function incidentPL(p, l) {
    return {
        toString: function() {
            return "point " + p.name + " incident line " + l.name;
        },
        apply: applyIncidence(p, l),
        holds: function() {
            var pn = List.scaldiv(List.abs(p.homog), p.homog);
            var ln = List.scaldiv(List.abs(l.homog), l.homog);
            var prod = CSNumber.abs(List.scalproduct(pn, ln));
            return (prod.value.real < 0.0000000000001);
        }
    };
}

function incidentPC(p, c) {
    return {
        toString: function() {
            return "point " + p.name + " incident conic " + c.name;
        },
        apply: applyIncidence(p, c),
        holds: function() {
            var erg = General.mult(c.matrix, p.homog);
            erg = General.mult(p.homog, erg);
            erg = CSNumber.abs(erg);
            if (erg.value.real < 0.0000000000001) {
                p.incidences.push(c.name);
                c.incidences.push(p.name);
            }
        }
    };
}

function checkConjectures() {
    if (conjectures.length === 0) return;
    //    debugger;
    backupGeo();
    // TODO: we need some randomized proving here:
    // move free elements and check conjectures a number of times.
    // For now assume that all conjectures could be verified.

    var ii, jj, kk;
    var free = csgeo.free;
    var newpos, el;
    var nummoves = 3;

    console.log("con before", conjectures);
    // iterate over all elements
    for (ii = 0; ii < free.length; ii++) {
        el = free[ii];
        // iterate over moves
        for (jj = 0; jj < nummoves; jj++) {
            newpos = geoOps[el.type].getRandomMove(el);
            movepointscr(el, newpos, "homog");
            // check if conjecture still holds
            conjectures = conjectures.filter(function(con){
                return con.holds();
            });
        } // end jj
    } // end ii
    console.log("con after", conjectures);

    restoreGeo();

    for (var i = 0; i < conjectures.length; ++i) {
        conjectures[i].apply();
    }
    conjectures = [];
}
<commit_msg>loops<commit_after>var conjectures = [];

function guessIncidences(el) {
    if (guessIncidences.hasOwnProperty(el.kind))
        guessIncidences[el.kind](el);
}

guessIncidences.P = function(p) {
    csgeo.lines.forEach(function(l) {
        var conjecture = incidentPL(p, l);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
    csgeo.conics.forEach(function(c) {
        var conjecture = incidentPC(p, c);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
};

guessIncidences.L = function(l) {
    csgeo.points.forEach(function(p) {
        var conjecture = incidentPL(p, l);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
};

guessIncidences.S = guessIncidences.L;

guessIncidences.C = function(c) {
    csgeo.points.forEach(function(p) {
        var conjecture = incidentPC(p, c);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
};

function applyIncidence(a, b) {
    return function() {
        a.incidences.push(b.name);
        b.incidences.push(a.name);
    };
}

function incidentPL(p, l) {
    return {
        toString: function() {
            return "point " + p.name + " incident line " + l.name;
        },
        apply: applyIncidence(p, l),
        holds: function() {
            var pn = List.scaldiv(List.abs(p.homog), p.homog);
            var ln = List.scaldiv(List.abs(l.homog), l.homog);
            var prod = CSNumber.abs(List.scalproduct(pn, ln));
            return (prod.value.real < 0.0000000000001);
        }
    };
}

function incidentPC(p, c) {
    return {
        toString: function() {
            return "point " + p.name + " incident conic " + c.name;
        },
        apply: applyIncidence(p, c),
        holds: function() {
            var erg = General.mult(c.matrix, p.homog);
            erg = General.mult(p.homog, erg);
            erg = CSNumber.abs(erg);
            if (erg.value.real < 0.0000000000001) {
                p.incidences.push(c.name);
                c.incidences.push(p.name);
            }
        }
    };
}

function checkConjectures() {
    if (conjectures.length === 0) return;
    //    debugger;
    backupGeo();
    // TODO: we need some randomized proving here:
    // move free elements and check conjectures a number of times.
    // For now assume that all conjectures could be verified.

    var ii, jj, kk;
    var free = csgeo.free;
    var newpos, el;
    var nummoves = 3;

    console.log("con before", conjectures);
    csgeo.free.forEach(function(el){
        jj = nummoves;
        while(jj--){
            newpos = geoOps[el.type].getRandomMove(el);
            movepointscr(el, newpos, "homog");
            // check if conjecture still holds
            conjectures = conjectures.filter(function(con){
                return con.holds();
            });
        }
    });
    console.log("con after", conjectures);

    restoreGeo();

    for (var i = 0; i < conjectures.length; ++i) {
        conjectures[i].apply();
    }
    conjectures = [];
}
<|endoftext|>


<commit_before>var conjectures = [];

function guessIncidences(el) {
    if (guessIncidences.hasOwnProperty(el.kind))
        guessIncidences[el.kind](el);
}

guessIncidences.P = function(p) {
    csgeo.lines.forEach(function(l) {
        var conjecture = incidentPL(p, l);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
    csgeo.conics.forEach(function(c) {
        var conjecture = incidentPC(p, c);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
};

guessIncidences.L = function(l) {
    csgeo.points.forEach(function(p) {
        var conjecture = incidentPL(p, l);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
};

guessIncidences.S = guessIncidences.L;

guessIncidences.C = function(c) {
    csgeo.points.forEach(function(p) {
        var conjecture = incidentPC(p, c);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
};

function applyIncidence(a, b) {
    return function() {
        a.incidences.push(b.name);
        b.incidences.push(a.name);
    };
}

function incidentPL(p, l) {
    return {
        getInvolved: function() {
            return [p, l];
        },
        toString: function() {
            return "point " + p.name + " incident line " + l.name;
        },
        apply: applyIncidence(p, l),
        holds: function() {
            var pn = List.scaldiv(List.abs(p.homog), p.homog);
            var ln = List.scaldiv(List.abs(l.homog), l.homog);
            var prod = CSNumber.abs(List.scalproduct(pn, ln));
            return (prod.value.real < 0.0000000000001);
        }
    };
}

function incidentPC(p, c) {
    return {
        getInvolved: function() {
            return [p, c];
        },
        toString: function() {
            return "point " + p.name + " incident conic " + c.name;
        },
        apply: applyIncidence(p, c),
        holds: function() {
            var erg = General.mult(c.matrix, p.homog);
            erg = General.mult(p.homog, erg);
            erg = CSNumber.abs(erg);
            return (erg.value.real < 0.0000000000001);
        }
    };
}

function checkConjectures() {
    var debug = true;
    if (debug) console.log("conjectures", conjectures.length);
    //if (!debug)
    if (conjectures.length === 0) return;
    backupGeo();

    var ii, jj, emove;
    var nummoves = 3;

    // filter free objects which are involved in conjectures
    var involved = [];
    conjectures.forEach(function(con) {
        var invs = con.getInvolved();
        invs = invs.forEach(function(el) {
            if (involved.indexOf(el) < 0 && csgeo.free.indexOf(el) >= 0) involved.push(el);
        });
    });

    // debug code remove later
    var nconject = conjectures.length;
    involved.forEach(function(el) {
        ii = nummoves;
        while (ii--) {
            if (el.pinned) {
                break;
            }
            if (debug) console.log("prover: moving element", el.name);
            // get random move and move free element
            emove = geoOps[el.type].getRandomMove(el);
            movepointscr(el, emove.value, emove.type);
            // if something bad happens
            if (tracingFailed) stateIn.set(stateLastGood);
            // check if conjecture still holds
            conjectures = conjectures.filter(function(con) {
                return con.holds();
            });
        }
    });

    if (debug) {
        console.log("dropped ", nconject - conjectures.length, " conjectures");
    }

    if (!debug) {
        restoreGeo();
    }

    for (var i = 0; i < conjectures.length; ++i) {
        conjectures[i].apply();
    }
    conjectures = [];
    if (debug) {
        csgeo.gslp.forEach(function(el) {
            console.log(el.name, el.incidences);
        });
    }
}
<commit_msg>introduce recalcinvolved<commit_after>var conjectures = [];

function guessIncidences(el) {
    if (guessIncidences.hasOwnProperty(el.kind))
        guessIncidences[el.kind](el);
}

guessIncidences.P = function(p) {
    csgeo.lines.forEach(function(l) {
        var conjecture = incidentPL(p, l);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
    csgeo.conics.forEach(function(c) {
        var conjecture = incidentPC(p, c);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
};

guessIncidences.L = function(l) {
    csgeo.points.forEach(function(p) {
        var conjecture = incidentPL(p, l);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
};

guessIncidences.S = guessIncidences.L;

guessIncidences.C = function(c) {
    csgeo.points.forEach(function(p) {
        var conjecture = incidentPC(p, c);
        if (conjecture.holds())
            conjectures.push(conjecture);
    });
};

function applyIncidence(a, b) {
    return function() {
        a.incidences.push(b.name);
        b.incidences.push(a.name);
    };
}

function incidentPL(p, l) {
    return {
        getInvolved: function() {
            return [p, l];
        },
        toString: function() {
            return "point " + p.name + " incident line " + l.name;
        },
        apply: applyIncidence(p, l),
        holds: function() {
            var pn = List.scaldiv(List.abs(p.homog), p.homog);
            var ln = List.scaldiv(List.abs(l.homog), l.homog);
            var prod = CSNumber.abs(List.scalproduct(pn, ln));
            return (prod.value.real < 0.0000000000001);
        }
    };
}

function incidentPC(p, c) {
    return {
        getInvolved: function() {
            return [p, c];
        },
        toString: function() {
            return "point " + p.name + " incident conic " + c.name;
        },
        apply: applyIncidence(p, c),
        holds: function() {
            var erg = General.mult(c.matrix, p.homog);
            erg = General.mult(p.homog, erg);
            erg = CSNumber.abs(erg);
            return (erg.value.real < 0.0000000000001);
        }
    };
}

function checkConjectures() {
    var debug = true;
    if (debug) console.log("conjectures", conjectures.length);
    //if (!debug)
    if (conjectures.length === 0) return;
    backupGeo();

    var ii, jj, emove;
    var nummoves = 3;

    // filter free objects which are involved in conjectures
    var involved;

    var recalcInvolved = function(){
        involved = [];
        conjectures.forEach(function(con) {
            var invs = con.getInvolved();
            invs = invs.forEach(function(el) {
                if (involved.indexOf(el) < 0 && el.moveable) involved.push(el);
            });
        });
    }

    recalcInvolved();

    // debug code remove later
    var nconject = conjectures.length;
    involved.forEach(function(el) {
        ii = nummoves;
        while (ii--) {
            if (el.pinned) {
                break;
            }
            if (debug) console.log("prover: moving element", el.name);
            // get random move and move free element
            emove = geoOps[el.type].getRandomMove(el);
            movepointscr(el, emove.value, emove.type);
            // if something bad happens
            if (tracingFailed) stateIn.set(stateLastGood);
            // check if conjecture still holds
            conjectures = conjectures.filter(function(con) {
                return con.holds();
            });
        } // while
    });

    if (debug) {
        console.log("dropped ", nconject - conjectures.length, " conjectures");
    }

    if (!debug) {
        restoreGeo();
    }

    for (var i = 0; i < conjectures.length; ++i) {
        conjectures[i].apply();
    }
    conjectures = [];
    if (debug) {
        csgeo.gslp.forEach(function(el) {
            console.log(el.name, el.incidences);
        });
    }
}
<|endoftext|>


<commit_before>import ElasticSearchDataSyncer from './data-syncer'

if (Meteor.isServer) {
  var Future = Npm.require('fibers/future'),
    elasticsearch = Npm.require('elasticsearch');
}

/**
 * The ElasticsearchEngine lets you search documents through an Elasticsearch Index.
 *
 * @type {ElasticSearchEngine}
 */
 class ElasticSearchEngine extends EasySearch.ReactiveEngine {
  /**
   * Constructor.
   */
  constructor() {
    super(...arguments);
  }

  /**
   * Return default configuration.
   *
   * @returns {Object}
   */
  defaultConfiguration() {
    return _.defaults({}, ElasticSearchEngine.defaultElasticsearchConfiguration(), super.defaultConfiguration());
  }

  /**
   * Default configuration.
   *
   * @returns {Object}
   */
  static defaultElasticsearchConfiguration() {
    return {
      indexName: 'easysearch',
      /**
       * Return the fields to index in ElasticSearch.
       *
       * @param {Object} options Index options
       *
       * @returns {null|Array}
       */
      fieldsToIndex(options) {
        return null;
      },
      /**
       * The ES query object used for searching the results.
       *
       * @param {Object} searchObject Search object
       * @param {Object} options      Search options
       *
       * @return array
       */
      query(searchObject, options) {
        let query = {
          bool: {
            should: []
          }
        };

        _.each(searchObject, function (searchString, field) {
          query.bool.should.push({
            match: {
              [field]: {
                query: searchString,
                fuzziness: 'AUTO',
                operator:  'or'
              }
            }
          });
        });

        return query;
      },
      /**
       * The ES sorting method used for sorting the results.
       *
       * @param {Object} searchObject Search object
       * @param {Object} options      Search options
       *
       * @return array
       */
      sort(searchObject, options) {
        return options.index.fields;
      },
      /**
       * Return the ElasticSearch document to index.
       *
       * @param {Object} doc    Document to index
       * @param {Array}  fields Array of document fields
       */
      getElasticSearchDoc(doc, fields) {
        if (null === fields) {
          return doc;
        }

        let partialDoc = {};

        _.each(fields, function (field) {
          if (_.has(doc, field)) {
            partialDoc[field] = _.get(doc, field);
          }
        });

        return partialDoc;
      },
      /**
       * Return the elastic search body.
       *
       * @param {Object} body Existing ES body
       *
       * @return {Object}
       */
      body: (body) => body,
      /**
       * Default ES client configuration.
       */
      client: {
        host: 'localhost:9200',
      },
    };
  }

  /**
   * Put mapping according to mapping field provided when creating an EasySearch index
   *
   * @param {Object}   indexConfig Index configuration
   * @param {Function} cb          callback on finished mapping
   */
  putMapping(indexConfig = {}, cb) {
    const {
      mapping: body,
      elasticSearchClient,
    } = indexConfig;

    if (!body) {
      return cb();
    }

    const { indexName } = this.config
    const type = this.getIndexType()

    elasticSearchClient.indices.create({
      updateAllTypes: false,
      index: indexName,
    }, Meteor.bindEnvironment(() => {
      elasticSearchClient.indices.getMapping({
        index: indexName,
        type
      }, Meteor.bindEnvironment((err, res) => {
        const isEmpty = Object.keys(res).length === 0 && res.constructor === Object;
        if (!isEmpty) {
          return cb();
        }

        elasticSearchClient.indices.putMapping({
          updateAllTypes: false,
          index: indexName,
          type,
          body
        }, cb);
      }));
    }));
  }

  /**
   * @returns {String}
   */
  getIndexType(indexConfig) {
    return this.config.indexType || indexConfig.name;
  }

  /**
   * Act on index creation.
   *
   * @param {Object} indexConfig Index configuration
   */
  onIndexCreate(indexConfig) {
    super.onIndexCreate(indexConfig);

    if (Meteor.isServer) {
      indexConfig.elasticSearchClient = new elasticsearch.Client(this.config.client);
      this.putMapping(indexConfig, Meteor.bindEnvironment(() => {
        indexConfig.elasticSearchSyncer = new ElasticSearchDataSyncer({
          indexName: this.config.indexName,
          indexType: this.getIndexType(indexConfig),
          collection: indexConfig.collection,
          client: indexConfig.elasticSearchClient,
          beforeIndex: (doc) => this.callConfigMethod('getElasticSearchDoc', doc, this.callConfigMethod('fieldsToIndex', indexConfig))
        });
      }));
    }
  }

  /**
   * Return the reactive search cursor.
   *
   * @param {Object} searchDefinition Search definition
   * @param {Object} options          Search and index options
   */
  getSearchCursor(searchDefinition, options) {
    let fut = new Future(),
      body = {};

    searchDefinition = EasySearch.MongoDB.prototype.transformSearchDefinition(searchDefinition, options);

    body.query = this.callConfigMethod('query', searchDefinition, options);
    body.sort = this.callConfigMethod('sort', searchDefinition, options);
    body.fields = ['_id'];

    body = this.callConfigMethod('body', body, options);

    options.index.elasticSearchClient.search({
      index: this.config.indexName,
      type: this.getIndexType(options.index),
      body: body,
      size: options.search.limit,
      from: options.search.skip
    }, Meteor.bindEnvironment((error, data) => {
      if (error) {
        console.log('Had an error while searching!');
        console.log(error);
        return;
      }

      let { total, ids } = this.getCursorData(data),
        cursor;

      if (ids.length > 0) {
        cursor = options.index.collection.find({
          $or: _.map(ids, (_id) => {
            return { _id };
          })
        }, { limit: options.search.limit });
      } else {
        cursor = EasySearch.Cursor.emptyCursor;
      }

      fut['return'](new EasySearch.Cursor(cursor, total));
    }));

    return fut.wait();
  }

  /**
   * Get data for the cursor from the elastic search response.
   *
   * @param {Object} data ElasticSearch data
   *
   * @returns {Object}
   */
  getCursorData(data) {
    return {
      ids : _.map(data.hits.hits, (resultSet) => resultSet._id),
      total: data.hits.total
    };
  }
}

EasySearch.ElasticSearch = ElasticSearchEngine

export default ElasticSearchEngine
<commit_msg>fix missing param<commit_after>import ElasticSearchDataSyncer from './data-syncer'

if (Meteor.isServer) {
  var Future = Npm.require('fibers/future'),
    elasticsearch = Npm.require('elasticsearch');
}

/**
 * The ElasticsearchEngine lets you search documents through an Elasticsearch Index.
 *
 * @type {ElasticSearchEngine}
 */
 class ElasticSearchEngine extends EasySearch.ReactiveEngine {
  /**
   * Constructor.
   */
  constructor() {
    super(...arguments);
  }

  /**
   * Return default configuration.
   *
   * @returns {Object}
   */
  defaultConfiguration() {
    return _.defaults({}, ElasticSearchEngine.defaultElasticsearchConfiguration(), super.defaultConfiguration());
  }

  /**
   * Default configuration.
   *
   * @returns {Object}
   */
  static defaultElasticsearchConfiguration() {
    return {
      indexName: 'easysearch',
      /**
       * Return the fields to index in ElasticSearch.
       *
       * @param {Object} options Index options
       *
       * @returns {null|Array}
       */
      fieldsToIndex(options) {
        return null;
      },
      /**
       * The ES query object used for searching the results.
       *
       * @param {Object} searchObject Search object
       * @param {Object} options      Search options
       *
       * @return array
       */
      query(searchObject, options) {
        let query = {
          bool: {
            should: []
          }
        };

        _.each(searchObject, function (searchString, field) {
          query.bool.should.push({
            match: {
              [field]: {
                query: searchString,
                fuzziness: 'AUTO',
                operator:  'or'
              }
            }
          });
        });

        return query;
      },
      /**
       * The ES sorting method used for sorting the results.
       *
       * @param {Object} searchObject Search object
       * @param {Object} options      Search options
       *
       * @return array
       */
      sort(searchObject, options) {
        return options.index.fields;
      },
      /**
       * Return the ElasticSearch document to index.
       *
       * @param {Object} doc    Document to index
       * @param {Array}  fields Array of document fields
       */
      getElasticSearchDoc(doc, fields) {
        if (null === fields) {
          return doc;
        }

        let partialDoc = {};

        _.each(fields, function (field) {
          if (_.has(doc, field)) {
            partialDoc[field] = _.get(doc, field);
          }
        });

        return partialDoc;
      },
      /**
       * Return the elastic search body.
       *
       * @param {Object} body Existing ES body
       *
       * @return {Object}
       */
      body: (body) => body,
      /**
       * Default ES client configuration.
       */
      client: {
        host: 'localhost:9200',
      },
    };
  }

  /**
   * Put mapping according to mapping field provided when creating an EasySearch index
   *
   * @param {Object}   indexConfig Index configuration
   * @param {Function} cb          callback on finished mapping
   */
  putMapping(indexConfig = {}, cb) {
    const {
      mapping: body,
      elasticSearchClient,
    } = indexConfig;

    if (!body) {
      return cb();
    }

    const { indexName } = this.config
    const type = this.getIndexType(indexConfig)

    elasticSearchClient.indices.create({
      updateAllTypes: false,
      index: indexName,
    }, Meteor.bindEnvironment(() => {
      elasticSearchClient.indices.getMapping({
        index: indexName,
        type
      }, Meteor.bindEnvironment((err, res) => {
        const isEmpty = Object.keys(res).length === 0 && res.constructor === Object;
        if (!isEmpty) {
          return cb();
        }

        elasticSearchClient.indices.putMapping({
          updateAllTypes: false,
          index: indexName,
          type,
          body
        }, cb);
      }));
    }));
  }

  /**
   * @returns {String}
   */
  getIndexType(indexConfig) {
    return this.config.indexType || indexConfig.name;
  }

  /**
   * Act on index creation.
   *
   * @param {Object} indexConfig Index configuration
   */
  onIndexCreate(indexConfig) {
    super.onIndexCreate(indexConfig);

    if (Meteor.isServer) {
      indexConfig.elasticSearchClient = new elasticsearch.Client(this.config.client);
      this.putMapping(indexConfig, Meteor.bindEnvironment(() => {
        indexConfig.elasticSearchSyncer = new ElasticSearchDataSyncer({
          indexName: this.config.indexName,
          indexType: this.getIndexType(indexConfig),
          collection: indexConfig.collection,
          client: indexConfig.elasticSearchClient,
          beforeIndex: (doc) => this.callConfigMethod('getElasticSearchDoc', doc, this.callConfigMethod('fieldsToIndex', indexConfig))
        });
      }));
    }
  }

  /**
   * Return the reactive search cursor.
   *
   * @param {Object} searchDefinition Search definition
   * @param {Object} options          Search and index options
   */
  getSearchCursor(searchDefinition, options) {
    let fut = new Future(),
      body = {};

    searchDefinition = EasySearch.MongoDB.prototype.transformSearchDefinition(searchDefinition, options);

    body.query = this.callConfigMethod('query', searchDefinition, options);
    body.sort = this.callConfigMethod('sort', searchDefinition, options);
    body.fields = ['_id'];

    body = this.callConfigMethod('body', body, options);

    options.index.elasticSearchClient.search({
      index: this.config.indexName,
      type: this.getIndexType(options.index),
      body: body,
      size: options.search.limit,
      from: options.search.skip
    }, Meteor.bindEnvironment((error, data) => {
      if (error) {
        console.log('Had an error while searching!');
        console.log(error);
        return;
      }

      let { total, ids } = this.getCursorData(data),
        cursor;

      if (ids.length > 0) {
        cursor = options.index.collection.find({
          $or: _.map(ids, (_id) => {
            return { _id };
          })
        }, { limit: options.search.limit });
      } else {
        cursor = EasySearch.Cursor.emptyCursor;
      }

      fut['return'](new EasySearch.Cursor(cursor, total));
    }));

    return fut.wait();
  }

  /**
   * Get data for the cursor from the elastic search response.
   *
   * @param {Object} data ElasticSearch data
   *
   * @returns {Object}
   */
  getCursorData(data) {
    return {
      ids : _.map(data.hits.hits, (resultSet) => resultSet._id),
      total: data.hits.total
    };
  }
}

EasySearch.ElasticSearch = ElasticSearchEngine

export default ElasticSearchEngine
<|endoftext|>


<commit_before>angular.module('grisu-noe').controller('overviewTabController',
    function($scope, $rootScope, dataService, util, $ionicModal, $state,
             $window, storageService, $cordovaClipboard, $cordovaToast, $ionicPopover, md5) {

    var easterEggClickCount;
    var calculatedHashes;

    $scope.doRefresh = function(loadFromCache) {
        util.genericRefresh($scope, dataService.getMainData(loadFromCache), function(data) {
            $scope.mainData = data;

            var svg = document.getElementsByClassName('lower-austria-map');
            var warnStatesString = dataService.getConfig().warnStates.join(' ');

            // cleanup of css classes
            angular.forEach(svg[0].getElementsByTagName('path'), function(path) {
                angular.element(path).removeClass(warnStatesString);
            });

            // add new classes to colorize map
            angular.forEach(data.mapColorStates, function(colorState) {
                var paths = svg[0].getElementsByClassName(colorState.key);
                angular.forEach(paths, function(path) {
                    angular.element(path).addClass(colorState.value);
                });
            });
        });

        if (!$scope.settings.showExtendedIncidentData) {
            return;
        }

        util.genericRefresh($scope, dataService.getInfoMessages(), function(data) {
            if (data.CurrentState != 'data') {
                $scope.messagesError = true;
                return;
            }
            handleInfoMessages(data.Infos);
        }, { hideRefreshers: false });
    };

    function handleInfoMessages(messages) {
        var storedHashes = storageService.get('messages', []);
        $scope.hasNewMessages = false;
        calculatedHashes = [];

        angular.forEach(messages, function(message) {
            var hash = md5.createHash(message.Title + message.Text);
            calculatedHashes.push(hash);
            if (storedHashes.indexOf(hash) === -1) {
                $scope.hasNewMessages = true;
            }
        });

        $scope.infoMessages = messages;
    }

    $scope.$on('cordova.resume', function() {
        $scope.doRefresh(false);
    });

    $scope.$on('$ionicView.enter', function() {
        $scope.doRefresh(true);

        if (!$scope.settings.showExtendedIncidentData || !angular.isUndefinedOrNull($scope.homeAddress)) {
            return;
        }

        dataService.getInfoscreenConfig().then(function(data) {
            $scope.homeAddress = data.Config.HomeAddress;
        });
    });

    $scope.onMapClicked = function(event) {
        var district = event.target.classList[0];
        var mappings = dataService.getConfig().districtMapMappings;
        for (var key in mappings) {
            if (mappings.hasOwnProperty(key)) {
                if (mappings[key] === district) {
                    $state.go('tabs.overview-incidents', { id: key });
                }
            }
        }
    };

    $scope.$on('$ionicView.loaded', function() {
        easterEggClickCount = 0;
        $scope.settings = storageService.getObject('settings');
        $scope.magicCookie = storageService.getObject('magicCookie');

        if ($scope.settings.jumpToDistrict === true &&
            $scope.settings.myDistrict.k !== 'LWZ' &&
            $rootScope.alreadyJumpedToDistrict !== true) {

            $rootScope.alreadyJumpedToDistrict = true;
            $state.go('tabs.overview-incidents', {
                id: $scope.settings.myDistrict.k
            });
        }

        $ionicModal.fromTemplateUrl('templates/about.html', {
            scope: $scope,
            animation: 'slide-in-up'
        }).then(function(modal) {
            $scope.date = new Date();
            $scope.aboutDialog = modal;
        });

        $ionicModal.fromTemplateUrl('templates/settings.html', {
            scope: $scope,
            animation: 'slide-in-up'
        }).then(function(modal) {
            if (!$scope.settings.myDistrict) {
                $scope.settings.myDistrict = {
                    k: 'LWZ'
                };
            }

            if (angular.isUndefinedOrNull($scope.settings.showIncidentDistance)) {
                $scope.settings.showIncidentDistance = true;
            }

            if (angular.isUndefinedOrNull($scope.settings.showIncidentHydrants)) {
                $scope.settings.showIncidentHydrants = true;
            }

            $scope.$watch('settings', function(newValue, oldValue) {
                console.debug('Settings changed', oldValue, newValue);
                storageService.setObject('settings', newValue);
            }, true);

            $scope.settingsDialog = modal;
        });

        $ionicModal.fromTemplateUrl('templates/info-messages.html', {
            scope: $scope,
            animation: 'slide-in-up'
        }).then(function(modal) {
            $scope.infoMessagesDialog = modal;
        });

        $ionicPopover.fromTemplateUrl('templates/magic-cookie.html', {
            scope: $scope
        }).then(function(popover) {
            // check for empty object
            if (angular.toJson($scope.magicCookie) === '{}') {
                $scope.magicCookie = {
                    value: '',
                    active: false
                };
            }

            $scope.$watch('magicCookie', function(newValue, oldValue) {
                console.debug('Magic cookie changed', oldValue, newValue);
                storageService.setObject('magicCookie', newValue);
            }, true);

            $scope.popover = popover;
        });
    });

    $scope.onExtendedIncidentDataChanged = function() {
        updateToken();
    };

    function updateToken() {
        if (!$scope.settings.showExtendedIncidentData) {
            return;
        }

        $scope.loadingTokenInfo = true;

        util.genericRefresh($scope, dataService.getInfoScreenData(false), function(data) {
            if (data.CurrentState == 'token' || data.CurrentState == 'waiting') {
                $scope.token = data.Token;
                $scope.waitForToken = true;
            } else {
                $scope.waitForToken = false;
            }

            $scope.loadingTokenInfo = false;
        });
    }

    $scope.copyTokenToClipboard = function() {
        if (!$window.cordova) {
            return;
        }

        $cordovaClipboard.copy($scope.token).then(function() {
            $cordovaToast.showShortBottom('Code wurde in die Zwischenablage kopiert');
        });
    };

    $scope.openAboutDialog = function() {
        $scope.aboutDialog.show();
    };

    $scope.closeAboutDialog = function() {
        $scope.aboutDialog.hide();
    };

    $scope.openSettingsDialog = function() {
        updateToken();
        $scope.settingsDialog.show();
    };

    $scope.closeSettingsDialog = function() {
        $scope.settingsDialog.hide();
    };

    $scope.openInfoMessagesDialog = function() {
        storageService.setObject('messages', calculatedHashes);
        $scope.hasNewMessages = false;
        $scope.infoMessagesDialog.show();
    };

    $scope.closeInfoMessagesDialog = function() {
        $scope.infoMessagesDialog.hide();
    };

    $scope.$on('$destroy', function() {
        $scope.aboutDialog.remove();
        $scope.settingsDialog.remove();
        $scope.infoMessagesDialog.remove();
        $scope.popover.remove();
    });

    $scope.openPopover = function($event) {
        $scope.popover.show($event);
    };

    $scope.closePopover = function() {
        $scope.popover.hide();
    };

    $scope.onEasterEggClicked = function(event) {
        easterEggClickCount++;
        if (easterEggClickCount > 10) {
            easterEggClickCount = 0;
            $scope.openPopover(event);
        }
    };
});<commit_msg>close #113: check for valid token<commit_after>angular.module('grisu-noe').controller('overviewTabController',
    function($scope, $rootScope, dataService, util, $ionicModal, $state,
             $window, storageService, $cordovaClipboard, $cordovaToast, $ionicPopover, md5) {

    var easterEggClickCount;
    var calculatedHashes;

    $scope.doRefresh = function(loadFromCache) {
        util.genericRefresh($scope, dataService.getMainData(loadFromCache), function(data) {
            $scope.mainData = data;

            var svg = document.getElementsByClassName('lower-austria-map');
            var warnStatesString = dataService.getConfig().warnStates.join(' ');

            // cleanup of css classes
            angular.forEach(svg[0].getElementsByTagName('path'), function(path) {
                angular.element(path).removeClass(warnStatesString);
            });

            // add new classes to colorize map
            angular.forEach(data.mapColorStates, function(colorState) {
                var paths = svg[0].getElementsByClassName(colorState.key);
                angular.forEach(paths, function(path) {
                    angular.element(path).addClass(colorState.value);
                });
            });
        });

        if (!$scope.settings.showExtendedIncidentData) {
            return;
        }

        util.genericRefresh($scope, dataService.getInfoMessages(), function(data) {
            if (data.CurrentState != 'data') {
                $scope.messagesError = true;
                return;
            }
            handleInfoMessages(data.Infos);
        }, { hideRefreshers: false });
    };

    function handleInfoMessages(messages) {
        var storedHashes = storageService.get('messages', []);
        $scope.hasNewMessages = false;
        calculatedHashes = [];

        angular.forEach(messages, function(message) {
            var hash = md5.createHash(message.Title + message.Text);
            calculatedHashes.push(hash);
            if (storedHashes.indexOf(hash) === -1) {
                $scope.hasNewMessages = true;
            }
        });

        $scope.infoMessages = messages;
    }

    $scope.$on('cordova.resume', function() {
        $scope.doRefresh(false);
    });

    $scope.$on('$ionicView.enter', function() {
        $scope.doRefresh(true);

        if (!$scope.settings.showExtendedIncidentData || !angular.isUndefinedOrNull($scope.homeAddress)) {
            return;
        }

        dataService.getInfoscreenConfig().then(function(data) {
            if (data.CurrentState != 'data') {
                return;
            }
            $scope.homeAddress = data.Config.HomeAddress;
        });
    });

    $scope.onMapClicked = function(event) {
        var district = event.target.classList[0];
        var mappings = dataService.getConfig().districtMapMappings;
        for (var key in mappings) {
            if (mappings.hasOwnProperty(key)) {
                if (mappings[key] === district) {
                    $state.go('tabs.overview-incidents', { id: key });
                }
            }
        }
    };

    $scope.$on('$ionicView.loaded', function() {
        easterEggClickCount = 0;
        $scope.settings = storageService.getObject('settings');
        $scope.magicCookie = storageService.getObject('magicCookie');

        if ($scope.settings.jumpToDistrict === true &&
            $scope.settings.myDistrict.k !== 'LWZ' &&
            $rootScope.alreadyJumpedToDistrict !== true) {

            $rootScope.alreadyJumpedToDistrict = true;
            $state.go('tabs.overview-incidents', {
                id: $scope.settings.myDistrict.k
            });
        }

        $ionicModal.fromTemplateUrl('templates/about.html', {
            scope: $scope,
            animation: 'slide-in-up'
        }).then(function(modal) {
            $scope.date = new Date();
            $scope.aboutDialog = modal;
        });

        $ionicModal.fromTemplateUrl('templates/settings.html', {
            scope: $scope,
            animation: 'slide-in-up'
        }).then(function(modal) {
            if (!$scope.settings.myDistrict) {
                $scope.settings.myDistrict = {
                    k: 'LWZ'
                };
            }

            if (angular.isUndefinedOrNull($scope.settings.showIncidentDistance)) {
                $scope.settings.showIncidentDistance = true;
            }

            if (angular.isUndefinedOrNull($scope.settings.showIncidentHydrants)) {
                $scope.settings.showIncidentHydrants = true;
            }

            $scope.$watch('settings', function(newValue, oldValue) {
                console.debug('Settings changed', oldValue, newValue);
                storageService.setObject('settings', newValue);
            }, true);

            $scope.settingsDialog = modal;
        });

        $ionicModal.fromTemplateUrl('templates/info-messages.html', {
            scope: $scope,
            animation: 'slide-in-up'
        }).then(function(modal) {
            $scope.infoMessagesDialog = modal;
        });

        $ionicPopover.fromTemplateUrl('templates/magic-cookie.html', {
            scope: $scope
        }).then(function(popover) {
            // check for empty object
            if (angular.toJson($scope.magicCookie) === '{}') {
                $scope.magicCookie = {
                    value: '',
                    active: false
                };
            }

            $scope.$watch('magicCookie', function(newValue, oldValue) {
                console.debug('Magic cookie changed', oldValue, newValue);
                storageService.setObject('magicCookie', newValue);
            }, true);

            $scope.popover = popover;
        });
    });

    $scope.onExtendedIncidentDataChanged = function() {
        updateToken();
    };

    function updateToken() {
        if (!$scope.settings.showExtendedIncidentData) {
            return;
        }

        $scope.loadingTokenInfo = true;

        util.genericRefresh($scope, dataService.getInfoScreenData(false), function(data) {
            if (data.CurrentState == 'token' || data.CurrentState == 'waiting') {
                $scope.token = data.Token;
                $scope.waitForToken = true;
            } else {
                $scope.waitForToken = false;
            }

            $scope.loadingTokenInfo = false;
        });
    }

    $scope.copyTokenToClipboard = function() {
        if (!$window.cordova) {
            return;
        }

        $cordovaClipboard.copy($scope.token).then(function() {
            $cordovaToast.showShortBottom('Code wurde in die Zwischenablage kopiert');
        });
    };

    $scope.openAboutDialog = function() {
        $scope.aboutDialog.show();
    };

    $scope.closeAboutDialog = function() {
        $scope.aboutDialog.hide();
    };

    $scope.openSettingsDialog = function() {
        updateToken();
        $scope.settingsDialog.show();
    };

    $scope.closeSettingsDialog = function() {
        $scope.settingsDialog.hide();
    };

    $scope.openInfoMessagesDialog = function() {
        storageService.setObject('messages', calculatedHashes);
        $scope.hasNewMessages = false;
        $scope.infoMessagesDialog.show();
    };

    $scope.closeInfoMessagesDialog = function() {
        $scope.infoMessagesDialog.hide();
    };

    $scope.$on('$destroy', function() {
        $scope.aboutDialog.remove();
        $scope.settingsDialog.remove();
        $scope.infoMessagesDialog.remove();
        $scope.popover.remove();
    });

    $scope.openPopover = function($event) {
        $scope.popover.show($event);
    };

    $scope.closePopover = function() {
        $scope.popover.hide();
    };

    $scope.onEasterEggClicked = function(event) {
        easterEggClickCount++;
        if (easterEggClickCount > 10) {
            easterEggClickCount = 0;
            $scope.openPopover(event);
        }
    };
});<|endoftext|>


<commit_before>export { TestCase, moduleFor } from './abstract-test-case';
import {
  AbstractApplicationTest,
  AbstractRenderingTest
} from './abstract-test-case';
import assign from 'ember-metal/assign';
import { GLIMMER } from 'ember-application/system/engine';
import ComponentLookup from 'ember-views/component_lookup';

export class ApplicationTest extends AbstractApplicationTest {
  get applicationOptions() {
    return assign(super.applicationOptions, { [GLIMMER]: true });
  }
}

export class RenderingTest extends AbstractRenderingTest {
  constructor() {
    super();
    let { owner } = this;

    this.env = owner.lookup('service:-glimmer-environment');
    owner.register('component-lookup:main', ComponentLookup);
    owner.registerOptionsForType('helper', { instantiate: false });
    owner.registerOptionsForType('component', { singleton: false });
  }

  render(...args) {
    super.render(...args);
    this.renderer._root = this.component;
  }
}
<commit_msg>Remove unused [GLIMMER] flag<commit_after>export { TestCase, moduleFor } from './abstract-test-case';
import {
  AbstractApplicationTest,
  AbstractRenderingTest
} from './abstract-test-case';
import ComponentLookup from 'ember-views/component_lookup';

export class ApplicationTest extends AbstractApplicationTest {
}

export class RenderingTest extends AbstractRenderingTest {
  constructor() {
    super();
    let { owner } = this;

    this.env = owner.lookup('service:-glimmer-environment');
    owner.register('component-lookup:main', ComponentLookup);
    owner.registerOptionsForType('helper', { instantiate: false });
    owner.registerOptionsForType('component', { singleton: false });
  }

  render(...args) {
    super.render(...args);
    this.renderer._root = this.component;
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

define(function (require, exports, module) {
    "use strict";

    var Immutable = require("immutable");

    var layerLib = require("adapter/lib/layer"),
        objUtil = require("js/util/object");

    /**
     * Model document bounds or layer bounds without effects.
     *
     * @constructor
     * @param {object} model
     */
    var Bounds = Immutable.Record({
        /**
         * @type {number}
         */
        top: null,

        /**
         * @type {number}
         */
        bottom: null,

        /**
         * @type {number}
         */
        left: null,

        /**
         * @type {number}
         */
        right: null
    });

    Object.defineProperties(Bounds.prototype, objUtil.cachedGetSpecs({
        /**
         * Width of the bounding box.
         * @type {number}
         */
        "width": function () {
            return this.right - this.left;
        },
        /**
         * Height of the bounding box.
         * @type {number}
         */
        "height": function () {
            return this.bottom - this.top;
        },
        /**
         * Horizontal center of the bounding box.
         * @type {number}
         */
        "xCenter": function () {
            return this.left + (this.width / 2);
        },
        /**
         * Vertical center of the bounding box.
         * @type {number}
         */
        "yCenter": function () {
            return this.top + (this.height / 2);
        },
        /**
         * Area of the bounding box
         * @type {number}
         */
        "area": function () {
            return this.width * this.height;
        }
    }));

    /**
     * Create a new Bounds object from the given document descriptor.
     *
     * @param {object} descriptor Photoshop document descriptor
     * @return {Bounds}
     */
    Bounds.fromDocumentDescriptor = function (descriptor) {
        var resolution = descriptor.resolution.value,
            multiplier = resolution / 72,
            model = {};

        var height = descriptor.height.value * multiplier,
            width = descriptor.width.value * multiplier;

        model.top = 0;
        model.left = 0;
        model.bottom = height;
        model.right = width;

        return new Bounds(model);
    };

    /**
     * Create a new Bounds object from the given layer descriptor.
     *
     * @param {object} descriptor Photoshop layer descriptor
     * @return {Bounds}
     */
    Bounds.fromLayerDescriptor = function (descriptor) {
        // Photoshop's group bounds are not useful, so ignore them.
        switch (descriptor.layerKind) {
        case layerLib.layerKinds.GROUP:
        case layerLib.layerKinds.GROUPEND:
            return null;
        }

        var boundsObject = descriptor.boundsNoEffects.value,
            model = {};

        model.top = boundsObject.top.value;
        model.left = boundsObject.left.value;
        model.bottom = boundsObject.bottom.value;
        model.right = boundsObject.right.value;

        return new Bounds(model);
    };

    /**
     * Create a new bounds object from the union of the given bounds objects.
     * Returns null if no bounds objects are supplied.
     *
     * @param {Array.<Bounds>} childBounds
     * @return {?Bounds}
     */
    Bounds.union = function (childBounds) {
        if (childBounds.isEmpty()) {
            return null;
        }

        var startBounds = childBounds.first(),
            nextBounds = startBounds.withMutations(function (model) {
                childBounds.rest().forEach(function (child) {
                    model.top = Math.min(model.top, child.top);
                    model.left = Math.min(model.left, child.left);
                    model.bottom = Math.max(model.bottom, child.bottom);
                    model.right = Math.max(model.right, child.right);
                });
            });

        return nextBounds;
    };

    /**
     * Update the bounds object with the bounds descriptor.
     *
     * @param {object} descriptor layer bounds descriptor
     * @return {Bounds}
     */
    Bounds.prototype.resetFromDescriptor = function (descriptor) {
        var boundsObject = descriptor.value,
            model = {};

        model.top = boundsObject.top.value;
        model.left = boundsObject.left.value;
        model.bottom = boundsObject.bottom.value;
        model.right = boundsObject.right.value;

        return this.merge(model);
    };

    /**
     * Indicates whether the given point is contained in the bounding box.
     *
     * @param {number} x
     * @param {number} y
     * @return {boolean}
     */
    Bounds.prototype.contains = function (x, y) {
        return this.top <= y && y <= this.bottom &&
            this.left <= x && x <= this.right;
    };

    /**
     * Clones this bounds object with an updated position.
     *
     * @protected
     * @param {number=} x New X position
     * @param {number=} y New Y position
     * @return {Bounds} The updated bounds object
     */
    Bounds.prototype.updatePosition = function (x, y) {
        var width = this.width,
            height = this.height;

        return this.withMutations(function (model) {
            if (typeof x === "number") {
                model.left = x;
                model.right = x + width;
            }

            if (typeof y === "number") {
                model.top = y;
                model.bottom = y + height;
            }
        });
    };

    /**
     * Clones this bounds object with an updated size.
     *
     * @protected
     * @param {number=} w New width
     * @param {number=} h New height
     * @param {boolean=} proportional size change
     * @return {Bounds} The updated bounds object
     */
    Bounds.prototype.updateSize = function (w, h, proportional) {
        return this.withMutations(function (model) {
            if (typeof w === "number") {
                var oldWidth  = model.width;
                model.right = model.left + w;
                if (proportional) {
                    var newHeight = model.height / oldWidth * model.width;
                    model.bottom = model.top + newHeight;
                }
            }

            if (typeof h === "number") {
                var oldHeight  = model.height;
                model.bottom = model.top + h;
                if (proportional) {
                    var newWidth =  model.width / oldHeight * model.height;
                    model.right = model.left + newWidth;
                }
            }
        });
    };

    /**
     * Clones this bounds object with an updated position and size.
     *
     * @protected
     * @param {number=} x New X position
     * @param {number=} y New Y position
     * @param {number=} width New width
     * @param {number=} height New height
     * @return {Bounds} The updated bounds object
     */
    Bounds.prototype.updateSizeAndPosition = function (x, y, width, height) {
        return this.withMutations(function (model) {
            if (typeof x === "number") {
                x = Math.ceil(x);
                model.left = x;
                if (typeof width === "number") {
                    model.right = x + Math.ceil(width);
                }
            }

            if (typeof y === "number") {
                y = Math.ceil(y);
                model.top = y;
                if (typeof height === "number") {
                    model.bottom = y + Math.ceil(height);
                }
            }
        });
    };

    module.exports = Bounds;
});
<commit_msg>bounds.updateSize no longer uses withMutations, thus avoiding a caching issue that caused width to be stale when not using proportional scaling<commit_after>/*
 * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

define(function (require, exports, module) {
    "use strict";

    var Immutable = require("immutable");

    var layerLib = require("adapter/lib/layer"),
        objUtil = require("js/util/object");

    /**
     * Model document bounds or layer bounds without effects.
     *
     * @constructor
     * @param {object} model
     */
    var Bounds = Immutable.Record({
        /**
         * @type {number}
         */
        top: null,

        /**
         * @type {number}
         */
        bottom: null,

        /**
         * @type {number}
         */
        left: null,

        /**
         * @type {number}
         */
        right: null
    });

    Object.defineProperties(Bounds.prototype, objUtil.cachedGetSpecs({
        /**
         * Width of the bounding box.
         * @type {number}
         */
        "width": function () {
            return this.right - this.left;
        },
        /**
         * Height of the bounding box.
         * @type {number}
         */
        "height": function () {
            return this.bottom - this.top;
        },
        /**
         * Horizontal center of the bounding box.
         * @type {number}
         */
        "xCenter": function () {
            return this.left + (this.width / 2);
        },
        /**
         * Vertical center of the bounding box.
         * @type {number}
         */
        "yCenter": function () {
            return this.top + (this.height / 2);
        },
        /**
         * Area of the bounding box
         * @type {number}
         */
        "area": function () {
            return this.width * this.height;
        }
    }));

    /**
     * Create a new Bounds object from the given document descriptor.
     *
     * @param {object} descriptor Photoshop document descriptor
     * @return {Bounds}
     */
    Bounds.fromDocumentDescriptor = function (descriptor) {
        var resolution = descriptor.resolution.value,
            multiplier = resolution / 72,
            model = {};

        var height = descriptor.height.value * multiplier,
            width = descriptor.width.value * multiplier;

        model.top = 0;
        model.left = 0;
        model.bottom = height;
        model.right = width;

        return new Bounds(model);
    };

    /**
     * Create a new Bounds object from the given layer descriptor.
     *
     * @param {object} descriptor Photoshop layer descriptor
     * @return {Bounds}
     */
    Bounds.fromLayerDescriptor = function (descriptor) {
        // Photoshop's group bounds are not useful, so ignore them.
        switch (descriptor.layerKind) {
        case layerLib.layerKinds.GROUP:
        case layerLib.layerKinds.GROUPEND:
            return null;
        }

        var boundsObject = descriptor.boundsNoEffects.value,
            model = {};

        model.top = boundsObject.top.value;
        model.left = boundsObject.left.value;
        model.bottom = boundsObject.bottom.value;
        model.right = boundsObject.right.value;

        return new Bounds(model);
    };

    /**
     * Create a new bounds object from the union of the given bounds objects.
     * Returns null if no bounds objects are supplied.
     *
     * @param {Array.<Bounds>} childBounds
     * @return {?Bounds}
     */
    Bounds.union = function (childBounds) {
        if (childBounds.isEmpty()) {
            return null;
        }

        var startBounds = childBounds.first(),
            nextBounds = startBounds.withMutations(function (model) {
                childBounds.rest().forEach(function (child) {
                    model.top = Math.min(model.top, child.top);
                    model.left = Math.min(model.left, child.left);
                    model.bottom = Math.max(model.bottom, child.bottom);
                    model.right = Math.max(model.right, child.right);
                });
            });

        return nextBounds;
    };

    /**
     * Update the bounds object with the bounds descriptor.
     *
     * @param {object} descriptor layer bounds descriptor
     * @return {Bounds}
     */
    Bounds.prototype.resetFromDescriptor = function (descriptor) {
        var boundsObject = descriptor.value,
            model = {};

        model.top = boundsObject.top.value;
        model.left = boundsObject.left.value;
        model.bottom = boundsObject.bottom.value;
        model.right = boundsObject.right.value;

        return this.merge(model);
    };

    /**
     * Indicates whether the given point is contained in the bounding box.
     *
     * @param {number} x
     * @param {number} y
     * @return {boolean}
     */
    Bounds.prototype.contains = function (x, y) {
        return this.top <= y && y <= this.bottom &&
            this.left <= x && x <= this.right;
    };

    /**
     * Clones this bounds object with an updated position.
     *
     * @protected
     * @param {number=} x New X position
     * @param {number=} y New Y position
     * @return {Bounds} The updated bounds object
     */
    Bounds.prototype.updatePosition = function (x, y) {
        var width = this.width,
            height = this.height;

        return this.withMutations(function (model) {
            if (typeof x === "number") {
                model.left = x;
                model.right = x + width;
            }

            if (typeof y === "number") {
                model.top = y;
                model.bottom = y + height;
            }
        });
    };

    /**
     * Clones this bounds object with an updated size.
     *
     * @protected
     * @param {number=} w New width
     * @param {number=} h New height
     * @param {boolean=} proportional size change
     * @return {Bounds} The updated bounds object
     */
    Bounds.prototype.updateSize = function (w, h, proportional) {
        var newBounds = {};

        if (typeof w === "number") {
            var oldWidth = this.width;
            newBounds.right = this.left + w;
            if (proportional) {
                var newHeight = this.height / oldWidth * w;
                newBounds.bottom = this.top + newHeight;
            }
        }

        if (typeof h === "number") {
            var oldHeight = this.height;
            newBounds.bottom = this.top + h;
            if (proportional) {
                var newWidth =  this.width / oldHeight * h;
                newBounds.right = this.left + newWidth;
            }
        }

        return this.merge(newBounds);
    };

    /**
     * Clones this bounds object with an updated position and size.
     *
     * @protected
     * @param {number=} x New X position
     * @param {number=} y New Y position
     * @param {number=} width New width
     * @param {number=} height New height
     * @return {Bounds} The updated bounds object
     */
    Bounds.prototype.updateSizeAndPosition = function (x, y, width, height) {
        return this.withMutations(function (model) {
            if (typeof x === "number") {
                x = Math.ceil(x);
                model.left = x;
                if (typeof width === "number") {
                    model.right = x + Math.ceil(width);
                }
            }

            if (typeof y === "number") {
                y = Math.ceil(y);
                model.top = y;
                if (typeof height === "number") {
                    model.bottom = y + Math.ceil(height);
                }
            }
        });
    };

    module.exports = Bounds;
});
<|endoftext|>


<commit_before>/**
 * Returns and object of the form {err_code, msg}
 * Where err_code is 0 only if the auth was valid
 * msg contains the authentificator if it was valid
 * and an error message if it wasn't
 */
function is_valid_auth(xml) {
    errcode = xml.getElementsByTagName("error_num");
    if(errcode.length == 0) {
        //No errors, return 0 and authenificator
        return {err_code:0, msg:xml.getElementsByTagName("authenticator")[0].childNodes[0].nodeValue}
    } else {
        //Error occurred, return error code and error message
        return {err_code:xml.getElementsByTagName("error_num")[0].childNodes[0].nodeValue,
                msg:xml.getElementsByTagName("error_msg")[0].childNodes[0].nodeValue}
    }
}

/**
 * Returns true if the server has given the client work,
 * returns false otherwise
 */
function has_work(xml) {
    return (xml.getElementsByTagName("file_info").length > 0)
}

/**
 * Returns the host id if it exists
 * returns null otherwise
 */
function get_host_id_from_scheduler_request(xml) {
    if(xml.getElementsByTagName("hostid").length == 0) {
        return null;
    } else {
        var e = xml.getElementsByTagName("hostid")[0];
        return e.childNodes[0].nodeValue;
    }
}

function get_work_config_url_from_scheduler_result(xml) {
    var file_infos = xml.getElementsByTagName("file_info");
    for (file_info_index in file_infos) {
        if (file_infos.hasOwnProperty(file_info_index)) {
            var elem = file_infos[file_info_index];
            console.log("bees:");
            console.log(elem);
            var url_node = elem.getElementsByTagName("url")[0]
            if (url_node.childNodes[0].nodeValue.indexOf("xml") != -1) {
                return url_node.childNodes[0].nodeValue;
            }
        }

    }

}

function get_work_unit_url_from_scheduler_result(xml) {
    var file_infos = xml.getElementsByTagName("file_info");
    for (var i = 2; i < file_infos.length; i++) {
        if (file_infos[i].getElementsByTagName("executable").length != 0) {
            var url_node = file_infos[i].getElementsByTagName("url")[0]
            return url_node.childNodes[0].nodeValue;
        }
    }

    return "";
}

/**
 * Adds a specified host id and a rpc seqno (of 0)
 * to the specified XML string and returns new the
 * XML string
 */
function update_request_xml(xml_str, host_id) {
    var xml_parser = new DOMParser();
    var xml = xml_parser.parseFromString(xml_str, "text/xml");
    var scheduler_request_node = xml.getElementsByTagName("scheduler_request")[0];
    var host_ID_node = xml.createElement("hostid");
    var rpc_seqno_node = xml.createElement("rpc_seqno");
    scheduler_request_node.appendChild(host_ID_node);
    scheduler_request_node.appendChild(rpc_seqno_node);
    $(xml).find("hostid").text(host_id);
    $(xml).find("rpc_seqno").text("0");
    return (new XMLSerializer()).serializeToString(xml)+"\n\n";

}

/**
 * Changes the authenticator to the given authenticator
 */
function update_authenticator(xml_str, authenticator) {
    var xml_parser = new DOMParser();
    var xml = xml_parser.parseFromString(xml_str, "text/xml");
    $(xml).find("authenticator").text(authenticator);
    return (new XMLSerializer()).serializeToString(xml)+"\n\n";
}

/**
 * Increments the rpc_seqno
 */

var global_rpc_seqno = 0;

function increment_rpcno(xml_str) {
    var xml_parser = new DOMParser();
    var xml = xml_parser.parseFromString(xml_str, "text/xml");
    $(xml).find("rpc_seqno").text(global_rpc_seqno.toString());
    global_rpc_seqno += 1;
    return (new XMLSerializer()).serializeToString(xml)+"\n\n";
}

<commit_msg>added a function to replace the job id in a completed work report<commit_after>/**
 * Returns and object of the form {err_code, msg}
 * Where err_code is 0 only if the auth was valid
 * msg contains the authentificator if it was valid
 * and an error message if it wasn't
 */
function is_valid_auth(xml) {
    errcode = xml.getElementsByTagName("error_num");
    if(errcode.length == 0) {
        //No errors, return 0 and authenificator
        return {err_code:0, msg:xml.getElementsByTagName("authenticator")[0].childNodes[0].nodeValue}
    } else {
        //Error occurred, return error code and error message
        return {err_code:xml.getElementsByTagName("error_num")[0].childNodes[0].nodeValue,
                msg:xml.getElementsByTagName("error_msg")[0].childNodes[0].nodeValue}
    }
}

/**
 * Returns true if the server has given the client work,
 * returns false otherwise
 */
function has_work(xml) {
    return (xml.getElementsByTagName("file_info").length > 0)
}

/**
 * Returns the host id if it exists
 * returns null otherwise
 */
function get_host_id_from_scheduler_request(xml) {
    if(xml.getElementsByTagName("hostid").length == 0) {
        return null;
    } else {
        var e = xml.getElementsByTagName("hostid")[0];
        return e.childNodes[0].nodeValue;
    }
}

function get_work_config_url_from_scheduler_result(xml) {
    var file_infos = xml.getElementsByTagName("file_info");
    for (file_info_index in file_infos) {
        if (file_infos.hasOwnProperty(file_info_index)) {
            var elem = file_infos[file_info_index];
            console.log("bees:");
            console.log(elem);
            var url_node = elem.getElementsByTagName("url")[0]
            if (url_node.childNodes[0].nodeValue.indexOf("xml") != -1) {
                return url_node.childNodes[0].nodeValue;
            }
        }

    }

}

function get_work_unit_url_from_scheduler_result(xml) {
    var file_infos = xml.getElementsByTagName("file_info");
    for (var i = 2; i < file_infos.length; i++) {
        if (file_infos[i].getElementsByTagName("executable").length != 0) {
            var url_node = file_infos[i].getElementsByTagName("url")[0]
            return url_node.childNodes[0].nodeValue;
        }
    }

    return "";
}

/**
 * Adds a specified host id and a rpc seqno (of 0)
 * to the specified XML string and returns new the
 * XML string
 */
function update_request_xml(xml_str, host_id) {
    console.log("updating request xml");
    var xml_parser = new DOMParser();
    var xml = xml_parser.parseFromString(xml_str, "text/xml");
    var scheduler_request_node = xml.getElementsByTagName("scheduler_request")[0];
    var host_ID_node = xml.createElement("hostid");
    var rpc_seqno_node = xml.createElement("rpc_seqno");
    scheduler_request_node.appendChild(host_ID_node);
    scheduler_request_node.appendChild(rpc_seqno_node);
    $(xml).find("hostid").text(host_id);
    $(xml).find("rpc_seqno").text("0");
    return (new XMLSerializer()).serializeToString(xml)+"\n\n";

}

/**
 * Changes the authenticator to the given authenticator
 */
function update_authenticator(xml_str, authenticator) {
    var xml_parser = new DOMParser();
    var xml = xml_parser.parseFromString(xml_str, "text/xml");
    $(xml).find("authenticator").text(authenticator);
    return (new XMLSerializer()).serializeToString(xml)+"\n\n";
}

/**
 * Increments the rpc_seqno
 */

var global_rpc_seqno = 0;

function increment_rpcno(xml_str) {
    var xml_parser = new DOMParser();
    var xml = xml_parser.parseFromString(xml_str, "text/xml");
    $(xml).find("rpc_seqno").text(global_rpc_seqno.toString());
    global_rpc_seqno += 1;
    return (new XMLSerializer()).serializeToString(xml)+"\n\n";
}

function replace_job_id(xml_str, job_id) {
    var xml_parser = new DOMParser();
    var xml = xml_parser.parseFromString(xml_str, "text/xml");
    $(xml).find("name").text(job_id);
    return (new XMLSerializer()).serializeToString(xml);

}
<|endoftext|>