<commit_before>/*global window, document*/
/*jshint laxbreak:true*/

var Util = (function() {
	return {
		oncef: function(aFunction) {
			var started = false;

			return function() {
				if (!started) {
					started = true;
					aFunction.apply(this, arguments);
				}
			};
		}
	};
})();

function Game() {
	var rings = [];
	var canvas = document.getElementById("canvas");
	var context = canvas.getContext('2d');
	var WIDTH = canvas.width;
	var HEIGHT = canvas.height;
	var CENTER_X = WIDTH / 2;
	var CENTER_Y = HEIGHT / 2;
	var MAX_SIDE = Math.max(WIDTH, HEIGHT);
	var MAX_LINE_WIDTH = 20;
	var RING_SPAWN_RATE = 1000;

	var INITIAL_SPEED = 4;
	var SPEED = INITIAL_SPEED;
	var SPEED_INCREMENT = 0;

	var ticker = (function() {
		return window.requestAnimationFrame
			|| window.webkitRequestAnimationFrame
			|| window.mozRequestAnimationFrame
			|| window.msRequestAnimationFrame
			|| window.oRequestAnimationFrame
			|| function(callback) {
				window.setTimeout(callback, 1000 / 60);
			};
	})();

	function spawnRing() {
		rings.unshift(new Ring());
	}

	function action() {
		for (var i = 0, len = rings.length; i < len; i++) {
			rings[i].act();
		}
	}

	function drawBgr() {
		context.rect(0, 0, WIDTH, HEIGHT);
		context.fillStyle = '#FFFFFF';
		context.fill();
	}

	function draw() {
		drawBgr();
		for (var i = 0, len = rings.length; i < len; i++) {
			rings[i].draw();
		}
	}

	function emptyRing(radius) {
		context.beginPath();
		context.arc(CENTER_X, CENTER_Y, radius, 0, 2 * Math.PI, false);
		context.lineWidth = MAX_LINE_WIDTH * (radius / MAX_SIDE);
		context.strokeStyle = '#000000';
		context.stroke();
	}

	function Ring() {
		this.radius = 10;

		this.draw = function () {
			emptyRing(this.radius);
		};

		this.act = function () {
			if (this.radius > MAX_SIDE) {
				rings.pop();
			}
			this.radius += SPEED * (this.radius / MAX_SIDE);
		};
	}

	var lastSpawn = 0;
	function render() {
		var now = +Date.now();

		if ((lastSpawn + RING_SPAWN_RATE) < now) {
			spawnRing();
			lastSpawn = lastSpawn ? (lastSpawn + RING_SPAWN_RATE) : now;
		}

		action();
		draw();
		SPEED += SPEED_INCREMENT;
	}

	function loop() {
		ticker(loop);
		render();
	}

	return {
		start: Util.oncef(loop)
	};
}

new Game().start();
<commit_msg>autoformat<commit_after>/*global window, document*/
/*jshint laxbreak:true*/

var Util = (function() {
	return {
		oncef: function(aFunction) {
			var started = false;

			return function() {
				if (!started) {
					started = true;
					aFunction.apply(this, arguments);
				}
			};
		}
	};
})();

function Game() {
	var rings = [];
	var canvas = document.getElementById("canvas");
	var context = canvas.getContext('2d');
	var WIDTH = canvas.width;
	var HEIGHT = canvas.height;
	var CENTER_X = WIDTH / 2;
	var CENTER_Y = HEIGHT / 2;
	var MAX_SIDE = Math.max(WIDTH, HEIGHT);
	var MAX_LINE_WIDTH = 20;
	var RING_SPAWN_RATE = 1000;

	var INITIAL_SPEED = 4;
	var SPEED = INITIAL_SPEED;
	var SPEED_INCREMENT = 0;

	var ticker = (function() {
		return window.requestAnimationFrame
			|| window.webkitRequestAnimationFrame
			|| window.mozRequestAnimationFrame
			|| window.msRequestAnimationFrame
			|| window.oRequestAnimationFrame
			|| function(callback) {
			window.setTimeout(callback, 1000 / 60);
		};
	})();

	function spawnRing() {
		rings.unshift(new Ring());
	}

	function action() {
		for (var i = 0, len = rings.length; i < len; i++) {
			rings[i].act();
		}
	}

	function drawBgr() {
		context.rect(0, 0, WIDTH, HEIGHT);
		context.fillStyle = '#FFFFFF';
		context.fill();
	}

	function draw() {
		drawBgr();
		for (var i = 0, len = rings.length; i < len; i++) {
			rings[i].draw();
		}
	}

	function emptyRing(radius) {
		context.beginPath();
		context.arc(CENTER_X, CENTER_Y, radius, 0, 2 * Math.PI, false);
		context.lineWidth = MAX_LINE_WIDTH * (radius / MAX_SIDE);
		context.strokeStyle = '#000000';
		context.stroke();
	}

	function Ring() {
		this.radius = 10;

		this.draw = function() {
			emptyRing(this.radius);
		};

		this.act = function() {
			if (this.radius > MAX_SIDE) {
				rings.pop();
			}
			this.radius += SPEED * (this.radius / MAX_SIDE);
		};
	}

	var lastSpawn = 0;

	function render() {
		var now = +Date.now();

		if ((lastSpawn + RING_SPAWN_RATE) < now) {
			spawnRing();
			lastSpawn = lastSpawn ? (lastSpawn + RING_SPAWN_RATE) : now;
		}

		action();
		draw();
		SPEED += SPEED_INCREMENT;
	}

	function loop() {
		ticker(loop);
		render();
	}

	return {
		start: Util.oncef(loop)
	};
}

new Game().start();
<|endoftext|>


<commit_before>(function() {
    'use strict';

    angular
        .module('blocks.storage')
        .factory('$localStorage', factory);

    factory.$inject = ['$window'];

    /* @ngInject */
    function factory($window) {
        var service = {
            set: set,
            get: get,
            setObject: setObject,
            getObject: getObject
        };

        return service;

        function set(key,value) {
          $window.localStorage[key] = value;
        }

        function get(key,defaultValue) {
          return $window.localStorage[key] || defaultValue;
        }

        function setObject(key,value) {
          $window.localStorage[key] = JSON.stringify(value);
        }

        function getObject(key) {
          return JSON.parse($window.localStorage[key] || '{}');
        }
    }
})();
<commit_msg>add remove for localStorage<commit_after>(function() {
    'use strict';

    angular
        .module('blocks.storage')
        .factory('$localStorage', factory);

    factory.$inject = ['$window'];

    /* @ngInject */
    function factory($window) {
        var service = {
            set: set,
            get: get,
            setObject: setObject,
            getObject: getObject,
            remove: remove
        };

        return service;

        function set(key,value) {
          $window.localStorage[key] = value;
        }

        function get(key,defaultValue) {
          return $window.localStorage[key] || defaultValue;
        }

        function setObject(key,value) {
          $window.localStorage[key] = JSON.stringify(value);
        }

        function getObject(key) {
          return JSON.parse($window.localStorage[key] || '{}');
        }

        function remove(key) {
            $window.localStorage.removeItem(key);
        }
    }
})();
<|endoftext|>


<commit_before>'use strict';

const assert = require('assert');
const fs = require('fs-extra');
const path = require('path');
const spawnSync = require('./spawn-sync');
const template = require('lodash.template');

const CONFIG = require('../config');

module.exports = function(packagedAppPath) {
  console.log(`Creating rpm package for "${packagedAppPath}"`);
  const atomExecutableName =
    CONFIG.channel === 'stable' ? 'atom' : `atom-${CONFIG.channel}`;
  const apmExecutableName =
    CONFIG.channel === 'stable' ? 'apm' : `apm-${CONFIG.channel}`;
  const appName = CONFIG.appName;
  const appDescription = CONFIG.appMetadata.description;
  // RPM versions can't have dashes or tildes in them.
  // (Ref.: https://twiki.cern.ch/twiki/bin/view/Main/RPMAndDebVersioning)
  const appVersion = CONFIG.appMetadata.version.replace(/-/g, '.');
  const policyFileName = `atom-${CONFIG.channel}.policy`;

  const rpmPackageDirPath = path.join(CONFIG.homeDirPath, 'rpmbuild');
  const rpmPackageBuildDirPath = path.join(rpmPackageDirPath, 'BUILD');
  const rpmPackageSourcesDirPath = path.join(rpmPackageDirPath, 'SOURCES');
  const rpmPackageSpecsDirPath = path.join(rpmPackageDirPath, 'SPECS');
  const rpmPackageRpmsDirPath = path.join(rpmPackageDirPath, 'RPMS');
  const rpmPackageApplicationDirPath = path.join(
    rpmPackageBuildDirPath,
    appName
  );
  const rpmPackageIconsDirPath = path.join(rpmPackageBuildDirPath, 'icons');

  if (fs.existsSync(rpmPackageDirPath)) {
    console.log(
      `Deleting existing rpm build directory at "${rpmPackageDirPath}"`
    );
    fs.removeSync(rpmPackageDirPath);
  }

  console.log(
    `Creating rpm package directory structure at "${rpmPackageDirPath}"`
  );
  fs.mkdirpSync(rpmPackageDirPath);
  fs.mkdirpSync(rpmPackageBuildDirPath);
  fs.mkdirpSync(rpmPackageSourcesDirPath);
  fs.mkdirpSync(rpmPackageSpecsDirPath);

  console.log(
    `Copying "${packagedAppPath}" to "${rpmPackageApplicationDirPath}"`
  );
  fs.copySync(packagedAppPath, rpmPackageApplicationDirPath);

  console.log(`Copying icons into "${rpmPackageIconsDirPath}"`);
  fs.copySync(
    path.join(
      CONFIG.repositoryRootPath,
      'resources',
      'app-icons',
      CONFIG.channel,
      'png'
    ),
    rpmPackageIconsDirPath
  );

  console.log(`Writing rpm package spec file into "${rpmPackageSpecsDirPath}"`);
  const rpmPackageSpecFilePath = path.join(rpmPackageSpecsDirPath, 'atom.spec');
  const rpmPackageSpecsTemplate = fs.readFileSync(
    path.join(
      CONFIG.repositoryRootPath,
      'resources',
      'linux',
      'redhat',
      'atom.spec.in'
    )
  );
  const rpmPackageSpecsContents = template(rpmPackageSpecsTemplate)({
    appName: appName,
    appFileName: atomExecutableName,
    apmFileName: apmExecutableName,
    description: appDescription,
    installDir: '/usr',
    version: appVersion,
    policyFileName
  });
  fs.writeFileSync(rpmPackageSpecFilePath, rpmPackageSpecsContents);

  console.log(`Writing desktop entry file into "${rpmPackageBuildDirPath}"`);
  const desktopEntryTemplate = fs.readFileSync(
    path.join(
      CONFIG.repositoryRootPath,
      'resources',
      'linux',
      'atom.desktop.in'
    )
  );
  const desktopEntryContents = template(desktopEntryTemplate)({
    appName: appName,
    appFileName: atomExecutableName,
    description: appDescription,
    installDir: '/usr',
    iconPath: atomExecutableName
  });
  fs.writeFileSync(
    path.join(rpmPackageBuildDirPath, `${atomExecutableName}.desktop`),
    desktopEntryContents
  );

  console.log(`Copying atom.sh into "${rpmPackageBuildDirPath}"`);
  fs.copySync(
    path.join(CONFIG.repositoryRootPath, 'atom.sh'),
    path.join(rpmPackageBuildDirPath, 'atom.sh')
  );

  console.log(`Copying atom.policy into "${rpmPackageBuildDirPath}"`);
  fs.copySync(
    path.join(CONFIG.repositoryRootPath, 'resources', 'linux', 'atom.policy'),
    path.join(rpmPackageBuildDirPath, policyFileName)
  );

  console.log(`Generating .rpm package from "${rpmPackageDirPath}"`);
  spawnSync('rpmbuild', ['-ba', '--clean', rpmPackageSpecFilePath]);
  for (let generatedArch of fs.readdirSync(rpmPackageRpmsDirPath)) {
    const generatedArchDirPath = path.join(
      rpmPackageRpmsDirPath,
      generatedArch
    );
    const generatedPackageFileNames = fs.readdirSync(generatedArchDirPath);
    assert(
      generatedPackageFileNames.length === 1,
      'Generated more than one rpm package'
    );
    const generatedPackageFilePath = path.join(
      generatedArchDirPath,
      generatedPackageFileNames[0]
    );
    const outputRpmPackageFilePath = path.join(
      CONFIG.buildOutputPath,
      `atom.${generatedArch}.rpm`
    );
    console.log(
      `Copying "${generatedPackageFilePath}" into "${outputRpmPackageFilePath}"`
    );
    fs.copySync(generatedPackageFilePath, outputRpmPackageFilePath);
  }
};
<commit_msg>Add debugging code to `create-rpm-package.js`<commit_after>'use strict';

const assert = require('assert');
const fs = require('fs-extra');
const path = require('path');
const spawnSync = require('./spawn-sync');
const template = require('lodash.template');

const CONFIG = require('../config');

module.exports = function(packagedAppPath) {
  console.log(`Creating rpm package for "${packagedAppPath}"`);
  const atomExecutableName =
    CONFIG.channel === 'stable' ? 'atom' : `atom-${CONFIG.channel}`;
  const apmExecutableName =
    CONFIG.channel === 'stable' ? 'apm' : `apm-${CONFIG.channel}`;
  const appName = CONFIG.appName;
  const appDescription = CONFIG.appMetadata.description;
  // RPM versions can't have dashes or tildes in them.
  // (Ref.: https://twiki.cern.ch/twiki/bin/view/Main/RPMAndDebVersioning)
  const appVersion = CONFIG.appMetadata.version.replace(/-/g, '.');
  const policyFileName = `atom-${CONFIG.channel}.policy`;

  const rpmPackageDirPath = path.join(CONFIG.homeDirPath, 'rpmbuild');
  const rpmPackageBuildDirPath = path.join(rpmPackageDirPath, 'BUILD');
  const rpmPackageSourcesDirPath = path.join(rpmPackageDirPath, 'SOURCES');
  const rpmPackageSpecsDirPath = path.join(rpmPackageDirPath, 'SPECS');
  const rpmPackageRpmsDirPath = path.join(rpmPackageDirPath, 'RPMS');
  const rpmPackageApplicationDirPath = path.join(
    rpmPackageBuildDirPath,
    appName
  );
  const rpmPackageIconsDirPath = path.join(rpmPackageBuildDirPath, 'icons');

  if (fs.existsSync(rpmPackageDirPath)) {
    console.log(
      `Deleting existing rpm build directory at "${rpmPackageDirPath}"`
    );
    fs.removeSync(rpmPackageDirPath);
  }

  console.log(
    `Creating rpm package directory structure at "${rpmPackageDirPath}"`
  );
  fs.mkdirpSync(rpmPackageDirPath);
  fs.mkdirpSync(rpmPackageBuildDirPath);
  fs.mkdirpSync(rpmPackageSourcesDirPath);
  fs.mkdirpSync(rpmPackageSpecsDirPath);

  console.log(
    `Copying "${packagedAppPath}" to "${rpmPackageApplicationDirPath}"`
  );
  fs.copySync(packagedAppPath, rpmPackageApplicationDirPath);

  try {
    fs.chmodSync(
      path.join(
        rpmPackageApplicationDirPath,
        'chrome-sandbox'
      ),
      '4755'
    );
  } catch (ex) {
    console.log('Chmod failed');

    spawnSync('find', [rpmPackageDirPath, '-name', 'chrome-sandbox'], {
      stdio: 'inherit',
    });
  }

  console.log(`Copying icons into "${rpmPackageIconsDirPath}"`);
  fs.copySync(
    path.join(
      CONFIG.repositoryRootPath,
      'resources',
      'app-icons',
      CONFIG.channel,
      'png'
    ),
    rpmPackageIconsDirPath
  );

  console.log(`Writing rpm package spec file into "${rpmPackageSpecsDirPath}"`);
  const rpmPackageSpecFilePath = path.join(rpmPackageSpecsDirPath, 'atom.spec');
  const rpmPackageSpecsTemplate = fs.readFileSync(
    path.join(
      CONFIG.repositoryRootPath,
      'resources',
      'linux',
      'redhat',
      'atom.spec.in'
    )
  );
  const rpmPackageSpecsContents = template(rpmPackageSpecsTemplate)({
    appName: appName,
    appFileName: atomExecutableName,
    apmFileName: apmExecutableName,
    description: appDescription,
    installDir: '/usr',
    version: appVersion,
    policyFileName
  });
  fs.writeFileSync(rpmPackageSpecFilePath, rpmPackageSpecsContents);

  console.log(`Writing desktop entry file into "${rpmPackageBuildDirPath}"`);
  const desktopEntryTemplate = fs.readFileSync(
    path.join(
      CONFIG.repositoryRootPath,
      'resources',
      'linux',
      'atom.desktop.in'
    )
  );
  const desktopEntryContents = template(desktopEntryTemplate)({
    appName: appName,
    appFileName: atomExecutableName,
    description: appDescription,
    installDir: '/usr',
    iconPath: atomExecutableName
  });
  fs.writeFileSync(
    path.join(rpmPackageBuildDirPath, `${atomExecutableName}.desktop`),
    desktopEntryContents
  );

  console.log(`Copying atom.sh into "${rpmPackageBuildDirPath}"`);
  fs.copySync(
    path.join(CONFIG.repositoryRootPath, 'atom.sh'),
    path.join(rpmPackageBuildDirPath, 'atom.sh')
  );

  console.log(`Copying atom.policy into "${rpmPackageBuildDirPath}"`);
  fs.copySync(
    path.join(CONFIG.repositoryRootPath, 'resources', 'linux', 'atom.policy'),
    path.join(rpmPackageBuildDirPath, policyFileName)
  );

  console.log(`Generating .rpm package from "${rpmPackageDirPath}"`);
  spawnSync('rpmbuild', ['-ba', '--clean', rpmPackageSpecFilePath]);
  for (let generatedArch of fs.readdirSync(rpmPackageRpmsDirPath)) {
    const generatedArchDirPath = path.join(
      rpmPackageRpmsDirPath,
      generatedArch
    );
    const generatedPackageFileNames = fs.readdirSync(generatedArchDirPath);
    assert(
      generatedPackageFileNames.length === 1,
      'Generated more than one rpm package'
    );
    const generatedPackageFilePath = path.join(
      generatedArchDirPath,
      generatedPackageFileNames[0]
    );
    const outputRpmPackageFilePath = path.join(
      CONFIG.buildOutputPath,
      `atom.${generatedArch}.rpm`
    );
    console.log(
      `Copying "${generatedPackageFilePath}" into "${outputRpmPackageFilePath}"`
    );
    fs.copySync(generatedPackageFilePath, outputRpmPackageFilePath);
  }
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

var normalizeOptions  = require('es5-ext/object/normalize-options')
  , capitalize        = require('es5-ext/string/#/capitalize')
  , hyphenToCamel     = require('es5-ext/string/#/hyphen-to-camel')
  , template          = require('es6-template-strings')
  , deferred          = require('deferred')
  , fs                = require('fs2')
  , path              = require('path')
  , exec              = deferred.promisify(require('child_process').execFile)
  , generateAppsList  = require('mano/scripts/generate-apps-list')
  , generateAppsConf  = require('mano/scripts/generate-apps-conf')
  , generateAppsCtrls = require('mano/scripts/generate-apps-controllers')
  , getApps           = require('mano/server/utils/resolve-apps');

var appTypes = {
	'users-admin': true,
	'meta-admin': { extraFiles: ['view/meta-admin'] },
	dispatcher: { extraFiles: ['view/dispatcher'],
		'client/model.js': 'client/model.js/official.tpl'
		},
	user: { extraFiles: ['view/user.js'] },
	public: { extraFiles: ['apps/public'] },
	official: true,
	'business-process-submitted': { 'client/program.js': 'client/program.js/business-process.tpl' },
	'business-process': true
};

var copyExtraFile = function (projectRoot, extraPath) {
	return fs.copy(path.resolve(extraPath),
		path.join(projectRoot, extraPath.split('extra-files/').slice(-1)[0]),
		{ intermediate: true });
};

module.exports = function (projectRoot, appName/*, options*/) {
	var options = normalizeOptions(arguments[2]), extraFilesPath, partialAppName, templateType
	  , appRootPath, templateVars = {}, findTemplate;

	appRootPath = path.resolve(projectRoot, 'apps', appName);
	extraFilesPath    = path.join(__dirname, 'extra-files');

	templateVars.appName       = appName;
	templateVars.className     = capitalize.call(hyphenToCamel.call(appName));
	templateVars.isBusinessProcessSubmitted = appName === 'business-process-submitted';

	if (appTypes[appName]) {
		templateType = appName;
	} else {
		var i = 0;
		do {
			--i;
			partialAppName = appName.split('-').slice(0, i).join('-');
			if (appTypes[partialAppName]) {
				templateType = partialAppName;
				break;
			}
		} while (partialAppName);
		if (!templateType) {
			templateType = 'authenticated';
		}
	}
	templateVars.appNameSuffix = hyphenToCamel.call(appName.replace(templateType + '-', ''));

	var templates = {};

	findTemplate = function (appPath, fName, templates, templatePath) {
		var partialAppName = appName, i = 0;
		if (templates[appPath] && path.basename(templates[appPath]) !== 'authenticated.tpl') return;
		while (partialAppName) {
			if (fName === partialAppName) {
				templates[appPath] = path.join(__dirname, 'templates', templatePath);
				return;
			}
			--i;
			partialAppName = appName.split('-').slice(0, i).join('-');
		}
	};

	return exec('node',
		[path.resolve(projectRoot, 'bin', 'adapt-app'), 'apps' + path.sep + appName],
		{ cwd: projectRoot }).then(function () {
		return fs.readdir(path.join(__dirname, 'templates'),
				{ depth: Infinity, type: { file: true } }).map(
			function (templatePath) {
				var fName = path.basename(templatePath, '.tpl')
			  , appPathRel = path.dirname(templatePath)
			  , appPath = path.join(appRootPath, appPathRel);

				if (appTypes[templateType][appPathRel] === templatePath) {
					templates[appPath] = path.join(__dirname, 'templates', templatePath);
					return;
				}
				if (fName === 'authenticated' && !templates[appPath]) {
					templates[appPath] = path.join(__dirname, 'templates', templatePath);
					return;
				}
				if (templateType === 'official') {
					findTemplate(appPath, fName, templates, templatePath);
					return;
				}
				if (fName === templateType) {
					templates[appPath] = path.join(__dirname, 'templates', templatePath);
				}
			}
		);
	}).then(function () {
		return fs.readdir(path.join(__dirname, 'extra-templates'),
				{ depth: Infinity, type: { file: true } }).map(
			function (templatePath) {
				var fName = path.basename(templatePath, '.tpl')
				  , projectPath = path.dirname(path.join(projectRoot,
						templatePath.replace('appname', templateVars.appName)));
				if (fName === templateType) {
					templates[projectPath] = path.join(__dirname, 'extra-templates', templatePath);
				}
			}
		);
	}).then(function () {
		var toResolve = [deferred.map(Object.keys(templates), function (appPath) {
			return fs.readFile(templates[appPath])(function (fContent) {
				var opts = { intermediate: true };
				fContent = template(fContent, templateVars, { partial: true });
				if (path.basename(path.dirname(appPath)) === 'bin') {
					opts.mode = 511;
				}
				return fs.writeFile(appPath, fContent, opts);
			})();
		})];
		if (appTypes[templateType] && appTypes[templateType].extraFiles) {
			var paths = appTypes[templateType].extraFiles.map(function (extraFile) {
				return path.join(extraFilesPath, extraFile);
			});
			toResolve.push(deferred.map(paths, function (extraPath) {
				return fs.stat(extraPath).then(function (stat) {
					if (stat.isDirectory()) {
						return fs.readdir(extraPath,
							{ depth: Infinity, type: { file: true } }).map(function (extraFile) {
							return copyExtraFile(projectRoot, path.join(extraPath, extraFile));
						});
					}
					return copyExtraFile(projectRoot, extraPath);
				});
			}));
		}
		return deferred.map(toResolve);
	}).then(function () {
		if (options.appFilesOnly) return;
		return deferred(
			generateAppsList(projectRoot),
			getApps(projectRoot).then(function (appsList) {
				return deferred(generateAppsConf(projectRoot, appsList),
					generateAppsCtrls(projectRoot, appsList));
			})
		);
	});
};
<commit_msg>#1108 fixed<commit_after>#!/usr/bin/env node

'use strict';

var normalizeOptions  = require('es5-ext/object/normalize-options')
  , capitalize        = require('es5-ext/string/#/capitalize')
  , hyphenToCamel     = require('es5-ext/string/#/hyphen-to-camel')
  , template          = require('es6-template-strings')
  , deferred          = require('deferred')
  , fs                = require('fs2')
  , path              = require('path')
  , exec              = deferred.promisify(require('child_process').execFile)
  , generateAppsList  = require('mano/scripts/generate-apps-list')
  , generateAppsConf  = require('mano/scripts/generate-apps-conf')
  , generateAppsCtrls = require('mano/scripts/generate-apps-controllers')
  , getApps           = require('mano/server/utils/resolve-apps');

var appTypes = {
	'users-admin': true,
	'meta-admin': { extraFiles: ['view/meta-admin'] },
	dispatcher: { extraFiles: ['view/dispatcher'],
		'client/model.js': 'client/model.js/official.tpl'
		},
	user: { extraFiles: ['view/user.js'] },
	public: { extraFiles: ['apps/public'] },
	official: true,
	'business-process-submitted': { 'client/program.js': 'client/program.js/business-process.tpl' },
	'business-process': true
};

var copyExtraFile = function (projectRoot, extraPath) {
	return fs.copy(path.resolve(extraPath),
		path.join(projectRoot, extraPath.split('extra-files/').slice(-1)[0]),
		{ intermediate: true });
};

module.exports = function (projectRoot, appName/*, options*/) {
	var options = normalizeOptions(arguments[2]), extraFilesPath, partialAppName, templateType
	  , appRootPath, templateVars = {}, findTemplate;

	appRootPath = path.resolve(projectRoot, 'apps', appName);
	extraFilesPath    = path.join(__dirname, 'extra-files');

	templateVars.appName       = appName;
	templateVars.className     = capitalize.call(hyphenToCamel.call(appName));
	templateVars.isBusinessProcessSubmitted = appName === 'business-process-submitted';

	if (appTypes[appName]) {
		templateType = appName;
	} else {
		var i = 0;
		do {
			--i;
			partialAppName = appName.split('-').slice(0, i).join('-');
			if (appTypes[partialAppName]) {
				templateType = partialAppName;
				break;
			}
		} while (partialAppName);
		if (!templateType) {
			templateType = 'authenticated';
		}
	}
	templateVars.appNameSuffix = hyphenToCamel.call(appName.replace(templateType + '-', ''));

	var templates = {};

	findTemplate = function (appPath, fName, templates, templatePath) {
		var partialAppName = appName, i = 0;
		if (templates[appPath] && path.basename(templates[appPath]) !== 'authenticated.tpl') return;
		while (partialAppName) {
			if (fName === partialAppName) {
				templates[appPath] = path.join(__dirname, 'templates', templatePath);
				return;
			}
			--i;
			partialAppName = appName.split('-').slice(0, i).join('-');
		}
	};

	return exec('node',
		[path.resolve(projectRoot, 'bin', 'adapt-app'), 'apps' + path.sep + appName],
		{ cwd: projectRoot }).then(function () {
		return fs.readdir(path.join(__dirname, 'templates'),
				{ depth: Infinity, type: { file: true } }).map(
			function (templatePath) {
				var fName = path.basename(templatePath, '.tpl')
			  , appPathRel = path.dirname(templatePath)
			  , appPath = path.join(appRootPath, appPathRel);

				if (appTypes[templateType] && appTypes[templateType][appPathRel] === templatePath) {
					templates[appPath] = path.join(__dirname, 'templates', templatePath);
					return;
				}
				if (fName === 'authenticated' && !templates[appPath]) {
					templates[appPath] = path.join(__dirname, 'templates', templatePath);
					return;
				}
				if (templateType === 'official') {
					findTemplate(appPath, fName, templates, templatePath);
					return;
				}
				if (fName === templateType) {
					templates[appPath] = path.join(__dirname, 'templates', templatePath);
				}
			}
		);
	}).then(function () {
		return fs.readdir(path.join(__dirname, 'extra-templates'),
				{ depth: Infinity, type: { file: true } }).map(
			function (templatePath) {
				var fName = path.basename(templatePath, '.tpl')
				  , projectPath = path.dirname(path.join(projectRoot,
						templatePath.replace('appname', templateVars.appName)));
				if (fName === templateType) {
					templates[projectPath] = path.join(__dirname, 'extra-templates', templatePath);
				}
			}
		);
	}).then(function () {
		var toResolve = [deferred.map(Object.keys(templates), function (appPath) {
			return fs.readFile(templates[appPath])(function (fContent) {
				var opts = { intermediate: true };
				fContent = template(fContent, templateVars, { partial: true });
				if (path.basename(path.dirname(appPath)) === 'bin') {
					opts.mode = 511;
				}
				return fs.writeFile(appPath, fContent, opts);
			})();
		})];
		if (appTypes[templateType] && appTypes[templateType].extraFiles) {
			var paths = appTypes[templateType].extraFiles.map(function (extraFile) {
				return path.join(extraFilesPath, extraFile);
			});
			toResolve.push(deferred.map(paths, function (extraPath) {
				return fs.stat(extraPath).then(function (stat) {
					if (stat.isDirectory()) {
						return fs.readdir(extraPath,
							{ depth: Infinity, type: { file: true } }).map(function (extraFile) {
							return copyExtraFile(projectRoot, path.join(extraPath, extraFile));
						});
					}
					return copyExtraFile(projectRoot, extraPath);
				});
			}));
		}
		return deferred.map(toResolve);
	}).then(function () {
		if (options.appFilesOnly) return;
		return deferred(
			generateAppsList(projectRoot),
			getApps(projectRoot).then(function (appsList) {
				return deferred(generateAppsConf(projectRoot, appsList),
					generateAppsCtrls(projectRoot, appsList));
			})
		);
	});
};
<|endoftext|>


<commit_before>/*! uppie v1.0.11 | (c) silverwind | BSD license */
!function(e,n){"function"==typeof define&&define.amd?define([],n):"object"==typeof module&&module.exports?module.exports=n():e.Uppie=n()}("undefined"!=typeof self?self:this,function(){"use strict";return function(){return function(e,n){e instanceof NodeList?[].slice.call(e).forEach(function(e){i(e,n)}):i(e,n)}};function i(e,i){if("input"===e.tagName.toLowerCase()&&"file"===e.type)e.addEventListener("change",function(e){var n=e.target;n.files&&n.files.length?a(n,i.bind(null,e)):"getFilesAndDirectories"in n?t(n,i.bind(null,e)):i(e)});else{var n=function(e){e.preventDefault()};e.addEventListener("dragover",n),e.addEventListener("dragenter",n),e.addEventListener("drop",function(e){e.preventDefault();var n=e.dataTransfer;n.items&&n.items.length&&"webkitGetAsEntry"in n.items[0]?function(e,n){var a=new FormData,o=[],i=[];function r(e,t,i){t||(t=e.name),function i(t,e,a,o){var r=e||t.createReader();r.readEntries(function(e){var n=a?a.concat(e):e;e.length?setTimeout(i.bind(null,t,r,n,o),0):o(n)})}(e,0,0,function(e){var n=[];e.forEach(function(e){n.push(new Promise(function(i){e.isFile?e.file(function(e){var n=t+"/"+e.name;a.append("files[]",e,n),o.push(n),i()},i.bind()):r(e,t+"/"+e.name,i)}))}),Promise.all(n).then(i.bind())})}[].slice.call(e).forEach(function(e){(e=e.webkitGetAsEntry())&&i.push(new Promise(function(n){e.isFile?e.file(function(e){a.append("files[]",e,e.name),o.push(e.name),n()},n.bind()):e.isDirectory&&r(e,null,n)}))}),Promise.all(i).then(n.bind(null,a,o))}(n.items,i.bind(null,e)):"getFilesAndDirectories"in n?t(n,i.bind(null,e)):n.files?a(n,i.bind(null,e)):i()})}}function t(e,i){var o=new FormData,r=[],l=function(e,t,n){var a=[];e.forEach(function(i){a.push(new Promise(function(n){if("getFilesAndDirectories"in i)i.getFilesAndDirectories().then(function(e){l(e,i.path+"/",n)});else{if(i.name){var e=(t+i.name).replace(/^[/\\]/,"");o.append("files[]",i,e),r.push(e)}n()}}))}),Promise.all(a).then(n)};e.getFilesAndDirectories().then(function(n){new Promise(function(e){l(n,"/",e)}).then(i.bind(null,o,r))})}function a(e,n){var i=new FormData,t=[];[].slice.call(e.files).forEach(function(e){i.append("files[]",e,e.webkitRelativePath||e.name),t.push(e.webkitRelativePath||e.name)}),n(i,t)}});<commit_msg>rebuild<commit_after>/*! uppie v1.0.11 | (c) silverwind | BSD license */
!function(e,n){"function"==typeof define&&define.amd?define([],n):"object"==typeof module&&module.exports?module.exports=n():e.Uppie=n()}("undefined"!=typeof self?self:this,function(){"use strict";return function(){return function(e,n){e instanceof NodeList?[].slice.call(e).forEach(function(e){i(e,n)}):i(e,n)}};function i(e,i){if("input"===e.tagName.toLowerCase()&&"file"===e.type)e.addEventListener("change",function(e){var n=e.target;n.files&&n.files.length?a(n,i.bind(null,e)):"getFilesAndDirectories"in n?t(n,i.bind(null,e)):i(e)});else{var n=function(e){e.preventDefault()};e.addEventListener("dragover",n),e.addEventListener("dragenter",n),e.addEventListener("drop",function(e){e.preventDefault();var n=e.dataTransfer;n.items&&n.items.length&&"webkitGetAsEntry"in n.items[0]?function(e,n){var a=new FormData,o=[],i=[];function r(e,t,i){t||(t=e.name),function i(t,e,a,o){var r=e||t.createReader();r.readEntries(function(e){var n=a?a.concat(e):e;e.length?setTimeout(i.bind(null,t,r,n,o),0):o(n)})}(e,0,0,function(e){var n=[];e.forEach(function(e){n.push(new Promise(function(i){e.isFile?e.file(function(e){var n=t+"/"+e.name;a.append("files[]",e,n),o.push(n),i()},i.bind()):r(e,t+"/"+e.name,i)}))}),Promise.all(n).then(i.bind())})}[].slice.call(e).forEach(function(e){(e=e.webkitGetAsEntry())&&i.push(new Promise(function(n){e.isFile?e.file(function(e){a.append("files[]",e,e.name),o.push(e.name),n()},n.bind()):e.isDirectory&&r(e,null,n)}))}),Promise.all(i).then(n.bind(null,a,o))}(n.items,i.bind(null,e)):"getFilesAndDirectories"in n?t(n,i.bind(null,e)):n.files?a(n,i.bind(null,e)):i(e)})}}function t(e,i){var o=new FormData,r=[],l=function(e,t,n){var a=[];e.forEach(function(i){a.push(new Promise(function(n){if("getFilesAndDirectories"in i)i.getFilesAndDirectories().then(function(e){l(e,i.path+"/",n)});else{if(i.name){var e=(t+i.name).replace(/^[/\\]/,"");o.append("files[]",i,e),r.push(e)}n()}}))}),Promise.all(a).then(n)};e.getFilesAndDirectories().then(function(n){new Promise(function(e){l(n,"/",e)}).then(i.bind(null,o,r))})}function a(e,n){var i=new FormData,t=[];[].slice.call(e.files).forEach(function(e){i.append("files[]",e,e.webkitRelativePath||e.name),t.push(e.webkitRelativePath||e.name)}),n(i,t)}});<|endoftext|>


<commit_before>// @flow

import { createSelector } from 'reselect';
import createEntityReducer from '../utils/createEntityReducer';
import { Poll } from '../actions/ActionTypes';

export type PollEntity = {
  id: number,
  title: string,
  description: string,
  pinned: boolean,
  tags: Array<string>,
  hasAnswered: boolean,
  totalVotes: number,
  options: Array<OptionEntity>
};

export type OptionEntity = {
  id: number,
  name: string,
  votes: number
};

export default createEntityReducer({
  key: 'polls',
  types: {
    fetch: [Poll.FETCH, Poll.FETCH_ALL],
    mutate: Poll.CREATE
  },
  mutate(state, action) {
    switch (action.type) {
      case Poll.DELETE.SUCCESS:
        return {
          ...state,
          items: state.items.filter(id => action.meta.polls !== id)
        };
      default:
        return state;
    }
  }
});

export const selectPolls = createSelector(
  state => state.polls.byId,
  state => state.polls.items,
  (pollsById, pollsIds) => {
    return pollsIds.map(id => pollsById[id]);
  }
);

export const selectPollsById = createSelector(
  selectPolls,
  (state, pollsId) => pollsId,
  (polls, pollsId) => {
    if (!polls || !pollsId) return {};
    return polls.find(polls => Number(polls.id) === Number(pollsId));
  }
);

export const selectPollByTag = createSelector(
  selectPolls,
  (state, tag) => tag,
  (polls, tag) => {
    if (!polls || !tag) return {};
    return polls.find(polls => polls.tags.includes(tag));
  }
);

export const selectPinnedPolls = createSelector(selectPolls, polls =>
  polls.find(polls => polls.pinned)
);
<commit_msg>Removed unused selector, change pinned selector to use filter and not find<commit_after>// @flow

import { createSelector } from 'reselect';
import createEntityReducer from '../utils/createEntityReducer';
import { Poll } from '../actions/ActionTypes';

export type PollEntity = {
  id: number,
  title: string,
  description: string,
  pinned: boolean,
  tags: Array<string>,
  hasAnswered: boolean,
  totalVotes: number,
  options: Array<OptionEntity>
};

export type OptionEntity = {
  id: number,
  name: string,
  votes: number
};

export default createEntityReducer({
  key: 'polls',
  types: {
    fetch: [Poll.FETCH, Poll.FETCH_ALL],
    mutate: Poll.CREATE
  },
  mutate(state, action) {
    switch (action.type) {
      case Poll.DELETE.SUCCESS:
        return {
          ...state,
          items: state.items.filter(id => action.meta.polls !== id)
        };
      default:
        return state;
    }
  }
});

export const selectPolls = createSelector(
  state => state.polls.byId,
  state => state.polls.items,
  (pollsById, pollsIds) => {
    return pollsIds.map(id => pollsById[id]);
  }
);

export const selectPollsById = createSelector(
  selectPolls,
  (state, pollsId) => pollsId,
  (polls, pollsId) => {
    if (!polls || !pollsId) return {};
    return polls.find(polls => Number(polls.id) === Number(pollsId));
  }
);

export const selectPinnedPolls = createSelector(selectPolls, polls =>
  polls.filter(polls => polls.pinned)
);
<|endoftext|>


<commit_before>"use strict";
// Log class

var config    = require('./config');
var plugins;
var connection;
var outbound;
var constants = require('./constants');
var util      = require('util');
var tty = require('tty')

var logger = exports;

logger.LOGDATA      = 9;
logger.LOGPROTOCOL  = 8;
logger.LOGDEBUG     = 7;
logger.LOGINFO      = 6;
logger.LOGNOTICE    = 5;
logger.LOGWARN      = 4;
logger.LOGERROR     = 3;
logger.LOGCRIT      = 2;
logger.LOGALERT     = 1;
logger.LOGEMERG     = 0;

logger.colors = { // Makes me cringe spelling it this way...
    "DATA" : "green",
    "PROTOCOL" : "green",
    "DEBUG" : "grey",
    "INFO" : "cyan",
    "info" : "cyan",
    "NOTICE" : "blue",
    "WARN" : "red",
    "ERROR" : "red",
    "CRIT" : "red",
    "ALERT" : "red",
    "EMERG" : "red"
};

var stdout_is_tty = tty.isatty(process.stdout.fd);

function colorize (color, str) {
    if (!util.inspect.colors[color]) return str;
    return '\u001b[' + util.inspect.colors[color][0] + 'm' + str +
              '\u001b[' + util.inspect.colors[color][1] + 'm';
}

var loglevel = logger.LOGWARN;

var deferred_logs = [];

logger.dump_logs = function (exit) {
    while (deferred_logs.length > 0) {
        var log_item = deferred_logs.shift();
        var color = logger.colors[log_item.level];
        if (color && stdout_is_tty) {
            console.log(colorize(color,log_item.data));
        }
        else {
            console.log(log_item.data);
        }
    }
    if (exit) {
        process.exit(1);
    }
}

logger.log = function (level, data) {
    if (level === 'PROTOCOL') {
        data = data.replace(/\n/g, '\\n\n');
    }
    data = data.replace(/\r/g, '\\r')
               .replace(/\n$/, '');
    // todo - just buffer these up (defer) until plugins are loaded
    if (plugins && plugins.plugin_list) {
        while (deferred_logs.length > 0) {
            var log_item = deferred_logs.shift();
            plugins.run_hooks('log', logger, log_item);
        }
        plugins.run_hooks('log', logger, {
            'level' : level,
            'data'  : data
        });
    }
    else {
        deferred_logs.push({
            'level' : level,
            'data'  : data
        });
    }
}

logger.log_respond = function (retval, msg, data) {
    // any other return code is irrelevant
    if (retval === constants.cont) {
        var color = logger.colors[data.level];
        if (color && stdout_is_tty) {
            return console.log(colorize(color,data.data));
        }
        else {
            return console.log(data.data);
        }
    }
};

logger._init_loglevel = function () {
    var self = this;
    var _loglevel = config.get('loglevel', 'value', function () {
        self._init_loglevel();
    });
    if (_loglevel) {
        var loglevel_num = parseInt(_loglevel);
        if (!loglevel_num || loglevel_num === NaN) {
            this.log('info', 'loglevel: ' + _loglevel.toUpperCase());
            loglevel = logger[_loglevel.toUpperCase()];
        }
        else {
            loglevel = loglevel_num;
        }
        if (!loglevel) {
            loglevel = logger.LOGWARN;
        }
    }
};

logger.would_log = function (level) {
    if (loglevel < level) return false;
    return true;
}

var original_console_log = console.log;

logger._init_timestamps = function () {
    var self = this;
    var _timestamps = config.get('log_timestamps', 'value', function () {
        self._init_timestamps();
    });
    if (_timestamps) {
        console.log = original_console_log.bind(console, new Date().toISOString());
    }
    else {
        console.log = original_console_log;
    }
}

logger._init_loglevel();
logger._init_timestamps();

var level, key;
for (key in logger) {
    if(logger.hasOwnProperty(key)) {
        if (key.match(/^LOG\w/)) {
            level = key.slice(3);
            logger[key.toLowerCase()] = (function(level, key) {
                return function() {
                    if (loglevel < logger[key])
                        return;
                    var levelstr = "[" + level + "]";
                    var str = "";
                    var uuidstr = "[-]";
                    var pluginstr = "[core]";
                    for (var i = 0; i < arguments.length; i++) {
                        var data = arguments[i];
                        if (typeof(data) === 'object') {
                            // if the object is a connection, we wish to add
                            // the connection id
                            if (data instanceof connection.Connection) {
                                uuidstr = "[" + data.uuid;
                                if (data.tran_count > 0) {
                                  uuidstr += "." + data.tran_count;
                                }
                                uuidstr += "]";
                            }
                            else if (data instanceof plugins.Plugin) {
                                pluginstr = "[" + data.name + "]";
                            }
                            else if (data instanceof outbound.HMailItem) {
                                pluginstr = "[outbound]";
                                if (data.todo && data.todo.uuid) {
                                    uuidstr = "[" + data.todo.uuid + "]";
                                }
                            }
                            else {
                                str += util.inspect(data);
                            }
                        }
                        else {
                            str += data;
                        }
                    }
                    logger.log(level, [levelstr, uuidstr, pluginstr, str].join(" "));
                }
            })(level, key);
        }
    }
}

// load these down here so it sees all the logger methods compiled above
plugins = require('./plugins');
connection = require('./connection');
outbound = require('./outbound');
<commit_msg>Update logger.js<commit_after>"use strict";
// Log class

var config    = require('./config');
var plugins;
var connection;
var outbound;
var constants = require('./constants');
var util      = require('util');
var tty = require('tty')

var logger = exports;

logger.LOGDATA      = 9;
logger.LOGPROTOCOL  = 8;
logger.LOGDEBUG     = 7;
logger.LOGINFO      = 6;
logger.LOGNOTICE    = 5;
logger.LOGWARN      = 4;
logger.LOGERROR     = 3;
logger.LOGCRIT      = 2;
logger.LOGALERT     = 1;
logger.LOGEMERG     = 0;

logger.colors = { // Makes me cringe spelling it this way...
    "DATA" : "green",
    "PROTOCOL" : "green",
    "DEBUG" : "grey",
    "INFO" : "cyan",
    "info" : "cyan",
    "NOTICE" : "blue",
    "WARN" : "red",
    "ERROR" : "red",
    "CRIT" : "red",
    "ALERT" : "red",
    "EMERG" : "red"
};

var stdout_is_tty = tty.isatty(process.stdout.fd);

function colorize (color, str) {
    if (!util.inspect.colors || !util.inspect.colors[color]) return str;
    return '\u001b[' + util.inspect.colors[color][0] + 'm' + str +
              '\u001b[' + util.inspect.colors[color][1] + 'm';
}

var loglevel = logger.LOGWARN;

var deferred_logs = [];

logger.dump_logs = function (exit) {
    while (deferred_logs.length > 0) {
        var log_item = deferred_logs.shift();
        var color = logger.colors[log_item.level];
        if (color && stdout_is_tty) {
            console.log(colorize(color,log_item.data));
        }
        else {
            console.log(log_item.data);
        }
    }
    if (exit) {
        process.exit(1);
    }
}

logger.log = function (level, data) {
    if (level === 'PROTOCOL') {
        data = data.replace(/\n/g, '\\n\n');
    }
    data = data.replace(/\r/g, '\\r')
               .replace(/\n$/, '');
    // todo - just buffer these up (defer) until plugins are loaded
    if (plugins && plugins.plugin_list) {
        while (deferred_logs.length > 0) {
            var log_item = deferred_logs.shift();
            plugins.run_hooks('log', logger, log_item);
        }
        plugins.run_hooks('log', logger, {
            'level' : level,
            'data'  : data
        });
    }
    else {
        deferred_logs.push({
            'level' : level,
            'data'  : data
        });
    }
}

logger.log_respond = function (retval, msg, data) {
    // any other return code is irrelevant
    if (retval === constants.cont) {
        var color = logger.colors[data.level];
        if (color && stdout_is_tty) {
            return console.log(colorize(color,data.data));
        }
        else {
            return console.log(data.data);
        }
    }
};

logger._init_loglevel = function () {
    var self = this;
    var _loglevel = config.get('loglevel', 'value', function () {
        self._init_loglevel();
    });
    if (_loglevel) {
        var loglevel_num = parseInt(_loglevel);
        if (!loglevel_num || loglevel_num === NaN) {
            this.log('info', 'loglevel: ' + _loglevel.toUpperCase());
            loglevel = logger[_loglevel.toUpperCase()];
        }
        else {
            loglevel = loglevel_num;
        }
        if (!loglevel) {
            loglevel = logger.LOGWARN;
        }
    }
};

logger.would_log = function (level) {
    if (loglevel < level) return false;
    return true;
}

var original_console_log = console.log;

logger._init_timestamps = function () {
    var self = this;
    var _timestamps = config.get('log_timestamps', 'value', function () {
        self._init_timestamps();
    });
    if (_timestamps) {
        console.log = original_console_log.bind(console, new Date().toISOString());
    }
    else {
        console.log = original_console_log;
    }
}

logger._init_loglevel();
logger._init_timestamps();

var level, key;
for (key in logger) {
    if(logger.hasOwnProperty(key)) {
        if (key.match(/^LOG\w/)) {
            level = key.slice(3);
            logger[key.toLowerCase()] = (function(level, key) {
                return function() {
                    if (loglevel < logger[key])
                        return;
                    var levelstr = "[" + level + "]";
                    var str = "";
                    var uuidstr = "[-]";
                    var pluginstr = "[core]";
                    for (var i = 0; i < arguments.length; i++) {
                        var data = arguments[i];
                        if (typeof(data) === 'object') {
                            // if the object is a connection, we wish to add
                            // the connection id
                            if (data instanceof connection.Connection) {
                                uuidstr = "[" + data.uuid;
                                if (data.tran_count > 0) {
                                  uuidstr += "." + data.tran_count;
                                }
                                uuidstr += "]";
                            }
                            else if (data instanceof plugins.Plugin) {
                                pluginstr = "[" + data.name + "]";
                            }
                            else if (data instanceof outbound.HMailItem) {
                                pluginstr = "[outbound]";
                                if (data.todo && data.todo.uuid) {
                                    uuidstr = "[" + data.todo.uuid + "]";
                                }
                            }
                            else {
                                str += util.inspect(data);
                            }
                        }
                        else {
                            str += data;
                        }
                    }
                    logger.log(level, [levelstr, uuidstr, pluginstr, str].join(" "));
                }
            })(level, key);
        }
    }
}

// load these down here so it sees all the logger methods compiled above
plugins = require('./plugins');
connection = require('./connection');
outbound = require('./outbound');
<|endoftext|>


<commit_before>/**
 * Processes and draws the TypeDNA diagram.
 *
 * Authors:
 *  - Michael Fiest
 *  - Eddie Antonio Santos
 *  - Ian Watts
 */

// http://colorbrewer2.org/?type=diverging&scheme=RdBu&n=3
// ['#ef8a62','#f7f7f7','#67a9cf'];
var COLOR_START = '#ef8a62';
var COLOR_END = '#67a9cf';

/* Run right after the page (and this script) finishes loading. */
document.addEventListener('DOMContentLoaded', function () {
  var container = document.getElementById('dna-table');

  /* XXX: */
  var processed = window.preprocessedData = preprocessData(window.DATA);
  var filtered = window.filteredData = filterTypes(processed, {
  });

  /* Make this arbitrarily large. */
  var height = 20 * filtered.types.length;

  drawGraph(filtered, container.offsetWidth, height);
});

/* Shim the assert function in there! */
!window.assert ? (window.assert = console.assert.bind(console)) : undefined;

var VALID_STEP_SIZES = d3.set(['hour', 'day', 'month', 'week']);

/*=== Classes ===*/

/**
 * Class: ASTDiff
 *
 * Instantiated with an original data object.
 */
function ASTDiff(original) {
  /* Instantiate a new ASTDiff object if called without `new`. */
  if (!(this instanceof ASTDiff)) {
    return new ASTDiff(original);
  }

  var date = new Date(original.date);
  /* The date must be reasonable... */
  assert(date > new Date('1970-01-01') && date < new Date());
  assert(typeof original.type === 'string');
  assert(ASTDiff.EDIT_KIND.has(original.edit));
  assert(looksLikeAnEmail(original.author));

  this.date = date;
  this.type = original.type;
  this.author = original.author;
  this.edit = original.edit;
  this.commit = original.commitID;
}

/**
 * The set of edit kinds.
 */
ASTDiff.EDIT_KIND = d3.set(['ADD', 'REMOVE']);

/**
 * ASTDiff methods and computed properties.
 */
Object.defineProperties(ASTDiff.prototype, {
  isAdd: {
    get: function () {
      return this.edit === 'ADD';
    }
  },

  isRemove: {
    get: function () {
      return this.edit === 'REMOVE';
    }
  },

  /**
   * Delegate valueOf() to the internal date object. This makes relational
   * comparisons with ASTDiff objects equivillent to comparing their dates.
   * (i.e.,
   *    (ASTDiff(...) < ASTDiff(...)) ===
   *        (ASTDiff(...).date < ASTDiff(...))
   * )
   */
  valueOf: {
    value: function () {
      return this.date.valueOf();
    },
  }
});

/**
 * Class: Cell
 *
 * Represents the data for a single cell in the table.
 */
function Cell(start, until, type) {
  /* Instantiate a new Cell object if called without `new`. */
  if (!(this instanceof Cell)) {
    return new Cell(start, until, type);
  }

  assert(start instanceof Date);
  assert(until instanceof Date);
  assert(typeof type === 'string');

  this.data = []
  this.startDate = start;
  this.endDate = until;
  this.type = type;
}

Object.defineProperties(Cell.prototype, {
  /**
   * Given a bunch of ASTDiffs,
   * sets this cell's data to the appropriate ASTDiff.
   */
  setDataFromSortedASTDiffs: {
    value: function setDataFromSortedASTDiffs(astDiffs) {
      assert(astDiffs instanceof Array);
      var typeName = this.type;

      var lowerIndex = d3.bisectLeft(astDiffs, this.startDate);
      /* Do not include upper index. */
      var upperIndex = d3.bisectLeft(astDiffs, this.endDate);

      this.data = astDiffs
        .slice(lowerIndex, upperIndex)
        .filter(function (diff) {
          return diff.type === typeName;
        });

      return this;
    },
  },

  /**
   * if the cell has demonstrable data.
   */
  hasData: {
    get: function () {
      return this.data && (this.data.length > 0);
    }
  }
});

/*=== Core functions ====*/

/**
 * Modifies original data.
 */
function preprocessData(data) {
  assert(data.types instanceof Array);
  assert(data.commits instanceof Array);
  assert(data.dates instanceof Array);

  return {
    /* A set of types. */
    types: d3.set(data.types),

    /* Mapping GitSha -> Commit MetaData. */
    commits: (function () {
      var commitMap = {};
      data.commits.forEach(function (commit) {
        assert(typeof commit.commitID  === 'string');
        var sha = commit.commitID;
        assert(looksLikeAGitSha(sha));

        commitMap[sha] = commit;
      });
      return commitMap;
    }()),

    /* A copy of AST Diff data, in asscending order of date. */
    astDiffs: (function (astDiffsByType) {
      return astDiffsByType
        .map(ASTDiff)
        .sort(function (a, b) {
          assert(a instanceof ASTDiff);
          return d3.ascending(a.date, b.date);
        });
    }(data.dates.slice()))
  };
}

/**
 * Takes preprocessed data, and returns an array of types, in ascending order
 * of popularity.
 *
 * Each type has its Cells, with ASTDiffs.
 */
function filterTypes(data, filters) {
  assert(filters);
  /* Either the date provided, or the first date attested. */
  var startDate = filters.start || data.astDiffs[0].date;
  /* Either the date provided or right NOW! */
  var endDate = filters.end || new Date();
  var numberOfTypesUpperBound = filters.limit || Infinity;
  var cellSize = filters.stepSize || 'day';

  assert(startDate instanceof Date);
  assert(endDate instanceof Date);
  assert(startDate < endDate);
  assert(typeof numberOfTypesUpperBound === 'number');
  assert(VALID_STEP_SIZES.has(cellSize));

  /* Find the range of diffs to use. */
  var lowerIndex = d3.bisectLeft(data.astDiffs, startDate);
  var upperIndex = d3.bisectRight(data.astDiffs, endDate);

  var applicableDiffs = data.astDiffs.slice(lowerIndex, upperIndex);
  /* Filter types, first by the types that are ACTUALLY present in the
   * filtered ASTDiffs */
  var typesPresent = countTypeAbsoluteFrequency(applicableDiffs);
  var sortedTypeNames = Object.keys(typesPresent)
    .sort(function (a, b) {
      return d3.descending(typesPresent[a], typesPresent[b]);
    })
    .slice(0, numberOfTypesUpperBound);

  assert(sortedTypeNames.length > 0);

  var cells = [];
  var numberOfColumns = 0;

  /**
   * Create all cells applicable to display.
   */
  forEachDateLimitsDescending(startDate, endDate, cellSize, function (start, end) {
    /* For each type... */
    sortedTypeNames.forEach(function (typeName) {
      /* Add all the cells that it covers. */
      cells.push(new Cell(start, end, typeName)
                 .setDataFromSortedASTDiffs(applicableDiffs)
      );
    });

    numberOfColumns++;
  });

  var maxDate = cells[0].endDate;
  var minDate = cells[cells.length - 1].startDate;
  assert(minDate <= maxDate);

  return {
    types: sortedTypeNames,
    cells: cells,
    numberOfColumns: numberOfColumns,
    minDate: minDate,
    maxDate: maxDate
  };
}

/**
 * Count all types in the given ASTDiff objects.
 */
function countTypeAbsoluteFrequency(astDiffs) {
  var typesFrequency = {};
  astDiffs.forEach(function (diff) {
    var freq = typesFrequency[diff.type] || 0;
    typesFrequency[diff.type] = freq + 1;
  });

  return typesFrequency;
}

/**
 * Given start and end dates, calls the given callback with the start and end
 * date.
 */
function forEachDateLimitsDescending(start, end, step, callback) {
  var currentStart;
  var currentEnd = end;

  while (start < currentEnd) {
    currentStart = moment(currentEnd);

    switch (step) {
        case 'hour':
            currentStart.subtract(1, 'hour');
            break;
        case 'day':
            currentStart.subtract(1, 'day');
            break;
        case 'week':
            /* TODO: Make this smarter? */
            currentStart.subtract(1, 'weeks');
            break;
        case 'month':
            currentStart.subtract(1, 'month');
    }

    callback(currentStart.toDate(), currentEnd);
    currentEnd = currentStart.toDate();
  }
}

/*=== Graph ===*/

function drawGraph(data, width, height) {
  //var cellWidth = width / data.numberOfColumns;

  /* Create a scale for the types i.e., the y-axis */
  var yScale = d3.scale.ordinal()
    .domain(data.types)
    .rangeBands([0, height]);

  /* Create a scale for the dates i.e., the x-axis */
  var xScale = d3.time.scale()
    .domain([data.minDate, data.maxDate])
    .rangeRound([0, width]);

  /**
   * Interpolates colours
   */
  var colorInterpolator = d3.interpolateHsl(COLOR_START, COLOR_END);
  var colorScale = function (_additions, _deletions) {
    var score = 0;
    assert(0 <= score && score <= 1);
    return colorInterpolator(score);
  };

  var svg = d3.select('#dna-table').append('svg')
      .attr("width", width)
      .attr("height", height);

  /* Create all the cells. */
  var cells = svg.selectAll('.cell')
      .data(data.cells)
    .enter().append('g')
      .attr('class', 'cell')
      .attr('transform', function (cell) {
        return 'translate(' +
          xScale(cell.startDate) +
          ',' +
          yScale(cell.type) +
          ')';
      });

  cells.append('rect')
    .attr('class', 'cell-data')
    .attr('width', cellWidthFromScale(data.cells[0], xScale))
    .attr('height', yScale.rangeBand())
    .style('fill', function (cell) {
      if (cell.hasData) {
        return colorScale(0, 0);
      } else {
        return 'none';
      }
    })
}

/*=== Utilties ===*/

function cellWidthFromScale(cell, scale) {
  var bigger = scale(cell.endDate);
  var smaller = scale(cell.startDate);
  assert(bigger > smaller);
  return bigger - smaller;

}

/*=== Predicates used in assertions and checks ===*/

function looksLikeAnEmail(thing) {
  if (typeof thing !== 'string') {
    return false;
  }

  /* Emails are actually really complicated, but let's... do this: */
  return thing.match(/^.+@.+$/);
}

function looksLikeAGitSha(thing) {
  if (typeof thing !== 'string') {
    return false;
  }

  return thing.match(/^[0-9a-f]{5,}$/i);
}

/*globals d3, moment*/
<commit_msg>Use colour interpolator.<commit_after>/**
 * Processes and draws the TypeDNA diagram.
 *
 * Authors:
 *  - Michael Fiest
 *  - Eddie Antonio Santos
 *  - Ian Watts
 */

// http://colorbrewer2.org/?type=diverging&scheme=RdBu&n=3
// ['#ef8a62','#f7f7f7','#67a9cf'];
var COLOR_START = '#ef8a62';
var COLOR_END = '#67a9cf';

/* Run right after the page (and this script) finishes loading. */
document.addEventListener('DOMContentLoaded', function () {
  var container = document.getElementById('dna-table');

  /* XXX: */
  var processed = window.preprocessedData = preprocessData(window.DATA);
  var filtered = window.filteredData = filterTypes(processed, {
  });

  /* Make this arbitrarily large. */
  var height = 20 * filtered.types.length;

  drawGraph(filtered, container.offsetWidth, height);
});

/* Shim the assert function in there! */
!window.assert ? (window.assert = console.assert.bind(console)) : undefined;

var VALID_STEP_SIZES = d3.set(['hour', 'day', 'month', 'week']);

/*=== Classes ===*/

/**
 * Class: ASTDiff
 *
 * Instantiated with an original data object.
 */
function ASTDiff(original) {
  /* Instantiate a new ASTDiff object if called without `new`. */
  if (!(this instanceof ASTDiff)) {
    return new ASTDiff(original);
  }

  var date = new Date(original.date);
  /* The date must be reasonable... */
  assert(date > new Date('1970-01-01') && date < new Date());
  assert(typeof original.type === 'string');
  assert(ASTDiff.EDIT_KIND.has(original.edit));
  assert(looksLikeAnEmail(original.author));

  this.date = date;
  this.type = original.type;
  this.author = original.author;
  this.edit = original.edit;
  this.commit = original.commitID;
}

/**
 * The set of edit kinds.
 */
ASTDiff.EDIT_KIND = d3.set(['ADD', 'REMOVE']);

/**
 * ASTDiff methods and computed properties.
 */
Object.defineProperties(ASTDiff.prototype, {
  isAdd: {
    get: function () {
      return this.edit === 'ADD';
    }
  },

  isRemove: {
    get: function () {
      return this.edit === 'REMOVE';
    }
  },

  /**
   * Delegate valueOf() to the internal date object. This makes relational
   * comparisons with ASTDiff objects equivillent to comparing their dates.
   * (i.e.,
   *    (ASTDiff(...) < ASTDiff(...)) ===
   *        (ASTDiff(...).date < ASTDiff(...))
   * )
   */
  valueOf: {
    value: function () {
      return this.date.valueOf();
    },
  }
});

/**
 * Class: Cell
 *
 * Represents the data for a single cell in the table.
 */
function Cell(start, until, type) {
  /* Instantiate a new Cell object if called without `new`. */
  if (!(this instanceof Cell)) {
    return new Cell(start, until, type);
  }

  assert(start instanceof Date);
  assert(until instanceof Date);
  assert(typeof type === 'string');

  this.data = []
  this.startDate = start;
  this.endDate = until;
  this.type = type;
}

Object.defineProperties(Cell.prototype, {
  /**
   * Given a bunch of ASTDiffs,
   * sets this cell's data to the appropriate ASTDiff.
   */
  setDataFromSortedASTDiffs: {
    value: function setDataFromSortedASTDiffs(astDiffs) {
      assert(astDiffs instanceof Array);
      var typeName = this.type;

      var lowerIndex = d3.bisectLeft(astDiffs, this.startDate);
      /* Do not include upper index. */
      var upperIndex = d3.bisectLeft(astDiffs, this.endDate);

      this.data = astDiffs
        .slice(lowerIndex, upperIndex)
        .filter(function (diff) {
          return diff.type === typeName;
        });

      return this;
    },
  },

  /** True if the cell contains at least one AST diff.  */
  hasData: {
    get: function () {
      return this.data && (this.data.length > 0);
    }
  },

  /** Returns number of additions.  */
  numberOfAdds: {
    get: function () {
      return this.data.filter(function (diff) {
        return diff.isAdd;
      }).length;
    }
  },

  /** Returns number of removes.  */
  numberOfRemoves: {
    get: function () {
      return this.data.filter(function (diff) {
        return diff.isRemove;
      }).length;
    }
  }
});

/*=== Core functions ====*/

/**
 * Modifies original data.
 */
function preprocessData(data) {
  assert(data.types instanceof Array);
  assert(data.commits instanceof Array);
  assert(data.dates instanceof Array);

  return {
    /* A set of types. */
    types: d3.set(data.types),

    /* Mapping GitSha -> Commit MetaData. */
    commits: (function () {
      var commitMap = {};
      data.commits.forEach(function (commit) {
        assert(typeof commit.commitID  === 'string');
        var sha = commit.commitID;
        assert(looksLikeAGitSha(sha));

        commitMap[sha] = commit;
      });
      return commitMap;
    }()),

    /* A copy of AST Diff data, in asscending order of date. */
    astDiffs: (function (astDiffsByType) {
      return astDiffsByType
        .map(ASTDiff)
        .sort(function (a, b) {
          assert(a instanceof ASTDiff);
          return d3.ascending(a.date, b.date);
        });
    }(data.dates.slice()))
  };
}

/**
 * Takes preprocessed data, and returns an array of types, in ascending order
 * of popularity.
 *
 * Each type has its Cells, with ASTDiffs.
 */
function filterTypes(data, filters) {
  assert(filters);
  /* Either the date provided, or the first date attested. */
  var startDate = filters.start || data.astDiffs[0].date;
  /* Either the date provided or right NOW! */
  var endDate = filters.end || new Date();
  var numberOfTypesUpperBound = filters.limit || Infinity;
  var cellSize = filters.stepSize || 'day';

  assert(startDate instanceof Date);
  assert(endDate instanceof Date);
  assert(startDate < endDate);
  assert(typeof numberOfTypesUpperBound === 'number');
  assert(VALID_STEP_SIZES.has(cellSize));

  /* Find the range of diffs to use. */
  var lowerIndex = d3.bisectLeft(data.astDiffs, startDate);
  var upperIndex = d3.bisectRight(data.astDiffs, endDate);

  var applicableDiffs = data.astDiffs.slice(lowerIndex, upperIndex);
  /* Filter types, first by the types that are ACTUALLY present in the
   * filtered ASTDiffs */
  var typesPresent = countTypeAbsoluteFrequency(applicableDiffs);
  var sortedTypeNames = Object.keys(typesPresent)
    .sort(function (a, b) {
      return d3.descending(typesPresent[a], typesPresent[b]);
    })
    .slice(0, numberOfTypesUpperBound);

  assert(sortedTypeNames.length > 0);

  var cells = [];
  var numberOfColumns = 0;

  /**
   * Create all cells applicable to display.
   */
  forEachDateLimitsDescending(startDate, endDate, cellSize, function (start, end) {
    /* For each type... */
    sortedTypeNames.forEach(function (typeName) {
      /* Add all the cells that it covers. */
      cells.push(new Cell(start, end, typeName)
                 .setDataFromSortedASTDiffs(applicableDiffs)
      );
    });

    numberOfColumns++;
  });

  var maxDate = cells[0].endDate;
  var minDate = cells[cells.length - 1].startDate;
  assert(minDate <= maxDate);

  return {
    types: sortedTypeNames,
    cells: cells,
    numberOfColumns: numberOfColumns,
    minDate: minDate,
    maxDate: maxDate
  };
}

/**
 * Count all types in the given ASTDiff objects.
 */
function countTypeAbsoluteFrequency(astDiffs) {
  var typesFrequency = {};
  astDiffs.forEach(function (diff) {
    var freq = typesFrequency[diff.type] || 0;
    typesFrequency[diff.type] = freq + 1;
  });

  return typesFrequency;
}

/**
 * Given start and end dates, calls the given callback with the start and end
 * date.
 */
function forEachDateLimitsDescending(start, end, step, callback) {
  var currentStart;
  var currentEnd = end;

  while (start < currentEnd) {
    currentStart = moment(currentEnd);

    switch (step) {
        case 'hour':
            currentStart.subtract(1, 'hour');
            break;
        case 'day':
            currentStart.subtract(1, 'day');
            break;
        case 'week':
            /* TODO: Make this smarter? */
            currentStart.subtract(1, 'weeks');
            break;
        case 'month':
            currentStart.subtract(1, 'month');
    }

    callback(currentStart.toDate(), currentEnd);
    currentEnd = currentStart.toDate();
  }
}

/*=== Graph ===*/

function drawGraph(data, width, height) {
  //var cellWidth = width / data.numberOfColumns;

  /* Create a scale for the types i.e., the y-axis */
  var yScale = d3.scale.ordinal()
    .domain(data.types)
    .rangeBands([0, height]);

  /* Create a scale for the dates i.e., the x-axis */
  var xScale = d3.time.scale()
    .domain([data.minDate, data.maxDate])
    .rangeRound([0, width]);

  /**
   * Given number of additions and deletions, returns an appropriate,
   * interpoloated colour.
   */
  var colorScale = (function () {
    var colorInterpolator = d3.interpolateHsl(COLOR_START, COLOR_END);

    return function (additions, deletions) {
      assert(additions + deletions > 0);
      var score = additions / (additions + deletions);
      assert(0 <= score && score <= 1);
      return colorInterpolator(score);
    };
  }());

  var svg = d3.select('#dna-table').append('svg')
      .attr("width", width)
      .attr("height", height);

  /* Create all the cells. */
  var cells = svg.selectAll('.cell')
      .data(data.cells)
    .enter().append('g')
      .attr('class', 'cell')
      .attr('transform', function (cell) {
        return 'translate(' +
          xScale(cell.startDate) +
          ',' +
          yScale(cell.type) +
          ')';
      });

  cells.append('rect')
    .attr('class', 'cell-data')
    .attr('width', cellWidthFromScale(data.cells[0], xScale))
    .attr('height', yScale.rangeBand())
    .style('fill', function (cell) {
      if (cell.hasData) {
        return colorScale(cell.numberOfAdds, cell.numberOfRemoves);
      } else {
        return 'none';
      }
    })
}

/*=== Utilties ===*/

function cellWidthFromScale(cell, scale) {
  var bigger = scale(cell.endDate);
  var smaller = scale(cell.startDate);
  assert(bigger > smaller);
  return bigger - smaller;

}

/*=== Predicates used in assertions and checks ===*/

function looksLikeAnEmail(thing) {
  if (typeof thing !== 'string') {
    return false;
  }

  /* Emails are actually really complicated, but let's... do this: */
  return thing.match(/^.+@.+$/);
}

function looksLikeAGitSha(thing) {
  if (typeof thing !== 'string') {
    return false;
  }

  return thing.match(/^[0-9a-f]{5,}$/i);
}

/*globals d3, moment*/
<|endoftext|>


<commit_before>'use strict';

// MODULES //

var frexp = require( '@stdlib/math/base/special/frexp' );
var ldexp = require( '@stdlib/math/base/special/ldexp' );

// VARIABLES //

// `frexp` workspace:
var PARTS = [ 0.0, 0 ];

// MAIN //

/**
* Returns an accumulator function which incrementally computes a product.
*
* ## Method
*
* To avoid overflow/underflow, we store the fractional and exponent parts of intermediate results separately. By keeping a normalized fraction, we prevent underflow/overflow of the fraction. Underflow of the exponent is impossible, as IEEE 754 floating-point exponents are integer values. Overflow of the exponent is possible, but highly unlikely. In the worst case, an intermediate exponent is greater than the minimum safe integer, and adding the exponent of an incoming value does not change the intermediate result. While incorrect, such behavior does not lead to exponent overflow.
*
* While intermediate results are largely immune to overflow and not subject to underflow, this is not mean that returned results will never be zero or infinite. In fact, zero (underflow) and infinite (overflow) results may be transient (i.e., infinity followed by a finite number).
*
*
* ## References
*
* * Ueberhuber, Christoph W. 1997. *Numerical Computation 1: Methods, Software, and Analysis*. Springer-Verlag Berlin Heidelberg. doi:[10.1007/978-3-642-59118-1](https://doi.org/10.1007/978-3-642-59118-1).
*
* @returns {Function} accumulator function
*
* @example
* var accumulator = incrprod();
*/
function incrprod() {
	var frac;
	var prod;
	var exp;

	// Initial product is 1.0, which may be split into its fractional and exponent parts (0.5 x 2.0**1 = 1.0):
	prod = 1.0;
	frac = 0.5;
	exp = 1.0;

	return accumulator;

	/**
	* If provided a value, the accumulator function returns an updated product. If not provided a value, the accumulator function returns the current product.
	*
	* @param {number} [x] - new value
	* @returns {number} product
	*
	* @example
	* var prod = accumulator();
	* // returns 1.0
	*
	* prod = accumulator( 2.0 );
	* // returns 2.0
	*
	* prod = accumulator( -5.0 );
	* // returns -10.0
	*
	* prod = accumulator();
	* // returns -10.0
	*/
	function accumulator( x ) {
		if ( arguments.length === 0 ) {
			return prod;
		}
		// Splitting the incoming value into a normalized fraction and exponent:
		frexp( PARTS, x );

		// Update the accumulated fraction:
		frac *= PARTS[ 0 ];

		// Update the accumulated exponent:
		exp += PARTS[ 1 ];

		// Ensure fraction remains normalized to avoid overflow/underflow...
		if ( frac > -0.5 && frac < 0.5 ) {
			frexp( PARTS, frac );
			frac = PARTS[ 0 ];
			exp += PARTS[ 1 ];
		}
		prod = ldexp( frac, exp );
		return prod;
	}
} // end FUNCTION incrprod()

// EXPORTS //

module.exports = incrprod;
<commit_msg>Add thread safety warning<commit_after>'use strict';

// MODULES //

var frexp = require( '@stdlib/math/base/special/frexp' );
var ldexp = require( '@stdlib/math/base/special/ldexp' );

// VARIABLES //

// `frexp` workspace:
var PARTS = [ 0.0, 0 ]; // WARNING: not thread safe

// MAIN //

/**
* Returns an accumulator function which incrementally computes a product.
*
* ## Method
*
* To avoid overflow/underflow, we store the fractional and exponent parts of intermediate results separately. By keeping a normalized fraction, we prevent underflow/overflow of the fraction. Underflow of the exponent is impossible, as IEEE 754 floating-point exponents are integer values. Overflow of the exponent is possible, but highly unlikely. In the worst case, an intermediate exponent is greater than the minimum safe integer, and adding the exponent of an incoming value does not change the intermediate result. While incorrect, such behavior does not lead to exponent overflow.
*
* While intermediate results are largely immune to overflow and not subject to underflow, this is not mean that returned results will never be zero or infinite. In fact, zero (underflow) and infinite (overflow) results may be transient (i.e., infinity followed by a finite number).
*
*
* ## References
*
* * Ueberhuber, Christoph W. 1997. *Numerical Computation 1: Methods, Software, and Analysis*. Springer-Verlag Berlin Heidelberg. doi:[10.1007/978-3-642-59118-1](https://doi.org/10.1007/978-3-642-59118-1).
*
* @returns {Function} accumulator function
*
* @example
* var accumulator = incrprod();
*/
function incrprod() {
	var frac;
	var prod;
	var exp;

	// Initial product is 1.0, which may be split into its fractional and exponent parts (0.5 x 2.0**1 = 1.0):
	prod = 1.0;
	frac = 0.5;
	exp = 1.0;

	return accumulator;

	/**
	* If provided a value, the accumulator function returns an updated product. If not provided a value, the accumulator function returns the current product.
	*
	* @param {number} [x] - new value
	* @returns {number} product
	*
	* @example
	* var prod = accumulator();
	* // returns 1.0
	*
	* prod = accumulator( 2.0 );
	* // returns 2.0
	*
	* prod = accumulator( -5.0 );
	* // returns -10.0
	*
	* prod = accumulator();
	* // returns -10.0
	*/
	function accumulator( x ) {
		if ( arguments.length === 0 ) {
			return prod;
		}
		// Splitting the incoming value into a normalized fraction and exponent:
		frexp( PARTS, x );

		// Update the accumulated fraction:
		frac *= PARTS[ 0 ];

		// Update the accumulated exponent:
		exp += PARTS[ 1 ];

		// Ensure fraction remains normalized to avoid overflow/underflow...
		if ( frac > -0.5 && frac < 0.5 ) {
			frexp( PARTS, frac );
			frac = PARTS[ 0 ];
			exp += PARTS[ 1 ];
		}
		prod = ldexp( frac, exp );
		return prod;
	}
} // end FUNCTION incrprod()

// EXPORTS //

module.exports = incrprod;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Button from 'components/Button';
import Icon from 'components/Icon';
import InfoEditForm from './InfoEditForm';
import { connect } from 'react-redux';
import { Color } from 'constants/css';
import { trimUrl } from 'helpers/stringHelpers';
import { uploadProfileInfo } from 'helpers/requestHelpers';
import { timeSince } from 'helpers/timeStampHelpers';
import { setProfileInfo } from 'redux/actions/UserActions';

class BasicInfos extends Component {
  static propTypes = {
    className: PropTypes.string,
    dispatch: PropTypes.func.isRequired,
    email: PropTypes.string,
    joinDate: PropTypes.string,
    lastActive: PropTypes.string,
    myId: PropTypes.number,
    selectedTheme: PropTypes.string.isRequired,
    userId: PropTypes.number.isRequired,
    username: PropTypes.string.isRequired,
    website: PropTypes.string,
    youtubeName: PropTypes.string,
    youtubeUrl: PropTypes.string,
    setProfileInfo: PropTypes.func.isRequired,
    style: PropTypes.object
  };

  state = {
    onEdit: false
  };

  render() {
    const {
      className,
      email,
      joinDate,
      lastActive,
      myId,
      selectedTheme,
      userId,
      username,
      website,
      youtubeName,
      youtubeUrl,
      style
    } = this.props;
    const { onEdit } = this.state;
    return (

          About {username}

        {onEdit && (
          <InfoEditForm
            email={email}
            youtubeUrl={youtubeUrl}
            youtubeName={youtubeName}
            website={website}
            onCancel={() => this.setState({ onEdit: false })}
            onSubmit={this.onEditedInfoSubmit}
          />
        )}
        {!onEdit &&
          (email || youtubeUrl) && (

              {email && (

                    Email:
                    <a
                      href={`mailto:${email}`}
                      target="_blank"
                      rel="noopener noreferrer"
                    >
                      {email}

              )}
              {youtubeUrl && (

                    YouTube:

                      {youtubeName || trimUrl(youtubeUrl)}

              )}
              {website && (

                  Website:

                    {trimUrl(website)}

              )}

          )}
        {!onEdit &&
          myId === userId &&
          (!email || !youtubeUrl || !website) && (

              {this.renderEditMessage({ email, youtubeUrl, website })}

          )}
        {myId === userId ? (
          !onEdit ? (
            <Button
              style={{
                marginTop: !email || !youtubeUrl || !website ? 0 : '1rem'
              }}
              transparent
              onClick={() => this.setState({ onEdit: true })}
            >
              <Icon icon="pencil-alt" />
              Edit
            </Button>
          ) : null
        ) : (

Became a member {timeSince(joinDate)}

Was last active {timeSince(lastActive)}

        )}

    );
  }

  onEditedInfoSubmit = async({ email, website, youtubeName, youtubeUrl }) => {
    const { dispatch, setProfileInfo } = this.props;
    const data = await uploadProfileInfo({
      dispatch,
      email,
      website,
      youtubeName,
      youtubeUrl
    });
    setProfileInfo(data);
    this.setState({ onEdit: false });
  };

  renderEditMessage = ({ email, youtubeUrl, website }) => {
    const unfilledItems = [
      { label: 'email', value: email },
      { label: 'YouTube', value: youtubeUrl },
      { label: 'website', value: website }
    ].filter(item => !item.value);
    const emptyItemsArray = unfilledItems.map(item => item.label);
    const emptyItemsString =
      emptyItemsArray.length === 3
        ? `${emptyItemsArray[0]}, ${emptyItemsArray[1]}, and ${
            emptyItemsArray[2]
          }`
        : emptyItemsArray.join(' and ');
    return `Add your ${emptyItemsString} address${
      emptyItemsArray.length > 1 ? 'es' : ''
    } by tapping the "Edit" button below`;
  };
}

export default connect(
  null,
  dispatch => ({
    dispatch,
    setProfileInfo: data => dispatch(setProfileInfo(data))
  })
)(BasicInfos);
<commit_msg>email verification icon added<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Button from 'components/Button';
import Icon from 'components/Icon';
import InfoEditForm from './InfoEditForm';
import { connect } from 'react-redux';
import { Color } from 'constants/css';
import { trimUrl } from 'helpers/stringHelpers';
import { uploadProfileInfo } from 'helpers/requestHelpers';
import { timeSince } from 'helpers/timeStampHelpers';
import { setProfileInfo } from 'redux/actions/UserActions';

class BasicInfos extends Component {
  static propTypes = {
    className: PropTypes.string,
    dispatch: PropTypes.func.isRequired,
    email: PropTypes.string,
    joinDate: PropTypes.string,
    lastActive: PropTypes.string,
    myId: PropTypes.number,
    selectedTheme: PropTypes.string.isRequired,
    userId: PropTypes.number.isRequired,
    username: PropTypes.string.isRequired,
    website: PropTypes.string,
    youtubeName: PropTypes.string,
    youtubeUrl: PropTypes.string,
    setProfileInfo: PropTypes.func.isRequired,
    style: PropTypes.object
  };

  state = {
    onEdit: false
  };

  render() {
    const {
      className,
      email,
      joinDate,
      lastActive,
      myId,
      selectedTheme,
      userId,
      username,
      website,
      youtubeName,
      youtubeUrl,
      style
    } = this.props;
    const { onEdit } = this.state;
    return (

          About {username}

        {onEdit && (
          <InfoEditForm
            email={email}
            youtubeUrl={youtubeUrl}
            youtubeName={youtubeName}
            website={website}
            onCancel={() => this.setState({ onEdit: false })}
            onSubmit={this.onEditedInfoSubmit}
          />
        )}
        {!onEdit &&
          (email || youtubeUrl) && (

              {email && (

                    Email:
                    <a
                      href={`mailto:${email}`}
                      target="_blank"
                      rel="noopener noreferrer"
                    >
                      {email}

                  <Icon
                    style={{
                      cursor: 'pointer',
                      marginLeft: '1rem',
                      color: Color.lightGray()
                    }}
                    icon="check-circle"
                  />

              )}
              {youtubeUrl && (

                    YouTube:

                      {youtubeName || trimUrl(youtubeUrl)}

              )}
              {website && (

                  Website:

                    {trimUrl(website)}

              )}

          )}
        {!onEdit &&
          myId === userId &&
          (!email || !youtubeUrl || !website) && (

              {this.renderEditMessage({ email, youtubeUrl, website })}

          )}
        {myId === userId ? (
          !onEdit ? (
            <Button
              style={{
                marginTop: !email || !youtubeUrl || !website ? 0 : '1rem'
              }}
              transparent
              onClick={() => this.setState({ onEdit: true })}
            >
              <Icon icon="pencil-alt" />
              Edit
            </Button>
          ) : null
        ) : (

Became a member {timeSince(joinDate)}

Was last active {timeSince(lastActive)}

        )}

    );
  }

  onEditedInfoSubmit = async({ email, website, youtubeName, youtubeUrl }) => {
    const { dispatch, setProfileInfo } = this.props;
    const data = await uploadProfileInfo({
      dispatch,
      email,
      website,
      youtubeName,
      youtubeUrl
    });
    setProfileInfo(data);
    this.setState({ onEdit: false });
  };

  renderEditMessage = ({ email, youtubeUrl, website }) => {
    const unfilledItems = [
      { label: 'email', value: email },
      { label: 'YouTube', value: youtubeUrl },
      { label: 'website', value: website }
    ].filter(item => !item.value);
    const emptyItemsArray = unfilledItems.map(item => item.label);
    const emptyItemsString =
      emptyItemsArray.length === 3
        ? `${emptyItemsArray[0]}, ${emptyItemsArray[1]}, and ${
            emptyItemsArray[2]
          }`
        : emptyItemsArray.join(' and ');
    return `Add your ${emptyItemsString} address${
      emptyItemsArray.length > 1 ? 'es' : ''
    } by tapping the "Edit" button below`;
  };
}

export default connect(
  null,
  dispatch => ({
    dispatch,
    setProfileInfo: data => dispatch(setProfileInfo(data))
  })
)(BasicInfos);
<|endoftext|>


<commit_before>import {adapt} from '@cycle/run/lib/adapt';
import xs from 'xstream';

function flatten (array) {
  if (typeof array.reduce !== 'function') {
    return array;
  }

  return array.reduce((flatArray, arrayElement) => flatArray.concat(flatten(arrayElement)), []);
}

function compact (array) {
  return array.filter(element => element !== undefined && element !== null);
}

function translateRect (element, origin) {
  return element.draw.map(operation => {
    const operations = [
      {set: 'lineWidth', value: operation.lineWidth || 1}
    ];

    if (operation.clear) {
      operations.push({
        call: 'clearRect',
        args: [
          origin.x,
          origin.y,
          element.width,
          element.height
        ]
      });
    }

    if (operation.fill) {
      operations.push({
        set: 'fillStyle',
        value: operation.fill || 'black'
      });

      operations.push({
        call: 'fillRect',
        args: [
          origin.x,
          origin.y,
          element.width,
          element.height
        ]
      });
    }

    if (operation.stroke) {
      operations.push({
        set: 'strokeStyle',
        value: operation.stroke || 'black'
      });

      operations.push({
        call: 'strokeRect',
        args: [
          origin.x,
          origin.y,
          element.width,
          element.height
        ]
      });
    }

    return operations;
  });
}

function translateLine (element, origin) {
  const operations = [
    {set: 'lineWidth', value: element.style.lineWidth || 1},
    {set: 'lineCap', value: element.style.lineCap || 'butt'},
    {set: 'lineJoin', value: element.style.lineJoin || 'mitter'},
    {set: 'strokeStyle', value: element.style.strokeStyle || 'black'}
  ];

  if (element.style.lineDash && element.style.lineDash.constructor === Array) {
    operations.push({
      call: 'setLineDash',
      args: element.style.lineDash
    });
  }

  operations.push({
    call: 'moveTo',
    args: [
      origin.x,
      origin.y
    ]
  });

  operations.push({
    call: 'beginPath',
    args: []
  });

  element.points.forEach(point => {
    operations.push({
      call: 'lineTo',
      args: [
        origin.x + point.x,
        origin.y + point.y
      ]
    });
  });

  operations.push({
    call: 'stroke',
    args: []
  });

  operations.push({
    call: 'setLineDash',
    args: []
  });

  return operations;
}

function translatePolygon (element, origin) {
  const [first, ...rest] = element.points;

  return [].concat(
    [{call: 'beginPath', args: []}],
    [{call: 'moveTo', args: [origin.x + first.x, origin.y + first. y]}],
    rest.map(point => {
      return {call: 'lineTo', args: [origin.x + point.x, origin.y + point.y]};
    }),
    [{call: 'closePath', args: []}],
    element.draw.map(operation => {
      const fillInstructions = [
        {set: 'fillStyle', value: operation.fill},
        {call: 'fill', args: []}
      ]
      const strokeInstructions = [
        {set: 'strokeStyle', value: operation.stroke},
        {call: 'stroke', args: []}
      ]
      return operation.fill
        ? fillInstructions
        : operation.stroke
          ? strokeInstructions
          : [];
    })
  );
}

function translateText (element, origin) {
  return element.draw.map(operation => {
    const operations = [
      {set: 'textAlign', value: element.textAlign || 'left'},
      {set: 'font', value: element.font}
    ];

    const args = [
      element.value,
      origin.x,
      origin.y
    ];

    if (element.width) {
      args.push(element.width);
    }

    if (operation.fill) {
      operations.push({
        set: 'fillStyle',
        value: operation.fill || 'black'
      });

      operations.push({
        call: 'fillText',
        args: args
      });
    }

    if (operation.stroke) {
      operations.push({
        set: 'strokeStyle',
        value: operation.stroke || 'black'
      });

      operations.push({
        call: 'strokeText',
        args: args
      });
    }

    return operations;
  });
}

export function translateVtreeToInstructions (element, parentEl) {
  if (!element) {
    return;
  }

  if (!parentEl) {
    parentEl = {x: 0, y: 0};
  }

  const origin = {
    x: element.x ? parentEl.x + element.x : parentEl.x,
    y: element.y ? parentEl.y + element.y : parentEl.y
  };

  const elementMapping = {
    rect: translateRect,
    line: translateLine,
    text: translateText,
    polygon: translatePolygon
  };

  const instructions = preDrawHooks(element);

  instructions.push(elementMapping[element.kind](element, origin));

  instructions.push(postDrawHooks());

  const flatInstructions = compact(flatten(instructions));

  if (element.children) {
    element.children.forEach((child) => {
      const childInstructions = translateVtreeToInstructions(child, element);

      if (childInstructions) {
        flatInstructions.push(...childInstructions);
      }
    });
  }

  return flatInstructions;
}

export function renderInstructionsToCanvas (instructions, context) {
  instructions.forEach(instruction => {
    if (instruction.set) {
      context[instruction.set] = instruction.value;
    } else if (instruction.call) {
      context[instruction.call](...instruction.args);
    }
  });
}

function preDrawHooks (element) {
  const operations = [
    {call: 'save', args: []}
  ];

  if (element.transformations) {
    element.transformations.forEach(transformation => {
      if (transformation.translate) {
        operations.push({
          call: 'translate',
          args: [transformation.translate.x, transformation.translate.y]
        });
      }

      if (transformation.rotate) {
        operations.push({
          call: 'rotate',
          args: [transformation.rotate]
        });
      }

      if (transformation.scale) {
        operations.push({
          call: 'scale',
          args: [transformation.scale.x, transformation.scale.y]
        });
      }
    });
  }

  return operations;
}

function postDrawHooks () {
  return [
    {call: 'restore', args: []}
  ];
}

export function c (kind, opts, children) {
  if (opts.children) {
    children = opts.children;
  }

  return Object.assign(
    {},
    opts,
    {kind, children}
  );
}

export function rect (opts, children) {
  return c('rect', opts, children);
}

export function text (opts, children) {
  const defaults = {
    draw: [
      {fill: 'black'}
    ]
  };

  return c('text', {...defaults, ...opts}, children);
}

export function line (opts, children) {
  const defaults = {
    style: {
      lineWidth: 1,
      lineCap: 'butt',
      lineJoin: 'miter',
      strokeStyle: 'black'
    }
  };
  return c('line', {...defaults, ...opts}, children);
}

export function polygon (opts, children) {
  return c('polygon', opts, children);
}

export function makeCanvasDriver (selector, {width, height}) {
  let canvas = document.querySelector(selector);

  if (!canvas) {
    canvas = document.createElement('canvas');

    document.body.appendChild(canvas);
  }

  canvas.width = width;
  canvas.height = height;

  const context = canvas.getContext('2d');

  let driver = function canvasDriver (sink$) {
    sink$.addListener({
      next: rootElement => {
        const defaults = {
          kind: 'rect',
          x: 0,
          y: 0,
          width: canvas.width,
          height: canvas.height,
          draw: [
          {clear: true}
          ]
        };

        const rootElementWithDefaults = Object.assign(
          {},
          defaults,
          rootElement
          );

        const instructions = translateVtreeToInstructions(rootElementWithDefaults);

        renderInstructionsToCanvas(instructions, context);
      },
      error: e => { throw e },
      complete: () => null
    });

    return adapt(xs.empty());
  }

  return driver;
}
<commit_msg>Second argument for makeCanvasDriver is now optional<commit_after>import {adapt} from '@cycle/run/lib/adapt';
import xs from 'xstream';

function flatten (array) {
  if (typeof array.reduce !== 'function') {
    return array;
  }

  return array.reduce((flatArray, arrayElement) => flatArray.concat(flatten(arrayElement)), []);
}

function compact (array) {
  return array.filter(element => element !== undefined && element !== null);
}

function translateRect (element, origin) {
  return element.draw.map(operation => {
    const operations = [
      {set: 'lineWidth', value: operation.lineWidth || 1}
    ];

    if (operation.clear) {
      operations.push({
        call: 'clearRect',
        args: [
          origin.x,
          origin.y,
          element.width,
          element.height
        ]
      });
    }

    if (operation.fill) {
      operations.push({
        set: 'fillStyle',
        value: operation.fill || 'black'
      });

      operations.push({
        call: 'fillRect',
        args: [
          origin.x,
          origin.y,
          element.width,
          element.height
        ]
      });
    }

    if (operation.stroke) {
      operations.push({
        set: 'strokeStyle',
        value: operation.stroke || 'black'
      });

      operations.push({
        call: 'strokeRect',
        args: [
          origin.x,
          origin.y,
          element.width,
          element.height
        ]
      });
    }

    return operations;
  });
}

function translateLine (element, origin) {
  const operations = [
    {set: 'lineWidth', value: element.style.lineWidth || 1},
    {set: 'lineCap', value: element.style.lineCap || 'butt'},
    {set: 'lineJoin', value: element.style.lineJoin || 'mitter'},
    {set: 'strokeStyle', value: element.style.strokeStyle || 'black'}
  ];

  if (element.style.lineDash && element.style.lineDash.constructor === Array) {
    operations.push({
      call: 'setLineDash',
      args: element.style.lineDash
    });
  }

  operations.push({
    call: 'moveTo',
    args: [
      origin.x,
      origin.y
    ]
  });

  operations.push({
    call: 'beginPath',
    args: []
  });

  element.points.forEach(point => {
    operations.push({
      call: 'lineTo',
      args: [
        origin.x + point.x,
        origin.y + point.y
      ]
    });
  });

  operations.push({
    call: 'stroke',
    args: []
  });

  operations.push({
    call: 'setLineDash',
    args: []
  });

  return operations;
}

function translatePolygon (element, origin) {
  const [first, ...rest] = element.points;

  return [].concat(
    [{call: 'beginPath', args: []}],
    [{call: 'moveTo', args: [origin.x + first.x, origin.y + first. y]}],
    rest.map(point => {
      return {call: 'lineTo', args: [origin.x + point.x, origin.y + point.y]};
    }),
    [{call: 'closePath', args: []}],
    element.draw.map(operation => {
      const fillInstructions = [
        {set: 'fillStyle', value: operation.fill},
        {call: 'fill', args: []}
      ]
      const strokeInstructions = [
        {set: 'strokeStyle', value: operation.stroke},
        {call: 'stroke', args: []}
      ]
      return operation.fill
        ? fillInstructions
        : operation.stroke
          ? strokeInstructions
          : [];
    })
  );
}

function translateText (element, origin) {
  return element.draw.map(operation => {
    const operations = [
      {set: 'textAlign', value: element.textAlign || 'left'},
      {set: 'font', value: element.font}
    ];

    const args = [
      element.value,
      origin.x,
      origin.y
    ];

    if (element.width) {
      args.push(element.width);
    }

    if (operation.fill) {
      operations.push({
        set: 'fillStyle',
        value: operation.fill || 'black'
      });

      operations.push({
        call: 'fillText',
        args: args
      });
    }

    if (operation.stroke) {
      operations.push({
        set: 'strokeStyle',
        value: operation.stroke || 'black'
      });

      operations.push({
        call: 'strokeText',
        args: args
      });
    }

    return operations;
  });
}

export function translateVtreeToInstructions (element, parentEl) {
  if (!element) {
    return;
  }

  if (!parentEl) {
    parentEl = {x: 0, y: 0};
  }

  const origin = {
    x: element.x ? parentEl.x + element.x : parentEl.x,
    y: element.y ? parentEl.y + element.y : parentEl.y
  };

  const elementMapping = {
    rect: translateRect,
    line: translateLine,
    text: translateText,
    polygon: translatePolygon
  };

  const instructions = preDrawHooks(element);

  instructions.push(elementMapping[element.kind](element, origin));

  instructions.push(postDrawHooks());

  const flatInstructions = compact(flatten(instructions));

  if (element.children) {
    element.children.forEach((child) => {
      const childInstructions = translateVtreeToInstructions(child, element);

      if (childInstructions) {
        flatInstructions.push(...childInstructions);
      }
    });
  }

  return flatInstructions;
}

export function renderInstructionsToCanvas (instructions, context) {
  instructions.forEach(instruction => {
    if (instruction.set) {
      context[instruction.set] = instruction.value;
    } else if (instruction.call) {
      context[instruction.call](...instruction.args);
    }
  });
}

function preDrawHooks (element) {
  const operations = [
    {call: 'save', args: []}
  ];

  if (element.transformations) {
    element.transformations.forEach(transformation => {
      if (transformation.translate) {
        operations.push({
          call: 'translate',
          args: [transformation.translate.x, transformation.translate.y]
        });
      }

      if (transformation.rotate) {
        operations.push({
          call: 'rotate',
          args: [transformation.rotate]
        });
      }

      if (transformation.scale) {
        operations.push({
          call: 'scale',
          args: [transformation.scale.x, transformation.scale.y]
        });
      }
    });
  }

  return operations;
}

function postDrawHooks () {
  return [
    {call: 'restore', args: []}
  ];
}

export function c (kind, opts, children) {
  if (opts.children) {
    children = opts.children;
  }

  return Object.assign(
    {},
    opts,
    {kind, children}
  );
}

export function rect (opts, children) {
  return c('rect', opts, children);
}

export function text (opts, children) {
  const defaults = {
    draw: [
      {fill: 'black'}
    ]
  };

  return c('text', {...defaults, ...opts}, children);
}

export function line (opts, children) {
  const defaults = {
    style: {
      lineWidth: 1,
      lineCap: 'butt',
      lineJoin: 'miter',
      strokeStyle: 'black'
    }
  };
  return c('line', {...defaults, ...opts}, children);
}

export function polygon (opts, children) {
  return c('polygon', opts, children);
}

export function makeCanvasDriver (selector, canvasOptions = null) {
  let canvas = document.querySelector(selector);

  if (!canvas) {
    canvas = document.createElement('canvas');

    document.body.appendChild(canvas);
  }

  if (canvasOptions) {
    canvas.width = canvasOptions.width;
    canvas.height = canvasOptions.height;
  }

  const context = canvas.getContext('2d');

  let driver = function canvasDriver (sink$) {
    sink$.addListener({
      next: rootElement => {
        const defaults = {
          kind: 'rect',
          x: 0,
          y: 0,
          width: canvas.width,
          height: canvas.height,
          draw: [
          {clear: true}
          ]
        };

        const rootElementWithDefaults = Object.assign(
          {},
          defaults,
          rootElement
          );

        const instructions = translateVtreeToInstructions(rootElementWithDefaults);

        renderInstructionsToCanvas(instructions, context);
      },
      error: e => { throw e },
      complete: () => null
    });

    return adapt(xs.empty());
  }

  return driver;
}
<|endoftext|>