<commit_before>/*global XMLHttpRequest, FormData, location */

import { Class } from '../core/Core.js';
import '../foundation/RunLoop.js';  // For Function#invokeInRunLoop

const isLocal = location.protocol === 'file:';

const parseHeaders = function ( allHeaders ) {
    const headers = {};
    let start = 0;
    while ( true ) {
        // Ignore any leading white space
        while ( /\s/.test( allHeaders.charAt( start ) ) ) {
            start += 1;
        }
        // Look for ":"
        let end = allHeaders.indexOf( ':', start );
        if ( end < 0 ) {
            break;
        }
        // Slice out the header name.
        // Convert to lower-case: HTTP2 will always be lower case, but HTTP1
        // may be mixed case, which causes bugs!
        const name = allHeaders.slice( start, end ).toLowerCase();
        // Trim off any spaces after the colon.
        start = end + 1;
        while ( allHeaders.charAt( start ) === ' ' ) {
            start += 1;
        }
        // And find the end of the header
        end = allHeaders.indexOf( '\n', start );
        if ( end < 0 ) {
            end = allHeaders.length;
        }
        // Trim any trailing white space
        while ( end > start && /\s/.test( allHeaders.charAt( end - 1 ) ) ) {
            end -= 1;
        }
        // Add to the headers object
        headers[ name ] = allHeaders.slice( start, end );
        // And start looking for the next header
        start = end + 1;
    }
    return headers;
};

/**
    Class: O.XHR

    Wrapper class for the native XMLHTTPRequest object in the browser. Hooks
    into the more fully featured <O.HttpRequest> class; you should use that
    class for most things.
*/
const XHR = Class({
    /**
        Property: O.XHR#io
        Type: (O.Object|null)

        Reference to object on which properties are set and events fired.
    */

    /**
        Property (private): O.XHR#_isRunning
        Type: Boolean

        Is a request in progress?
    */

    /**
        Property: O.XHR#makeAsyncRequests
        Type: Boolean
        Default: true

        If changed to false, the connections will be synchronous rather than
        async. This should *only* ever be set during the onunload event,
        where you need to make a request synchronous to ensure it completes
        before the tab process is killed.
    */
    makeAsyncRequests: true,

    /**
        Constructor: O.XHR

        Parameters:
            io - {O.Object} (optional).
    */
    init ( io ) {
        this._isRunning = false;
        this._status = 0;
        this.io = io || null;
        this.xhr = null;
    },

    destroy () {
        this.abort();
    },

    /**
        Method: O.XHR#isRunning

        Determines whether a request is currently in progress.

        Returns:
            {Boolean} Is there a request still in progress?
    */
    isRunning () {
        return !!this._isRunning;
    },

    /**
        Method: O.XHR#getHeader

        Returns the contents of the response header corresponding to the name
        supplied as a parameter to the method.

        Parameters:
            name - {String} The name of the header to be fetched.

        Returns:
            {String} The text of the header or the empty string if not found.
    */
    getHeader ( name ) {
        try {
            return this.xhr.getResponseHeader( name ) || '';
        } catch ( error ) {
            return '';
        }
    },

    /**
        Method: O.XHR#getResponse

        Returns the response to the request.

        Returns:
            {String|ArrayBuffer|Blob|Document|Object} The response.
            (The type is determined by the responseType parameter to #send.)
    */
    getResponse () {
        return this.xhr.response;
    },

    /**
        Method: O.XHR#getStatus

        Returns the HTTP status code returned by the server in response to the
        request.

        Returns:
            {Number} The HTTP status code
    */
    getStatus () {
        return this._status;
    },

    /**
        Method: O.XHR#send

        If a request is currently active, it is first aborted. A new request is
        then made to the server, using the parameters supplied.

        Parameters:
            method  - {String} The HTTP method to use ('GET' or 'POST').
            url     - {String} The URL to which the request is to be made. This
                      must be at the same domain as the current page or a
                      security error will be thrown.
            data    - {String} The data to send in the body of the request; only
                      valid for POST requests; this will be ignored if the
                      method is GET.
            headers - {Object} (Optional) A set of key:value pairs corresponding
                      to header names and their values which will be sent with
                      the request.
            withCredentials - {Boolean} (Optional) (Default false) Whether or
                              not to include credentials in cross-site requests
            responseType - {String} See XMLHttpRequest.responseType for
                           permitted values. This controls the type of
                           {O.XHR#getResponse} and in consequence the {data}
                           field on an {io:success} or {io:failure} event.

        Returns:
            {O.XHR} Returns self.
    */
    send ( method, url, data, headers, withCredentials, responseType ) {
        if ( this._isRunning ) {
            this.abort();
        }
        this._isRunning = true;

        const xhr = this.xhr = new XMLHttpRequest();
        const io = this.io;
        const that = this;

        xhr.open( method, url, this.makeAsyncRequests );
        xhr.withCredentials = !!withCredentials;
        responseType = responseType || '';
        xhr.responseType = responseType;
        // If a browser doesn’t support a particular value (IE 11 with 'json'),
        // xhr.responseType becomes an empty string, and we will need to
        // simulate it ourselves later. (We don’t support IE≤9 which don’t do
        // responseType at all. We assume all the other values will work fine.)
        this._actualResponseType = xhr.responseType !== responseType ?
            responseType : '';
        for ( const name in headers || {} ) {
            // Let the browser set the Content-type automatically if submitting
            // FormData, otherwise it might be missing the boundary marker.
            if ( name !== 'Content-type' || !( data instanceof FormData ) ) {
                xhr.setRequestHeader( name, headers[ name ] );
            }
        }
        xhr.onreadystatechange = function () {
            that._xhrStateDidChange( this );
        };
        if ( xhr.upload ) {
            // FF will force a preflight on simple cross-origin requests if
            // there is an upload handler set. This follows the spec, but the
            // spec is clearly wrong here and Blink/Webkit do not follow it.
            // See https://bugzilla.mozilla.org/show_bug.cgi?id=727412
            // Workaround by not bothering registering an upload progress
            // handler for GET requests, as it's not needed in this case anyway.
            if ( method !== 'GET' ) {
                xhr.upload.addEventListener( 'progress', this, false );
            }
            xhr.addEventListener( 'progress', this, false );
        }
        xhr.send( data );

        if ( io ) {
            io.fire( 'io:begin' );
        }

        return this;
    },

    /**
        Method (private): O.XHR#_xhrStateDidChange

        Determines the state of the XMLHttpRequest object and fires the
        appropriate callbacks when it is loading/finished.

        Parameters:
            xhr - {XMLHttpRequest} The object whose state has changed.
    */
    _xhrStateDidChange: function ( xhr ) {
        const state = xhr.readyState;
        const io = this.io;

        if ( state < 3 || !this._isRunning ) {
            return;
        }

        if ( state === 3 ) {
            if ( io ) {
                io.set( 'uploadProgress', 100 )
                  .fire( 'io:loading' );
            }
            return;
        }

        this._isRunning = false;
        xhr.onreadystatechange = function () {};
        if ( xhr.upload ) {
            xhr.upload.removeEventListener( 'progress', this, false );
            xhr.removeEventListener( 'progress', this, false );
        }

        let status = xhr.status;
        this._status = status =
            // Local requests will have a 0 response
            ( !status && isLocal ) ? 200 :
            status;

        if ( io ) {
            const allHeaders = xhr.getAllResponseHeaders();
            const responseHeaders = parseHeaders( allHeaders );
            let response = this.getResponse();
            if ( this._actualResponseType === 'json' ) {
                try {
                    response = JSON.parse( response );
                } catch ( error ) {
                    response = null;
                }
            }
            // IE returns 200 status code when there's no network! But for a
            // real connection there must have been at least one header, so
            // check that's not empty. Except for cross-domain requests no
            // headers may be returned, so also check for a body
            const isSuccess = ( status >= 200 && status < 300 ) &&
                ( !!allHeaders || !!response );
            io.set( 'uploadProgress', 100 )
              .set( 'progress', 100 )
              .set( 'status', status )
              .set( 'responseHeaders', responseHeaders )
              .set( 'response', response )
              .fire( isSuccess ? 'io:success' : 'io:failure', {
                status,
                headers: responseHeaders,
                data: response,
              })
              .fire( 'io:end' );
        }
    }.invokeInRunLoop(),

    handleEvent: function ( event ) {
        const io = this.io;
        if ( io && event.type === 'progress' ) {
            const type = event.target === this.xhr ? 'progress' :
                                                     'uploadProgress';
            // CORE-47058. Limit to 99% on progress events, as Opera can report
            // event.loaded > event.total! Will be set to 100 in onSuccess
            // handler.
            io.set( type, Math.min( 99,
                    ~~( ( event.loaded / event.total ) * 100 ) ) )
              .fire( 'io:' + type, event );
        }
    }.invokeInRunLoop(),

    /**
        Method: O.XHR#abort

        Aborts the currently active request. No further callbacks will be made
        for that request. If there is no active request, calling this method has
        no effect.

        Returns:
            {O.XHR} Returns self.
    */
    abort () {
        if ( this._isRunning ) {
            this._isRunning = false;
            const xhr = this.xhr;
            const io = this.io;
            xhr.abort();
            xhr.onreadystatechange = function () {};
            if ( xhr.upload ) {
                xhr.upload.removeEventListener( 'progress', this, false );
                xhr.removeEventListener( 'progress', this, false );
            }
            if ( io ) {
                io.fire( 'io:abort' )
                  .fire( 'io:end' );
            }
        }
        return this;
    },
});

export default XHR;
<commit_msg>Handle error thrown by XmlHttpRequest#send<commit_after>/*global XMLHttpRequest, FormData, location */

import { Class } from '../core/Core.js';
import '../foundation/RunLoop.js';  // For Function#invokeInRunLoop

const isLocal = location.protocol === 'file:';

const parseHeaders = function ( allHeaders ) {
    const headers = {};
    let start = 0;
    while ( true ) {
        // Ignore any leading white space
        while ( /\s/.test( allHeaders.charAt( start ) ) ) {
            start += 1;
        }
        // Look for ":"
        let end = allHeaders.indexOf( ':', start );
        if ( end < 0 ) {
            break;
        }
        // Slice out the header name.
        // Convert to lower-case: HTTP2 will always be lower case, but HTTP1
        // may be mixed case, which causes bugs!
        const name = allHeaders.slice( start, end ).toLowerCase();
        // Trim off any spaces after the colon.
        start = end + 1;
        while ( allHeaders.charAt( start ) === ' ' ) {
            start += 1;
        }
        // And find the end of the header
        end = allHeaders.indexOf( '\n', start );
        if ( end < 0 ) {
            end = allHeaders.length;
        }
        // Trim any trailing white space
        while ( end > start && /\s/.test( allHeaders.charAt( end - 1 ) ) ) {
            end -= 1;
        }
        // Add to the headers object
        headers[ name ] = allHeaders.slice( start, end );
        // And start looking for the next header
        start = end + 1;
    }
    return headers;
};

/**
    Class: O.XHR

    Wrapper class for the native XMLHTTPRequest object in the browser. Hooks
    into the more fully featured <O.HttpRequest> class; you should use that
    class for most things.
*/
const XHR = Class({
    /**
        Property: O.XHR#io
        Type: (O.Object|null)

        Reference to object on which properties are set and events fired.
    */

    /**
        Property (private): O.XHR#_isRunning
        Type: Boolean

        Is a request in progress?
    */

    /**
        Property: O.XHR#makeAsyncRequests
        Type: Boolean
        Default: true

        If changed to false, the connections will be synchronous rather than
        async. This should *only* ever be set during the onunload event,
        where you need to make a request synchronous to ensure it completes
        before the tab process is killed.
    */
    makeAsyncRequests: true,

    /**
        Constructor: O.XHR

        Parameters:
            io - {O.Object} (optional).
    */
    init ( io ) {
        this._isRunning = false;
        this._status = 0;
        this.io = io || null;
        this.xhr = null;
    },

    destroy () {
        this.abort();
    },

    /**
        Method: O.XHR#isRunning

        Determines whether a request is currently in progress.

        Returns:
            {Boolean} Is there a request still in progress?
    */
    isRunning () {
        return !!this._isRunning;
    },

    /**
        Method: O.XHR#getHeader

        Returns the contents of the response header corresponding to the name
        supplied as a parameter to the method.

        Parameters:
            name - {String} The name of the header to be fetched.

        Returns:
            {String} The text of the header or the empty string if not found.
    */
    getHeader ( name ) {
        try {
            return this.xhr.getResponseHeader( name ) || '';
        } catch ( error ) {
            return '';
        }
    },

    /**
        Method: O.XHR#getResponse

        Returns the response to the request.

        Returns:
            {String|ArrayBuffer|Blob|Document|Object} The response.
            (The type is determined by the responseType parameter to #send.)
    */
    getResponse () {
        return this.xhr.response;
    },

    /**
        Method: O.XHR#getStatus

        Returns the HTTP status code returned by the server in response to the
        request.

        Returns:
            {Number} The HTTP status code
    */
    getStatus () {
        return this._status;
    },

    /**
        Method: O.XHR#send

        If a request is currently active, it is first aborted. A new request is
        then made to the server, using the parameters supplied.

        Parameters:
            method  - {String} The HTTP method to use ('GET' or 'POST').
            url     - {String} The URL to which the request is to be made. This
                      must be at the same domain as the current page or a
                      security error will be thrown.
            data    - {String} The data to send in the body of the request; only
                      valid for POST requests; this will be ignored if the
                      method is GET.
            headers - {Object} (Optional) A set of key:value pairs corresponding
                      to header names and their values which will be sent with
                      the request.
            withCredentials - {Boolean} (Optional) (Default false) Whether or
                              not to include credentials in cross-site requests
            responseType - {String} See XMLHttpRequest.responseType for
                           permitted values. This controls the type of
                           {O.XHR#getResponse} and in consequence the {data}
                           field on an {io:success} or {io:failure} event.

        Returns:
            {O.XHR} Returns self.
    */
    send ( method, url, data, headers, withCredentials, responseType ) {
        if ( this._isRunning ) {
            this.abort();
        }
        this._isRunning = true;

        const xhr = this.xhr = new XMLHttpRequest();
        const io = this.io;
        const that = this;

        if ( io ) {
            io.fire( 'io:begin' );
        }

        xhr.open( method, url, this.makeAsyncRequests );
        xhr.withCredentials = !!withCredentials;
        responseType = responseType || '';
        xhr.responseType = responseType;
        // If a browser doesn’t support a particular value (IE 11 with 'json'),
        // xhr.responseType becomes an empty string, and we will need to
        // simulate it ourselves later. (We don’t support IE≤9 which don’t do
        // responseType at all. We assume all the other values will work fine.)
        this._actualResponseType = xhr.responseType !== responseType ?
            responseType : '';
        for ( const name in headers || {} ) {
            // Let the browser set the Content-type automatically if submitting
            // FormData, otherwise it might be missing the boundary marker.
            if ( name !== 'Content-type' || !( data instanceof FormData ) ) {
                xhr.setRequestHeader( name, headers[ name ] );
            }
        }
        xhr.onreadystatechange = function () {
            that._xhrStateDidChange( this );
        };

        if ( xhr.upload ) {
            // FF will force a preflight on simple cross-origin requests if
            // there is an upload handler set. This follows the spec, but the
            // spec is clearly wrong here and Blink/Webkit do not follow it.
            // See https://bugzilla.mozilla.org/show_bug.cgi?id=727412
            // Workaround by not bothering registering an upload progress
            // handler for GET requests, as it's not needed in this case anyway.
            if ( method !== 'GET' ) {
                xhr.upload.addEventListener( 'progress', this, false );
            }
            xhr.addEventListener( 'progress', this, false );
        }

        try {
            xhr.send( data );
        } catch ( error ) {
            // Some browsers can throw a NetworkError under certain conditions
            // for example if this is a synchronous request and there's no
            // network. Treat as an abort.
            this.abort();
        }

        return this;
    },

    /**
        Method (private): O.XHR#_xhrStateDidChange

        Determines the state of the XMLHttpRequest object and fires the
        appropriate callbacks when it is loading/finished.

        Parameters:
            xhr - {XMLHttpRequest} The object whose state has changed.
    */
    _xhrStateDidChange: function ( xhr ) {
        const state = xhr.readyState;
        const io = this.io;

        if ( state < 3 || !this._isRunning ) {
            return;
        }

        if ( state === 3 ) {
            if ( io ) {
                io.set( 'uploadProgress', 100 )
                  .fire( 'io:loading' );
            }
            return;
        }

        this._isRunning = false;
        xhr.onreadystatechange = function () {};
        if ( xhr.upload ) {
            xhr.upload.removeEventListener( 'progress', this, false );
            xhr.removeEventListener( 'progress', this, false );
        }

        let status = xhr.status;
        this._status = status =
            // Local requests will have a 0 response
            ( !status && isLocal ) ? 200 :
            status;

        if ( io ) {
            const allHeaders = xhr.getAllResponseHeaders();
            const responseHeaders = parseHeaders( allHeaders );
            let response = this.getResponse();
            if ( this._actualResponseType === 'json' ) {
                try {
                    response = JSON.parse( response );
                } catch ( error ) {
                    response = null;
                }
            }
            // IE returns 200 status code when there's no network! But for a
            // real connection there must have been at least one header, so
            // check that's not empty. Except for cross-domain requests no
            // headers may be returned, so also check for a body
            const isSuccess = ( status >= 200 && status < 300 ) &&
                ( !!allHeaders || !!response );
            io.set( 'uploadProgress', 100 )
              .set( 'progress', 100 )
              .set( 'status', status )
              .set( 'responseHeaders', responseHeaders )
              .set( 'response', response )
              .fire( isSuccess ? 'io:success' : 'io:failure', {
                status,
                headers: responseHeaders,
                data: response,
              })
              .fire( 'io:end' );
        }
    }.invokeInRunLoop(),

    handleEvent: function ( event ) {
        const io = this.io;
        if ( io && event.type === 'progress' ) {
            const type = event.target === this.xhr ? 'progress' :
                                                     'uploadProgress';
            // CORE-47058. Limit to 99% on progress events, as Opera can report
            // event.loaded > event.total! Will be set to 100 in onSuccess
            // handler.
            io.set( type, Math.min( 99,
                    ~~( ( event.loaded / event.total ) * 100 ) ) )
              .fire( 'io:' + type, event );
        }
    }.invokeInRunLoop(),

    /**
        Method: O.XHR#abort

        Aborts the currently active request. No further callbacks will be made
        for that request. If there is no active request, calling this method has
        no effect.

        Returns:
            {O.XHR} Returns self.
    */
    abort () {
        if ( this._isRunning ) {
            this._isRunning = false;
            const xhr = this.xhr;
            const io = this.io;
            xhr.abort();
            xhr.onreadystatechange = function () {};
            if ( xhr.upload ) {
                xhr.upload.removeEventListener( 'progress', this, false );
                xhr.removeEventListener( 'progress', this, false );
            }
            if ( io ) {
                io.fire( 'io:abort' )
                  .fire( 'io:end' );
            }
        }
        return this;
    },
});

export default XHR;
<|endoftext|>


<commit_before>
// getting width and height of browser
var WIDTH = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
var HEIGHT = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

// creating instance of Phaser.Game
var game = new Phaser.Game(WIDTH, HEIGHT, Phaser.CANVAS, '', { preload: preload, create: create, update: update, render: render});

// phaser function for loading assets
function preload() {

  // loading assets
  game.load.image('background', 'assets/background.jpg');

  // loading target spritesheet
  // game.load.atlasJSONHash('target', 'assets/target1/target.png', 'assets/target1/target.json');
  game.load.atlasJSONArray('target', 'assets/target/target.png', 'assets/target/target.json');

  // shot sound
  game.load.audio('gunshot', ['assets/shot.mp3', 'assets/shot.ogg', 'assets/shot.wav']);

  // debugging for fps
  game.time.advancedTiming = true;

}

// variable declarations
var worldScale = 1;
var background;
var snipingCam;
var mask;
var target;
var gunshot;
var hole;
var cursors;
var crosshairX;
var crosshairY;

var indicator;

// group declarations
var backgroundGroup;
var crosshair;

// phaser function for setting up game.world
function create() {

  // setting game bounds
  game.world.setBounds(0, 0, 1495, 1000);

  // enabling phaser's physics engine
  game.physics.startSystem(Phaser.Physics.ARCADE);

  // adding background to game.world
  background = game.add.image(0, 0, 'background');

  // creating groups
  backgroundGroup = game.add.group();
  crosshair = game.add.group();

  // adding target to game.world
  target = game.add.sprite(0, 170, 'target', 6);
  target.animations.add('move', '', 5, true);
  target.animations.play('move');
  // enabling physics in target sprite
  game.physics.arcade.enable(target);
  // target will collide with world bounds so that it won't be out of game.world
  target.body.collideWorldBounds = true;
  // target.body.gravity.y = 100;

  indicator = game.add.graphics(150, 150);
  // drawing red border line
  indicator.lineStyle(3, 0xffffff);
  indicator.beginFill(0xff0000, 0.2);
  indicator.drawCircle(0, 0, 2);
  indicator.endFill();

  // add gunshot to the game so we can play it later
  gunshot = game.add.audio('gunshot');

  // adding hole that is rendered if the player misses the target after firing the bullet
  hole = game.add.graphics(0, 0);
  hole.beginFill(0x000, 1);
  hole.drawCircle(0, 0, 10);
  hole.endFill();
  hole.visible = false;

  // adding background to the backgroundGroup
  backgroundGroup.add(background);

  // circle that acts as a sniping camera
  snipingCam = game.add.graphics(90, 90);
  // drawing red border line
  snipingCam.lineStyle(3, 0xff0004);
  snipingCam.beginFill(0xff0000, 0.2);
  snipingCam.drawCircle(0, 0, 170);
  snipingCam.drawCircle(0, 0, 2);
  snipingCam.endFill();

  // creating mask
  mask = game.add.graphics(0, 0);

  // coloring
  mask.beginFill(0xffffff);

  // drawing circle
  mask.drawCircle(90, 90, 170);

  // applying the mask to the background group
  backgroundGroup.mask = mask;

  // adding snipingCam and mask to crosshair group
  crosshair.add(snipingCam);
  crosshair.add(mask);

  // following the crosshair
  game.camera.follow(crosshair);

  // tracking the mouse position and accelerate to it
  game.input.addMoveCallback(moveCrosshair, this);

  // adding shift key and keyboard cursors to game
  shiftKey = game.input.keyboard.addKey(Phaser.Keyboard.SHIFT);
  cursors = game.input.keyboard.createCursorKeys();

}

// phaser function that runs every frame and updates the UI
function update(pointer, x, y) {

  // crosshair movement
  if (cursors.left.isDown)
  {
    crosshair.x -= 5;
  }
  else if (cursors.right.isDown)
  {
    crosshair.x += 5;
  }
  else if (cursors.up.isDown) {
    crosshair.y -= 5;
  }
  else if (cursors.down.isDown) {
    crosshair.y += 5;
  }

  // firing bullet
  if (game.input.activePointer.leftButton.isDown || game.input.keyboard.isDown(Phaser.Keyboard.SPACEBAR)) {

    // play bullet sound
    gunshot.play();

    // getting actual crosshair coordinates respective to the game.world.scale
    if (worldScale == 1) {

      crosshairX = getActualCrosshairX(0);
      crosshairY = getActualCrosshairY(0);

    }
    else if (worldScale > 1 && worldScale <= 1.1) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(10);
      console.log(crosshairX,crosshairY);

    }
    else if (worldScale > 1.1 && worldScale <= 1.2) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(22);
      console.log(crosshairX,crosshairY);

    }
    else if (worldScale > 1.2 && worldScale <= 1.3) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(52);
      console.log(crosshairX,crosshairY);

    }
    else if (worldScale > 1.3 && worldScale <= 1.4) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(52);
      console.log(crosshairX,crosshairY);

    }
    else if (worldScale > 1.4 && worldScale <= 1.5) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(79);
      console.log(crosshairX,crosshairY);

    }
    else if (worldScale > 1.5 && worldScale <= 1.6) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(99);
      console.log(crosshairX,crosshairY);

    }
    else if (worldScale > 1.6 && worldScale <= 1.7) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(119);
      console.log(crosshairX,crosshairY);

    }
    else if (worldScale > 1.7 && worldScale >= 1.75) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(132);
      console.log(crosshairX,crosshairY);

    }

    // debugging
    var result = checkTargetHit(crosshairX, crosshairY, target);
    console.log(result);
    console.log(crosshairX, crosshairY);

    //checking if the bullet hit the target or not
    if (checkTargetHit(crosshairX, crosshairY, target)) {

      // disposing the target sprite
      target.kill();

    }
    else {

      // repositioning the hole
      hole.x = crosshairX;
      hole.y = crosshairY;
      hole.visible = true;

    }

  }

  // zooming in and out
  if (game.input.keyboard.isDown(Phaser.Keyboard.W)) {
      worldScale += 0.05;
  }
  else if (game.input.keyboard.isDown(Phaser.Keyboard.E)) {
      worldScale -= 0.05;
  }

  // set a minimum and maximum scale value
  worldScale = Phaser.Math.clamp(worldScale, 1, 1.75);

  // set our world scale as needed
  game.world.scale.set(worldScale);

  if (game.input.keyboard.isDown(Phaser.Keyboard.T)) {
      console.log(worldScale);
  }

  // debugging
  if (game.input.keyboard.isDown(Phaser.Keyboard.P)) {
    target.revive();
    updateIndicator(crosshair.x,crosshair.y);
  }

  if (game.input.keyboard.isDown(Phaser.Keyboard.L)) {
    target.x += 2;
  }

}

function render(game) {
  game.debug.text(game.time.fps || '--', 2, 14, "#ff0004");
  game.debug.spriteInfo(target, 32, 32);
  game.debug.spriteBounds(target);
}

function moveCrosshair(pointer, x, y) {
  crosshair.x = x - 90;
  crosshair.y = y - 90;
}

function getActualCrosshairX(factor) {
  return (crosshair.x + (90 + factor));
}

function getActualCrosshairY(factor) {
  return (crosshair.y + (90 + factor));
}

function checkTargetHit(x1, y1, target) {
  var crosshairCenter = {x: x1, y: y1};
  var targetBounds = target.getBounds();

  return Phaser.Rectangle.containsPoint(targetBounds, crosshairCenter);
}

function updateIndicator(x, y) {
  indicator.x = x + 90;
  indicator.y = y + 90;
  console.log(indicator.x, indicator.y);
}
<commit_msg>little tweaks<commit_after>
// getting width and height of browser
var WIDTH = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
var HEIGHT = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

// creating instance of Phaser.Game
var game = new Phaser.Game(WIDTH, HEIGHT, Phaser.CANVAS, '', { preload: preload, create: create, update: update, render: render});

// phaser function for loading assets
function preload() {

  // loading assets
  game.load.image('background', 'assets/background.jpg');

  // loading target spritesheet
  // game.load.atlasJSONHash('target', 'assets/target1/target.png', 'assets/target1/target.json');
  game.load.atlasJSONArray('target', 'assets/target/target.png', 'assets/target/target.json');

  // shot sound
  game.load.audio('gunshot', ['assets/shot.mp3', 'assets/shot.ogg', 'assets/shot.wav']);

  // debugging for fps
  game.time.advancedTiming = true;

}

// variable declarations
var worldScale = 1;
var background;
var snipingCam;
var mask;
var target;
var gunshot;
var hole;
var cursors;
var crosshairX;
var crosshairY;

var indicator;

// group declarations
var backgroundGroup;
var crosshair;

// phaser function for setting up game.world
function create() {

  // setting game bounds
  game.world.setBounds(0, 0, 1495, 1000);

  // enabling phaser's physics engine
  game.physics.startSystem(Phaser.Physics.ARCADE);

  // adding background to game.world
  background = game.add.image(0, 0, 'background');

  // creating groups
  backgroundGroup = game.add.group();
  crosshair = game.add.group();

  // adding target to game.world
  target = game.add.sprite(0, 170, 'target', 6);
  target.animations.add('move', '', 5, true);
  target.animations.play('move');
  // enabling physics in target sprite
  game.physics.arcade.enable(target);
  // target will collide with world bounds so that it won't be out of game.world
  target.body.collideWorldBounds = true;
  // target.body.gravity.y = 100;

  indicator = game.add.graphics(150, 150);
  // drawing red border line
  indicator.lineStyle(3, 0xffffff);
  indicator.beginFill(0xff0000, 0.2);
  indicator.drawCircle(0, 0, 2);
  indicator.endFill();

  // add gunshot to the game so we can play it later
  gunshot = game.add.audio('gunshot');

  // adding hole that is rendered if the player misses the target after firing the bullet
  hole = game.add.graphics(0, 0);
  hole.beginFill(0x000, 1);
  hole.drawCircle(0, 0, 10);
  hole.endFill();
  hole.visible = false;

  // adding background to the backgroundGroup
  backgroundGroup.add(background);
  backgroundGroup.add(target);

  // circle that acts as a sniping camera
  snipingCam = game.add.graphics(90, 90);
  // drawing red border line
  snipingCam.lineStyle(3, 0xff0004);
  snipingCam.beginFill(0xff0000, 0.2);
  snipingCam.drawCircle(0, 0, 170);
  snipingCam.drawCircle(0, 0, 2);
  snipingCam.endFill();

  // creating mask
  mask = game.add.graphics(0, 0);

  // coloring
  mask.beginFill(0xffffff);

  // drawing circle
  mask.drawCircle(90, 90, 170);

  // applying the mask to the background group
  backgroundGroup.mask = mask;

  // adding snipingCam and mask to crosshair group
  crosshair.add(snipingCam);
  crosshair.add(mask);

  // following the crosshair
  game.camera.follow(crosshair);

  // tracking the mouse position and accelerate to it
  game.input.addMoveCallback(moveCrosshair, this);

  // adding shift key and keyboard cursors to game
  shiftKey = game.input.keyboard.addKey(Phaser.Keyboard.SHIFT);
  cursors = game.input.keyboard.createCursorKeys();

}

// phaser function that runs every frame and updates the UI
function update(pointer, x, y) {

  // crosshair movement
  if (cursors.left.isDown)
  {
    crosshair.x -= 5;
  }
  else if (cursors.right.isDown)
  {
    crosshair.x += 5;
  }
  else if (cursors.up.isDown) {
    crosshair.y -= 5;
  }
  else if (cursors.down.isDown) {
    crosshair.y += 5;
  }

  // firing bullet
  if (game.input.activePointer.leftButton.isDown || game.input.keyboard.isDown(Phaser.Keyboard.SPACEBAR)) {

    // play bullet sound
    gunshot.play();

    // getting actual crosshair coordinates respective to the game.world.scale
    if (worldScale == 1) {

      crosshairX = getActualCrosshairX(0);
      crosshairY = getActualCrosshairY(0);

    }
    else if (worldScale > 1 && worldScale <= 1.1) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(10);
      console.log(crosshairX,crosshairY);

    }
    else if (worldScale > 1.1 && worldScale <= 1.2) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(22);
      console.log(crosshairX,crosshairY);

    }
    else if (worldScale > 1.2 && worldScale <= 1.3) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(52);
      console.log(crosshairX,crosshairY);

    }
    else if (worldScale > 1.3 && worldScale <= 1.4) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(52);
      console.log(crosshairX,crosshairY);

    }
    else if (worldScale > 1.4 && worldScale <= 1.5) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(79);
      console.log(crosshairX,crosshairY);

    }
    else if (worldScale > 1.5 && worldScale <= 1.6) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(99);
      console.log(crosshairX,crosshairY);

    }
    else if (worldScale > 1.6 && worldScale <= 1.7) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(119);
      console.log(crosshairX,crosshairY);

    }
    else if (worldScale > 1.7 && worldScale >= 1.75) {

      crosshairX = getActualCrosshairX(10);
      crosshairY = getActualCrosshairY(132);
      console.log(crosshairX,crosshairY);

    }

    // debugging
    var result = checkTargetHit(crosshairX, crosshairY, target);
    console.log(result);
    console.log(crosshairX, crosshairY);

    //checking if the bullet hit the target or not
    if (checkTargetHit(crosshairX, crosshairY, target)) {

      // disposing the target sprite
      target.kill();

    }
    else {

      // repositioning the hole
      hole.x = crosshairX;
      hole.y = crosshairY;
      hole.visible = true;

    }

  }

  // zooming in and out
  if (game.input.keyboard.isDown(Phaser.Keyboard.W)) {
      worldScale += 0.05;
  }
  else if (game.input.keyboard.isDown(Phaser.Keyboard.E)) {
      worldScale -= 0.05;
  }

  // set a minimum and maximum scale value
  worldScale = Phaser.Math.clamp(worldScale, 1, 1.75);

  // set our world scale as needed
  game.world.scale.set(worldScale);

  if (game.input.keyboard.isDown(Phaser.Keyboard.T)) {
      console.log(worldScale);
  }

  // debugging
  if (game.input.keyboard.isDown(Phaser.Keyboard.P)) {
    target.revive();
    updateIndicator(crosshair.x,crosshair.y);
  }

  if (game.input.keyboard.isDown(Phaser.Keyboard.L)) {
    target.x += 2;
  }

}

function render(game) {
  game.debug.text(game.time.fps || '--', 2, 14, "#ff0004");
  game.debug.spriteInfo(target, 32, 32);
  game.debug.spriteBounds(target);
}

function moveCrosshair(pointer, x, y) {
  crosshair.x = x - 90;
  crosshair.y = y - 90;
}

function getActualCrosshairX(factor) {
  return (crosshair.x + (90 + factor));
}

function getActualCrosshairY(factor) {
  return (crosshair.y + (90 + factor));
}

function checkTargetHit(x1, y1, target) {
  var targetBounds = target.getBounds();

  return targetBounds.contains(x1, y1);
}

function updateIndicator(x, y) {
  indicator.x = x + 90;
  indicator.y = y + 90;
  console.log(indicator.x, indicator.y);
}
<|endoftext|>


<commit_before>const getLanguage = require('./language').getLanguage;

function url_for(path, params) {
    if (!path) {
        path = '';
    } else if (path.length > 0 && path[0] === '/') {
        path = path.substr(1);
    }
    const lang = getLanguage().toLowerCase();
    let url = '';
    if (typeof window !== 'undefined') {
        url  = window.location.href;
    }
    return `${url.substring(0, url.indexOf(`/${lang}/`) + lang.length + 2)}${path || 'home'}.html${params ? `?${params}` : ''}`;
}

function url_for_static(path) {
    if (!path) {
        path = '';
    } else if (path.length > 0 && path[0] === '/') {
        path = path.substr(1);
    }

    let staticHost;
    if (typeof window !== 'undefined') {
        staticHost = window.staticHost;
    }
    if (!staticHost || staticHost.length === 0) {
        staticHost = $('script[src*="bundle.min.js"],script[src*="bundle.js"]').attr('src');

        if (staticHost && staticHost.length > 0) {
            staticHost = staticHost.substr(0, staticHost.indexOf('/js/') + 1);
        } else {
            staticHost = 'https://www.champion-fx.com/';
        }

        if (typeof window !== 'undefined') {
            window.staticHost = staticHost;
        }
    }

    return staticHost + path;
}

function default_redirect_url() {
    return url_for('home');
}

module.exports = {
    url_for             : url_for,
    url_for_static      : url_for_static,
    default_redirect_url: default_redirect_url,
};
<commit_msg>Update default redirect url<commit_after>const getLanguage = require('./language').getLanguage;

function url_for(path, params) {
    if (!path) {
        path = '';
    } else if (path.length > 0 && path[0] === '/') {
        path = path.substr(1);
    }
    const lang = getLanguage().toLowerCase();
    let url = '';
    if (typeof window !== 'undefined') {
        url  = window.location.href;
    }
    return `${url.substring(0, url.indexOf(`/${lang}/`) + lang.length + 2)}${path || 'home'}.html${params ? `?${params}` : ''}`;
}

function url_for_static(path) {
    if (!path) {
        path = '';
    } else if (path.length > 0 && path[0] === '/') {
        path = path.substr(1);
    }

    let staticHost;
    if (typeof window !== 'undefined') {
        staticHost = window.staticHost;
    }
    if (!staticHost || staticHost.length === 0) {
        staticHost = $('script[src*="bundle.min.js"],script[src*="bundle.js"]').attr('src');

        if (staticHost && staticHost.length > 0) {
            staticHost = staticHost.substr(0, staticHost.indexOf('/js/') + 1);
        } else {
            staticHost = 'https://www.champion-fx.com/';
        }

        if (typeof window !== 'undefined') {
            window.staticHost = staticHost;
        }
    }

    return staticHost + path;
}

function default_redirect_url() {
    return url_for('user/settings');
}

module.exports = {
    url_for             : url_for,
    url_for_static      : url_for_static,
    default_redirect_url: default_redirect_url,
};
<|endoftext|>


<commit_before>/**
 * node-compress-commons
 *
 * Copyright (c) 2014 Chris Talkington, contributors.
 * Licensed under the MIT license.
 * https://github.com/ctalkington/node-compress-commons/blob/master/LICENSE-MIT
 */
var inherits = require('util').inherits;
var crc32 = require('buffer-crc32');
var CRC32Stream = require('crc32-stream');
var DeflateCRC32Stream = CRC32Stream.DeflateCRC32Stream;

var ArchiveOutputStream = require('../archive-output-stream');
var ZipArchiveEntry = require('./zip-archive-entry');
var GeneralPurposeBit = require('./general-purpose-bit');

var constants = require('./constants');
var util = require('../../util');
var zipUtil = require('./util');

var ZipArchiveOutputStream = module.exports = function(options) {
  if (!(this instanceof ZipArchiveOutputStream)) {
    return new ZipArchiveOutputStream(options);
  }

  options = this.options = this._defaults(options);

  ArchiveOutputStream.call(this, options);

  this._entry = null;
  this._entries = [];
  this._archive = {
    centralLength: 0,
    centralOffset: 0,
    comment: '',
    finish: false,
    finished: false,
    processing: false
  };
};

inherits(ZipArchiveOutputStream, ArchiveOutputStream);

ZipArchiveOutputStream.prototype._afterAppend = function(zae) {
  this._entries.push(zae);
  this._writeDataDescriptor(zae);

  this._archive.processing = false;
  this._entry = null;

  if (this._archive.finish && !this._archive.finished) {
    this._finish();
  }
};

ZipArchiveOutputStream.prototype._appendBuffer = function(ae, source, callback) {
  if (source.length === 0) {
    ae.setMethod(constants.METHOD_STORED);
  }

  var method = ae.getMethod();

  if (method === constants.METHOD_STORED) {
    ae.setSize(source.length);
    ae.setCompressedSize(source.length);
    ae.setCrc(crc32.unsigned(source));
  }

  this._writeLocalFileHeader(ae);

  if (method === constants.METHOD_STORED) {
    this.write(source);
    this._afterAppend(ae);
    callback(null, ae);
    return;
  } else if (method === constants.METHOD_DEFLATED) {
    this._smartStream(ae, callback).end(source);
    return;
  } else {
    callback(new Error('compression method ' + method + ' not implemented'));
    return;
  }
};

ZipArchiveOutputStream.prototype._appendStream = function(ae, source, callback) {
  ae.getGeneralPurposeBit().useDataDescriptor(true);

  this._writeLocalFileHeader(ae);

  var smart = this._smartStream(ae, callback);
  source.pipe(smart);
};

ZipArchiveOutputStream.prototype._defaults = function(o) {
  if (typeof o !== 'object') {
    o = {};
  }

  if (typeof o.zlib !== 'object') {
    o.zlib = {};
  }

  if (typeof o.zlib.level !== 'number') {
    o.zlib.level = constants.ZLIB_BEST_SPEED;
  }

  return o;
};

ZipArchiveOutputStream.prototype._finish = function() {
  this._archive.centralOffset = this.offset;

  this._entries.forEach(function(ae) {
    this._writeCentralFileHeader(ae);
  }.bind(this));

  this._archive.centralLength = this.offset - this._archive.centralOffset;

  this._writeCentralDirectoryZip64();
  this._writeCentralDirectoryEnd();

  this._archive.processing = false;
  this._archive.finish = true;
  this._archive.finished = true;
  this.end();
};

ZipArchiveOutputStream.prototype._normalizeEntry = function(ae) {
  if (ae.getMethod() === -1) {
    ae.setMethod(constants.METHOD_DEFLATED);
  }

  if (ae.getMethod() === constants.METHOD_DEFLATED) {
    ae.getGeneralPurposeBit().useDataDescriptor(true);
    ae.setVersionNeededToExtract(constants.MIN_VERSION_DATA_DESCRIPTOR);
  }

  if (ae.getTime() === -1) {
    ae.setTime(new Date());
  }

  ae._offsets = {
    file: 0,
    data: 0,
    contents: 0,
  };
};

ZipArchiveOutputStream.prototype._smartStream = function(ae, callback) {
  var deflate = ae.getMethod() === constants.METHOD_DEFLATED;
  var process = deflate ? new DeflateCRC32Stream(this.options.zlib) : new CRC32Stream();

  function handleStuff(err) {
    ae.setCrc(process.digest());
    ae.setSize(process.size());
    ae.setCompressedSize(process.size(true));
    this._afterAppend(ae);
    callback(null, ae);
  }

  process.once('error', callback);
  process.once('end', handleStuff.bind(this));

  process.pipe(this, { end: false });

  return process;
};

ZipArchiveOutputStream.prototype._writeCentralDirectoryEnd = function() {
  var records = this._entries.length;
  var size = this._archive.centralLength;
  var offset = this._archive.centralOffset;

  if (this.isZip64()) {
    records = constants.ZIP64_MAGIC_SHORT;
    size = constants.ZIP64_MAGIC;
    offset = constants.ZIP64_MAGIC;
  }

  // signature
  this.write(zipUtil.getLongBytes(constants.SIG_EOCD));

  // disk numbers
  this.write(constants.SHORT_ZERO);
  this.write(constants.SHORT_ZERO);

  // number of entries
  this.write(zipUtil.getShortBytes(records));
  this.write(zipUtil.getShortBytes(records));

  // length and location of CD
  this.write(zipUtil.getLongBytes(size));
  this.write(zipUtil.getLongBytes(offset));

  // archive comment
  var comment = this.getComment();
  var commentLength = Buffer.byteLength(comment);
  this.write(zipUtil.getShortBytes(commentLength));
  this.write(comment);
};

ZipArchiveOutputStream.prototype._writeCentralDirectoryZip64 = function() {
  if (!this.isZip64()) {
    return;
  }

  // signature
  this.write(constants.SIG_ZIP64_EOCD);

  // size of the ZIP64 EOCD record
  this.write(zipUtil.getEightBytes((constants.SHORT * 2) + (constants.LONG * 2) + (8 * 4)));

  // version made by
  this.write(zipUtil.getShortBytes((ae.getPlatform() << 8) | constants.VERSION_MADEBY));

  // version needed to extract
  this.write(zipUtil.getShortBytes(ae.getVersionNeededToExtract()));

  // disk numbers
  this.write(constants.LONG_ZERO);
  this.write(constants.LONG_ZERO);

  // number of entries
  this.write(zipUtil.getEightBytes(this._entries.length));
  this.write(zipUtil.getEightBytes(this._entries.length));

  // length and location of CD
  this.write(zipUtil.getEightBytes(this._archive.centralLength));
  this.write(zipUtil.getEightBytes(this._archive.centralOffset));

  // extensible data sector
  // not implemented at this time

  // end of central directory locator
  this.write(costants.SIG_ZIP64_EOCD_LOC);

  // disk number holding the ZIP64 EOCD record
  this.write(constants.LONG_ZERO);

  // relative offset of the ZIP64 EOCD record
  this.write(zipUtil.getEightBytes(this._archive.centralOffset + this._archive.centralLength));

  // total number of disks
  this.write(this.getLongBytes(1));
};

ZipArchiveOutputStream.prototype._writeCentralFileHeader = function(ae) {
  var gpb = ae.getGeneralPurposeBit();
  var method = ae.getMethod();
  var offsets = ae._offsets;

  var extraBuf;
  var size = ae.getSize();
  var compressedSize = ae.getCompressedSize();

  if (ae.isZip64() || offsets.file > constants.ZIP64_MAGIC) {
    size = constants.ZIP64_MAGIC;
    compressedSize = constants.ZIP64_MAGIC;

    ae.setVersionNeededToExtract(constants.MIN_VERSION_ZIP64);

    extraBuf = new Buffer(28);
    extraBuf.write(zipUtil.getShortBytes(constants.ZIP64_EXTRA_ID));
    extraBuf.write(zipUtil.getShortBytes(24));
    extraBuf.write(zipUtil.getEightBytes(ae.getSize()));
    extraBuf.write(zipUtil.getEightBytes(ae.getCompressedSize()));
    extraBuf.write(zipUtil.getEightBytes(offsets.file));
    ae.setExtra(extraBuf);
  }

  // signature
  this.write(zipUtil.getLongBytes(constants.SIG_CFH));

  // version made by
  this.write(zipUtil.getShortBytes((ae.getPlatform() << 8) | constants.VERSION_MADEBY));

  // version to extract and general bit flag
  this.write(zipUtil.getShortBytes(ae.getVersionNeededToExtract()));
  this.write(gpb.encode());

  // compression method
  this.write(zipUtil.getShortBytes(method));

  // datetime
  this.write(zipUtil.getLongBytes(ae.getTimeDos()));

  // crc32 checksum
  this.write(zipUtil.getLongBytes(ae.getCrc()));

  // sizes
  this.write(zipUtil.getLongBytes(compressedSize));
  this.write(zipUtil.getLongBytes(size));

  var name = ae.getName();
  var comment = ae.getComment();
  var extra = ae.getCentralDirectoryExtra();

  if (gpb.usesUTF8ForNames()) {
    name = new Buffer(name);
    comment = new Buffer(comment);
  }

  // name length
  this.write(zipUtil.getShortBytes(name.length));

  // extra length
  this.write(zipUtil.getShortBytes(extra.length));

  // comments length
  this.write(zipUtil.getShortBytes(comment.length));

  // disk number start
  this.write(constants.SHORT_ZERO);

  // internal attributes
  this.write(zipUtil.getShortBytes(ae.getInternalAttributes()));

  // external attributes
  this.write(zipUtil.getLongBytes(ae.getExternalAttributes()));

  // relative offset of LFH
  if (offsets.file > constants.ZIP64_MAGIC) {
    this.write(zipUtil.getLongBytes(constants.ZIP64_MAGIC));
  } else {
    this.write(zipUtil.getLongBytes(offsets.file));
  }

  // name
  this.write(name);

  // extra
  this.write(extra);

  // comment
  this.write(comment);
};

ZipArchiveOutputStream.prototype._writeDataDescriptor = function(ae) {
  if (!ae.getGeneralPurposeBit().usesDataDescriptor()) {
    return;
  }

  // signature
  this.write(zipUtil.getLongBytes(constants.SIG_DD));

  // crc32 checksum
  this.write(zipUtil.getLongBytes(ae.getCrc()));

  // sizes
  if (ae.isZip64()) {
    this.write(zipUtil.getEightBytes(ae.getCompressedSize()));
    this.write(zipUtil.getEightBytes(ae.getSize()));
  } else {
    this.write(zipUtil.getLongBytes(ae.getCompressedSize()));
    this.write(zipUtil.getLongBytes(ae.getSize()));
  }
};

ZipArchiveOutputStream.prototype._writeLocalFileHeader = function(ae) {
  var gpb = ae.getGeneralPurposeBit();
  var method = ae.getMethod();
  var name = ae.getName();
  var extra = ae.getLocalFileDataExtra();

  if (gpb.usesUTF8ForNames()) {
    name = new Buffer(name);
  }

  ae._offsets.file = this.offset;

  // signature
  this.write(zipUtil.getLongBytes(constants.SIG_LFH));

  // version to extract and general bit flag
  this.write(zipUtil.getShortBytes(ae.getVersionNeededToExtract()));
  this.write(gpb.encode());

  // compression method
  this.write(zipUtil.getShortBytes(method));

  // datetime
  this.write(zipUtil.getLongBytes(ae.getTimeDos()));

  ae._offsets.data = this.offset;

  // crc32 checksum and sizes
  if (gpb.usesDataDescriptor()) {
    this.write(constants.LONG_ZERO);
    this.write(constants.LONG_ZERO);
    this.write(constants.LONG_ZERO);
  } else {
    this.write(zipUtil.getLongBytes(ae.getCrc()));
    this.write(zipUtil.getLongBytes(ae.getCompressedSize()));
    this.write(zipUtil.getLongBytes(ae.getSize()));
  }

  // name length
  this.write(zipUtil.getShortBytes(name.length));

  // extra length
  this.write(zipUtil.getShortBytes(extra.length));

  // name
  this.write(name);

  // extra
  this.write(extra);

  ae._offsets.contents = this.offset;
};

ZipArchiveOutputStream.prototype.getComment = function(comment) {
  return this._archive.comment !== null ? this._archive.comment : '';
};

ZipArchiveOutputStream.prototype.isZip64 = function() {
  return this._entries.length > constants.ZIP64_MAGIC_SHORT || this._archive.centralLength > constants.ZIP64_MAGIC || this._archive.centralOffset > constants.ZIP64_MAGIC;
};

ZipArchiveOutputStream.prototype.setComment = function(comment) {
  this._archive.comment = comment;
};<commit_msg>zip: always use data descriptor when dealing with ZIP64.<commit_after>/**
 * node-compress-commons
 *
 * Copyright (c) 2014 Chris Talkington, contributors.
 * Licensed under the MIT license.
 * https://github.com/ctalkington/node-compress-commons/blob/master/LICENSE-MIT
 */
var inherits = require('util').inherits;
var crc32 = require('buffer-crc32');
var CRC32Stream = require('crc32-stream');
var DeflateCRC32Stream = CRC32Stream.DeflateCRC32Stream;

var ArchiveOutputStream = require('../archive-output-stream');
var ZipArchiveEntry = require('./zip-archive-entry');
var GeneralPurposeBit = require('./general-purpose-bit');

var constants = require('./constants');
var util = require('../../util');
var zipUtil = require('./util');

var ZipArchiveOutputStream = module.exports = function(options) {
  if (!(this instanceof ZipArchiveOutputStream)) {
    return new ZipArchiveOutputStream(options);
  }

  options = this.options = this._defaults(options);

  ArchiveOutputStream.call(this, options);

  this._entry = null;
  this._entries = [];
  this._archive = {
    centralLength: 0,
    centralOffset: 0,
    comment: '',
    finish: false,
    finished: false,
    processing: false
  };
};

inherits(ZipArchiveOutputStream, ArchiveOutputStream);

ZipArchiveOutputStream.prototype._afterAppend = function(zae) {
  this._entries.push(zae);
  this._writeDataDescriptor(zae);

  this._archive.processing = false;
  this._entry = null;

  if (this._archive.finish && !this._archive.finished) {
    this._finish();
  }
};

ZipArchiveOutputStream.prototype._appendBuffer = function(ae, source, callback) {
  if (source.length === 0) {
    ae.setMethod(constants.METHOD_STORED);
  }

  var method = ae.getMethod();

  if (method === constants.METHOD_STORED) {
    ae.setSize(source.length);
    ae.setCompressedSize(source.length);
    ae.setCrc(crc32.unsigned(source));
  }

  this._writeLocalFileHeader(ae);

  if (method === constants.METHOD_STORED) {
    this.write(source);
    this._afterAppend(ae);
    callback(null, ae);
    return;
  } else if (method === constants.METHOD_DEFLATED) {
    this._smartStream(ae, callback).end(source);
    return;
  } else {
    callback(new Error('compression method ' + method + ' not implemented'));
    return;
  }
};

ZipArchiveOutputStream.prototype._appendStream = function(ae, source, callback) {
  ae.getGeneralPurposeBit().useDataDescriptor(true);

  this._writeLocalFileHeader(ae);

  var smart = this._smartStream(ae, callback);
  source.pipe(smart);
};

ZipArchiveOutputStream.prototype._defaults = function(o) {
  if (typeof o !== 'object') {
    o = {};
  }

  if (typeof o.zlib !== 'object') {
    o.zlib = {};
  }

  if (typeof o.zlib.level !== 'number') {
    o.zlib.level = constants.ZLIB_BEST_SPEED;
  }

  return o;
};

ZipArchiveOutputStream.prototype._finish = function() {
  this._archive.centralOffset = this.offset;

  this._entries.forEach(function(ae) {
    this._writeCentralFileHeader(ae);
  }.bind(this));

  this._archive.centralLength = this.offset - this._archive.centralOffset;

  this._writeCentralDirectoryZip64();
  this._writeCentralDirectoryEnd();

  this._archive.processing = false;
  this._archive.finish = true;
  this._archive.finished = true;
  this.end();
};

ZipArchiveOutputStream.prototype._normalizeEntry = function(ae) {
  if (ae.getMethod() === -1) {
    ae.setMethod(constants.METHOD_DEFLATED);
  }

  if (ae.getMethod() === constants.METHOD_DEFLATED) {
    ae.getGeneralPurposeBit().useDataDescriptor(true);
    ae.setVersionNeededToExtract(constants.MIN_VERSION_DATA_DESCRIPTOR);
  }

  if (ae.getTime() === -1) {
    ae.setTime(new Date());
  }

  ae._offsets = {
    file: 0,
    data: 0,
    contents: 0,
  };
};

ZipArchiveOutputStream.prototype._smartStream = function(ae, callback) {
  var deflate = ae.getMethod() === constants.METHOD_DEFLATED;
  var process = deflate ? new DeflateCRC32Stream(this.options.zlib) : new CRC32Stream();

  function handleStuff(err) {
    ae.setCrc(process.digest());
    ae.setSize(process.size());
    ae.setCompressedSize(process.size(true));
    this._afterAppend(ae);
    callback(null, ae);
  }

  process.once('error', callback);
  process.once('end', handleStuff.bind(this));

  process.pipe(this, { end: false });

  return process;
};

ZipArchiveOutputStream.prototype._writeCentralDirectoryEnd = function() {
  var records = this._entries.length;
  var size = this._archive.centralLength;
  var offset = this._archive.centralOffset;

  if (this.isZip64()) {
    records = constants.ZIP64_MAGIC_SHORT;
    size = constants.ZIP64_MAGIC;
    offset = constants.ZIP64_MAGIC;
  }

  // signature
  this.write(zipUtil.getLongBytes(constants.SIG_EOCD));

  // disk numbers
  this.write(constants.SHORT_ZERO);
  this.write(constants.SHORT_ZERO);

  // number of entries
  this.write(zipUtil.getShortBytes(records));
  this.write(zipUtil.getShortBytes(records));

  // length and location of CD
  this.write(zipUtil.getLongBytes(size));
  this.write(zipUtil.getLongBytes(offset));

  // archive comment
  var comment = this.getComment();
  var commentLength = Buffer.byteLength(comment);
  this.write(zipUtil.getShortBytes(commentLength));
  this.write(comment);
};

ZipArchiveOutputStream.prototype._writeCentralDirectoryZip64 = function() {
  if (!this.isZip64()) {
    return;
  }

  // signature
  this.write(constants.SIG_ZIP64_EOCD);

  // size of the ZIP64 EOCD record
  this.write(zipUtil.getEightBytes((constants.SHORT * 2) + (constants.LONG * 2) + (8 * 4)));

  // version made by
  this.write(zipUtil.getShortBytes((ae.getPlatform() << 8) | constants.VERSION_MADEBY));

  // version needed to extract
  this.write(zipUtil.getShortBytes(ae.getVersionNeededToExtract()));

  // disk numbers
  this.write(constants.LONG_ZERO);
  this.write(constants.LONG_ZERO);

  // number of entries
  this.write(zipUtil.getEightBytes(this._entries.length));
  this.write(zipUtil.getEightBytes(this._entries.length));

  // length and location of CD
  this.write(zipUtil.getEightBytes(this._archive.centralLength));
  this.write(zipUtil.getEightBytes(this._archive.centralOffset));

  // extensible data sector
  // not implemented at this time

  // end of central directory locator
  this.write(costants.SIG_ZIP64_EOCD_LOC);

  // disk number holding the ZIP64 EOCD record
  this.write(constants.LONG_ZERO);

  // relative offset of the ZIP64 EOCD record
  this.write(zipUtil.getEightBytes(this._archive.centralOffset + this._archive.centralLength));

  // total number of disks
  this.write(this.getLongBytes(1));
};

ZipArchiveOutputStream.prototype._writeCentralFileHeader = function(ae) {
  var gpb = ae.getGeneralPurposeBit();
  var method = ae.getMethod();
  var offsets = ae._offsets;

  var extraBuf;
  var size = ae.getSize();
  var compressedSize = ae.getCompressedSize();

  if (ae.isZip64() || offsets.file > constants.ZIP64_MAGIC) {
    size = constants.ZIP64_MAGIC;
    compressedSize = constants.ZIP64_MAGIC;

    ae.setVersionNeededToExtract(constants.MIN_VERSION_ZIP64);

    extraBuf = new Buffer(28);
    extraBuf.write(zipUtil.getShortBytes(constants.ZIP64_EXTRA_ID));
    extraBuf.write(zipUtil.getShortBytes(24));
    extraBuf.write(zipUtil.getEightBytes(ae.getSize()));
    extraBuf.write(zipUtil.getEightBytes(ae.getCompressedSize()));
    extraBuf.write(zipUtil.getEightBytes(offsets.file));
    ae.setExtra(extraBuf);
  }

  // signature
  this.write(zipUtil.getLongBytes(constants.SIG_CFH));

  // version made by
  this.write(zipUtil.getShortBytes((ae.getPlatform() << 8) | constants.VERSION_MADEBY));

  // version to extract and general bit flag
  this.write(zipUtil.getShortBytes(ae.getVersionNeededToExtract()));
  this.write(gpb.encode());

  // compression method
  this.write(zipUtil.getShortBytes(method));

  // datetime
  this.write(zipUtil.getLongBytes(ae.getTimeDos()));

  // crc32 checksum
  this.write(zipUtil.getLongBytes(ae.getCrc()));

  // sizes
  this.write(zipUtil.getLongBytes(compressedSize));
  this.write(zipUtil.getLongBytes(size));

  var name = ae.getName();
  var comment = ae.getComment();
  var extra = ae.getCentralDirectoryExtra();

  if (gpb.usesUTF8ForNames()) {
    name = new Buffer(name);
    comment = new Buffer(comment);
  }

  // name length
  this.write(zipUtil.getShortBytes(name.length));

  // extra length
  this.write(zipUtil.getShortBytes(extra.length));

  // comments length
  this.write(zipUtil.getShortBytes(comment.length));

  // disk number start
  this.write(constants.SHORT_ZERO);

  // internal attributes
  this.write(zipUtil.getShortBytes(ae.getInternalAttributes()));

  // external attributes
  this.write(zipUtil.getLongBytes(ae.getExternalAttributes()));

  // relative offset of LFH
  if (offsets.file > constants.ZIP64_MAGIC) {
    this.write(zipUtil.getLongBytes(constants.ZIP64_MAGIC));
  } else {
    this.write(zipUtil.getLongBytes(offsets.file));
  }

  // name
  this.write(name);

  // extra
  this.write(extra);

  // comment
  this.write(comment);
};

ZipArchiveOutputStream.prototype._writeDataDescriptor = function(ae) {
  if (!ae.getGeneralPurposeBit().usesDataDescriptor()) {
    return;
  }

  // signature
  this.write(zipUtil.getLongBytes(constants.SIG_DD));

  // crc32 checksum
  this.write(zipUtil.getLongBytes(ae.getCrc()));

  // sizes
  if (ae.isZip64()) {
    this.write(zipUtil.getEightBytes(ae.getCompressedSize()));
    this.write(zipUtil.getEightBytes(ae.getSize()));
  } else {
    this.write(zipUtil.getLongBytes(ae.getCompressedSize()));
    this.write(zipUtil.getLongBytes(ae.getSize()));
  }
};

ZipArchiveOutputStream.prototype._writeLocalFileHeader = function(ae) {
  var gpb = ae.getGeneralPurposeBit();
  var method = ae.getMethod();
  var name = ae.getName();
  var extra = ae.getLocalFileDataExtra();

  if (ae.isZip64()) {
    gpb.useDataDescriptor(true);
  }

  if (gpb.usesUTF8ForNames()) {
    name = new Buffer(name);
  }

  ae._offsets.file = this.offset;

  // signature
  this.write(zipUtil.getLongBytes(constants.SIG_LFH));

  // version to extract and general bit flag
  this.write(zipUtil.getShortBytes(ae.getVersionNeededToExtract()));
  this.write(gpb.encode());

  // compression method
  this.write(zipUtil.getShortBytes(method));

  // datetime
  this.write(zipUtil.getLongBytes(ae.getTimeDos()));

  ae._offsets.data = this.offset;

  // crc32 checksum and sizes
  if (gpb.usesDataDescriptor()) {
    this.write(constants.LONG_ZERO);
    this.write(constants.LONG_ZERO);
    this.write(constants.LONG_ZERO);
  } else {
    this.write(zipUtil.getLongBytes(ae.getCrc()));
    this.write(zipUtil.getLongBytes(ae.getCompressedSize()));
    this.write(zipUtil.getLongBytes(ae.getSize()));
  }

  // name length
  this.write(zipUtil.getShortBytes(name.length));

  // extra length
  this.write(zipUtil.getShortBytes(extra.length));

  // name
  this.write(name);

  // extra
  this.write(extra);

  ae._offsets.contents = this.offset;
};

ZipArchiveOutputStream.prototype.getComment = function(comment) {
  return this._archive.comment !== null ? this._archive.comment : '';
};

ZipArchiveOutputStream.prototype.isZip64 = function() {
  return this._entries.length > constants.ZIP64_MAGIC_SHORT || this._archive.centralLength > constants.ZIP64_MAGIC || this._archive.centralOffset > constants.ZIP64_MAGIC;
};

ZipArchiveOutputStream.prototype.setComment = function(comment) {
  this._archive.comment = comment;
};<|endoftext|>


<commit_before><commit_msg>added cb docs<commit_after><|endoftext|>


<commit_before>// We assume that we have a separate class for People

// Basic class for all people
var Person={
    // Static vars
    Low: 0,
    Mid: 1,
    Hi: 2,

    // the create function
    createNew: function(data){  // data is a Table
        console.log("[People] created.");
        var p={};

        // Class vars
        p.type=data.type;               // must be one of Person.types
        p.name=data.name;               // nullable
        p.portIndex=data.portIndex;     // nullable
        p.workplace=null;
        p.home=null;
        p.health=0;
        p.education=0;
        p.shelter=0;
        p.influence=null;
        p.role=null;
        p.loyalty=null;

        // Class funcs
        p.isLow=function(){return p.type===0};  // Class func: inline style
        p.isMid=function(){return p.type===1};  // Class func: inline style
        p.isHi=function(){return p.type===2};   // Class func: inline style
        p.report=function(){Person.report(p)};  // Class func: Declaration
        // TODO: add other funcs

        return p;
    },

    // Class func: Implementation
    report: function(p){
        console.log("[Person] type="+p.type+", name="+p.name);
        // TODO: add other infomation that needs to show
    },
};

// Contains all the literal information (string/number/bool vars) of all people
var Population={
    // please see stage1.json: it will be created by stage1.population table.
    createNew: function(data){  // data is an Array
        console.log("[Population] created with count:"+data.length);
        console.assert(Array.isArray(data), "[Population] data must be an Array!");
        var pop={};

        // Class vars
        pop.lowList=[];
        pop.midList=[];
        pop.highList=[];

        // Class funcs
        pop.count=function(){return pop.length};        // Class func: inline style
        pop.report=function(){Population.report(pop)};  // Class func: Declaration
        // TODO: add other funcs

        return pop;
    },

    // Class func: Implementation
    report: function(pop){
        console.log("[Population] now reporting-------");
        for(var i=0;i<pop.length;i++){
            pop[i].report();
        }
        // TODO: add other information that needs to show
        console.log("[Population] end of report.");
    },
};<commit_msg>Pushing progress on People.js so I can pull the current testing branch.<commit_after>// We assume that we have a separate class for People

// Basic class for all people
var Person={
    // Static vars
    Low: 0,
    Mid: 1,
    Hi: 2,

    // the create function
    createNew: function(data){  // data is a Table
        console.log("[People] created.");
        var p={};

        // Class vars
        p.type=data.type;               // must be one of Person.types
        p.name=data.name;               // nullable
        p.portIndex=data.portIndex;     // nullable
        p.workplace=null;
        p.home=null;
        p.health=0;
        p.education=0;
        p.shelter=0;
        p.influence=null;
        p.role=null;
        p.loyalty=null;

        // Class funcs
        p.isLow=function(){return p.type===0};  // Class func: inline style
        p.isMid=function(){return p.type===1};  // Class func: inline style
        p.isHi=function(){return p.type===2};   // Class func: inline style
        p.nextTurn=function(){};
        p.report=function(){Person.report(p)};  // Class func: Declaration
        p.findHousing=function(){Person.findHousing()};
        // TODO: add other funcs

        return p;
    },

    // Class func: Implementation
    report: function(p){
        console.log("[Person] type="+p.type+", name="+p.name);
        // TODO: add other infomation that needs to show
    },

    findHousing: function(){

    },
};

// Contains all the literal information (string/number/bool vars) of all people
var Population={
    // please see stage1.json: it will be created by stage1.population table.
    createNew: function(data){  // data is an Array
        console.log("[Population] created with count:"+data.length);
        console.assert(Array.isArray(data), "[Population] data must be an Array!");
        var pop={};

        // Class vars
        pop.unemployed;
        pop.homeless;
        pop.lowList=[];
        pop.midList=[];
        pop.highList=[];

        // Class funcs
        pop.nextTurn=function(){Population.nextTurn(pop)};
        pop.count=function(){return pop.length};        // Class func: inline style
        pop.report=function(){Population.report(pop)};  // Class func: Declaration
        pop.increasePopulation=function(amount){Population.increasePopulation(pop,amount)};
        pop.hire=function(tileIndex,buildingType){Population.hire(tileIndex,buildingType)};
        pop.fire=function(tileIndex,buildingType){Population.fire(tileIndex,buildingType)};
        // TODO: add other funcs

        return pop;
    },

    // Class func: Implementation
    nextTurn: function(pop){
        for(var p in pop.lowList){
            p.nextTurn();
        }
        for(var p in pop.midList){
            p.nextTurn();
        }
        for(var p in pop.highList){
            p.nextTurn();
        }
    },

    report: function(pop){
        console.log("[Population] now reporting-------");
        for(var i=0;i<pop.length;i++){
            pop[i].report();
        }
        // TODO: add other information that needs to show
        console.log("[Population] end of report.");
    },

    increasePopulation: function(pop,amount){
        for(var i = 1; i < amount; i += 1){
            var per=Person.createNew({"type":0});
            pop.lowList.push(per);
        }
    },

    hire: function(tileIndex,buildingType){

    },

    fire: function(tileIndex,buildingType){

    }
};<|endoftext|>


<commit_before>var properties = [
  {type: 'range', id: "Rows", value: 8, min: 1, max: 10, step: 1},
  {type: 'range', id: "Columns", value: 10, min: 1, max: 10, step: 1},
  {id: "Shapes", type: "list", value: "fill", options: [["fill", "Fill"], ["stroke", "Outline"]]},
];

var executor = function(args, success, failure) {
  var params = args[0];
  var rowCount = params.Rows;
  var columnCount = params.Columns;
  var shapeType = params.Shapes;

  var shape = args[1];
  var width = shape.right - shape.left;
  var height = shape.top - shape.bottom;

  // Returns 6 points representing the shape of one edge of a puzzle piece.
  // Point coordinates are expressed as percentage distances across the width
  // and height of the piece.
  var edgeDistributions = function() {
    var randomBetween = function(min, max) {
      return Math.random() * (max - min) + min;
    };

    var baselineOffsets = {
      xMin: 51,
      xMax: 62,
      yMin: -15,
      yMax: 5
    };

    var upperOffsets = {
      xMin: 20,
      xMax: 30,
      yMin: 20,
      yMax: 44
    };

    var point1 = [0, 0];
    var point2 = [
      randomBetween(baselineOffsets.xMin, baselineOffsets.xMax),
      randomBetween(baselineOffsets.yMin, baselineOffsets.yMax)
    ];
    var point3 = [
      randomBetween(upperOffsets.xMin, upperOffsets.xMax),
      randomBetween(upperOffsets.yMin, upperOffsets.yMax)
    ];
    var point4 = [
      randomBetween(100-upperOffsets.xMax, 100-upperOffsets.xMin),
      randomBetween(upperOffsets.yMin, upperOffsets.yMax)
    ];
    var point5 = [
      randomBetween(100-baselineOffsets.xMax, 100-baselineOffsets.xMin),
      randomBetween(baselineOffsets.yMin, baselineOffsets.yMax)
    ];
    var point6 = [100, 0];

    var sign = Math.random() < 0.5 ? -1 : 1;

    return [point1, point2, point3, point4, point5, point6].map(function(p) {
      return [p[0] / 100, p[1] * sign / 100];
    });
  };

  // Builds an m + 1 x n matrix of edge shapes. The first and last rows
  // are straight edges.
  var buildDistributions = function(m, n) {
    var lineGroups = [];
    var lines = [];
    var points, i, j;

    for (j = 0; j < n; j++) {
      lines.push([[0, 0], [1,0]]);
    }
    lineGroups.push(lines);

    for (i = 1; i < m; i++) {
      lines = [];
      for (j = 0; j < n; j++) {
        lines.push(edgeDistributions());
      }
      lineGroups.push(lines);
    }

    lines = [];
    for (j = 0; j < n; j++) {
      lines.push([[0, 0], [1,0]]);
    }
    lineGroups.push(lines);

    return lineGroups;
  };

  var transposePoint = function(point) {
    return [point[1], point[0]];
  };

  var offsetPoint = function(point, columnIndex, rowIndex, columnWidth, rowHeight) {
    var offsetColumnPosition = function(percent, columnWidth, columnIndex) {
      var columnOffset = columnWidth * columnIndex + shape.left;
      return percent * columnWidth + columnOffset;
    };

    var offsetRowPosition = function(percent, rowHeight, rowIndex) {
      var rowOffset = rowHeight * rowIndex + shape.bottom;
      return percent * rowHeight + rowOffset;
    };

    var x = offsetColumnPosition(point[0], columnWidth, columnIndex);
    var y = offsetRowPosition(point[1], rowHeight, rowIndex);

    return [x, y];
  };

  var offsetPoints = function(lineGroups, offsetter) {
    for (var i=0; i<lineGroups.length; i++) {
      var lines = lineGroups[i];
      for (var j=0; j<lines.length; j++) {
        lines[j] = lines[j].map(function(point) {
          return offsetter(point, j, i);
        });
      }
    }
  };

  var buildPieces = function() {
    var rowHeight = height / rowCount;
    var columnWidth = width / columnCount;
    var pieces = [];

    var rows = buildDistributions(rowCount, columnCount);
    offsetPoints(rows, function(point, j, i) {
      return offsetPoint(point, j, i, columnWidth, rowHeight);
    });

    var columns = buildDistributions(columnCount, rowCount);
    offsetPoints(columns, function(point, j, i) {
      return offsetPoint(transposePoint(point), i, j, columnWidth, rowHeight);
    });

    for (var rowIndex = 1; rowIndex <= rowCount; rowIndex++) {
      for (var columnIndex = 0; columnIndex < columnCount; columnIndex++) {
        var edges = [];
        edges.push(rows[rowIndex - 1][columnIndex]);
        edges.push(columns[columnIndex + 1][rowIndex - 1]);
        edges.push(rows[rowIndex][columnIndex].slice().reverse());
        edges.push(columns[columnIndex][rowIndex - 1].slice().reverse());

        pieces.push(edges);
      }
    }

    return pieces;
  };

  var d3CurvedLine = d3_shape.line().curve(d3_shape.curveBasis);

  var piecePathData = function(piece) {
    return piece.map(function(edge) {
      return d3CurvedLine(edge);
    }).join(" ");
  };

  var buildPiecePaths = function(pieces) {
    return pieces.map(function(piece) {
      return svg.path("stroke", piecePathData(piece), "#000");
    });
  };

  var buildPaths = function(pointArrays) {
    var d3Line = d3_shape.line();

    return pointArrays.map(function(pointArray) {
      return svg.path(shapeType, d3Line(pointArray), "#999");
    })
  };

  var clippedPieces = function(pieces) {
    var scale = 32768; // Clipper can only deal with ints

    var scaleUpLine = function(line) {
      return line.map(function(point) {
        if (point.x)
          return {X: point.x * scale, Y: point.y * scale};
        else
          return {X: point[0] * scale, Y: point[1] * scale};
      });
    };

    var scaleDownLine = function(line) {
      return line.map(function(point) {
        return [point.X / scale, point.Y / scale];
      });
    };

    var closePoints = function(points) {
      var firstPoint, lastPoint;

      if (points.length === 0) {
        return points;
      }

      firstPoint = points[0];
      lastPoint = points[points.length - 1];

      if (firstPoint[0] !== lastPoint[0] || firstPoint[1] !== lastPoint[1]) {
        points.push(firstPoint);
      }

      return points;
    }

    var intersect = function(pieceLines, shapeLines) {
      var scaledUpPieceLines = pieceLines.map(scaleUpLine);
      var scaledUpShapeLines = shapeLines.map(scaleUpLine);

      var solutions = [];

      for (var i = 0; i < scaledUpPieceLines.length; i++) {
        var cpr = new ClipperLib.Clipper();
        var scaledUpPieceLine = scaledUpPieceLines[i];
        var solution = new ClipperLib.Paths();

        cpr.AddPath(scaledUpPieceLine, ClipperLib.PolyType.ptSubject, true);
        cpr.AddPaths(scaledUpShapeLines, ClipperLib.PolyType.ptClip, true);

        cpr.Execute(ClipperLib.ClipType.ctIntersection, solution);

        var closedSolution = solution.map(scaleDownLine).map(closePoints); // Design + piece

        solutions = solutions.concat(closedSolution);
      }
      return solutions;
    };

    var polylineGenerator = EASEL.pathPolylineGenerator(0.001, EASEL.matrix());
    var piecePathDataStrings = pieces.map(piecePathData);

    var pieceLines = piecePathDataStrings.map(function(dataString) {
      var controlPoints = EASEL.pathToControlPoints(EASEL.pathStringParser.parse(dataString));
      var polylines = polylineGenerator.toPolylines(controlPoints);

      var points = [];
      for (var i = 0; i < polylines.length; i++) {
        points = points.concat(polylines[i]);
      }
      return points;
    });

    return intersect(pieceLines, shape.pointArrays);
  };

  // SVG helpers
  var svg = {
    header: '<?xml version="1.0" standalone="no"?>',
    openTag: '<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="' + width + 'in" height="' + height + 'in"' +
               ' viewBox="' + shape.left + ' ' + shape.bottom + ' ' + width + ' ' + height + '">',
    closeTag: '</svg>',
    openGTag: '<g transform="translate(0,' + (shape.top + shape.bottom) + ') scale(1,-1)">',
    closeGTag: '</g>',
    path: function(type, pathData, color) {
      var strokeFill = [color, 'none'];
      if (type === 'fill') {
        strokeFill.reverse();
      }
      return '<path stroke-width="1" stroke="' + strokeFill[0] + '" fill="' + strokeFill[1] + '" vector-effect="non-scaling-stroke" d="' + pathData + '"/>';
    }
  };

  var pieces = buildPieces();
  var piecePaths = buildPiecePaths(pieces).join("");
  var clippedPieceLines = clippedPieces(pieces);

  success([
    svg.header,
    svg.openTag,
    svg.openGTag,
    //buildPaths(shape.pointArrays),
    buildPaths(clippedPieceLines),
    piecePaths,
    svg.closeGTag,
    svg.closeTag
  ].join(""));
};

<commit_msg>Use boolean to indicate stroke/fill<commit_after>var alert = function() {

}

var properties = [
  {type: 'range', id: "Rows", value: 8, min: 1, max: 10, step: 1},
  {type: 'range', id: "Columns", value: 10, min: 1, max: 10, step: 1},
  {id: "Shapes", type: "list", value: "fill", options: [["fill", "Fill"], ["stroke", "Outline"]]},
];

var executor = function(args, success, failure) {
  var params = args[0];
  var rowCount = params.Rows;
  var columnCount = params.Columns;
  var usingFills = params.Shapes === 'fill';

  var shape = args[1];
  var width = shape.right - shape.left;
  var height = shape.top - shape.bottom;

  // Returns 6 points representing the shape of one edge of a puzzle piece.
  // Point coordinates are expressed as percentage distances across the width
  // and height of the piece.
  var edgeDistributions = function() {
    var randomBetween = function(min, max) {
      return Math.random() * (max - min) + min;
    };

    var baselineOffsets = {
      xMin: 51,
      xMax: 62,
      yMin: -15,
      yMax: 5
    };

    var upperOffsets = {
      xMin: 20,
      xMax: 30,
      yMin: 20,
      yMax: 44
    };

    var point1 = [0, 0];
    var point2 = [
      randomBetween(baselineOffsets.xMin, baselineOffsets.xMax),
      randomBetween(baselineOffsets.yMin, baselineOffsets.yMax)
    ];
    var point3 = [
      randomBetween(upperOffsets.xMin, upperOffsets.xMax),
      randomBetween(upperOffsets.yMin, upperOffsets.yMax)
    ];
    var point4 = [
      randomBetween(100-upperOffsets.xMax, 100-upperOffsets.xMin),
      randomBetween(upperOffsets.yMin, upperOffsets.yMax)
    ];
    var point5 = [
      randomBetween(100-baselineOffsets.xMax, 100-baselineOffsets.xMin),
      randomBetween(baselineOffsets.yMin, baselineOffsets.yMax)
    ];
    var point6 = [100, 0];

    var sign = Math.random() < 0.5 ? -1 : 1;

    return [point1, point2, point3, point4, point5, point6].map(function(p) {
      return [p[0] / 100, p[1] * sign / 100];
    });
  };

  // Builds an m + 1 x n matrix of edge shapes. The first and last rows
  // are straight edges.
  var buildDistributions = function(m, n) {
    var lineGroups = [];
    var lines = [];
    var points, i, j;

    for (j = 0; j < n; j++) {
      lines.push([[0, 0], [1,0]]);
    }
    lineGroups.push(lines);

    for (i = 1; i < m; i++) {
      lines = [];
      for (j = 0; j < n; j++) {
        lines.push(edgeDistributions());
      }
      lineGroups.push(lines);
    }

    lines = [];
    for (j = 0; j < n; j++) {
      lines.push([[0, 0], [1,0]]);
    }
    lineGroups.push(lines);

    return lineGroups;
  };

  var transposePoint = function(point) {
    return [point[1], point[0]];
  };

  var offsetPoint = function(point, columnIndex, rowIndex, columnWidth, rowHeight) {
    var offsetColumnPosition = function(percent, columnWidth, columnIndex) {
      var columnOffset = columnWidth * columnIndex + shape.left;
      return percent * columnWidth + columnOffset;
    };

    var offsetRowPosition = function(percent, rowHeight, rowIndex) {
      var rowOffset = rowHeight * rowIndex + shape.bottom;
      return percent * rowHeight + rowOffset;
    };

    var x = offsetColumnPosition(point[0], columnWidth, columnIndex);
    var y = offsetRowPosition(point[1], rowHeight, rowIndex);

    return [x, y];
  };

  var offsetPoints = function(lineGroups, offsetter) {
    for (var i=0; i<lineGroups.length; i++) {
      var lines = lineGroups[i];
      for (var j=0; j<lines.length; j++) {
        lines[j] = lines[j].map(function(point) {
          return offsetter(point, j, i);
        });
      }
    }
  };

  var buildPieces = function() {
    var rowHeight = height / rowCount;
    var columnWidth = width / columnCount;
    var pieces = [];

    var rows = buildDistributions(rowCount, columnCount);
    offsetPoints(rows, function(point, j, i) {
      return offsetPoint(point, j, i, columnWidth, rowHeight);
    });

    var columns = buildDistributions(columnCount, rowCount);
    offsetPoints(columns, function(point, j, i) {
      return offsetPoint(transposePoint(point), i, j, columnWidth, rowHeight);
    });

    for (var rowIndex = 1; rowIndex <= rowCount; rowIndex++) {
      for (var columnIndex = 0; columnIndex < columnCount; columnIndex++) {
        var edges = [];
        edges.push(rows[rowIndex - 1][columnIndex]);
        edges.push(columns[columnIndex + 1][rowIndex - 1]);
        edges.push(rows[rowIndex][columnIndex].slice().reverse());
        edges.push(columns[columnIndex][rowIndex - 1].slice().reverse());

        pieces.push(edges);
      }
    }

    return pieces;
  };

  var d3CurvedLine = d3_shape.line().curve(d3_shape.curveBasis);

  var piecePathData = function(piece) {
    return piece.map(function(edge) {
      return d3CurvedLine(edge);
    }).join(" ");
  };

  var buildPiecePaths = function(pieces) {
    return pieces.map(function(piece) {
      return svg.path(false, piecePathData(piece), "#000");
    });
  };

  var buildPaths = function(pointArrays) {
    var d3Line = d3_shape.line();

    return pointArrays.map(function(pointArray) {
      return svg.path(usingFills, d3Line(pointArray), "#999");
    })
  };

  var clippedPieces = function(pieces) {
    var scale = 32768; // Clipper can only deal with ints

    var scaleUpLine = function(line) {
      return line.map(function(point) {
        if (point.x)
          return {X: point.x * scale, Y: point.y * scale};
        else
          return {X: point[0] * scale, Y: point[1] * scale};
      });
    };

    var scaleDownLine = function(line) {
      return line.map(function(point) {
        return [point.X / scale, point.Y / scale];
      });
    };

    var closePoints = function(points) {
      var firstPoint, lastPoint;

      if (points.length === 0) {
        return points;
      }

      firstPoint = points[0];
      lastPoint = points[points.length - 1];

      if (firstPoint[0] !== lastPoint[0] || firstPoint[1] !== lastPoint[1]) {
        points.push(firstPoint);
      }

      return points;
    }

    var intersect = function(pieceLines, shapeLines) {
      var scaledUpPieceLines = pieceLines.map(scaleUpLine);
      var scaledUpShapeLines = shapeLines.map(scaleUpLine);

      var solutions = [];

      for (var i = 0; i < scaledUpPieceLines.length; i++) {
        var cpr = new ClipperLib.Clipper();
        var scaledUpPieceLine = scaledUpPieceLines[i];
        var solution = new ClipperLib.Paths();

        cpr.AddPath(scaledUpPieceLine, ClipperLib.PolyType.ptClip, true);
        cpr.AddPaths(scaledUpShapeLines, ClipperLib.PolyType.ptSubject, usingFills);

        cpr.Execute(ClipperLib.ClipType.ctIntersection, solution);

        solution = solution.map(scaleDownLine);

        if (usingFills) {
          solution = solution.map(closePoints);
        }

        solutions = solutions.concat(solution);
      }
      return solutions;
    };

    var polylineGenerator = EASEL.pathPolylineGenerator(0.001, EASEL.matrix());
    var piecePathDataStrings = pieces.map(piecePathData);

    var pieceLines = piecePathDataStrings.map(function(dataString) {
      var controlPoints = EASEL.pathToControlPoints(EASEL.pathStringParser.parse(dataString));
      var polylines = polylineGenerator.toPolylines(controlPoints);

      var points = [];
      for (var i = 0; i < polylines.length; i++) {
        points = points.concat(polylines[i]);
      }
      return points;
    });

    return intersect(pieceLines, shape.pointArrays);
  };

  // SVG helpers
  var svg = {
    header: '<?xml version="1.0" standalone="no"?>',
    openTag: '<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="' + width + 'in" height="' + height + 'in"' +
               ' viewBox="' + shape.left + ' ' + shape.bottom + ' ' + width + ' ' + height + '">',
    closeTag: '</svg>',
    openGTag: '<g transform="translate(0,' + (shape.top + shape.bottom) + ') scale(1,-1)">',
    closeGTag: '</g>',
    path: function(isFill, pathData, color) {
      var strokeFill = [color, 'none'];
      if (isFill) {
        strokeFill.reverse();
      }
      return '<path stroke-width="1" stroke="' + strokeFill[0] + '" fill="' + strokeFill[1] + '" vector-effect="non-scaling-stroke" d="' + pathData + '"/>';
    }
  };

  var pieces = buildPieces();
  var piecePaths = buildPiecePaths(pieces).join("");
  var clippedPieceLines = clippedPieces(pieces);

  success([
    svg.header,
    svg.openTag,
    svg.openGTag,
    //buildPaths(shape.pointArrays),
    buildPaths(clippedPieceLines),
    piecePaths,
    svg.closeGTag,
    svg.closeTag
  ].join(""));
};

<|endoftext|>


<commit_before>import API from 'src/util/api';
import UI from 'src/util/ui';

import getViewInfo from './getViewInfo';

// ModulePrefsManager is created in the init script
// Any module may have a gear in the settings allowing to change preferences
// the system will either store in Roc or localStorge depending what is available

export class ModulePrefsManager {
  constructor(options = {}) {
    let promises = [];
    if (options.hasRoc) {
      let waitingRoc = new Promise(resolveRoc => {
        this.resolveRoc = resolveRoc;
      }).then(() => {
        console.log('Roc initialized');
      });
      promises.push(waitingRoc);
    }

    let waitingView = getViewInfo().then(result => {
      this.viewID = result._id;
    });
    promises.push(waitingView);

    let promiseAll = Promise.all(promises).then(() => {
      this.waiting = () => true;
    });
    this.waiting = () => promiseAll;
  }

  setRoc(roc) {
    this.roc = roc;
    this.resolveRoc();
  }

  async updateSlickGridPrefs(moduleID) {
    await this.waiting();
    const objectStructure = API.getModule(moduleID).data.resurrect()[0];

    const cols = JSON.parse(
      JSON.stringify(API.getModulePreferences(moduleID).cols)
    );
    cols.forEach(item => {
      if (!item.id) item.id = Math.random();
    });

    await UI.editTable(cols, {
      remove: true,
      reorder: true,
      dialog: {
        title: 'Configure the columns of the module'
      },
      columns: [
        {
          id: 'id',
          name: 'name',
          jpath: ['name'],
          editor: Slick.CustomEditors.TextValue
        },
        {
          id: 'rendererOptions',
          name: 'rendererOptions',
          jpath: ['rendererOptions'],
          editor: Slick.CustomEditors.TextValue
        },
        {
          id: 'width',
          name: 'width',
          jpath: ['width'],
          editor: Slick.CustomEditors.NumberValue
        },
        {
          id: 'x',
          name: 'x',
          jpath: ['x'],
          editor: Slick.CustomEditors.Select,
          editorOptions: { choices: 'ab:cd;ef:gh' }
        },
        {
          id: 'jpath',
          name: 'jpath',
          jpath: ['jpath'],
          editor: Slick.CustomEditors.JPathFactory(objectStructure),
          forceType: 'jpath',
          rendererOptions: {
            forceType: 'jpath'
          }
        }
      ]
    });

    cols.forEach(item => {
      item.formatter = 'typerenderer';
    });
    API.updateModulePreferences(moduleID, {
      cols: JSON.parse(JSON.stringify(cols))
    });

    this.saveModulePrefs(moduleID, { cols });
  }

  async reloadModulePrefs(moduleID) {
    await this.waiting();
    if (this.roc) {
      this.reloadModulePrefsFromRoc(moduleID);
    } else {
      this.reloadModulePrefsFromLocalStorage(moduleID);
    }
  }

  async reloadModulePrefsFromLocalStorage(moduleID) {
    let prefs = JSON.parse(
      localStorage.getItem('viewModulePreferences') || '{}'
    );
    if (!prefs[this.viewID]) return;
    if (moduleID && !prefs[this.viewID][moduleID]) return;
    if (moduleID) {
      API.updateModulePreferences(moduleID, prefs[this.viewID][moduleID]);
    } else {
      for (moduleID in prefs[this.viewID]) {
        API.updateModulePreferences(moduleID, prefs[this.viewID][moduleID]);
      }
    }
  }

  async getRecord() {
    var user = await this.roc.getUser();
    if (!user || !user.username) return undefined;
    return (
      await this.roc.view('entryByOwnerAndId', {
        key: [user.username, ['userModulePrefs', this.viewID]]
      })
    )[0];
  }

  async reloadModulePrefsFromRoc(moduleID) {
    const record = await this.getRecord();
    if (!record) return;
    if (moduleID) {
      API.updateModulePreferences(moduleID, record.$content[moduleID]);
    } else {
      for (moduleID in record.$content[moduleID]) {
        API.updateModulePreferences(moduleID, record.$content[moduleID]);
      }
    }
  }

  async saveModulePrefs(moduleID, modulePrefs) {
    await this.waiting();
    if (this.roc) {
      this.saveModulePrefsToRoc(moduleID, modulePrefs);
    } else {
      this.saveModulePrefsToLocalStorage(moduleID, modulePrefs);
    }
  }

  async saveModulePrefsToLocalStorage(moduleID, modulePrefs) {
    let prefs = JSON.parse(
      localStorage.getItem('viewModulePreferences') || '{}'
    );
    if (!prefs[this.viewID]) prefs[this.viewID] = {};
    prefs[this.viewID][moduleID] = modulePrefs;
    localStorage.setItem('viewModulePreferences', JSON.stringify(prefs));
  }

  async saveModulePrefsToRoc(moduleID, modulePrefs) {
    let record = await this.getRecord();
    if (record) {
      record.$content[moduleID] = modulePrefs;
      return this.roc.update(record);
    } else {
      let content = {};
      content[moduleID] = modulePrefs;
      return this.roc.create({
        $id: ['userModulePrefs', this.viewID],
        $content: content,
        $kind: 'userModulePrefs'
      });
    }
  }
}

module.exports = ModulePrefsManager;
<commit_msg>feat: save in local storage if no roc<commit_after>import API from 'src/util/api';
import UI from 'src/util/ui';

import getViewInfo from './getViewInfo';

// ModulePrefsManager is created in the init script
// Any module may have a gear in the settings allowing to change preferences
// the system will either store in Roc or localStorge depending what is available

export class ModulePrefsManager {
  constructor(options = {}) {
    let promises = [];
    if (options.hasRoc) {
      let waitingRoc = new Promise((resolveRoc) => {
        this.resolveRoc = resolveRoc;
      }).then(() => {
        console.log('Roc initialized');
      });
      promises.push(waitingRoc);
    }

    let waitingView = getViewInfo().then((result) => {
      this.viewID = result._id;
    });
    promises.push(waitingView);

    let promiseAll = Promise.all(promises).then(() => {
      this.waiting = () => true;
    });
    this.waiting = () => promiseAll;
  }

  setRoc(roc) {
    this.roc = roc;
    this.resolveRoc();
  }

  async updateSlickGridPrefs(moduleID) {
    await this.waiting();
    const objectStructure = API.getModule(moduleID).data.resurrect()[0];

    const cols = JSON.parse(
      JSON.stringify(API.getModulePreferences(moduleID).cols)
    );
    cols.forEach((item) => {
      if (!item.id) item.id = Math.random();
    });

    await UI.editTable(cols, {
      remove: true,
      reorder: true,
      dialog: {
        title: 'Configure the columns of the module'
      },
      columns: [
        {
          id: 'id',
          name: 'name',
          jpath: ['name'],
          editor: Slick.CustomEditors.TextValue
        },
        {
          id: 'rendererOptions',
          name: 'rendererOptions',
          jpath: ['rendererOptions'],
          editor: Slick.CustomEditors.TextValue
        },
        {
          id: 'width',
          name: 'width',
          jpath: ['width'],
          editor: Slick.CustomEditors.NumberValue
        },
        {
          id: 'x',
          name: 'x',
          jpath: ['x'],
          editor: Slick.CustomEditors.Select,
          editorOptions: { choices: 'ab:cd;ef:gh' }
        },
        {
          id: 'jpath',
          name: 'jpath',
          jpath: ['jpath'],
          editor: Slick.CustomEditors.JPathFactory(objectStructure),
          forceType: 'jpath',
          rendererOptions: {
            forceType: 'jpath'
          }
        }
      ]
    });

    cols.forEach((item) => {
      item.formatter = 'typerenderer';
    });
    API.updateModulePreferences(moduleID, {
      cols: JSON.parse(JSON.stringify(cols))
    });

    this.saveModulePrefs(moduleID, { cols });
  }

  async reloadModulePrefs(moduleID) {
    await this.waiting();
    if (this.roc) {
      this.reloadModulePrefsFromRoc(moduleID);
    } else {
      this.reloadModulePrefsFromLocalStorage(moduleID);
    }
  }

  async reloadModulePrefsFromLocalStorage(moduleID) {
    let prefs = JSON.parse(
      localStorage.getItem('viewModulePreferences') || '{}'
    );
    if (!prefs[this.viewID]) return;
    if (moduleID && !prefs[this.viewID][moduleID]) return;
    if (moduleID) {
      API.updateModulePreferences(moduleID, prefs[this.viewID][moduleID]);
    } else {
      for (moduleID in prefs[this.viewID]) {
        API.updateModulePreferences(moduleID, prefs[this.viewID][moduleID]);
      }
    }
  }

  async getRecord() {
    var user = await this.roc.getUser();
    if (!user || !user.username) return undefined;
    return (
      await this.roc.view('entryByOwnerAndId', {
        key: [user.username, ['userModulePrefs', this.viewID]]
      })
    )[0];
  }

  async reloadModulePrefsFromRoc(moduleID) {
    const record = await this.getRecord();
    if (!record) return;
    if (moduleID) {
      API.updateModulePreferences(moduleID, record.$content[moduleID]);
    } else {
      for (moduleID in record.$content[moduleID]) {
        API.updateModulePreferences(moduleID, record.$content[moduleID]);
      }
    }
  }

  async saveModulePrefs(moduleID, modulePrefs) {
    await this.waiting();
    if (this.roc) {
      this.saveModulePrefsToRoc(moduleID, modulePrefs);
    } else {
      this.saveModulePrefsToLocalStorage(moduleID, modulePrefs);
    }
  }

  async saveModulePrefsToLocalStorage(moduleID, modulePrefs) {
    let prefs = JSON.parse(
      localStorage.getItem('viewModulePreferences') || '{}'
    );
    if (!prefs[this.viewID]) prefs[this.viewID] = {};
    prefs[this.viewID][moduleID] = modulePrefs;
    localStorage.setItem('viewModulePreferences', JSON.stringify(prefs));
  }

  async saveModulePrefsToRoc(moduleID, modulePrefs) {
    let record = await this.getRecord();
    if (record) {
      record.$content[moduleID] = modulePrefs;
      return this.roc.update(record);
    } else {
      let content = {};
      content[moduleID] = modulePrefs;
      return this.roc.create({
        $id: ['userModulePrefs', this.viewID],
        $content: content,
        $kind: 'userModulePrefs'
      });
    }
  }
}

module.exports = ModulePrefsManager;
<|endoftext|>