<commit_before>var _ = require('underscore');
var checkAndBuildOpts = require('../helpers/required-opts');
var WidgetsService = require('../editor/widgets/widgets-service');
var WidgetDefinitionModel = require('../data/widget-definition-model');
var WidgetsNotifications = require('../widgets-notifications');
var getStylesWithoutAutostyles = require('../helpers/styles-without-autostyle');

var WIDGET_STYLE_PARAMS = [
  'widget_style_definition',
  'auto_style_definition',
  'auto_style_allowed'
];

var REQUIRED_OPTS = [
  'diDashboardHelpers',
  'layerDefinitionsCollection',
  'widgetDefinitionsCollection',
  'analysisDefinitionNodesCollection'
];

/**
 *  Only manage **WIDGET** actions between Deep-Insights (CARTO.js) and Builder
 *
 */

module.exports = {

  track: function (options) {
    checkAndBuildOpts(options, REQUIRED_OPTS, this);

    this._getStylesWithoutAutostyles = getStylesWithoutAutostyles();

    this._widgetDefinitionsCollection.on('add', this._onWidgetDefinitionAdded, this);
    this._widgetDefinitionsCollection.on('sync', this._onWidgetDefinitionSynced, this);
    this._widgetDefinitionsCollection.on('change', this._onWidgetDefinitionChanged, this);
    this._widgetDefinitionsCollection.on('destroy', this._onWidgetDefinitionDestroyed, this);
    this._widgetDefinitionsCollection.on('add remove reset', this._invalidateSize, this);
    this._widgetDefinitionsCollection.each(this._onWidgetDefinitionAdded, this);

    WidgetsNotifications.track(this._widgetDefinitionsCollection);

    return this;
  },

  _invalidateSize: function () {
    var vis = this._diDashboardHelpers.getMap();
    vis.invalidateSize();
  },

  _onWidgetDefinitionAdded: function (m) {
    var widgetModel = this._diDashboardHelpers.getWidget(m.id);
    if (widgetModel) {
      widgetModel.set({
        show_source: true,
        show_stats: true,
        show_options: true
      });

      this._bindWidgetChanges(widgetModel);
    }
  },

  _onWidgetDefinitionSynced: function (m) {
    var widgetModel = this._diDashboardHelpers.getWidget(m.id);
    if (!widgetModel) {
      this._createWidgetModel(m);
    }
  },

  _onWidgetAutoStyleColorChanged: function (m) {
    var isAutoStyleApplied = m.isAutoStyle();
    var autoStyleInfo = m.getAutoStyle();
    var layerId = m.dataviewModel.layer.id;
    var layerDefModel = this._layerDefinitionsCollection.findWhere({ id: layerId });
    var nodeDefModel = layerDefModel && layerDefModel.getAnalysisDefinitionNodeModel();
    var styleModel = layerDefModel && layerDefModel.styleModel;
    var geometryType = nodeDefModel && nodeDefModel.get('simple_geom');

    if (layerDefModel) {
      layerDefModel.set({
        autoStyle: isAutoStyleApplied ? m.id : false,
        cartocss: autoStyleInfo.cartocss
      });
    }

    if (isAutoStyleApplied && styleModel && geometryType) {
      styleModel.setPropertiesFromAutoStyle({
        definition: autoStyleInfo.definition,
        geometryType: geometryType,
        widgetId: m.id
      });
    }
  },

  _onWidgetAutoStyleChanged: function (m) {
    var isAutoStyleApplied = m.isAutoStyle();
    var autoStyleInfo = m.getAutoStyle();
    var layerId = m.dataviewModel.layer.id;
    var layerDefModel = this._layerDefinitionsCollection.findWhere({ id: layerId });
    var nodeDefModel = layerDefModel && layerDefModel.getAnalysisDefinitionNodeModel();
    var styleModel = layerDefModel && layerDefModel.styleModel;
    var onLayerChange = _.debounce(function () {
      var dontResetStyles = true; // In order to make it more visible
      m.cancelAutoStyle(dontResetStyles);
    }, 10);

    var stylesWithoutAutostyles = this._getStylesWithoutAutostyles(layerDefModel);

    if (layerDefModel && nodeDefModel) {
      if (isAutoStyleApplied) {
        layerDefModel.set({
          autoStyle: m.id
        });
      }
    } else {
      return;
    }

    if (isAutoStyleApplied) {
      var geometryType = nodeDefModel.get('simple_geom');
      styleModel.setPropertiesFromAutoStyle({
        definition: autoStyleInfo.definition,
        geometryType: geometryType,
        widgetId: m.id
      });

      layerDefModel.set(_.extend(
        {
          cartocss: autoStyleInfo.cartocss,
          cartocss_custom: false
        },
        stylesWithoutAutostyles
      ));

      layerDefModel.once('change:autoStyle change:cartocss', onLayerChange, this);
    } else {
      layerDefModel.unbind('change:autoStyle change:cartocss', onLayerChange, this);
      var autoStyleId = layerDefModel.get('autoStyle');

      if (autoStyleId && autoStyleId === m.id) {
        styleModel.resetPropertiesFromAutoStyle();

        layerDefModel.set({
          autoStyle: false,
          cartocss_custom: layerDefModel.get('previousCartoCSSCustom'),
          cartocss: layerDefModel.get('previousCartoCSS')
        });

        // Because we are messing with the autoStyle property on saving,
        // whenever we disable autoStyle, we save the layer to force
        // the sync on the cartocss
        layerDefModel.save();
      }
    }
  },

  _onWidgetCustomAutoStyleColorChanged: function (m) {
    var isAutoStyleApplied = m.isAutoStyle();
    var autoStyleInfo = m.getAutoStyle();
    var layerId = m.dataviewModel.layer.id;
    var layerDefModel = this._layerDefinitionsCollection.findWhere({ id: layerId });
    var nodeDefModel = layerDefModel && layerDefModel.getAnalysisDefinitionNodeModel();
    var styleModel = layerDefModel && layerDefModel.styleModel;

    if (isAutoStyleApplied) {
      var geometryType = nodeDefModel.get('simple_geom');
      styleModel.setPropertiesFromAutoStyle({
        definition: autoStyleInfo.definition,
        geometryType: geometryType,
        widgetId: m.id
      });

      layerDefModel.set({
        cartocss: autoStyleInfo.cartocss,
        cartocss_custom: false
      }, {silent: true});

      // In order to make legends aware
      styleModel.trigger('style:update');
    }
  },

  _onWidgetDefinitionChanged: function (m) {
    var widgetModel = this._diDashboardHelpers.getWidget(m.id);

    // Only try to update if there's a corresponding widget model
    // E.g. the change of type will remove the model and provoke change events, which are not of interest (here),
    // since the widget model should be re-created for the new type anyway.
    if (widgetModel) {
      if (m.hasChanged('type')) {
        widgetModel.remove();
        this._createWidgetModel(m);
      } else {
        var attrs = this._formatWidgetAttrs(m.changedAttributes(), m);
        widgetModel.update(attrs);
      }
    }

    var colorChanged = !m.get('widget_color_changed') &&
                        m.changedAttributes() &&
                        m.changedAttributes().widget_style_definition &&
                        m.changedAttributes().widget_style_definition.color;

    if (colorChanged) {
      m.set({ widget_color_changed: true });
    }
  },

  _onWidgetDefinitionDestroyed: function (m) {
    var widgetModel = this._diDashboardHelpers.getWidget(m.id);

    if (widgetModel) {
      if (widgetModel.isAutoStyle()) {
        widgetModel.cancelAutoStyle();
      }
      this._unbindWidgetChanges(widgetModel);
      widgetModel.remove();
    }
  },

  _onEditWidget: function (m) {
    var widgetDefModel = this._widgetDefinitionsCollection.get(m.id);
    if (widgetDefModel) {
      WidgetsService.editWidget(widgetDefModel);
    }
  },

  _onRemoveWidget: function (m) {
    var widgetDefModel = this._widgetDefinitionsCollection.get(m.id);
    if (widgetDefModel) {
      WidgetsService.removeWidget(widgetDefModel);
    }
  },

  _bindWidgetChanges: function (m) {
    m.bind('editWidget', this._onEditWidget, this);
    m.bind('removeWidget', this._onRemoveWidget, this);
    m.bind('customAutoStyle', this._onWidgetCustomAutoStyleColorChanged, this);
    m.bind('change:autoStyle', this._onWidgetAutoStyleChanged, this);
    m.bind('change:color', this._onWidgetAutoStyleColorChanged, this);
  },

  _unbindWidgetChanges: function (m) {
    m.unbind('editWidget', this._onEditWidget, this);
    m.unbind('removeWidget', this._onRemoveWidget, this);
    m.unbind('customAutoStyle', this._onWidgetCustomAutoStyleColorChanged, this);
    m.unbind('change:autoStyle', this._onWidgetAutoStyleChanged, this);
    m.unbind('change:color', this._onWidgetAutoStyleColorChanged, this);
  },

  _createWidgetModel: function (m) {
    // e.g. 'time-series' => createTimeSeriesWidget
    var infix = m.get('type').replace(/(^\w|-\w)/g, function (match) {
      return match.toUpperCase().replace('-', '');
    });
    var methodName = 'create' + infix + 'Widget';

    var layerModel = this._diDashboardHelpers.getLayer(m.get('layer_id'));
    var attrs = this._formatWidgetAttrs(m.attributes, m);

    var widgetModel = this._diDashboardHelpers.getDashboard()[methodName](attrs, layerModel);

    if (widgetModel) {
      widgetModel.set({
        show_source: true,
        show_stats: true,
        show_options: true
      });

      this._bindWidgetChanges(widgetModel);
    }
  },

  /**
   * Massage some data points to the expected format of deep-insights API
   */
  _formatWidgetAttrs: function (changedAttrs, widgetDefModel) {
    var formattedAttrs = changedAttrs;

    // Source formatting
    if (_.isString(formattedAttrs.source)) {
      formattedAttrs = _.omit(formattedAttrs, 'source');
      formattedAttrs.source = {id: changedAttrs.source};
    }

    // Widget style or auto style changes
    var thereIsWidgetStyleChange = _.find(formattedAttrs, function (value, key) {
      return _.contains(WIDGET_STYLE_PARAMS, key);
    });

    if (!_.isUndefined(thereIsWidgetStyleChange)) {
      formattedAttrs = _.omit(formattedAttrs, WIDGET_STYLE_PARAMS);
      formattedAttrs.style = widgetDefModel.toJSON().style;
    }

    return formattedAttrs;
  },

  manageTimeSeriesForTorque: function (m) {
    function recreateWidget (currentTimeseries, newLayer, animated) {
      var persistName = currentTimeseries && currentTimeseries.get('title');
      // This prevents a bug if user has a range selected and switches column
      newLayer.unset('customDuration');
      this._createTimeseries(newLayer, animated, persistName);
    }

    // not a cartodb layer
    if (!m.styleModel) return;
    var animatedChanged = m.styleModel.changedAttributes().animated;
    var previousAnimated = m.styleModel.previous('animated');
    var attributeChanged;
    if (animatedChanged && previousAnimated && animatedChanged.attribute !== previousAnimated.attribute) attributeChanged = animatedChanged.attribute;
    var typeChanged = m.styleModel.changedAttributes().type;
    var animatedAttribute = m.styleModel.get('animated') && m.styleModel.get('animated').attribute;
    var previousType = m.styleModel.previous('type');

    if (!typeChanged && !attributeChanged) return;

    var type = m.styleModel.get('type');
    var widgetModel = this._diDashboardHelpers.getWidgets().filter(function (m) {
      return m.get('type') === 'time-series';
    })[0];

    var currentTimeseries = this._getTimeseriesDefinition();
    var newLayer = this._diDashboardHelpers.getLayer(m.id);

    if (type !== 'animation' && previousType === 'animation' && this._lastType !== type) {
      if (widgetModel) {
        this._removeTimeseries();
      }

      this._lastType = type;
      this._lastTSAnimateChange = '';
    }

    if (type === 'animation' && (this._lastTSAnimateChange !== attributeChanged || this._lastType !== 'animation')) {
      if (widgetModel) {
        this._removeTimeseries();
      }

      if (newLayer.get('type') === 'torque' || m.get('type') === 'torque') {
        recreateWidget.call(this, currentTimeseries, newLayer, _.extend({ animated: true }, animatedChanged, { attribute: animatedAttribute }));
      }

      this._lastType = type;
      this._lastTSAnimateChange = attributeChanged;
    }
  },

  _removeTimeseries: function () {
    this._widgetDefinitionsCollection.models.forEach(function (def) {
      if (def.get('type') === 'time-series') {
        def.set({avoidNotification: true}, {silent: true});
        def.destroy();
      }
    });
  },

  _getTimeseriesDefinition: function () {
    return this._widgetDefinitionsCollection.findWhere({type: 'time-series'});
  },

  _createTimeseries: function (newLayer, animatedChanged, persist) {
    function getColumnType (source, columnName) {
      var node = this._analysisDefinitionNodesCollection.get(source);
      return node && node.querySchemaModel.getColumnType(columnName);
    }

    this._removeTimeseries();
    var attribute = animatedChanged && animatedChanged.attribute || '';
    var animated = animatedChanged && animatedChanged.animated;
    if (attribute) {
      var baseAttrs = {
        type: 'time-series',
        layer_id: newLayer.get('id'),
        source: {
          id: newLayer.get('source')
        },
        options: {
          column: attribute,
          title: persist || 'time_date__t',
          animated: animated
        },
        style: {
          widget_style: WidgetDefinitionModel.getDefaultWidgetStyle('time-series')
        }
      };

      var columnType = getColumnType.call(this, newLayer.get('source'), attribute);
      if (columnType !== 'date') {
        baseAttrs.options.bins = 256;
      }

      this._widgetDefinitionsCollection.create(baseAttrs, { wait: true });
    }
  }
};
<commit_msg>Use the source id instead the whole node.<commit_after>var _ = require('underscore');
var checkAndBuildOpts = require('../helpers/required-opts');
var WidgetsService = require('../editor/widgets/widgets-service');
var WidgetDefinitionModel = require('../data/widget-definition-model');
var WidgetsNotifications = require('../widgets-notifications');
var getStylesWithoutAutostyles = require('../helpers/styles-without-autostyle');

var WIDGET_STYLE_PARAMS = [
  'widget_style_definition',
  'auto_style_definition',
  'auto_style_allowed'
];

var REQUIRED_OPTS = [
  'diDashboardHelpers',
  'layerDefinitionsCollection',
  'widgetDefinitionsCollection',
  'analysisDefinitionNodesCollection'
];

/**
 *  Only manage **WIDGET** actions between Deep-Insights (CARTO.js) and Builder
 *
 */

module.exports = {

  track: function (options) {
    checkAndBuildOpts(options, REQUIRED_OPTS, this);

    this._getStylesWithoutAutostyles = getStylesWithoutAutostyles();

    this._widgetDefinitionsCollection.on('add', this._onWidgetDefinitionAdded, this);
    this._widgetDefinitionsCollection.on('sync', this._onWidgetDefinitionSynced, this);
    this._widgetDefinitionsCollection.on('change', this._onWidgetDefinitionChanged, this);
    this._widgetDefinitionsCollection.on('destroy', this._onWidgetDefinitionDestroyed, this);
    this._widgetDefinitionsCollection.on('add remove reset', this._invalidateSize, this);
    this._widgetDefinitionsCollection.each(this._onWidgetDefinitionAdded, this);

    WidgetsNotifications.track(this._widgetDefinitionsCollection);

    return this;
  },

  _invalidateSize: function () {
    var vis = this._diDashboardHelpers.getMap();
    vis.invalidateSize();
  },

  _onWidgetDefinitionAdded: function (m) {
    var widgetModel = this._diDashboardHelpers.getWidget(m.id);
    if (widgetModel) {
      widgetModel.set({
        show_source: true,
        show_stats: true,
        show_options: true
      });

      this._bindWidgetChanges(widgetModel);
    }
  },

  _onWidgetDefinitionSynced: function (m) {
    var widgetModel = this._diDashboardHelpers.getWidget(m.id);
    if (!widgetModel) {
      this._createWidgetModel(m);
    }
  },

  _onWidgetAutoStyleColorChanged: function (m) {
    var isAutoStyleApplied = m.isAutoStyle();
    var autoStyleInfo = m.getAutoStyle();
    var layerId = m.dataviewModel.layer.id;
    var layerDefModel = this._layerDefinitionsCollection.findWhere({ id: layerId });
    var nodeDefModel = layerDefModel && layerDefModel.getAnalysisDefinitionNodeModel();
    var styleModel = layerDefModel && layerDefModel.styleModel;
    var geometryType = nodeDefModel && nodeDefModel.get('simple_geom');

    if (layerDefModel) {
      layerDefModel.set({
        autoStyle: isAutoStyleApplied ? m.id : false,
        cartocss: autoStyleInfo.cartocss
      });
    }

    if (isAutoStyleApplied && styleModel && geometryType) {
      styleModel.setPropertiesFromAutoStyle({
        definition: autoStyleInfo.definition,
        geometryType: geometryType,
        widgetId: m.id
      });
    }
  },

  _onWidgetAutoStyleChanged: function (m) {
    var isAutoStyleApplied = m.isAutoStyle();
    var autoStyleInfo = m.getAutoStyle();
    var layerId = m.dataviewModel.layer.id;
    var layerDefModel = this._layerDefinitionsCollection.findWhere({ id: layerId });
    var nodeDefModel = layerDefModel && layerDefModel.getAnalysisDefinitionNodeModel();
    var styleModel = layerDefModel && layerDefModel.styleModel;
    var onLayerChange = _.debounce(function () {
      var dontResetStyles = true; // In order to make it more visible
      m.cancelAutoStyle(dontResetStyles);
    }, 10);

    var stylesWithoutAutostyles = this._getStylesWithoutAutostyles(layerDefModel);

    if (layerDefModel && nodeDefModel) {
      if (isAutoStyleApplied) {
        layerDefModel.set({
          autoStyle: m.id
        });
      }
    } else {
      return;
    }

    if (isAutoStyleApplied) {
      var geometryType = nodeDefModel.get('simple_geom');
      styleModel.setPropertiesFromAutoStyle({
        definition: autoStyleInfo.definition,
        geometryType: geometryType,
        widgetId: m.id
      });

      layerDefModel.set(_.extend(
        {
          cartocss: autoStyleInfo.cartocss,
          cartocss_custom: false
        },
        stylesWithoutAutostyles
      ));

      layerDefModel.once('change:autoStyle change:cartocss', onLayerChange, this);
    } else {
      layerDefModel.unbind('change:autoStyle change:cartocss', onLayerChange, this);
      var autoStyleId = layerDefModel.get('autoStyle');

      if (autoStyleId && autoStyleId === m.id) {
        styleModel.resetPropertiesFromAutoStyle();

        layerDefModel.set({
          autoStyle: false,
          cartocss_custom: layerDefModel.get('previousCartoCSSCustom'),
          cartocss: layerDefModel.get('previousCartoCSS')
        });

        // Because we are messing with the autoStyle property on saving,
        // whenever we disable autoStyle, we save the layer to force
        // the sync on the cartocss
        layerDefModel.save();
      }
    }
  },

  _onWidgetCustomAutoStyleColorChanged: function (m) {
    var isAutoStyleApplied = m.isAutoStyle();
    var autoStyleInfo = m.getAutoStyle();
    var layerId = m.dataviewModel.layer.id;
    var layerDefModel = this._layerDefinitionsCollection.findWhere({ id: layerId });
    var nodeDefModel = layerDefModel && layerDefModel.getAnalysisDefinitionNodeModel();
    var styleModel = layerDefModel && layerDefModel.styleModel;

    if (isAutoStyleApplied) {
      var geometryType = nodeDefModel.get('simple_geom');
      styleModel.setPropertiesFromAutoStyle({
        definition: autoStyleInfo.definition,
        geometryType: geometryType,
        widgetId: m.id
      });

      layerDefModel.set({
        cartocss: autoStyleInfo.cartocss,
        cartocss_custom: false
      }, {silent: true});

      // In order to make legends aware
      styleModel.trigger('style:update');
    }
  },

  _onWidgetDefinitionChanged: function (m) {
    var widgetModel = this._diDashboardHelpers.getWidget(m.id);

    // Only try to update if there's a corresponding widget model
    // E.g. the change of type will remove the model and provoke change events, which are not of interest (here),
    // since the widget model should be re-created for the new type anyway.
    if (widgetModel) {
      if (m.hasChanged('type')) {
        widgetModel.remove();
        this._createWidgetModel(m);
      } else {
        var attrs = this._formatWidgetAttrs(m.changedAttributes(), m);
        widgetModel.update(attrs);
      }
    }

    var colorChanged = !m.get('widget_color_changed') &&
                        m.changedAttributes() &&
                        m.changedAttributes().widget_style_definition &&
                        m.changedAttributes().widget_style_definition.color;

    if (colorChanged) {
      m.set({ widget_color_changed: true });
    }
  },

  _onWidgetDefinitionDestroyed: function (m) {
    var widgetModel = this._diDashboardHelpers.getWidget(m.id);

    if (widgetModel) {
      if (widgetModel.isAutoStyle()) {
        widgetModel.cancelAutoStyle();
      }
      this._unbindWidgetChanges(widgetModel);
      widgetModel.remove();
    }
  },

  _onEditWidget: function (m) {
    var widgetDefModel = this._widgetDefinitionsCollection.get(m.id);
    if (widgetDefModel) {
      WidgetsService.editWidget(widgetDefModel);
    }
  },

  _onRemoveWidget: function (m) {
    var widgetDefModel = this._widgetDefinitionsCollection.get(m.id);
    if (widgetDefModel) {
      WidgetsService.removeWidget(widgetDefModel);
    }
  },

  _bindWidgetChanges: function (m) {
    m.bind('editWidget', this._onEditWidget, this);
    m.bind('removeWidget', this._onRemoveWidget, this);
    m.bind('customAutoStyle', this._onWidgetCustomAutoStyleColorChanged, this);
    m.bind('change:autoStyle', this._onWidgetAutoStyleChanged, this);
    m.bind('change:color', this._onWidgetAutoStyleColorChanged, this);
  },

  _unbindWidgetChanges: function (m) {
    m.unbind('editWidget', this._onEditWidget, this);
    m.unbind('removeWidget', this._onRemoveWidget, this);
    m.unbind('customAutoStyle', this._onWidgetCustomAutoStyleColorChanged, this);
    m.unbind('change:autoStyle', this._onWidgetAutoStyleChanged, this);
    m.unbind('change:color', this._onWidgetAutoStyleColorChanged, this);
  },

  _createWidgetModel: function (m) {
    // e.g. 'time-series' => createTimeSeriesWidget
    var infix = m.get('type').replace(/(^\w|-\w)/g, function (match) {
      return match.toUpperCase().replace('-', '');
    });
    var methodName = 'create' + infix + 'Widget';

    var layerModel = this._diDashboardHelpers.getLayer(m.get('layer_id'));
    var attrs = this._formatWidgetAttrs(m.attributes, m);

    var widgetModel = this._diDashboardHelpers.getDashboard()[methodName](attrs, layerModel);

    if (widgetModel) {
      widgetModel.set({
        show_source: true,
        show_stats: true,
        show_options: true
      });

      this._bindWidgetChanges(widgetModel);
    }
  },

  /**
   * Massage some data points to the expected format of deep-insights API
   */
  _formatWidgetAttrs: function (changedAttrs, widgetDefModel) {
    var formattedAttrs = changedAttrs;

    // Source formatting
    if (_.isString(formattedAttrs.source)) {
      formattedAttrs = _.omit(formattedAttrs, 'source');
      formattedAttrs.source = {id: changedAttrs.source};
    }

    // Widget style or auto style changes
    var thereIsWidgetStyleChange = _.find(formattedAttrs, function (value, key) {
      return _.contains(WIDGET_STYLE_PARAMS, key);
    });

    if (!_.isUndefined(thereIsWidgetStyleChange)) {
      formattedAttrs = _.omit(formattedAttrs, WIDGET_STYLE_PARAMS);
      formattedAttrs.style = widgetDefModel.toJSON().style;
    }

    return formattedAttrs;
  },

  manageTimeSeriesForTorque: function (m) {
    function recreateWidget (currentTimeseries, newLayer, animated) {
      var persistName = currentTimeseries && currentTimeseries.get('title');
      // This prevents a bug if user has a range selected and switches column
      newLayer.unset('customDuration');
      this._createTimeseries(newLayer, animated, persistName);
    }

    // not a cartodb layer
    if (!m.styleModel) return;
    var animatedChanged = m.styleModel.changedAttributes().animated;
    var previousAnimated = m.styleModel.previous('animated');
    var attributeChanged;
    if (animatedChanged && previousAnimated && animatedChanged.attribute !== previousAnimated.attribute) attributeChanged = animatedChanged.attribute;
    var typeChanged = m.styleModel.changedAttributes().type;
    var animatedAttribute = m.styleModel.get('animated') && m.styleModel.get('animated').attribute;
    var previousType = m.styleModel.previous('type');

    if (!typeChanged && !attributeChanged) return;

    var type = m.styleModel.get('type');
    var widgetModel = this._diDashboardHelpers.getWidgets().filter(function (m) {
      return m.get('type') === 'time-series';
    })[0];

    var currentTimeseries = this._getTimeseriesDefinition();
    var newLayer = this._diDashboardHelpers.getLayer(m.id);

    if (type !== 'animation' && previousType === 'animation' && this._lastType !== type) {
      if (widgetModel) {
        this._removeTimeseries();
      }

      this._lastType = type;
      this._lastTSAnimateChange = '';
    }

    if (type === 'animation' && (this._lastTSAnimateChange !== attributeChanged || this._lastType !== 'animation')) {
      if (widgetModel) {
        this._removeTimeseries();
      }

      if (newLayer.get('type') === 'torque' || m.get('type') === 'torque') {
        recreateWidget.call(this, currentTimeseries, newLayer, _.extend({ animated: true }, animatedChanged, { attribute: animatedAttribute }));
      }

      this._lastType = type;
      this._lastTSAnimateChange = attributeChanged;
    }
  },

  _removeTimeseries: function () {
    this._widgetDefinitionsCollection.models.forEach(function (def) {
      if (def.get('type') === 'time-series') {
        def.set({avoidNotification: true}, {silent: true});
        def.destroy();
      }
    });
  },

  _getTimeseriesDefinition: function () {
    return this._widgetDefinitionsCollection.findWhere({type: 'time-series'});
  },

  _createTimeseries: function (newLayer, animatedChanged, persist) {
    function getColumnType (source, columnName) {
      var node = this._analysisDefinitionNodesCollection.get(source);
      return node && node.querySchemaModel.getColumnType(columnName);
    }

    this._removeTimeseries();
    var attribute = animatedChanged && animatedChanged.attribute || '';
    var animated = animatedChanged && animatedChanged.animated;
    if (attribute) {
      var baseAttrs = {
        type: 'time-series',
        layer_id: newLayer.get('id'),
        source: {
          id: newLayer.getSourceId()
        },
        options: {
          column: attribute,
          title: persist || 'time_date__t',
          animated: animated
        },
        style: {
          widget_style: WidgetDefinitionModel.getDefaultWidgetStyle('time-series')
        }
      };

      var columnType = getColumnType.call(this, newLayer.get('source'), attribute);
      if (columnType !== 'date') {
        baseAttrs.options.bins = 256;
      }

      this._widgetDefinitionsCollection.create(baseAttrs, { wait: true });
    }
  }
};
<|endoftext|>


<commit_before>(function(App) {

  'use strict';

  App.Controller = App.Controller || {};

  App.Controller.Activities = App.Controller.Page.extend({

    index: function(params) {
      new App.View.Masonry({
        el: '#masonry-layout'
      });
      this.filtersView = new App.View.MediaFilters({
        callback: this._filter.bind(this)
      });
    },

    show: function(params) {
      new App.View.ActivitiesAnchors({});
      if(this.isMobile) {
        this.initSliders();
      } else {
        new App.View.Masonry({
          el: '#masonry-layouts'
        });
      }
    },

    _filter: function() {
      jQuery.ajaxSetup({cache: true});
      $.getScript($(location).attr('href'));
      return false;
    },

    initSliders: function() {
      Array.prototype.slice.call(document.querySelectorAll('.js_slider')).forEach(function (element, index) {
        var loryOptions = {
          enableMouseEvents: true
        };
        if(false) {
          loryOptions['infinite'] = 1;
        } else {
          loryOptions['rewind'] = true;
        }

        lory(element, loryOptions);
      });
    }

  });

})(this.App);
<commit_msg>Lory options<commit_after>(function(App) {

  'use strict';

  App.Controller = App.Controller || {};

  App.Controller.Activities = App.Controller.Page.extend({

    index: function(params) {
      new App.View.Masonry({
        el: '#masonry-layout'
      });
      this.filtersView = new App.View.MediaFilters({
        callback: this._filter.bind(this)
      });
    },

    show: function(params) {
      new App.View.ActivitiesAnchors({});
      if(this.isMobile) {
        this.initSliders();
      } else {
        new App.View.Masonry({
          el: '#masonry-layouts'
        });
      }
    },

    _filter: function() {
      jQuery.ajaxSetup({cache: true});
      $.getScript($(location).attr('href'));
      return false;
    },

    initSliders: function() {
      Array.prototype.slice.call(document.querySelectorAll('.js_slider')).forEach(function (element, index) {
        lory(element, {
          rewind: true,
          enableMouseEvents: true
        });
      });
    }

  });

})(this.App);
<|endoftext|>


<commit_before>/* jshint -W079 */
/* Related to https://github.com/linnovate/mean/issues/898 */
'use strict';

/**
 * Module dependencies.
 */
var expect = require('expect.js'),
        mongoose = require('mongoose'),
        Project = mongoose.model('Project'),
        Organisation = mongoose.model('Organisation'),
        BankAccount = mongoose.model('BankAccount');

var project1;
var project2;
var project3;
var organisation;
var bank_account;

describe('<Unit Test>', function () {
    describe('Model Project:', function () {
        beforeEach(function (done) {
            this.timeout(10000);

            organisation = new Organisation({
                "name": "Humanrights org",
                "representative": "Representative",
                "address": "Adress 123",
                "tel": "123445",
                "email": "email@org.com",
                "website": "www.org.com",
                "legal_status": "legal status",
                "history_status": "history status",
                "int_links": "international links",
                "bank_account": bank_account});
            bank_account = new BankAccount({
                "bank_contact_details": "Branch, address",
                "iban": "abcdefg1234",
                "swift": "OKOYFI",
                "holder_name": "John Smith"});
            project1 = new Project(
                    {"project_ref": 15001,
                      "title": "Human rights",
                        "coordinator": "Keijo Koordinaattori",
                        "organisation": organisation,
                        "status": "approved",
                        "reg_date": "12.10.2014",
                        "funding": {
                            "applied_curr_local": "50 000",
                            "applied_curr_eur": "10 000",
                            "granted_curr_local": "50 000",
                            "granted_curr_eur": "10 000"},
                        "duration_months": 30,
                        "description": "A short description of project",
                        "description_en": "Description in english",
                        "background": "Project background",
                        "beneficiaries": "The project benefits...",
                        "gender_aspect": "Gender aspects include...",
                        "project_goal": "Project goal is...",
                        "sustainability_risks": "Some data here",
                        "reporting_evaluation": "Data",
                        "other_donors_proposed": "Donated amount",
                        "dac": "abcd123"});
            project1.save();
            project2 = new Project(
                    {"project_ref": 15002,
                      "title": "Humans",
                        "coordinator": "Keijo Koordi",
                        "organisation": organisation,
                        "status": "approved",
                        "reg_date": "12.9.2014",
                        "funding": {
                            "applied_curr_local": "50 000",
                            "applied_curr_eur": "11 000",
                            "granted_curr_local": "50 000",
                            "granted_curr_eur": "11 000"},
                        "duration_months": 12,
                        "description": "A short description of project",
                        "description_en": "Description in english",
                        "background": "Project background 2",
                        "beneficiaries": "The project benefits such and such",
                        "gender_aspect": "Gender aspects include this and that",
                        "project_goal": "Project goal is...",
                        "sustainability_risks": "Some data here",
                        "reporting_evaluation": "More data",
                        "other_donors_proposed": "Donated amount",
                        "dac": "abcd123"
                    });
            project2.save();
            done();
        });

        describe('Method All', function () {

            it('should list all projects', function (done) {

                this.timeout(10000);
                var query = Project
                return query.find(function (err, data) {
                    expect(err).to.be(null);
                    expect(data.length).to.be(2);
//                    expect(data[0].title).to.equal("Human rights");
//                    expect(data[1].status).to.be("approved");
                    done();
                });

            });
        });

        describe('Method Show', function () {

            it('should find given project', function (done) {
                this.timeout(10000);
                var query = Project;
                return query.findOne({title: 'Humans'}).exec(function (err, data) {
                    expect(err).to.be(null);
                    expect(data.title).to.be("Humans");
                    done();
                });
            });
        });

        describe('Method Save', function () {

            beforeEach(function (done) {
                project3 = new Project(
                        {"project_ref": 15003,
                          "title": "Children rights",
                            "coordinator": "Kaija Koordi",
                            "organisation": organisation,
                            "status": "registered",
                            "funding": {
                                "applied_curr_local": "50 000",
                                "applied_curr_eur": "11 000",
                                "granted_curr_local": "50 000",
                                "granted_curr_eur": "11 000"},
                            "duration_months": 19,
                            "description": "A short description of project",
                            "description_en": "Description in english",
                            "background": "Project background 3",
                            "beneficiaries": "The project benefits such and such",
                            "gender_aspect": "Gender aspects include this and that",
                            "project_goal": "Project goal is...",
                            "sustainability_risks": "Some data here",
                            "reporting_evaluation": "More data",
                            "other_donors_proposed": "Donated amount",
                            "dac": "19191123"
                        });
                done();
            });

            it('should be able to save project without problems', function (done) {
                this.timeout(10000);

                return project3.save(function (err, data) {
                    expect(err).to.be(null);
                    expect(data.title).to.equal('Children rights');
                    expect(data.coordinator).to.equal('Kaija Koordi');
                    expect(data.organisation.length).to.not.equal(0);
                    expect(data.reg_date.length).to.not.equal(0);
                    project3.remove();
                    done();
                });
            });

            it('should show an error when try to save without a title', function (done) {
                this.timeout(10000);

                project3.title = '';
                return project3.save(function (err) {
                    expect(err).to.not.be(null);
                    project3.remove();
                    done();
                });
            });
        });

        afterEach(function (done) {
            this.timeout(10000);
            project1.remove();
            project2.remove();

            done();
        });
    });
});
<commit_msg>trying build<commit_after>/* jshint -W079 */
/* Related to https://github.com/linnovate/mean/issues/898 */
'use strict';

/**
 * Module dependencies.
 */
var expect = require('expect.js'),
        mongoose = require('mongoose'),
        Project = mongoose.model('Project'),
        Organisation = mongoose.model('Organisation'),
        BankAccount = mongoose.model('BankAccount');

var project1;
var project2;
var project3;
var organisation;
var bank_account;

describe('<Unit Test>', function () {
    describe('Model Project:', function () {
        beforeEach(function (done) {
            this.timeout(10000);

            organisation = new Organisation({
                "name": "Humanrights org",
                "representative": "Representative",
                "address": "Adress 123",
                "tel": "123445",
                "email": "email@org.com",
                "website": "www.org.com",
                "legal_status": "legal status",
                "history_status": "history status",
                "int_links": "international links",
                "bank_account": bank_account});
            bank_account = new BankAccount({
                "bank_contact_details": "Branch, address",
                "iban": "abcdefg1234",
                "swift": "OKOYFI",
                "holder_name": "John Smith"});
            project1 = new Project(
                    {"title": "Human rights",
                        "coordinator": "Keijo Koordinaattori",
                        "organisation": organisation,
                        "status": "approved",
                        "reg_date": "12.10.2014",
                        "funding": {
                            "applied_curr_local": "50 000",
                            "applied_curr_eur": "10 000",
                            "granted_curr_local": "50 000",
                            "granted_curr_eur": "10 000"},
                        "duration_months": 30,
                        "description": "A short description of project",
                        "description_en": "Description in english",
                        "background": "Project background",
                        "beneficiaries": "The project benefits...",
                        "gender_aspect": "Gender aspects include...",
                        "project_goal": "Project goal is...",
                        "sustainability_risks": "Some data here",
                        "reporting_evaluation": "Data",
                        "other_donors_proposed": "Donated amount",
                        "dac": "abcd123"});
            project1.save();
            project2 = new Project(
                    {"title": "Humans",
                        "coordinator": "Keijo Koordi",
                        "organisation": organisation,
                        "status": "approved",
                        "reg_date": "12.9.2014",
                        "funding": {
                            "applied_curr_local": "50 000",
                            "applied_curr_eur": "11 000",
                            "granted_curr_local": "50 000",
                            "granted_curr_eur": "11 000"},
                        "duration_months": 12,
                        "description": "A short description of project",
                        "description_en": "Description in english",
                        "background": "Project background 2",
                        "beneficiaries": "The project benefits such and such",
                        "gender_aspect": "Gender aspects include this and that",
                        "project_goal": "Project goal is...",
                        "sustainability_risks": "Some data here",
                        "reporting_evaluation": "More data",
                        "other_donors_proposed": "Donated amount",
                        "dac": "abcd123"
                    });
            project2.save();
            done();
        });

        describe('Method All', function () {

            it('should list all projects', function (done) {

                this.timeout(10000);
                var query = Project
                return query.find(function (err, data) {
                    expect(err).to.be(null);
                    expect(data.length).to.be(2);
//                    expect(data[0].title).to.equal("Human rights");
//                    expect(data[1].status).to.be("approved");
                    done();
                });

            });
        });

        describe('Method Show', function () {

            it('should find given project', function (done) {
                this.timeout(10000);
                var query = Project;
                return query.findOne({title: 'Humans'}).exec(function (err, data) {
                    expect(err).to.be(null);
                    expect(data.title).to.be("Humans");
                    done();
                });
            });
        });

        describe('Method Save', function () {

            beforeEach(function (done) {
                project3 = new Project(
                        {"title": "Children rights",
                            "coordinator": "Kaija Koordi",
                            "organisation": organisation,
                            "status": "registered",
                            "funding": {
                                "applied_curr_local": "50 000",
                                "applied_curr_eur": "11 000",
                                "granted_curr_local": "50 000",
                                "granted_curr_eur": "11 000"},
                            "duration_months": 19,
                            "description": "A short description of project",
                            "description_en": "Description in english",
                            "background": "Project background 3",
                            "beneficiaries": "The project benefits such and such",
                            "gender_aspect": "Gender aspects include this and that",
                            "project_goal": "Project goal is...",
                            "sustainability_risks": "Some data here",
                            "reporting_evaluation": "More data",
                            "other_donors_proposed": "Donated amount",
                            "dac": "19191123"
                        });
                done();
            });

            it('should be able to save project without problems', function (done) {
                this.timeout(10000);

                return project3.save(function (err, data) {
                    expect(err).to.be(null);
                    expect(data.title).to.equal('Children rights');
                    expect(data.coordinator).to.equal('Kaija Koordi');
                    expect(data.organisation.length).to.not.equal(0);
                    expect(data.reg_date.length).to.not.equal(0);
                    project3.remove();
                    done();
                });
            });

            it('should show an error when try to save without a title', function (done) {
                this.timeout(10000);

                project3.title = '';
                return project3.save(function (err) {
                    expect(err).to.not.be(null);
                    project3.remove();
                    done();
                });
            });
        });

        afterEach(function (done) {
            this.timeout(10000);
            project1.remove();
            project2.remove();

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


<commit_before>/**
 * Created by kuroky360 on 16-1-25.
 */
!function(window,document,undefined){

    var angular=window.angular||{},
        toString=Object.prototype.toString;
    //todo fns
    function copy(){

    }

    function extend(){

    }

    function isFunciton(value){return typeof value ==='function';}

    function noop(){}

    function isUndefined(value){return typeof value ==='undefined';}

    function isDefined(value){return typeof value !=='undefined';}

    function isString(value){return typeof value==='string';}

    function isObject(value){return value!==null&&typeof value==='object'}

    function isNumber(value){return typeof value === 'number'}

    function isDate(value){ toString.call(value)==='[object Date]'}

    function lowercase(value){return isString(value)?value.toLowerCase():value}

    function uppercase(value){return isString(value)?value.toUpperCase():value}

    function fromJson(value){
        return isString(value)?JSON.parse(value):value;
    }

    function toJson(value){
    }

    function setupModuleLoader(window) {

        function ensure(obj, child, factory) {
            return obj[child] || (obj[child] = factory());
        }

        var angular = ensure(window, angular, Object);

        return ensure(angular, 'module', function () {
            var modules = {};

            return function module(name, require, config) {
                if (require && modules.hasOwnProperty(name)) {
                    modules[name] = null;
                }
                return ensure(modules, name, function () {
                    var invokeQueue=[];
                    var configBlocks=[];
                    var runBlocks=[];
                    var moduleInstance={
                        _invokeQueue:invokeQueue,
                        _configBlock:configBlocks,
                        _runBlocks:runBlocks,
                        _require:require,
                        _name:name
                    };

                    function invokeLater(provider,method,insertMethod,queue){
                        if(!queue) queue=invokeQueue;
                        return function(){
                            queue[insertMethod||'push']([provider,method,arguments]);
                            return moduleInstance;
                        }
                    }

                    function invokeLaterAndSetModuleName(provider,method){
                        if(isFunciton(method)) method.$$moduleName=name;
                        return function(recipeName,factoryName){
                            invokeQueue.push([provider,method,arguments]);
                            return moduleInstance;
                        };
                    }
                });
            };
        });
    }

}(window,document);

<commit_msg>add  identity fn<commit_after>/**
 * Created by kuroky360 on 16-1-25.
 */
!function(window,document,undefined){

    var angular=window.angular||{},
        toString=Object.prototype.toString;
    //todo fns
    function copy(){

    }

    function extend(){

    }

    function isFunciton(value){return typeof value ==='function';}

    function noop(){}

    function isUndefined(value){return typeof value ==='undefined';}

    function isDefined(value){return typeof value !=='undefined';}

    function isString(value){return typeof value==='string';}

    function isObject(value){return value!==null&&typeof value==='object'}

    function isNumber(value){return typeof value === 'number'}

    function isDate(value){ toString.call(value)==='[object Date]'}

    function lowercase(value){return isString(value)?value.toLowerCase():value}

    function uppercase(value){return isString(value)?value.toUpperCase():value}

    function fromJson(value){
        return isString(value)?JSON.parse(value):value;
    }

    function identity($){return $;}

    function toJson(value){
    }

    function setupModuleLoader(window) {

        function ensure(obj, child, factory) {
            return obj[child] || (obj[child] = factory());
        }

        var angular = ensure(window, angular, Object);

        return ensure(angular, 'module', function () {
            var modules = {};

            return function module(name, require, config) {
                if (require && modules.hasOwnProperty(name)) {
                    modules[name] = null;
                }
                return ensure(modules, name, function () {
                    var invokeQueue=[];
                    var configBlocks=[];
                    var runBlocks=[];
                    var moduleInstance={
                        _invokeQueue:invokeQueue,
                        _configBlock:configBlocks,
                        _runBlocks:runBlocks,
                        _require:require,
                        _name:name
                    };

                    function invokeLater(provider,method,insertMethod,queue){
                        if(!queue) queue=invokeQueue;
                        return function(){
                            queue[insertMethod||'push']([provider,method,arguments]);
                            return moduleInstance;
                        }
                    }

                    function invokeLaterAndSetModuleName(provider,method){
                        if(isFunciton(method)) method.$$moduleName=name;
                        return function(recipeName,factoryName){
                            invokeQueue.push([provider,method,arguments]);
                            return moduleInstance;
                        };
                    }
                });
            };
        });
    }

}(window,document);

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
 */

var rest = require('../../../common/rest.api'),
    config = require('../../../../../config/config.global.js'),
    authApi = require('../../../common/auth.api'),
    plugins = require('../plugins.api'),
    appErrors = require('../../../errors/app.errors'),
    commonUtils = require('../../../utils/common.utils')
    ;
var glanceAPIServer;

glanceApi = module.exports;

var imgMgrIp = ((config.imageManager) && (config.imageManager.ip)) ?
    config.imageManager.ip : global.DFLT_SERVER_IP;
var imgMgrPort = ((config.imageManager) && (config.imageManager.port)) ?
    config.imageManager.port : '9292';

glanceAPIServer = rest.getAPIServer({apiName:global.label.IDENTITY_SERVER,
                                      server:imgMgrIp, port:imgMgrPort});
function getTenantIdByReqCookie (req)
{
    if (req.cookies && req.cookies.project) {
        return req.cookies.project;
    } else {
        var ajaxCall = req.headers['x-requested-with'];
        if (ajaxCall == 'XMLHttpRequest') {
           req.res.setHeader('X-Redirect-Url','/logout');
           req.res.send(307,'');
        } else {
           req.res.redirect('/logout');
        }
        return null;
    }
}

/* Function: doGlanceOpCb
 */
function doGlanceOpCb (reqUrl, tenantId, req, glanceCallback, stopRetry,
                       callback)
{
    var forceAuth = stopRetry;

    authApi.getTokenObj(req, tenantId, forceAuth, function(err, tokenObj) {
        if ((err) || (null == tokenObj) || (null == tokenObj.id)) {
            if (stopRetry) {
                console.log("We are done retrying for tenantId:" + tenantId +
                            " with err:" + err);
                commonUtils.redirectToLogout(req, req.res);
                callback(err, null);
            } else {
                /* Retry once again */
                console.log("We are about to retry for tenantId:" + tenantId);
                glanceCallback(reqUrl, req, callback, true);
            }
        } else {
            console.log("doGlanceOpCb() success with tenantId:" + tenantId);
            callback(err, tokenObj);
        }
    });
}

/* Wrapper function to GET Data from Glance-Server */
glanceApi.get = function(reqUrl, req, callback, stopRetry) {
    var headers = {};
    var forceAuth = stopRetry;
    var tenantId = getTenantIdByReqCookie(req);
    if (null == tenantId) {
        /* Just return as we will be redirected to login page */
        return;
    }

    headers['User-Agent'] = 'Contrail-WebClient';
    doGlanceOpCb(reqUrl, tenantId, req, glanceApi.get, stopRetry,
                function(err, tokenObj) {
        if ((err) || (null == tokenObj) || (null == tokenObj.id)) {
            callback(err, null);
        } else {
            headers['X-Auth-Token'] = tokenObj.id;
		    glanceAPIServer.api.get(reqUrl, function(err, data) {
                if (err) {
                    /* Just retry in case of if it fails, it may happen that failure is
                     * due to token change, so give one more change
                     */
                    if (stopRetry) {
		                callback(err, data);
                    } else {
                        glanceApi.get(reqUrl, req, callback, true);
                    }
                 } else {
                    callback(err, data);
                 }
		    }, headers);
        }
    });
}

var imageListVerList = ['v1'];

var imageListCB = {
    'v1': getImageListV1
};

function getImageListV1 (err, data, callback)
{
    callback(err, data);
}

function parseImageListByAPIVersion (err, data, apiVer, callback)
{
    if (null != err) {
        imgListCB(err, data, callback);
        return;
    }
    var imgListCB = imageListCB[apiVer];
    if (null == imgListCB) {
        var str = 'Glance API Version <' + apiVer + '>' +
            ' not supported';
        var error = appErrors.RESTServerError(str);
        callback(error, null);
        return;
    }
    imgListCB(err, data, callback);
}

function glanceApiGetByAPIVersionList (reqUrlPrefix, apiVerList, req, startIndex,
                                       callback)
{
    var apiVer = plugins.getApiVersion(imageListVerList, apiVerList, startIndex);
    if (null == apiVer) {
        var err = new appErrors.RESTServerError('apiVersion <' +
                                                apiVerList.join(',') + '> for' +
                                                ' Glance is unsupported');
        callback(err, null, null);
        return;
    }
    var reqUrl = '/' + apiVer['version'] + reqUrlPrefix;
    glanceApi.get(reqUrl, req, function(err, data) {
        if ((null != err) || (null == data)) {
            glanceApiGetByAPIVersionList(reqUrlPrefix, apiVerList, req,
                                         startIndex + 1, callback);
        } else {
            callback(null, data, apiVerList[startIndex]);
        }
    });
}

function getImageList (req, callback)
{
    plugins.getServiceAPIVersionByReqObj(req,
                                         global.SERVICE_ENDPT_TYPE_IMAGE,
                                         function(apiVer) {
        if (null == apiVer) {
            var error =
                new appErrors.RESTServerError('apiVersion for Glance is NULL');
            callback(error, null);
            return;
        }

        var glanceImagesURL = '/images';
        var startIndex = 0;
        glanceApiGetByAPIVersionList(glanceImagesURL, apiVer, req, startIndex,
                                     function(err, data, ver) {
            parseImageListByAPIVersion(err, data, ver, callback);
        });
    });
}

exports.getImageList = getImageList;

<commit_msg>1. Adding v2 as supported glance API version. 2. In error case handle with common error message.<commit_after>/*
 * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
 */

var rest = require('../../../common/rest.api'),
    config = require('../../../../../config/config.global.js'),
    authApi = require('../../../common/auth.api'),
    plugins = require('../plugins.api'),
    appErrors = require('../../../errors/app.errors'),
    commonUtils = require('../../../utils/common.utils')
    ;
var glanceAPIServer;

glanceApi = module.exports;

var imgMgrIp = ((config.imageManager) && (config.imageManager.ip)) ?
    config.imageManager.ip : global.DFLT_SERVER_IP;
var imgMgrPort = ((config.imageManager) && (config.imageManager.port)) ?
    config.imageManager.port : '9292';

glanceAPIServer = rest.getAPIServer({apiName:global.label.IDENTITY_SERVER,
                                      server:imgMgrIp, port:imgMgrPort});
function getTenantIdByReqCookie (req)
{
    if (req.cookies && req.cookies.project) {
        return req.cookies.project;
    } else {
        var ajaxCall = req.headers['x-requested-with'];
        if (ajaxCall == 'XMLHttpRequest') {
           req.res.setHeader('X-Redirect-Url','/logout');
           req.res.send(307,'');
        } else {
           req.res.redirect('/logout');
        }
        return null;
    }
}

/* Function: doGlanceOpCb
 */
function doGlanceOpCb (reqUrl, tenantId, req, glanceCallback, stopRetry,
                       callback)
{
    var forceAuth = stopRetry;

    authApi.getTokenObj(req, tenantId, forceAuth, function(err, tokenObj) {
        if ((err) || (null == tokenObj) || (null == tokenObj.id)) {
            if (stopRetry) {
                console.log("We are done retrying for tenantId:" + tenantId +
                            " with err:" + err);
                commonUtils.redirectToLogout(req, req.res);
                callback(err, null);
            } else {
                /* Retry once again */
                console.log("We are about to retry for tenantId:" + tenantId);
                glanceCallback(reqUrl, req, callback, true);
            }
        } else {
            console.log("doGlanceOpCb() success with tenantId:" + tenantId);
            callback(err, tokenObj);
        }
    });
}

/* Wrapper function to GET Data from Glance-Server */
glanceApi.get = function(reqUrl, req, callback, stopRetry) {
    var headers = {};
    var forceAuth = stopRetry;
    var tenantId = getTenantIdByReqCookie(req);
    if (null == tenantId) {
        /* Just return as we will be redirected to login page */
        return;
    }

    headers['User-Agent'] = 'Contrail-WebClient';
    doGlanceOpCb(reqUrl, tenantId, req, glanceApi.get, stopRetry,
                function(err, tokenObj) {
        if ((err) || (null == tokenObj) || (null == tokenObj.id)) {
            callback(err, null);
        } else {
            headers['X-Auth-Token'] = tokenObj.id;
		    glanceAPIServer.api.get(reqUrl, function(err, data) {
                if (err) {
                    /* Just retry in case of if it fails, it may happen that failure is
                     * due to token change, so give one more change
                     */
                    if (stopRetry) {
		                callback(err, data);
                    } else {
                        glanceApi.get(reqUrl, req, callback, true);
                    }
                 } else {
                    callback(err, data);
                 }
		    }, headers);
        }
    });
}

var imageListVerList = ['v1', 'v2'];

var imageListCB = {
    'v1': getImageListV1,
    'v2': getImageListV1
};

function getImageListV1 (err, data, callback)
{
    callback(err, data);
}

function parseImageListByAPIVersion (err, data, apiVer, callback)
{
    var imgListCB = imageListCB[apiVer];
    if ((null == imgListCB) || (null != err)) {
        var str = 'Glance API Version <' + apiVer + '>' +
            ' not supported';
        var error = new appErrors.RESTServerError(str);
        callback(error, null);
        return;
    }
    imgListCB(err, data, callback);
}

function glanceApiGetByAPIVersionList (reqUrlPrefix, apiVerList, req, startIndex,
                                       callback)
{
    var apiVer = plugins.getApiVersion(imageListVerList, apiVerList, startIndex);
    if (null == apiVer) {
        var err = new appErrors.RESTServerError('apiVersion <' +
                                                apiVerList.join(',') + '> for' +
                                                ' Glance is unsupported');
        callback(err, null, null);
        return;
    }
    var reqUrl = '/' + apiVer['version'] + reqUrlPrefix;
    glanceApi.get(reqUrl, req, function(err, data) {
        if ((null != err) || (null == data)) {
            glanceApiGetByAPIVersionList(reqUrlPrefix, apiVerList, req,
                                         startIndex + 1, callback);
        } else {
            callback(null, data, apiVerList[startIndex]);
        }
    });
}

function getImageList (req, callback)
{
    plugins.getServiceAPIVersionByReqObj(req,
                                         global.SERVICE_ENDPT_TYPE_IMAGE,
                                         function(apiVer) {
        if (null == apiVer) {
            var error =
                new appErrors.RESTServerError('apiVersion for Glance is NULL');
            callback(error, null);
            return;
        }

        var glanceImagesURL = '/images';
        var startIndex = 0;
        glanceApiGetByAPIVersionList(glanceImagesURL, apiVer, req, startIndex,
                                     function(err, data, ver) {
            parseImageListByAPIVersion(err, data, ver, callback);
        });
    });
}

exports.getImageList = getImageList;

<|endoftext|>


<commit_before>var system = require('system');
var webPage = require('webpage');
var page = webPage.create();

page.customHeaders = {
    'User-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.5',
    'Referer': 'http://www.google.com',
};

debug_messages = ''

page.onConsoleMessage = function (msg) {debug_messages += '\n' + msg}
page.onError = function () {}
page.onAlert = function () {}

setTimeout(function () {
    console.log('Error: Timeout reached')
    phantom.exit()
}, 30000)

page.open(system.args[1], function (status) {
    setTimeout(function () {
        page.evaluate(function () {
            (function () {
                if (document.body == null) {
                    body = document.createElement("body");
                    document.body = body;
                }

                // Remove extra elements
                var els = document.querySelectorAll('meta,style,script,noscript,iframe,link,object')
                for (var i = 0; i < els.length; i++) {
                    els[i].parentNode.removeChild(els[i])
                }

                document.body.innerHTML = grabArticle().innerHTML;
            })()

            function grabArticle() {
                var allParagraphs = document.getElementsByTagName("p");
                var topDivCount = 0;
                var topDiv = null;
                var topDivParas;

                // Replace all doubled-up
 tags with
 tags, and remove fonts.
                var pattern =  new RegExp ("
[ \r\n\s]*
", "g");
                document.body.innerHTML = document.body.innerHTML.replace(pattern, "

").replace(/<\/?font[^>]*>/g, '');

                // Study all the paragraphs and find the chunk that has the best score.
                // A score is determined by things like: Number of
's, commas, special classes, etc.
                for (var j=0; j	< allParagraphs.length; j++) {
                    parentNode = allParagraphs[j].parentNode;

                    // Initialize readability data
                    if(typeof parentNode.readability == 'undefined') {
                        parentNode.readability = {"contentScore": 0};
                    }

                    parentNode.readability.contentScore += getMetaScore(parentNode);

                    // Add a point for the paragraph found
                    if(allParagraphs[j].textContent.length > 10) {
                        parentNode.readability.contentScore++;
                    }

                    // Add points for any commas within this paragraph
                    parentNode.readability.contentScore += getCharCount(allParagraphs[j]);
                }

                // Assignment from index for performance. See http://www.peachpit.com/articles/article.aspx?p=31567&seqNum=5
                for(nodeIndex = 0; (node = document.getElementsByTagName('*')[nodeIndex]); nodeIndex++) {
                    if(typeof node.readability != 'undefined' && (topDiv == null || node.readability.contentScore > topDiv.readability.contentScore)) {
                        topDiv = node;
                    }
                }

                if(topDiv == null) {
                  topDiv = document.createElement('div');
                }

                topDiv = removeExtraElements(topDiv);
                topDiv = combineBreaks(topDiv);

                topDiv = clean(topDiv, "form,h1,h2");
                topDiv = clean(topDiv, "table", 250);

                // Remove most attributes
                for(nodeIndex = 0; (node = document.getElementsByTagName('*')[nodeIndex]); nodeIndex++) {
                    for (var i = node.attributes.length - 1; i >= 0; i--) {
                        if (['href','src'].indexOf(node.attributes[i].name.toLowerCase()) < 0) {
                            node.removeAttributeNode(node.attributes[i]);
                        }
                    }
                }

                return topDiv;
            }

            function getMetaScore( e ) {
                var score = 0

                // Returns score based on element meta data (tag name, classes, and id) rather than actual content
                nodeProperties = e.tagName

                for (var i = 0; i < e.attributes.length; i++) {
                    nodeProperties += ' ' + e.attributes[i].name
                    nodeProperties += ' ' + e.attributes[i].value
                }

                // Look for a special classes, ids, and tag names
                if(nodeProperties.match(/(^|\s)(comment|meta|footer|footnote|ad|share|hidden|figure|caption)(\s|$)/i)) {
                    score -= 50;
                } else if(nodeProperties.match(/((^|\s)(post|hentry|entry[-]?(content|text|body)?|article[-]?(content|text|body)?)(\s|$))/i)) {
                    score += 25;
                }

                return score
            }

            // Get character count
            function getCharCount ( e,s ) {
                s = s || ",";
                return e.textContent.split(s).length;
            }

            function removeExtraElements ( e ) {
                var divsList = e.querySelectorAll("*:not(p)");
                var curDivLength = divsList.length;

                // Gather counts for other typical elements embedded within.
                // Traverse backwards so we can remove nodes at the same time without effecting the traversal.
                for (var i=curDivLength-1; i >= 0; i--) {
                    var p = divsList[i].getElementsByTagName("p").length;
                    var img = divsList[i].getElementsByTagName("img").length;
                    var li = divsList[i].getElementsByTagName("li").length;
                    var a = divsList[i].getElementsByTagName("a").length;
                    var embed = divsList[i].getElementsByTagName("embed").length;

                    // If the number of commas is less than 10 (bad sign) ...
                    if ( getCharCount(divsList[i]) < 10) {
                        // And the number of non-paragraph elements is more than paragraphs
                        // or other ominous signs :

                        if ( img > p || li > p || a > p || p == 0 || embed > 0 || getMetaScore(divsList[i]) < 0) {
                            divsList[i].parentNode.removeChild(divsList[i]);
                        }
                    }
                }
                return e;
            }

            function combineBreaks ( e ) {
                e.innerHTML = e.innerHTML.replace(/(
(\s| ?)*){1,}/g,'
');
                return e;
            }

            function clean(e, selector, minWords) {
                var targetList = e.querySelectorAll( selector );
                minWords = minWords || 1000000;

                for (var y=0; y < targetList.length; y++) {
                    // If the text content isn't laden with words, remove the child:
                    if (getCharCount(targetList[y], " ") < minWords) {
                        targetList[y].parentNode.removeChild(targetList[y]);
                    }
                }
                return e;
            }
        })

        function cleanText(text) {
            text = text.replace(//g, "")
            text = text.replace(/[\t ]+/g, " ")
            text = text.replace(/\n /g, "\n")
            text = text.replace(/\n\n+/g, "\n\n")
            return text
        }

        console.log(JSON.stringify({
            'title':cleanText(page.title),
            'text':cleanText(page.plainText),
            'html':cleanText(page.content),
            'debug_messages':debug_messages,
        }))
        phantom.exit();
    }, 5000)
});
<commit_msg>Decreased default timeout to 10 seconds<commit_after>var system = require('system');
var webPage = require('webpage');
var page = webPage.create();

page.customHeaders = {
    'User-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.5',
    'Referer': 'http://www.google.com',
};

debug_messages = ''

page.onConsoleMessage = function (msg) {debug_messages += '\n' + msg}
page.onError = function () {}
page.onAlert = function () {}

setTimeout(function () {
    console.log('Error: Timeout reached')
    phantom.exit()
}, 10000)

page.open(system.args[1], function (status) {
    setTimeout(function () {
        page.evaluate(function () {
            (function () {
                if (document.body == null) {
                    body = document.createElement("body");
                    document.body = body;
                }

                // Remove extra elements
                var els = document.querySelectorAll('meta,style,script,noscript,iframe,link,object')
                for (var i = 0; i < els.length; i++) {
                    els[i].parentNode.removeChild(els[i])
                }

                document.body.innerHTML = grabArticle().innerHTML;
            })()

            function grabArticle() {
                var allParagraphs = document.getElementsByTagName("p");
                var topDivCount = 0;
                var topDiv = null;
                var topDivParas;

                // Replace all doubled-up
 tags with
 tags, and remove fonts.
                var pattern =  new RegExp ("
[ \r\n\s]*
", "g");
                document.body.innerHTML = document.body.innerHTML.replace(pattern, "

").replace(/<\/?font[^>]*>/g, '');

                // Study all the paragraphs and find the chunk that has the best score.
                // A score is determined by things like: Number of
's, commas, special classes, etc.
                for (var j=0; j	< allParagraphs.length; j++) {
                    parentNode = allParagraphs[j].parentNode;

                    // Initialize readability data
                    if(typeof parentNode.readability == 'undefined') {
                        parentNode.readability = {"contentScore": 0};
                    }

                    parentNode.readability.contentScore += getMetaScore(parentNode);

                    // Add a point for the paragraph found
                    if(allParagraphs[j].textContent.length > 10) {
                        parentNode.readability.contentScore++;
                    }

                    // Add points for any commas within this paragraph
                    parentNode.readability.contentScore += getCharCount(allParagraphs[j]);
                }

                // Assignment from index for performance. See http://www.peachpit.com/articles/article.aspx?p=31567&seqNum=5
                for(nodeIndex = 0; (node = document.getElementsByTagName('*')[nodeIndex]); nodeIndex++) {
                    if(typeof node.readability != 'undefined' && (topDiv == null || node.readability.contentScore > topDiv.readability.contentScore)) {
                        topDiv = node;
                    }
                }

                if(topDiv == null) {
                  topDiv = document.createElement('div');
                }

                topDiv = removeExtraElements(topDiv);
                topDiv = combineBreaks(topDiv);

                topDiv = clean(topDiv, "form,h1,h2");
                topDiv = clean(topDiv, "table", 250);

                // Remove most attributes
                for(nodeIndex = 0; (node = document.getElementsByTagName('*')[nodeIndex]); nodeIndex++) {
                    for (var i = node.attributes.length - 1; i >= 0; i--) {
                        if (['href','src'].indexOf(node.attributes[i].name.toLowerCase()) < 0) {
                            node.removeAttributeNode(node.attributes[i]);
                        }
                    }
                }

                return topDiv;
            }

            function getMetaScore( e ) {
                var score = 0

                // Returns score based on element meta data (tag name, classes, and id) rather than actual content
                nodeProperties = e.tagName

                for (var i = 0; i < e.attributes.length; i++) {
                    nodeProperties += ' ' + e.attributes[i].name
                    nodeProperties += ' ' + e.attributes[i].value
                }

                // Look for a special classes, ids, and tag names
                if(nodeProperties.match(/(^|\s)(comment|meta|footer|footnote|ad|share|hidden|figure|caption)(\s|$)/i)) {
                    score -= 50;
                } else if(nodeProperties.match(/((^|\s)(post|hentry|entry[-]?(content|text|body)?|article[-]?(content|text|body)?)(\s|$))/i)) {
                    score += 25;
                }

                return score
            }

            // Get character count
            function getCharCount ( e,s ) {
                s = s || ",";
                return e.textContent.split(s).length;
            }

            function removeExtraElements ( e ) {
                var divsList = e.querySelectorAll("*:not(p)");
                var curDivLength = divsList.length;

                // Gather counts for other typical elements embedded within.
                // Traverse backwards so we can remove nodes at the same time without effecting the traversal.
                for (var i=curDivLength-1; i >= 0; i--) {
                    var p = divsList[i].getElementsByTagName("p").length;
                    var img = divsList[i].getElementsByTagName("img").length;
                    var li = divsList[i].getElementsByTagName("li").length;
                    var a = divsList[i].getElementsByTagName("a").length;
                    var embed = divsList[i].getElementsByTagName("embed").length;

                    // If the number of commas is less than 10 (bad sign) ...
                    if ( getCharCount(divsList[i]) < 10) {
                        // And the number of non-paragraph elements is more than paragraphs
                        // or other ominous signs :

                        if ( img > p || li > p || a > p || p == 0 || embed > 0 || getMetaScore(divsList[i]) < 0) {
                            divsList[i].parentNode.removeChild(divsList[i]);
                        }
                    }
                }
                return e;
            }

            function combineBreaks ( e ) {
                e.innerHTML = e.innerHTML.replace(/(
(\s| ?)*){1,}/g,'
');
                return e;
            }

            function clean(e, selector, minWords) {
                var targetList = e.querySelectorAll( selector );
                minWords = minWords || 1000000;

                for (var y=0; y < targetList.length; y++) {
                    // If the text content isn't laden with words, remove the child:
                    if (getCharCount(targetList[y], " ") < minWords) {
                        targetList[y].parentNode.removeChild(targetList[y]);
                    }
                }
                return e;
            }
        })

        function cleanText(text) {
            text = text.replace(//g, "")
            text = text.replace(/[\t ]+/g, " ")
            text = text.replace(/\n /g, "\n")
            text = text.replace(/\n\n+/g, "\n\n")
            return text
        }

        console.log(JSON.stringify({
            'title':cleanText(page.title),
            'text':cleanText(page.plainText),
            'html':cleanText(page.content),
            'debug_messages':debug_messages,
        }))
        phantom.exit();
    }, 5000)
});
<|endoftext|>


<commit_before>module.exports = {
  config: {
    // default font size in pixels for all tabs
    fontSize: 14,

    // font family with optional fallbacks
    fontFamily: '"DejaVu Sans Mono", "Lucida Console", monospace',

    // terminal cursor background color and opacity (hex, rgb, hsl, hsv, hwb or cmyk)
    cursorColor: 'rgba(248,28,229,0.8)',

    // `BEAM` for |, `UNDERLINE` for _, `BLOCK` for █
    cursorShape: 'UNDERLINE',

    // color of the text
    foregroundColor: '#fff',

    // terminal background color
    backgroundColor: '#000',

    // border color (window, tabs)
    borderColor: '#333',

    // custom css to embed in the main window
    css: '',

    // custom css to embed in the terminal window
    termCSS: '',

    // custom padding (css format, i.e.: `top right bottom left`)
    padding: '12px 14px',

    // the full list. if you're going to provide the full color palette,
    // including the 6 x 6 color cubes and the grayscale map, just provide
    // an array here instead of a color map object
    colors: {
      black: '#000000',
      red: '#ff0000',
      green: '#33ff00',
      yellow: '#ffff00',
      blue: '#0066ff',
      magenta: '#cc00ff',
      cyan: '#00ffff',
      white: '#d0d0d0',
      lightBlack: '#808080',
      lightRed: '#ff0000',
      lightGreen: '#33ff00',
      lightYellow: '#ffff00',
      lightBlue: '#0066ff',
      lightMagenta: '#cc00ff',
      lightCyan: '#00ffff',
      lightWhite: '#ffffff'
    },

    // the shell to run when spawning a new session (i.e. /usr/local/bin/fish)
    // if left empty, your system's login shell will be used by default
    shell: '',

    // for setting shell arguments (i.e. for using interactive shellArgs: ['-i'])
    // by default ['--login'] will be used
    shellArgs: ['--login'],

    // for environment variables
    env: {},

    // set to false for no bell
    bell: 'SOUND',

    // if true, selected text will automatically be copied to the clipboard
    copyOnSelect: true

    // URL to custom bell
    // bellSoundURL: 'http://example.com/bell.mp3',

    // for advanced config flags please refer to https://hyper.is/#cfg
  },

  // a list of plugins to fetch and install from npm
  // format: [@org/]project[#version]
  // examples:
  //   `hyperpower`
  //   `@company/project`
  //   `project#1.0.1`
  plugins: [
      'hyper-solarized-dark',
  ],

  // in development, you can create a directory under
  // `~/.hyper_plugins/local/` and include it here
  // to load it and avoid it being `npm install`ed
  localPlugins: []
};
<commit_msg>fix fontfamily line<commit_after>module.exports = {
  config: {
    // default font size in pixels for all tabs
    fontSize: 14,

    // font family with optional fallbacks
    fontFamily: '"DejaVu Sans Mono For Powerline", "DejaVu Sans Mono", "Lucida Console", monospace',

    // terminal cursor background color and opacity (hex, rgb, hsl, hsv, hwb or cmyk)
    cursorColor: 'rgba(248,28,229,0.8)',

    // `BEAM` for |, `UNDERLINE` for _, `BLOCK` for █
    cursorShape: 'UNDERLINE',

    // color of the text
    foregroundColor: '#fff',

    // terminal background color
    backgroundColor: '#000',

    // border color (window, tabs)
    borderColor: '#333',

    // custom css to embed in the main window
    css: '',

    // custom css to embed in the terminal window
    termCSS: '',

    // custom padding (css format, i.e.: `top right bottom left`)
    padding: '12px 14px',

    // the full list. if you're going to provide the full color palette,
    // including the 6 x 6 color cubes and the grayscale map, just provide
    // an array here instead of a color map object
    colors: {
      black: '#000000',
      red: '#ff0000',
      green: '#33ff00',
      yellow: '#ffff00',
      blue: '#0066ff',
      magenta: '#cc00ff',
      cyan: '#00ffff',
      white: '#d0d0d0',
      lightBlack: '#808080',
      lightRed: '#ff0000',
      lightGreen: '#33ff00',
      lightYellow: '#ffff00',
      lightBlue: '#0066ff',
      lightMagenta: '#cc00ff',
      lightCyan: '#00ffff',
      lightWhite: '#ffffff'
    },

    // the shell to run when spawning a new session (i.e. /usr/local/bin/fish)
    // if left empty, your system's login shell will be used by default
    shell: '',

    // for setting shell arguments (i.e. for using interactive shellArgs: ['-i'])
    // by default ['--login'] will be used
    shellArgs: ['--login'],

    // for environment variables
    env: {},

    // set to false for no bell
    bell: 'SOUND',

    // if true, selected text will automatically be copied to the clipboard
    copyOnSelect: true

    // URL to custom bell
    // bellSoundURL: 'http://example.com/bell.mp3',

    // for advanced config flags please refer to https://hyper.is/#cfg
  },

  // a list of plugins to fetch and install from npm
  // format: [@org/]project[#version]
  // examples:
  //   `hyperpower`
  //   `@company/project`
  //   `project#1.0.1`
  plugins: [
      'hyper-solarized-dark',
  ],

  // in development, you can create a directory under
  // `~/.hyper_plugins/local/` and include it here
  // to load it and avoid it being `npm install`ed
  localPlugins: []
};
<|endoftext|>


<commit_before>var fs = require("fs");
var twitterPkg = require("twitter");
var express = require('express');
var hexu = require("hexu");
var request = require("request");
var Spark = require("sparkai");
var app = express();

var config = JSON.parse(fs.readFileSync("./config.json"));

var data = JSON.parse(fs.readFileSync("./data/data.json"));

var Twitter = new twitterPkg(config);

var opts = {
  min: 2,
  max: 3
}

var generator = new Spark.generator(opts);

generator.train(data);

var makePost = function() {
  var post = generator.generate();
  if(post.split(" ").length > 7) {
    makePost();
  } else {
    Twitter.post('statuses/update', {status: post},  function(error, tweet, response){
      if(error){
        console.log(hexu.red(JSON.stringify(error)));
      }
      console.log(hexu.green("📢  Tweeted: " + post));
    });
  }
}

// Routes
app.get("/", function(req, res) {
  res.header('Content-Type', 'application/json');
  res.end(JSON.stringify(require("./data/data.js").quotes));
});

app.get("/new", function(req, res) {
  makePost();
  console.log(hexu.green("GET '/new', making new post..."));
})

app.listen(process.env.OPENSHIFT_NODEJS_PORT || 3000, process.env.OPENSHIFT_NODEJS_IP || "localhost");
console.log(hexu.blue("======= ✨ Ice is Awake ✨ ======="))

makePost();
setInterval(makePost, 1000 * 60 * 20);
<commit_msg>semi colon<commit_after>var fs = require("fs");
var twitterPkg = require("twitter");
var express = require('express');
var hexu = require("hexu");
var request = require("request");
var Spark = require("sparkai");
var app = express();

var config = JSON.parse(fs.readFileSync("./config.json"));

var data = JSON.parse(fs.readFileSync("./data/data.json"));

var Twitter = new twitterPkg(config);

var opts = {
  min: 2,
  max: 3
}

var generator = new Spark.generator(opts);

generator.train(data);

var makePost = function() {
  var post = generator.generate();
  if(post.split(" ").length > 7) {
    makePost();
  } else {
    Twitter.post('statuses/update', {status: post},  function(error, tweet, response){
      if(error){
        console.log(hexu.red(JSON.stringify(error)));
      }
      console.log(hexu.green("📢  Tweeted: " + post));
    });
  }
}

// Routes
app.get("/", function(req, res) {
  res.header('Content-Type', 'application/json');
  res.end(JSON.stringify(require("./data/data.js").quotes));
});

app.get("/new", function(req, res) {
  makePost();
  console.log(hexu.green("GET '/new', making new post..."));
})

app.listen(process.env.OPENSHIFT_NODEJS_PORT || 3000, process.env.OPENSHIFT_NODEJS_IP || "localhost");
console.log(hexu.blue("======= ✨ Ice is Awake ✨ ======="));

makePost();
setInterval(makePost, 1000 * 60 * 20);
<|endoftext|>


<commit_before>(function(root) {
    'use strict';

    /**
    * Represents a Stats in the game map
    * @class Stats
    * @constructor
    * @param {Object} game - Game instance this obj is attached to.
    * @param {String} type - Type of Stats. When created this object is merged with the value of Stats.Types[type].
    * @param {Number} x - The map Stats coordinate position of this Stats on the x axis.
    * @param {Number} y - The map Stats coordinate position of this Stats on the y axis.
    */
    var Stats = function Stats(entity, type, x, y) {
        this.game = game;
        this.modifierLists = [];

    };

    Stats.prototype = {
        constructor: Stats,

        /**
        * Game instance this obj is attached to.
        *
        * @property game
        * @type Game
        */
        game: null,

        data: null,

        modifierLists: null,

        addModifierList: function(modifierList){
            var default = {
                id: null,
                stat: null,
                value: null,
                source: null,
            };
        },
        removeModifier: function(){

        },
        reset: function(){

            for(var key in Stats.Types){
                var stat = Stats.Types[key];
                this.data[key] = stat.default;
            }

        }
    };

    /**
    * Describes different types of Statss. Used by the Stats constructor 'type' param.
    *
    *     Stats.Types = {
    *         floor: {
    *            name: 'Floor',
    *            char: '.',
    *            color: '#333',
    *            bgColor: '#111',
    *            passable: true,
    *            blocksLos: false
    *         },
    *         // ...
    *     }
    *
    * @class Stats.Types
    * @statsic
    */
    Stats.Types = {
        hp: {
            name: 'HP',
            modifiable: false,
            default: 1,
        },
        hp_max: {
            name: 'HP Max',
            modifiable: true,
            default: 1
        },

    };

    root.RL.Stats = Stats;

}(this));
<commit_msg>removed incomplete stats.js<commit_after><|endoftext|>