<commit_before>if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.exports === exports){
  module.exports = 'highcharts-ng';
}
(function () {
  'use strict';
  /*global angular: false, Highcharts: false */

  angular.module('highcharts-ng', [])
    .factory('highchartsNGUtils', highchartsNGUtils)
    .directive('highchart', ['highchartsNGUtils', '$timeout', highchart]);

  function highchartsNGUtils() {

    return {

      //IE8 support
      indexOf: function (arr, find, i /*opt*/) {
        if (i === undefined) i = 0;
        if (i < 0) i += arr.length;
        if (i < 0) i = 0;
        for (var n = arr.length; i < n; i++)
          if (i in arr && arr[i] === find)
            return i;
        return -1;
      },

      prependMethod: function (obj, method, func) {
        var original = obj[method];
        obj[method] = function () {
          var args = Array.prototype.slice.call(arguments);
          func.apply(this, args);
          if (original) {
            return original.apply(this, args);
          } else {
            return;
          }

        };
      },

      deepExtend: function deepExtend(destination, source) {
        //Slightly strange behaviour in edge cases (e.g. passing in non objects)
        //But does the job for current use cases.
        if (angular.isArray(source)) {
          destination = angular.isArray(destination) ? destination : [];
          for (var i = 0; i < source.length; i++) {
            destination[i] = deepExtend(destination[i] || {}, source[i]);
          }
        } else if (angular.isObject(source)) {
          for (var property in source) {
            destination[property] = deepExtend(destination[property] || {}, source[property]);
          }
        } else {
          destination = source;
        }
        return destination;
      }
    };
  }

  function highchart(highchartsNGUtils, $timeout) {

    // acceptable shared state
    var seriesId = 0;
    var ensureIds = function (series) {
      var changed = false;
      angular.forEach(series, function(s) {
        if (!angular.isDefined(s.id)) {
          s.id = 'series-' + seriesId++;
          changed = true;
        }
      });
      return changed;
    };

    // immutable
    var axisNames = [ 'xAxis', 'yAxis' ];
    var chartTypeMap = {
      'stock': 'StockChart',
      'map':   'Map',
      'chart': 'Chart'
    };

    var getMergedOptions = function (scope, element, config) {
      var mergedOptions = {};

      var defaultOptions = {
        chart: {
          events: {}
        },
        title: {},
        subtitle: {},
        series: [],
        credits: {},
        plotOptions: {},
        navigator: {enabled: false}
      };

      if (config.options) {
        mergedOptions = highchartsNGUtils.deepExtend(defaultOptions, config.options);
      } else {
        mergedOptions = defaultOptions;
      }
      mergedOptions.chart.renderTo = element[0];

      angular.forEach(axisNames, function(axisName) {
        if(angular.isDefined(config[axisName])) {
          mergedOptions[axisName] = angular.copy(config[axisName]);

          if(angular.isDefined(config[axisName].currentMin) ||
              angular.isDefined(config[axisName].currentMax)) {

            highchartsNGUtils.prependMethod(mergedOptions.chart.events, 'selection', function(e){
              var thisChart = this;
              if (e[axisName]) {
                scope.$apply(function () {
                  scope.config[axisName].currentMin = e[axisName][0].min;
                  scope.config[axisName].currentMax = e[axisName][0].max;
                });
              } else {
                //handle reset button - zoom out to all
                scope.$apply(function () {
                  scope.config[axisName].currentMin = thisChart[axisName][0].dataMin;
                  scope.config[axisName].currentMax = thisChart[axisName][0].dataMax;
                });
              }
            });

            highchartsNGUtils.prependMethod(mergedOptions.chart.events, 'addSeries', function(e){
              scope.config[axisName].currentMin = this[axisName][0].min || scope.config[axisName].currentMin;
              scope.config[axisName].currentMax = this[axisName][0].max || scope.config[axisName].currentMax;
            });
          }
        }
      });

      if(config.title) {
        mergedOptions.title = config.title;
      }
      if (config.subtitle) {
        mergedOptions.subtitle = config.subtitle;
      }
      if (config.credits) {
        mergedOptions.credits = config.credits;
      }
      if(config.size) {
        if (config.size.width) {
          mergedOptions.chart.width = config.size.width;
        }
        if (config.size.height) {
          mergedOptions.chart.height = config.size.height;
        }
      }
      return mergedOptions;
    };

    var updateZoom = function (axis, modelAxis) {
      var extremes = axis.getExtremes();
      if(modelAxis.currentMin !== extremes.dataMin || modelAxis.currentMax !== extremes.dataMax) {
        axis.setExtremes(modelAxis.currentMin, modelAxis.currentMax, false);
      }
    };

    var processExtremes = function(chart, axis, axisName) {
      if(axis.currentMin || axis.currentMax) {
        chart[axisName][0].setExtremes(axis.currentMin, axis.currentMax, true);
      }
    };

    var chartOptionsWithoutEasyOptions = function (options) {
      return angular.extend({}, options, {data: null, visible: null});
    };

    return {
      restrict: 'EAC',
      replace: true,
      template: '

',
      scope: {
        config: '=',
        disableDataWatch: '='
      },
      link: function (scope, element, attrs) {
        // We keep some chart-specific variables here as a closure
        // instead of storing them on 'scope'.

        // prevSeriesOptions is maintained by processSeries
        var prevSeriesOptions = {};

        var processSeries = function(series) {
          var i;
          var ids = [];

          if(series) {
            var setIds = ensureIds(series);
            if(setIds) {
              //If we have set some ids this will trigger another digest cycle.
              //In this scenario just return early and let the next cycle take care of changes
              return false;
            }

            //Find series to add or update
            angular.forEach(series, function(s) {
              ids.push(s.id);
              var chartSeries = chart.get(s.id);
              if (chartSeries) {
                if (!angular.equals(prevSeriesOptions[s.id], chartOptionsWithoutEasyOptions(s))) {
                  chartSeries.update(angular.copy(s), false);
                } else {
                  if (s.visible !== undefined && chartSeries.visible !== s.visible) {
                    chartSeries.setVisible(s.visible, false);
                  }
                  chartSeries.setData(angular.copy(s.data), false);
                }
              } else {
                chart.addSeries(angular.copy(s), false);
              }
              prevSeriesOptions[s.id] = chartOptionsWithoutEasyOptions(s);
            });

            //  Shows no data text if all series are empty
            if(scope.config.noData) {
              var chartContainsData = false;

              for(i = 0; i < series.length; i++) {
                if (series[i].data && series[i].data.length > 0) {
                  chartContainsData = true;

                  break;
                }
              }

              if (!chartContainsData) {
                chart.showLoading(scope.config.noData);
              } else {
                chart.hideLoading();
              }
            }
          }

          //Now remove any missing series
          for(i = chart.series.length - 1; i >= 0; i--) {
            var s = chart.series[i];
            if (s.options.id !== 'highcharts-navigator-series' && highchartsNGUtils.indexOf(ids, s.options.id) < 0) {
              s.remove(false);
            }
          }

          return true;
        };

        // chart is maintained by initChart
        var chart = false;
        var initChart = function() {
          if (chart) chart.destroy();
          prevSeriesOptions = {};
          var config = scope.config || {};
          var mergedOptions = getMergedOptions(scope, element, config);
          var func = config.func || undefined;
          var chartType = chartTypeMap[('' + config.chartType).toLowerCase()] || 'Chart';

          chart = new Highcharts[chartType](mergedOptions, func);

          for (var i = 0; i < axisNames.length; i++) {
            if (config[axisNames[i]]) {
              processExtremes(chart, config[axisNames[i]], axisNames[i]);
            }
          }
          if(config.loading) {
            chart.showLoading();
          }
          config.getHighcharts = function() {
            return chart;
          };

        };
        initChart();

        if(scope.disableDataWatch){
          scope.$watchCollection('config.series', function (newSeries, oldSeries) {
            processSeries(newSeries);
            chart.redraw();
          });
        } else {
          scope.$watch('config.series', function (newSeries, oldSeries) {
            var needsRedraw = processSeries(newSeries);
            if(needsRedraw) {
              chart.redraw();
            }
          }, true);
        }

        scope.$watch('config.title', function (newTitle) {
          chart.setTitle(newTitle, true);
        }, true);

        scope.$watch('config.subtitle', function (newSubtitle) {
          chart.setTitle(true, newSubtitle);
        }, true);

        scope.$watch('config.loading', function (loading) {
          if(loading) {
            chart.showLoading(loading === true ? null : loading);
          } else {
            chart.hideLoading();
          }
        });

        scope.$watch('config.credits.enabled', function (enabled) {
          if (enabled) {
            chart.credits.show();
          } else if (chart.credits) {
            chart.credits.hide();
          }
        });

        scope.$watch('config.chartType', function (chartType, oldChartType) {
          if (chartType === oldChartType) return;
          initChart();
        });

        angular.forEach(axisNames, function(axisName) {
          scope.$watch('config.' + axisName, function (newAxes, oldAxes) {
            if (newAxes === oldAxes) return;
            if(newAxes) {
              chart[axisName][0].update(newAxes, false);
              updateZoom(chart[axisName][0], angular.copy(newAxes));
              chart.redraw();
            }
          }, true);
        });
        scope.$watch('config.options', function (newOptions, oldOptions, scope) {
          //do nothing when called on registration
          if (newOptions === oldOptions) return;
          initChart();
          processSeries(scope.config.series);
          chart.redraw();
        }, true);

        scope.$watch('config.size', function (newSize, oldSize) {
          if(newSize === oldSize) return;
          if(newSize) {
            chart.setSize(newSize.width || undefined, newSize.height || undefined);
          }
        }, true);

        scope.$on('highchartsng.reflow', function () {
          chart.reflow();
        });

        scope.$on('$destroy', function() {
          if (chart) {
            chart.destroy();
            $timeout(function(){
              element.remove();
            }, 0);
          }
        });

      }
    };
  }
}());
<commit_msg>fix: Support for useHighStocks property<commit_after>if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.exports === exports){
  module.exports = 'highcharts-ng';
}
(function () {
  'use strict';
  /*global angular: false, Highcharts: false */

  angular.module('highcharts-ng', [])
    .factory('highchartsNGUtils', highchartsNGUtils)
    .directive('highchart', ['highchartsNGUtils', '$timeout', highchart]);

  function highchartsNGUtils() {

    return {

      //IE8 support
      indexOf: function (arr, find, i /*opt*/) {
        if (i === undefined) i = 0;
        if (i < 0) i += arr.length;
        if (i < 0) i = 0;
        for (var n = arr.length; i < n; i++)
          if (i in arr && arr[i] === find)
            return i;
        return -1;
      },

      prependMethod: function (obj, method, func) {
        var original = obj[method];
        obj[method] = function () {
          var args = Array.prototype.slice.call(arguments);
          func.apply(this, args);
          if (original) {
            return original.apply(this, args);
          } else {
            return;
          }

        };
      },

      deepExtend: function deepExtend(destination, source) {
        //Slightly strange behaviour in edge cases (e.g. passing in non objects)
        //But does the job for current use cases.
        if (angular.isArray(source)) {
          destination = angular.isArray(destination) ? destination : [];
          for (var i = 0; i < source.length; i++) {
            destination[i] = deepExtend(destination[i] || {}, source[i]);
          }
        } else if (angular.isObject(source)) {
          for (var property in source) {
            destination[property] = deepExtend(destination[property] || {}, source[property]);
          }
        } else {
          destination = source;
        }
        return destination;
      }
    };
  }

  function highchart(highchartsNGUtils, $timeout) {

    // acceptable shared state
    var seriesId = 0;
    var ensureIds = function (series) {
      var changed = false;
      angular.forEach(series, function(s) {
        if (!angular.isDefined(s.id)) {
          s.id = 'series-' + seriesId++;
          changed = true;
        }
      });
      return changed;
    };

    // immutable
    var axisNames = [ 'xAxis', 'yAxis' ];
    var chartTypeMap = {
      'stock': 'StockChart',
      'map':   'Map',
      'chart': 'Chart'
    };

    var getMergedOptions = function (scope, element, config) {
      var mergedOptions = {};

      var defaultOptions = {
        chart: {
          events: {}
        },
        title: {},
        subtitle: {},
        series: [],
        credits: {},
        plotOptions: {},
        navigator: {enabled: false}
      };

      if (config.options) {
        mergedOptions = highchartsNGUtils.deepExtend(defaultOptions, config.options);
      } else {
        mergedOptions = defaultOptions;
      }
      mergedOptions.chart.renderTo = element[0];

      angular.forEach(axisNames, function(axisName) {
        if(angular.isDefined(config[axisName])) {
          mergedOptions[axisName] = angular.copy(config[axisName]);

          if(angular.isDefined(config[axisName].currentMin) ||
              angular.isDefined(config[axisName].currentMax)) {

            highchartsNGUtils.prependMethod(mergedOptions.chart.events, 'selection', function(e){
              var thisChart = this;
              if (e[axisName]) {
                scope.$apply(function () {
                  scope.config[axisName].currentMin = e[axisName][0].min;
                  scope.config[axisName].currentMax = e[axisName][0].max;
                });
              } else {
                //handle reset button - zoom out to all
                scope.$apply(function () {
                  scope.config[axisName].currentMin = thisChart[axisName][0].dataMin;
                  scope.config[axisName].currentMax = thisChart[axisName][0].dataMax;
                });
              }
            });

            highchartsNGUtils.prependMethod(mergedOptions.chart.events, 'addSeries', function(e){
              scope.config[axisName].currentMin = this[axisName][0].min || scope.config[axisName].currentMin;
              scope.config[axisName].currentMax = this[axisName][0].max || scope.config[axisName].currentMax;
            });
          }
        }
      });

      if(config.title) {
        mergedOptions.title = config.title;
      }
      if (config.subtitle) {
        mergedOptions.subtitle = config.subtitle;
      }
      if (config.credits) {
        mergedOptions.credits = config.credits;
      }
      if(config.size) {
        if (config.size.width) {
          mergedOptions.chart.width = config.size.width;
        }
        if (config.size.height) {
          mergedOptions.chart.height = config.size.height;
        }
      }
      return mergedOptions;
    };

    var updateZoom = function (axis, modelAxis) {
      var extremes = axis.getExtremes();
      if(modelAxis.currentMin !== extremes.dataMin || modelAxis.currentMax !== extremes.dataMax) {
        axis.setExtremes(modelAxis.currentMin, modelAxis.currentMax, false);
      }
    };

    var processExtremes = function(chart, axis, axisName) {
      if(axis.currentMin || axis.currentMax) {
        chart[axisName][0].setExtremes(axis.currentMin, axis.currentMax, true);
      }
    };

    var chartOptionsWithoutEasyOptions = function (options) {
      return angular.extend({}, options, {data: null, visible: null});
    };

    var getChartType = function(scope) {
      return chartTypeMap[('' + scope.config.chartType).toLowerCase()] ||
             scope.config.useHighStocks ? 'StockChart' : 'Chart';
    };

    return {
      restrict: 'EAC',
      replace: true,
      template: '

',
      scope: {
        config: '=',
        disableDataWatch: '='
      },
      link: function (scope, element, attrs) {
        // We keep some chart-specific variables here as a closure
        // instead of storing them on 'scope'.

        // prevSeriesOptions is maintained by processSeries
        var prevSeriesOptions = {};

        var processSeries = function(series) {
          var i;
          var ids = [];

          if(series) {
            var setIds = ensureIds(series);
            if(setIds) {
              //If we have set some ids this will trigger another digest cycle.
              //In this scenario just return early and let the next cycle take care of changes
              return false;
            }

            //Find series to add or update
            angular.forEach(series, function(s) {
              ids.push(s.id);
              var chartSeries = chart.get(s.id);
              if (chartSeries) {
                if (!angular.equals(prevSeriesOptions[s.id], chartOptionsWithoutEasyOptions(s))) {
                  chartSeries.update(angular.copy(s), false);
                } else {
                  if (s.visible !== undefined && chartSeries.visible !== s.visible) {
                    chartSeries.setVisible(s.visible, false);
                  }
                  chartSeries.setData(angular.copy(s.data), false);
                }
              } else {
                chart.addSeries(angular.copy(s), false);
              }
              prevSeriesOptions[s.id] = chartOptionsWithoutEasyOptions(s);
            });

            //  Shows no data text if all series are empty
            if(scope.config.noData) {
              var chartContainsData = false;

              for(i = 0; i < series.length; i++) {
                if (series[i].data && series[i].data.length > 0) {
                  chartContainsData = true;

                  break;
                }
              }

              if (!chartContainsData) {
                chart.showLoading(scope.config.noData);
              } else {
                chart.hideLoading();
              }
            }
          }

          //Now remove any missing series
          for(i = chart.series.length - 1; i >= 0; i--) {
            var s = chart.series[i];
            if (s.options.id !== 'highcharts-navigator-series' && highchartsNGUtils.indexOf(ids, s.options.id) < 0) {
              s.remove(false);
            }
          }

          return true;
        };

        // chart is maintained by initChart
        var chart = false;
        var initChart = function() {
          if (chart) chart.destroy();
          prevSeriesOptions = {};
          var config = scope.config || {};
          var mergedOptions = getMergedOptions(scope, element, config);
          var func = config.func || undefined;
          var chartType = getChartType(scope);

          chart = new Highcharts[chartType](mergedOptions, func);

          for (var i = 0; i < axisNames.length; i++) {
            if (config[axisNames[i]]) {
              processExtremes(chart, config[axisNames[i]], axisNames[i]);
            }
          }
          if(config.loading) {
            chart.showLoading();
          }
          config.getHighcharts = function() {
            return chart;
          };

        };
        initChart();

        if(scope.disableDataWatch){
          scope.$watchCollection('config.series', function (newSeries, oldSeries) {
            processSeries(newSeries);
            chart.redraw();
          });
        } else {
          scope.$watch('config.series', function (newSeries, oldSeries) {
            var needsRedraw = processSeries(newSeries);
            if(needsRedraw) {
              chart.redraw();
            }
          }, true);
        }

        scope.$watch('config.title', function (newTitle) {
          chart.setTitle(newTitle, true);
        }, true);

        scope.$watch('config.subtitle', function (newSubtitle) {
          chart.setTitle(true, newSubtitle);
        }, true);

        scope.$watch('config.loading', function (loading) {
          if(loading) {
            chart.showLoading(loading === true ? null : loading);
          } else {
            chart.hideLoading();
          }
        });

        scope.$watch('config.credits.enabled', function (enabled) {
          if (enabled) {
            chart.credits.show();
          } else if (chart.credits) {
            chart.credits.hide();
          }
        });

        scope.$watch(getChartType, function (chartType, oldChartType) {
          if (chartType === oldChartType) return;
          initChart();
        });

        angular.forEach(axisNames, function(axisName) {
          scope.$watch('config.' + axisName, function (newAxes, oldAxes) {
            if (newAxes === oldAxes) return;
            if(newAxes) {
              chart[axisName][0].update(newAxes, false);
              updateZoom(chart[axisName][0], angular.copy(newAxes));
              chart.redraw();
            }
          }, true);
        });
        scope.$watch('config.options', function (newOptions, oldOptions, scope) {
          //do nothing when called on registration
          if (newOptions === oldOptions) return;
          initChart();
          processSeries(scope.config.series);
          chart.redraw();
        }, true);

        scope.$watch('config.size', function (newSize, oldSize) {
          if(newSize === oldSize) return;
          if(newSize) {
            chart.setSize(newSize.width || undefined, newSize.height || undefined);
          }
        }, true);

        scope.$on('highchartsng.reflow', function () {
          chart.reflow();
        });

        scope.$on('$destroy', function() {
          if (chart) {
            chart.destroy();
            $timeout(function(){
              element.remove();
            }, 0);
          }
        });

      }
    };
  }
}());
<|endoftext|>


<commit_before>var _ = require( 'lodash' );
var when = require( 'when' );
var passport = require( 'passport' );
var log = require( '../log' )( 'autohost.passport' );
var metronic = require( '../metrics' );
var noOp = function() {
	return when( true );
};
var userCountCheck = noOp;
var passportInitialize;
var passportSession;
var authProvider;
var anonPaths;
var metrics;

reset();

function authConditionally( req, res, next ) {
	// if previous middleware has said to skip auth OR
	// a user was attached from a session, skip authenticating
	if ( req.skipAuth || req.user ) {
		metrics.authenticationSkips.record();
		next();
	} else {
		metrics.authenticationAttempts.record();
		var timer = metrics.authenticationTimer();
		authProvider.authenticate( req, res, next );
		timer.record();
	}
}

function getAuthMiddleware( uri ) {
	var list = [
		{ path: uri, fn: passportInitialize },
		{ path: uri, fn: passportSession }
	]
		.concat( _.map( anonPaths, function( pattern ) {
			return { path: pattern, fn: skipAuthentication };
		} ) )
		.concat( [ { path: uri, fn: whenNoUsers },
			{ path: uri, fn: authConditionally },
		{ path: uri, fn: getRoles } ] );
	return list;
}

function getRoles( req, res, next ) {
	var userName = _.isObject( req.user.name ) ? req.user.name.name : req.user.name;
	req.authenticatedUser = userName || req.user.id || 'anonymous';
	if ( userName === 'anonymous' ) {
		req.user.roles = [ 'anonymous' ];
		next();
	} else {
		var timer = metrics.authorizationTimer();
		authProvider.getUserRoles( req.user, req.context )
			.then( null, function( err ) {
				metrics.authorizationErrors.record();
				timer.record();
				log.debug( 'Failed to get roles for %s with %s', getUserString( req.user ), err.stack );
				// during a socket connection, express is not fully initialized and this call fails ... hard
				try {
					res.status( 500 ).send( 'Could not determine user permissions' );
				} catch ( err ) {
					return [];
				}
			} )
			.then( function( roles ) {
				log.debug( 'Got roles [ %s ] for %s', roles, req.user );
				req.user.roles = roles;
				timer.record();
				next();
			} );
	}
}

function getSocketRoles( user ) {
	if ( user.name === 'anonymous' ) {
		return when( [ 'anonymous' ] );
	} else {
		var timer = metrics.authorizationTimer();
		return authProvider.getUserRoles( user, {} )
			.then( null, function( err ) {
				metrics.authorizationErrors.record();
				timer.record();
				log.debug( 'Failed to get roles for %s with %s', getUserString( user ), err.stack );
				return [];
			} )
			.then( function( roles ) {
				log.debug( 'Got roles [ %s ] for %s', roles, getUserString( user ) );
				timer.record();
				return roles;
			} );
	}
}

function getUserString( user ) {
	return user.name ? user.name : JSON.stringify( user );
}

function reset() {
	passportInitialize = passport.initialize();
	passportSession = passport.session();
	authProvider = undefined;
	anonPaths = undefined;
}

function resetUserCount() {
	userCountCheck = authProvider.hasUsers;
}

function skipAuthentication( req, res, next ) {
	req.skipAuth = true;
	if ( !req.user ) {
		log.debug( 'Skipping authentication and assigning user anonymous to request %s %s', req.method, req.url );
		req.user = {
			id: 'anonymous',
			name: 'anonymous',
			roles: []
		};
	}
	next();
}

function whenNoUsers( req, res, next ) {
	userCountCheck()
		.then( function( hasUsers ) {
			if ( hasUsers ) {
				userCountCheck = noOp;
				next();
			} else {
				skipAuthentication( req, res, next );
			}
		} );
}

function withAuthLib( authProvider ) {
	userCountCheck = authProvider.hasUsers || userCountCheck;
	_.each( authProvider.strategies, function( strategy ) {
		passport.use( strategy );
	} );
}

module.exports = function( config, authPlugin, resetState ) {
	if ( resetState ) {
		reset();
	}
	metrics = metronic();
	authProvider = authPlugin;
	authProvider.initPassport( passport );
	passport.serializeUser( authProvider.serializeUser );
	passport.deserializeUser( authProvider.deserializeUser );
	if ( config.anonymous ) {
		anonPaths = _.isArray( config.anonymous ) ? config.anonymous : [ config.anonymous ];
	} else {
		anonPaths = [];
	}
	withAuthLib( authProvider );
	return {
		getMiddleware: getAuthMiddleware,
		getSocketRoles: getSocketRoles,
		hasUsers: userCountCheck,
		resetUserCheck: resetUserCount
	};
};
<commit_msg>Clean up use of then chains in passport.<commit_after>var _ = require( 'lodash' );
var when = require( 'when' );
var passport = require( 'passport' );
var log = require( '../log' )( 'autohost.passport' );
var metronic = require( '../metrics' );
var noOp = function() {
	return when( true );
};
var userCountCheck = noOp;
var passportInitialize;
var passportSession;
var authProvider;
var anonPaths;
var metrics;

reset();

function authConditionally( req, res, next ) {
	// if previous middleware has said to skip auth OR
	// a user was attached from a session, skip authenticating
	if ( req.skipAuth || req.user ) {
		metrics.authenticationSkips.record();
		next();
	} else {
		metrics.authenticationAttempts.record();
		var timer = metrics.authenticationTimer();
		authProvider.authenticate( req, res, next );
		timer.record();
	}
}

function getAuthMiddleware( uri ) {
	var list = [
		{ path: uri, fn: passportInitialize },
		{ path: uri, fn: passportSession }
	]
		.concat( _.map( anonPaths, function( pattern ) {
			return { path: pattern, fn: skipAuthentication };
		} ) )
		.concat( [ { path: uri, fn: whenNoUsers },
			{ path: uri, fn: authConditionally },
		{ path: uri, fn: getRoles } ] );
	return list;
}

function getRoles( req, res, next ) {
	var userName = _.isObject( req.user.name ) ? req.user.name.name : req.user.name;
	req.authenticatedUser = userName || req.user.id || 'anonymous';

	function onError( err ) {
		metrics.authorizationErrors.record();
		req.user.roles = [];
		timer.record();
		log.debug( 'Failed to get roles for %s with %s', getUserString( req.user ), err.stack );
		// during a socket connection, express is not fully initialized and this call fails ... hard
		try {
			res.status( 500 ).send( 'Could not determine user permissions' );
		} catch ( err ) {
			log.warn( 'Could not reply with user permission error to request before express is fully initialized.' );
		}
		next();
	}

	function onRoles( roles ) {
		log.debug( 'Got roles [ %s ] for %s', roles, req.user );
		req.user.roles = roles;
		timer.record();
		next();
	}

	if ( userName === 'anonymous' ) {
		req.user.roles = [ 'anonymous' ];
		next();
	} else {
		var timer = metrics.authorizationTimer();
		authProvider.getUserRoles( req.user, req.context )
			.then( onRoles, onError );
	}
}

function getSocketRoles( user ) {
	function onError( err ) {
		metrics.authorizationErrors.record();
		timer.record();
		log.debug( 'Failed to get roles for %s with %s', getUserString( user ), err.stack );
		return [];
	}

	function onRoles( roles ) {
		log.debug( 'Got roles [ %s ] for %s', roles, getUserString( user ) );
		timer.record();
		return roles;
	}

	if ( user.name === 'anonymous' ) {
		return when( [ 'anonymous' ] );
	} else {
		var timer = metrics.authorizationTimer();
		return authProvider.getUserRoles( user, {} )
			.then( onRoles, onError );
	}
}

function getUserString( user ) {
	return user.name ? user.name : JSON.stringify( user );
}

function reset() {
	passportInitialize = passport.initialize();
	passportSession = passport.session();
	authProvider = undefined;
	anonPaths = undefined;
}

function resetUserCount() {
	userCountCheck = authProvider.hasUsers;
}

function skipAuthentication( req, res, next ) {
	req.skipAuth = true;
	if ( !req.user ) {
		log.debug( 'Skipping authentication and assigning user anonymous to request %s %s', req.method, req.url );
		req.user = {
			id: 'anonymous',
			name: 'anonymous',
			roles: []
		};
	}
	next();
}

function whenNoUsers( req, res, next ) {
	userCountCheck()
		.then( function( hasUsers ) {
			if ( hasUsers ) {
				userCountCheck = noOp;
				next();
			} else {
				skipAuthentication( req, res, next );
			}
		} );
}

function withAuthLib( authProvider ) {
	userCountCheck = authProvider.hasUsers || userCountCheck;
	_.each( authProvider.strategies, function( strategy ) {
		passport.use( strategy );
	} );
}

module.exports = function( config, authPlugin, resetState ) {
	if ( resetState ) {
		reset();
	}
	metrics = metronic();
	authProvider = authPlugin;
	authProvider.initPassport( passport );
	passport.serializeUser( authProvider.serializeUser );
	passport.deserializeUser( authProvider.deserializeUser );
	if ( config.anonymous ) {
		anonPaths = _.isArray( config.anonymous ) ? config.anonymous : [ config.anonymous ];
	} else {
		anonPaths = [];
	}
	withAuthLib( authProvider );
	return {
		getMiddleware: getAuthMiddleware,
		getSocketRoles: getSocketRoles,
		hasUsers: userCountCheck,
		resetUserCheck: resetUserCount
	};
};
<|endoftext|>


<commit_before>import path from 'path';
import * as FirebaseAdmin from 'firebase-admin';
import algoliasearch from 'algoliasearch';

import Debug from './debug';

const info = Debug('figolia:info:init');

export default function initServices() {

    global.CONFIG = {
        // Firebase credentials
        firebase: {
            instance: process.env.FIREBASE_INSTANCE || '',
            serviceAccountFile: process.env.FIREBASE_ACCOUNT || '',
            // Where to store server metadata
            path: process.env.FIREBASE_PATH || 'algolia',
            // Firebase token will be generated with this uid (to write above path)
            uid: process.env.FIREBASE_UID || 'algolia'
        },
        // Algolia credentials
        algolia: {
            applicationId: process.env.ALGOLIA_APP_ID || '',
            // *Admin* API Key
            apiKey: process.env.ALGOLIA_API_KEY || ''
        },
        ...global.CONFIG
    };

    // Connect to algolia
    const { applicationId, apiKey } = global.CONFIG.algolia;
    if (!applicationId || !apiKey) {
        info('ERROR: Will not connect to algolia (missing app ID or key)');
        return { fb: null, algolia: null };
    }
    const algolia = algoliasearch(applicationId, apiKey);

    info(`Connected to Algolia appId ${applicationId}`);

    // Only initialize Firebase if it wasn't done before
    if (!FirebaseAdmin.apps.length) {
        FirebaseAdmin.database.enableLogging(Debug.enabled('firebase'), Debug('firebase'));
        // Service account is provided as a file, but for testing purposes on external services
        // (like travis) indivdual fields are provided in the environment. Private key can be found
        // in the service account file and provided as an environment variable, only new lines (\n)
        // must be replaced by %NEWLINE% so the script below can provide the correct key.
        // Also, firebaseProjectId is the same as the instance, except it does not accept leading numbers
        const firebaseProjectId = (process.env.FIREBASE_INSTANCE || '').replace(/^[0-9]+/, '');
        if (!global.CONFIG.firebase.serviceAccountFile &&
            (!process.env.FIREBASE_INSTANCE || !process.env.FIREBASE_PRIVATE_KEY)) {
            info('ERROR: Will not connect to algolia (missing serviceAccount file)');
            return { fb: null, algolia: null };
        }
        const serviceAccount = global.CONFIG.firebase.serviceAccountFile !== null ?
            require(global.CONFIG.firebase.serviceAccountFile) : {
                projectId: firebaseProjectId,
                clientEmail: `server@${firebaseProjectId}.iam.gserviceaccount.com`,
                privateKey: (process.env.FIREBASE_PRIVATE_KEY || '').replace(/%NEWLINE%/g, '\n')
            };
        FirebaseAdmin.initializeApp({
            credential: FirebaseAdmin.credential.cert(serviceAccount),
            databaseURL: `https://${global.CONFIG.firebase.instance}.firebaseio.com`,
            databaseAuthVariableOverride: {
                uid: global.CONFIG.firebase.uid
            }
        });

        info(
            `Connected to Firebase instance ${global.CONFIG.firebase.instance} ` +
            `(authenticated as ${global.CONFIG.firebase.uid})`
        );
    }

    return { fb: FirebaseAdmin.database().ref(), algolia };
}
<commit_msg>Fix init services for third party services<commit_after>import path from 'path';
import * as FirebaseAdmin from 'firebase-admin';
import algoliasearch from 'algoliasearch';

import Debug from './debug';

const info = Debug('figolia:info:init');

export default function initServices() {

    global.CONFIG = {
        // Firebase credentials
        firebase: {
            instance: process.env.FIREBASE_INSTANCE || '',
            serviceAccountFile: process.env.FIREBASE_ACCOUNT || '',
            // Where to store server metadata
            path: process.env.FIREBASE_PATH || 'algolia',
            // Firebase token will be generated with this uid (to write above path)
            uid: process.env.FIREBASE_UID || 'algolia'
        },
        // Algolia credentials
        algolia: {
            applicationId: process.env.ALGOLIA_APP_ID || '',
            // *Admin* API Key
            apiKey: process.env.ALGOLIA_API_KEY || ''
        },
        ...global.CONFIG
    };

    // Connect to algolia
    const { applicationId, apiKey } = global.CONFIG.algolia;
    if (!applicationId || !apiKey) {
        info('ERROR: Will not connect to algolia (missing app ID or key)');
        return { fb: null, algolia: null };
    }
    const algolia = algoliasearch(applicationId, apiKey);

    info(`Connected to Algolia appId ${applicationId}`);

    // Only initialize Firebase if it wasn't done before
    if (!FirebaseAdmin.apps.length) {
        FirebaseAdmin.database.enableLogging(Debug.enabled('firebase'), Debug('firebase'));
        // Service account is provided as a file, but for testing purposes on external services
        // (like travis) indivdual fields are provided in the environment. Private key can be found
        // in the service account file and provided as an environment variable, only new lines (\n)
        // must be replaced by %NEWLINE% so the script below can provide the correct key.
        // Also, firebaseProjectId is the same as the instance, except it does not accept leading numbers
        const firebaseProjectId = (process.env.FIREBASE_INSTANCE || '').replace(/^[0-9]+/, '');
        if (!global.CONFIG.firebase.serviceAccountFile &&
            (!process.env.FIREBASE_INSTANCE || !process.env.FIREBASE_PRIVATE_KEY)) {
            info('ERROR: Will not connect to algolia (missing serviceAccount file)');
            return { fb: null, algolia: null };
        }
        const serviceAccount = global.CONFIG.firebase.serviceAccountFile ?
            require(global.CONFIG.firebase.serviceAccountFile) : {
                projectId: firebaseProjectId,
                clientEmail: `server@${firebaseProjectId}.iam.gserviceaccount.com`,
                privateKey: (process.env.FIREBASE_PRIVATE_KEY || '').replace(/%NEWLINE%/g, '\n')
            };
        FirebaseAdmin.initializeApp({
            credential: FirebaseAdmin.credential.cert(serviceAccount),
            databaseURL: `https://${global.CONFIG.firebase.instance}.firebaseio.com`,
            databaseAuthVariableOverride: {
                uid: global.CONFIG.firebase.uid
            }
        });

        info(
            `Connected to Firebase instance ${global.CONFIG.firebase.instance} ` +
            `(authenticated as ${global.CONFIG.firebase.uid})`
        );
    }

    return { fb: FirebaseAdmin.database().ref(), algolia };
}
<|endoftext|>


<commit_before>/*************************************************
 *  JavaScript that gets injected
 *************************************************/

/*************************************************
 *  Autohide Stuff
 *************************************************/
// Autohide items when a card is refreshed
$('.list-card-details').click( function() {
    setTimeout(function() {
        hideCheckedItems();
    }, 1000);
});

// Autohide items when a card is clicked
$(document).ready(function() {
    if( $('.js-checklist-list').length ) {
        setTimeout(function() {
            hideCheckedItems();
        }, 1000);
    }
});

/*************************************************
 *  Helper Functions
 *************************************************/
// Hide checked items
function hideCheckedItems() {
    $('.js-hide-checked-items').each( function() {
        this.click();
    });
};
<commit_msg>Restructure inject.js and add checked toggle button<commit_after>/*************************************************
 *  JavaScript that gets injected
 *************************************************/

/*************************************************
 *  Event: Card is clicked
 *************************************************/
$('.list-card-details').click( function() {
    setTimeout(function() {
        // Hide items
        hideCheckedItems();

        // Add toggle button
        addCheckedToggle();
    }, 1000);
});

/*************************************************
 *  Event: Card is refreshed
 *************************************************/
$(document).ready(function() {
    if( $('.js-checklist-list').length ) {
        setTimeout(function() {
            // Hide items
            hideCheckedItems();

            // Add toggle button
            addCheckedToggle();
        }, 1000);
    }
});

/*************************************************
 *  Event: Button is clicked
 *************************************************/
// $(document).ready(function() {
    $(document).on('click', '.js-tt-toggle-checked', function() {
        console.log('toggle checked items');
    });
// });

/*************************************************
 *  Helper Functions
 *************************************************/
// Hide checked items
function hideCheckedItems() {
    $('.js-hide-checked-items').each( function() {
        this.click();
    });
};

// Add a button for toggling checked items
function addCheckedToggle() {
    $('.window-module.other-actions .u-clearfix').append(' Hide Checked');
}
<|endoftext|>


<commit_before>'use strict';

chrome.storage.sync.get({sitesEnabled:[]}, function(items) {
  var url = window.location.href;
  var sites = items.sitesEnabled;

  for (var i = 0; i < sites.length; i++) {
    if ( url.match(new RegExp(sites[i])) ) {
      shouldNotCopy();
      break;
    }
  }
});

function shouldNotCopy() {
  var div = document.createElement('div');
    div.classList.add('_tio-message');
    div.innerHTML = '
Type it out
';

  document.body.appendChild(div);

  document.oncopy = function(e) {
    window.getSelection().empty();
    div.classList.add('_tio-animate');

    setTimeout(function() {
      div.classList.remove('_tio-animate');
    }, 1000);
  }
}
<commit_msg>add defaults to laod<commit_after>'use strict';
console.log('werking')
chrome.storage.sync.get({sitesEnabled:['developer.mozilla.org', 'stackoverflow.com\/questions\/*']}, function(items) {
  var url = window.location.href;
  var sites = items.sitesEnabled;

  for (var i = 0; i < sites.length; i++) {
    if ( url.match(new RegExp(sites[i])) ) {
      shouldNotCopy();
      break;
    }
  }
});

function shouldNotCopy() {
  var div = document.createElement('div');
    div.classList.add('_tio-message');
    div.innerHTML = '
Type it out
';

  document.body.appendChild(div);

  document.oncopy = function(e) {
    window.getSelection().empty();
    div.classList.add('_tio-animate');

    setTimeout(function() {
      div.classList.remove('_tio-animate');
    }, 1000);
  }
}
<|endoftext|>


<commit_before>chrome.extension.sendMessage({}, function(response) {
	var readyStateCheckInterval = setInterval(function() {
	if (document.readyState === "complete") {
		clearInterval(readyStateCheckInterval);

		// ----------------------------------------------------------
		// This part of the script triggers when page is done loading
		//console.log("Hello. This message was sent from scripts/inject.js");
		// ----------------------------------------------------------
	}}, 10);
});

////////////// TODO : TOOLS CLASS ////////////
function GetQueryStringInUrl(name) {
    var url = window.location.href;
    name = name.replace(/[\[\]]/g, "\\$&");
    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, " "));
}
//////////////////////////////////////////////

var co2Count = 0;

function AddCo2(co2ToAdd)
{
	var key = "co2Count";
	chrome.storage.local.get(key, function (obj) {
		if(!isNaN(obj.co2Count)){
			co2Count = parseFloat(obj.co2Count);
			co2Count += parseFloat(co2ToAdd);
			SaveToLocalStorage(key, co2Count);
		}
	});

}

function SaveToLocalStorage(key, value)
{
	var obj = {};
	obj[key] = value;
	chrome.storage.local.set(obj, function() {
		console.log('local storage \"' + key + '\" saved with value :');
    console.log(value);
	});
}

var _streamingTimer;
var _streaming = false;
var _nbSecondsStreamingInterval = 5;
var _isHtml5Video = false;

function VideoStarted()
{
	_streaming = true;
	_streamingTimer = window.setInterval("VideoPlaying()", 1000 * _nbSecondsStreamingInterval);
}

function VideoPlaying()
{
	var co2 = 0.02 * _nbSecondsStreamingInterval;
	AddCo2(co2);
	console.log("CO2 : +" + co2 + " = " + co2Count);
}

function VideoStopped()
{
	_streaming = false;
	console.log("CO2 : STOPPED VIDEO DETECTED");
	window.clearInterval(_streamingTimer);
}

function AudioStarted()
{
	_streaming = true;
	_streamingTimer = window.setInterval("AudioPlaying()", 1000 * _nbSecondsStreamingInterval);
}

function AudioPlaying()
{
	var co2 = 0.01 * _nbSecondsStreamingInterval;
	AddCo2(co2);
	console.log("CO2 : +" + co2 + " = " + co2Count);
}

function GoogleSearch()
{
	var co2 = 6.5;
	AddCo2(co2);
	console.log("CO2 : GOOGLE SEARCH : " + window.location.host);
	console.log("CO2 : +" + co2 + " = " + co2Count);
}

function RegularPageLoaded()
{
	var co2 = 1.1;
	AddCo2(co2);
	console.log("CO2 : REGULAR PAGE LOAD DETECTED : " + window.location.host);
	console.log("CO2 : +" + co2 + " = " + co2Count);
}

function PageLoaded()
{
	var host = window.location.host.toLowerCase();
	if(host.indexOf(".google.") > -1 && GetQueryStringInUrl("q")){
		GoogleSearch();
	}
	else{
		RegularPageLoaded();
	}

	if (!_isHtml5Video){
		if(	host.indexOf("stream") > -1 ||
			host.indexOf("netflix.") > -1 ||
			host.indexOf("hulu.") > -1){
			VideoStarted();
		}
		else if (	host.indexOf("deezer.") > -1 ||
					host.indexOf("soundcloud.") > -1){
			AudioStarted();
		}
	}
}

function InitCo2Detections()
{
	//html5 video
    var video = $('video');
	if(video.length > 0){
		_isHtml5Video = true;
		if(!video.paused && !_streaming){ //since the co2Count take some times to come from the storage, the video might be playing already
			VideoStarted()
		}
		video.on('playing', function(){
			if(!video.paused && !_streaming){
				VideoStarted()
			}
		});
		video.on('pause', function(){
			VideoStopped();
		});
	}

	//page loaded
	PageLoaded();
}

//init
$(function(){
	chrome.storage.local.get("co2Count", function (obj) {
		if(isNaN(obj.co2Count)){ obj.co2Count = 0.0; SaveCo2Count(obj.co2Count); }
		co2Count = obj.co2Count;
		InitCo2Detections();
	});
})

/*

requête de navigateur web c'est quand tu mets directement l'adresse du site web
1.01

requête internet c'est une recherche.
6.5

Pour 1 sec de video - source googlegreen
0,02

1 km en voiture = 250 gCO2
1 km en avion par personne = 85 gCO2 (attention à celui la, possible qu'il envoit un mauvais signal, les gens peuvent se dire que ca n'émet pas bcp en fait l'avion...)
frigo allumé pendant 1 heure en France = 2,6 gCO2
incinération d'1 kg de papier en France = 46,6 gCO2

ampoule fr 8 gCO2/heure
Si on fait une moyenne Europe, ca serait plutôt 29 gCO2/heure.

mail	0.004	4.00
mail avec PJ (1Mo)	0.035	35.00
tweet	0.00002	0.02
achat sur le web	0.00755	7.55
requête de navigation web	0.00101	1.01
requête internet	0.0065	6.50
spam	0.00005	0.05

*/<commit_msg>cleanup<commit_after>chrome.extension.sendMessage({}, function(response) {
	var readyStateCheckInterval = setInterval(function() {
	if (document.readyState === "complete") {
		clearInterval(readyStateCheckInterval);

		// ----------------------------------------------------------
		// This part of the script triggers when page is done loading
		//console.log("Hello. This message was sent from scripts/inject.js");
		// ----------------------------------------------------------
	}}, 10);
});

////////////// TODO : TOOLS CLASS ////////////
function GetQueryStringInUrl(name) {
    var url = window.location.href;
    name = name.replace(/[\[\]]/g, "\\$&");
    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, " "));
}
//////////////////////////////////////////////

var _co2Count = 0;
var _streamingTimer;
var _streaming = false;
var _nbSecondsStreamingInterval = 5;
var _isHtml5Video = false;

function AddCo2(co2ToAdd)
{
	var key = "co2Count";
	chrome.storage.local.get(key, function (obj) {
		if(!isNaN(obj.co2Count)){
			_co2Count = parseFloat(obj.co2Count);
			_co2Count += parseFloat(co2ToAdd);
			SaveToLocalStorage(key, _co2Count);
		}
	});

}

function SaveToLocalStorage(key, value)
{
	var obj = {};
	obj[key] = value;
	chrome.storage.local.set(obj, function() {
		console.log('local storage \"' + key + '\" saved with value :');
    console.log(value);
	});
}

function VideoStarted()
{
	_streaming = true;
	_streamingTimer = window.setInterval("VideoPlaying()", 1000 * _nbSecondsStreamingInterval);
}

function VideoPlaying()
{
	var co2 = 0.02 * _nbSecondsStreamingInterval;
	AddCo2(co2);
	console.log("CO2 : +" + co2 + " = " + _co2Count);
}

function VideoStopped()
{
	_streaming = false;
	console.log("CO2 : STOPPED VIDEO DETECTED");
	window.clearInterval(_streamingTimer);
}

function AudioStarted()
{
	_streaming = true;
	_streamingTimer = window.setInterval("AudioPlaying()", 1000 * _nbSecondsStreamingInterval);
}

function AudioPlaying()
{
	var co2 = 0.01 * _nbSecondsStreamingInterval;
	AddCo2(co2);
	console.log("CO2 : +" + co2 + " = " + _co2Count);
}

function GoogleSearch()
{
	var co2 = 6.5;
	AddCo2(co2);
	console.log("CO2 : GOOGLE SEARCH : " + window.location.host);
	console.log("CO2 : +" + co2 + " = " + _co2Count);
}

function RegularPageLoaded()
{
	var co2 = 1.1;
	AddCo2(co2);
	console.log("CO2 : REGULAR PAGE LOAD DETECTED : " + window.location.host);
	console.log("CO2 : +" + co2 + " = " + _co2Count);
}

function PageLoaded()
{
	var host = window.location.host.toLowerCase();
	if(host.indexOf(".google.") > -1 && GetQueryStringInUrl("q")){
		GoogleSearch();
	}
	else{
		RegularPageLoaded();
	}

	if (!_isHtml5Video){
		if(	host.indexOf("stream") > -1 ||
			host.indexOf("netflix.") > -1 ||
			host.indexOf("hulu.") > -1){
			VideoStarted();
		}
		else if (	host.indexOf("deezer.") > -1 ||
					host.indexOf("soundcloud.") > -1){
			AudioStarted();
		}
	}
}

function InitCo2Detections()
{
	//html5 video
    var video = $('video');
	if(video.length > 0){
		_isHtml5Video = true;
		if(!video.paused && !_streaming){ //since the co2Count take some times to come from the storage, the video might be playing already
			VideoStarted()
		}
		video.on('playing', function(){
			if(!video.paused && !_streaming){
				VideoStarted()
			}
		});
		video.on('pause', function(){
			VideoStopped();
		});
	}

	//page loaded
	PageLoaded();
}

//init
$(function(){
	chrome.storage.local.get("co2Count", function (obj) {
		if(isNaN(obj.co2Count)){ obj.co2Count = 0.0; SaveCo2Count(obj.co2Count); }
		_co2Count = obj.co2Count;
		InitCo2Detections();
	});
})

/*

requête de navigateur web c'est quand tu mets directement l'adresse du site web
1.01

requête internet c'est une recherche.
6.5

Pour 1 sec de video - source googlegreen
0,02

1 km en voiture = 250 gCO2
1 km en avion par personne = 85 gCO2 (attention à celui la, possible qu'il envoit un mauvais signal, les gens peuvent se dire que ca n'émet pas bcp en fait l'avion...)
frigo allumé pendant 1 heure en France = 2,6 gCO2
incinération d'1 kg de papier en France = 46,6 gCO2

ampoule fr 8 gCO2/heure
Si on fait une moyenne Europe, ca serait plutôt 29 gCO2/heure.

mail	0.004	4.00
mail avec PJ (1Mo)	0.035	35.00
tweet	0.00002	0.02
achat sur le web	0.00755	7.55
requête de navigation web	0.00101	1.01
requête internet	0.0065	6.50
spam	0.00005	0.05

*/<|endoftext|>


<commit_before>import React, {PropTypes} from 'react'
import FormBuilderPropTypes from '../FormBuilderPropTypes'
import DefaultTextField from 'component:@sanity/components/textfields/default'

export default class Num extends React.Component {
  static displayName = 'Number';

  static propTypes = {
    field: FormBuilderPropTypes.field,
    value: PropTypes.number,
    onChange: PropTypes.func,
    focus: PropTypes.bool
  };

  static defaultProps = {
    onChange() {}
  };

  constructor(props, context) {
    super(props, context)
    this.handleChange = this.handleChange.bind(this)
  }

  handleChange(e) {
    const val = e.target.value.trim()
    this.props.onChange({patch: {$set: val === '' ? undefined : Number(e.target.value)}})
  }

  render() {
    const {value, field, focus} = this.props
    return (
      <DefaultTextField
        label={field.title}
        type="number"
        placeholder={field.placeholder || 'Must be a number. Ex 1234'}
        onChange={this.handleChange}
        onKeyPress={this.handleKeyPress}
        value={value}
        focus={focus}
        ref={this.setInputElement}
      />
    )
  }
}
<commit_msg>Convert number value to string<commit_after>import React, {PropTypes} from 'react'
import FormBuilderPropTypes from '../FormBuilderPropTypes'
import DefaultTextField from 'component:@sanity/components/textfields/default'

export default class Num extends React.Component {
  static displayName = 'Number';

  static propTypes = {
    field: FormBuilderPropTypes.field,
    value: PropTypes.number,
    onChange: PropTypes.func,
    focus: PropTypes.bool
  };

  static defaultProps = {
    onChange() {}
  };

  constructor(props, context) {
    super(props, context)
    this.handleChange = this.handleChange.bind(this)
  }

  handleChange(e) {
    const val = e.target.value.trim()
    this.props.onChange({patch: {$set: val === '' ? undefined : Number(e.target.value)}})
  }

  render() {
    const {value, field, focus} = this.props
    return (
      <DefaultTextField
        label={field.title}
        type="number"
        placeholder={field.placeholder || 'Must be a number. Ex 1234'}
        onChange={this.handleChange}
        onKeyPress={this.handleKeyPress}
        value={String(value)}
        focus={focus}
        ref={this.setInputElement}
      />
    )
  }
}
<|endoftext|>


<commit_before>'use strict';

window.Darwinator.GeneticAlgorithm = window.Darwinator.GeneticAlgorithm || {

  POPULATION_SIZE:          10,
  CROSSOVER_PROBABILITY:    0.8,
  MUTATION_PROBABILITY:     0.025,
  TOURNAMENT_PARAMETER:     0.75,
  NUMBER_OF_GENERATIONS:    100,
  NUMBER_OF_VARIABLES:      3,
  NUMBER_OF_GENES:          3,
  TOURNAMENT_SIZE:          4,
  ELITISM_DEGREE:           2,
  PLAYER_ADVANTAGE:         10, // increase to make enemies weaker

  // depends on player attributes
  VARIABLE_RANGE:           undefined, // max sum of enemy attributes

  // depends on population success
  MUTATION_RATE:            undefined,
  POOR_MAX_FITNESS:         0.1,  // used to set mutation rate

  /**
  * Generates a population of individuals from a given population. The new population is likely to be
  * more adapted to find a solution to the enemyScore() function.
  *
  * @method Darwinator.GeneticAlgorithm#generatePopulation
  * @param {Phaser.Game} [game] - The game that uses the algorithm.
  * @param {Phaser.Sprite} [target] - The sprite to be attacked by the enemies.
  * @param {Phaser.Group} [enemyGroup] - Optional. If not provided, a group with default values will be set.
  * @param {Boolean} [singleGeneration] - If true, only one iteration will be run, else, this.NUMBER_OF_GENERATIONS is used.
  * @param {Array} [spawnPositions] - The positions on which the enemies are allowed to spawn.
  * @return {Array} The last population generated.
  */
  generatePopulation: function(game, target, enemyGroup, singleGeneration, spawnPositions) {
    var attributes = target.attributes;
    this.VARIABLE_RANGE = attributes.strength + attributes.agility + attributes.intellect - this.PLAYER_ADVANTAGE;

    if(!enemyGroup){
      enemyGroup = game.add.group();
      console.log('GA: Enemy group not provided. Initializing with default values.');
      enemyGroup = this.initPopulation(enemyGroup, game, target, spawnPositions);
      return enemyGroup;
    }
    console.log('GA: Starting GA run..');
    var translatedEnemies = this.translateEnemyWave(enemyGroup);
    var population        = translatedEnemies[0];
    var fitnessLevels     = translatedEnemies[1];
    var bestIndex         = translatedEnemies[2];
    var bestIndividual    = population[bestIndex];

    // to eliminate weak populations
    if(fitnessLevels[bestIndex] <= this.POOR_MAX_FITNESS){
      this.MUTATION_RATE = 20;
    }else{
      this.MUTATION_RATE = 1;
    }

    // algorithm main loop
    for (var i = 0; i < (singleGeneration ? 1 : this.NUMBER_OF_GENERATIONS); i++) {

      // clone population
      var tmpPopulation = population.slice(0);

      // selection
      for(var l = 0; l < population.length; l += 2) {
        var ind1 = this.selection(fitnessLevels);
        var ind2 = this.selection(fitnessLevels);
        // crossover
        if (Math.random() < this.CROSSOVER_PROBABILITY) {
          var chromePair        = this.cross(population[ind1], population[ind2]);
          tmpPopulation[l]      = chromePair[0];
          tmpPopulation[l + 1]  = chromePair[1];
        } else {
          tmpPopulation[l]      = population[ind1];
          tmpPopulation[l + 1]  = population[ind2];
        }
        // mutation
        tmpPopulation[l]    = this.mutate(tmpPopulation[l]);
        tmpPopulation[l+1]  = this.mutate(tmpPopulation[l+1]);
      }

      if(fitnessLevels[bestIndex] > this.POOR_MAX_FITNESS){
        // elitism
        for(l = 0; l < this.ELITISM_DEGREE; l++) {
          tmpPopulation[l] = bestIndividual;
        }
      }

      // replace old population
      population = tmpPopulation;
    } //endof algorithm main loop

    var nextGeneration = this.translatePopulation(population, enemyGroup, game, target, spawnPositions);
    console.log('GA: Returning the new generation!');
    return nextGeneration;
  },

  /**
  * Generates a group of enemy sprites with some default values.
  *
  * @method Darwinator.GeneticAlgorithm#initPopulation
  * @param {Phaser.Group} [enemyGroup] - The enemy group to fill with enemies.
  * @param {Phaser.Game} [game] - The game that uses the algorithm.
  * @param {Phaser.Sprite} [target] - The sprite to be attacked by the enemies.
  * @param {Array} [spawnPositions] - The positions on which the enemies are allowed to spawn.
  * @return {Array} An enemy population with default attribute values.
  */
  initPopulation: function(enemyGroup, game, target, spawnPositions) {
    // 4 different enemy initial set of attributes - just an example, not permanent!
    var enemiesPerType  = this.POPULATION_SIZE / 5;
    var pos;
    var strength, agility, intellect;
    spawnPositions = this.shuffle(spawnPositions);
    for(var i = 0; i < this.POPULATION_SIZE; i++){
      pos = spawnPositions[i % spawnPositions.length];
      if(i < enemiesPerType){
        // smart but slow and weak
        strength  = 0;
        agility   = 0;
        intellect = this.VARIABLE_RANGE;
      }else if(i < enemiesPerType*2){
        // strong but slow and stupid
        strength  = this.VARIABLE_RANGE;
        agility   = 0;
        intellect = 0;
      }else if(i < enemiesPerType*3){
        // fast but weak and stupid
        strength  = 0;
        agility   = this.VARIABLE_RANGE;
        intellect = 0;
      }else{
        // hybrid
        strength  = agility = intellect = Math.round(this.VARIABLE_RANGE / 3);
      }
      enemyGroup.add(new Darwinator.Enemy(game, target, pos.x, pos.y, undefined, strength, agility, intellect));
    }
    return enemyGroup;
  },

  // returns a shuffled version of the given array
  shuffle: function(array){
    array = array.slice(0);
    var shuff = [];

    while(array.length > 0)
      shuff = shuff.concat(array.splice(Math.round(Math.random() * (array.length-1)), 1));
    return shuff;
  },

  /**
  * Cross two individuals to create two new ones by performing a tradeoff between
  * two randomly selected genes in each individual.
  *
  * Example: Select index of x and y.
  * First individual: decrease x and increase y
  * Second individual: decrease y and increase x
  *
  * @method Darwinator.GeneticAlgorithm#cross
  * @param {Array} [firstInd] - The first individual to be crossed
  * @param {Array} [secondInd] - The second individual to be crossed
  * @return {Array} - A tuple containing the two new individuals.
  */
  cross: function(firstInd, secondInd) {
    var crossPoint1 = Math.round(Math.random()*(this.NUMBER_OF_GENES - 1));
    var crossPoint2 = Math.round(Math.random()*(this.NUMBER_OF_GENES - 1));

    var tradeOff = Math.random();
    var tradeOffAmount1 = Math.round(tradeOff * firstInd[crossPoint1]);
    var tradeOffAmount2 = Math.round(tradeOff * secondInd[crossPoint2]);

    var newInd1 = firstInd.slice(0);
    var newInd2 = secondInd.slice(0);

    newInd1[crossPoint1] -= tradeOffAmount1;
    newInd1[crossPoint2] += tradeOffAmount1;

    newInd2[crossPoint2] -= tradeOffAmount2;
    newInd2[crossPoint1] += tradeOffAmount2;

    return [newInd1, newInd2];
  },

  /**
  * Select a individual based on the fitness levels of the entire population.
  * this.TOURNAMENT_SIZE many individuals will be selected at random, and one of them will
  * be returned. The tournament works in such a way that a individual with a high fitness level
  * is more likely to be returned from the tournament, but is not more likely to participate.
  *
  * @method Darwinator.GeneticAlgorithm#selection
  * @param {Array} - The fitness levels of the entire population
  * @return {Number} - The index of the selected individual.
  */
  selection: function(fitnessLevels) {
    var tournamentParticipants = new Array(this.TOURNAMENT_SIZE);

    /* Select individuals at random, and represent them as a touple containing their indexes and their
    * fitness levels. */
    for (var i = 0; i < this.TOURNAMENT_SIZE; i++) {
      tournamentParticipants[i]    = new Array(2);
      tournamentParticipants[i][0] = Math.round(Math.random() * (this.POPULATION_SIZE - 1));
      tournamentParticipants[i][1] = fitnessLevels[tournamentParticipants[i][0]];
    }

    /* Sort by fitness levels */
    tournamentParticipants.sort(
      function(a,b) {return b[1]-a[1];}
    );

    for(i = 0; i < this.TOURNAMENT_SIZE; i++) {
      if (Math.random() < this.TOURNAMENT_PARAMETER) {
        return tournamentParticipants[i][0];
      }
    }

    return tournamentParticipants[i - 1][0];
  },

  /**
  * Mutate a given individual by performing a tradeoff between two randomly selected genes.
  *
  * @method Darwinator.GeneticAlgorithm#mutate
  * @param {Array} - The individual to be mutated
  * @return {Array} - The mutated individual.
  */
  mutate: function(individual) {
    if (Math.random() < this.MUTATION_PROBABILITY * this.MUTATION_RATE) {
      var gene1 = Math.round(Math.random()*(this.NUMBER_OF_GENES - 1));
      var gene2 = Math.round(Math.random()*(this.NUMBER_OF_GENES - 1));
      var tradeOffAmount = Math.round(Math.random() * individual[gene1]);
      individual[gene1] -= tradeOffAmount;
      individual[gene2] += tradeOffAmount;
    }
    return individual;
  },

  /**
  * Evaluates an enemy sprite based on its score.
  *
  * @method Darwinator.GeneticAlgorithm#evaluateInd
  * @param {Phaser.Sprite} - The individual to be evaluated
  * @return {Number} - The fitness level of the individual
  */
  evaluateInd: function(enemy) {
    var fitness = 1 - (1 / this.enemyScore(enemy));
    return fitness == -Infinity ? 0 : fitness;// maximize fitness based on enemy score
  },

  /**
  * Calculates the score of an enemy based on statistical attributes.
  *
  * @method Darwinator.GeneticAlgorithm#enemyScore
  * @param {Phaser.Sprite} - An enemy sprite
  * @return {Number} - The score of the enemy for a given game round.
  */
  enemyScore: function(enemy) {
    var score = enemy.alive ? enemy.damageDone*2 : enemy.damageDone;
    return score;
  },

  /**
  *
  * Use the attributes of an enemy sprite as genes in a real-value chromosome.
  *
  * @method Darwinator.GeneticAlgorithm#enemyToChromosome
  * @param {Phaser.Sprite} - An enemy sprite
  * @return {Number} - The enemy represented as a real-value chromosome
  */
  enemyToChromosome: function (enemy){
    return [enemy.attributes.strength, enemy.attributes.agility, enemy.attributes.intellect];
  },

  /**
  * Translates an enemy group of sprites to chromosomes and fitness levels.
  * The index of the most fit individual is also provided.
  *
  * @method Darwinator.GeneticAlgorithm#translateEnemyWave
  * @param {Phaser.Group} - A group of enemy sprites
  * @return {Array} - Chromosomes, fitnessLevels and the index of the fittest individual.
  *                     as [chromosomes, fitnessLevels, fittestIndex]
  */
  translateEnemyWave: function(enemyGroup){
    var currentSize = enemyGroup.length; //could add an extra param for this.
    var population  = new Array(currentSize);
    var fitness     = new Array(currentSize);
    var bestIndex   = 0;
    for(var i = 0; i < currentSize; i++){
      var enemy     = enemyGroup.getAt(i);
      population[i] = this.enemyToChromosome(enemy);
      fitness[i]    = this.evaluateInd(enemy);
      if(fitness[i] > fitness[bestIndex]){
        bestIndex = i;
      }
    }
    return [population, fitness, bestIndex];
  },

  /**
  * Replaces the given group of enemy sprites to the next generation of sprites.
  *
  * @method Darwinator.GeneticAlgorithm#translatePopulation
  * @param {Array} [population] - The chromosomes of the new generation.
  * @param {Phaser.Group} [enemyGroup] - The enemy sprite group to replace.
  * @param {Phaser.Game} [game] - The game that uses the algorithm.
  * @param {Phaser.Sprite} [target] - The sprite to be attacked by the enemies.
  * @param {Array} [spawnPositions] - The positions on which the enemies are allowed to spawn.
  * @return {Phaser.Group} The new group of enemies.
  */
  translatePopulation: function(population, enemyGroup, game, target, spawnPositions){
    // FIXME possible memory leak, should call destroy but it crashes for some reason..
    //game.enemies.destroy(true);
    enemyGroup      = game.add.group();
    spawnPositions  = this.shuffle(spawnPositions);
    for(var i = 0; i < population.length; i++){
      var pos         = spawnPositions[i % spawnPositions.length];
      var strength    = population[i][0];
      var agility     = population[i][1];
      var intellect   = population[i][2];
      var enemy       = new Darwinator.Enemy(game, target, pos.x, pos.y, undefined, strength, agility, intellect);
      enemyGroup.add(enemy);
    }
    return enemyGroup;
  },

};
<commit_msg>move shuffle calls to generatePopulation<commit_after>'use strict';

window.Darwinator.GeneticAlgorithm = window.Darwinator.GeneticAlgorithm || {

  POPULATION_SIZE:          10,
  CROSSOVER_PROBABILITY:    0.8,
  MUTATION_PROBABILITY:     0.025,
  TOURNAMENT_PARAMETER:     0.75,
  NUMBER_OF_GENERATIONS:    100,
  NUMBER_OF_VARIABLES:      3,
  NUMBER_OF_GENES:          3,
  TOURNAMENT_SIZE:          4,
  ELITISM_DEGREE:           2,
  PLAYER_ADVANTAGE:         10, // increase to make enemies weaker

  // depends on player attributes
  VARIABLE_RANGE:           undefined, // max sum of enemy attributes

  // depends on population success
  MUTATION_RATE:            undefined,
  POOR_MAX_FITNESS:         0.1,  // used to set mutation rate

  /**
  * Generates a population of individuals from a given population. The new population is likely to be
  * more adapted to find a solution to the enemyScore() function.
  *
  * @method Darwinator.GeneticAlgorithm#generatePopulation
  * @param {Phaser.Game} [game] - The game that uses the algorithm.
  * @param {Phaser.Sprite} [target] - The sprite to be attacked by the enemies.
  * @param {Phaser.Group} [enemyGroup] - Optional. If not provided, a group with default values will be set.
  * @param {Boolean} [singleGeneration] - If true, only one iteration will be run, else, this.NUMBER_OF_GENERATIONS is used.
  * @param {Array} [spawnPositions] - The positions on which the enemies are allowed to spawn.
  * @return {Array} The last population generated.
  */
  generatePopulation: function(game, target, enemyGroup, singleGeneration, spawnPositions) {
    var attributes = target.attributes;
    this.VARIABLE_RANGE = attributes.strength + attributes.agility + attributes.intellect - this.PLAYER_ADVANTAGE;
    spawnPositions  = this.shuffle(spawnPositions);

    if(!enemyGroup){
      enemyGroup = game.add.group();
      console.log('GA: Enemy group not provided. Initializing with default values.');
      enemyGroup = this.initPopulation(enemyGroup, game, target, spawnPositions);
      return enemyGroup;
    }
    console.log('GA: Starting GA run..');
    var translatedEnemies = this.translateEnemyWave(enemyGroup);
    var population        = translatedEnemies[0];
    var fitnessLevels     = translatedEnemies[1];
    var bestIndex         = translatedEnemies[2];
    var bestIndividual    = population[bestIndex];

    // to eliminate weak populations
    if(fitnessLevels[bestIndex] <= this.POOR_MAX_FITNESS){
      this.MUTATION_RATE = 20;
    }else{
      this.MUTATION_RATE = 1;
    }

    // algorithm main loop
    for (var i = 0; i < (singleGeneration ? 1 : this.NUMBER_OF_GENERATIONS); i++) {

      // clone population
      var tmpPopulation = population.slice(0);

      // selection
      for(var l = 0; l < population.length; l += 2) {
        var ind1 = this.selection(fitnessLevels);
        var ind2 = this.selection(fitnessLevels);
        // crossover
        if (Math.random() < this.CROSSOVER_PROBABILITY) {
          var chromePair        = this.cross(population[ind1], population[ind2]);
          tmpPopulation[l]      = chromePair[0];
          tmpPopulation[l + 1]  = chromePair[1];
        } else {
          tmpPopulation[l]      = population[ind1];
          tmpPopulation[l + 1]  = population[ind2];
        }
        // mutation
        tmpPopulation[l]    = this.mutate(tmpPopulation[l]);
        tmpPopulation[l+1]  = this.mutate(tmpPopulation[l+1]);
      }

      if(fitnessLevels[bestIndex] > this.POOR_MAX_FITNESS){
        // elitism
        for(l = 0; l < this.ELITISM_DEGREE; l++) {
          tmpPopulation[l] = bestIndividual;
        }
      }

      // replace old population
      population = tmpPopulation;
    } //endof algorithm main loop

    var nextGeneration = this.translatePopulation(population, enemyGroup, game, target, spawnPositions);
    console.log('GA: Returning the new generation!');
    return nextGeneration;
  },

  /**
  * Generates a group of enemy sprites with some default values.
  *
  * @method Darwinator.GeneticAlgorithm#initPopulation
  * @param {Phaser.Group} [enemyGroup] - The enemy group to fill with enemies.
  * @param {Phaser.Game} [game] - The game that uses the algorithm.
  * @param {Phaser.Sprite} [target] - The sprite to be attacked by the enemies.
  * @param {Array} [spawnPositions] - The positions on which the enemies are allowed to spawn.
  * @return {Array} An enemy population with default attribute values.
  */
  initPopulation: function(enemyGroup, game, target, spawnPositions) {
    // 4 different enemy initial set of attributes - just an example, not permanent!
    var enemiesPerType  = this.POPULATION_SIZE / 5;
    var pos;
    var strength, agility, intellect;
    for(var i = 0; i < this.POPULATION_SIZE; i++){
      pos = spawnPositions[i % spawnPositions.length];
      if(i < enemiesPerType){
        // smart but slow and weak
        strength  = 0;
        agility   = 0;
        intellect = this.VARIABLE_RANGE;
      }else if(i < enemiesPerType*2){
        // strong but slow and stupid
        strength  = this.VARIABLE_RANGE;
        agility   = 0;
        intellect = 0;
      }else if(i < enemiesPerType*3){
        // fast but weak and stupid
        strength  = 0;
        agility   = this.VARIABLE_RANGE;
        intellect = 0;
      }else{
        // hybrid
        strength  = agility = intellect = Math.round(this.VARIABLE_RANGE / 3);
      }
      enemyGroup.add(new Darwinator.Enemy(game, target, pos.x, pos.y, undefined, strength, agility, intellect));
    }
    return enemyGroup;
  },

  // returns a shuffled version of the given array
  shuffle: function(array){
    array = array.slice(0);
    var shuff = [];

    while(array.length > 0)
      shuff = shuff.concat(array.splice(Math.round(Math.random() * (array.length-1)), 1));
    return shuff;
  },

  /**
  * Cross two individuals to create two new ones by performing a tradeoff between
  * two randomly selected genes in each individual.
  *
  * Example: Select index of x and y.
  * First individual: decrease x and increase y
  * Second individual: decrease y and increase x
  *
  * @method Darwinator.GeneticAlgorithm#cross
  * @param {Array} [firstInd] - The first individual to be crossed
  * @param {Array} [secondInd] - The second individual to be crossed
  * @return {Array} - A tuple containing the two new individuals.
  */
  cross: function(firstInd, secondInd) {
    var crossPoint1 = Math.round(Math.random()*(this.NUMBER_OF_GENES - 1));
    var crossPoint2 = Math.round(Math.random()*(this.NUMBER_OF_GENES - 1));

    var tradeOff = Math.random();
    var tradeOffAmount1 = Math.round(tradeOff * firstInd[crossPoint1]);
    var tradeOffAmount2 = Math.round(tradeOff * secondInd[crossPoint2]);

    var newInd1 = firstInd.slice(0);
    var newInd2 = secondInd.slice(0);

    newInd1[crossPoint1] -= tradeOffAmount1;
    newInd1[crossPoint2] += tradeOffAmount1;

    newInd2[crossPoint2] -= tradeOffAmount2;
    newInd2[crossPoint1] += tradeOffAmount2;

    return [newInd1, newInd2];
  },

  /**
  * Select a individual based on the fitness levels of the entire population.
  * this.TOURNAMENT_SIZE many individuals will be selected at random, and one of them will
  * be returned. The tournament works in such a way that a individual with a high fitness level
  * is more likely to be returned from the tournament, but is not more likely to participate.
  *
  * @method Darwinator.GeneticAlgorithm#selection
  * @param {Array} - The fitness levels of the entire population
  * @return {Number} - The index of the selected individual.
  */
  selection: function(fitnessLevels) {
    var tournamentParticipants = new Array(this.TOURNAMENT_SIZE);

    /* Select individuals at random, and represent them as a touple containing their indexes and their
    * fitness levels. */
    for (var i = 0; i < this.TOURNAMENT_SIZE; i++) {
      tournamentParticipants[i]    = new Array(2);
      tournamentParticipants[i][0] = Math.round(Math.random() * (this.POPULATION_SIZE - 1));
      tournamentParticipants[i][1] = fitnessLevels[tournamentParticipants[i][0]];
    }

    /* Sort by fitness levels */
    tournamentParticipants.sort(
      function(a,b) {return b[1]-a[1];}
    );

    for(i = 0; i < this.TOURNAMENT_SIZE; i++) {
      if (Math.random() < this.TOURNAMENT_PARAMETER) {
        return tournamentParticipants[i][0];
      }
    }

    return tournamentParticipants[i - 1][0];
  },

  /**
  * Mutate a given individual by performing a tradeoff between two randomly selected genes.
  *
  * @method Darwinator.GeneticAlgorithm#mutate
  * @param {Array} - The individual to be mutated
  * @return {Array} - The mutated individual.
  */
  mutate: function(individual) {
    if (Math.random() < this.MUTATION_PROBABILITY * this.MUTATION_RATE) {
      var gene1 = Math.round(Math.random()*(this.NUMBER_OF_GENES - 1));
      var gene2 = Math.round(Math.random()*(this.NUMBER_OF_GENES - 1));
      var tradeOffAmount = Math.round(Math.random() * individual[gene1]);
      individual[gene1] -= tradeOffAmount;
      individual[gene2] += tradeOffAmount;
    }
    return individual;
  },

  /**
  * Evaluates an enemy sprite based on its score.
  *
  * @method Darwinator.GeneticAlgorithm#evaluateInd
  * @param {Phaser.Sprite} - The individual to be evaluated
  * @return {Number} - The fitness level of the individual
  */
  evaluateInd: function(enemy) {
    var fitness = 1 - (1 / this.enemyScore(enemy));
    return fitness == -Infinity ? 0 : fitness;// maximize fitness based on enemy score
  },

  /**
  * Calculates the score of an enemy based on statistical attributes.
  *
  * @method Darwinator.GeneticAlgorithm#enemyScore
  * @param {Phaser.Sprite} - An enemy sprite
  * @return {Number} - The score of the enemy for a given game round.
  */
  enemyScore: function(enemy) {
    var score = enemy.alive ? enemy.damageDone*2 : enemy.damageDone;
    return score;
  },

  /**
  *
  * Use the attributes of an enemy sprite as genes in a real-value chromosome.
  *
  * @method Darwinator.GeneticAlgorithm#enemyToChromosome
  * @param {Phaser.Sprite} - An enemy sprite
  * @return {Number} - The enemy represented as a real-value chromosome
  */
  enemyToChromosome: function (enemy){
    return [enemy.attributes.strength, enemy.attributes.agility, enemy.attributes.intellect];
  },

  /**
  * Translates an enemy group of sprites to chromosomes and fitness levels.
  * The index of the most fit individual is also provided.
  *
  * @method Darwinator.GeneticAlgorithm#translateEnemyWave
  * @param {Phaser.Group} - A group of enemy sprites
  * @return {Array} - Chromosomes, fitnessLevels and the index of the fittest individual.
  *                     as [chromosomes, fitnessLevels, fittestIndex]
  */
  translateEnemyWave: function(enemyGroup){
    var currentSize = enemyGroup.length; //could add an extra param for this.
    var population  = new Array(currentSize);
    var fitness     = new Array(currentSize);
    var bestIndex   = 0;
    for(var i = 0; i < currentSize; i++){
      var enemy     = enemyGroup.getAt(i);
      population[i] = this.enemyToChromosome(enemy);
      fitness[i]    = this.evaluateInd(enemy);
      if(fitness[i] > fitness[bestIndex]){
        bestIndex = i;
      }
    }
    return [population, fitness, bestIndex];
  },

  /**
  * Replaces the given group of enemy sprites to the next generation of sprites.
  *
  * @method Darwinator.GeneticAlgorithm#translatePopulation
  * @param {Array} [population] - The chromosomes of the new generation.
  * @param {Phaser.Group} [enemyGroup] - The enemy sprite group to replace.
  * @param {Phaser.Game} [game] - The game that uses the algorithm.
  * @param {Phaser.Sprite} [target] - The sprite to be attacked by the enemies.
  * @param {Array} [spawnPositions] - The positions on which the enemies are allowed to spawn.
  * @return {Phaser.Group} The new group of enemies.
  */
  translatePopulation: function(population, enemyGroup, game, target, spawnPositions){
    // FIXME possible memory leak, should call destroy but it crashes for some reason..
    //game.enemies.destroy(true);
    enemyGroup      = game.add.group();
    for(var i = 0; i < population.length; i++){
      var pos         = spawnPositions[i % spawnPositions.length];
      var strength    = population[i][0];
      var agility     = population[i][1];
      var intellect   = population[i][2];
      var enemy       = new Darwinator.Enemy(game, target, pos.x, pos.y, undefined, strength, agility, intellect);
      enemyGroup.add(enemy);
    }
    return enemyGroup;
  },

};
<|endoftext|>


<commit_before>vde.App.controller('GroupsCtrl', function($scope, $rootScope, $location) {
  $scope.gMdl = { // General catch-all model for scoping
    groups: vde.Vis.groups,
    pipelines: vde.Vis.pipelines
  };

  $scope.toggleVisual = function(v) {
    $rootScope.activeVisual = v;
    $rootScope.activeGroup  = v.group || v;

    $rootScope.activePipeline = v.pipeline;
    $scope.gMdl.activeVisualPipeline = (v.pipeline || {}).name;
  };

  $scope.setPipeline = function() {
    var p = $scope.gMdl.activeVisualPipeline;
    if(p == '') $scope.activeVisual.pipeline = null;
    else if(p == 'vdeNewPipeline') {
      $scope.activeVisual.pipeline = new vde.Vis.Pipeline();
      $rootScope.activePipeline = $scope.activeVisual.pipeline;
      $scope.gMdl.activeVisualPipeline = $scope.activeVisual.pipeline.name;
    }
    else {
      $scope.activeVisual.pipeline = vde.Vis.pipelines[p];
      $rootScope.activePipeline = vde.Vis.pipelines[p];
    }

    vde.Vis.parse();
  };

  $scope.addAxis = function() {
    var axis = new vde.Vis.Axis('', $rootScope.activeGroup);
    $rootScope.activeVisual = axis;
  };

  $scope.removeVisual = function(type, name) {
    var cnf = confirm("Are you sure you wish to delete this mark?")
    if(!cnf) return;

    delete $rootScope.activeGroup[type][name];
    vde.Vis.parse();
  };

  $scope.toggleFont = function(prop, value) {
    var p = $rootScope.activeVisual.properties[prop];
    if(p.value == value) delete p.value;
    else p.value = value;

    $rootScope.activeVisual.checkExtents(prop);

    vde.Vis.parse();
  };
});<commit_msg>Confirmation typo<commit_after>vde.App.controller('GroupsCtrl', function($scope, $rootScope, $location) {
  $scope.gMdl = { // General catch-all model for scoping
    groups: vde.Vis.groups,
    pipelines: vde.Vis.pipelines
  };

  $scope.toggleVisual = function(v) {
    $rootScope.activeVisual = v;
    $rootScope.activeGroup  = v.group || v;

    $rootScope.activePipeline = v.pipeline;
    $scope.gMdl.activeVisualPipeline = (v.pipeline || {}).name;
  };

  $scope.setPipeline = function() {
    var p = $scope.gMdl.activeVisualPipeline;
    if(p == '') $scope.activeVisual.pipeline = null;
    else if(p == 'vdeNewPipeline') {
      $scope.activeVisual.pipeline = new vde.Vis.Pipeline();
      $rootScope.activePipeline = $scope.activeVisual.pipeline;
      $scope.gMdl.activeVisualPipeline = $scope.activeVisual.pipeline.name;
    }
    else {
      $scope.activeVisual.pipeline = vde.Vis.pipelines[p];
      $rootScope.activePipeline = vde.Vis.pipelines[p];
    }

    vde.Vis.parse();
  };

  $scope.addAxis = function() {
    var axis = new vde.Vis.Axis('', $rootScope.activeGroup);
    $rootScope.activeVisual = axis;
  };

  $scope.removeVisual = function(type, name) {
    var cnf = confirm("Are you sure you wish to delete this visual element?")
    if(!cnf) return;

    delete $rootScope.activeGroup[type][name];
    vde.Vis.parse();
  };

  $scope.toggleFont = function(prop, value) {
    var p = $rootScope.activeVisual.properties[prop];
    if(p.value == value) delete p.value;
    else p.value = value;

    $rootScope.activeVisual.checkExtents(prop);

    vde.Vis.parse();
  };
});<|endoftext|>


<commit_before>//var mode = 0; //à intégrer dans chaque jeu, 0 pour adaptation de la difficulté en fonction win/fail, 1 pour courbe bonds, 2 pour aléatoire total

/* variables à récupérer des jeux :
 * winState
 * mise
 * tours
 * difficulty (gameSpeed dans tomcruise.js)
 */

/* à intégrer dans chaque jeu
function changeMetaDiff() {
    if (mode === 0) {
        // reprendre code actuel fonctionnement diff
    } else if (mode === 1) {
        // envoyer vers contenu de courbeDiff.js
        cumulTours();
        checkWinFail();
        changeDifficulty();
    }
}
*/

// conserver le nombre de tours gagnants d'affilé
var lastWinFail = [];
var cumulWin = [];
var cumulFail = [];
var bondDiff = [0.1, 0.3, 0.6];

var newDiff = 0;

var compareArrayWin = 0;
var compareArrayFail = 0;

var compteurTours = 0; //compteur qui augmente après chaque tour
var toursBeforeChange = 2; //nbre de tours avant changement de comportement de la courbe de difficulté

function cumulTours() {
    if (winState === true) {
        lastWinFail.push("true");
        compteurTours++;

        console.log("dernier win:" + lastWinFail)

    } else if (winState === false) {
        lastWinFail.push("fail");
        compteurTours++;

        console.log("dernier fail:" + lastWinFail)

    }

    checkWinFail();
}

function clearArray() {
    if (compteurTours === toursBeforeChange) {
        lastWinFail = [];
        compteurTours = 0;
    }
}

function checkWinFail() {
    var idx = lastWinFail.indexOf("true");
    while (idx != -1) {
        cumulWin.push("true");
        idx = lastWinFail.indexOf("true", idx + 1);
    }
    console.log("cumul des win:" + cumulWin);

    var idx2 = lastWinFail.indexOf("fail");
    while (idx2 != -1) {
        cumulFail.push("fail");
        idx2 = lastWinFail.indexOf("fail", idx2 + 1);
    }
    console.log("cumul des fail:" + cumulFail);

    behaviorDiff();
}

//comparer les tableaux pour vérifier la présence de trois win
compareArrayWin = function (lastWinFail, cumulWin) {
    if (lastWinFail.length !== cumulWin.length) {
        return false;
    } else if (lastWinFail.length === cumulWin.length) {
        for (var i = 0; i < lastWinFail.length; i++) {
            if (lastWinFail[i] !== cumulWin[i]) {
                return false;
            }
        }
    console.log("coucou1");
    return true;
    }
};

//comparer les tableaux pour vérifier la présence de trois fail
compareArrayFail = function (lastWinFail, cumulFail) {
    if (lastWinFail.length !== cumulFail.length) {
        return false;
    } else if (lastWinFail.length === cumulFail.length) {
        for (var i = 0; i < lastWinFail.length; i++) {
            if (lastWinFail[i] !== cumulFail[i]) {
                return true;
            }
        }
    console.log("coucou2");
    return true;
    }
};

function behaviorDiff() {
    if (compareArrayWin(lastWinFail, cumulWin) === true && compteurTours === toursBeforeChange) {
        var tailleBondDiff = bondDiff[Math.floor(bondDiff.length * Math.random())];
        console.log("taille du bond de difficulté win" + tailleBondDiff);
        newDiff = difficulty + tailleBondDiff;
        console.log("newDiff = " + newDiff);

        if (newDiff >= 1) {
            newDiff = 1;
            //difficulty = newDiff;
        }

    } else if (compareArrayFail(lastWinFail, cumulFail) === true && compteurTours === toursBeforeChange) {
        var tailleBondDiff = bondDiff[Math.floor(bondDiff.length * Math.random())];
        console.log("taille du bond de difficulté fail" + tailleBondDiff);
        newDiff = difficulty - tailleBondDiff;
        console.log("newDiff = " + newDiff);

        if (newDiff < 0) {
            newDiff = 0;
            //difficulty = newDiff;
        }

    } else {

    }

    cumulWin = [];
    cumulFail = [];
    clearArray();
}

<commit_msg>nouvelle courbe de difficulté selon bonds fixes<commit_after>//var mode = 0; //à intégrer dans chaque jeu, 0 pour adaptation de la difficulté en fonction win/fail, 1 pour courbe bonds, 2 pour aléatoire total

/* variables à récupérer des jeux :
 * winState
 * mise
 * tours
 * difficulty (gameSpeed dans tomcruise.js)
 */

/* à intégrer dans chaque jeu
function changeMetaDiff() {
    if (mode === 0) {
        // reprendre code actuel fonctionnement diff
    } else if (mode === 1) {
        // envoyer vers contenu de courbeDiff.js
        selectFirstBondDiff();
        selectNewBondDiff();
        difficulty = newDiff;
    }
}
*/

// conserver le nombre de tours gagnants d'affilé
var lastWinFail = [];
var cumulWin = [];
var cumulFail = [];

var firstBondDiff = false; //false : premier bond de difficulté non sélectionné ; true, premier bond sélectionné

var bondDiffLittle = 0.1;
var bondDiffMedium = 0.3;
var bondDiffHigh = 0.6;
var bondDiffActual = 0;

var bondDiffNoLittle = [0.3, 0.6];
var bondDiffNoMedium = [0.1, 0.6];
var bondDiffNoHigh = [0.3, 0.6];
var bondDiffAll = [0.1, 0.3, 0.6];

var newDiff = 0;
var newBondDiff = 0;

var compareArrayWin = 0;
var compareArrayFail = 0;

var compteurTours = 0; //compteur qui augmente après chaque tour
var toursBeforeChange = 2; //nbre de tours avant changement de comportement de la courbe de difficulté

//générer aléatoirement premier bond de difficulté après la fin des tours de chauffe
function selectFirstBondDiff() {
    if (modeTest === false && firstBondDiff === false) {
        bondDiffActual = bondDiffAll[Math.floor(bondDiffAll.length * Math.random())];
        firstBondDiff = true;
        console.log("premier bond de difficulté: " + bondDiffActual);
    }
}

function selectNewBondDiff() {
    if (bondDiffActual === bondDiffLittle) {
        newBondDiff = bondDiffNoLittle[Math.floor(bondDiffNoLittle.length * Math.random())];
    } else if (bondDiffActual === bondDiffMedium) {
        newBondDiff = bondDiffNoMedium[Math.floor(bondDiffNoMedium.length * Math.random())];
    } else if (bondDiffActual === bondDiffHigh) {
        newBondDiff = bondDiffNoHigh[Math.floor(bondDiffNoHigh.length * Math.random())];
    }
    console.log("nouveau bond de difficulté: " + newBondDiff);

    changeDifficulty();
}

function changeDifficulty() {
    var array = [0, 1];
    var addOrSub = array[Math.floor(array.length * Math.random())];
    console.log("progression de la difficulté: " + addOrSub);

    if (addOrSub === 0) { //changement de difficulté par soustraction
        newDiff = difficulty - newBondDiff;
        console.log("newDiff = " + newDiff);

        if (newDiff < 0) {
            newDiff = 0;
            console.log("newDiff corrected = " + newDiff);
        }
    } else if (addOrSub === 1) { //changement de difficulté par addition
        newDiff = difficulty + newBondDiff;
        console.log("newDiff = " + newDiff);

        if (newDiff >= 1) {
            newDiff = 1;
            console.log("newDiff corrected = " + newDiff);
        }
    }

}

/*function cumulTours() {
    if (winState === true) {
        lastWinFail.push("true");
        compteurTours++;

        console.log("dernier win:" + lastWinFail)

    } else if (winState === false) {
        lastWinFail.push("fail");
        compteurTours++;

        console.log("dernier fail:" + lastWinFail)

    }

    checkWinFail();
}

function clearArray() {
    if (compteurTours === toursBeforeChange) {
        lastWinFail = [];
        compteurTours = 0;
    }
}

function checkWinFail() {
    var idx = lastWinFail.indexOf("true");
    while (idx != -1) {
        cumulWin.push("true");
        idx = lastWinFail.indexOf("true", idx + 1);
    }
    console.log("cumul des win:" + cumulWin);

    var idx2 = lastWinFail.indexOf("fail");
    while (idx2 != -1) {
        cumulFail.push("fail");
        idx2 = lastWinFail.indexOf("fail", idx2 + 1);
    }
    console.log("cumul des fail:" + cumulFail);

    behaviorDiff();
}

//comparer les tableaux pour vérifier la présence de trois win
compareArrayWin = function (lastWinFail, cumulWin) {
    if (lastWinFail.length !== cumulWin.length) {
        return false;
    } else if (lastWinFail.length === cumulWin.length) {
        for (var i = 0; i < lastWinFail.length; i++) {
            if (lastWinFail[i] !== cumulWin[i]) {
                return false;
            }
        }
    console.log("coucou1");
    return true;
    }
};

//comparer les tableaux pour vérifier la présence de trois fail
compareArrayFail = function (lastWinFail, cumulFail) {
    if (lastWinFail.length !== cumulFail.length) {
        return false;
    } else if (lastWinFail.length === cumulFail.length) {
        for (var i = 0; i < lastWinFail.length; i++) {
            if (lastWinFail[i] !== cumulFail[i]) {
                return true;
            }
        }
    console.log("coucou2");
    return true;
    }
};

function behaviorDiff() {
    if (compareArrayWin(lastWinFail, cumulWin) === true && compteurTours === toursBeforeChange) {
        var tailleBondDiff = bondDiff[Math.floor(bondDiff.length * Math.random())];
        console.log("taille du bond de difficulté win" + tailleBondDiff);
        newDiff = difficulty + tailleBondDiff;
        console.log("newDiff = " + newDiff);

        if (newDiff >= 1) {
            newDiff = 1;
            //difficulty = newDiff;
        }

    } else if (compareArrayFail(lastWinFail, cumulFail) === true && compteurTours === toursBeforeChange) {
        var tailleBondDiff = bondDiff[Math.floor(bondDiff.length * Math.random())];
        console.log("taille du bond de difficulté fail" + tailleBondDiff);
        newDiff = difficulty - tailleBondDiff;
        console.log("newDiff = " + newDiff);

        if (newDiff < 0) {
            newDiff = 0;
            //difficulty = newDiff;
        }

    } else {

    }

    cumulWin = [];
    cumulFail = [];
    clearArray();
}*/

<|endoftext|>