<commit_before>module.exports = {
  'rules': {
    // enforces getter/setter pairs in objects
    'accessor-pairs': 0,
    // enforces return statements in callbacks of array's methods
    // http://eslint.org/docs/rules/array-callback-return
    'array-callback-return': 2,
    // treat var statements as if they were block scoped
    'block-scoped-var': 2,
    // specify the maximum cyclomatic complexity allowed in a program
    'complexity': [0, 11],
    // require return statements to either always or never specify values
    'consistent-return': 2,
    // specify curly brace conventions for all control statements
    'curly': [2, 'multi-line'],
    // require default case in switch statements
    'default-case': 2,
    // encourages use of dot notation whenever possible
    'dot-notation': [2, { 'allowKeywords': true }],
    // enforces consistent newlines before or after dots
    'dot-location': 0,
    // require the use of === and !==
    'eqeqeq': 2,
    // make sure for-in loops have an if statement
    'guard-for-in': 2,
    // Blacklist certain identifiers to prevent them being used
    // http://eslint.org/docs/rules/id-blacklist
    'id-blacklist': 0,
    // disallow the use of alert, confirm, and prompt
    'no-alert': 1,
    // disallow use of arguments.caller or arguments.callee
    'no-caller': 2,
    // disallow lexical declarations in case/default clauses
    // http://eslint.org/docs/rules/no-case-declarations.html
    'no-case-declarations': 2,
    // disallow division operators explicitly at beginning of regular expression
    'no-div-regex': 0,
    // disallow else after a return in an if
    'no-else-return': 2,
    // disallow Unnecessary Labels
    // http://eslint.org/docs/rules/no-extra-label
    'no-extra-label': 2,
    // disallow comparisons to null without a type-checking operator
    'no-eq-null': 0,
    // disallow use of eval()
    'no-eval': 2,
    // disallow adding to native types
    'no-extend-native': 2,
    // disallow unnecessary function binding
    'no-extra-bind': 2,
    // disallow fallthrough of case statements
    'no-fallthrough': 2,
    // disallow the use of leading or trailing decimal points in numeric literals
    'no-floating-decimal': 2,
    // disallow the type conversions with shorter notations
    'no-implicit-coercion': 0,
    // disallow use of eval()-like methods
    'no-implied-eval': 2,
    // disallow this keywords outside of classes or class-like objects
    'no-invalid-this': 0,
    // disallow usage of __iterator__ property
    'no-iterator': 2,
    // disallow use of labels for anything other then loops and switches
    'no-labels': [2, { 'allowLoop': false, 'allowSwitch': false }],
    // disallow unnecessary nested blocks
    'no-lone-blocks': 2,
    // disallow creation of functions within loops
    'no-loop-func': 2,
    // disallow use of multiple spaces
    'no-multi-spaces': 2,
    // disallow use of multiline strings
    'no-multi-str': 2,
    // disallow reassignments of native objects
    'no-native-reassign': 2,
    // disallow use of new operator when not part of the assignment or comparison
    'no-new': 2,
    // disallow use of new operator for Function object
    'no-new-func': 2,
    // disallows creating new instances of String, Number, and Boolean
    'no-new-wrappers': 2,
    // disallow use of (old style) octal literals
    'no-octal': 2,
    // disallow use of octal escape sequences in string literals, such as
    // var foo = 'Copyright \251';
    'no-octal-escape': 2,
    // disallow reassignment of function parameters
    // disallow parameter object manipulation
    // rule: http://eslint.org/docs/rules/no-param-reassign.html
    'no-param-reassign': [2, { 'props': true }],
    // disallow use of process.env
    'no-process-env': 0,
    // disallow usage of __proto__ property
    'no-proto': 2,
    // disallow declaring the same variable more then once
    'no-redeclare': 2,
    // disallow use of assignment in return statement
    'no-return-assign': 2,
    // disallow use of `javascript:` urls.
    'no-script-url': 2,
    // disallow comparisons where both sides are exactly the same
    'no-self-compare': 2,
    // disallow use of comma operator
    'no-sequences': 2,
    // restrict what can be thrown as an exception
    'no-throw-literal': 2,
    // disallow unmodified conditions of loops
    // http://eslint.org/docs/rules/no-unmodified-loop-condition
    'no-unmodified-loop-condition': 0,
    // disallow usage of expressions in statement position
    'no-unused-expressions': 2,
    // disallow unused labels
    // http://eslint.org/docs/rules/no-unused-labels
    'no-unused-labels': 2,
    // disallow unnecessary .call() and .apply()
    'no-useless-call': 0,
    // disallow unnecessary string escaping
    // http://eslint.org/docs/rules/no-useless-escape
    'no-useless-escape': 2,
    // disallow use of void operator
    'no-void': 0,
    // disallow usage of configurable warning terms in comments: e.g. todo
    'no-warning-comments': [0, { 'terms': ['todo', 'fixme', 'xxx'], 'location': 'start' }],
    // disallow use of the with statement
    'no-with': 2,
    // require use of the second argument for parseInt()
    'radix': 2,
    // requires to declare all vars on top of their containing scope
    'vars-on-top': 2,
    // require immediate function invocation to be wrapped in parentheses
    // http://eslint.org/docs/rules/wrap-iife.html
    'wrap-iife': [2, 'outside'],
    // require or disallow Yoda conditions
    'yoda': 2
  }
};
<commit_msg>[eslint config] [semver-patch] Enable `no-useless-concat` rule which `prefer-template` already covers<commit_after>module.exports = {
  'rules': {
    // enforces getter/setter pairs in objects
    'accessor-pairs': 0,
    // enforces return statements in callbacks of array's methods
    // http://eslint.org/docs/rules/array-callback-return
    'array-callback-return': 2,
    // treat var statements as if they were block scoped
    'block-scoped-var': 2,
    // specify the maximum cyclomatic complexity allowed in a program
    'complexity': [0, 11],
    // require return statements to either always or never specify values
    'consistent-return': 2,
    // specify curly brace conventions for all control statements
    'curly': [2, 'multi-line'],
    // require default case in switch statements
    'default-case': 2,
    // encourages use of dot notation whenever possible
    'dot-notation': [2, { 'allowKeywords': true }],
    // enforces consistent newlines before or after dots
    'dot-location': 0,
    // require the use of === and !==
    'eqeqeq': 2,
    // make sure for-in loops have an if statement
    'guard-for-in': 2,
    // Blacklist certain identifiers to prevent them being used
    // http://eslint.org/docs/rules/id-blacklist
    'id-blacklist': 0,
    // disallow the use of alert, confirm, and prompt
    'no-alert': 1,
    // disallow use of arguments.caller or arguments.callee
    'no-caller': 2,
    // disallow lexical declarations in case/default clauses
    // http://eslint.org/docs/rules/no-case-declarations.html
    'no-case-declarations': 2,
    // disallow division operators explicitly at beginning of regular expression
    'no-div-regex': 0,
    // disallow else after a return in an if
    'no-else-return': 2,
    // disallow Unnecessary Labels
    // http://eslint.org/docs/rules/no-extra-label
    'no-extra-label': 2,
    // disallow comparisons to null without a type-checking operator
    'no-eq-null': 0,
    // disallow use of eval()
    'no-eval': 2,
    // disallow adding to native types
    'no-extend-native': 2,
    // disallow unnecessary function binding
    'no-extra-bind': 2,
    // disallow fallthrough of case statements
    'no-fallthrough': 2,
    // disallow the use of leading or trailing decimal points in numeric literals
    'no-floating-decimal': 2,
    // disallow the type conversions with shorter notations
    'no-implicit-coercion': 0,
    // disallow use of eval()-like methods
    'no-implied-eval': 2,
    // disallow this keywords outside of classes or class-like objects
    'no-invalid-this': 0,
    // disallow usage of __iterator__ property
    'no-iterator': 2,
    // disallow use of labels for anything other then loops and switches
    'no-labels': [2, { 'allowLoop': false, 'allowSwitch': false }],
    // disallow unnecessary nested blocks
    'no-lone-blocks': 2,
    // disallow creation of functions within loops
    'no-loop-func': 2,
    // disallow use of multiple spaces
    'no-multi-spaces': 2,
    // disallow use of multiline strings
    'no-multi-str': 2,
    // disallow reassignments of native objects
    'no-native-reassign': 2,
    // disallow use of new operator when not part of the assignment or comparison
    'no-new': 2,
    // disallow use of new operator for Function object
    'no-new-func': 2,
    // disallows creating new instances of String, Number, and Boolean
    'no-new-wrappers': 2,
    // disallow use of (old style) octal literals
    'no-octal': 2,
    // disallow use of octal escape sequences in string literals, such as
    // var foo = 'Copyright \251';
    'no-octal-escape': 2,
    // disallow reassignment of function parameters
    // disallow parameter object manipulation
    // rule: http://eslint.org/docs/rules/no-param-reassign.html
    'no-param-reassign': [2, { 'props': true }],
    // disallow use of process.env
    'no-process-env': 0,
    // disallow usage of __proto__ property
    'no-proto': 2,
    // disallow declaring the same variable more then once
    'no-redeclare': 2,
    // disallow use of assignment in return statement
    'no-return-assign': 2,
    // disallow use of `javascript:` urls.
    'no-script-url': 2,
    // disallow comparisons where both sides are exactly the same
    'no-self-compare': 2,
    // disallow use of comma operator
    'no-sequences': 2,
    // restrict what can be thrown as an exception
    'no-throw-literal': 2,
    // disallow unmodified conditions of loops
    // http://eslint.org/docs/rules/no-unmodified-loop-condition
    'no-unmodified-loop-condition': 0,
    // disallow usage of expressions in statement position
    'no-unused-expressions': 2,
    // disallow unused labels
    // http://eslint.org/docs/rules/no-unused-labels
    'no-unused-labels': 2,
    // disallow unnecessary .call() and .apply()
    'no-useless-call': 0,
    // disallow useless string concatenation
    // http://eslint.org/docs/rules/no-useless-concat
    'no-useless-concat': 2,
    // disallow unnecessary string escaping
    // http://eslint.org/docs/rules/no-useless-escape
    'no-useless-escape': 2,
    // disallow use of void operator
    'no-void': 0,
    // disallow usage of configurable warning terms in comments: e.g. todo
    'no-warning-comments': [0, { 'terms': ['todo', 'fixme', 'xxx'], 'location': 'start' }],
    // disallow use of the with statement
    'no-with': 2,
    // require use of the second argument for parseInt()
    'radix': 2,
    // requires to declare all vars on top of their containing scope
    'vars-on-top': 2,
    // require immediate function invocation to be wrapped in parentheses
    // http://eslint.org/docs/rules/wrap-iife.html
    'wrap-iife': [2, 'outside'],
    // require or disallow Yoda conditions
    'yoda': 2
  }
};
<|endoftext|>


<commit_before>/** @jsx React.DOM */

define(function (require) {

    var React = require('react');
    var Header = require('./Header.react');
    var Sidebar = require('./Sidebar.react');
    var Footer = require('./Footer.react');
    var Notifications = require('./Notifications.react');
    var Router = require('router');
    var Profile = require('controllers/profile');
    var Settings = require('./Settings.react');
    var Projects = require('./projects/List.react');
    var ApplicationList = require('./applications/ApplicationsHome.react');
    var ApplicationFavorites = require('./applications/Favorites.react');
    var ApplicationDetail = require('./applications/ApplicationDetail.react');
    var ProviderController = require('controllers/providers');
    var Providers = require('./Providers.react');
    var Help = require('./Help.react');
    var InstanceDetail = require('./instances/InstanceDetail.react');
    var ReportInstance = require('./instances/Report.react');
    var VolumeDetail = require('./VolumeDetailWrapper.react');
    var ApplicationSearchResults = require('./applications/SearchResults.react');
    var InstanceCollection = require('collections/instances');
    var Instance = require('models/instance');
    var VolumeCollection = require('collections/volumes');
    var Volume = require('models/volume');
    var AppCollection = require('collections/applications');
    var Application = require('models/application');
    var ProjectController = require('controllers/projects');
    var NotificationController = require('controllers/notifications');

    return React.createClass({

      getInitialState: function () {
        return {
          loggedIn: this.props.session.isValid(),
          profile: null,
          route: null,
          routeArgs: [],
          providers: null,
          identities: null,
          instances: new InstanceCollection(),
          volumes: new VolumeCollection(),
          applications: new AppCollection()
        };
      },

      handleRoute: function (page, args) {
        if (page === 'handleDefaultRoute') return;
        this.setState({route: page, routeArgs: args});
      },

      beginRouting: function () {
        this.router = new Router({
          loggedIn: this.state.loggedIn,
          application: this
        });

        this.router.on("route", this.handleRoute);

        Backbone.history.start({
          pushState: true,
          root: '/application'
        });
      },

      fetchProfile: function () {
        Profile.getProfile().then(function (profile) {
          this.setState({profile: profile});

          profile.on('change', function (m) {
            this.setState({profile: m});
          }.bind(this));
        }.bind(this));
      },

      fetchProviders: function () {
        // TODO: fetch providers only on demand in stead of at mount
        ProviderController.getProviders().then(function (providers) {
          this.setState({providers: providers});

          providers.on('change', function (m) {
            this.setState({providers: providers});
          }.bind(this));
        }.bind(this));
      },

      componentDidMount: function () {
        this.beginRouting();
        if (this.props.session.isValid()) {
          this.fetchProfile();
          this.fetchProviders();
        }
      },

      handleNavigate: function (route, options) {
        this.router.navigate(route, options);
      },

      fetchInstance: function (providerId, identityId, instanceId) {
        var model = new Instance({
          identity: {
            provider: providerId,
            id: identityId
          },
          id: instanceId
        });

        model.fetch({
          success: function (instance) {
            this.state.instances.add(instance);
            this.setState({instances: this.state.instances});
          }.bind(this),
          error: function () {
            NotificationController.danger("Unknown Instance", "The requested instance does not exist.");
          }
        });
      },

      fetchVolume: function (providerId, identityId, volumeId) {
        var model = new Volume({
          identity: {
            provider: providerId,
            id: identityId
          },
          id: volumeId
        });

        model.fetch({
          success: function (volume) {
            this.state.volumes.add(volume);
            this.setState({volumes: this.state.volumes});
          }.bind(this),
          error: function () {
            NotificationController.danger("Unknown Volume", "The requested volume does not exist.");
          }
        });
      },

      fetchApplication: function (appId) {
        var app = new Application({id: appId});
        app.fetch({success: function (model) {
          this.state.applications.add(model);
          this.setState({applications: this.state.applications});
        }.bind(this)});
      },

      fetchIdentities: function () {
        Profile.getIdentities().then(function (identities) {
          this.setState({identities: identities});
        }.bind(this));
      },

      fetchProjects: function () {
        ProjectController.get().then().then(function (projects) {
          this.setState({projects: projects});

          projects.on('change add remove', function () {
            this.setState({projects: projects});
          }.bind(this));
        }.bind(this));
      },

      pages: {
        projects: function () {
          return (
            <Projects projects={this.state.projects} onRequestProjects={this.fetchProjects}/>
          );
        },
        images: function () {
          return (
            <ApplicationList/>
          );
        },
        appFavorites: function () {
          return (
            <ApplicationFavorites/>
          );
        },
        appDetail: function (appId) {
          var application = this.state.applications.get(appId);
          return (
            <ApplicationDetail
              application={application}
              onRequestApplication={this.fetchApplication.bind(this, appId)}
              onRequestIdentities={this.fetchIdentities}
              profile={this.state.profile}
              identities={this.state.identities}
              providers={this.state.providers}
            />
          );
        },
        appSearch: function (query) {
          return (
            <ApplicationSearchResults query={query}/>
          );
        },
        instanceDetail: function (providerId, identityId, instanceId) {
          var instance = this.state.instances.get(instanceId);
          return (
            <InstanceDetail
              instance={instance}
              providers={this.state.providers}
              onRequestInstance={this.fetchInstance.bind(this, providerId, identityId, instanceId)}
            />
          );
        },
        reportInstance: function (providerId, identityId, instanceId) {
          return (
            <ReportInstance
              instance={this.state.instances.get(instanceId)}
              providers={this.state.providers}
              onRequestInstance={this.fetchInstance.bind(this, providerId, identityId, instanceId)}
            />
          );
        },
        volumeDetail: function (providerId, identityId, volumeId) {
          var volume = this.state.volumes.get(volumeId);
          return (
            <VolumeDetail
              volume={volume}
              providers={this.state.providers}
              onRequestVolume={this.fetchVolume.bind(this, providerId, identityId, volumeId)}
            />
          );
        },
        providers: function () {
          // TODO: Get providers lazily
          return (
            <Providers providers={this.state.providers}/>
          );
        },
        settings: function () {
          return (
            <Settings profile={this.state.profile}/>
          );
        },
        help: function () {
          return (
            <Help/>
          );
        }
      },

      renderContent: function () {
        if (this.state.route){
          return this.pages[this.state.route].apply(this, this.state.routeArgs);
        }
        return (

        );
      },

      render: function () {
        return (

            <Sidebar loggedIn={this.state.loggedIn}
                     currentRoute={this.state.route}
                     onNavigate={this.handleNavigate}/>
            <Notifications/>

              {this.renderContent()}

        );
      }

    });

  });
<commit_msg>remove unused original Root component<commit_after><|endoftext|>


<commit_before>export default ['$scope', '$http', '$stateParams', function($scope, $http, $stateParams) {

  $http.get('/api/pipelines/' + $stateParams.id).then(response => {
    $scope.pipeline = response.data.data

    $http.get('/api/projects/' + response.data.data.project_id).then(response => {
      $scope.project = response.data.data
    })

  })

  $http.get('api/pipelines/' + $stateParams.id + '/stages').then(response => {
    $scope.stages = response.data.data

    setTimeout(function() {
      $(function() {
        $('.pipeline-stage a.configure').on('click', function() {
          console.log('clicked')
          $(this).parent().parent().find('.panel-body').slideToggle(200)
        })
      })

    }, 1)
  })

}]
<commit_msg>Request stage type data with stage configs<commit_after>export default ['$q', '$scope', '$http', '$stateParams', function($q, $scope, $http, $stateParams) {

  $http.get('/api/pipelines/' + $stateParams.id).then(response => {
    $scope.pipeline = response.data.data

    $http.get('/api/projects/' + response.data.data.project_id).then(response => {
      $scope.project = response.data.data
    })

  })

  let stageTypes = $http.get('/api/stage-types')
  let stageConfigs= $http.get('api/pipelines/' + $stateParams.id + '/stages')

  $q.all([stageTypes, stageConfigs])
    .then(args => {
      let types = args[0].data.data
      let stages = args[1].data.data

      $scope.stages = stages.map(stage => {
        let type = types.find(type => type.fqid === stage.type)
        if (type) {
          stage.schema = type
        }
        return stage
      })

      setTimeout(function() {
        $(function() {
          $('.pipeline-stage a.configure').on('click', function() {
            console.log('clicked')
            $(this).parent().parent().find('.panel-body').slideToggle(200)
          })
        })

      }, 1)

    })

}]
<|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.
*/

/*
* This script compiles modules for evaluating polynomial functions. If any polynomial coefficients change, this script should be rerun to update the compiled files.
*/
'use strict';

// MODULES //

var resolve = require( 'path' ).resolve;
var writeFileSync = require( '@stdlib/fs/write-file' ).sync;
var compile = require( '@stdlib/math/base/tools/evalrational-compile' );

// VARIABLES //

// Polynomial coefficients ordered in ascending degree...

/*
* arcsin(x) = x + x^3 P(x^2)/Q(x^2)
* 0 <= x <= 0.625
* Peak relative error = 1.2e-18
*/
var P = [
	-8.198089802484824371615e0,
	1.956261983317594739197e1,
	-1.626247967210700244449e1,
	5.444622390564711410273e0,
	-6.019598008014123785661e-1,
	4.253011369004428248960e-3
];
var Q = [
	-4.918853881490881290097e1,
	1.395105614657485689735e2,
	-1.471791292232726029859e2,
	7.049610280856842141659e1,
	-1.474091372988853791896e1,
	1.0
];

/*
* arcsin(1-x) = pi/2 - sqrt(2x)(1+R(x))
* 0 <= x <= 0.5
* Peak relative error = 4.2e-18
*/
var R = [
	2.853665548261061424989e1,
	-2.556901049652824852289e1,
	6.968710824104713396794e0,
	-5.634242780008963776856e-1,
	2.967721961301243206100e-3
];
var S = [
	3.424398657913078477438e2,
	-3.838770957603691357202e2,
	1.470656354026814941758e2,
	-2.194779531642920639778e1,
	1.0
];

// Header line to add to output files:
var header = '/* This is a generated file. Do not edit directly. */\n';

// MAIN //

/**
* Main execution sequence.
*/
function main() {
	var fpath;
	var opts;
	var str;

	opts = {
		'encoding': 'utf8'
	};

	fpath = resolve( __dirname, '..', 'lib', 'rational_pq.js' );
	str = header + compile( P, Q );
	writeFileSync( fpath, str, opts );

	fpath = resolve( __dirname, '..', 'lib', 'rational_rs.js' );
	str = header + compile( R, S );
	writeFileSync( fpath, str, opts );
}

main();
<commit_msg>Update to insert license header<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.
*/

/*
* This script compiles modules for evaluating polynomial functions. If any polynomial coefficients change, this script should be rerun to update the compiled files.
*/
'use strict';

// MODULES //

var resolve = require( 'path' ).resolve;
var writeFileSync = require( '@stdlib/fs/write-file' ).sync;
var licenseHeader = require( '@stdlib/_tools/licenses/header' );
var compile = require( '@stdlib/math/base/tools/evalrational-compile' );

// VARIABLES //

// Polynomial coefficients ordered in ascending degree...

/*
* arcsin(x) = x + x^3 P(x^2)/Q(x^2)
* 0 <= x <= 0.625
* Peak relative error = 1.2e-18
*/
var P = [
	-8.198089802484824371615e0,
	1.956261983317594739197e1,
	-1.626247967210700244449e1,
	5.444622390564711410273e0,
	-6.019598008014123785661e-1,
	4.253011369004428248960e-3
];
var Q = [
	-4.918853881490881290097e1,
	1.395105614657485689735e2,
	-1.471791292232726029859e2,
	7.049610280856842141659e1,
	-1.474091372988853791896e1,
	1.0
];

/*
* arcsin(1-x) = pi/2 - sqrt(2x)(1+R(x))
* 0 <= x <= 0.5
* Peak relative error = 4.2e-18
*/
var R = [
	2.853665548261061424989e1,
	-2.556901049652824852289e1,
	6.968710824104713396794e0,
	-5.634242780008963776856e-1,
	2.967721961301243206100e-3
];
var S = [
	3.424398657913078477438e2,
	-3.838770957603691357202e2,
	1.470656354026814941758e2,
	-2.194779531642920639778e1,
	1.0
];

// Header line to add to output files:
var header = licenseHeader( 'Apache-2.0', 'js', {
	'year': ( new Date() ).getFullYear(),
	'copyright': 'The Stdlib Authors'
});
header += '\n/* This is a generated file. Do not edit directly. */\n';

// MAIN //

/**
* Main execution sequence.
*
* @private
*/
function main() {
	var fpath;
	var opts;
	var str;

	opts = {
		'encoding': 'utf8'
	};

	fpath = resolve( __dirname, '..', 'lib', 'rational_pq.js' );
	str = header + compile( P, Q );
	writeFileSync( fpath, str, opts );

	fpath = resolve( __dirname, '..', 'lib', 'rational_rs.js' );
	str = header + compile( R, S );
	writeFileSync( fpath, str, opts );
}

main();
<|endoftext|>


<commit_before>import Promise from 'bluebird';
import path from 'path';
import configHelper from '../configHelper.js';

let Response = (status, error, data) => {
  return {
    status, //Use HTTP status code
    error,  //Error object
    data    //Response data
  };
}

let fs = Promise.promisifyAll(require('fs'));

const add = (req, res) => {
  if(!path.isAbsolute(req.body.folder)) {
    res.sendStatus(404);
  } else {
    fs.statAsync(req.body.folder)
    .then(stats => {
      if(stats.isDirectory()) {
        configHelper.saveFolder(
        {'folder': {
            'name': path.basename(req.body.folder),
            'path': path.dirname(req.body.folder)
          }
        }).then(() => res.sendStatus(201));

      } else {

        res.sendStatus(420);
      }
    })
    .catch(err => {
      res.sendStatus(420);
    })
  }
};

const get = (req, res) => {
  configHelper.get().then((folders) => {
    folders.fest = 'hej';
    res.sender.send('folders/get', new Response(200, null, folders));
  })
  .catch(err => {
    res.sender.send('folders/get', new Response(404, err.message, null));
  })
}

module.exports = {
  add,
  get
};<commit_msg>correct the use of response data object<commit_after>import Promise from 'bluebird';
import path from 'path';
import configHelper from '../configHelper.js';

let Response = (error, data, status) => {
  return {
    error,
    data,
    status
  };
}

let fs = Promise.promisifyAll(require('fs'));

const add = (req, res) => {
  if(!path.isAbsolute(req.body.folder)) {
    res.sendStatus(404);
  } else {
    fs.statAsync(req.body.folder)
    .then(stats => {
      if(stats.isDirectory()) {
        configHelper.saveFolder(
        {'folder': {
            'name': path.basename(req.body.folder),
            'path': path.dirname(req.body.folder)
          }
        }).then(() => res.sendStatus(null, null, 200));

      } else {

        res.sendStatus(420);
      }
    })
    .catch(err => {
      res.sendStatus(420);
    })
  }
};

const get = (req, res) => {
  configHelper.get().then((folders) => {
    console.log(folders);
    folders.fest = 'hej';
    console.log("Skickar response!");
    res.sender.send('folders/get', new Response(null, folders, 200));
  })
  .catch(err => {
    res.sender.send('folders/get', new Response(err.message, null, 404));
  })
}

module.exports = {
  add,
  get
};<|endoftext|>


<commit_before>const bitapScore = require('./bitap_score')
const matchedIndices = require('./bitap_matched_indices')

module.exports = (text, pattern, patternAlphabet, { location = 0, distance = 100, threshold = 0.6, findAllMatches = false, minMatchCharLength = 1 }) => {
  const expectedLocation = location
  // Set starting location at beginning text and initialize the alphabet.
  const textLen = text.length
  // Highest score beyond which we give up.
  let currentThreshold = threshold
  // Is there a nearby exact match? (speedup)
  let bestLocation = text.indexOf(pattern, expectedLocation)

  const patternLen = pattern.length

  // a mask of the matches
  const matchMask = []
  for (let i = 0; i < textLen; i += 1) {
    matchMask[i] = 0
  }

  if (bestLocation != -1) {
    let score = bitapScore(pattern, {
      errors: 0,
      currentLocation: bestLocation,
      expectedLocation,
      distance
    })
    currentThreshold = Math.min(score, currentThreshold)

    // What about in the other direction? (speed up)
    bestLocation = text.lastIndexOf(pattern, expectedLocation + patternLen)

    if (bestLocation != -1) {
      let score = bitapScore(pattern, {
        errors: 0,
        currentLocation: bestLocation,
        expectedLocation,
        distance
      })
      currentThreshold = Math.min(score, currentThreshold)
    }
  }

  // Reset the best location
  bestLocation = -1

  let lastBitArr = []
  let finalScore = 1
  let binMax = patternLen + textLen

  const mask = 1 << (patternLen - 1)

  for (let i = 0; i < patternLen; i += 1) {
    // Scan for the best match; each iteration allows for one more error.
    // Run a binary search to determine how far from the match location we can stray
    // at this error level.
    let binMin = 0
    let binMid = binMax

    while (binMin < binMid) {
      const score = bitapScore(pattern, {
        errors: i,
        currentLocation: expectedLocation + binMid,
        expectedLocation,
        distance
      })

      if (score <= currentThreshold) {
        binMin = binMid
      } else {
        binMax = binMid
      }

      binMid = Math.floor((binMax - binMin) / 2 + binMin)
    }

    // Use the result from this iteration as the maximum for the next.
    binMax = binMid

    let start = Math.max(1, expectedLocation - binMid + 1)
    let finish = findAllMatches ? textLen : Math.min(expectedLocation + binMid, textLen) + patternLen

    // Initialize the bit array
    let bitArr = Array(finish + 2)

    bitArr[finish + 1] = (1 << i) - 1

    for (let j = finish; j >= start; j -= 1) {
      let currentLocation = j - 1
      let charMatch = patternAlphabet[text.charAt(currentLocation)]

      if (charMatch) {
        matchMask[currentLocation] = 1
      }

      // First pass: exact match
      bitArr[j] = ((bitArr[j + 1] << 1) | 1) & charMatch

      // Subsequent passes: fuzzy match
      if (i !== 0) {
        bitArr[j] |= (((lastBitArr[j + 1] | lastBitArr[j]) << 1) | 1) | lastBitArr[j + 1]
      }

      if (bitArr[j] & mask) {
        finalScore = bitapScore(pattern, {
          errors: i,
          currentLocation,
          expectedLocation,
          distance
        })

        // This match will almost certainly be better than any existing match.
        // But check anyway.
        if (finalScore <= currentThreshold) {
          // Indeed it is
          currentThreshold = finalScore
          bestLocation = currentLocation

          // Already passed `loc`, downhill from here on in.
          if (bestLocation <= expectedLocation) {
            break
          }

          // When passing `bestLocation`, don't exceed our current distance from `expectedLocation`.
          start = Math.max(1, 2 * expectedLocation - bestLocation)
        }
      }
    }

    // No hope for a (better) match at greater error levels.
    const score = bitapScore(pattern, {
      errors: i + 1,
      currentLocation: expectedLocation,
      expectedLocation,
      distance
    })

    if (score > currentThreshold) {
      break
    }

    lastBitArr = bitArr
  }

  // Count exact matches (those with a score of 0) to be "almost" exact
  return {
    isMatch: bestLocation >= 0,
    score: finalScore === 0 ? 0.001 : finalScore,
    matchedIndices: matchedIndices(matchMask, minMatchCharLength)
  }
}<commit_msg>Convert all != to !== (#169)<commit_after>const bitapScore = require('./bitap_score')
const matchedIndices = require('./bitap_matched_indices')

module.exports = (text, pattern, patternAlphabet, { location = 0, distance = 100, threshold = 0.6, findAllMatches = false, minMatchCharLength = 1 }) => {
  const expectedLocation = location
  // Set starting location at beginning text and initialize the alphabet.
  const textLen = text.length
  // Highest score beyond which we give up.
  let currentThreshold = threshold
  // Is there a nearby exact match? (speedup)
  let bestLocation = text.indexOf(pattern, expectedLocation)

  const patternLen = pattern.length

  // a mask of the matches
  const matchMask = []
  for (let i = 0; i < textLen; i += 1) {
    matchMask[i] = 0
  }

  if (bestLocation !== -1) {
    let score = bitapScore(pattern, {
      errors: 0,
      currentLocation: bestLocation,
      expectedLocation,
      distance
    })
    currentThreshold = Math.min(score, currentThreshold)

    // What about in the other direction? (speed up)
    bestLocation = text.lastIndexOf(pattern, expectedLocation + patternLen)

    if (bestLocation !== -1) {
      let score = bitapScore(pattern, {
        errors: 0,
        currentLocation: bestLocation,
        expectedLocation,
        distance
      })
      currentThreshold = Math.min(score, currentThreshold)
    }
  }

  // Reset the best location
  bestLocation = -1

  let lastBitArr = []
  let finalScore = 1
  let binMax = patternLen + textLen

  const mask = 1 << (patternLen - 1)

  for (let i = 0; i < patternLen; i += 1) {
    // Scan for the best match; each iteration allows for one more error.
    // Run a binary search to determine how far from the match location we can stray
    // at this error level.
    let binMin = 0
    let binMid = binMax

    while (binMin < binMid) {
      const score = bitapScore(pattern, {
        errors: i,
        currentLocation: expectedLocation + binMid,
        expectedLocation,
        distance
      })

      if (score <= currentThreshold) {
        binMin = binMid
      } else {
        binMax = binMid
      }

      binMid = Math.floor((binMax - binMin) / 2 + binMin)
    }

    // Use the result from this iteration as the maximum for the next.
    binMax = binMid

    let start = Math.max(1, expectedLocation - binMid + 1)
    let finish = findAllMatches ? textLen : Math.min(expectedLocation + binMid, textLen) + patternLen

    // Initialize the bit array
    let bitArr = Array(finish + 2)

    bitArr[finish + 1] = (1 << i) - 1

    for (let j = finish; j >= start; j -= 1) {
      let currentLocation = j - 1
      let charMatch = patternAlphabet[text.charAt(currentLocation)]

      if (charMatch) {
        matchMask[currentLocation] = 1
      }

      // First pass: exact match
      bitArr[j] = ((bitArr[j + 1] << 1) | 1) & charMatch

      // Subsequent passes: fuzzy match
      if (i !== 0) {
        bitArr[j] |= (((lastBitArr[j + 1] | lastBitArr[j]) << 1) | 1) | lastBitArr[j + 1]
      }

      if (bitArr[j] & mask) {
        finalScore = bitapScore(pattern, {
          errors: i,
          currentLocation,
          expectedLocation,
          distance
        })

        // This match will almost certainly be better than any existing match.
        // But check anyway.
        if (finalScore <= currentThreshold) {
          // Indeed it is
          currentThreshold = finalScore
          bestLocation = currentLocation

          // Already passed `loc`, downhill from here on in.
          if (bestLocation <= expectedLocation) {
            break
          }

          // When passing `bestLocation`, don't exceed our current distance from `expectedLocation`.
          start = Math.max(1, 2 * expectedLocation - bestLocation)
        }
      }
    }

    // No hope for a (better) match at greater error levels.
    const score = bitapScore(pattern, {
      errors: i + 1,
      currentLocation: expectedLocation,
      expectedLocation,
      distance
    })

    if (score > currentThreshold) {
      break
    }

    lastBitArr = bitArr
  }

  // Count exact matches (those with a score of 0) to be "almost" exact
  return {
    isMatch: bestLocation >= 0,
    score: finalScore === 0 ? 0.001 : finalScore,
    matchedIndices: matchedIndices(matchMask, minMatchCharLength)
  }
}<|endoftext|>


<commit_before>(function() {

  'use strict';

  angular
    .module('application')
    .directive('preview', PreviewDirective);

  function PreviewDirective() {
    return {
      restrict : 'E',
      templateUrl: '/static/templates/preview.directive.html',
      controller: 'PreviewController',
      controllerAs: 'vm',
      link: function (scope,elem,attrs) {
        // Determine if last ng-repeat item has been loaded and then
        // Bind foundation to document
        if (scope.$last === true) {
            elem.ready(function () {
                $(document).foundation();
                console.log("Sticky Started");
            });
        }
      }
    };
  }

})();
<commit_msg>Ignored sticky menu<commit_after>(function() {

  'use strict';

  angular
    .module('application')
    .directive('preview', PreviewDirective);

  function PreviewDirective() {
    return {
      restrict : 'E',
      templateUrl: '/static/templates/preview.directive.html',
      controller: 'PreviewController',
      controllerAs: 'vm',
      link: function (scope,elem,attrs) {
        // Determine if last ng-repeat item has been loaded and then
        // Bind foundation to document
        // if (scope.$last === true) {
        //     elem.ready(function () {
        //         $(document).foundation();
        //         console.log("Sticky Started");
        //     });
        // }
      }
    };
  }

})();
<|endoftext|>


<commit_before>'use strict'

const phoneFormatter = require('phone-formatter');

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

/**
 * Verifies new webhook when setting up Messenger app
 *
 * @param req
 * @param res
 */
function verify(req, res) {
    console.log("Receiving webhook verification from FB.");
    var verifyToken = config.facebookVerifyToken;
    if (req.query['hub.verify_token'] === verifyToken) {
        res.send(req.query['hub.challenge'])
    }
    res.send('Error, wrong token');
}

/**
 * Makes array of generic request objects from incoming context
 *
 * @param context
 * @return {genericRequests}
 */
function translateRequestToGenericFormats(context) {
  var genericRequests = [];
  // iterate over messaging events - FBM uses batch processing
  var messaging_events = context.userRequest.entry[0].messaging;
  for (let i = 0; i < messaging_events.length; i++) {
    let singleGenericRequest = {
      reqType: '',
      userInput: '',
      context: context
    };
    var event = context.userRequest.entry[0].messaging[i];
    if (event.message && event.message.text) {
      console.log("Standard user input Post detected from FB");
      singleGenericRequest.userInput = event.message.text;
      singleGenericRequest.reqType = 'user-input';
      genericRequests.push(singleGenericRequest);
    }
    else if (event.postback) {
      console.log("Postback Post detected from FB");
    // Later: determine if this is triggering a new search, or displaying more Companies - right now just triggers new search
      singleGenericRequest.userInput = event.postback.payload;
      singleGenericRequest.reqType = 'postback';
      genericRequests.push(singleGenericRequest);
    }
    else {
      console.log("Non-text-input Post detected from FB");
      singleGenericRequest.reqType = 'confirmation';
      genericRequests.push(singleGenericRequest);
    }
  }
  return genericRequests;
}

/**
 * Takes generic response data and structures payloads for Messenger sending
 *
 * @param genericResponse
 * @return {payloads}
 */
function generateResponsePayloads(genericResponse) {
  console.log("About to begin generating payloads from genericResponse.");
  var payloads = [];

  // if a False object passed in (eg from a confirmation, returns blank payload)
  if (!genericResponse) {
    payloads = false;
    return payloads;
  };

  var token = config.facebookAccessToken;
  var url = 'https://graph.facebook.com/v2.6/me/messages';
  var sender = genericResponse.context.userRequest.entry[0].messaging[0].sender.id;
  var userInput = genericResponse.userInput;

  // Case: nothing returned from Companies search / junk input
  if (genericResponse.type === 'nothing-found') {
    console.log('No Company Results flag detected in genericResponse.');
    let elements = [{
        "title": "Nothing found!",
        "subtitle": 'I couldn\'t tell what you meant by \"' + userInput + '\". Please tell me company you are looking for. (ex: \"Verizon Wireless\")',
        "buttons": [{
            "type": "web_url",
            "url": "https://gethuman.com",
            "title": "Go to GetHuman"
        }],
    }];
    payloads.push(makePayload(token, url, sender, elements));
  }
  else if (genericResponse.type === 'standard') {
    console.log('Standard type flag detected in genericResponse.');

    var name = genericResponse.data.name || '';
    var posts = genericResponse.data.posts || [];
    var contactMethods = genericResponse.data.contactMethods || [];
    var otherCompanies = genericResponse.data.otherCompanies || [];

    // load Payload cards for Posts
    // export to a function
    if (posts && posts.length) {
      var postElements = loadPostElements(posts);
      // var postElements = [];
      // for (let i = 0; i < posts.length; i++) {
      //   let text = posts[i].title || '';
      //   let urlId = posts[i].urlId || ''
      //   let singleElement = {
      //       "title": "Top issues for " + name + ", #" + (i+1) + " of " + posts.length + ":",
      //       "subtitle": text,
      //       "buttons": [{
      //           "type": "web_url",
      //           "url": "https://gethuman.com?company=" + encodeURIComponent(name) ,
      //           "title": "Solve for Me - $20"
      //       },
      //       {
      //           "type": "web_url",
      //           "url": "https://answers.gethuman.co/_" + encodeURIComponent(urlId) ,
      //           "title": "More info ..."
      //       }],
      //   };
      //   postElements.push(singleElement);
      // }
      payloads.push(makePayload(token, url, sender, postElements));
    }

    // load Contact Methods card to Payload
    // export to a function?
    if (contactMethods) {
      var contactMethodsElements = [{
          "title": "Best ways to contact " + name + ":",
          'buttons': formatContactButtons(contactMethods)
      }];
      if (contactMethods.email) {
          contactMethodsElements[0].subtitle = contactMethods.email;
      };
      // only push in if at least one button exists:
      if (contactMethodsElements[0].subtitle || contactMethodsElements[0].buttons.length) {
          payloads.push(makePayload(token, url, sender, contactMethodsElements));
      };
    }

    // make Other Companies Card
    // export to a function?
    if (otherCompanies && otherCompanies.length) {
      var otherCompaniesElements = [{
          "title": "Were you trying to reach " + name + "?",
          "subtitle": "Perhaps you would like to ask me about these companies:",
          "buttons": [],
      }];
      var otherCompaniesSubSet = otherCompanies.slice(0,3);
      otherCompaniesSubSet.forEach(function(altCompany){
          otherCompaniesElements[0].buttons.push({
              "type": "postback",
              "title": altCompany,
              // payload must be string, max 100 chars
              "payload": altCompany
          })
      })
      payloads.push(makePayload(token, url, sender, otherCompaniesElements));
    }

    // if no other payload loaded up, send a Nothing-Found reponse
    if (!payloads.length) {
      let elements = [{
          "title": "Nothing found!",
          "subtitle": 'I couldn\'t tell what you meant by \"' + userInput + '\". Please tell me company you are looking for. (ex: \"Verizon Wireless\")',
          "buttons": [{
              "type": "web_url",
              "url": "https://gethuman.com",
              "title": "Go to GetHuman"
          }],
      }];
      payloads.push(makePayload(token, url, sender, elements));
    }
  }
  console.log('Payloads prepared by Messenger bot.');
  return payloads;
}

function loadPostElements(posts, name) {
  var postElements = [];
  for (let i = 0; i < posts.length; i++) {
    let text = posts[i].title || '';
    let urlId = posts[i].urlId || ''
    let singleElement = {
        "title": "Top issues for " + name + ", #" + (i+1) + " of " + posts.length + ":",
        "subtitle": text,
        "buttons": [{
            "type": "web_url",
            "url": "https://gethuman.com?company=" + encodeURIComponent(name) ,
            "title": "Solve for Me - $20"
        },
        {
            "type": "web_url",
            "url": "https://answers.gethuman.co/_" + encodeURIComponent(urlId) ,
            "title": "More info ..."
        }],
    };
    postElements.push(singleElement);
  }
};

/**
 * Takes contact methods, formats associated buttons for Messenger card
 *
 * @param contactMethods
 * @return {buttons}
 */
function formatContactButtons(contactMethods) {
    var buttons = [];
    var counter = 1;
    for(var key in contactMethods) {
        if ((counter <= 3) && (contactMethods[key])) {
            var button = {};
            switch(key) {
                case 'twitter':
                    button = {
                        "type": "web_url",
                        "url": 'https://twitter.com/' + contactMethods[key],
                        "title": "Twitter"
                    };
                    break;
                case 'web':
                    button = {
                        "type": "web_url",
                        "url": contactMethods[key],
                        "title": "Web"
                    };
                    break;
                case 'chat':
                    button = {
                        "type": "web_url",
                        "url": contactMethods[key],
                        "title": "Chat"
                    };
                    break;
                case 'facebook':
                    button = {
                        "type": "web_url",
                        "url": contactMethods[key],
                        "title": "Facebook"
                    };
                    break;
                case 'phone':
                    button = {
                        "type": "phone_number",
                        "payload": phoneFormatter.format(contactMethods[key], "+1NNNNNNNNNN"),
                        "title": contactMethods[key]
                    }
                    break;
                case 'email':
                    console.log("Email detected, not creating button for it because Messenger won't let us.");
                    break;
                default:
                    console.log("Something went wrong in Facebook contact button formatting");
            }
            if (button.type) {
                buttons.push(button);
                counter += 1;
            }
        }
    }
    console.log("Buttons formatted from contact methods: " + JSON.stringify(buttons));
    return buttons;
}

/**
 * Forms payload for sending to Messenger
 *
 * @param token
 * @param url
 * @param sender
 * @param elements
 * @return {payload}
 */
function makePayload(token, url, sender, elements) {
  return {
    url: url,
    qs: {access_token: token},
    method: 'POST',
    json: {
        recipient: {id: sender},
        message: {
            "attachment": {
                "type": "template",
                "payload": {
                    "template_type": "generic",
                    "elements": elements
                }
            }
        },
    }
  };
};

module.exports = {
  verify: verify,
  translateRequestToGenericFormats: translateRequestToGenericFormats,
  generateResponsePayloads: generateResponsePayloads,
  formatContactButtons: formatContactButtons,
  makePayload: makePayload
};<commit_msg>debug<commit_after>'use strict'

const phoneFormatter = require('phone-formatter');

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

/**
 * Verifies new webhook when setting up Messenger app
 *
 * @param req
 * @param res
 */
function verify(req, res) {
    console.log("Receiving webhook verification from FB.");
    var verifyToken = config.facebookVerifyToken;
    if (req.query['hub.verify_token'] === verifyToken) {
        res.send(req.query['hub.challenge'])
    }
    res.send('Error, wrong token');
}

/**
 * Makes array of generic request objects from incoming context
 *
 * @param context
 * @return {genericRequests}
 */
function translateRequestToGenericFormats(context) {
  var genericRequests = [];
  // iterate over messaging events - FBM uses batch processing
  var messaging_events = context.userRequest.entry[0].messaging;
  for (let i = 0; i < messaging_events.length; i++) {
    let singleGenericRequest = {
      reqType: '',
      userInput: '',
      context: context
    };
    var event = context.userRequest.entry[0].messaging[i];
    if (event.message && event.message.text) {
      console.log("Standard user input Post detected from FB");
      singleGenericRequest.userInput = event.message.text;
      singleGenericRequest.reqType = 'user-input';
      genericRequests.push(singleGenericRequest);
    }
    else if (event.postback) {
      console.log("Postback Post detected from FB");
    // Later: determine if this is triggering a new search, or displaying more Companies - right now just triggers new search
      singleGenericRequest.userInput = event.postback.payload;
      singleGenericRequest.reqType = 'postback';
      genericRequests.push(singleGenericRequest);
    }
    else {
      console.log("Non-text-input Post detected from FB");
      singleGenericRequest.reqType = 'confirmation';
      genericRequests.push(singleGenericRequest);
    }
  }
  return genericRequests;
}

/**
 * Takes generic response data and structures payloads for Messenger sending
 *
 * @param genericResponse
 * @return {payloads}
 */
function generateResponsePayloads(genericResponse) {
  console.log("About to begin generating payloads from genericResponse.");
  var payloads = [];

  // if a False object passed in (eg from a confirmation, returns blank payload)
  if (!genericResponse) {
    payloads = false;
    return payloads;
  };

  var token = config.facebookAccessToken;
  var url = 'https://graph.facebook.com/v2.6/me/messages';
  var sender = genericResponse.context.userRequest.entry[0].messaging[0].sender.id;
  var userInput = genericResponse.userInput;

  // Case: nothing returned from Companies search / junk input
  if (genericResponse.type === 'nothing-found') {
    console.log('No Company Results flag detected in genericResponse.');
    let elements = [{
        "title": "Nothing found!",
        "subtitle": 'I couldn\'t tell what you meant by \"' + userInput + '\". Please tell me company you are looking for. (ex: \"Verizon Wireless\")',
        "buttons": [{
            "type": "web_url",
            "url": "https://gethuman.com",
            "title": "Go to GetHuman"
        }],
    }];
    payloads.push(makePayload(token, url, sender, elements));
  }
  else if (genericResponse.type === 'standard') {
    console.log('Standard type flag detected in genericResponse.');

    var name = genericResponse.data.name || '';
    var posts = genericResponse.data.posts || [];
    var contactMethods = genericResponse.data.contactMethods || [];
    var otherCompanies = genericResponse.data.otherCompanies || [];

    // load Payload cards for Posts
    // export to a function
    if (posts && posts.length) {
      var postElements = loadPostElements(posts);
      // var postElements = [];
      // for (let i = 0; i < posts.length; i++) {
      //   let text = posts[i].title || '';
      //   let urlId = posts[i].urlId || ''
      //   let singleElement = {
      //       "title": "Top issues for " + name + ", #" + (i+1) + " of " + posts.length + ":",
      //       "subtitle": text,
      //       "buttons": [{
      //           "type": "web_url",
      //           "url": "https://gethuman.com?company=" + encodeURIComponent(name) ,
      //           "title": "Solve for Me - $20"
      //       },
      //       {
      //           "type": "web_url",
      //           "url": "https://answers.gethuman.co/_" + encodeURIComponent(urlId) ,
      //           "title": "More info ..."
      //       }],
      //   };
      //   postElements.push(singleElement);
      // }
      payloads.push(makePayload(token, url, sender, postElements));
    }

    // load Contact Methods card to Payload
    // export to a function?
    if (contactMethods) {
      var contactMethodsElements = [{
          "title": "Best ways to contact " + name + ":",
          'buttons': formatContactButtons(contactMethods)
      }];
      if (contactMethods.email) {
          contactMethodsElements[0].subtitle = contactMethods.email;
      };
      // only push in if at least one button exists:
      if (contactMethodsElements[0].subtitle || contactMethodsElements[0].buttons.length) {
          payloads.push(makePayload(token, url, sender, contactMethodsElements));
      };
    }

    // make Other Companies Card
    // export to a function?
    if (otherCompanies && otherCompanies.length) {
      var otherCompaniesElements = [{
          "title": "Were you trying to reach " + name + "?",
          "subtitle": "Perhaps you would like to ask me about these companies:",
          "buttons": [],
      }];
      var otherCompaniesSubSet = otherCompanies.slice(0,3);
      otherCompaniesSubSet.forEach(function(altCompany){
          otherCompaniesElements[0].buttons.push({
              "type": "postback",
              "title": altCompany,
              // payload must be string, max 100 chars
              "payload": altCompany
          })
      })
      payloads.push(makePayload(token, url, sender, otherCompaniesElements));
    }

    // if no other payload loaded up, send a Nothing-Found reponse
    if (!payloads.length) {
      let elements = [{
          "title": "Nothing found!",
          "subtitle": 'I couldn\'t tell what you meant by \"' + userInput + '\". Please tell me company you are looking for. (ex: \"Verizon Wireless\")',
          "buttons": [{
              "type": "web_url",
              "url": "https://gethuman.com",
              "title": "Go to GetHuman"
          }],
      }];
      payloads.push(makePayload(token, url, sender, elements));
    }
  }
  console.log('Payloads prepared by Messenger bot.');
  return payloads;
}

function loadPostElements(posts, name) {
  var postElements = [];
  for (let i = 0; i < posts.length; i++) {
    let text = posts[i].title || '';
    let urlId = posts[i].urlId || ''
    let singleElement = {
        "title": "Top issues for " + name + ", #" + (i+1) + " of " + posts.length + ":",
        "subtitle": text,
        "buttons": [{
            "type": "web_url",
            "url": "https://gethuman.com?company=" + encodeURIComponent(name) ,
            "title": "Solve for Me - $20"
        },
        {
            "type": "web_url",
            "url": "https://answers.gethuman.co/_" + encodeURIComponent(urlId) ,
            "title": "More info ..."
        }],
    };
    postElements.push(singleElement);
  }
  return postElements;
};

/**
 * Takes contact methods, formats associated buttons for Messenger card
 *
 * @param contactMethods
 * @return {buttons}
 */
function formatContactButtons(contactMethods) {
    var buttons = [];
    var counter = 1;
    for(var key in contactMethods) {
        if ((counter <= 3) && (contactMethods[key])) {
            var button = {};
            switch(key) {
                case 'twitter':
                    button = {
                        "type": "web_url",
                        "url": 'https://twitter.com/' + contactMethods[key],
                        "title": "Twitter"
                    };
                    break;
                case 'web':
                    button = {
                        "type": "web_url",
                        "url": contactMethods[key],
                        "title": "Web"
                    };
                    break;
                case 'chat':
                    button = {
                        "type": "web_url",
                        "url": contactMethods[key],
                        "title": "Chat"
                    };
                    break;
                case 'facebook':
                    button = {
                        "type": "web_url",
                        "url": contactMethods[key],
                        "title": "Facebook"
                    };
                    break;
                case 'phone':
                    button = {
                        "type": "phone_number",
                        "payload": phoneFormatter.format(contactMethods[key], "+1NNNNNNNNNN"),
                        "title": contactMethods[key]
                    }
                    break;
                case 'email':
                    console.log("Email detected, not creating button for it because Messenger won't let us.");
                    break;
                default:
                    console.log("Something went wrong in Facebook contact button formatting");
            }
            if (button.type) {
                buttons.push(button);
                counter += 1;
            }
        }
    }
    console.log("Buttons formatted from contact methods: " + JSON.stringify(buttons));
    return buttons;
}

/**
 * Forms payload for sending to Messenger
 *
 * @param token
 * @param url
 * @param sender
 * @param elements
 * @return {payload}
 */
function makePayload(token, url, sender, elements) {
  return {
    url: url,
    qs: {access_token: token},
    method: 'POST',
    json: {
        recipient: {id: sender},
        message: {
            "attachment": {
                "type": "template",
                "payload": {
                    "template_type": "generic",
                    "elements": elements
                }
            }
        },
    }
  };
};

module.exports = {
  verify: verify,
  translateRequestToGenericFormats: translateRequestToGenericFormats,
  generateResponsePayloads: generateResponsePayloads,
  formatContactButtons: formatContactButtons,
  makePayload: makePayload
};<|endoftext|>


<commit_before>var CodeEditorComponent = function() {

  var initCodeMirror = function(textarea) {
    var codemirror_opts = {
      autofocus: false,
      lineNumbers: true,
      lineWrapping: true
    };

    var codemirror = CodeMirror.fromTextArea(textarea, codemirror_opts);
    codemirror.setOption("mode", this.getAttribute("data-language"));

    // FIXME horrible horrible hack to work around a bug in codemirror where
    // the editor can't be rendered properly before the browser has actually
    // rendered the backing textarea. yield to the browser and poll for
    // completed rendering
    var poll = (function(base){
      return function() {
        if ($(".CodeMirror-gutter", base).offsetWidth == 0) {
          codemirror.refresh();
          window.setTimeout(poll, 1);
        }
      };
    })(this);
    poll();

    return codemirror;
  }

  var setupKeyPressHandlers = function() {
    var base = this;

    var cmd_pressed = false;
    this.addEventListener('keydown', function(e) {
      if (e.keyCode == 17 || e.keyCode == 91) {
        cmd_pressed = true;
      }
    }, false);

    this.addEventListener('keyup', function(e) {
      if (e.keyCode == 17 || e.keyCode == 91) {
        cmd_pressed = false;
      }
    }, false);

    this.addEventListener('keydown', function(e) {
      if (e.keyCode == 13 && cmd_pressed) {
        e.preventDefault();
        base.execute.call(base);
      }
    }, false);
  };

  this.createdCallback = function() {
    var tpl = $.getTemplate("widgets/z-codeeditor", "z-codeeditor-base-tpl");

    var textarea = document.createElement("textarea");
    textarea.setAttribute("autofocus", "autofocus");
    this.appendChild(textarea);

    var codemirror = initCodeMirror.call(this, textarea);
    setupKeyPressHandlers.call(this);

    this.getValue = function() {
      return codemirror.getValue();
    };

    this.setValue = function(value) {
      if (!value) {return;}
      codemirror.setValue(value);
    }

    this.execute = function() {
      var ev = new Event('execute');
      ev.value = this.getValue();
      this.dispatchEvent(ev);
    }

    this.setupResizing = function(resizer) {
      var gutters = this.querySelector(".CodeMirror-gutters");
      var benchmark_y;

      resizer.addEventListener('dragstart', function(e) {
        this.style.background = "transparent";
        this.style.border = "none";
        benchmark_y = e.clientY;
      }, false);

      resizer.addEventListener('drag', (function(elem) {
        return function(e) {
          e.preventDefault();
          this.style.background = "";
          this.style.border = "";
          var offset = benchmark_y - e.clientY;
          elem.style.height = (elem.offsetHeight - offset) + "px";
          gutters.style.height = (elem.offsetHeight - offset) + "px";
          benchmark_y = e.clientY;
        }
      })(this));
    }
  };
};

var proto = Object.create(HTMLElement.prototype);
CodeEditorComponent.apply(proto);
document.registerElement("z-codeeditor", { prototype: proto });
<commit_msg>codeeditor handle resizing<commit_after>var CodeEditorComponent = function() {

  var initCodeMirror = function(textarea) {
    var codemirror_opts = {
      autofocus: false,
      lineNumbers: true,
      lineWrapping: true
    };

    var codemirror = CodeMirror.fromTextArea(textarea, codemirror_opts);
    codemirror.setOption("mode", this.getAttribute("data-language"));

    // FIXME horrible horrible hack to work around a bug in codemirror where
    // the editor can't be rendered properly before the browser has actually
    // rendered the backing textarea. yield to the browser and poll for
    // completed rendering
    var poll = (function(base){
      return function() {
        if ($(".CodeMirror-gutter", base).offsetWidth == 0) {
          codemirror.refresh();
          window.setTimeout(poll, 1);
        }
      };
    })(this);
    poll();

    return codemirror;
  }

  var setupKeyPressHandlers = function() {
    var base = this;

    var cmd_pressed = false;
    this.addEventListener('keydown', function(e) {
      if (e.keyCode == 17 || e.keyCode == 91) {
        cmd_pressed = true;
      }
    }, false);

    this.addEventListener('keyup', function(e) {
      if (e.keyCode == 17 || e.keyCode == 91) {
        cmd_pressed = false;
      }
    }, false);

    this.addEventListener('keydown', function(e) {
      if (e.keyCode == 13 && cmd_pressed) {
        e.preventDefault();
        base.execute.call(base);
      }
    }, false);
  };

  var setupResizer = function() {
    var resizer = this.querySelector("z-codeeditor-resizer-tooltip");
    var gutters = this.querySelector(".CodeMirror-gutters");
    var codemirror = this.querySelector(".CodeMirror");
    var benchmark_y;
    codemirror.style.height = (this.offsetHeight - resizer.offsetHeight) + "px";

    //TODO handle horizontal resizing
    resizer.addEventListener('dragstart', function(e) {
      this.style.background = "transparent";
      this.style.border = "none";
      benchmark_y = e.clientY;
    }, false);

    resizer.addEventListener('drag', (function(elem) {
      return function(e) {
        e.preventDefault();
        this.style.background = "";
        this.style.border = "";
        var offset = benchmark_y - e.clientY;
        var height = elem.offsetHeight - offset;
        elem.style.height = height + "px";
        codemirror.style.height = (height - resizer.offsetHeight) + "px";
        gutters.style.height = height + "px";
        benchmark_y = e.clientY;
      }
    })(this));
  };

  this.createdCallback = function() {
    var tpl = $.getTemplate("widgets/z-codeeditor", "z-codeeditor-base-tpl");
    this.appendChild(tpl);

    var codemirror = initCodeMirror.call(this, this.querySelector("textarea"));
    setupKeyPressHandlers.call(this);

    if (this.hasAttribute("data-resizable")) {
      window.setTimeout(setupResizer.bind(this));
    }

    this.getValue = function() {
      return codemirror.getValue();
    };

    this.setValue = function(value) {
      if (!value) {return;}
      codemirror.setValue(value);
    }

    this.execute = function() {
      var ev = new Event('execute');
      ev.value = this.getValue();
      this.dispatchEvent(ev);
    }
  };
};

var proto = Object.create(HTMLElement.prototype);
CodeEditorComponent.apply(proto);
document.registerElement("z-codeeditor", { prototype: proto });
<|endoftext|>


<commit_before>import { expect } from 'chai'
import head from '../functions/head'

describe( 'head', () => {
  it('returns the first element of an array', () => {
    expect( head([1,2,3]) ).to.eql( 1 )
  }
  it('returns the first element of a string', () => {
    expect( head('asdf') ).to.eql( 'a' )
  })

  it('returns undefined when passed an empty array', () => {
    expect( head([]) ).to.eql( undefined )
  })

  it('returns undefined when passed an empty string', () => {
    expect( head('') ).to.eql( undefined )
  })

  it('returns undefined when passed an object', () => {
    expect( head('') ).to.eql( undefined )
  })
})
<commit_msg>fix mysterious deleted close parenthesis<commit_after>import { expect } from 'chai'
import head from '../functions/head'

describe.only( 'head', () => {
  it('returns the first element of an array', () => {
    expect( head([1,2,3]) ).to.eql( 1 )
  })
  it('returns the first element of a string', () => {
    expect( head('asdf') ).to.eql( 'a' )
  })

  it('returns undefined when passed an empty array', () => {
    expect( head([]) ).to.eql( undefined )
  })

  it('returns undefined when passed an empty string', () => {
    expect( head('') ).to.eql( undefined )
  })

  it('returns undefined when passed an object', () => {
    expect( head('') ).to.eql( undefined )
  })
})
<|endoftext|>


<commit_before>(function($, window, undefined) {
	$.fn.myselect = function(settings) {

		var target = this;

		var defaultOptions = {
    		limit: 10,
    		onchangeCallback: ''
    	};

    	var currentYear = (new Date).getFullYear();
		var currentMonth = (new Date).getMonth() + 1;

		var limitYear;

		var longMonthNames = [
			"January",
			"February",
			"March",
			"April",
			"May",
			"June",
			"July",
			"August",
			"September",
			"October",
			"November",
			"December"
		];

		var shortMonthNames = [
			"Jan",
			"Feb",
			"Mar",
			"Apr",
			"May",
			"Jun",
			"Jul",
			"Aug",
			"Sep",
			"Oct",
			"Nov",
			"Dec"
		];

		var pluginWrapper = $('<div/>', {
			class: 'myselect'
		});

		var previous = $('<button/>', {
			class : "previous-year",
			title : "Previous Year"
		});

		var next = $('<button/>', {
			class : "next-year",
			title : "Next Year"
		});

		var select = $('<select/>');

		var element = pluginWrapper;

		function _getYearLimit (limit) {
			if(limit == 1)
				return currentYear;
			if(limit < 1)
				return currentYear - 10;
			else
				return currentYear - limit;
		}

		function _setupDom (element, currentYear) {
			if(currentYear) {
				$(element).append(select);
			}else {
				$(element).append(previous);
				$(element).append(select);
				$(element).append(next);
			}
		}

		function _populateSelect (element, year) {
			$select = $(element).children('select');

			$select.html('');
			$select.append($('<option/>', {
				value: "",
				text : 'Year ' + year
			}));

			$.each(longMonthNames, function (index, value) {
				$select.append($('<option/>', {
					value: index + 1,
					text : value + ' ' + year,
					disabled: (year == currentYear && index + 1 > currentMonth) ? true : false
				}));
			});

			$select.attr('data-year', year);

			if(year == currentYear) {
				$select.val(currentMonth).trigger('change');
			}
		}

		function _initButtonTexts (element, year, limitYear) {
			var selectedYear = parseInt(year);

			$previous = $(element).children('.previous-year');
			$next = $(element).children('.next-year');

			if(selectedYear == limitYear)
				$previous.attr('disabled', true).text(selectedYear - 1);
			else
				$previous.attr('disabled', false).text(selectedYear - 1);

			if(selectedYear == currentYear)
				$next.attr('disabled', true).text(selectedYear + 1);
			else
				$next.attr('disabled', false).text(selectedYear + 1);
		}

		function _initEventHandlers (element, limitYear, onchangeCallback) {
			$select = $(element).children('select');
			$select.change(function() {
				var month = $(this).val();
				var year = parseInt( $select.attr('data-year') );

				if (typeof onchangeCallback === "function") {
					onchangeCallback(month, year);
				}
			});

			$select.val(currentMonth).trigger('change');

			$previous = $(element).children('.previous-year');
			$next = $(element).children('.next-year');

			$previous.on('click', function() {
				var selectedYear = parseInt( $select.attr('data-year') );
				var previousYear = selectedYear - 1;

				_populateSelect(element, previousYear);
				_initButtonTexts(element, previousYear, limitYear);
			});

			$next.on('click', function() {
				var selectedYear = parseInt( $select.attr('data-year') );
				var nextYear = selectedYear + 1;

				_populateSelect(element, nextYear);
				_initButtonTexts(element, nextYear, limitYear);
			});

			$(document).on('data-year', function() {
			    var year = $select.attr('data-year');
			    _populateSelect(year);
			});
		}

    	defaultOptions = $.extend(defaultOptions, settings);
		limitYear = _getYearLimit(defaultOptions.limit);

		if(defaultOptions.limit != 'current-year') {
			_setupDom(target, false);
		}else {
			_setupDom(target, true);
		}

		_populateSelect(target, currentYear);
		_initButtonTexts(target, currentYear, limitYear);
		_initEventHandlers(target, limitYear, defaultOptions.onchangeCallback);

	};
})( jQuery, window );
<commit_msg>Iteration 3 of better code.<commit_after>(function($, window, undefined) {
	$.fn.myselect = function(settings) {

		var target = this;

		var defaultOptions = {
    		limit : 10,
    		onchangeCallback : '',
    		monthNames : 'long'
    	};

    	var currentYear = (new Date).getFullYear();
		var currentMonth = (new Date).getMonth() + 1;

		var limitYear;

		var longMonthNames = [
			"January",
			"February",
			"March",
			"April",
			"May",
			"June",
			"July",
			"August",
			"September",
			"October",
			"November",
			"December"
		];

		var shortMonthNames = [
			"Jan",
			"Feb",
			"Mar",
			"Apr",
			"May",
			"Jun",
			"Jul",
			"Aug",
			"Sep",
			"Oct",
			"Nov",
			"Dec"
		];

		var pluginWrapper = $('<div/>', {
			class: 'myselect'
		});

		var previous = $('<button/>', {
			class : "previous-year",
			title : "Previous Year"
		});

		var next = $('<button/>', {
			class : "next-year",
			title : "Next Year"
		});

		var select = $('<select/>');

		var element = pluginWrapper;

		function _getYearLimit (limit) {
			if(limit == 1)
				return currentYear;
			if(limit < 1)
				return currentYear - 10;
			else
				return currentYear - limit;
		}

		function _setupDom (element, options, limitYear) {
			if(options.limit != 'current-year') {
				$(element).append(previous);
				$(element).append(select);
				$(element).append(next);
			}else {
				$(element).append(select);
			}

			_populateSelect(element, currentYear);
			_initButtonTexts(element, currentYear, limitYear);
		}

		function _populateSelect (element, year) {
			$select = $(element).children('select');

			$select.html('');
			$select.append($('<option/>', {
				value: "",
				text : 'Year ' + year
			}));

			$.each(longMonthNames, function (index, value) {
				$select.append($('<option/>', {
					value: index + 1,
					text : value + ' ' + year,
					disabled: (year == currentYear && index + 1 > currentMonth) ? true : false
				}));
			});

			$select.attr('data-year', year);

			if(year == currentYear) {
				$select.val(currentMonth).trigger('change');
			}
		}

		function _initButtonTexts (element, year, limitYear) {
			var selectedYear = parseInt(year);

			$previous = $(element).children('.previous-year');
			$next = $(element).children('.next-year');

			if(selectedYear == limitYear)
				$previous.attr('disabled', true).text(selectedYear - 1);
			else
				$previous.attr('disabled', false).text(selectedYear - 1);

			if(selectedYear == currentYear)
				$next.attr('disabled', true).text(selectedYear + 1);
			else
				$next.attr('disabled', false).text(selectedYear + 1);
		}

		function _initEventHandlers (element, limitYear, onchangeCallback) {
			$select = $(element).children('select');
			$select.change(function() {
				var month = $(this).val();
				var year = parseInt( $select.attr('data-year') );

				if (typeof onchangeCallback === "function") {
					onchangeCallback(month, year);
				}
			});

			$select.val(currentMonth).trigger('change');

			$previous = $(element).children('.previous-year');
			$next = $(element).children('.next-year');

			$previous.on('click', function() {
				var selectedYear = parseInt( $select.attr('data-year') );
				var previousYear = selectedYear - 1;

				_populateSelect(element, previousYear);
				_initButtonTexts(element, previousYear, limitYear);
			});

			$next.on('click', function() {
				var selectedYear = parseInt( $select.attr('data-year') );
				var nextYear = selectedYear + 1;

				_populateSelect(element, nextYear);
				_initButtonTexts(element, nextYear, limitYear);
			});

			$(document).on('data-year', function() {
			    var year = $select.attr('data-year');
			    _populateSelect(year);
			});
		}

    	defaultOptions = $.extend(defaultOptions, settings);
		limitYear = _getYearLimit(defaultOptions.limit);
		_setupDom(target, defaultOptions, limitYear);
		_initEventHandlers(target, limitYear, defaultOptions.onchangeCallback);

	};
})( jQuery, window );
<|endoftext|>


<commit_before>'use strict'

/**
 * Provide Room-level Security
 */

class CityDefense extends kernel.process {
  constructor (...args) {
    super(...args)
    this.priority = PRIORITIES_DEFENSE
  }

  getDescriptor () {
    return this.data.room
  }

  main () {
    if (!Game.rooms[this.data.room]) {
      return this.suicide()
    }

    const room = Game.rooms[this.data.room]

    const towers = sos.lib.cache.getOrUpdate(
        [this.data.room, 'towers'],
        () => room.find(FIND_MY_STRUCTURES, {
          filter: {
            structureType: STRUCTURE_TOWER
          }
        })
        .map(s => s.id), {
          persist: true,
          maxttl: 5000,
          chance: 0.001
        })
      .map(id => Game.getObjectById(id))
      .filter(t => t)

    const hostiles = room.find(FIND_HOSTILE_CREEPS)

    if (towers && towers.length > 0) {
      this.fireTowers(towers, hostiles)
    }

    if (towers && _.some(towers, tower => tower.energy < tower.energyCapacity)) {
      this.launchCreepProcess('loader', 'replenisher', this.data.room, 1)
    }

    const playerHostiles = hostiles.filter(c => c.owner.username !== 'Invader' && this.isPotentialHazard(c))

    if (playerHostiles.length > 0) {
      Logger.log(`Hostile creep owned by ${playerHostiles[0].owner.username} detected in room ${this.data.room}.`, LOG_WARN)
      this.safeMode(playerHostiles)
    }
  }

  fireTowers (towers, hostiles) {
    if (hostiles.length > 0) {
      // for now, just shoot closest for each tower
      let tower
      for (tower of towers) {
        if (tower.energy < TOWER_ENERGY_COST) {
          continue
        }
        const closest = _.min(hostiles, c => c.pos.getRangeTo(tower.pos))
        tower.attack(closest)
      }
      return
    }

    const healFunc = (healTarget) => {
      // TODO: clever calculations to avoid overheals
      let tower
      for (tower of towers) {
        tower.heal(healTarget)
      }
    }

    if (this.data.healTarget !== undefined) {
      const healTarget = Game.getObjectById(this.data.healTarget)
      if (healTarget &&
        (healTarget.pos.roomName === this.data.room) &&
        (healTarget.hits < healTarget.hitsMax)) {
        healFunc(healTarget)
        return
      }

      // heal target no longer valid
      delete this.data.healTarget
    }

    // look for a heal target every healFrequency ticks
    const healFrequency = 5
    if (this.period(healFrequency, 'healTargetSelection')) {
      const room = Game.rooms[this.data.room]
      const myCreeps = room.find(FIND_MY_CREEPS)
      const lowestCreep = _.min(myCreeps, c => c.hits / c.hitsMax)
      if (!_.isNumber(lowestCreep) &&
        (lowestCreep.hits < lowestCreep.hitsMax)) {
        this.data.healTarget = lowestCreep.id
        healFunc(lowestCreep)
      }
    }
  }

  safeMode (hostiles) {
    const room = Game.rooms[this.data.room]
    if (room.controller.safeMode && room.controller.safeMode > 0) {
      return true
    }
    if (room.controller.safeModeAvailable <= 0 || room.controller.safeModeCooldown || room.controller.upgradeBlocked) {
      return false
    }

    let safeStructures = room.find(FIND_MY_SPAWNS)
    safeStructures.push(room.controller)
    let structure
    for (structure of safeStructures) {
      const closest = structure.pos.findClosestByRange(hostiles)
      if (structure.pos.getRangeTo(closest) < 5) {
        // Trigger safemode
        Logger.log(`Activating safemode in ${this.data.room}`, LOG_ERROR)
        room.controller.activateSafeMode()
        return true
      }
    }
    return false
  }

  isPotentialHazard (hostile) {
  	const hazardTypes = [ATTACK, RANGED_ATTACK, HEAL, WORK]

    return _.some(hostile.body, b => _.include(hazardTypes, b.type))
  }
}

module.exports = CityDefense
<commit_msg>Style requirements...<commit_after>'use strict'

/**
 * Provide Room-level Security
 */

class CityDefense extends kernel.process {
  constructor (...args) {
    super(...args)
    this.priority = PRIORITIES_DEFENSE
  }

  getDescriptor () {
    return this.data.room
  }

  main () {
    if (!Game.rooms[this.data.room]) {
      return this.suicide()
    }

    const room = Game.rooms[this.data.room]

    const towers = sos.lib.cache.getOrUpdate(
        [this.data.room, 'towers'],
        () => room.find(FIND_MY_STRUCTURES, {
          filter: {
            structureType: STRUCTURE_TOWER
          }
        })
        .map(s => s.id), {
          persist: true,
          maxttl: 5000,
          chance: 0.001
        })
      .map(id => Game.getObjectById(id))
      .filter(t => t)

    const hostiles = room.find(FIND_HOSTILE_CREEPS)

    if (towers && towers.length > 0) {
      this.fireTowers(towers, hostiles)
    }

    if (towers && _.some(towers, tower => tower.energy < tower.energyCapacity)) {
      this.launchCreepProcess('loader', 'replenisher', this.data.room, 1)
    }

    const playerHostiles = hostiles.filter(c => c.owner.username !== 'Invader' && this.isPotentialHazard(c))

    if (playerHostiles.length > 0) {
      Logger.log(`Hostile creep owned by ${playerHostiles[0].owner.username} detected in room ${this.data.room}.`, LOG_WARN)
      this.safeMode(playerHostiles)
    }
  }

  fireTowers (towers, hostiles) {
    if (hostiles.length > 0) {
      // for now, just shoot closest for each tower
      let tower
      for (tower of towers) {
        if (tower.energy < TOWER_ENERGY_COST) {
          continue
        }
        const closest = _.min(hostiles, c => c.pos.getRangeTo(tower.pos))
        tower.attack(closest)
      }
      return
    }

    const healFunc = (healTarget) => {
      // TODO: clever calculations to avoid overheals
      let tower
      for (tower of towers) {
        tower.heal(healTarget)
      }
    }

    if (this.data.healTarget !== undefined) {
      const healTarget = Game.getObjectById(this.data.healTarget)
      if (healTarget &&
        (healTarget.pos.roomName === this.data.room) &&
        (healTarget.hits < healTarget.hitsMax)) {
        healFunc(healTarget)
        return
      }

      // heal target no longer valid
      delete this.data.healTarget
    }

    // look for a heal target every healFrequency ticks
    const healFrequency = 5
    if (this.period(healFrequency, 'healTargetSelection')) {
      const room = Game.rooms[this.data.room]
      const myCreeps = room.find(FIND_MY_CREEPS)
      const lowestCreep = _.min(myCreeps, c => c.hits / c.hitsMax)
      if (!_.isNumber(lowestCreep) &&
        (lowestCreep.hits < lowestCreep.hitsMax)) {
        this.data.healTarget = lowestCreep.id
        healFunc(lowestCreep)
      }
    }
  }

  safeMode (hostiles) {
    const room = Game.rooms[this.data.room]
    if (room.controller.safeMode && room.controller.safeMode > 0) {
      return true
    }
    if (room.controller.safeModeAvailable <= 0 || room.controller.safeModeCooldown || room.controller.upgradeBlocked) {
      return false
    }

    let safeStructures = room.find(FIND_MY_SPAWNS)
    safeStructures.push(room.controller)
    let structure
    for (structure of safeStructures) {
      const closest = structure.pos.findClosestByRange(hostiles)
      if (structure.pos.getRangeTo(closest) < 5) {
        // Trigger safemode
        Logger.log(`Activating safemode in ${this.data.room}`, LOG_ERROR)
        room.controller.activateSafeMode()
        return true
      }
    }
    return false
  }

  isPotentialHazard (hostile) {
    const hazardTypes = [ATTACK, RANGED_ATTACK, HEAL, WORK]
    return _.some(hostile.body, b => _.include(hazardTypes, b.type))
  }
}

module.exports = CityDefense
<|endoftext|>


<commit_before>(function () {

    Sudoku.PossibilityCubeCell3D = function (i, j, k) {

        this.geometry = Sudoku.PossibilityCube3D.geometry;

        this.i = i;
        this.j = j;
        this.k = k;

        //states

        this._tempStateTimer = null;

        this.defaultOpacity = 0.65;

    };

    Sudoku.PossibilityCube3D.geometry = new THREE.CubeGeometry(
        Sudoku.GameBoard3D.cellSize - Sudoku.PossibilityCube3D.cellSpacing,
        Sudoku.GameBoard3D.cellSize - Sudoku.PossibilityCube3D.cellSpacing,
        Sudoku.GameBoard3D.cellSize - Sudoku.PossibilityCube3D.cellSpacing
    );
    Sudoku.PossibilityCube3D.geometry.computeBoundingSphere();
    Sudoku.PossibilityCube3D.geometry.boundRadius = Sudoku.PossibilityCube3D.geometry.boundingSphere.radius;

    Sudoku.PossibilityCubeCell3D.prototype.constructor = Sudoku.PossibilityCubeCell3D;

    Sudoku.PossibilityCubeCell3D.prototype.show = function (length, callback) {

        length = length || 500;

        callback = callback || function(){};

        if (this._isHidden) {

            this._isHidden = false;

            Utils.animate({
                obj:this.material,
                prop:'opacity',
                targetValue:this.defaultOpacity,
                length:length
            });
            Utils.animate({
                obj:this.rotation,
                prop:'z',
                targetValue:Math.PI*4,
                length:length,
                callback:function(obj,prop){
                    obj[prop] = 0;
                    callback();
                }
            });

        }

    }

    Sudoku.PossibilityCubeCell3D.prototype.hide = function (length, callback) {

        var self = this;

        length = length || 500;

        callback = callback || function(){};

        if (!this._isHidden) {

            Utils.animate({
                obj:this.material,
                prop:'opacity',
                targetValue:0,
                length:length
            });
            Utils.animate({
                obj:this.rotation,
                prop:'z',
                targetValue:Math.PI*4,
                length:length,
                callback:function(obj,prop){
                    obj[prop] = 0;
                    self._isHidden = true;
                    callback();
                }
            });

        }

    }

})();<commit_msg>signature<commit_after>/*
0xor1   http://github.com/0xor1
*/
(function () {

    Sudoku.PossibilityCubeCell3D = function (i, j, k) {

        this.geometry = Sudoku.PossibilityCube3D.geometry;

        this.i = i;
        this.j = j;
        this.k = k;

        //states

        this._tempStateTimer = null;

        this.defaultOpacity = 0.65;

    };

    Sudoku.PossibilityCube3D.geometry = new THREE.CubeGeometry(
        Sudoku.GameBoard3D.cellSize - Sudoku.PossibilityCube3D.cellSpacing,
        Sudoku.GameBoard3D.cellSize - Sudoku.PossibilityCube3D.cellSpacing,
        Sudoku.GameBoard3D.cellSize - Sudoku.PossibilityCube3D.cellSpacing
    );
    Sudoku.PossibilityCube3D.geometry.computeBoundingSphere();
    Sudoku.PossibilityCube3D.geometry.boundRadius = Sudoku.PossibilityCube3D.geometry.boundingSphere.radius;

    Sudoku.PossibilityCubeCell3D.prototype.constructor = Sudoku.PossibilityCubeCell3D;

    Sudoku.PossibilityCubeCell3D.prototype.show = function (length, callback) {

        length = length || 500;

        callback = callback || function(){};

        if (this._isHidden) {

            this._isHidden = false;

            Utils.animate({
                obj:this.material,
                prop:'opacity',
                targetValue:this.defaultOpacity,
                length:length
            });
            Utils.animate({
                obj:this.rotation,
                prop:'z',
                targetValue:Math.PI*4,
                length:length,
                callback:function(obj,prop){
                    obj[prop] = 0;
                    callback();
                }
            });

        }

    }

    Sudoku.PossibilityCubeCell3D.prototype.hide = function (length, callback) {

        var self = this;

        length = length || 500;

        callback = callback || function(){};

        if (!this._isHidden) {

            Utils.animate({
                obj:this.material,
                prop:'opacity',
                targetValue:0,
                length:length
            });
            Utils.animate({
                obj:this.rotation,
                prop:'z',
                targetValue:Math.PI*4,
                length:length,
                callback:function(obj,prop){
                    obj[prop] = 0;
                    self._isHidden = true;
                    callback();
                }
            });

        }

    }

})();
<|endoftext|>