<commit_before>/*eslint quote-props: [2, "always"] */

'use strict';

module.exports = {
    'plugins': [],

    'extends': [],

    // http://stylelint.io/user-guide/rules/
    'rules': {
        // 'at-rule-blacklist': [],
        'at-rule-empty-line-before': ['always', {
            'except': ['blockless-after-same-name-blockless'], // Reverse the primary option for at-rules that are nested.
            'ignore': ['after-comment'], // Ignore at-rules that come after a comment.
        }],
        'at-rule-name-case': 'lower',
        'at-rule-name-newline-after': 'always-multi-line',
        'at-rule-name-space-after': 'always-single-line',
        'at-rule-no-unknown': [true, {
            'ignoreAtRules': [],
        }],
        'at-rule-no-vendor-prefix': true,
        'at-rule-semicolon-newline-after': 'always',
        'at-rule-semicolon-space-before': 'never',
        // 'at-rule-whitelist': [],
        // 'block-closing-brace-empty-line-before': 'always-multi-line'|'never',
        'block-closing-brace-newline-after': 'always',
        // 'block-closing-brace-newline-before': 'always'|'always-multi-line'|'never-multi-line',
        // 'block-closing-brace-space-after': 'always'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line',
        // 'block-closing-brace-space-before': 'always'|'never'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line',
        'block-no-empty': [true, {
            'severity': 'warning',
        }],
        'block-opening-brace-newline-after': 'always',
        // 'block-opening-brace-newline-before': 'always'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line',
        // 'block-opening-brace-space-after': 'always'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line',
        // 'block-opening-brace-space-before': 'always'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line',
        'color-hex-case': 'lower',
        'color-hex-length': 'long',
        // 'color-named': 'always-where-possible'|'never',
        // 'color-no-hex': true,
        'color-no-invalid-hex': true,
        // 'comment-empty-line-before': 'always'|'never',
        'comment-no-empty': true,
        // 'comment-whitespace-inside': 'always'|'never',
        // 'comment-word-blacklist': string|[],
        // 'custom-media-pattern': string,
        // 'custom-property-empty-line-before': 'always'|'never',
        // 'custom-property-pattern': string,
        'declaration-bang-space-after': 'never',
        'declaration-bang-space-before': 'always',
        'declaration-block-no-duplicate-properties': true,
        'declaration-block-no-redundant-longhand-properties': true,
        'declaration-block-no-shorthand-property-overrides': true,
        // 'declaration-block-semicolon-newline-after': 'always'|'always-multi-line'|'never-multi-line',
        // 'declaration-block-semicolon-newline-before': 'always'|'always-multi-line'|'never-multi-line',
        'declaration-block-semicolon-space-after': 'always-single-line',
        'declaration-block-semicolon-space-before': 'never',
        'declaration-block-single-line-max-declarations': 1,
        'declaration-block-trailing-semicolon': 'always',
        // 'declaration-colon-newline-after': 'always'|'always-multi-line',
        'declaration-colon-space-after': 'always-single-line',
        'declaration-colon-space-before': 'never',
        // 'declaration-empty-line-before': 'always'|'never',
        'declaration-no-important': true,
        // 'declaration-property-unit-blacklist': {},
        // 'declaration-property-unit-whitelist': {},
        // 'declaration-property-value-blacklist': {},
        // 'declaration-property-value-whitelist': {},
        'font-family-name-quotes': 'always-unless-keyword',
        // 'font-family-no-duplicate-names': boolean,
        'font-weight-notation': 'named-where-possible',
        //'function-blacklist': [],
        'function-calc-no-unspaced-operator': true,
        'function-comma-newline-after': 'never-multi-line',
        'function-comma-newline-before': 'never-multi-line',
        'function-comma-space-after': 'always',
        'function-comma-space-before': 'never',
        'function-linear-gradient-no-nonstandard-direction': true,
        'function-max-empty-lines': 0,
        'function-name-case': 'lower',
        // 'function-parentheses-newline-inside': 'always'|'always-multi-line'|'never-multi-line',
        'function-parentheses-space-inside': 'never-single-line',
        // 'function-url-data-uris': 'always'|'never',
        // 'function-url-no-scheme-relative': true,
        'function-url-scheme-whitelist': ['https'],
        'function-url-quotes': ['always', {
            // except: ['empty'],
        }],
        //'function-whitelist': [],
        'function-whitespace-after': 'always',
        'indentation': 4,
        'keyframe-declaration-no-important': true,
        // 'length-zero-no-unit': true,
        'max-empty-lines': [2, {
            'ignore': ['comments']
        }],
        // 'max-line-length': int,
        'media-feature-colon-space-after': 'always',
        'media-feature-colon-space-before': 'never',
        'media-feature-name-case': 'lower',
        'media-feature-name-no-unknown': [true, {
            'ignoreMediaFeatureNames': [],
        }],
        'media-feature-name-no-vendor-prefix': true,
        // 'media-feature-name-blacklist'
        // 'media-feature-name-whitelist'
        'media-feature-parentheses-space-inside': 'never',
        'media-feature-range-operator-space-after': 'always',
        'media-feature-range-operator-space-before': 'always',
        // 'media-query-list-comma-newline-after': 'always'|'always-multi-line'|'never-multi-line',
        // 'media-query-list-comma-newline-before': 'always'|'always-multi-line'|'never-multi-line',
        // 'media-query-list-comma-space-after': 'always'|'never'|'always-single-line'|'never-single-line',
        // 'media-query-list-comma-space-before': 'always'|'never'|'always-single-line'|'never-single-line',
        'no-descending-specificity': true,
        'no-duplicate-selectors': true,
        'no-empty-source': true,
        // 'no-eol-whitespace': true,
        'no-extra-semicolons': true,
        'no-invalid-double-slash-comments': true,
        'no-missing-end-of-source-newline': true,
        'no-unknown-animations': true,
        // 'number-leading-zero': 'always'|'never',
        // 'number-max-precision': int,
        // 'number-no-trailing-zeros': true,
        // 'property-blacklist': string|[],
        'property-case': 'lower',
        'property-no-unknown': true,
        'property-no-vendor-prefix': true,
        // 'property-whitelist': string|[],
        'selector-attribute-brackets-space-inside': 'never',
        // 'selector-attribute-operator-blacklist': string|[],
        'selector-attribute-operator-space-after': 'never',
        'selector-attribute-operator-space-before': 'never',
        // 'selector-attribute-operator-whitelist': string|[],
        'selector-attribute-quotes': 'always',
        // 'selector-class-pattern': string,
        'selector-combinator-space-after': 'always',
        'selector-combinator-space-before': 'always',
        'selector-descendant-combinator-no-non-space': true,
        // 'selector-id-pattern': string,
        // 'selector-list-comma-newline-after': 'always'|'always-multi-line'|'never-multi-line',
        // 'selector-list-comma-newline-before': 'always'|'always-multi-line'|'never-multi-line',
        'selector-list-comma-space-after': 'always-single-line',
        'selector-list-comma-space-before': 'never-single-line',
        //'selector-max-class': 0,
        'selector-max-empty-lines': 0,
        // 'selector-max-compound-selectors': int,
        // 'selector-max-specificity': string,
        // 'selector-nested-pattern': string,
        // 'selector-no-attribute': true,
        // 'selector-no-combinator': true,
        // 'selector-no-id': true,
        // 'selector-no-qualifying-type': true,
        // 'selector-no-type': true,
        'selector-no-universal': true,
        'selector-no-vendor-prefix': true,
        // 'selector-pseudo-class-blacklist': [],
        'selector-pseudo-class-case': 'lower',
        'selector-pseudo-class-no-unknown': true,
        // 'selector-pseudo-class-parentheses-space-inside': 'always'|'never',
        // 'selector-pseudo-class-whitelist': string|[],
        'selector-pseudo-element-case': 'lower',
        'selector-pseudo-element-colon-notation': 'double',
        'selector-pseudo-element-no-unknown': true,
        'selector-type-case': 'lower',
        'selector-type-no-unknown': [true, {
            'ignore': ['default-namespace', 'custom-elements'],
            'ignoreNamespaces': [],
            'ignoreTypes': [],
        }],
        'shorthand-property-no-redundant-values': [true, {
            'severity': 'warning',
        }],
        'string-no-newline': true,
        'string-quotes': 'single',
        'time-min-milliseconds': true,
        // 'unit-blacklist': string|[],
        'unit-case': 'lower',
        'unit-no-unknown': true,
        // 'unit-whitelist': string|[],
        'value-keyword-case': 'lower',
        // 'value-list-comma-newline-after': 'always'|'always-multi-line'|'never-multi-line',
        // 'value-list-comma-newline-before': 'always'|'always-multi-line'|'never-multi-line',
        'value-list-comma-space-after': 'always-single-line',
        'value-list-comma-space-before': 'never-single-line',
        'value-list-max-empty-lines': 0,
        'value-no-vendor-prefix': true,
    },
};
<commit_msg>Fix rule value for time-min-milliseconds<commit_after>/*eslint quote-props: [2, "always"] */

'use strict';

module.exports = {
    'plugins': [],

    'extends': [],

    // http://stylelint.io/user-guide/rules/
    'rules': {
        // 'at-rule-blacklist': [],
        'at-rule-empty-line-before': ['always', {
            'except': ['blockless-after-same-name-blockless'], // Reverse the primary option for at-rules that are nested.
            'ignore': ['after-comment'], // Ignore at-rules that come after a comment.
        }],
        'at-rule-name-case': 'lower',
        'at-rule-name-newline-after': 'always-multi-line',
        'at-rule-name-space-after': 'always-single-line',
        'at-rule-no-unknown': [true, {
            'ignoreAtRules': [],
        }],
        'at-rule-no-vendor-prefix': true,
        'at-rule-semicolon-newline-after': 'always',
        'at-rule-semicolon-space-before': 'never',
        // 'at-rule-whitelist': [],
        // 'block-closing-brace-empty-line-before': 'always-multi-line'|'never',
        'block-closing-brace-newline-after': 'always',
        // 'block-closing-brace-newline-before': 'always'|'always-multi-line'|'never-multi-line',
        // 'block-closing-brace-space-after': 'always'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line',
        // 'block-closing-brace-space-before': 'always'|'never'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line',
        'block-no-empty': [true, {
            'severity': 'warning',
        }],
        'block-opening-brace-newline-after': 'always',
        // 'block-opening-brace-newline-before': 'always'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line',
        // 'block-opening-brace-space-after': 'always'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line',
        // 'block-opening-brace-space-before': 'always'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line',
        'color-hex-case': 'lower',
        'color-hex-length': 'long',
        // 'color-named': 'always-where-possible'|'never',
        // 'color-no-hex': true,
        'color-no-invalid-hex': true,
        // 'comment-empty-line-before': 'always'|'never',
        'comment-no-empty': true,
        // 'comment-whitespace-inside': 'always'|'never',
        // 'comment-word-blacklist': string|[],
        // 'custom-media-pattern': string,
        // 'custom-property-empty-line-before': 'always'|'never',
        // 'custom-property-pattern': string,
        'declaration-bang-space-after': 'never',
        'declaration-bang-space-before': 'always',
        'declaration-block-no-duplicate-properties': true,
        'declaration-block-no-redundant-longhand-properties': true,
        'declaration-block-no-shorthand-property-overrides': true,
        // 'declaration-block-semicolon-newline-after': 'always'|'always-multi-line'|'never-multi-line',
        // 'declaration-block-semicolon-newline-before': 'always'|'always-multi-line'|'never-multi-line',
        'declaration-block-semicolon-space-after': 'always-single-line',
        'declaration-block-semicolon-space-before': 'never',
        'declaration-block-single-line-max-declarations': 1,
        'declaration-block-trailing-semicolon': 'always',
        // 'declaration-colon-newline-after': 'always'|'always-multi-line',
        'declaration-colon-space-after': 'always-single-line',
        'declaration-colon-space-before': 'never',
        // 'declaration-empty-line-before': 'always'|'never',
        'declaration-no-important': true,
        // 'declaration-property-unit-blacklist': {},
        // 'declaration-property-unit-whitelist': {},
        // 'declaration-property-value-blacklist': {},
        // 'declaration-property-value-whitelist': {},
        'font-family-name-quotes': 'always-unless-keyword',
        // 'font-family-no-duplicate-names': boolean,
        'font-weight-notation': 'named-where-possible',
        //'function-blacklist': [],
        'function-calc-no-unspaced-operator': true,
        'function-comma-newline-after': 'never-multi-line',
        'function-comma-newline-before': 'never-multi-line',
        'function-comma-space-after': 'always',
        'function-comma-space-before': 'never',
        'function-linear-gradient-no-nonstandard-direction': true,
        'function-max-empty-lines': 0,
        'function-name-case': 'lower',
        // 'function-parentheses-newline-inside': 'always'|'always-multi-line'|'never-multi-line',
        'function-parentheses-space-inside': 'never-single-line',
        // 'function-url-data-uris': 'always'|'never',
        // 'function-url-no-scheme-relative': true,
        'function-url-scheme-whitelist': ['https'],
        'function-url-quotes': ['always', {
            // except: ['empty'],
        }],
        //'function-whitelist': [],
        'function-whitespace-after': 'always',
        'indentation': 4,
        'keyframe-declaration-no-important': true,
        // 'length-zero-no-unit': true,
        'max-empty-lines': [2, {
            'ignore': ['comments']
        }],
        // 'max-line-length': int,
        'media-feature-colon-space-after': 'always',
        'media-feature-colon-space-before': 'never',
        'media-feature-name-case': 'lower',
        'media-feature-name-no-unknown': [true, {
            'ignoreMediaFeatureNames': [],
        }],
        'media-feature-name-no-vendor-prefix': true,
        // 'media-feature-name-blacklist'
        // 'media-feature-name-whitelist'
        'media-feature-parentheses-space-inside': 'never',
        'media-feature-range-operator-space-after': 'always',
        'media-feature-range-operator-space-before': 'always',
        // 'media-query-list-comma-newline-after': 'always'|'always-multi-line'|'never-multi-line',
        // 'media-query-list-comma-newline-before': 'always'|'always-multi-line'|'never-multi-line',
        // 'media-query-list-comma-space-after': 'always'|'never'|'always-single-line'|'never-single-line',
        // 'media-query-list-comma-space-before': 'always'|'never'|'always-single-line'|'never-single-line',
        'no-descending-specificity': true,
        'no-duplicate-selectors': true,
        'no-empty-source': true,
        // 'no-eol-whitespace': true,
        'no-extra-semicolons': true,
        'no-invalid-double-slash-comments': true,
        'no-missing-end-of-source-newline': true,
        'no-unknown-animations': true,
        // 'number-leading-zero': 'always'|'never',
        // 'number-max-precision': int,
        // 'number-no-trailing-zeros': true,
        // 'property-blacklist': string|[],
        'property-case': 'lower',
        'property-no-unknown': true,
        'property-no-vendor-prefix': true,
        // 'property-whitelist': string|[],
        'selector-attribute-brackets-space-inside': 'never',
        // 'selector-attribute-operator-blacklist': string|[],
        'selector-attribute-operator-space-after': 'never',
        'selector-attribute-operator-space-before': 'never',
        // 'selector-attribute-operator-whitelist': string|[],
        'selector-attribute-quotes': 'always',
        // 'selector-class-pattern': string,
        'selector-combinator-space-after': 'always',
        'selector-combinator-space-before': 'always',
        'selector-descendant-combinator-no-non-space': true,
        // 'selector-id-pattern': string,
        // 'selector-list-comma-newline-after': 'always'|'always-multi-line'|'never-multi-line',
        // 'selector-list-comma-newline-before': 'always'|'always-multi-line'|'never-multi-line',
        'selector-list-comma-space-after': 'always-single-line',
        'selector-list-comma-space-before': 'never-single-line',
        //'selector-max-class': 0,
        'selector-max-empty-lines': 0,
        // 'selector-max-compound-selectors': int,
        // 'selector-max-specificity': string,
        // 'selector-nested-pattern': string,
        // 'selector-no-attribute': true,
        // 'selector-no-combinator': true,
        // 'selector-no-id': true,
        // 'selector-no-qualifying-type': true,
        // 'selector-no-type': true,
        'selector-no-universal': true,
        'selector-no-vendor-prefix': true,
        // 'selector-pseudo-class-blacklist': [],
        'selector-pseudo-class-case': 'lower',
        'selector-pseudo-class-no-unknown': true,
        // 'selector-pseudo-class-parentheses-space-inside': 'always'|'never',
        // 'selector-pseudo-class-whitelist': string|[],
        'selector-pseudo-element-case': 'lower',
        'selector-pseudo-element-colon-notation': 'double',
        'selector-pseudo-element-no-unknown': true,
        'selector-type-case': 'lower',
        'selector-type-no-unknown': [true, {
            'ignore': ['default-namespace', 'custom-elements'],
            'ignoreNamespaces': [],
            'ignoreTypes': [],
        }],
        'shorthand-property-no-redundant-values': [true, {
            'severity': 'warning',
        }],
        'string-no-newline': true,
        'string-quotes': 'single',
        'time-min-milliseconds': 100,
        // 'unit-blacklist': string|[],
        'unit-case': 'lower',
        'unit-no-unknown': true,
        // 'unit-whitelist': string|[],
        'value-keyword-case': 'lower',
        // 'value-list-comma-newline-after': 'always'|'always-multi-line'|'never-multi-line',
        // 'value-list-comma-newline-before': 'always'|'always-multi-line'|'never-multi-line',
        'value-list-comma-space-after': 'always-single-line',
        'value-list-comma-space-before': 'never-single-line',
        'value-list-max-empty-lines': 0,
        'value-no-vendor-prefix': true,
    },
};
<|endoftext|>


<commit_before>/*jslint node: true, plusplus: true, nomen: true, esnext: true*/
(function () {
	'use strict';
	var express = require('express'),
	    cluster = require('cluster'),
	    numCPUs = require('os').cpus().length,
	    Sequelize = require("sequelize"),
	    db = new Sequelize(process.env.DATABASE_URL),
	    bodyParser = require('body-parser'),
	    crypto = require('crypto'),
	    url = require('url'),
	    https = require('https'),
	    request = require('request'),
	    i, server;

	// Databases
	var Package = db.define('packages', {
	    Package: Sequelize.STRING,
	    Size: Sequelize.INTEGER,
	    Architecture: Sequelize.STRING,
	    Section: Sequelize.STRING,
	    Filename: Sequelize.STRING,
	    Depends: Sequelize.STRING,
	    Maintainer: Sequelize.STRING,
	    Version: Sequelize.STRING,
	    Description: Sequelize.STRING,
	    MD5Sum: Sequelize.STRING,
	    Source: Sequelize.JSON,
	    Feed: Sequelize.STRING
	});

	var Redirect = db.define('redirects', {
	    Filename: Sequelize.STRING,
	    Location: Sequelize.STRING,
	    Feed: Sequelize.STRING
	});

	function addOrUpdateRedirect(filename, feed,location) {
		Redirect
			.findOrCreate({
				where: {
					Filename: filename,
					Feed: feed
				},
				defaults: {
					Location: location
				}
			})
			.spread((redirect, created) => {
				if (!created) {
					redirect.Location = location;
					redirect.save();
				}
			});
	}

	db.sync().then(() => {

		if (cluster.isMaster) {
			// Fork workers.
			for (i = 0; i < numCPUs; i++) {
				cluster.fork();
			}

			cluster.on('exit', (worker) => {
				console.log('worker ' + worker.process.pid + ' died');
				console.log('spawing a new worker');
				cluster.fork();
			});
		} else {
			server = express();

			server.use(bodyParser.json());

			server.use((req, res, next) => {
				console.log('Incoming request (' +
							req.path +
							') handled by worker ' + cluster.worker.id);
				next();
			});

			// TODO: this code is fixed to testing/stable feeds. Try to make this more generic
			server.post('/releaseHook', (req, res) => {
				// Verify required fields
				if (!req.body || // Should be JSON
				    req.body.action !== "published" || // Should be correct hook
				    !req.body.release || // Should have a release
				    !req.body.repository || // Should have a repository
				    !req.body.repository.name || // Repository should have a name
				    !req.body.release.assets || // Should have assets
				    req.body.release.assets.length !== 1) { // Should have one asset
					res.status(400).end();
				} else {
					Package.findOne({
						where: {
							Package: req.body.repository.name,
							Feed: req.body.release.prerelease ? "testing" : "stable"
						}
					}).then((pkg) => {
						// Calculate the hash
						var hash = crypto.createHash('md5');

						var parsedURL = url.parse(req.body.release.assets[0].browser_download_url);

						var options = {method: 'HEAD', host: parsedURL.host, port: 443, path: parsedURL.path};

						https.request(options, (response) => {
							var newURL = url.parse(response.headers.location);
							var newOptions = {method: 'GET', host: newURL.host, port: 443, path: newURL.path};
							https.request(newOptions, (response) => {
								response.on('data', (data) => {
									hash.update(data);
								});

								response.on('end', () => {
									var MD5Sum = hash.digest('hex');
									pkg.MD5Sum = MD5Sum;
									pkg.Filename = req.body.release.assets[0].name;
									pkg.Size = req.body.release.assets[0].size;
									pkg.Version = req.body.release.tag_name;
									// pkg.Source.Location = req.body.release.assets[0].browser_download_url;

									addOrUpdateRedirect(req.body.release.assets[0].name, (req.body.release.prerelease ? "testing" : "stable"), req.body.release.assets[0].browser_download_url);

									pkg.Source.LastUpdated = "" + (Date.parse(req.body.release.published_at)/1000);
									pkg.Source.Changelog = req.body.release.html_url;
									pkg.save({
										fields: (pkg.changed() || []).concat(['Source'])
									}).then(() => {
										res.status(200).end();
									}).catch(() => {
										res.status(500).end();
									});
								})

								response.on('error', () => {
									res.status(500).end();
								});
							}).end();
						}).end();

					});
				}
			});

			server.post('/addPackage', (req, res) => {
				if (req.header('SECRET') !== process.env.SECRET) {
					req.status(401).end();
				} else {
					var body = req.body;
					// TODO: verify required parameters
					Package.create({
						Package: body.Package,
						Size: 0,
						Architecture: body.Architecture,
						Section: body.Section,
						Filename: "",
						Depends: body.Depends,
						Maintainer: body.Maintainer,
						Version: body.Version,
						Description: body.Description,
						MD5Sum: "",
						Source: body.Source,
						Feed: "testing"
					});
					Package.create({
						Package: body.Package,
						Size: 0,
						Architecture: body.Architecture,
						Section: body.Section,
						Filename: "",
						Depends: body.Depends,
						Maintainer: body.Maintainer,
						Version: body.Version,
						Description: body.Description,
						MD5Sum: "",
						Source: body.Source,
						Feed: "stable"
					});
					res.status(200).end();
				}
			});

			server.get('/:feed/Packages', (req, res) => {
				Package.findAll({
					where: {
						Feed: req.params.feed
					}
				}).then((pkgs) => {
					res.set('Content-Type', 'text/plain');
					var response = "";

					for (var pkg of pkgs) {
						response += "Package: " + pkg.Package + "\n";
						response += "Size: " + pkg.Size + "\n";
						response += "Architecture: " + pkg.Architecture + "\n";
						response += "Section: " + pkg.Section + "\n";
						response += "Filename: " + pkg.Filename + "\n";
						if (pkg.Depends !== "") {
							response += "Depends: " + pkg.Depends + "\n";
						}
						response += "Maintainer: " + pkg.Maintainer + "\n";
						response += "Version: " + pkg.Version + "\n";
						response += "Description: " + pkg.Description + "\n";
						response += "MD5Sum: " + pkg.MD5Sum + "\n";

						var source = pkg.Source;
						source.Feed = process.env.FEED_PREFIX + "-" + req.params.feed;

						response += "Source: " + JSON.stringify(source) + "\n";
						response += "\n";
					}

					res.status(200).send(response);
				});
			});

			server.get('/:feed/:file', (req, res) => {
				Redirect.findOne({
					where: {
						Filename: req.params.file,
						Feed: req.params.feed
					}
				}).then((redirect) => {
					if (redirect === null) {
						res.status(404).send("Cannot GET " + req.path);
					} else {
						request.get(redirect.Location).pipe(res);
					}
				});
			});

			// TODO: implement Packages.gz handler

			server.listen(process.env.PORT || 5000);
		}
	});
}());
<commit_msg>Switch from testing/stable to alpha/beta/stable<commit_after>/*jslint node: true, plusplus: true, nomen: true, esnext: true*/
(function () {
	'use strict';
	var express = require('express'),
	    cluster = require('cluster'),
	    numCPUs = require('os').cpus().length,
	    Sequelize = require("sequelize"),
	    db = new Sequelize(process.env.DATABASE_URL),
	    bodyParser = require('body-parser'),
	    crypto = require('crypto'),
	    url = require('url'),
	    https = require('https'),
	    request = require('request'),
	    i, server;

	// Databases
	var Package = db.define('packages', {
	    Package: Sequelize.STRING,
	    Size: Sequelize.INTEGER,
	    Architecture: Sequelize.STRING,
	    Section: Sequelize.STRING,
	    Filename: Sequelize.STRING,
	    Depends: Sequelize.STRING,
	    Maintainer: Sequelize.STRING,
	    Version: Sequelize.STRING,
	    Description: Sequelize.STRING,
	    MD5Sum: Sequelize.STRING,
	    Source: Sequelize.JSON,
	    Feed: Sequelize.STRING
	});

	var Redirect = db.define('redirects', {
	    Filename: Sequelize.STRING,
	    Location: Sequelize.STRING,
	    Feed: Sequelize.STRING
	});

	function addOrUpdateRedirect(filename, feed, location) {
		Redirect
			.findOrCreate({
				where: {
					Filename: filename,
					Feed: feed
				},
				defaults: {
					Location: location
				}
			})
			.spread((redirect, created) => {
				if (!created) {
					redirect.Location = location;
					redirect.save();
				}
			});
	}

	db.sync().then(() => {

		if (cluster.isMaster) {
			// Fork workers.
			for (i = 0; i < numCPUs; i++) {
				cluster.fork();
			}

			cluster.on('exit', (worker) => {
				console.log('worker ' + worker.process.pid + ' died');
				console.log('spawing a new worker');
				cluster.fork();
			});
		} else {
			server = express();

			server.use(bodyParser.json());

			server.use((req, res, next) => {
				console.log('Incoming request (' +
							req.path +
							') handled by worker ' + cluster.worker.id);
				next();
			});

			// TODO: this code is fixed to testing/stable feeds. Try to make this more generic
			server.post('/releaseHook', (req, res) => {
				// Verify required fields
				if (!req.body || // Should be JSON
				    req.body.action !== "published" || // Should be correct hook
				    !req.body.release || // Should have a release
				    !req.body.repository || // Should have a repository
				    !req.body.repository.name || // Repository should have a name
				    !req.body.release.assets || // Should have assets
				    req.body.release.assets.length !== 1) { // Should have one asset
					res.status(400).end();
				} else {
					var feed = req.body.release.tag_name.indexOf("alpha") >= 0 ? "alpha" : req.body.release.tag_name.indexOf("beta") >= 0 ? "beta" : "stable";
					Package.findOne({
						where: {
							Package: req.body.repository.name,
							Feed: feed
						}
					}).then((pkg) => {
						// Calculate the hash
						var hash = crypto.createHash('md5');

						var parsedURL = url.parse(req.body.release.assets[0].browser_download_url);

						var options = {method: 'HEAD', host: parsedURL.host, port: 443, path: parsedURL.path};

						https.request(options, (response) => {
							var newURL = url.parse(response.headers.location);
							var newOptions = {method: 'GET', host: newURL.host, port: 443, path: newURL.path};
							https.request(newOptions, (response) => {
								response.on('data', (data) => {
									hash.update(data);
								});

								response.on('end', () => {
									var MD5Sum = hash.digest('hex');
									pkg.MD5Sum = MD5Sum;
									pkg.Filename = req.body.release.assets[0].name;
									pkg.Size = req.body.release.assets[0].size;
									pkg.Version = req.body.release.tag_name;
									// pkg.Source.Location = req.body.release.assets[0].browser_download_url;

									addOrUpdateRedirect(req.body.release.assets[0].name, feed, req.body.release.assets[0].browser_download_url);

									pkg.Source.LastUpdated = "" + (Date.parse(req.body.release.published_at)/1000);
									pkg.Source.Changelog = req.body.release.html_url;
									pkg.save({
										fields: (pkg.changed() || []).concat(['Source'])
									}).then(() => {
										res.status(200).end();
									}).catch(() => {
										res.status(500).end();
									});
								})

								response.on('error', () => {
									res.status(500).end();
								});
							}).end();
						}).end();

					});
				}
			});

			server.post('/addPackage', (req, res) => {
				if (req.header('SECRET') !== process.env.SECRET) {
					req.status(401).end();
				} else {
					var body = req.body;
					// TODO: verify required parameters
					Package.create({
						Package: body.Package,
						Size: 0,
						Architecture: body.Architecture,
						Section: body.Section,
						Filename: "",
						Depends: body.Depends,
						Maintainer: body.Maintainer,
						Version: body.Version,
						Description: body.Description,
						MD5Sum: "",
						Source: body.Source,
						Feed: "alpha"
					});
					Package.create({
						Package: body.Package,
						Size: 0,
						Architecture: body.Architecture,
						Section: body.Section,
						Filename: "",
						Depends: body.Depends,
						Maintainer: body.Maintainer,
						Version: body.Version,
						Description: body.Description,
						MD5Sum: "",
						Source: body.Source,
						Feed: "beta"
					});
					Package.create({
						Package: body.Package,
						Size: 0,
						Architecture: body.Architecture,
						Section: body.Section,
						Filename: "",
						Depends: body.Depends,
						Maintainer: body.Maintainer,
						Version: body.Version,
						Description: body.Description,
						MD5Sum: "",
						Source: body.Source,
						Feed: "stable"
					});
					res.status(200).end();
				}
			});

			server.get('/:feed/Packages', (req, res) => {
				Package.findAll({
					where: {
						Feed: req.params.feed
					}
				}).then((pkgs) => {
					res.set('Content-Type', 'text/plain');
					var response = "";

					for (var pkg of pkgs) {
						response += "Package: " + pkg.Package + "\n";
						response += "Size: " + pkg.Size + "\n";
						response += "Architecture: " + pkg.Architecture + "\n";
						response += "Section: " + pkg.Section + "\n";
						response += "Filename: " + pkg.Filename + "\n";
						if (pkg.Depends !== "") {
							response += "Depends: " + pkg.Depends + "\n";
						}
						response += "Maintainer: " + pkg.Maintainer + "\n";
						response += "Version: " + pkg.Version + "\n";
						response += "Description: " + pkg.Description + "\n";
						response += "MD5Sum: " + pkg.MD5Sum + "\n";

						var source = pkg.Source;
						source.Feed = process.env.FEED_PREFIX + "-" + req.params.feed;

						response += "Source: " + JSON.stringify(source) + "\n";
						response += "\n";
					}

					res.status(200).send(response);
				});
			});

			server.get('/:feed/:file', (req, res) => {
				Redirect.findOne({
					where: {
						Filename: req.params.file,
						Feed: req.params.feed
					}
				}).then((redirect) => {
					if (redirect === null) {
						res.status(404).send("Cannot GET " + req.path);
					} else {
						request.get(redirect.Location).pipe(res);
					}
				});
			});

			// TODO: implement Packages.gz handler

			server.listen(process.env.PORT || 5000);
		}
	});
}());
<|endoftext|>


<commit_before>( function() {

	var Backstab = this.Backstab;

	// helpers
	var factorySetup = function( setupRes, opts, setupParams ) {

		var setupOpts = $.extend( {
			params: {},
			extend: {}
		}, opts );

		// auto-stuff
		setupRes = setupParams( setupRes, setupOpts.params );

		// extend events if it exists
		if ( setupRes.events && setupOpts.extend.events ) {
			setupRes.events = $.extend(
				setupRes.events,
				setupOpts.extend.events
			);
			delete setupOpts.extend.events;
		}

		// extend the rest
		setupRes = $.extend( setupRes, setupOpts.extend );

		return setupRes;
	}

	//
	Backstab.factory = function( options ) {

		var opts = $.extend( {
			script: {},
			model: {},
			collection: {},
			itemView: {},
			listView: {}
		}, options );

		if ( !opts.name_plural ) {
			opts.name_plural = opts.name + 's';
		}

		var ent = {};

		// --- model -------------------------------------------------------------------------------

		if ( false !== opts.model ) {

			var mdPrms = $.extend( {}, opts.model.params );

			var modelExt = {};

			modelExt = factorySetup( modelExt, opts.model, function( ext, params ) {

				if ( params.autourl ) {
					ext.url = opts.script.ajax_content + '&section=' + opts.name;
				}

				return ext;

			} );

			ent.Model = Backstab.Model.extend( modelExt );
		}

		// --- collection --------------------------------------------------------------------------

		if ( false !== opts.collection ) {

			var clPrms = $.extend( {}, opts.collection.params );

			var collectionExt = { model: ent.Model };

			collectionExt = factorySetup( collectionExt, opts.collection, function( ext, params ) {

				if ( params.autourl ) {
					ext.url = opts.script.ajax_content + '&section=' + opts.name_plural;
				}

				return ext;

			} );

			ent.Collection = Backstab.Collection.extend( collectionExt );
		}

		// --- item view ---------------------------------------------------------------------------

		if ( false !== opts.itemView ) {

			var ivPrms = $.extend( {}, opts.itemView.params );

			var itemViewExt = {

				events: {
					'model:change :first': 'updateItem',
					'model:destroy :first': 'removeItem'
				},

				initialize: function() {

					if ( ivPrms.inittmpl ) {
						this.$el = $( '#' + opts.name + '-tmpl' ).tmpl( {} );
					}

					if ( ivPrms.postinit ) {
						ivPrms.postinit.call( this );
					}
				},

				updateItem: function( e, model ) {

					if ( ivPrms.populatehash ) {
						this.model.populateElem( this.$el, ivPrms.populatehash );
					} else {
						this.model.populateElem( this.$el );
					}

					if ( ivPrms.postupdate ) {
						ivPrms.postupdate.call( this );
					}
				},

				removeItem: function( e, model ) {
					this.unbind();
					this.remove();
				},

				render: function() {
					this.updateItem();
					return this;
				}

			};

			itemViewExt = factorySetup( itemViewExt, opts.itemView, function( ext, params ) {

				return ext;

			} );

			ent.ItemView = Backstab.View.extend( itemViewExt );
		}

		// --- list view ---------------------------------------------------------------------------

		if ( false !== opts.listView ) {

			var lvPrms = $.extend( {}, opts.listView.params );

			var listViewExt = {

				events: {
					'collection:initialize :first; collection:add :first': 'appendItem'
				},

				_items: [],

				initialize: function() {

					if ( lvPrms.inittmpl ) {
						this.$el = $( '#' + opts.name_plural + '-tmpl' ).tmpl( {} );
					}

					if ( lvPrms.postinit ) {
						lvPrms.postinit.call( this );
					}
				},

				appendItem: function( e, model ) {

					var item = new ent.ItemView( { model: model } );
					this._items.push( item );

					item.render();

					var appendTarget = this.$el;
					if ( lvPrms.appendtarget ) {
						appendTarget = this.$( lvPrms.appendtarget );
					}

					appendTarget.append( item.$el );

					if ( lvPrms.postappend ) {
						lvPrms.postappend.call( this, appendTarget, item, model, e );
					}

					return item;
				},

				render: function() {
					return this;
				}

			};

			listViewExt = factorySetup( listViewExt, opts.listView, function( ext, params ) {

				return ext;

			} );

			ent.ListView = Backstab.View.extend( listViewExt );
		}

		// -----------------------------------------------------------------------------------------

		return ent;

	};

} ).call( this );<commit_msg>Added "parseinfo" param to factory/collection<commit_after>( function() {

	var Backstab = this.Backstab;

	// helpers
	var factorySetup = function( setupRes, opts, setupParams ) {

		var setupOpts = $.extend( {
			params: {},
			extend: {}
		}, opts );

		// auto-stuff
		setupRes = setupParams( setupRes, setupOpts.params );

		// extend events if it exists
		if ( setupRes.events && setupOpts.extend.events ) {
			setupRes.events = $.extend(
				setupRes.events,
				setupOpts.extend.events
			);
			delete setupOpts.extend.events;
		}

		// extend the rest
		setupRes = $.extend( setupRes, setupOpts.extend );

		return setupRes;
	}

	//
	Backstab.factory = function( options ) {

		var opts = $.extend( {
			script: {},
			model: {},
			collection: {},
			itemView: {},
			listView: {}
		}, options );

		if ( !opts.name_plural ) {
			opts.name_plural = opts.name + 's';
		}

		var ent = {};

		// --- model -------------------------------------------------------------------------------

		if ( false !== opts.model ) {

			var mdPrms = $.extend( {}, opts.model.params );

			var modelExt = {};

			modelExt = factorySetup( modelExt, opts.model, function( ext, params ) {

				if ( params.autourl ) {
					ext.url = opts.script.ajax_content + '&section=' + opts.name;
				}

				return ext;

			} );

			ent.Model = Backstab.Model.extend( modelExt );
		}

		// --- collection --------------------------------------------------------------------------

		if ( false !== opts.collection ) {

			var clPrms = $.extend( {}, opts.collection.params );

			var collectionExt = { model: ent.Model };

			collectionExt = factorySetup( collectionExt, opts.collection, function( ext, params ) {

				if ( params.autourl ) {
					ext.url = opts.script.ajax_content + '&section=' + opts.name_plural;
				}

				if ( params.parseinfo ) {

					ext.parse = function( response, options ) {

						this.info = null;	// reset

						if ( response[ '__info' ] && response[ '__body' ] ) {
							this.info = response[ '__info' ];
							return response[ '__body' ];
						}

						return response;
					}

				}

				return ext;

			} );

			ent.Collection = Backstab.Collection.extend( collectionExt );
		}

		// --- item view ---------------------------------------------------------------------------

		if ( false !== opts.itemView ) {

			var ivPrms = $.extend( {}, opts.itemView.params );

			var itemViewExt = {

				events: {
					'model:change :first': 'updateItem',
					'model:destroy :first': 'removeItem'
				},

				initialize: function() {

					if ( ivPrms.inittmpl ) {
						this.$el = $( '#' + opts.name + '-tmpl' ).tmpl( {} );
					}

					if ( ivPrms.postinit ) {
						ivPrms.postinit.call( this );
					}
				},

				updateItem: function( e, model ) {

					if ( ivPrms.populatehash ) {
						this.model.populateElem( this.$el, ivPrms.populatehash );
					} else {
						this.model.populateElem( this.$el );
					}

					if ( ivPrms.postupdate ) {
						ivPrms.postupdate.call( this );
					}
				},

				removeItem: function( e, model ) {
					this.unbind();
					this.remove();
				},

				render: function() {
					this.updateItem();
					return this;
				}

			};

			itemViewExt = factorySetup( itemViewExt, opts.itemView, function( ext, params ) {

				return ext;

			} );

			ent.ItemView = Backstab.View.extend( itemViewExt );
		}

		// --- list view ---------------------------------------------------------------------------

		if ( false !== opts.listView ) {

			var lvPrms = $.extend( {}, opts.listView.params );

			var listViewExt = {

				events: {
					'collection:initialize :first; collection:add :first': 'appendItem'
				},

				_items: [],

				initialize: function() {

					if ( lvPrms.inittmpl ) {
						this.$el = $( '#' + opts.name_plural + '-tmpl' ).tmpl( {} );
					}

					if ( lvPrms.postinit ) {
						lvPrms.postinit.call( this );
					}
				},

				appendItem: function( e, model ) {

					var item = new ent.ItemView( { model: model } );
					this._items.push( item );

					item.render();

					var appendTarget = this.$el;
					if ( lvPrms.appendtarget ) {
						appendTarget = this.$( lvPrms.appendtarget );
					}

					appendTarget.append( item.$el );

					if ( lvPrms.postappend ) {
						lvPrms.postappend.call( this, appendTarget, item, model, e );
					}

					return item;
				},

				render: function() {
					return this;
				}

			};

			listViewExt = factorySetup( listViewExt, opts.listView, function( ext, params ) {

				return ext;

			} );

			ent.ListView = Backstab.View.extend( listViewExt );
		}

		// -----------------------------------------------------------------------------------------

		return ent;

	};

} ).call( this );<|endoftext|>


<commit_before>//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Draws "square" and "circle" shapes using svg:rect
//------------------------------------------------------------------------------
d3plus.shape.area = function(vars,selection,enter,exit) {

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // D3 area definition
  //----------------------------------------------------------------------------
  var area = d3.svg.area()
    .x(function(d) { return d.d3plus.x; })
    .y0(function(d) { return d.d3plus.y0; })
    .y1(function(d) { return d.d3plus.y; })
    .interpolate(vars.shape.interpolate.default)

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // "paths" Enter
  //----------------------------------------------------------------------------
  enter.append("path").attr("class","data")
    .attr("d",function(d){ return area(d.values) })
    .call(d3plus.shape.style,vars)

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // "paths" Update
  //----------------------------------------------------------------------------
  selection.selectAll("path.data")
    .data(function(d) {

      if (vars.labels.default && !d.d3plus.label) {

        var areas = [],
            obj = null,
            obj2 = null,
            label = {
              "w": 0,
              "h": 0,
              "x": 0,
              "y": 0
            }

        function check_area(area) {

          obj.y = d3.max([obj.y,area.y])
          obj.y0 = d3.min([obj.y0,area.y0])
          obj.x0 = area.x

          obj.h = (obj.y0 - obj.y)
          obj.w = (obj.x0 - obj.x)

          var toosmall = obj.h < 10 || obj.w < 30,
              aspect_old = label.w/label.h,
              size_old = label.w*label.h,
              aspect_new = obj.w/obj.h,
              size_new = obj.w*obj.h

          if ((!toosmall && size_old < size_new) || !label.w) {
            label = {
              "w": obj.w-(vars.style.labels.padding*2),
              "h": obj.h-(vars.style.labels.padding*2),
              "x": obj.x+(obj.w/2),
              "y": obj.y+(obj.h/2)
            }
          }
          if (obj.h < 10) {
            obj = d3plus.utils.copy(area)
          }

        }

        d.values.forEach(function(v,i){

          if (!obj) {
            obj = d3plus.utils.copy(v.d3plus)
          }
          else {
            var arr = d3plus.utils.buckets([0,1],vars.style.labels.segments+1)
            arr.shift()
            arr.pop()
            arr.forEach(function(n){

              var test = d3plus.utils.copy(v.d3plus),
                  last = d.values[i-1].d3plus

              test.x = last.x + (test.x-last.x) * n
              test.y = last.y + (test.y-last.y) * n
              test.y0 = last.y0 + (test.y0-last.y0) * n

              check_area(test)

            })
            check_area(d3plus.utils.copy(v.d3plus))
          }
        })

        if (label.w) {
          d.d3plus_label = label
        }

      }
      else if (d.d3plus.label) {
        d.d3plus_label = d.d3plus.label
      }

      return [d];
    })
    .transition().duration(vars.style.timing.transitions)
      .attr("d",function(d){ return area(d.values) })
      .call(d3plus.shape.style,vars)

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // Define mouse event area
  //----------------------------------------------------------------------------
  var mouses = selection.selectAll("path.mouse")
    .data(function(d) {return [d];})

  mouses.enter().append("path")
    .attr("class","mouse")
    .attr("opacity",0)
    .attr("stroke",1)
    .attr("d",function(d){ return area(d.values) })

  mouses
    .data(function(d) {return [d];})
    .on(d3plus.evt.over,function(d){

      if (!vars.frozen) {

        d3.select(this).style("cursor","pointer")

        var mouse = d3.event[vars.continuous_axis]
            positions = d3plus.utils.uniques(d.values,function(x){return x.d3plus[vars.continuous_axis]}),
            closest = d3plus.utils.closest(positions,mouse)

        d.data = d.values[positions.indexOf(closest)]
        d.d3plus = d.values[positions.indexOf(closest)].d3plus

        d3.select(this.parentNode).selectAll("path.data")
          .transition().duration(vars.style.timing.mouseevents)
          .style("opacity",1)

      }

    })
    .on(d3plus.evt.move,function(d){

      if (!vars.frozen) {

        var mouse = d3.event.x,
            positions = d3plus.utils.uniques(d.values,function(x){return x.d3plus.x}),
            closest = d3plus.utils.closest(positions,mouse)

        d.data = d.values[positions.indexOf(closest)]
        d.d3plus = d.values[positions.indexOf(closest)].d3plus

      }

    })
    .on(d3plus.evt.out,function(d){

      if (!vars.frozen) {

        d3.select(this.parentNode).selectAll("path.data")
          .transition().duration(vars.style.timing.mouseevents)
          .style("opacity",vars.style.data.opacity)

        delete d.d3plus

      }

    })
    .transition().duration(vars.style.timing.transitions)
      .attr("d",function(d){ return area(d.values) })

}
<commit_msg>removed manual labels from area shapes<commit_after>//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Draws "square" and "circle" shapes using svg:rect
//------------------------------------------------------------------------------
d3plus.shape.area = function(vars,selection,enter,exit) {

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // D3 area definition
  //----------------------------------------------------------------------------
  var area = d3.svg.area()
    .x(function(d) { return d.d3plus.x; })
    .y0(function(d) { return d.d3plus.y0; })
    .y1(function(d) { return d.d3plus.y; })
    .interpolate(vars.shape.interpolate.default)

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // "paths" Enter
  //----------------------------------------------------------------------------
  enter.append("path").attr("class","data")
    .attr("d",function(d){ return area(d.values) })
    .call(d3plus.shape.style,vars)

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // "paths" Update
  //----------------------------------------------------------------------------
  selection.selectAll("path.data")
    .data(function(d) {

      if (vars.labels.default) {

        var areas = [],
            obj = null,
            obj2 = null,
            label = {
              "w": 0,
              "h": 0,
              "x": 0,
              "y": 0
            }

        function check_area(area) {

          obj.y = d3.max([obj.y,area.y])
          obj.y0 = d3.min([obj.y0,area.y0])
          obj.x0 = area.x

          obj.h = (obj.y0 - obj.y)
          obj.w = (obj.x0 - obj.x)

          var toosmall = obj.h < 10 || obj.w < 30,
              aspect_old = label.w/label.h,
              size_old = label.w*label.h,
              aspect_new = obj.w/obj.h,
              size_new = obj.w*obj.h

          if ((!toosmall && size_old < size_new) || !label.w) {
            label = {
              "w": obj.w-(vars.style.labels.padding*2),
              "h": obj.h-(vars.style.labels.padding*2),
              "x": obj.x+(obj.w/2),
              "y": obj.y+(obj.h/2)
            }
          }
          if (obj.h < 10) {
            obj = d3plus.utils.copy(area)
          }

        }

        d.values.forEach(function(v,i){

          if (!obj) {
            obj = d3plus.utils.copy(v.d3plus)
          }
          else {
            var arr = d3plus.utils.buckets([0,1],vars.style.labels.segments+1)
            arr.shift()
            arr.pop()
            arr.forEach(function(n){

              var test = d3plus.utils.copy(v.d3plus),
                  last = d.values[i-1].d3plus

              test.x = last.x + (test.x-last.x) * n
              test.y = last.y + (test.y-last.y) * n
              test.y0 = last.y0 + (test.y0-last.y0) * n

              check_area(test)

            })
            check_area(d3plus.utils.copy(v.d3plus))
          }
        })

        if (label.w) {
          d.d3plus_label = label
        }

      }

      return [d];
    })
    .transition().duration(vars.style.timing.transitions)
      .attr("d",function(d){ return area(d.values) })
      .call(d3plus.shape.style,vars)

  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // Define mouse event area
  //----------------------------------------------------------------------------
  var mouses = selection.selectAll("path.mouse")
    .data(function(d) {return [d];})

  mouses.enter().append("path")
    .attr("class","mouse")
    .attr("opacity",0)
    .attr("stroke",1)
    .attr("d",function(d){ return area(d.values) })

  mouses
    .data(function(d) {return [d];})
    .on(d3plus.evt.over,function(d){

      if (!vars.frozen) {

        d3.select(this).style("cursor","pointer")

        var mouse = d3.event[vars.continuous_axis]
            positions = d3plus.utils.uniques(d.values,function(x){return x.d3plus[vars.continuous_axis]}),
            closest = d3plus.utils.closest(positions,mouse)

        d.data = d.values[positions.indexOf(closest)]
        d.d3plus = d.values[positions.indexOf(closest)].d3plus

        d3.select(this.parentNode).selectAll("path.data")
          .transition().duration(vars.style.timing.mouseevents)
          .style("opacity",1)

      }

    })
    .on(d3plus.evt.move,function(d){

      if (!vars.frozen) {

        var mouse = d3.event.x,
            positions = d3plus.utils.uniques(d.values,function(x){return x.d3plus.x}),
            closest = d3plus.utils.closest(positions,mouse)

        d.data = d.values[positions.indexOf(closest)]
        d.d3plus = d.values[positions.indexOf(closest)].d3plus

      }

    })
    .on(d3plus.evt.out,function(d){

      if (!vars.frozen) {

        d3.select(this.parentNode).selectAll("path.data")
          .transition().duration(vars.style.timing.mouseevents)
          .style("opacity",vars.style.data.opacity)

        delete d.d3plus

      }

    })
    .transition().duration(vars.style.timing.transitions)
      .attr("d",function(d){ return area(d.values) })

}
<|endoftext|>


<commit_before>import {VIEW_PROFILE, PLAYERLIST_SUCCESS, VIEW_LEADERBOARD, RECENT_GAMES, PLAYERLIST_DONE} from '../actions/types';

export default function currentProfile(state = {}, action) {
    switch(action.type) {
        case VIEW_PROFILE:
            return action.payload;
        case 'CLEAR_CURRENT_PROFILE':
            return {};
        default:
            return state;
    }
}

export function playerList(state = {
    players: [],
    hasMore: true,
}, action) {
    let newState = null;
    switch(action.type) {
        case PLAYERLIST_SUCCESS:
            newState = Object.assign({}, state);
            newState.players = action.payload;
            return newState;
        case PLAYERLIST_DONE:
            newState = Object.assign({}, state);
            newState.hasMore = false;
            return newState;
        default:
            return state;
    }
}

export function leaderboard(state = {}, action) {
    switch(action.type) {
        case VIEW_LEADERBOARD:
            return action.payload;
        default:
            return state;
    }
}

export function recentGames(state = [], action) {

    switch (action.type) {
        case RECENT_GAMES:
            return action.payload;
        case 'CLEAR_RECENT_GAMES':
            return [];
        default:
            return state;
    }
}
<commit_msg>add to list don't replace<commit_after>import {VIEW_PROFILE, PLAYERLIST_SUCCESS, VIEW_LEADERBOARD, RECENT_GAMES, PLAYERLIST_DONE} from '../actions/types';

export default function currentProfile(state = {}, action) {
    switch(action.type) {
        case VIEW_PROFILE:
            return action.payload;
        case 'CLEAR_CURRENT_PROFILE':
            return {};
        default:
            return state;
    }
}

export function playerList(state = {
    players: [],
    hasMore: true,
}, action) {
    let newState = null;
    switch(action.type) {
        case PLAYERLIST_SUCCESS:
            newState = Object.assign({}, state);
            newState.players = newState.players.concat(action.payload);
            return newState;
        case PLAYERLIST_DONE:
            newState = Object.assign({}, state);
            newState.hasMore = false;
            return newState;
        default:
            return state;
    }
}

export function leaderboard(state = {}, action) {
    switch(action.type) {
        case VIEW_LEADERBOARD:
            return action.payload;
        default:
            return state;
    }
}

export function recentGames(state = [], action) {

    switch (action.type) {
        case RECENT_GAMES:
            return action.payload;
        case 'CLEAR_RECENT_GAMES':
            return [];
        default:
            return state;
    }
}
<|endoftext|>


<commit_before>
/** Module dependencies. */

var config  = require('../config/config.js');

var guess_origin = require("./lib/guess_origin");
var Trie = require('./lib/trie');
var _ = require("lodash");

var elastic = require('elasticsearch');
var elasticClient = new elastic.Client({
    "apiVersion" : "1.4"
***REMOVED***);

const source = ["cui", "str", "exact", "pref", "source", "types"];

// Build regex objects for demographic check
var DEMOGRAPHICS = new Trie(config.demographic_types);

module.exports = function *() {
  var query = this.request.body.query;

  // Check special matches, such as demographic options
  var specialMatches = yield findSpecial(query);

  // Lookup matches in Elasticsearch
  var exactMatches = yield findExact(query);
  var closeMatches = yield findMatches(query);

  this.body = {
    "took": exactMatches.took + closeMatches.took,
    "special": specialMatches,

    "hits": _.uniq(exactMatches.hits.concat(closeMatches.hits), "exact")
  ***REMOVED***
***REMOVED***;

function findExact(query) {
    var wantedTerm = query.trim().toLowerCase();

***REMOVED*** Filter out CUI codes that the user already selected
    return function(callback) {
        var elastic_query =  {
            "_source": source,

            "size": 3,

            "query": {
                "term" : {
                    "exact" : wantedTerm
            ***REMOVED***
        ***REMOVED***
    ***REMOVED***;

    ***REMOVED*** Search in all indexes
        var queryObj = {
            "index" : 'autocomplete',
            "body"  : elastic_query
    ***REMOVED***;

        elasticClient.search(queryObj, function(err, res) {
            var hits = res.hits;
            var result = [];

            if (hits && hits.total > 0) {
                for (var i=0; i < hits.hits.length; i++) {
                    result.push(hits.hits[i]._source);
            ***REMOVED***
        ***REMOVED***

            callback(err, {
                "took": res.took,
                "hits": result
        ***REMOVED***);
    ***REMOVED***);
***REMOVED***
***REMOVED***

function findMatches(query) {
    var origin = guess_origin(query);

***REMOVED*** Filter out CUI codes that the user already selected
    return function(callback) {

    ***REMOVED*** DBC code check needs prefix matching
        if (origin === "code") {
            var elastic_query =  {
                "_source": source,
                "size": 6,

                "query": {
                    "match_phrase_prefix" : {
                        "str" : query.trim()
                ***REMOVED***
            ***REMOVED***
        ***REMOVED***;
    ***REMOVED***
        ***REMOVED***
            var elastic_query =  {
                "_source": source,
                "size": 6,

                "query": {
                    "function_score" : {
                        "query" : {
                            "match_phrase" : {
                                "str" : query.trim()
                        ***REMOVED***
                    ***REMOVED***,

                        "functions" : [
                        ***REMOVED*** Prefer SnomedCT / MeSH
                            {
                                "filter": {
                                    "terms": { "source": ["SNOMEDCT_US", "MSH", "MSHDUT"] ***REMOVED***
                            ***REMOVED***,
                                "weight": 1.25
                        ***REMOVED***,

                        ***REMOVED*** Negative weight for some categories
                            {
                                "filter": {
                                    "terms": { "types": ["Health Care Activity", "Biomedical Occupation or Discipline"] ***REMOVED***
                            ***REMOVED***,
                                "weight": 0.7
                        ***REMOVED***
                        ]
                ***REMOVED***
            ***REMOVED***
        ***REMOVED***;
    ***REMOVED***

        var queryObj = {
            "index" : 'autocomplete',
            "body"  : elastic_query
    ***REMOVED***;

        elasticClient.search(queryObj, function(err, res) {
            var hits = res.hits;
            var result = [];

            if (hits && hits.total > 0) {
                for (var i=0; i < hits.hits.length; i++) {
                    result.push(hits.hits[i]._source);
            ***REMOVED***
        ***REMOVED***

            callback(err, {
                "took": res.took,
                "hits": result
        ***REMOVED***);
    ***REMOVED***);
***REMOVED***
***REMOVED***

function findSpecial(query) {
    var _query = query.trim().toLowerCase();

    return function(callback) {
        var result = false;
        var match = DEMOGRAPHICS.search(_query)

        if (match.length > 0) {
            var split = match[0]["value"].split(":");

            var result = {
                "str"      : split[0],
                "value"    : split[1] || "",
                "pref"     : "demographic",
                "cui"      : "custom",
                "category" : "demographic"
        ***REMOVED***
    ***REMOVED***

        callback(false, result);
***REMOVED***
***REMOVED***<commit_msg>Value as object<commit_after>
/** Module dependencies. */

var config  = require('../config/config.js');

var guess_origin = require("./lib/guess_origin");
var Trie = require('./lib/trie');
var _ = require("lodash");

var elastic = require('elasticsearch');
var elasticClient = new elastic.Client({
    "apiVersion" : "1.4"
***REMOVED***);

const source = ["cui", "str", "exact", "pref", "source", "types"];

// Build regex objects for demographic check
var DEMOGRAPHICS = new Trie(config.demographic_types);

module.exports = function *() {
  var query = this.request.body.query;

  // Check special matches, such as demographic options
  var specialMatches = yield findSpecial(query);

  // Lookup matches in Elasticsearch
  var exactMatches = yield findExact(query);
  var closeMatches = yield findMatches(query);

  this.body = {
    "took": exactMatches.took + closeMatches.took,
    "special": specialMatches,

    "hits": _.uniq(exactMatches.hits.concat(closeMatches.hits), "exact")
  ***REMOVED***
***REMOVED***;

function findExact(query) {
    var wantedTerm = query.trim().toLowerCase();

***REMOVED*** Filter out CUI codes that the user already selected
    return function(callback) {
        var elastic_query =  {
            "_source": source,

            "size": 3,

            "query": {
                "term" : {
                    "exact" : wantedTerm
            ***REMOVED***
        ***REMOVED***
    ***REMOVED***;

    ***REMOVED*** Search in all indexes
        var queryObj = {
            "index" : 'autocomplete',
            "body"  : elastic_query
    ***REMOVED***;

        elasticClient.search(queryObj, function(err, res) {
            var hits = res.hits;
            var result = [];

            if (hits && hits.total > 0) {
                for (var i=0; i < hits.hits.length; i++) {
                    result.push(hits.hits[i]._source);
            ***REMOVED***
        ***REMOVED***

            callback(err, {
                "took": res.took,
                "hits": result
        ***REMOVED***);
    ***REMOVED***);
***REMOVED***
***REMOVED***

function findMatches(query) {
    var origin = guess_origin(query);

***REMOVED*** Filter out CUI codes that the user already selected
    return function(callback) {

    ***REMOVED*** DBC code check needs prefix matching
        if (origin === "code") {
            var elastic_query =  {
                "_source": source,
                "size": 6,

                "query": {
                    "match_phrase_prefix" : {
                        "str" : query.trim()
                ***REMOVED***
            ***REMOVED***
        ***REMOVED***;
    ***REMOVED***
        ***REMOVED***
            var elastic_query =  {
                "_source": source,
                "size": 6,

                "query": {
                    "function_score" : {
                        "query" : {
                            "match_phrase" : {
                                "str" : query.trim()
                        ***REMOVED***
                    ***REMOVED***,

                        "functions" : [
                        ***REMOVED*** Prefer SnomedCT / MeSH
                            {
                                "filter": {
                                    "terms": { "source": ["SNOMEDCT_US", "MSH", "MSHDUT"] ***REMOVED***
                            ***REMOVED***,
                                "weight": 1.25
                        ***REMOVED***,

                        ***REMOVED*** Negative weight for some categories
                            {
                                "filter": {
                                    "terms": { "types": ["Health Care Activity", "Biomedical Occupation or Discipline"] ***REMOVED***
                            ***REMOVED***,
                                "weight": 0.7
                        ***REMOVED***
                        ]
                ***REMOVED***
            ***REMOVED***
        ***REMOVED***;
    ***REMOVED***

        var queryObj = {
            "index" : 'autocomplete',
            "body"  : elastic_query
    ***REMOVED***;

        elasticClient.search(queryObj, function(err, res) {
            var hits = res.hits;
            var result = [];

            if (hits && hits.total > 0) {
                for (var i=0; i < hits.hits.length; i++) {
                    result.push(hits.hits[i]._source);
            ***REMOVED***
        ***REMOVED***

            callback(err, {
                "took": res.took,
                "hits": result
        ***REMOVED***);
    ***REMOVED***);
***REMOVED***
***REMOVED***

function findSpecial(query) {
    var _query = query.trim().toLowerCase();

    return function(callback) {
        var result = false;
        var match = DEMOGRAPHICS.search(_query)

        if (match.length > 0) {
            var split = match[0]["value"].split(":");

            var label = split[0];
            var value = false;

            if (split[1]) {
                label = split[0] + ": " + split[1];

                value = {***REMOVED***;
                value[split[0]] = split[1];
        ***REMOVED***

            var result = {
                "str"      : label,
                "value"    : value,
                "pref"     : "demographic",
                "cui"      : "custom",
                "category" : "demographic"
        ***REMOVED***
    ***REMOVED***

        callback(false, result);
***REMOVED***
***REMOVED***<|endoftext|>


<commit_before>// Testing min.js because if the min works, the unminned should also work
describe("Dice", function(){

	it("inits properly", function(){
		expect(dice).toBeDefined();
		expect(dice.eval).toBeDefined();
		expect(dice.parse).toBeDefined();
		expect(dice.eval.eval).toBeDefined();
		expect(dice.parse.parse).toBeDefined();
		expect(dice.roll).toBeDefined();
	});

	describe("can parse a variety of intputs", function(){
		var strings = ["1", "1d6", "d20", "3d8", "3d2..8", "1d20 + 5",
		"3d6 + 1d12", "d20 + [Con Mod]", "3d[W]",
		"3d[W] + 2 + [Strength Mod] + [Enhance]d12", "3d6 + 1w6",
		"3d6 + -2", "3d6 * 2", "15 / 3", "f[scope var]",
		"3dr[roundable]", "c[tough]w7", "3..5", "(1)", "(1 + 2)",
		"( 2d6 * 7)", "1d6 + (3d6 *7 )", "( 1 + 2) * 3",
		"1d20 * (1d6 * ( 3 + [variable] ) )", "r([variable] + 2)d6",
		"f(5 /3)", "( c([variable] / 7) + 3) * 2",
		"3 + r(3/ [variable])"];

		strings.map(function(toParse){
			it("parses " + toParse, function(){
				var parseIt = function(){
					dice.parse.parse(toParse);
				}
				expect(parseIt).not.toThrow();
			});
		});
	});

	describe("Roll results", function(){

		it("returns static numbers", function(){
			var res = dice.roll("3");
			expect(res).toEqual(3);
		});

		it("parses and evals simple rolls", function(){
			var res = dice.roll("d20");
			expect(res).toBeLessThan(21);
			expect(res).toBeGreaterThan(0);
		});

		it("parses and evals a basic scope", function(){
			var scope = {"Key Thing":4};
			var res = dice.roll("[Key Thing]", scope);

			expect(res).toEqual(4);

			scope["Key Thing"] = 27;
			res = dice.roll("[Key Thing]", scope);

			expect(res).toEqual(27);
		});

		it("of a simple roll from static numbers", function(){
			var res = dice.roll("3d6");
			expect(res).toBeLessThan(19);
			expect(res).toBeGreaterThan(2);
			expect((res >= 3));
			expect(res.rolls).toBeDefined();
			res.rolls.map(function(n){
				expect(n).toBeLessThan(7);
				expect(n).toBeGreaterThan(0);
			});
		});

		it("rolls a simple roll with a bonus", function(){
			var res = dice.roll("1d20 + 4");
			expect(res).toBeLessThan(25);
			expect(res).toBeGreaterThan(4);
			var stringy = dice.stringify(res);
			expect(stringy).toMatch(/1d20:\[\d+\] \+ 4/);
		});

		it("parse and roll correct number of dice", function(){
			res = dice.roll("3d6..6");
			expect(res).toEqual(18);
			expect(res.rolls).toBeDefined();
			expect(res.rolls.length).toEqual(3);
			res.rolls.map(function(n){
				expect(n).toEqual(6);
			});
		});

		it("parse scope in num dice", function(){
			var rollStr = "[Key Thing]d5..5";

			var scope = {"Key Thing":4};
			var res = dice.roll(rollStr, scope);

			expect(res).toEqual(20);

			scope["Key Thing"] = 27;
			res = dice.roll(rollStr, scope);

			expect(res).toEqual(27 * 5);
		});

		it("parse scope in min and max", function(){
			var rollStr = "2d[Key Thing]..[Key Thing]";

			var scope = {"Key Thing":4};
			var res = dice.roll(rollStr, scope);

			expect(res).toEqual(8);

			scope["Key Thing"] = 27;
			res = dice.roll(rollStr, scope);

			expect(res).toEqual(27 * 2);

		});

		it("adds negative numbers correctly", function(){
			var rollStr = "5 + -2";
			var parsed = dice.roll(rollStr, {});
			expect(parsed).toEqual(3);
		});

		it("handles multiplication", function(){
			var rollStr = "1d3..3 * 5";
			var parsed = dice.roll(rollStr, {});
			expect(parsed).toEqual(15);
		});

		it("can divide two numbers", function(){
			var rollStr = "1d15..15 / 3";
			var parsed = dice.roll(rollStr, {});
			expect(parsed).toEqual(5);
		});

		it("floors variable numbers", function(){
			var rollStr = "f[thang]d5..5";
			var scope = {'thang':3.7};
			var res = dice.roll(rollStr, scope);
			expect(res).toEqual(15);
		});

		it("rounds variable numbers", function(){
			var rollStr = "r[3 2]dr[4 5]..5 + r[6 7]";
			var scope = {'3 2': 3.2, '4 5': 4.5, '6 7':6.7};
			var res = dice.roll(rollStr, scope);
			expect(res).toEqual(22);
		});

		it("ceilings variable numbers", function(){
			var rollStr = "1d4..c[not four]";
			var scope = {'not four': 3.2};
			var res = dice.roll(rollStr, scope);
			expect(res).toEqual(4)
		});

		it("respects order of operations", function(){
			var rollStr = "[n] + 2 * 5";
			var scope = {'n':7};
			var res = dice.roll(rollStr, scope);
			expect(res).toEqual(17);
		});

		it("handles basic parenthsis correctly", function(){
			var rollStr = "(2 + 3) * 7";
			var res = dice.roll(rollStr, {});
			expect(res).toEqual(35);
			var stringy = dice.stringify(res);
			expect(stringy).toEqual("( 2 + 3 ) * 7");
		});

		var testThings = [
		["f(10 / 3)", 3, "f( 10 / 3 )"],
		["r(10/3)", 3, "r( 10 / 3 )"],
		["c(10 /3)", 4, "c( 10 / 3 )"]
		];
		testThings.map(function(ar){
			it("round evals " + ar[0], function(){
				var res = dice.roll(ar[0], {});
				expect(res).toEqual(ar[1]);
				var stringy = dice.stringify(res);
				expect(stringy).toEqual(ar[2]);
			});
		});

		it("evaluates simple statistics with no extra params", function(){
			var results = dice.statistics("1d1");
			expect(results.min).toEqual(1);
			expect(results.max).toEqual(1);
			expect(results.mean).toEqual(1);
		});

		it("evaluates simple statistics with only samples", function(){
			var results = dice.statistics("1d1", 10);
			expect(results.min).toEqual(1);
			expect(results.results.length).toEqual(10);
			expect(results.max).toEqual(1);
			expect(results.mean).toEqual(1);
		});

		it("evaluates simple statistics with only scope", function(){
			var results = dice.statistics("1d[one]", {'one': 1});
			expect(results.min).toEqual(1);
			expect(results.max).toEqual(1);
			expect(results.mean).toEqual(1);
		});

		it("evaluates simple statistics with both scope and samples", function(){
			var results = dice.statistics("[one]d1", {'one': 1}, 50);
			expect(results.min).toEqual(1);
			expect(results.results.length).toEqual(50);
			expect(results.max).toEqual(1);
			expect(results.mean).toEqual(1);
		});

	});
});

<commit_msg>Altered test spec for both browser and node<commit_after>// Testing min.js because if the min works, the unminned should also work
if(typeof require !== 'undefined'){
    var dice = require('../src/dice.js');
}

describe("Dice", function(){

	it("inits properly", function(){
		expect(dice).toBeDefined();
		expect(dice.eval).toBeDefined();
		expect(dice.parse).toBeDefined();
		expect(dice.roll).toBeDefined();
	});

	describe("can parse a variety of intputs", function(){
		var strings = ["1", "1d6", "d20", "3d8", "3d2..8", "1d20 + 5",
		"3d6 + 1d12", "d20 + [Con Mod]", "3d[W]",
		"3d[W] + 2 + [Strength Mod] + [Enhance]d12", "3d6 + 1w6",
		"3d6 + -2", "3d6 * 2", "15 / 3", "f[scope var]",
		"3dr[roundable]", "c[tough]w7", "3..5", "(1)", "(1 + 2)",
		"( 2d6 * 7)", "1d6 + (3d6 *7 )", "( 1 + 2) * 3",
		"1d20 * (1d6 * ( 3 + [variable] ) )", "r([variable] + 2)d6",
		"f(5 /3)", "( c([variable] / 7) + 3) * 2",
		"3 + r(3/ [variable])"];

		strings.map(function(toParse){
			it("parses " + toParse, function(){
				var parseIt = function(){
					dice.parse(toParse);
				}
				expect(parseIt).not.toThrow();
			});
		});
	});

	describe("Roll results", function(){

		it("returns static numbers", function(){
			var res = dice.roll("3");
			expect(res).toEqual(3);
		});

		it("parses and evals simple rolls", function(){
			var res = dice.roll("d20");
			expect(res).toBeLessThan(21);
			expect(res).toBeGreaterThan(0);
		});

		it("parses and evals a basic scope", function(){
			var scope = {"Key Thing":4};
			var res = dice.roll("[Key Thing]", scope);

			expect(res).toEqual(4);

			scope["Key Thing"] = 27;
			res = dice.roll("[Key Thing]", scope);

			expect(res).toEqual(27);
		});

		it("of a simple roll from static numbers", function(){
			var res = dice.roll("3d6");
			expect(res).toBeLessThan(19);
			expect(res).toBeGreaterThan(2);
			expect((res >= 3));
			expect(res.rolls).toBeDefined();
			res.rolls.map(function(n){
				expect(n).toBeLessThan(7);
				expect(n).toBeGreaterThan(0);
			});
		});

		it("rolls a simple roll with a bonus", function(){
			var res = dice.roll("1d20 + 4");
			expect(res).toBeLessThan(25);
			expect(res).toBeGreaterThan(4);
			var stringy = dice.stringify(res);
			expect(stringy).toMatch(/1d20:\[\d+\] \+ 4/);
		});

		it("parse and roll correct number of dice", function(){
			res = dice.roll("3d6..6");
			expect(res).toEqual(18);
			expect(res.rolls).toBeDefined();
			expect(res.rolls.length).toEqual(3);
			res.rolls.map(function(n){
				expect(n).toEqual(6);
			});
		});

		it("parse scope in num dice", function(){
			var rollStr = "[Key Thing]d5..5";

			var scope = {"Key Thing":4};
			var res = dice.roll(rollStr, scope);

			expect(res).toEqual(20);

			scope["Key Thing"] = 27;
			res = dice.roll(rollStr, scope);

			expect(res).toEqual(27 * 5);
		});

		it("parse scope in min and max", function(){
			var rollStr = "2d[Key Thing]..[Key Thing]";

			var scope = {"Key Thing":4};
			var res = dice.roll(rollStr, scope);

			expect(res).toEqual(8);

			scope["Key Thing"] = 27;
			res = dice.roll(rollStr, scope);

			expect(res).toEqual(27 * 2);

		});

		it("adds negative numbers correctly", function(){
			var rollStr = "5 + -2";
			var parsed = dice.roll(rollStr, {});
			expect(parsed).toEqual(3);
		});

		it("handles multiplication", function(){
			var rollStr = "1d3..3 * 5";
			var parsed = dice.roll(rollStr, {});
			expect(parsed).toEqual(15);
		});

		it("can divide two numbers", function(){
			var rollStr = "1d15..15 / 3";
			var parsed = dice.roll(rollStr, {});
			expect(parsed).toEqual(5);
		});

		it("floors variable numbers", function(){
			var rollStr = "f[thang]d5..5";
			var scope = {'thang':3.7};
			var res = dice.roll(rollStr, scope);
			expect(res).toEqual(15);
		});

		it("rounds variable numbers", function(){
			var rollStr = "r[3 2]dr[4 5]..5 + r[6 7]";
			var scope = {'3 2': 3.2, '4 5': 4.5, '6 7':6.7};
			var res = dice.roll(rollStr, scope);
			expect(res).toEqual(22);
		});

		it("ceilings variable numbers", function(){
			var rollStr = "1d4..c[not four]";
			var scope = {'not four': 3.2};
			var res = dice.roll(rollStr, scope);
			expect(res).toEqual(4)
		});

		it("respects order of operations", function(){
			var rollStr = "[n] + 2 * 5";
			var scope = {'n':7};
			var res = dice.roll(rollStr, scope);
			expect(res).toEqual(17);
		});

		it("handles basic parenthsis correctly", function(){
			var rollStr = "(2 + 3) * 7";
			var res = dice.roll(rollStr, {});
			expect(res).toEqual(35);
			var stringy = dice.stringify(res);
			expect(stringy).toEqual("( 2 + 3 ) * 7");
		});

		var testThings = [
		["f(10 / 3)", 3, "f( 10 / 3 )"],
		["r(10/3)", 3, "r( 10 / 3 )"],
		["c(10 /3)", 4, "c( 10 / 3 )"]
		];
		testThings.map(function(ar){
			it("round evals " + ar[0], function(){
				var res = dice.roll(ar[0], {});
				expect(res).toEqual(ar[1]);
				var stringy = dice.stringify(res);
				expect(stringy).toEqual(ar[2]);
			});
		});

		it("evaluates simple statistics with no extra params", function(){
			var results = dice.statistics("1d1");
			expect(results.min).toEqual(1);
			expect(results.max).toEqual(1);
			expect(results.mean).toEqual(1);
		});

		it("evaluates simple statistics with only samples", function(){
			var results = dice.statistics("1d1", 10);
			expect(results.min).toEqual(1);
			expect(results.results.length).toEqual(10);
			expect(results.max).toEqual(1);
			expect(results.mean).toEqual(1);
		});

		it("evaluates simple statistics with only scope", function(){
			var results = dice.statistics("1d[one]", {'one': 1});
			expect(results.min).toEqual(1);
			expect(results.max).toEqual(1);
			expect(results.mean).toEqual(1);
		});

		it("evaluates simple statistics with both scope and samples", function(){
			var results = dice.statistics("[one]d1", {'one': 1}, 50);
			expect(results.min).toEqual(1);
			expect(results.results.length).toEqual(50);
			expect(results.max).toEqual(1);
			expect(results.mean).toEqual(1);
		});

	});
});

<|endoftext|>