<commit_before>/**
 * The reload plugin to free your finger.
 *
 * Active this plugin with seajs hook:
 *
 * - ?seajs-reload
 * - ?seajs-reload=8000
 * - ?seajs-reload=192.168.1.2:8000
 *
 * the default request location is localhost:8000
 *
 * You need a reload server that supports it.
 * The server should watch the file changes, and sent a "update" message.
 *
 * For example::
 *
 *   var io = require('socket.io').listen(8000)
 *   io.sockes.on('connection', function(socket) {
 *     // if (fileChanged) {
 *     socket.emit('update', {message: 'file changed'})
 *     // }
 *   })
 *
 * We provided a server for you at:
 *
 * https://github.com/seajs/reload-server
 */
define('seajs/plugin-reload', [], function(require) {

  var loc = location.search.match(/seajs-reload=?([^:]*:)?(\d+)?/)
  var host = loc[1] || 'localhost:'
  var port = loc[2] || '8000'
  var url = 'http://' + host + port

  require.async(url + '/socket.io/socket.io.js', function() {
    var socket = io.connect(url)
    socket.on('update', function() {
      location.reload()
    })
  })
});
<commit_msg>Fix comments<commit_after>/**
 * The reload plugin to free your finger.
 *
 * Active this plugin with seajs hook:
 *
 * - ?seajs-reload
 * - ?seajs-reload=8000
 * - ?seajs-reload=192.168.1.2:8000
 *
 * The default request location is localhost:8000
 *
 * You need a reload server that supports it.
 * The server should watch the file changes, and sent a "update" message.
 *
 * For example:
 *
 *   var io = require('socket.io').listen(8000)
 *   io.sockets.on('connection', function(socket) {
 *     // if (fileChanged) {
 *     socket.emit('update', {message: 'file changed'})
 *     // }
 *   })
 *
 * We provided a server for you at:
 *
 * https://github.com/seajs/reload-server
 */
define('seajs/plugin-reload', [], function(require) {

  var loc = location.search.match(/seajs-reload=?([^:]*:)?(\d+)?/)
  var host = loc[1] || 'localhost:'
  var port = loc[2] || '8000'
  var url = 'http://' + host + port

  require.async(url + '/socket.io/socket.io.js', function() {
    var socket = io.connect(url)
    socket.on('update', function() {
      location.reload()
    })
  })

});
<|endoftext|>


<commit_before>/**
* @author       Richard Davey <rich@photonstorm.com>
* @copyright    2016 Photon Storm Ltd.
* @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/

/**
* Create a new `Bullet` object. Bullets are used by the `Phaser.Weapon` class, and are normal Sprites,
* with a few extra properties in the data object to handle Weapon specific features.
*
* @class Phaser.Bullet
* @constructor
* @extends Phaser.Sprite
* @param {Phaser.Game} game - A reference to the currently running game.
* @param {number} x - The x coordinate (in world space) to position the Particle at.
* @param {number} y - The y coordinate (in world space) to position the Particle at.
* @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the Particle during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
* @param {string|number} frame - If this Particle is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
*/
Phaser.Bullet = function (game, x, y, key, frame) {

    Phaser.Sprite.call(this, game, x, y, key, frame);

    this.anchor.set(0.5);

    this.data = {
        bulletManager: null,
        fromX: 0,
        fromY: 0,
        bodyDirty: true,
        rotateToVelocity: false,
        killType: 0,
        killDistance: 0
    };

};

Phaser.Bullet.prototype = Object.create(Phaser.Sprite.prototype);
Phaser.Bullet.prototype.constructor = Phaser.Bullet;

/**
* Kills the Bullet, freeing it up for re-use by the Weapon bullet pool.
* Also dispatches the `Weapon.onKill` signal.
*
* @method Phaser.Bullet#kill
* @memberof Phaser.Bullet
*/
Phaser.Bullet.prototype.kill = function () {

    this.alive = false;
    this.exists = false;
    this.visible = false;

    this.data.bulletManager.onKill.dispatch(this);

    return this;

};

/**
* Updates the Bullet, killing as required.
*
* @method Phaser.Bullet#kill
* @memberof Phaser.Bullet
*/
Phaser.Bullet.prototype.update = function () {

    if (!this.exists)
    {
        return;
    }

    if (this.data.killType > Phaser.Weapon.KILL_LIFESPAN)
    {
        if (this.data.killType === Phaser.Weapon.KILL_DISTANCE)
        {
            if (this.game.physics.arcade.distanceToXY(this, this.data.fromX, this.data.fromY, true) > this.data.killDistance)
            {
                this.kill();
            }
        }
        else
        {
            if (!this.data.bulletManager.bulletBounds.intersects(this))
            {
                this.kill();
            }
        }
    }

    if (this.data.rotateToVelocity)
    {
        this.rotation = Math.atan2(this.body.velocity.y, this.body.velocity.x);
    }

    if (this.data.bulletManager.bulletWorldWrap)
    {
        this.game.world.wrap(this, this.data.bulletManager.bulletWorldWrapPadding);
    }

};
<commit_msg>Fix method name in Bullet#update<commit_after>/**
* @author       Richard Davey <rich@photonstorm.com>
* @copyright    2016 Photon Storm Ltd.
* @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/

/**
* Create a new `Bullet` object. Bullets are used by the `Phaser.Weapon` class, and are normal Sprites,
* with a few extra properties in the data object to handle Weapon specific features.
*
* @class Phaser.Bullet
* @constructor
* @extends Phaser.Sprite
* @param {Phaser.Game} game - A reference to the currently running game.
* @param {number} x - The x coordinate (in world space) to position the Particle at.
* @param {number} y - The y coordinate (in world space) to position the Particle at.
* @param {string|Phaser.RenderTexture|Phaser.BitmapData|PIXI.Texture} key - This is the image or texture used by the Particle during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
* @param {string|number} frame - If this Particle is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
*/
Phaser.Bullet = function (game, x, y, key, frame) {

    Phaser.Sprite.call(this, game, x, y, key, frame);

    this.anchor.set(0.5);

    this.data = {
        bulletManager: null,
        fromX: 0,
        fromY: 0,
        bodyDirty: true,
        rotateToVelocity: false,
        killType: 0,
        killDistance: 0
    };

};

Phaser.Bullet.prototype = Object.create(Phaser.Sprite.prototype);
Phaser.Bullet.prototype.constructor = Phaser.Bullet;

/**
* Kills the Bullet, freeing it up for re-use by the Weapon bullet pool.
* Also dispatches the `Weapon.onKill` signal.
*
* @method Phaser.Bullet#kill
* @memberof Phaser.Bullet
*/
Phaser.Bullet.prototype.kill = function () {

    this.alive = false;
    this.exists = false;
    this.visible = false;

    this.data.bulletManager.onKill.dispatch(this);

    return this;

};

/**
* Updates the Bullet, killing as required.
*
* @method Phaser.Bullet#update
* @memberof Phaser.Bullet
*/
Phaser.Bullet.prototype.update = function () {

    if (!this.exists)
    {
        return;
    }

    if (this.data.killType > Phaser.Weapon.KILL_LIFESPAN)
    {
        if (this.data.killType === Phaser.Weapon.KILL_DISTANCE)
        {
            if (this.game.physics.arcade.distanceToXY(this, this.data.fromX, this.data.fromY, true) > this.data.killDistance)
            {
                this.kill();
            }
        }
        else
        {
            if (!this.data.bulletManager.bulletBounds.intersects(this))
            {
                this.kill();
            }
        }
    }

    if (this.data.rotateToVelocity)
    {
        this.rotation = Math.atan2(this.body.velocity.y, this.body.velocity.x);
    }

    if (this.data.bulletManager.bulletWorldWrap)
    {
        this.game.world.wrap(this, this.data.bulletManager.bulletWorldWrapPadding);
    }

};
<|endoftext|>


<commit_before>require('es6-promise/auto');  // polyfill Promise on IE

var PageConfig = require('@jupyterlab/coreutils').PageConfig;
__webpack_public_path__ = PageConfig.getOption('publicUrl');

// This needs to come after __webpack_public_path__ is set.
require('font-awesome/css/font-awesome.min.css');
var app = require('@jupyterlab/application').JupyterLab;

function main() {
    var version = PageConfig.getOption('appVersion') || 'unknown';
    var name = PageConfig.getOption('appName') || 'JupyterLab';
    var namespace = PageConfig.getOption('appNamespace') || 'jupyterlab';
    var devMode = PageConfig.getOption('devMode') || 'false';
    var settingsDir = PageConfig.getOption('settingsDir') || '';
    var assetsDir = PageConfig.getOption('assetsDir') || '';

    if (version[0] === 'v') {
        version = version.slice(1);
    }

    // Get the disabled extensions.
    var disabled = [];
    try {
        var option = PageConfig.getOption('disabledExtensions');
        disabled = JSON.parse(option);
    } catch (e) {
        // No-op
    }

    // Get the deferred extensions.
    var deferredExtensions = [];
    var ignorePlugins = [];
    try {
        var option = PageConfig.getOption('deferredExtensions');
        deferredExtensions = JSON.parse(option).map(function(pattern) {
            return { raw: pattern, rule: new RegExp(pattern) };
        });
    } catch (e) {
        // No-op
    }

    // Handle the registered mime extensions.
    var mimeExtensions = [];
    {{#each jupyterlab_mime_extensions}}
    try {
        var deferred = !deferredExtensions.some(function(pattern) {
            return pattern.raw === '{{@key}}' || pattern.rule.test('{{@key}}')
        });
        var enabled = !disabled.some(function(pattern) {
            return pattern.raw === '{{@key}}' || pattern.rule.test('{{@key}}')
        });

        if (deferred) {
            ignorePlugins.push('{{key}}');
        }
        if (enabled) {
            mimeExtensions.push(require('{{@key}}/{{this}}'));
        }
    } catch (e) {
        console.error(e);
    }
    {{/each}}

    lab = new app({
        namespace: namespace,
        name: name,
        version: version,
        devMode: devMode.toLowerCase() === 'true',
        settingsDir: settingsDir,
        assetsDir: assetsDir,
        mimeExtensions: mimeExtensions
    });

    // Handled the registered standard extensions.
    {{#each jupyterlab_extensions}}
    try {
        var deferred = !deferredExtensions.some(function(pattern) {
            return pattern.raw === '{{@key}}' || pattern.rule.test('{{@key}}')
        });
        var enabled = !disabled.some(function(pattern) {
            return pattern.raw === '{{@key}}' || pattern.rule.test('{{@key}}')
        });

        if (deferred) {
            ignorePlugins.push('{{key}}');
        }
        if (enabled) {
            lab.registerPluginModule(require('{{@key}}/{{this}}'));
        }
    } catch (e) {
        console.error(e);
    }
    {{/each}}

    lab.start({ ignorePlugins: ignorePlugins });

    // Handle a selenium test.
    var seleniumTest = PageConfig.getOption('seleniumTest');
    if (seleniumTest.toLowerCase() === 'true') {
        var caught_errors = []
        window.onerror = function(msg, url, line, col, error) {
           caught_errors.push(String(error));
        };
        lab.restored.then(function() {
            var el = document.createElement('div');
            el.id = 'seleniumResult';
            el.textContent = JSON.stringify(caught_errors);
            document.body.appendChild(el);
        });
    }

}

window.onload = main;
<commit_msg>Make sure disabled extensions are processed.<commit_after>require('es6-promise/auto');  // polyfill Promise on IE

var PageConfig = require('@jupyterlab/coreutils').PageConfig;
__webpack_public_path__ = PageConfig.getOption('publicUrl');

// This needs to come after __webpack_public_path__ is set.
require('font-awesome/css/font-awesome.min.css');
var app = require('@jupyterlab/application').JupyterLab;

function main() {
    var version = PageConfig.getOption('appVersion') || 'unknown';
    var name = PageConfig.getOption('appName') || 'JupyterLab';
    var namespace = PageConfig.getOption('appNamespace') || 'jupyterlab';
    var devMode = PageConfig.getOption('devMode') || 'false';
    var settingsDir = PageConfig.getOption('settingsDir') || '';
    var assetsDir = PageConfig.getOption('assetsDir') || '';

    if (version[0] === 'v') {
        version = version.slice(1);
    }

    // Get the disabled extensions.
    var disabled = [];
    try {
        var option = PageConfig.getOption('disabledExtensions');
        disabled = JSON.parse(option).map(function(pattern) {
            return { raw: pattern, rule: new RegExp(pattern) };
        });
    } catch (e) {
        // No-op
    }

    // Get the deferred extensions.
    var deferredExtensions = [];
    var ignorePlugins = [];
    try {
        var option = PageConfig.getOption('deferredExtensions');
        deferredExtensions = JSON.parse(option).map(function(pattern) {
            return { raw: pattern, rule: new RegExp(pattern) };
        });
    } catch (e) {
        // No-op
    }

    // Handle the registered mime extensions.
    var mimeExtensions = [];
    {{#each jupyterlab_mime_extensions}}
    try {
        var deferred = !deferredExtensions.some(function(pattern) {
            return pattern.raw === '{{@key}}' || pattern.rule.test('{{@key}}')
        });
        var enabled = !disabled.some(function(pattern) {
            return pattern.raw === '{{@key}}' || pattern.rule.test('{{@key}}')
        });

        if (deferred) {
            ignorePlugins.push('{{key}}');
        }
        if (enabled) {
            mimeExtensions.push(require('{{@key}}/{{this}}'));
        }
    } catch (e) {
        console.error(e);
    }
    {{/each}}

    lab = new app({
        namespace: namespace,
        name: name,
        version: version,
        devMode: devMode.toLowerCase() === 'true',
        settingsDir: settingsDir,
        assetsDir: assetsDir,
        mimeExtensions: mimeExtensions
    });

    // Handled the registered standard extensions.
    {{#each jupyterlab_extensions}}
    try {
        var deferred = !deferredExtensions.some(function(pattern) {
            return pattern.raw === '{{@key}}' || pattern.rule.test('{{@key}}')
        });
        var enabled = !disabled.some(function(pattern) {
            return pattern.raw === '{{@key}}' || pattern.rule.test('{{@key}}')
        });

        if (deferred) {
            ignorePlugins.push('{{key}}');
        }
        if (enabled) {
            lab.registerPluginModule(require('{{@key}}/{{this}}'));
        }
    } catch (e) {
        console.error(e);
    }
    {{/each}}

    lab.start({ ignorePlugins: ignorePlugins });

    // Handle a selenium test.
    var seleniumTest = PageConfig.getOption('seleniumTest');
    if (seleniumTest.toLowerCase() === 'true') {
        var caught_errors = []
        window.onerror = function(msg, url, line, col, error) {
           caught_errors.push(String(error));
        };
        lab.restored.then(function() {
            var el = document.createElement('div');
            el.id = 'seleniumResult';
            el.textContent = JSON.stringify(caught_errors);
            document.body.appendChild(el);
        });
    }

}

window.onload = main;
<|endoftext|>


<commit_before>/*
 Copyright 2010 WebDriver committers
 Copyright 2010 Google Inc.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/**
 * @fileoverview An implementation of a timer that can be used without an
 * assocuated window.
 */

var CC = Components.classes;
var CI = Components.interfaces;

/**
 * @constructor
 */
function Timer() { /* Empty */ }

/**
 * Set a callback to be executed after a specified time out. The default time
 * out is 10ms.
 *
 * @param {!function(*=): *} callback The callback to use.
 * @param {number=} opt_timeout An optional timeout to use.
 */
Timer.prototype.setTimeout = function(callback, opt_timeout) {
  var timeout = opt_timeout || 10;
  var timer = CC['@mozilla.org/timer;1'].createInstance(CI['nsITimer']);

  timer.initWithCallback({
    notify: function() {
      callback.apply(null);
    }
  }, timeout, CI.nsITimer.TYPE_ONE_SHOT);
};

/**
 * Wait until a condition is true before calling "callback". On error, call
 * ontimeout.
 *
 * @param {function():boolean} condition The condition to check.
 * @param {function():undefined} callback The callback to use when condition is
 *    true.
 * @param {number} timeout Time to wait in milliseconds.
 * @param {function():undefined} ontimeout Called if condition doesn't become
 *    true.
 */
Timer.prototype.runWhenTrue = function(condition, callback, timeout, ontimeout) {
  var remaining = timeout;
  var interval = 100;

  var timed = function () {
    if (remaining >= 0 && !condition()) {
      remaining -= interval;
      this.setTimeout(timed, interval);
    } else if (remaining <= 0) {
      ontimeout();
    } else {
      callback();
    }
  };
  timed();
};

// Required for Mozilla component importing
var EXPORTED_SYMBOLS = [ 'Timer' ];
<commit_msg>SimonStewart: Minor change to the timer<commit_after>/*
 Copyright 2010 WebDriver committers
 Copyright 2010 Google Inc.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/**
 * @fileoverview An implementation of a timer that can be used without an
 * assocuated window.
 */

var CC = Components.classes;
var CI = Components.interfaces;

/**
 * @constructor
 */
function Timer() { /* Empty */ }

/**
 * Set a callback to be executed after a specified time out. The default time
 * out is 10ms.
 *
 * @param {!function(*=): *} callback The callback to use.
 * @param {number=} opt_timeout An optional timeout to use.
 */
Timer.prototype.setTimeout = function(callback, opt_timeout) {
  var timeout = opt_timeout || 10;
  var timer = CC['@mozilla.org/timer;1'].createInstance(CI['nsITimer']);

  timer.initWithCallback({
    notify: function() {
      callback.apply(null);
    }
  }, timeout, CI.nsITimer.TYPE_ONE_SHOT);
};

/**
 * Wait until a condition is true before calling "callback". On error, call
 * ontimeout.
 *
 * @param {function():boolean} condition The condition to check.
 * @param {function():undefined} callback The callback to use when condition is
 *    true.
 * @param {number} timeout Time to wait in milliseconds.
 * @param {function():undefined} ontimeout Called if condition doesn't become
 *    true.
 */
Timer.prototype.runWhenTrue = function(condition, callback, timeout, ontimeout) {
  var remaining = timeout;
  var interval = 100;

  var timed = function () {
    if (remaining >= 0 && !condition()) {
      remaining -= interval;
      new Timer().setTimeout(timed, interval);
    } else if (remaining <= 0) {
      ontimeout();
    } else {
      callback();
    }
  };
  timed();
};

// Required for Mozilla component importing
var EXPORTED_SYMBOLS = [ 'Timer' ];
<|endoftext|>


<commit_before>'use strict'

/**
 * Provide Room-level Security
 */

class CityDefense extends kernel.process {
  constructor (...args) {
    super(...args)
    this.priority = PRIORITIES_DEFENSE

    // Pre-load all effect values.
    if (!global.TOWER_DAMAGE_EFFECT || !global.TOWER_REPAIR_EFFECT || !global.TOWER_HEAL_EFFECT) {
      global.TOWER_DAMAGE_EFFECT = []
      global.TOWER_REPAIR_EFFECT = []
      global.TOWER_HEAL_EFFECT = []

      for (let i = 0; i < 50; i++) {
        global.TOWER_DAMAGE_EFFECT[i] = this.calculateWithFallOff(TOWER_POWER_ATTACK, i)
        global.TOWER_REPAIR_EFFECT[i] = this.calculateWithFallOff(TOWER_POWER_REPAIR, i)
        global.TOWER_HEAL_EFFECT[i] = this.calculateWithFallOff(TOWER_POWER_HEAL, i)
      }
    }
  }

  getDescriptor () {
    return this.data.room
  }

  main () {
    if (!Game.rooms[this.data.room]) {
      return this.suicide()
    }

    const room = Game.rooms[this.data.room]

    const towers = sos.lib.cache.getOrUpdate(
        [this.data.room, 'towers'],
        () => room.find(FIND_MY_STRUCTURES, {
          filter: {
            structureType: STRUCTURE_TOWER
          }
        })
        .map(s => s.id), {
          persist: true,
          maxttl: 5000,
          chance: 0.001
        })
      .map(id => Game.getObjectById(id))
      .filter(t => t)

    const hostiles = room.find(FIND_HOSTILE_CREEPS)

    if (towers && towers.length > 0) {
      this.fireTowers(towers, hostiles)
    }

    if (towers && _.some(towers, tower => tower.energy < tower.energyCapacity)) {
      this.launchCreepProcess('loader', 'replenisher', this.data.room, 1)
    }

    const playerHostiles = hostiles.filter(c => c.owner.username !== 'Invader' && this.isPotentialHazard(c))

    if (playerHostiles.length > 0) {
      Logger.log(`Hostile creep owned by ${playerHostiles[0].owner.username} detected in room ${this.data.room}.`, LOG_WARN)
      qlib.notify.send(`Hostile creep owned by ${playerHostiles[0].owner.username} detected in room ${this.data.room}.`, 1000)
      this.safeMode(playerHostiles)
    }
  }

  fireTowers (towers, hostiles) {
    const attackFunc = (attackTarget) => {
      for (let tower of towers) {
        if (tower.energy < TOWER_ENERGY_COST) {
          continue
        }

        tower.attack(attackTarget)
      }
    }

    const healFunc = (healTarget) => {
      let damage = healTarget.hitsMax - healTarget.hits

      for (let tower of towers) {
        if (damage <= 0) {
          break
        }

        const distance = tower.pos.getRangeTo(healTarget.pos)
        damage -= global.TOWER_HEAL_EFFECT[distance]
        tower.heal(healTarget)
      }
    }

    if (hostiles.length > 0) {
      const closestHostile = _.min(hostiles, c => c.pos.getRangeTo(towers[0].pos))
      attackFunc(closestHostile)
      return
    }

    if (this.data.healTarget !== undefined) {
      const healTarget = Game.getObjectById(this.data.healTarget)
      if (healTarget &&
        (healTarget.pos.roomName === this.data.room) &&
        (healTarget.hits < healTarget.hitsMax)) {
        healFunc(healTarget)
        return
      }

      // heal target no longer valid
      delete this.data.healTarget
    }

    // look for a heal target every healFrequency ticks
    const healFrequency = 5
    if (this.period(healFrequency, 'healTargetSelection')) {
      const room = Game.rooms[this.data.room]
      const myCreeps = room.find(FIND_MY_CREEPS)
      const lowestCreep = _.min(myCreeps, c => c.hits / c.hitsMax)
      if (!_.isNumber(lowestCreep) &&
        (lowestCreep.hits < lowestCreep.hitsMax)) {
        this.data.healTarget = lowestCreep.id
        healFunc(lowestCreep)
      }
    }
  }

  safeMode (hostiles) {
    const room = Game.rooms[this.data.room]
    if (room.controller.safeMode && room.controller.safeMode > 0) {
      return true
    }
    if (room.controller.safeModeAvailable <= 0 || room.controller.safeModeCooldown || room.controller.upgradeBlocked) {
      return false
    }

    let safeStructures = room.find(FIND_MY_SPAWNS)
    safeStructures.push(room.controller)
    let structure
    for (structure of safeStructures) {
      const closest = structure.pos.findClosestByRange(hostiles)
      if (structure.pos.getRangeTo(closest) < 5) {
        // Trigger safemode
        Logger.log(`Activating safemode in ${this.data.room}`, LOG_ERROR)
        room.controller.activateSafeMode()
        return true
      }
    }
    return false
  }

  isPotentialHazard (hostile) {
    const hazardTypes = [ATTACK, RANGED_ATTACK, HEAL, WORK, CLAIM]
    return _.some(hostile.body, b => _.include(hazardTypes, b.type))
  }

  calculateWithFallOff (optimalValue, distance) {
    let effect = optimalValue
    if (distance > TOWER_OPTIMAL_RANGE) {
      if (distance > TOWER_FALLOFF_RANGE) {
        distance = TOWER_FALLOFF_RANGE
      }
      effect -= effect * TOWER_FALLOFF * (distance - TOWER_OPTIMAL_RANGE) / (TOWER_FALLOFF_RANGE - TOWER_OPTIMAL_RANGE)
    }
    return Math.floor(effect)
  }
}

module.exports = CityDefense
<commit_msg>Only log safe mode if it succeeds<commit_after>'use strict'

/**
 * Provide Room-level Security
 */

class CityDefense extends kernel.process {
  constructor (...args) {
    super(...args)
    this.priority = PRIORITIES_DEFENSE

    // Pre-load all effect values.
    if (!global.TOWER_DAMAGE_EFFECT || !global.TOWER_REPAIR_EFFECT || !global.TOWER_HEAL_EFFECT) {
      global.TOWER_DAMAGE_EFFECT = []
      global.TOWER_REPAIR_EFFECT = []
      global.TOWER_HEAL_EFFECT = []

      for (let i = 0; i < 50; i++) {
        global.TOWER_DAMAGE_EFFECT[i] = this.calculateWithFallOff(TOWER_POWER_ATTACK, i)
        global.TOWER_REPAIR_EFFECT[i] = this.calculateWithFallOff(TOWER_POWER_REPAIR, i)
        global.TOWER_HEAL_EFFECT[i] = this.calculateWithFallOff(TOWER_POWER_HEAL, i)
      }
    }
  }

  getDescriptor () {
    return this.data.room
  }

  main () {
    if (!Game.rooms[this.data.room]) {
      return this.suicide()
    }

    const room = Game.rooms[this.data.room]

    const towers = sos.lib.cache.getOrUpdate(
        [this.data.room, 'towers'],
        () => room.find(FIND_MY_STRUCTURES, {
          filter: {
            structureType: STRUCTURE_TOWER
          }
        })
        .map(s => s.id), {
          persist: true,
          maxttl: 5000,
          chance: 0.001
        })
      .map(id => Game.getObjectById(id))
      .filter(t => t)

    const hostiles = room.find(FIND_HOSTILE_CREEPS)

    if (towers && towers.length > 0) {
      this.fireTowers(towers, hostiles)
    }

    if (towers && _.some(towers, tower => tower.energy < tower.energyCapacity)) {
      this.launchCreepProcess('loader', 'replenisher', this.data.room, 1)
    }

    const playerHostiles = hostiles.filter(c => c.owner.username !== 'Invader' && this.isPotentialHazard(c))

    if (playerHostiles.length > 0) {
      Logger.log(`Hostile creep owned by ${playerHostiles[0].owner.username} detected in room ${this.data.room}.`, LOG_WARN)
      qlib.notify.send(`Hostile creep owned by ${playerHostiles[0].owner.username} detected in room ${this.data.room}.`, 1000)
      this.safeMode(playerHostiles)
    }
  }

  fireTowers (towers, hostiles) {
    const attackFunc = (attackTarget) => {
      for (let tower of towers) {
        if (tower.energy < TOWER_ENERGY_COST) {
          continue
        }

        tower.attack(attackTarget)
      }
    }

    const healFunc = (healTarget) => {
      let damage = healTarget.hitsMax - healTarget.hits

      for (let tower of towers) {
        if (damage <= 0) {
          break
        }

        const distance = tower.pos.getRangeTo(healTarget.pos)
        damage -= global.TOWER_HEAL_EFFECT[distance]
        tower.heal(healTarget)
      }
    }

    if (hostiles.length > 0) {
      const closestHostile = _.min(hostiles, c => c.pos.getRangeTo(towers[0].pos))
      attackFunc(closestHostile)
      return
    }

    if (this.data.healTarget !== undefined) {
      const healTarget = Game.getObjectById(this.data.healTarget)
      if (healTarget &&
        (healTarget.pos.roomName === this.data.room) &&
        (healTarget.hits < healTarget.hitsMax)) {
        healFunc(healTarget)
        return
      }

      // heal target no longer valid
      delete this.data.healTarget
    }

    // look for a heal target every healFrequency ticks
    const healFrequency = 5
    if (this.period(healFrequency, 'healTargetSelection')) {
      const room = Game.rooms[this.data.room]
      const myCreeps = room.find(FIND_MY_CREEPS)
      const lowestCreep = _.min(myCreeps, c => c.hits / c.hitsMax)
      if (!_.isNumber(lowestCreep) &&
        (lowestCreep.hits < lowestCreep.hitsMax)) {
        this.data.healTarget = lowestCreep.id
        healFunc(lowestCreep)
      }
    }
  }

  safeMode (hostiles) {
    const room = Game.rooms[this.data.room]
    if (room.controller.safeMode && room.controller.safeMode > 0) {
      return true
    }
    if (room.controller.safeModeAvailable <= 0 || room.controller.safeModeCooldown || room.controller.upgradeBlocked) {
      return false
    }

    let safeStructures = room.find(FIND_MY_SPAWNS)
    safeStructures.push(room.controller)
    let structure
    for (structure of safeStructures) {
      const closest = structure.pos.findClosestByRange(hostiles)
      if (structure.pos.getRangeTo(closest) < 5) {
        // Trigger safemode
        if (room.controller.activateSafeMode() === OK) {
          Logger.log(`Activating safemode in ${this.data.room}`, LOG_ERROR)
        }
        return true
      }
    }
    return false
  }

  isPotentialHazard (hostile) {
    const hazardTypes = [ATTACK, RANGED_ATTACK, HEAL, WORK, CLAIM]
    return _.some(hostile.body, b => _.include(hazardTypes, b.type))
  }

  calculateWithFallOff (optimalValue, distance) {
    let effect = optimalValue
    if (distance > TOWER_OPTIMAL_RANGE) {
      if (distance > TOWER_FALLOFF_RANGE) {
        distance = TOWER_FALLOFF_RANGE
      }
      effect -= effect * TOWER_FALLOFF * (distance - TOWER_OPTIMAL_RANGE) / (TOWER_FALLOFF_RANGE - TOWER_OPTIMAL_RANGE)
    }
    return Math.floor(effect)
  }
}

module.exports = CityDefense
<|endoftext|>


<commit_before>'use strict'

/**
 * Provide Room-level Security
 */

class CityDefense extends kernel.process {
  constructor (...args) {
    super(...args)
    this.priority = PRIORITIES_DEFENSE

    // Pre-load all effect values.
    if (!global.TOWER_DAMAGE_EFFECT || !global.TOWER_REPAIR_EFFECT || !global.TOWER_HEAL_EFFECT) {
      global.TOWER_DAMAGE_EFFECT = []
      global.TOWER_REPAIR_EFFECT = []
      global.TOWER_HEAL_EFFECT = []

      for (let i = 0; i < 50; i++) {
        global.TOWER_DAMAGE_EFFECT[i] = this.calculateWithFallOff(TOWER_POWER_ATTACK, i)
        global.TOWER_REPAIR_EFFECT[i] = this.calculateWithFallOff(TOWER_POWER_REPAIR, i)
        global.TOWER_HEAL_EFFECT[i] = this.calculateWithFallOff(TOWER_POWER_HEAL, i)
      }
    }
  }

  getDescriptor () {
    return this.data.room
  }

  main () {
    if (!Game.rooms[this.data.room]) {
      return this.suicide()
    }

    const room = Game.rooms[this.data.room]

    const towers = sos.lib.cache.getOrUpdate(
        [this.data.room, 'towers'],
        () => room.find(FIND_MY_STRUCTURES, {
          filter: {
            structureType: STRUCTURE_TOWER
          }
        })
        .map(s => s.id), {
          persist: true,
          maxttl: 5000,
          chance: 0.001
        })
      .map(id => Game.getObjectById(id))
      .filter(t => t)

    const hostiles = room.find(FIND_HOSTILE_CREEPS)

    if (towers && towers.length > 0) {
      this.fireTowers(towers, hostiles)
    }

    if (towers && _.some(towers, tower => tower.energy < tower.energyCapacity)) {
      this.launchCreepProcess('loader', 'replenisher', this.data.room, 1)
    }

    const playerHostiles = hostiles.filter(c => c.owner.username !== 'Invader' && this.isPotentialHazard(c))

    if (playerHostiles.length > 0) {
      Logger.log(`Hostile creep owned by ${playerHostiles[0].owner.username} detected in room ${this.data.room}.`, LOG_WARN)
      this.safeMode(playerHostiles)
    }
  }

  fireTowers (towers, hostiles) {
    const attackFunc = (attackTargets) => {
      let usableTowers = _.countBy(towers, (tower) => tower.energy < TOWER_ENERGY_COST)

      while(usableTowers > 0){
        const closest = _.min(attackTargets, c => c.pos.getRangeTo(towers[0].pos))

        if(!closest){
          break
        }

        let hitpoints = closest.hits

        for (let tower of towers) {
          if (tower.energy < TOWER_ENERGY_COST) {
            continue
          }

          if(usableTowers === 0 || hitpoints <= 0){
            break
          }

          const distance = tower.pos.getRangeTo(healTarget.pos)
          hitpoints -= global.TOWER_DAMAGE_EFFECT[distance]
          usableTowers -= 1

          tower.attack(closest)
        }
      }
    }

    const healFunc = (healTarget) => {
      let damage = healTarget.hitsMax - healTarget.hits

      for (let tower of towers) {
        if (damage <= 0) {
          break
        }

        const distance = tower.pos.getRangeTo(healTarget.pos)
        damage -= global.TOWER_HEAL_EFFECT[distance]
        tower.heal(healTarget)
      }
    }

    if (hostiles.length > 0) {
      attackFunc(hostiles)
      return
    }

    if (this.data.healTarget !== undefined) {
      const healTarget = Game.getObjectById(this.data.healTarget)
      if (healTarget &&
        (healTarget.pos.roomName === this.data.room) &&
        (healTarget.hits < healTarget.hitsMax)) {
        healFunc(healTarget)
        return
      }

      // heal target no longer valid
      delete this.data.healTarget
    }

    // look for a heal target every healFrequency ticks
    const healFrequency = 5
    if (this.period(healFrequency, 'healTargetSelection')) {
      const room = Game.rooms[this.data.room]
      const myCreeps = room.find(FIND_MY_CREEPS)
      const lowestCreep = _.min(myCreeps, c => c.hits / c.hitsMax)
      if (!_.isNumber(lowestCreep) &&
        (lowestCreep.hits < lowestCreep.hitsMax)) {
        this.data.healTarget = lowestCreep.id
        healFunc(lowestCreep)
      }
    }
  }

  safeMode (hostiles) {
    const room = Game.rooms[this.data.room]
    if (room.controller.safeMode && room.controller.safeMode > 0) {
      return true
    }
    if (room.controller.safeModeAvailable <= 0 || room.controller.safeModeCooldown || room.controller.upgradeBlocked) {
      return false
    }

    let safeStructures = room.find(FIND_MY_SPAWNS)
    safeStructures.push(room.controller)
    let structure
    for (structure of safeStructures) {
      const closest = structure.pos.findClosestByRange(hostiles)
      if (structure.pos.getRangeTo(closest) < 5) {
        // Trigger safemode
        Logger.log(`Activating safemode in ${this.data.room}`, LOG_ERROR)
        room.controller.activateSafeMode()
        return true
      }
    }
    return false
  }

  isPotentialHazard (hostile) {
    const hazardTypes = [ATTACK, RANGED_ATTACK, HEAL, WORK, CLAIM]
    return _.some(hostile.body, b => _.include(hazardTypes, b.type))
  }

  calculateWithFallOff (optimalValue, distance) {
    let factor = 0.0

    if (distance < TOWER_OPTIMAL_RANGE) {
      factor = 1
    } else if (distance >= TOWER_FALLOFF_RANGE) {
      factor = 1 - TOWER_FALLOFF
    } else {
      factor = 1 - (distance - TOWER_OPTIMAL_RANGE) * (TOWER_FALLOFF / (TOWER_FALLOFF_RANGE - TOWER_OPTIMAL_RANGE))
    }

    return Math.round(optimalValue * factor)
  }
}

module.exports = CityDefense
<commit_msg>Few style fixes and a copy paste error.<commit_after>'use strict'

/**
 * Provide Room-level Security
 */

class CityDefense extends kernel.process {
  constructor (...args) {
    super(...args)
    this.priority = PRIORITIES_DEFENSE

    // Pre-load all effect values.
    if (!global.TOWER_DAMAGE_EFFECT || !global.TOWER_REPAIR_EFFECT || !global.TOWER_HEAL_EFFECT) {
      global.TOWER_DAMAGE_EFFECT = []
      global.TOWER_REPAIR_EFFECT = []
      global.TOWER_HEAL_EFFECT = []

      for (let i = 0; i < 50; i++) {
        global.TOWER_DAMAGE_EFFECT[i] = this.calculateWithFallOff(TOWER_POWER_ATTACK, i)
        global.TOWER_REPAIR_EFFECT[i] = this.calculateWithFallOff(TOWER_POWER_REPAIR, i)
        global.TOWER_HEAL_EFFECT[i] = this.calculateWithFallOff(TOWER_POWER_HEAL, i)
      }
    }
  }

  getDescriptor () {
    return this.data.room
  }

  main () {
    if (!Game.rooms[this.data.room]) {
      return this.suicide()
    }

    const room = Game.rooms[this.data.room]

    const towers = sos.lib.cache.getOrUpdate(
        [this.data.room, 'towers'],
        () => room.find(FIND_MY_STRUCTURES, {
          filter: {
            structureType: STRUCTURE_TOWER
          }
        })
        .map(s => s.id), {
          persist: true,
          maxttl: 5000,
          chance: 0.001
        })
      .map(id => Game.getObjectById(id))
      .filter(t => t)

    const hostiles = room.find(FIND_HOSTILE_CREEPS)

    if (towers && towers.length > 0) {
      this.fireTowers(towers, hostiles)
    }

    if (towers && _.some(towers, tower => tower.energy < tower.energyCapacity)) {
      this.launchCreepProcess('loader', 'replenisher', this.data.room, 1)
    }

    const playerHostiles = hostiles.filter(c => c.owner.username !== 'Invader' && this.isPotentialHazard(c))

    if (playerHostiles.length > 0) {
      Logger.log(`Hostile creep owned by ${playerHostiles[0].owner.username} detected in room ${this.data.room}.`, LOG_WARN)
      this.safeMode(playerHostiles)
    }
  }

  fireTowers (towers, hostiles) {
    const attackFunc = (attackTargets) => {
      let usableTowers = _.countBy(towers, (tower) => tower.energy < TOWER_ENERGY_COST)

      while (usableTowers > 0) {
        const closest = _.min(attackTargets, c => c.pos.getRangeTo(towers[0].pos))

        if (!closest) {
          break
        }

        let hitpoints = closest.hits

        for (let tower of towers) {
          if (tower.energy < TOWER_ENERGY_COST) {
            continue
          }

          if (usableTowers === 0 || hitpoints <= 0) {
            break
          }

          const distance = tower.pos.getRangeTo(closest.pos)
          hitpoints -= global.TOWER_DAMAGE_EFFECT[distance]
          usableTowers -= 1

          tower.attack(closest)
        }
      }
    }

    const healFunc = (healTarget) => {
      let damage = healTarget.hitsMax - healTarget.hits

      for (let tower of towers) {
        if (damage <= 0) {
          break
        }

        const distance = tower.pos.getRangeTo(healTarget.pos)
        damage -= global.TOWER_HEAL_EFFECT[distance]
        tower.heal(healTarget)
      }
    }

    if (hostiles.length > 0) {
      attackFunc(hostiles)
      return
    }

    if (this.data.healTarget !== undefined) {
      const healTarget = Game.getObjectById(this.data.healTarget)
      if (healTarget &&
        (healTarget.pos.roomName === this.data.room) &&
        (healTarget.hits < healTarget.hitsMax)) {
        healFunc(healTarget)
        return
      }

      // heal target no longer valid
      delete this.data.healTarget
    }

    // look for a heal target every healFrequency ticks
    const healFrequency = 5
    if (this.period(healFrequency, 'healTargetSelection')) {
      const room = Game.rooms[this.data.room]
      const myCreeps = room.find(FIND_MY_CREEPS)
      const lowestCreep = _.min(myCreeps, c => c.hits / c.hitsMax)
      if (!_.isNumber(lowestCreep) &&
        (lowestCreep.hits < lowestCreep.hitsMax)) {
        this.data.healTarget = lowestCreep.id
        healFunc(lowestCreep)
      }
    }
  }

  safeMode (hostiles) {
    const room = Game.rooms[this.data.room]
    if (room.controller.safeMode && room.controller.safeMode > 0) {
      return true
    }
    if (room.controller.safeModeAvailable <= 0 || room.controller.safeModeCooldown || room.controller.upgradeBlocked) {
      return false
    }

    let safeStructures = room.find(FIND_MY_SPAWNS)
    safeStructures.push(room.controller)
    let structure
    for (structure of safeStructures) {
      const closest = structure.pos.findClosestByRange(hostiles)
      if (structure.pos.getRangeTo(closest) < 5) {
        // Trigger safemode
        Logger.log(`Activating safemode in ${this.data.room}`, LOG_ERROR)
        room.controller.activateSafeMode()
        return true
      }
    }
    return false
  }

  isPotentialHazard (hostile) {
    const hazardTypes = [ATTACK, RANGED_ATTACK, HEAL, WORK, CLAIM]
    return _.some(hostile.body, b => _.include(hazardTypes, b.type))
  }

  calculateWithFallOff (optimalValue, distance) {
    let factor = 0.0

    if (distance < TOWER_OPTIMAL_RANGE) {
      factor = 1
    } else if (distance >= TOWER_FALLOFF_RANGE) {
      factor = 1 - TOWER_FALLOFF
    } else {
      factor = 1 - (distance - TOWER_OPTIMAL_RANGE) * (TOWER_FALLOFF / (TOWER_FALLOFF_RANGE - TOWER_OPTIMAL_RANGE))
    }

    return Math.round(optimalValue * factor)
  }
}

module.exports = CityDefense
<|endoftext|>


<commit_before>/**
 * Turn first character into uppercase
 * @param str
 * @returns {string}
 */
export const ucfirst = str => {
    str += "";
    let f = str.charAt(0).toUpperCase();
    return f + str.substr(1);
};

/**
 * Checks is a variable is an array
 * @param a
 * @returns {boolean}
 */
export const isArray = a => {
    return !!a && a.constructor === Array;
};

/**
 * Checks is a variable is an object
 * @param a
 * @returns {boolean}
 */
export const isObject = a => {
    return !!a && a.constructor === Object;
};

/**
 * Returns first key of Object list to get type
 * @param object
 */
export const getObjectType = object => {
    return Object.keys(object)[0];
};

// list of keys which should be anonymized
export const anonymizeKeys = [
    "card_authorisation_id_response",
    "public_nick_name",
    "display_name",
    "second_line",
    "description",
    "country",
    "api_key",
    "session_id",
    "uuid",
    "iban"
];
// list of special handlers, used to keep certain formatting or values
export const anonymizedHandlers = {
    value: val => {
        return parseFloat(val) < 0 ? "-1.00" : "1.00";
    },
    address_billing: val => {
        if (!val) return val;
        return {
            emptied: "address"
        };
    },
    address_shipping: val => {
        if (!val) return val;
        return {
            emptied: "address"
        };
    },
    radius: val => 1.1,
    latitude: val => 1.1,
    longitude: val => 1.1,
    altitude: val => 1.1
};
export const anonymizedHandlerKeys = Object.keys(anonymizedHandlers);

/**
 * Goes through object and removes possibly personal info
 * @param object
 * @returns {*}
 */
export const anonymizeObject = (object, key = false) => {
    // this could be an item itself
    if (key) {
        if (anonymizeKeys.includes(key)) {
            // just return the same string value
            return "Anonymized value";
        }
        if (anonymizedHandlerKeys.includes(key)) {
            // run the special function to handle this item
            return anonymizedHandlers[key](object);
        }
    }

    // check if this item is an object or an array
    if (isObject(object)) {
        let noRefObject = { ...object };
        // go through all keys
        Object.keys(noRefObject).forEach(objectKey => {
            const objectItem = noRefObject[objectKey];
            // anonymize this item and re-set it
            noRefObject[objectKey] = anonymizeObject(objectItem, objectKey);
        });

        return noRefObject;
    } else if (isArray(object)) {
        let noRefArray = [...object];
        // go through all keys
        noRefArray.forEach((objectItem, key) => {
            // anonymize this item and re-set it
            noRefArray[key] = anonymizeObject(objectItem);
        });

        return noRefArray;
    }

    return object;
};

/**
 * returns a , or . depending on localized result
 */
export const { preferedThousandSeparator, preferedDecimalSeparator } = (() => {
    return {
        preferedThousandSeparator: (10000).toLocaleString().substring(2, 3),
        preferedDecimalSeparator: (1.1).toLocaleString().substring(1, 2)
    };
})();

/**
 * Parses strings as float and returns a correct localized format
 * @param value
 * @param stayNegative
 * @returns {string}
 */
export const formatMoney = (value, stayNegative = false) => {
    let parsedValue = parseFloat(value);
    parsedValue = parsedValue < 0 && stayNegative === false ? parsedValue * -1 : parsedValue;

    const localeType = window.BUNQDESKTOP_LANGUAGE_SETTING || "nl";

    return parsedValue.toLocaleString(localeType, {
        currency: "EUR",
        style: "currency",
        currencyDisplay: "symbol",
        minimumFractionDigits: 2,
        maximumFractionDigits: 2
    });
};

/**
 * validates json input by checking for thrown error
 * @param input
 * @returns {boolean}
 */
export const validateJSON = input => {
    if (typeof input === "object") {
        return true;
    }
    try {
        JSON.parse(input);
    } catch (ex) {
        return false;
    }
    return true;
};

/**
 * Turns language key into pretty human-readable text
 * @param key
 * @returns {*}
 */
export const getPrettyLanguage = key => {
    switch (key) {
        case "en":
            return "English";
        case "nl":
            return "Nederlands";
        case "de":
            return "Deutsch";
        case "es":
            return "Español (Needs work)";
        case "it":
            return "Italiano (Needs work)";
        case "gr":
            return "Greek (Needs work)";
    }
    return key;
};

/**
 * Turns date into a UTC timezone date
 * @param dateString
 * @returns {Date}
 */
export const getUTCDate = dateString => {
    const date = new Date(dateString);

    return new Date(
        date.getUTCFullYear(),
        date.getUTCMonth(),
        date.getUTCDate(),
        date.getUTCHours(),
        date.getUTCMinutes(),
        date.getUTCSeconds()
    );
};

/**
 * transforms a date into a date object in current timezone
 * @param date
 * @returns {Date}
 * @constructor
 */
export const UTCDateToLocalDate = date => {
    const utcDate = new Date(date);

    // get the timezoneOffset
    const timezoneOffset = utcDate.getTimezoneOffset();

    // return a new date with the correct timezone offset
    return new Date(utcDate.setMinutes(utcDate.getMinutes() - timezoneOffset));
};

/**
 * human readable date using locales
 * @param date
 * @param displayHoursMins
 * @param localization
 * @returns {string}
 */
export const humanReadableDate = (date, displayHoursMins = true, localization = "nl") => {
    const currentDate = new Date();
    const createDate = UTCDateToLocalDate(date);

    const localeType = window.BUNQDESKTOP_LANGUAGE_SETTING || localization;

    const month = createDate.toLocaleString(localeType, { month: "long" });

    // hide hours:minutes:seconds if disabled
    const hoursMinutes = displayHoursMins ? createDate.toLocaleTimeString(localeType) : "";

    // different year, add it to the label
    if (currentDate.getFullYear() !== createDate.getFullYear()) {
        return `${createDate.getDate()} ${month}, ${createDate.getFullYear()} ${hoursMinutes}`;
    }
    // only date/month and time
    return `${createDate.getDate()} ${month} ${hoursMinutes}`;
};

export const getCardDescription = card => {
    let second_line = card.second_line;
    console.log(card, second_line);
    const primaryNumbers = card.primary_account_numbers;
    if (primaryNumbers && primaryNumbers.length > 0) {
        // if no status is set or status is ACTIVE use alternative second line
        const firstActivePrimaryNumber = primaryNumbers.find(primaryNumber => {
            if (!primaryNumber.status) return true;
            return primaryNumber.status === "ACTIVE";
        });

        if (firstActivePrimaryNumber) {
            second_line = firstActivePrimaryNumber.description;
        }
    } else if (second_line.length === 0 && card.type === "MAESTRO_MOBILE_NFC") {
        second_line = "Apple Pay";
    }

    console.log(card, second_line);
    console.log("");

    return second_line || card.type;
};

/**
 * Adds space every fourth character for IBAN numbers
 * @param iban
 * @returns {string}
 */
export const formatIban = iban => {
    if (!iban) return "";
    const ret = [];

    let len;
    for (let i = 0, len = iban.length; i < len; i += 4) {
        ret.push(iban.substr(i, 4));
    }

    return ret.join(" ");
};

/**
 * Used to create basic random identifiers
 * @returns {string}
 */
export const generateGUID = () => {
    function s4() {
        return Math.floor((1 + Math.random()) * 0x10000)
            .toString(16)
            .substring(1);
    }
    return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4();
};
<commit_msg><commit_after>/**
 * Turn first character into uppercase
 * @param str
 * @returns {string}
 */
export const ucfirst = str => {
    str += "";
    let f = str.charAt(0).toUpperCase();
    return f + str.substr(1);
};

/**
 * Checks is a variable is an array
 * @param a
 * @returns {boolean}
 */
export const isArray = a => {
    return !!a && a.constructor === Array;
};

/**
 * Checks is a variable is an object
 * @param a
 * @returns {boolean}
 */
export const isObject = a => {
    return !!a && a.constructor === Object;
};

/**
 * Returns first key of Object list to get type
 * @param object
 */
export const getObjectType = object => {
    return Object.keys(object)[0];
};

// list of keys which should be anonymized
export const anonymizeKeys = [
    "card_authorisation_id_response",
    "public_nick_name",
    "display_name",
    "second_line",
    "description",
    "country",
    "api_key",
    "session_id",
    "uuid",
    "iban"
];
// list of special handlers, used to keep certain formatting or values
export const anonymizedHandlers = {
    value: val => {
        return parseFloat(val) < 0 ? "-1.00" : "1.00";
    },
    address_billing: val => {
        if (!val) return val;
        return {
            emptied: "address"
        };
    },
    address_shipping: val => {
        if (!val) return val;
        return {
            emptied: "address"
        };
    },
    radius: val => 1.1,
    latitude: val => 1.1,
    longitude: val => 1.1,
    altitude: val => 1.1
};
export const anonymizedHandlerKeys = Object.keys(anonymizedHandlers);

/**
 * Goes through object and removes possibly personal info
 * @param object
 * @returns {*}
 */
export const anonymizeObject = (object, key = false) => {
    // this could be an item itself
    if (key) {
        if (anonymizeKeys.includes(key)) {
            // just return the same string value
            return "Anonymized value";
        }
        if (anonymizedHandlerKeys.includes(key)) {
            // run the special function to handle this item
            return anonymizedHandlers[key](object);
        }
    }

    // check if this item is an object or an array
    if (isObject(object)) {
        let noRefObject = { ...object };
        // go through all keys
        Object.keys(noRefObject).forEach(objectKey => {
            const objectItem = noRefObject[objectKey];
            // anonymize this item and re-set it
            noRefObject[objectKey] = anonymizeObject(objectItem, objectKey);
        });

        return noRefObject;
    } else if (isArray(object)) {
        let noRefArray = [...object];
        // go through all keys
        noRefArray.forEach((objectItem, key) => {
            // anonymize this item and re-set it
            noRefArray[key] = anonymizeObject(objectItem);
        });

        return noRefArray;
    }

    return object;
};

/**
 * returns a , or . depending on localized result
 */
export const { preferedThousandSeparator, preferedDecimalSeparator } = (() => {
    return {
        preferedThousandSeparator: (10000).toLocaleString().substring(2, 3),
        preferedDecimalSeparator: (1.1).toLocaleString().substring(1, 2)
    };
})();

/**
 * Parses strings as float and returns a correct localized format
 * @param value
 * @param stayNegative
 * @returns {string}
 */
export const formatMoney = (value, stayNegative = false) => {
    let parsedValue = parseFloat(value);
    parsedValue = parsedValue < 0 && stayNegative === false ? parsedValue * -1 : parsedValue;

    const localeType = window.BUNQDESKTOP_LANGUAGE_SETTING || "nl";

    return parsedValue.toLocaleString(localeType, {
        currency: "EUR",
        style: "currency",
        currencyDisplay: "symbol",
        minimumFractionDigits: 2,
        maximumFractionDigits: 2
    });
};

/**
 * validates json input by checking for thrown error
 * @param input
 * @returns {boolean}
 */
export const validateJSON = input => {
    if (typeof input === "object") {
        return true;
    }
    try {
        JSON.parse(input);
    } catch (ex) {
        return false;
    }
    return true;
};

/**
 * Turns language key into pretty human-readable text
 * @param key
 * @returns {*}
 */
export const getPrettyLanguage = key => {
    switch (key) {
        case "en":
            return "English";
        case "nl":
            return "Nederlands";
        case "de":
            return "Deutsch";
        case "es":
            return "Español (Needs work)";
        case "it":
            return "Italiano (Needs work)";
        case "gr":
            return "Greek (Needs work)";
    }
    return key;
};

/**
 * Turns date into a UTC timezone date
 * @param dateString
 * @returns {Date}
 */
export const getUTCDate = dateString => {
    const date = new Date(dateString);

    return new Date(
        date.getUTCFullYear(),
        date.getUTCMonth(),
        date.getUTCDate(),
        date.getUTCHours(),
        date.getUTCMinutes(),
        date.getUTCSeconds()
    );
};

/**
 * transforms a date into a date object in current timezone
 * @param date
 * @returns {Date}
 * @constructor
 */
export const UTCDateToLocalDate = date => {
    const utcDate = new Date(date);

    // get the timezoneOffset
    const timezoneOffset = utcDate.getTimezoneOffset();

    // return a new date with the correct timezone offset
    return new Date(utcDate.setMinutes(utcDate.getMinutes() - timezoneOffset));
};

/**
 * human readable date using locales
 * @param date
 * @param displayHoursMins
 * @param localization
 * @returns {string}
 */
export const humanReadableDate = (date, displayHoursMins = true, localization = "nl") => {
    const currentDate = new Date();
    const createDate = UTCDateToLocalDate(date);

    const localeType = window.BUNQDESKTOP_LANGUAGE_SETTING || localization;

    const month = createDate.toLocaleString(localeType, { month: "long" });

    // hide hours:minutes:seconds if disabled
    const hoursMinutes = displayHoursMins ? createDate.toLocaleTimeString(localeType) : "";

    // different year, add it to the label
    if (currentDate.getFullYear() !== createDate.getFullYear()) {
        return `${createDate.getDate()} ${month}, ${createDate.getFullYear()} ${hoursMinutes}`;
    }
    // only date/month and time
    return `${createDate.getDate()} ${month} ${hoursMinutes}`;
};

export const getCardDescription = card => {
    let second_line = card.second_line;

    const primaryNumbers = card.primary_account_numbers;
    if (primaryNumbers && primaryNumbers.length > 0) {
        // if no status is set or status is ACTIVE use alternative second line
        const firstActivePrimaryNumber = primaryNumbers.find(primaryNumber => {
            if (!primaryNumber.status) return true;
            return primaryNumber.status === "ACTIVE";
        });

        if (firstActivePrimaryNumber) {
            second_line = firstActivePrimaryNumber.description;
        }
    } else if (second_line.length === 0 && card.type === "MAESTRO_MOBILE_NFC") {
        second_line = "Apple Pay";
    }

    return second_line || card.type;
};

/**
 * Adds space every fourth character for IBAN numbers
 * @param iban
 * @returns {string}
 */
export const formatIban = iban => {
    if (!iban) return "";
    const ret = [];

    let len;
    for (let i = 0, len = iban.length; i < len; i += 4) {
        ret.push(iban.substr(i, 4));
    }

    return ret.join(" ");
};

/**
 * Used to create basic random identifiers
 * @returns {string}
 */
export const generateGUID = () => {
    function s4() {
        return Math.floor((1 + Math.random()) * 0x10000)
            .toString(16)
            .substring(1);
    }
    return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4();
};
<|endoftext|>


<commit_before>import { get } from 'lodash/fp'
import { includes, map, toPairs } from 'lodash'
import qs from 'querystring'
import { appendUniq } from './util'

import {
  CREATE_POST,
  CLEAR_CACHE,
  FETCH_POSTS
} from '../actions'

const matchesCommunity = (key, post, tags) => {
  const communityIds = post.communities.map(c => c.slug).concat(post.communities.map(c => c.id))
  return key.subject === 'community' &&
    (includes(communityIds, key.id) || key.id === 'all') &&
    (!key.tag || includes([post.tag].concat(tags), key.tag))
}

export default function (state = {}, action) {
  if (action.error) return state

  let { type, payload, meta } = action
  switch (type) {
    case FETCH_POSTS:
      return appendUniq(state, meta.cache.id, map(payload.posts, 'id'))
    case CREATE_POST:
      let post = payload

      // find all lists that should contain this post id, and prepend it to each
      // of them
      let updatedPostLists = toPairs(state).reduce((changedLists, [id, postIds]) => {
        let key = qs.parse(id)
        let tags = get('tags', meta) || []

        if ((key.subject === 'person' && key.id === post.user.id) ||
          key.subject === 'all-posts' ||
          matchesCommunity(key, post, tags)) {
          changedLists[id] = [post.id, ...postIds]
        }

        return changedLists
      }, {})
      return {...state, ...updatedPostLists}
    case CLEAR_CACHE:
      if (payload.bucket === 'postsByQuery') {
        return {...state, [payload.id]: null}
      }
      break
  }

  return state
}
<commit_msg>add new thread to dropdown list<commit_after>import { get } from 'lodash/fp'
import { includes, map, toPairs } from 'lodash'
import qs from 'querystring'
import { appendUniq } from './util'

import {
  CREATE_POST,
  CLEAR_CACHE,
  FETCH_POSTS,
  FIND_OR_CREATE_THREAD
} from '../actions'

const matchesCommunity = (key, post, tags) => {
  const communityIds = post.communities.map(c => c.slug).concat(post.communities.map(c => c.id))
  return key.subject === 'community' &&
    (includes(communityIds, key.id) || key.id === 'all') &&
    (!key.tag || includes([post.tag].concat(tags), key.tag))
}

export default function (state = {}, action) {
  if (action.error) return state

  let { type, payload, meta } = action
  switch (type) {
    case FETCH_POSTS:
      return appendUniq(state, meta.cache.id, map(payload.posts, 'id'))
    case CREATE_POST:
      let post = payload

      // find all lists that should contain this post id, and prepend it to each
      // of them
      let updatedPostLists = toPairs(state).reduce((changedLists, [id, postIds]) => {
        let key = qs.parse(id)
        let tags = get('tags', meta) || []

        if ((key.subject === 'person' && key.id === post.user.id) ||
          key.subject === 'all-posts' ||
          matchesCommunity(key, post, tags)) {
          changedLists[id] = [post.id, ...postIds]
        }

        return changedLists
      }, {})
      return {...state, ...updatedPostLists}
    case CLEAR_CACHE:
      if (payload.bucket === 'postsByQuery') {
        return {...state, [payload.id]: null}
      }
      break
    case FIND_OR_CREATE_THREAD:
      return {
        ...state,
        threads: [payload.id, ...(state.threads || [])]
      }
  }

  return state
}
<|endoftext|>


<commit_before>/* @flow */
import type { Action } from '../../actions/types'

export type UserProfileState = {
  displayName: string,
  photoURL: ?string
}

const initialState = {
  displayName: 'anonymous',
  photoURL: '/img/default.png'
}

export default function reducer (state: UserProfileState = initialState, action: Action) {
  switch (action.type) {
    case 'UPDATE_USER_PROFILE':
    case 'HYDRATE_USER_PROFILE':
      return { ...state, ...action.user }
    default:
      return state
  }
}
<commit_msg>Remove default user avatar image<commit_after>/* @flow */
import type { Action } from '../../actions/types'

export type UserProfileState = {
  displayName: string,
  photoURL: ?string
}

const initialState = {
  displayName: 'anonymous',
  photoURL: ''
}

export default function reducer (state: UserProfileState = initialState, action: Action) {
  switch (action.type) {
    case 'UPDATE_USER_PROFILE':
    case 'HYDRATE_USER_PROFILE':
      return { ...state, ...action.user }
    default:
      return state
  }
}
<|endoftext|>


<commit_before>/*
 * MelonJS Game Engine
 * Copyright (C) 2011 - 2017, Olivier Biot, Jason Oster, Aaron McLeod
 * http://www.melonjs.org
 *
 */
(function () {

    /**
     * a generic Image Layer Object
     * @class
     * @extends me.Renderable
     * @memberOf me
     * @constructor
     * @param {Number} x x coordinate
     * @param {Number} y y coordinate
     * @param {Object} settings ImageLayer properties
     * @param {Image|String} settings.image Image reference. See {@link me.loader.getImage}
     * @param {String} [settings.name="me.ImageLayer"] Layer name
     * @param {Number} [settings.z=0] z-index position
     * @param {Number|me.Vector2d} [settings.ratio=1.0] Scrolling ratio to be applied
     * @param {Number|me.Vector2d} [settings.anchorPoint=0.0] Image origin. See {@link me.ImageLayer#anchorPoint}
     */
    me.ImageLayer = me.Renderable.extend({
        /**
         * constructor
         * @ignore
         */
        init: function (x, y, settings) {
            // layer name
            this.name = settings.name || "me.ImageLayer";

            // get the corresponding image
            this.image = me.utils.getImage(settings.image);

            // XXX: Keep this check?
            if (!this.image) {
                throw new me.Error((
                    (typeof(settings.image) === "string") ?
                    "'" + settings.image + "'" :
                    "Image"
                ) + " file for Image Layer '" + this.name + "' not found!");
            }

            this.imagewidth = this.image.width;
            this.imageheight = this.image.height;

            // call the constructor
            this._super(me.Renderable, "init", [x, y, Infinity, Infinity]);

            // render in screen coordinates
            this.floating = true;

            // displaying order
            this.pos.z = settings.z || 0;

            this.offset = new me.Vector2d(x, y);

            /**
             * Define the image scrolling ratio

             * Scrolling speed is defined by multiplying the viewport delta position (e.g. followed entity) by the specified ratio.
             * Setting this vector to <0.0,0.0> will disable automatic scrolling.

             * To specify a value through Tiled, use one of the following format :

             * - a number, to change the value for both axis

             * - a json expression like `json:{"x":0.5,"y":0.5}` if you wish to specify a different value for both x and y
             * @public
             * @type me.Vector2d
             * @default <1.0,1.0>
             * @name me.ImageLayer#ratio
             */
            this.ratio = new me.Vector2d(1.0, 1.0);

            if (typeof(settings.ratio) !== "undefined") {
                // little hack for backward compatiblity
                if (typeof(settings.ratio) === "number") {
                    this.ratio.set(settings.ratio, settings.ratio);
                } else /* vector */ {
                    this.ratio.setV(settings.ratio);
                }
            }

            if (typeof(settings.anchorPoint) === "undefined") {
                /**
                 * Define how the image is anchored to the viewport bounds

                 * By default, its upper-left corner is anchored to the viewport bounds upper left corner.

                 * The anchorPoint is a unit vector where each component falls in range [0.0,1.0].

                 * Some common examples:

                 * * <0.0,0.0> : (Default) Anchor image to the upper-left corner of viewport bounds
                 * * <0.5,0.5> : Center the image within viewport bounds
                 * * <1.0,1.0> : Anchor image to the lower-right corner of viewport bounds
                 * To specify a value through Tiled, use one of the following format :

                 * - a number, to change the value for both axis

                 * - a json expression like `json:{"x":0.5,"y":0.5}` if you wish to specify a different value for both x and y
                 * @public
                 * @type me.Vector2d
                 * @default <0.0,0.0>
                 * @name me.ImageLayer#anchorPoint
                 */
                this.anchorPoint.set(0, 0);
            }
            else {
                if (typeof(settings.anchorPoint) === "number") {
                    this.anchorPoint.set(settings.anchorPoint, settings.anchorPoint);
                }
                else /* vector */ {
                    this.anchorPoint.setV(settings.anchorPoint);
                }
            }

            /**
             * Define if and how an Image Layer should be repeated.

             * By default, an Image Layer is repeated both vertically and horizontally.

             * Acceptable values :

             * * 'repeat' - The background image will be repeated both vertically and horizontally. (default)

             * * 'repeat-x' - The background image will be repeated only horizontally.

             * * 'repeat-y' - The background image will be repeated only vertically.

             * * 'no-repeat' - The background-image will not be repeated.

             * @public
             * @type String
             * @name me.ImageLayer#repeat
             */
            Object.defineProperty(this, "repeat", {
                /**
                 * @ignore
                 */
                get : function get() {
                    return this._repeat;
                },
                /**
                 * @ignore
                 */
                set : function set(val) {
                    this._repeat = val;
                    switch (this._repeat) {
                        case "no-repeat" :
                            this.repeatX = false;
                            this.repeatY = false;
                            break;
                        case "repeat-x" :
                            this.repeatX = true;
                            this.repeatY = false;
                            break;
                        case "repeat-y" :
                            this.repeatX = false;
                            this.repeatY = true;
                            break;
                        default : // "repeat"
                            this.repeatX = true;
                            this.repeatY = true;
                            break;
                    }
                    this.resize(me.game.viewport.width, me.game.viewport.height);
                    this.createPattern();
                }
            });

            this.repeat = settings.repeat || "repeat";
        },

        // called when the layer is added to the game world or a container
        onActivateEvent : function () {
            var _updateLayerFn = this.updateLayer.bind(this);
            // register to the viewport change notification
            this.vpChangeHdlr = me.event.subscribe(me.event.VIEWPORT_ONCHANGE, _updateLayerFn);
            this.vpResizeHdlr = me.event.subscribe(me.event.VIEWPORT_ONRESIZE, this.resize.bind(this));
            this.vpLoadedHdlr = me.event.subscribe(me.event.LEVEL_LOADED, function() {
                // force a first refresh when the level is loaded
                _updateLayerFn(me.game.viewport.pos);
            });
            // in case the level is not added to the root container,
            // the onActivateEvent call happens after the LEVEL_LOADED event
            // so we need to force a first update
            if (this.ancestor._root !== true) {
                this.updateLayer(me.game.viewport.pos);
            }
        },

        /**
         * resize the Image Layer to match the given size
         * @name resize
         * @memberOf me.ImageLayer
         * @function
         * @param {Number} w new width
         * @param {Number} h new height
        */
        resize : function (w, h) {
            this._super(me.Renderable, "resize", [
                this.repeatX ? Infinity : w,
                this.repeatY ? Infinity : h
            ]);
        },

        /**
         * createPattern function
         * @ignore
         * @function
         */
        createPattern : function () {
            this._pattern = me.video.renderer.createPattern(this.image, this._repeat);
        },

        /**
         * updateLayer function
         * @ignore
         * @function
         */
        updateLayer : function (vpos) {
            var rx = this.ratio.x,
                ry = this.ratio.y;

            if (rx === ry === 0) {
                // static image
                return;
            }

            var viewport = me.game.viewport,
                width = this.imagewidth,
                height = this.imageheight,
                bw = viewport.bounds.width,
                bh = viewport.bounds.height,
                ax = this.anchorPoint.x,
                ay = this.anchorPoint.y,

                /*
                 * Automatic positioning
                 *
                 * See https://github.com/melonjs/melonJS/issues/741#issuecomment-138431532
                 * for a thorough description of how this works.
                 */
                x = ax * (rx - 1) * (bw - viewport.width) + this.offset.x - rx * vpos.x,
                y = ay * (ry - 1) * (bh - viewport.height) + this.offset.y - ry * vpos.y;

            // Repeat horizontally; start drawing from left boundary
            if (this.repeatX) {
                this.pos.x = x % width;
            }
            else {
                this.pos.x = x;
            }

            // Repeat vertically; start drawing from top boundary
            if (this.repeatY) {
                this.pos.y = y % height;
            }
            else {
                this.pos.y = y;
            }
        },

        /**
         * draw the image layer
         * @ignore
         */
        draw : function (renderer) {
            var viewport = me.game.viewport,
                width = this.imagewidth,
                height = this.imageheight,
                bw = viewport.bounds.width,
                bh = viewport.bounds.height,
                ax = this.anchorPoint.x,
                ay = this.anchorPoint.y,
                x = this.pos.x,
                y = this.pos.y;

            if (this.ratio.x === this.ratio.y === 0) {
                x = x + ax * (bw - width);
                y = y + ay * (bh - height);
            }

            renderer.translate(x, y);
            renderer.drawPattern(
                this._pattern,
                0,
                0,
                viewport.width * 2,
                viewport.height * 2
            );
            renderer.translate(-x, -y);
        },

        // called when the layer is removed from the game world or a container
        onDeactivateEvent : function () {
            // cancel all event subscriptions
            me.event.unsubscribe(this.vpChangeHdlr);
            me.event.unsubscribe(this.vpResizeHdlr);
            me.event.unsubscribe(this.vpLoadedHdlr);
        }

    });
})();
<commit_msg>[#854] fix a regression with ImageLayer<commit_after>/*
 * MelonJS Game Engine
 * Copyright (C) 2011 - 2017, Olivier Biot, Jason Oster, Aaron McLeod
 * http://www.melonjs.org
 *
 */
(function () {

    /**
     * a generic Image Layer Object
     * @class
     * @extends me.Renderable
     * @memberOf me
     * @constructor
     * @param {Number} x x coordinate
     * @param {Number} y y coordinate
     * @param {Object} settings ImageLayer properties
     * @param {Image|String} settings.image Image reference. See {@link me.loader.getImage}
     * @param {String} [settings.name="me.ImageLayer"] Layer name
     * @param {Number} [settings.z=0] z-index position
     * @param {Number|me.Vector2d} [settings.ratio=1.0] Scrolling ratio to be applied
     * @param {Number|me.Vector2d} [settings.anchorPoint=0.0] Image origin. See {@link me.ImageLayer#anchorPoint}
     */
    me.ImageLayer = me.Renderable.extend({
        /**
         * constructor
         * @ignore
         */
        init: function (x, y, settings) {
            // layer name
            this.name = settings.name || "me.ImageLayer";

            // get the corresponding image
            this.image = me.utils.getImage(settings.image);

            // XXX: Keep this check?
            if (!this.image) {
                throw new me.Error((
                    (typeof(settings.image) === "string") ?
                    "'" + settings.image + "'" :
                    "Image"
                ) + " file for Image Layer '" + this.name + "' not found!");
            }

            this.imagewidth = this.image.width;
            this.imageheight = this.image.height;

            // call the constructor
            this._super(me.Renderable, "init", [x, y, Infinity, Infinity]);

            // render in screen coordinates
            this.floating = true;

            // displaying order
            this.pos.z = settings.z || 0;

            this.offset = new me.Vector2d(x, y);

            /**
             * Define the image scrolling ratio

             * Scrolling speed is defined by multiplying the viewport delta position (e.g. followed entity) by the specified ratio.
             * Setting this vector to <0.0,0.0> will disable automatic scrolling.

             * To specify a value through Tiled, use one of the following format :

             * - a number, to change the value for both axis

             * - a json expression like `json:{"x":0.5,"y":0.5}` if you wish to specify a different value for both x and y
             * @public
             * @type me.Vector2d
             * @default <1.0,1.0>
             * @name me.ImageLayer#ratio
             */
            this.ratio = new me.Vector2d(1.0, 1.0);

            if (typeof(settings.ratio) !== "undefined") {
                // little hack for backward compatiblity
                if (typeof(settings.ratio) === "number") {
                    this.ratio.set(settings.ratio, settings.ratio);
                } else /* vector */ {
                    this.ratio.setV(settings.ratio);
                }
            }

            if (typeof(settings.anchorPoint) === "undefined") {
                /**
                 * Define how the image is anchored to the viewport bounds

                 * By default, its upper-left corner is anchored to the viewport bounds upper left corner.

                 * The anchorPoint is a unit vector where each component falls in range [0.0,1.0].

                 * Some common examples:

                 * * <0.0,0.0> : (Default) Anchor image to the upper-left corner of viewport bounds
                 * * <0.5,0.5> : Center the image within viewport bounds
                 * * <1.0,1.0> : Anchor image to the lower-right corner of viewport bounds
                 * To specify a value through Tiled, use one of the following format :

                 * - a number, to change the value for both axis

                 * - a json expression like `json:{"x":0.5,"y":0.5}` if you wish to specify a different value for both x and y
                 * @public
                 * @type me.Vector2d
                 * @default <0.0,0.0>
                 * @name me.ImageLayer#anchorPoint
                 */
                this.anchorPoint.set(0, 0);
            }
            else {
                if (typeof(settings.anchorPoint) === "number") {
                    this.anchorPoint.set(settings.anchorPoint, settings.anchorPoint);
                }
                else /* vector */ {
                    this.anchorPoint.setV(settings.anchorPoint);
                }
            }

            /**
             * Define if and how an Image Layer should be repeated.

             * By default, an Image Layer is repeated both vertically and horizontally.

             * Acceptable values :

             * * 'repeat' - The background image will be repeated both vertically and horizontally. (default)

             * * 'repeat-x' - The background image will be repeated only horizontally.

             * * 'repeat-y' - The background image will be repeated only vertically.

             * * 'no-repeat' - The background-image will not be repeated.

             * @public
             * @type String
             * @name me.ImageLayer#repeat
             */
            Object.defineProperty(this, "repeat", {
                /**
                 * @ignore
                 */
                get : function get() {
                    return this._repeat;
                },
                /**
                 * @ignore
                 */
                set : function set(val) {
                    this._repeat = val;
                    switch (this._repeat) {
                        case "no-repeat" :
                            this.repeatX = false;
                            this.repeatY = false;
                            break;
                        case "repeat-x" :
                            this.repeatX = true;
                            this.repeatY = false;
                            break;
                        case "repeat-y" :
                            this.repeatX = false;
                            this.repeatY = true;
                            break;
                        default : // "repeat"
                            this.repeatX = true;
                            this.repeatY = true;
                            break;
                    }
                    this.resize(me.game.viewport.width, me.game.viewport.height);
                    this.createPattern();
                }
            });

            this.repeat = settings.repeat || "repeat";
        },

        // called when the layer is added to the game world or a container
        onActivateEvent : function () {
            var _updateLayerFn = this.updateLayer.bind(this);
            // register to the viewport change notification
            this.vpChangeHdlr = me.event.subscribe(me.event.VIEWPORT_ONCHANGE, _updateLayerFn);
            this.vpResizeHdlr = me.event.subscribe(me.event.VIEWPORT_ONRESIZE, this.resize.bind(this));
            this.vpLoadedHdlr = me.event.subscribe(me.event.LEVEL_LOADED, function() {
                // force a first refresh when the level is loaded
                _updateLayerFn(me.game.viewport.pos);
            });
            // in case the level is not added to the root container,
            // the onActivateEvent call happens after the LEVEL_LOADED event
            // so we need to force a first update
            if (this.ancestor._root !== true) {
                this.updateLayer(me.game.viewport.pos);
            }
        },

        /**
         * resize the Image Layer to match the given size
         * @name resize
         * @memberOf me.ImageLayer
         * @function
         * @param {Number} w new width
         * @param {Number} h new height
        */
        resize : function (w, h) {
            this._super(me.Renderable, "resize", [
                this.repeatX ? Infinity : w,
                this.repeatY ? Infinity : h
            ]);
        },

        /**
         * createPattern function
         * @ignore
         * @function
         */
        createPattern : function () {
            this._pattern = me.video.renderer.createPattern(this.image, this._repeat);
        },

        /**
         * updateLayer function
         * @ignore
         * @function
         */
        updateLayer : function (vpos) {
            var rx = this.ratio.x,
                ry = this.ratio.y;

            if (rx === ry === 0) {
                // static image
                return;
            }

            var viewport = me.game.viewport,
                width = this.imagewidth,
                height = this.imageheight,
                bw = viewport.bounds.width,
                bh = viewport.bounds.height,
                ax = this.anchorPoint.x,
                ay = this.anchorPoint.y,

                /*
                 * Automatic positioning
                 *
                 * See https://github.com/melonjs/melonJS/issues/741#issuecomment-138431532
                 * for a thorough description of how this works.
                 */
                x = ax * (rx - 1) * (bw - viewport.width) + this.offset.x - rx * vpos.x,
                y = ay * (ry - 1) * (bh - viewport.height) + this.offset.y - ry * vpos.y;

            // Repeat horizontally; start drawing from left boundary
            if (this.repeatX) {
                this.pos.x = x % width;
            }
            else {
                this.pos.x = x;
            }

            // Repeat vertically; start drawing from top boundary
            if (this.repeatY) {
                this.pos.y = y % height;
            }
            else {
                this.pos.y = y;
            }
        },

       /*
        * override the default predraw function
        * as repeat and anchor are managed directly in the draw method
        * @ignore
        */
        preDraw : function (renderer) {
            // save the context
            renderer.save();
        },

        /**
         * draw the image layer
         * @ignore
         */
        draw : function (renderer) {
            var viewport = me.game.viewport,
                width = this.imagewidth,
                height = this.imageheight,
                bw = viewport.bounds.width,
                bh = viewport.bounds.height,
                ax = this.anchorPoint.x,
                ay = this.anchorPoint.y,
                x = this.pos.x,
                y = this.pos.y;

            if (this.ratio.x === this.ratio.y === 0) {
                x = x + ax * (bw - width);
                y = y + ay * (bh - height);
            }

            renderer.translate(x, y);
            renderer.drawPattern(
                this._pattern,
                0,
                0,
                viewport.width * 2,
                viewport.height * 2
            );
        },

        // called when the layer is removed from the game world or a container
        onDeactivateEvent : function () {
            // cancel all event subscriptions
            me.event.unsubscribe(this.vpChangeHdlr);
            me.event.unsubscribe(this.vpResizeHdlr);
            me.event.unsubscribe(this.vpLoadedHdlr);
        }

    });
})();
<|endoftext|>


<commit_before>const TYPES = [
  'communities',
  'featured-users',
  'recent',
  'recommended',
  'trending',
]

const getComponents = (location, cb) => {
  cb(null, require('../../containers/discover/Discover').default)
}

const bindOnEnter = path => (nextState, replace) => {
  const type = nextState.params.type

  // redirect back to root path if type is unrecognized
  if (type && TYPES.indexOf(type) === -1) {
    replace({ state: nextState, pathname: path })
  }
}

const indexRoute = {
  getComponents,
}

const explore = store => ({
  path: '/explore(/:type)',
  getComponents,
  onEnter: (nextState, replace) => {
    const { params: { type } } = nextState
    const { authentication } = store.getState()

    const rootPath = authentication.isLoggedIn ? '/discover' : '/'

    if (type && TYPES.indexOf(type) === -1) {
      replace({ state: nextState, pathname: rootPath })
    } else if (authentication.isLoggedIn) {
      replace({ state: nextState, pathname: '/discover' })
    } else {
      replace({ state: nextState, pathname: '/' })
    }
  },
})

const discover = {
  path: 'discover(/:type)',
  getComponents,
  onEnter: bindOnEnter('/discover'),
}

export {
  indexRoute,
  getComponents,
  discover,
  explore,
}

export default [
  discover,
  explore,
]
<commit_msg>Fix bug with redirecting explore routes<commit_after>const TYPES = [
  'communities',
  'featured-users',
  'recent',
  'recommended',
  'trending',
]

const getComponents = (location, cb) => {
  cb(null, require('../../containers/discover/Discover').default)
}

const bindOnEnter = path => (nextState, replace) => {
  const type = nextState.params.type

  // redirect back to root path if type is unrecognized
  if (type && TYPES.indexOf(type) === -1) {
    replace({ state: nextState, pathname: path })
  }
}

const indexRoute = {
  getComponents,
}

const explore = store => ({
  path: '/explore(/:type)',
  getComponents,
  onEnter: (nextState, replace) => {
    const { params: { type } } = nextState
    const { authentication } = store.getState()

    const rootPath = authentication.isLoggedIn ? '/discover' : '/'

    if (type && TYPES.indexOf(type) === -1) {
      replace({ state: nextState, pathname: rootPath })
    } else if (authentication.isLoggedIn) {
      replace({ state: nextState, pathname: '/discover' })
    } else if (!type) {
      replace({ state: nextState, pathname: '/' })
    }
  },
})

const discover = {
  path: 'discover(/:type)',
  getComponents,
  onEnter: bindOnEnter('/discover'),
}

export {
  indexRoute,
  getComponents,
  discover,
  explore,
}

export default [
  discover,
  explore,
]
<|endoftext|>


<commit_before>'use strict';

module.exports = {
  // http://stackoverflow.com/a/105074
  guid: function() {
    function s4() {
      return Math.floor((1 + Math.random()) * 0x10000)
        .toString(16)
        .substring(1);
    }
    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
      s4() + '-' + s4() + s4() + s4();
  },
  objectToArray: function(obj) {
    return Object.keys(obj).map(function(key) {
      return obj[key];
    });
  }
}
<commit_msg>Add function to parse query parameters<commit_after>'use strict';

module.exports = {
  // http://codereview.stackexchange.com/a/10396
  getQueryParams: function() {
    var query = (window.location.search || '?').substr(1);
    var map = {};

    query.replace(/([^&=]+)=?([^&]*)(?:&+|$)/g, function(match, key, value) {
      map[decodeURIComponent(key)] = decodeURIComponent(value);
    });

    return map;
  },
  // http://stackoverflow.com/a/105074
  guid: function() {
    function s4() {
      return Math.floor((1 + Math.random()) * 0x10000)
        .toString(16)
        .substring(1);
    }
    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
      s4() + '-' + s4() + s4() + s4();
  },
  objectToArray: function(obj) {
    return Object.keys(obj).map(function(key) {
      return obj[key];
    });
  }
}
<|endoftext|>


<commit_before>var AuthController = require('./authController.js');

module.exports = function(router) {
  router.route('/api/auth/signup')
    .post(AuthController.signup);

  router.route('/api/auth/login')
    .post(AuthController.login)

  router.get('/auth/github', AuthController.authentication);

  router.get('/auth/github/callback', AuthController.authenticationCallback);

};<commit_msg>remove signup route<commit_after>var AuthController = require('./authController.js');

module.exports = function(router) {
  router.route('/api/auth/login')
    .post(AuthController.login)

  router.get('/auth/github', AuthController.authentication);

  router.get('/auth/github/callback', AuthController.authenticationCallback);

};<|endoftext|>