<commit_before>'use strict';

var sinon = require('sinon');
var net = require('net');
var sendCommandToSocket = require('../lib/base/communication').sendCommandToSocket;

// Monkey patch to help with debugging Buffer comparison assertions
(function(BufferToString) {
    Buffer.prototype.toString = function(encoding) {
        if (encoding === undefined) {
            var array = [];
            for (var i = 0; i < this.length; i++) {
                var hex = this[i].toString(16);
                if (this[i] < 0x10) {
                    hex = '0' + hex;
                }
                array.push('0x' + hex);
            }
            return '[' + array.join(', ') + ']';
        } else {
            return BufferToString.apply(this, arguments);
        }
    };
})(Buffer.prototype.toString);

describe('Communication Test', function () {

    describe('sending a command', function () {

        it('should open a connection to the server', function () {
            var options = {
                server: '127.0.0.1',
                port: 4304
            };
            var socket = new net.Socket();
            var mock = sinon.mock(socket);
            mock.expects('connect').once().withExactArgs(4304, '127.0.0.1');

            sendCommandToSocket(options, socket, function() {});

            mock.verify();
        });

        it('should send a command to the server once connected', function () {
            var options = {
                path: '/some/path',
                command: 2,
                data_len: 8192,
                server: '127.0.0.1',
                port: 4304
            };
            var socket = new net.Socket();
            var mock = sinon.mock(socket);
            sinon.stub(socket, 'connect', function() {
                socket.emit('connect');
            });

            var expect = new Buffer([
                0x00, 0x00, 0x00, 0x00,   // Protocol Version
                0x00, 0x00, 0x00, 0x0b,   // Length (in bytes) of payload data
                0x00, 0x00, 0x00, 0x02,   // Type of function call
                0x00, 0x00, 0x00, 0x20,   // Format flags
                0x00, 0x00, 0x20, 0x00,   // Expected size of data
                0x00, 0x00, 0x00, 0x00,   // Offset for read or write
                0x2f, 0x73, 0x6f, 0x6d, 0x65, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x00
            ]);
            mock.expects('end').once().withExactArgs(expect);

            sendCommandToSocket(options, socket, function() {});

            mock.verify();
        });

    });

});
<commit_msg>Skip Communication Tests in old versions of node.js<commit_after>'use strict';

var sinon = require('sinon');
var net = require('net');
var sendCommandToSocket = require('../lib/base/communication').sendCommandToSocket;

// Monkey patch to help with debugging Buffer comparison assertions
(function(BufferToString) {
    Buffer.prototype.toString = function(encoding) {
        if (encoding === undefined) {
            var array = [];
            for (var i = 0; i < this.length; i++) {
                var hex = this[i].toString(16);
                if (this[i] < 0x10) {
                    hex = '0' + hex;
                }
                array.push('0x' + hex);
            }
            return '[' + array.join(', ') + ']';
        } else {
            return BufferToString.apply(this, arguments);
        }
    };
})(Buffer.prototype.toString);

describe('Communication Test', function () {
    beforeEach(function() {
        var version = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
        if (version < 4.0) {
            // These tests erroneously fails on old versions of node.js
            this.skip();
        }
    });

    describe('sending a command', function () {

        it('should open a connection to the server', function () {
            var options = {
                server: '127.0.0.1',
                port: 4304
            };
            var socket = new net.Socket();
            var mock = sinon.mock(socket);
            mock.expects('connect').once().withExactArgs(4304, '127.0.0.1');

            sendCommandToSocket(options, socket, function() {});

            mock.verify();
        });

        it('should send a command to the server once connected', function () {
            var options = {
                path: '/some/path',
                command: 2,
                data_len: 8192,
                server: '127.0.0.1',
                port: 4304
            };
            var socket = new net.Socket();
            var mock = sinon.mock(socket);
            sinon.stub(socket, 'connect', function() {
                socket.emit('connect');
            });

            var expect = new Buffer([
                0x00, 0x00, 0x00, 0x00,   // Protocol Version
                0x00, 0x00, 0x00, 0x0b,   // Length (in bytes) of payload data
                0x00, 0x00, 0x00, 0x02,   // Type of function call
                0x00, 0x00, 0x00, 0x20,   // Format flags
                0x00, 0x00, 0x20, 0x00,   // Expected size of data
                0x00, 0x00, 0x00, 0x00,   // Offset for read or write
                0x2f, 0x73, 0x6f, 0x6d, 0x65, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x00
            ]);
            mock.expects('end').once().withExactArgs(expect);

            sendCommandToSocket(options, socket, function() {});

            mock.verify();
        });

    });

});
<|endoftext|>


<commit_before>// @flow
import React, { Component } from 'react';
import { Provider, observer } from 'mobx-react';
import { ThemeProvider } from 'react-polymorph/lib/components/ThemeProvider';
import DevTools from 'mobx-react-devtools';
import { Router } from 'react-router';
import { IntlProvider } from 'react-intl';
import { Routes } from './Routes';
import { daedalusTheme } from './themes/daedalus';
import environment from '../../common/environment';
import translations from './i18n/translations';
import type { StoresMap } from './stores/index';
import type { ActionsMap } from './actions/index';
import ThemeManager from './ThemeManager';
import AboutDialog from './containers/static/AboutDialog';

@observer
export default class App extends Component<{
  stores: StoresMap,
  actions: ActionsMap,
  history: Object,
}> {
  render() {
    const { stores, actions, history } = this.props;
    const { app } = stores;
    const locale = stores.profile.currentLocale;
    const mobxDevTools = environment.MOBX_DEV_TOOLS ? <DevTools /> : null;
    const currentTheme = stores.profile.currentTheme;
    const themeVars = require(`./themes/daedalus/${currentTheme}.js`); // eslint-disable-line

    return (

        <ThemeManager variables={themeVars} />
        <Provider stores={stores} actions={actions}>
          <ThemeProvider theme={daedalusTheme}>
            <IntlProvider {...{ locale, key: locale, messages: translations[locale] }}>

                <Router history={history} routes={Routes} />
                {mobxDevTools}
                {app.isAboutDialogOpen && <AboutDialog />}

            </IntlProvider>
          </ThemeProvider>
        </Provider>

    );
  }
}
<commit_msg>[DDW-262] Adds initAppEnvironment to componentWillMount in App.js<commit_after>// @flow
import React, { Component } from 'react';
import { Provider, observer } from 'mobx-react';
import { ThemeProvider } from 'react-polymorph/lib/components/ThemeProvider';
import DevTools from 'mobx-react-devtools';
import { Router } from 'react-router';
import { IntlProvider } from 'react-intl';
import { Routes } from './Routes';
import { daedalusTheme } from './themes/daedalus';
import environment from '../../common/environment';
import translations from './i18n/translations';
import type { StoresMap } from './stores/index';
import type { ActionsMap } from './actions/index';
import ThemeManager from './ThemeManager';
import AboutDialog from './containers/static/AboutDialog';

@observer
export default class App extends Component<{
  stores: StoresMap,
  actions: ActionsMap,
  history: Object,
}> {
  componentWillMount() {
    // loads app's global environment variables over ipc channel
    this.props.actions.app.initAppEnvironment.trigger();
  }
  render() {
    const { stores, actions, history } = this.props;
    const { app } = stores;
    const locale = stores.profile.currentLocale;
    const mobxDevTools = environment.MOBX_DEV_TOOLS ? <DevTools /> : null;
    const currentTheme = stores.profile.currentTheme;
    const themeVars = require(`./themes/daedalus/${currentTheme}.js`); // eslint-disable-line
    return (

        <ThemeManager variables={themeVars} />
        <Provider stores={stores} actions={actions}>
          <ThemeProvider theme={daedalusTheme}>
            <IntlProvider {...{ locale, key: locale, messages: translations[locale] }}>

                <Router history={history} routes={Routes} />
                {mobxDevTools}
                {app.isAboutDialogOpen && <AboutDialog />}

            </IntlProvider>
          </ThemeProvider>
        </Provider>

    );
  }
}
<|endoftext|>


<commit_before>/*
 * spawner.js: Spawner object responsible for starting carapace processes.
 *
 * (C) 2010, Nodejitsu Inc.
 *
 */

var fs = require('fs'),
    path = require('path'),
    forever = require('forever'),
    semver = require('semver'),
    haibu = require('../../haibu');

haibu.getSpawnOptions = function getSpawnOptions (app) {
  var env = app.env,
      command = 'node',
      nodeDir,
      version,
      engine = (app.engines || app.engine || {node: app.engine}).node,
      cwd,
      engineDir = haibu.config.get('directories:node-installs'),
      nodeVersions = engineDir && fs.readdirSync(engineDir),
      carapaceDir = haibu.config.get('directories:carapace-installs'),
      carapaceVersions = carapaceDir && fs.readdirSync(carapaceDir);

  var options = {};
  if (nodeVersions) {
    engine = (app.engines || app.engine || {node: app.engine}).node;
    if (typeof engine !== 'string') {
      engine = '0.4.x';
    }
    version = semver.maxSatisfying(nodeVersions, engine);
    if (!version) {
      var err = new Error('Error spawning drone: no matching engine found');
      err.blame = {
        type: 'user',
        message: 'Repository configuration'
      }
      throw err;
    }
    nodeDir = path.join(engineDir, version);
  }
  if (carapaceVersions) {
    if (typeof engine !== 'string') {
      engine = '0.4.x';
    }
    version = semver.maxSatisfying(carapaceVersions, engine);
    if (!version) {
      var err = new Error('Error spawning drone: no matching carapace found');
      err.blame = {
        type: 'user',
        message: 'Repository configuration'
      }
      throw err;
    }
    options.carapaceBin = path.join(carapaceDir, version, 'node_modules', 'haibu-carapace', 'bin', 'carapace');
  }
  else {
    options.carapaceBin = path.join(require.resolve('haibu-carapace'), '..', '..', 'bin', 'carapace');
  }

  if (version) {
    //
    // Add node (should be configured with --no-npm) and -g modules to path of repo
    //
    if (semver.lt(version, '0.6.5')) {
      options.forkShim = carapaceVersions ? path.join(options.carapaceBin, '..', '..', '..', 'node-fork', 'lib', 'fork.js') : true;
    }
    env = env || {}
      env.NODE_VERSION = 'v'+version;
      env.NODE_PREFIX = nodeDir;
      env.NODE_PATH = path.join(nodeDir, 'lib', 'node_modules');
      var concatPATH = (process.env.PATH ? ':' + process.env.PATH : '');
      env.PATH = path.join(nodeDir, 'bin') + ':' + path.join(nodeDir, 'node_modules') + concatPATH;
      var concatCPATH = (process.env.CPATH ? ':' + process.env.CPATH : '');
      env.CPATH = path.join(nodeDir, 'include') + ':' + path.join(nodeDir, 'include', 'node') + concatCPATH;
      var concatLIBRARY_PATH = (process.env.LIBRARY_PATH ? ':' + process.env.LIBRARY_PATH : '');
      env.LIBRARY_PATH = path.join(nodeDir, 'lib') + ':' + path.join(nodeDir, 'lib', 'node') + concatLIBRARY_PATH;

    options.cwd = nodeDir;
    command = path.join(nodeDir, 'bin', 'node');
  }

  options.env = env;
  options.command = command;
  return options;
}

var Spawner = exports.Spawner = function Spawner(options) {
  options = options || {};

  this.maxRestart = options.maxRestart;
  this.options    = options
  this.silent     = options.silent     || false;
  this.host       = options.host       || '127.0.0.1';
  this.packageDir = options.packageDir || haibu.config.get('directories:packages');
  this.minUptime  = typeof options.minUptime !== 'undefined' ? options.minUptime : 2000;
};

//
// ### function trySpawn (app, callback)
// #### @app {App} Application to attempt to spawn on this server.
// #### @callback {function} Continuation passed to respond to.
// Attempts to spawn the application with the package.json manifest
// represented by @app, then responds to @callback.
//
Spawner.prototype.trySpawn = function (app, callback) {
  var self = this,
      repo;

  try { repo = app instanceof haibu.repository.Repository ? app : haibu.repository.create(app) }
  catch (ex) { return callback(ex) }

  if (repo instanceof Error) {
    return callback(repo);
  }

  repo.bootstrap(function (err, existed) {
    if (err) {
      return callback(err);
    }
    else if (existed) {
      return self.spawn(repo, callback);
    }

    repo.init(function (err, inited) {
      if (err) {
        return callback(err);
      }

      self.spawn(repo, callback);
    });
  });
};

//
// ### function spawn (app, callback)
// #### @repo {Repository} App code repository to spawn from on this server.
// #### @callback {function} Continuation passed to respond to.
// spawns the appropriate carapace for an Application repository and bootstraps with the events listed
//
Spawner.prototype.spawn = function spawn (repo, callback) {
  if (!(repo instanceof haibu.repository.Repository)) {
    var err = new Error('Error spawning drone: no repository defined');
    err.blame = {
      type: 'user',
      message: 'Repository configuration'
    }
    return callback();
  }

  var self = this,
      app  = repo.app,
      meta = { app: app.name, user: app.user },
      script = repo.startScript,
      result,
      responded = false,
      stderr = [],
      stdout = [],
      options = [],
      foreverOptions,
      carapaceBin,
      error,
      drone;

  haibu.emit('spawn:setup', 'info', meta);

  try {
    var spawnOptions = haibu.getSpawnOptions(app);
  }
  catch (e) {
    return callback(e);
  }

  foreverOptions = {
    fork:      true,
    silent:    true,
    cwd:       repo.homeDir,
    hideEnv:   haibu.config.get('hideEnv'),
    env:       spawnOptions.env,
    forkShim:  spawnOptions.forkShim,
    minUptime: this.minUptime,
    command:   spawnOptions.command,
    options:   [spawnOptions.carapaceBin].concat(options)
  };
  //
  // Concatenate the `argv` of any plugins onto the options
  // to be passed to the carapace script.
  //
  Object.keys(haibu.plugins).forEach(function (plugin) {
    var spawn;

    if (haibu.plugins[plugin].argv) {
      haibu.emit('plugin:argv', 'info', {
        app: app.name,
        user: app.user,
        plugin: plugin
      });

      spawn = haibu.plugins[plugin].argv(repo);

      if (spawn.script) {
        script = spawn.script
      }

      if (spawn.argv) {
        foreverOptions.options = foreverOptions.options.concat(spawn.argv);
      }
    }
  });

  foreverOptions.forever = typeof self.maxRestart === 'undefined';
  if (typeof self.maxRestart !== 'undefined') {
    foreverOptions.max = self.maxRestart;
  }

  //
  // Before we attempt to spawn, let's check if the startPath actually points to a file
  // Trapping this specific error is useful as the error indicates an incorrect
  // scripts.start property in the package.json
  //
  fs.stat(repo.startScript, function (err, stats) {
    if (err) {
      var err = new Error('package.json error: ' + 'can\'t find starting script: ' + repo.app.scripts.start);
      err.blame = {
        type: 'user',
        message: 'Package.json start script declared but not found'
      }
      return callback(err);
    }

    foreverOptions.options.push(script);
    carapaceBin = foreverOptions.options.shift();
    drone = new forever.Monitor(carapaceBin, foreverOptions);
    drone.on('error', function () {
      //
      // 'error' event needs to be caught, otherwise
      // the haibu process will die
      //
    });

    haibu.emit(['spawn', 'begin'], 'info', {
      options: foreverOptions.options.join(' '),
      app: meta.app,
      user: meta.user,
      drone: drone,
      pkg: app
    });

    //
    // Log data from `drone.stdout` to haibu
    //
    function onStdout (data) {
      data = data.toString();
      haibu.emit('drone:stdout', 'info', data, meta);

      if (!responded) {
        stdout = stdout.concat(data.split('\n').filter(function (line) { return line.length > 0 }));
      }
    }

    //
    // Log data from `drone.stderr` to haibu
    //
    function onStderr (data) {
      data = data.toString();
      haibu.emit('drone:stderr', 'error', data, meta);

      if (!responded) {
        stderr = stderr.concat(data.split('\n').filter(function (line) { return line.length > 0 }));
      }
    }

    //
    // If the `forever.Monitor` instance emits an error then
    // pass this error back up to the callback.
    //
    // (remark) this may not work if haibu starts two apps at the same time
    //
    function onError (err) {
      if (!responded) {
        errState = true;
        responded = true;
        callback(err);

        //
        // Remove listeners to related events.
        //
        drone.removeListener('exit', onExit);
        drone.removeListener('message', onCarapacePort);
      }
    }

    //
    // When the carapace provides the port that the drone
    // has bound to then respond to the callback
    //
    function onCarapacePort (info) {
      if (!responded && info && info.event === 'port') {
        responded = true;
        result.socket = {
          host: self.host,
          port: info.data.port
        };

        drone.minUptime = 0;

        haibu.emit('drone:port', 'info', {
          pkg: app,
          info: info
        });

        callback(null, result);

        //
        // Remove listeners to related events
        //
        drone.removeListener('exit', onExit);
        drone.removeListener('error', onError);
      }
    }

    //
    // When the drone starts, update the result for monitoring software
    //
    function onChildStart (monitor, data) {
      result = {
        monitor: monitor,
        process: monitor.child,
        data: data,
        pid: monitor.childData.pid,
        pkg: app
      };

      haibu.emit(['drone', 'start'], 'info', {
        pid: result.pid,
        pkg: result.pkg
      });
    }

    //
    // When the drone stops, update the result for monitoring software
    //
    function onChildRestart (monitor, data) {

      haibu.emit(['drone', 'stop'], 'info', {
        pid: result.pid,
        pkg: result.pkg
      });

      onChildStart(monitor, data)
    }

    //
    // If the drone exits prematurely then respond with an error
    // containing the data we receieved from `stderr`
    //
    function onExit () {
      if (!responded) {
        errState = true;
        responded = true;
        error = new Error('Error spawning drone');
        error.blame = {
          type: 'user',
          message: 'Script prematurely exited'
        }
        error.stdout = stdout.join('\n');
        error.stderr = stderr.join('\n');
        callback(error);

        //
        // Remove listeners to related events.
        //
        drone.removeListener('error', onError);
        drone.removeListener('message', onCarapacePort);
      }
    }

    //
    // Listen to the appropriate events and start the drone process.
    //
    drone.on('stdout', onStdout);
    drone.on('stderr', onStderr);
    drone.once('exit', onExit);
    drone.once('error', onError);
    drone.once('start', onChildStart);
    drone.on('restart', onChildRestart);
    drone.on('message', onCarapacePort);
    drone.start();
  });
};

<commit_msg>[fix] namespace the pid into the entire process info for monitors of spawn events<commit_after>/*
 * spawner.js: Spawner object responsible for starting carapace processes.
 *
 * (C) 2010, Nodejitsu Inc.
 *
 */

var fs = require('fs'),
    path = require('path'),
    forever = require('forever'),
    semver = require('semver'),
    haibu = require('../../haibu');

haibu.getSpawnOptions = function getSpawnOptions (app) {
  var env = app.env,
      command = 'node',
      nodeDir,
      version,
      engine = (app.engines || app.engine || {node: app.engine}).node,
      cwd,
      engineDir = haibu.config.get('directories:node-installs'),
      nodeVersions = engineDir && fs.readdirSync(engineDir),
      carapaceDir = haibu.config.get('directories:carapace-installs'),
      carapaceVersions = carapaceDir && fs.readdirSync(carapaceDir);

  var options = {};
  if (nodeVersions) {
    engine = (app.engines || app.engine || {node: app.engine}).node;
    if (typeof engine !== 'string') {
      engine = '0.4.x';
    }
    version = semver.maxSatisfying(nodeVersions, engine);
    if (!version) {
      var err = new Error('Error spawning drone: no matching engine found');
      err.blame = {
        type: 'user',
        message: 'Repository configuration'
      }
      throw err;
    }
    nodeDir = path.join(engineDir, version);
  }
  if (carapaceVersions) {
    if (typeof engine !== 'string') {
      engine = '0.4.x';
    }
    version = semver.maxSatisfying(carapaceVersions, engine);
    if (!version) {
      var err = new Error('Error spawning drone: no matching carapace found');
      err.blame = {
        type: 'user',
        message: 'Repository configuration'
      }
      throw err;
    }
    options.carapaceBin = path.join(carapaceDir, version, 'node_modules', 'haibu-carapace', 'bin', 'carapace');
  }
  else {
    options.carapaceBin = path.join(require.resolve('haibu-carapace'), '..', '..', 'bin', 'carapace');
  }

  if (version) {
    //
    // Add node (should be configured with --no-npm) and -g modules to path of repo
    //
    if (semver.lt(version, '0.6.5')) {
      options.forkShim = carapaceVersions ? path.join(options.carapaceBin, '..', '..', '..', 'node-fork', 'lib', 'fork.js') : true;
    }
    env = env || {}
      env.NODE_VERSION = 'v'+version;
      env.NODE_PREFIX = nodeDir;
      env.NODE_PATH = path.join(nodeDir, 'lib', 'node_modules');
      var concatPATH = (process.env.PATH ? ':' + process.env.PATH : '');
      env.PATH = path.join(nodeDir, 'bin') + ':' + path.join(nodeDir, 'node_modules') + concatPATH;
      var concatCPATH = (process.env.CPATH ? ':' + process.env.CPATH : '');
      env.CPATH = path.join(nodeDir, 'include') + ':' + path.join(nodeDir, 'include', 'node') + concatCPATH;
      var concatLIBRARY_PATH = (process.env.LIBRARY_PATH ? ':' + process.env.LIBRARY_PATH : '');
      env.LIBRARY_PATH = path.join(nodeDir, 'lib') + ':' + path.join(nodeDir, 'lib', 'node') + concatLIBRARY_PATH;

    options.cwd = nodeDir;
    command = path.join(nodeDir, 'bin', 'node');
  }

  options.env = env;
  options.command = command;
  return options;
}

var Spawner = exports.Spawner = function Spawner(options) {
  options = options || {};

  this.maxRestart = options.maxRestart;
  this.options    = options
  this.silent     = options.silent     || false;
  this.host       = options.host       || '127.0.0.1';
  this.packageDir = options.packageDir || haibu.config.get('directories:packages');
  this.minUptime  = typeof options.minUptime !== 'undefined' ? options.minUptime : 2000;
};

//
// ### function trySpawn (app, callback)
// #### @app {App} Application to attempt to spawn on this server.
// #### @callback {function} Continuation passed to respond to.
// Attempts to spawn the application with the package.json manifest
// represented by @app, then responds to @callback.
//
Spawner.prototype.trySpawn = function (app, callback) {
  var self = this,
      repo;

  try { repo = app instanceof haibu.repository.Repository ? app : haibu.repository.create(app) }
  catch (ex) { return callback(ex) }

  if (repo instanceof Error) {
    return callback(repo);
  }

  repo.bootstrap(function (err, existed) {
    if (err) {
      return callback(err);
    }
    else if (existed) {
      return self.spawn(repo, callback);
    }

    repo.init(function (err, inited) {
      if (err) {
        return callback(err);
      }

      self.spawn(repo, callback);
    });
  });
};

//
// ### function spawn (app, callback)
// #### @repo {Repository} App code repository to spawn from on this server.
// #### @callback {function} Continuation passed to respond to.
// spawns the appropriate carapace for an Application repository and bootstraps with the events listed
//
Spawner.prototype.spawn = function spawn (repo, callback) {
  if (!(repo instanceof haibu.repository.Repository)) {
    var err = new Error('Error spawning drone: no repository defined');
    err.blame = {
      type: 'user',
      message: 'Repository configuration'
    }
    return callback();
  }

  var self = this,
      app  = repo.app,
      meta = { app: app.name, user: app.user },
      script = repo.startScript,
      result,
      responded = false,
      stderr = [],
      stdout = [],
      options = [],
      foreverOptions,
      carapaceBin,
      error,
      drone;

  haibu.emit('spawn:setup', 'info', meta);

  try {
    var spawnOptions = haibu.getSpawnOptions(app);
  }
  catch (e) {
    return callback(e);
  }

  foreverOptions = {
    fork:      true,
    silent:    true,
    cwd:       repo.homeDir,
    hideEnv:   haibu.config.get('hideEnv'),
    env:       spawnOptions.env,
    forkShim:  spawnOptions.forkShim,
    minUptime: this.minUptime,
    command:   spawnOptions.command,
    options:   [spawnOptions.carapaceBin].concat(options)
  };
  //
  // Concatenate the `argv` of any plugins onto the options
  // to be passed to the carapace script.
  //
  Object.keys(haibu.plugins).forEach(function (plugin) {
    var spawn;

    if (haibu.plugins[plugin].argv) {
      haibu.emit('plugin:argv', 'info', {
        app: app.name,
        user: app.user,
        plugin: plugin
      });

      spawn = haibu.plugins[plugin].argv(repo);

      if (spawn.script) {
        script = spawn.script
      }

      if (spawn.argv) {
        foreverOptions.options = foreverOptions.options.concat(spawn.argv);
      }
    }
  });

  foreverOptions.forever = typeof self.maxRestart === 'undefined';
  if (typeof self.maxRestart !== 'undefined') {
    foreverOptions.max = self.maxRestart;
  }

  //
  // Before we attempt to spawn, let's check if the startPath actually points to a file
  // Trapping this specific error is useful as the error indicates an incorrect
  // scripts.start property in the package.json
  //
  fs.stat(repo.startScript, function (err, stats) {
    if (err) {
      var err = new Error('package.json error: ' + 'can\'t find starting script: ' + repo.app.scripts.start);
      err.blame = {
        type: 'user',
        message: 'Package.json start script declared but not found'
      }
      return callback(err);
    }

    foreverOptions.options.push(script);
    carapaceBin = foreverOptions.options.shift();
    drone = new forever.Monitor(carapaceBin, foreverOptions);
    drone.on('error', function () {
      //
      // 'error' event needs to be caught, otherwise
      // the haibu process will die
      //
    });

    haibu.emit(['spawn', 'begin'], 'info', {
      options: foreverOptions.options.join(' '),
      app: meta.app,
      user: meta.user,
      drone: drone,
      pkg: app
    });

    //
    // Log data from `drone.stdout` to haibu
    //
    function onStdout (data) {
      data = data.toString();
      haibu.emit('drone:stdout', 'info', data, meta);

      if (!responded) {
        stdout = stdout.concat(data.split('\n').filter(function (line) { return line.length > 0 }));
      }
    }

    //
    // Log data from `drone.stderr` to haibu
    //
    function onStderr (data) {
      data = data.toString();
      haibu.emit('drone:stderr', 'error', data, meta);

      if (!responded) {
        stderr = stderr.concat(data.split('\n').filter(function (line) { return line.length > 0 }));
      }
    }

    //
    // If the `forever.Monitor` instance emits an error then
    // pass this error back up to the callback.
    //
    // (remark) this may not work if haibu starts two apps at the same time
    //
    function onError (err) {
      if (!responded) {
        errState = true;
        responded = true;
        callback(err);

        //
        // Remove listeners to related events.
        //
        drone.removeListener('exit', onExit);
        drone.removeListener('message', onCarapacePort);
      }
    }

    //
    // When the carapace provides the port that the drone
    // has bound to then respond to the callback
    //
    function onCarapacePort (info) {
      if (!responded && info && info.event === 'port') {
        responded = true;
        result.socket = {
          host: self.host,
          port: info.data.port
        };

        drone.minUptime = 0;

        haibu.emit('drone:port', 'info', {
          pkg: app,
          info: info
        });

        callback(null, result);

        //
        // Remove listeners to related events
        //
        drone.removeListener('exit', onExit);
        drone.removeListener('error', onError);
      }
    }

    //
    // When the drone starts, update the result for monitoring software
    //
    function onChildStart (monitor, data) {
      result = {
        monitor: monitor,
        process: monitor.child,
        data: data,
        pid: monitor.childData.pid,
        pkg: app
      };

      haibu.emit(['drone', 'start'], 'info', {
        process: result.process,
        pkg: result.pkg
      });
    }

    //
    // When the drone stops, update the result for monitoring software
    //
    function onChildRestart (monitor, data) {

      haibu.emit(['drone', 'stop'], 'info', {
        process: result.process,
        pkg: result.pkg
      });

      onChildStart(monitor, data)
    }

    //
    // If the drone exits prematurely then respond with an error
    // containing the data we receieved from `stderr`
    //
    function onExit () {
      if (!responded) {
        errState = true;
        responded = true;
        error = new Error('Error spawning drone');
        error.blame = {
          type: 'user',
          message: 'Script prematurely exited'
        }
        error.stdout = stdout.join('\n');
        error.stderr = stderr.join('\n');
        callback(error);

        //
        // Remove listeners to related events.
        //
        drone.removeListener('error', onError);
        drone.removeListener('message', onCarapacePort);
      }
    }

    //
    // Listen to the appropriate events and start the drone process.
    //
    drone.on('stdout', onStdout);
    drone.on('stderr', onStderr);
    drone.once('exit', onExit);
    drone.once('error', onError);
    drone.once('start', onChildStart);
    drone.on('restart', onChildRestart);
    drone.on('message', onCarapacePort);
    drone.start();
  });
};

<|endoftext|>


<commit_before>import { applyMiddleware, createStore, compose } from 'redux';
import thunk from 'redux-thunk';
import reducers from './reducers/index';

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; //eslint-disable-line
const middleware = applyMiddleware(thunk);

const initialState = () => {
  const persistedState = localStorage.getItem('reduxState');
  if (persistedState) {
    return JSON.parse(persistedState);
  }
  return {};
};

const store = createStore(reducers, initialState(), composeEnhancers(
    middleware,
));

store.subscribe(() => {
  const state = store.getState();
  const persistedState = {
    auth: state.auth,
    settings: state.settings,
    user: state.user,
  };
  localStorage.setItem('reduxState', JSON.stringify(persistedState));
});

export default store;
<commit_msg>saving column to persistant state<commit_after>import { applyMiddleware, createStore, compose } from 'redux';
import thunk from 'redux-thunk';
import reducers from './reducers/index';

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; //eslint-disable-line
const middleware = applyMiddleware(thunk);

const initialState = () => {
  const persistedState = localStorage.getItem('reduxState');
  if (persistedState) {
    return JSON.parse(persistedState);
  }
  return {};
};

const store = createStore(reducers, initialState(), composeEnhancers(
    middleware,
));

store.subscribe(() => {
  const state = store.getState();
  const persistedState = {
    auth: state.auth,
    settings: state.settings,
    user: state.user,
    columns: state.columns,
  };
  localStorage.setItem('reduxState', JSON.stringify(persistedState));
});

export default store;
<|endoftext|>


<commit_before>/**
 * Test case for decorateMsg.
 * Runs with mocha.
 */
"use strict";

const decorateMsg = require("../lib/msg/decorate_msg.js");
const assert = require("assert");

describe("decorate", () => {
  it("Decorate msg", done => {
    if (process.env.CI) {
      return;
    }
    assert.ok(decorateMsg("foo", "green"));
    assert.equal(decorateMsg(null), null);
    done();
  });

  it("Decorate msg with invalid color.", done => {
    assert.throws(function() {
      decorateMsg("foo", "__not_existing_color");
    });
    done();
  });
});

/* global describe, it */
<commit_msg>fix travis<commit_after>/**
 * Test case for decorateMsg.
 * Runs with mocha.
 */
"use strict";

const decorateMsg = require("../lib/msg/decorate_msg.js");
const assert = require("assert");

describe("decorate", () => {
  it("Decorate msg", done => {
    if (process.env.CI) {
      return;
    }
    assert.ok(decorateMsg("foo", "green"));
    assert.equal(decorateMsg(null), null);
    done();
  });

  it("Decorate msg with invalid color.", done => {
    if (process.env.CI) {
      return;
    }
    assert.throws(function() {
      decorateMsg("foo", "__not_existing_color");
    });
    done();
  });
});

/* global describe, it */
<|endoftext|>


<commit_before>define('page/GamePage', [
  'goo/entities/GooRunner',
  'component/CameraComponent',
  'component/SunComponent',
  'component/FinalZoneComponent',
  'component/FuelZoneComponent',
  'component/StarshipComponent',
  'helper/DomHelper',
  'helper/ShootHelper',
  'page/PausePage',
  'manager/EntityManager',
  'util/MapUtil',
  'util/RadarUtil',
  'util/OptionsUtil'
], function(
  GooRunner,
  CameraComponent,
  SunComponent,
  FinalZoneComponent,
  FuelZoneComponent,
  StarshipComponent,
  DomHelper,
  ShootHelper,
  PausePage,
  EntityManager,
  MapUtil,
  RadarUtil,
  OptionsUtil) {

    var screenWidth = window.innerWidth || document.documentElement.clientWidth || document.getElementsByTagName('body')[0].clientWidth;
    var screenHeight = window.innerHeight|| document.documentElement.clientHeight|| document.getElementsByTagName('body')[0].clientHeight;

    var backCallback;
    var canvas;
    var pauseButton;
    var crosschair;
    var fuelDiv;

    var fuelZone;
    var camera;

    function build() {
      DomHelper.clearPageContent();
      DomHelper.hidePage();
      crosschair = DomHelper.addCrosschair();
      fuelDiv = DomHelper.addFuelAmount(screenHeight - (screenHeight * 0.5));
      fuelDiv.update(100);
      var goo = startGame();
      var isRunningGame = true;
      pauseButton = DomHelper.buildButton('', function(e) {
        if(isRunningGame) {
          goo.stopGameLoop();
          isRunningGame = false;
          elementsDomVisible(false);
          PausePage.show(function() {
            DomHelper.clearPageContent();
            DomHelper.hidePage();
            var w = screenWidth * OptionsUtil.get('screenSize');
            var h = screenHeight * OptionsUtil.get('screenSize');
            goo.renderer.setSize(w, h);
            goo.startGameLoop();
            isRunningGame = true;
            elementsDomVisible(true);
          });
          DomHelper.showPage();
        } else {
          goo.startGameLoop();
          isRunningGame = true;
        }
      });
      pauseButton.classList.add('pause');
      document.body.appendChild(pauseButton);
    }

    var elementsDomVisible = function elementsDomVisible(bool) {
      for(var i=0, len=document.body.children.length; i<len; i++) {
        document.body.children[i].style.display = ((bool === false) ? 'none' : 'block');
      }
    };

    var startGame = function startGame() {
      var goo = new GooRunner();
      var w = screenWidth * OptionsUtil.get('screenSize');
      var h = screenHeight * OptionsUtil.get('screenSize');
      canvas = goo.renderer.domElement;
      canvas.classList.add('canvas');
      goo.renderer.setSize(w, h);
      goo.renderer.setClearColor(0, 0, 0, 1);
      document.body.appendChild(canvas);

      var sun = new SunComponent(goo.world, true);

      fuelZone = new FuelZoneComponent(goo.world, true);

      //new StarshipComponent(goo.world, true);

      camera = new CameraComponent(
        goo.world,
        fuelZone.entity,
        function(fuelAmount) {
          fuelDiv.update(fuelAmount);
        },
        true);

      //new FinalZoneComponent(goo.world, true);

      EntityManager.onRemoveEntity(function callbackAfterRemoveEntities(entity, nbEntityInGame) {
        if(nbEntityInGame === 0) {
          startNextMap(goo.world);
        }
      });

      ShootHelper.start(goo.world, camera);

      RadarUtil.draw(camera, fuelZone);
      startNextMap(goo.world);
      return goo;
    };

    var startNextMap = function startNextMap(world) {
      var currentMap = MapUtil.getNextMap();
      if(currentMap) {
        if(currentMap.fuelZone) {
          fuelZone.entity.transformComponent.setTranslation(
            currentMap.fuelZone.position.x,
            currentMap.fuelZone.position.y,
            currentMap.fuelZone.position.z
          );
        } else {
          fuelZone.entity.transformComponent.setTranslation( 0, -100, 0 );
        }
        camera.updateFuelAmount(100);
        fuelDiv.update(100);
        camera.entity.transformComponent.setTranslation(
          currentMap.camera.position.x,
          currentMap.camera.position.y,
          currentMap.camera.position.z
        );
        camera.script.yRotationAcc = 0;
        EntityManager.addToWorld(world, currentMap.getEntities());
      }
    };

    return {
      show: function(back) {
        backCallback = back;
        build();
      }
    };

  }
);<commit_msg>create function to update scene size<commit_after>define('page/GamePage', [
  'goo/entities/GooRunner',
  'component/CameraComponent',
  'component/SunComponent',
  'component/FinalZoneComponent',
  'component/FuelZoneComponent',
  'component/StarshipComponent',
  'helper/DomHelper',
  'helper/ShootHelper',
  'page/PausePage',
  'manager/EntityManager',
  'util/MapUtil',
  'util/RadarUtil',
  'util/OptionsUtil'
], function(
  GooRunner,
  CameraComponent,
  SunComponent,
  FinalZoneComponent,
  FuelZoneComponent,
  StarshipComponent,
  DomHelper,
  ShootHelper,
  PausePage,
  EntityManager,
  MapUtil,
  RadarUtil,
  OptionsUtil) {

    var screenWidth = window.innerWidth || document.documentElement.clientWidth || document.getElementsByTagName('body')[0].clientWidth;
    var screenHeight = window.innerHeight|| document.documentElement.clientHeight|| document.getElementsByTagName('body')[0].clientHeight;

    var backCallback;
    var canvas;
    var pauseButton;
    var crosschair;
    var fuelDiv;

    var fuelZone;
    var camera;

    function build() {
      DomHelper.clearPageContent();
      DomHelper.hidePage();
      crosschair = DomHelper.addCrosschair();
      fuelDiv = DomHelper.addFuelAmount(screenHeight - (screenHeight * 0.5));
      fuelDiv.update(100);
      var goo = startGame();
      var isRunningGame = true;
      pauseButton = DomHelper.buildButton('', function(e) {
        if(isRunningGame) {
          goo.stopGameLoop();
          isRunningGame = false;
          elementsDomVisible(false);
          PausePage.show(function() {
            DomHelper.clearPageContent();
            DomHelper.hidePage();
            updateSceneSize(goo);
            goo.startGameLoop();
            isRunningGame = true;
            elementsDomVisible(true);
          });
          DomHelper.showPage();
        } else {
          goo.startGameLoop();
          isRunningGame = true;
        }
      });
      pauseButton.classList.add('pause');
      document.body.appendChild(pauseButton);
    }

    var elementsDomVisible = function elementsDomVisible(bool) {
      for(var i=0, len=document.body.children.length; i<len; i++) {
        document.body.children[i].style.display = ((bool === false) ? 'none' : 'block');
      }
    };

    var updateSceneSize = function updateSceneSize(goo) {
      var w = screenWidth * OptionsUtil.get('screenSize');
      var h = screenHeight * OptionsUtil.get('screenSize');
      goo.renderer.setSize(w, h);
    };

    var startGame = function startGame() {
      var goo = new GooRunner();
      canvas = goo.renderer.domElement;
      canvas.classList.add('canvas');
      updateSceneSize(goo);
      goo.renderer.setClearColor(0, 0, 0, 1);
      document.body.appendChild(canvas);

      var sun = new SunComponent(goo.world, true);

      fuelZone = new FuelZoneComponent(goo.world, true);

      //new StarshipComponent(goo.world, true);

      camera = new CameraComponent(
        goo.world,
        fuelZone.entity,
        function(fuelAmount) {
          fuelDiv.update(fuelAmount);
        },
        true);

      //new FinalZoneComponent(goo.world, true);

      EntityManager.onRemoveEntity(function callbackAfterRemoveEntities(entity, nbEntityInGame) {
        if(nbEntityInGame === 0) {
          startNextMap(goo.world);
        }
      });

      ShootHelper.start(goo.world, camera);

      RadarUtil.draw(camera, fuelZone);
      startNextMap(goo.world);
      return goo;
    };

    var startNextMap = function startNextMap(world) {
      var currentMap = MapUtil.getNextMap();
      if(currentMap) {
        if(currentMap.fuelZone) {
          fuelZone.entity.transformComponent.setTranslation(
            currentMap.fuelZone.position.x,
            currentMap.fuelZone.position.y,
            currentMap.fuelZone.position.z
          );
        } else {
          fuelZone.entity.transformComponent.setTranslation( 0, -100, 0 );
        }
        camera.updateFuelAmount(100);
        fuelDiv.update(100);
        camera.entity.transformComponent.setTranslation(
          currentMap.camera.position.x,
          currentMap.camera.position.y,
          currentMap.camera.position.z
        );
        camera.script.yRotationAcc = 0;
        EntityManager.addToWorld(world, currentMap.getEntities());
      }
    };

    return {
      show: function(back) {
        backCallback = back;
        build();
      }
    };

  }
);<|endoftext|>


<commit_before>'use strict';

/* global describe it */

// core modules
var assert = require('assert');

module.exports = function(Stream) {
  describe('is a Stream', function() {
    it('starts without next when empty', function() {
      var stream = Stream('');
      assert.equal(stream.hasNext(), false);
    });

    it('contains values it was constructed with', function() {
      var stream = Stream('abc');

      assert.equal(stream.next(), 'a');
      assert.equal(stream.next(), 'b');
      assert.equal(stream.next(), 'c');
    });

    it('peek doesn\'t move the stream forward', function() {
      var stream = Stream('abc');

      assert.equal(stream.peek(), 'a');
      assert.equal(stream.peek(), 'a');
      assert.equal(stream.next(), 'a');
    });

    it('can mark and restore', function() {
      var stream = Stream('abc');

      assert.equal(stream.next(), 'a');

      var mark = stream.mark();

      assert.equal(stream.next(), 'b');
      assert.equal(stream.next(), 'c');

      stream.restore(mark);

      assert.equal(stream.next(), 'b');
      assert.equal(stream.next(), 'c');
    });
  });
};
<commit_msg>Add describeMark test<commit_after>'use strict';

/* global describe it */

// core modules
var assert = require('assert');

module.exports = function(Stream) {
  describe('is a Stream', function() {
    it('starts without next when empty', function() {
      var stream = Stream('');
      assert.equal(stream.hasNext(), false);
    });

    it('contains values it was constructed with', function() {
      var stream = Stream('abc');

      assert.equal(stream.next(), 'a');
      assert.equal(stream.next(), 'b');
      assert.equal(stream.next(), 'c');
    });

    it('peek doesn\'t move the stream forward', function() {
      var stream = Stream('abc');

      assert.equal(stream.peek(), 'a');
      assert.equal(stream.peek(), 'a');
      assert.equal(stream.next(), 'a');
    });

    it('can mark and restore', function() {
      var stream = Stream('abc');

      assert.equal(stream.next(), 'a');

      var mark = stream.mark();

      assert.equal(stream.next(), 'b');
      assert.equal(stream.next(), 'c');

      stream.restore(mark);

      assert.equal(stream.next(), 'b');
      assert.equal(stream.next(), 'c');
    });

    it('has a describeMark which doesn\'t throw when called with a mark', function() {
      var stream = Stream('abc');
      stream.describeMark(stream.mark());
    });
  });
};
<|endoftext|>


<commit_before>    /**
     * Created by JetBrains WebStorm.
     * User: creynder
     * Date: 21/09/11
     * Time: 14:53
     * To change this template use File | Settings | File Templates.
     */
    var injector;

    function TestClassA(){
        this.name = 'TestClassA';
    }

    function TestClassB(){
        this.name = 'TestClassB';

        this.bar = undefined;
    }

    //TODO: test Injectro#setValue

    module( 'dijon.Injector', {
        setup : function(){
            injector = new dijon.System();
        },
        teardown : function(){
            injector = undefined;
        }
    });

    test( 'mapSingleton', function(){
        injector.mapSingleton( 'a', TestClassA );
        ok( injector.hasMapping( 'a' ) );
    })

    test( 'mapValue', function(){
        var a = new TestClassA();
        injector.mapValue( 'a', a );
        ok( injector.hasMapping( 'a' ) );
    })

    test( 'mapClass', function(){
        injector.mapClass( 'a', function(){} );
        ok( injector.hasMapping( 'a' ) );
    })

    test( 'getObject for mapSingleton', function(){
        injector.mapSingleton( 'a', TestClassA );
        var inj = injector;
        var a = injector.getObject( 'a' );
        ok( a instanceof TestClassA, 'must be instance of TestClassA' );
        strictEqual( injector.getObject( 'a' ), a, 'must be single instance' );
    })

    test( 'getObject for mapClass', function(){
        injector.mapClass( 'a', TestClassA );
        var a = injector.getObject( 'a' );
        ok( a instanceof TestClassA );
        notStrictEqual( injector.getObject( 'a' ), a );
    })

    test( 'getObject for mapValue', function(){
        var a = new TestClassA();
        injector.mapValue( 'a', a );
        strictEqual( injector.getObject( 'a' ), a );
    })

    test( 'instantiate for mapSingleton', function(){
        injector.mapSingleton( 'a', TestClassA );
        var a = injector.getObject( 'a' );
        notStrictEqual( injector.instantiate( 'a' ), a, 'instantiate must always provide a new instance regardless of rules' );
    })

    test( 'instantiate for mapClass', function(){
        injector.mapClass( 'a', TestClassA );
        var a = injector.getObject( 'a' );
        notStrictEqual( injector.instantiate( 'a' ), a );
    })

    test( 'instantiate for mapValue', function(){
        var a = new TestClassA();
        injector.mapValue( 'a', a );
        notStrictEqual( injector.instantiate( 'a' ), a );
    })

    test( 'unmap', function(){
        injector.mapSingleton( 'a', TestClassA )
        injector.unmap( 'a' );
        ok( ! injector.hasMapping( 'a' ) );
    })

    test( 'addOutlet', function(){
        injector.mapSingleton( 'a', TestClassA );
        injector.mapSingleton( 'b', TestClassB );
        injector.mapOutlet( 'a', 'b', 'bar' );
        var b = injector.getObject( 'b' );
        ok( b.bar instanceof TestClassA );
    })

    test( 'removeOutlet', function() {
        injector.mapSingleton( 'a', TestClassA );
        injector.mapSingleton( 'b', TestClassB );
        injector.mapOutlet( 'a', 'b', 'bar' );
        injector.unmapOutlet( 'b', 'bar' );
        var b = injector.getObject( 'b' );
        strictEqual( b.bar, undefined );
    })
    test( 'addHandler: simple use', function(){
        var hasExecuted = false;
        var c = function(){
            this.loginStart = function(){
                hasExecuted = true;
            }
        }
        injector.mapSingleton( 'a', c );
        injector.mapHandler( 'loginStart', 'a' )
        injector.notify( 'loginStart' );
        ok( hasExecuted );
    })

    test( 'addHandler: oneShot', function(){
        var hasExecuted = 0;
        var c = function(){
            this.loginStart = function(){
                hasExecuted++;
            }
        }
        injector.mapSingleton( 'a', c );
        injector.mapHandler( 'loginStart', 'a', null, true );
        injector.notify( 'loginStart' );
        injector.notify( 'loginStart' );
        injector.notify( 'loginStart' );
        injector.notify( 'loginStart' );
        injector.notify( 'loginStart' );
        ok( hasExecuted==1);
    })

    test( 'addHandler: diffreten handler name', function(){
         var hasExecuted = false;
         var c = function(){
             this.onLoginStart = function(){
                 hasExecuted = true;
             }
         }
         injector.mapSingleton( 'a', c );
         injector.mapHandler( 'loginStart', 'a', 'onLoginStart' )
         injector.notify( 'loginStart' );
         ok( hasExecuted );
     })

    test( 'unmapHandler: simple use', function(){
        var hasExecuted = 0;
        var c = function(){
            this.loginStart = function(){
                hasExecuted++;
            }
        }
        injector.mapSingleton( 'a', c );
        injector.mapHandler( 'loginStart', 'a' );
        injector.notify( 'loginStart' );
        injector.notify( 'loginStart' );
        injector.unmapHandler( 'loginStart', 'a' );
        injector.notify( 'loginStart' );
        ok( hasExecuted == 2 );
    })

    test( 'instantiate value', function(){
        var a = {
            name : 'a'
        }

        injector.mapValue( 'a', a );
        var inst  = injector.instantiate( 'a' );
        ok( inst !== a );
    })

    test( 'getInstance value', function(){
        var a = {
            name : 'a'
        }

        injector.mapValue( 'a', a );
        var inst  = injector.getObject( 'a' );
        ok( inst === a );
    })<commit_msg>updated tests<commit_after>    /**
     * Created by JetBrains WebStorm.
     * User: creynder
     * Date: 21/09/11
     * Time: 14:53
     * To change this template use File | Settings | File Templates.
     */
    var system;

    function TestClassA(){
        this.name = 'TestClassA';
    }

    function TestClassB(){
        this.name = 'TestClassB';

        this.bar = undefined;
    }

    //TODO: test Injectro#setValue

    module( 'dijon.system', {
        setup : function(){
            system = new dijon.System();
        },
        teardown : function(){
            system = undefined;
        }
    });

    test( 'mapSingleton', function(){
        system.mapSingleton( 'a', TestClassA );
        ok( system.hasMapping( 'a' ) );
    })

    test( 'mapValue', function(){
        var a = new TestClassA();
        system.mapValue( 'a', a );
        ok( system.hasMapping( 'a' ) );
    })

    test( 'mapClass: hasMapping', function(){
        system.mapClass( 'a', function(){} );
        ok( system.hasMapping( 'a' ) );
    })

    test( 'mapClass: unique instances', function(){
        var SomeClass = function(){
        }
        system.mapClass( 'o', SomeClass );

        var s1 = system.getObject( 'o' );
        var s2 = system.getObject( 'o' );

        ok( s1 instanceof SomeClass );
        ok( s2 instanceof SomeClass );
        notEqual( s1, s2 );
    })

    test( 'injectInto', function(){
        var UserModel = function(){
        }
        system.mapSingleton( 'userModel', UserModel );
        var SomeClass = function(){
             user = undefined; //inject
        }
        system.mapSingleton( 'o', SomeClass );
        system.mapOutlet( 'userModel', 'o', 'user' );

        var foo = {
              user : undefined //inject
        }

        system.injectInto( foo, 'o' );

        strictEqual( foo.user, system.getObject( 'userModel' ) );
    })

    test( 'getObject for mapSingleton', function(){
        system.mapSingleton( 'a', TestClassA );
        var inj = system;
        var a = system.getObject( 'a' );
        ok( a instanceof TestClassA, 'must be instance of TestClassA' );
        strictEqual( system.getObject( 'a' ), a, 'must be single instance' );
    })

    test( 'getObject for mapClass', function(){
        system.mapClass( 'a', TestClassA );
        var a = system.getObject( 'a' );
        ok( a instanceof TestClassA );
        notStrictEqual( system.getObject( 'a' ), a );
    })

    test( 'getObject for mapValue', function(){
        var a = new TestClassA();
        system.mapValue( 'a', a );
        strictEqual( system.getObject( 'a' ), a );
    })

    test( 'instantiate for mapSingleton', function(){
        system.mapSingleton( 'a', TestClassA );
        var a = system.getObject( 'a' );
        notStrictEqual( system.instantiate( 'a' ), a, 'instantiate must always provide a new instance regardless of rules' );
    })

    test( 'instantiate for mapClass', function(){
        system.mapClass( 'a', TestClassA );
        var a = system.getObject( 'a' );
        notStrictEqual( system.instantiate( 'a' ), a );
    })

    test( 'instantiate for mapValue', function(){
        var a = new TestClassA();
        system.mapValue( 'a', a );
        var result = system.instantiate( 'a' );
        strictEqual( result, a );
    })

    test( 'unmap', function(){
        system.mapSingleton( 'a', TestClassA )
        system.unmap( 'a' );
        ok( ! system.hasMapping( 'a' ) );
    })

    test( 'mapOutlet: all params given', function(){
        system.mapSingleton( 'userModel', TestClassA );
        var o = {
            user : undefined //inject
        }
        system.mapOutlet( 'userModel', 'o', 'user' );
        system.mapValue( 'o', o );

        var obj = system.getObject( 'o' );
        ok( obj.user instanceof TestClassA );
    })

    test( 'mapOutlet: source and target given', function(){
        system.mapSingleton( 'userModel', TestClassA );
        var o = {
            userModel : undefined //inject
        }
        system.mapOutlet( 'userModel', 'o' );
        system.mapValue( 'o', o );

        var obj = system.getObject( 'o' );
        ok( obj.userModel instanceof TestClassA );
    })

    test( 'mapOutlet: source given', function(){
        system.mapSingleton( 'userModel', TestClassA );
        system.mapOutlet( 'userModel' );
        var o = {
            userModel : undefined //inject
        }
        system.mapValue( 'o', o );

        var obj = system.getObject( 'o' );
        ok( obj.userModel instanceof TestClassA );
    })

    test( 'removeOutlet', function() {
        system.mapSingleton( 'a', TestClassA );
        system.mapSingleton( 'b', TestClassB );
        system.mapOutlet( 'a', 'b', 'bar' );
        system.unmapOutlet( 'b', 'bar' );
        var b = system.getObject( 'b' );
        strictEqual( b.bar, undefined );
    })
    test( 'addHandler: simple use', function(){
        var hasExecuted = false;
        var c = function(){
            this.loginStart = function(){
                hasExecuted = true;
            }
        }
        system.mapSingleton( 'a', c );
        system.mapHandler( 'loginStart', 'a' )
        system.notify( 'loginStart' );
        ok( hasExecuted );
    })

    test( 'addHandler: oneShot', function(){
        var hasExecuted = 0;
        var c = function(){
            this.loginStart = function(){
                hasExecuted++;
            }
        }
        system.mapSingleton( 'a', c );
        system.mapHandler( 'loginStart', 'a', null, true );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        ok( hasExecuted==1);
    })

    test( 'addHandler: diffreten handler name', function(){
         var hasExecuted = false;
         var c = function(){
             this.onLoginStart = function(){
                 hasExecuted = true;
             }
         }
         system.mapSingleton( 'a', c );
         system.mapHandler( 'loginStart', 'a', 'onLoginStart' )
         system.notify( 'loginStart' );
         ok( hasExecuted );
     })

    test( 'unmapHandler: simple use', function(){
        var hasExecuted = 0;
        var c = function(){
            this.loginStart = function(){
                hasExecuted++;
            }
        }
        system.mapSingleton( 'a', c );
        system.mapHandler( 'loginStart', 'a' );
        system.notify( 'loginStart' );
        system.notify( 'loginStart' );
        system.unmapHandler( 'loginStart', 'a' );
        system.notify( 'loginStart' );
        ok( hasExecuted == 2 );
    })
<|endoftext|>


<commit_before>/*
Geodesic extension to Leaflet library, by Fragger
https://github.com/Fragger/Leaflet.Geodesic
Version from master branch, dated Apr 26, 2013
Modified by qnstie 2013-07-17 to maintain compatibility with Leaflet.draw
*/
(function () {
  function geodesicPoly(Klass, fill) {
    return Klass.extend({
      initialize: function (latlngs, options) {
        Klass.prototype.initialize.call(this, L.geodesicConvertLines(latlngs, fill), options);
        this._latlngsinit = this._convertLatLngs(latlngs);
      },
      getLatLngs: function () {
        return this._latlngsinit;
      },
      setLatLngs: function (latlngs) {
        this._latlngsinit = this._convertLatLngs(latlngs);
        return this.redraw();
      },
      addLatLng: function (latlng) {
        this._latlngsinit.push(L.latLng(latlng));
        return this.redraw();
      },
      spliceLatLngs: function () { // (Number index, Number howMany)
        var removed = [].splice.apply(this._latlngsinit, arguments);
        this._convertLatLngs(this._latlngsinit);
        this.redraw();
        return removed;
      },
      redraw: function() {
        this._latlngs = this._convertLatLngs(L.geodesicConvertLines(this._latlngsinit, fill));
        return Klass.prototype.redraw.call(this);
      }
    });
  }

  function geodesicConvertLine(startLatlng, endLatlng, convertedPoints) {
    var i,
      R = 6378137, // earth radius in meters (doesn't have to be exact)
      maxlength = 5000, // meters before splitting
      d2r = L.LatLng.DEG_TO_RAD,
      r2d = L.LatLng.RAD_TO_DEG,
      lat1, lat2, lng1, lng2, dLng, d, segments,
      f, A, B, x, y, z, fLat, fLng;

    dLng = Math.abs(endLatlng.lng - startLatlng.lng) * d2r;
    lat1 = startLatlng.lat * d2r;
    lat2 = endLatlng.lat * d2r;
    lng1 = startLatlng.lng * d2r;
    lng2 = endLatlng.lng * d2r;

    // http://en.wikipedia.org/wiki/Great-circle_distance
    d = Math.atan2(Math.sqrt( Math.pow(Math.cos(lat2) * Math.sin(dLng), 2) + Math.pow(Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLng), 2) ), Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(dLng));

    segments = Math.ceil(d * R / maxlength);
    // loop starts at 1 - we don't add the very first point
    // loop ends before 'segments' is reached - we don't add the very last point here but outside the loop
    // (this was to fix a bug - https://github.com/jonatkins/ingress-intel-total-conversion/issues/471
    //  rounding errors? maths bug? not sure - but it solves the issue! and is a slight optimisation)
    for (i = 1; i < segments; i++) {
      // http://williams.best.vwh.net/avform.htm#Intermediate
      f = i / segments;
      A = Math.sin((1-f)*d) / Math.sin(d);
      B = Math.sin(f*d) / Math.sin(d);
      x = A * Math.cos(lat1) * Math.cos(lng1) + B * Math.cos(lat2) * Math.cos(lng2);
      y = A * Math.cos(lat1) * Math.sin(lng1) + B * Math.cos(lat2) * Math.sin(lng2);
      z = A * Math.sin(lat1)                  + B * Math.sin(lat2);
      fLat = r2d * Math.atan2(z, Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
      fLng = r2d * Math.atan2(y, x);

      convertedPoints.push(L.latLng([fLat, fLng]));
    }
    // push the final point unmodified
    convertedPoints.push(L.latLng(endLatlng));
  }

  L.geodesicConvertLines = function (latlngs, fill) {
    var i, j, len, geodesiclatlngs = [];
    for (i = 0, len = latlngs.length; i < len; i++) {
      if (L.Util.isArray(latlngs[i]) && typeof latlngs[i][0] !== 'number') {
        return;
      }
      latlngs[i] = L.latLng(latlngs[i]);
    }

    if(!fill) {
      geodesiclatlngs.push(latlngs[0]);
    }
    for (i = 0, len = latlngs.length - 1; i < len; i++) {
      geodesicConvertLine(latlngs[i], latlngs[i+1], geodesiclatlngs);
    }
    if(fill) {
      geodesicConvertLine(latlngs[len], latlngs[0], geodesiclatlngs);
    }
    return geodesiclatlngs;
  }

  L.GeodesicPolyline = geodesicPoly(L.Polyline, 0);
  L.GeodesicPolygon = geodesicPoly(L.Polygon, 1);

  //L.GeodesicMultiPolyline = createMulti(L.GeodesicPolyline);
  //L.GeodesicMultiPolygon = createMulti(L.GeodesicPolygon);

  /*L.GeodesicMultiPolyline = L.MultiPolyline.extend({
    initialize: function (latlngs, options) {
      L.MultiPolyline.prototype.initialize.call(this, L.geodesicConvertLines(latlngs), options);
    }
  });*/

  /*L.GeodesicMultiPolygon = L.MultiPolygon.extend({
    initialize: function (latlngs, options) {
      L.MultiPolygon.prototype.initialize.call(this, L.geodesicConvertLines(latlngs), options);
    }
  });*/

  L.GeodesicCircle = L.Polygon.extend({
    initialize: function (latlng, radius, options) {
      this._latlng = L.latLng(latlng);
      this._mRadius = radius;

      points = this._calcPoints();

      L.Polygon.prototype.initialize.call(this, points, options);
    },

    options: {
      fill: true
    },

    setLatLng: function (latlng) {
      this._latlng = L.latLng(latlng);
      points = this._calcPoints();
      this.setLatLngs(points);
    },

    setRadius: function (radius) {
      this._mRadius = radius;
      points = this._calcPoints();
      this.setLatLngs(points);

    },

    getLatLng: function () {
      return this._latlng;
    },

    getRadius: function() {
      return this._mRadius;
    },

    _calcPoints: function() {
      var R = 6378137; //earth radius in meters (approx - taken from leaflet source code)
      var d2r = L.LatLng.DEG_TO_RAD;
      var r2d = L.LatLng.RAD_TO_DEG;
//console.log("geodesicCircle: radius = "+this._mRadius+"m, centre "+this._latlng.lat+","+this._latlng.lng);

      // circle radius as an angle from the centre of the earth
      var radRadius = this._mRadius / R;

//console.log(" (radius in radians "+radRadius);

      // pre-calculate various values used for every point on the circle
      var centreLat = this._latlng.lat * d2r;
      var centreLng = this._latlng.lng * d2r;

      var cosCentreLat = Math.cos(centreLat);
      var sinCentreLat = Math.sin(centreLat);

      var cosRadRadius = Math.cos(radRadius);
      var sinRadRadius = Math.sin(radRadius);

      var calcLatLngAtAngle = function(angle) {
        var lat = Math.asin(sinCentreLat*cosRadRadius + cosCentreLat*sinRadRadius*Math.cos(angle));

        var lon = centreLng + Math.asin( Math.sin(angle) * sinRadRadius / cosCentreLat )

        return L.latLng(lat * r2d,lon * r2d);
      }

      var segments = Math.max(32,Math.floor(this._mRadius/1000));
//console.log(" (drawing circle as "+segments+" lines)");
      var points = [];
      for (var i=0; i<segments; i++) {
        var angle = Math.PI*2/segments*i;

        var point = calcLatLngAtAngle(angle)
        points.push ( point );
      }

      return points;
    },

  });

  L.geodesicPolyline = function (latlngs, options) {
    return new L.GeodesicPolyline(latlngs, options);
  };

  L.geodesicPolygon = function (latlngs, options) {
    return new L.GeodesicPolygon(latlngs, options);
  };

  /*
  L.geodesicMultiPolyline = function (latlngs, options) {
    return new L.GeodesicMultiPolyline(latlngs, options);
  };

  L.geodesicMultiPolygon = function (latlngs, options) {
    return new L.GeodesicMultiPolygon(latlngs, options);
  };

  */

  L.geodesicCircle = function (latlng, radius, options) {
    return new L.GeodesicCircle(latlng, radius, options);
  }

}());
<commit_msg>fix geodesic circle - formula had errors! https://plus.google.com/108582664457219405296/posts/CoNTvk5i4xF<commit_after>/*
Geodesic extension to Leaflet library, by Fragger
https://github.com/Fragger/Leaflet.Geodesic
Version from master branch, dated Apr 26, 2013
Modified by qnstie 2013-07-17 to maintain compatibility with Leaflet.draw
*/
(function () {
  function geodesicPoly(Klass, fill) {
    return Klass.extend({
      initialize: function (latlngs, options) {
        Klass.prototype.initialize.call(this, L.geodesicConvertLines(latlngs, fill), options);
        this._latlngsinit = this._convertLatLngs(latlngs);
      },
      getLatLngs: function () {
        return this._latlngsinit;
      },
      setLatLngs: function (latlngs) {
        this._latlngsinit = this._convertLatLngs(latlngs);
        return this.redraw();
      },
      addLatLng: function (latlng) {
        this._latlngsinit.push(L.latLng(latlng));
        return this.redraw();
      },
      spliceLatLngs: function () { // (Number index, Number howMany)
        var removed = [].splice.apply(this._latlngsinit, arguments);
        this._convertLatLngs(this._latlngsinit);
        this.redraw();
        return removed;
      },
      redraw: function() {
        this._latlngs = this._convertLatLngs(L.geodesicConvertLines(this._latlngsinit, fill));
        return Klass.prototype.redraw.call(this);
      }
    });
  }

  function geodesicConvertLine(startLatlng, endLatlng, convertedPoints) {
    var i,
      R = 6378137, // earth radius in meters (doesn't have to be exact)
      maxlength = 5000, // meters before splitting
      d2r = L.LatLng.DEG_TO_RAD,
      r2d = L.LatLng.RAD_TO_DEG,
      lat1, lat2, lng1, lng2, dLng, d, segments,
      f, A, B, x, y, z, fLat, fLng;

    dLng = Math.abs(endLatlng.lng - startLatlng.lng) * d2r;
    lat1 = startLatlng.lat * d2r;
    lat2 = endLatlng.lat * d2r;
    lng1 = startLatlng.lng * d2r;
    lng2 = endLatlng.lng * d2r;

    // http://en.wikipedia.org/wiki/Great-circle_distance
    d = Math.atan2(Math.sqrt( Math.pow(Math.cos(lat2) * Math.sin(dLng), 2) + Math.pow(Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLng), 2) ), Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(dLng));

    segments = Math.ceil(d * R / maxlength);
    // loop starts at 1 - we don't add the very first point
    // loop ends before 'segments' is reached - we don't add the very last point here but outside the loop
    // (this was to fix a bug - https://github.com/jonatkins/ingress-intel-total-conversion/issues/471
    //  rounding errors? maths bug? not sure - but it solves the issue! and is a slight optimisation)
    for (i = 1; i < segments; i++) {
      // http://williams.best.vwh.net/avform.htm#Intermediate
      f = i / segments;
      A = Math.sin((1-f)*d) / Math.sin(d);
      B = Math.sin(f*d) / Math.sin(d);
      x = A * Math.cos(lat1) * Math.cos(lng1) + B * Math.cos(lat2) * Math.cos(lng2);
      y = A * Math.cos(lat1) * Math.sin(lng1) + B * Math.cos(lat2) * Math.sin(lng2);
      z = A * Math.sin(lat1)                  + B * Math.sin(lat2);
      fLat = r2d * Math.atan2(z, Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
      fLng = r2d * Math.atan2(y, x);

      convertedPoints.push(L.latLng([fLat, fLng]));
    }
    // push the final point unmodified
    convertedPoints.push(L.latLng(endLatlng));
  }

  L.geodesicConvertLines = function (latlngs, fill) {
    var i, j, len, geodesiclatlngs = [];
    for (i = 0, len = latlngs.length; i < len; i++) {
      if (L.Util.isArray(latlngs[i]) && typeof latlngs[i][0] !== 'number') {
        return;
      }
      latlngs[i] = L.latLng(latlngs[i]);
    }

    if(!fill) {
      geodesiclatlngs.push(latlngs[0]);
    }
    for (i = 0, len = latlngs.length - 1; i < len; i++) {
      geodesicConvertLine(latlngs[i], latlngs[i+1], geodesiclatlngs);
    }
    if(fill) {
      geodesicConvertLine(latlngs[len], latlngs[0], geodesiclatlngs);
    }
    return geodesiclatlngs;
  }

  L.GeodesicPolyline = geodesicPoly(L.Polyline, 0);
  L.GeodesicPolygon = geodesicPoly(L.Polygon, 1);

  //L.GeodesicMultiPolyline = createMulti(L.GeodesicPolyline);
  //L.GeodesicMultiPolygon = createMulti(L.GeodesicPolygon);

  /*L.GeodesicMultiPolyline = L.MultiPolyline.extend({
    initialize: function (latlngs, options) {
      L.MultiPolyline.prototype.initialize.call(this, L.geodesicConvertLines(latlngs), options);
    }
  });*/

  /*L.GeodesicMultiPolygon = L.MultiPolygon.extend({
    initialize: function (latlngs, options) {
      L.MultiPolygon.prototype.initialize.call(this, L.geodesicConvertLines(latlngs), options);
    }
  });*/

  L.GeodesicCircle = L.Polygon.extend({
    initialize: function (latlng, radius, options) {
      this._latlng = L.latLng(latlng);
      this._mRadius = radius;

      points = this._calcPoints();

      L.Polygon.prototype.initialize.call(this, points, options);
    },

    options: {
      fill: true
    },

    setLatLng: function (latlng) {
      this._latlng = L.latLng(latlng);
      points = this._calcPoints();
      this.setLatLngs(points);
    },

    setRadius: function (radius) {
      this._mRadius = radius;
      points = this._calcPoints();
      this.setLatLngs(points);

    },

    getLatLng: function () {
      return this._latlng;
    },

    getRadius: function() {
      return this._mRadius;
    },

    _calcPoints: function() {
      var R = 6378137; //earth radius in meters (approx - taken from leaflet source code)
      var d2r = L.LatLng.DEG_TO_RAD;
      var r2d = L.LatLng.RAD_TO_DEG;
//console.log("geodesicCircle: radius = "+this._mRadius+"m, centre "+this._latlng.lat+","+this._latlng.lng);

      // circle radius as an angle from the centre of the earth
      var radRadius = this._mRadius / R;

//console.log(" (radius in radians "+radRadius);

      // pre-calculate various values used for every point on the circle
      var centreLat = this._latlng.lat * d2r;
      var centreLng = this._latlng.lng * d2r;

      var cosCentreLat = Math.cos(centreLat);
      var sinCentreLat = Math.sin(centreLat);

      var cosRadRadius = Math.cos(radRadius);
      var sinRadRadius = Math.sin(radRadius);

      var calcLatLngAtAngle = function(angle) {
        var lat = Math.asin(sinCentreLat*cosRadRadius + cosCentreLat*sinRadRadius*Math.cos(angle));
        var lng = centreLng + Math.atan2(Math.sin(angle)*sinRadRadius*cosCentreLat, cosRadRadius-sinCentreLat*Math.sin(lat));

        return L.latLng(lat * r2d,lng * r2d);
      }

      var segments = Math.max(32,Math.floor(this._mRadius/1000));
//console.log(" (drawing circle as "+segments+" lines)");
      var points = [];
      for (var i=0; i<segments; i++) {
        var angle = Math.PI*2/segments*i;

        var point = calcLatLngAtAngle(angle)
        points.push ( point );
      }

      return points;
    },

  });

  L.geodesicPolyline = function (latlngs, options) {
    return new L.GeodesicPolyline(latlngs, options);
  };

  L.geodesicPolygon = function (latlngs, options) {
    return new L.GeodesicPolygon(latlngs, options);
  };

  /*
  L.geodesicMultiPolyline = function (latlngs, options) {
    return new L.GeodesicMultiPolyline(latlngs, options);
  };

  L.geodesicMultiPolygon = function (latlngs, options) {
    return new L.GeodesicMultiPolygon(latlngs, options);
  };

  */

  L.geodesicCircle = function (latlng, radius, options) {
    return new L.GeodesicCircle(latlng, radius, options);
  }

}());
<|endoftext|>


<commit_before>/** This class should be used as a super class for those section classes
 * which wrap a given section of previousProcess
 * (it's about businessProcessUpdate functionality).
 */

'use strict';

var memoize               = require('memoizee/plain')
  , _                     = require('mano').i18n.bind('Model: FormSectionUpdate')
  , validDb               = require('dbjs/valid-dbjs')
  , defineStringLine      = require('dbjs-ext/string/string-line')
  , defineFormSectionBase = require('./form-section-base')
  , defineProgressRule    = require('./lib/progress-rule');

module.exports = memoize(function (db) {
	var StringLine, FormSectionUpdate, FormSectionBase, ProgressRule;
	validDb(db);
	StringLine      = defineStringLine(db);
	FormSectionBase = defineFormSectionBase(db);
	ProgressRule    = defineProgressRule(db);
	FormSectionUpdate = FormSectionBase.extend('FormSectionUpdate', {
		label: {
			value: function (_observe) {
				if (!this.sourceSection) return;
				return _observe(this.sourceSection._label);
			}
		},
		actionUrl: {
			value: function (_observe) {
				if (!this.sourceSection) return;
				return _observe(this.sourceSection._actionUrl);
			}
		},
		legend: {
			value: function (_observe) {
				if (!this.sourceSection) return;
				return _observe(this.sourceSection._legend);
			}
		},
		sourceSectionPath: {
			type: StringLine,
			value: function () {
				return this.__id__.slice(this.__id__.indexOf('/') + 1)
					.replace(this.constructor.updateSectionPostfix, '');
			}
		},
		sourceSection: {
			type: FormSectionBase,
			value: function () {
				var resolved;
				resolved = this.master.resolveSKeyPath(this.sourceSectionPath);
				if (!resolved || !resolved.value) return;
				return resolved.value;
			}
		},
		originalSourceSection: {
			type: FormSectionBase,
			value: function () {
				if (!this.master.previousProcess) return;
				return this.master.previousProcess.resolveSKeyPath(this.sourceSectionPath).value;
			}
		},
		resolvent: {
			label: _("Do you want to amend this section?"),
			type: db.Boolean,
			required: true
		},
		resolventValue: {
			value: true
		},
		resolventProperty: {
			value: function (_observe) {
				// We allow resolvent only if originalSourceSection is acceptable
				if (_observe(this.originalSourceSection._status) === 1) {
					return this.__id__.split('/').slice(1).join('/') + '/resolvent';
				}
			}
		},
		lastEditStamp: {
			value: function (_observe) {
				var res = 0, resolvedResolvent;

				if (this.resolventProperty) {
					resolvedResolvent = this.ensureResolvent(_observe);

					if (!resolvedResolvent) return;

					res = _observe(resolvedResolvent.object['_' + resolvedResolvent.key]._lastModified);
					if (res < 1e6) res = 0; // Ignore model stamps
				}

				if (_observe(this.sourceSection._lastEditStamp) > res) {
					res = this.sourceSection.lastEditStamp;
				}

				return res;
			}
		},
		propertyNamesDeep: {
			value: function (_observe) {
				var result = [];
				if (this.resolventProperty) result.push(this.resolventProperty);

				_observe(this.sourceSection.propertyNamesDeep).forEach(function (property) {
					result.push(property);
				});

				return result;
			}
		},
		hasDisplayableRuleDeep: {
			value: function (_observe) {
				if (_observe(this.progressRules.displayable._size) > 0) return true;

				return _observe(this.sourceSection._hasDisplayableRuleDeep);
			}
		},
		hasMissingRequiredPropertyNamesDeep: {
			value: function (_observe) {
				if (this.isUnresolved) {
					return this.resolventStatus < 1;
				}

				return _observe(this.sourceSection._hasMissingRequiredPropertyNamesDeep);
			}
		},
		hasFilledPropertyNamesDeep: {
			value: function (_observe) {
				if (this.isResolventFilled(_observe)) return true;

				return _observe(this.sourceSection._hasFilledPropertyNamesDeep);
			}
		},
		toJSON: { value: function (ignore) {
			var result = this.commonToJSON();
			if (this.resolventProperty) {
				result.fields = [this.master.resolveSKeyPath(this.resolventProperty)
					.ownDescriptor.fieldToJSON()];
			}
			if (!this.isUnresolved && this.sourceSection.hasFilledPropertyNamesDeep) {
				result.sections = [this.sourceSection.toJSON()];
			}
			return result;
		} },
		toWebServiceJSON: { value: function (ignore) {
			var fields = [], resolventDescriptor;
			if (this.resolventProperty) {
				resolventDescriptor = this.master.resolveSKeyPath(this.resolventProperty).ownDescriptor;
				if (!resolventDescriptor.isValueEmpty()) {
					fields.push(resolventDescriptor.fieldToWebServiceJSON());
				}
			}
			if (!this.isUnresolved && this.sourceSection.hasFilledPropertyNamesDeep) {
				fields = fields.concat(this.toWebServiceJSON());
			}

			return fields;
		} },
		toMetaDataJSON: {
			value: function (ignore) {
				return this.sourceSection.toMetaDataJSON();
			}
		},
		toWSSchema: {
			value: function (ignore) {
				// method is not for instance-only logic as is this class.
				throw new Error("toWSSchema not implemented for " + this.__id__);
			}
		}
	}, {
		updateSectionPostfix: {
			type: StringLine,
			value: "UpdatePostfix"
		}
	});

	FormSectionUpdate.prototype.progressRules.map.define('sourceSection', {
		type: ProgressRule,
		nested: true
	});

	FormSectionUpdate.prototype.progressRules.map.sourceSection.setProperties({
		progress: function (_observe) {
			var sum = 0, resolvedResolvent, isResolventExcluded, section;
			section = this.owner.owner.owner;

			if (_observe(section._resolventProperty)) {
				resolvedResolvent = section.ensureResolvent(_observe);

				if (!resolvedResolvent) return 0;

				isResolventExcluded = section.isPropertyExcludedFromStatus(resolvedResolvent, _observe);
				if (_observe(resolvedResolvent.observable) !== _observe(section._resolventValue)) {
					if (isResolventExcluded) return 1;

					if (resolvedResolvent.descriptor.multiple) {
						if (_observe(resolvedResolvent.observable).size) return 1;
					} else {
						if (_observe(resolvedResolvent.observable) != null) return 1;
					}

					return 0;
				}
				if (!isResolventExcluded) {
					++sum;
				}
			}
			if (section.sourceSection) {
				sum += (_observe(section.sourceSection._status) * _observe(section.sourceSection._weight));
			}

			if (!this.weight) return 1;

			return sum / this.weight;
		},
		weight: function (_observe) {
			var weightTotal = 0, resolvedResolvent, isResolventExcluded, section;
			section = this.owner.owner.owner;

			if (_observe(section._resolventProperty)) {
				resolvedResolvent = section.ensureResolvent(_observe);

				if (!resolvedResolvent) return 0;

				isResolventExcluded = section.isPropertyExcludedFromStatus(resolvedResolvent, _observe);
				if (_observe(resolvedResolvent.observable) !== _observe(section._resolventValue)) {
					return isResolventExcluded ? 0 : 1;
				}

				if (!isResolventExcluded) {
					++weightTotal;
				}
			}

			if (section.sourceSection) {
				weightTotal += _observe(section.sourceSection._weight);
			}

			return weightTotal;
		}
	});

	return FormSectionUpdate;
}, { normalizer: require('memoizee/normalizers/get-1')() });
<commit_msg>modified logic so that it will not crash once toWSSchema method is called for this object.<commit_after>/** This class should be used as a super class for those section classes
 * which wrap a given section of previousProcess
 * (it's about businessProcessUpdate functionality).
 */

'use strict';

var memoize               = require('memoizee/plain')
  , _                     = require('mano').i18n.bind('Model: FormSectionUpdate')
  , validDb               = require('dbjs/valid-dbjs')
  , defineStringLine      = require('dbjs-ext/string/string-line')
  , defineFormSectionBase = require('./form-section-base')
  , defineProgressRule    = require('./lib/progress-rule');

module.exports = memoize(function (db) {
	var StringLine, FormSectionUpdate, FormSectionBase, ProgressRule;
	validDb(db);
	StringLine      = defineStringLine(db);
	FormSectionBase = defineFormSectionBase(db);
	ProgressRule    = defineProgressRule(db);
	FormSectionUpdate = FormSectionBase.extend('FormSectionUpdate', {
		label: {
			value: function (_observe) {
				if (!this.sourceSection) return;
				return _observe(this.sourceSection._label);
			}
		},
		actionUrl: {
			value: function (_observe) {
				if (!this.sourceSection) return;
				return _observe(this.sourceSection._actionUrl);
			}
		},
		legend: {
			value: function (_observe) {
				if (!this.sourceSection) return;
				return _observe(this.sourceSection._legend);
			}
		},
		sourceSectionPath: {
			type: StringLine,
			value: function () {
				return this.__id__.slice(this.__id__.indexOf('/') + 1)
					.replace(this.constructor.updateSectionPostfix, '');
			}
		},
		sourceSection: {
			type: FormSectionBase,
			value: function () {
				var resolved;
				resolved = this.master.resolveSKeyPath(this.sourceSectionPath);
				if (!resolved || !resolved.value) return;
				return resolved.value;
			}
		},
		originalSourceSection: {
			type: FormSectionBase,
			value: function () {
				if (!this.master.previousProcess) return;
				return this.master.previousProcess.resolveSKeyPath(this.sourceSectionPath).value;
			}
		},
		resolvent: {
			label: _("Do you want to amend this section?"),
			type: db.Boolean,
			required: true
		},
		resolventValue: {
			value: true
		},
		resolventProperty: {
			value: function (_observe) {
				// We allow resolvent only if originalSourceSection is acceptable
				if (_observe(this.originalSourceSection._status) === 1) {
					return this.__id__.split('/').slice(1).join('/') + '/resolvent';
				}
			}
		},
		lastEditStamp: {
			value: function (_observe) {
				var res = 0, resolvedResolvent;

				if (this.resolventProperty) {
					resolvedResolvent = this.ensureResolvent(_observe);

					if (!resolvedResolvent) return;

					res = _observe(resolvedResolvent.object['_' + resolvedResolvent.key]._lastModified);
					if (res < 1e6) res = 0; // Ignore model stamps
				}

				if (_observe(this.sourceSection._lastEditStamp) > res) {
					res = this.sourceSection.lastEditStamp;
				}

				return res;
			}
		},
		propertyNamesDeep: {
			value: function (_observe) {
				var result = [];
				if (this.resolventProperty) result.push(this.resolventProperty);

				_observe(this.sourceSection.propertyNamesDeep).forEach(function (property) {
					result.push(property);
				});

				return result;
			}
		},
		hasDisplayableRuleDeep: {
			value: function (_observe) {
				if (_observe(this.progressRules.displayable._size) > 0) return true;

				return _observe(this.sourceSection._hasDisplayableRuleDeep);
			}
		},
		hasMissingRequiredPropertyNamesDeep: {
			value: function (_observe) {
				if (this.isUnresolved) {
					return this.resolventStatus < 1;
				}

				return _observe(this.sourceSection._hasMissingRequiredPropertyNamesDeep);
			}
		},
		hasFilledPropertyNamesDeep: {
			value: function (_observe) {
				if (this.isResolventFilled(_observe)) return true;

				return _observe(this.sourceSection._hasFilledPropertyNamesDeep);
			}
		},
		toJSON: { value: function (ignore) {
			var result = this.commonToJSON();
			if (this.resolventProperty) {
				result.fields = [this.master.resolveSKeyPath(this.resolventProperty)
					.ownDescriptor.fieldToJSON()];
			}
			if (!this.isUnresolved && this.sourceSection.hasFilledPropertyNamesDeep) {
				result.sections = [this.sourceSection.toJSON()];
			}
			return result;
		} },
		toWebServiceJSON: { value: function (ignore) {
			var fields = [], resolventDescriptor;
			if (this.resolventProperty) {
				resolventDescriptor = this.master.resolveSKeyPath(this.resolventProperty).ownDescriptor;
				if (!resolventDescriptor.isValueEmpty()) {
					fields.push(resolventDescriptor.fieldToWebServiceJSON());
				}
			}
			if (!this.isUnresolved && this.sourceSection.hasFilledPropertyNamesDeep) {
				fields = fields.concat(this.toWebServiceJSON());
			}

			return fields;
		} },
		toMetaDataJSON: {
			value: function (ignore) {
				return this.sourceSection.toMetaDataJSON();
			}
		},
		toWSSchema: {
			value: function (ignore) {
				// method is not for instance-only logic as is this class. Use fallback.
				return this.sourceSection.toWSSchema();
			}
		}
	}, {
		updateSectionPostfix: {
			type: StringLine,
			value: "UpdatePostfix"
		}
	});

	FormSectionUpdate.prototype.progressRules.map.define('sourceSection', {
		type: ProgressRule,
		nested: true
	});

	FormSectionUpdate.prototype.progressRules.map.sourceSection.setProperties({
		progress: function (_observe) {
			var sum = 0, resolvedResolvent, isResolventExcluded, section;
			section = this.owner.owner.owner;

			if (_observe(section._resolventProperty)) {
				resolvedResolvent = section.ensureResolvent(_observe);

				if (!resolvedResolvent) return 0;

				isResolventExcluded = section.isPropertyExcludedFromStatus(resolvedResolvent, _observe);
				if (_observe(resolvedResolvent.observable) !== _observe(section._resolventValue)) {
					if (isResolventExcluded) return 1;

					if (resolvedResolvent.descriptor.multiple) {
						if (_observe(resolvedResolvent.observable).size) return 1;
					} else {
						if (_observe(resolvedResolvent.observable) != null) return 1;
					}

					return 0;
				}
				if (!isResolventExcluded) {
					++sum;
				}
			}
			if (section.sourceSection) {
				sum += (_observe(section.sourceSection._status) * _observe(section.sourceSection._weight));
			}

			if (!this.weight) return 1;

			return sum / this.weight;
		},
		weight: function (_observe) {
			var weightTotal = 0, resolvedResolvent, isResolventExcluded, section;
			section = this.owner.owner.owner;

			if (_observe(section._resolventProperty)) {
				resolvedResolvent = section.ensureResolvent(_observe);

				if (!resolvedResolvent) return 0;

				isResolventExcluded = section.isPropertyExcludedFromStatus(resolvedResolvent, _observe);
				if (_observe(resolvedResolvent.observable) !== _observe(section._resolventValue)) {
					return isResolventExcluded ? 0 : 1;
				}

				if (!isResolventExcluded) {
					++weightTotal;
				}
			}

			if (section.sourceSection) {
				weightTotal += _observe(section.sourceSection._weight);
			}

			return weightTotal;
		}
	});

	return FormSectionUpdate;
}, { normalizer: require('memoizee/normalizers/get-1')() });
<|endoftext|>