<commit_before>'use strict';

angular.module('openhimConsoleApp')
  .controller('ExportImportCtrl', function ($upload, $scope, $modal, Api) {

    /***************************************************/
    /**         Initial page load functions           **/
    /***************************************************/

    $scope.downloadLink = '';

    // function to reset export options to default
    $scope.resetExportOptions = function(){
      // assign all collections to select exports object
      $scope.selectedExports = {};
      $scope.selectedExports.Users = $scope.exportCollections.Users;
      $scope.selectedExports.Clients = $scope.exportCollections.Clients;
      $scope.selectedExports.Channels = $scope.exportCollections.Channels;
      $scope.selectedExports.Mediators = $scope.exportCollections.Mediators;
      $scope.selectedExports.ContactGroups = $scope.exportCollections.ContactGroups;

      // set show all records to false - Entire collections being exported
      $scope.showRecordOptions = {};
      $scope.showRecordOptions.Users = false;
      $scope.showRecordOptions.Clients = false;
      $scope.showRecordOptions.Channels = false;
      $scope.showRecordOptions.Mediators = false;
      $scope.showRecordOptions.ContactGroups = false;
    };

    // Make API requests for the export configuration options
    var Users = Api.Users.query();
    var Clients = Api.Clients.query();
    var Channels = Api.Channels.query();
    var Mediators = Api.Mediators.query();
    var ContactGroups = Api.ContactGroups.query();

    // set up settings object
    $scope.exportSettings = {};
    $scope.exportSettings.removeIds = true;

    // Assign API collections to export options object
    $scope.exportCollections = {};
    $scope.exportCollections.Users = Users;
    $scope.exportCollections.Clients = Clients;
    $scope.exportCollections.Channels = Channels;
    $scope.exportCollections.Mediators = Mediators;
    $scope.exportCollections.ContactGroups = ContactGroups;

    // set inital reset ( default export option )
    $scope.resetExportOptions();

    /***************************************************/
    /**         Initial page load functions           **/
    /***************************************************/

    /****************************************/
    /**         Export Functions           **/
    /****************************************/

    // function to toggle entire collection
    $scope.toggleCollectionExportSelection = function(model, collection) {
      if ( $scope.selectedExports[model] === collection) {
        $scope.selectedExports[model] = [];
        $scope.showRecordOptions[model] = true;
      }else {
        $scope.selectedExports[model] = collection;
        $scope.showRecordOptions[model] = false;
      }
    };

    // function to toggle specific records
    $scope.toggleRecordExportSelection = function(model, record) {

      var idx = $scope.selectedExports[model].indexOf(record);

      // is currently selected
      if (idx > -1) {
        $scope.selectedExports[model].splice(idx, 1);
      }else {
        // is newly selected
        $scope.selectedExports[model].push(record);
      }
    };

    // function to remove certain properties from export object
    $scope.removeProperties = function(obj) {

      var propertyID = '_id';
      var propertyV = '__v';

      for (var prop in obj) {
        if (prop === propertyID || prop === propertyV) {
          delete obj[prop];
        } else if ( typeof obj[prop] === 'object' || obj[prop] instanceof Array ){
          $scope.removeProperties(obj[prop]);
        }
      }

      return obj;
    };

    var NewBlob = function(data, datatype){
      var out;
      try {
        out = new Blob([data], {type: datatype});
      }
      catch (e) {

        var BlobBuilder = function(){
          window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
        };

        if (e.name === 'TypeError' && window.BlobBuilder) {
          var bb = new BlobBuilder();
          bb.append(data);
          out = bb.getBlob(datatype);
        }
        else if (e.name === 'InvalidStateError') {
          // InvalidStateError (tested on FF13 WinXP)
          out = new Blob([data], {type: datatype});
        }
        else {
          out = { error: 'Browser not supported for Blob creation' };
          // We're screwed, blob constructor unsupported entirely
        }
      }
      return out;
    };

    // function to create the export file object
    $scope.createExportFile = function(){

      var exportData = angular.copy( $scope.selectedExports );
      var textFile = null;

      // create the export script as a blob file
      var makeTextFile = function (text) {
        //var data = new Blob([text], {type: 'application/json'});
        var data = new NewBlob(text, 'application/json');

        // if blob error exist
        if ( data.error ){
          return;
        }else{
          // If we are replacing a previously generated file we need to
          // manually revoke the object URL to avoid memory leaks.
          if (textFile !== null) {
            window.URL.revokeObjectURL(textFile);
          }

          textFile = window.URL.createObjectURL(data);
          return textFile;
        }
      };

      if ( $scope.exportSettings.removeIds === false ){
        exportData = JSON.stringify( exportData, null, 2 );
        $scope.importScriptName = 'openhim-update.json';
      }else{
        exportData = JSON.stringify( $scope.removeProperties( exportData ), null, 2 );
        $scope.importScriptName = 'openhim-insert.json';
      }

      // assign download link and show download button
      var blobLink = makeTextFile( exportData );
      if ( blobLink ){
        $scope.downloadLink = blobLink;
      }

    };

    // function for when the download button is clicked
    $scope.downloadExportFile = function(){
      //reset download link and remove download button
      $scope.downloadLink = '';
    };

    /****************************************/
    /**         Export Functions           **/
    /****************************************/

    /****************************************/
    /**         Import Functions           **/
    /****************************************/

    // import failed function
    var importFail = function(model, value, err){
      $scope.failedImports.push({ model:model, record: value, error: err.data, status: err.status });
      $scope.importFail++;
    };

    // import success function
    var importSuccess = function(){
      $scope.importSuccess++;
    };

    // function to run import file
    $scope.runImportFile = function(data){

      // set counter variables
      $scope.importFail = 0;
      $scope.importSuccess = 0;
      $scope.failedImports = [];
      $scope.importProgressStatus = 0;
      $scope.importProgressType = '';

      // convert to json object
      data = JSON.parse(data);

      var totalRecords = 0;
      totalRecords += data.Clients.length;
      totalRecords += data.Channels.length;
      totalRecords += data.ContactGroups.length;
      totalRecords += data.Users.length;
      totalRecords += data.Mediators.length;

      var doneItems = 0;

      //loop through each collection in object
      angular.forEach(data, function(modelRecords, model) {

        // loop through each record
        angular.forEach(modelRecords, function(value) {

          var record;
          var insertParams = {};

          // check model to determine which API to call
          switch(model) {
            case 'Clients':
              record = new Api.Clients( value );
              break;
            case 'Channels':
              record = new Api.Channels( value );
              break;
            case 'ContactGroups':
              record = new Api.ContactGroups( value );
              break;
            case 'Mediators':
              if ( value._id ){
                delete value._id;
              }
              record = new Api.Mediators( value );
              insertParams.urn = '';
              break;
            case 'Users':
              record = new Api.Users( value );
              insertParams.email = '';
              break;
            default:
              // no default yet
          }

          // if record has _id then do update
          if ( record._id ){
            record.$update(function(){
              importSuccess();
            }, function(err){
              importFail(model, value, err);
            });
          }else{
            record.$save(insertParams, function(){
              importSuccess();
            }, function(err){
              importFail(model, value, err);
            });
          }

          doneItems++;
          $scope.importProgressStatus = Math.floor( doneItems / totalRecords );

          // update progress bar too 100%
          if( doneItems === totalRecords ){
            $scope.importProgressStatus = 100;
            $scope.importProgressType = 'success';
          }

        });

      });

    };

    // watch if files have been dropped
    $scope.$watch('files', function () {
      $scope.upload($scope.files);
    });

    // function to upload the file
    $scope.upload = function (files) {
      if (files && files.length) {

        var reader = new FileReader();

        // onload function used by the reader
        reader.onload = function(event) {
          var data = event.target.result;
          // read the import script data and process
          $scope.runImportFile(data);
        };

        // foreach uploaded file
        for (var i = 0; i < files.length; i++) {
          var file = files[i];

          // when the file is read it triggers the onload event function above.
          reader.readAsText(file);
        }
      }
    };

    /****************************************/
    /**         Import Functions           **/
    /****************************************/

  });
<commit_msg>Config import: added null checks<commit_after>'use strict';

angular.module('openhimConsoleApp')
  .controller('ExportImportCtrl', function ($upload, $scope, $modal, Api) {

    /***************************************************/
    /**         Initial page load functions           **/
    /***************************************************/

    $scope.downloadLink = '';

    // function to reset export options to default
    $scope.resetExportOptions = function(){
      // assign all collections to select exports object
      $scope.selectedExports = {};
      $scope.selectedExports.Users = $scope.exportCollections.Users;
      $scope.selectedExports.Clients = $scope.exportCollections.Clients;
      $scope.selectedExports.Channels = $scope.exportCollections.Channels;
      $scope.selectedExports.Mediators = $scope.exportCollections.Mediators;
      $scope.selectedExports.ContactGroups = $scope.exportCollections.ContactGroups;

      // set show all records to false - Entire collections being exported
      $scope.showRecordOptions = {};
      $scope.showRecordOptions.Users = false;
      $scope.showRecordOptions.Clients = false;
      $scope.showRecordOptions.Channels = false;
      $scope.showRecordOptions.Mediators = false;
      $scope.showRecordOptions.ContactGroups = false;
    };

    // Make API requests for the export configuration options
    var Users = Api.Users.query();
    var Clients = Api.Clients.query();
    var Channels = Api.Channels.query();
    var Mediators = Api.Mediators.query();
    var ContactGroups = Api.ContactGroups.query();

    // set up settings object
    $scope.exportSettings = {};
    $scope.exportSettings.removeIds = true;

    // Assign API collections to export options object
    $scope.exportCollections = {};
    $scope.exportCollections.Users = Users;
    $scope.exportCollections.Clients = Clients;
    $scope.exportCollections.Channels = Channels;
    $scope.exportCollections.Mediators = Mediators;
    $scope.exportCollections.ContactGroups = ContactGroups;

    // set inital reset ( default export option )
    $scope.resetExportOptions();

    /***************************************************/
    /**         Initial page load functions           **/
    /***************************************************/

    /****************************************/
    /**         Export Functions           **/
    /****************************************/

    // function to toggle entire collection
    $scope.toggleCollectionExportSelection = function(model, collection) {
      if ( $scope.selectedExports[model] === collection) {
        $scope.selectedExports[model] = [];
        $scope.showRecordOptions[model] = true;
      }else {
        $scope.selectedExports[model] = collection;
        $scope.showRecordOptions[model] = false;
      }
    };

    // function to toggle specific records
    $scope.toggleRecordExportSelection = function(model, record) {

      var idx = $scope.selectedExports[model].indexOf(record);

      // is currently selected
      if (idx > -1) {
        $scope.selectedExports[model].splice(idx, 1);
      }else {
        // is newly selected
        $scope.selectedExports[model].push(record);
      }
    };

    // function to remove certain properties from export object
    $scope.removeProperties = function(obj) {

      var propertyID = '_id';
      var propertyV = '__v';

      for (var prop in obj) {
        if (prop === propertyID || prop === propertyV) {
          delete obj[prop];
        } else if ( typeof obj[prop] === 'object' || obj[prop] instanceof Array ){
          $scope.removeProperties(obj[prop]);
        }
      }

      return obj;
    };

    var NewBlob = function(data, datatype){
      var out;
      try {
        out = new Blob([data], {type: datatype});
      }
      catch (e) {

        var BlobBuilder = function(){
          window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
        };

        if (e.name === 'TypeError' && window.BlobBuilder) {
          var bb = new BlobBuilder();
          bb.append(data);
          out = bb.getBlob(datatype);
        }
        else if (e.name === 'InvalidStateError') {
          // InvalidStateError (tested on FF13 WinXP)
          out = new Blob([data], {type: datatype});
        }
        else {
          out = { error: 'Browser not supported for Blob creation' };
          // We're screwed, blob constructor unsupported entirely
        }
      }
      return out;
    };

    // function to create the export file object
    $scope.createExportFile = function(){

      var exportData = angular.copy( $scope.selectedExports );
      var textFile = null;

      // create the export script as a blob file
      var makeTextFile = function (text) {
        //var data = new Blob([text], {type: 'application/json'});
        var data = new NewBlob(text, 'application/json');

        // if blob error exist
        if ( data.error ){
          return;
        }else{
          // If we are replacing a previously generated file we need to
          // manually revoke the object URL to avoid memory leaks.
          if (textFile !== null) {
            window.URL.revokeObjectURL(textFile);
          }

          textFile = window.URL.createObjectURL(data);
          return textFile;
        }
      };

      if ( $scope.exportSettings.removeIds === false ){
        exportData = JSON.stringify( exportData, null, 2 );
        $scope.importScriptName = 'openhim-update.json';
      }else{
        exportData = JSON.stringify( $scope.removeProperties( exportData ), null, 2 );
        $scope.importScriptName = 'openhim-insert.json';
      }

      // assign download link and show download button
      var blobLink = makeTextFile( exportData );
      if ( blobLink ){
        $scope.downloadLink = blobLink;
      }

    };

    // function for when the download button is clicked
    $scope.downloadExportFile = function(){
      //reset download link and remove download button
      $scope.downloadLink = '';
    };

    /****************************************/
    /**         Export Functions           **/
    /****************************************/

    /****************************************/
    /**         Import Functions           **/
    /****************************************/

    // import failed function
    var importFail = function(model, value, err){
      $scope.failedImports.push({ model:model, record: value, error: err.data, status: err.status });
      $scope.importFail++;
    };

    // import success function
    var importSuccess = function(){
      $scope.importSuccess++;
    };

    // function to run import file
    $scope.runImportFile = function(data){

      // set counter variables
      $scope.importFail = 0;
      $scope.importSuccess = 0;
      $scope.failedImports = [];
      $scope.importProgressStatus = 0;
      $scope.importProgressType = '';

      // convert to json object
      data = JSON.parse(data);

      var totalRecords = 0;
      if (data.Clients) {
        totalRecords += data.Clients.length;
      }
      if (data.Channels) {
        totalRecords += data.Channels.length;
      }
      if (data.ContactGroups) {
        totalRecords += data.ContactGroups.length;
      }
      if (data.Users) {
        totalRecords += data.Users.length;
      }
      if (data.Mediators) {
        totalRecords += data.Mediators.length;
      }

      var doneItems = 0;

      //loop through each collection in object
      angular.forEach(data, function(modelRecords, model) {

        // loop through each record
        angular.forEach(modelRecords, function(value) {

          var record;
          var insertParams = {};

          // check model to determine which API to call
          switch(model) {
            case 'Clients':
              record = new Api.Clients( value );
              break;
            case 'Channels':
              record = new Api.Channels( value );
              break;
            case 'ContactGroups':
              record = new Api.ContactGroups( value );
              break;
            case 'Mediators':
              if ( value._id ){
                delete value._id;
              }
              record = new Api.Mediators( value );
              insertParams.urn = '';
              break;
            case 'Users':
              record = new Api.Users( value );
              insertParams.email = '';
              break;
            default:
              // no default yet
          }

          // if record has _id then do update
          if ( record._id ){
            record.$update(function(){
              importSuccess();
            }, function(err){
              importFail(model, value, err);
            });
          }else{
            record.$save(insertParams, function(){
              importSuccess();
            }, function(err){
              importFail(model, value, err);
            });
          }

          doneItems++;
          $scope.importProgressStatus = Math.floor( doneItems / totalRecords );

          // update progress bar too 100%
          if( doneItems === totalRecords ){
            $scope.importProgressStatus = 100;
            $scope.importProgressType = 'success';
          }

        });

      });

    };

    // watch if files have been dropped
    $scope.$watch('files', function () {
      $scope.upload($scope.files);
    });

    // function to upload the file
    $scope.upload = function (files) {
      if (files && files.length) {

        var reader = new FileReader();

        // onload function used by the reader
        reader.onload = function(event) {
          var data = event.target.result;
          // read the import script data and process
          $scope.runImportFile(data);
        };

        // foreach uploaded file
        for (var i = 0; i < files.length; i++) {
          var file = files[i];

          // when the file is read it triggers the onload event function above.
          reader.readAsText(file);
        }
      }
    };

    /****************************************/
    /**         Import Functions           **/
    /****************************************/

  });
<|endoftext|>


<commit_before>/**
 * (c) 2016 Tieto Finland Oy
 * Licensed under the MIT license.
 */
'use strict';

/**
 * @ngdoc function
 * @name dashboard.controller:MeetingCtrl
 * @description
 * # MeetingCtrl
 * Controller of the dashboard
 */
angular.module('dashboard')
    .controller('meetingCtrl', ['$log', 'AhjoMeetingSrv', '$stateParams', '$rootScope', '$scope', '$state', 'CONST', 'StorageSrv', 'AttachmentData', 'ListData', function ($log, AhjoMeetingSrv, $stateParams, $rootScope, $scope, $state, CONST, StorageSrv, AttachmentData, ListData) {
        $log.debug("meetingCtrl: CONTROLLER");
        var self = this;
        var isMobile = $rootScope.isMobile;
        self.upperUrl = {};
        self.lowerUrl = {};
        self.error = null;
        self.topic = StorageSrv.get(CONST.KEY.TOPIC);
        self.blockMode = CONST.BLOCKMODE.BOTH;
        self.header = '';
        $rootScope.menu = $stateParams.menu;

        self.topicData = null;
        self.attachmentData = null;
        self.decisionData = null;
        self.additionalMaterialData = null;

        function setData(topic) {
            if (topic instanceof Object) {
                self.header = topic.topicTitle;
                if (topic.esitykset instanceof Array) {
                    var item = topic.esitykset[0];
                    if (item instanceof Object) {
                        self.topicData = AttachmentData.create((item.documentTitle ? item.documentTitle : 'STR_TOPIC'), item.link);
                    }
                }

                self.lowerUrl = {};
                self.upperUrl = (self.topicData && self.topicData.link) ? self.topicData.link : {};

                self.attachmentData = ListData.createAttachmentList('STR_ATTACHMENTS', topic.attachment);
                self.decisionData = ListData.createDecisionList('STR_DECISION_HISTORY', topic.decision);
                self.additionalMaterialData = ListData.createAdditionalMaterialList('STR_ADDITIONAL_MATERIAL', topic.additionalMaterial);
            }
            else {
                self.lowerUrl = {};
                self.upperUrl = {};
            }
        }

        self.upperClicked = function () {
            self.blockMode = (self.blockMode === CONST.BLOCKMODE.BOTH || self.blockMode === CONST.BLOCKMODE.LOWER) ? CONST.BLOCKMODE.UPPER : CONST.BLOCKMODE.BOTH;
        };

        self.lowerClicked = function () {
            self.blockMode = (self.blockMode === CONST.BLOCKMODE.BOTH || self.blockMode === CONST.BLOCKMODE.UPPER) ? CONST.BLOCKMODE.LOWER : CONST.BLOCKMODE.BOTH;
        };

        self.topicClicked = function () {
            if (isMobile) {
                StorageSrv.set(CONST.KEY.LISTPDF_DATA, self.topicData);
                $state.go(CONST.APPSTATE.TOPIC);
            }
            else {

            }
        };

        self.attachmentClicked = function (attachment) {
            if (isMobile) {
                StorageSrv.set(CONST.KEY.SELECTION_DATA, self.attachmentData);
                $state.go(CONST.APPSTATE.LIST);
            }
            else if (attachment instanceof Object) {
                self.lowerUrl = attachment.link ? attachment.link : {};
            }
        };

        self.decisionClicked = function (decision) {
            if (isMobile) {
                StorageSrv.set(CONST.KEY.SELECTION_DATA, self.decisionData);
                $state.go(CONST.APPSTATE.LIST);
            }
            else if (decision instanceof Object) {
                self.lowerUrl = decision.link ? decision.link : {};
            }
        };

        self.additionalMaterialClicked = function (material) {
            if (isMobile) {
                StorageSrv.set(CONST.KEY.SELECTION_DATA, self.additionalMaterialData);
                $state.go(CONST.APPSTATE.LIST);
            }
            else if (material instanceof Object) {
                self.lowerUrl = material.link ? material.link : {};
            }
        };

        self.isBothMode = function () {
            return self.blockMode === CONST.BLOCKMODE.BOTH;
        };

        self.isUpperMode = function () {
            return self.blockMode === CONST.BLOCKMODE.UPPER;
        };

        self.isLowerMode = function () {
            return self.blockMode === CONST.BLOCKMODE.LOWER;
        };

        self.isSecret = function (item) {
            return (item && item.publicity) ? (item.publicity === CONST.PUBLICITY.SECRET) : false;
        };

        self.isUrlString = function (url) {
            return (url && (typeof url === "string") && url.length) ? true : false;
        };

        $scope.$watch(
            // This function returns the value being watched. It is called for each turn of the $digest loop
            function () {
                return StorageSrv.get(CONST.KEY.TOPIC);
            },
            function (newTopic, oldTopic) {
                if (newTopic !== oldTopic) {
                    self.topic = newTopic;
                    setData(self.topic);
                }
            }
            );

        $scope.$on('$destroy', function () {
            $log.debug("meetingCtrl: DESTROY");
        });

        setData(self.topic);
    }]);
<commit_msg>agenda item missing data handling improved<commit_after>/**
 * (c) 2016 Tieto Finland Oy
 * Licensed under the MIT license.
 */
'use strict';

/**
 * @ngdoc function
 * @name dashboard.controller:MeetingCtrl
 * @description
 * # MeetingCtrl
 * Controller of the dashboard
 */
angular.module('dashboard')
    .controller('meetingCtrl', ['$log', 'AhjoMeetingSrv', '$stateParams', '$rootScope', '$scope', '$state', 'CONST', 'StorageSrv', 'AttachmentData', 'ListData', function ($log, AhjoMeetingSrv, $stateParams, $rootScope, $scope, $state, CONST, StorageSrv, AttachmentData, ListData) {
        $log.debug("meetingCtrl: CONTROLLER");
        var self = this;
        var isMobile = $rootScope.isMobile;
        self.upperUrl = {};
        self.lowerUrl = {};
        self.error = null;
        self.topic = StorageSrv.get(CONST.KEY.TOPIC);
        self.blockMode = CONST.BLOCKMODE.BOTH;
        self.header = '';
        $rootScope.menu = $stateParams.menu;

        self.topicData = null;
        self.attachmentData = null;
        self.decisionData = null;
        self.additionalMaterialData = null;

        function setData(topic) {
            if (topic instanceof Object) {
                self.header = topic.topicTitle;
                if (topic.esitykset instanceof Array) {
                    var item = topic.esitykset[0];
                    if (item instanceof Object) {
                        self.topicData = AttachmentData.create((item.documentTitle ? item.documentTitle : 'STR_TOPIC'), item.link);
                    }
                    else {
                        self.topicData = null;
                    }
                }
                else {
                    self.topicData = null;
                }

                self.lowerUrl = {};
                self.upperUrl = (self.topicData && self.topicData.link) ? self.topicData.link : {};

                self.attachmentData = ListData.createAttachmentList('STR_ATTACHMENTS', topic.attachment);
                self.decisionData = ListData.createDecisionList('STR_DECISION_HISTORY', topic.decision);
                self.additionalMaterialData = ListData.createAdditionalMaterialList('STR_ADDITIONAL_MATERIAL', topic.additionalMaterial);
            }
            else {
                self.lowerUrl = {};
                self.upperUrl = {};
            }
        }

        self.upperClicked = function () {
            self.blockMode = (self.blockMode === CONST.BLOCKMODE.BOTH || self.blockMode === CONST.BLOCKMODE.LOWER) ? CONST.BLOCKMODE.UPPER : CONST.BLOCKMODE.BOTH;
        };

        self.lowerClicked = function () {
            self.blockMode = (self.blockMode === CONST.BLOCKMODE.BOTH || self.blockMode === CONST.BLOCKMODE.UPPER) ? CONST.BLOCKMODE.LOWER : CONST.BLOCKMODE.BOTH;
        };

        self.topicClicked = function () {
            if (isMobile) {
                StorageSrv.set(CONST.KEY.LISTPDF_DATA, self.topicData);
                $state.go(CONST.APPSTATE.TOPIC);
            }
            else {

            }
        };

        self.attachmentClicked = function (attachment) {
            if (isMobile) {
                StorageSrv.set(CONST.KEY.SELECTION_DATA, self.attachmentData);
                $state.go(CONST.APPSTATE.LIST);
            }
            else if (attachment instanceof Object) {
                self.lowerUrl = attachment.link ? attachment.link : {};
            }
        };

        self.decisionClicked = function (decision) {
            if (isMobile) {
                StorageSrv.set(CONST.KEY.SELECTION_DATA, self.decisionData);
                $state.go(CONST.APPSTATE.LIST);
            }
            else if (decision instanceof Object) {
                self.lowerUrl = decision.link ? decision.link : {};
            }
        };

        self.additionalMaterialClicked = function (material) {
            if (isMobile) {
                StorageSrv.set(CONST.KEY.SELECTION_DATA, self.additionalMaterialData);
                $state.go(CONST.APPSTATE.LIST);
            }
            else if (material instanceof Object) {
                self.lowerUrl = material.link ? material.link : {};
            }
        };

        self.isBothMode = function () {
            return self.blockMode === CONST.BLOCKMODE.BOTH;
        };

        self.isUpperMode = function () {
            return self.blockMode === CONST.BLOCKMODE.UPPER;
        };

        self.isLowerMode = function () {
            return self.blockMode === CONST.BLOCKMODE.LOWER;
        };

        self.isSecret = function (item) {
            return (item && item.publicity) ? (item.publicity === CONST.PUBLICITY.SECRET) : false;
        };

        self.isUrlString = function (url) {
            return (url && (typeof url === "string") && url.length) ? true : false;
        };

        $scope.$watch(
            // This function returns the value being watched. It is called for each turn of the $digest loop
            function () {
                return StorageSrv.get(CONST.KEY.TOPIC);
            },
            function (newTopic, oldTopic) {
                if (newTopic !== oldTopic) {
                    self.topic = newTopic;
                    setData(self.topic);
                }
            }
            );

        $scope.$on('$destroy', function () {
            $log.debug("meetingCtrl: DESTROY");
        });

        setData(self.topic);
    }]);
<|endoftext|>


<commit_before>var {getTypeBonus, calcDefenseDebuff, calcLBHaisuiValue, isDarkOpus} = require('./global_logic.js');

describe('#getTypeBonus', () => {
    test('when self element and enemy element is not set, type bonus is 1', () => {
        expect(getTypeBonus(undefined, undefined)).toBe(1)
    });
});

describe('#calcDefenseDebuff', () => {
    test('when enemyDefense and defenseDebuff is not set, defense is 10', () => {
        expect(calcDefenseDebuff(undefined, undefined)).toBe(10);
    });

    test('when enemyDefense is not set, the default value is 10', () => {
        expect(calcDefenseDebuff(undefined, 0)).toBe(10);
        expect(calcDefenseDebuff(undefined, 50)).toBe(5);
    });

    test('when defenseDebuff is not set, the default value is 0', () => {
        expect(calcDefenseDebuff(10, undefined)).toBe(10);
        expect(calcDefenseDebuff(20, undefined)).toBe(20);
    });

    test('when defenseDebuff was negative numbers, defense is up', () => {
        expect(calcDefenseDebuff(10, -50)).toBe(15);
    });

    test('when defense debuff is over 100, defense is 1', () => {
        expect(calcDefenseDebuff(10, 100)).toBe(1);
    });
});

describe('#calcLBHaisui', () => {
    const haisui = calcLBHaisuiValue.bind(null, 'EXLBHaisui');
    const konshin = calcLBHaisuiValue.bind(null, 'EXLBKonshin');

    const exlbHaisuiMaxTable = [
        [1, 0.05],
        [2, 0.06],
        [3, 0.075],
        [4, 0.09],
        [5, 0.10],
        [6, 0.11],
        [7, 0.12],
        [8, 0.125],
        [9, 0.1375],
        [10, 0.15],
    ];
    const exlbHaisuiMinTable = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    const exlbKonshinMaxTable = [
        [1, 0.03],
        [2, 0.04],
        [3, 0.05],
        [4, 0.06],
        [5, 0.07],
        [6, 0.08],
        [7, 0.09],
        [8, 0.10],
        [9, 0.11],
        [10, 0.12],
    ];
    const exlbKonshinMinTable = [
        [1, 0.01],
        [2, 0.01],
        [3, 0.02],
        [4, 0.02],
        [5, 0.03],
        [6, 0.03],
        [7, 0.03],
        [8, 0.04],
        [9, 0.04],
        [10, 0.04],
    ];

    test.each(exlbHaisuiMaxTable, 'Haisui max value', (amount, expected) => {
        expect(haisui(amount, 0.0)).toBeCloseTo(expected);
    });

    test.each(exlbHaisuiMinTable, 'Haisui min value (until HP 75.1%)', (amount) => {
        expect(haisui(amount, 1.0)).toBeCloseTo(0.01);
        expect(haisui(amount, 0.751)).toBeCloseTo(0.01);
    });

    test.each(exlbKonshinMaxTable, 'konshin max value', (amount, expected) => {
        expect(konshin(amount, 1.0)).toBeCloseTo(expected);
    });

    test.each(exlbKonshinMinTable, 'konshin min value', (amount, expected) => {
        expect(konshin(amount, 0.0)).toBeCloseTo(expected);
    });

    test('ignore unknown type arguments', () => {
        expect(calcLBHaisuiValue('unknown-type', 10, 0.0)).toBeCloseTo(0.0);
    });

    test('illegal amount numbers return 0.0', () => {
        expect(haisui(0, 0.0)).toBeCloseTo(0.0);
        expect(haisui(11, 0.0)).toBeCloseTo(0.0);
        expect(konshin(0, 0.0)).toBeCloseTo(0.0);
        expect(konshin(11, 0.0)).toBeCloseTo(0.0);
    });

    test.skip('illegal remainHP return ?', () => {
        // TODO: what illegal remainHP should return?
    });
});

describe('#isDarkOpus', () => {
    test('Checking Dark Opus arm', () => {
        expect(isDarkOpus({"name": "絶対否定の剣"})).toBeTruthy();
        expect(isDarkOpus({"name": "Sword of Renunciation"})).toBeTruthy();
        expect(isDarkOpus({"name": "永遠拒絶の槍"})).toBeTruthy();
        expect(isDarkOpus({"name": "Scythe of Repudiation"})).toBeTruthy();
        expect(isDarkOpus({"name": "Katana of Renunciation.Lvl185.Sl18+78"})).toBeTruthy();
        expect(isDarkOpus({"name": "永遠拒絶の杖Lv.26SLv.6+17"})).toBeTruthy();
    });

    test('Checking invalid arms', () => {
        expect(isDarkOpus(undefined)).toBeFalsy();
        expect(isDarkOpus({})).toBeFalsy();
        expect(isDarkOpus({"name": ""})).toBeFalsy();
        expect(isDarkOpus({"name": undefined})).toBeFalsy();
    });

    test('Checking non dark opus arms', () => {
        expect(isDarkOpus({"name": "Ultima Bow"})).toBeFalsy();
        expect(isDarkOpus({"name": "バハムートソード・フツルスLv.60SLv.4+13"})).toBeFalsy();
        expect(isDarkOpus({"name": "Katana of Repudiatio"})).toBeFalsy();
        expect(isDarkOpus({"name": "永遠拒絶大鎌"})).toBeFalsy();
        expect(isDarkOpus({"name": "Katana f Repudiation"})).toBeFalsy();
        expect(isDarkOpus({"name": "遠拒絶の太刀"})).toBeFalsy();
        expect(isDarkOpus({"name": "Staff of Repudition"})).toBeFalsy();
        expect(isDarkOpus({"name": "絶対力定の竪琴"})).toBeFalsy();
        expect(isDarkOpus({"name": "Staff of epudiation"})).toBeFalsy();
    });

});<commit_msg>Fix unittest for calcLBHaisui<commit_after>var {getTypeBonus, calcDefenseDebuff, calcLBHaisuiValue, isDarkOpus} = require('./global_logic.js');

describe('#getTypeBonus', () => {
    test('when self element and enemy element is not set, type bonus is 1', () => {
        expect(getTypeBonus(undefined, undefined)).toBe(1)
    });
});

describe('#calcDefenseDebuff', () => {
    test('when enemyDefense and defenseDebuff is not set, defense is 10', () => {
        expect(calcDefenseDebuff(undefined, undefined)).toBe(10);
    });

    test('when enemyDefense is not set, the default value is 10', () => {
        expect(calcDefenseDebuff(undefined, 0)).toBe(10);
        expect(calcDefenseDebuff(undefined, 50)).toBe(5);
    });

    test('when defenseDebuff is not set, the default value is 0', () => {
        expect(calcDefenseDebuff(10, undefined)).toBe(10);
        expect(calcDefenseDebuff(20, undefined)).toBe(20);
    });

    test('when defenseDebuff was negative numbers, defense is up', () => {
        expect(calcDefenseDebuff(10, -50)).toBe(15);
    });

    test('when defense debuff is over 100, defense is 1', () => {
        expect(calcDefenseDebuff(10, 100)).toBe(1);
    });
});

describe('#calcLBHaisui', () => {
    const haisui = calcLBHaisuiValue.bind(null, 'EXLBHaisui');
    const konshin = calcLBHaisuiValue.bind(null, 'EXLBKonshin');

    const exlbHaisuiMaxTable = [
        [1, 0.05],
        [2, 0.06],
        [3, 0.075],
        [4, 0.09],
        [5, 0.10],
        [6, 0.11],
        [7, 0.12],
        [8, 0.125],
        [9, 0.1375],
        [10, 0.15],
    ];
    const exlbHaisuiMinTable = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    const exlbKonshinMaxTable = [
        [1, 0.03],
        [2, 0.04],
        [3, 0.05],
        [4, 0.06],
        [5, 0.07],
        [6, 0.08],
        [7, 0.09],
        [8, 0.10],
        [9, 0.11],
        [10, 0.12],
    ];
    const exlbKonshinMinTable = [
        [1, 0.01],
        [2, 0.01],
        [3, 0.02],
        [4, 0.02],
        [5, 0.03],
        [6, 0.03],
        [7, 0.03],
        [8, 0.04],
        [9, 0.04],
        [10, 0.04],
    ];

    test.each(exlbHaisuiMaxTable)('Haisui slv%d max is %d', (amount, expected) => {
        expect(haisui(amount, 0.0)).toBeCloseTo(expected);
    });

    test.each(exlbHaisuiMinTable)('Haisui slv%d min is 0.01 (until HP 75.1%)', (amount) => {
        expect(haisui(amount, 1.0)).toBeCloseTo(0.01);
        expect(haisui(amount, 0.751)).toBeCloseTo(0.01);
    });

    test.each(exlbKonshinMaxTable)('konshin slv%d max is %d', (amount, expected) => {
        expect(konshin(amount, 1.0)).toBeCloseTo(expected);
    });

    test.each(exlbKonshinMinTable)('konshin slv%d min is %d', (amount, expected) => {
        expect(konshin(amount, 0.0)).toBeCloseTo(expected);
    });

    test('ignore unknown type arguments', () => {
        expect(calcLBHaisuiValue('unknown-type', 10, 0.0)).toBeCloseTo(0.0);
    });

    test('illegal amount numbers return 0.0', () => {
        expect(haisui(0, 0.0)).toBeCloseTo(0.0);
        expect(haisui(11, 0.0)).toBeCloseTo(0.0);
        expect(konshin(0, 0.0)).toBeCloseTo(0.0);
        expect(konshin(11, 0.0)).toBeCloseTo(0.0);
    });

    test.skip('illegal remainHP return ?', () => {
        // TODO: what illegal remainHP should return?
    });
});

describe('#isDarkOpus', () => {
    test('Checking Dark Opus arm', () => {
        expect(isDarkOpus({"name": "絶対否定の剣"})).toBeTruthy();
        expect(isDarkOpus({"name": "Sword of Renunciation"})).toBeTruthy();
        expect(isDarkOpus({"name": "永遠拒絶の槍"})).toBeTruthy();
        expect(isDarkOpus({"name": "Scythe of Repudiation"})).toBeTruthy();
        expect(isDarkOpus({"name": "Katana of Renunciation.Lvl185.Sl18+78"})).toBeTruthy();
        expect(isDarkOpus({"name": "永遠拒絶の杖Lv.26SLv.6+17"})).toBeTruthy();
    });

    test('Checking invalid arms', () => {
        expect(isDarkOpus(undefined)).toBeFalsy();
        expect(isDarkOpus({})).toBeFalsy();
        expect(isDarkOpus({"name": ""})).toBeFalsy();
        expect(isDarkOpus({"name": undefined})).toBeFalsy();
    });

    test('Checking non dark opus arms', () => {
        expect(isDarkOpus({"name": "Ultima Bow"})).toBeFalsy();
        expect(isDarkOpus({"name": "バハムートソード・フツルスLv.60SLv.4+13"})).toBeFalsy();
        expect(isDarkOpus({"name": "Katana of Repudiatio"})).toBeFalsy();
        expect(isDarkOpus({"name": "永遠拒絶大鎌"})).toBeFalsy();
        expect(isDarkOpus({"name": "Katana f Repudiation"})).toBeFalsy();
        expect(isDarkOpus({"name": "遠拒絶の太刀"})).toBeFalsy();
        expect(isDarkOpus({"name": "Staff of Repudition"})).toBeFalsy();
        expect(isDarkOpus({"name": "絶対力定の竪琴"})).toBeFalsy();
        expect(isDarkOpus({"name": "Staff of epudiation"})).toBeFalsy();
    });

});<|endoftext|>


<commit_before>'use strict';

angular.module('confRegistrationWebApp')
  .controller('paymentModal', function ($scope, $modalInstance, $http, registration, conference) {
    $scope.registration = registration;
    $scope.conference = conference;
    $scope.currentYear = new Date().getFullYear();
    $scope.processing = false;

    $scope.close = function () {
      $modalInstance.close($scope.registration);
    };

    $scope.registrantName = function(registrantId) {
      var nameBlock = _.find(_.flatten(conference.registrationPages, 'blocks'), { 'profileType': 'NAME' }).id;
      var registrant = _.find(registration.registrants, { 'id': registrantId });
      nameBlock = _.find(registrant.answers, { 'blockId': nameBlock }).value;

      return nameBlock.firstName + ' ' + nameBlock.lastName;
    };

    $scope.getBlocks = function() {
      var allBlocks = [];
      _.each(conference.registrationPages, function (page) {
        allBlocks = allBlocks.concat(page.blocks);
      });
      return allBlocks;
    };

    $scope.getRegistrantType = function(id) {
      return _.find(conference.registrantTypes, { 'id': id });
    };

    $scope.getBlock = function (blockId) {
      return _.find($scope.getBlocks(), {id: blockId});
    };

    $scope.newTransaction = {
      registrationId: registration.id,
      amount: registration.remainingBalance
    };

    $scope.updateCostRegistration = [];
    angular.forEach(registration.registrants, function (r) {
      $scope.updateCostRegistration[r.id] = r.calculatedTotalDue;
    });

    $scope.processTransaction = function () {
      if (_.isEmpty($scope.newTransaction.paymentType)) {
        alert('Please select a transaction type.');
        return;
      }
      if (Number($scope.newTransaction.amount) <= 0) {
        alert('Transaction amount must be a positive number.');
        return;
      }

      $scope.processing = true;

      var path = 'payments';
      if($scope.newTransaction.paymentType === 'ADDITIONAL_EXPENSE') {
        path = 'expenses';
        delete $scope.newTransaction.paymentType;
      } else {
          $scope.newTransaction.readyToProcess = true;
      }

      $http.post(path, $scope.newTransaction).success(function () {
        $http.get('registrations/' + $scope.registration.id).success(function (data) {
          $scope.registration = data;
          $scope.processing = false;

          $scope.newTransaction = {
            registrationId: registration.id,
            amount: data.remainingBalance
          };
        });

      }).error(function () {
        alert('Transaction failed...');
        $scope.processing = false;
      });
    };

    $scope.canBeRefunded = function (payment) {
      return payment.paymentType !== 'CREDIT_CARD_REFUND' &&
        payment.paymentType !== 'REFUND' &&
        $scope.calculateRefundableAmount(payment) > 0;
    };

    $scope.calculateRefundableAmount = function (payment) {
      if(angular.isUndefined(payment)) {
        return 0;
      }
      var sum = payment.amount;
      _.each($scope.registration.pastPayments, function (prevRefund) {
        if ((prevRefund.paymentType === 'CREDIT_CARD_REFUND' || prevRefund.paymentType === 'REFUND') &&
          prevRefund.refundedPaymentId === payment.id) {
          sum -= prevRefund.amount;
        }
      });
      return sum;
    };

    $scope.isCreditCardPayment = function () {
      return $scope.paymentToRefund && $scope.paymentToRefund.paymentType === 'CREDIT_CARD';
    };

    $scope.startRefund = function (payment) {
      $scope.paymentToRefund = payment;

      if ($scope.isCreditCardPayment()) {
        $scope.refund = {
          amount: $scope.calculateRefundableAmount(payment),
          refundedPaymentId: payment.id,
          registrationId: payment.registrationId,
          paymentType: 'CREDIT_CARD_REFUND',
          creditCard: {
            lastFourDigits: payment.creditCard.lastFourDigits
          },
          readyToProcess: true
        };
      } else {
        $scope.refund = {
          amount: $scope.calculateRefundableAmount(payment),
          refundedPaymentId: payment.id,
          registrationId: payment.registrationId,
          paymentType: 'REFUND',
          readyToProcess: true
        };
      }
    };

    $scope.processRefund = function () {
      $scope.processing = true;
      $http.post('payments/', $scope.refund).success(function () {
        $http.get('registrations/' + $scope.registration.id).success(function (data) {
          //RegistrationCache.update('registrations/' + data.id, data, function () {});
          $scope.registration = data;
          $scope.processing = false;
          $scope.refund = null;
          if(angular.isDefined($scope.newTransaction)) {
            $scope.newTransaction.amount = data.remainingBalance;
          }
        });
      }).error(function () {
        alert('Refund failed...');
        $scope.processing = false;
      });
    };

    $scope.cancelRefund = function () {
      delete $scope.refund;
    };

    $scope.removeExpense = function (expense) {
      $http.delete('expenses/' + expense.id).success(function() {
        $http.get('registrations/' + $scope.registration.id).success(function (data) {
          $scope.registration = data;
        });
      }).error(function () {
        alert('Error removing expense.');
      });
    };
  });<commit_msg>move code out of function into function where it is used<commit_after>'use strict';

angular.module('confRegistrationWebApp')
  .controller('paymentModal', function ($scope, $modalInstance, $http, registration, conference) {
    $scope.registration = registration;
    $scope.conference = conference;
    $scope.currentYear = new Date().getFullYear();
    $scope.processing = false;

    $scope.close = function () {
      $modalInstance.close($scope.registration);
    };

    $scope.registrantName = function(registrantId) {
      var nameBlock = _.find(_.flatten(conference.registrationPages, 'blocks'), { 'profileType': 'NAME' }).id;
      var registrant = _.find(registration.registrants, { 'id': registrantId });
      nameBlock = _.find(registrant.answers, { 'blockId': nameBlock }).value;

      return nameBlock.firstName + ' ' + nameBlock.lastName;
    };

    $scope.getRegistrantType = function(id) {
      return _.find(conference.registrantTypes, { 'id': id });
    };

    $scope.getBlock = function (blockId) {
      var allBlocks = [];

      _.each(conference.registrationPages, function (page) {
        allBlocks = allBlocks.concat(page.blocks);
      });

      return _.find(allBlocks, {id: blockId});
    };

    $scope.newTransaction = {
      registrationId: registration.id,
      amount: registration.remainingBalance
    };

    $scope.updateCostRegistration = [];
    angular.forEach(registration.registrants, function (r) {
      $scope.updateCostRegistration[r.id] = r.calculatedTotalDue;
    });

    $scope.processTransaction = function () {
      if (_.isEmpty($scope.newTransaction.paymentType)) {
        alert('Please select a transaction type.');
        return;
      }
      if (Number($scope.newTransaction.amount) <= 0) {
        alert('Transaction amount must be a positive number.');
        return;
      }

      $scope.processing = true;

      var path = 'payments';
      if($scope.newTransaction.paymentType === 'ADDITIONAL_EXPENSE') {
        path = 'expenses';
        delete $scope.newTransaction.paymentType;
      } else {
          $scope.newTransaction.readyToProcess = true;
      }

      $http.post(path, $scope.newTransaction).success(function () {
        $http.get('registrations/' + $scope.registration.id).success(function (data) {
          $scope.registration = data;
          $scope.processing = false;

          $scope.newTransaction = {
            registrationId: registration.id,
            amount: data.remainingBalance
          };
        });

      }).error(function () {
        alert('Transaction failed...');
        $scope.processing = false;
      });
    };

    $scope.canBeRefunded = function (payment) {
      return payment.paymentType !== 'CREDIT_CARD_REFUND' &&
        payment.paymentType !== 'REFUND' &&
        $scope.calculateRefundableAmount(payment) > 0;
    };

    $scope.calculateRefundableAmount = function (payment) {
      if(angular.isUndefined(payment)) {
        return 0;
      }
      var sum = payment.amount;
      _.each($scope.registration.pastPayments, function (prevRefund) {
        if ((prevRefund.paymentType === 'CREDIT_CARD_REFUND' || prevRefund.paymentType === 'REFUND') &&
          prevRefund.refundedPaymentId === payment.id) {
          sum -= prevRefund.amount;
        }
      });
      return sum;
    };

    $scope.isCreditCardPayment = function () {
      return $scope.paymentToRefund && $scope.paymentToRefund.paymentType === 'CREDIT_CARD';
    };

    $scope.startRefund = function (payment) {
      $scope.paymentToRefund = payment;

      if ($scope.isCreditCardPayment()) {
        $scope.refund = {
          amount: $scope.calculateRefundableAmount(payment),
          refundedPaymentId: payment.id,
          registrationId: payment.registrationId,
          paymentType: 'CREDIT_CARD_REFUND',
          creditCard: {
            lastFourDigits: payment.creditCard.lastFourDigits
          },
          readyToProcess: true
        };
      } else {
        $scope.refund = {
          amount: $scope.calculateRefundableAmount(payment),
          refundedPaymentId: payment.id,
          registrationId: payment.registrationId,
          paymentType: 'REFUND',
          readyToProcess: true
        };
      }
    };

    $scope.processRefund = function () {
      $scope.processing = true;
      $http.post('payments/', $scope.refund).success(function () {
        $http.get('registrations/' + $scope.registration.id).success(function (data) {
          //RegistrationCache.update('registrations/' + data.id, data, function () {});
          $scope.registration = data;
          $scope.processing = false;
          $scope.refund = null;
          if(angular.isDefined($scope.newTransaction)) {
            $scope.newTransaction.amount = data.remainingBalance;
          }
        });
      }).error(function () {
        alert('Refund failed...');
        $scope.processing = false;
      });
    };

    $scope.cancelRefund = function () {
      delete $scope.refund;
    };

    $scope.removeExpense = function (expense) {
      $http.delete('expenses/' + expense.id).success(function() {
        $http.get('registrations/' + $scope.registration.id).success(function (data) {
          $scope.registration = data;
        });
      }).error(function () {
        alert('Error removing expense.');
      });
    };
  });<|endoftext|>


<commit_before>define(['modules/BaseScoreKeeper'], function(BaseScoreKeeper){
  'use strict';

  function CountScoreKeeper(){
    BaseScoreKeeper.call(this);
  }

  CountScoreKeeper.prototype = Object.create(BaseScoreKeeper.prototype);
  CountScoreKeeper.prototype.constructor = CountScoreKeeper;

  function combinationUtil(inputArray, sizeOfInputArray, sizeOfCombination, index, tempArray, indexOfCurrentElementOfInputArray, matchesArr, matchCondition)
  {
    // Current combination is ready, check it
    if (index === sizeOfCombination)
    {
      var total = 0;
      for (var j=0; j<sizeOfCombination; j++)
        total += tempArray[j].value;
      if(total === matchCondition)
        matchesArr.push(tempArray.slice(0, tempArray.length));
      return;
    }

    // When no more elements are there to put in data[]
    if (indexOfCurrentElementOfInputArray >= sizeOfInputArray)
      return;

    // current is included, put next at next location
    tempArray[index] = inputArray[indexOfCurrentElementOfInputArray];
    combinationUtil(inputArray, sizeOfInputArray, sizeOfCombination, index+1, tempArray, indexOfCurrentElementOfInputArray+1, matchesArr, matchCondition);

    // current is excluded, replace it with next (Note that
    // i+1 is passed, but index is not changed)
    combinationUtil(inputArray, sizeOfInputArray, sizeOfCombination, index, tempArray, indexOfCurrentElementOfInputArray+1, matchesArr, matchCondition);
  }

  CountScoreKeeper.prototype.get15s = function(hand, starter){
    var cards = hand.concat(starter);
    var arrayOfMatches = [];
    var tempArray = [];
    for(var i = 0; i <= cards.length; i++){
      combinationUtil(cards, cards.length, i, 0, tempArray, 0, arrayOfMatches, 15);
    }

    return arrayOfMatches.length * 2;
  };

  CountScoreKeeper.prototype.getPairs = function(hand, starter){
    var pairs = [];
    var cards = hand.concat(starter);
    cards.forEach(function(card, index, array){
      for(var i = index + 1; i < array.length; i++){
        if(card.faceValue === array[i].faceValue){
          pairs.push([card, array[i]]);
        }
      }
    });

    return pairs.length * 2;
  };

  CountScoreKeeper.prototype.getRuns = function(hand, starter){
    var points = 0;

    var cards = hand.concat(starter);

    function combine(a, min) {
      var fn = function(n, src, got, all) {
        if (n === 0) {
          if (got.length > 0) {
            all[all.length] = got;
          }
          return;
        }
        for (var j = 0; j < src.length; j++) {
          fn(n - 1, src.slice(j + 1), got.concat([src[j]]), all);
        }
        return;
      };
      var all = [];
      for (var i = min; i < a.length; i++) {
        fn(i, a, [], all);
      }
      all.push(a);
      return all;
    }

    function sortByFaceValue(a, b){
      return a.faceValue - b.faceValue;
    }

    function sortComboByFaceValue(array){
      array.sort(sortByFaceValue);
      return array;
    }

    function isSequential(card, i, arr){
      if(i === arr.length - 1)//isLastCard
        return true;
      return card.faceValue + 1 === arr[i + 1].faceValue;
    }

    var combinations = combine(cards, 3);
    combinations.forEach(sortComboByFaceValue);

    var sequentialCombos = combinations.filter(function(array){
      return array.every(isSequential);
    });

    var largestSize = 0;
    sequentialCombos.forEach(function(value){
      if(value.length > largestSize)
        largestSize = value.length;
    });

    var filtered = sequentialCombos.filter(function(array){
      return array.length === largestSize;
    });

    filtered.forEach(function(set){
      points += set.length;
    });

    return points;
  };

  CountScoreKeeper.prototype.getHandFlush = function(hand, starter){

    function isFlush(card, index, array){
      return card.suit === array[0].suit;
    }

    var handAndStarter = hand.slice(0,hand.length);
    handAndStarter.push(starter);
    if(handAndStarter.every(isFlush))
      return 5;
    if(hand.every(isFlush))
      return 4;

    return 0;
  };

  CountScoreKeeper.prototype.getNobs = function(hand, starter){
    var hasMatchingJack = hand.some(function(card){
      return card.faceValue === 11 && card.suit === starter.suit;
    });
    return hasMatchingJack ? 1 : 0;
  };

  CountScoreKeeper.prototype.evaluateHand = function(player, starter){
    var gainedPoints = 0;
    var pointDifference = 0;
    var additionalMessage = '';
    gainedPoints += this.get15s(player.hand,starter);

    gainedPoints += this.getPairs(player.hand, starter);

    gainedPoints += this.getRuns(player.hand, starter);

    gainedPoints += this.getHandFlush(player.hand, starter);

    gainedPoints += this.getNobs(player.hand, starter);

    if(player.selectedScore){
      pointDifference = player.selectedScore - gainedPoints;//positive, negative 0
      if(pointDifference > 0){
        this.mediator.publish('messages-add', player.name + ' said ' + player.selectedScore + ' points');
        this.mediator.publish('messages-add', 'the actual points were ' + gainedPoints);
        gainedPoints = (gainedPoints - pointDifference) >= 0 ? (gainedPoints - pointDifference) : 0 ;
        additionalMessage = ' (-' + pointDifference + ')';
      } else {
        this.mediator.publish('messages-add', player.name + ' found ' + player.selectedScore + ' of the total ' + gainedPoints + ' points');
        additionalMessage = ' (-' + (gainedPoints - player.selectedScore) + ')';
        gainedPoints = player.selectedScore;
      }
    }

    if(gainedPoints !== 0)
      player.currentPoints = player.points;
    player.points += gainedPoints;
    this.mediator.publish('messages-add', player.name + ' scored ' + gainedPoints + ' points' + additionalMessage);
  };

  return CountScoreKeeper;
});
<commit_msg>forgot about CountScoreKeeper<commit_after>define(['modules/BaseScoreKeeper'], function(BaseScoreKeeper){
  'use strict';

  function CountScoreKeeper(){
    BaseScoreKeeper.call(this);
  }

  CountScoreKeeper.prototype = Object.create(BaseScoreKeeper.prototype);
  CountScoreKeeper.prototype.constructor = CountScoreKeeper;

  function combinationUtil(inputArray, sizeOfInputArray, sizeOfCombination, index, tempArray, indexOfCurrentElementOfInputArray, matchesArr, matchCondition)
  {
    // Current combination is ready, check it
    if (index === sizeOfCombination)
    {
      var total = 0;
      for (var j=0; j<sizeOfCombination; j++)
        total += tempArray[j].value;
      if(total === matchCondition)
        matchesArr.push(tempArray.slice(0, tempArray.length));
      return;
    }

    // When no more elements are there to put in data[]
    if (indexOfCurrentElementOfInputArray >= sizeOfInputArray)
      return;

    // current is included, put next at next location
    tempArray[index] = inputArray[indexOfCurrentElementOfInputArray];
    combinationUtil(inputArray, sizeOfInputArray, sizeOfCombination, index+1, tempArray, indexOfCurrentElementOfInputArray+1, matchesArr, matchCondition);

    // current is excluded, replace it with next (Note that
    // i+1 is passed, but index is not changed)
    combinationUtil(inputArray, sizeOfInputArray, sizeOfCombination, index, tempArray, indexOfCurrentElementOfInputArray+1, matchesArr, matchCondition);
  }

  CountScoreKeeper.prototype.get15s = function(hand, starter){
    var cards = hand.concat(starter);
    var arrayOfMatches = [];
    var tempArray = [];
    for(var i = 0; i <= cards.length; i++){
      combinationUtil(cards, cards.length, i, 0, tempArray, 0, arrayOfMatches, 15);
    }

    return arrayOfMatches.length * 2;
  };

  CountScoreKeeper.prototype.getPairs = function(hand, starter){
    var pairs = [];
    var cards = hand.concat(starter);
    cards.forEach(function(card, index, array){
      for(var i = index + 1; i < array.length; i++){
        if(card.faceValue === array[i].faceValue){
          pairs.push([card, array[i]]);
        }
      }
    });

    return pairs.length * 2;
  };

  CountScoreKeeper.prototype.getRuns = function(hand, starter){
    var points = 0;

    var cards = hand.concat(starter);

    function combine(a, min) {
      var fn = function(n, src, got, all) {
        if (n === 0) {
          if (got.length > 0) {
            all[all.length] = got;
          }
          return;
        }
        for (var j = 0; j < src.length; j++) {
          fn(n - 1, src.slice(j + 1), got.concat([src[j]]), all);
        }
        return;
      };
      var all = [];
      for (var i = min; i < a.length; i++) {
        fn(i, a, [], all);
      }
      all.push(a);
      return all;
    }

    function sortByFaceValue(a, b){
      return a.faceValue - b.faceValue;
    }

    function sortComboByFaceValue(array){
      array.sort(sortByFaceValue);
      return array;
    }

    function isSequential(card, i, arr){
      if(i === arr.length - 1)//isLastCard
        return true;
      return card.faceValue + 1 === arr[i + 1].faceValue;
    }

    var combinations = combine(cards, 3);
    combinations.forEach(sortComboByFaceValue);

    var sequentialCombos = combinations.filter(function(array){
      return array.every(isSequential);
    });

    var largestSize = 0;
    sequentialCombos.forEach(function(value){
      if(value.length > largestSize)
        largestSize = value.length;
    });

    var filtered = sequentialCombos.filter(function(array){
      return array.length === largestSize;
    });

    filtered.forEach(function(set){
      points += set.length;
    });

    return points;
  };

  CountScoreKeeper.prototype.getHandFlush = function(hand, starter){

    function isFlush(card, index, array){
      return card.suit === array[0].suit;
    }

    var handAndStarter = hand.slice(0,hand.length);
    handAndStarter.push(starter);
    if(handAndStarter.every(isFlush))
      return 5;
    if(hand.every(isFlush))
      return 4;

    return 0;
  };

  CountScoreKeeper.prototype.getNobs = function(hand, starter){
    var hasMatchingJack = hand.some(function(card){
      return card.faceValue === 11 && card.suit === starter.suit;
    });
    return hasMatchingJack ? 1 : 0;
  };

  CountScoreKeeper.prototype.evaluateHand = function(player, starter){
    var gainedPoints = 0;
    var pointDifference = 0;
    var additionalMessage = '';
    gainedPoints += this.get15s(player.hand,starter);

    gainedPoints += this.getPairs(player.hand, starter);

    gainedPoints += this.getRuns(player.hand, starter);

    gainedPoints += this.getHandFlush(player.hand, starter);

    gainedPoints += this.getNobs(player.hand, starter);

    if(!isNaN(player.selectedScore)){
      pointDifference = player.selectedScore - gainedPoints;//positive, negative 0
      if(pointDifference > 0){
        this.mediator.publish('messages-add', player.name + ' said ' + player.selectedScore + ' points');
        this.mediator.publish('messages-add', 'the actual points were ' + gainedPoints);
        gainedPoints = (gainedPoints - pointDifference) >= 0 ? (gainedPoints - pointDifference) : 0 ;
        additionalMessage = ' (-' + pointDifference + ')';
      } else {
        this.mediator.publish('messages-add', player.name + ' found ' + player.selectedScore + ' of the total ' + gainedPoints + ' points');
        additionalMessage = ' (-' + (gainedPoints - player.selectedScore) + ')';
        gainedPoints = player.selectedScore;
      }
    }

    if(gainedPoints !== 0)
      player.currentPoints = player.points;
    player.points += gainedPoints;
    this.mediator.publish('messages-add', player.name + ' scored ' + gainedPoints + ' points' + additionalMessage);
  };

  return CountScoreKeeper;
});
<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var tape = require( 'tape' );
var incrmmean = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof incrmmean, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function throws an error if not provided a positive integer', function test( t ) {
	var values;
	var i;

	values = [
		'5',
		-5.0,
		0.0,
		Math.PI,
		true,
		null,
		undefined,
		NaN,
		[],
		{},
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			incrmmean( value );
		};
	}
});

tape( 'the function returns an accumulator function', function test( t ) {
	t.equal( typeof incrmmean( 3 ), 'function', 'returns a function' );
	t.end();
});

tape( 'the accumulator function computes a moving arithmetic mean incrementally', function test( t ) {
	var expected;
	var actual;
	var data;
	var acc;
	var N;
	var i;

	data = [ 2.0, 3.0, 2.0, 4.0, 3.0, 4.0 ];
	N = data.length;

	acc = incrmmean( 3 );

	actual = new Array( N );
	for ( i = 0; i < N; i++ ) {
		actual[ i ] = acc( data[ i ] );
	}
	expected = [ 2.0, 2.5, 7.0/3.0, 3.0, 3.0, 11.0/3.0 ];

	t.deepEqual( actual, expected, 'returns expected incremental results' );
	t.end();
});

tape( 'if not provided an input value, the accumulator function returns the current mean', function test( t ) {
	var data;
	var acc;
	var i;

	data = [ 2.0, 3.0, 5.0 ];
	acc = incrmmean( 2 );
	for ( i = 0; i < data.length; i++ ) {
		acc( data[ i ] );
	}
	t.equal( acc(), 4.0 );
	t.end();
});

tape( 'if data has yet to be provided, the accumulator function returns `null`', function test( t ) {
	var acc = incrmmean( 3 );
	t.equal( acc(), null, 'returns null' );
	t.end();
});
<commit_msg>Update test values<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var tape = require( 'tape' );
var incrmmean = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof incrmmean, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function throws an error if not provided a positive integer', function test( t ) {
	var values;
	var i;

	values = [
		'5',
		-5.0,
		0.0,
		3.14,
		true,
		null,
		void 0,
		NaN,
		[],
		{},
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			incrmmean( value );
		};
	}
});

tape( 'the function returns an accumulator function', function test( t ) {
	t.equal( typeof incrmmean( 3 ), 'function', 'returns a function' );
	t.end();
});

tape( 'the accumulator function computes a moving arithmetic mean incrementally', function test( t ) {
	var expected;
	var actual;
	var data;
	var acc;
	var N;
	var i;

	data = [ 2.0, 3.0, 2.0, 4.0, 3.0, 4.0 ];
	N = data.length;

	acc = incrmmean( 3 );

	actual = new Array( N );
	for ( i = 0; i < N; i++ ) {
		actual[ i ] = acc( data[ i ] );
	}
	expected = [ 2.0, 2.5, 7.0/3.0, 3.0, 3.0, 11.0/3.0 ];

	t.deepEqual( actual, expected, 'returns expected incremental results' );
	t.end();
});

tape( 'if not provided an input value, the accumulator function returns the current mean', function test( t ) {
	var data;
	var acc;
	var i;

	data = [ 2.0, 3.0, 5.0 ];
	acc = incrmmean( 2 );
	for ( i = 0; i < data.length; i++ ) {
		acc( data[ i ] );
	}
	t.equal( acc(), 4.0 );
	t.end();
});

tape( 'if data has yet to be provided, the accumulator function returns `null`', function test( t ) {
	var acc = incrmmean( 3 );
	t.equal( acc(), null, 'returns null' );
	t.end();
});
<|endoftext|>


<commit_before>'use strict';

import Spinner from 'spin.js';
let angular = require('angular');

import {ACCOUNT_TAG_COMPONENT} from './account/accountTag.component';
import {AUTHENTICATION} from './authentication/authentication.module';
import {API_SERVICE} from './api/api.service';
import {CANCEL_MODAL_SERVICE} from './cancelModal/cancelModal.service';
import {CLOUD_PROVIDER_LOGO} from './cloudProvider/cloudProviderLogo.component';
import {CORE_DIFF_MODULE} from './diffs';
import {HELP_FIELD_COMPONENT} from './help/helpField.component';
import {STATE_CONFIG_PROVIDER} from './navigation/state.provider';
import {APPLICATIONS_STATE_PROVIDER} from './application/applications.state.provider';
import {INFRASTRUCTURE_STATES} from './search/infrastructure/infrastructure.states';
import {VERSION_CHECK_SERVICE} from './config/versionCheck.service';
import {CORE_WIDGETS_MODULE} from './widgets';
import {TRAVIS_STAGE_MODULE} from './pipeline/config/stages/travis/travisStage.module';
import {WEBHOOK_STAGE_MODULE} from './pipeline/config/stages/webhook/webhookStage.module';
import {UNMATCHED_STAGE_TYPE_STAGE} from './pipeline/config/stages/unmatchedStageTypeStage/unmatchedStageTypeStage';
import {SETTINGS} from 'core/config/settings';
import {INSIGHT_NGMODULE} from './insight/insight.module';
import {REPLACE_FILTER} from './filter/replace.filter';
import {PIPELINE_TEMPLATE_MODULE} from './pipeline/config/templates/pipelineTemplate.module';
import {HEALTH_COUNTS_COMPONENT} from './healthCounts/healthCounts.component';
import {CORE_PAGETITLE_SERVICE} from './pageTitle/pageTitle.service';
import {INTERCEPTOR_MODULE} from './interceptor/interceptor.module';

require('../../../fonts/spinnaker/icons.css');

import 'Select2';
import 'jquery-ui';
// Must come after jquery-ui - we want the bootstrap tooltip, JavaScript is fun
import 'bootstrap/dist/js/bootstrap.js';
import 'bootstrap/dist/css/bootstrap.css';
import 'select2-bootstrap-css/select2-bootstrap.css';
import 'Select2/select2.css';
import 'ui-select/dist/select.css';

import 'source-sans-pro';

import 'font-awesome/css/font-awesome.css';
import 'react-select/dist/react-select.css';

import { UI_ROUTER_STATE_SHIM } from './routing/uirouter.stateEvents.shim';

// load all templates into the $templateCache
var templates = require.context('./', true, /\.html$/);
templates.keys().forEach(function(key) {
  templates(key);
});

module.exports = angular
  .module('spinnaker.core', [
    require('angular-messages'),
    require('angular-sanitize'),
    require('angular-ui-router').default,
    UI_ROUTER_STATE_SHIM,
    require('angular-ui-bootstrap'),
    require('exports-loader?"ui.select"!ui-select'),
    require('imports-loader?define=>false!exports-loader?"angularSpinner"!angular-spinner'),

    require('./projects/projects.module.js'),

    require('./application/application.module.js'),

    ACCOUNT_TAG_COMPONENT,
    require('./analytics/analytics.service'),
    AUTHENTICATION,
    require('./bootstrap/applicationBootstrap.directive.js'),

    API_SERVICE,

    require('./cache/caches.module.js'),
    CANCEL_MODAL_SERVICE,
    CLOUD_PROVIDER_LOGO,
    PIPELINE_TEMPLATE_MODULE,
    CORE_DIFF_MODULE,
    require('./cloudProvider/cloudProviderLabel.directive.js'),
    require('./cloudProvider/serviceDelegate.service.js'),
    require('./cluster/cluster.module.js'),
    VERSION_CHECK_SERVICE,

    require('./delivery/delivery.module.js'),
    require('./deploymentStrategy/deploymentStrategy.module.js'),
    require('./deploymentStrategy/strategies/highlander/highlander.strategy.module.js'),
    require('./deploymentStrategy/strategies/none/none.strategy.module.js'),
    require('./deploymentStrategy/strategies/redblack/redblack.strategy.module.js'),
    require('./deploymentStrategy/strategies/custom/custom.strategy.module.js'),
    require('./deploymentStrategy/strategies/rollingPush/rollingPush.strategy.module.js'),

    require('./forms/forms.module.js'),

    HEALTH_COUNTS_COMPONENT,
    HELP_FIELD_COMPONENT,

    INSIGHT_NGMODULE.name,
    require('./instance/instance.module.js'),
    INTERCEPTOR_MODULE,

    require('./loadBalancer/loadBalancer.module.js'),

    require('./modal/modal.module.js'),

    STATE_CONFIG_PROVIDER,
    APPLICATIONS_STATE_PROVIDER,
    INFRASTRUCTURE_STATES,
    require('./notification/notifications.module.js'),
    require('./notification/types/email/email.notification.type.module.js'),
    require('./notification/types/hipchat/hipchat.notification.type.module.js'),
    require('./notification/types/slack/slack.notification.type.module.js'),
    require('./notification/types/sms/sms.notification.type.module.js'),

    CORE_PAGETITLE_SERVICE,

    require('./pipeline/pipelines.module.js'),
    require('./pipeline/config/stages/bake/bakeStage.module.js'),
    require('./pipeline/config/stages/checkPreconditions/checkPreconditionsStage.module.js'),
    require('./pipeline/config/stages/cloneServerGroup/cloneServerGroupStage.module.js'),
    require('./pipeline/config/stages/core/stage.core.module.js'),
    require('./pipeline/config/stages/deploy/deployStage.module.js'),
    require('./pipeline/config/stages/destroyAsg/destroyAsgStage.module.js'),
    require('./pipeline/config/stages/disableAsg/disableAsgStage.module.js'),
    require('./pipeline/config/stages/disableCluster/disableClusterStage.module.js'),
    require('./pipeline/config/stages/enableAsg/enableAsgStage.module.js'),
    require('./pipeline/config/stages/executionWindows/executionWindowsStage.module.js'),
    require('./pipeline/config/stages/findAmi/findAmiStage.module.js'),
    require('./pipeline/config/stages/findImageFromTags/findImageFromTagsStage.module.js'),
    require('./pipeline/config/stages/jenkins/jenkinsStage.module.js'),
    TRAVIS_STAGE_MODULE,
    WEBHOOK_STAGE_MODULE,
    require('./pipeline/config/stages/manualJudgment/manualJudgmentStage.module.js'),
    require('./pipeline/config/stages/tagImage/tagImageStage.module.js'),
    require('./pipeline/config/stages/pipeline/pipelineStage.module.js'),
    require('./pipeline/config/stages/resizeAsg/resizeAsgStage.module.js'),
    require('./pipeline/config/stages/runJob/runJobStage.module.js'),
    require('./pipeline/config/stages/scaleDownCluster/scaleDownClusterStage.module.js'),
    require('./pipeline/config/stages/script/scriptStage.module.js'),
    require('./pipeline/config/stages/shrinkCluster/shrinkClusterStage.module.js'),
    require('./pipeline/config/stages/wait/waitStage.module.js'),
    require('./pipeline/config/stages/waitForParentTasks/waitForParentTasks.js'),
    require('./pipeline/config/stages/createLoadBalancer/createLoadBalancerStage.module.js'),
    require('./pipeline/config/stages/applySourceServerGroupCapacity/applySourceServerGroupCapacityStage.module.js'),
    require('./pipeline/config/preconditions/preconditions.module.js'),
    require('./pipeline/config/preconditions/types/clusterSize/clusterSize.precondition.type.module.js'),
    require('./pipeline/config/preconditions/types/expression/expression.precondition.type.module.js'),
    require('./presentation/presentation.module.js'),
    REPLACE_FILTER,

    require('./search/search.module.js'),
    require('./securityGroup/securityGroup.module.js'),
    require('./serverGroup/serverGroup.module.js'),

    require('./task/task.module.js'),

    UNMATCHED_STAGE_TYPE_STAGE,

    require('./utils/utils.module.js'),

    require('./whatsNew/whatsNew.directive.js'),
    CORE_WIDGETS_MODULE,
    require('./validation/validation.module.js'),
  ])
  .run(function($rootScope, $log, $state) {
    window.Spinner = Spinner;

    $rootScope.feature = SETTINGS.feature;

    $rootScope.$state = $state; // TODO: Do we really need this?

    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
      $log.debug(event.name, {
        event: event,
        toState: toState,
        toParams: toParams,
        fromState: fromState,
        fromParams: fromParams
      });
    });

    $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
      $log.debug(event.name, {
        event: event,
        toState: toState,
        toParams: toParams,
        fromState: fromState,
        fromParams: fromParams,
        error: error
      });
    });

    $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
      $log.debug(event.name, {
        event: event,
        toState: toState,
        toParams: toParams,
        fromState: fromState,
        fromParams: fromParams
      });
    });
  })
  .run(function (cacheInitializer) {
    cacheInitializer.initialize();
  })
  .config(function ($logProvider) {
    $logProvider.debugEnabled(SETTINGS.debugEnabled);
  })
  .config(function($uibTooltipProvider) {
    $uibTooltipProvider.options({
      appendToBody: true
    });
    $uibTooltipProvider.setTriggers({
      'mouseenter focus': 'mouseleave blur'
    });
  })
  .config(function($uibModalProvider) {
    $uibModalProvider.options.backdrop = 'static';
    $uibModalProvider.options.keyboard = false;
  })
  .config(function($httpProvider) {
    $httpProvider.defaults.headers.patch = {
      'Content-Type': 'application/json;charset=utf-8'
    };
  })
  .config(function($qProvider) {
    // Angular 1.6 stops suppressing unhandle rejections on promises. This resets it back to 1.5 behavior.
    // See https://docs.angularjs.org/guide/migration#migrate1.5to1.6-ng-services-$q
    $qProvider.errorOnUnhandledRejections(false);
  })
  .config(function($compileProvider) {
    $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|mailto|hipchat|slack):/);
    // Angular 1.6 defaults preAssignBindingsEnabled to false, reset to true to mimic 1.5 behavior.
    // See https://docs.angularjs.org/guide/migration#migrate1.5to1.6-ng-services-$compile
    $compileProvider.preAssignBindingsEnabled(true);
  })
  .config(function($locationProvider) {
    // Angular 1.6 sets default hashPrefix to '!', change it back to ''
    // See https://docs.angularjs.org/guide/migration#migrate1.5to1.6-ng-services-$location
    $locationProvider.hashPrefix('');
  })
  .config(require('./forms/uiSelect.decorator.js'))
  .config(function(uiSelectConfig) {
    uiSelectConfig.theme = 'select2';
    uiSelectConfig.appendToBody = true;
  })
  .run(function($stateRegistry, $uiRouter) {

    // Type javascript:vis() in the browser url
    window.vis = function() {
      const collapsedStates = [
        'home.data',
        'home.project',
        'home.projects',
        'home.applications',
        'home.applications.application.insight',
        'home.applications.application.insight.clusters',
        'home.applications.application.insight.securityGroups',
        'home.applications.application.insight.loadBalancers',
        'home.applications.application.pipelines',
        'home.project.application.insight',
        'home.project.application.insight.clusters',
        'home.project.application.insight.securityGroups',
        'home.project.application.insight.loadBalancers',
        'home.project.application.pipelines',
      ];

      // eslint-disable-next-line no-underscore-dangle
      collapsedStates.forEach(state => $stateRegistry.get(state).$$state()._collapsed = true);

      System.import('ui-router-visualizer').then(vis => $uiRouter.plugin(vis.Visualizer));
    };
  });

<commit_msg>feat: Allow ssh links<commit_after>'use strict';

import Spinner from 'spin.js';
let angular = require('angular');

import {ACCOUNT_TAG_COMPONENT} from './account/accountTag.component';
import {AUTHENTICATION} from './authentication/authentication.module';
import {API_SERVICE} from './api/api.service';
import {CANCEL_MODAL_SERVICE} from './cancelModal/cancelModal.service';
import {CLOUD_PROVIDER_LOGO} from './cloudProvider/cloudProviderLogo.component';
import {CORE_DIFF_MODULE} from './diffs';
import {HELP_FIELD_COMPONENT} from './help/helpField.component';
import {STATE_CONFIG_PROVIDER} from './navigation/state.provider';
import {APPLICATIONS_STATE_PROVIDER} from './application/applications.state.provider';
import {INFRASTRUCTURE_STATES} from './search/infrastructure/infrastructure.states';
import {VERSION_CHECK_SERVICE} from './config/versionCheck.service';
import {CORE_WIDGETS_MODULE} from './widgets';
import {TRAVIS_STAGE_MODULE} from './pipeline/config/stages/travis/travisStage.module';
import {WEBHOOK_STAGE_MODULE} from './pipeline/config/stages/webhook/webhookStage.module';
import {UNMATCHED_STAGE_TYPE_STAGE} from './pipeline/config/stages/unmatchedStageTypeStage/unmatchedStageTypeStage';
import {SETTINGS} from 'core/config/settings';
import {INSIGHT_NGMODULE} from './insight/insight.module';
import {REPLACE_FILTER} from './filter/replace.filter';
import {PIPELINE_TEMPLATE_MODULE} from './pipeline/config/templates/pipelineTemplate.module';
import {HEALTH_COUNTS_COMPONENT} from './healthCounts/healthCounts.component';
import {CORE_PAGETITLE_SERVICE} from './pageTitle/pageTitle.service';
import {INTERCEPTOR_MODULE} from './interceptor/interceptor.module';

require('../../../fonts/spinnaker/icons.css');

import 'Select2';
import 'jquery-ui';
// Must come after jquery-ui - we want the bootstrap tooltip, JavaScript is fun
import 'bootstrap/dist/js/bootstrap.js';
import 'bootstrap/dist/css/bootstrap.css';
import 'select2-bootstrap-css/select2-bootstrap.css';
import 'Select2/select2.css';
import 'ui-select/dist/select.css';

import 'source-sans-pro';

import 'font-awesome/css/font-awesome.css';
import 'react-select/dist/react-select.css';

import { UI_ROUTER_STATE_SHIM } from './routing/uirouter.stateEvents.shim';

// load all templates into the $templateCache
var templates = require.context('./', true, /\.html$/);
templates.keys().forEach(function(key) {
  templates(key);
});

module.exports = angular
  .module('spinnaker.core', [
    require('angular-messages'),
    require('angular-sanitize'),
    require('angular-ui-router').default,
    UI_ROUTER_STATE_SHIM,
    require('angular-ui-bootstrap'),
    require('exports-loader?"ui.select"!ui-select'),
    require('imports-loader?define=>false!exports-loader?"angularSpinner"!angular-spinner'),

    require('./projects/projects.module.js'),

    require('./application/application.module.js'),

    ACCOUNT_TAG_COMPONENT,
    require('./analytics/analytics.service'),
    AUTHENTICATION,
    require('./bootstrap/applicationBootstrap.directive.js'),

    API_SERVICE,

    require('./cache/caches.module.js'),
    CANCEL_MODAL_SERVICE,
    CLOUD_PROVIDER_LOGO,
    PIPELINE_TEMPLATE_MODULE,
    CORE_DIFF_MODULE,
    require('./cloudProvider/cloudProviderLabel.directive.js'),
    require('./cloudProvider/serviceDelegate.service.js'),
    require('./cluster/cluster.module.js'),
    VERSION_CHECK_SERVICE,

    require('./delivery/delivery.module.js'),
    require('./deploymentStrategy/deploymentStrategy.module.js'),
    require('./deploymentStrategy/strategies/highlander/highlander.strategy.module.js'),
    require('./deploymentStrategy/strategies/none/none.strategy.module.js'),
    require('./deploymentStrategy/strategies/redblack/redblack.strategy.module.js'),
    require('./deploymentStrategy/strategies/custom/custom.strategy.module.js'),
    require('./deploymentStrategy/strategies/rollingPush/rollingPush.strategy.module.js'),

    require('./forms/forms.module.js'),

    HEALTH_COUNTS_COMPONENT,
    HELP_FIELD_COMPONENT,

    INSIGHT_NGMODULE.name,
    require('./instance/instance.module.js'),
    INTERCEPTOR_MODULE,

    require('./loadBalancer/loadBalancer.module.js'),

    require('./modal/modal.module.js'),

    STATE_CONFIG_PROVIDER,
    APPLICATIONS_STATE_PROVIDER,
    INFRASTRUCTURE_STATES,
    require('./notification/notifications.module.js'),
    require('./notification/types/email/email.notification.type.module.js'),
    require('./notification/types/hipchat/hipchat.notification.type.module.js'),
    require('./notification/types/slack/slack.notification.type.module.js'),
    require('./notification/types/sms/sms.notification.type.module.js'),

    CORE_PAGETITLE_SERVICE,

    require('./pipeline/pipelines.module.js'),
    require('./pipeline/config/stages/bake/bakeStage.module.js'),
    require('./pipeline/config/stages/checkPreconditions/checkPreconditionsStage.module.js'),
    require('./pipeline/config/stages/cloneServerGroup/cloneServerGroupStage.module.js'),
    require('./pipeline/config/stages/core/stage.core.module.js'),
    require('./pipeline/config/stages/deploy/deployStage.module.js'),
    require('./pipeline/config/stages/destroyAsg/destroyAsgStage.module.js'),
    require('./pipeline/config/stages/disableAsg/disableAsgStage.module.js'),
    require('./pipeline/config/stages/disableCluster/disableClusterStage.module.js'),
    require('./pipeline/config/stages/enableAsg/enableAsgStage.module.js'),
    require('./pipeline/config/stages/executionWindows/executionWindowsStage.module.js'),
    require('./pipeline/config/stages/findAmi/findAmiStage.module.js'),
    require('./pipeline/config/stages/findImageFromTags/findImageFromTagsStage.module.js'),
    require('./pipeline/config/stages/jenkins/jenkinsStage.module.js'),
    TRAVIS_STAGE_MODULE,
    WEBHOOK_STAGE_MODULE,
    require('./pipeline/config/stages/manualJudgment/manualJudgmentStage.module.js'),
    require('./pipeline/config/stages/tagImage/tagImageStage.module.js'),
    require('./pipeline/config/stages/pipeline/pipelineStage.module.js'),
    require('./pipeline/config/stages/resizeAsg/resizeAsgStage.module.js'),
    require('./pipeline/config/stages/runJob/runJobStage.module.js'),
    require('./pipeline/config/stages/scaleDownCluster/scaleDownClusterStage.module.js'),
    require('./pipeline/config/stages/script/scriptStage.module.js'),
    require('./pipeline/config/stages/shrinkCluster/shrinkClusterStage.module.js'),
    require('./pipeline/config/stages/wait/waitStage.module.js'),
    require('./pipeline/config/stages/waitForParentTasks/waitForParentTasks.js'),
    require('./pipeline/config/stages/createLoadBalancer/createLoadBalancerStage.module.js'),
    require('./pipeline/config/stages/applySourceServerGroupCapacity/applySourceServerGroupCapacityStage.module.js'),
    require('./pipeline/config/preconditions/preconditions.module.js'),
    require('./pipeline/config/preconditions/types/clusterSize/clusterSize.precondition.type.module.js'),
    require('./pipeline/config/preconditions/types/expression/expression.precondition.type.module.js'),
    require('./presentation/presentation.module.js'),
    REPLACE_FILTER,

    require('./search/search.module.js'),
    require('./securityGroup/securityGroup.module.js'),
    require('./serverGroup/serverGroup.module.js'),

    require('./task/task.module.js'),

    UNMATCHED_STAGE_TYPE_STAGE,

    require('./utils/utils.module.js'),

    require('./whatsNew/whatsNew.directive.js'),
    CORE_WIDGETS_MODULE,
    require('./validation/validation.module.js'),
  ])
  .run(function($rootScope, $log, $state) {
    window.Spinner = Spinner;

    $rootScope.feature = SETTINGS.feature;

    $rootScope.$state = $state; // TODO: Do we really need this?

    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
      $log.debug(event.name, {
        event: event,
        toState: toState,
        toParams: toParams,
        fromState: fromState,
        fromParams: fromParams
      });
    });

    $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
      $log.debug(event.name, {
        event: event,
        toState: toState,
        toParams: toParams,
        fromState: fromState,
        fromParams: fromParams,
        error: error
      });
    });

    $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
      $log.debug(event.name, {
        event: event,
        toState: toState,
        toParams: toParams,
        fromState: fromState,
        fromParams: fromParams
      });
    });
  })
  .run(function (cacheInitializer) {
    cacheInitializer.initialize();
  })
  .config(function ($logProvider) {
    $logProvider.debugEnabled(SETTINGS.debugEnabled);
  })
  .config(function($uibTooltipProvider) {
    $uibTooltipProvider.options({
      appendToBody: true
    });
    $uibTooltipProvider.setTriggers({
      'mouseenter focus': 'mouseleave blur'
    });
  })
  .config(function($uibModalProvider) {
    $uibModalProvider.options.backdrop = 'static';
    $uibModalProvider.options.keyboard = false;
  })
  .config(function($httpProvider) {
    $httpProvider.defaults.headers.patch = {
      'Content-Type': 'application/json;charset=utf-8'
    };
  })
  .config(function($qProvider) {
    // Angular 1.6 stops suppressing unhandle rejections on promises. This resets it back to 1.5 behavior.
    // See https://docs.angularjs.org/guide/migration#migrate1.5to1.6-ng-services-$q
    $qProvider.errorOnUnhandledRejections(false);
  })
  .config(function($compileProvider) {
    $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|mailto|hipchat|slack|ssh):/);
    // Angular 1.6 defaults preAssignBindingsEnabled to false, reset to true to mimic 1.5 behavior.
    // See https://docs.angularjs.org/guide/migration#migrate1.5to1.6-ng-services-$compile
    $compileProvider.preAssignBindingsEnabled(true);
  })
  .config(function($locationProvider) {
    // Angular 1.6 sets default hashPrefix to '!', change it back to ''
    // See https://docs.angularjs.org/guide/migration#migrate1.5to1.6-ng-services-$location
    $locationProvider.hashPrefix('');
  })
  .config(require('./forms/uiSelect.decorator.js'))
  .config(function(uiSelectConfig) {
    uiSelectConfig.theme = 'select2';
    uiSelectConfig.appendToBody = true;
  })
  .run(function($stateRegistry, $uiRouter) {

    // Type javascript:vis() in the browser url
    window.vis = function() {
      const collapsedStates = [
        'home.data',
        'home.project',
        'home.projects',
        'home.applications',
        'home.applications.application.insight',
        'home.applications.application.insight.clusters',
        'home.applications.application.insight.securityGroups',
        'home.applications.application.insight.loadBalancers',
        'home.applications.application.pipelines',
        'home.project.application.insight',
        'home.project.application.insight.clusters',
        'home.project.application.insight.securityGroups',
        'home.project.application.insight.loadBalancers',
        'home.project.application.pipelines',
      ];

      // eslint-disable-next-line no-underscore-dangle
      collapsedStates.forEach(state => $stateRegistry.get(state).$$state()._collapsed = true);

      System.import('ui-router-visualizer').then(vis => $uiRouter.plugin(vis.Visualizer));
    };
  });

<|endoftext|>


<commit_before>define([
    'backbone',
    'underscore',
    'models/source',
    'models/sources',
    'models/header',
    'models/content',
    'services/defined-checker'
], function (Backbone, _, Source, Sources, Header, Content, definedChecker) {
    'use strict';

    return Backbone.Model.extend({

        initialize: function (options) {
            definedChecker.isDefined(options.listingUrl, 'listingUrl');
            definedChecker.isDefined(options.contentUrl, 'contentUrl');

            _.bindAll(this, 'getSources', 'successReadListing', 'call');

            this.listingUrl = options.listingUrl;
            this.contentUrl = options.contentUrl;
        },

        getSources: function (callback) {
            definedChecker.isDefined(callback, 'callback');

            var that = this;
            this.call(
                this.listingUrl,
                function (responseData) {
                    that.successReadListing(callback, responseData);
                },
                function () {
                    that.successReadListing(callback, ['listing-problem.json']);
                }
            );
        },

        successReadListing: function (callback, listings) {
            var sources = new Sources();

            var that = this;
            _.forEach(listings, function (listing) {

                var source = new Source({
                    url: that.contentUrl + listing
                });

                that.call(
                    source.get('url'),
                    function (data) {

                        if (!data.importance) {
                            data.importance = 1;
                        }

                        source.set({
                            header: new Header({
                                name: data.name
                            }),
                            content: new Content({
                                content: data.content
                            }),
                            tags: data.tags,
                            importance: data.importance
                        });
                    },
                    function (jqXHR, textStatus) {
                        source.set({
                            header: new Header({
                                name: 'Error loading'
                            }),
                            content: new Content({
                                content: 'Error loading ' + source.get('url') + '(' + textStatus + ')'
                            })
                        });
                    }
                );

                sources.add(source);
            });
            callback(sources);
        },

        call: function (url, success, error) {
            $.ajax({
                url: url,
                type: 'GET',
                dataType: 'json',
                success: success,
                error: error,
                cache: false,
                async: false
            });
        }
    });
});<commit_msg>replace _.each with forEach<commit_after>define([
    'backbone',
    'underscore',
    'models/source',
    'models/sources',
    'models/header',
    'models/content',
    'services/defined-checker'
], function (Backbone, _, Source, Sources, Header, Content, definedChecker) {
    'use strict';

    return Backbone.Model.extend({

        initialize: function (options) {
            definedChecker.isDefined(options.listingUrl, 'listingUrl');
            definedChecker.isDefined(options.contentUrl, 'contentUrl');

            _.bindAll(this, 'getSources', 'successReadListing', 'call');

            this.listingUrl = options.listingUrl;
            this.contentUrl = options.contentUrl;
        },

        getSources: function (callback) {
            definedChecker.isDefined(callback, 'callback');

            var that = this;
            this.call(
                this.listingUrl,
                function (responseData) {
                    that.successReadListing(callback, responseData);
                },
                function () {
                    that.successReadListing(callback, ['listing-problem.json']);
                }
            );
        },

        successReadListing: function (callback, listings) {
            var sources = new Sources();

            var that = this;
            listings.forEach(function (listing) {

                var source = new Source({
                    url: that.contentUrl + listing
                });

                that.call(
                    source.get('url'),
                    function (data) {

                        if (!data.importance) {
                            data.importance = 1;
                        }

                        source.set({
                            header: new Header({
                                name: data.name
                            }),
                            content: new Content({
                                content: data.content
                            }),
                            tags: data.tags,
                            importance: data.importance
                        });
                    },
                    function (jqXHR, textStatus) {
                        source.set({
                            header: new Header({
                                name: 'Error loading'
                            }),
                            content: new Content({
                                content: 'Error loading ' + source.get('url') + '(' + textStatus + ')'
                            })
                        });
                    }
                );

                sources.add(source);
            });
            callback(sources);
        },

        call: function (url, success, error) {
            $.ajax({
                url: url,
                type: 'GET',
                dataType: 'json',
                success: success,
                error: error,
                cache: false,
                async: false
            });
        }
    });
});<|endoftext|>