<commit_before>import ns from 'imajs/client/core/namespace';
import IMAError from 'imajs/client/core/imaError';

ns.namespace('Core.Router');

/**
 * Wrapper for the ExpressJS response, exposing only the neccessary minimum.
 *
 * @class Response
 * @namespace Core.Router
 * @module Core
 * @submodule Core.Router
 */
export default class Response {

	/**
	 * Initializes the response.
	 *
	 * @constructor
	 * @method constructor
	 */
	constructor() {

		/**
		 * The ExpressJS response object, or {@code null} if running at the client
		 * side.
		 *
		 * @private
		 * @property _response
		 * @type {?Express.Response}
		 * @default null
		 */
		this._response = null;

		/**
		 * It is flag for sent response for request.
		 *
		 * @private
		 * @property _isSent
		 * @type {boolean}
		 * @default false
		 */
		this._isSent = false;

		/**
		 * HTTP Status code.
		 *
		 * @private
		 * @property _status
		 * @type {number}
		 * @default 500
		 */
		this._status = 500;

		/**
		 * The content of response.
		 *
		 * @private
		 * @property _content
		 * @type {string}
		 * @default ''
		 */
		this._content = '';

		/**
		 * Transform function for cookie value.
		 *
		 * @private
		 * @property _cookieTransformFunction
		 * @type {{encode: function, decode: function}}
		 */
		this._cookieTransformFunction = {
			encode: (s) => s,
			decode: (s) => s
		};
	}

	/**
	 * Initializes this response wrapper with the provided ExpressJS response
	 * object.
	 *
	 * @method init
	 * @chainable
	 * @param {?Express.Response} response The ExpressJS response, or
	 *        {@code null} if the code is running at the client side.
	 * @param {{encode: function, decode: function}} [cookieTransformFunction={}]
	 * @return {Core.Router.Response} This response.
	 */
	init(response, cookieTransformFunction = {}) {
		this._cookieTransformFunction = Object.assign(this._cookieTransformFunction, cookieTransformFunction);
		this._response = response;
		this._isSent = false;
		this._status = 500;
		this._content = '';

		return this;
	}

	/**
	 * Redirects the client to the specified location, with the specified
	 * redirect HTTP response code.
	 *
	 * For full list of HTTP response status codes see
	 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
	 *
	 * Use this method only at the server side.
	 *
	 * @chainable
	 * @method redirect
	 * @param {string} url The URL to which the client should be redirected.
	 * @param {number=} [status=302] The HTTP status code to send to the client.
	 * @return {Core.Router.Response} This response.
	 */
	redirect(url, status = 302) {
		if ($Debug) {
			if (this._isSent === true) {
				var params = this.getResponseParams();
				params.url = url;

				throw new IMAError('Core.Router.Response:redirect The response has already ' +
						'been sent. Check your workflow.', params);
			}
		}

		this._isSent = true;
		this._status = status;
		this._response.redirect(status, url);

		return this;
	}

	/**
	 * Sets the HTTP status code that will be sent to the client when the
	 * response is sent.
	 *
	 * For full list of available response codes see
	 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
	 *
	 * Use this method only at the server side.
	 *
	 * @chainable
	 * @method status
	 * @param {number} httpStatus HTTP response status code to send to the
	 *        client.
	 * @return {Core.Router.Response} This response.
	 */
	status(httpStatus) {
		if ($Debug) {
			if (this._isSent === true) {
				var params = this.getResponseParams();

				throw new IMAError('Core.Router.Response:status The response has already ' +
						'been sent. Check your workflow.', params);
			}
		}

		this._status = httpStatus;
		this._response.status(httpStatus);

		return this;
	}

	/**
	 * Sends the response to the client with the provided content. Use this
	 * method only at the server side.
	 *
	 * @chainable
	 * @method send
	 * @param {string} content The response body.
	 * @return {Core.Router.Response} This response.
	 */
	send(content) {
		if ($Debug) {
			if (this._isSent === true) {
				var params = this.getResponseParams();
				params.content = content;

				throw new IMAError('Core.Router.Response:send The response has already ' +
						'been sent. Check your workflow.', params);
			}
		}

		this._isSent = true;
		this._content = content;
		this._response.send(content);

		return this;
	}

	/**
	 * Sets a cookie, which will be sent to the client with the response.
	 *
	 * @chainable
	 * @method setCookie
	 * @param {string} name The cookie name.
	 * @param {(boolean|number|string)} value The cookie value, will be converted
	 *        to string.
	 * @param {{domain: string=, expires: (number|string)=}} options Cookie
	 *        attributes. Only the attributes listed in the type annotation of
	 *        this field are supported. For documentation and full list of cookie
	 *        attributes see http://tools.ietf.org/html/rfc2965#page-5
	 * @return {Core.Router.Response} This response.
	 */
	setCookie(name, value, options = {}) {
		if ($Debug) {
			if (this._isSent === true) {
				var params = this.getResponseParams();
				params.name = name;
				params.value = value;
				params.options = options;

				throw new IMAError('Core.Router.Response:setCookie The response has already ' +
						'been sent. Check your workflow.', params);
			}
		}

		var advanceOptions = Object.assign({}, this._cookieTransformFunction, options);

		this._response.cookie(name, value, advanceOptions);

		return this;
	}

	/**
	 * Return object which contains response status and content.
	 *
	 * @method getResponseParams
	 * @return {{status: number, content: string}}
	 */
	getResponseParams() {
		return { status: this._status, content: this._content };
	}

	/**
	 * Return true if response is sent from server to client.
	 *
	 * @method isResponseSent
	 * @return {boolean}
	 */
	isResponseSent() {
		return this._isSent;
	}
}

ns.Core.Router.Response = Response;
<commit_msg>#34 response send set cookie only once for same cookie name<commit_after>import ns from 'imajs/client/core/namespace';
import IMAError from 'imajs/client/core/imaError';

ns.namespace('Core.Router');

/**
 * Wrapper for the ExpressJS response, exposing only the neccessary minimum.
 *
 * @class Response
 * @namespace Core.Router
 * @module Core
 * @submodule Core.Router
 */
export default class Response {

	/**
	 * Initializes the response.
	 *
	 * @constructor
	 * @method constructor
	 */
	constructor() {

		/**
		 * The ExpressJS response object, or {@code null} if running at the client
		 * side.
		 *
		 * @private
		 * @property _response
		 * @type {?Express.Response}
		 * @default null
		 */
		this._response = null;

		/**
		 * It is flag for sent response for request.
		 *
		 * @private
		 * @property _isSent
		 * @type {boolean}
		 * @default false
		 */
		this._isSent = false;

		/**
		 * HTTP Status code.
		 *
		 * @private
		 * @property _status
		 * @type {number}
		 * @default 500
		 */
		this._status = 500;

		/**
		 * The content of response.
		 *
		 * @private
		 * @property _content
		 * @type {string}
		 * @default ''
		 */
		this._content = '';

		/**
		 * Internal cookie storage for Set-Cookie header.
		 *
		 * @private
		 * @property _internalCookieStorage
		 * @type {Map}
		 */
		this._internalCookieStorage = new Map();

		/**
		 * Transform function for cookie value.
		 *
		 * @private
		 * @property _cookieTransformFunction
		 * @type {{encode: function, decode: function}}
		 */
		this._cookieTransformFunction = {
			encode: (s) => s,
			decode: (s) => s
		};
	}

	/**
	 * Initializes this response wrapper with the provided ExpressJS response
	 * object.
	 *
	 * @method init
	 * @chainable
	 * @param {?Express.Response} response The ExpressJS response, or
	 *        {@code null} if the code is running at the client side.
	 * @param {{encode: function, decode: function}} [cookieTransformFunction={}]
	 * @return {Core.Router.Response} This response.
	 */
	init(response, cookieTransformFunction = {}) {
		this._cookieTransformFunction = Object.assign(this._cookieTransformFunction, cookieTransformFunction);
		this._response = response;
		this._isSent = false;
		this._status = 500;
		this._content = '';
		this._internalCookieStorage = new Map();

		return this;
	}

	/**
	 * Redirects the client to the specified location, with the specified
	 * redirect HTTP response code.
	 *
	 * For full list of HTTP response status codes see
	 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
	 *
	 * Use this method only at the server side.
	 *
	 * @chainable
	 * @method redirect
	 * @param {string} url The URL to which the client should be redirected.
	 * @param {number=} [status=302] The HTTP status code to send to the client.
	 * @return {Core.Router.Response} This response.
	 */
	redirect(url, status = 302) {
		if ($Debug) {
			if (this._isSent === true) {
				var params = this.getResponseParams();
				params.url = url;

				throw new IMAError('Core.Router.Response:redirect The response has already ' +
						'been sent. Check your workflow.', params);
			}
		}

		this._isSent = true;
		this._status = status;
		this._setCookieHeaders();
		this._response.redirect(status, url);

		return this;
	}

	/**
	 * Sets the HTTP status code that will be sent to the client when the
	 * response is sent.
	 *
	 * For full list of available response codes see
	 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
	 *
	 * Use this method only at the server side.
	 *
	 * @chainable
	 * @method status
	 * @param {number} httpStatus HTTP response status code to send to the
	 *        client.
	 * @return {Core.Router.Response} This response.
	 */
	status(httpStatus) {
		if ($Debug) {
			if (this._isSent === true) {
				var params = this.getResponseParams();

				throw new IMAError('Core.Router.Response:status The response has already ' +
						'been sent. Check your workflow.', params);
			}
		}

		this._status = httpStatus;
		this._response.status(httpStatus);

		return this;
	}

	/**
	 * Sends the response to the client with the provided content. Use this
	 * method only at the server side.
	 *
	 * @chainable
	 * @method send
	 * @param {string} content The response body.
	 * @return {Core.Router.Response} This response.
	 */
	send(content) {
		if ($Debug) {
			if (this._isSent === true) {
				var params = this.getResponseParams();
				params.content = content;

				throw new IMAError('Core.Router.Response:send The response has already ' +
						'been sent. Check your workflow.', params);
			}
		}

		this._isSent = true;
		this._content = content;
		this._setCookieHeaders();
		this._response.send(content);

		return this;
	}

	/**
	 * Sets a cookie, which will be sent to the client with the response.
	 *
	 * @chainable
	 * @method setCookie
	 * @param {string} name The cookie name.
	 * @param {(boolean|number|string)} value The cookie value, will be converted
	 *        to string.
	 * @param {{domain: string=, expires: (number|string)=}} options Cookie
	 *        attributes. Only the attributes listed in the type annotation of
	 *        this field are supported. For documentation and full list of cookie
	 *        attributes see http://tools.ietf.org/html/rfc2965#page-5
	 * @return {Core.Router.Response} This response.
	 */
	setCookie(name, value, options = {}) {
		if ($Debug) {
			if (this._isSent === true) {
				var params = this.getResponseParams();
				params.name = name;
				params.value = value;
				params.options = options;

				throw new IMAError('Core.Router.Response:setCookie The response has already ' +
						'been sent. Check your workflow.', params);
			}
		}

		var advanceOptions = Object.assign({}, this._cookieTransformFunction, options);
		this._internalCookieStorage.set(name, { value, options: advanceOptions });

		return this;
	}

	/**
	 * Return object which contains response status and content.
	 *
	 * @method getResponseParams
	 * @return {{status: number, content: string}}
	 */
	getResponseParams() {
		return { status: this._status, content: this._content };
	}

	/**
	 * Return true if response is sent from server to client.
	 *
	 * @method isResponseSent
	 * @return {boolean}
	 */
	isResponseSent() {
		return this._isSent;
	}

	/**
	 * Set cookie headers for response.
	 *
	 * @private
	 * @method _setCookieHeaders
	 */
	_setCookieHeaders() {
		for (var [name, param] of this._internalCookieStorage) {
			this._response.cookie(name, param.value, param.options);
		}
	}
}

ns.Core.Router.Response = Response;
<|endoftext|>


<commit_before>s.Radar = new Class({
    toString: 'Radar',
    extend: s.Game,

    construct: function(options){

        this.game = options.game;
        var that = this.game;

        /////////////////////
        // SCENE AND INIT  //
        /////////////////////

        // Init THREE Environment
        that.radarScene = new THREE.Scene();
        that.radarCamera = new THREE.PerspectiveCamera( 40, 1, 1, 1000 );
        that.radarRenderer = this.renderer || new THREE.WebGLRenderer({ antialias: true });
        that.radar = '';

        // Append Renderer+Canvas
        that.radarRenderer.setSize( 256, 256 );
        that.radarCanvas = document.body.appendChild( that.radarRenderer.domElement );

        // Styling
        that.radarCanvas.style.position = 'absolute';
        that.radarCanvas.style.top = '0px';
        that.radarCanvas.style.left = window.innerWidth-256+"px";

        // Init Camera
        that.radarCamera.position.x = 0;
        that.radarCamera.position.y = 0;
        that.radarCamera.position.z = 180;
        that.radarScene.add( that.radarCamera );

        // Init Lights
        var light = new THREE.DirectionalLight( 0x000000 );
        light.position.set( 0, 1, 1 ).normalize();
        that.radarScene.add( light );

        that.radarScene.tempLog = [];

        ///////////////////////////////
        //  RADAR SPHERE PROPERTIES  //
        ///////////////////////////////

        that.radius = 60;

        var mesh = new THREE.MeshNormalMaterial(),
            sphere = new THREE.SphereGeometry( that.radius, 16, 16 );

        var materials = [
            //new THREE.MeshLambertMaterial( { color: 0xcccccc, shading: THREE.FlatShading, vertexColors: THREE.VertexColors } ),
            new THREE.MeshBasicMaterial( { color:0x5dfc0a, shading: THREE.FlatShading, wireframe: true, transparent: true } )
        ];

        var radar = THREE.SceneUtils.createMultiMaterialObject( sphere, materials );
        radar.position.x = 0;
        radar.position.y = 0;
        radar.position.z = 0;
        //radar.rotation.y = -Math.PI/4;

        radar.name = "radar";
        that.radarScene.add( radar );

        ///////////////////////
        //  PLAYER LOCATION  //
        ///////////////////////

        var selfGeo = new THREE.TetrahedronGeometry(5);
        selfGeo.faces[0].color.setHex(0x330066);
        selfGeo.faces[1].color.setHex(0x003366);
        selfGeo.faces[2].color.setHex(0x336666);
        selfGeo.faces[3].color.setHex(0x000000);
        //selfGeo.colorsNeedUpdate = true;

        // marker for player position
        var selfMarker = new THREE.Mesh(
            selfGeo,
            new THREE.MeshBasicMaterial( { color: 0xffffff, vertexColors: THREE.FaceColors } ) );

        selfMarker.name = "self";
        radar.add( selfMarker );

        // marker for player motion
        var trajectoryGeo = new THREE.Geometry();
        trajectoryGeo.vertices.push(new THREE.Vector3(0,0,0));
        trajectoryGeo.vertices.push(new THREE.Vector3(0,0,0));

        var selfTrajectory = new THREE.Line(
            trajectoryGeo,
            new THREE.LineBasicMaterial( { color: 0xffffff } ),
            THREE.LineStrip
        );
        selfTrajectory.name = "selfTrajectory";

        radar.add( selfTrajectory );

        ///////////////////
        // ENEMY MARKERS //
        ///////////////////
        that.enemies.add( { name: 'blah', pos: [Math.random()*1000000-5000,Math.random()*1000000-5000,Math.random()*1000000-5000], rot: [0,0,0], aVeloc: [0,0,0], lVeloc: [100,100,100] } );

        var enemyGeo = [], enemyMarker = [];
        for (var i = 0, len = that.enemies.list().length; i < len; i++){

            enemyGeo[i] = new THREE.TetrahedronGeometry(5);

            // marker for player position
            enemyMarker[i] = new THREE.Mesh(
                enemyGeo[i],
                new THREE.MeshBasicMaterial( { color: 0xff0000, shading: THREE.FlatShading } ) );

            enemyMarker[i].name = "enemy"+i;
            radar.add( enemyMarker[i] );

            radar.enemyCount = i+1;

        }

        /////////////////
        // MOON MARKER //
        /////////////////

        // moon instantiation
        var moonGeo = s.models.phobos_lofi.geometry;
        var moonMarker = new THREE.Mesh( moonGeo, new THREE.MeshNormalMaterial() );

        // Moon marker size scaling
        /* TODO: scale in a more meaningful way */
        moonMarker.scale.multiplyScalar(0.005);
        moonMarker.name = "moon";

        // Moon radar positioning
        var moonPosition = that.scene.getChildByName( 'moon' ).position.clone();
        moonMarker.position = moonPosition.normalize().multiplyScalar(that.radius);

        radar.add( moonMarker );

        // Move radar on screen resize
        var context = this;
        $(window).on('resize', context.fitWindow.bind(that));
        context.fitWindow();

        // Trigger render loop and assign bindings
        this.update = this.update.bind(that);
        that.hook(this.update);
        that.radarRenderer.render( that.radarScene, that.radarCamera );

    },

    fitWindow: function(){
        s.game.radarCanvas.style.left = window.innerWidth-256+"px";
    },

    update: function(options){

        /////////////////////////
        // 3JS SCENE SELECTORS //
        /////////////////////////

        var radar       = this.radarScene.getChildByName( 'radar' ),
            self        = radar.getChildByName( 'self' ),
            moon        = radar.getChildByName( 'moon' ),
            trajectory  = radar.getChildByName( 'selfTrajectory'),
            allies      = radar.getChildByName( 'allies' ),
            enemies     = this.enemies.list(),
            radarRadius = this.radius/ 5,
            that        = s.game;

        ////////////////////
        // RADAR ROTATION //
        ////////////////////

        // Clone of the current player's position
        this.selfPosition = this.player.root.position.clone();

        // Rotate player tetrahedron in accordance with ship rotation
        self.rotation = this.player.root.rotation;

        // Radar sphere rotation with respect to player's current rotation
        var now  = this.selfPosition.clone();
        var last = this.lastPosition || now;

        // xz dot product parameters
        var top  = last.x*now.x + last.z*now.z;
        var bot1 = Math.sqrt( last.x*last.x + last.z*last.z );
        var bot2 = Math.sqrt(  now.x*now.x  +  now.z*now.z );

        var findTheta = top/(bot1*bot2);

        // Calculate angle of rotation; Javascript is a floating point failbus.
        radar.rotation.y += findTheta>1 || findTheta<-1 ? Math.acos( Math.round( findTheta ) ) : Math.acos( findTheta );

        this.lastPosition = this.selfPosition.clone();

        ////////////////////////////////
        // SELF POSITION AND ROTATION //
        ////////////////////////////////

        // Distance from center of the map, scaled logarithmically
        var selfLength   = this.player.root.position.length();
        selfLength = Math.log( selfLength ) - 7 || 0.1;

        // Apply normalization and multiplier to cover full sphere coordinates and set the position
        self.position = this.selfPosition.normalize().multiplyScalar(selfLength*(radarRadius));

        // Player trajectory marker; scales with velocity, and is never shorter than length 3
        var playerTrajectory = this.player.root.getLinearVelocity().clone().multiplyScalar(1/80);
        playerTrajectory = playerTrajectory.length()>3 ? playerTrajectory : playerTrajectory.normalize().multiplyScalar(3);

        // Set the second line vertex
        trajectory.geometry.vertices[0] = self.position.clone();
        trajectory.geometry.vertices[1] = trajectory.geometry.vertices[0].clone().add( playerTrajectory );
        trajectory.geometry.verticesNeedUpdate = true;

        /////////////////////////////////
        // ENEMY POSITION AND ROTATION //
        /////////////////////////////////

        var enemyLength = [], enemyPosition = [];

        // Search for new enemies and add them to the map
        if (enemies.length > radar.enemyCount){
            for (var j = 0, lenj = that.enemies.list().length; j < lenj; j++){
                if (!radar.getChildByName('enemy'+j)){
                    var enemyGeo = new THREE.TetrahedronGeometry(5);

                    // marker for player position
                    var enemyMarker = new THREE.Mesh(
                        enemyGeo,
                        new THREE.MeshBasicMaterial( { color: 0xff0000, shading: THREE.FlatShading } ) );

                    enemyMarker.name = "enemy"+j;
                    radar.add( enemyMarker );

                    radar.enemyCount = j+1;
                }
            }
        }

        // Update positions of enemies
        for (var i = 0, len = enemies.length; i < len; i++){

            enemyPosition[i] = enemies[i].root.position.clone();

            // Distance from center of the map, scaled logarithmically
            enemyLength[i] = enemyPosition[i].clone().length();
            enemyLength[i] = Math.log( enemyLength[i] ) - 7 || 0.1;

            // Apply normalization and multiplier to cover full sphere coordinates and set the position
            radar.getChildByName('enemy'+i).position = enemyPosition[i].normalize().multiplyScalar(enemyLength[i]*(radarRadius));

        }
    }
});

<commit_msg>Fixed a bug caused by fixing issue #68<commit_after>s.Radar = new Class({
    toString: 'Radar',
    extend: s.Game,

    construct: function(options){

        this.game = options.game;
        var that = this.game;

        /////////////////////
        // SCENE AND INIT  //
        /////////////////////

        // Init THREE Environment
        that.radarScene = new THREE.Scene();
        that.radarCamera = new THREE.PerspectiveCamera( 40, 1, 1, 1000 );
        that.radarRenderer = this.renderer || new THREE.WebGLRenderer({ antialias: true });
        that.radar = '';

        // Append Renderer+Canvas
        that.radarRenderer.setSize( 256, 256 );
        that.radarCanvas = document.body.appendChild( that.radarRenderer.domElement );

        // Styling
        that.radarCanvas.style.position = 'absolute';
        that.radarCanvas.style.top = '0px';
        that.radarCanvas.style.left = window.innerWidth-256+"px";

        // Init Camera
        that.radarCamera.position.x = 0;
        that.radarCamera.position.y = 0;
        that.radarCamera.position.z = 180;
        that.radarScene.add( that.radarCamera );

        // Init Lights
        var light = new THREE.DirectionalLight( 0x000000 );
        light.position.set( 0, 1, 1 ).normalize();
        that.radarScene.add( light );

        that.radarScene.tempLog = [];

        ///////////////////////////////
        //  RADAR SPHERE PROPERTIES  //
        ///////////////////////////////

        that.radius = 60;

        var mesh = new THREE.MeshNormalMaterial(),
            sphere = new THREE.SphereGeometry( that.radius, 16, 16 );

        var materials = [
            //new THREE.MeshLambertMaterial( { color: 0xcccccc, shading: THREE.FlatShading, vertexColors: THREE.VertexColors } ),
            new THREE.MeshBasicMaterial( { color:0x5dfc0a, shading: THREE.FlatShading, wireframe: true, transparent: true } )
        ];

        var radar = THREE.SceneUtils.createMultiMaterialObject( sphere, materials );
        radar.position.x = 0;
        radar.position.y = 0;
        radar.position.z = 0;
        //radar.rotation.y = -Math.PI/4;

        radar.name = "radar";
        that.radarScene.add( radar );

        ///////////////////////
        //  PLAYER LOCATION  //
        ///////////////////////

        var selfGeo = new THREE.TetrahedronGeometry(5);
        selfGeo.faces[0].color.setHex(0x330066);
        selfGeo.faces[1].color.setHex(0x003366);
        selfGeo.faces[2].color.setHex(0x336666);
        selfGeo.faces[3].color.setHex(0x000000);
        //selfGeo.colorsNeedUpdate = true;

        // marker for player position
        var selfMarker = new THREE.Mesh(
            selfGeo,
            new THREE.MeshBasicMaterial( { color: 0xffffff, vertexColors: THREE.FaceColors } ) );

        selfMarker.name = "self";
        radar.add( selfMarker );

        // marker for player motion
        var trajectoryGeo = new THREE.Geometry();
        trajectoryGeo.vertices.push(new THREE.Vector3(0,0,0));
        trajectoryGeo.vertices.push(new THREE.Vector3(0,0,0));

        var selfTrajectory = new THREE.Line(
            trajectoryGeo,
            new THREE.LineBasicMaterial( { color: 0xffffff } ),
            THREE.LineStrip
        );
        selfTrajectory.name = "selfTrajectory";

        radar.add( selfTrajectory );

        ///////////////////
        // ENEMY MARKERS //
        ///////////////////
        var enemyGeo = [], enemyMarker = [];
        radar.enemyCount = 0;
        for (var i = 0, len = that.enemies.list().length; i < len; i++){

            enemyGeo[i] = new THREE.TetrahedronGeometry(5);

            // marker for player position
            enemyMarker[i] = new THREE.Mesh(
                enemyGeo[i],
                new THREE.MeshBasicMaterial( { color: 0xff0000, shading: THREE.FlatShading } ) );

            enemyMarker[i].name = "enemy"+i;
            radar.add( enemyMarker[i] );

            radar.enemyCount = i+1;

        }

        /////////////////
        // MOON MARKER //
        /////////////////

        // moon instantiation
        var moonGeo = s.models.phobos_lofi.geometry;
        var moonMarker = new THREE.Mesh( moonGeo, new THREE.MeshNormalMaterial() );

        // Moon marker size scaling
        /* TODO: scale in a more meaningful way */
        moonMarker.scale.multiplyScalar(0.005);
        moonMarker.name = "moon";

        // Moon radar positioning
        var moonPosition = that.scene.getChildByName( 'moon' ).position.clone();
        moonMarker.position = moonPosition.normalize().multiplyScalar(that.radius);

        radar.add( moonMarker );

        // Move radar on screen resize
        var context = this;
        $(window).on('resize', context.fitWindow.bind(that));
        context.fitWindow();

        // Trigger render loop and assign bindings
        this.update = this.update.bind(that);
        that.hook(this.update);
        that.radarRenderer.render( that.radarScene, that.radarCamera );

    },

    fitWindow: function(){
        s.game.radarCanvas.style.left = window.innerWidth-256+"px";
    },

    update: function(options){

        /////////////////////////
        // 3JS SCENE SELECTORS //
        /////////////////////////

        var radar       = this.radarScene.getChildByName( 'radar' ),
            self        = radar.getChildByName( 'self' ),
            moon        = radar.getChildByName( 'moon' ),
            trajectory  = radar.getChildByName( 'selfTrajectory'),
            allies      = radar.getChildByName( 'allies' ),
            enemies     = this.enemies.list(),
            radarRadius = this.radius/ 5,
            that        = s.game;

        ////////////////////
        // RADAR ROTATION //
        ////////////////////

        // Clone of the current player's position
        this.selfPosition = this.player.root.position.clone();

        // Rotate player tetrahedron in accordance with ship rotation
        self.rotation = this.player.root.rotation;

        // Radar sphere rotation with respect to player's current rotation
        var now  = this.selfPosition.clone();
        var last = this.lastPosition || now;

        // xz dot product parameters
        var top  = last.x*now.x + last.z*now.z;
        var bot1 = Math.sqrt( last.x*last.x + last.z*last.z );
        var bot2 = Math.sqrt(  now.x*now.x  +  now.z*now.z );

        var findTheta = top/(bot1*bot2);

        // Calculate angle of rotation; Javascript is a floating point failbus.
        radar.rotation.y += findTheta>1 || findTheta<-1 ? Math.acos( Math.round( findTheta ) ) : Math.acos( findTheta );

        this.lastPosition = this.selfPosition.clone();

        ////////////////////////////////
        // SELF POSITION AND ROTATION //
        ////////////////////////////////

        // Distance from center of the map, scaled logarithmically
        var selfLength   = this.player.root.position.length();
        selfLength = Math.log( selfLength ) - 7 || 0.1;

        // Apply normalization and multiplier to cover full sphere coordinates and set the position
        self.position = this.selfPosition.normalize().multiplyScalar(selfLength*(radarRadius));

        // Player trajectory marker; scales with velocity, and is never shorter than length 3
        var playerTrajectory = this.player.root.getLinearVelocity().clone().multiplyScalar(1/80);
        playerTrajectory = playerTrajectory.length()>3 ? playerTrajectory : playerTrajectory.normalize().multiplyScalar(3);

        // Set the second line vertex
        trajectory.geometry.vertices[0] = self.position.clone();
        trajectory.geometry.vertices[1] = trajectory.geometry.vertices[0].clone().add( playerTrajectory );
        trajectory.geometry.verticesNeedUpdate = true;

        /////////////////////////////////
        // ENEMY POSITION AND ROTATION //
        /////////////////////////////////

        var enemyLength = [], enemyPosition = [];

        // Search for new enemies and add them to the map
        if (enemies.length > radar.enemyCount){
            for (var j = 0, lenj = that.enemies.list().length; j < lenj; j++){
                if (!radar.getChildByName('enemy'+j)){
                    var enemyGeo = new THREE.TetrahedronGeometry(5);

                    // marker for player position
                    var enemyMarker = new THREE.Mesh(
                        enemyGeo,
                        new THREE.MeshBasicMaterial( { color: 0xff0000, shading: THREE.FlatShading } ) );

                    enemyMarker.name = "enemy"+j;
                    radar.add( enemyMarker );

                    radar.enemyCount = j+1;
                }
            }
        }

        // Update positions of enemies
        for (var i = 0, len = enemies.length; i < len; i++){

            enemyPosition[i] = enemies[i].root.position.clone();

            // Distance from center of the map, scaled logarithmically
            enemyLength[i] = enemyPosition[i].clone().length();
            enemyLength[i] = Math.log( enemyLength[i] ) - 7 || 0.1;

            // Apply normalization and multiplier to cover full sphere coordinates and set the position
            radar.getChildByName('enemy'+i).position = enemyPosition[i].normalize().multiplyScalar(enemyLength[i]*(radarRadius));

        }
    }
});

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 Vanderbilt University, All rights reserved.
 *
 * Author: Robert Kereskenyi
 */

"use strict";

/*
 * Utility helper functions implementing GME concepts...
 */

define(['jquery',
        'js/Constants',
        'js/NodePropertyNames',
        'js/Panels/MetaEditor/MetaEditorConstants'], function (_jquery,
                                           CONSTANTS,
                                           nodePropertyNames,
                                           MetaEditorConstants) {

    var _client;

    var _initialize = function (client) {
        if (!_client) {
            _client = client;
        }
    };

    /*
     * a connection is an object that has CONSTANTS.POINTER_SOURCE and CONSTANTS.POINTER_TARGET pointers and those values are set
     */
    var _isConnection = function (objID) {
        var validConnection = false,
            obj = _client.getNode(objID);

        if (obj) {
            var ptrNames = obj.getPointerNames();
            if (ptrNames.indexOf(CONSTANTS.POINTER_SOURCE) !== -1 &&
                ptrNames.indexOf(CONSTANTS.POINTER_TARGET) !== -1 &&
                obj.getPointer(CONSTANTS.POINTER_SOURCE).to &&
                obj.getPointer(CONSTANTS.POINTER_TARGET).to) {
                validConnection = true;
            }
        }

        return validConnection;
    };

    /*
     * a connectiontype is an object that has CONSTANTS.POINTER_SOURCE and CONSTANTS.POINTER_TARGET pointers
     */
    var _isConnectionType = function (objID) {
        var valid = false,
            obj = _client.getNode(objID);

        if (obj) {
            var ptrNames = obj.getPointerNames();
            if (ptrNames.indexOf(CONSTANTS.POINTER_SOURCE) !== -1 &&
                ptrNames.indexOf(CONSTANTS.POINTER_TARGET) !== -1) {
                valid = true;
            }
        }

        return valid;
    };

    /*
     * Determines if the given object in the given container can be a valid connection source
     *
     * The given parent has a valid children type that has CONSTANTS.POINTER_SOURCE and CONSTANTS.POINTER_TARGET pointers
     * and the given object can be a valid target for CONSTANTS.POINTER_SOURCE
     */
    var _isValidConnectionSource = function (objID, parentID) {
        var valid = false,
            validChildrenTypes,
            len,
            childID;

        validChildrenTypes = _client.getValidChildrenTypes(parentID) || [];
        len = validChildrenTypes.length;
        while (len--) {
            childID = validChildrenTypes[len];
            if (_client.getPointerMeta(childID, CONSTANTS.POINTER_SOURCE) &&
                _client.getPointerMeta(childID, CONSTANTS.POINTER_TARGET) &&
                _client.isValidTarget(childID, CONSTANTS.POINTER_SOURCE, objID)) {
                valid = true;
                break;
            }
        }

        return valid;
    };

    /*
     * Determines if a GME Connection can be created between source and target in parent
     */
    var _getValidConnectionTypes = function (sourceID, targetID, parentID) {
        var validTypes = [],
            validChildrenTypes,
            len,
            childID;

        validChildrenTypes = _client.getValidChildrenTypes(parentID) || [];
        len = validChildrenTypes.length;
        while (len--) {
            childID = validChildrenTypes[len];
            if (_client.getPointerMeta(childID, CONSTANTS.POINTER_SOURCE) &&
                _client.getPointerMeta(childID, CONSTANTS.POINTER_TARGET) &&
                _client.isValidTarget(childID, CONSTANTS.POINTER_SOURCE, sourceID) &&
                _client.isValidTarget(childID, CONSTANTS.POINTER_TARGET, targetID)) {
                validTypes.push(childID);
            }
        }

        return validTypes;
    };

    /*
     * Determines if a GME Connection is valid by META between source and destination
     */
    var _isValidConnection = function (sourceID, targetID, connectionID) {
        var valid = false;

        if (sourceID !== undefined && targetID !== undefined && connectionID !== undefined) {
            if (_client.isValidTarget(connectionID, CONSTANTS.POINTER_SOURCE, sourceID) &&
                _client.isValidTarget(connectionID, CONSTANTS.POINTER_TARGET, targetID)) {
                valid = true;
            }
        }

        return valid;
    };

    /*
     * Returns true if a new child with the given baseId (instance of base) can be created in parent
     */
    var _canCreateChild = function (parentId, baseId) {
        var result = false,
            validChildrenItems,
            len,
            parentNode,
            childrenIDs,
            i,
            counter,
            childrenMeta;

        //TODO: implement real logic based on META and CONSTRAINTS...
        if(parentId && baseId){
            if (parentId === CONSTANTS.PROJECT_ROOT_ID) {
                //do not let them create
                // - FCO instances and
                // - META instances
                if (!_isProjectFCO(baseId) && !_isProjectMETA(baseId)) {
                    result = true;
                }
            } else {
                result = true;
            }

            //Check #1: is baseId a valid child of parentId
            if (result === true) {
                result = _client.isValidChild(parentId, baseId);
            }

            //Check #2: Global children number multiplicity
            if (result === true) {
                result = false;

                parentNode = _client.getNode(parentId);
                childrenIDs = parentNode.getChildrenIds();
                childrenMeta = _client.getChildrenMeta(parentId);
                if (childrenMeta.max === undefined ||
                    (childrenMeta.max && childrenIDs.length < childrenMeta.max)) {
                    result = true;
                }
            }

            //Check #3: exact child type multiplicity
            if (result === true) {
                result = false;
                parentNode = _client.getNode(parentId);

                validChildrenItems = _client.getValidChildrenItems(parentId);
                len = validChildrenItems.length;
                while (len--) {
                    if (_client.isTypeOf(baseId, validChildrenItems[len].id)) {
                        childrenIDs = parentNode.getChildrenIds();
                        counter = 0;
                        result = false;

                        for (i = 0; i < childrenIDs.length; i += 1) {
                            if (_client.isTypeOf(childrenIDs[i], validChildrenItems[len].id)) {
                                counter += 1;
                            }
                        }

                        if (validChildrenItems[len].max === undefined ||
                            (validChildrenItems[len].max && counter < validChildrenItems[len].max)) {
                            result = true;
                        }

                        if (result === false) {
                            break;
                        }
                    }
                }
            }
        }

        return result;
    };

    var _createBasicProjectSeed = function () {
        var metaRuleBase = {
            "children": {},
            "attributes": {},
            "pointers": {}
        };

        _client.startTransaction();

        //create FCO, META, PROJECT_BASE
        var FCO_ID = _client.createChild({'parentId': CONSTANTS.PROJECT_ROOT_ID});
        _client.setAttributes(FCO_ID, nodePropertyNames.Attributes.name, 'FCO');

        var META_ID = _client.createChild({'parentId': CONSTANTS.PROJECT_ROOT_ID});
        _client.setAttributes(META_ID, nodePropertyNames.Attributes.name, 'META');

        var PROJECT_BASE_ID = _client.createChild({'parentId': CONSTANTS.PROJECT_ROOT_ID});
        _client.setAttributes(PROJECT_BASE_ID, nodePropertyNames.Attributes.name, 'PROJECT');

        var projectRegistry = {};
        projectRegistry[CONSTANTS.PROJECT_FCO_ID] = FCO_ID;
        projectRegistry[CONSTANTS.PROJECT_META_ID] = META_ID;
        projectRegistry[CONSTANTS.PROJECT_PROJECT_BASE_ID] = PROJECT_BASE_ID;
        _client.setRegistry(CONSTANTS.PROJECT_ROOT_ID, nodePropertyNames.Registry.ProjectRegistry, projectRegistry);

        //FCO has a DisplayAttr registry field that controls what Attribute's value should be displayed
        //by default the Attributes.name is the to-be-displayed attribute
        _client.setRegistry(FCO_ID, nodePropertyNames.Registry.DisplayFormat, "%" + nodePropertyNames.Attributes.name);

        //set META rules accordingly

        //ROOT's meta rules
        var rootMeta = $.extend(true, {}, metaRuleBase);
        rootMeta.children.items = [{'$ref': '#' + FCO_ID}, {'$ref': '#' + META_ID}, {'$ref': '#' + PROJECT_BASE_ID}];
        rootMeta.children.minItems = [1,1,-1];
        rootMeta.children.maxItems = [1,1,-1];
        rootMeta.attributes.name = {'type': 'string'};
        _client.setMeta(CONSTANTS.PROJECT_ROOT_ID, rootMeta);

        //META's meta rules
        var metaMeta = $.extend(true, {}, metaRuleBase);
        metaMeta.children.items = [{'$ref': '#' + FCO_ID}, {'$ref': '#' + PROJECT_BASE_ID}];
        metaMeta.children.minItems = [-1,-1];
        metaMeta.children.maxItems = [-1,-1];
        metaMeta.attributes.name = {'type': 'string'};
        _client.setMeta(META_ID, metaMeta);

        //META's meta rules
        var projectBaseMeta = $.extend(true, {}, metaRuleBase);
        projectBaseMeta.attributes.name = {'type': 'string'};
        _client.setMeta(PROJECT_BASE_ID, projectBaseMeta);

        //FCO's meta rules
        var fcoMeta = $.extend(true, {}, metaRuleBase);
        fcoMeta.attributes.name = {'type': 'string'};
        _client.setMeta(FCO_ID, fcoMeta);

        //set METAEDITOR object containment correctly
        var rootMetaEditorDesc = MetaEditorConstants.GET_EMPTY_META_EDITOR_REGISTRY_OBJ();
        rootMetaEditorDesc.Members = [PROJECT_BASE_ID];
        rootMetaEditorDesc.MemberCoord[PROJECT_BASE_ID] = {'x': 100, 'y': 100};
        _client.setRegistry(CONSTANTS.PROJECT_ROOT_ID, MetaEditorConstants.META_EDITOR_REGISTRY_KEY, rootMetaEditorDesc);

        _client.completeTransaction();
    };

    var _isProjectRegistryValue = function (key, objID) {
        var rootNode = _client.getNode(CONSTANTS.PROJECT_ROOT_ID),
            projectRegistry = rootNode.getRegistry(nodePropertyNames.Registry.ProjectRegistry),
            value = projectRegistry ?  projectRegistry[key] : null;

        return objID === value;
    };

    var _isProjectFCO = function (objID) {
        return _isProjectRegistryValue(CONSTANTS.PROJECT_FCO_ID, objID);
    };

    var _isProjectMETA = function (objID) {
        return _isProjectRegistryValue(CONSTANTS.PROJECT_META_ID, objID);
    };

    var _isProjectPROJECTBASE = function (objID) {
        return _isProjectRegistryValue(CONSTANTS.PROJECT_PROJECT_BASE_ID, objID);
    };

    var _isBrowsable = function (objID) {
        var result = false;

        if (!_isProjectFCO(objID) &&
            !_isProjectPROJECTBASE(objID)) {
            result = true;
        }

        return result;
    };

    //return utility functions
    return {
        initialize: _initialize,
        isConnection: _isConnection,
        isConnectionType: _isConnectionType,
        isValidConnectionSource: _isValidConnectionSource,
        getValidConnectionTypes: _getValidConnectionTypes,
        canCreateChild: _canCreateChild,
        isValidConnection: _isValidConnection,
        createBasicProjectSeed: _createBasicProjectSeed,
        isBrowsable: _isBrowsable
    }
});<commit_msg>expose isProjectFCO, isProjectMETA, isProjectPROJECTBASE<commit_after>/*
 * Copyright (C) 2013 Vanderbilt University, All rights reserved.
 *
 * Author: Robert Kereskenyi
 */

"use strict";

/*
 * Utility helper functions implementing GME concepts...
 */

define(['jquery',
        'js/Constants',
        'js/NodePropertyNames',
        'js/Panels/MetaEditor/MetaEditorConstants'], function (_jquery,
                                           CONSTANTS,
                                           nodePropertyNames,
                                           MetaEditorConstants) {

    var _client;

    var _initialize = function (client) {
        if (!_client) {
            _client = client;
        }
    };

    /*
     * a connection is an object that has CONSTANTS.POINTER_SOURCE and CONSTANTS.POINTER_TARGET pointers and those values are set
     */
    var _isConnection = function (objID) {
        var validConnection = false,
            obj = _client.getNode(objID);

        if (obj) {
            var ptrNames = obj.getPointerNames();
            if (ptrNames.indexOf(CONSTANTS.POINTER_SOURCE) !== -1 &&
                ptrNames.indexOf(CONSTANTS.POINTER_TARGET) !== -1 &&
                obj.getPointer(CONSTANTS.POINTER_SOURCE).to &&
                obj.getPointer(CONSTANTS.POINTER_TARGET).to) {
                validConnection = true;
            }
        }

        return validConnection;
    };

    /*
     * a connectiontype is an object that has CONSTANTS.POINTER_SOURCE and CONSTANTS.POINTER_TARGET pointers
     */
    var _isConnectionType = function (objID) {
        var valid = false,
            obj = _client.getNode(objID);

        if (obj) {
            var ptrNames = obj.getPointerNames();
            if (ptrNames.indexOf(CONSTANTS.POINTER_SOURCE) !== -1 &&
                ptrNames.indexOf(CONSTANTS.POINTER_TARGET) !== -1) {
                valid = true;
            }
        }

        return valid;
    };

    /*
     * Determines if the given object in the given container can be a valid connection source
     *
     * The given parent has a valid children type that has CONSTANTS.POINTER_SOURCE and CONSTANTS.POINTER_TARGET pointers
     * and the given object can be a valid target for CONSTANTS.POINTER_SOURCE
     */
    var _isValidConnectionSource = function (objID, parentID) {
        var valid = false,
            validChildrenTypes,
            len,
            childID;

        validChildrenTypes = _client.getValidChildrenTypes(parentID) || [];
        len = validChildrenTypes.length;
        while (len--) {
            childID = validChildrenTypes[len];
            if (_client.getPointerMeta(childID, CONSTANTS.POINTER_SOURCE) &&
                _client.getPointerMeta(childID, CONSTANTS.POINTER_TARGET) &&
                _client.isValidTarget(childID, CONSTANTS.POINTER_SOURCE, objID)) {
                valid = true;
                break;
            }
        }

        return valid;
    };

    /*
     * Determines if a GME Connection can be created between source and target in parent
     */
    var _getValidConnectionTypes = function (sourceID, targetID, parentID) {
        var validTypes = [],
            validChildrenTypes,
            len,
            childID;

        validChildrenTypes = _client.getValidChildrenTypes(parentID) || [];
        len = validChildrenTypes.length;
        while (len--) {
            childID = validChildrenTypes[len];
            if (_client.getPointerMeta(childID, CONSTANTS.POINTER_SOURCE) &&
                _client.getPointerMeta(childID, CONSTANTS.POINTER_TARGET) &&
                _client.isValidTarget(childID, CONSTANTS.POINTER_SOURCE, sourceID) &&
                _client.isValidTarget(childID, CONSTANTS.POINTER_TARGET, targetID)) {
                validTypes.push(childID);
            }
        }

        return validTypes;
    };

    /*
     * Determines if a GME Connection is valid by META between source and destination
     */
    var _isValidConnection = function (sourceID, targetID, connectionID) {
        var valid = false;

        if (sourceID !== undefined && targetID !== undefined && connectionID !== undefined) {
            if (_client.isValidTarget(connectionID, CONSTANTS.POINTER_SOURCE, sourceID) &&
                _client.isValidTarget(connectionID, CONSTANTS.POINTER_TARGET, targetID)) {
                valid = true;
            }
        }

        return valid;
    };

    /*
     * Returns true if a new child with the given baseId (instance of base) can be created in parent
     */
    var _canCreateChild = function (parentId, baseId) {
        var result = false,
            validChildrenItems,
            len,
            parentNode,
            childrenIDs,
            i,
            counter,
            childrenMeta;

        //TODO: implement real logic based on META and CONSTRAINTS...
        if(parentId && baseId){
            if (parentId === CONSTANTS.PROJECT_ROOT_ID) {
                //do not let them create
                // - FCO instances and
                // - META instances
                if (!_isProjectFCO(baseId) && !_isProjectMETA(baseId)) {
                    result = true;
                }
            } else {
                result = true;
            }

            //Check #1: is baseId a valid child of parentId
            if (result === true) {
                result = _client.isValidChild(parentId, baseId);
            }

            //Check #2: Global children number multiplicity
            if (result === true) {
                result = false;

                parentNode = _client.getNode(parentId);
                childrenIDs = parentNode.getChildrenIds();
                childrenMeta = _client.getChildrenMeta(parentId);
                if (childrenMeta.max === undefined ||
                    (childrenMeta.max && childrenIDs.length < childrenMeta.max)) {
                    result = true;
                }
            }

            //Check #3: exact child type multiplicity
            if (result === true) {
                result = false;
                parentNode = _client.getNode(parentId);

                validChildrenItems = _client.getValidChildrenItems(parentId);
                len = validChildrenItems.length;
                while (len--) {
                    if (_client.isTypeOf(baseId, validChildrenItems[len].id)) {
                        childrenIDs = parentNode.getChildrenIds();
                        counter = 0;
                        result = false;

                        for (i = 0; i < childrenIDs.length; i += 1) {
                            if (_client.isTypeOf(childrenIDs[i], validChildrenItems[len].id)) {
                                counter += 1;
                            }
                        }

                        if (validChildrenItems[len].max === undefined ||
                            (validChildrenItems[len].max && counter < validChildrenItems[len].max)) {
                            result = true;
                        }

                        if (result === false) {
                            break;
                        }
                    }
                }
            }
        }

        return result;
    };

    var _createBasicProjectSeed = function () {
        var metaRuleBase = {
            "children": {},
            "attributes": {},
            "pointers": {}
        };

        _client.startTransaction();

        //create FCO, META, PROJECT_BASE
        var FCO_ID = _client.createChild({'parentId': CONSTANTS.PROJECT_ROOT_ID});
        _client.setAttributes(FCO_ID, nodePropertyNames.Attributes.name, 'FCO');

        var META_ID = _client.createChild({'parentId': CONSTANTS.PROJECT_ROOT_ID});
        _client.setAttributes(META_ID, nodePropertyNames.Attributes.name, 'META');

        var PROJECT_BASE_ID = _client.createChild({'parentId': CONSTANTS.PROJECT_ROOT_ID});
        _client.setAttributes(PROJECT_BASE_ID, nodePropertyNames.Attributes.name, 'PROJECT');

        var projectRegistry = {};
        projectRegistry[CONSTANTS.PROJECT_FCO_ID] = FCO_ID;
        projectRegistry[CONSTANTS.PROJECT_META_ID] = META_ID;
        projectRegistry[CONSTANTS.PROJECT_PROJECT_BASE_ID] = PROJECT_BASE_ID;
        _client.setRegistry(CONSTANTS.PROJECT_ROOT_ID, nodePropertyNames.Registry.ProjectRegistry, projectRegistry);

        //FCO has a DisplayAttr registry field that controls what Attribute's value should be displayed
        //by default the Attributes.name is the to-be-displayed attribute
        _client.setRegistry(FCO_ID, nodePropertyNames.Registry.DisplayFormat, "%" + nodePropertyNames.Attributes.name);

        //set META rules accordingly

        //ROOT's meta rules
        var rootMeta = $.extend(true, {}, metaRuleBase);
        rootMeta.children.items = [{'$ref': '#' + FCO_ID}, {'$ref': '#' + META_ID}, {'$ref': '#' + PROJECT_BASE_ID}];
        rootMeta.children.minItems = [1,1,-1];
        rootMeta.children.maxItems = [1,1,-1];
        rootMeta.attributes.name = {'type': 'string'};
        _client.setMeta(CONSTANTS.PROJECT_ROOT_ID, rootMeta);

        //META's meta rules
        var metaMeta = $.extend(true, {}, metaRuleBase);
        metaMeta.children.items = [{'$ref': '#' + FCO_ID}, {'$ref': '#' + PROJECT_BASE_ID}];
        metaMeta.children.minItems = [-1,-1];
        metaMeta.children.maxItems = [-1,-1];
        metaMeta.attributes.name = {'type': 'string'};
        _client.setMeta(META_ID, metaMeta);

        //META's meta rules
        var projectBaseMeta = $.extend(true, {}, metaRuleBase);
        projectBaseMeta.attributes.name = {'type': 'string'};
        _client.setMeta(PROJECT_BASE_ID, projectBaseMeta);

        //FCO's meta rules
        var fcoMeta = $.extend(true, {}, metaRuleBase);
        fcoMeta.attributes.name = {'type': 'string'};
        _client.setMeta(FCO_ID, fcoMeta);

        //set METAEDITOR object containment correctly
        var rootMetaEditorDesc = MetaEditorConstants.GET_EMPTY_META_EDITOR_REGISTRY_OBJ();
        rootMetaEditorDesc.Members = [PROJECT_BASE_ID];
        rootMetaEditorDesc.MemberCoord[PROJECT_BASE_ID] = {'x': 100, 'y': 100};
        _client.setRegistry(CONSTANTS.PROJECT_ROOT_ID, MetaEditorConstants.META_EDITOR_REGISTRY_KEY, rootMetaEditorDesc);

        _client.completeTransaction();
    };

    var _isProjectRegistryValue = function (key, objID) {
        var rootNode = _client.getNode(CONSTANTS.PROJECT_ROOT_ID),
            projectRegistry = rootNode.getRegistry(nodePropertyNames.Registry.ProjectRegistry),
            value = projectRegistry ?  projectRegistry[key] : null;

        return objID === value;
    };

    var _isProjectFCO = function (objID) {
        return _isProjectRegistryValue(CONSTANTS.PROJECT_FCO_ID, objID);
    };

    var _isProjectMETA = function (objID) {
        return _isProjectRegistryValue(CONSTANTS.PROJECT_META_ID, objID);
    };

    var _isProjectPROJECTBASE = function (objID) {
        return _isProjectRegistryValue(CONSTANTS.PROJECT_PROJECT_BASE_ID, objID);
    };

    var _isBrowsable = function (objID) {
        var result = false;

        if (!_isProjectFCO(objID) &&
            !_isProjectPROJECTBASE(objID)) {
            result = true;
        }

        return result;
    };

    //return utility functions
    return {
        initialize: _initialize,
        isConnection: _isConnection,
        isConnectionType: _isConnectionType,
        isValidConnectionSource: _isValidConnectionSource,
        getValidConnectionTypes: _getValidConnectionTypes,
        canCreateChild: _canCreateChild,
        isValidConnection: _isValidConnection,
        createBasicProjectSeed: _createBasicProjectSeed,
        isBrowsable: _isBrowsable,
        isProjectFCO: _isProjectFCO,
        isProjectMETA: _isProjectMETA,
        isProjectPROJECTBASE: _isProjectPROJECTBASE
    }
});<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Aalto University and University of Helsinki
 * MIT License
 * see LICENSE.txt for more information
 */
var treeIndex = {};
var urlToUri = {};
var rest = rest_base_url;

/*
 * For legacy browsers that don't natively support Object.size().
 * @param {Object} obj
 */
Object.size = function (obj) {
  var size = 0, key;
  for (key in obj) {
    if (obj.hasOwnProperty(key)) {
      size += 1;
    }
  }
  return size;
};

function getNode(uri) { return treeIndex[uri]; }

function setNode(node) { treeIndex[node.uri] = node; storeUri(node); }

function storeUri(node) { urlToUri[node.a_attr.href] = node.uri; }

/*
 * Forces node to open when it's clicked.
 * @param {Object} tree
 */
function invokeParentTree(tree) {
  var $treeObject = $('.sidebar-grey');
  $treeObject.on('activate_node.jstree', function(event, node) {
    $treeObject.jstree('open_node', node.node);
  });

  $treeObject.on('loaded.jstree', function(event, node) {
    if ($('.mCustomScrollbar').length === 0) {
      $(".sidebar-grey").mCustomScrollbar({
        alwaysShowScrollbar: 1,
        scrollInertia: 0,
        mouseWheel:{ scrollAmount: 105 },
        snapAmount: 18,
        snapOffset: 1
      });
    }
    if ($('.jstree-leaf-proper').length > 0) {
      $('.sidebar-grey').jstree('select_node', $('.jstree-leaf-proper').toArray());
      $('.sidebar-grey').mCustomScrollbar('scrollTo', getLeafOffset());
    }
  });
}

function getLeafOffset() {
  var containerHeight = $('.sidebar-grey').height();
  var conceptCount = Math.floor((containerHeight * 0.66) / 18);
  var scrollAmount = 18 * conceptCount;
  if ($('.jstree-leaf-proper').length) {
    var newOffset = $('.jstree-leaf-proper')[0].offsetTop-scrollAmount;
    if (newOffset > 0) // only scrolls the view if the concept isn't already at the top.
      return newOffset;
  }
}

/*
 * Creates a concept object from the data returned by a rest query.
 * @param
 * @param
 */
function createConceptObject(conceptUri, conceptData) {
  var prefLabel = conceptData.prefLabel; // the json narrower response has a different structure.
  newNode = {
    text: prefLabel,
    a_attr: { "href" : conceptUri },
    uri: conceptUri,
    parents: conceptData.broader,
    state: { opened: true },
    children: []
  };
  // setting the flag manually if the concept is known to have narrowers, but they aren't included eg. included topconcepts
  if(conceptData.hasChildren === true) {
    newNode.children = true;
    newNode.state.opened = false;
  }
  // if we are at a top concepts page we want to highlight that node and mark it as to be initially opened.
  if (newNode.uri === $('.uri-input-box').html()) { newNode.li_attr = { class: 'jstree-leaf-proper' }; }
  if (conceptData.narrower) { // filtering out the ones that don't have labels
    var childArray = [];
    for (var child in conceptData.narrower) {
      var conceptObject = conceptData.narrower[child];
      var hasChildren = conceptObject.hasChildren;
      var childObject = {
        text: conceptObject.label,
        a_attr: { "href" : conceptData.narrower[child].uri },
        uri: conceptData.narrower[child].uri,
        parents: conceptUri,
        state: { opened: true }
      };
      if (child === $('.uri-input-box').html()) { /* childObject.data.attr.id = 'jstree-leaf-proper'; */ }
      // if the childConcept hasn't got any children the state is not needed.
      if (hasChildren) {
        childObject.children = true;
        childObject.state.opened = false;
      }
      if(!childArray[childObject.uri])
        childArray.push(childObject);
      storeUri(childObject);
    }
    newNode.children = childArray;
  }

  return newNode;
}

/*
 * For building a parent hierarchy tree from the leaf concept to the ontology/vocabulary root.
 * @param {String} uri
 * @param {Object} parentData
 */
function buildParentTree(uri, parentData) {
  if (parentData === undefined || parentData === null) { return; }

  var loopIndex = 0, // for adding the last concept as a root if no better candidates have been found.
    currentNode,
    rootArray = [],
    rootNode;

    for(var conceptUri in parentData) {
    var previousNode = currentNode,
      branchHelper,
      exactMatchFound;
    currentNode = createConceptObject(conceptUri, parentData[conceptUri]);
    /* if a node has the property topConceptOf set it as the root node.
     * Or just setting the last node as a root if nothing else has been found
     */
    if (parentData[conceptUri].top || ( loopIndex == Object.size(parentData)-1) && !rootNode || !currentNode.parents && !rootNode) {
      if (!rootNode) {
        branchHelper = currentNode;
      }
      rootNode = currentNode;
      rootArray.push(rootNode);
    }
    if (exactMatchFound) { // combining branches if we have met a exact match during the previous iteration.
      currentNode.children.push(branchHelper);
      branchHelper = undefined;
      exactMatchFound = false;
    }
    // here we have iterated far enough to find the merging point of the trees.
    if (branchHelper && parentData[branchHelper.uri].exact === currentNode.uri) {
      exactMatchFound = true;
    }
    setNode(currentNode);
    loopIndex++;
  }

  // Iterating over the nodes to make sure all concepts have their children set.
  appendChildrenToParents();
  console.log(rootArray);
  return rootArray;
}

function vocabRoot(topConcepts) {
  var topArray = [];
  for (var i = 0; i < topConcepts.length; i++) {
    var conceptData = topConcepts[i];
    var childObject = {
      text: conceptData.label,
      a_attr : { "href" : conceptData.uri },
      uri: conceptData.uri,
      children: [],
      state: { opened: false }
    };
    setNode(childObject);
    topArray.push(childObject);
  }
  return topArray;
}

/*
 * Iterates through the tree and fixes all the parents by adding references to their child concepts.
 */
function appendChildrenToParents() {
  for (var j in treeIndex) {
    var current = treeIndex[j];
    for (var index in current.parents) {
      var parentNode = getNode(current.parents[index]);
      if (parentNode !== current)
        if (parentNode && $.inArray(current, parentNode.children) === -1) {
          for(var sibling in parentNode.children) {
            if(parentNode.children[sibling].uri === current.uri){
              // if the concept has already been enrich the previous one with the additional information.
              parentNode.children[sibling].children = current.children;
              parentNode.children[sibling].state = current.state;
              parentNode.children[sibling].li_attr = current.li_attr;
            }
          }
        }
    }
  }
}

function createObjectsFromNarrowers(narrowerResponse) {
  var childArray = [];
  for (var child in narrowerResponse.narrower) {
    var conceptObject = narrowerResponse.narrower[child];
    var hasChildren = conceptObject.hasChildren;
    var childObject = {
      text : conceptObject.prefLabel,
      a_attr : { "href" : conceptObject.uri },
      uri: conceptObject.uri,
      parents: narrowerResponse.uri,
      state: { opened: false, disabled: false, selected: false }
    };
    if (hasChildren) {
      childObject.children = true;
      childObject.state.opened = false;
    }
    setNode(childObject);
    childArray.push(childObject);
  }
  return childArray;
}

function getParams(node) {
  var nodeId;
  if (node.id === '#')
    nodeId = $('.uri-input-box').html(); // using the real uri of the concept from the view.
  else
    nodeId = node.original.uri;
  var contentLanguage = getUrlParams().clang ? getUrlParams().clang : lang;
  return $.param({'uri' : nodeId, 'lang' : contentLanguage});
}

/*
 * Gives you the Skosmos default jsTree configuration.
 */
function getTreeConfiguration(root) {
  $('.sidebar-grey').empty().jstree({
    'core' : {
      'animation' : 0,
      'themes' : { 'icons': false },
      'data' :
        function(node, cb) {
          var json_url = (rest_base_url + vocab + '/hierarchy');
          if (node.id === '#') {
            nodeId = $('.uri-input-box').html(); // using the real uri of the concept from the view.
          } else  {
            nodeId = node.uri;
            json_url = (rest_base_url + vocab + '/children');
          }
          var params = getParams(node);
          var jsondata = $.ajax({
            data: params,
            url: json_url,
            success: function (response) {
              if (response.broaderTransitive) { // the default hierarchy query that fires when a page loads.
                cb(buildParentTree(nodeId, response.broaderTransitive));
              } else if(response.topconcepts) {
                cb(vocabRoot(response.topconcepts));
              } else {
                cb(createObjectsFromNarrowers(response));
              }
            }
          });
      }
    },
    'plugins' : ['sort']
  });
}

<commit_msg>cleaning up logging js code<commit_after>/*
 * Copyright (c) 2012 Aalto University and University of Helsinki
 * MIT License
 * see LICENSE.txt for more information
 */
var treeIndex = {};
var urlToUri = {};
var rest = rest_base_url;

/*
 * For legacy browsers that don't natively support Object.size().
 * @param {Object} obj
 */
Object.size = function (obj) {
  var size = 0, key;
  for (key in obj) {
    if (obj.hasOwnProperty(key)) {
      size += 1;
    }
  }
  return size;
};

function getNode(uri) { return treeIndex[uri]; }

function setNode(node) { treeIndex[node.uri] = node; storeUri(node); }

function storeUri(node) { urlToUri[node.a_attr.href] = node.uri; }

/*
 * Forces node to open when it's clicked.
 * @param {Object} tree
 */
function invokeParentTree(tree) {
  var $treeObject = $('.sidebar-grey');
  $treeObject.on('activate_node.jstree', function(event, node) {
    $treeObject.jstree('open_node', node.node);
  });

  $treeObject.on('loaded.jstree', function(event, node) {
    if ($('.mCustomScrollbar').length === 0) {
      $(".sidebar-grey").mCustomScrollbar({
        alwaysShowScrollbar: 1,
        scrollInertia: 0,
        mouseWheel:{ scrollAmount: 105 },
        snapAmount: 18,
        snapOffset: 1
      });
    }
    if ($('.jstree-leaf-proper').length > 0) {
      $('.sidebar-grey').jstree('select_node', $('.jstree-leaf-proper').toArray());
      $('.sidebar-grey').mCustomScrollbar('scrollTo', getLeafOffset());
    }
  });
}

function getLeafOffset() {
  var containerHeight = $('.sidebar-grey').height();
  var conceptCount = Math.floor((containerHeight * 0.66) / 18);
  var scrollAmount = 18 * conceptCount;
  if ($('.jstree-leaf-proper').length) {
    var newOffset = $('.jstree-leaf-proper')[0].offsetTop-scrollAmount;
    if (newOffset > 0) // only scrolls the view if the concept isn't already at the top.
      return newOffset;
  }
}

/*
 * Creates a concept object from the data returned by a rest query.
 * @param
 * @param
 */
function createConceptObject(conceptUri, conceptData) {
  var prefLabel = conceptData.prefLabel; // the json narrower response has a different structure.
  newNode = {
    text: prefLabel,
    a_attr: { "href" : conceptUri },
    uri: conceptUri,
    parents: conceptData.broader,
    state: { opened: true },
    children: []
  };
  // setting the flag manually if the concept is known to have narrowers, but they aren't included eg. included topconcepts
  if(conceptData.hasChildren === true) {
    newNode.children = true;
    newNode.state.opened = false;
  }
  // if we are at a top concepts page we want to highlight that node and mark it as to be initially opened.
  if (newNode.uri === $('.uri-input-box').html()) { newNode.li_attr = { class: 'jstree-leaf-proper' }; }
  if (conceptData.narrower) { // filtering out the ones that don't have labels
    var childArray = [];
    for (var child in conceptData.narrower) {
      var conceptObject = conceptData.narrower[child];
      var hasChildren = conceptObject.hasChildren;
      var childObject = {
        text: conceptObject.label,
        a_attr: { "href" : conceptData.narrower[child].uri },
        uri: conceptData.narrower[child].uri,
        parents: conceptUri,
        state: { opened: true }
      };
      if (child === $('.uri-input-box').html()) { /* childObject.data.attr.id = 'jstree-leaf-proper'; */ }
      // if the childConcept hasn't got any children the state is not needed.
      if (hasChildren) {
        childObject.children = true;
        childObject.state.opened = false;
      }
      if(!childArray[childObject.uri])
        childArray.push(childObject);
      storeUri(childObject);
    }
    newNode.children = childArray;
  }

  return newNode;
}

/*
 * For building a parent hierarchy tree from the leaf concept to the ontology/vocabulary root.
 * @param {String} uri
 * @param {Object} parentData
 */
function buildParentTree(uri, parentData) {
  if (parentData === undefined || parentData === null) { return; }

  var loopIndex = 0, // for adding the last concept as a root if no better candidates have been found.
    currentNode,
    rootArray = [],
    rootNode;

    for(var conceptUri in parentData) {
    var previousNode = currentNode,
      branchHelper,
      exactMatchFound;
    currentNode = createConceptObject(conceptUri, parentData[conceptUri]);
    /* if a node has the property topConceptOf set it as the root node.
     * Or just setting the last node as a root if nothing else has been found
     */
    if (parentData[conceptUri].top || ( loopIndex == Object.size(parentData)-1) && !rootNode || !currentNode.parents && !rootNode) {
      if (!rootNode) {
        branchHelper = currentNode;
      }
      rootNode = currentNode;
      rootArray.push(rootNode);
    }
    if (exactMatchFound) { // combining branches if we have met a exact match during the previous iteration.
      currentNode.children.push(branchHelper);
      branchHelper = undefined;
      exactMatchFound = false;
    }
    // here we have iterated far enough to find the merging point of the trees.
    if (branchHelper && parentData[branchHelper.uri].exact === currentNode.uri) {
      exactMatchFound = true;
    }
    setNode(currentNode);
    loopIndex++;
  }

  // Iterating over the nodes to make sure all concepts have their children set.
  appendChildrenToParents();
  return rootArray;
}

function vocabRoot(topConcepts) {
  var topArray = [];
  for (var i = 0; i < topConcepts.length; i++) {
    var conceptData = topConcepts[i];
    var childObject = {
      text: conceptData.label,
      a_attr : { "href" : conceptData.uri },
      uri: conceptData.uri,
      children: [],
      state: { opened: false }
    };
    setNode(childObject);
    topArray.push(childObject);
  }
  return topArray;
}

/*
 * Iterates through the tree and fixes all the parents by adding references to their child concepts.
 */
function appendChildrenToParents() {
  for (var j in treeIndex) {
    var current = treeIndex[j];
    for (var index in current.parents) {
      var parentNode = getNode(current.parents[index]);
      if (parentNode !== current)
        if (parentNode && $.inArray(current, parentNode.children) === -1) {
          for(var sibling in parentNode.children) {
            if(parentNode.children[sibling].uri === current.uri){
              // if the concept has already been enrich the previous one with the additional information.
              parentNode.children[sibling].children = current.children;
              parentNode.children[sibling].state = current.state;
              parentNode.children[sibling].li_attr = current.li_attr;
            }
          }
        }
    }
  }
}

function createObjectsFromNarrowers(narrowerResponse) {
  var childArray = [];
  for (var child in narrowerResponse.narrower) {
    var conceptObject = narrowerResponse.narrower[child];
    var hasChildren = conceptObject.hasChildren;
    var childObject = {
      text : conceptObject.prefLabel,
      a_attr : { "href" : conceptObject.uri },
      uri: conceptObject.uri,
      parents: narrowerResponse.uri,
      state: { opened: false, disabled: false, selected: false }
    };
    if (hasChildren) {
      childObject.children = true;
      childObject.state.opened = false;
    }
    setNode(childObject);
    childArray.push(childObject);
  }
  return childArray;
}

function getParams(node) {
  var nodeId;
  if (node.id === '#')
    nodeId = $('.uri-input-box').html(); // using the real uri of the concept from the view.
  else
    nodeId = node.original.uri;
  var contentLanguage = getUrlParams().clang ? getUrlParams().clang : lang;
  return $.param({'uri' : nodeId, 'lang' : contentLanguage});
}

/*
 * Gives you the Skosmos default jsTree configuration.
 */
function getTreeConfiguration(root) {
  $('.sidebar-grey').empty().jstree({
    'core' : {
      'animation' : 0,
      'themes' : { 'icons': false },
      'data' :
        function(node, cb) {
          var json_url = (rest_base_url + vocab + '/hierarchy');
          if (node.id === '#') {
            nodeId = $('.uri-input-box').html(); // using the real uri of the concept from the view.
          } else  {
            nodeId = node.uri;
            json_url = (rest_base_url + vocab + '/children');
          }
          var params = getParams(node);
          var jsondata = $.ajax({
            data: params,
            url: json_url,
            success: function (response) {
              if (response.broaderTransitive) { // the default hierarchy query that fires when a page loads.
                cb(buildParentTree(nodeId, response.broaderTransitive));
              } else if(response.topconcepts) {
                cb(vocabRoot(response.topconcepts));
              } else {
                cb(createObjectsFromNarrowers(response));
              }
            }
          });
      }
    },
    'plugins' : ['sort']
  });
}

<|endoftext|>


<commit_before>function drawBarChart(element, data, threshold) {

  var svg = d3.select(element),
    margin = {top: 20, right: 20, bottom: 110, left: 40},
    margin2 = {top: 430, right: 20, bottom: 30, left: 40},
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom,
    height2 = +svg.attr("height") - margin2.top - margin2.bottom;

  var x = d3.scaleLinear().range([0, width]),
    x2 = d3.scaleLinear().range([0, width]),
    y = d3.scaleLinear().range([height, 0]),
    y2 = d3.scaleLinear().range([height2, 0]);

  var xAxis = d3.axisBottom(x),
    xAxis2 = d3.axisBottom(x2),
    yAxis = d3.axisLeft(y);

  var brush = d3.brushX()
    .extent([[0, 0], [width, height2]])
    .on("brush end", brushed);

  var area = d3.area()
    .curve(d3.curveMonotoneX)
    .x(function(d, i) { return x(i); })
    .y0(height)
    .y1(function(d) { return y(d.total); });

  var area2 = d3.area()
    .curve(d3.curveMonotoneX)
    .x(function(d, i) { return x2(i); })
    .y0(height2)
    .y1(function(d) { return y2(d.total); });

  svg.append("defs").append("clipPath")
    .attr("id", "clip")
    .append("rect")
    .attr("width", width)
    .attr("height", height);

  var focus = svg.append("g")
    .attr("class", "focus")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var context = svg.append("g")
    .attr("class", "context")
    .attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");

    x.domain(d3.extent(data, function(d, i) { return i; }));
    y.domain([0, d3.max(data, function(d) { return d.total; })]);
    x2.domain(x.domain());
    y2.domain(y.domain());

  // Returns a function, that, as long as it continues to be invoked, will not
  // be triggered. The function will be called after it stops being called for
  // N milliseconds. If `immediate` is passed, trigger the function on the
  // leading edge, instead of the trailing.
  // debounce function stolen from https://github.com/jashkenas/underscore/blob/master/underscore.js
  function debounce(func, wait, immediate) {
    var timeout;
    return function() {
      var context = this, args = arguments;
      var later = function() {
        timeout = null;
        if (!immediate) func.apply(context, args);
      };
      var callNow = immediate && !timeout;
      clearTimeout(timeout);
      timeout = setTimeout(later, wait);
      if (callNow) func.apply(context, args);
    };
  };

  const efficientDrawBars = debounce(drawBars, 100);

  function drawBars(dataset, selection) {
    var bars = focus.selectAll(".bar").data(dataset, datum => datum);
    var segment = width / dataset.length;
    var barW = (segment / 10) * 8

    bars.exit().remove();

    //ENTER
    bars.enter()
          .append("rect")
        // .attr("class", "bar")
        .attr("class", function(d) { return d.total < FRAUD_THRESHOLD + 1 ? "bar" : "bar is-fraud" })
        .attr("x", function(d, i) { return x( i + selection[0] ); })
        .attr("y", function(d) { return y(d.total); })
        .attr("width", function() { return barW; })
        .attr("height", function(d) { return height - y(d.total); });

    bars.enter()
          .append("rect")
        .attr("class", "bar enter")
        .attr("x", function(d, i) { return x( i + selection[0] ); })
        .attr("y", function(d) { return y(d.checkOne); })
        .attr("width", function() { return barW; })
        .attr("height", function(d) { return height - y(d.checkOne); });

    focus.append('line')
         .attr("x1", 0)
         .attr("y1", y(threshold))
         .attr("x2", width)
         .attr("y2", y(threshold))
         .attr("stroke-width", 2)
         .attr("stroke", "#cc333f");
  }

  // efficientDrawBars(data, x2.range());
  drawBars(data, x2.range());

  focus.append("g")
    .attr("class", "axis axis--x")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

  focus.append("g")
    .attr("class", "axis axis--y")
    .call(yAxis);

  context.append("path")
    .datum(data)
    .attr("class", "area")
    .attr("d", area2);

  context.append("g")
    .attr("class", "axis axis--x")
    .attr("transform", "translate(0," + height2 + ")")
    .call(xAxis2);

  context.append("g")
    .attr("class", "brush")
    .call(brush)
    .call(brush.move, x.range());

  function brushed() {
    var s = d3.event.selection || x2.range();
    var xs = s.map(x2.invert, x2)
    var rounded = [Math.floor(xs[0]), Math.floor(xs[1])];

    x.domain(xs);
    focus.select(".area").attr("d", area);
    focus.select(".axis--x").call(xAxis);

    // efficientDrawBars(data.slice(rounded[0], rounded[1]), rounded);
    drawBars(data.slice(rounded[0], rounded[1]), rounded);

  }

}
<commit_msg>position bar on top of axis tics instead of between them<commit_after>function drawBarChart(element, data, threshold) {

  var svg = d3.select(element),
    margin = {top: 20, right: 20, bottom: 110, left: 40},
    margin2 = {top: 430, right: 20, bottom: 30, left: 40},
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom,
    height2 = +svg.attr("height") - margin2.top - margin2.bottom;

  var x = d3.scaleLinear().range([0, width]),
    x2 = d3.scaleLinear().range([0, width]),
    y = d3.scaleLinear().range([height, 0]),
    y2 = d3.scaleLinear().range([height2, 0]);

  var xAxis = d3.axisBottom(x),
    xAxis2 = d3.axisBottom(x2),
    yAxis = d3.axisLeft(y);

  var brush = d3.brushX()
    .extent([[0, 0], [width, height2]])
    .on("brush end", brushed);

  var area = d3.area()
    .curve(d3.curveMonotoneX)
    .x(function(d, i) { return x(i); })
    .y0(height)
    .y1(function(d) { return y(d.total); });

  var area2 = d3.area()
    .curve(d3.curveMonotoneX)
    .x(function(d, i) { return x2(i); })
    .y0(height2)
    .y1(function(d) { return y2(d.total); });

  svg.append("defs").append("clipPath")
    .attr("id", "clip")
    .append("rect")
    .attr("width", width)
    .attr("height", height);

  var focus = svg.append("g")
    .attr("class", "focus")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var context = svg.append("g")
    .attr("class", "context")
    .attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");

    x.domain(d3.extent(data, function(d, i) { return i; }));
    y.domain([0, d3.max(data, function(d) { return d.total; })]);
    x2.domain(x.domain());
    y2.domain(y.domain());

  // Returns a function, that, as long as it continues to be invoked, will not
  // be triggered. The function will be called after it stops being called for
  // N milliseconds. If `immediate` is passed, trigger the function on the
  // leading edge, instead of the trailing.
  // debounce function stolen from https://github.com/jashkenas/underscore/blob/master/underscore.js
  function debounce(func, wait, immediate) {
    var timeout;
    return function() {
      var context = this, args = arguments;
      var later = function() {
        timeout = null;
        if (!immediate) func.apply(context, args);
      };
      var callNow = immediate && !timeout;
      clearTimeout(timeout);
      timeout = setTimeout(later, wait);
      if (callNow) func.apply(context, args);
    };
  };

  const efficientDrawBars = debounce(drawBars, 20);

  function drawBars(dataset, selection) {
    var bars = focus.selectAll(".bar").data(dataset, datum => datum);
    var segment = width / dataset.length;
    console.log(segment);
    var tenth = (segment / 10);
    var barW = (segment / 10) * 8;
    console.log(barW);

    bars.exit().remove();

    //ENTER
    bars.enter()
          .append("rect")
        // .attr("class", "bar")
        .attr("class", function(d) { return d.total < FRAUD_THRESHOLD + 1 ? "bar" : "bar is-fraud" })
        .attr("x", function(d, i) { return x( i + selection[0] ); })
        .attr("y", function(d) { return y(d.total); })
        .attr("width", function() { return barW; })
        .attr("height", function(d) { return height - y(d.total); });

    bars.enter()
          .append("rect")
        .attr("class", "bar enter")
        .attr("x", function(d, i) { return x(i + selection[0]) - (barW / 2); })
        .attr("y", function(d) { return y(d.checkOne); })
        .attr("width", function() { return barW; })
        .attr("height", function(d) { return height - y(d.checkOne); });

    focus.append('line')
         .attr("x1", 0)
         .attr("y1", y(threshold))
         .attr("x2", width)
         .attr("y2", y(threshold))
         .attr("stroke-width", 2)
         .attr("stroke", "#cc333f");
  }

  // efficientDrawBars(data, x2.range());
  drawBars(data, x2.range());

  focus.append("g")
    .attr("class", "axis axis--x")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

  focus.append("g")
    .attr("class", "axis axis--y")
    .call(yAxis);

  context.append("path")
    .datum(data)
    .attr("class", "area")
    .attr("d", area2);

  context.append("g")
    .attr("class", "axis axis--x")
    .attr("transform", "translate(0," + height2 + ")")
    .call(xAxis2);

  context.append("g")
    .attr("class", "brush")
    .call(brush)
    .call(brush.move, x.range());

  function brushed() {
    var s = d3.event.selection || x2.range();
    var xs = s.map(x2.invert, x2)

    x.domain(xs);
    focus.select(".area").attr("d", area);
    focus.select(".axis--x").call(xAxis);

<<<<<<< e5bdeb527561b3958da3f06c286336db6286a983
    // efficientDrawBars(data.slice(rounded[0], rounded[1]), rounded);
    drawBars(data.slice(rounded[0], rounded[1]), rounded);
=======
    efficientDrawBars(data.slice(xs[0], xs[1]), xs);
>>>>>>> position bar on top of axis tics instead of between them

  }

}
<|endoftext|>


<commit_before>const ctrlTest = require('./pokemon.ctrl');

describe('PokemonCtrl', function() {

  let $controller, $scope, $routeParams, io, tested;

  beforeEach(inject(function(_$controller_){
    // The injector unwraps the underscores (_) from around the parameter names when matching
    $controller = _$controller_;
    $scope = {};
    $routeParams = {};
    io = {
      socket: {
        get: function () {}
      }
    };
  }));

  describe('controller variables', function() {
    it('are correctly taken from the box input', function() {
      tested = $controller(ctrlTest, {
        $scope: $scope,
        io: io, $routeParams:
        $routeParams
      }, {data: {
        speciesName: 'Pelipper',
        nickname: 'pokemondNickname',
        dexNo: 'pokemonDexNo',
        owner: 'boxUser',
        id: 'pokemonId',
        isShiny: false
      }});
      tested.parseProps();
      expect(tested.data.nickname).to.equal('pokemondNickname');
      expect(tested.data.owner).to.equal('boxUser');
      expect(tested.data.dexNo).to.equal('pokemonDexNo');
      expect(tested.data.id).to.equal('pokemonId');
      expect(tested.iconUrl).to.equal('pokemon/regular/pelipper');
    });

    it('are correctly instantiated when not provided at construction', function() {
      $routeParams.pokemonid = 'routeParamId';
      tested = $controller(ctrlTest, {
        $scope: $scope,
        io: io, $routeParams:
        $routeParams
      }, {});
      tested.parseProps();
      expect(tested.id).to.equal('routeParamId');
      expect(Object.keys(tested.data).length).to.equal(0);
    });

    it("pads a Pokémon's TID correctly", function() {
      const tested1 = $controller(ctrlTest, {$scope, io, $routeParams}, {data: {tid: 12345}});
      tested1.parseProps();
      expect(tested1.paddedTid).to.equal('12345');
      const tested2 = $controller(ctrlTest, {$scope, io, $routeParams}, {data: {tid: 1234}});
      tested2.parseProps();
      expect(tested2.paddedTid).to.equal('01234');
      const tested3 = $controller(ctrlTest, {$scope, io, $routeParams}, {data: {tid: 123}});
      tested3.parseProps();
      expect(tested3.paddedTid).to.equal('00123');
      const tested4 = $controller(ctrlTest, {$scope, io, $routeParams}, {data: {tid: 12}});
      tested4.parseProps();
      expect(tested4.paddedTid).to.equal('00012');
      const tested5 = $controller(ctrlTest, {$scope, io, $routeParams}, {data: {tid: 1}});
      tested5.parseProps();
      expect(tested5.paddedTid).to.equal('00001');
      const tested6 = $controller(ctrlTest, {$scope, io, $routeParams}, {data: {tid: 0}});
      tested6.parseProps();
      expect(tested6.paddedTid).to.equal('00000');
    });
  });
});
<commit_msg>Fix pokemon tests<commit_after>const ctrlTest = require('./pokemon.ctrl');

describe('PokemonCtrl', function() {

  let $controller, $scope, $routeParams, io, tested;

  beforeEach(inject(function(_$controller_){
    // The injector unwraps the underscores (_) from around the parameter names when matching
    $controller = _$controller_;
    $scope = {};
    $routeParams = {};
    io = {
      socket: {
        get: function () {}
      }
    };
  }));

  describe('controller variables', function() {
    it('are correctly taken from the box input', function() {
      tested = $controller(ctrlTest, {
        $scope: $scope,
        io: io, $routeParams:
        $routeParams
      }, {data: {
        speciesName: 'Pelipper',
        nickname: 'pokemondNickname',
        dexNo: 'pokemonDexNo',
        owner: 'boxUser',
        id: 'pokemonId',
        isShiny: false,
        tid: 1, sid: 1, esv: 1, tsv: 1
      }});
      tested.parseProps();
      expect(tested.data.nickname).to.equal('pokemondNickname');
      expect(tested.data.owner).to.equal('boxUser');
      expect(tested.data.dexNo).to.equal('pokemonDexNo');
      expect(tested.data.id).to.equal('pokemonId');
      expect(tested.iconUrl).to.equal('pokemon/regular/pelipper');
    });

    it('are correctly instantiated when not provided at construction', function() {
      $routeParams.pokemonid = 'routeParamId';
      tested = $controller(ctrlTest, {
        $scope: $scope,
        io: io, $routeParams:
        $routeParams
      }, {data: {tid: 1, sid: 1, esv: 1, tsv: 1}});
      tested.parseProps();
      expect(tested.id).to.equal('routeParamId');
      expect(Object.keys(tested.data).length).to.equal(4);
    });

    it("pads a Pokémon's TID correctly", function() {
      const tested1 = $controller(ctrlTest, {$scope, io, $routeParams},
        {data: {tid: 12345, sid: 1, esv: 1, tsv: 1}});
      tested1.parseProps();
      expect(tested1.paddedTid).to.equal('12345');
      const tested2 = $controller(ctrlTest, {$scope, io, $routeParams},
        {data: {tid: 1234, sid: 1, esv: 1, tsv: 1}});
      tested2.parseProps();
      expect(tested2.paddedTid).to.equal('01234');
      const tested3 = $controller(ctrlTest, {$scope, io, $routeParams},
        {data: {tid: 123, sid: 1, esv: 1, tsv: 1}});
      tested3.parseProps();
      expect(tested3.paddedTid).to.equal('00123');
      const tested4 = $controller(ctrlTest, {$scope, io, $routeParams},
        {data: {tid: 12, sid: 1, esv: 1, tsv: 1}});
      tested4.parseProps();
      expect(tested4.paddedTid).to.equal('00012');
      const tested5 = $controller(ctrlTest, {$scope, io, $routeParams},
        {data: {tid: 1, sid: 1, esv: 1, tsv: 1}});
      tested5.parseProps();
      expect(tested5.paddedTid).to.equal('00001');
      const tested6 = $controller(ctrlTest, {$scope, io, $routeParams},
        {data: {tid: 0, sid: 1, esv: 1, tsv: 1}});
      tested6.parseProps();
      expect(tested6.paddedTid).to.equal('00000');
    });
  });
});
<|endoftext|>