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

/** @class

  Deals with an array of attributes and maintains univariate (categorical or numeric) statistics
 for them.

 @extends SC.Object
 */
DG.AttributeStats = SC.Object.extend(
  /** @scope DG.AttributeStats.prototype */ {

    /**
     * The attributes for this slot
     * @property {Array of DG.AttributeModel}
     */
    attributes: null,

    /**
     * A cache of computed univariate statistics
     * @property {DG.UnivariateStats}
     */
    numericStats:null,

    /**
     * A cache of computed categorical statistics
     * @property {DG.CategoricalStats}
     */
    categoricalStats:null,

    /**
     * @property {Array of DG.Case} Passed in through invalidateCaches
     */
    _cases:null,

    /**
     * @property {Boolean}
     */
    _numericCacheIsValid:null,

    /**
     * @property {Boolean}
     */
    _categoricalCacheIsValid:null,

    /**
     * Only gets a value if 'attributeType' is set rather than computed.
     * @property {DG.Analysis.EAttributeType}
     */
    _attributeType:DG.Analysis.EAttributeType.eNone,

    /**
     * Initialize those members that require it.
     */
    init:function () {
      sc_super();
      this._cases = [];
      this.attributes = [];
      this.numericStats = DG.UnivariateStats.create();
      this._numericCacheIsValid = true; // because there is nothing to compute

      this.categoricalStats = DG.CategoricalStats.create();
      this._categoricalCacheIsValid = true; // because there is nothing to compute
    },

    attributeDidChange:function () {
      var tAttributes = this.get('attributes'),
          tFirstAttr = (tAttributes.length > 0) ? tAttributes[0] : null,
          tType = SC.none(tFirstAttr) ? null : tFirstAttr.get('type');
      switch( tType) {
        case 'numeric':
          tType = DG.Analysis.EAttributeType.eNumeric;
          break;
        case 'categorical':
          tType = DG.Analysis.EAttributeType.eCategorical;
          break;
        default:
          tType = null;
      }
      this.invalidateCaches();
      this.set( 'attributeType', tType );
    }.observes( 'attributes' ),

    /**
     *
     * @param iCases {Array} of DG.Case
     */
    invalidateCaches:function ( iCases, iChange ) {

      function isBetterMin( n1, n2) {
        return SC.none( n2) || (n1 < n2);
      }

      function isBetterMax( n1, n2) {
        return SC.none( n2) || (n1 > n2);
      }

      var
        processOneNumeric = function( iCase, iVarID) {
          var tInfo = {}, tValue = iCase.getNumValue( iVarID, tInfo);
          if( isFinite( tValue)) {
            this.numericStats.incrementProperty( 'count' );
            this.numericStats.set('sum', this.numericStats.sum + tValue);
            if( isBetterMin( tValue, this.numericStats.rangeMin))
              this.numericStats.set('rangeMin', tValue);
            if( isBetterMax( tValue, this.numericStats.rangeMax))
              this.numericStats.set('rangeMax', tValue);
            if( tValue > 0 ) {
              if( isBetterMin( tValue, this.numericStats.positiveMin))
                this.numericStats.set('positiveMin', tValue);
              if( isBetterMax( tValue, this.numericStats.positiveMax))
                this.numericStats.set('positiveMax', tValue);
            }
            this.numericStats.setIfChanged('squaredDeviations', null);  // We can't compute this without iteration
          }
          else if( tInfo.isNominal && !isNaN( tValue)) {
            this.numericStats.setIfChanged('attributeType',
                DG.ColorUtilities.isColorSpecString( tValue) ? DG.Analysis.EAttributeType.eColor :
                  DG.Analysis.EAttributeType.eCategorical);
          }
        }.bind( this ),

        processOneCategorical = function( iCase, iVarID) {
          var tValue = iCase.getStrValue( iVarID);
          if( !SC.empty( tValue)) {
            var tCellMap = this.getPath('categoricalStats.cellMap' );
            if( SC.none( tCellMap[ tValue] ) )
              tCellMap[ tValue] = [];
            tCellMap[ tValue].push( iCase );
            this.categoricalStats.incrementProperty( 'count' );
            this.setPath( 'categoricalStats.cellMap', tCellMap ); // Replace with notifyPropertyChange?
          }
        }.bind(this);

      this._cases = iCases || this._cases; // Do this first so subsequently computed stats will use the right cases
      if( iChange &&
          ((iChange.operation === 'createCase') || (iChange.operation === 'createCases'))) {

        var tCaseIDs = iChange.result.caseIDs || [ iChange.result.caseID ],
            tVarID = this.getPath('attribute.id'),
            tType = this.get('attributeType'),
            tAttributes = this.get('attributes' ),
            shouldProcessNumeric = this._numericCacheIsValid,
            shouldProcessCategorical = this._categoricalCacheIsValid &&
                                      (tType === DG.Analysis.EAttributeType.eCategorical);

        if( shouldProcessNumeric)
          this.numericStats.beginPropertyChanges();
        if( shouldProcessCategorical)
          this.categoricalStats.beginPropertyChanges();
        tCaseIDs.forEach( function( iCaseID) {
                            var tCase = DG.store.find( DG.Case, iCaseID);
                            if( tCase) {
                              tAttributes.forEach( function( iAttribute) {
                                tVarID = iAttribute.get( 'id' );
                                if( shouldProcessNumeric) {
                                  processOneNumeric( tCase, tVarID);
                                }
                                if( shouldProcessCategorical)
                                  processOneCategorical( tCase, tVarID);
                                else
                                  this.setIfChanged('_categoricalCacheIsValid', false);
                              }.bind(this));
                            }
                          }.bind( this));
        if( shouldProcessNumeric)
          this.numericStats.endPropertyChanges();
        if( shouldProcessCategorical)
          this.categoricalStats.endPropertyChanges();
        return;
      }

      // We're currently required to use set here so that dependents will hear about change
      this.setIfChanged( '_numericCacheIsValid', false );
      this.setIfChanged( '_categoricalCacheIsValid', false );
    },

    /**
     @property{{min:{Number}, max:{Number} isDataInteger:{Boolean}}}
     */
    minMax:function () {
      if( !this._numericCacheIsValid )
        this._computeNumericStats();
      var tRange = this.numericStats.get( 'numericRange' );
      return { min:tRange.min,
              max:tRange.max,
              isDataInteger:this.numericStats.get( 'dataIsInteger' ) };
    }.property(),

    /**
     It is possible to set this property, thus implying that the attributes
     are to be treated one way or another.
     @property{DG.Analysis.EAttributeType} True if all values are numbers or blank
     */
    attributeType:function ( iKey, iValue ) {
      if( iValue !== undefined )
        this._attributeType = iValue;
      if( !SC.none( this._attributeType ) )
        return this._attributeType;

      var tAttributes = this.get('attributes');

      // We don't have a value stored, so we compute the answer
      if( tAttributes.length === 0 )
      {
        this._attributeType = DG.Analysis.EAttributeType.eNone;
      }
      else {
        // If our first attribute has a type assigned, we return it
        switch( tAttributes[ 0].get('type')) {
          case 'nominal':
            this._attributeType = DG.Analysis.EAttributeType.eCategorical;
          case 'numeric':
            this._attributeType = DG.Analysis.EAttributeType.eNumeric;
          default:
          // Do nothing
        }
      }

      // If we still haven't got a type, determine it from the actual values, if any
      if(SC.none( this._attributeType)) {
        if( !this._numericCacheIsValid )
          this._computeNumericStats();
        this._attributeType = this.getPath( 'numericStats.attributeType' );
      }

      return this._attributeType;
    }.property('attributes'),

    attributeTypeDidChange: function() {
      this.notifyPropertyChange('attributeType');
    }.observes('*numericStats.attributeType'),

    /**
     Run through all attributes and their values and cache computed statistics.
     @private
     */
    _computeNumericStats:function () {
      var tCases = this._cases,
        tAttributes = this.get('attributes' ),
        tCaseCount = 0,
        tAttributeType,
        tDataIsNumeric = true,
        tColorValuesExist = false,
        tMin = Number.POSITIVE_INFINITY,
        tMax = Number.NEGATIVE_INFINITY,
        tPositiveMin = Number.MAX_VALUE,
        tPositiveMax = -Number.MAX_VALUE,
        tSum = 0,
        tSumDiffs = 0,
        tSumSquareDiffs = 0,
        //tDataIsInteger = true,
        tMean,
        tValues = [];

      function addCaseValueToStats( iCaseValue ) {
         var tValue = Number( iCaseValue );
         if( !SC.empty( iCaseValue ) && isFinite( tValue ) ) {
           tCaseCount++;
           if( tValue < tMin ) tMin = tValue;
           if( tValue > tMax ) tMax = tValue;
           tSum += tValue;
           //tDataIsInteger = tDataIsInteger && (Math.floor( tValue ) === tValue);
           tValues.push( tValue );
           if( tValue > 0 ) {
             tPositiveMin = Math.min( tValue, tPositiveMin );
             tPositiveMax = Math.max( tValue, tPositiveMax );
           }
         }
         // Let infinity and NaN through as numbers. And don't let null be treated as categorical
         else if( (typeof iCaseValue !== 'number') && !SC.empty( iCaseValue ) ) {
           tValue = String( iCaseValue );
           tDataIsNumeric = tDataIsNumeric && SC.empty( tValue );
           tColorValuesExist = tColorValuesExist || DG.ColorUtilities.isColorSpecString(tValue);
         }
       }

      this.numericStats.reset();

      this.numericStats.beginPropertyChanges();
        if( SC.isArray( tCases)) {
          tAttributes.forEach( function( iAttribute) {
            var tVarID = iAttribute.get('id');
            tCases.forEach( function ( iCase ) {
              addCaseValueToStats( iCase.getValue( tVarID ) );
            } );
          });
        }

        if( tCaseCount > 0 ) {
          this.numericStats.set( 'count', tCaseCount );
          this.numericStats.set( 'sum', tSum );
          this.numericStats.set( 'rangeMin', tMin );
          this.numericStats.set( 'rangeMax', tMax );
          tMean = tSum / tCaseCount;
          tValues.forEach( function ( iValue ) {
            var tDiff = iValue - tMean;
            tSumDiffs += tDiff;
            tSumSquareDiffs += tDiff * tDiff;
          } );
          // The second term serves as a correction factor for roundoff error.
          // See Numeric Recipes in C, section 14.1 for details.
          tSumSquareDiffs -= tSumDiffs * tSumDiffs / tCaseCount;
          this.numericStats.set( 'squaredDeviations', tSumSquareDiffs );

          if( tPositiveMin <= tPositiveMax ) {
            this.numericStats.set( 'positiveMin', tPositiveMin );
            this.numericStats.set( 'positiveMax', tPositiveMax );
          }
        }
        tAttributeType = tDataIsNumeric ? DG.Analysis.EAttributeType.eNumeric :
            (tColorValuesExist ? DG.Analysis.EAttributeType.eColor :
                DG.Analysis.EAttributeType.eCategorical);
        this.numericStats.set( 'attributeType', tAttributeType );
        this._numericCacheIsValid = true;
      this.numericStats.endPropertyChanges();
    },

    /**
     @property{Number} The number of categorical cells
     */
    numberOfCells:function () {
      if( !this._categoricalCacheIsValid )
        this._computeCategoricalStats();
      return this.getPath( 'categoricalStats.numberOfCells' );
    }.property(),

    numberOfCellsDidChange: function() {
      this.notifyPropertyChange('numberOfCells');
    }.observes('*categoricalStats.numberOfCells'),

    /**
     @property{Number} The number of categorical cells
     */
    numericRange:function () {
      if( !this._numericCacheIsValid)
        this._computeNumericStats();
      return this.getPath( 'numericStats.numericRange' );
    }.property(),

    numericRangeDidChange: function() {
      this.notifyPropertyChange('numericRange');
    }.observes('*numericStats.numericRange'),

    dataDidChange:function () {
      // We only have to deal with categorical stats if we are not numeric
      // Note that for this to work in the long run we're going to have to respond to any change
      //    in whether the attributes are numeric or not.
      if( (this.get( 'attributeType' ) === DG.Analysis.EAttributeType.eCategorical) &&
          !this._categoricalCacheIsValid ) {
        var tOldNumCells = this.categoricalStats.get( 'numberOfCells' ),
          tNewNumCells;
        this._computeCategoricalStats();
        tNewNumCells = this.categoricalStats.get( 'numberOfCells' );
        if( tNewNumCells !== tOldNumCells ) {
          this.notifyPropertyChange( 'numberOfCells' );
        }
      }
    }.observes( '_categoricalCacheIsValid' ),

    /**
     @property{Object} The names of the properties of this object are the cell names
     */
    cellMap:function () {
      if( !this._categoricalCacheIsValid )
        this._computeCategoricalStats();
      return this.categoricalStats.get( 'cellMap' );
    }.property(),
    cellMapDidChange: function() {
      this.notifyPropertyChange('cellMap');
    }.observes('*categoricalStats.cellMap'),

    /**
     @return{Number} corresponding to given name
     */
    cellNameToCellNumber:function ( iCellName ) {
      if( !this._categoricalCacheIsValid )
        this._computeCategoricalStats();
      return this.categoricalStats.cellNameToCellNumber( iCellName );
    },

    /**
     Run through all attribute values and cache categorical stats
     @private
     */
    _computeCategoricalStats:function () {
      var tCases = this._cases,
        tAttributes = this.get('attributes' ),
        tCaseCount = 0,
        tCellMap = {};

      function addCaseValueToStats( iCase, iCaseValue) {
        var tValue = String( iCaseValue );
        // Note that a null iCaseValue becomes "null" under string coercion
        if( !SC.none( iCaseValue ) && !SC.empty( tValue ) ) {
          // consider a DG.CategoricalStats.addCaseValue() method
          if( SC.none( tCellMap[ tValue] ) )
            tCellMap[ tValue] = [];
          tCellMap[ tValue].push( iCase );
          tCaseCount++;
        }
      }

      this.categoricalStats.reset();

      if( SC.isArray( tCases )) {
        tAttributes.forEach( function( iAttribute) {
          // If the attribute has a colormap, use it to predetermine the order of the categories
          var tColorMap = iAttribute.get('colormap');
          if( tColorMap) {
            DG.ObjectMap.forEach( tColorMap, function( iKey) {
              tCellMap[ iKey] = [];
            });
          }

          var tVarID = iAttribute.get('id');
          tCases.forEach( function ( iCase ) {
            addCaseValueToStats( iCase, iCase.getValue( tVarID ));
          } );
          if( iAttribute.get('blockDisplayOfEmptyCategories')) {
            DG.ObjectMap.forEach(tCellMap, function (iKey, iValue) {
              if (iValue.length === 0)
                delete tCellMap[iKey];
            });
          }
        });

        this.categoricalStats.beginPropertyChanges();
        this.categoricalStats.set( 'cellMap', tCellMap );
        this.categoricalStats.set( 'count', tCaseCount );
        this.categoricalStats.endPropertyChanges();
      }
      this._categoricalCacheIsValid = true;
    }

  } );

<commit_msg>[Fixes #126716477] Add missing 'break' statements in a switch statement such that the fall-through was always producing 'numeric'. Now it can return 'categorical'.<commit_after>// ==========================================================================
//                        DG.AttributeStats
//
//  Author:   William Finzer
//
//  Copyright (c) 2014 by The Concord Consortium, Inc. All rights reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// ==========================================================================

/** @class

  Deals with an array of attributes and maintains univariate (categorical or numeric) statistics
 for them.

 @extends SC.Object
 */
DG.AttributeStats = SC.Object.extend(
  /** @scope DG.AttributeStats.prototype */ {

    /**
     * The attributes for this slot
     * @property {Array of DG.AttributeModel}
     */
    attributes: null,

    /**
     * A cache of computed univariate statistics
     * @property {DG.UnivariateStats}
     */
    numericStats:null,

    /**
     * A cache of computed categorical statistics
     * @property {DG.CategoricalStats}
     */
    categoricalStats:null,

    /**
     * @property {Array of DG.Case} Passed in through invalidateCaches
     */
    _cases:null,

    /**
     * @property {Boolean}
     */
    _numericCacheIsValid:null,

    /**
     * @property {Boolean}
     */
    _categoricalCacheIsValid:null,

    /**
     * Only gets a value if 'attributeType' is set rather than computed.
     * @property {DG.Analysis.EAttributeType}
     */
    _attributeType:DG.Analysis.EAttributeType.eNone,

    /**
     * Initialize those members that require it.
     */
    init:function () {
      sc_super();
      this._cases = [];
      this.attributes = [];
      this.numericStats = DG.UnivariateStats.create();
      this._numericCacheIsValid = true; // because there is nothing to compute

      this.categoricalStats = DG.CategoricalStats.create();
      this._categoricalCacheIsValid = true; // because there is nothing to compute
    },

    attributeDidChange:function () {
      var tAttributes = this.get('attributes'),
          tFirstAttr = (tAttributes.length > 0) ? tAttributes[0] : null,
          tType = SC.none(tFirstAttr) ? null : tFirstAttr.get('type');
      switch( tType) {
        case 'numeric':
          tType = DG.Analysis.EAttributeType.eNumeric;
          break;
        case 'categorical':
          tType = DG.Analysis.EAttributeType.eCategorical;
          break;
        default:
          tType = null;
      }
      this.invalidateCaches();
      this.set( 'attributeType', tType );
    }.observes( 'attributes' ),

    /**
     *
     * @param iCases {Array} of DG.Case
     */
    invalidateCaches:function ( iCases, iChange ) {

      function isBetterMin( n1, n2) {
        return SC.none( n2) || (n1 < n2);
      }

      function isBetterMax( n1, n2) {
        return SC.none( n2) || (n1 > n2);
      }

      var
        processOneNumeric = function( iCase, iVarID) {
          var tInfo = {}, tValue = iCase.getNumValue( iVarID, tInfo);
          if( isFinite( tValue)) {
            this.numericStats.incrementProperty( 'count' );
            this.numericStats.set('sum', this.numericStats.sum + tValue);
            if( isBetterMin( tValue, this.numericStats.rangeMin))
              this.numericStats.set('rangeMin', tValue);
            if( isBetterMax( tValue, this.numericStats.rangeMax))
              this.numericStats.set('rangeMax', tValue);
            if( tValue > 0 ) {
              if( isBetterMin( tValue, this.numericStats.positiveMin))
                this.numericStats.set('positiveMin', tValue);
              if( isBetterMax( tValue, this.numericStats.positiveMax))
                this.numericStats.set('positiveMax', tValue);
            }
            this.numericStats.setIfChanged('squaredDeviations', null);  // We can't compute this without iteration
          }
          else if( tInfo.isNominal && !isNaN( tValue)) {
            this.numericStats.setIfChanged('attributeType',
                DG.ColorUtilities.isColorSpecString( tValue) ? DG.Analysis.EAttributeType.eColor :
                  DG.Analysis.EAttributeType.eCategorical);
          }
        }.bind( this ),

        processOneCategorical = function( iCase, iVarID) {
          var tValue = iCase.getStrValue( iVarID);
          if( !SC.empty( tValue)) {
            var tCellMap = this.getPath('categoricalStats.cellMap' );
            if( SC.none( tCellMap[ tValue] ) )
              tCellMap[ tValue] = [];
            tCellMap[ tValue].push( iCase );
            this.categoricalStats.incrementProperty( 'count' );
            this.setPath( 'categoricalStats.cellMap', tCellMap ); // Replace with notifyPropertyChange?
          }
        }.bind(this);

      this._cases = iCases || this._cases; // Do this first so subsequently computed stats will use the right cases
      if( iChange &&
          ((iChange.operation === 'createCase') || (iChange.operation === 'createCases'))) {

        var tCaseIDs = iChange.result.caseIDs || [ iChange.result.caseID ],
            tVarID = this.getPath('attribute.id'),
            tType = this.get('attributeType'),
            tAttributes = this.get('attributes' ),
            shouldProcessNumeric = this._numericCacheIsValid,
            shouldProcessCategorical = this._categoricalCacheIsValid &&
                                      (tType === DG.Analysis.EAttributeType.eCategorical);

        if( shouldProcessNumeric)
          this.numericStats.beginPropertyChanges();
        if( shouldProcessCategorical)
          this.categoricalStats.beginPropertyChanges();
        tCaseIDs.forEach( function( iCaseID) {
                            var tCase = DG.store.find( DG.Case, iCaseID);
                            if( tCase) {
                              tAttributes.forEach( function( iAttribute) {
                                tVarID = iAttribute.get( 'id' );
                                if( shouldProcessNumeric) {
                                  processOneNumeric( tCase, tVarID);
                                }
                                if( shouldProcessCategorical)
                                  processOneCategorical( tCase, tVarID);
                                else
                                  this.setIfChanged('_categoricalCacheIsValid', false);
                              }.bind(this));
                            }
                          }.bind( this));
        if( shouldProcessNumeric)
          this.numericStats.endPropertyChanges();
        if( shouldProcessCategorical)
          this.categoricalStats.endPropertyChanges();
        return;
      }

      // We're currently required to use set here so that dependents will hear about change
      this.setIfChanged( '_numericCacheIsValid', false );
      this.setIfChanged( '_categoricalCacheIsValid', false );
    },

    /**
     @property{{min:{Number}, max:{Number} isDataInteger:{Boolean}}}
     */
    minMax:function () {
      if( !this._numericCacheIsValid )
        this._computeNumericStats();
      var tRange = this.numericStats.get( 'numericRange' );
      return { min:tRange.min,
              max:tRange.max,
              isDataInteger:this.numericStats.get( 'dataIsInteger' ) };
    }.property(),

    /**
     It is possible to set this property, thus implying that the attributes
     are to be treated one way or another.
     @property{DG.Analysis.EAttributeType} True if all values are numbers or blank
     */
    attributeType:function ( iKey, iValue ) {
      if( iValue !== undefined )
        this._attributeType = iValue;
      if( !SC.none( this._attributeType ) )
        return this._attributeType;

      var tAttributes = this.get('attributes');

      // We don't have a value stored, so we compute the answer
      if( tAttributes.length === 0 )
      {
        this._attributeType = DG.Analysis.EAttributeType.eNone;
      }
      else {
        // If our first attribute has a type assigned, we return it
        switch( tAttributes[ 0].get('type')) {
          case 'nominal':
            this._attributeType = DG.Analysis.EAttributeType.eCategorical;
            break;
          case 'numeric':
            this._attributeType = DG.Analysis.EAttributeType.eNumeric;
            break;
          default:
          // Do nothing
        }
      }

      // If we still haven't got a type, determine it from the actual values, if any
      if(SC.none( this._attributeType)) {
        if( !this._numericCacheIsValid )
          this._computeNumericStats();
        this._attributeType = this.getPath( 'numericStats.attributeType' );
      }

      return this._attributeType;
    }.property('attributes'),

    attributeTypeDidChange: function() {
      this.notifyPropertyChange('attributeType');
    }.observes('*numericStats.attributeType'),

    /**
     Run through all attributes and their values and cache computed statistics.
     @private
     */
    _computeNumericStats:function () {
      var tCases = this._cases,
        tAttributes = this.get('attributes' ),
        tCaseCount = 0,
        tAttributeType,
        tDataIsNumeric = true,
        tColorValuesExist = false,
        tMin = Number.POSITIVE_INFINITY,
        tMax = Number.NEGATIVE_INFINITY,
        tPositiveMin = Number.MAX_VALUE,
        tPositiveMax = -Number.MAX_VALUE,
        tSum = 0,
        tSumDiffs = 0,
        tSumSquareDiffs = 0,
        //tDataIsInteger = true,
        tMean,
        tValues = [];

      function addCaseValueToStats( iCaseValue ) {
         var tValue = Number( iCaseValue );
         if( !SC.empty( iCaseValue ) && isFinite( tValue ) ) {
           tCaseCount++;
           if( tValue < tMin ) tMin = tValue;
           if( tValue > tMax ) tMax = tValue;
           tSum += tValue;
           //tDataIsInteger = tDataIsInteger && (Math.floor( tValue ) === tValue);
           tValues.push( tValue );
           if( tValue > 0 ) {
             tPositiveMin = Math.min( tValue, tPositiveMin );
             tPositiveMax = Math.max( tValue, tPositiveMax );
           }
         }
         // Let infinity and NaN through as numbers. And don't let null be treated as categorical
         else if( (typeof iCaseValue !== 'number') && !SC.empty( iCaseValue ) ) {
           tValue = String( iCaseValue );
           tDataIsNumeric = tDataIsNumeric && SC.empty( tValue );
           tColorValuesExist = tColorValuesExist || DG.ColorUtilities.isColorSpecString(tValue);
         }
       }

      this.numericStats.reset();

      this.numericStats.beginPropertyChanges();
        if( SC.isArray( tCases)) {
          tAttributes.forEach( function( iAttribute) {
            var tVarID = iAttribute.get('id');
            tCases.forEach( function ( iCase ) {
              addCaseValueToStats( iCase.getValue( tVarID ) );
            } );
          });
        }

        if( tCaseCount > 0 ) {
          this.numericStats.set( 'count', tCaseCount );
          this.numericStats.set( 'sum', tSum );
          this.numericStats.set( 'rangeMin', tMin );
          this.numericStats.set( 'rangeMax', tMax );
          tMean = tSum / tCaseCount;
          tValues.forEach( function ( iValue ) {
            var tDiff = iValue - tMean;
            tSumDiffs += tDiff;
            tSumSquareDiffs += tDiff * tDiff;
          } );
          // The second term serves as a correction factor for roundoff error.
          // See Numeric Recipes in C, section 14.1 for details.
          tSumSquareDiffs -= tSumDiffs * tSumDiffs / tCaseCount;
          this.numericStats.set( 'squaredDeviations', tSumSquareDiffs );

          if( tPositiveMin <= tPositiveMax ) {
            this.numericStats.set( 'positiveMin', tPositiveMin );
            this.numericStats.set( 'positiveMax', tPositiveMax );
          }
        }
        tAttributeType = tDataIsNumeric ? DG.Analysis.EAttributeType.eNumeric :
            (tColorValuesExist ? DG.Analysis.EAttributeType.eColor :
                DG.Analysis.EAttributeType.eCategorical);
        this.numericStats.set( 'attributeType', tAttributeType );
        this._numericCacheIsValid = true;
      this.numericStats.endPropertyChanges();
    },

    /**
     @property{Number} The number of categorical cells
     */
    numberOfCells:function () {
      if( !this._categoricalCacheIsValid )
        this._computeCategoricalStats();
      return this.getPath( 'categoricalStats.numberOfCells' );
    }.property(),

    numberOfCellsDidChange: function() {
      this.notifyPropertyChange('numberOfCells');
    }.observes('*categoricalStats.numberOfCells'),

    /**
     @property{Number} The number of categorical cells
     */
    numericRange:function () {
      if( !this._numericCacheIsValid)
        this._computeNumericStats();
      return this.getPath( 'numericStats.numericRange' );
    }.property(),

    numericRangeDidChange: function() {
      this.notifyPropertyChange('numericRange');
    }.observes('*numericStats.numericRange'),

    dataDidChange:function () {
      // We only have to deal with categorical stats if we are not numeric
      // Note that for this to work in the long run we're going to have to respond to any change
      //    in whether the attributes are numeric or not.
      if( (this.get( 'attributeType' ) === DG.Analysis.EAttributeType.eCategorical) &&
          !this._categoricalCacheIsValid ) {
        var tOldNumCells = this.categoricalStats.get( 'numberOfCells' ),
          tNewNumCells;
        this._computeCategoricalStats();
        tNewNumCells = this.categoricalStats.get( 'numberOfCells' );
        if( tNewNumCells !== tOldNumCells ) {
          this.notifyPropertyChange( 'numberOfCells' );
        }
      }
    }.observes( '_categoricalCacheIsValid' ),

    /**
     @property{Object} The names of the properties of this object are the cell names
     */
    cellMap:function () {
      if( !this._categoricalCacheIsValid )
        this._computeCategoricalStats();
      return this.categoricalStats.get( 'cellMap' );
    }.property(),
    cellMapDidChange: function() {
      this.notifyPropertyChange('cellMap');
    }.observes('*categoricalStats.cellMap'),

    /**
     @return{Number} corresponding to given name
     */
    cellNameToCellNumber:function ( iCellName ) {
      if( !this._categoricalCacheIsValid )
        this._computeCategoricalStats();
      return this.categoricalStats.cellNameToCellNumber( iCellName );
    },

    /**
     Run through all attribute values and cache categorical stats
     @private
     */
    _computeCategoricalStats:function () {
      var tCases = this._cases,
        tAttributes = this.get('attributes' ),
        tCaseCount = 0,
        tCellMap = {};

      function addCaseValueToStats( iCase, iCaseValue) {
        var tValue = String( iCaseValue );
        // Note that a null iCaseValue becomes "null" under string coercion
        if( !SC.none( iCaseValue ) && !SC.empty( tValue ) ) {
          // consider a DG.CategoricalStats.addCaseValue() method
          if( SC.none( tCellMap[ tValue] ) )
            tCellMap[ tValue] = [];
          tCellMap[ tValue].push( iCase );
          tCaseCount++;
        }
      }

      this.categoricalStats.reset();

      if( SC.isArray( tCases )) {
        tAttributes.forEach( function( iAttribute) {
          // If the attribute has a colormap, use it to predetermine the order of the categories
          var tColorMap = iAttribute.get('colormap');
          if( tColorMap) {
            DG.ObjectMap.forEach( tColorMap, function( iKey) {
              tCellMap[ iKey] = [];
            });
          }

          var tVarID = iAttribute.get('id');
          tCases.forEach( function ( iCase ) {
            addCaseValueToStats( iCase, iCase.getValue( tVarID ));
          } );
          if( iAttribute.get('blockDisplayOfEmptyCategories')) {
            DG.ObjectMap.forEach(tCellMap, function (iKey, iValue) {
              if (iValue.length === 0)
                delete tCellMap[iKey];
            });
          }
        });

        this.categoricalStats.beginPropertyChanges();
        this.categoricalStats.set( 'cellMap', tCellMap );
        this.categoricalStats.set( 'count', tCaseCount );
        this.categoricalStats.endPropertyChanges();
      }
      this._categoricalCacheIsValid = true;
    }

  } );

<|endoftext|>


<commit_before>
// When

this.When(/^я введу в текстовое поле "([^"]*)" значение "([^"]*)"$/, function (fieldName, value, next) {
    var haveField = function(){
        return window.testHelpers.getControlByName(fieldName) != undefined;
    }
    var success = function(){
        try {
            window.testHelpers.getControlByName(fieldName).setValue(value);
            next();
        } catch (err) {
            next(err);
        }
    }
    var fail = function(){
        next(new Error(fieldName + ' not found!'));
    }
    window.testHelpers.waitCondition(haveField, success, fail);
});

this.When(/^я введу в числовое поле "([^"]*)" значение "([^"]*)"$/, function (fieldName, value, next) {
    var haveField = function(){
        return window.testHelpers.getControlByName(fieldName) != undefined;
    }
    var success = function(){
        try {
            var numValue = parseInt(value);
            chai.assert.isNumber(numValue);

            window.testHelpers.getControlByName(fieldName).setValue(numValue);

            next();
        } catch (err) {
            next(err);
        }
    }
    var fail = function(){
        next(new Error(fieldName + ' not found!'));
    }
    window.testHelpers.waitCondition(haveField, success, fail);
});

this.When(/^я введу в поле типа дата "([^"]*)" значение Сегодня$/, function (fieldName, next) {
    var haveField = function(){
        return window.testHelpers.getControlByName(fieldName) != undefined;
    }
    var success = function(){
        try {
            var value = window.testHelpers.getCurrentDate();
            window.testHelpers.getControlByName(fieldName).setValue(value);
            next();
        } catch (err) {
            next(err);
        }
    }
    var fail = function(){
        next(new Error(fieldName + ' not found!'));
    }
    window.testHelpers.waitCondition(haveField, success, fail);
});

// Then

this.Then(/^значение в поле "([^"]*)" равно "([^"]*)"$/, function (fieldName, value, next) {
    var haveValue = function () {
        return window.testHelpers.getControlByName(fieldName) != undefined;
    };

    var checkValue = function () {
        try {
            var field = window.testHelpers.getControlByName(fieldName);
            chai.assert.isDefined(field);

            var actValue = field.getText();
            chai.assert.isTrue((actValue == value), actValue + ' != ' + value);

            next();
        } catch (err) {
            next(err);
        }
    };

    var fail = function () {
        next(new Error(fieldName + ' is undefined'));
    };

    window.testHelpers.waitCondition(haveValue, checkValue, fail);
});

this.Then(/^значение в поле типа дата "([^"]*)" равно Сегодня$/, function (fieldName, next) {
    var haveValue = function () {
        return window.testHelpers.getControlByName(fieldName) != undefined;
    };

    var checkValue = function () {
        try {
            var field = window.testHelpers.getControlByName(fieldName);
            chai.assert.isDefined(field);

            var actValue = field.getValue().Date;
            var value = window.testHelpers.getCurrentDate();
            chai.assert.isTrue(actValue == value);

            next();
        } catch (err) {
            next(err);
        }
    };

    var fail = function () {
        next(new Error(fieldName + ' is undefined'));
    };

    window.testHelpers.waitCondition(haveValue, checkValue, fail);
});

this.Then(/^значение в выпадающем списке "([^"]*)" равно "([^"]*)"$/, function (fieldName, value, next) {
    var haveValue = function () {
        return window.testHelpers.getControlByName(fieldName) != undefined;
    };

    var checkValue = function () {
        try {
            var field = window.testHelpers.getControlByName(fieldName);
            chai.assert.isDefined(field);

            var actValue = field.getValue().DisplayName;
            chai.assert.isTrue((actValue == value), actValue + ' != ' + value);

            next();
        } catch (err) {
            next(err);
        }
    };

    var fail = function () {
        next(new Error(fieldName + ' is undefined'));
    };

    window.testHelpers.waitCondition(haveValue, checkValue, fail);
});

this.Then(/^флаг "([^"]*)" будет иметь значение "([^"]*)"$/, function (flagName, value, next) {
    var haveFlag = function(){
        return window.testHelpers.getControlByName(flagName) != undefined;
    }
    var success = function(){
        var flag = window.testHelpers.getControlByName(flagName);

        try{
            chai.assert.isDefined(flag);
            chai.assert.equal(flag.getValue(), JSON.parse(value));
            next();
        }catch(err){
            next(err);
        }
    }
    var fail = function(){
        next(new Error(flagName + ' not found!'));
    }
    window.testHelpers.waitCondition(haveFlag, success, fail);
});

this.When(/^я поменяю значение флага "([^"]*)" на "([^"]*)"$/, function(flagName, value, next){
	var haveFlag = function(){
		return window.testHelpers.getControlByName(flagName) != undefined;
	}
	var success = function(){
		var flag = window.testHelpers.getControlByName(flagName);
		var parseValue = JSON.parse(value);

		if(typeof parseValue == "boolean"){
			flag.setValue(parseValue);
			next();
		}else{
			next(new Error("'" + value + "' is not correct value"));
		}
	}
	var fail = function(){
		next(new Error(flagName + ' not found!'));
	}

	window.testHelpers.waitCondition(haveFlag, success, fail);
});<commit_msg>fix Date<commit_after>
// When

this.When(/^я введу в текстовое поле "([^"]*)" значение "([^"]*)"$/, function (fieldName, value, next) {
    var haveField = function(){
        return window.testHelpers.getControlByName(fieldName) != undefined;
    }
    var success = function(){
        try {
            window.testHelpers.getControlByName(fieldName).setValue(value);
            next();
        } catch (err) {
            next(err);
        }
    }
    var fail = function(){
        next(new Error(fieldName + ' not found!'));
    }
    window.testHelpers.waitCondition(haveField, success, fail);
});

this.When(/^я введу в числовое поле "([^"]*)" значение "([^"]*)"$/, function (fieldName, value, next) {
    var haveField = function(){
        return window.testHelpers.getControlByName(fieldName) != undefined;
    }
    var success = function(){
        try {
            var numValue = parseInt(value);
            chai.assert.isNumber(numValue);

            window.testHelpers.getControlByName(fieldName).setValue(numValue);

            next();
        } catch (err) {
            next(err);
        }
    }
    var fail = function(){
        next(new Error(fieldName + ' not found!'));
    }
    window.testHelpers.waitCondition(haveField, success, fail);
});

this.When(/^я введу в поле типа дата "([^"]*)" значение Сегодня$/, function (fieldName, next) {
    var haveField = function(){
        return window.testHelpers.getControlByName(fieldName) != undefined;
    }
    var success = function(){
        try {
            var value = window.testHelpers.getCurrentDate();
            window.testHelpers.getControlByName(fieldName).setValue(value);
            next();
        } catch (err) {
            next(err);
        }
    }
    var fail = function(){
        next(new Error(fieldName + ' not found!'));
    }
    window.testHelpers.waitCondition(haveField, success, fail);
});

// Then

this.Then(/^значение в поле "([^"]*)" равно "([^"]*)"$/, function (fieldName, value, next) {
    var haveValue = function () {
        return window.testHelpers.getControlByName(fieldName) != undefined;
    };

    var checkValue = function () {
        try {
            var field = window.testHelpers.getControlByName(fieldName);
            chai.assert.isDefined(field);

            var actValue = field.getText();
            chai.assert.isTrue((actValue == value), actValue + ' != ' + value);

            next();
        } catch (err) {
            next(err);
        }
    };

    var fail = function () {
        next(new Error(fieldName + ' is undefined'));
    };

    window.testHelpers.waitCondition(haveValue, checkValue, fail);
});

this.Then(/^значение в поле типа дата "([^"]*)" равно Сегодня$/, function (fieldName, next) {
    var haveValue = function () {
        return window.testHelpers.getControlByName(fieldName) != undefined;
    };

    var checkValue = function () {
        try {
            var field = window.testHelpers.getControlByName(fieldName);
            chai.assert.isDefined(field);

            var actValue = field.getValue();

            if(typeof actValue != "string"){
                actValue = actValue.Date;
            }

            var value = window.testHelpers.getCurrentDate();
            chai.assert.isTrue(actValue == value);

            next();
        } catch (err) {
            next(err);
        }
    };

    var fail = function () {
        next(new Error(fieldName + ' is undefined'));
    };

    window.testHelpers.waitCondition(haveValue, checkValue, fail);
});

this.Then(/^значение в выпадающем списке "([^"]*)" равно "([^"]*)"$/, function (fieldName, value, next) {
    var haveValue = function () {
        return window.testHelpers.getControlByName(fieldName) != undefined;
    };

    var checkValue = function () {
        try {
            var field = window.testHelpers.getControlByName(fieldName);
            chai.assert.isDefined(field);

            var actValue = field.getValue().DisplayName;
            chai.assert.isTrue((actValue == value), actValue + ' != ' + value);

            next();
        } catch (err) {
            next(err);
        }
    };

    var fail = function () {
        next(new Error(fieldName + ' is undefined'));
    };

    window.testHelpers.waitCondition(haveValue, checkValue, fail);
});

this.Then(/^флаг "([^"]*)" будет иметь значение "([^"]*)"$/, function (flagName, value, next) {
    var haveFlag = function(){
        return window.testHelpers.getControlByName(flagName) != undefined;
    }
    var success = function(){
        var flag = window.testHelpers.getControlByName(flagName);

        try{
            chai.assert.isDefined(flag);
            chai.assert.equal(flag.getValue(), JSON.parse(value));
            next();
        }catch(err){
            next(err);
        }
    }
    var fail = function(){
        next(new Error(flagName + ' not found!'));
    }
    window.testHelpers.waitCondition(haveFlag, success, fail);
});

this.When(/^я поменяю значение флага "([^"]*)" на "([^"]*)"$/, function(flagName, value, next){
	var haveFlag = function(){
		return window.testHelpers.getControlByName(flagName) != undefined;
	}
	var success = function(){
		var flag = window.testHelpers.getControlByName(flagName);
		var parseValue = JSON.parse(value);

		if(typeof parseValue == "boolean"){
			flag.setValue(parseValue);
			next();
		}else{
			next(new Error("'" + value + "' is not correct value"));
		}
	}
	var fail = function(){
		next(new Error(flagName + ' not found!'));
	}

	window.testHelpers.waitCondition(haveFlag, success, fail);
});<|endoftext|>


<commit_before>// Avoid `console` errors in browsers that lack a console.
(function() {
    var method;
    var noop = function () {};
    var methods = [
        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
        'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = (window.console = window.console || {});

    while (length--) {
        method = methods[length];

        // Only stub undefined methods.
        if (!console[method]) {
            console[method] = noop;
        }
    }
}());

// Place any jQuery/helper plugins in here.

//@codekit-append "../../../bower_components/cssuseragent/cssua.js"
//@codekit-append "../../../bower_components/ev-emitter/ev-emitter.js"
//@codekit-append "../../../bower_components/imagesloaded/imagesloaded.js"
//@codekit-append "../../../bower_components/jquery-smooth-scroll/jquery.smooth-scroll.js"
//@codekit-append "../../../bower_components/setAnimationFrameTimeout/dist/setAnimationFrameTimeout.js"
//@codekit-append "../../../bower_components/underscore/underscore.js"
//@codekit-append "../../../bower_components/velocity/velocity.js"
<commit_msg>[JS] 不要なプラグインの読み込みを削除<commit_after>// Avoid `console` errors in browsers that lack a console.
(function() {
    var method;
    var noop = function () {};
    var methods = [
        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
        'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = (window.console = window.console || {});

    while (length--) {
        method = methods[length];

        // Only stub undefined methods.
        if (!console[method]) {
            console[method] = noop;
        }
    }
}());

// Place any jQuery/helper plugins in here.

//@codekit-append "../../../bower_components/cssuseragent/cssua.js"
//@codekit-append "../../../bower_components/ev-emitter/ev-emitter.js"
//@codekit-append "../../../bower_components/imagesloaded/imagesloaded.js"
//@codekit-append "../../../bower_components/setAnimationFrameTimeout/dist/setAnimationFrameTimeout.js"
//@codekit-append "../../../bower_components/underscore/underscore.js"
//@codekit-append "../../../bower_components/velocity/velocity.js"
<|endoftext|>


<commit_before>var assert = require('assert');
var mongoose = require('mongoose');

var Dishes = require('./dishes');
var Leaders = require('./leadership');
var Promotions = require('./promotions');

describe('mongooseTest', function() {
	var db;
	beforeEach(function() {
		mongoose.connect('mongodb://localhost/test');
		db = mongoose.connection;
		db.on('error', console.error.bind(console, 'connection error:'));
		db.once('open', function() {
			console.log('we are connected!');
		});
    });

    afterEach(function() {

    });

	it('Test Dishes Schema', function(done) {
		// create a new dish
		Dishes.create({
			name: 'Uthapizza',
			image: 'images/uthapizza.png',
			category: 'mains',
			label: 'Hot',
			price: 4.99,
			description: 'A unique . . .',
			comments: [
				{
					rating: 4,
					comment: 'Imagine all the eatables, living in conFusion!',
					author: 'John Lemon'
				},
				{
					rating: 5,
					comment: 'Sends anyone to heaven, I wish I could get my mother-in-law to eat it!',
					author: 'Paul McVites'
				}
			]
		}, function (err, dish) {
			if (err) throw err;
			console.log('Dish created!');
			console.log(dish);

			var id = dish._id;
			Dishes.remove({ _id: id }, function (err) {
				if (err) throw err;
				console.log('removed Dish ' + id)
			});

		});

		Leaders.create({
			name: 'Peter Pan',
			image: 'images/alberto.png',
			designation: 'Chief Epicurious Officer',
			abbr: 'CEO',
			description: 'Our CEO, Peter, . . .'
		}, function (err, leader) {
			if (err) throw err;
			console.log('Leader created!');
			console.log(leader);

			var id = leader._id;

			Leaders.remove({ _id: id }, function (err) {
				if (err) throw err;
				console.log('removed Leader ' + id)
			});
		});

		Promotions.create({
			name: 'Weekend Grand Buffet',
			image: 'images/buffet.png',
			label: 'New',
			price: '19.99',
			description: 'Featuring . . .'
		}, function (err, promotion) {
			if (err) throw err;
			console.log('Promotion created!');
			console.log(promotion);

			var id = promotion._id;

			Promotions.remove({ _id: id }, function (err) {
				if (err) throw err;
				console.log('removed Promotion ' + id)
			});

			done();
		});
	});

});<commit_msg>Assignment 3<commit_after>var assert = require('assert');
var mongoose = require('mongoose');

describe('testAss3', function() {

	beforeEach(function() {

    });

    afterEach(function() {

    });

	it('Test Assignment 3', function(done) {

		done();
	});

});<|endoftext|>


<commit_before>var gulp = require('gulp'),
	shell = require('gulp-shell');

// Jekyll

var jekyll = 'jekyll build --config jekyll.yml --source src --destination dest';

gulp.task('jekyll:full', shell.task([
	jekyll + ' JEKYLL_ENV=production'
]));

gulp.task('jekyll:limit', shell.task([
	jekyll + ' --limit_posts 150' + ' JEKYLL_ENV=development'
]));
<commit_msg>Fix `JEKYLL_ENV` setting<commit_after>var gulp = require('gulp'),
	shell = require('gulp-shell');

// Jekyll

var command = 'jekyll build --config jekyll.yml --source src --destination dest';

gulp.task('jekyll:full', shell.task([
	'JEKYLL_ENV=production ' + command
]));

gulp.task('jekyll:limit', shell.task([
	'JEKYLL_ENV=development ' + command + ' --limit_posts 150'
]));
<|endoftext|>


<commit_before>"use strict"

// process.hrtime

const
SEC = 1e3,
MIN = 6e4,
HOUR = 36e5

let
Timer = function(){
	// MICROSECONDS BASED

	this.starttime = 0

	this.then = 0
	this.now = 0

	this.delta = 0
	this.elapsed = 0
	this.μs = 0
}

Timer.prototype = {
	start:function(){
		// let hrT = process.hrtime()
		// hrT[0] * 1000000 + hrT[1]
		let hr = process.hrtime()
		this.starttime = this.now = (hr[0] * 1e9 + hr[1]) / 1e6
	},

	update:function(){
		this.then = this.now
		let hr = process.hrtime()
		this.now = (hr[0] * 1e9 + hr[1]) / 1e6

		this.delta = this.now - this.then
		this.elapsed = this.now - this.starttime

		this.μs = this.elapsed * 1e3
	},

	msToString:function(num){
		return struct.msToString( typeof num == "number" ? num : this.elapsed )
	}
}

let
struct = function(){ return new Timer() }

struct.msToString = function(num){
	if(num > 0){
		let str = "", digit = 0

		num = Math.floor(num)

		// SEC
		digit = Math.floor(num / SEC) % 60
		str = ( digit > 9 )? digit.toString() : "0" + digit.toString()

		// MIN
		digit = Math.floor((num % HOUR) / MIN)
		str = ( digit > 9 )?(digit.toString() + ":" + str):("0" + digit.toString() + ":" + str)

		// HOUR
		digit = Math.floor(num / HOUR)
		if(digit > 0) str = ( digit > 9 )?(digit.toString() + ":" + str):("0" + digit.toString() + ":" + str)

		return str
	}else{
		return "00:00"
	}
}

// Number.prototype.msToString = function(){ return struct.msToString(this) }

exports = module.exports = struct
<commit_msg>Update Index.js<commit_after>"use strict"

// process.hrtime

const
SEC = 1e3,
MIN = 6e4,
HOUR = 36e5

let
Timer = function(){
	// MICROSECONDS BASED

	this.starttime = 0

	this.then = 0
	this.now = 0

	this.delta = 0
	this.elapsed = 0

	this.μs = 0
	this.sec = 0

	this.offset = 0
}

Timer.prototype = {
	start:function(offset){
		// let hrT = process.hrtime()
		// hrT[0] * 1000000 + hrT[1]
		let hr = process.hrtime()
		this.starttime = this.now = (hr[0] * 1e9 + hr[1]) / 1e6
		this.offset = offset || 0
	},

	update:function(){
		this.then = this.now
		let hr = process.hrtime()
		this.now = (hr[0] * 1e9 + hr[1]) / 1e6

		this.delta = this.now - this.then
		this.elapsed = this.now - this.starttime + this.offset

	},

	msToString:function(num){
		return struct.msToString( typeof num == "number" ? num : this.elapsed )
	}
}

let
struct = function(){ return new Timer() }

struct.msToString = function(num){
	if(num > 0){
		let str = "", digit = 0

		num = Math.floor(num)

		// SEC
		digit = Math.floor(num / SEC) % 60
		str = ( digit > 9 )? digit.toString() : "0" + digit.toString()

		// MIN
		digit = Math.floor((num % HOUR) / MIN)
		str = ( digit > 9 )?(digit.toString() + ":" + str):("0" + digit.toString() + ":" + str)

		// HOUR
		digit = Math.floor(num / HOUR)
		if(digit > 0) str = ( digit > 9 )?(digit.toString() + ":" + str):("0" + digit.toString() + ":" + str)

		return str
	}else{
		return "00:00"
	}
}

// Number.prototype.msToString = function(){ return struct.msToString(this) }

exports = module.exports = struct
<|endoftext|>


<commit_before>// search.js
var React = require('react');
var ReactDOM = require('react-dom');
var ymirAPI =require('../static/js/ymirWrapper.js');
var Model = ymirAPI;

function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1);
        if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
    }
    return "";
}

var Category = React.createClass({
	getInitialState: function(){
	    return {worlds:[]}
	},

	componentDidMount: function(){
	    var self = this;
	    var context = this.props.category;
	    Model(getCookie('worldId'))[context].all().then(function(res){
	    	console.log(res);
	        var st=self.state;
	        st.worlds = res.data;
	        self.setState(st);
	    });
	},

	rm: function(id){
	    var context = this.props.category;
		Model(getCookie('worldId'))[context].del(id).then(function(res){
			console.log(res);
		});
		location.reload()
	},

	cookieFunction: function(id) {
		document.cookie = "characterEditId="+id;
		location.href=this.props.category+"Edit.html"
	},

	render: function(){
		var self = this;
		var items = this.state.worlds.map((i,n)=>{
			return(

					{i.name}
					edit
					delete

			);
		});
	    return(

{this.props.category} +

						<input type="text" className="search" placeholder="Search" />

						{items}

	    )
	},

})

module.exports = Category;

<commit_msg>undo strong delete<commit_after>// search.js
var React = require('react');
var ReactDOM = require('react-dom');
var ymirAPI =require('../static/js/ymirWrapper.js');
var Model = ymirAPI;

function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1);
        if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
    }
    return "";
}

var Category = React.createClass({
	getInitialState: function(){
	    return {worlds:[]}
	},

	componentDidMount: function(){
	    var self = this;
	    var context = this.props.category;
	    Model(getCookie('worldId'))[context].all().then(function(res){
	    	console.log(res);
	        var st=self.state;
	        st.worlds = res.data;
	        self.setState(st);
	    });
	},

	rm: function(id){
	    var context = this.props.category;
		Model(getCookie('worldId'))[context].del(id).then(function(res){
			console.log(res);
		});
		location.reload()
	},

	cookieFunction: function(id) {
		document.cookie = "characterEditId="+id;
		location.href=this.props.category+"Edit.html"
	},

	render: function(){
		var self = this;
		var items = this.state.worlds.map((i,n)=>{
			return(

					{i.name}
					edit
					delete

			);
		});
	    return(

{this.props.category} +

						<input type="text" className="search" placeholder="Search" />

						{items}

	    )
	},

})

module.exports = Category;

<|endoftext|>


<commit_before>( function() {
	var api = wp.customize;

	_.each( jsvars, function( jsVars, setting ) {

		var css      = '',
		    cssArray = {};

		api( setting, function( value ) {

			value.bind( function( newval ) {

				if ( undefined !== jsVars && 0 < jsVars.length ) {

					_.each( jsVars, function( jsVar ) {

						var val = newval;

						// Make sure element is defined.
						if ( undefined === jsVar.element ) {
							jsVar.element = '';
						}

						// Make sure property is defined.
						if ( undefined === jsVar.property ) {
							jsVar.property = '';
						}

						// Use empty prefix if undefined
						if ( undefined === jsVar.prefix ) {
							jsVar.prefix = '';
						}

						// Use empty suffix if undefined
						if ( undefined === jsVar.suffix ) {
							jsVar.suffix = '';
						}

						// Use empty units if undefined
						if ( undefined === jsVar.units ) {
							jsVar.units = '';
						}

						// Use css if method is undefined
						if ( undefined === jsVar['function'] ) {
							jsVar['function'] = 'css';
						}

						// Use $ (just the value) if value_pattern is undefined
						if ( undefined === jsVar.value_pattern ) {
							jsVar.value_pattern = '$';
						}

						_.each( jsVars, function( args, i ) {

							// Value is a string
							if ( 'string' === typeof newval ) {

								// Process the value pattern
								if ( undefined !== args.value_pattern ) {
									val = args.value_pattern.replace( /\$/g, args.prefix + newval + args.units + args.suffix );
								} else {
									val = args.prefix + newval + args.units + args.suffix;
								}

								// Inject HTML
								if ( 'html' === args['function'] ) {
									if ( 'undefined' !== typeof args.attr && undefined !== args.attr ) {
										jQuery( args.element ).attr( args.attr, val );
									} else {
										jQuery( args.element ).html( val );
									}

								// Add CSS
								} else {

									// If we have new value, replace style contents with custom css
									if ( '' !== val ) {
										cssArray[ i ] = args.element + '{' + args.property + ':' + val + ';}';
									}

									// Else let's clear it out
									else {
										cssArray[ i ] = '';
									}

								}

							// Value is an object
							} else if ( 'object' === typeof newval ) {

								cssArray[ i ] = '';
								_.each( newval, function( subValueValue, subValueKey ) {
									if ( undefined !== args.choice ) {
										if ( args.choice === subValueKey ) {
											cssArray[ i ] += args.element + '{' + args.property + ':' + args.prefix + subValueValue + args.units + args.suffix + ';}';
										}
									} else {
										if ( _.contains( [ 'top', 'bottom', 'left', 'right' ], subValueKey ) ) {
											cssArray[ i ] += args.element + '{' + args.property + '-' + subValueKey + ':' + args.prefix + subValueValue + args.units + args.suffix + ';}';
										} else {
											cssArray[ i ] += args.element + '{' + subValueKey + ':' + args.prefix + subValueValue + args.units + args.suffix + ';}';
										}
									}
								});

							}

						});

					});

					_.each( cssArray, function( singleCSS ) {

						css = '';

						setTimeout( function() {

							if ( '' !== singleCSS ) {
								css += singleCSS;
							}

							// Attach to <head>
							if ( '' !== css ) {

								// Make sure we have a stylesheet with the defined ID.
								// If we don't then add it.
								if ( ! jQuery( '#kirki-customizer-postmessage' + setting.replace( /\[/g, '-' ).replace( /\]/g, '' ) ).size() ) {
									jQuery( 'head' ).append( '<style id="kirki-customizer-postmessage' + setting.replace( /\[/g, '-' ).replace( /\]/g, '' ) + '"></style>' );
								}
								jQuery( '#kirki-customizer-postmessage' + setting.replace( /\[/g, '-' ).replace( /\]/g, '' ) ).text( css );
							}

						}, 100 );

					});

				}

			});

		});

	});

})( jQuery );
<commit_msg>fixes #963<commit_after>( function() {
	var api = wp.customize;

	_.each( jsvars, function( jsVars, setting ) {

		var css      = '',
		    cssArray = {};

		api( setting, function( value ) {

			value.bind( function( newval ) {

				if ( undefined !== jsVars && 0 < jsVars.length ) {

					_.each( jsVars, function( jsVar ) {

						var val = newval;

						// Make sure element is defined.
						if ( undefined === jsVar.element ) {
							jsVar.element = '';
						}

						// Make sure property is defined.
						if ( undefined === jsVar.property ) {
							jsVar.property = '';
						}

						// Use empty prefix if undefined
						if ( undefined === jsVar.prefix ) {
							jsVar.prefix = '';
						}

						// Use empty suffix if undefined
						if ( undefined === jsVar.suffix ) {
							jsVar.suffix = '';
						}

						// Use empty units if undefined
						if ( undefined === jsVar.units ) {
							jsVar.units = '';
						}

						// Use css if method is undefined
						if ( undefined === jsVar['function'] ) {
							jsVar['function'] = 'css';
						}

						// Use $ (just the value) if value_pattern is undefined
						if ( undefined === jsVar.value_pattern ) {
							jsVar.value_pattern = '$';
						}

						_.each( jsVars, function( args, i ) {

							// Value is a string
							if ( 'string' === typeof newval ) {

								// Process the value pattern
								if ( undefined !== args.value_pattern ) {
									val = args.value_pattern.replace( /\$/g, args.prefix + newval + args.units + args.suffix );
								} else {
									val = args.prefix + newval + args.units + args.suffix;
								}

								// Simple tweak for background-image properties.
								if ( 'background-image' === args.property ) {
									if ( 0 > val.indexOf( 'url(' ) ) {
										val = 'url("' + val + '")';
									}
								}

								// Inject HTML
								if ( 'html' === args['function'] ) {
									if ( 'undefined' !== typeof args.attr && undefined !== args.attr ) {
										jQuery( args.element ).attr( args.attr, val );
									} else {
										jQuery( args.element ).html( val );
									}

								// Add CSS
								} else {

									// If we have new value, replace style contents with custom css
									if ( '' !== val ) {
										cssArray[ i ] = args.element + '{' + args.property + ':' + val + ';}';
									}

									// Else let's clear it out
									else {
										cssArray[ i ] = '';
									}

								}

							// Value is an object
							} else if ( 'object' === typeof newval ) {

								cssArray[ i ] = '';
								_.each( newval, function( subValueValue, subValueKey ) {
									if ( undefined !== args.choice ) {
										if ( args.choice === subValueKey ) {
											cssArray[ i ] += args.element + '{' + args.property + ':' + args.prefix + subValueValue + args.units + args.suffix + ';}';
										}
									} else {
										if ( _.contains( [ 'top', 'bottom', 'left', 'right' ], subValueKey ) ) {
											cssArray[ i ] += args.element + '{' + args.property + '-' + subValueKey + ':' + args.prefix + subValueValue + args.units + args.suffix + ';}';
										} else {
											cssArray[ i ] += args.element + '{' + subValueKey + ':' + args.prefix + subValueValue + args.units + args.suffix + ';}';
										}
									}
								});

							}

						});

					});

					_.each( cssArray, function( singleCSS ) {

						css = '';

						setTimeout( function() {

							if ( '' !== singleCSS ) {
								css += singleCSS;
							}

							// Attach to <head>
							if ( '' !== css ) {

								// Make sure we have a stylesheet with the defined ID.
								// If we don't then add it.
								if ( ! jQuery( '#kirki-customizer-postmessage' + setting.replace( /\[/g, '-' ).replace( /\]/g, '' ) ).size() ) {
									jQuery( 'head' ).append( '<style id="kirki-customizer-postmessage' + setting.replace( /\[/g, '-' ).replace( /\]/g, '' ) + '"></style>' );
								}
								jQuery( '#kirki-customizer-postmessage' + setting.replace( /\[/g, '-' ).replace( /\]/g, '' ) ).text( css );
							}

						}, 100 );

					});

				}

			});

		});

	});

})( jQuery );
<|endoftext|>


<commit_before>'use strict';

exports.register = function (server, options, next) {
  server.route({
    method: 'GET',
    path: '/',
    handler: function (request, reply) {
      var uri = server.connections[0].info.uri;
      var docsFolder = server.app.config.product.docsFolder || '/docs';
      var name = server.app.config.product.name || 'goldvault';
      var info = server.app.config.product.info;
      var response = {
        name: name,
        docs: uri + docsFolder
      };

      if (info) {
        response.info = info;
      }

      reply(response);
    }
  });

  next();
};

exports.register.attributes = {
  name: 'Index page for goldvault.',
  version: '1.0.0'
};<commit_msg>Fix plugin.<commit_after>'use strict';

exports.register = function (server, options, next) {
  server.route({
    method: 'GET',
    path: '/',
    handler: function (request, reply) {
      //console.log(server);
      var uri = server.connections[0].info.uri;
      var docsFolder = server.settings.app.config.product.docsFolder || '/docs';
      var name = server.settings.app.config.product.name || 'goldvault';
      var info = server.settings.app.config.product.info;
      var response = {
        name: name,
        docs: uri + docsFolder
      };

      if (info) {
        response.info = info;
      }

      reply(response);
    }
  });

  next();
};

exports.register.attributes = {
  name: 'Index page for goldvault.',
  version: '1.0.0'
};<|endoftext|>


<commit_before>/*!
 * jQuery Sexyforms
 * version: 0.0.1 (Monday, 19 August 2013) * requires jQuery v1.7 or later *
 * Examples at http://fdaciuk.github.io/sexyforms
 * License:
 *
 * Copyright 2013 Fernando Daciuk - https://github.com/fdaciuk
 *
 */!function(a,b,c){function d(a,b){this.element=a,this.settings=c.extend({},f,b),this._defaults=f,this._name=e,this.init()}var e="sexyforms",f={setStyle:!0,theme:"default",wrap:"div"};d.prototype={init:function(){var a,b=c(this.element),d=this.settings,e=d.theme?" sf-theme-"+d.theme:"",f="<"+d.wrap+' class="sexyforms'+e+'" />',g=b.wrap(f).closest(".sexyforms"),h={"float":b.css("float"),margin:b.css("margin"),bottom:b.css("bottom"),display:"inline"===b.css("display")?"inline-block":b.css("display"),left:b.css("left"),position:"static"===b.css("position")?"relative":b.css("position"),right:b.css("right"),top:b.css("top"),height:b.outerHeight(),width:b.outerWidth()},i={left:0,margin:0,position:"absolute",top:0};d.setStyle&&g.css(h).find(this.element).css(i),b.is("input:radio")&&(this.initRadio(g),a=this.radioChange),b.is("input:checkbox")&&(this.initCheckbox(g),a=this.checkboxChange),b.is("select")&&(this.initSelect(g),a=this.selectChange),b.is("input:file")&&(this.initFile(g),a=this.fileChange),b.on("change",a)},initRadio:function(a){var b=a.find("input").is(":checked");a.addClass("sf-radio"),b&&a.addClass("sf-checked")},radioChange:function(a){a.preventDefault();var b=c(this),d=b[0].id,e=b[0].name;c('input[name="'+e+'"]').not("#"+d).closest(".sf-radio").removeClass("sf-checked"),b.closest(".sf-radio").addClass("sf-checked")},initCheckbox:function(a){var b=a.find("input").is(":checked");a.addClass("sf-checkbox"),b&&a.addClass("sf-checked")},checkboxChange:function(a){a.preventDefault();var b=c(this),d=b.closest(".sf-checkbox"),e=b.is(":checked");e?d.addClass("sf-checked"):d.removeClass("sf-checked")},initSelect:function(a){var b=a.find("option:selected").text();a.addClass("sf-select").append(""+b+"")},selectChange:function(){var a=c(this),b=a.closest(".sf-select"),d=a.find("option:selected").text();b.find("span").text(d)},initFile:function(a){console.log("File",a),a.addClass("sf-file")},fileChange:function(a){console.log("File",a),a.addClass("sf-file")}},c.fn[e]=function(a){return this.each(function(){c.data(this,"plugin_"+e)||c.data(this,"plugin_"+e,new d(this,a))})}}(window,document,jQuery);<commit_msg>v0.0.2 minificada<commit_after>/*!
 * jQuery Sexyforms
 * version: 0.0.2 (Wednesday, 21 August 2013) * requires jQuery v1.7 or later *
 * Examples at http://fdaciuk.github.io/sexyforms
 * License:
 *
 * Copyright 2013 Fernando Daciuk - https://github.com/fdaciuk
 *
 */!function(a,b,c){function d(a,b){this.element=a,this.settings=c.extend({},f,b),this._defaults=f,this._name=e,this.init()}var e="sexyforms",f={setStyle:!0,theme:"default",wrap:"div"};d.prototype={init:function(){var a,b=c(this.element),d=this.settings,e=d.theme?" sf-theme-"+d.theme:"",f="<"+d.wrap+' class="sexyforms'+e+'" />',g=b.wrap(f).closest(".sexyforms"),h={"float":b.css("float"),margin:b.css("margin"),bottom:b.css("bottom"),display:"inline"===b.css("display")?"inline-block":b.css("display"),left:b.css("left"),position:"static"===b.css("position")?"relative":b.css("position"),right:b.css("right"),top:b.css("top"),height:b.outerHeight(),width:b.outerWidth()},i={left:0,margin:0,position:"absolute",top:0};d.setStyle&&g.css(h).find(this.element).css(i),b.is("input:radio")&&(this.initRadio(g),a=this.radioChange),b.is("input:checkbox")&&(this.initCheckbox(g),a=this.checkboxChange),b.is("select")&&(this.initSelect(g),a=this.selectChange),b.is("input:file")&&(this.initFile(g),a=this.fileChange),b.on("change",a)},initRadio:function(a){var b=a.find("input").is(":checked");a.addClass("sf-radio"),b&&a.addClass("sf-checked")},radioChange:function(a){a.preventDefault();var b=c(this),d=b[0].name;c('input[name="'+d+'"]').not(this).closest(".sf-radio").removeClass("sf-checked"),b.closest(".sf-radio").addClass("sf-checked")},initCheckbox:function(a){var b=a.find("input").is(":checked");a.addClass("sf-checkbox"),b&&a.addClass("sf-checked")},checkboxChange:function(a){a.preventDefault();var b=c(this),d=b.closest(".sf-checkbox"),e=b.is(":checked");e?d.addClass("sf-checked"):d.removeClass("sf-checked")},initSelect:function(a){var b=a.find("option:selected").text();a.addClass("sf-select").append(""+b+"")},selectChange:function(){var a=c(this),b=a.closest(".sf-select"),d=a.find("option:selected").text();b.find("span").text(d)},initFile:function(a){console.log("File",a),a.addClass("sf-file")},fileChange:function(a){console.log("File",a),a.addClass("sf-file")}},c.fn[e]=function(a){return this.each(function(){c.data(this,"plugin_"+e)||c.data(this,"plugin_"+e,new d(this,a))})}}(window,document,jQuery);<|endoftext|>


<commit_before>var $ = require("jquery")
var _ = require("lodash")
var ð = require("../util/dom")
var ƒ = require("../util/functional")
var Rx = require("rx")
var moment = require("moment")
require("rx-jquery")
require("../util/rx-extensions")

window.jQuery = $
window.moment = moment
require("livestamp")

var entryIdRegex = /\/(edit|entry)\/(.*)/
var entryId = (entryIdRegex.exec(document.location.pathname) || [undefined, undefined, undefined])[2]

function iconFor(sport) {
  return allSports.find(function(item) { return item.label == sport} ).icon
}

function populate(fromEditMode) {
  var entry = $.getJSONAsObservable("/trail/rest/blog/" + entryId).map(ƒ.attrF("data")).take(1)
  entry.subscribe(function(entry) {
    var date = moment.unix(entry.date)
    $("#page-title").text(entry.title)
    $("#ex-title").text(entry.title)
    $("#ex-body").html(entry.body)
    $("#ex-date").attr("data-timestamp", entry.date).livestamp(date)
    if (fromEditMode) {
      $("#ex-sport").val(entry.sport)
    }
    if (entry.sport)
      $("#distance-logo").toggleClass(iconFor(entry.sport)).show()
    if (entry.distance) {
      $("#distance-text").text(entry.distance).show()
    }
    if (entry.time) {
      $("#time-text").text(entry.time).show()
      $("#time-logo").show()
    }
    if (!fromEditMode) {
      $("#author-fullname").text(entry.user)
      $("#author-image").attr('src', entry.avatar)
    }
  })
  return entry;
}

function edit() {
  function _zipObj(keys) {
    return function() {
      var arr = []
      for (var i = 0; i < arguments.length; i++)
        arr[i] = arguments[i]
      return _.zipObject(keys, arr)
    }
  }

  var titles = $("#ex-title").onAsObservable('input').throttledEventTarget(300).map(ð.text).startWith("")
  var bodies = $("#ex-body").onAsObservable('input').throttledEventTarget(300).map(ð.html).startWith("")
  var distance = $("#ex-distance").onAsObservable('change').map(ƒ.attrF("target")).map(ð.val).startWith("")
  var time = $("#ex-time").onAsObservable('change').map(ƒ.attrF("target")).map(ð.val).startWith("")
  var sport = $("#ex-sport").onAsObservable('change').map(ƒ.attrF("target")).map(ð.val).startWith("")
  var date = $("#ex-date").onAsObservable('change').map(ƒ.attrF("target")).map(ð.attrF('data-timestamp')).startWith("")

  var createdDraft = $.postAsObservable("/trail/rest/blog/draft", {}).map(ƒ.attrF("data"))

  var drafts =
    createdDraft.flatMapLatest(function(blogPost) {
      return Rx.Observable.combineLatest([titles, bodies, distance, time, sport, date], _zipObj(["title", "body", "distance", "time", "sport", "date"]))
        .map(function(values) { return _.merge({}, blogPost, values) })
    }).distinctUntilChanged().skip(1)

  if (entryId) populate(true)
  return { drafts: drafts, allSports: allSports }
}

var allSports = _([
  { "Beach volley": "flaticon-volleyball3" },
  { "Crossfit": "flaticon-weightlift" },
  { "Crosstrainer": "flaticon-person212" },
  { "Cyclocross": "flaticon-time13" },
  { "Golf": "flaticon-golf22" },
  { "Hiihto": "flaticon-ski2" },
  { "Jalkapallo": "flaticon-soccer43" },
  { "Jooga": "flaticon-guru1" },
  { "Jumppa": "flaticon-jump7" },
  { "Juoksu": "flaticon-running30" },
  { "Jääkiekko": "flaticon-ice57" },
  { "Kahvakuula": "flaticon-biceps" },
  { "Kamppailulaji": "flaticon-martial2" },
  { "Kaukalopallo": "flaticon-ice46" },
  { "Kickbike": "flaticon-regular2" },
  { "Kiipeily": "flaticon-climbing6" },
  { "Koripallo": "flaticon-basketball3" },
  { "Kuntopiiri": "flaticon-flexions" },
  { "Kuntopyörä": "flaticon-bicycle14" },
  { "Kuntosali": "flaticon-barbell" },
  { "Kävely": "flaticon-walking17" },
  { "Laskettelu": "flaticon-skiing7" },
  { "Lentopallo": "flaticon-person39" },
  { "Leuanveto": "flaticon-pulling" },
  { "Luistelu": "flaticon-ice49" },
  { "Luisteluhiihto": "flaticon-ski2" },
  { "Lumikenkäily": "flaticon-walking17" },
  { "Lumilautailu": "flaticon-extreme1" },
  { "Maantiepyöräily": "flaticon-time13" },
  { "Maastojuoksu": "flaticon-mountain23" },
  { "Maastopyöräily": "flaticon-mountain24" },
  { "Melonta": "flaticon-padding" },
  { "Nyrkkeily": "flaticon-female139" },
  { "Perinteinen hiihto": "flaticon-ski2" },
  { "Pilates": "flaticon-leg1" },
  { "Potkukelkkailu": "flaticon-trekking" },
  { "Pumppi": "flaticon-dumbbell21" },
  { "Pyöräily": "flaticon-regular2" },
  { "Ratsastus": "flaticon-silhouette2" },
  { "Ringette": "flaticon-ice46" },
  { "Rullahiihto": "flaticon-ski2" },
  { "Rullaluistelu": "flaticon-skater1" },
  { "Salibandy": "flaticon-hockey2" },
  { "Sauvakävely": "flaticon-trekking" },
  { "Seikkailu-urheilu": "flaticon-compass" },
  { "Sisäsoutu": "flaticon-person209" },
  { "Soutu": "flaticon-person209" },
  { "Spinning": "flaticon-bicycle14" },
  { "Squash": "flaticon-squash" },
  { "Sulkapallo": "flaticon-man36" },
  { "Suunnistus": "flaticon-map49" },
  { "Sähly": "flaticon-hockey2" },
  { "Tanssi": "flaticon-american36" },
  { "Telinevoimistelu": "flaticon-individual3" },
  { "Tennis": "flaticon-person17" },
  { "Triathlon": "flaticon-mountain24" },
  { "Uinti": "flaticon-swimming20" },
  { "Vaellus": "flaticon-hiking" },
  { "Venyttely": "flaticon-man252" },
  { "Vesijuoksu": "flaticon-swimming20" },
  { "Yleisurheilu": "flaticon-jumping2" }
]).map(function(sport) {
  var key = _.keys(sport)[0]
  return {
    label: key,
    icon: sport[key],
    value: key
  }
})

function renderEntries(el, draft, entries) {
  $(el).append(_(entries.blogs).map(function(entry) {
    var excerptText = $(entry.body).filter("p").text().substring(0,140)
    var hasExcerpt = excerptText != ""
    var hasTitle = entry.title && entry.title != ""
    var titleText = hasTitle ? entry.title : (draft ? "Harjoituksen otsikko on vielä hakusessa" : excerptText)

    var $title = $("<h3>", { "class": hasTitle ? "" : "generated" }).text(titleText)
    var $excerpt = $("<p>",  { "class": hasExcerpt ? "" : "generated" }).text( (excerptText != "" || !draft) ? excerptText : "Lenkkisi kaipaa kuvausta")
    var $sport = (entry.sport ? $("<span>", {"class": iconFor(entry.sport)}).text(entry.distance? " " + entry.distance : "") : "")
    var $time = (entry.time ? $("<span>", {"class": "flaticon-stopwatch7"}).text(entry.time ? " " + entry.time : "") : "")
    var $user = $("<h5>").append($("<span>", {"class": "author"}).text(entry.user)).append($sport).append($time)
    return $("<div>", {"class": "entry-preview pure-u-1", "data-sid": draft ? entry.id : entry.sid}).append($title).append($excerpt).append($user)
  }).value())
}

var elementBottomIsAlmostVisible = function($el, margin) {
    if (!$el.is(':visible')) return false;

    // Toim.huom. $(window).height() näyttäis olevan rikki jquery 1.8.1:ssä...
    var viewportBottom = $(window).scrollTop() + window.innerHeight
    var loadingPoint = $el.offset().top + $el.outerHeight()

    return (viewportBottom  + margin) >= loadingPoint
}

var pager = function(fromUrl) {
    return fromUrl.scan( {page: 0},
      function(val, url) { var pg = val.page + 1; return {page: pg, url: url } })
      .map(function(item) { return item.url + "page=" + item.page })
}

function entries(el, drafts) {
  require("../app/user").requiredAuths()

  var url = drafts ? "/trail/rest/blog/list/drafts?" : "/trail/rest/blog/list/all?"
  var $el = $("#blog-posts")

  var ajaxReady = $el.onAsObservable("blog-update").throttle(100)
  var shouldUpdate = ajaxReady.merge($(window).onAsObservable('scroll').throttle(100)).filter(_.partial(elementBottomIsAlmostVisible, $el, 100))
  var pages = ajaxReady.startWith("").zip(shouldUpdate.startWith(""), _.identity)

  var entries = pager(pages.map(function() { return url })).flatMap(function(url) {
    console.log("get from url", url)
    return $.getJSONAsObservable(url)
  })

  entries.map(ƒ.attrF("data")).subscribe(function(entries) {
    renderEntries($el, drafts, entries)
    if (entries.blogs.length > 0)
      $el.trigger("blog-update")
  }, function() { $el.trigger("blog-update") })

  return entries
}

exports.entries = entries
exports.edit = edit
exports.populate = populate

<commit_msg>fix avatar<commit_after>var $ = require("jquery")
var _ = require("lodash")
var ð = require("../util/dom")
var ƒ = require("../util/functional")
var Rx = require("rx")
var moment = require("moment")
require("rx-jquery")
require("../util/rx-extensions")

window.jQuery = $
window.moment = moment
require("livestamp")

var entryIdRegex = /\/(edit|entry)\/(.*)/
var entryId = (entryIdRegex.exec(document.location.pathname) || [undefined, undefined, undefined])[2]

function iconFor(sport) {
  return allSports.find(function(item) { return item.label == sport} ).icon
}

function populate(fromEditMode) {
  var entry = $.getJSONAsObservable("/trail/rest/blog/" + entryId).map(ƒ.attrF("data")).take(1)
  entry.subscribe(function(entry) {
    var date = moment.unix(entry.date)
    $("#page-title").text(entry.title)
    $("#ex-title").text(entry.title)
    $("#ex-body").html(entry.body)
    $("#ex-date").attr("data-timestamp", entry.date).livestamp(date)
    if (fromEditMode) {
      $("#ex-sport").val(entry.sport)
    }
    if (entry.sport)
      $("#distance-logo").toggleClass(iconFor(entry.sport)).show()
    if (entry.distance) {
      $("#distance-text").text(entry.distance).show()
    }
    if (entry.time) {
      $("#time-text").text(entry.time).show()
      $("#time-logo").show()
    }
    if (!fromEditMode) {
      $("#author-fullname").text(entry.user)
      $("#author-image").attr('style', "background-image: url(" + entry.avatar + ");")
    }
  })
  return entry;
}

function edit() {
  function _zipObj(keys) {
    return function() {
      var arr = []
      for (var i = 0; i < arguments.length; i++)
        arr[i] = arguments[i]
      return _.zipObject(keys, arr)
    }
  }

  var titles = $("#ex-title").onAsObservable('input').throttledEventTarget(300).map(ð.text).startWith("")
  var bodies = $("#ex-body").onAsObservable('input').throttledEventTarget(300).map(ð.html).startWith("")
  var distance = $("#ex-distance").onAsObservable('change').map(ƒ.attrF("target")).map(ð.val).startWith("")
  var time = $("#ex-time").onAsObservable('change').map(ƒ.attrF("target")).map(ð.val).startWith("")
  var sport = $("#ex-sport").onAsObservable('change').map(ƒ.attrF("target")).map(ð.val).startWith("")
  var date = $("#ex-date").onAsObservable('change').map(ƒ.attrF("target")).map(ð.attrF('data-timestamp')).startWith("")

  var createdDraft = $.postAsObservable("/trail/rest/blog/draft", {}).map(ƒ.attrF("data"))

  var drafts =
    createdDraft.flatMapLatest(function(blogPost) {
      return Rx.Observable.combineLatest([titles, bodies, distance, time, sport, date], _zipObj(["title", "body", "distance", "time", "sport", "date"]))
        .map(function(values) { return _.merge({}, blogPost, values) })
    }).distinctUntilChanged().skip(1)

  if (entryId) populate(true)
  return { drafts: drafts, allSports: allSports }
}

var allSports = _([
  { "Beach volley": "flaticon-volleyball3" },
  { "Crossfit": "flaticon-weightlift" },
  { "Crosstrainer": "flaticon-person212" },
  { "Cyclocross": "flaticon-time13" },
  { "Golf": "flaticon-golf22" },
  { "Hiihto": "flaticon-ski2" },
  { "Jalkapallo": "flaticon-soccer43" },
  { "Jooga": "flaticon-guru1" },
  { "Jumppa": "flaticon-jump7" },
  { "Juoksu": "flaticon-running30" },
  { "Jääkiekko": "flaticon-ice57" },
  { "Kahvakuula": "flaticon-biceps" },
  { "Kamppailulaji": "flaticon-martial2" },
  { "Kaukalopallo": "flaticon-ice46" },
  { "Kickbike": "flaticon-regular2" },
  { "Kiipeily": "flaticon-climbing6" },
  { "Koripallo": "flaticon-basketball3" },
  { "Kuntopiiri": "flaticon-flexions" },
  { "Kuntopyörä": "flaticon-bicycle14" },
  { "Kuntosali": "flaticon-barbell" },
  { "Kävely": "flaticon-walking17" },
  { "Laskettelu": "flaticon-skiing7" },
  { "Lentopallo": "flaticon-person39" },
  { "Leuanveto": "flaticon-pulling" },
  { "Luistelu": "flaticon-ice49" },
  { "Luisteluhiihto": "flaticon-ski2" },
  { "Lumikenkäily": "flaticon-walking17" },
  { "Lumilautailu": "flaticon-extreme1" },
  { "Maantiepyöräily": "flaticon-time13" },
  { "Maastojuoksu": "flaticon-mountain23" },
  { "Maastopyöräily": "flaticon-mountain24" },
  { "Melonta": "flaticon-padding" },
  { "Nyrkkeily": "flaticon-female139" },
  { "Perinteinen hiihto": "flaticon-ski2" },
  { "Pilates": "flaticon-leg1" },
  { "Potkukelkkailu": "flaticon-trekking" },
  { "Pumppi": "flaticon-dumbbell21" },
  { "Pyöräily": "flaticon-regular2" },
  { "Ratsastus": "flaticon-silhouette2" },
  { "Ringette": "flaticon-ice46" },
  { "Rullahiihto": "flaticon-ski2" },
  { "Rullaluistelu": "flaticon-skater1" },
  { "Salibandy": "flaticon-hockey2" },
  { "Sauvakävely": "flaticon-trekking" },
  { "Seikkailu-urheilu": "flaticon-compass" },
  { "Sisäsoutu": "flaticon-person209" },
  { "Soutu": "flaticon-person209" },
  { "Spinning": "flaticon-bicycle14" },
  { "Squash": "flaticon-squash" },
  { "Sulkapallo": "flaticon-man36" },
  { "Suunnistus": "flaticon-map49" },
  { "Sähly": "flaticon-hockey2" },
  { "Tanssi": "flaticon-american36" },
  { "Telinevoimistelu": "flaticon-individual3" },
  { "Tennis": "flaticon-person17" },
  { "Triathlon": "flaticon-mountain24" },
  { "Uinti": "flaticon-swimming20" },
  { "Vaellus": "flaticon-hiking" },
  { "Venyttely": "flaticon-man252" },
  { "Vesijuoksu": "flaticon-swimming20" },
  { "Yleisurheilu": "flaticon-jumping2" }
]).map(function(sport) {
  var key = _.keys(sport)[0]
  return {
    label: key,
    icon: sport[key],
    value: key
  }
})

function renderEntries(el, draft, entries) {
  $(el).append(_(entries.blogs).map(function(entry) {
    var excerptText = $(entry.body).filter("p").text().substring(0,140)
    var hasExcerpt = excerptText != ""
    var hasTitle = entry.title && entry.title != ""
    var titleText = hasTitle ? entry.title : (draft ? "Harjoituksen otsikko on vielä hakusessa" : excerptText)

    var $title = $("<h3>", { "class": hasTitle ? "" : "generated" }).text(titleText)
    var $excerpt = $("<p>",  { "class": hasExcerpt ? "" : "generated" }).text( (excerptText != "" || !draft) ? excerptText : "Lenkkisi kaipaa kuvausta")
    var $sport = (entry.sport ? $("<span>", {"class": iconFor(entry.sport)}).text(entry.distance? " " + entry.distance : "") : "")
    var $time = (entry.time ? $("<span>", {"class": "flaticon-stopwatch7"}).text(entry.time ? " " + entry.time : "") : "")
    var $user = $("<h5>").append($("<span>", {"class": "author"}).text(entry.user)).append($sport).append($time)
    return $("<div>", {"class": "entry-preview pure-u-1", "data-sid": draft ? entry.id : entry.sid}).append($title).append($excerpt).append($user)
  }).value())
}

var elementBottomIsAlmostVisible = function($el, margin) {
    if (!$el.is(':visible')) return false;

    // Toim.huom. $(window).height() näyttäis olevan rikki jquery 1.8.1:ssä...
    var viewportBottom = $(window).scrollTop() + window.innerHeight
    var loadingPoint = $el.offset().top + $el.outerHeight()

    return (viewportBottom  + margin) >= loadingPoint
}

var pager = function(fromUrl) {
    return fromUrl.scan( {page: 0},
      function(val, url) { var pg = val.page + 1; return {page: pg, url: url } })
      .map(function(item) { return item.url + "page=" + item.page })
}

function entries(el, drafts) {
  require("../app/user").requiredAuths()

  var url = drafts ? "/trail/rest/blog/list/drafts?" : "/trail/rest/blog/list/all?"
  var $el = $("#blog-posts")

  var ajaxReady = $el.onAsObservable("blog-update").throttle(100)
  var shouldUpdate = ajaxReady.merge($(window).onAsObservable('scroll').throttle(100)).filter(_.partial(elementBottomIsAlmostVisible, $el, 100))
  var pages = ajaxReady.startWith("").zip(shouldUpdate.startWith(""), _.identity)

  var entries = pager(pages.map(function() { return url })).flatMap(function(url) {
    console.log("get from url", url)
    return $.getJSONAsObservable(url)
  })

  entries.map(ƒ.attrF("data")).subscribe(function(entries) {
    renderEntries($el, drafts, entries)
    if (entries.blogs.length > 0)
      $el.trigger("blog-update")
  }, function() { $el.trigger("blog-update") })

  return entries
}

exports.entries = entries
exports.edit = edit
exports.populate = populate

<|endoftext|>


<commit_before>'use strict';

var htmlHelper = {}

htmlHelper.adicionarCavaleiroComBotoes = function (cava) {
    var $cavaleiros = $('#cavaleiros');
    var $liCavaleiro = $('<li>').append(cava.Nome);
    $cavaleiros.append($liCavaleiro);
    idUltimoCavaleiro = cava.Id;

    var $btnExcluir = $("<button>").attr('data-id-btn', cava.Id).addClass('btn btn-danger').addClass("btnExcluir");
    $liCavaleiro.append($btnExcluir);
    $btnExcluir.click(excluirCavaleiro);
    $btnExcluir.text("Excluir");

    var $btnEditar = $("<button>").attr('data-id-btn', cava.Id).addClass('btn btn-danger').addClass("btnEditar");
    $liCavaleiro.append($btnEditar);
    $btnEditar.click(editarCavaleiro);
    $btnEditar.text("Editar");
};

htmlHelper.gerarInputUrl = function () {
    var $novoInput = $('<input>').attr('name', 'Imagens.imagem.Url')
                               .attr('type', 'text')
                               .attr("id", "Imagens_imagem_Url")
                               .attr('placeholder', 'Ex: bit.ly/shiryu.png')
                               .addClass("form-control").addClass("text-box").addClass("single-line");
    return $('<li>').append($novoInput);
}

htmlHelper.gerarInputThumb = function () {
    var $novoInput = $('<input>').attr('name', 'Imagens.imagem.IsThumb')
                                 .attr('type', 'checkbox')
                                 .attr("id", "Imagens.imagem.IsThumb")
                                 .attr("checked", "checked")
                                 .attr("data-val", "true")
                                 .attr("data-val-required", "The IsThumb field is required.")
                                 .attr("value", "true");
    return $('<li>').append($novoInput);
}

htmlHelper.gerarInputTexto = function () {
    var $novoInput = $('<input>').attr('name', 'Golpes.golpe')
                                 .attr('type', 'text')
                                 .attr("id", "Golpes_golpe")
                                 .attr('placeholder', 'Ex: Meteoro de pegasus')
                                 .addClass("form-control").addClass("text-box").addClass("single-line");
    return $('<li>').append($novoInput);
}

<commit_msg>refactor(html-helper): alterar id dos inputs baseado em alteração na model.<commit_after>'use strict';

var htmlHelper = {}

htmlHelper.adicionarCavaleiroComBotoes = function (cava) {
    var $cavaleiros = $('#cavaleiros');
    var $liCavaleiro = $('<li>').append(cava.Nome);
    $cavaleiros.append($liCavaleiro);
    idUltimoCavaleiro = cava.Id;

    var $btnExcluir = $("<button>").attr('data-id-btn', cava.Id).addClass('btn btn-danger').addClass("btnExcluir");
    $liCavaleiro.append($btnExcluir);
    $btnExcluir.click(excluirCavaleiro);
    $btnExcluir.text("Excluir");

    var $btnEditar = $("<button>").attr('data-id-btn', cava.Id).addClass('btn btn-danger').addClass("btnEditar");
    $liCavaleiro.append($btnEditar);
    $btnEditar.click(editarCavaleiro);
    $btnEditar.text("Editar");
};

htmlHelper.gerarInputUrl = function () {
    var $novoInput = $('<input>').attr('name', 'Imagens.imagem.Url')
                               .attr('type', 'text')
                               .attr("id", "Imagens_imagem_Url")
                               .attr('placeholder', 'Ex: bit.ly/shiryu.png')
                               .addClass("form-control").addClass("text-box").addClass("single-line");
    return $('<li>').append($novoInput);
}

htmlHelper.gerarInputThumb = function () {
    var $novoInput = $('<input>').attr('name', 'Imagens.imagem.IsThumb')
                                 .attr('type', 'checkbox')
                                 .attr("id", "Imagens.imagem.IsThumb")
                                 .attr("checked", "checked")
                                 .attr("data-val", "true")
                                 .attr("data-val-required", "The IsThumb field is required.")
                                 .attr("value", "true");
    return $('<li>').append($novoInput).append($("<label>").attr("for", "Imagens_imagem_IsThumb").text("IsThumb"));
}

htmlHelper.gerarInputTexto = function () {
    var $novoInput = $('<input>').attr('name', 'Golpes.golpe.Nome')
                                 .attr('type', 'text')
                                 .attr("id", "Golpes.golpe.Nome")
                                 .attr('placeholder', 'Ex: Meteoro de pegasus')
                                 .addClass("form-control").addClass("text-box").addClass("single-line");
    return $('<li>').append($novoInput);
}

<|endoftext|>


<commit_before>var express = require('express');

function router() {

  var parseDelay = function(delay) {
    var lowered = delay.toLowerCase();
    var hCount, mCount, sCount = 0;
    var pieces = null;
    var milliseconds = 0;

    // Test for disallowed characters
    if (/^[0-9hms]+$/.test(lowered) === false) {
      return null;
    }

    // Count occurrences of the letters 'h', 'm', and 's'
    for (var a=0; a<lowered.length; a++) {
      if (lowered[a] === 'h') { hCount++; }
      if (lowered[a] === 'm') { mCount++; }
      if (lowered[a] === 's') { sCount++; }
    }

    // Test for too many occurrences of the letters 'h', 'm', and 's'
    if (hCount > 1 || mCount > 1 || sCount > 1) {
      return null;
    }

    // Parse delay into pieces
    pieces = /^([0-9]+[h|m|s])?([0-9]+[h|m|s])?([0-9]+[h|m|s])?$/.exec(lowered);
    if (pieces === null) {
      return null;
    }

    // Calculate milliseconds from pieces
    for (var b=1; b<=3; b++) {
      if (pieces[b]) {
        if (pieces[b].slice(-1) === 'h') { milliseconds += pieces[b].slice(0, -1) * 1000 * 60 * 60; }
        if (pieces[b].slice(-1) === 'm') { milliseconds += pieces[b].slice(0, -1) * 1000 * 60; }
        if (pieces[b].slice(-1) === 's') { milliseconds += pieces[b].slice(0, -1) * 1000; }
      }
    }

    return milliseconds;
  };

  var cors = function(req, res, next) {
    if (req.method === 'OPTIONS') {
      /* Preflight */

      res.header('Access-Control-Allow-Origin', '*');
      res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS');
      if (req.headers['access-control-request-headers']) {
        res.header('Access-Control-Allow-Headers', req.headers['access-control-request-headers']);
      }

      res.send(204);

    } else {
      /* Simple */

      res.header('Access-Control-Allow-Origin', '*');
      // TODO Access-Control-Expose-Headers

      next();
    }
  };

  var delay = function(req, res, next) {
    var timeout = parseDelay(req.params.delay);

    if (timeout === null) {
      return res.send(400);
    }

    setTimeout(next, timeout);
  };

  var echo = function(req, res) {
    res.json(req.body);
  };

  var siteRouter = express.Router();

  siteRouter.all('*', cors);
  siteRouter.all('/:delay', delay, echo);
  siteRouter.all('/', echo);

  return siteRouter;
}

module.exports = router;<commit_msg>Switch from res.send() to res.json() in route handlers<commit_after>var express = require('express');

function router() {

  var parseDelay = function(delay) {
    var lowered = delay.toLowerCase();
    var hCount, mCount, sCount = 0;
    var pieces = null;
    var milliseconds = 0;

    // Test for disallowed characters
    if (/^[0-9hms]+$/.test(lowered) === false) {
      return null;
    }

    // Count occurrences of the letters 'h', 'm', and 's'
    for (var a=0; a<lowered.length; a++) {
      if (lowered[a] === 'h') { hCount++; }
      if (lowered[a] === 'm') { mCount++; }
      if (lowered[a] === 's') { sCount++; }
    }

    // Test for too many occurrences of the letters 'h', 'm', and 's'
    if (hCount > 1 || mCount > 1 || sCount > 1) {
      return null;
    }

    // Parse delay into pieces
    pieces = /^([0-9]+[h|m|s])?([0-9]+[h|m|s])?([0-9]+[h|m|s])?$/.exec(lowered);
    if (pieces === null) {
      return null;
    }

    // Calculate milliseconds from pieces
    for (var b=1; b<=3; b++) {
      if (pieces[b]) {
        if (pieces[b].slice(-1) === 'h') { milliseconds += pieces[b].slice(0, -1) * 1000 * 60 * 60; }
        if (pieces[b].slice(-1) === 'm') { milliseconds += pieces[b].slice(0, -1) * 1000 * 60; }
        if (pieces[b].slice(-1) === 's') { milliseconds += pieces[b].slice(0, -1) * 1000; }
      }
    }

    return milliseconds;
  };

  var cors = function(req, res, next) {
    if (req.method === 'OPTIONS') {
      /* Preflight */

      res.header('Access-Control-Allow-Origin', '*');
      res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS');
      if (req.headers['access-control-request-headers']) {
        res.header('Access-Control-Allow-Headers', req.headers['access-control-request-headers']);
      }

      res.send(204);

    } else {
      /* Simple */

      res.header('Access-Control-Allow-Origin', '*');
      // TODO Access-Control-Expose-Headers

      next();
    }
  };

  var delay = function(req, res, next) {
    var timeout = parseDelay(req.params.delay);

    if (timeout === null) {
      return res.json(400, { message: 'Invalid Delay' });
    }

    setTimeout(next, timeout);
  };

  var echo = function(req, res) {
    res.json(req.body);
  };

  var siteRouter = express.Router();

  siteRouter.all('*', cors);
  siteRouter.all('/:delay', delay, echo);
  siteRouter.all('/', echo);

  return siteRouter;
}

module.exports = router;<|endoftext|>