<commit_before>import Graph from '../graph.core'
import LRU from '../graph.lru'
import Plugin from './graph.plugin'
import * as util from '../graph.util'

/**
 * @class PluginTimeSerieManager
 * @implements Plugin
 */
class PluginTimeSerieManager extends Plugin {

  constructor() {

    super( ...arguments );

    this.series = [];
    this.plugins = [];
    this.currentSlots = {};

    this.requestLevels = {};
    this.update = ( noRecalculate, force ) => {

      this.series.forEach( function( serie ) {

        this.updateSerie( serie, noRecalculate );

      } );

      if ( !noRecalculate ) {
        this.recalculateSeries( force );
      }
    }

  }

  static defaults() {

    return {

      LRUName: "PluginTimeSerieManager",
      intervals: [ 1000, 15000, 60000, 900000, 3600000, 8640000 ],
      maxParallelRequests: 3,
      optimalPxPerPoint: 2,
      nbPoints: 1000,
      url: ""
    };
  }

  /**
   * Init method
   * @private
   * @memberof PluginTimeSerieManager
   */
  init( graph, options ) {
    this.graph = graph;
    LRU.create( this.options.LRUName, 200 );
    this.requestsRunning = 0;

  }

  setURL( url ) {
    this.options.url = url;
    return this;
  }

  setAvailableIntervals() {
    this.options.intervals = arguments;
  }

  newSerie( serieName, serieOptions, serieType, dbElements, noZoneSerie ) {
    var s = this.graph.newSerie( serieName, serieOptions, serieType );

    this.currentSlots[ serieName ] = {
      min: 0,
      max: 0,
      interval: 0
    };

    s.on( "hide", function() {

      if ( s._zoneSerie ) {

        s._zoneSerie.hide();
      }
    } );

    s.on( "show", function() {

      if ( s._zoneSerie ) {
        s._zoneSerie.show();
      }
    } );

    s.setInfo( "timeSerieManagerDBElements", dbElements );

    if ( !noZoneSerie ) {
      s._zoneSerie = this.graph.newSerie( serieName + "_zone", {}, Graph.SERIE_ZONE );
    }

    this.series.push( s );
    return s;
  }

  registerPlugin( plugin, event ) {

    var index;
    if ( ( index = this.plugins.indexOf( plugin ) ) > -1 ) {

      for ( var i = 1; i < arguments.length; i++ ) {
        plugin.removeListener( arguments[  i ], this.update );
      }
    }

    for ( var i = 1; i < arguments.length; i++ ) {
      plugin.on( arguments[  i ], this.update );
    }
  }

  updateSerie( serie, noRecalculate ) {

    var self = this;
    var from = serie.getXAxis().getCurrentMin();
    var to = serie.getXAxis().getCurrentMax();
    var priority = 1;

    var optimalInterval = this.getOptimalInterval( to - from );
    var optimalIntervalIndex = this.options.intervals.indexOf( optimalInterval );
    var interval;

    for ( var i = optimalIntervalIndex - 1; i <= optimalIntervalIndex + 1; i++ ) {

      interval = this.options.intervals[ i ];
      var startSlotId = self.computeSlotID( from, interval );
      var endSlotId = self.computeSlotID( to, interval );

      var intervalMultipliers = [
        [ 2, 5, 6 ],
        [ 1, 2, 4 ],
        [ 0, 1, 3 ]
      ];

      intervalMultipliers.forEach( function( multiplier ) {

        var firstSlotId = startSlotId - multiplier[ 0 ] * ( endSlotId - startSlotId );
        var lastSlotId = endSlotId + multiplier[ 0 ] * ( endSlotId - startSlotId );

        var slotId = firstSlotId;

        while ( slotId <= lastSlotId ) {

          if ( self.computeTimeMin( slotId, interval ) > Date.now() ) {
            break;
          }

          self.register( serie, slotId, interval, interval == optimalInterval ? multiplier[ 1 ] : multiplier[ 2 ], true, noRecalculate );
          slotId++;
        }

      } );

    }

    this.processRequests();
  }

  register( serie, slotId, interval, priority, noProcess, noRecalculate ) {

    var id = this.computeUniqueID( serie, slotId, interval );

    var data = LRU.get( this.options.LRUName, id );

    if ( !data || ( this.computeTimeMax( slotId, interval ) > Date.now() && data.timeout < ( Date.now() - ( noRecalculate ? 5000 : 100000 ) ) ) && priority == 1 ) {

      this.request( serie, slotId, interval, priority, id, noProcess );
    }
  }

  request( serie, slotId, interval, priority, slotName, noProcess ) {

    for ( var i in this.requestLevels ) {

      if ( i == priority ) {
        continue;
      }

      if ( this.requestLevels[ i ][ slotName ] ) {

        if ( this.requestLevels[ i ][ slotName ][ 0 ] !== 1 ) { // If the request is not pending

          delete this.requestLevels[ i ][ slotName ];

        } else {
          this.requestLevels[ i ][ slotName ][ 5 ] = priority;
        }

      }
    }

    if ( this.requestLevels[ priority ] && this.requestLevels[ priority ][ slotName ] ) {
      return;
    }

    this.requestLevels[ priority ] = this.requestLevels[ priority ] || {};
    this.requestLevels[ priority ][ slotName ] = [ 0, slotName, serie.getName(), slotId, interval, priority, serie.getInfo( 'timeSerieManagerDBElements' ) ];

    if ( !noProcess ) {
      this.processRequests();
    }
  }

  processRequests() {

    if ( this.requestsRunning >= this.options.maxParallelRequests ) {
      return;
    }

    var self = this,
      currentLevelChecking = 1,
      requestToMake;

    while ( true ) {

      for ( var i in this.requestLevels[ currentLevelChecking ] ) {

        if ( this.requestLevels[ currentLevelChecking ][ i ][ 0 ] == 1 ) { // Running request
          continue;
        }

        requestToMake = this.requestLevels[ currentLevelChecking ][ i ];
        break;
      }

      if ( requestToMake ) {
        break;
      }

      currentLevelChecking++;

      if ( currentLevelChecking > 10 ) {
        return;
      }

    }

    this.requestsRunning++;

    if ( !requestToMake ) {
      return;
    }

    requestToMake[ 0 ] = 1;

    util.ajaxGet( {

      url: this.getURL( requestToMake ),
      method: 'GET',
      json: true

    } ).done( function( data ) {

      if ( data.status == 1 ) { // Success

        self.requestsRunning--;

        delete self.requestLevels[ currentLevelChecking ][ i ];

        LRU.store( self.options.LRUName, requestToMake[ 1 ], data.data ); // Element 1 is the unique ID
        self.processRequests();

        if ( requestToMake[ 5 ] == 1 && Object.keys( self.requestLevels[ 1 ] ).length == 0 ) {

          self.recalculateSeries( true );
        }
      }

    } );
  }

  computeTimeMax( slotId, interval ) {
    return ( slotId + 1 ) * ( interval * this.options.nbPoints );
  }

  computeTimeMin( slotId, interval ) {
    return ( slotId ) * ( interval * this.options.nbPoints );
  }

  getURL( requestElements ) {

    var url = this.options.url
      .replace( "<measurementid>", requestElements[  2 ] )
      .replace( '<from>', this.computeTimeMin( requestElements[  3 ], requestElements[ 4 ] ) )
      .replace( '<to>', this.computeTimeMax( requestElements[  3 ], requestElements[ 4 ] ) )
      .replace( '<interval>', requestElements[  4 ] );

    var dbElements = requestElements[ 6 ] || {};

    for ( var i in dbElements ) {
      url = url.replace( "<" + i + ">", dbElements[ i ] );
    }

    return url;
  }

  getOptimalInterval( totalspan ) {

    var optimalInterval = ( this.options.optimalPxPerPoint ||  1 ) * totalspan / this.graph.getDrawingWidth(),
      diff = Infinity,
      optimalIntervalAmongAvailable;

    this.options.intervals.forEach( function( interval ) {

      var newDiff = Math.min( diff, Math.abs( interval - optimalInterval ) );
      if ( diff !== newDiff ) {

        optimalIntervalAmongAvailable = interval;
        diff = newDiff;
      }
    } );

    return optimalIntervalAmongAvailable ||  1000;
  }

  computeUniqueID( serie, slotId, interval ) {
    var extra = "";
    var info = serie.getInfo( 'timeSerieManagerDBElements' );
    for ( var i in info ) {
      extra += ";" + i + ":" + info[ i ];
    }

    return serie.getName() + ";" + slotId + ";" + interval + extra;
  }

  computeSlotID( time, interval ) {
    return Math.floor( time / ( interval * this.options.nbPoints ) );
  }

  computeSlotTime( slotId, interval ) {
    return slotId * ( interval * this.options.nbPoints );
  }

  getZoneSerie( serie ) {
    return serie._zoneSerie;
  }

  updateZoneSerie( serieName ) {

    var serie = this.graph.getSerie( serieName );

    if ( !serie ) {
      return;
    }

    if ( !serie._zoneSerie ) {
      return;
    }

    serie._zoneSerie.setXAxis( serie.getXAxis() );
    serie._zoneSerie.setYAxis( serie.getYAxis() );
    serie._zoneSerie.setFillColor( serie.getLineColor() );
    serie._zoneSerie.setLineColor( serie.getLineColor() );
    serie._zoneSerie.setFillOpacity( 0.2 );
    serie._zoneSerie.setLineOpacity( 0.3 );
  }

  recalculateSeries( force ) {

    var self = this;

    if ( this.locked ) {
      return;
    }

    this.changed = false;

    this.series.map( function( serie ) {
      self.recalculateSerie( serie, force );
    } );

    /*if ( this.changed ) {
        self.graph._applyToAxes( "scaleToFitAxis", [ this.graph.getXAxis(), false, undefined, undefined, false, true ], false, true );
      }
  */
    this.changed = false;
    //self.graph.autoscaleAxes();

    self.graph.draw();
  }

  recalculateSerie( serie, force ) {

    var from = serie.getXAxis().getCurrentMin(),
      to = serie.getXAxis().getCurrentMax(),
      interval = this.getOptimalInterval( to - from );

    var startSlotId = this.computeSlotID( from, interval );
    var endSlotId = this.computeSlotID( to, interval );

    var data = [];
    var dataMinMax = [];

    if ( !force && interval == this.currentSlots[ serie.getName() ].interval && this.currentSlots[ serie.getName() ].min <= startSlotId && this.currentSlots[ serie.getName() ].max >= endSlotId ) {
      return;
    }

    startSlotId -= 2;
    endSlotId += 2;

    this.currentSlots[ serie.getName() ].min = startSlotId;
    this.currentSlots[ serie.getName() ].max = endSlotId;
    this.currentSlots[ serie.getName() ].interval = interval;

    var slotId = startSlotId;

    while ( slotId <= endSlotId ) {

      const lruData = LRU.get( this.options.LRUName, this.computeUniqueID( serie, slotId, interval ) );
      if ( lruData ) {

        data = data.concat( lruData.data.mean );
        dataMinMax = dataMinMax.concat( lruData.data.minmax );

      } else {

        this.recalculateSerieUpwards( serie, slotId, interval, data, dataMinMax )
      }

      slotId++;
    }

    this.changed = true;

    serie.setData( data );

    if ( serie._zoneSerie ) {
      serie._zoneSerie.setData( dataMinMax );
    }
  }

  setIntervalCheck( interval ) {

    if ( this.interval ) {
      clearInterval( this.interval )
    }

    var self = this;

    this.interval = setInterval( function() {
      self.update( true, false );
    }, interval );
  }

  recalculateSerieUpwards( serie, downSlotId, downInterval, data, dataMinMax ) {

    var intervals = this.options.intervals.slice( 0 );
    intervals.sort();

    var nextInterval = intervals[ intervals.indexOf( downInterval ) + 1 ] ||  -1;
    if ( nextInterval < 0 ) {
      return [];
    }

    var newSlotTime = this.computeSlotTime( downSlotId, downInterval );
    var newSlotTimeEnd = this.computeSlotTime( downSlotId + 1, downInterval );
    var newSlotId = this.computeSlotID( newSlotTime, nextInterval ),
      start = false;

    const lruData = LRU.get( this.options.LRUName, this.computeUniqueID( serie, newSlotId, nextInterval ) );
    if ( lruData ) {

      for ( var i = 0, l = lruData.data.mean.length; i < l; i += 2 ) {

        if ( lruData.data.mean[ i ] < newSlotTime ) {
          continue;

        } else if ( start === false ) {
          start = i;
        }

        if ( lruData.data.mean[  i ] >= newSlotTimeEnd ) {

          data = data.concat( lruData.data.mean.slice( start, i ) );
          dataMinMax = data.concat( lruData.data.minmax.slice( start, i ) );

          return;
        }
      }
    }

    return this.recalculateSerieUpwards( serie, newSlotId, nextInterval, data, dataMinMax );
  }

  lockRedraw() {
    this.locked = true;
  }

  unlockRedraw() {
    this.locked = false;
  }

  isRedrawLocked() {
    return !!this.locked;
  }
}

export default PluginTimeSerieManager;<commit_msg>Update time serie manager<commit_after>import Graph from '../graph.core'
import LRU from '../graph.lru'
import Plugin from './graph.plugin'
import * as util from '../graph.util'

/**
 * @class PluginTimeSerieManager
 * @implements Plugin
 */
class PluginTimeSerieManager extends Plugin {

  constructor() {

    super( ...arguments );

    this.series = [];
    this.plugins = [];
    this.currentSlots = {};

    this.requestLevels = new Map();
    this.update = ( noRecalculate, force ) => {

      this.series.forEach( function( serie ) {

        this.updateSerie( serie, noRecalculate );

      } );

      if ( !noRecalculate ) {
        this.recalculateSeries( force );
      }
    }

  }

  static defaults() {

    return {

      LRUName: "PluginTimeSerieManager",
      intervals: [ 1000, 15000, 60000, 900000, 3600000, 8640000 ],
      maxParallelRequests: 3,
      optimalPxPerPoint: 2,
      nbPoints: 1000,
      url: ""
    };
  }

  /**
   * Init method
   * @private
   * @memberof PluginTimeSerieManager
   */
  init( graph, options ) {
    this.graph = graph;
    LRU.create( this.options.LRUName, 200 );
    this.requestsRunning = 0;

  }

  setURL( url ) {
    this.options.url = url;
    return this;
  }

  setAvailableIntervals() {
    this.options.intervals = arguments;
  }

  newSerie( serieName, serieOptions, serieType, dbElements, noZoneSerie ) {
    var s = this.graph.newSerie( serieName, serieOptions, serieType );

    this.currentSlots[ serieName ] = {
      min: 0,
      max: 0,
      interval: 0
    };

    s.on( "hide", function() {

      if ( s._zoneSerie ) {

        s._zoneSerie.hide();
      }
    } );

    s.on( "show", function() {

      if ( s._zoneSerie ) {
        s._zoneSerie.show();
      }
    } );

    s.setInfo( "timeSerieManagerDBElements", dbElements );

    if ( !noZoneSerie ) {
      s._zoneSerie = this.graph.newSerie( serieName + "_zone", {}, Graph.SERIE_ZONE );
    }

    this.series.push( s );
    return s;
  }

  registerPlugin( plugin, event ) {

    var index;
    if ( ( index = this.plugins.indexOf( plugin ) ) > -1 ) {

      for ( var i = 1; i < arguments.length; i++ ) {
        plugin.removeListener( arguments[  i ], this.update );
      }
    }

    for ( var i = 1; i < arguments.length; i++ ) {
      plugin.on( arguments[  i ], this.update );
    }
  }

  updateSerie( serie, noRecalculate ) {

    var self = this;
    var from = serie.getXAxis().getCurrentMin();
    var to = serie.getXAxis().getCurrentMax();
    var priority = 1;

    var optimalInterval = this.getOptimalInterval( to - from );
    var optimalIntervalIndex = this.options.intervals.indexOf( optimalInterval );
    var interval;

    this.cleanRegister( optimalIntervalIndex );

    for ( var i = optimalIntervalIndex; i <= optimalIntervalIndex + 1; i++ ) {

      interval = this.options.intervals[ i ];
      var startSlotId = self.computeSlotID( from, interval );
      var endSlotId = self.computeSlotID( to, interval );

      var intervalMultipliers = [
        [ 2, 5, 6 ],
        [ 1, 2, 4 ],
        [ 0, 1, 3 ]
      ];

      intervalMultipliers.forEach( function( multiplier ) {

        var firstSlotId = startSlotId - multiplier[ 0 ] * ( endSlotId - startSlotId );
        var lastSlotId = endSlotId + multiplier[ 0 ] * ( endSlotId - startSlotId );

        var slotId = firstSlotId;

        while ( slotId <= lastSlotId ) {

          if ( self.computeTimeMin( slotId, interval ) > Date.now() ) {
            break;
          }

          self.register( serie, slotId, interval, interval == optimalInterval ? multiplier[ 1 ] : multiplier[ 2 ], true, noRecalculate );
          slotId++;
        }

      } );

    }

    this.processRequests();
  }

  cleanRegister( interval ) {

     if( ! this.requestLevels ) {
       return;
     }

     this.requestLevels.forEach( ( levelArray ) => {

       levelArray.forEach( ( levelElement, levelIndex ) => {

         if( levelElement[ 4 ] < interval ) {
           levelArray.splice( levelIndex, 1 );
         }
       } );

     } );
   }

  register( serie, slotId, interval, priority, noProcess, noRecalculate ) {

    var id = this.computeUniqueID( serie, slotId, interval );

    var data = LRU.get( this.options.LRUName, id );

    if ( !data || ( this.computeTimeMax( slotId, interval ) > Date.now() && data.timeout < ( Date.now() - ( noRecalculate ? 5000 : 100000 ) ) ) && priority == 1 ) {

      this.request( serie, slotId, interval, priority, id, noProcess );
    }
  }

  request( serie, slotId, interval, priority, slotName, noProcess ) {

    for ( var i in this.requestLevels ) {

      if ( i == priority ) {
        continue;
      }

      if ( this.requestLevels[ i ][ slotName ] ) {

        if ( this.requestLevels[ i ][ slotName ][ 0 ] !== 1 ) { // If the request is not pending

          delete this.requestLevels[ i ][ slotName ];

        } else {
          this.requestLevels[ i ][ slotName ][ 5 ] = priority;
        }

      }
    }

    if ( this.requestLevels[ priority ] && this.requestLevels[ priority ][ slotName ] ) {
      return;
    }

    this.requestLevels[ priority ] = this.requestLevels[ priority ] || {};
    this.requestLevels[ priority ][ slotName ] = [ 0, slotName, serie.getName(), slotId, interval, priority, serie.getInfo( 'timeSerieManagerDBElements' ) ];

    if ( !noProcess ) {
      this.processRequests();
    }
  }

  processRequests() {

    if ( this.requestsRunning >= this.options.maxParallelRequests ) {
      return;
    }

    var self = this,
      currentLevelChecking = 1,
      requestToMake;

    while ( true ) {

      for ( var i in this.requestLevels[ currentLevelChecking ] ) {

        if ( this.requestLevels[ currentLevelChecking ][ i ][ 0 ] == 1 ) { // Running request
          continue;
        }

        requestToMake = this.requestLevels[ currentLevelChecking ][ i ];
        break;
      }

      if ( requestToMake ) {
        break;
      }

      currentLevelChecking++;

      if ( currentLevelChecking > 10 ) {
        return;
      }

    }

    this.requestsRunning++;

    if ( !requestToMake ) {
      return;
    }

    requestToMake[ 0 ] = 1;

    util.ajaxGet( {

      url: this.getURL( requestToMake ),
      method: 'GET',
      json: true

    } ).done( function( data ) {

      if ( data.status == 1 ) { // Success

        self.requestsRunning--;

        delete self.requestLevels[ currentLevelChecking ][ i ];

        LRU.store( self.options.LRUName, requestToMake[ 1 ], data.data ); // Element 1 is the unique ID
        self.processRequests();

        if ( requestToMake[ 5 ] == 1 && Object.keys( self.requestLevels[ 1 ] ).length == 0 ) {

          self.recalculateSeries( true );
        }
      }

    } );
  }

  computeTimeMax( slotId, interval ) {
    return ( slotId + 1 ) * ( interval * this.options.nbPoints );
  }

  computeTimeMin( slotId, interval ) {
    return ( slotId ) * ( interval * this.options.nbPoints );
  }

  getURL( requestElements ) {

    var url = this.options.url
      .replace( "<measurementid>", requestElements[  2 ] )
      .replace( '<from>', this.computeTimeMin( requestElements[  3 ], requestElements[ 4 ] ) )
      .replace( '<to>', this.computeTimeMax( requestElements[  3 ], requestElements[ 4 ] ) )
      .replace( '<interval>', requestElements[  4 ] );

    var dbElements = requestElements[ 6 ] || {};

    for ( var i in dbElements ) {
      url = url.replace( "<" + i + ">", dbElements[ i ] );
    }

    return url;
  }

  getOptimalInterval( totalspan ) {

    var optimalInterval = ( this.options.optimalPxPerPoint ||  1 ) * totalspan / this.graph.getDrawingWidth(),
      diff = Infinity,
      optimalIntervalAmongAvailable;

    this.options.intervals.forEach( function( interval ) {

      var newDiff = Math.min( diff, Math.abs( interval - optimalInterval ) );
      if ( diff !== newDiff ) {

        optimalIntervalAmongAvailable = interval;
        diff = newDiff;
      }
    } );

    return optimalIntervalAmongAvailable ||  1000;
  }

  computeUniqueID( serie, slotId, interval ) {
    var extra = "";
    var info = serie.getInfo( 'timeSerieManagerDBElements' );
    for ( var i in info ) {
      extra += ";" + i + ":" + info[ i ];
    }

    return serie.getName() + ";" + slotId + ";" + interval + extra;
  }

  computeSlotID( time, interval ) {
    return Math.floor( time / ( interval * this.options.nbPoints ) );
  }

  computeSlotTime( slotId, interval ) {
    return slotId * ( interval * this.options.nbPoints );
  }

  getZoneSerie( serie ) {
    return serie._zoneSerie;
  }

  updateZoneSerie( serieName ) {

    var serie = this.graph.getSerie( serieName );

    if ( !serie ) {
      return;
    }

    if ( !serie._zoneSerie ) {
      return;
    }

    serie._zoneSerie.setXAxis( serie.getXAxis() );
    serie._zoneSerie.setYAxis( serie.getYAxis() );
    serie._zoneSerie.setFillColor( serie.getLineColor() );
    serie._zoneSerie.setLineColor( serie.getLineColor() );
    serie._zoneSerie.setFillOpacity( 0.2 );
    serie._zoneSerie.setLineOpacity( 0.3 );
  }

  recalculateSeries( force ) {

    var self = this;

    if ( this.locked ) {
      return;
    }

    this.changed = false;

    this.series.map( function( serie ) {
      self.recalculateSerie( serie, force );
    } );

    /*if ( this.changed ) {
        self.graph._applyToAxes( "scaleToFitAxis", [ this.graph.getXAxis(), false, undefined, undefined, false, true ], false, true );
      }
  */
    this.changed = false;
    //self.graph.autoscaleAxes();

    self.graph.draw();
  }

  recalculateSerie( serie, force ) {

    var from = serie.getXAxis().getCurrentMin(),
      to = serie.getXAxis().getCurrentMax(),
      interval = this.getOptimalInterval( to - from );

    var startSlotId = this.computeSlotID( from, interval );
    var endSlotId = this.computeSlotID( to, interval );

    var data = [];
    var dataMinMax = [];

    if ( !force && interval == this.currentSlots[ serie.getName() ].interval && this.currentSlots[ serie.getName() ].min <= startSlotId && this.currentSlots[ serie.getName() ].max >= endSlotId ) {
      return;
    }

    startSlotId -= 2;
    endSlotId += 2;

    this.currentSlots[ serie.getName() ].min = startSlotId;
    this.currentSlots[ serie.getName() ].max = endSlotId;
    this.currentSlots[ serie.getName() ].interval = interval;

    var slotId = startSlotId;

    while ( slotId <= endSlotId ) {

      const lruData = LRU.get( this.options.LRUName, this.computeUniqueID( serie, slotId, interval ) );
      if ( lruData ) {

        data = data.concat( lruData.data.mean );
        dataMinMax = dataMinMax.concat( lruData.data.minmax );

      } else {

        this.recalculateSerieUpwards( serie, slotId, interval, data, dataMinMax )
      }

      slotId++;
    }

    this.changed = true;

    serie.setData( data );

    if ( serie._zoneSerie ) {
      serie._zoneSerie.setData( dataMinMax );
    }
  }

  setIntervalCheck( interval ) {

    if ( this.interval ) {
      clearInterval( this.interval )
    }

    this.update( true, true );
    this.interval = setInterval( () => {
      this.update( true, false );
    }, interval );
  }

  recalculateSerieUpwards( serie, downSlotId, downInterval, data, dataMinMax ) {

    var intervals = this.options.intervals.slice( 0 );
    intervals.sort();

    var nextInterval = intervals[ intervals.indexOf( downInterval ) + 1 ] ||  -1;
    if ( nextInterval < 0 ) {
      return [];
    }

    var newSlotTime = this.computeSlotTime( downSlotId, downInterval );
    var newSlotTimeEnd = this.computeSlotTime( downSlotId + 1, downInterval );
    var newSlotId = this.computeSlotID( newSlotTime, nextInterval ),
      start = false;

    const lruData = LRU.get( this.options.LRUName, this.computeUniqueID( serie, newSlotId, nextInterval ) );
    if ( lruData ) {

      for ( var i = 0, l = lruData.data.mean.length; i < l; i += 2 ) {

        if ( lruData.data.mean[ i ] < newSlotTime ) {
          continue;

        } else if ( start === false ) {
          start = i;
        }

        if ( lruData.data.mean[  i ] >= newSlotTimeEnd ) {

          data = data.concat( lruData.data.mean.slice( start, i ) );
          dataMinMax = data.concat( lruData.data.minmax.slice( start, i ) );

          return;
        }
      }
    }

    return this.recalculateSerieUpwards( serie, newSlotId, nextInterval, data, dataMinMax );
  }

  lockRedraw() {
    this.locked = true;
  }

  unlockRedraw() {
    this.locked = false;
  }

  isRedrawLocked() {
    return !!this.locked;
  }
}

export default PluginTimeSerieManager;<|endoftext|>


<commit_before>var EverestConfig = {
	endpoint: {

		base: "http://everest-build:8081" /*,
		patient: 	// show ability to extend
		*/
	}
};<commit_msg>Update port for services<commit_after>var EverestConfig = {
	endpoint: {

		base: "http://everest-build:8082" /*,
		patient: 	// show ability to extend
		*/
	}
};<|endoftext|>


<commit_before>var schema = require('../schema')
  , RandExp = require('randexp')
  , utils = require('../utils')
  , anything = require('./anything')
  , nothing = require('./nothing')
  , _ = require('underscore')

var ObjectSchema = module.exports = function(properties, other) {
  var self = this

  this.other = other || anything
  this.properties = properties || []

  // Sorting properties into two groups
  this.stringProps = {}, this.regexpProps = []
  this.properties.forEach(function(property) {
    if (typeof property.key === 'string') {
      self.stringProps[property.key] = property
    } else {
      self.regexpProps.push(property)
    }
  })

  return new schema(this)
}

ObjectSchema.prototype = {
  compile : function() {
    var checks = ['instance != null']
      , references = []
      , ref = utils.referenceHandler(references)

    // Simple string properties
    var check
    for (var key in this.stringProps) {
      check = '{schema}(instance[{key}])'.replace('{schema}', ref(this.stringProps[key].value))
                                         .replace('{key}', ref(key))
      if (this.stringProps[key].min === 0) {
        check = '(instance[{key}] === undefined || {check})'.replace('{key}', ref(key))
                                                            .replace('{check}', check)
      }
      checks.push(check)
    }

    if (!this.regexpProps.length && this.other === anything) {
      return { references : references, expression : checks.join(' && ') }
    }

    // Regexp and other properties
    var stringPropNames = Object.keys(this.stringProps)

    var fn = 'if (!( {checks} )) return false;'.replace('{checks}', checks.join(' && '))

    if (this.other !== anything) fn += 'var checked;'

    // Iterating over the keys in the instance
    fn += 'for (var key in instance) {'

      // Checking the key against every key regexps
      if (this.other !== anything) fn += 'checked = false;'
      for (var i = 0; i < this.regexpProps.length; i++) {
        if (this.other !== anything) {
          check = '({regexp}.test(key) && (checked = true)) && !{schema}(instance[key])'
        } else {
          check = '{regexp}.test(key) && !{schema}(instance[key])'
        }
        check = 'if (' + check + ') return false;'
        fn += check.replace('{regexp}', ref(this.regexpProps[i].key))
                   .replace('{schema}', ref(this.regexpProps[i].value))
      }

      // If the key is not matched by regexps and by simple string checks
      // then check it against this.other
      if (this.other !== anything) {
        check = '!checked && {stringProps}.indexOf(key) === -1 && !{other}(instance[key])'
        check = 'if (' + check + ') return false;'
        fn += check.replace('{stringProps}', ref(stringPropNames))
                   .replace('{other}', ref(this.other))
      }

    fn += '}'
    // Iteration ends

    // If all checks passed, the instance conforms to the schema
    fn += 'return true;'

    return { references : references, fn : fn }
  },

  generate : function() {
    var object = {}

    for (var key in this.stringProps) {
      if (this.stringProps[key].min === 1 || Math.random() < 0.5) {
        object[key] = this.stringProps[key].value.generate()
      }
    }

    var n, property, randexp
    for (var i = 0; i < this.regexpProps.length; i++) {
      property = this.regexpProps[i]
      n = Object.keys(object).filter(function(ikey){ return property.key.test(ikey) }).length

      randexp = new RandExp(property.key)
      while (n < property.min || (n < property.max && Math.random() < 0.5)) {
        key = randexp.gen()
        if (key in object) continue

        object[key] = property.value.generate()
        n += 1
      }
    }

    if (this.other !== nothing) {
      while (Math.random() < 0.5) {
        key = String.schema.generate()
        if (!(key in object)) object[key] = this.other.generate()
      }
    }

    return object
  },

  leafs : function() {
    var certain = [], uncertain = []

    this.properties.forEach(function(property) {
      var property_leafs = property.value.leafs ? property.value.leafs()
                                                : { certain : [ property.value ], uncertain : [] }

      if (property.min > 0) {
        certain.push(property_leafs.certain)
        uncertain.push(property_leafs.uncertain)
      } else {
        uncertain.push(property_leafs.uncertain)
        uncertain.push(property_leafs.certain)
      }
    })

    return { certain : _.union.apply(null, certain)
           , uncertain : _.union.apply(null, uncertain.concat([this.other]))
           }
  },

  getId : function() {
    if (!this.id) this.id = new RandExp(/^[a-zA-Z]{4,6}$/).gen()

    return this.id
  },

  toJSON : function() {
    var i, property, regexp, json = { type : 'object' }

    for (i in this.stringProps) {
      property = this.stringProps[i]
      json.properties = json.properties || {}
      json.properties[property.key] = property.value.toJSON()
      if (property.min === 1) json.properties[property.key].required = true
      if (property.description) json.properties[property.key].description = property.description
    }

    for (i = 0; i < this.regexpProps.length; i++) {
      property = this.regexpProps[i]
      json.patternProperties = json.patternProperties || {}
      regexp = property.key.toString()
      regexp = regexp.substr(2, regexp.length - 4)
      json.patternProperties[regexp] = property.value.toJSON()
      if (property.description) json.patternProperties[regexp].description = property.description
    }

    if (this.other !== anything) {
      json.additionalProperties = (this.other === nothing) ? false : this.other.toJSON()
    }

    if (this.id) json.id = this.id

    return json
  }
}

// Testing if a given string is a real regexp or just a single string escaped
// If it is just a string escaped, return the string. Otherwise return the regexp
var regexpString = (function() {
  // Special characters that should be escaped when describing a regular string in regexp
  var shouldBeEscaped = '[](){}^$?*+.'.split('').map(function(element) {
        return RegExp('(\\\\)*\\' + element, 'g')
      })
  // Special characters that shouldn't be escaped when describing a regular string in regexp
  var shouldntBeEscaped = 'bBwWdDsS'.split('').map(function(element) {
        return RegExp('(\\\\)*' + element, 'g')
      })

  return function(string) {
    var i, j, match

    for (i = 0; i < shouldBeEscaped.length; i++) {
      match = string.match(shouldBeEscaped[i])
      if (!match) continue
      for (j = 0; j < match.length; j++) {
        // If it is not escaped, it must be a regexp (e.g. [, \\[, \\\\[, etc.)
        if (match[j].length % 2 === 1) return RegExp('^' + string + '$')
      }
    }
    for (i = 0; i < shouldntBeEscaped.length; i++) {
      match = string.match(shouldntBeEscaped[i])
      if (!match) continue
      for (j = 0; j < match.length; j++) {
        // If it is escaped, it must be a regexp (e.g. \b, \\\b, \\\\\b, etc.)
        if (match[j].length % 2 === 0) return RegExp('^' + string + '$')
      }
    }

    // It is not a real regexp. Removing the escaping.
    for (i = 0; i < shouldBeEscaped.length; i++) {
      string = string.replace(shouldBeEscaped[i], function(match) {
        return match.substr(1)
      })
    }

    return string
  }
})()

schema.fromJS.def(function(object) {
  if (!(object instanceof Object)) return

  var other, property, properties = []
  for (var key in object) {
    property = { value : schema.fromJS(object[key]) }

    // '*' as property name means 'every other property should match this schema'
    if (key === '*') {
      other = property.value
      continue
    }

    // Handling special chars at the beginning of the property name
    key = key.replace(/^[*?+]/, function(first) {
      property.min = (first === '*' || first === '?') ? 0 : 1
      property.max = (first === '*' || first === '+') ? Infinity : 1
      return ''
    })

    // Handling property description that looks like: { 'a : an important property' : Number }
    key = key.replace(/\s*:[^:]+$/, function(match) {
      property.description = match.replace(/^\s*:\s*/, '')
      return ''
    })

    // Testing if it is regexp-like or not. If it is, then converting to a regexp object
    property.key = regexpString(key)

    properties.push(property)
  }

  return new ObjectSchema(properties, other)
})

schema.fromJSON.def(function(json) {
  if (!json || json.type !== 'object') return

  var key, properties = []
  for (key in json.properties) {
    properties.push({ min : json.properties[key].required ? 1 : 0
                    , max : 1
                    , key : key
                    , value : schema.fromJSON(json.properties[key])
                    , description : json.properties[key].description
                    })
  }
  for (key in json.patternProperties) {
    properties.push({ min : 0
                    , max : Infinity
                    , key : RegExp('^' + key + '$')
                    , value : schema.fromJSON(json.properties[key])
                    , description : json.patternProperties[key].description
                    })
  }

  var other
  if (json.additionalProperties !== undefined) {
    other = json.additionalProperties === false ? nothing : schema.fromJSON(json.additionalProperties)
  }

  return new ObjectSchema(properties, other)
})
<commit_msg>Fixing a bug in object.js fromJSON.<commit_after>var schema = require('../schema')
  , RandExp = require('randexp')
  , utils = require('../utils')
  , anything = require('./anything')
  , nothing = require('./nothing')
  , _ = require('underscore')

var ObjectSchema = module.exports = function(properties, other) {
  var self = this

  this.other = other || anything
  this.properties = properties || []

  // Sorting properties into two groups
  this.stringProps = {}, this.regexpProps = []
  this.properties.forEach(function(property) {
    if (typeof property.key === 'string') {
      self.stringProps[property.key] = property
    } else {
      self.regexpProps.push(property)
    }
  })

  return new schema(this)
}

ObjectSchema.prototype = {
  compile : function() {
    var checks = ['instance != null']
      , references = []
      , ref = utils.referenceHandler(references)

    // Simple string properties
    var check
    for (var key in this.stringProps) {
      check = '{schema}(instance[{key}])'.replace('{schema}', ref(this.stringProps[key].value))
                                         .replace('{key}', ref(key))
      if (this.stringProps[key].min === 0) {
        check = '(instance[{key}] === undefined || {check})'.replace('{key}', ref(key))
                                                            .replace('{check}', check)
      }
      checks.push(check)
    }

    if (!this.regexpProps.length && this.other === anything) {
      return { references : references, expression : checks.join(' && ') }
    }

    // Regexp and other properties
    var stringPropNames = Object.keys(this.stringProps)

    var fn = 'if (!( {checks} )) return false;'.replace('{checks}', checks.join(' && '))

    if (this.other !== anything) fn += 'var checked;'

    // Iterating over the keys in the instance
    fn += 'for (var key in instance) {'

      // Checking the key against every key regexps
      if (this.other !== anything) fn += 'checked = false;'
      for (var i = 0; i < this.regexpProps.length; i++) {
        if (this.other !== anything) {
          check = '({regexp}.test(key) && (checked = true)) && !{schema}(instance[key])'
        } else {
          check = '{regexp}.test(key) && !{schema}(instance[key])'
        }
        check = 'if (' + check + ') return false;'
        fn += check.replace('{regexp}', ref(this.regexpProps[i].key))
                   .replace('{schema}', ref(this.regexpProps[i].value))
      }

      // If the key is not matched by regexps and by simple string checks
      // then check it against this.other
      if (this.other !== anything) {
        check = '!checked && {stringProps}.indexOf(key) === -1 && !{other}(instance[key])'
        check = 'if (' + check + ') return false;'
        fn += check.replace('{stringProps}', ref(stringPropNames))
                   .replace('{other}', ref(this.other))
      }

    fn += '}'
    // Iteration ends

    // If all checks passed, the instance conforms to the schema
    fn += 'return true;'

    return { references : references, fn : fn }
  },

  generate : function() {
    var object = {}

    for (var key in this.stringProps) {
      if (this.stringProps[key].min === 1 || Math.random() < 0.5) {
        object[key] = this.stringProps[key].value.generate()
      }
    }

    var n, property, randexp
    for (var i = 0; i < this.regexpProps.length; i++) {
      property = this.regexpProps[i]
      n = Object.keys(object).filter(function(ikey){ return property.key.test(ikey) }).length

      randexp = new RandExp(property.key)
      while (n < property.min || (n < property.max && Math.random() < 0.5)) {
        key = randexp.gen()
        if (key in object) continue

        object[key] = property.value.generate()
        n += 1
      }
    }

    if (this.other !== nothing) {
      while (Math.random() < 0.5) {
        key = String.schema.generate()
        if (!(key in object)) object[key] = this.other.generate()
      }
    }

    return object
  },

  leafs : function() {
    var certain = [], uncertain = []

    this.properties.forEach(function(property) {
      var property_leafs = property.value.leafs ? property.value.leafs()
                                                : { certain : [ property.value ], uncertain : [] }

      if (property.min > 0) {
        certain.push(property_leafs.certain)
        uncertain.push(property_leafs.uncertain)
      } else {
        uncertain.push(property_leafs.uncertain)
        uncertain.push(property_leafs.certain)
      }
    })

    return { certain : _.union.apply(null, certain)
           , uncertain : _.union.apply(null, uncertain.concat([this.other]))
           }
  },

  getId : function() {
    if (!this.id) this.id = new RandExp(/^[a-zA-Z]{4,6}$/).gen()

    return this.id
  },

  toJSON : function() {
    var i, property, regexp, json = { type : 'object' }

    for (i in this.stringProps) {
      property = this.stringProps[i]
      json.properties = json.properties || {}
      json.properties[property.key] = property.value.toJSON()
      if (property.min === 1) json.properties[property.key].required = true
      if (property.description) json.properties[property.key].description = property.description
    }

    for (i = 0; i < this.regexpProps.length; i++) {
      property = this.regexpProps[i]
      json.patternProperties = json.patternProperties || {}
      regexp = property.key.toString()
      regexp = regexp.substr(2, regexp.length - 4)
      json.patternProperties[regexp] = property.value.toJSON()
      if (property.description) json.patternProperties[regexp].description = property.description
    }

    if (this.other !== anything) {
      json.additionalProperties = (this.other === nothing) ? false : this.other.toJSON()
    }

    if (this.id) json.id = this.id

    return json
  }
}

// Testing if a given string is a real regexp or just a single string escaped
// If it is just a string escaped, return the string. Otherwise return the regexp
var regexpString = (function() {
  // Special characters that should be escaped when describing a regular string in regexp
  var shouldBeEscaped = '[](){}^$?*+.'.split('').map(function(element) {
        return RegExp('(\\\\)*\\' + element, 'g')
      })
  // Special characters that shouldn't be escaped when describing a regular string in regexp
  var shouldntBeEscaped = 'bBwWdDsS'.split('').map(function(element) {
        return RegExp('(\\\\)*' + element, 'g')
      })

  return function(string) {
    var i, j, match

    for (i = 0; i < shouldBeEscaped.length; i++) {
      match = string.match(shouldBeEscaped[i])
      if (!match) continue
      for (j = 0; j < match.length; j++) {
        // If it is not escaped, it must be a regexp (e.g. [, \\[, \\\\[, etc.)
        if (match[j].length % 2 === 1) return RegExp('^' + string + '$')
      }
    }
    for (i = 0; i < shouldntBeEscaped.length; i++) {
      match = string.match(shouldntBeEscaped[i])
      if (!match) continue
      for (j = 0; j < match.length; j++) {
        // If it is escaped, it must be a regexp (e.g. \b, \\\b, \\\\\b, etc.)
        if (match[j].length % 2 === 0) return RegExp('^' + string + '$')
      }
    }

    // It is not a real regexp. Removing the escaping.
    for (i = 0; i < shouldBeEscaped.length; i++) {
      string = string.replace(shouldBeEscaped[i], function(match) {
        return match.substr(1)
      })
    }

    return string
  }
})()

schema.fromJS.def(function(object) {
  if (!(object instanceof Object)) return

  var other, property, properties = []
  for (var key in object) {
    property = { value : schema.fromJS(object[key]) }

    // '*' as property name means 'every other property should match this schema'
    if (key === '*') {
      other = property.value
      continue
    }

    // Handling special chars at the beginning of the property name
    key = key.replace(/^[*?+]/, function(first) {
      property.min = (first === '*' || first === '?') ? 0 : 1
      property.max = (first === '*' || first === '+') ? Infinity : 1
      return ''
    })

    // Handling property description that looks like: { 'a : an important property' : Number }
    key = key.replace(/\s*:[^:]+$/, function(match) {
      property.description = match.replace(/^\s*:\s*/, '')
      return ''
    })

    // Testing if it is regexp-like or not. If it is, then converting to a regexp object
    property.key = regexpString(key)

    properties.push(property)
  }

  return new ObjectSchema(properties, other)
})

schema.fromJSON.def(function(json) {
  if (!json || json.type !== 'object') return

  var key, properties = []
  for (key in json.properties) {
    properties.push({ min : json.properties[key].required ? 1 : 0
                    , max : 1
                    , key : key
                    , value : schema.fromJSON(json.properties[key])
                    , description : json.properties[key].description
                    })
  }
  for (key in json.patternProperties) {
    properties.push({ min : 0
                    , max : Infinity
                    , key : RegExp('^' + key + '$')
                    , value : schema.fromJSON(json.patternProperties[key])
                    , description : json.patternProperties[key].description
                    })
  }

  var other
  if (json.additionalProperties !== undefined) {
    other = json.additionalProperties === false ? nothing : schema.fromJSON(json.additionalProperties)
  }

  return new ObjectSchema(properties, other)
})
<|endoftext|>


<commit_before>const varuint = require('varuint-bitcoin')
const Buffer = require('safe-buffer').Buffer

const txHex = '0100000001545f6161d2be3bdfe7184ee1f72123c3918738da8b97f11e23acdd34059f7a2d010000006b4830450221008c33d765ae16cfa3cc653c5c039d58131fbbdf76266af7a76910fc1ba39de0b8022048ae83fc9b82f62b816641158dd1cfd398d2c56d5f6f812c9fa588947311d8400121033701fc7f242ae2dd63a18753518b6d1425e53496878924b6c0dc08d800af46adffffffff0200e1f505000000001976a91461ca8116d03694952a3ad252d53c695da7d95f6188ac18ddf505000000001976a9145e9f5c8cc17ecaaea1b4e5a3d091ca0aed1342f788ac00000000'
const buffer = Buffer.from(txHex, 'hex')
let offset = 0

const version = buffer.readInt32LE(offset)
offset += 4

// VIN
const vinLen = varuint.decode(buffer, offset)
offset += varuint.decode.bytes
console.log(`vinLen bytes = ${varuint.decode.bytes}`)

const hash = buffer.slice(offset, 32)
offset += 32

const index = buffer.readUInt32LE(offset)
offset += 4

const scriptLen = varuint.decode(buffer, offset)
offset += varuint.decode.bytes
console.log(`scriptLen bytes = ${varuint.decode.bytes}`)

const script = buffer.slice(offset, scriptLen)
offset += scriptLen

const sequence = buffer.readUInt32LE(offset)
offset += 4

// VOUT-1
const voutLen = varuint.decode(buffer, offset)
offset += varuint.decode.bytes

const valueA = buffer.readUInt32LE(offset)
const valueB = buffer.readUInt32LE(offset + 4)
const valueB2 = valueB * 0x100000000
const value = valueA + valueB2
offset += 8

const lockingScriptLen = varuint.decode(buffer, offset)
offset += varuint.decode.bytes
console.log(`lockingScriptLen bytes = ${varuint.decode.bytes}`)

console.log(`*** lockingScript ::: offset=${offset}, lockingScriptLen=${lockingScriptLen}, buffer.length=${buffer.length}`)
const lockingScript = buffer.slice(offset, lockingScriptLen)
offset += lockingScriptLen

// script: readVarSlice()

console.log(`version = ${version}`)
console.log(`vinLen = ${vinLen}`)
console.log(`hash = ${hash.toString('hex')}`)
console.log(`index = ${index}`)
console.log(`scriptLen = ${scriptLen}`)
console.log(`script = ${script.toString('hex')}`)
console.log(`sequence = ${sequence}`)
console.log(`voutLen = ${voutLen}`)
console.log(`valueA = ${valueA}`)
console.log(`valueB = ${valueB}`)
console.log(`valueB2 = ${valueB2}`)
console.log(`value = ${value}`)
console.log(`lockingScriptLen = ${lockingScriptLen}`)
console.log(`lockingScript hex = ${lockingScript.toString('hex')}`)
console.log(`lockingScript = ${lockingScript}`)
console.log(`BUFFER LEFT = ${buffer.slice(offset).toString('hex')}`)<commit_msg>fixed manual decoding<commit_after>const varuint = require('varuint-bitcoin')
const Buffer = require('safe-buffer').Buffer

const txHex = '0100000001545f6161d2be3bdfe7184ee1f72123c3918738da8b97f11e23acdd34059f7a2d010000006b4830450221008c33d765ae16cfa3cc653c5c039d58131fbbdf76266af7a76910fc1ba39de0b8022048ae83fc9b82f62b816641158dd1cfd398d2c56d5f6f812c9fa588947311d8400121033701fc7f242ae2dd63a18753518b6d1425e53496878924b6c0dc08d800af46adffffffff0200e1f505000000001976a91461ca8116d03694952a3ad252d53c695da7d95f6188ac18ddf505000000001976a9145e9f5c8cc17ecaaea1b4e5a3d091ca0aed1342f788ac00000000'
const buffer = Buffer.from(txHex, 'hex')
let offset = 0

const version = buffer.readInt32LE(offset)
offset += 4

// VIN
const vinLen = varuint.decode(buffer, offset)
offset += varuint.decode.bytes
console.log(`vinLen bytes = ${varuint.decode.bytes}`)

const hash = buffer.slice(offset, offset + 32)
offset += 32

const index = buffer.readUInt32LE(offset)
offset += 4

const scriptLen = varuint.decode(buffer, offset)
offset += varuint.decode.bytes
console.log(`scriptLen bytes = ${varuint.decode.bytes}`)

const script = buffer.slice(offset, offset + scriptLen)
offset += scriptLen

const sequence = buffer.readUInt32LE(offset)
offset += 4

// VOUT
const voutLen = varuint.decode(buffer, offset)
offset += varuint.decode.bytes

// VOUT-1
const valueA = buffer.readUInt32LE(offset)
const valueB = buffer.readUInt32LE(offset + 4)
const valueBB = valueB * 0x100000000
const value = valueA + valueBB
offset += 8

const lockingScriptLen = varuint.decode(buffer, offset)
offset += varuint.decode.bytes

const lockingScript = buffer.slice(offset, offset + lockingScriptLen)
offset += lockingScriptLen

// VOUT-2
const valueA2 = buffer.readUInt32LE(offset)
const valueB2 = buffer.readUInt32LE(offset + 4)
const valueBB2 = valueB2 * 0x100000000
const value2 = valueA2 + valueBB2
offset += 8

const lockingScriptLen2 = varuint.decode(buffer, offset)
offset += varuint.decode.bytes

const lockingScript2 = buffer.slice(offset, offset + lockingScriptLen2)
offset += lockingScriptLen2

// Locktime
const locktime = buffer.readUInt32LE(offset)
offset += 4

console.log(`version = ${version}`)
console.log(`vinLen = ${vinLen}`)
console.log(`hash = ${hash.toString('hex')}`)
console.log(`index = ${index}`)
console.log(`scriptLen = ${scriptLen}`)
console.log(`script = ${script.toString('hex')}`)
console.log(`sequence = ${sequence}`)
console.log(`voutLen = ${voutLen}`)
console.log(`valueA = ${valueA}`)
console.log(`valueB = ${valueB}`)
console.log(`valueB2 = ${valueBB}`)
console.log(`value = ${value}`)
console.log(`lockingScriptLen = ${lockingScriptLen}`)
console.log(`lockingScript = ${lockingScript.toString('hex')}`)
console.log(`value2 = ${value2}`)
console.log(`lockingScriptLen2 = ${lockingScriptLen2}`)
console.log(`lockingScriptLen2 = ${lockingScriptLen2}`)
console.log(`lockingScript2 = ${lockingScript2.toString('hex')}`)
console.log(`locktime = ${locktime}`)

console.log(`BUFFER LEFT = ${buffer.slice(offset).toString('hex')}`)<|endoftext|>


<commit_before>import Media from '../mixin/media';
import {getMaxPathLength} from '../core/svg';
import {css, Dimensions, each, isNumber, isString, isUndefined, startsWith, toFloat, toPx, ucfirst} from 'uikit-util';

const props = ['x', 'y', 'bgx', 'bgy', 'rotate', 'scale', 'color', 'backgroundColor', 'borderColor', 'opacity', 'blur', 'hue', 'grayscale', 'invert', 'saturate', 'sepia', 'fopacity', 'stroke'];

export default {

    mixins: [Media],

    props: props.reduce((props, prop) => {
        props[prop] = 'list';
        return props;
    }, {}),

    data: props.reduce((data, prop) => {
        data[prop] = undefined;
        return data;
    }, {}),

    computed: {

        props(properties, $el) {

            return props.reduce((props, prop) => {

                if (isUndefined(properties[prop])) {
                    return props;
                }

                const isColor = prop.match(/color/i);
                const isCssProp = isColor || prop === 'opacity';

                let pos, bgPos, diff;
                let steps = properties[prop].slice(0);

                if (isCssProp) {
                    css($el, prop, '');
                }

                if (steps.length < 2) {
                    steps.unshift((prop === 'scale'
                        ? 1
                        : isCssProp
                            ? css($el, prop)
                            : 0) || 0);
                }

                const unit = getUnit(steps, prop);

                if (isColor) {

                    const {color} = $el.style;
                    steps = steps.map(step => parseColor($el, step));
                    $el.style.color = color;

                } else if (startsWith(prop, 'bg')) {

                    const attr = prop === 'bgy' ? 'height' : 'width';
                    steps = steps.map(step => toPx(step, attr, this.$el));

                    css($el, `background-position-${prop[2]}`, '');
                    bgPos = css($el, 'backgroundPosition').split(' ')[prop[2] === 'x' ? 0 : 1]; // IE 11 can't read background-position-[x|y]

                    if (this.covers) {

                        const min = Math.min(...steps);
                        const max = Math.max(...steps);
                        const down = steps.indexOf(min) < steps.indexOf(max);

                        diff = max - min;

                        steps = steps.map(step => step - (down ? min : max));
                        pos = `${down ? -diff : 0}px`;

                    } else {

                        pos = bgPos;

                    }

                } else {

                    steps = steps.map(toFloat);

                }

                if (prop === 'stroke') {

                    const length = getMaxPathLength(this.$el);
                    css($el, 'strokeDasharray', length);

                    if (unit === '%') {
                        steps = steps.map(step => step * length / 100);
                    }

                    steps = steps.reverse();

                    prop = 'strokeDashoffset';
                }

                props[prop] = {steps, unit, pos, bgPos, diff};

                return props;

            }, {});

        },

        bgProps() {
            return ['bgx', 'bgy'].filter(bg => bg in this.props);
        },

        covers(_, $el) {
            return covers($el);
        }

    },

    disconnected() {
        delete this._image;
    },

    update: {

        read(data) {

            data.active = this.matchMedia;

            if (!data.active) {
                return;
            }

            if (!data.image && this.covers && this.bgProps.length) {
                const src = css(this.$el, 'backgroundImage').replace(/^none|url\(["']?(.+?)["']?\)$/, '$1');

                if (src) {
                    const img = new Image();
                    img.src = src;
                    data.image = img;

                    if (!img.naturalWidth) {
                        img.onload = () => this.$emit();
                    }
                }

            }

            const {image} = data;

            if (!image || !image.naturalWidth) {
                return;
            }

            const dimEl = {
                width: this.$el.offsetWidth,
                height: this.$el.offsetHeight
            };
            const dimImage = {
                width: image.naturalWidth,
                height: image.naturalHeight
            };

            let dim = Dimensions.cover(dimImage, dimEl);

            this.bgProps.forEach(prop => {

                const {diff, bgPos, steps} = this.props[prop];
                const attr = prop === 'bgy' ? 'height' : 'width';
                const span = dim[attr] - dimEl[attr];

                if (span < diff) {
                    dimEl[attr] = dim[attr] + diff - span;
                } else if (span > diff) {

                    const posPercentage = dimEl[attr] / toPx(bgPos, attr, this.$el);

                    if (posPercentage) {
                        this.props[prop].steps = steps.map(step => step - (span - diff) / posPercentage);
                    }
                }

                dim = Dimensions.cover(dimImage, dimEl);
            });

            data.dim = dim;
        },

        write({dim, active}) {

            if (!active) {
                css(this.$el, {backgroundSize: '', backgroundRepeat: ''});
                return;
            }

            dim && css(this.$el, {
                backgroundSize: `${dim.width}px ${dim.height}px`,
                backgroundRepeat: 'no-repeat'
            });

        },

        events: ['resize']

    },

    methods: {

        reset() {
            each(this.getCss(0), (_, prop) => css(this.$el, prop, ''));
        },

        getCss(percent) {

            const {props} = this;
            return Object.keys(props).reduce((css, prop) => {

                let {steps, unit, pos} = props[prop];
                const value = getValue(steps, percent);

                switch (prop) {

                    // transforms
                    case 'x':
                    case 'y': {
                        unit = unit || 'px';
                        css.transform += ` translate${ucfirst(prop)}(${
                            toFloat(value).toFixed(unit === 'px' ? 0 : 2)
                        }${unit})`;
                        break;
                    }
                    case 'rotate':
                        unit = unit || 'deg';
                        css.transform += ` rotate(${value + unit})`;
                        break;
                    case 'scale':
                        css.transform += ` scale(${value})`;
                        break;

                    // bg image
                    case 'bgy':
                    case 'bgx':
                        css[`background-position-${prop[2]}`] = `calc(${pos} + ${value}px)`;
                        break;

                    // color
                    case 'color':
                    case 'backgroundColor':
                    case 'borderColor': {

                        const [start, end, p] = getStep(steps, percent);

                        css[prop] = `rgba(${
                            start.map((value, i) => {
                                value = value + p * (end[i] - value);
                                return i === 3 ? toFloat(value) : parseInt(value, 10);
                            }).join(',')
                        })`;
                        break;
                    }
                    // CSS Filter
                    case 'blur':
                        unit = unit || 'px';
                        css.filter += ` blur(${value + unit})`;
                        break;
                    case 'hue':
                        unit = unit || 'deg';
                        css.filter += ` hue-rotate(${value + unit})`;
                        break;
                    case 'fopacity':
                        unit = unit || '%';
                        css.filter += ` opacity(${value + unit})`;
                        break;
                    case 'grayscale':
                    case 'invert':
                    case 'saturate':
                    case 'sepia':
                        unit = unit || '%';
                        css.filter += ` ${prop}(${value + unit})`;
                        break;
                    default:
                        css[prop] = value;
                }

                return css;

            }, {transform: '', filter: ''});

        }

    }

};

function parseColor(el, color) {
    return css(css(el, 'color', color), 'color')
        .split(/[(),]/g)
        .slice(1, -1)
        .concat(1)
        .slice(0, 4)
        .map(toFloat);
}

function getStep(steps, percent) {
    const count = steps.length - 1;
    const index = Math.min(Math.floor(count * percent), count - 1);
    const step = steps.slice(index, index + 2);

    step.push(percent === 1 ? 1 : percent % (1 / count) * count);

    return step;
}

function getValue(steps, percent, digits = 2) {
    const [start, end, p] = getStep(steps, percent);
    return (isNumber(start)
        ? start + Math.abs(start - end) * p * (start < end ? 1 : -1)
        : +end
    ).toFixed(digits);
}

function getUnit(steps) {
    return steps.reduce((unit, step) => isString(step) && step.replace(/-|\d/g, '').trim() || unit, '');
}

function covers(el) {
    const {backgroundSize} = el.style;
    const covers = css(css(el, 'backgroundSize', ''), 'backgroundSize') === 'cover';
    el.style.backgroundSize = backgroundSize;
    return covers;
}
<commit_msg>fix: check for valid steps in stroke props<commit_after>import Media from '../mixin/media';
import {getMaxPathLength} from '../core/svg';
import {css, Dimensions, each, isNumber, isString, isUndefined, startsWith, toFloat, toPx, ucfirst} from 'uikit-util';

const props = ['x', 'y', 'bgx', 'bgy', 'rotate', 'scale', 'color', 'backgroundColor', 'borderColor', 'opacity', 'blur', 'hue', 'grayscale', 'invert', 'saturate', 'sepia', 'fopacity', 'stroke'];

export default {

    mixins: [Media],

    props: props.reduce((props, prop) => {
        props[prop] = 'list';
        return props;
    }, {}),

    data: props.reduce((data, prop) => {
        data[prop] = undefined;
        return data;
    }, {}),

    computed: {

        props(properties, $el) {

            return props.reduce((props, prop) => {

                if (isUndefined(properties[prop])) {
                    return props;
                }

                const isColor = prop.match(/color/i);
                const isCssProp = isColor || prop === 'opacity';

                let pos, bgPos, diff;
                let steps = properties[prop].slice(0);

                if (isCssProp) {
                    css($el, prop, '');
                }

                if (steps.length < 2) {
                    steps.unshift((prop === 'scale'
                        ? 1
                        : isCssProp
                            ? css($el, prop)
                            : 0) || 0);
                }

                const unit = getUnit(steps, prop);

                if (isColor) {

                    const {color} = $el.style;
                    steps = steps.map(step => parseColor($el, step));
                    $el.style.color = color;

                } else if (startsWith(prop, 'bg')) {

                    const attr = prop === 'bgy' ? 'height' : 'width';
                    steps = steps.map(step => toPx(step, attr, this.$el));

                    css($el, `background-position-${prop[2]}`, '');
                    bgPos = css($el, 'backgroundPosition').split(' ')[prop[2] === 'x' ? 0 : 1]; // IE 11 can't read background-position-[x|y]

                    if (this.covers) {

                        const min = Math.min(...steps);
                        const max = Math.max(...steps);
                        const down = steps.indexOf(min) < steps.indexOf(max);

                        diff = max - min;

                        steps = steps.map(step => step - (down ? min : max));
                        pos = `${down ? -diff : 0}px`;

                    } else {

                        pos = bgPos;

                    }

                } else {

                    steps = steps.map(toFloat);

                }

                if (prop === 'stroke') {

                    if (!steps.some(step => step)) {
                        return props;
                    }

                    const length = getMaxPathLength(this.$el);
                    css($el, 'strokeDasharray', length);

                    if (unit === '%') {
                        steps = steps.map(step => step * length / 100);
                    }

                    steps = steps.reverse();

                    prop = 'strokeDashoffset';
                }

                props[prop] = {steps, unit, pos, bgPos, diff};

                return props;

            }, {});

        },

        bgProps() {
            return ['bgx', 'bgy'].filter(bg => bg in this.props);
        },

        covers(_, $el) {
            return covers($el);
        }

    },

    disconnected() {
        delete this._image;
    },

    update: {

        read(data) {

            data.active = this.matchMedia;

            if (!data.active) {
                return;
            }

            if (!data.image && this.covers && this.bgProps.length) {
                const src = css(this.$el, 'backgroundImage').replace(/^none|url\(["']?(.+?)["']?\)$/, '$1');

                if (src) {
                    const img = new Image();
                    img.src = src;
                    data.image = img;

                    if (!img.naturalWidth) {
                        img.onload = () => this.$emit();
                    }
                }

            }

            const {image} = data;

            if (!image || !image.naturalWidth) {
                return;
            }

            const dimEl = {
                width: this.$el.offsetWidth,
                height: this.$el.offsetHeight
            };
            const dimImage = {
                width: image.naturalWidth,
                height: image.naturalHeight
            };

            let dim = Dimensions.cover(dimImage, dimEl);

            this.bgProps.forEach(prop => {

                const {diff, bgPos, steps} = this.props[prop];
                const attr = prop === 'bgy' ? 'height' : 'width';
                const span = dim[attr] - dimEl[attr];

                if (span < diff) {
                    dimEl[attr] = dim[attr] + diff - span;
                } else if (span > diff) {

                    const posPercentage = dimEl[attr] / toPx(bgPos, attr, this.$el);

                    if (posPercentage) {
                        this.props[prop].steps = steps.map(step => step - (span - diff) / posPercentage);
                    }
                }

                dim = Dimensions.cover(dimImage, dimEl);
            });

            data.dim = dim;
        },

        write({dim, active}) {

            if (!active) {
                css(this.$el, {backgroundSize: '', backgroundRepeat: ''});
                return;
            }

            dim && css(this.$el, {
                backgroundSize: `${dim.width}px ${dim.height}px`,
                backgroundRepeat: 'no-repeat'
            });

        },

        events: ['resize']

    },

    methods: {

        reset() {
            each(this.getCss(0), (_, prop) => css(this.$el, prop, ''));
        },

        getCss(percent) {

            const {props} = this;
            return Object.keys(props).reduce((css, prop) => {

                let {steps, unit, pos} = props[prop];
                const value = getValue(steps, percent);

                switch (prop) {

                    // transforms
                    case 'x':
                    case 'y': {
                        unit = unit || 'px';
                        css.transform += ` translate${ucfirst(prop)}(${
                            toFloat(value).toFixed(unit === 'px' ? 0 : 2)
                        }${unit})`;
                        break;
                    }
                    case 'rotate':
                        unit = unit || 'deg';
                        css.transform += ` rotate(${value + unit})`;
                        break;
                    case 'scale':
                        css.transform += ` scale(${value})`;
                        break;

                    // bg image
                    case 'bgy':
                    case 'bgx':
                        css[`background-position-${prop[2]}`] = `calc(${pos} + ${value}px)`;
                        break;

                    // color
                    case 'color':
                    case 'backgroundColor':
                    case 'borderColor': {

                        const [start, end, p] = getStep(steps, percent);

                        css[prop] = `rgba(${
                            start.map((value, i) => {
                                value = value + p * (end[i] - value);
                                return i === 3 ? toFloat(value) : parseInt(value, 10);
                            }).join(',')
                        })`;
                        break;
                    }
                    // CSS Filter
                    case 'blur':
                        unit = unit || 'px';
                        css.filter += ` blur(${value + unit})`;
                        break;
                    case 'hue':
                        unit = unit || 'deg';
                        css.filter += ` hue-rotate(${value + unit})`;
                        break;
                    case 'fopacity':
                        unit = unit || '%';
                        css.filter += ` opacity(${value + unit})`;
                        break;
                    case 'grayscale':
                    case 'invert':
                    case 'saturate':
                    case 'sepia':
                        unit = unit || '%';
                        css.filter += ` ${prop}(${value + unit})`;
                        break;
                    default:
                        css[prop] = value;
                }

                return css;

            }, {transform: '', filter: ''});

        }

    }

};

function parseColor(el, color) {
    return css(css(el, 'color', color), 'color')
        .split(/[(),]/g)
        .slice(1, -1)
        .concat(1)
        .slice(0, 4)
        .map(toFloat);
}

function getStep(steps, percent) {
    const count = steps.length - 1;
    const index = Math.min(Math.floor(count * percent), count - 1);
    const step = steps.slice(index, index + 2);

    step.push(percent === 1 ? 1 : percent % (1 / count) * count);

    return step;
}

function getValue(steps, percent, digits = 2) {
    const [start, end, p] = getStep(steps, percent);
    return (isNumber(start)
        ? start + Math.abs(start - end) * p * (start < end ? 1 : -1)
        : +end
    ).toFixed(digits);
}

function getUnit(steps) {
    return steps.reduce((unit, step) => isString(step) && step.replace(/-|\d/g, '').trim() || unit, '');
}

function covers(el) {
    const {backgroundSize} = el.style;
    const covers = css(css(el, 'backgroundSize', ''), 'backgroundSize') === 'cover';
    el.style.backgroundSize = backgroundSize;
    return covers;
}
<|endoftext|>


<commit_before>'use strict';
/**
 * @file middleware408 test
 * @module logger-request
 * @subpackage test
 * @version 0.0.1
 * @author hex7c0 <hex7c0@gmail.com>
 * @license GPLv3
 */

/*
 * initialize module
 */
var logger = require('..');
var app = require('express')();
var timeout = require('timeout-request');
var request = require('supertest');
var assert = require('assert');
var fs = require('fs');

/*
 * test module
 */
describe('408', function() {

  var f = 'r8.log';

  before(function(done) {

    app.use(timeout({
      milliseconds: 1800,
      callback: function(req, res) {

        res.status(408).send('timeout');
      }
    })).use(logger({
      filename: f,
      winston: {
        logger: 'r8'
      }
    })).get('/', function(req, res) {

      // wait timeout-request callback
    });
    done();
  });

  it('should read log of GET "/" 408', function(done) {

    request(app).get('/').expect(408).end(function(err, res) {

      assert.ifError(err);
      setTimeout(function() {

        fs.readFile(f, function(err, data) {

          assert.ifError(err);
          var d = JSON.parse(data);
          assert.deepEqual(d.method, 'GET', 'method');
          assert.deepEqual(d.status, 408, 'status code');
          assert.deepEqual(d.url, '/', 'url');
          assert.deepEqual(d.message, 'r8', 'logger');
          assert.deepEqual(d.level, 'info', 'log level');
          fs.unlink(f, done);
        });
      }, 100);
    });
  });
});
<commit_msg>tests: decrease timeout to 1.5s<commit_after>'use strict';
/**
 * @file middleware408 test
 * @module logger-request
 * @subpackage test
 * @version 0.0.1
 * @author hex7c0 <hex7c0@gmail.com>
 * @license GPLv3
 */

/*
 * initialize module
 */
var logger = require('..');
var app = require('express')();
var timeout = require('timeout-request');
var request = require('supertest');
var assert = require('assert');
var fs = require('fs');

/*
 * test module
 */
describe('408', function() {

  var f = 'r8.log';

  before(function(done) {

    app.use(timeout({
      milliseconds: 1500,
      callback: function(req, res) {

        res.status(408).send('timeout');
      }
    })).use(logger({
      filename: f,
      winston: {
        logger: 'r8'
      }
    })).get('/', function(req, res) {

      // wait timeout-request callback
    });
    done();
  });

  it('should read log of GET "/" 408', function(done) {

    request(app).get('/').expect(408).end(function(err, res) {

      assert.ifError(err);
      setTimeout(function() {

        fs.readFile(f, function(err, data) {

          assert.ifError(err);
          var d = JSON.parse(data);
          assert.deepEqual(d.method, 'GET', 'method');
          assert.deepEqual(d.status, 408, 'status code');
          assert.deepEqual(d.url, '/', 'url');
          assert.deepEqual(d.message, 'r8', 'logger');
          assert.deepEqual(d.level, 'info', 'log level');
          fs.unlink(f, done);
        });
      }, 100);
    });
  });
});
<|endoftext|>


<commit_before>const webpack = require('webpack');
const path = require('path');

const nodeEnv = process.env.NODE_ENV || 'development';
const isProd = nodeEnv === 'production';

const sourcePath = path.join(__dirname, './src');
const staticsPath = path.join(__dirname, './static');

const plugins = [
  new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    minChunks: Infinity,
    filename: 'vendor.js',
  }),
  new webpack.DefinePlugin({
    'process.env': { NODE_ENV: JSON.stringify(nodeEnv) },
    BASE_URL: JSON.stringify('http://localhost:8080'),
  }),
  new webpack.NamedModulesPlugin(),
];

if (isProd) {
  plugins.push(
    new webpack.LoaderOptionsPlugin({
      minimize: true,
      debug: false,
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
        screw_ie8: true,
        conditionals: true,
        unused: true,
        comparisons: true,
        sequences: true,
        dead_code: true,
        evaluate: true,
        if_return: true,
        join_vars: true,
      },
      output: {
        comments: false,
      },
    }),
  );
} else {
  plugins.push(
    new webpack.HotModuleReplacementPlugin(),
  );
}

module.exports = {
  devtool: isProd ? 'source-map' : 'eval',
  context: sourcePath,
  entry: {
    app: [
      'babel-polyfill',
      'webpack-hot-middleware/client',
      './index.js',
    ],
    vendor: ['react'],
  },
  output: {
    path: staticsPath,
    filename: '[name].js',
  },
  module: {
    rules: [
      {
        test: /\.html$/,
        exclude: /node_modules/,
        use: 'file-loader?name=[name].[ext]',
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader'],
      },
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: 'babel-loader',
      },
      {
        test: /\.png$/,
        use: 'file-loader?name=[md5:hash:base64:10].[ext]',
      }, {
        test: /\.jpg$/,
        use: 'file-loader?name=[md5:hash:base64:10].[ext]',
      },
      {
        test: /\.gif$/,
        use: 'file-loader?name=[name].[ext]',
      }, {
        test: /\.json$/,
        use: 'json',
      }, {
        test: /\.md$/,
        use: 'file-loader?name=[name].[ext]',
      }, {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        use: 'url-loader?limit=10000&mimetype=image/svg+xml',
      },
    ],
  },
  resolve: {
    extensions: ['.js', '.jsx', '.less', '.scss', '.css'],
    modules: [
      path.resolve(__dirname, 'node_modules'),
      sourcePath,
    ],
  },
  plugins,
  devServer: {
    contentBase: './src',
    historyApiFallback: true,
    proxy: {
      '/': 'http://localhost:3000'
    },
    compress: isProd,
    inline: true,
    hot: true,
    stats: {
      assets: true,
      children: false,
      chunks: false,
      hash: false,
      modules: false,
      publicPath: true,
      timings: true,
      version: false,
      warnings: true,
      colors: {
        green: '\u001b[32m',
      },
    },
  },
};
<commit_msg>fix(webpack): syntax corrections<commit_after>const webpack = require('webpack');
const path = require('path');

const nodeEnv = process.env.NODE_ENV || 'development';
const isProd = nodeEnv === 'production';

const sourcePath = path.join(__dirname, './src');
const staticsPath = path.join(__dirname, './static');

const plugins = [
  new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    minChunks: Infinity,
    filename: 'vendor.js',
  }),
  new webpack.DefinePlugin({
    'process.env': { NODE_ENV: JSON.stringify(nodeEnv) },
    BASE_URL: JSON.stringify('http://localhost:8080'),
  }),
  new webpack.NamedModulesPlugin(),
];

if (isProd) {
  plugins.push(
    new webpack.LoaderOptionsPlugin({
      minimize: true,
      debug: false,
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false,
        screw_ie8: true,
        conditionals: true,
        unused: true,
        comparisons: true,
        sequences: true,
        dead_code: true,
        evaluate: true,
        if_return: true,
        join_vars: true,
      },
      output: {
        comments: false,
      },
    })
  );
} else {
  plugins.push(
    new webpack.HotModuleReplacementPlugin()
  );
}

module.exports = {
  devtool: isProd ? 'source-map' : 'eval',
  context: sourcePath,
  entry: {
    app: [
      'babel-polyfill',
      'webpack-hot-middleware/client',
      './index.js',
    ],
    vendor: ['react'],
  },
  output: {
    path: staticsPath,
    filename: '[name].js',
  },
  module: {
    rules: [
      {
        test: /\.html$/,
        exclude: /node_modules/,
        use: 'file-loader?name=[name].[ext]',
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader'],
      },
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: 'babel-loader',
      },
      {
        test: /\.png$/,
        use: 'file-loader?name=[md5:hash:base64:10].[ext]',
      }, {
        test: /\.jpg$/,
        use: 'file-loader?name=[md5:hash:base64:10].[ext]',
      },
      {
        test: /\.gif$/,
        use: 'file-loader?name=[name].[ext]',
      }, {
        test: /\.json$/,
        use: 'json',
      }, {
        test: /\.md$/,
        use: 'file-loader?name=[name].[ext]',
      }, {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        use: 'url-loader?limit=10000&mimetype=image/svg+xml',
      },
    ],
  },
  resolve: {
    extensions: ['.js', '.jsx', '.less', '.scss', '.css'],
    modules: [
      path.resolve(__dirname, 'node_modules'),
      sourcePath,
    ],
  },
  plugins,
  devServer: {
    contentBase: './src',
    historyApiFallback: true,
    proxy: {
      '/': 'http://localhost:3000'
    },
    compress: isProd,
    inline: true,
    hot: true,
    stats: {
      assets: true,
      children: false,
      chunks: false,
      hash: false,
      modules: false,
      publicPath: true,
      timings: true,
      version: false,
      warnings: true,
      colors: {
        green: '\u001b[32m',
      },
    },
  },
};
<|endoftext|>


<commit_before>define([
  'summernote/core/func',
  'summernote/core/list',
  'summernote/module/Button'
], function (func, list, Button) {
  /**
   * Popover (http://getbootstrap.com/javascript/#popovers)
   */
  var Popover = function () {
    var button = new Button();

    /**
     * returns position from placeholder
     * @param {Node} placeholder
     * @param {Boolean} isAirMode
     */
    var posFromPlaceholder = function (placeholder, isAirMode) {
      var $placeholder = $(placeholder);
      var pos = isAirMode ? $placeholder.offset() : $placeholder.position();
      var height = $placeholder.outerHeight(true); // include margin

      // popover below placeholder.
      return {
        left: pos.left,
        top: pos.top + height
      };
    };

    /**
     * show popover
     * @param {jQuery} popover
     * @param {Position} pos
     */
    var showPopover = function ($popover, pos) {
      $popover.css({
        display: 'block',
        left: pos.left,
        top: pos.top
      });
    };

    var PX_POPOVER_ARROW_OFFSET_X = 20;

    /**
     * update current state
     * @param {jQuery} $popover - popover container
     * @param {Object} styleInfo - style object
     * @param {Boolean} isAirMode
     */
    this.update = function ($popover, styleInfo, isAirMode) {
      button.update($popover, styleInfo);

      var $linkPopover = $popover.find('.note-link-popover');
      if (styleInfo.anchor) {
        var $anchor = $linkPopover.find('a');
        var href = $(styleInfo.anchor).attr('href');
        $anchor.attr('href', href).html(href);
        showPopover($linkPopover, posFromPlaceholder(styleInfo.anchor, isAirMode));
      } else {
        $linkPopover.hide();
      }

      var $imagePopover = $popover.find('.note-image-popover');
      if (styleInfo.image) {
        showPopover($imagePopover, posFromPlaceholder(styleInfo.image, isAirMode));
      } else {
        $imagePopover.hide();
      }

      var $airPopover = $popover.find('.note-air-popover');
      if (isAirMode && !styleInfo.range.isCollapsed()) {
        var bnd = func.rect2bnd(list.last(styleInfo.range.getClientRects()));
        showPopover($airPopover, {
          left: Math.max(bnd.left + bnd.width / 2 - PX_POPOVER_ARROW_OFFSET_X, 0),
          top: bnd.top + bnd.height
        });
      } else {
        $airPopover.hide();
      }
    };

    /**
     * @param {Node} button
     * @param {String} eventName
     * @param {String} value
     */
    this.updateRecentColor = function (button, eventName, value) {
      button.updateRecentColor(button, eventName, value);
    };

    /**
     * hide all popovers
     * @param {jQuery} $popover - popover contaienr
     */
    this.hide = function ($popover) {
      $popover.children().hide();
    };
  };

  return Popover;
});
<commit_msg>Fix typo in comment<commit_after>define([
  'summernote/core/func',
  'summernote/core/list',
  'summernote/module/Button'
], function (func, list, Button) {
  /**
   * Popover (http://getbootstrap.com/javascript/#popovers)
   */
  var Popover = function () {
    var button = new Button();

    /**
     * returns position from placeholder
     * @param {Node} placeholder
     * @param {Boolean} isAirMode
     */
    var posFromPlaceholder = function (placeholder, isAirMode) {
      var $placeholder = $(placeholder);
      var pos = isAirMode ? $placeholder.offset() : $placeholder.position();
      var height = $placeholder.outerHeight(true); // include margin

      // popover below placeholder.
      return {
        left: pos.left,
        top: pos.top + height
      };
    };

    /**
     * show popover
     * @param {jQuery} popover
     * @param {Position} pos
     */
    var showPopover = function ($popover, pos) {
      $popover.css({
        display: 'block',
        left: pos.left,
        top: pos.top
      });
    };

    var PX_POPOVER_ARROW_OFFSET_X = 20;

    /**
     * update current state
     * @param {jQuery} $popover - popover container
     * @param {Object} styleInfo - style object
     * @param {Boolean} isAirMode
     */
    this.update = function ($popover, styleInfo, isAirMode) {
      button.update($popover, styleInfo);

      var $linkPopover = $popover.find('.note-link-popover');
      if (styleInfo.anchor) {
        var $anchor = $linkPopover.find('a');
        var href = $(styleInfo.anchor).attr('href');
        $anchor.attr('href', href).html(href);
        showPopover($linkPopover, posFromPlaceholder(styleInfo.anchor, isAirMode));
      } else {
        $linkPopover.hide();
      }

      var $imagePopover = $popover.find('.note-image-popover');
      if (styleInfo.image) {
        showPopover($imagePopover, posFromPlaceholder(styleInfo.image, isAirMode));
      } else {
        $imagePopover.hide();
      }

      var $airPopover = $popover.find('.note-air-popover');
      if (isAirMode && !styleInfo.range.isCollapsed()) {
        var bnd = func.rect2bnd(list.last(styleInfo.range.getClientRects()));
        showPopover($airPopover, {
          left: Math.max(bnd.left + bnd.width / 2 - PX_POPOVER_ARROW_OFFSET_X, 0),
          top: bnd.top + bnd.height
        });
      } else {
        $airPopover.hide();
      }
    };

    /**
     * @param {Node} button
     * @param {String} eventName
     * @param {String} value
     */
    this.updateRecentColor = function (button, eventName, value) {
      button.updateRecentColor(button, eventName, value);
    };

    /**
     * hide all popovers
     * @param {jQuery} $popover - popover container
     */
    this.hide = function ($popover) {
      $popover.children().hide();
    };
  };

  return Popover;
});
<|endoftext|>


<commit_before>var should = require('should');
var ModelManager = require('../lib/model-manager');
var Repo = require('../lib/repo');
var Service = require('../lib/service');

describe('ModelManager', function () {
  describe('loadResources()', function () {
    it('should load named entity constructors from configured model directory', function (done) {
        var modelManager = new ModelManager({modelDirs: [__dirname + '/fixtures/model-manager']});
        should(modelManager.entityConstructors['Artist']).be.Undefined();
        should(modelManager.entityConstructors['Album']).be.Undefined();
        modelManager.loadResources().then(function(){
            should(modelManager.entityConstructors['Artist']).be.a.Function();
            should(modelManager.entityConstructors['Album']).be.a.Function();
            done();
        }).catch(function(err){
          done(err);
        });
    });
    it('should inject constructors into repo config', function (done) {
        var modelManager = new ModelManager({modelDirs: [__dirname + '/fixtures/model-manager']});
        should(modelManager.repos['artist']).be.Undefined();
        modelManager.loadResources().then(function(){
            console.log(modelManager.repos['artist'].config.constructors);
            should(modelManager.repos['artist'].config.constructors.length).eql(2);
            done();
        }).catch(function(err){
          done(err);
        });
    });
    it('should load repository instances from configured model directory', function (done) {
        var modelManager = new ModelManager({modelDirs: [__dirname + '/fixtures/model-manager']});
        should(modelManager.repos['artist']).be.Undefined();
        modelManager.loadResources().then(function(){
            should(modelManager.repos['artist']).be.a.Object();
            done();
        }).catch(function(err){
          done(err);
        });
    });
    it('should load service instances from configured model directory', function (done) {
        var modelManager = new ModelManager({modelDirs: [__dirname + '/fixtures/model-manager']});
        should(modelManager.services['artistSignup']).be.Undefined();
        modelManager.loadResources().then(function(){
          should(modelManager.services['artistSignup']).be.a.Object();
          done();
      }).catch(function(err){
        done(err);
      });
    });
  });
  describe('init()', function () {
    it('should inject named datasource into each repo', function (done) {
      var person = new Repo({name: 'person', dataSource: 'db'});
      should(person.dataSource).be.null();

      var modelManager = new ModelManager();
      var dataSource = {test: 1};
      modelManager.dataSources = {db: dataSource};
      modelManager.addRepo(person);
      modelManager.init().then(function(){
        should(person.dataSource).eql(dataSource);
        done();
      }).catch(function(err){
        done(err);
      });
    });
    it('should inject repos hash into each repo', function (done) {
      var person = new Repo({name: 'person'});
      var post = new Repo({name: 'post'});
      should(person.repos.person).be.undefined();
      should(person.repos.post).be.undefined();
      should(post.repos.person).be.undefined();
      should(post.repos.post).be.undefined();

      var modelManager = new ModelManager();
      modelManager.addRepo(person);
      modelManager.addRepo(post);
      modelManager.init().then(function(){
        should(person.repos.person).eql(person);
        should(person.repos.post).eql(post);
        should(post.repos.person).eql(person);
        should(post.repos.post).eql(post);
        done();
      }).catch(function(err){
        done(err);
      });
    });
    it('should inject repos hash into each service', function (done) {
      var person = new Repo({name: 'person'});
      var post = new Repo({name: 'post'});
      var checkoutService = new Service({name: 'checkout'});

      should(checkoutService.repos.person).be.undefined();
      should(checkoutService.repos.post).be.undefined();

      var modelManager = new ModelManager();
      modelManager.addRepo(person);
      modelManager.addRepo(post);
      modelManager.addService(checkoutService);
      modelManager.init().then(function(){
        should(checkoutService.repos.person).eql(person);
        should(checkoutService.repos.post).eql(post);
        done();
      }).catch(function(err){
        done(err);
      });
    });
    it('should inject services hash into each service', function (done) {
      var checkoutService = new Service({name: 'checkout'});
      var refundService = new Service({name: 'refund'});

      should(checkoutService.services.checkout).be.undefined();
      should(checkoutService.services.refund).be.undefined();
      should(refundService.services.checkout).be.undefined();
      should(refundService.services.refund).be.undefined();

      var modelManager = new ModelManager();
      modelManager.addService(checkoutService);
      modelManager.addService(refundService);
      modelManager.init().then(function(){
        should(checkoutService.services.checkout).eql(checkoutService);
        should(checkoutService.services.refund).eql(refundService);
        should(refundService.services.checkout).eql(checkoutService);
        should(refundService.services.refund).eql(refundService);
        done();
      }).catch(function(err){
        done(err);
      });
    });
  });
});
<commit_msg>Refactor tests<commit_after>var should = require('should');
var ModelManager = require('../lib/model-manager');
var Repo = require('../lib/repo');
var Service = require('../lib/service');

describe('ModelManager', function () {
  describe('loadResources()', function () {
    it('should load named entity constructors from configured model directory', function (done) {
        var modelManager = new ModelManager({modelDirs: [__dirname + '/fixtures/model-manager']});
        should(modelManager.entityConstructors['Artist']).be.Undefined();
        should(modelManager.entityConstructors['Album']).be.Undefined();
        modelManager.loadResources().then(function(){
          should(modelManager.entityConstructors['Artist']).be.a.Function();
          should(modelManager.entityConstructors['Album']).be.a.Function();
          done();
        }).catch(function(err){
          done(err);
        });
    });
    it('should inject constructors into repo config', function (done) {
        var modelManager = new ModelManager({modelDirs: [__dirname + '/fixtures/model-manager']});
        should(modelManager.repos['artist']).be.Undefined();
        modelManager.loadResources().then(function(){
          console.log(modelManager.repos['artist'].config.constructors);
          should(modelManager.repos['artist'].config.constructors.length).eql(2);
          done();
        }).catch(function(err){
          done(err);
        });
    });
    it('should load repository instances from configured model directory', function (done) {
        var modelManager = new ModelManager({modelDirs: [__dirname + '/fixtures/model-manager']});
        should(modelManager.repos['artist']).be.Undefined();
        modelManager.loadResources().then(function(){
          should(modelManager.repos['artist']).be.a.Object();
          done();
        }).catch(function(err){
          done(err);
        });
    });
    it('should load service instances from configured model directory', function (done) {
        var modelManager = new ModelManager({modelDirs: [__dirname + '/fixtures/model-manager']});
        should(modelManager.services['artistSignup']).be.Undefined();
        modelManager.loadResources().then(function(){
          should(modelManager.services['artistSignup']).be.a.Object();
          done();
      }).catch(function(err){
        done(err);
      });
    });
  });
  describe('init()', function () {
    it('should inject named datasource into each repo', function (done) {
      var person = new Repo({name: 'person', dataSource: 'db'});
      should(person.dataSource).be.null();

      var modelManager = new ModelManager();
      var dataSource = {test: 1};
      modelManager.dataSources = {db: dataSource};
      modelManager.addRepo(person);
      modelManager.init().then(function(){
        should(person.dataSource).eql(dataSource);
        done();
      }).catch(function(err){
        done(err);
      });
    });
    it('should inject repos hash into each repo', function (done) {
      var person = new Repo({name: 'person'});
      var post = new Repo({name: 'post'});
      should(person.repos.person).be.undefined();
      should(person.repos.post).be.undefined();
      should(post.repos.person).be.undefined();
      should(post.repos.post).be.undefined();

      var modelManager = new ModelManager();
      modelManager.addRepo(person);
      modelManager.addRepo(post);
      modelManager.init().then(function(){
        should(person.repos.person).eql(person);
        should(person.repos.post).eql(post);
        should(post.repos.person).eql(person);
        should(post.repos.post).eql(post);
        done();
      }).catch(function(err){
        done(err);
      });
    });
    it('should inject repos hash into each service', function (done) {
      var person = new Repo({name: 'person'});
      var post = new Repo({name: 'post'});
      var checkoutService = new Service({name: 'checkout'});

      should(checkoutService.repos.person).be.undefined();
      should(checkoutService.repos.post).be.undefined();

      var modelManager = new ModelManager();
      modelManager.addRepo(person);
      modelManager.addRepo(post);
      modelManager.addService(checkoutService);
      modelManager.init().then(function(){
        should(checkoutService.repos.person).eql(person);
        should(checkoutService.repos.post).eql(post);
        done();
      }).catch(function(err){
        done(err);
      });
    });
    it('should inject services hash into each service', function (done) {
      var checkoutService = new Service({name: 'checkout'});
      var refundService = new Service({name: 'refund'});

      should(checkoutService.services.checkout).be.undefined();
      should(checkoutService.services.refund).be.undefined();
      should(refundService.services.checkout).be.undefined();
      should(refundService.services.refund).be.undefined();

      var modelManager = new ModelManager();
      modelManager.addService(checkoutService);
      modelManager.addService(refundService);
      modelManager.init().then(function(){
        should(checkoutService.services.checkout).eql(checkoutService);
        should(checkoutService.services.refund).eql(refundService);
        should(refundService.services.checkout).eql(checkoutService);
        should(refundService.services.refund).eql(refundService);
        done();
      }).catch(function(err){
        done(err);
      });
    });
  });
});
<|endoftext|>


<commit_before>const { resolve } = require('path');
const { isProd, isDev } = require('./webpack/env');

let config = {
  devtool: 'cheap-module-eval-source-map',

  cache: true,
  performance: {
    hints: false,
  },

  context: resolve(__dirname, 'src'),
  entry: {
    bundle: [
      './index.js',
    ],
    vendor: [
      'react',
      'react-dom',
    ],
  },

  output: {
    pathinfo: isDev,
    publicPath: '/',
    path: resolve(__dirname, 'dist'),
    filename: 'js/[name]-[chunkhash:8].js',
    chunkFilename: 'js/[name]-[chunkhash:8].chunk.js',
  },

  resolve: {
    alias: {},
    extensions: [],
    modules: [
      resolve(__dirname, 'src'),
      'node_modules',
    ],
  },

  plugins: [],
  module: {
    rules: [],
  },
};

// Context
config = require('./webpack/stats')(config);
config = require('./webpack/node')(config);

// Modules
config = require('./webpack/modules/noParse')(config);
config = require('./webpack/modules/babel')(config);
config = require('./webpack/modules/css')(config);
config = require('./webpack/modules/urlFont')(config);
config = require('./webpack/modules/urlImage')(config);
config = require('./webpack/modules/urlVideo')(config);

// Plugins
config = require('./webpack/plugins/define')(config);
config = require('./webpack/plugins/hash')(config);

if (isProd) {
  config.devtool = 'source-map';

  // Context
  config = require('./webpack/perf')(config);

  // Plugins
  config = require('./webpack/plugins/clean')(config);
  config = require('./webpack/plugins/manifest')(config);
  config = require('./webpack/plugins/commonsChunk')(config);
  config = require('./webpack/plugins/moduleConcat')(config);
  config = require('./webpack/plugins/uglify')(config);
  config = require('./webpack/plugins/optimizeCss')(config);
}

module.exports = config;
<commit_msg>Move node options to prod env<commit_after>const { resolve } = require('path');
const { isProd, isDev } = require('./webpack/env');

let config = {
  devtool: 'cheap-module-eval-source-map',

  cache: true,
  performance: {
    hints: false,
  },

  context: resolve(__dirname, 'src'),
  entry: {
    bundle: [
      './index.js',
    ],
    vendor: [
      'react',
      'react-dom',
    ],
  },

  output: {
    pathinfo: isDev,
    publicPath: '/',
    path: resolve(__dirname, 'dist'),
    filename: 'js/[name]-[chunkhash:8].js',
    chunkFilename: 'js/[name]-[chunkhash:8].chunk.js',
  },

  resolve: {
    alias: {},
    extensions: [],
    modules: [
      resolve(__dirname, 'src'),
      'node_modules',
    ],
  },

  plugins: [],
  module: {
    rules: [],
  },
};

// Context
config = require('./webpack/stats')(config);

// Modules
config = require('./webpack/modules/noParse')(config);
config = require('./webpack/modules/babel')(config);
config = require('./webpack/modules/css')(config);
config = require('./webpack/modules/urlFont')(config);
config = require('./webpack/modules/urlImage')(config);
config = require('./webpack/modules/urlVideo')(config);

// Plugins
config = require('./webpack/plugins/define')(config);
config = require('./webpack/plugins/hash')(config);

if (isProd) {
  config.devtool = 'source-map';

  // Context
  config = require('./webpack/perf')(config);
  config = require('./webpack/node')(config);

  // Plugins
  config = require('./webpack/plugins/clean')(config);
  config = require('./webpack/plugins/manifest')(config);
  config = require('./webpack/plugins/commonsChunk')(config);
  config = require('./webpack/plugins/moduleConcat')(config);
  config = require('./webpack/plugins/uglify')(config);
  config = require('./webpack/plugins/optimizeCss')(config);
}

module.exports = config;
<|endoftext|>