<commit_before>// Part of <http://miracle.systems/p/h5.modbus> licensed under <MIT>

'use strict';

const EventEmitter = require('events').EventEmitter;
const ExceptionCode = require('./ExceptionCode');
const FunctionCode = require('./FunctionCode');
const ExceptionResponse = require('./messages/ExceptionResponse');
const responses = require('./messages').responses;

/**
 * The MODBUS slave (server).
 */
class Slave extends EventEmitter
{
  /**
   * @param {SlaveOptions} options
   */
  constructor(options)
  {
    super();

    /**
     * @private
     * @type {function(this:Slave, RemoteClient)}
     */
    this.onRemoteClient = this.onRemoteClient.bind(this);

    /**
     * @type {Listener}
     */
    this.listener = this.setUpListener(options.listener);

    /**
     * @type {Transport}
     */
    this.transport = options.transport;

    /**
     * @private
     * @type {handleRequestCallback}
     */
    this.requestHandler = options.requestHandler;

    /**
     * @private
     * @type {boolean}
     */
    this.suppressClientErrors = options.suppressClientErrors !== false;

    /**
     * @private
     * @type {boolean}
     */
    this.maxClients = options.maxClients || 0;

    /**
     * @private
     * @type {Set<RemoteClient>}
     */
    this.clients = new Set();
  }

  /**
   * @param {boolean} recursive
   */
  destroy(recursive)
  {
    this.removeAllListeners();
    this.destroyTransport(recursive);
    this.destroyListener(recursive);
    this.clients.clear();
  }

  /**
   * @private
   * @param {boolean} recursive
   */
  destroyTransport(recursive)
  {
    if (!this.transport)
    {
      return;
    }

    if (recursive)
    {
      this.transport.destroy();
    }

    this.transport = null;
  }

  /**
   * @private
   * @param {Listener} listener
   * @returns {Listener}
   */
  setUpListener(listener)
  {
    listener.on('client', this.onRemoteClient);

    return listener;
  }

  /**
   * @private
   * @param {boolean} recursive
   */
  destroyListener(recursive)
  {
    if (!this.listener)
    {
      return;
    }

    this.listener.removeListener('client', this.onRemoteClient);

    if (recursive)
    {
      this.listener.destroy();
    }

    this.listener = null;
  }

  /**
   * @private
   * @param {RemoteClient} client
   */
  onRemoteClient(client)
  {
    if (this.hasMaxClients())
    {
      client.destroy();

      return;
    }

    client.on('adu', this.handleAdu.bind(this, client));
    client.on('close', () => this.clients.delete(client));

    if (this.suppressClientErrors)
    {
      client.on('error', () => {});
    }

    this.transport.add(client);
    this.clients.add(client);
  }

  /**
   * @private
   * @returns {boolean}
   */
  hasMaxClients()
  {
    return this.maxClients > 0 && this.clients.size === this.maxClients;
  }

  /**
   * @private
   * @param {RemoteClient} client
   * @param {ApplicationDataUnit} adu
   */
  handleAdu(client, adu)
  {
    let request = null;

    try
    {
      request = adu.toRequest();
    }
    catch (err)
    {
      client.emit('error', err);
    }

    if (request)
    {
      this.handleRequest(client, adu, request);
    }
  }

  /**
   * @private
   * @param {RemoteClient} client
   * @param {ApplicationDataUnit} adu
   * @param {Request} request
   * @fires Slave#request
   */
  handleRequest(client, adu, request)
  {
    this.emit('request', {
      client: client,
      adu: adu,
      request: request
    });

    this.requestHandler(adu.unit, request, this.createRespondCallback(client, adu, request));
  }

  /**
   * @private
   * @param {RemoteClient} client
   * @param {ApplicationDataUnit} adu
   * @param {Request} request
   * @returns {respondCallback}
   */
  createRespondCallback(client, adu, request)
  {
    /**
     * @param {*} result
     * @fires Slave#response
     */
    return (result) =>
    {
      if (!this.transport)
      {
        return;
      }

      const response = this.createResponse(adu.functionCode, result);
      const pdu = response.toBuffer();
      const frame = this.transport.encode(adu.id, adu.unit, pdu);

      this.emit('response', {
        client: client,
        adu: adu,
        request: request,
        response: response
      });

      client.write(frame);
    };
  }

  /**
   * @private
   * @param {FunctionCode} functionCode
   * @param {*} result
   * @returns {Response}
   * @throws {Error} If the specified `result` is not an `ExceptionCode`, a `Response` or a `Response` options object.
   */
  createResponse(functionCode, result)
  {
    if (result == null)
    {
      throw new Error(
        'Invalid response result. '
        + 'Expected an ExceptionCode, a Response, a Response options object or a Response Buffer, '
        + `but got [${result}].`
      );
    }

    if (typeof result === 'number')
    {
      return new ExceptionResponse(functionCode, result);
    }

    if (typeof result.toBuffer === 'function')
    {
      if (result.functionCode !== functionCode)
      {
        throw new Error(
          'Invalid response result. '
          + `Expected a Response with function code ${FunctionCode[functionCode]} (${functionCode}), `
          + `but got ${FunctionCode[result.functionCode]} (${result.functionCode}).`
        );
      }

      return result;
    }

    if (typeof result.message === 'string')
    {
      return new ExceptionResponse(functionCode, ExceptionCode.SlaveDeviceFailure);
    }

    const ResponseClass = responses[functionCode];

    if (!ResponseClass)
    {
      throw new Error(
        'Invalid response result. '
        + 'Expected an options object or Buffer for an implemented MODBUS function code, '
        + `but ${FunctionCode[functionCode]} (${functionCode}) is not implemented.`
      );
    }

    return Buffer.isBuffer(result)
      ? ResponseClass.fromBuffer(result)
      : ResponseClass.fromOptions(result);
  }
}

module.exports = Slave;

/**
 * @typedef {Object} SlaveOptions
 * @property {Listener} listener
 * @property {Transport} transport
 * @property {handleRequestCallback} requestHandler
 * @property {boolean} [suppressClientErrors=true]
 */

/**
 * @event Slave#request
 * @type {Object}
 * @property {RemoteClient} client
 * @property {ApplicationDataUnit} adu
 * @property {Request} request
 */

/**
 * @event Slave#response
 * @type {Object}
 * @property {RemoteClient} client
 * @property {ApplicationDataUnit} adu
 * @property {Request} request
 * @property {Response} response
 */

/**
 * @callback respondCallback
 * @param {*} result
 */

/**
 * @callback handleRequestCallback
 * @param {number} unit
 * @param {Request} request
 * @param {respondCallback} respond
 */
<commit_msg>Slave: throw exceptions if `listener`, `transport` or `requestHandler` option is not specified.<commit_after>// Part of <http://miracle.systems/p/h5.modbus> licensed under <MIT>

'use strict';

const EventEmitter = require('events').EventEmitter;
const ExceptionCode = require('./ExceptionCode');
const FunctionCode = require('./FunctionCode');
const ExceptionResponse = require('./messages/ExceptionResponse');
const responses = require('./messages').responses;

/**
 * The MODBUS slave (server).
 */
class Slave extends EventEmitter
{
  /**
   * @param {SlaveOptions} options
   * @throws {Error} If the `listener` option is not specified.
   * @throws {Error} If the `transport` option is not specified.
   * @throws {Error} If the `requestHandler` option is not specified.
   */
  constructor(options)
  {
    super();

    /**
     * @private
     * @type {function(this:Slave, RemoteClient)}
     */
    this.onRemoteClient = this.onRemoteClient.bind(this);

    /**
     * @type {Listener}
     */
    this.listener = this.setUpListener(options.listener);

    /**
     * @type {Transport}
     */
    this.transport = this.setUpTransport(options.transport);

    /**
     * @private
     * @type {handleRequestCallback}
     */
    this.requestHandler = this.setUpRequestHandler(options.requestHandler);

    /**
     * @private
     * @type {boolean}
     */
    this.suppressClientErrors = options.suppressClientErrors !== false;

    /**
     * @private
     * @type {boolean}
     */
    this.maxClients = options.maxClients || 0;

    /**
     * @private
     * @type {Set<RemoteClient>}
     */
    this.clients = new Set();
  }

  /**
   * @param {boolean} recursive
   */
  destroy(recursive)
  {
    this.removeAllListeners();
    this.destroyTransport(recursive);
    this.destroyListener(recursive);
    this.clients.clear();
  }

  /**
   * @private
   * @param {?handleRequestCallback} requestHandler
   * @returns {handleRequestCallback}
   * @throws {Error} If the specified `requestHandler` is NULL or undefined.
   */
  setUpRequestHandler(requestHandler)
  {
    if (!requestHandler)
    {
      throw new Error('The `requestHandler` option must be specified!');
    }

    return requestHandler;
  }

  /**
   * @private
   * @param {?Transport} transport
   * @returns {Transport}
   * @throws {Error} If the specified `transport` is NULL or undefined.
   */
  setUpTransport(transport)
  {
    if (!transport)
    {
      throw new Error('The `transport` option must be specified!');
    }

    return transport;
  }

  /**
   * @private
   * @param {boolean} recursive
   */
  destroyTransport(recursive)
  {
    if (!this.transport)
    {
      return;
    }

    if (recursive)
    {
      this.transport.destroy();
    }

    this.transport = null;
  }

  /**
   * @private
   * @param {Listener} listener
   * @returns {Listener}
   * @throws {Error} If the specified `listener` is NULL or undefined.
   */
  setUpListener(listener)
  {
    if (!listener)
    {
      throw new Error('The `listener` option must be specified!');
    }

    listener.on('client', this.onRemoteClient);

    return listener;
  }

  /**
   * @private
   * @param {boolean} recursive
   */
  destroyListener(recursive)
  {
    if (!this.listener)
    {
      return;
    }

    this.listener.removeListener('client', this.onRemoteClient);

    if (recursive)
    {
      this.listener.destroy();
    }

    this.listener = null;
  }

  /**
   * @private
   * @param {RemoteClient} client
   */
  onRemoteClient(client)
  {
    if (this.hasMaxClients())
    {
      client.destroy();

      return;
    }

    client.on('adu', this.handleAdu.bind(this, client));
    client.on('close', () => this.clients.delete(client));

    if (this.suppressClientErrors)
    {
      client.on('error', () => {});
    }

    this.transport.add(client);
    this.clients.add(client);
  }

  /**
   * @private
   * @returns {boolean}
   */
  hasMaxClients()
  {
    return this.maxClients > 0 && this.clients.size === this.maxClients;
  }

  /**
   * @private
   * @param {RemoteClient} client
   * @param {ApplicationDataUnit} adu
   */
  handleAdu(client, adu)
  {
    let request = null;

    try
    {
      request = adu.toRequest();
    }
    catch (err)
    {
      client.emit('error', err);
    }

    if (request)
    {
      this.handleRequest(client, adu, request);
    }
  }

  /**
   * @private
   * @param {RemoteClient} client
   * @param {ApplicationDataUnit} adu
   * @param {Request} request
   * @fires Slave#request
   */
  handleRequest(client, adu, request)
  {
    this.emit('request', {
      client: client,
      adu: adu,
      request: request
    });

    this.requestHandler(adu.unit, request, this.createRespondCallback(client, adu, request));
  }

  /**
   * @private
   * @param {RemoteClient} client
   * @param {ApplicationDataUnit} adu
   * @param {Request} request
   * @returns {respondCallback}
   */
  createRespondCallback(client, adu, request)
  {
    /**
     * @param {*} result
     * @fires Slave#response
     */
    return (result) =>
    {
      if (!this.transport)
      {
        return;
      }

      const response = this.createResponse(adu.functionCode, result);
      const pdu = response.toBuffer();
      const frame = this.transport.encode(adu.id, adu.unit, pdu);

      this.emit('response', {
        client: client,
        adu: adu,
        request: request,
        response: response
      });

      client.write(frame);
    };
  }

  /**
   * @private
   * @param {FunctionCode} functionCode
   * @param {*} result
   * @returns {Response}
   * @throws {Error} If the specified `result` is not an `ExceptionCode`, a `Response` or a `Response` options object.
   */
  createResponse(functionCode, result)
  {
    if (result == null)
    {
      throw new Error(
        'Invalid response result. '
        + 'Expected an ExceptionCode, a Response, a Response options object or a Response Buffer, '
        + `but got [${result}].`
      );
    }

    if (typeof result === 'number')
    {
      return new ExceptionResponse(functionCode, result);
    }

    if (typeof result.toBuffer === 'function')
    {
      if (result.functionCode !== functionCode)
      {
        throw new Error(
          'Invalid response result. '
          + `Expected a Response with function code ${FunctionCode[functionCode]} (${functionCode}), `
          + `but got ${FunctionCode[result.functionCode]} (${result.functionCode}).`
        );
      }

      return result;
    }

    if (typeof result.message === 'string')
    {
      return new ExceptionResponse(functionCode, ExceptionCode.SlaveDeviceFailure);
    }

    const ResponseClass = responses[functionCode];

    if (!ResponseClass)
    {
      throw new Error(
        'Invalid response result. '
        + 'Expected an options object or Buffer for an implemented MODBUS function code, '
        + `but ${FunctionCode[functionCode]} (${functionCode}) is not implemented.`
      );
    }

    return Buffer.isBuffer(result)
      ? ResponseClass.fromBuffer(result)
      : ResponseClass.fromOptions(result);
  }
}

module.exports = Slave;

/**
 * @typedef {Object} SlaveOptions
 * @property {Listener} listener
 * @property {Transport} transport
 * @property {handleRequestCallback} [requestHandler]
 * @property {boolean} [suppressClientErrors=true]
 */

/**
 * @event Slave#request
 * @type {Object}
 * @property {RemoteClient} client
 * @property {ApplicationDataUnit} adu
 * @property {Request} request
 */

/**
 * @event Slave#response
 * @type {Object}
 * @property {RemoteClient} client
 * @property {ApplicationDataUnit} adu
 * @property {Request} request
 * @property {Response} response
 */

/**
 * @callback respondCallback
 * @param {*} result
 */

/**
 * @callback handleRequestCallback
 * @param {number} unit
 * @param {Request} request
 * @param {respondCallback} respond
 */
<|endoftext|>


<commit_before>javascript:
(function() {

    var page = prompt("page");
    if (page == "" || page == null) return;
    page = page.replace(/_/g, " ");
    var pages = page.split("|");
    wpTextbox1.value = wpTextbox1.value.replace(/(==.+==)\n\n?/, "$1\n{{saveto|" + page + "}}\n");
    wpSummary.value = wpSummary.value + " saveto [[" + pages.join("]]、[[") + "]]";
    wpMinoredit.click();
    if (confirm("Save?")) wpSave.click();

})();
<commit_msg>Fix regex<commit_after>javascript:
(function() {

    var page = prompt("page");
    if (page == "" || page == null) return;
    page = page.replace(/_/g, " ");
    var pages = page.split("|");
    wpTextbox1.value = wpTextbox1.value.replace(/(==.+==) *\n\n?/, "$1\n{{saveto|" + page + "}}\n");
    wpSummary.value = wpSummary.value + " saveto [[" + pages.join("]]、[[") + "]]";
    wpMinoredit.click();
    if (confirm("Save?")) wpSave.click();

})();
<|endoftext|>


<commit_before>const log = require('npmlog');
const path = require('path');
const uniq = require('lodash').uniq;
const flatten = require('lodash').flatten;
const pkg = require('../package.json');

const isEmpty = require('lodash').isEmpty;
const promiseWaterfall = require('./promiseWaterfall');
const registerDependencyAndroid = require('./android/registerNativeModule');
const registerDependencyIOS = require('./ios/registerNativeModule');
const isInstalledAndroid = require('./android/isInstalled');
const isInstalledIOS = require('./ios/isInstalled');
const copyAssetsAndroid = require('./android/copyAssets');
const copyAssetsIOS = require('./ios/copyAssets');
const getProjectDependencies = require('./getProjectDependencies');
const getDependencyConfig = require('./getDependencyConfig');
const pollParams = require('./pollParams');

log.heading = 'rnpm-link';

const commandStub = (cb) => cb();
const dedupeAssets = (assets) => uniq(assets, asset => path.basename(asset));

const promisify = (func) => new Promise((resolve, reject) =>
  func((err, res) => err ? reject(err) : resolve(res))
);

const linkDependencyAndroid = (androidProject, dependency) => {
  if (!androidProject || !dependency.config.android) {
    return null;
  }

  const isInstalled = isInstalledAndroid(androidProject, dependency.name);

  if (isInstalled) {
    log.info(`Android module ${dependency.name} is already linked`);
    return null;
  }

  return pollParams(dependency.config.params).then(params => {
    log.info(`Linking ${dependency.name} android dependency`);

    registerDependencyAndroid(
      dependency.name,
      dependency.config.android,
      params,
      androidProject
    );

    log.info(`Android module ${dependency.name} has been successfully linked`);
  });
};

const linkDependencyIOS = (iOSProject, dependency) => {
  if (!iOSProject || !dependency.config.ios) {
    return;
  }

  const isInstalled = isInstalledIOS(iOSProject, dependency.config.ios);

  if (isInstalled) {
    log.info(`iOS module ${dependency.name} is already linked`);
    return;
  }

  log.info(`Linking ${dependency.name} ios dependency`);

  registerDependencyIOS(dependency.config.ios, iOSProject);

  log.info(`iOS module ${dependency.name} has been successfully linked`);
};

const linkAssets = (project, assets) => {
  if (isEmpty(assets)) {
    return;
  }

  if (project.ios) {
    log.info('Linking assets to ios project');
    copyAssetsIOS(assets, project.ios);
  }

  if (project.android) {
    log.info('Linking assets to android project');
    copyAssetsAndroid(assets, project.android.assetsPath);
  }

  log.info(`Assets has been successfully linked to your project`);
};

/**
 * Updates project and linkes all dependencies to it
 *
 * If optional argument [packageName] is provided, it's the only one that's checked
 */
module.exports = function link(config, args) {
  try {
    const project = config.getProjectConfig();
  } catch (err) {
    log.error('ERRPACKAGEJSON', `No package found. Are you sure it's a React Native project?`);
    return Promise.reject(err);
  }

  const packageName = args[0];

  const dependencies = getDependencyConfig(
    config,
    packageName ? [packageName] : getProjectDependencies()
  );

  const assets = dedupeAssets(dependencies.reduce(
    (assets, dependency) => assets.concat(dependency.config.assets),
    project.assets
  ));

  const tasks = flatten(dependencies.map(dependency => [
    () => promisify(dependency.config.commands.prelink || commandStub),
    () => linkDependencyAndroid(project.android, dependency),
    () => linkDependencyIOS(project.ios, dependency),
    () => promisify(dependency.config.commands.postlink || commandStub),
  ]));

  tasks.push(() => linkAssets(project, assets));

  return promiseWaterfall(tasks).catch(err => {
    log.error(
      `It seems something went wrong while linking. Error: ${err.message} \n`
      + `Please file an issue here: ${pkg.bugs.url}`
    );
    throw err;
  });
};
<commit_msg>fix undefined project, closes rnpm/rnpm-plugin-link#76 (#77)<commit_after>const log = require('npmlog');
const path = require('path');
const uniq = require('lodash').uniq;
const flatten = require('lodash').flatten;
const pkg = require('../package.json');

const isEmpty = require('lodash').isEmpty;
const promiseWaterfall = require('./promiseWaterfall');
const registerDependencyAndroid = require('./android/registerNativeModule');
const registerDependencyIOS = require('./ios/registerNativeModule');
const isInstalledAndroid = require('./android/isInstalled');
const isInstalledIOS = require('./ios/isInstalled');
const copyAssetsAndroid = require('./android/copyAssets');
const copyAssetsIOS = require('./ios/copyAssets');
const getProjectDependencies = require('./getProjectDependencies');
const getDependencyConfig = require('./getDependencyConfig');
const pollParams = require('./pollParams');

log.heading = 'rnpm-link';

const commandStub = (cb) => cb();
const dedupeAssets = (assets) => uniq(assets, asset => path.basename(asset));

const promisify = (func) => new Promise((resolve, reject) =>
  func((err, res) => err ? reject(err) : resolve(res))
);

const linkDependencyAndroid = (androidProject, dependency) => {
  if (!androidProject || !dependency.config.android) {
    return null;
  }

  const isInstalled = isInstalledAndroid(androidProject, dependency.name);

  if (isInstalled) {
    log.info(`Android module ${dependency.name} is already linked`);
    return null;
  }

  return pollParams(dependency.config.params).then(params => {
    log.info(`Linking ${dependency.name} android dependency`);

    registerDependencyAndroid(
      dependency.name,
      dependency.config.android,
      params,
      androidProject
    );

    log.info(`Android module ${dependency.name} has been successfully linked`);
  });
};

const linkDependencyIOS = (iOSProject, dependency) => {
  if (!iOSProject || !dependency.config.ios) {
    return;
  }

  const isInstalled = isInstalledIOS(iOSProject, dependency.config.ios);

  if (isInstalled) {
    log.info(`iOS module ${dependency.name} is already linked`);
    return;
  }

  log.info(`Linking ${dependency.name} ios dependency`);

  registerDependencyIOS(dependency.config.ios, iOSProject);

  log.info(`iOS module ${dependency.name} has been successfully linked`);
};

const linkAssets = (project, assets) => {
  if (isEmpty(assets)) {
    return;
  }

  if (project.ios) {
    log.info('Linking assets to ios project');
    copyAssetsIOS(assets, project.ios);
  }

  if (project.android) {
    log.info('Linking assets to android project');
    copyAssetsAndroid(assets, project.android.assetsPath);
  }

  log.info(`Assets has been successfully linked to your project`);
};

/**
 * Updates project and linkes all dependencies to it
 *
 * If optional argument [packageName] is provided, it's the only one that's checked
 */
module.exports = function link(config, args) {
  var project;
  try {
    project = config.getProjectConfig();
  } catch (err) {
    log.error('ERRPACKAGEJSON', `No package found. Are you sure it's a React Native project?`);
    return Promise.reject(err);
  }

  const packageName = args[0];

  const dependencies = getDependencyConfig(
    config,
    packageName ? [packageName] : getProjectDependencies()
  );

  const assets = dedupeAssets(dependencies.reduce(
    (assets, dependency) => assets.concat(dependency.config.assets),
    project.assets
  ));

  const tasks = flatten(dependencies.map(dependency => [
    () => promisify(dependency.config.commands.prelink || commandStub),
    () => linkDependencyAndroid(project.android, dependency),
    () => linkDependencyIOS(project.ios, dependency),
    () => promisify(dependency.config.commands.postlink || commandStub),
  ]));

  tasks.push(() => linkAssets(project, assets));

  return promiseWaterfall(tasks).catch(err => {
    log.error(
      `It seems something went wrong while linking. Error: ${err.message} \n`
      + `Please file an issue here: ${pkg.bugs.url}`
    );
    throw err;
  });
};
<|endoftext|>


<commit_before>import Ember from 'ember';

var ENV = <%= namespace %>ENV;

var Router = Ember.Router.extend({
  location: ENV.locationType
});

Router.map(function() {
});

export default Router;
<commit_msg>Revert "add router.js file"<commit_after><|endoftext|>


<commit_before>// Copyright 2006 The Closure Library Authors. All Rights Reserved.
//
// 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 Definition of various formatters for logging. Please minimize
 * dependencies this file has on other closure classes as any dependency it
 * takes won't be able to use the logging infrastructure.
 *
 */

goog.provide('goog.debug.Formatter');
goog.provide('goog.debug.HtmlFormatter');
goog.provide('goog.debug.TextFormatter');

goog.require('goog.debug.RelativeTimeProvider');
goog.require('goog.string');

/**
 * Base class for Formatters. A Formatter is used to format a LogRecord into
 * something that can be displayed to the user.
 *
 * @param {string=} opt_prefix The prefix to place before text records.
 * @constructor
 */
goog.debug.Formatter = function(opt_prefix) {
  this.prefix_ = opt_prefix || '';

  /**
   * A provider that returns the relative start time.
   * @type {goog.debug.RelativeTimeProvider}
   * @private
   */
  this.startTimeProvider_ =
      goog.debug.RelativeTimeProvider.getDefaultInstance();
};

/**
 * Whether to show absolute time in the DebugWindow.
 * @type {boolean}
 */
goog.debug.Formatter.prototype.showAbsoluteTime = true;

/**
 * Whether to show relative time in the DebugWindow.
 * @type {boolean}
 */
goog.debug.Formatter.prototype.showRelativeTime = true;

/**
 * Whether to show the logger name in the DebugWindow.
 * @type {boolean}
 */
goog.debug.Formatter.prototype.showLoggerName = true;

/**
 * Whether to show the logger exception text.
 * @type {boolean}
 */
goog.debug.Formatter.prototype.showExceptionText = false;

/**
 * Whether to show the severity level.
 * @type {boolean}
 */
goog.debug.Formatter.prototype.showSeverityLevel = false;

/**
 * Formats a record.
 * @param {goog.debug.LogRecord} logRecord the logRecord to format.
 * @return {string} The formatted string.
 */
goog.debug.Formatter.prototype.formatRecord = goog.abstractMethod;

/**
 * Sets the start time provider. By default, this is the default instance
 * but can be changed.
 * @param {goog.debug.RelativeTimeProvider} provider The provider to use.
 */
goog.debug.Formatter.prototype.setStartTimeProvider = function(provider) {
  this.startTimeProvider_ = provider;
};

/**
 * Returns the start time provider. By default, this is the default instance
 * but can be changed.
 * @return {goog.debug.RelativeTimeProvider} The start time provider.
 */
goog.debug.Formatter.prototype.getStartTimeProvider = function() {
  return this.startTimeProvider_;
};

/**
 * Resets the start relative time.
 */
goog.debug.Formatter.prototype.resetRelativeTimeStart = function() {
  this.startTimeProvider_.reset();
};

/**
 * Returns a string for the time/date of the LogRecord.
 * @param {goog.debug.LogRecord} logRecord The record to get a time stamp for.
 * @return {string} A string representation of the time/date of the LogRecord.
 * @private
 */
goog.debug.Formatter.getDateTimeStamp_ = function(logRecord) {
  var time = new Date(logRecord.getMillis());
  return goog.debug.Formatter.getTwoDigitString_((time.getFullYear() - 2000)) +
         goog.debug.Formatter.getTwoDigitString_((time.getMonth() + 1)) +
         goog.debug.Formatter.getTwoDigitString_(time.getDate()) + ' ' +
         goog.debug.Formatter.getTwoDigitString_(time.getHours()) + ':' +
         goog.debug.Formatter.getTwoDigitString_(time.getMinutes()) + ':' +
         goog.debug.Formatter.getTwoDigitString_(time.getSeconds()) + '.' +
         goog.debug.Formatter.getTwoDigitString_(
             Math.floor(time.getMilliseconds() / 10));
};

/**
 * Returns the number as a two-digit string, meaning it prepends a 0 if the
 * number if less than 10.
 * @param {number} n The number to format.
 * @return {string} A two-digit string representation of {@code n}.
 * @private
 */
goog.debug.Formatter.getTwoDigitString_ = function(n) {
  if (n < 10) {
    return '0' + n;
  }
  return String(n);
};

/**
 * Returns a string for the number of seconds relative to the start time.
 * Prepads with spaces so that anything less than 1000 seconds takes up the
 * same number of characters for better formatting.
 * @param {goog.debug.LogRecord} logRecord The log to compare time to.
 * @param {number} relativeTimeStart The start time to compare to.
 * @return {string} The number of seconds of the LogRecord relative to the
 *     start time.
 * @private
 */
goog.debug.Formatter.getRelativeTime_ = function(logRecord,
                                                 relativeTimeStart) {
  var ms = logRecord.getMillis() - relativeTimeStart;
  var sec = ms / 1000;
  var str = sec.toFixed(3);

  var spacesToPrepend = 0;
  if (sec < 1) {
    spacesToPrepend = 2;
  } else {
    while (sec < 100) {
      spacesToPrepend++;
      sec *= 10;
    }
  }
  while (spacesToPrepend-- > 0) {
    str = ' ' + str;
  }
  return str;
};

/**
 * Formatter that returns formatted html. See formatRecord for the classes
 * it uses for various types of formatted output.
 *
 * @param {string=} opt_prefix The prefix to place before text records.
 * @constructor
 * @extends {goog.debug.Formatter}
 */
goog.debug.HtmlFormatter = function(opt_prefix) {
  goog.debug.Formatter.call(this, opt_prefix);
};
goog.inherits(goog.debug.HtmlFormatter, goog.debug.Formatter);

/**
 * Whether to show the logger exception text
 * @type {boolean}
 * @override
 */
goog.debug.HtmlFormatter.prototype.showExceptionText = true;

/**
 * Formats a record
 * @param {goog.debug.LogRecord} logRecord the logRecord to format.
 * @return {string} The formatted string as html.
 * @override
 */
goog.debug.HtmlFormatter.prototype.formatRecord = function(logRecord) {
  var className;
  switch (logRecord.getLevel().value) {
    case goog.debug.Logger.Level.SHOUT.value:
      className = 'dbg-sh';
      break;
    case goog.debug.Logger.Level.SEVERE.value:
      className = 'dbg-sev';
      break;
    case goog.debug.Logger.Level.WARNING.value:
      className = 'dbg-w';
      break;
    case goog.debug.Logger.Level.INFO.value:
      className = 'dbg-i';
      break;
    case goog.debug.Logger.Level.FINE.value:
    default:
      className = 'dbg-f';
      break;
  }

  // Build message html
  var sb = [];
  sb.push(this.prefix_, ' ');
  if (this.showAbsoluteTime) {
    sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');
  }
  if (this.showRelativeTime) {
    sb.push('[',
        goog.string.whitespaceEscape(
            goog.debug.Formatter.getRelativeTime_(logRecord,
                this.startTimeProvider_.get())),
        's] ');
  }

  if (this.showLoggerName) {
    sb.push('[', goog.string.htmlEscape(logRecord.getLoggerName()), '] ');
  }
  sb.push('',
      goog.string.newLineToBr(goog.string.whitespaceEscape(
          goog.string.htmlEscape(logRecord.getMessage()))));

  if (this.showExceptionText && logRecord.getException()) {
    sb.push('
',
        goog.string.newLineToBr(goog.string.whitespaceEscape(
            logRecord.getExceptionText() || '')));
  }
  sb.push('
');

  // If the logger is enabled, open window and write html message to log
  // otherwise save it
  return sb.join('');
};

/**
 * Formatter that returns formatted plain text
 *
 * @param {string=} opt_prefix The prefix to place before text records.
 * @constructor
 * @extends {goog.debug.Formatter}
 */
goog.debug.TextFormatter = function(opt_prefix) {
  goog.debug.Formatter.call(this, opt_prefix);
};
goog.inherits(goog.debug.TextFormatter, goog.debug.Formatter);

/**
 * Formats a record as text
 * @param {goog.debug.LogRecord} logRecord the logRecord to format.
 * @return {string} The formatted string.
 * @override
 */
goog.debug.TextFormatter.prototype.formatRecord = function(logRecord) {
  // Build message html
  var sb = [];
  sb.push(this.prefix_, ' ');
  if (this.showAbsoluteTime) {
    sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');
  }
  if (this.showRelativeTime) {
    sb.push('[', goog.debug.Formatter.getRelativeTime_(logRecord,
        this.startTimeProvider_.get()), 's] ');
  }

  if (this.showLoggerName) {
    sb.push('[', logRecord.getLoggerName(), '] ');
  }
  if (this.showSeverityLevel) {
    sb.push('[', logRecord.getLevel().name, '] ');
  }
  sb.push(logRecord.getMessage(), '\n');
  if (this.showExceptionText && logRecord.getException()) {
    sb.push(logRecord.getExceptionText(), '\n');
  }
  // If the logger is enabled, open window and write html message to log
  // otherwise save it
  return sb.join('');
};
<commit_msg><commit_after>// Copyright 2006 The Closure Library Authors. All Rights Reserved.
//
// 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 Definition of various formatters for logging. Please minimize
 * dependencies this file has on other closure classes as any dependency it
 * takes won't be able to use the logging infrastructure.
 *
 */

goog.provide('goog.debug.Formatter');
goog.provide('goog.debug.HtmlFormatter');
goog.provide('goog.debug.TextFormatter');

goog.require('goog.debug.RelativeTimeProvider');
goog.require('goog.string');

/**
 * Base class for Formatters. A Formatter is used to format a LogRecord into
 * something that can be displayed to the user.
 *
 * @param {string=} opt_prefix The prefix to place before text records.
 * @constructor
 */
goog.debug.Formatter = function(opt_prefix) {
  this.prefix_ = opt_prefix || '';

  /**
   * A provider that returns the relative start time.
   * @type {goog.debug.RelativeTimeProvider}
   * @private
   */
  this.startTimeProvider_ =
      goog.debug.RelativeTimeProvider.getDefaultInstance();
};

/**
 * Whether to show absolute time in the DebugWindow.
 * @type {boolean}
 */
goog.debug.Formatter.prototype.showAbsoluteTime = true;

/**
 * Whether to show relative time in the DebugWindow.
 * @type {boolean}
 */
goog.debug.Formatter.prototype.showRelativeTime = true;

/**
 * Whether to show the logger name in the DebugWindow.
 * @type {boolean}
 */
goog.debug.Formatter.prototype.showLoggerName = true;

/**
 * Whether to show the logger exception text.
 * @type {boolean}
 */
goog.debug.Formatter.prototype.showExceptionText = false;

/**
 * Whether to show the severity level.
 * @type {boolean}
 */
goog.debug.Formatter.prototype.showSeverityLevel = false;

/**
 * Formats a record.
 * @param {goog.debug.LogRecord} logRecord the logRecord to format.
 * @return {string} The formatted string.
 */
goog.debug.Formatter.prototype.formatRecord = goog.abstractMethod;

/**
 * Sets the start time provider. By default, this is the default instance
 * but can be changed.
 * @param {goog.debug.RelativeTimeProvider} provider The provider to use.
 */
goog.debug.Formatter.prototype.setStartTimeProvider = function(provider) {
  this.startTimeProvider_ = provider;
};

/**
 * Returns the start time provider. By default, this is the default instance
 * but can be changed.
 * @return {goog.debug.RelativeTimeProvider} The start time provider.
 */
goog.debug.Formatter.prototype.getStartTimeProvider = function() {
  return this.startTimeProvider_;
};

/**
 * Resets the start relative time.
 */
goog.debug.Formatter.prototype.resetRelativeTimeStart = function() {
  this.startTimeProvider_.reset();
};

/**
 * Returns a string for the time/date of the LogRecord.
 * @param {goog.debug.LogRecord} logRecord The record to get a time stamp for.
 * @return {string} A string representation of the time/date of the LogRecord.
 * @private
 */
goog.debug.Formatter.getDateTimeStamp_ = function(logRecord) {
  var time = new Date(logRecord.getMillis());
  return goog.debug.Formatter.getTwoDigitString_((time.getFullYear() - 2000)) +
         goog.debug.Formatter.getTwoDigitString_((time.getMonth() + 1)) +
         goog.debug.Formatter.getTwoDigitString_(time.getDate()) + ' ' +
         goog.debug.Formatter.getTwoDigitString_(time.getHours()) + ':' +
         goog.debug.Formatter.getTwoDigitString_(time.getMinutes()) + ':' +
         goog.debug.Formatter.getTwoDigitString_(time.getSeconds()) + '.' +
         goog.debug.Formatter.getTwoDigitString_(
             Math.floor(time.getMilliseconds() / 10));
};

/**
 * Returns the number as a two-digit string, meaning it prepends a 0 if the
 * number if less than 10.
 * @param {number} n The number to format.
 * @return {string} A two-digit string representation of {@code n}.
 * @private
 */
goog.debug.Formatter.getTwoDigitString_ = function(n) {
  if (n < 10) {
    return '0' + n;
  }
  return String(n);
};

/**
 * Returns a string for the number of seconds relative to the start time.
 * Prepads with spaces so that anything less than 1000 seconds takes up the
 * same number of characters for better formatting.
 * @param {goog.debug.LogRecord} logRecord The log to compare time to.
 * @param {number} relativeTimeStart The start time to compare to.
 * @return {string} The number of seconds of the LogRecord relative to the
 *     start time.
 * @private
 */
goog.debug.Formatter.getRelativeTime_ = function(logRecord,
                                                 relativeTimeStart) {
  var ms = logRecord.getMillis() - relativeTimeStart;
  var sec = ms / 1000;
  var str = sec.toFixed(3);

  var spacesToPrepend = 0;
  if (sec < 1) {
    spacesToPrepend = 2;
  } else {
    while (sec < 100) {
      spacesToPrepend++;
      sec *= 10;
    }
  }
  while (spacesToPrepend-- > 0) {
    str = ' ' + str;
  }
  return str;
};

/**
 * Formatter that returns formatted html. See formatRecord for the classes
 * it uses for various types of formatted output.
 *
 * @param {string=} opt_prefix The prefix to place before text records.
 * @constructor
 * @extends {goog.debug.Formatter}
 */
goog.debug.HtmlFormatter = function(opt_prefix) {
  goog.debug.Formatter.call(this, opt_prefix);
};
goog.inherits(goog.debug.HtmlFormatter, goog.debug.Formatter);

/**
 * Whether to show the logger exception text
 * @type {boolean}
 * @override
 */
goog.debug.HtmlFormatter.prototype.showExceptionText = true;

/**
 * Formats a record
 * @param {goog.debug.LogRecord} logRecord the logRecord to format.
 * @return {string} The formatted string as html.
 * @override
 */
goog.debug.HtmlFormatter.prototype.formatRecord = function(logRecord) {
  var className;
  switch (logRecord.getLevel().value) {
    case goog.debug.Logger.Level.SHOUT.value:
      className = 'dbg-sh';
      break;
    case goog.debug.Logger.Level.SEVERE.value:
      className = 'dbg-sev';
      break;
    case goog.debug.Logger.Level.WARNING.value:
      className = 'dbg-w';
      break;
    case goog.debug.Logger.Level.INFO.value:
      className = 'dbg-i';
      break;
    case goog.debug.Logger.Level.FINE.value:
    default:
      className = 'dbg-f';
      break;
  }

  // Build message html
  var sb = [];
  sb.push(this.prefix_, ' ');
  if (this.showAbsoluteTime) {
    sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');
  }
  if (this.showRelativeTime) {
    sb.push('[',
        goog.string.whitespaceEscape(
            goog.debug.Formatter.getRelativeTime_(logRecord,
                this.startTimeProvider_.get())),
        's] ');
  }

  if (this.showLoggerName) {
    sb.push('[', goog.string.htmlEscape(logRecord.getLoggerName()), '] ');
  }
  if (this.showSeverityLevel) {
    sb.push('[', goog.string.htmlEscape(logRecord.getLevel().name), '] ');
  }
  sb.push('',
      goog.string.newLineToBr(goog.string.whitespaceEscape(
          goog.string.htmlEscape(logRecord.getMessage()))));

  if (this.showExceptionText && logRecord.getException()) {
    sb.push('
',
        goog.string.newLineToBr(goog.string.whitespaceEscape(
            logRecord.getExceptionText() || '')));
  }
  sb.push('
');

  // If the logger is enabled, open window and write html message to log
  // otherwise save it
  return sb.join('');
};

/**
 * Formatter that returns formatted plain text
 *
 * @param {string=} opt_prefix The prefix to place before text records.
 * @constructor
 * @extends {goog.debug.Formatter}
 */
goog.debug.TextFormatter = function(opt_prefix) {
  goog.debug.Formatter.call(this, opt_prefix);
};
goog.inherits(goog.debug.TextFormatter, goog.debug.Formatter);

/**
 * Formats a record as text
 * @param {goog.debug.LogRecord} logRecord the logRecord to format.
 * @return {string} The formatted string.
 * @override
 */
goog.debug.TextFormatter.prototype.formatRecord = function(logRecord) {
  // Build message html
  var sb = [];
  sb.push(this.prefix_, ' ');
  if (this.showAbsoluteTime) {
    sb.push('[', goog.debug.Formatter.getDateTimeStamp_(logRecord), '] ');
  }
  if (this.showRelativeTime) {
    sb.push('[', goog.debug.Formatter.getRelativeTime_(logRecord,
        this.startTimeProvider_.get()), 's] ');
  }

  if (this.showLoggerName) {
    sb.push('[', logRecord.getLoggerName(), '] ');
  }
  if (this.showSeverityLevel) {
    sb.push('[', logRecord.getLevel().name, '] ');
  }
  sb.push(logRecord.getMessage(), '\n');
  if (this.showExceptionText && logRecord.getException()) {
    sb.push(logRecord.getExceptionText(), '\n');
  }
  // If the logger is enabled, open window and write html message to log
  // otherwise save it
  return sb.join('');
};
<|endoftext|>


<commit_before>// --------------------------------------------------
// Load Plugins
// --------------------------------------------------

var $             = require('gulp-load-plugins')();
var argv          = require('yargs').argv;
var autoprefixer  = require('gulp-autoprefixer');
var browserSync   = require('browser-sync');
var collect       = require('gulp-rev-collector');
var gulp          = require('gulp');
var notify        = require('gulp-notify');
var rev           = require('gulp-rev');
var rimraf        = require('rimraf');
var sequence      = require('run-sequence');
var sass          = require('gulp-sass');
var spawn         = require('child_process').spawn;

// --------------------------------------------------
// General Config
// --------------------------------------------------

// Check for --production flag
var isProduction = !!(argv.production);

// Browsers to target when prefixing CSS.
var COMPATIBILITY = ['last 2 versions', 'ie >= 9'];

// File paths to various assets are defined here.
var PATHS = {
  pages: [
    '*.{md,html,yml,xml}',
    '{_data,_includes,_layouts,_pages,_posts}/**/*.{md,html,yml,xml}',
    '!_site/**/*.*',
    '!assets/**/*.*'
  ],
  javascript: [
    // jQuery
    'assets/vendor/jquery/dist/jquery.js',
    // Foundation for Sites
    'assets/vendor/foundation-sites/js/foundation.core.js', // all F6 components need this!
    // 'assets/vendor/foundation-sites/js/foundation.abide.js',
    // 'assets/vendor/foundation-sites/js/foundation.accordion.js',
    // 'assets/vendor/foundation-sites/js/foundation.accordionMenu.js',
    // 'assets/vendor/foundation-sites/js/foundation.drilldown.js',
    // 'assets/vendor/foundation-sites/js/foundation.dropdown.js',
    // 'assets/vendor/foundation-sites/js/foundation.dropdownMenu.js',
    // 'assets/vendor/foundation-sites/js/foundation.equalizer.js',
    // 'assets/vendor/foundation-sites/js/foundation.interchange.js',
    // 'assets/vendor/foundation-sites/js/foundation.magellan.js',
    // 'assets/vendor/foundation-sites/js/foundation.offcanvas.js',
    // 'assets/vendor/foundation-sites/js/foundation.orbit.js',
    // 'assets/vendor/foundation-sites/js/foundation.responsiveMenu.js',
    // 'assets/vendor/foundation-sites/js/foundation.responsiveToggle.js',
    // 'assets/vendor/foundation-sites/js/foundation.reveal.js',
    // 'assets/vendor/foundation-sites/js/foundation.slider.js',
    // 'assets/vendor/foundation-sites/js/foundation.sticky.js',
    // 'assets/vendor/foundation-sites/js/foundation.tabs.js',
    // 'assets/vendor/foundation-sites/js/foundation.toggler.js',
    // 'assets/vendor/foundation-sites/js/foundation.tooltip.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.box.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.keyboard.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.mediaQuery.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.motion.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.nest.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.timerAndImageLoader.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.touch.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.triggers.js',
    // Foundation for Sites dependencies
    // 'assets/vendor/what-input/what-input.js',
    // Additional vendor JavaScript for the site

    // Site's JavaScript
    'assets/js/app.js'
  ],
  assets: [
    'assets/css/app.css',
    'assets/js/all.js',
  ]
};

// --------------------------------------------------
// Custom Messages
// --------------------------------------------------

/**
 * Adding custom messages to output to the browserSync status
 */
var messages = {
  jekyll: 'Running: jekyll',
  jekyllincremental: 'Running: jekyll incremental',
  sass: 'Running: sass',
  javascript: 'Running: javascript'
};

// --------------------------------------------------
// Helpers
// --------------------------------------------------

// Delete the "_site" folder
// This happens every time a build starts
gulp.task('clean', function(done) {
  rimraf('_site', done);
});

// --------------------------------------------------
// Sass
// --------------------------------------------------

/**
 * Compile Sass into CSS
 */
gulp.task('sass', function() {
  browserSync.notify(messages.sass);
  var minifycss = $.if(isProduction, $.minifyCss());

  return gulp.src('assets/scss/*.scss')
    .pipe($.sourcemaps.init())
    .pipe($.sass()
      .on('error', $.sass.logError))
    .pipe(autoprefixer(COMPATIBILITY))
    .pipe(minifycss)
    .pipe($.if(!isProduction, $.sourcemaps.write()))
    // for live injecting, for production builds we write the revised version
    .pipe($.if(!isProduction, gulp.dest('_site/assets/css/')))
    // for future jekyll builds
    .pipe(gulp.dest('assets/css/'))
    //auto-inject styles into browsers
    .pipe(browserSync.stream());
});

// --------------------------------------------------
// JavaScript
// --------------------------------------------------

/**
 * Concatenate and minify ALL the JavaScript files
 */

gulp.task('javascript', function() {
  browserSync.notify(messages.javascript);
  var uglify = $.if(isProduction, $.uglify()
    .on('error', function (e) {
      console.log(e);
    }));

  return gulp.src(PATHS.javascript)
    .pipe($.sourcemaps.init())
    .pipe($.concat('all.js'))
    .pipe($.if(isProduction, $.uglify({ mangle: false })))
    .pipe($.if(!isProduction, $.sourcemaps.write()))
    // for live injecting, for production builds we write the revised version
    .pipe($.if(!isProduction, gulp.dest('_site/assets/js/')))
    // for future jekyll builds
    .pipe(gulp.dest('assets/js/'));
});

// --------------------------------------------------
// Jekyll
// --------------------------------------------------

/**
 * Build the Jekyll Site (full site builds)
 */
gulp.task('jekyll-build', function(done) {
  browserSync.notify(messages.jekyll);
  // Spawn jekyll commands
  if (isProduction) {
    return spawn('bundle', ['exec', 'jekyll', 'build',
      '--config', '_config.yml,_config-production.yml'], {stdio: 'inherit'})
    .on('close', done);
  } else {
    return spawn('bundle', ['exec', 'jekyll', 'build'], {stdio: 'inherit'})
    .on('close', done);
  }
});

/**
 * Incremental jekyll build
 */
gulp.task('jekyll-incremental', function(done) {
  browserSync.notify(messages.jekyllincremental);
  // Spawn jekyll commands
  return spawn('bundle', ['exec', 'jekyll', 'build', '--incremental'], {stdio: 'inherit'})
  .on('close', done);
});

// --------------------------------------------------
// Browser Sync
// --------------------------------------------------

/**
 * Wait for jekyll-build, then launch the Server
 */
gulp.task('browser-sync', function() {
  browserSync.init({
    server: {
      baseDir: '_site/'
    },
    xip: true,
    notify: true,
    open: false
  });
});

// --------------------------------------------------
// Revisioning
// --------------------------------------------------

/**
 * Revision all asset files and
 * write a manifest file
 */

gulp.task('revision', function() {
    return gulp.src(PATHS.assets, {base: 'assets'})
      .pipe(rev())
      // write revised assets to build dir
      .pipe(gulp.dest('_site/assets'))
      .pipe(rev.manifest())
      // write manifest to jekyll root
      .pipe(gulp.dest('./'));
});

/**
 * Replace all links to assets in files
 * from a manifest file
 */
gulp.task('rev:collect', ['revision'], function() {
  return gulp.src(['./rev-manifest.json',
    '_site/*.{html,xml,txt,json,css,js}',
    '_site/**/*.{html,xml,txt,json,css,js}',
    '!_site/assets/vendor'])
  .pipe(collect())
  .pipe(gulp.dest('_site'));
});

// --------------------------------------------------
// Build
// --------------------------------------------------

gulp.task('build', function(done) {
  if(isProduction) {
    sequence('clean', ['sass', 'javascript'], 'jekyll-build', 'rev:collect', done);
  } else {
    sequence('clean', ['sass', 'javascript'], 'jekyll-build', done);
  }
});

// --------------------------------------------------
// Watch
// --------------------------------------------------

/**
 * Watch files for changes, recompile/rebuild and
 * reload the browser
 */
gulp.task('watch', function() {
  gulp.watch(PATHS.pages, ['jekyll-incremental', browserSync.reload]);
  gulp.watch('assets/img/**/*', ['jekyll-build', browserSync.reload]);
  //no browser reload needed here, browserSync injects the stylesheet into browsers
  gulp.watch('assets/scss/**/*.scss', ['sass']);
  gulp.watch('assets/js/app.js', ['javascript', browserSync.reload]);
});

// --------------------------------------------------
// Default
// --------------------------------------------------

/**
 * Default task, running just `gulp` will build the site and
 * launch BrowserSync and watch files.
 */
gulp.task('default', function(done) {
  sequence('build', 'browser-sync', 'watch', done);
});
<commit_msg>minor fix [ci skip]<commit_after>// --------------------------------------------------
// Load Plugins
// --------------------------------------------------

var $             = require('gulp-load-plugins')();
var argv          = require('yargs').argv;
var autoprefixer  = require('gulp-autoprefixer');
var browserSync   = require('browser-sync');
var collect       = require('gulp-rev-collector');
var gulp          = require('gulp');
var notify        = require('gulp-notify');
var rev           = require('gulp-rev');
var rimraf        = require('rimraf');
var sequence      = require('run-sequence');
var sass          = require('gulp-sass');
var spawn         = require('child_process').spawn;

// --------------------------------------------------
// General Config
// --------------------------------------------------

// Check for --production flag
var isProduction = !!(argv.production);

// Browsers to target when prefixing CSS.
var COMPATIBILITY = ['last 2 versions', 'ie >= 9'];

// File paths to various assets are defined here.
var PATHS = {
  pages: [
    '*.{md,html,yml,xml}',
    '{_data,_includes,_layouts,_pages,_posts}/**/*.{md,html,yml,xml}',
    '!_site/**/*.*',
    '!assets/**/*.*'
  ],
  javascript: [
    // jQuery
    'assets/vendor/jquery/dist/jquery.js',
    // Foundation for Sites
    'assets/vendor/foundation-sites/js/foundation.core.js', // all F6 components need this!
    // 'assets/vendor/foundation-sites/js/foundation.abide.js',
    // 'assets/vendor/foundation-sites/js/foundation.accordion.js',
    // 'assets/vendor/foundation-sites/js/foundation.accordionMenu.js',
    // 'assets/vendor/foundation-sites/js/foundation.drilldown.js',
    // 'assets/vendor/foundation-sites/js/foundation.dropdown.js',
    // 'assets/vendor/foundation-sites/js/foundation.dropdownMenu.js',
    // 'assets/vendor/foundation-sites/js/foundation.equalizer.js',
    // 'assets/vendor/foundation-sites/js/foundation.interchange.js',
    // 'assets/vendor/foundation-sites/js/foundation.magellan.js',
    // 'assets/vendor/foundation-sites/js/foundation.offcanvas.js',
    // 'assets/vendor/foundation-sites/js/foundation.orbit.js',
    // 'assets/vendor/foundation-sites/js/foundation.responsiveMenu.js',
    // 'assets/vendor/foundation-sites/js/foundation.responsiveToggle.js',
    // 'assets/vendor/foundation-sites/js/foundation.reveal.js',
    // 'assets/vendor/foundation-sites/js/foundation.slider.js',
    // 'assets/vendor/foundation-sites/js/foundation.sticky.js',
    // 'assets/vendor/foundation-sites/js/foundation.tabs.js',
    // 'assets/vendor/foundation-sites/js/foundation.toggler.js',
    // 'assets/vendor/foundation-sites/js/foundation.tooltip.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.box.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.keyboard.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.mediaQuery.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.motion.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.nest.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.timerAndImageLoader.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.touch.js',
    // 'assets/vendor/foundation-sites/js/foundation.util.triggers.js',
    // Foundation for Sites dependencies
    // 'assets/vendor/what-input/what-input.js',
    // Additional vendor JavaScript for the site

    // Site's JavaScript
    'assets/js/app.js'
  ],
  assets: [
    'assets/css/app.css',
    'assets/js/all.js',
  ]
};

// --------------------------------------------------
// Custom Messages
// --------------------------------------------------

/**
 * Adding custom messages to output to the browserSync status
 */
var messages = {
  jekyll: 'Running: jekyll',
  jekyllincremental: 'Running: jekyll incremental',
  sass: 'Running: sass',
  javascript: 'Running: javascript'
};

// --------------------------------------------------
// Helpers
// --------------------------------------------------

// Delete the "_site" folder
// This happens every time a build starts
gulp.task('clean', function(done) {
  rimraf('_site', done);
});

// --------------------------------------------------
// Sass
// --------------------------------------------------

/**
 * Compile Sass into CSS
 */
gulp.task('sass', function() {
  browserSync.notify(messages.sass);
  var minifycss = $.if(isProduction, $.minifyCss());

  return gulp.src('assets/scss/*.scss')
    .pipe($.sourcemaps.init())
    .pipe($.sass()
      .on('error', $.sass.logError))
    .pipe(autoprefixer(COMPATIBILITY))
    .pipe(minifycss)
    .pipe($.if(!isProduction, $.sourcemaps.write()))
    // for live injecting, for production builds we write the revised version
    .pipe($.if(!isProduction, gulp.dest('_site/assets/css/')))
    // for future jekyll builds
    .pipe(gulp.dest('assets/css/'))
    //auto-inject styles into browsers
    .pipe(browserSync.stream());
});

// --------------------------------------------------
// JavaScript
// --------------------------------------------------

/**
 * Concatenate and minify ALL the JavaScript files
 */

gulp.task('javascript', function() {
  browserSync.notify(messages.javascript);
  var uglify = $.if(isProduction, $.uglify()
    .on('error', function (e) {
      console.log(e);
    }));

  return gulp.src(PATHS.javascript)
    .pipe($.sourcemaps.init())
    .pipe($.concat('all.js'))
    .pipe($.if(isProduction, $.uglify({ mangle: false })))
    .pipe($.if(!isProduction, $.sourcemaps.write()))
    // for live injecting, for production builds we write the revised version
    .pipe($.if(!isProduction, gulp.dest('_site/assets/js/')))
    // for future jekyll builds
    .pipe(gulp.dest('assets/js/'));
});

// --------------------------------------------------
// Jekyll
// --------------------------------------------------

/**
 * Build the Jekyll Site (full site builds)
 */
gulp.task('jekyll-build', function(done) {
  browserSync.notify(messages.jekyll);
  // Spawn jekyll commands
  if (isProduction) {
    return spawn('bundle', ['exec', 'jekyll', 'build',
      '--config', '_config.yml,_config-production.yml'], {stdio: 'inherit'})
    .on('close', done);
  } else {
    return spawn('bundle', ['exec', 'jekyll', 'build'], {stdio: 'inherit'})
    .on('close', done);
  }
});

/**
 * Incremental jekyll build
 */
gulp.task('jekyll-incremental', function(done) {
  browserSync.notify(messages.jekyllincremental);
  // Spawn jekyll commands
  return spawn('bundle', ['exec', 'jekyll', 'build', '--incremental'], {stdio: 'inherit'})
  .on('close', done);
});

// --------------------------------------------------
// Browser Sync
// --------------------------------------------------

/**
 * Wait for jekyll-build, then launch the Server
 */
gulp.task('browser-sync', function() {
  browserSync.init({
    server: {
      baseDir: '_site/'
    },
    xip: true,
    notify: true,
    open: false
  });
});

// --------------------------------------------------
// Revisioning
// --------------------------------------------------

/**
 * Revision all asset files and
 * write a manifest file
 */

gulp.task('revision', function() {
    return gulp.src(PATHS.assets, {base: 'assets'})
      .pipe(rev())
      // write revised assets to build dir
      .pipe(gulp.dest('_site/assets'))
      .pipe(rev.manifest())
      // write manifest to jekyll root
      .pipe(gulp.dest('./'));
});

/**
 * Replace all links to assets in files
 * from a manifest file
 */
gulp.task('rev:collect', ['revision'], function() {
  return gulp.src(['./rev-manifest.json',
    '_site/*.{html,xml,txt,json,css,js}',
    '_site/**/*.{html,xml,txt,json,css,js}',
    '!_site/assets/vendor'])
  .pipe(collect())
  .pipe(gulp.dest('_site'));
});

// --------------------------------------------------
// Build
// --------------------------------------------------

gulp.task('build', function(done) {
  if(isProduction) {
    sequence('clean', ['sass', 'javascript'], 'jekyll-build', 'rev:collect', done);
  } else {
    sequence('clean', ['sass', 'javascript'], 'jekyll-build', done);
  }
});

// --------------------------------------------------
// Watch
// --------------------------------------------------

/**
 * Watch files for changes, recompile/rebuild and
 * reload the browser
 */
gulp.task('watch', function() {
  gulp.watch(PATHS.pages, ['jekyll-incremental', browserSync.reload]);
  gulp.watch('assets/img/**/*', ['jekyll-incremental', browserSync.reload]);
  //no browser reload needed here, browserSync injects the stylesheet into browsers
  gulp.watch('assets/scss/**/*.scss', ['sass']);
  gulp.watch('assets/js/app.js', ['javascript', browserSync.reload]);
});

// --------------------------------------------------
// Default
// --------------------------------------------------

/**
 * Default task, running just `gulp` will build the site and
 * launch BrowserSync and watch files.
 */
gulp.task('default', function(done) {
  sequence('build', 'browser-sync', 'watch', done);
});
<|endoftext|>


<commit_before>define(['jquery', 'underscore', 'backbone',
	'text!./app/views/templates/search-empty.html',
	'text!./app/views/templates/search-listing.html',
	'text!./app/views/templates/search-listings.html',
	'text!./app/views/templates/add-listing.html',
	'models', 'utils'], function($, _, Backbone, emptySearchTemplate, searchListingTemplate, searchContainerTemplate, addListingTemplate, Models, Utils) {
	var Views = {};

	Views.AddItemModal = Backbone.View.extend({
		template: _.template(addListingTemplate),

		initialize: function() {
			this.render();
		},

		render: function() {
			this.$el.html(this.template(this.model.attributes));
		},

		events: {
			"click button.btn-success": "submitRequest",
			"click button.btn-danger": "closeModal"
		},

		submitRequest: function() {
			var country = $('select.form-control').val();
			var city = $('#inputPickupCity').val();
			var locationCombined = city + ", " + country;

			// JS uses milliseconds, we need seconds.
			var dateStart = Math.floor(Date.now() / 1000);

			var inputDate = $('#inputExpiryDate').val();
			var dateEnd = (new Date(inputDate)).getTime() / 1000;

			var that = this;
			$.ajax({
				url: '/service/listings/create',
				dataType: 'json',
				type: 'POST',
				data: {
					product_id: this.model.attributes.id,
					date_start: dateStart,
					date_expire: dateEnd,
					location: locationCombined
				},
				success: function() {
					$('#add-listing-modal').modal('hide');
					that.trigger("viewClosed");
				},
				error: function() {
					alert("Oops, something went wrong. Try sending your request again!");
				}
			});
		},

		closeModal: function() {
			this.trigger("viewClosed");
		}
	});

	Views.SearchResult = Backbone.View.extend({
		template: _.template(searchListingTemplate),

		events: {
			"click a.search-result": "clickResult"
		},

		clickResult: function() {
			if (this.modal) {
				this.disposeModal();
			}

			this.modal = new Views.AddItemModal({
				model: this.model,
				el: '#modal-container'
			});
			this.listenTo(this.modal, 'viewClosed', this.disposeModal);
			$('#add-listing-modal').modal('show');
		},

		initialize: function() {
			this.listenTo(this.model, "change", this.render);
			this.id = "search-" + this.model.attributes.id;
		},

		render: function() {
			this.$el.html(this.template(this.model.attributes));
			return this;
		},

		disposeModal: function() {
			this.modal.undelegateEvents();
		}
	});

	Views.SearchResultListing = Backbone.View.extend({
		initialize: function() {
			this.listenTo(this.collection, 'add', this.collectionAdded);
			this.listenTo(this.collection, 'change', this.collectionChanged);
			this.listenTo(this.collection, 'remove', this.collectionRemoved);

			this.childViews = [];

			this._addAllModels();
		},

		render: function() {
			var fragment = document.createDocumentFragment();

			if (this.childViews.length > 0) {
				_(this.childViews).each(function(currentView) {
					fragment.appendChild(currentView.render().el);
				});
			} else {
				$(emptySearchTemplate).appendTo(fragment);
			}

			this.$el.html(fragment);
			return this;
		},

		collectionAdded: function(item) {
			this._addViewForModel(item);
			this.render();
		},

		collectionRemoved: function(item) {
			this.childViews = this.childViews.filter(function(view) {
				return view.model.id !== item.id;
			});
			this.render();
		},

		collectionChanged: function() {
			this.childViews = [];
			this._addAllModels();
		},

		_addViewForModel: function(item) {
			this.childViews.push(new Views.SearchResult({
				model: item
			}));
		},

		_addAllModels: function() {
			var that = this;
			this.collection.each(function(item) {
				that._addViewForModel(item);
			});
			this.render();
		}
	});

	Views.SearchSession = Backbone.View.extend({
		events: {
			"click button.close": "clickClose"
		},
		initialize: function() {
			var escapedSearchTerm = Utils.urlencode(Utils.urlencode(this.options.searchTerm));
			var productSearchUrl = '/service/products/search/' + escapedSearchTerm;
			var productResultCollection = new Models.ProductSearchResults([], {
				url: productSearchUrl
			});
			this.productSearchResultView = new Views.SearchResultListing({
				collection: productResultCollection
			});

			var listingSearchUrl = '/service/listings/search/' + escapedSearchTerm;
			var listingResultCollection = new Models.Wants([], {
				url: listingSearchUrl
			});
			this.listingSearchResultView = new Views.ListingView({
				collection: listingResultCollection
			});

			this.render();
		},

		render: function() {
			this.$el.html(_.template(searchContainerTemplate, {
				searchTerm: this.options.searchTerm
			}));

			this.productSearchResultView.setElement('#product-listing');
			this.productSearchResultView.render();

			this.listingSearchResultView.setElement('#request-listing');
			this.listingSearchResultView.render();

			$('#search-section').fadeIn();
		},

		clickClose: function() {
			this.trigger("goHome");
		}
	});

	Views.SearchForm = Backbone.View.extend({
		events: {
			"click a#btn-search": "searchClick",
            "keypress input[type=text]": "keypress"
		},

        keypress: function(e) {
            switch (e.keyCode) {
                case 13:
                this.searchClick();
            }
        },

		searchClick: function() {
			var searchListingView = new Views.SearchSession({
				searchTerm: $('#txt-search').val()
			});

			this.trigger('changeView', searchListingView);
		},

		initialize: function() {}
	});

	return Views;
});<commit_msg>Fix search View dependency issue.<commit_after>define(['jquery', 'underscore', 'backbone',
	'text!./app/views/templates/search-empty.html',
	'text!./app/views/templates/search-listing.html',
	'text!./app/views/templates/search-listings.html',
	'text!./app/views/templates/add-listing.html',
	'models', 'utils'], function($, _, Backbone, emptySearchTemplate, searchListingTemplate, searchContainerTemplate, addListingTemplate, Models, Utils) {
	Views.AddItemModal = Backbone.View.extend({
		template: _.template(addListingTemplate),

		initialize: function() {
			this.render();
		},

		render: function() {
			this.$el.html(this.template(this.model.attributes));
		},

		events: {
			"click button.btn-success": "submitRequest",
			"click button.btn-danger": "closeModal"
		},

		submitRequest: function() {
			var country = $('select.form-control').val();
			var city = $('#inputPickupCity').val();
			var locationCombined = city + ", " + country;

			// JS uses milliseconds, we need seconds.
			var dateStart = Math.floor(Date.now() / 1000);

			var inputDate = $('#inputExpiryDate').val();
			var dateEnd = (new Date(inputDate)).getTime() / 1000;

			var that = this;
			$.ajax({
				url: '/service/listings/create',
				dataType: 'json',
				type: 'POST',
				data: {
					product_id: this.model.attributes.id,
					date_start: dateStart,
					date_expire: dateEnd,
					location: locationCombined
				},
				success: function() {
					$('#add-listing-modal').modal('hide');
					that.trigger("viewClosed");
				},
				error: function() {
					alert("Oops, something went wrong. Try sending your request again!");
				}
			});
		},

		closeModal: function() {
			this.trigger("viewClosed");
		}
	});

	Views.SearchResult = Backbone.View.extend({
		template: _.template(searchListingTemplate),

		events: {
			"click a.search-result": "clickResult"
		},

		clickResult: function() {
			if (this.modal) {
				this.disposeModal();
			}

			this.modal = new Views.AddItemModal({
				model: this.model,
				el: '#modal-container'
			});
			this.listenTo(this.modal, 'viewClosed', this.disposeModal);
			$('#add-listing-modal').modal('show');
		},

		initialize: function() {
			this.listenTo(this.model, "change", this.render);
			this.id = "search-" + this.model.attributes.id;
		},

		render: function() {
			this.$el.html(this.template(this.model.attributes));
			return this;
		},

		disposeModal: function() {
			this.modal.undelegateEvents();
		}
	});

	Views.SearchResultListing = Backbone.View.extend({
		initialize: function() {
			this.listenTo(this.collection, 'add', this.collectionAdded);
			this.listenTo(this.collection, 'change', this.collectionChanged);
			this.listenTo(this.collection, 'remove', this.collectionRemoved);

			this.childViews = [];

			this._addAllModels();
		},

		render: function() {
			var fragment = document.createDocumentFragment();

			if (this.childViews.length > 0) {
				_(this.childViews).each(function(currentView) {
					fragment.appendChild(currentView.render().el);
				});
			} else {
				$(emptySearchTemplate).appendTo(fragment);
			}

			this.$el.html(fragment);
			return this;
		},

		collectionAdded: function(item) {
			this._addViewForModel(item);
			this.render();
		},

		collectionRemoved: function(item) {
			this.childViews = this.childViews.filter(function(view) {
				return view.model.id !== item.id;
			});
			this.render();
		},

		collectionChanged: function() {
			this.childViews = [];
			this._addAllModels();
		},

		_addViewForModel: function(item) {
			this.childViews.push(new Views.SearchResult({
				model: item
			}));
		},

		_addAllModels: function() {
			var that = this;
			this.collection.each(function(item) {
				that._addViewForModel(item);
			});
			this.render();
		}
	});

	Views.SearchSession = Backbone.View.extend({
		events: {
			"click button.close": "clickClose"
		},
		initialize: function() {
			var escapedSearchTerm = Utils.urlencode(Utils.urlencode(this.options.searchTerm));
			var productSearchUrl = '/service/products/search/' + escapedSearchTerm;
			var productResultCollection = new Models.ProductSearchResults([], {
				url: productSearchUrl
			});
			this.productSearchResultView = new Views.SearchResultListing({
				collection: productResultCollection
			});

			var listingSearchUrl = '/service/listings/search/' + escapedSearchTerm;
			var listingResultCollection = new Models.Wants([], {
				url: listingSearchUrl
			});
			this.listingSearchResultView = new Views.ListingView({
				collection: listingResultCollection
			});

			this.render();
		},

		render: function() {
			this.$el.html(_.template(searchContainerTemplate, {
				searchTerm: this.options.searchTerm
			}));

			this.productSearchResultView.setElement('#product-listing');
			this.productSearchResultView.render();

			this.listingSearchResultView.setElement('#request-listing');
			this.listingSearchResultView.render();

			$('#search-section').fadeIn();
		},

		clickClose: function() {
			this.trigger("goHome");
		}
	});

	Views.SearchForm = Backbone.View.extend({
		events: {
			"click a#btn-search": "searchClick",
            "keypress input[type=text]": "keypress"
		},

        keypress: function(e) {
            switch (e.keyCode) {
                case 13:
                this.searchClick();
            }
        },

		searchClick: function() {
			var searchListingView = new Views.SearchSession({
				searchTerm: $('#txt-search').val()
			});

			this.trigger('changeView', searchListingView);
		},

		initialize: function() {}
	});

	return Views;
});<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import THREE from 'three';
import CANNON from 'cannon/src/Cannon';
import { lerp } from '../../helpers/Utils';

const rayCount = 4;
const maxLength = 10;

// dam son see http://stackoverflow.com/questions/5501581/javascript-new-arrayn-and-array-prototype-map-weirdness
const rayArray = new Array( rayCount ).fill( 0 );
const emitterPosition = new THREE.Vector3( -0.5, 0, 0 );
const emitterScale = new THREE.Vector3( 0.1, 1, 1 );
const colRotation = new THREE.Euler( -Math.PI / 2, 0, Math.PI / 2 );
const axis = new THREE.Vector3( 0, 1, 0 );

const bubbleMinSize = 0.5;
const foamGrowSize = 0.3;
const foamGrowSpeed = 5.2;
const foamSpeed = 4.2;

const defaultImpulse = 20.0;

const minimumPercentToShowFoam = 0.9;

const raycaster = new THREE.Raycaster();

export default class Waterfall extends Component {

    static propTypes = {
        position: PropTypes.object.isRequired,
        rotation: PropTypes.object,
        scale: PropTypes.object,
        world: PropTypes.object,
        paused: PropTypes.bool,
        time: PropTypes.number,
        playerRadius: PropTypes.number,
    }

    constructor( props, context ) {

        super( props, context );

        this.state = {
            lengths: rayArray.map( () => 1 ),
            lengthTargets: rayArray.map( () => 1 ),
            counter: 0,
            impulse: ( props.impulse || defaultImpulse ) / Math.pow( 1 / props.scale.x, 3 ),
            //fromVector, toVector
        };
        this._onUpdate = this._onUpdate.bind( this );

    }

    _onUpdate() {

        const { world, position, paused, playerRadius, rotation } = this.props;
        const {
            counter, impulse,
            lengths: oldLengths,
            lengthTargets: oldLengthTargets,
            //fromVector, toVector
        } = this.state;

        const angle = new THREE.Euler().setFromQuaternion( rotation ).y;

        if( world && !paused ) {

            let lengthTargets = oldLengthTargets;

            lengthTargets = rayArray.map( ( zero, index ) => {
                const result = new CANNON.RaycastResult();

                const fromVector = new THREE.Vector3(
                    -0.499,
                    -0.5 + ( playerRadius || 0.45 ),
                    -0.5 + ( ( 1 / rayCount ) * index ) + ( 0.5 / rayCount )
                );

                const toVector = new THREE.Vector3(
                    fromVector.x + maxLength,
                    fromVector.y,
                    fromVector.z,
                );

                world.rayTest(
                    fromVector.applyAxisAngle( axis, angle ).add( position ),
                    toVector.applyAxisAngle( axis, angle ).add( position ),
                    result
                );

                const { hasHit, body, distance, hitPointWorld } = result;

                if( hasHit ) {

                    const { mass, position: bodyPosition, } = body;
                    if( mass ) {
                        body.applyImpulse(
                            new THREE.Vector3( impulse, 0, 0 ).applyAxisAngle( axis, angle ),
                            new CANNON.Vec3( 0, 0, 0 )
                        );
                    }
                    return distance;

                } else {

                    return maxLength;

                }

            });

            const lengths = oldLengths.map( ( length, index ) => {
                const target = lengthTargets[ index ];
                return target > length ? Math.min( length + 0.2, target ) : target;
            });

            this.setState({
                counter: counter + 1,
                lengths, lengthTargets
            });

        }

    }

    render() {

        const {
            position, rotation, scale, time, materialId, playerRadius
        } = this.props;
        const { lengths, lengthTargets } = this.state;
        const waterfallHeight = -0.5 + ( playerRadius || 0.45 );

        return <group
            position={ position }
            quaternion={ rotation || new THREE.Quaternion( 0, 0, 0, 1 ) }
            scale={ scale }
            onUpdate={ this._onUpdate }
        >
            <mesh
                ref="mesh"
                position={ emitterPosition }
                scale={ emitterScale }
            >
                <geometryResource
                    resourceId="1x1box"
                />
                <materialResource
                    resourceId="transparent"
                />
            </mesh>

            {/* Foam */}
            { rayArray.map( ( zero, index ) => {

                const length = lengths[ index ];
                const target = lengthTargets[ index ];
                const percentToTarget = Math.max(
                    ( 1.0 - ( Math.abs( target - length ) / target ) ) - minimumPercentToShowFoam,
                    0
                ) * ( 1 / ( 1 - minimumPercentToShowFoam ) );

                return <group
                    key={ index }
                    position={ new THREE.Vector3(
                        -0.5 + length,
                        waterfallHeight,
                        -0.5 + ( ( 1 / rayCount ) * index ) + ( 0.5 / rayCount ),
                    ) }
                    scale={
                        new THREE.Vector3( 1, 1, 1 ).multiplyScalar( 1 / rayCount )
                    }
                >
                    <mesh
                        position={ new THREE.Vector3(
                            0, 0, -0.25
                        ) }
                        scale={
                            new THREE.Vector3( 1, 1, 1 )
                                .multiplyScalar(
                                    ( bubbleMinSize * 2 + foamGrowSize * Math.sin( foamGrowSpeed * time * 0.6 - index ) ) *
                                    percentToTarget
                                )
                        }
                        rotation={ new THREE.Euler(
                            ( foamSpeed * time - index ) * 0.1,
                            ( foamSpeed * time + index ) * 1.1,
                            foamSpeed * time
                        )}
                    >
                        <geometryResource
                            resourceId="radius1sphere"
                        />
                        <materialResource
                            resourceId="waterFoam"
                        />
                    </mesh>
                    <mesh
                        position={ new THREE.Vector3(
                            0, 0, 0.25
                        ) }
                        scale={
                            new THREE.Vector3( 1, 1, 1 )
                                .multiplyScalar(
                                    ( bubbleMinSize * 2 + foamGrowSize * Math.cos( foamGrowSpeed * time * 1.2 + index ) ) *
                                    percentToTarget
                                )
                        }
                        rotation={ new THREE.Euler(
                            ( foamSpeed * time + index ) * 0.6,
                            foamSpeed * time,
                            ( foamSpeed * time + index ) * 1.2,
                        )}
                    >
                        <geometryResource
                            resourceId="radius1sphere"
                        />
                        <materialResource
                            resourceId="waterFoam"
                        />
                    </mesh>
                </group>;

            })}

            {/* Waterfalls */}
            { rayArray.map( ( zero, index ) =>
                <mesh
                    key={ index }
                    position={ new THREE.Vector3(
                        -0.5 + ( lengths[ index ] / 2 ),
                        waterfallHeight,
                        -0.5 + ( ( 1 / rayCount ) * index ) + ( 0.5 / rayCount )
                    ) }
                    scale={ new THREE.Vector3(
                        1 / rayCount,
                        lengths[ index ],
                        1,
                    ) }
                    rotation={ colRotation }
                >
                    <geometryResource
                        resourceId="1x1plane"
                    />
                    <materialResource
                        resourceId={ materialId }
                    />
                </mesh>
            )}

        </group>;

    }

}
<commit_msg>damn damneil :(<commit_after>import React, { Component, PropTypes } from 'react';
import THREE from 'three';
import CANNON from 'cannon/src/Cannon';
import { lerp } from '../../helpers/Utils';

// Waterfall configuration
const rayCount = 4;
const maxLength = 10;

const bubbleMinSize = 0.5;
const foamGrowSize = 0.3;
const foamGrowSpeed = 5.2;
const foamSpeed = 4.2;

const defaultImpulse = 20.0;
const minimumPercentToShowFoam = 0.9;

// Computed values

// dam son see http://stackoverflow.com/questions/5501581/javascript-new-arrayn-and-array-prototype-map-weirdness
const rayArray = new Array( rayCount ).fill( 0 );
const emitterPosition = new THREE.Vector3( -0.5, 0, 0 );
const emitterScale = new THREE.Vector3( 0.1, 1, 1 );
const colRotation = new THREE.Euler( -Math.PI / 2, 0, Math.PI / 2 );
const axis = new THREE.Vector3( 0, 1, 0 );

const raycaster = new THREE.Raycaster();

export default class Waterfall extends Component {

    static propTypes = {
        position: PropTypes.object.isRequired,
        rotation: PropTypes.object,
        scale: PropTypes.object,
        world: PropTypes.object,
        paused: PropTypes.bool,
        time: PropTypes.number,
        playerRadius: PropTypes.number,
    }

    constructor( props, context ) {

        super( props, context );

        this.state = this.getStateFromProps( props, {} );

        this._onUpdate = this._onUpdate.bind( this );

    }

    componentWillReceiveProps( nextProps ) {

        if( ( nextProps.playerRadius !== this.props.playerRadius ) ||
           ( nextProps.rotation !== this.props.rotation ) ||
           ( nextProps.position !== this.props.position )
        ) {

            this.setState( this.getStateFromProps( nextProps, this.state ) );

        }

    }

    getStateFromProps( props, state ) {

        const { position, rotation, playerRadius, scale } = props;
        const angle = new THREE.Euler().setFromQuaternion( rotation ).y;
        const impulse = ( defaultImpulse / Math.pow( 1 / scale.x, 3 ) ) * ( playerRadius / 0.45 );
        console.log('impulse',impulse);

        return {
            lengths: state.lengths || rayArray.map( () => 1 ),
            lengthTargets: state.lengths || rayArray.map( () => 1 ),
            counter: 0,
            hitVectors: rayArray.map( ( zero, index ) => {

                const fromVector = new THREE.Vector3(
                    -0.499,
                    -0.5 + ( playerRadius || 0.45 ),
                    -0.5 + ( ( 1 / rayCount ) * index ) + ( 0.5 / rayCount )
                );

                const toVector = new THREE.Vector3(
                    fromVector.x + maxLength,
                    fromVector.y,
                    fromVector.z,
                );

                return {
                    fromVector: fromVector.applyAxisAngle( axis, angle ).add( position ),
                    toVector: toVector.applyAxisAngle( axis, angle ).add( position ),
                    impulseVector: new THREE.Vector3( impulse, 0, 0 ).applyAxisAngle( axis, angle ),
                };

            })
        };

    }

    _onUpdate() {

        const { world, position, paused } = this.props;
        const {
            counter,
            lengths: oldLengths,
            lengthTargets: oldLengthTargets,
            hitVectors,
        } = this.state;

        if( world && !paused ) {

            let lengthTargets = oldLengthTargets;

            lengthTargets = rayArray.map( ( zero, index ) => {
                const result = new CANNON.RaycastResult();

                world.rayTest(
                    hitVectors[ index ].fromVector,
                    hitVectors[ index ].toVector,
                    result
                );

                const { hasHit, body, distance, hitPointWorld } = result;

                if( hasHit ) {

                    const { mass, position: bodyPosition, } = body;
                    if( mass ) {
                        body.applyImpulse(
                            hitVectors[ index ].impulseVector,
                            new CANNON.Vec3( 0, 0, 0 )
                        );
                    }
                    return distance;

                } else {

                    return maxLength;

                }

            });

            const lengths = oldLengths.map( ( length, index ) => {
                const target = lengthTargets[ index ];
                return target > length ? Math.min( length + 0.2, target ) : target;
            });

            this.setState({
                counter: counter + 1,
                lengths, lengthTargets
            });

        }

    }

    render() {

        const {
            position, rotation, scale, time, materialId, playerRadius
        } = this.props;
        const { lengths, lengthTargets } = this.state;
        const waterfallHeight = -0.5 + ( playerRadius || 0.45 );

        return <group
            position={ position }
            quaternion={ rotation || new THREE.Quaternion( 0, 0, 0, 1 ) }
            scale={ scale }
            onUpdate={ this._onUpdate }
        >
            <mesh
                ref="mesh"
                position={ emitterPosition }
                scale={ emitterScale }
            >
                <geometryResource
                    resourceId="1x1box"
                />
                <materialResource
                    resourceId="transparent"
                />
            </mesh>

            {/* Foam */}
            { rayArray.map( ( zero, index ) => {

                const length = lengths[ index ];
                const target = lengthTargets[ index ];
                const percentToTarget = Math.max(
                    ( 1.0 - ( Math.abs( target - length ) / target ) ) - minimumPercentToShowFoam,
                    0
                ) * ( 1 / ( 1 - minimumPercentToShowFoam ) );

                return <group
                    key={ index }
                    position={ new THREE.Vector3(
                        -0.5 + length,
                        waterfallHeight,
                        -0.5 + ( ( 1 / rayCount ) * index ) + ( 0.5 / rayCount ),
                    ) }
                    scale={
                        new THREE.Vector3( 1, 1, 1 ).multiplyScalar( 1 / rayCount )
                    }
                >
                    <mesh
                        position={ new THREE.Vector3(
                            0, 0, -0.25
                        ) }
                        scale={
                            new THREE.Vector3( 1, 1, 1 )
                                .multiplyScalar(
                                    ( bubbleMinSize * 2 + foamGrowSize * Math.sin( foamGrowSpeed * time * 0.6 - index ) ) *
                                    percentToTarget
                                )
                        }
                        rotation={ new THREE.Euler(
                            ( foamSpeed * time - index ) * 0.1,
                            ( foamSpeed * time + index ) * 1.1,
                            foamSpeed * time
                        )}
                    >
                        <geometryResource
                            resourceId="radius1sphere"
                        />
                        <materialResource
                            resourceId="waterFoam"
                        />
                    </mesh>
                    <mesh
                        position={ new THREE.Vector3(
                            0, 0, 0.25
                        ) }
                        scale={
                            new THREE.Vector3( 1, 1, 1 )
                                .multiplyScalar(
                                    ( bubbleMinSize * 2 + foamGrowSize * Math.cos( foamGrowSpeed * time * 1.2 + index ) ) *
                                    percentToTarget
                                )
                        }
                        rotation={ new THREE.Euler(
                            ( foamSpeed * time + index ) * 0.6,
                            foamSpeed * time,
                            ( foamSpeed * time + index ) * 1.2,
                        )}
                    >
                        <geometryResource
                            resourceId="radius1sphere"
                        />
                        <materialResource
                            resourceId="waterFoam"
                        />
                    </mesh>
                </group>;

            })}

            {/* Waterfalls */}
            { rayArray.map( ( zero, index ) =>
                <mesh
                    key={ index }
                    position={ new THREE.Vector3(
                        -0.5 + ( lengths[ index ] / 2 ),
                        waterfallHeight,
                        -0.5 + ( ( 1 / rayCount ) * index ) + ( 0.5 / rayCount )
                    ) }
                    scale={ new THREE.Vector3(
                        1 / rayCount,
                        lengths[ index ],
                        1,
                    ) }
                    rotation={ colRotation }
                >
                    <geometryResource
                        resourceId="1x1plane"
                    />
                    <materialResource
                        resourceId={ materialId }
                    />
                </mesh>
            )}

        </group>;

    }

}
<|endoftext|>


<commit_before>var timer, status;

UserPresence = {
	awayTime: 60000, //1 minute
	awayOnWindowBlur: false,

	startTimer: function() {
		UserPresence.stopTimer();
		timer = setTimeout(UserPresence.setAway, UserPresence.awayTime);
	},
	stopTimer: function() {
		clearTimeout(timer);
	},
	restartTimer: function() {
		UserPresence.startTimer();
	},
	setAway: function() {
		if (status !== 'away') {
			status = 'away';
			Meteor.call('UserPresence:away');
		}
		UserPresence.stopTimer();
	},
	setOnline: function() {
		if (status !== 'online') {
			status = 'online';
			Meteor.call('UserPresence:online');
		}
		UserPresence.startTimer();
	},
	start: function() {
		Deps.autorun(function() {
			var user = Meteor.user();
			status = user && user.statusConnection;
			UserPresence.startTimer();
		});

		Meteor.methods({
			'UserPresence:setDefaultStatus': function(status) {
				Meteor.users.update({_id: Meteor.userId()}, {$set: {status: status, statusDefault: status}});
			},
			'UserPresence:online': function() {
				var user = Meteor.user();
				if (user && user.statusDefault === 'online') {
					Meteor.users.update({_id: Meteor.userId()}, {$set: {status: 'online'}});
				}
			}
		});

		document.addEventListener('mousemove', UserPresence.setOnline);
		document.addEventListener('mousedown', UserPresence.setOnline);
		document.addEventListener('keydown', UserPresence.setOnline);
		window.addEventListener('focus', UserPresence.setOnline);

		if (UserPresence.awayOnWindowBlur === true) {
			window.addEventListener('blur', UserPresence.setAway);
		}
	}
}
<commit_msg>Add callback *onSetUserStatus* to watch status changes<commit_after>var timer, status;

UserPresence = {
	awayTime: 60000, //1 minute
	awayOnWindowBlur: false,
	onSetUserStatus: function() {},

	startTimer: function() {
		UserPresence.stopTimer();
		timer = setTimeout(UserPresence.setAway, UserPresence.awayTime);
	},
	stopTimer: function() {
		clearTimeout(timer);
	},
	restartTimer: function() {
		UserPresence.startTimer();
	},
	setAway: function() {
		if (status !== 'away') {
			status = 'away';
			Meteor.call('UserPresence:away');
		}
		UserPresence.stopTimer();
	},
	setOnline: function() {
		if (status !== 'online') {
			status = 'online';
			Meteor.call('UserPresence:online');
		}
		UserPresence.startTimer();
	},
	start: function() {
		Deps.autorun(function() {
			var user = Meteor.user();
			status = user && user.statusConnection;
			UserPresence.startTimer();
		});

		Meteor.methods({
			'UserPresence:setDefaultStatus': function(status) {
				Meteor.users.update({_id: Meteor.userId()}, {$set: {status: status, statusDefault: status}});
			},
			'UserPresence:online': function() {
				var user = Meteor.user();
				if (user && user.statusDefault === 'online') {
					Meteor.users.update({_id: Meteor.userId()}, {$set: {status: 'online'}});
				}
				UserPresence.onSetUserStatus(user, 'online');
			},
			'UserPresence:away': function() {
				var user = Meteor.user();
				UserPresence.onSetUserStatus(user, 'away');
			}
		});

		document.addEventListener('mousemove', UserPresence.setOnline);
		document.addEventListener('mousedown', UserPresence.setOnline);
		document.addEventListener('keydown', UserPresence.setOnline);
		window.addEventListener('focus', UserPresence.setOnline);

		if (UserPresence.awayOnWindowBlur === true) {
			window.addEventListener('blur', UserPresence.setAway);
		}
	}
}
<|endoftext|>