<commit_before>(function () {
    'use strict';
    angular
        .module(HygieiaConfig.module)
        .controller('subnetController', SubnetController);

    SubnetController.$inject = ['$scope', 'cloudData', '$http', '$modal', '$compile'];

    function SubnetController($scope, cloudData, $http, $modal, $compile) {

        var ctrl = this;
        $scope.vpcs = [];

        ctrl.accountNumber = $scope.widgetConfig.options.accountNumber || "";

        $scope.ipUtilizations;

       $scope.ipUtilizationsOptions = {
            horizontalBars: true,
            stackBars: true,

            axisY: {
    offset: 100
  },
  axisX: {
    offset:20,
     labelInterpolationFnc: function(value, index) {
      return index % 2 === 0 ? value : null;
    }
  }

        };

        $scope.ipUtilizationsEvents = {

  draw: function (data) {

if (data.type === 'bar') {
  var strokeColor = '##05ac45';

  if (data.meta == 'high') {
        strokeColor = '#d8514d'
  } else if (data.meta == 'med') {
      strokeColor = '#ffbd35'
  }
    data.element.attr({
      style: 'stroke-width: 20px; stroke: ' + strokeColor + ';'
    });
  }

  if (data.type === 'label') {
    //var compiledHtml = $compile(strElm);
    //element.append(compiledHtml);
    data.valueOf;
    data.element.attr({
     // onclick: "angular.element(document.getElementById('iptutildiv')).scope().viewSubnetUtilization2(this.innerHTML)",
      class: 'clickable'
    });  }

  }

      }

        ctrl.calculatePercentage = function(count, total) {
          var percentage = count / total * 100;
          return Math.round(percentage);
        }

        $scope.totalAvailable = 0;
        $scope.totalUsed = 0;

        $scope.getIpUtilizations = function() {
            $scope.getSubnets
            var vpcData = {labels:[], series:[[], [], []]};
            angular.forEach($scope.vpcs, function(vpc) {

              var angularModalPopUpCall = "angular.element(document.getElementById('iptutildiv')).scope().viewSubnetUtilization('" + vpc.id + "')";

              var clickableLabel = '
' + vpc.id + '
';

              vpcData.labels.push(clickableLabel);
              var countOfSubnetsByUtilization = vpc.countOfSubnetsByUtilization;
              var totalSubnets = countOfSubnetsByUtilization.high + countOfSubnetsByUtilization.med + countOfSubnetsByUtilization.low;

              vpcData.series[0].push({ meta: 'low', value:ctrl.calculatePercentage(countOfSubnetsByUtilization.low, totalSubnets)});
              vpcData.series[1].push({ meta: 'med', value:ctrl.calculatePercentage(countOfSubnetsByUtilization.med, totalSubnets)});
              vpcData.series[2].push({ meta: 'high', value:ctrl.calculatePercentage(countOfSubnetsByUtilization.high, totalSubnets)});

              $scope.totalAvailable += vpc.ips.totalAvailable;
              $scope.totalUsed += vpc.ips.totalUsed ;

            });

            $scope.ipUtilizations = vpcData;
            $scope.totalIPs = $scope.totalAvailable + $scope.totalUsed;
            $scope.avgUtilization = ctrl.calculatePercentage($scope.totalUsed, $scope.totalIPs);

        }

        $scope.getSubnets = function() {

            cloudData.getAWSSubnetsByAccount(ctrl.accountNumber)
                .then(function(subnets){
                    $scope.vpcs = ctrl.groupByVpc(subnets);
                    $scope.getIpUtilizations();
                    console.log($scope.vpcs)
            });
        };

$scope.getHeight = function() {

    return $scope.vpcs.length * 30;
}
        $scope.viewSubnetUtilization = function(vpcId) {

            var vpc = {};

            angular.forEach($scope.vpcs, function(item) {
              if (item.id.toUpperCase() == vpcId.toUpperCase()) {
                  vpc = item;
              }
            });

            $modal.open({
                controller: 'SubnetUtilizationController',
                controllerAs: 'subnetUtilization',
                templateUrl: 'components/widgets/cloud/subnetUtilization.html',
                size: 'lg',
                resolve: {
                  vpc: function() {
                    return vpc;
                  }
                },

            });
        };

        ctrl.calculateUtilization = function(subnet) {
            return subnet.usedIPCount/(subnet.usedIPCount + subnet.availableIPCount) * 100;
        }

        ctrl.groupByVpc = function(subnets) {
          var vpcMap = {};
          var vpcs = []
          angular.forEach(subnets, function(subnet) {
            if (!vpcMap[subnet.virtualNetworkId]) {
              var vpc = {};
              vpc.id = subnet.virtualNetworkId;
              vpc.subnets = [];
              vpc.ips = {totalAvailable:0, totalUsed: 0};
              vpc.countOfSubnetsByUtilization = {};
              vpc.countOfSubnetsByUtilization.high = 0;
              vpc.countOfSubnetsByUtilization.med = 0;
              vpc.countOfSubnetsByUtilization.low = 0;
              vpcs.push(vpc);
              vpcMap[subnet.virtualNetworkId] = vpc;
            };

            vpcMap[subnet.virtualNetworkId].subnets.push(subnet);
            var utilization = ctrl.calculateUtilization(subnet);
            if (utilization > 70) {
              vpcMap[subnet.virtualNetworkId].countOfSubnetsByUtilization.high+=1;
            } else if (utilization <= 70 && utilization > 50) {
                vpcMap[subnet.virtualNetworkId].countOfSubnetsByUtilization.med+=1;
            } else {
                vpcMap[subnet.virtualNetworkId].countOfSubnetsByUtilization.low+=1;
            }

            vpcMap[subnet.virtualNetworkId].ips.totalAvailable += subnet.availableIPCount;
            vpcMap[subnet.virtualNetworkId].ips.totalUsed += subnet.usedIPCount;

          });
          return vpcs;
        };

    }

})();<commit_msg>remove unused line<commit_after>(function () {
    'use strict';
    angular
        .module(HygieiaConfig.module)
        .controller('subnetController', SubnetController);

    SubnetController.$inject = ['$scope', 'cloudData', '$http', '$modal', '$compile'];

    function SubnetController($scope, cloudData, $http, $modal, $compile) {

        var ctrl = this;
        $scope.vpcs = [];

        ctrl.accountNumber = $scope.widgetConfig.options.accountNumber || "";

        $scope.ipUtilizations;

       $scope.ipUtilizationsOptions = {
            horizontalBars: true,
            stackBars: true,

            axisY: {
    offset: 100
  },
  axisX: {
    offset:20,
     labelInterpolationFnc: function(value, index) {
      return index % 2 === 0 ? value : null;
    }
  }

        };

        $scope.ipUtilizationsEvents = {

  draw: function (data) {

if (data.type === 'bar') {
  var strokeColor = '##05ac45';

  if (data.meta == 'high') {
        strokeColor = '#d8514d'
  } else if (data.meta == 'med') {
      strokeColor = '#ffbd35'
  }
    data.element.attr({
      style: 'stroke-width: 20px; stroke: ' + strokeColor + ';'
    });
  }

  if (data.type === 'label') {
    //var compiledHtml = $compile(strElm);
    //element.append(compiledHtml);
    data.valueOf;
    data.element.attr({
     // onclick: "angular.element(document.getElementById('iptutildiv')).scope().viewSubnetUtilization2(this.innerHTML)",
      class: 'clickable'
    });  }

  }

      }

        ctrl.calculatePercentage = function(count, total) {
          var percentage = count / total * 100;
          return Math.round(percentage);
        }

        $scope.totalAvailable = 0;
        $scope.totalUsed = 0;

        $scope.getIpUtilizations = function() {
            $scope.getSubnets
            var vpcData = {labels:[], series:[[], [], []]};
            angular.forEach($scope.vpcs, function(vpc) {

              var angularModalPopUpCall = "angular.element(document.getElementById('iptutildiv')).scope().viewSubnetUtilization('" + vpc.id + "')";

              var clickableLabel = '
' + vpc.id + '
';

              vpcData.labels.push(clickableLabel);
              var countOfSubnetsByUtilization = vpc.countOfSubnetsByUtilization;
              var totalSubnets = countOfSubnetsByUtilization.high + countOfSubnetsByUtilization.med + countOfSubnetsByUtilization.low;

              vpcData.series[0].push({ meta: 'low', value:ctrl.calculatePercentage(countOfSubnetsByUtilization.low, totalSubnets)});
              vpcData.series[1].push({ meta: 'med', value:ctrl.calculatePercentage(countOfSubnetsByUtilization.med, totalSubnets)});
              vpcData.series[2].push({ meta: 'high', value:ctrl.calculatePercentage(countOfSubnetsByUtilization.high, totalSubnets)});

              $scope.totalAvailable += vpc.ips.totalAvailable;
              $scope.totalUsed += vpc.ips.totalUsed ;

            });

            $scope.ipUtilizations = vpcData;
            $scope.totalIPs = $scope.totalAvailable + $scope.totalUsed;
            $scope.avgUtilization = ctrl.calculatePercentage($scope.totalUsed, $scope.totalIPs);

        }

        $scope.getSubnets = function() {

            cloudData.getAWSSubnetsByAccount(ctrl.accountNumber)
                .then(function(subnets){
                    $scope.vpcs = ctrl.groupByVpc(subnets);
                    $scope.getIpUtilizations();
                    console.log($scope.vpcs)
            });
        };

$scope.getHeight = function() {

    return $scope.vpcs.length * 30;
}
        $scope.viewSubnetUtilization = function(vpcId) {

            var vpc = {};

            angular.forEach($scope.vpcs, function(item) {
              if (item.id.toUpperCase() == vpcId.toUpperCase()) {
                  vpc = item;
              }
            });

            $modal.open({
                controller: 'SubnetUtilizationController',
                controllerAs: 'subnetUtilization',
                templateUrl: 'components/widgets/cloud/subnetUtilization.html',
                size: 'lg',
                resolve: {
                  vpc: function() {
                    return vpc;
                  }
                }

            });
        };

        ctrl.calculateUtilization = function(subnet) {
            return subnet.usedIPCount/(subnet.usedIPCount + subnet.availableIPCount) * 100;
        }

        ctrl.groupByVpc = function(subnets) {
          var vpcMap = {};
          var vpcs = []
          angular.forEach(subnets, function(subnet) {
            if (!vpcMap[subnet.virtualNetworkId]) {
              var vpc = {};
              vpc.id = subnet.virtualNetworkId;
              vpc.subnets = [];
              vpc.ips = {totalAvailable:0, totalUsed: 0};
              vpc.countOfSubnetsByUtilization = {};
              vpc.countOfSubnetsByUtilization.high = 0;
              vpc.countOfSubnetsByUtilization.med = 0;
              vpc.countOfSubnetsByUtilization.low = 0;
              vpcs.push(vpc);
              vpcMap[subnet.virtualNetworkId] = vpc;
            };

            vpcMap[subnet.virtualNetworkId].subnets.push(subnet);
            var utilization = ctrl.calculateUtilization(subnet);
            if (utilization > 70) {
              vpcMap[subnet.virtualNetworkId].countOfSubnetsByUtilization.high+=1;
            } else if (utilization <= 70 && utilization > 50) {
                vpcMap[subnet.virtualNetworkId].countOfSubnetsByUtilization.med+=1;
            } else {
                vpcMap[subnet.virtualNetworkId].countOfSubnetsByUtilization.low+=1;
            }

            vpcMap[subnet.virtualNetworkId].ips.totalAvailable += subnet.availableIPCount;
            vpcMap[subnet.virtualNetworkId].ips.totalUsed += subnet.usedIPCount;

          });
          return vpcs;
        };

    }

})();<|endoftext|>


<commit_before>export const defaultSignInProviders = {
  logingov: true,
  idme: true,
  mhv: true,
  dslogon: true,
};

export const defaultSignUpProviders = {
  logingov: true,
  idme: true,
};

export const defaultMobileQueryParams = {
  allowOAuth: true,
  allowPostLogin: false,
  allowRedirect: false,
};
<commit_msg>updates ordering of signin buttons (#21209)<commit_after>export const defaultSignInProviders = {
  logingov: true,
  idme: true,
  dslogon: true,
  mhv: true,
};

export const defaultSignUpProviders = {
  logingov: true,
  idme: true,
};

export const defaultMobileQueryParams = {
  allowOAuth: true,
  allowPostLogin: false,
  allowRedirect: false,
};
<|endoftext|>


<commit_before>
angular.module('os.biospecimen.extensions')
  .directive('osFormData', function() {

    function getSimpleFieldsEl() {
      return angular.element('
');
    }

    function getFieldValueEl(field) {
      var el = angular.element('
');
      el.append(angular.element('').text(field.caption));

      var value = field.value;
      if (value instanceof Array) {
        value = value.join(", ");
      }
      el.append(angular.element('').text(value));

      return el;
    }

    function getSectionEl(field) {
      var title = angular.element('
').append(field.caption);
      return angular.element('
').append(title);
    }

    function getSubFormSection(field) {

      var table = angular.element('
')
        .append(getSubFormTableHead(field.value))
        .append(getSubFormTableBody(field.value));

      return getSectionEl(field)
        .append(angular.element('
').append(table));
    }

    function getSubFormTableHead(sfRecs) {
      var thead = angular.element('
');
      if (sfRecs.length < 1) {
        return thead;
      }

      var row = angular.element('
');
      angular.forEach(sfRecs[0].fields, function(field) {
        row.append(angular.element('').append(field.caption));
      });

      return thead.append(row);
    }

    function getSubFormTableBody(sfRecs) {
      var tbody = angular.element('
');
      angular.forEach(sfRecs, function(rec) {
        var row = angular.element('
');
        angular.forEach(rec.fields, function(field) {
          var value = field.value;
          if (value instanceof Array) {
            value = value.join(", ");
          }
          row.append(angular.element('').append(value));
        });
        tbody.append(row);
      });

      return tbody;
    };

    return {
      restrict: 'E',

      replace: true,

      template: '

',

      scope: {
        data: '='
      },

      link: function(scope, element, attrs) {
        var fields = scope.data.fields;

        var els = [];
        var simpleFieldsEl = undefined;
        angular.forEach(fields, function(field) {
          if (field.type == 'subForm') {
            if (simpleFieldsEl) {
              els.push(simpleFieldsEl);
              simpleFieldsEl = undefined;
            }
            els.push(getSubFormSection(field));
          } else {
            if (!simpleFieldsEl) {
              simpleFieldsEl = getSimpleFieldsEl();
            }

            simpleFieldsEl.append(getFieldValueEl(field));
          }
        });

        if (simpleFieldsEl) {
          els.push(simpleFieldsEl);
        }

        element.append(els);
      }
    };
  });
<commit_msg>OPSMN-2663: Fixed code styling and white space issues<commit_after>
angular.module('os.biospecimen.extensions')
  .directive('osFormData', function() {

    function getSimpleFieldsEl() {
      return angular.element('
');
    }

    function getFieldValueEl(field) {
      var el = angular.element('
')
        .append(angular.element('').text(field.caption));

      var value = field.value;
      if (value instanceof Array) {
        value = value.join(", ");
      }
      el.append(angular.element('').text(value));

      return el;
    }

    function getSectionEl(field) {
      var title = angular.element('
').append(field.caption);
      return angular.element('
').append(title);
    }

    function getSubFormSection(field) {
      var table = angular.element('
')
        .append(getSubFormTableHead(field.value))
        .append(getSubFormTableBody(field.value));

      return getSectionEl(field)
        .append(angular.element('
').append(table));
    }

    function getSubFormTableHead(sfRecs) {
      var thead = angular.element('
');
      if (sfRecs.length < 1) {
        return thead;
      }

      var row = angular.element('
');
      angular.forEach(sfRecs[0].fields, function(field) {
        row.append(angular.element('').append(field.caption));
      });

      return thead.append(row);
    }

    function getSubFormTableBody(sfRecs) {
      var tbody = angular.element('
');
      angular.forEach(sfRecs, function(rec) {
        var row = angular.element('
');
        angular.forEach(rec.fields, function(field) {
          var value = field.value;
          if (value instanceof Array) {
            value = value.join(", ");
          }
          row.append(angular.element('').append(value));
        });
        tbody.append(row);
      });

      return tbody;
    };

    return {
      restrict: 'E',

      replace: true,

      template: '

',

      scope: {
        data: '='
      },

      link: function(scope, element, attrs) {
        var fields = scope.data.fields;

        var els = [];
        var simpleFieldsEl = undefined;
        angular.forEach(fields, function(field) {
          if (field.type == 'subForm') {
            if (simpleFieldsEl) {
              els.push(simpleFieldsEl);
              simpleFieldsEl = undefined;
            }
            els.push(getSubFormSection(field));
          } else {
            if (!simpleFieldsEl) {
              simpleFieldsEl = getSimpleFieldsEl();
            }

            simpleFieldsEl.append(getFieldValueEl(field));
          }
        });

        if (simpleFieldsEl) {
          els.push(simpleFieldsEl);
        }

        element.append(els);
      }
    };
  });
<|endoftext|>


<commit_before>steal('can/util', 'can/view/elements.js', function (can) {
	// In some browsers, text nodes can not take expando properties.
	// We test that here.
	var canExpando = true;
	try {
		document.createTextNode('')
			._ = 0;
	} catch (ex) {
		canExpando = false;
	}
	// A mapping of element ids to nodeList id
	var nodeMap = {},
		// A mapping of ids to text nodes
		textNodeMap = {}, expando = 'ejs_' + Math.random(),
		_id = 0,
		id = function (node) {
			if (canExpando || node.nodeType !== 3) {
				if (node[expando]) {
					return node[expando];
				} else {
					++_id;
					return node[expando] = (node.nodeName ? 'element_' : 'obj_') + _id;
				}
			} else {
				for (var textNodeID in textNodeMap) {
					if (textNodeMap[textNodeID] === node) {
						return textNodeID;
					}
				}
				++_id;
				textNodeMap['text_' + _id] = node;
				return 'text_' + _id;
			}
		}, splice = [].splice;
	/**
	 * @property {Object} can.view.nodeLists
	 * @parent can.view.static
	 *
	 * Stores hierarchical node references.
	 *
	 * ## Use
	 *
	 * `can.view.nodeLists` is used to make sure "directly nested" live-binding
	 * sections update content correctly.
	 *
	 * Consider a template like:
	 *
	 *

	 *     {{#if items.length}}
	 *        Items:
	 *        {{#items}}
	 *
	 *        {{/items}}
	 *     {{/if}}
	 *

	 *
	 *
	 * The `{{#if}}` and `{{#items}}` seconds are "directly nested" because
	 * they share the same `<div>` parent element.
	 *
	 * If `{{#items}}` changes the DOM by adding more `<labels>`,
	 * `{{#if}}` needs to know about the `<labels>` to remove them
	 * if `{{#if}}` is re-rendered.  `{{#if}}` would be re-rendered, for example, if
	 * all items were removed.
	 *
	 *
	 * To keep all live-bound sections knowing which elements they are managing,
	 * all live-bound elments are [can.view.nodeLists.register registered] and
	 * [can.view.nodeLists.update updated] when the change.
	 *
	 * For example, the above template, when rendered with data like:
	 *
	 *     data = new can.Map({
	 *       items: ["first","second"]
	 *     })
	 *
	 * This will first render the following content:
	 *
	 *

	 *
	 *

	 *
	 * When the `5` [can.view.hookup hookup] callback is called, this will register the `<span>` like:
	 *
	 *     var ifsNodes = []
	 *     nodeLists.register(ifsNodes);
	 *
	 * And then render `{{if}}`'s contents and update `ifsNodes` with it:
	 *
	 *     nodeLists.update( ifsNodes, [<"\nItems:\n">, ] );
	 *
	 * Next, hookup `6` is called which will regsiter the `<span>` like:
	 *
	 *     var eachsNodes = [];
	 *     nodeLists.register(eachsNodes);
	 *
	 * And then it will render `{{#each}}`'s content and update `eachsNodes` with it:
	 *
	 *     nodeLists.update(eachsNodes, [,]);
	 *
	 * As `nodeLists` knows that `eachsNodes` is inside `ifsNodes`, it also updates
	 * `ifsNodes`'s nodes to look like:
	 *
	 *     [<"\nItems:\n">,,]
	 *
	 * Now, if all items were removed, `{{#if}}` would be able to remove
	 * all the `<label>` elements.
	 *
	 * When you regsiter a nodeList, you can also provide a callback to know when
	 * that nodeList has been replaced by a parent nodeList.  This is
	 * useful for tearing down live-binding.
	 *
	 *
	 *
	 *
	 *
	 */
	var nodeLists = {
		id: id,

		/**
		 * @function can.view.nodeLists.update
		 * @parent can.view.nodeLists
		 *
		 * Updates a nodeList with new items
		 *
		 * @param {Array.<HTMLElement>} nodeList A registered nodeList.
		 *
		 * @param {Array.<HTMLElement>} newNodes HTML nodes that should be placed in the nodeList.
		 *
		 */
		update: function (nodeList, newNodes) {
			// Unregister all childNodes.
			can.each(nodeList.childNodeLists, function (nodeList) {
				nodeLists.unregister(nodeList);
			});
			nodeList.childNodeLists = [];
			// Remove old node pointers to this list.
			can.each(nodeList, function (node) {
				delete nodeMap[id(node)];
			});
			newNodes = can.makeArray(newNodes);
			// indicate the new nodes belong to this list
			can.each(newNodes, function (node) {
				nodeMap[id(node)] = nodeList;
			});
			var oldListLength = nodeList.length,
				firstNode = nodeList[0];
			// Replace oldNodeLists's contents'
			splice.apply(nodeList, [
				0,
				oldListLength
			].concat(newNodes));
			// update all parent nodes so they are able to replace the correct elements
			var parentNodeList = nodeList;
			while (parentNodeList = parentNodeList.parentNodeList) {
				splice.apply(parentNodeList, [
					can.inArray(firstNode, parentNodeList),
					oldListLength
				].concat(newNodes));
			}
		},
		/**
		 * @function can.view.nodeLists.register
		 * @parent can.view.nodeLists
		 *
		 * Registers a nodeList.
		 *
		 * @param {Array.<HTMLElement>} nodeList An array of elements. This array will be kept live if child nodeLists
		 * update themselves.
		 *
		 * @param {function} [unregistered] An optional callback that is called when the `nodeList` is
		 * replaced due to a parentNode list being updated.
		 *
		 * @param {Array.<HTMLElement>} [parent] An optional parent nodeList.  If no parentNode list is found,
		 * the first element in `nodeList`'s current nodeList will be used.
		 *
		 * @return {Array.<HTMLElement>} The `nodeList` passed to `register`.
		 */
		register: function (nodeList, unregistered, parent) {
			// add an id to the nodeList
			nodeList.unregistered = unregistered;
			nodeList.childNodeLists = [];
			if (!parent) {
				// find the parent by looking up where this node is
				if (nodeList.length > 1) {
					throw 'does not work';
				}
				var nodeId = id(nodeList[0]);
				parent = nodeMap[nodeId];
			}
			nodeList.parentNodeList = parent;
			if (parent) {
				parent.childNodeLists.push(nodeList);
			}
			return nodeList;
		},
		// removes node in all parent nodes and unregisters all childNodes
		/**
		 * @function can.view.nodeLists.unregister
		 * @parent can.view.nodeLists
		 *
		 * Unregister's a nodeList.  Call if the nodeList is no longer being
		 * updated.  This will unregister all child nodeLists.
		 *
		 *
		 * @param {Array.<HTMLElement>} nodeList The nodelist to unregister.
		 */
		unregister: function (nodeList) {
			if (!nodeList.isUnregistered) {
				nodeList.isUnregistered = true;
				// unregister all childNodeLists
				delete nodeList.parentNodeList;
				can.each(nodeList, function (node) {
					var nodeId = id(node);
					delete nodeMap[nodeId];
				});
				// this can unbind which will call itself
				if (nodeList.unregistered) {
					nodeList.unregistered();
				}
				can.each(nodeList.childNodeLists, function (nodeList) {
					nodeLists.unregister(nodeList);
				});
			}
		},
		nodeMap: nodeMap
	};
	return nodeLists;
});
<commit_msg>Worked on #835. Added docco documentation.<commit_after>// # can/view/node_lists/node_list.js
// Consider the following template:
//
//

//  {{#if items.length}}
//		Items:
//		{{#items}}
//
//      {{/items}}
//	{{/if}}
//

//
// The `{{#if}}` and `{{#items}}` seconds are "directly nested" because
// they share the same `<div>` parent element.
//
// If `{{#items}}` changes the DOM by adding more `<labels>`,
// `{{#if}}` needs to know about the `<labels>` to remove them
// if `{{#if}}` is re-rendered.  `{{#if}}` would be re-rendered, for example, if
// all items were removed.
//
// `can.view.nodeLists` are used to make sure "directly nested" live-binding
// sections update content correctly.

steal('can/util', 'can/view/elements.js', function (can) {
	// Some browsers don't allow expando properties on HTMLTextNodes
	// so let's try to assign a custom property, an 'expando' property.
	// We use this boolean to determine how we are going to hold on
	// to HTMLTextNode within a nodeList.  More about this in the 'id'
	// function.
	var canExpando = true;
	try {
		document.createTextNode('')._ = 0;
	} catch (ex) {
		canExpando = false;
	}

	// ## Helpers

	// A mapping of element ids to nodeList id
	var nodeMap = {},

		// A mapping of ids to text nodes, this map will be used in the
		// case of the browser not supporting expando properties
		textNodeMap = {},

		// The id used as the key in our nodeMap, this integer
		// will be preceded by 'element_' or 'obj_' depending on whether
		// the element has a nodeName.
		_id = 0,

		// The name of the expando property; the value returned
		// given a nodeMap key.
		expando = 'ejs_' + Math.random(),

		// ## nodeLists.id
		// Given a template node, create an id on the node as a expando
		// property, or if the node is an HTMLTextNode and the browser
		// doesn't support expando properties store the id with a
		// reference to the text node in an internal collection then return
		// the lookup id.
		/**
		 * @hide
		 * Returns the id of the newly registered node or the lookup id of
		 * an already registered node.
		 * @param  {HTMLElement} node The HTMLElement to be stored in the nodeList
		 * @return {String} The lookup id of the node
		 */
		id = function (node) {
			// If the browser supports expando properties and the node
			// provided is not an HTMLTextNode, we don't need to work
			// with the internal textNodeMap and we can place the property
			// on the node.
			if (canExpando || node.nodeType !== 3) {
				// If the node already has an (internal) id, then just
				// return the key of the nodeMap. This would be the case
				// in updating and unregistering a nodeList.
				if (node[expando]) {
					return node[expando];
				} else {
					// If the node isn't already referenced in the map we need
					// to generate a lookup id and place it on the node itself.
					++_id;
					return node[expando] = (node.nodeName ? 'element_' : 'obj_') + _id;
				}
			} else {
				// The nodeList has a specific collection for HTMLTextNodes for
				// (older) browsers that do not support expando properties.
				for (var textNodeID in textNodeMap) {
					if (textNodeMap[textNodeID] === node) {
						return textNodeID;
					}
				}
				// If we didn't find the node, we need to register it and return
				// the id used.
				++_id;
				// We have to store the node itself because of the browser's lack
				// of support for expando properties (i.e. we can't use a look-up
				// table and store the id on the node as a custom property).
				textNodeMap['text_' + _id] = node;
				return 'text_' + _id;
			}
		}, splice = [].splice;
	var nodeLists = {
		id: id,

		// ## Registering & Updating
		//
		// To keep all live-bound sections knowing which elements they are managing,
		// all live-bound elments are [can.view.nodeLists.register registered] and
		// [can.view.nodeLists.update updated] when the change.
		//
		// For example, the above template, when rendered with data like:
		//
		//      data = new can.Map({
		//        items: ["first","second"]
		//      })
		//
		// This will first render the following content:
		//
		//

		//
		//

		//
		// When the `5` [can.view.hookup hookup] callback is called, this will register the `<span>` like:
		//
		//      var ifsNodes = []
		//      nodeLists.register(ifsNodes);
		//
		// And then render `{{if}}`'s contents and update `ifsNodes` with it:
		//
		//     nodeLists.update( ifsNodes, [<"\nItems:\n">, ] );
		//
		// Next, hookup `6` is called which will regsiter the `<span>` like:
		//
		//     var eachsNodes = [];
		//     nodeLists.register(eachsNodes);
		//
		// And then it will render `{{#each}}`'s content and update `eachsNodes` with it:
		//
		//     nodeLists.update(eachsNodes, [,]);
		//
		// As `nodeLists` knows that `eachsNodes` is inside `ifsNodes`, it also updates
		// `ifsNodes`'s nodes to look like:
		//
		//     [<"\nItems:\n">,,]
		//
		// Now, if all items were removed, `{{#if}}` would be able to remove
		// all the `<label>` elements.
		//
		// When you regsiter a nodeList, you can also provide a callback to know when
		// that nodeList has been replaced by a parent nodeList.  This is
		// useful for tearing down live-binding.

		// ## nodeLists.register
		// Registers a nodeList and returns the nodeList passed to register
		/**
		 * Registers a nodeList.
		 *
		 * @param {Array.<HTMLElement>} nodeList An array of elements. This array will
		 * be kept live if child nodeLists update themselves.
		 * @param {function} [unregistered] An optional callback that is called when
		 * the `nodeList` is replaced due to a parentNode list being updated.
		 * @param {Array.<HTMLElement>} [parent] An optional parent nodeList.  If no
		 * parentNode list is found, the first element in `nodeList`'s current nodeList
		 * will be used.
		 * @return {Array.<HTMLElement>} The `nodeList` passed to `register`.
		 */
		register: function (nodeList, unregistered, parent) {
			// if a unregistered callback has been provided assign it to the nodeList
			// as a property to be called when the nodeList is unregistred.
			nodeList.unregistered = unregistered;
			// Until this nodeLists is passed as the 'parent' paremeter of another
			// nodeList this array will remain empty.
			nodeList.childNodeLists = [];
			if (!parent) {
				// find the parent by looking up where this node is
				if (nodeList.length > 1) {
					throw 'does not work';
				}
				// if no parent is specified, look up the 0th element of nodeMap
				// and assign that to the parent slot.
				var nodeId = id(nodeList[0]);
				parent = nodeMap[nodeId];
			}
			nodeList.parentNodeList = parent;
			if (parent) {
				// now that we have found our parent, whether passed in as an
				// argument or the 0th element of the list assign the nodeList
				// as a child of that parent nodeList
				parent.childNodeLists.push(nodeList);
			}
			return nodeList;
		},

		// ## nodeLists.update
		// Updates a nodeList with new items, i.e. when values for the template have changed.
		/**
		 * Updates a nodeList with new items.
		 * @param {Array.<HTMLElement>} nodeList A registered nodeList.
		 * @param {Array.<HTMLElement>} newNodes HTML nodes that should be placed in the nodeList.
		 */
		update: function (nodeList, newNodes) {
			// Unregister all childNodes.
			can.each(nodeList.childNodeLists, function (nodeList) {
				nodeLists.unregister(nodeList);
			});
			nodeList.childNodeLists = [];
			// Remove old node pointers to this list.
			can.each(nodeList, function (node) {
				delete nodeMap[id(node)];
			});
			newNodes = can.makeArray(newNodes);
			// indicate the new nodes belong to this list
			can.each(newNodes, function (node) {
				nodeMap[id(node)] = nodeList;
			});
			var oldListLength = nodeList.length,
				firstNode = nodeList[0];
			// Replace oldNodeLists's contents'
			splice.apply(nodeList, [
				0,
				oldListLength
			].concat(newNodes));
			// update all parent nodes so they are able to replace the correct elements
			var parentNodeList = nodeList;
			while (parentNodeList = parentNodeList.parentNodeList) {
				splice.apply(parentNodeList, [
					can.inArray(firstNode, parentNodeList),
					oldListLength
				].concat(newNodes));
			}
		},

		// ## nodeLists.unregister
		// Unregister's a nodeList.  Call if the nodeList is no longer
		// being updated. This will also unregister all child nodeLists.
		/**
		 * Unregister's a nodeList.  Call if the nodeList is no longer
		 * being updated. This will also unregister all child nodeLists.
		 * @param {Array.<HTMLElement>} nodeList The nodeList to unregister.
		 */
		unregister: function (nodeList) {
			if (!nodeList.isUnregistered) {
				// if the nodeList isn't already unregistered, mark it as
				// unregistered so we don't do more work than necessary
				nodeList.isUnregistered = true;
				// we only want to unregister 'down' the prototype chain, so
				// we need to to detach the parent nodeList by deleting the
				// pointer
				delete nodeList.parentNodeList;
				// for each node in the nodeList we want to compute it's id
				// and delete it from the nodeList's internal map
				can.each(nodeList, function (node) {
					var nodeId = id(node);
					delete nodeMap[nodeId];
				});
				// if an 'unregisted' function was provided during registration
				// then call that function
 				if (nodeList.unregistered) {
					nodeList.unregistered();
				}
				// now recursive down through the child node preforming the
				// same unregister process
				can.each(nodeList.childNodeLists, function (nodeList) {
					nodeLists.unregister(nodeList);
				});
			}
		},
		nodeMap: nodeMap
	};
	return nodeLists;
});
<|endoftext|>


<commit_before>// Glasses.paginations = [];
//
// Glasses.paginations.push(new Meteor.Pagination(Glasses, {
//   infinite: true,
//   itemTemplate: 'glassInFindList',
//   templateName: "glasses",
//   sort: {
//     createdAt: -1
//   },
//   availableSettings: {
//     sort: true,
//     filter: true
//   },
//   fastRender: true,
// }));

var constructRangeQuery = function(lowerBound, upperBound){
  return {
    $gte:lowerBound,
    $lte:upperBound
  };
};

var constructFloorRangeQuery = function(val){
  if(val <= 0){
    return constructRangeQuery(val, 0);
  } else {
    return constructRangeQuery(0, val);
  }
};

// var constructAxisQuery = function(axis){
//   //TODO check this function
//   var range = 30;
//
//   if(axis + range > 180){
//     return {$or:[constructRangeQuery(0,(axis + range) % 180),
//       constructRangeQuery(axis - range,180)]};
//   }
//
//   if(axis - range < 0){
//     return {$or:[constructRangeQuery(0,axis + range),
//       constructRangeQuery(180 + (axis - range),180)]};
//   }
//   return constructRangeQuery((axis - range) % 180, (axis + range) % 180);
// };

var constructGlassesQuery = function(glasses){
  // var query = {$or:['leftRx.axis':constructAxisQuery()]};
  var range = 30;

  var query = {};

  if(glasses["leftRx.axis"] + range > 180){
    query.$or = [{'leftRx.axis':constructRangeQuery(0,(glasses["leftRx.axis"] + range) % 180)},
      {'leftRx.axis':constructRangeQuery(glasses["leftRx.axis"] - range,180)}];
  }
  else if(glasses["leftRx.axis"] - range < 0){
    query.$or = [{'leftRx.axis':constructRangeQuery(0,glasses["leftRx.axis"] + range)},
      {'leftRx.axis':constructRangeQuery(180 + (glasses["leftRx.axis"] - range), 180)}];
  } else{
    query['leftRx.axis'] = constructRangeQuery(glasses["leftRx.axis"] - range, glasses["leftRx.axis"]+ range);
  }

  query['leftRx.sphere'] = constructFloorRangeQuery(glasses['leftRx.sphere']);
  query['leftRx.cylinder'] = constructFloorRangeQuery(glasses['leftRx.cylinder']);

  query['rightRx.sphere'] = constructFloorRangeQuery(glasses['rightRx.sphere']);
  query['rightRx.cylinder'] = constructFloorRangeQuery(glasses['rightRx.cylinder']);

  if(glasses["rightRx.axis"] + range > 180){
    query.$or = [{'rightRx.axis':constructRangeQuery(0,(glasses["rightRx.axis"] + range) % 180)},
      {'rightRx.axis':constructRangeQuery(glasses["rightRx.axis"] - range,180)}];
  }
  else if(glasses["rightRx.axis"] - range < 0){
    query.$or = [{'rightRx.axis':constructRangeQuery(0,glasses["rightRx.axis"] + range)},
      {'rightRx.axis':constructRangeQuery(180 + (glasses["rightRx.axis"] - range), 180)}];
  } else{
    query['rightRx.axis'] = constructRangeQuery(glasses["rightRx.axis"] - range, glasses["rightRx.axis"]+ range);
  }

  return query;
}

if(Meteor.isServer){
  glassesQuery = {};
  Meteor.methods({
    searchGlasses:function(query,idealGlasses){
      // inner product
      function innerProduct(a, b){
        return a.dot(b.trans()).data[0][0];
      }

      // norm function
      function norm(matrix) {
        m = matrix.data;
        var squared_sum = 0;
        for (i = 0; i < m[0].length; i++) {
          squared_sum += Math.pow(m[0][i], 2);
        }
        return Math.sqrt(squared_sum);
      }

      // calculates innerProduct(ideal, actual) / (norm(actual)*norm(ideal))
      function calcCosSim(idealMatrix, actualMatrix) {
        var innerProductValue = innerProduct(idealMatrix, actualMatrix);
        var idealMatrixNorm = norm(idealMatrix);
        var actualMatrixNorm = norm(actualMatrix);
        // avoids the edge case where denominator = 0;
        if (idealMatrixNorm == 0 && actualMatrixNorm == 0) {
          return 1;
        }
        else if (idealMatrixNorm == 0){
          return actualMatrixNorm;
        }
        else if (actualMatrixNorm == 0) {
          return idealMatrixNorm;
        }
        else {
          var cosSim = innerProductValue / (idealMatrixNorm * actualMatrixNorm);
          return Math.round(cosSim * 10000) / 10000;
        }
      }

      var linearAlgebra = Meteor.npmRequire('linear-algebra')(),     // initialise it
          Vector = linearAlgebra.Vector,
          Matrix = linearAlgebra.Matrix;

      var res = Glasses.find(query).fetch();

      const SPH_WEIGHT = 100;
      const CYL_WEIGHT = 10;
      const AXIS_WEIGHT = 1;

      function getSimScore(actualGlasses) {
      	var weights = new Matrix([SPH_WEIGHT, SPH_WEIGHT, CYL_WEIGHT, CYL_WEIGHT, AXIS_WEIGHT, AXIS_WEIGHT]);

      	var idealMatrix = new Matrix(weights.mul(new Matrix([idealGlasses["rightRx.sphere"], idealGlasses["leftRx.sphere"], idealGlasses["rightRx.cylinder"], idealGlasses["leftRx.cylinder"], idealGlasses["rightRx.axis"], idealGlasses["leftRx.axis"]])).data[0]);
      	// var actualMatrix = new Matrix(weights.mul(new Matrix([actualGlasses["rightRx.sphere"], actualGlasses["leftRx.sphere"], actualGlasses["rightRx.cylinder"], actualGlasses["leftRx.cylinder"], actualGlasses["rightRx.axis"], actualGlasses["leftRx.axis"]])).data[0]);
        var actualMatrix = new Matrix(weights.mul(new Matrix([actualGlasses.rightRx.sphere, actualGlasses.leftRx.sphere, actualGlasses.rightRx.cylinder, actualGlasses.leftRx.cylinder, actualGlasses.rightRx.axis, actualGlasses.leftRx.axis])).data[0]);

        actualGlasses.cosSim = calcCosSim(idealMatrix, actualMatrix);

      	return actualGlasses;
      }

      res = res.map(getSimScore);

      console.log(res);

      return res;
    }
  });
}

if (Meteor.isClient) {
  Session.set('glasses',[]);
  AutoForm.hooks({
    findGlass:{
      before:{
        update:function(doc){
          // We have to call the server bc minimongo derps out here
          // TODO fix when meteor gets updated
          var searchQuery = constructGlassesQuery(doc.$set);

          // console.log(query);

          Meteor.call('searchGlasses', searchQuery, doc.$set, function(err,res){
            console.log(res);
            Session.set('glasses',res);
          });

          this.result(false);
        }
      }
    }
  });

  Template.findGlasses.helpers({
    glasses:function(){
      return Session.get('glasses')
    }
  });

}
<commit_msg>Sorted glasses by cosine similarity value<commit_after>// Glasses.paginations = [];
//
// Glasses.paginations.push(new Meteor.Pagination(Glasses, {
//   infinite: true,
//   itemTemplate: 'glassInFindList',
//   templateName: "glasses",
//   sort: {
//     createdAt: -1
//   },
//   availableSettings: {
//     sort: true,
//     filter: true
//   },
//   fastRender: true,
// }));

var constructRangeQuery = function(lowerBound, upperBound){
  return {
    $gte:lowerBound,
    $lte:upperBound
  };
};

var constructFloorRangeQuery = function(val){
  if(val <= 0){
    return constructRangeQuery(val, 0);
  } else {
    return constructRangeQuery(0, val);
  }
};

// var constructAxisQuery = function(axis){
//   //TODO check this function
//   var range = 30;
//
//   if(axis + range > 180){
//     return {$or:[constructRangeQuery(0,(axis + range) % 180),
//       constructRangeQuery(axis - range,180)]};
//   }
//
//   if(axis - range < 0){
//     return {$or:[constructRangeQuery(0,axis + range),
//       constructRangeQuery(180 + (axis - range),180)]};
//   }
//   return constructRangeQuery((axis - range) % 180, (axis + range) % 180);
// };

var constructGlassesQuery = function(glasses){
  // var query = {$or:['leftRx.axis':constructAxisQuery()]};
  var range = 30;

  var query = {};

  if(glasses["leftRx.axis"] + range > 180){
    query.$or = [{'leftRx.axis':constructRangeQuery(0,(glasses["leftRx.axis"] + range) % 180)},
      {'leftRx.axis':constructRangeQuery(glasses["leftRx.axis"] - range,180)}];
  }
  else if(glasses["leftRx.axis"] - range < 0){
    query.$or = [{'leftRx.axis':constructRangeQuery(0,glasses["leftRx.axis"] + range)},
      {'leftRx.axis':constructRangeQuery(180 + (glasses["leftRx.axis"] - range), 180)}];
  } else{
    query['leftRx.axis'] = constructRangeQuery(glasses["leftRx.axis"] - range, glasses["leftRx.axis"]+ range);
  }

  query['leftRx.sphere'] = constructFloorRangeQuery(glasses['leftRx.sphere']);
  query['leftRx.cylinder'] = constructFloorRangeQuery(glasses['leftRx.cylinder']);

  query['rightRx.sphere'] = constructFloorRangeQuery(glasses['rightRx.sphere']);
  query['rightRx.cylinder'] = constructFloorRangeQuery(glasses['rightRx.cylinder']);

  if(glasses["rightRx.axis"] + range > 180){
    query.$or = [{'rightRx.axis':constructRangeQuery(0,(glasses["rightRx.axis"] + range) % 180)},
      {'rightRx.axis':constructRangeQuery(glasses["rightRx.axis"] - range,180)}];
  }
  else if(glasses["rightRx.axis"] - range < 0){
    query.$or = [{'rightRx.axis':constructRangeQuery(0,glasses["rightRx.axis"] + range)},
      {'rightRx.axis':constructRangeQuery(180 + (glasses["rightRx.axis"] - range), 180)}];
  } else{
    query['rightRx.axis'] = constructRangeQuery(glasses["rightRx.axis"] - range, glasses["rightRx.axis"]+ range);
  }

  return query;
}

if(Meteor.isServer){
  glassesQuery = {};
  Meteor.methods({
    searchGlasses:function(query,idealGlasses){
      // inner product
      function innerProduct(a, b){
        return a.dot(b.trans()).data[0][0];
      }

      // norm function
      function norm(matrix) {
        m = matrix.data;
        var squared_sum = 0;
        for (i = 0; i < m[0].length; i++) {
          squared_sum += Math.pow(m[0][i], 2);
        }
        return Math.sqrt(squared_sum);
      }

      // calculates innerProduct(ideal, actual) / (norm(actual)*norm(ideal))
      function calcCosSim(idealMatrix, actualMatrix) {
        var innerProductValue = innerProduct(idealMatrix, actualMatrix);
        var idealMatrixNorm = norm(idealMatrix);
        var actualMatrixNorm = norm(actualMatrix);
        // avoids the edge case where denominator = 0;
        if (idealMatrixNorm == 0 && actualMatrixNorm == 0) {
          return 1;
        }
        else if (idealMatrixNorm == 0){
          return actualMatrixNorm;
        }
        // ignoring the glasses with all 0s parameters
        else if (actualMatrixNorm == 0) {
          return 0;
        }
        else {
          var cosSim = innerProductValue / (idealMatrixNorm * actualMatrixNorm);
          return Math.round(cosSim * 10000) / 10000;
        }
      }

      var linearAlgebra = Meteor.npmRequire('linear-algebra')(),     // initialise it
          Vector = linearAlgebra.Vector,
          Matrix = linearAlgebra.Matrix;

      var res = Glasses.find(query).fetch();

      const SPH_WEIGHT = 100;
      const CYL_WEIGHT = 10;
      const AXIS_WEIGHT = 1;

      function getSimScore(actualGlasses) {
      	var weights = new Matrix([SPH_WEIGHT, SPH_WEIGHT, CYL_WEIGHT, CYL_WEIGHT, AXIS_WEIGHT, AXIS_WEIGHT]);

      	var idealMatrix = new Matrix(weights.mul(new Matrix([idealGlasses["rightRx.sphere"], idealGlasses["leftRx.sphere"], idealGlasses["rightRx.cylinder"], idealGlasses["leftRx.cylinder"], idealGlasses["rightRx.axis"], idealGlasses["leftRx.axis"]])).data[0]);
      	// var actualMatrix = new Matrix(weights.mul(new Matrix([actualGlasses["rightRx.sphere"], actualGlasses["leftRx.sphere"], actualGlasses["rightRx.cylinder"], actualGlasses["leftRx.cylinder"], actualGlasses["rightRx.axis"], actualGlasses["leftRx.axis"]])).data[0]);
        var actualMatrix = new Matrix(weights.mul(new Matrix([actualGlasses.rightRx.sphere, actualGlasses.leftRx.sphere, actualGlasses.rightRx.cylinder, actualGlasses.leftRx.cylinder, actualGlasses.rightRx.axis, actualGlasses.leftRx.axis])).data[0]);

        actualGlasses.cosSim = calcCosSim(idealMatrix, actualMatrix);

      	return actualGlasses;
      }

      res = res.map(getSimScore);
      res.sort(function(a,b) { return b.cosSim - a.cosSim});

      console.log(res);

      return res;
    }
  });
}

if (Meteor.isClient) {
  Session.set('glasses',[]);
  AutoForm.hooks({
    findGlass:{
      before:{
        update:function(doc){
          // We have to call the server bc minimongo derps out here
          // TODO fix when meteor gets updated
          var searchQuery = constructGlassesQuery(doc.$set);

          // console.log(query);

          Meteor.call('searchGlasses', searchQuery, doc.$set, function(err,res){
            console.log(res);
            Session.set('glasses',res);
          });

          this.result(false);
        }
      }
    }
  });

  Template.findGlasses.helpers({
    glasses:function(){
      return Session.get('glasses')
    }
  });

}
<|endoftext|>


<commit_before>(function(){var _callbacks,_delim=/\s+/;var Shout=this.Shout={listen:function(events,callback){var cbs,ev,sub;if(!callback||!events)return;events=events.split(_delim);cbs=_callbacks||(_callbacks={});while(ev=events.shift()){sub=cbs[ev]||(cbs[ev]=[]);sub.push(callback)}},deaf:function(events){var cbs,ev,sub;if(!events)return;events=events.split(_delim);while(ev=events.shift()){delete _callbacks[ev]}},yell:function(events,context){var cbs,ev,sub;if(!events)return;events=events.split(_delim);context=context||{};while(ev=events.shift()){sub=_callbacks[ev];if(sub)for(var i=sub.length-1;i>=0;i--)sub[i](context)}},register:function(newNS,bindToNS){if(Shout[bindToNS])Shout[newNS]=Shout[bindToNS]}};Shout.on=Shout.bind=Shout.listen;Shout.off=Shout.unbind=Shout.deaf;Shout.trigger=Shout.shout=Shout.yell}).call(this);<commit_msg>no need for a minified build in the repo itself<commit_after><|endoftext|>


<commit_before>/*Copyright 2018 Bang & Olufsen A/S
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.*/

// MPD CONTROL FOR BEOCREATE

var exec = require("child_process").exec;

module.exports = function(beoBus, globals) {
	var beoBus = beoBus;
	var debug = globals.debug;

	var version = require("./package.json").version;

	var sources = null;

	var mpdEnabled = false;

	beoBus.on('general', function(event) {

		if (event.header == "startup") {

			if (globals.extensions.sources &&
				globals.extensions.sources.setSourceOptions &&
				globals.extensions.sources.sourceDeactivated) {
				sources = globals.extensions.sources;
			}

			if (sources) {
				getMPDStatus(function(enabled) {
					sources.setSourceOptions("mpd", {
						enabled: enabled,
						transportControls: true,
						usesHifiberryControl: true
					});
				});
			}

		}

		if (event.header == "activatedExtension") {
			if (event.content == "mpd") {
				beoBus.emit("ui", {target: "mpd", header: "mpdSettings", content: {mpdEnabled: mpdEnabled}});
			}
		}
	});

	beoBus.on('mpd', function(event) {

		if (event.header == "mpdEnabled") {

			if (event.content.enabled != undefined) {
				setMPDStatus(event.content.enabled, function(newStatus, error) {
					beoBus.emit("ui", {target: "mpd", header: "mpdSettings", content: {mpdEnabled: newStatus}});
					if (sources) sources.setSourceOptions("mpd", {enabled: newStatus});
					if (newStatus == false) {
						if (sources) sources.sourceDeactivated("mpd");
					}
					if (error) {
						beoBus.emit("ui", {target: "mpd", header: "errorTogglingMPD", content: {}});
					}
				});
			}

		}
	});

	function getMPDStatus(callback) {
		exec("systemctl is-active --quiet mpd.service mpd-mpris.service").on('exit', function(code) {
			if (code == 0) {
				mpdEnabled = true;
				callback(true);
			} else {
				mpdEnabled = false;
				callback(false);
			}
		});
	}

	function setMPDStatus(enabled, callback) {
		if (enabled) {
			exec("systemctl enable --now mpd.service mpd-mpris.service").on('exit', function(code) {
				if (code == 0) {
					mpdEnabled = true;
					if (debug) console.log("MPD enabled.");
					callback(true);
				} else {
					mpdEnabled = false;
					callback(false, true);
				}
			});
		} else {
			exec("systemctl disable --now mpd.service mpd-mpris.service").on('exit', function(code) {
				mpdEnabled = false;
				if (code == 0) {
					callback(false);
					if (debug) console.log("MPD disabled.");
				} else {
					callback(false, true);
				}
			});
		}
	}

	return {
		version: version
	}

};

<commit_msg>MPD fix<commit_after>/*Copyright 2018 Bang & Olufsen A/S
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.*/

// MPD CONTROL FOR BEOCREATE

var exec = require("child_process").exec;

module.exports = function(beoBus, globals) {
	var beoBus = beoBus;
	var debug = globals.debug;

	var version = require("./package.json").version;

	var sources = null;

	var mpdEnabled = false;

	beoBus.on('general', function(event) {

		if (event.header == "startup") {

			if (globals.extensions.sources &&
				globals.extensions.sources.setSourceOptions &&
				globals.extensions.sources.sourceDeactivated) {
				sources = globals.extensions.sources;
			}

			if (sources) {
				getMPDStatus(function(enabled) {
					sources.setSourceOptions("mpd", {
						enabled: enabled,
						transportControls: true,
						usesHifiberryControl: true
					});
				});
			}

		}

		if (event.header == "activatedExtension") {
			if (event.content == "mpd") {
				beoBus.emit("ui", {target: "mpd", header: "mpdSettings", content: {mpdEnabled: mpdEnabled}});
			}
		}
	});

	beoBus.on('mpd', function(event) {

		if (event.header == "mpdEnabled") {

			if (event.content.enabled != undefined) {
				setMPDStatus(event.content.enabled, function(newStatus, error) {
					beoBus.emit("ui", {target: "mpd", header: "mpdSettings", content: {mpdEnabled: newStatus}});
					if (sources) sources.setSourceOptions("mpd", {enabled: newStatus});
					if (newStatus == false) {
						if (sources) sources.sourceDeactivated("mpd");
					}
					if (error) {
						beoBus.emit("ui", {target: "mpd", header: "errorTogglingMPD", content: {}});
					}
				});
			}

		}
	});

	function getMPDStatus(callback) {
		exec("systemctl is-active --quiet mpd.service").on('exit', function(code) {
			if (code == 0) {
				mpdEnabled = true;
				callback(true);
			} else {
				mpdEnabled = false;
				callback(false);
			}
		});
	}

	function setMPDStatus(enabled, callback) {
		if (enabled) {
			exec("systemctl enable --now mpd.service mpd-mpris.service ympd.service").on('exit', function(code) {
				if (code == 0) {
					mpdEnabled = true;
					if (debug) console.log("MPD enabled.");
					callback(true);
				} else {
					mpdEnabled = false;
					callback(false, true);
				}
			});
		} else {
			exec("systemctl disable --now mpd.service mpd-mpris.service ympd.service").on('exit', function(code) {
				mpdEnabled = false;
				if (code == 0) {
					callback(false);
					if (debug) console.log("MPD disabled.");
				} else {
					callback(false, true);
				}
			});
		}
	}

	return {
		version: version
	}

};

<|endoftext|>


<commit_before>var TelemetryData=require('./models/TelemetryData');
var StatusManager=require('./StatusManager');
var Bitmask=require('./util/Bitmask');
var Validator=require('./util/Validator');
var Logger=require('./util/Logger');
var picpilot_config=require('../config/picpilot-config');
var Commands=require('./models/Commands');

var AircraftStatus=function(){
  this.following_path=false;
  this.killModeActive=false;
  this.killModeWarning=false;
  this.armed=false;
  this.initializing=false;
  this.running=false;
  this.manualMode=false;
  this.heartBeatTimeout=picpilot_config.get('heart_beat_timeout');

  this.xbee={//has not been implemented yet from the picpilots side
    status:false,
    timeSinceLost:null
  };
  this.gps={
    status: false,
    timeSinceLost: null
  };
  this.uhf={
    status: false,
    timeSinceLost: null
  };

  this.pastErrorCode=null;
  this.startup_errors={
    POWER_ON_RESET: false,
    BROWN_OUT_RESET: false,
    IDLE_MODE_RESET: false,
    SLEEP_MODE_RESET: false,
    SOFTWARE_WATCH_DOG_RESET: false,
    SOFTWARE_RESET: false,
    EXTERNAL_RESET: false,
    VOLTAGE_REGULATOR_RESET: false,
    ILLEGAL_OPCODE_RESET: false,
    TRAP_RESET: false
  };

  //sending a heartbeat every 5 seconds
  setInterval(function(){
    Commands.sendHeartbeat();
  }, this.heartBeatTimeout);

  TelemetryData.on('data_received',function(data){
    this.checkErrorCodes(data.startup_error_codes);
    this.checkGPS(data.gps_status);
    this.checkUHFStatus(data.wireless_connection);
    this.checkManualMode(data.wireless_connection);
    this.checkPlaneStatus(data.autopilot_active);
    this.checkPathFollowing(data.following_path);
  }.bind(this));

  this.checkPathFollowing=function(status){
    if(typeof status !== 'undefined' || status!==null){
      this.following_path=!!Number(status);
    }
  }

  this.checkPlaneStatus=function(number){
    if(!Validator.isValidNumber(number)){
      Logger.warn('Invalid value for autopilot_active received. Value: '+number);
    }
    else{
      number=Number(number);
      this.initializing= (number===0);
      if(number===1){ //only set armed to false if the number is ONLY 1
        this.armed= false;
      }
      this.armed= (number===2);
      this.running= (number===3);
      this.killModeWarning= (number===4);
      this.killModeActive= (number===5);

      StatusManager.setStatusCode('AIRCRAFT_INITIALIZE',this.initializing);
      StatusManager.setStatusCode('AIRCRAFT_UNARMED',!this.armed);
      StatusManager.setStatusCode('AIRCRAFT_ARMED',this.armed);
      StatusManager.setStatusCode('AIRCRAFT_RUNNING',this.running);
      StatusManager.setStatusCode('AIRCRAFT_KILLMODE_WARNING',this.killModeWarning);
      StatusManager.setStatusCode('AIRCRAFT_KILLMODE',this.killModeActive);
    }
  };

  this.checkUHFStatus=function(data){
    var number=Number(data);
    if(!Validator.isInteger(number)){
      Logger.warn('Invalid value for wireless_connection received. Value: '+data);
    }
    else{
      var bitmask=new Bitmask(number);
      this.uhf.status= bitmask.getBit(1);

      if(this.uhf.status){ //has been turned to true
        this.uhf.timeSinceLost=null;
      }
      else{ //has been turned to false
        this.uhf.timeSinceLost=Date.now();
      }
      StatusManager.setStatusCode('UHF_LOST',!this.uhfStatus);
    }
  };

  this.checkManualMode=function(data){
    var number=Number(data);
    if(!Validator.isInteger(number)){
      Logger.warn('Invalid value for wireless_connection received. Value: '+data);
    }
    else{
      var bitmask=new Bitmask(number);
      this.manualMode= !bitmask.getBit(0);
      StatusManager.setStatusCode('MANUAL_MODE',this.manualMode);
    }
  };

  this.checkGPS=function(data){
    var number=Number(data);
    if(!Validator.isValidNumber(number)){
      Logger.warn('Invalid GPS status received. Status: '+data);
    }
    var connection_status=((number & 0xf0) >> 4)>0; // if theres at least 1 fix
    if (connection_status !== this.gps.status){ //if its a different status
      this.gps.status=connection_status;
      StatusManager.setStatusCode('GPS_LOST',!this.gps.status);
      if(this.gps.status===false){ //if it was set to false, start the timer
        this.gps.timeSinceLost=Date.now();
      }
      else{
        this.gps.timeSinceLost=null;
      }
    }
  };

  this.checkErrorCodes=function(startup_error_codes){
    var dataNumber=Number(startup_error_codes);
    if(!Validator.isInteger(dataNumber)){
      Logger.warn('Invalid data value for startup_error_codes received. Value : '+startup_error_codes);
    }
    else if(this.pastErrorCode!==dataNumber){ //if we got an error code value thats different from last time
      var error_codes=new Bitmask(dataNumber);
      this.pastErrorCode=dataNumber;

      this.startup_errors.POWER_ON_RESET=error_codes.getBit(0);
      this.startup_errors.BROWN_OUT_RESET=error_codes.getBit(1);
      this.startup_errors.IDLE_MODE_RESET=error_codes.getBit(2);
      this.startup_errors.SLEEP_MODE_RESET=error_codes.getBit(3);
      this.startup_errors.SOFTWARE_WATCH_DOG_RESET=error_codes.getBit(4);
      this.startup_errors.SOFTWARE_RESET=error_codes.getBit(5);
      this.startup_errors.EXTERNAL_RESET=error_codes.getBit(6);
      this.startup_errors.VOLTAGE_REGULATOR_RESET=error_codes.getBit(7);
      this.startup_errors.ILLEGAL_OPCODE_RESET=error_codes.getBit(8);
      this.startup_errors.TRAP_RESET=error_codes.getBit(9);

      StatusManager.setStatusCode('AIRCRAFT_ERROR_POWER_ON_RESET',this.startup_errors.POWER_ON_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_BROWN_OUT_RESET',this.startup_errors.BROWN_OUT_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_IDLE_MODE_RESET',this.startup_errors.IDLE_MODE_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_SLEEP_MODE_RESET',this.startup_errors.SLEEP_MODE_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_SOFTWARE_WATCH_DOG_RESET',this.startup_errors.SOFTWARE_WATCH_DOG_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_SOFTWARE_RESET',this.startup_errors.SOFTWARE_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_EXTERNAL_RESET',this.startup_errors.EXTERNAL_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_VOLTAGE_REGULATOR_RESET',this.startup_errors.VOLTAGE_REGULATOR_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_ILLEGAL_OPCODE_RESET',this.startup_errors.ILLEGAL_OPCODE_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_TRAP_RESET',this.startup_errors.TRAP_RESET);
    }
  }
};

module.exports=new AircraftStatus();<commit_msg>Fixed start path following button<commit_after>var TelemetryData=require('./models/TelemetryData');
var StatusManager=require('./StatusManager');
var Bitmask=require('./util/Bitmask');
var Validator=require('./util/Validator');
var Logger=require('./util/Logger');
var picpilot_config=require('../config/picpilot-config');
var Commands=require('./models/Commands');

var AircraftStatus=function(){
  this.following_path=false;
  this.killModeActive=false;
  this.killModeWarning=false;
  this.armed=false;
  this.initializing=false;
  this.running=false;
  this.manualMode=false;
  this.heartBeatTimeout=picpilot_config.get('heart_beat_timeout');

  this.xbee={//has not been implemented yet from the picpilots side
    status:false,
    timeSinceLost:null
  };
  this.gps={
    status: false,
    timeSinceLost: null
  };
  this.uhf={
    status: false,
    timeSinceLost: null
  };

  this.pastErrorCode=null;
  this.startup_errors={
    POWER_ON_RESET: false,
    BROWN_OUT_RESET: false,
    IDLE_MODE_RESET: false,
    SLEEP_MODE_RESET: false,
    SOFTWARE_WATCH_DOG_RESET: false,
    SOFTWARE_RESET: false,
    EXTERNAL_RESET: false,
    VOLTAGE_REGULATOR_RESET: false,
    ILLEGAL_OPCODE_RESET: false,
    TRAP_RESET: false
  };

  //sending a heartbeat every 5 seconds
  setInterval(function(){
    Commands.sendHeartbeat();
  }, this.heartBeatTimeout);

  TelemetryData.on('data_received',function(data){
    this.checkErrorCodes(data.startup_error_codes);
    this.checkGPS(data.gps_status);
    this.checkUHFStatus(data.wireless_connection);
    this.checkManualMode(data.wireless_connection);
    this.checkPlaneStatus(data.autopilot_active);
    this.checkPathFollowing(data.path_following);
  }.bind(this));

  this.checkPathFollowing=function(status){
    if(typeof status !== 'undefined' || status!==null){
      this.following_path=(Number(status)===1);
    }
  }

  this.checkPlaneStatus=function(number){
    if(!Validator.isValidNumber(number)){
      Logger.warn('Invalid value for autopilot_active received. Value: '+number);
    }
    else{
      number=Number(number);
      this.initializing= (number===0);
      if(number===1){ //only set armed to false if the number is ONLY 1
        this.armed= false;
      }
      this.armed= (number===2);
      this.running= (number===3);
      this.killModeWarning= (number===4);
      this.killModeActive= (number===5);

      StatusManager.setStatusCode('AIRCRAFT_INITIALIZE',this.initializing);
      StatusManager.setStatusCode('AIRCRAFT_UNARMED',!this.armed);
      StatusManager.setStatusCode('AIRCRAFT_ARMED',this.armed);
      StatusManager.setStatusCode('AIRCRAFT_RUNNING',this.running);
      StatusManager.setStatusCode('AIRCRAFT_KILLMODE_WARNING',this.killModeWarning);
      StatusManager.setStatusCode('AIRCRAFT_KILLMODE',this.killModeActive);
    }
  };

  this.checkUHFStatus=function(data){
    var number=Number(data);
    if(!Validator.isInteger(number)){
      Logger.warn('Invalid value for wireless_connection received. Value: '+data);
    }
    else{
      var bitmask=new Bitmask(number);
      this.uhf.status= bitmask.getBit(1);

      if(this.uhf.status){ //has been turned to true
        this.uhf.timeSinceLost=null;
      }
      else{ //has been turned to false
        this.uhf.timeSinceLost=Date.now();
      }
      StatusManager.setStatusCode('UHF_LOST',!this.uhfStatus);
    }
  };

  this.checkManualMode=function(data){
    var number=Number(data);
    if(!Validator.isInteger(number)){
      Logger.warn('Invalid value for wireless_connection received. Value: '+data);
    }
    else{
      var bitmask=new Bitmask(number);
      this.manualMode= !bitmask.getBit(0);
      StatusManager.setStatusCode('MANUAL_MODE',this.manualMode);
    }
  };

  this.checkGPS=function(data){
    var number=Number(data);
    if(!Validator.isValidNumber(number)){
      Logger.warn('Invalid GPS status received. Status: '+data);
    }
    var connection_status=((number & 0xf0) >> 4)>0; // if theres at least 1 fix
    if (connection_status !== this.gps.status){ //if its a different status
      this.gps.status=connection_status;
      StatusManager.setStatusCode('GPS_LOST',!this.gps.status);
      if(this.gps.status===false){ //if it was set to false, start the timer
        this.gps.timeSinceLost=Date.now();
      }
      else{
        this.gps.timeSinceLost=null;
      }
    }
  };

  this.checkErrorCodes=function(startup_error_codes){
    var dataNumber=Number(startup_error_codes);
    if(!Validator.isInteger(dataNumber)){
      Logger.warn('Invalid data value for startup_error_codes received. Value : '+startup_error_codes);
    }
    else if(this.pastErrorCode!==dataNumber){ //if we got an error code value thats different from last time
      var error_codes=new Bitmask(dataNumber);
      this.pastErrorCode=dataNumber;

      this.startup_errors.POWER_ON_RESET=error_codes.getBit(0);
      this.startup_errors.BROWN_OUT_RESET=error_codes.getBit(1);
      this.startup_errors.IDLE_MODE_RESET=error_codes.getBit(2);
      this.startup_errors.SLEEP_MODE_RESET=error_codes.getBit(3);
      this.startup_errors.SOFTWARE_WATCH_DOG_RESET=error_codes.getBit(4);
      this.startup_errors.SOFTWARE_RESET=error_codes.getBit(5);
      this.startup_errors.EXTERNAL_RESET=error_codes.getBit(6);
      this.startup_errors.VOLTAGE_REGULATOR_RESET=error_codes.getBit(7);
      this.startup_errors.ILLEGAL_OPCODE_RESET=error_codes.getBit(8);
      this.startup_errors.TRAP_RESET=error_codes.getBit(9);

      StatusManager.setStatusCode('AIRCRAFT_ERROR_POWER_ON_RESET',this.startup_errors.POWER_ON_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_BROWN_OUT_RESET',this.startup_errors.BROWN_OUT_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_IDLE_MODE_RESET',this.startup_errors.IDLE_MODE_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_SLEEP_MODE_RESET',this.startup_errors.SLEEP_MODE_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_SOFTWARE_WATCH_DOG_RESET',this.startup_errors.SOFTWARE_WATCH_DOG_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_SOFTWARE_RESET',this.startup_errors.SOFTWARE_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_EXTERNAL_RESET',this.startup_errors.EXTERNAL_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_VOLTAGE_REGULATOR_RESET',this.startup_errors.VOLTAGE_REGULATOR_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_ILLEGAL_OPCODE_RESET',this.startup_errors.ILLEGAL_OPCODE_RESET);
      StatusManager.setStatusCode('AIRCRAFT_ERROR_TRAP_RESET',this.startup_errors.TRAP_RESET);
    }
  }
};

module.exports=new AircraftStatus();<|endoftext|>


<commit_before>/** The examiner management methods for StudentsManager.
 *
 * Note that this class depends on createRecordFromStoreRecord(),
 * onSelectNone() and loadFirstPage() from StudentsManager to be available. */
Ext.define('devilry.administrator.studentsmanager.StudentsManagerManageExaminers', {

    randomDistResultTpl: Ext.create('Ext.XTemplate',
        '
The selected examiners got the following number of groups:
',
        '
',
        '<tpl for="result">',
        '
{examiner}: {groups.length}
',
        '</tpl>',
        '
'
    ),

    /**
     * @private
     */
    onRandomDistributeExaminers: function() {
        if(this.noneSelected()) {
            this.onSelectNone();
            return;
        }
        var win = Ext.widget('window', {
            title: 'Select examiners',
            modal: true,
            width: 500,
            height: 400,
            maximizable: true,
            layout: 'fit',
            items: {
                xtype: 'setlistofusers',
                //usernames: ['donald', 'scrooge', 'daisy', 'clarabelle'],
                usernames: [],
                helptext: '
The username of a single examiner on each line. Example:
',
                listeners: {
                    scope: this,
                    saveClicked: function(setlistofusersobj, usernames) {
                        this.randomDistributeExaminersOnSelected(setlistofusersobj, usernames);
                    }
                },

                extraToolbarButtons: [{
                    xtype: 'button',
                    scale: 'large',
                    text: Ext.String.format('Import examiners registered in {0}', DevilrySettings.DEVILRY_SYNCSYSTEM),
                    listeners: {
                        scope: this,
                        click: this.onImportRelatedExaminers
                    }
                }]
            }
        });
        win.show();
    },

    /**
     * @private
     */
    randomDistributeExaminersOnSelected: function(setlistofusersobj, examiners) {
        setlistofusersobj.up('window').close();

        this._randomDistributeTmp = {
            remainingExaminers: Ext.Array.clone(examiners),
            allExaminers: examiners,
            totExaminers: examiners.length,
            result: {}
        };
        Ext.each(examiners, function(examiner, index) {
            this._randomDistributeTmp.result[examiner] = [];
        }, this);

        this.down('studentsmanager_studentsgrid').performActionOnSelected({
            scope: this,
            callback: this.randomDistributeExaminers,
            extraArgs: []
        });
    },

    /**
     * @private
     */
    getRandomExaminer: function() {
        var numRemainingExaminers = this._randomDistributeTmp.remainingExaminers.length;
        var randomIndex = Math.floor(Math.random() * (numRemainingExaminers));
        return this._randomDistributeTmp.remainingExaminers[randomIndex];
    },

    /**
     * @private
     */
    removeExaminerIfEnoughStudents: function(examiner, totalSelectedGroups) {
        var totExaminers = this._randomDistributeTmp.totExaminers;
        var groupsPerExaminer = Math.ceil(totalSelectedGroups/totExaminers);
        if(this._randomDistributeTmp.result[examiner].length === groupsPerExaminer) {
            Ext.Array.remove(this._randomDistributeTmp.remainingExaminers, examiner);
        }
    },

    /**
     * @private
     */
    showRandomDistributeResults: function() {
        //console.log(this._randomDistributeTmp.result);
        var resultArray = [];
        Ext.each(this._randomDistributeTmp.allExaminers, function(examiner, index) {
            resultArray.push({
                examiner: examiner,
                groups: this._randomDistributeTmp.result[examiner]
            });
        }, this);

        Ext.MessageBox.show({
            title: 'Random distribution of examiners complete',
            msg: this.randomDistResultTpl.apply({result: resultArray}),
            buttons: Ext.Msg.OK,
            scope: this
        });
    },

    /**
     * @private
     */
    randomDistributeExaminers: function(record, index, totalSelectedGroups) {
        var msg = Ext.String.format('Random distributing examiner to group {0}/{1}', index, totalSelectedGroups);
        this.getEl().mask(msg);

        var editRecord = this.createRecordFromStoreRecord(record);
        var examiner = this.getRandomExaminer();
        this._randomDistributeTmp.result[examiner].push(editRecord);
        this.removeExaminerIfEnoughStudents(examiner, totalSelectedGroups);

        editRecord.data.fake_examiners = [examiner];
        editRecord.save({
            failure: function() {
                console.error('Failed to save record');
            }
        });

        if(index == totalSelectedGroups) {
            this.loadFirstPage();
            this.getEl().unmask();
            this.showRandomDistributeResults();
        }
    },

    /**
     * @private
     */
    onSetExaminers: function(append) {
        if(this.noneSelected()) {
            this.onSelectNone();
            return;
        }
        var win = Ext.widget('window', {
            title: 'Select examiners',
            modal: true,
            width: 500,
            height: 400,
            maximizable: true,
            layout: 'fit',
            items: {
                xtype: 'setlistofusers',
                //usernames: ['donald', 'scrooge'],
                usernames: [],
                helptext: '
The username of a single examiner on each line. Example:
',
                listeners: {
                    scope: this,
                    saveClicked: function(setlistofusersobj, usernames) {
                        this.setExaminersOnSelected(setlistofusersobj, usernames, append);
                    }
                },

                extraToolbarButtons: [{
                    xtype: 'button',
                    scale: 'large',
                    text: Ext.String.format('Import examiners registered in {0}', DevilrySettings.DEVILRY_SYNCSYSTEM),
                    listeners: {
                        scope: this,
                        click: this.onImportRelatedExaminers
                    }
                }]
            },
        });
        win.show();
    },

    onImportRelatedExaminers: function(button) {
        var setlistofusersobj = button.up('setlistofusers');
        this.loadAllRelatedExaminers({
            scope: this,
            callback: this.importRelatedExaminers,
            args: [setlistofusersobj]
        });
    },

    importRelatedExaminers: function(relatedExaminers, setlistofusersobj) {
        var examiners = this.relatedUserRecordsToArray(relatedExaminers);
        setlistofusersobj.setValueFromArray(examiners);
    },

    /**
     * @private
     */
    onAddExaminers: function() {
        //this.down('studentsmanager_studentsgrid').selModel.selectAll();
        this.onSetExaminers(true);
    },

    /**
     * @private
     */
    onReplaceExaminers: function() {
        this.onSetExaminers(false);
    },

    /**
     * @private
     */
    onClearExaminers: function() {
        if(this.noneSelected()) {
            this.onSelectNone();
            return;
        }

        Ext.MessageBox.show({
            title: 'Confirm clear examiners?',
            msg: 'Are you sure you want to clear examiners on all the selected groups?',
            buttons: Ext.Msg.YESNO,
            icon: Ext.Msg.WARNING,
            scope: this,
            fn: function(btn) {
                if(btn == 'yes') {
                    this.down('studentsmanager_studentsgrid').performActionOnSelected({
                        scope: this,
                        callback: this.setExaminers,
                        extraArgs: [[], false]
                    });
                }
            }
        });
    },

    /**
     * @private
     */
    setExaminersOnSelected: function(setlistofusersobj, usernames, append) {
        setlistofusersobj.up('window').close();
        this.down('studentsmanager_studentsgrid').performActionOnSelected({
            scope: this,
            callback: this.setExaminers,
            extraArgs: [usernames, append]
        });
    },

    /**
     * @private
     */
    setExaminers: function(record, index, totalSelectedGroups, usernames, append) {
        var msg = Ext.String.format('Setting examiners on group {0}/{1}', index, totalSelectedGroups);
        this.getEl().mask(msg);

        if(append) {
            usernames = Ext.Array.merge(usernames, record.data.examiners__username);
        };

        var editRecord = this.createRecordFromStoreRecord(record);
        editRecord.data.fake_examiners = usernames;
        editRecord.save({
            failure: function() {
                console.error('Failed to save record');
            }
        });

        if(index == totalSelectedGroups) {
            this.loadFirstPage();
            this.getEl().unmask();
        }
    }
});
<commit_msg>apps.administrator...StudentsManagerManageExaminers: Better help.<commit_after>/** The examiner management methods for StudentsManager.
 *
 * Note that this class depends on createRecordFromStoreRecord(),
 * onSelectNone() and loadFirstPage() from StudentsManager to be available. */
Ext.define('devilry.administrator.studentsmanager.StudentsManagerManageExaminers', {

    randomDistResultTpl: Ext.create('Ext.XTemplate',
        '
The selected examiners got the following number of groups:
',
        '
',
        '<tpl for="result">',
        '
{examiner}: {groups.length}
',
        '</tpl>',
        '
'
    ),

    /**
     * @private
     */
    onRandomDistributeExaminers: function() {
        if(this.noneSelected()) {
            this.onSelectNone();
            return;
        }
        var win = Ext.widget('window', {
            title: 'Select examiners',
            modal: true,
            width: 500,
            height: 400,
            maximizable: true,
            layout: 'fit',
            items: {
                xtype: 'setlistofusers',
                //usernames: ['donald', 'scrooge', 'daisy', 'clarabelle'],
                usernames: [],
                helptext: '
The username of a single examiner on each line. Example:
',
                listeners: {
                    scope: this,
                    saveClicked: function(setlistofusersobj, usernames) {
                        this.randomDistributeExaminersOnSelected(setlistofusersobj, usernames);
                    }
                },

                extraToolbarButtons: [{
                    xtype: 'button',
                    scale: 'large',
                    text: Ext.String.format('Import examiners registered in {0}', DevilrySettings.DEVILRY_SYNCSYSTEM),
                    listeners: {
                        scope: this,
                        click: this.onImportRelatedExaminers
                    }
                }]
            }
        });
        win.show();
    },

    /**
     * @private
     */
    randomDistributeExaminersOnSelected: function(setlistofusersobj, examiners) {
        setlistofusersobj.up('window').close();

        this._randomDistributeTmp = {
            remainingExaminers: Ext.Array.clone(examiners),
            allExaminers: examiners,
            totExaminers: examiners.length,
            result: {}
        };
        Ext.each(examiners, function(examiner, index) {
            this._randomDistributeTmp.result[examiner] = [];
        }, this);

        this.down('studentsmanager_studentsgrid').performActionOnSelected({
            scope: this,
            callback: this.randomDistributeExaminers,
            extraArgs: []
        });
    },

    /**
     * @private
     */
    getRandomExaminer: function() {
        var numRemainingExaminers = this._randomDistributeTmp.remainingExaminers.length;
        var randomIndex = Math.floor(Math.random() * (numRemainingExaminers));
        return this._randomDistributeTmp.remainingExaminers[randomIndex];
    },

    /**
     * @private
     */
    removeExaminerIfEnoughStudents: function(examiner, totalSelectedGroups) {
        var totExaminers = this._randomDistributeTmp.totExaminers;
        var groupsPerExaminer = Math.ceil(totalSelectedGroups/totExaminers);
        if(this._randomDistributeTmp.result[examiner].length === groupsPerExaminer) {
            Ext.Array.remove(this._randomDistributeTmp.remainingExaminers, examiner);
        }
    },

    /**
     * @private
     */
    showRandomDistributeResults: function() {
        //console.log(this._randomDistributeTmp.result);
        var resultArray = [];
        Ext.each(this._randomDistributeTmp.allExaminers, function(examiner, index) {
            resultArray.push({
                examiner: examiner,
                groups: this._randomDistributeTmp.result[examiner]
            });
        }, this);

        Ext.MessageBox.show({
            title: 'Random distribution of examiners complete',
            msg: this.randomDistResultTpl.apply({result: resultArray}),
            buttons: Ext.Msg.OK,
            scope: this
        });
    },

    /**
     * @private
     */
    randomDistributeExaminers: function(record, index, totalSelectedGroups) {
        var msg = Ext.String.format('Random distributing examiner to group {0}/{1}', index, totalSelectedGroups);
        this.getEl().mask(msg);

        var editRecord = this.createRecordFromStoreRecord(record);
        var examiner = this.getRandomExaminer();
        this._randomDistributeTmp.result[examiner].push(editRecord);
        this.removeExaminerIfEnoughStudents(examiner, totalSelectedGroups);

        editRecord.data.fake_examiners = [examiner];
        editRecord.save({
            failure: function() {
                console.error('Failed to save record');
            }
        });

        if(index == totalSelectedGroups) {
            this.loadFirstPage();
            this.getEl().unmask();
            this.showRandomDistributeResults();
        }
    },

    /**
     * @private
     */
    onSetExaminers: function(append) {
        //this.down('studentsmanager_studentsgrid').selModel.selectAll();
        if(this.noneSelected()) {
            this.onSelectNone();
            return;
        }
        var helptext = '
The username of a single examiner on each line.' +
            (append? '': ' Current examiners will be replaced.') +
            '

Example:
';
        var win = Ext.widget('window', {
            title: (append? 'Add examiners': 'Replace examiners') + ' - select examiners',
            modal: true,
            width: 500,
            height: 400,
            maximizable: true,
            layout: 'fit',
            items: {
                xtype: 'setlistofusers',
                //usernames: ['donald', 'scrooge'],
                usernames: [],
                helptext: helptext,
                listeners: {
                    scope: this,
                    saveClicked: function(setlistofusersobj, usernames) {
                        this.setExaminersOnSelected(setlistofusersobj, usernames, append);
                    }
                },

                extraToolbarButtons: [{
                    xtype: 'button',
                    scale: 'large',
                    text: Ext.String.format('Import examiners registered in {0}', DevilrySettings.DEVILRY_SYNCSYSTEM),
                    listeners: {
                        scope: this,
                        click: this.onImportRelatedExaminers
                    }
                }]
            },
        });
        win.show();
    },

    onImportRelatedExaminers: function(button) {
        var setlistofusersobj = button.up('setlistofusers');
        this.loadAllRelatedExaminers({
            scope: this,
            callback: this.importRelatedExaminers,
            args: [setlistofusersobj]
        });
    },

    importRelatedExaminers: function(relatedExaminers, setlistofusersobj) {
        var examiners = this.relatedUserRecordsToArray(relatedExaminers);
        setlistofusersobj.setValueFromArray(examiners);
    },

    /**
     * @private
     */
    onAddExaminers: function() {
        this.onSetExaminers(true);
    },

    /**
     * @private
     */
    onReplaceExaminers: function() {
        this.onSetExaminers(false);
    },

    /**
     * @private
     */
    onClearExaminers: function() {
        if(this.noneSelected()) {
            this.onSelectNone();
            return;
        }

        Ext.MessageBox.show({
            title: 'Confirm clear examiners?',
            msg: 'Are you sure you want to clear examiners on all the selected groups?',
            buttons: Ext.Msg.YESNO,
            icon: Ext.Msg.WARNING,
            scope: this,
            fn: function(btn) {
                if(btn == 'yes') {
                    this.down('studentsmanager_studentsgrid').performActionOnSelected({
                        scope: this,
                        callback: this.setExaminers,
                        extraArgs: [[], false]
                    });
                }
            }
        });
    },

    /**
     * @private
     */
    setExaminersOnSelected: function(setlistofusersobj, usernames, append) {
        setlistofusersobj.up('window').close();
        this.down('studentsmanager_studentsgrid').performActionOnSelected({
            scope: this,
            callback: this.setExaminers,
            extraArgs: [usernames, append]
        });
    },

    /**
     * @private
     */
    setExaminers: function(record, index, totalSelectedGroups, usernames, append) {
        var msg = Ext.String.format('Setting examiners on group {0}/{1}', index, totalSelectedGroups);
        this.getEl().mask(msg);

        if(append) {
            usernames = Ext.Array.merge(usernames, record.data.examiners__username);
        };

        var editRecord = this.createRecordFromStoreRecord(record);
        editRecord.data.fake_examiners = usernames;
        editRecord.save({
            failure: function() {
                console.error('Failed to save record');
            }
        });

        if(index == totalSelectedGroups) {
            this.loadFirstPage();
            this.getEl().unmask();
        }
    }
});
<|endoftext|>


<commit_before>import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from '../reducers'
import App from './App'

let store = createStore(todoApp)

const Index = () => (
  <Provider store={store}>
    <App />
  </Provider>
)

export default Index
<commit_msg>remove unneeded react dom<commit_after>import React from 'react'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from '../reducers'
import App from './App'

let store = createStore(todoApp)

const Index = () => (
  <Provider store={store}>
    <App />
  </Provider>
)

export default Index
<|endoftext|>


<commit_before>var _ = require('grunt').util._;
var files = require('../files');
var glob = require('glob');

var jar = glob.sync('node_modules/protractor/selenium/selenium-server-standalone-2.*.jar')[0];
var chromeDriver = process.cwd() + '/node_modules/protractor/selenium/chromedriver';

var options = {
  configFile: 'test/e2e/env/config.js',
  args: {}
};

var args = {
  specs: [files.e2eTests],
  framework: 'jasmine',
  allScriptsTimeout: 120000
};

function extendOptions(addArgs) {
  return _.extend({}, options, {args: _.extend({}, args, addArgs)});
}

module.exports = {
  single: {
    options: extendOptions({
      chromeDriver: chromeDriver,
      seleniumServerJar: jar
    })
  },
  tdd: {
    options: extendOptions({
      chromeDriver: chromeDriver,
      seleniumAddress: 'http://localhost:4444/wd/hub'
    })
  }
};
<commit_msg>Add --debug option to protractor<commit_after>var _ = require('grunt').util._;
var files = require('../files');
var glob = require('glob');
var grunt = require('grunt');
var isDebug = !!grunt.option('debug');

var jar = glob.sync('node_modules/protractor/selenium/selenium-server-standalone-2.*.jar')[0];
var chromeDriver = process.cwd() + '/node_modules/protractor/selenium/chromedriver';

var options = {
  debug: debug,
  configFile: 'test/e2e/env/config.js',
  args: {}
};

var args = {
  specs: [files.e2eTests],
  framework: 'jasmine',
  allScriptsTimeout: 120000
};

function extendOptions(addArgs) {
  return _.extend({}, options, {args: _.extend({}, args, addArgs)});
}

module.exports = {
  single: {
    options: extendOptions({
      chromeDriver: chromeDriver,
      seleniumServerJar: jar
    })
  },
  tdd: {
    options: extendOptions({
      chromeDriver: chromeDriver,
      seleniumAddress: 'http://localhost:4444/wd/hub'
    })
  }
};
<|endoftext|>