<commit_before>/**
 * @author dmarcos / https://github.com/dmarcos
 * @author mrdoob / http://mrdoob.com
 */

THREE.VRControls = function ( object, onError ) {

	var scope = this;

	var vrDisplay, vrDisplays;

	var standingMatrix = new THREE.Matrix4();

	var frameData = null;

	if ( 'VRFrameData' in window ) {

		frameData = new VRFrameData();

	}

	function gotVRDisplays( displays ) {

		vrDisplays = displays;

		if ( displays.length > 0 ) {

			vrDisplay = displays[ 0 ];

		} else {

			if ( onError ) onError( 'VR input not available.' );

		}

	}

	if ( navigator.getVRDisplays ) {

		navigator.getVRDisplays().then( gotVRDisplays ).catch ( function () {

			console.warn( 'THREE.VRControls: Unable to get VR Displays' );

		} );

	}

	// the Rift SDK returns the position in meters
	// this scale factor allows the user to define how meters
	// are converted to scene units.

	this.scale = 1;

	// If true will use "standing space" coordinate system where y=0 is the
	// floor and x=0, z=0 is the center of the room.
	this.standing = false;

	// Distance from the users eyes to the floor in meters. Used when
	// standing=true but the VRDisplay doesn't provide stageParameters.
	this.userHeight = 1.6;

	this.getVRDisplay = function () {

		return vrDisplay;

	};

	this.setVRDisplay = function ( value ) {

		vrDisplay = value;

	};

	this.getVRDisplays = function () {

		console.warn( 'THREE.VRControls: getVRDisplays() is being deprecated.' );
		return vrDisplays;

	};

	this.getStandingMatrix = function () {

		return standingMatrix;

	};

	this.update = function () {

		if ( vrDisplay ) {

			var pose;

			if ( vrDisplay.getFrameData ) {

				vrDisplay.getFrameData( frameData );
				pose = frameData.pose;

			} else if ( vrDisplay.getPose ) {

				pose = vrDisplay.getPose();

			}

			if ( pose.orientation !== null ) {

				object.quaternion.fromArray( pose.orientation );

			}

			if ( pose.position !== null ) {

				object.position.fromArray( pose.position );

			} else {

				object.position.set( 0, 0, 0 );

			}

			if ( this.standing ) {

				if ( vrDisplay.stageParameters ) {

					object.updateMatrix();

					standingMatrix.fromArray( vrDisplay.stageParameters.sittingToStandingTransform );
					object.applyMatrix( standingMatrix );

				} else {

					object.position.setY( object.position.y + this.userHeight );

				}

			}

			object.position.multiplyScalar( scope.scale );

		}

	};

	this.resetPose = function () {

		if ( vrDisplay ) {

			vrDisplay.resetPose();

		}

	};

	this.resetSensor = function () {

		console.warn( 'THREE.VRControls: .resetSensor() is now .resetPose().' );
		this.resetPose();

	};

	this.zeroSensor = function () {

		console.warn( 'THREE.VRControls: .zeroSensor() is now .resetPose().' );
		this.resetPose();

	};

	this.dispose = function () {

		vrDisplay = null;

	};

};
<commit_msg>add window to VRFrameData (#2477)<commit_after>/**
 * @author dmarcos / https://github.com/dmarcos
 * @author mrdoob / http://mrdoob.com
 */

THREE.VRControls = function ( object, onError ) {

	var scope = this;

	var vrDisplay, vrDisplays;

	var standingMatrix = new THREE.Matrix4();

	var frameData = null;

	if ( 'VRFrameData' in window ) {

		frameData = new window.VRFrameData();

	}

	function gotVRDisplays( displays ) {

		vrDisplays = displays;

		if ( displays.length > 0 ) {

			vrDisplay = displays[ 0 ];

		} else {

			if ( onError ) onError( 'VR input not available.' );

		}

	}

	if ( navigator.getVRDisplays ) {

		navigator.getVRDisplays().then( gotVRDisplays ).catch ( function () {

			console.warn( 'THREE.VRControls: Unable to get VR Displays' );

		} );

	}

	// the Rift SDK returns the position in meters
	// this scale factor allows the user to define how meters
	// are converted to scene units.

	this.scale = 1;

	// If true will use "standing space" coordinate system where y=0 is the
	// floor and x=0, z=0 is the center of the room.
	this.standing = false;

	// Distance from the users eyes to the floor in meters. Used when
	// standing=true but the VRDisplay doesn't provide stageParameters.
	this.userHeight = 1.6;

	this.getVRDisplay = function () {

		return vrDisplay;

	};

	this.setVRDisplay = function ( value ) {

		vrDisplay = value;

	};

	this.getVRDisplays = function () {

		console.warn( 'THREE.VRControls: getVRDisplays() is being deprecated.' );
		return vrDisplays;

	};

	this.getStandingMatrix = function () {

		return standingMatrix;

	};

	this.update = function () {

		if ( vrDisplay ) {

			var pose;

			if ( vrDisplay.getFrameData ) {

				vrDisplay.getFrameData( frameData );
				pose = frameData.pose;

			} else if ( vrDisplay.getPose ) {

				pose = vrDisplay.getPose();

			}

			if ( pose.orientation !== null ) {

				object.quaternion.fromArray( pose.orientation );

			}

			if ( pose.position !== null ) {

				object.position.fromArray( pose.position );

			} else {

				object.position.set( 0, 0, 0 );

			}

			if ( this.standing ) {

				if ( vrDisplay.stageParameters ) {

					object.updateMatrix();

					standingMatrix.fromArray( vrDisplay.stageParameters.sittingToStandingTransform );
					object.applyMatrix( standingMatrix );

				} else {

					object.position.setY( object.position.y + this.userHeight );

				}

			}

			object.position.multiplyScalar( scope.scale );

		}

	};

	this.resetPose = function () {

		if ( vrDisplay ) {

			vrDisplay.resetPose();

		}

	};

	this.resetSensor = function () {

		console.warn( 'THREE.VRControls: .resetSensor() is now .resetPose().' );
		this.resetPose();

	};

	this.zeroSensor = function () {

		console.warn( 'THREE.VRControls: .zeroSensor() is now .resetPose().' );
		this.resetPose();

	};

	this.dispose = function () {

		vrDisplay = null;

	};

};
<|endoftext|>


<commit_before>// User Manager: Clients view

'use strict';

var _            = require('mano').i18n.bind('View: Client');

exports._parent = require('./manager');

exports['manager-account-clients'] = { class: { active: true } };

exports['manager-account-content'] = function () {
	var clients = this.user.managedUsers;

	section(a({ href: url('new-client'), class: 'button-main' },
				_("Add client"))
		);

	insert(_if(clients._size, function () {
		return section({ class: 'submitted-main table-responsive-container' },
			table(
				{ class: 'submitted-user-data-table' },
				thead(tr(
					th(_("Client")),
					th(_('Linked entities')),
					th(_('Services')),
					th(_('Email')),
					th()
				)),
				tbody(
					clients,
					function (client) {
						var bpSet = client.initialBusinessProcesses.and(this.user.managedBusinessProcesses)
									.filterByKey('businessName');
						return tr(
							td(client._fullName),

							td(ul(bpSet,
								function (bp) {
									return [bp._businessName, " (", bp.label, ")"];
								})),

							td(bpSet.map(function (bp) { return bp.constructor; })._size),

							td(span(client._email),
								_if(client.roles._has('user'), span({ class: 'fa fa-check' }))),

							td({ class: 'actions' },
								_if(eq(client._manager, this.user),
									[
										a({ href:  url('clients', client.__id__) },
											span({ class: 'fa fa-edit' })),
										_if(eq(client.initialBusinessProcesses
											.filterByKey('isSubmitted', true)._size, 0),
											postButton({ buttonClass: 'actions-delete',
												action: url('clients', client.__id__, 'delete'),
												confirm: _("Are you sure?"), value: span({ class: 'fa fa-trash-o' }) })
											)
									]
									)
								)
						);
					},
					this
				)
			));
	}.bind(this),
		p(_('You have no clients yet.'))));
};
<commit_msg>Improve spacing<commit_after>// User Manager: Clients view

'use strict';

var _            = require('mano').i18n.bind('View: Client');

exports._parent = require('./manager');

exports['manager-account-clients'] = { class: { active: true } };

exports['manager-account-content'] = function () {
	var clients = this.user.managedUsers;

	section(a({ href: url('new-client'), class: 'button-main' },
				_("Add client"))
		);

	insert(_if(clients._size, function () {
		return section({ class: 'submitted-main table-responsive-container' },
			table(
				{ class: 'submitted-user-data-table' },
				thead(tr(
					th(_("Client")),
					th(_('Linked entities')),
					th(_('Services')),
					th(_('Email')),
					th()
				)),
				tbody(
					clients,
					function (client) {
						var bpSet = client.initialBusinessProcesses.and(this.user.managedBusinessProcesses)
									.filterByKey('businessName');
						return tr(
							td(client._fullName),

							td(ul(bpSet,
								function (bp) {
									return [bp._businessName, " (", bp.label, ")"];
								})),

							td(bpSet.map(function (bp) { return bp.constructor; })._size),

							td(span(client._email),
								_if(client.roles._has('user'), [" ", span({ class: 'fa fa-check' })])),

							td({ class: 'actions' },
								_if(eq(client._manager, this.user),
									[
										a({ href:  url('clients', client.__id__) },
											span({ class: 'fa fa-edit' })),
										_if(eq(client.initialBusinessProcesses
											.filterByKey('isSubmitted', true)._size, 0),
											postButton({ buttonClass: 'actions-delete',
												action: url('clients', client.__id__, 'delete'),
												confirm: _("Are you sure?"), value: span({ class: 'fa fa-trash-o' }) })
											)
									]
									)
								)
						);
					},
					this
				)
			));
	}.bind(this),
		p(_('You have no clients yet.'))));
};
<|endoftext|>


<commit_before>// Karma configuration
// Generated on Thu Nov 24 2016 13:10:00 GMT-0800 (PST)

module.exports = function (config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: "",

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ["mocha", "chai", "fixture"],

    // list of files / patterns to load in the browser
    files: [
      "https://code.jquery.com/jquery-1.12.4.js",
      "https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js",
      "node_modules/clipboard/dist/clipboard.js",
      "add-heading-anchors.js",
      "test/**/*.js"
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ["progress"],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values:
    // config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ["Chrome", "Firefox"],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  });
};
<commit_msg>not really sure if this is needed, but it says it is...<commit_after>// Karma configuration
// Generated on Thu Nov 24 2016 13:10:00 GMT-0800 (PST)

module.exports = function (config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: "",

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ["mocha", "chai", "fixture"],

    // list of files / patterns to load in the browser
    files: [
      "https://code.jquery.com/jquery-1.12.4.js",
      "https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js",
      "node_modules/clipboard/dist/clipboard.js",
      "add-heading-anchors.js",
      "test/**/*.js",
      "fixtures/*/*.html",
    ],

    // list of files to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      '**/*.html'   : ['html2js'],
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ["progress"],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values:
    // config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ["Chrome", "Firefox"],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  });
};
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var package = require('../package');
var emitter = require('hyper-emitter');
var utils = require('../lib/utils');
var $watchPath = utils.$watchPath;
var $safeApply = utils.$safeApply;
var merge = utils.merge;
var shallowMerge = utils.shallowMerge;
var loading = utils.loading;
var loaded = utils.loaded;
var each = require('each');
var createLink = require('./hyper-link').create;
var qs = require('querystring');

/**
 * hyperForm
 */

package.directive('hyperForm', [
  '$location',
  function($location) {
    return {
      scope: true,
      require: 'form',
      link: function($scope, elem, attrs, form) {
        loading(elem);

        var handle = getHandleFunction($scope, attrs);

        elem.bind('submit', function() {
          if ($scope.submit) $scope.submit();
        });

        $watchPath.call($scope, attrs.hyperForm, function(err, value) {
          // TODO come up with an error strategy
          if (err) return console.error(err.stack || err);

          if (value && value.action) return setup(value);
          return teardown(value);
        });

        function setup(config) {
          if (!canUpdate()) return;

          unwatch();
          $scope.values = {};
          $scope.inputs = getInputs(config.input, $scope);

          $scope.set = initSet($scope.inputs);
          $scope.submit = initSubmit(config.method, config.action);
          $scope.reset = initReset();

          return loaded(elem);
        }

        function teardown() {
          unwatch();
          delete $scope.values;
          delete $scope.inputs;

          delete $scope.set;
          delete $scope.submit;
          delete $scope.reset;

          return loading(elem);
        }

        function unwatch(inputs) {
          if (!inputs) return;
          each(inputs, function(input) {
            input.$unwatch();
          });
        }

        function getInputs(inputs, $scope) {
          var ins = {};
          var old = $scope.inputs;
          var i = 0;

          var setValue = initSetValue(inputs);

          each(inputs, function(name, conf) {
            var value = conf.value;

            if (conf.type === 'hidden') return setValue(name, value);

            // We have to clone this object so hyper-path doesn't watch for changes on the model
            var input = shallowMerge({
              $model: value,
              $orig: value, // TODO do we need to clone this so it doesn't change on us?
              name: name
            }, conf);

            // Allow addressing the input from either the index or the name
            ins[i++] = input;
            ins[name] = input;

            input.$unwatch = $scope.$watch(function () {
              return input.$model;
            }, function() {
              setValue(name, input.$model);
            });
          });

          if (i === 0) return [];

          ins.length = i;
          return merge(old, ins);
        }

        function initSetValue (inputs) {
          return function setValue(name, value) {
            $scope.values[name] = value;
            if (inputs[name].$orig !== value) form.$setDirty();
          };
        }

        function canUpdate() {
          // TODO allow dirty updating config via attr
          return !form.$dirty;
        }

        function initSet(inputs) {
          return function set(name, value) {
            if (inputs[name]) inputs[name].$model = value;
          };
        }

        function initSubmit(method, action) {
          method = (method || 'GET').toUpperCase();
          return function submit() {
            // TODO if the method is idempotent and the form is pristine don't submit
            // TODO verify the form is valid
            $scope.hyperFormLoading = true;
            attrs.hyperAction && method === 'GET'
              ? followLink(action, $scope.values, onfinish)
              : emitter.submit(method, action, $scope.values, onfinish);
          };
        }

        function initReset() {
          return function reset() {
            // TODO
          };
        }

        function onfinish(err, res) {
          $safeApply.call($scope, function() {
            delete $scope.hyperFormLoading;
            handle(err, res);
            if (err) $scope.hyperFormError = err.error;
            // TODO what are other status that we want to expose?
            $setPristine(form, elem);
          });
        }

        function followLink(action) {
          // TODO check if action has a '?'
          var url = action + '?' + qs.stringify($scope.values);
          var $tmp = $scope.$new();
          $tmp.query = {query: {href: url}};
          var res = createLink(attrs.hyperAction, $tmp);
          $tmp.$destroy();
          if (!res.loaded) return;
          $safeApply.call($scope, function() {
            $location.path(res.href);
          });
        }

        function getHandleFunction() {
          return attrs.hyperHandle
            ? $scope.$eval(attrs.hyperHandle)
            : noop;
        }
      }
    };
  }
]);

function $setPristine(form, elem) {
  if (form.$setPristine) return form.$setPristine();
  form.$pristine = true;
  form.$dirty = false;
  elem.addClass('ng-pristine');
  elem.removeClass('ng-dirty');
  each(form, function(key, input) {
    if (!input || key.charAt(0) === '$') return;
    if (input.$pristine) input.$pristine = true;
    if (input.$dirty) input.$dirty = false;
  });
}

function noop() {}
<commit_msg>refactor<commit_after>/**
 * Module dependencies
 */

var package = require('../package');
var emitter = require('hyper-emitter');
var utils = require('../lib/utils');
var $watchPath = utils.$watchPath;
var $safeApply = utils.$safeApply;
var merge = utils.merge;
var shallowMerge = utils.shallowMerge;
var loading = utils.loading;
var loaded = utils.loaded;
var each = require('each');
var createLink = require('./hyper-link').create;
var qs = require('querystring');

/**
 * hyperForm
 */

package.directive('hyperForm', [
  '$location',
  function($location) {
    return {
      scope: true,
      require: 'form',
      link: function($scope, elem, attrs, form) {
        loading(elem);

        var handle = getHandleFunction($scope, attrs);

        elem.bind('submit', function() {
          if ($scope.submit) $scope.submit();
        });

        $watchPath.call($scope, attrs.hyperForm, function(err, value) {
          // TODO come up with an error strategy
          if (err) return console.error(err.stack || err);

          if (value && value.action) return setup(value);
          return teardown(value);
        });

        function setup(config) {
          if (!canUpdate()) return;

          unwatch();
          $scope.values = {};
          $scope.inputs = getInputs(config.input, $scope);

          $scope.set = initSet($scope.inputs);
          $scope.submit = initSubmit(config.method, config.action);
          $scope.reset = initReset();

          return loaded(elem);
        }

        function teardown() {
          unwatch();
          delete $scope.values;
          delete $scope.inputs;

          delete $scope.set;
          delete $scope.submit;
          delete $scope.reset;

          return loading(elem);
        }

        function getInputs(inputs, $scope) {
          var ins = {};
          var old = $scope.inputs;
          var i = 0;

          var setValue = initSetValue(inputs);

          each(inputs, function(name, conf) {
            var value = conf.value;

            if (conf.type === 'hidden') return setValue(name, value);

            // We have to clone this object so hyper-path doesn't watch for changes on the model
            var input = shallowMerge({
              $model: value,
              $orig: value, // TODO do we need to clone this so it doesn't change on us?
              name: name
            }, conf);

            // Allow addressing the input from either the index or the name
            ins[i++] = input;
            ins[name] = input;

            input.$unwatch = $scope.$watch(function () {
              return input.$model;
            }, function() {
              setValue(name, input.$model);
            });
          });

          if (i === 0) return [];

          ins.length = i;
          return merge(old, ins);
        }

        function initSetValue (inputs) {
          return function setValue(name, value) {
            $scope.values[name] = value;
            if (inputs[name].$orig !== value) form.$setDirty();
          };
        }

        function canUpdate() {
          // TODO allow dirty updating config via attr
          return !form.$dirty;
        }

        function initSet(inputs) {
          return function set(name, value) {
            if (inputs[name]) inputs[name].$model = value;
          };
        }

        function initSubmit(method, action) {
          method = (method || 'GET').toUpperCase();
          return function submit() {
            // TODO if the method is idempotent and the form is pristine don't submit
            // TODO verify the form is valid
            $scope.hyperFormLoading = true;
            attrs.hyperAction && method === 'GET'
              ? followLink(action, $scope.values, attrs.hyperAction)
              : emitter.submit(method, action, $scope.values, onfinish);
          };
        }

        function initReset() {
          return function reset() {
            // TODO
          };
        }

        function onfinish(err, res) {
          $safeApply.call($scope, function() {
            delete $scope.hyperFormLoading;
            handle(err, res);
            if (err) $scope.hyperFormError = err.error;
            // TODO what are other status that we want to expose?
            $setPristine(form, elem);
          });
        }

        function followLink(action, values, hyperAction) {
          // TODO check if action has a '?'
          var url = action + '?' + qs.stringify(values);
          var $tmp = $scope.$new();
          $tmp.query = {query: {href: url}};
          var res = createLink(hyperAction, $tmp);
          $tmp.$destroy();
          if (!res.loaded) return;
          $safeApply.call($scope, function() {
            $location.path(res.href);
          });
        }
      }
    };
  }
]);

function $setPristine(form, elem) {
  if (form.$setPristine) return form.$setPristine();
  form.$pristine = true;
  form.$dirty = false;
  elem.addClass('ng-pristine');
  elem.removeClass('ng-dirty');
  each(form, function(key, input) {
    if (!input || key.charAt(0) === '$') return;
    if (input.$pristine) input.$pristine = true;
    if (input.$dirty) input.$dirty = false;
  });
}

function getHandleFunction($scope, attrs) {
  return attrs.hyperHandle
    ? $scope.$eval(attrs.hyperHandle)
    : noop;
}

function unwatch(inputs) {
  if (!inputs) return;
    each(inputs, function(input) {
    input.$unwatch();
  });
}

function noop() {}
<|endoftext|>


<commit_before>///**
// * Created by Jiawei.Lv on 6/8/2015.
// */
var colorGrid = angular.module('colorGrid', []);

colorGrid.controller('colorGridController', function ($scope) {
    var rowIds = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    rowIds = rowIds.map(function (id) {
       return 'row-' + id;
    });

    $scope.rowIds = rowIds;
    $scope.color = {
        hue: 100,
        opac: 1
    };

    $scope.backgroundColorStrings = buildGrid($scope.color.hue, $scope.color.opac);

    $scope.calcStyle = function (hue, opac) {
        $scope.backgroundColorStrings = buildGrid(hue, opac);
    };
});

function hueToRgb(m1, m2, h) {
    if(h < 0) {
        h = h + 1;
    }
    else if (h > 1) {
        h = h - 1;
    }

    if (h * 6 < 1) {
        return m1 + (m2 - m1) * h * 6;
    }
    else if (h * 2 < 1) {
        return m2;
    }
    else if(h * 3 < 2) {
        return m1 + (m2 - m1) * (2/3 - h) * 6;
    }
    else {
        return m1;
    }
}

function hslToRgb(h, s, l) {
    h /= 360;
    s /= 100;
    l /= 100;
    var m2 = (l <= 0.5) ? l * (s + 1) : l + s - (l * s),
        m1 = l * 2 - m2,
        r = parseInt(hueToRgb(m1, m2, h + 1/3) * 255),
        g = parseInt(hueToRgb(m1, m2, h) * 255),
        b = parseInt(hueToRgb(m1, m2, h - 1/3) * 255);
    return [r, g, b];
}

function decimalToHex(decimal) {
    var hex = decimal.toString(16);
    return hex.length === 1 ? '0' + hex : hex;
}

function rgbToHex(r, g, b) {
    return '#' + decimalToHex(r) + decimalToHex(r) + decimalToHex(r);
}

function rgbToHex2(r,g,b) {
    return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString().slice(1);
}

// RGBa to HEX: color = color * alpha + bg * (1 - alpha);

function buildGrid(hue, opac) {
    var backgroundColorStrings = [];
    for (var i = 0; i < 10; i++) {
        var tempRow = [];
        for (var j = 0; j < 10; j++) {
            var hslaString = "hsla(" + hue + ", " + ((i * 10) + 5) + "%, " + ((j * 10) + 5) + "%, " + opac + ")";
            var rgb = hslToRgb(hue, (i * 10) + 5, (j * 10) + 5);
            var rgbaString = "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "," + opac + ")";
            var hexString = rgbToHex(rgb[0], rgb[1], rgb[2]);
            tempRow.push([hslaString, rgb, rgbaString, hexString]);
        };
        backgroundColorStrings.push(tempRow);
    };
    return backgroundColorStrings;
}<commit_msg>style fix<commit_after>///**
// * Created by Jiawei.Lv on 6/8/2015.
// */
var colorGrid = angular.module('colorGrid', []);

colorGrid.controller('colorGridController', function ($scope) {
    var rowIds = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    rowIds = rowIds.map(function (id) {
       return 'row-' + id;
    });

    $scope.rowIds = rowIds;
    $scope.color = {
        hue: 100,
        opac: 1
    };

    $scope.backgroundColorStrings = buildGrid($scope.color.hue, $scope.color.opac);

    $scope.calcStyle = function (hue, opac) {
        $scope.backgroundColorStrings = buildGrid(hue, opac);
        console.log($scope.color.hue);
    };
});

function hueToRgb(m1, m2, h) {
    if(h < 0) {
        h = h + 1;
    }
    else if (h > 1) {
        h = h - 1;
    }

    if (h * 6 < 1) {
        return m1 + (m2 - m1) * h * 6;
    }
    else if (h * 2 < 1) {
        return m2;
    }
    else if(h * 3 < 2) {
        return m1 + (m2 - m1) * (2/3 - h) * 6;
    }
    else {
        return m1;
    }
}

function hslToRgb(h, s, l) {
    h /= 360;
    s /= 100;
    l /= 100;
    var m2 = (l <= 0.5) ? l * (s + 1) : l + s - (l * s),
        m1 = l * 2 - m2,
        r = parseInt(hueToRgb(m1, m2, h + 1/3) * 255),
        g = parseInt(hueToRgb(m1, m2, h) * 255),
        b = parseInt(hueToRgb(m1, m2, h - 1/3) * 255);
    return [r, g, b];
}

function decimalToHex(decimal) {
    var hex = decimal.toString(16);
    return hex.length === 1 ? '0' + hex : hex;
}

function rgbToHex(r, g, b) {
    return '#' + decimalToHex(r) + decimalToHex(r) + decimalToHex(r);
}

function rgbToHex2(r,g,b) {
    return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString().slice(1);
}

// RGBa to HEX: color = color * alpha + bg * (1 - alpha);

function buildGrid(hue, opac) {
    var backgroundColorStrings = [];
    for (var i = 0; i < 10; i++) {
        var tempRow = [];
        for (var j = 0; j < 10; j++) {
            var hslaString = "hsla(" + hue + ", " + ((i * 10) + 5) + "%, " + ((j * 10) + 5) + "%, " + opac + ")";
            var rgb = hslToRgb(hue, (i * 10) + 5, (j * 10) + 5);
            var rgbaString = "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "," + opac + ")";
            var hexString = rgbToHex(rgb[0], rgb[1], rgb[2]);
            tempRow.push([hslaString, rgb, rgbaString, hexString]);
        };
        backgroundColorStrings.push(tempRow);
    };
    return backgroundColorStrings;
}<|endoftext|>


<commit_before>/*
 * Waltz - Enterprise Architecture
 * Copyright (C) 2016, 2017 Waltz open source project
 * See README.md for more information
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

import _ from "lodash";

import template from "./flow-diagrams-panel-view.html";

import {initialiseData} from "../../../../common/index";
import {CORE_API} from "../../../../common/services/core-api-utils";
import {mkSelectionOptions} from "../../../../common/selector-utils";
import {dyamicSectionNavigationDefaultOffset} from "../../../../dynamic-section/components/dynamic-section-navigation/dynamic-section-navigation";
import {pageHeaderDefaultOffset} from "../../../../widgets/page-header/page-header";

const bindings = {
    parentEntityRef: '<',
    onEditDiagram: '<',
    onDismissDiagram: '<'
};

const initialState = {
    contextPopup: {
        entityReference: null,
        entity: null,
        styling: {}
    },
    visibility: {
        layers: {},
        menuPopup: false,
        contextPopup: false
    }
};

function determinePopupTopPosition(evt, scrollOffset, elementHeight) {
    // get the width and height of the element
    const navOffset = 60; // the nav bar margin (navbar.html)
    const pageHeaderOffset = scrollOffset > pageHeaderDefaultOffset ? 40 : 0;  // refer to page-header.js
    const dynamicNavOffset = scrollOffset > dyamicSectionNavigationDefaultOffset ? 40 : 0; // refer to dynamic-section-navigation

    const halfHeight = elementHeight / 2;

    // evt.clientY + scrollOffset is for IE support to get the same and pageY accounting for the scroll
    const pageY = (evt.pageY || evt.clientY + scrollOffset);
    const shiftedTop = pageY - halfHeight > scrollOffset ? pageY - halfHeight : scrollOffset;
    return shiftedTop + navOffset + pageHeaderOffset + dynamicNavOffset
}

function determinePopupPosition(evt, $window, $element) {
    //get the width and height of the element
    const elementWidth = _.get($element, '[0].parentElement.clientWidth');
    const elementHeight = _.get($element, '[0].parentElement.clientHeight');
    const scrollOffset = $window.pageYOffset;
    const halfWidth = elementWidth / 2;

    const top = determinePopupTopPosition(evt, scrollOffset, elementHeight);
    const left = evt.clientX < halfWidth
        ? evt.clientX
        : evt.clientX - halfWidth;

    return {
        top: `${top}px`,
        left: `${left}px`
    };
}

function enrichDiagram(flowDiagram, flowActions = []) {

    return Object.assign(
        {},
        flowDiagram,
        {type: "Flow", icon: "random", actions: flowActions}
    );

}

function controller($element,
                    $q,
                    $window,
                    $timeout,
                    flowDiagramStateService,
                    serviceBroker,
                    notification) {
    const vm = initialiseData(this, initialState);

    const loadVisibility = () =>
        vm.visibility.layers = flowDiagramStateService.getState().visibility.layers;

    const loadFlowDiagram = (force = true, id) => serviceBroker
        .loadViewData(
            CORE_API.FlowDiagramStore.getById,
            [ id ],
            { force })
        .then(r => vm.diagram = r.data);

    const flowActions = [
        {
            name: "Clone",
            icon: "clone",
            execute: (diagram) => {
                const newName = prompt("What should the cloned copy be called ?", `Copy of ${diagram.name}`);
                if (newName == null) {
                    notification.warning("Clone cancelled");
                    return;
                }
                if (_.isEmpty(newName.trim())) {
                    notification.warning("Clone cancelled, no name given");
                    return;
                }
                serviceBroker
                    .execute(CORE_API.FlowDiagramStore.clone, [diagram.id, newName])
                    .then(newId => {
                        notification.success("Diagram cloned");
                        reload(newId.data);
                    })
                    .catch(e => notification.error(`Failed to clone diagram: ${e.data.message}`));

            }}
    ];

    function reload(newId) {
        let id = newId ? newId : vm.parentEntityRef.id;

        return loadFlowDiagram(true, id)
            .then((flowDiagram) => {
                flowDiagramStateService.reset();
                flowDiagramStateService
                    .load(id)
                    .then(() => loadVisibility());
                vm.diagram = enrichDiagram(flowDiagram, flowActions);
                return vm.diagram;
            });
    }

    vm.$onInit = () => {
        reload();
    };

    vm.toggleLayer = (layer) => {
        const currentlyVisible = flowDiagramStateService.getState().visibility.layers[layer];
        const cmd = {
            command: currentlyVisible ? 'HIDE_LAYER' : 'SHOW_LAYER',
            payload: layer
        };
        flowDiagramStateService.processCommands([cmd]);
        loadVisibility();
    };

    const showNodeDetail = (n) => {
        $timeout(() => vm.visibility.contextPopup = false);

        vm.contextPopup.styling = determinePopupPosition(event, $window, $element);

        const nodeRef = n.data;
        if (nodeRef.kind === 'APPLICATION') {
            serviceBroker
                .loadViewData(CORE_API.ApplicationStore.getById, [ nodeRef.id ])
                .then(r => {
                    $timeout(() => {
                        vm.contextPopup.entityReference = nodeRef;
                        vm.contextPopup.entity = r.data;
                        vm.visibility.contextPopup = true;
                    })
                });
        }
    };

    const showFlowBucketDetail = (logicalFlow) => {
        $timeout(() => vm.visibility.contextPopup = false);
        vm.contextPopup.styling = determinePopupPosition(event, $window, $element);

        const state = flowDiagramStateService.getState();
        const physFlowsPath = ['model', 'decorations', logicalFlow.id];
        const physicalFlowIds = _
            .chain(state)
            .get(physFlowsPath)
            .map('data')
            .map('id')
            .value();

        const diagramSelector = mkSelectionOptions(vm.parentEntityRef);

        const flowPromise = serviceBroker
            .loadViewData(
                CORE_API.PhysicalFlowStore.findBySelector,
                [ diagramSelector ])
            .then(r => r.data);

        const specPromise = serviceBroker
            .loadViewData(
                CORE_API.PhysicalSpecificationStore.findBySelector,
                [ diagramSelector ])
            .then(r => r.data);

        $q.all([flowPromise, specPromise])
            .then(([flows, specs]) => {
                const flowsById = _.keyBy(flows, 'id');
                const specsById = _.keyBy(specs, 'id');

                const flowData = _
                    .chain(physicalFlowIds)
                    .map(flowId => {
                        const physicalFlow = flowsById[flowId];
                        const specId = physicalFlow.specificationId;
                        const physicalSpecification = specsById[specId];
                        return {
                            physicalFlow,
                            physicalSpecification
                        };})
                    .orderBy('physicalSpecification.name')
                    .value();

                vm.contextPopup.entityReference = logicalFlow.data;
                vm.contextPopup.entity = {
                    logical: logicalFlow,
                    physical: flowData
                };
                vm.visibility.contextPopup = true;
            });
    };

    vm.clickHandlers = {
        node: showNodeDetail,
        flowBucket: showFlowBucketDetail
    };
}

controller.$inject = [
    '$element',
    '$q',
    '$window',
    '$timeout',
    'FlowDiagramStateService',
    'ServiceBroker',
    'Notification'
];

const component = {
    controller,
    template,
    bindings
};

export default {
    component,
    id: 'waltzFlowDiagramsPanelView'
};
<commit_msg>Update flow-diagrams-panel-view.js<commit_after>/*
 * Waltz - Enterprise Architecture
 * Copyright (C) 2016, 2017 Waltz open source project
 * See README.md for more information
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

import _ from "lodash";

import template from "./flow-diagrams-panel-view.html";

import {initialiseData} from "../../../../common/index";
import {CORE_API} from "../../../../common/services/core-api-utils";
import {mkSelectionOptions} from "../../../../common/selector-utils";
import {dyamicSectionNavigationDefaultOffset} from "../../../../dynamic-section/components/dynamic-section-navigation/dynamic-section-navigation";
import {pageHeaderDefaultOffset} from "../../../../widgets/page-header/page-header";

const bindings = {
    parentEntityRef: '<',
    onEditDiagram: '<',
    onDismissDiagram: '<'
};

const initialState = {
    contextPopup: {
        entityReference: null,
        entity: null,
        styling: {}
    },
    visibility: {
        layers: {},
        menuPopup: false,
        contextPopup: false
    }
};

function determinePopupTopPosition(evt, scrollOffset, elementHeight) {
    // get the width and height of the element
    const navOffset = 60; // the nav bar margin (navbar.html)
    const pageHeaderOffset = scrollOffset > pageHeaderDefaultOffset ? 40 : 0;  // refer to page-header.js
    const dynamicNavOffset = scrollOffset > dyamicSectionNavigationDefaultOffset ? 40 : 0; // refer to dynamic-section-navigation

    const halfHeight = elementHeight / 2;

    // evt.clientY + scrollOffset is for IE support to get the same and pageY accounting for the scroll
    const pageY = (evt.pageY || evt.clientY + scrollOffset);
    const shiftedTop = pageY - halfHeight > scrollOffset ? pageY - halfHeight : scrollOffset;
    return shiftedTop + navOffset + pageHeaderOffset + dynamicNavOffset
}

function determinePopupPosition(evt, $window, $element) {
    //get the width and height of the element
    const elementWidth = _.get($element, '[0].parentElement.clientWidth');
    const elementHeight = _.get($element, '[0].parentElement.clientHeight');
    const scrollOffset = $window.pageYOffset;
    const halfWidth = elementWidth / 2;

    const top = determinePopupTopPosition(evt, scrollOffset, elementHeight);
    const left = evt.clientX < halfWidth
        ? evt.clientX
        : evt.clientX - halfWidth;

    return {
        top: `${top}px`,
        left: `${left}px`
    };
}

function enrichDiagram(flowDiagram, flowActions = []) {

    return Object.assign(
        {},
        flowDiagram,
        {type: "Flow", icon: "random", actions: flowActions}
    );

}

function controller($element,
                    $q,
                    $window,
                    $timeout,
                    flowDiagramStateService,
                    serviceBroker,
                    notification) {
    const vm = initialiseData(this, initialState);

    const loadVisibility = () =>
        vm.visibility.layers = flowDiagramStateService.getState().visibility.layers;

    const loadFlowDiagram = (force = true, id) => serviceBroker
        .loadViewData(
            CORE_API.FlowDiagramStore.getById,
            [ id ],
            { force })
        .then(r => vm.diagram = r.data);

    const flowActions = [
        {
            name: "Clone",
            icon: "clone",
            execute: (diagram) => {
                const newName = prompt("What should the cloned copy be called?", `Copy of ${diagram.name}`);
                if (newName == null) {
                    notification.warning("Clone cancelled");
                    return;
                }
                if (_.isEmpty(newName.trim())) {
                    notification.warning("Clone cancelled, no name given");
                    return;
                }
                serviceBroker
                    .execute(CORE_API.FlowDiagramStore.clone, [diagram.id, newName])
                    .then(newId => {
                        notification.success("Diagram cloned");
                        reload(newId.data);
                    })
                    .catch(e => notification.error(`Failed to clone diagram: ${e.data.message}`));

            }}
    ];

    function reload(newId) {
        let id = newId ? newId : vm.parentEntityRef.id;

        return loadFlowDiagram(true, id)
            .then((flowDiagram) => {
                flowDiagramStateService.reset();
                flowDiagramStateService
                    .load(id)
                    .then(() => loadVisibility());
                vm.diagram = enrichDiagram(flowDiagram, flowActions);
                return vm.diagram;
            });
    }

    vm.$onInit = () => {
        reload();
    };

    vm.toggleLayer = (layer) => {
        const currentlyVisible = flowDiagramStateService.getState().visibility.layers[layer];
        const cmd = {
            command: currentlyVisible ? 'HIDE_LAYER' : 'SHOW_LAYER',
            payload: layer
        };
        flowDiagramStateService.processCommands([cmd]);
        loadVisibility();
    };

    const showNodeDetail = (n) => {
        $timeout(() => vm.visibility.contextPopup = false);

        vm.contextPopup.styling = determinePopupPosition(event, $window, $element);

        const nodeRef = n.data;
        if (nodeRef.kind === 'APPLICATION') {
            serviceBroker
                .loadViewData(CORE_API.ApplicationStore.getById, [ nodeRef.id ])
                .then(r => {
                    $timeout(() => {
                        vm.contextPopup.entityReference = nodeRef;
                        vm.contextPopup.entity = r.data;
                        vm.visibility.contextPopup = true;
                    })
                });
        }
    };

    const showFlowBucketDetail = (logicalFlow) => {
        $timeout(() => vm.visibility.contextPopup = false);
        vm.contextPopup.styling = determinePopupPosition(event, $window, $element);

        const state = flowDiagramStateService.getState();
        const physFlowsPath = ['model', 'decorations', logicalFlow.id];
        const physicalFlowIds = _
            .chain(state)
            .get(physFlowsPath)
            .map('data')
            .map('id')
            .value();

        const diagramSelector = mkSelectionOptions(vm.parentEntityRef);

        const flowPromise = serviceBroker
            .loadViewData(
                CORE_API.PhysicalFlowStore.findBySelector,
                [ diagramSelector ])
            .then(r => r.data);

        const specPromise = serviceBroker
            .loadViewData(
                CORE_API.PhysicalSpecificationStore.findBySelector,
                [ diagramSelector ])
            .then(r => r.data);

        $q.all([flowPromise, specPromise])
            .then(([flows, specs]) => {
                const flowsById = _.keyBy(flows, 'id');
                const specsById = _.keyBy(specs, 'id');

                const flowData = _
                    .chain(physicalFlowIds)
                    .map(flowId => {
                        const physicalFlow = flowsById[flowId];
                        const specId = physicalFlow.specificationId;
                        const physicalSpecification = specsById[specId];
                        return {
                            physicalFlow,
                            physicalSpecification
                        };})
                    .orderBy('physicalSpecification.name')
                    .value();

                vm.contextPopup.entityReference = logicalFlow.data;
                vm.contextPopup.entity = {
                    logical: logicalFlow,
                    physical: flowData
                };
                vm.visibility.contextPopup = true;
            });
    };

    vm.clickHandlers = {
        node: showNodeDetail,
        flowBucket: showFlowBucketDetail
    };
}

controller.$inject = [
    '$element',
    '$q',
    '$window',
    '$timeout',
    'FlowDiagramStateService',
    'ServiceBroker',
    'Notification'
];

const component = {
    controller,
    template,
    bindings
};

export default {
    component,
    id: 'waltzFlowDiagramsPanelView'
};
<|endoftext|>


<commit_before>'use strict';

const co = require('bluebird-co').co;

module.exports.up = co.wrap(function* (N) {
  let usergroupStore = N.settings.getStore('usergroup');

  // add usergroup settings for admin

  let adminGroup = yield N.models.users.UserGroup.findOne({ short_name: 'administrators' });

  yield usergroupStore.set({
    forum_can_reply: { value: true },
    forum_can_start_topics: { value: true },
    forum_can_close_topic: { value: true },
    forum_mod_can_pin_topic: { value: true },
    forum_mod_can_edit_posts: { value: true },
    forum_mod_can_delete_topics: { value: true },
    forum_mod_can_edit_titles: { value: true },
    forum_mod_can_close_topic: { value: true },
    forum_mod_can_hard_delete_topics: { value: true },
    forum_mod_can_see_hard_deleted_topics: { value: true },
    forum_mod_can_add_infractions: { value: true }
  }, { usergroup_id: adminGroup._id });

  // add usergroup settings for member

  let memberGroup = yield N.models.users.UserGroup.findOne({ short_name: 'members' });

  yield usergroupStore.set({
    forum_can_reply: { value: true },
    forum_can_start_topics: { value: true }
  }, { usergroup_id: memberGroup._id });

  // add usergroup settings for violators
  //
  // note: it is a modifier group added to users in addition to their
  //       existing usergroups, thus we should turn "force" flag on

  let violatorsGroup = yield N.models.users.UserGroup.findOne({ short_name: 'violators' });

  yield usergroupStore.set({
    forum_can_reply: { value: false, force: true },
    forum_can_start_topics: { value: false, force: true },
    forum_edit_max_time: { value: 0, force: true },
    forum_can_close_topic: { value: false, force: true }
  }, { usergroup_id: violatorsGroup._id });

  // add usergroup settings for banned

  let bannedGroup = yield N.models.users.UserGroup.findOne({ short_name: 'banned' });

  yield usergroupStore.set({
    forum_edit_max_time: { value: 0 }
  }, { usergroup_id: bannedGroup._id });

  // Recalculate store settings of all groups.
  yield usergroupStore.updateInherited();
});
<commit_msg>Change inherited settings in usergroup store<commit_after>'use strict';

const co = require('bluebird-co').co;

module.exports.up = co.wrap(function* (N) {
  let usergroupStore = N.settings.getStore('usergroup');

  // add usergroup settings for admin

  let adminGroup = yield N.models.users.UserGroup.findOne({ short_name: 'administrators' });

  yield usergroupStore.set({
    forum_can_reply: { value: true },
    forum_can_start_topics: { value: true },
    forum_can_close_topic: { value: true },
    forum_mod_can_pin_topic: { value: true },
    forum_mod_can_edit_posts: { value: true },
    forum_mod_can_delete_topics: { value: true },
    forum_mod_can_edit_titles: { value: true },
    forum_mod_can_close_topic: { value: true },
    forum_mod_can_hard_delete_topics: { value: true },
    forum_mod_can_see_hard_deleted_topics: { value: true },
    forum_mod_can_add_infractions: { value: true }
  }, { usergroup_id: adminGroup._id });

  // add usergroup settings for member

  let memberGroup = yield N.models.users.UserGroup.findOne({ short_name: 'members' });

  yield usergroupStore.set({
    forum_can_reply: { value: true },
    forum_can_start_topics: { value: true }
  }, { usergroup_id: memberGroup._id });

  // add usergroup settings for violators
  //
  // note: it is a modifier group added to users in addition to their
  //       existing usergroups, thus we should turn "force" flag on

  let violatorsGroup = yield N.models.users.UserGroup.findOne({ short_name: 'violators' });

  yield usergroupStore.set({
    forum_can_reply: { value: false, force: true },
    forum_can_start_topics: { value: false, force: true },
    forum_edit_max_time: { value: 0, force: true },
    forum_can_close_topic: { value: false, force: true }
  }, { usergroup_id: violatorsGroup._id });

  // add usergroup settings for banned

  let bannedGroup = yield N.models.users.UserGroup.findOne({ short_name: 'banned' });

  yield usergroupStore.set({
    forum_edit_max_time: { value: 0 }
  }, { usergroup_id: bannedGroup._id });
});
<|endoftext|>


<commit_before>const debug = require('../debug').sub('voting', 'condorcets')
const EE    = require('events').EventEmitter

const ndarray = require('ndarray')
ndarray.zeros = require('zeros')
ndarray.show  = require('ndarray-show')
ndarray.ops   = require('ndarray-ops')

function baseMatrix(movies) {
	return ndarray.zeros([ movies.length, movies.length ])
}

module.exports = function(data) {
	const voting = new EE

	var titles

	function updateTitles() {
		titles = data.movies.map(function(movie) {
			return movie.name.replace(/a|an|and|the|\s+/gi, '').replace(/[^A-Z:]/g, '')
		})

		titles.maxLength = Math.max.apply(Math, [0].concat(titles.map(function(title) {
			return title.length
		})))
	}
	updateTitles()

	function renderMatrix(matrix, numbers) {
		if(titles.length == 0)
			return ''

		var res = new Array(titles.maxLength + 2).join(' ') + titles.join(' ')
		for(var y = 0; y < matrix.shape[1]; y++) {
			res += '\n' + titles[y] + new Array(titles.maxLength - titles[y].length + 2).join(' ')
			for(var x = 0; x < matrix.shape[0]; x++) {
				var num = matrix.get(x, y)
				var content = num ? '<' : ' '
				if(numbers && num)
					content = num + ''
				res += content + new Array(Math.max(titles[x].length + 1 - content.length, 0)).join(' ') + ' '
			}
			res = res.slice(0, res.length - 1)
		}
		return res
	}

	function generateMatrix(person) {
		const vote = person.vote

		const moviesOrder = {}
		data.movies.forEach(function(movie, id) {
			moviesOrder[id] = Infinity
		})
		vote.forEach(function(id, i) {
			moviesOrder[id] = i
		})
		debug('movies order:', moviesOrder)

		const matrix = baseMatrix(data.movies)
		var val
		for(var x = 0; x < matrix.shape[0]; x++) {
			for(var y = 0; y < matrix.shape[1]; y++) {
				if(moviesOrder[y] < moviesOrder[x]) {
					val = 1
				} else {
					val = 0
				}
				matrix.set(x, y, val)
				debug.trace('setting %d (%d), %d (%d) to %d', x, moviesOrder[x], y, moviesOrder[y], val)
			}
		}
		debug('generated matrix for %s (%d):', person.name, person.id)
		if(debug.enabled) console.log(renderMatrix(matrix))
		return matrix
	}

	function update() {
		updateTitles()

		voting.matrix = baseMatrix(data.movies)
		voting.people.forEach(function(matrix) {
			ndarray.ops.add(voting.matrix, voting.matrix, matrix)
		})

		debug('matrix:')
		if(debug.enabled) console.log(renderMatrix(voting.matrix, true))

		voting.results = []

		const wins = {}
		data.movies.forEach(function(movie, id) {
			wins[id] = 0
		})

		for(var y = 0; y < voting.matrix.shape[1]; y++) {
			for(var x = 0; x < voting.matrix.shape[0]; x++) {
				if(x <= y) continue

				var runner   = voting.matrix.get(x, y)
				var opponent = voting.matrix.get(y, x)

				if(runner > opponent)
					wins[y] += 1
				else if(opponent > runner)
					wins[x] += 1

				debug.trace('%s (%d): %d | %s (%d): %d', data.movies[y].name, y, runner, data.movies[x].name, x, opponent)
			}
		}

		(function() {
			var maxWins = 0
			for(var id = 0; id < data.movies.length; id++) {
				/*if(wins[id] >= data.movies.length - 1) {
					voting.results = [ id ]
					return
				} else */
				if(wins[id] >= maxWins) {
					debug('adding %s (%d) - %d to the tie %s at %d', data.movies[id].name, id, wins[id], voting.results.map(function(id) {
						return data.movies[id].name
					}).join(', '), maxWins)
					if(wins[id] > maxWins) {
						maxWins = wins[id]
						voting.results = []
					}

					voting.results.push(id)
				}
			}
		})()

		debug('wins:', wins)

		if(voting.results.length == data.movies.length)
			voting.results = []

		voting.debugInfo = 'Result:\n' + renderMatrix(voting.matrix, true).split('\n').map(function(line) {
			return '  ' + line
		}).join('\n') + '\n\n' + voting.people.map(function(matrix, i) {
			const person = data.people[i]
			return person.name + ': ' + person.vote.map(function(i) {
				return titles[i]
			}).join(' ') + '\n' + renderMatrix(matrix).split('\n').map(function(line) {
				return '  ' + line
			}).join('\n')
		}).join('\n\n')

		debug('results: %s', voting.results.map(function(id) {
			return data.movies[id].name
		}).join(', '))

		voting.emit('update')
	}

	voting.update = function(person) { return function(cb) {
		if(!cb) cb = function(err) { if(err) throw err }

		voting.people[person.id] = generateMatrix(person)
		update()

		process.nextTick(function() { cb(null) })
	} }

	voting.delete = function(person) { return function(cb) {
		if(!cb) cb = function(err) { if(err) throw err }

		voting.people[person.id] = baseMatrix(data.movies)

		update()

		process.nextTick(function() { cb(null) })
	} }

	voting.reset = function() { return function(cb) {
		if(!cb) cb = function(err) { if(err) throw err }

		voting.people = []
		voting.matrix = baseMatrix(data.movies)
		voting.results = []
		debug('reseting')

		process.nextTick(function() { cb(null) })
	} }

	return voting
}<commit_msg>Fix baseMatrix<commit_after>const debug = require('../debug').sub('voting', 'condorcets')
const EE    = require('events').EventEmitter

const ndarray = require('ndarray')
ndarray.zeros = require('zeros')
ndarray.show  = require('ndarray-show')
ndarray.ops   = require('ndarray-ops')

function baseMatrix(movies) {
	const matrix = ndarray.zeros([ movies.length, movies.length ])
	for(var x = 0; x < matrix.shape[0]; x++) {
		for(var y = 0; y < matrix.shape[1]; y++) {
			matrix.set(x, y, 0)
		}
	}
	return matrix
}

module.exports = function(data) {
	const voting = new EE

	var titles

	function updateTitles() {
		titles = data.movies.map(function(movie) {
			return movie.name.replace(/a|an|and|the|\s+/gi, '').replace(/[^A-Z:]/g, '')
		})

		titles.maxLength = Math.max.apply(Math, [0].concat(titles.map(function(title) {
			return title.length
		})))
	}
	updateTitles()

	function renderMatrix(matrix, numbers) {
		if(titles.length == 0)
			return ''

		var res = new Array(titles.maxLength + 2).join(' ') + titles.join(' ')
		for(var y = 0; y < matrix.shape[1]; y++) {
			res += '\n' + titles[y] + new Array(titles.maxLength - titles[y].length + 2).join(' ')
			for(var x = 0; x < matrix.shape[0]; x++) {
				var num = matrix.get(x, y)
				var content = num ? '<' : ' '
				if(numbers && num)
					content = num + ''
				res += content + new Array(Math.max(titles[x].length + 1 - content.length, 0)).join(' ') + ' '
			}
			res = res.slice(0, res.length - 1)
		}
		return res
	}

	function generateMatrix(person) {
		const vote = person.vote

		const moviesOrder = {}
		data.movies.forEach(function(movie, id) {
			moviesOrder[id] = Infinity
		})
		vote.forEach(function(id, i) {
			moviesOrder[id] = i
		})
		debug('movies order:', moviesOrder)

		const matrix = baseMatrix(data.movies)
		var val
		for(var x = 0; x < matrix.shape[0]; x++) {
			for(var y = 0; y < matrix.shape[1]; y++) {
				if(moviesOrder[y] < moviesOrder[x]) {
					val = 1
				} else {
					val = 0
				}
				matrix.set(x, y, val)
				debug.trace('setting %d (%d), %d (%d) to %d', x, moviesOrder[x], y, moviesOrder[y], val)
			}
		}
		debug('generated matrix for %s (%d):', person.name, person.id)
		if(debug.enabled) console.log(renderMatrix(matrix))
		return matrix
	}

	function update() {
		updateTitles()

		voting.matrix = baseMatrix(data.movies)
		voting.people.forEach(function(matrix) {
			ndarray.ops.add(voting.matrix, voting.matrix, matrix)
		})

		debug('matrix:')
		if(debug.enabled) console.log(renderMatrix(voting.matrix, true))

		voting.results = []

		const wins = {}
		data.movies.forEach(function(movie, id) {
			wins[id] = 0
		})

		for(var y = 0; y < voting.matrix.shape[1]; y++) {
			for(var x = 0; x < voting.matrix.shape[0]; x++) {
				if(x <= y) continue

				var runner   = voting.matrix.get(x, y)
				var opponent = voting.matrix.get(y, x)

				if(runner > opponent)
					wins[y] += 1
				else if(opponent > runner)
					wins[x] += 1

				debug.trace('%s (%d): %d | %s (%d): %d', data.movies[y].name, y, runner, data.movies[x].name, x, opponent)
			}
		}

		(function() {
			var maxWins = 0
			for(var id = 0; id < data.movies.length; id++) {
				/*if(wins[id] >= data.movies.length - 1) {
					voting.results = [ id ]
					return
				} else */
				if(wins[id] >= maxWins) {
					debug('adding %s (%d) - %d to the tie %s at %d', data.movies[id].name, id, wins[id], voting.results.map(function(id) {
						return data.movies[id].name
					}).join(', '), maxWins)
					if(wins[id] > maxWins) {
						maxWins = wins[id]
						voting.results = []
					}

					voting.results.push(id)
				}
			}
		})()

		debug('wins:', wins)

		if(voting.results.length == data.movies.length)
			voting.results = []

		voting.debugInfo = 'Result:\n' + renderMatrix(voting.matrix, true).split('\n').map(function(line) {
			return '  ' + line
		}).join('\n') + '\n\n' + voting.people.map(function(matrix, i) {
			const person = data.people[i]
			return person.name + ': ' + person.vote.map(function(i) {
				return titles[i]
			}).join(' ') + '\n' + renderMatrix(matrix).split('\n').map(function(line) {
				return '  ' + line
			}).join('\n')
		}).join('\n\n')

		debug('results: %s', voting.results.map(function(id) {
			return data.movies[id].name
		}).join(', '))

		voting.emit('update')
	}

	voting.update = function(person) { return function(cb) {
		if(!cb) cb = function(err) { if(err) throw err }

		voting.people[person.id] = generateMatrix(person)
		update()

		process.nextTick(function() { cb(null) })
	} }

	voting.delete = function(person) { return function(cb) {
		if(!cb) cb = function(err) { if(err) throw err }

		voting.people[person.id] = baseMatrix(data.movies)

		update()

		process.nextTick(function() { cb(null) })
	} }

	voting.reset = function() { return function(cb) {
		if(!cb) cb = function(err) { if(err) throw err }

		voting.people = []
		voting.matrix = baseMatrix(data.movies)
		voting.results = []
		debug('reseting')

		process.nextTick(function() { cb(null) })
	} }

	return voting
}<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 by frePPLe bvba
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

'use strict';

angular.module('operationplandetailapp').controller('operationplandetailCtrl', operationplanCtrl);

operationplanCtrl.$inject = ['$scope', 'OperationPlan'];

function operationplanCtrl($scope, OperationPlan) {
  $scope.test = "angular controller";
  $scope.operationplan = new OperationPlan();
  $scope.aggregatedopplan = null;

  // This template function will pass the values to the grid, function(id,column,value)
  // will set the row as "edited", and trigger "save undo" buttons.
  // If the function does not exist it makes no sense to watch for changes on the bottom part.
  $scope.displayongrid = displayongrid;

  if (typeof $scope.displayongrid === 'function') {
    //watch is only needed if we can update the grid
    $scope.$watchGroup(['operationplan.id','operationplan.start','operationplan.end','operationplan.quantity','operationplan.status'], function(newValue, oldValue) {
      if (oldValue[0] === newValue[0] && newValue[0] !== -1 && typeof oldValue[0] !== 'undefined') { //is a change to the current operationplan

        if (typeof oldValue[1] !== 'undefined' && typeof newValue[1] !== 'undefined' && oldValue[1] !== newValue[1]) {
          $scope.displayongrid($scope.operationplan.id,"startdate",$scope.operationplan.start);
        }
        if (typeof oldValue[2] !== 'undefined' && typeof newValue[2] !== 'undefined' && oldValue[2] !== newValue[2]) {
          $scope.displayongrid($scope.operationplan.id,"enddate",$scope.operationplan.end);
        }
        if (typeof oldValue[3] !== 'undefined' && typeof newValue[3] !== 'undefined' && oldValue[3] !== newValue[3]) {
          $scope.displayongrid($scope.operationplan.id,"quantity",$scope.operationplan.quantity);
        }
        if (typeof oldValue[4] !== 'undefined' && typeof newValue[4] !== 'undefined' && oldValue[4] !== newValue[4]) {
          $scope.displayongrid($scope.operationplan.id,"status",$scope.operationplan.status);
        }
      }
      oldValue[0] = newValue[0];
    }); //end watchGroup
  }

  function processAggregatedInfo(selectionData, colModel) {
    console.log(selectionData);
    console.log(colModel);
    var aggColModel = [];
    var aggregatedopplan = {};
    aggregatedopplan.colmodel = {};
    var temp = 0;
    angular.forEach (colModel, function(value,key) {
      if (value.hasOwnProperty('summaryType')) {
        aggColModel.push([key, value.name, value.summaryType, value.formatter]);
        aggregatedopplan[value.name] = null;
        aggregatedopplan.colmodel[value.name] = {'type': value.summaryType, 'label': value.label};
      }
    });
    //console.log(aggColModel);
    angular.forEach (selectionData, function(opplan) {
      angular.forEach (aggColModel, function(field) {
        if (field[2] === 'sum') {// console.log(field[1],parseFloat(opplan[field[1]]));
          if (!isNaN(parseFloat(opplan[field[1]]))) {
            if (aggregatedopplan[field[1]] === null) {
              aggregatedopplan[field[1]] = parseFloat(opplan[field[1]]);
            } else {
              aggregatedopplan[field[1]] += parseFloat(opplan[field[1]]);
            }
          }
        } else if (field[2] === 'max') {

          if ( ['color','number'].indexOf(field[3]) !== -1 && opplan[field[1]] !== "") { //console.log(opplan[field[1]]);
            if (parseFloat(opplan[field[1]])) {
              if (aggregatedopplan[field[1]] === null) { //console.log(opplan[field[1]]);
                aggregatedopplan[field[1]] = parseFloat(opplan[field[1]]);
              } else {
                aggregatedopplan[field[1]] = Math.max(aggregatedopplan[field[1]], parseFloat(opplan[field[1]]));
              }
            }
          } else if (field[3] === 'duration') { //console.log(field[1],opplan[field[1]],field[3]);
            temp = new moment.duration(opplan[field[1]]).asSeconds();
            if (temp._d !== 'Invalid Date') {
              if (aggregatedopplan[field[1]] === null) { //console.log(opplan[field[1]]);
                aggregatedopplan[field[1]] = temp;
              } else {
                aggregatedopplan[field[1]] = Math.max(aggregatedopplan[field[1]], temp);
              }
            }
          } else if (field[3] === 'date') {
            temp = new moment(opplan[field[1]]);
            if (temp._d !== 'Invalid Date') {
              if (aggregatedopplan[field[1]] === null) { //console.log(opplan[field[1]]);
                aggregatedopplan[field[1]] = temp;
              } else {
                aggregatedopplan[field[1]] = moment.max(aggregatedopplan[field[1]], temp);
              }
            }
          }

        } else if (field[2] === 'min') { //console.log(field[1],opplan[field[1]],field[3]);

          if ( ['color','number'].indexOf(field[3]) !== -1 && opplan[field[1]] !== "") {
            //console.log(field[1],opplan[field[1]],field[3]);
            temp = parseFloat(opplan[field[1]]);
            if (!isNaN(temp)) {
              if (aggregatedopplan[field[1]] === null) { //console.log(opplan[field[1]]);
                aggregatedopplan[field[1]] = temp;
              } else {
                aggregatedopplan[field[1]] = Math.min(aggregatedopplan[field[1]], temp);
              }
              //console.log( Math.min(aggregatedopplan[field[1]], temp));
            }
          }  else if (field[3] === 'duration') { //console.log(field[1],opplan[field[1]],field[3]);
            temp = new moment.duration(opplan[field[1]]).asSeconds();
            if (temp._d !== 'Invalid Date') {
              if (aggregatedopplan[field[1]] === null) { //console.log(opplan[field[1]]);
                aggregatedopplan[field[1]] = temp;
              } else {
                aggregatedopplan[field[1]] = Math.min(aggregatedopplan[field[1]], temp);
              }
            }
          } else if (field[3] === 'date') {
            temp = new moment(opplan[field[1]]);
            if (temp._d !== 'Invalid Date') {
              if (aggregatedopplan[field[1]] === null) { //console.log(opplan[field[1]]);
                aggregatedopplan[field[1]] = temp;
              } else {
                aggregatedopplan[field[1]] = moment.min(aggregatedopplan[field[1]], temp);
              }
            }
          }

        }
      });
    });
    $scope.operationplan = new OperationPlan();
    aggregatedopplan.start = aggregatedopplan.startdate;
    aggregatedopplan.end = aggregatedopplan.enddate;
    aggregatedopplan.id = -1;
    aggregatedopplan.type = selectionData[0].type;
    $scope.$apply(function(){ $scope.operationplan.extend(aggregatedopplan); });

    //console.log($scope.operationplan);
  }
  $scope.processAggregatedInfo = processAggregatedInfo;

  function displayInfo(row) {
    var rowid=(typeof row === 'undefined')?undefined:row.id;
    $scope.operationplan = new OperationPlan();

    if (typeof row !== 'undefined') {
      if (row.hasOwnProperty('operationplan__id')) {
        rowid = row.operationplan__id;
        $scope.operationplan.editable = false;
      } else {
        $scope.operationplan.editable = true;
      }
    }

    $scope.operationplan.id = (typeof rowid === 'undefined')?undefined:parseInt(rowid);
    function callback(opplan) {
      if (row === undefined) {
        return opplan;
      }
      // load previous changes from grid
      if (row.startdate !== undefined && row.startdate !== '') {
        opplan.start = row.startdate;
      }
      if (row.enddate !== undefined && row.enddate !== '') {
        opplan.end = row.enddate;
      }
      if (row.quantity !== undefined && row.quantity !== '') {
        opplan.quantity = parseInt(row.quantity);
      }

      if (row.status !== undefined && row.status !== '') {
        opplan.status = row.status;
      }
    }

    if (typeof $scope.operationplan.id === 'undefined') {
      $scope.$apply(function(){$scope.operationplan = new OperationPlan();});
    } else {
      $scope.operationplan.get(callback);
    }
  }
  $scope.displayInfo = displayInfo;

  function refreshstatus(value) {

    if (value !== 'no_action') {
      $scope.$apply(function(){  $scope.operationplan.status = value;});
    }
  }
  $scope.refreshstatus = refreshstatus;

  function displayonpanel(rowid,columnid,value) {
    angular.element(document).find("#" + $scope.operationplan.id).removeClass("edited").addClass("edited");
    if (rowid === $scope.operationplan.id.toString()) {
      if (columnid === "startdate") {
        $scope.$apply(function() {$scope.operationplan.start = value;});
      }
      if (columnid === "enddate") {
        $scope.$apply(function() {$scope.operationplan.end = value;});
      }
      if (columnid === "quantity") {
        $scope.$apply(function() {$scope.operationplan.quantity = parseInt(value);});
      }
      if (columnid === "status") {
        $scope.refreshstatus(value);
      }
    }
  }
  $scope.displayonpanel = displayonpanel;

}
<commit_msg>operationplandetail: fix max item cost not showing in bottom panel on multiple selection.<commit_after>/*
 * Copyright (C) 2017 by frePPLe bvba
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

'use strict';

angular.module('operationplandetailapp').controller('operationplandetailCtrl', operationplanCtrl);

operationplanCtrl.$inject = ['$scope', 'OperationPlan'];

function operationplanCtrl($scope, OperationPlan) {
  $scope.test = "angular controller";
  $scope.operationplan = new OperationPlan();
  $scope.aggregatedopplan = null;

  // This template function will pass the values to the grid, function(id,column,value)
  // will set the row as "edited", and trigger "save undo" buttons.
  // If the function does not exist it makes no sense to watch for changes on the bottom part.
  $scope.displayongrid = displayongrid;

  if (typeof $scope.displayongrid === 'function') {
    //watch is only needed if we can update the grid
    $scope.$watchGroup(['operationplan.id','operationplan.start','operationplan.end','operationplan.quantity','operationplan.status'], function(newValue, oldValue) {
      if (oldValue[0] === newValue[0] && newValue[0] !== -1 && typeof oldValue[0] !== 'undefined') { //is a change to the current operationplan

        if (typeof oldValue[1] !== 'undefined' && typeof newValue[1] !== 'undefined' && oldValue[1] !== newValue[1]) {
          $scope.displayongrid($scope.operationplan.id,"startdate",$scope.operationplan.start);
        }
        if (typeof oldValue[2] !== 'undefined' && typeof newValue[2] !== 'undefined' && oldValue[2] !== newValue[2]) {
          $scope.displayongrid($scope.operationplan.id,"enddate",$scope.operationplan.end);
        }
        if (typeof oldValue[3] !== 'undefined' && typeof newValue[3] !== 'undefined' && oldValue[3] !== newValue[3]) {
          $scope.displayongrid($scope.operationplan.id,"quantity",$scope.operationplan.quantity);
        }
        if (typeof oldValue[4] !== 'undefined' && typeof newValue[4] !== 'undefined' && oldValue[4] !== newValue[4]) {
          $scope.displayongrid($scope.operationplan.id,"status",$scope.operationplan.status);
        }
      }
      oldValue[0] = newValue[0];
    }); //end watchGroup
  }

  function processAggregatedInfo(selectionData, colModel) {
    //console.log(selectionData);
    //console.log(colModel);
    var aggColModel = [];
    var aggregatedopplan = {};
    aggregatedopplan.colmodel = {};
    var temp = 0;
    angular.forEach (colModel, function(value,key) {
      if (value.hasOwnProperty('summaryType')) {
        aggColModel.push([key, value.name, value.summaryType, value.formatter]);
        aggregatedopplan[value.name] = null;
        aggregatedopplan.colmodel[value.name] = {'type': value.summaryType, 'label': value.label};
      }
    });
    //console.log(aggColModel);
    angular.forEach (selectionData, function(opplan) {
      angular.forEach (aggColModel, function(field) {
        if (field[2] === 'sum') {// console.log(field[1],parseFloat(opplan[field[1]]));
          if (!isNaN(parseFloat(opplan[field[1]]))) {
            if (aggregatedopplan[field[1]] === null) {
              aggregatedopplan[field[1]] = parseFloat(opplan[field[1]]);
            } else {
              aggregatedopplan[field[1]] += parseFloat(opplan[field[1]]);
            }
          }
        } else if (field[2] === 'max') {

          if ( ['color','number','currency'].indexOf(field[3]) !== -1 && opplan[field[1]] !== "") { //console.log(opplan[field[1]]);
            if (parseFloat(opplan[field[1]])) {
              if (aggregatedopplan[field[1]] === null) { //console.log(opplan[field[1]]);
                aggregatedopplan[field[1]] = parseFloat(opplan[field[1]]);
              } else {
                aggregatedopplan[field[1]] = Math.max(aggregatedopplan[field[1]], parseFloat(opplan[field[1]]));
              }
            }
          } else if (field[3] === 'duration') { //console.log(field[1],opplan[field[1]],field[3]);
            temp = new moment.duration(opplan[field[1]]).asSeconds();
            if (temp._d !== 'Invalid Date') {
              if (aggregatedopplan[field[1]] === null) { //console.log(opplan[field[1]]);
                aggregatedopplan[field[1]] = temp;
              } else {
                aggregatedopplan[field[1]] = Math.max(aggregatedopplan[field[1]], temp);
              }
            }
          } else if (field[3] === 'date') {
            temp = new moment(opplan[field[1]]);
            if (temp._d !== 'Invalid Date') {
              if (aggregatedopplan[field[1]] === null) { //console.log(opplan[field[1]]);
                aggregatedopplan[field[1]] = temp;
              } else {
                aggregatedopplan[field[1]] = moment.max(aggregatedopplan[field[1]], temp);
              }
            }
          }

        } else if (field[2] === 'min') { //console.log(field[1],opplan[field[1]],field[3]);

          if ( ['color','number'].indexOf(field[3]) !== -1 && opplan[field[1]] !== "") {
            //console.log(field[1],opplan[field[1]],field[3]);
            temp = parseFloat(opplan[field[1]]);
            if (!isNaN(temp)) {
              if (aggregatedopplan[field[1]] === null) { //console.log(opplan[field[1]]);
                aggregatedopplan[field[1]] = temp;
              } else {
                aggregatedopplan[field[1]] = Math.min(aggregatedopplan[field[1]], temp);
              }
              //console.log( Math.min(aggregatedopplan[field[1]], temp));
            }
          }  else if (field[3] === 'duration') { //console.log(field[1],opplan[field[1]],field[3]);
            temp = new moment.duration(opplan[field[1]]).asSeconds();
            if (temp._d !== 'Invalid Date') {
              if (aggregatedopplan[field[1]] === null) { //console.log(opplan[field[1]]);
                aggregatedopplan[field[1]] = temp;
              } else {
                aggregatedopplan[field[1]] = Math.min(aggregatedopplan[field[1]], temp);
              }
            }
          } else if (field[3] === 'date') {
            temp = new moment(opplan[field[1]]);
            if (temp._d !== 'Invalid Date') {
              if (aggregatedopplan[field[1]] === null) { //console.log(opplan[field[1]]);
                aggregatedopplan[field[1]] = temp;
              } else {
                aggregatedopplan[field[1]] = moment.min(aggregatedopplan[field[1]], temp);
              }
            }
          }

        }
      });
    });
    $scope.operationplan = new OperationPlan();
    aggregatedopplan.start = aggregatedopplan.startdate;
    aggregatedopplan.end = aggregatedopplan.enddate;
    aggregatedopplan.id = -1;
    aggregatedopplan.type = selectionData[0].type;
    $scope.$apply(function(){ $scope.operationplan.extend(aggregatedopplan); });

    //console.log($scope.operationplan);
  }
  $scope.processAggregatedInfo = processAggregatedInfo;

  function displayInfo(row) {
    var rowid=(typeof row === 'undefined')?undefined:row.id;
    $scope.operationplan = new OperationPlan();

    if (typeof row !== 'undefined') {
      if (row.hasOwnProperty('operationplan__id')) {
        rowid = row.operationplan__id;
        $scope.operationplan.editable = false;
      } else {
        $scope.operationplan.editable = true;
      }
    }

    $scope.operationplan.id = (typeof rowid === 'undefined')?undefined:parseInt(rowid);
    function callback(opplan) {
      if (row === undefined) {
        return opplan;
      }
      // load previous changes from grid
      if (row.startdate !== undefined && row.startdate !== '') {
        opplan.start = row.startdate;
      }
      if (row.enddate !== undefined && row.enddate !== '') {
        opplan.end = row.enddate;
      }
      if (row.quantity !== undefined && row.quantity !== '') {
        opplan.quantity = parseInt(row.quantity);
      }

      if (row.status !== undefined && row.status !== '') {
        opplan.status = row.status;
      }
    }

    if (typeof $scope.operationplan.id === 'undefined') {
      $scope.$apply(function(){$scope.operationplan = new OperationPlan();});
    } else {
      $scope.operationplan.get(callback);
    }
  }
  $scope.displayInfo = displayInfo;

  function refreshstatus(value) {

    if (value !== 'no_action') {
      $scope.$apply(function(){  $scope.operationplan.status = value;});
    }
  }
  $scope.refreshstatus = refreshstatus;

  function displayonpanel(rowid,columnid,value) {
    angular.element(document).find("#" + $scope.operationplan.id).removeClass("edited").addClass("edited");
    if (rowid === $scope.operationplan.id.toString()) {
      if (columnid === "startdate") {
        $scope.$apply(function() {$scope.operationplan.start = value;});
      }
      if (columnid === "enddate") {
        $scope.$apply(function() {$scope.operationplan.end = value;});
      }
      if (columnid === "quantity") {
        $scope.$apply(function() {$scope.operationplan.quantity = parseInt(value);});
      }
      if (columnid === "status") {
        $scope.refreshstatus(value);
      }
    }
  }
  $scope.displayonpanel = displayonpanel;

}
<|endoftext|>