<commit_before>export { SameWhenPassThrough_PrefixSqueezeExcitation };

import * as BoundsArraySet from "../BoundsArraySet.js";
import * as SqueezeExcitation from "../SqueezeExcitation.js";
import { SameWhenPassThrough } from "./Pointwise_SameWhenPassThrough.js";

//!!! ...unfinished... (2022/05/14)
// Q: Perhaps, let pointwise1 become squeeze and excitation before depthwise.
// A: It may not be possible because input and output channel count may be different.

//!!! ...unfinished... (2022/05/08) Add squeeze and excitation before pointwise.
// globale avg pooling - pointwise - pointwise - multiplyToInput
// And the, the original pointwise

//!!! ...unfinished... (2022/05/09) What if:
// pointwise1 ( bias, activation )
// depthwise ( channelMultipler > 1, bias / no bias, activation / no activation )
// pointwiseSE ( bias, activation )
// pointwise2 ( bias, activation )
//
// pointwise1 - depthwise - pointwiseSE - multiply - pointwise2
//                        \-------------/
//
// No global average pooloing.
//
//
//
//

/**
 * A Pointwise_SameWhenPassThrough with a SqueezeExcitation in front of it.
 *
 *
 * @member {number} byteOffsetBegin
 *   The position which is started (inclusive) to extract from inputFloat32Array.buffer by init(). This is relative to the
 * inputFloat32Array.buffer (not to the inputFloat32Array.byteOffset).
 *
 * @member {number} byteOffsetEnd
 *   The position which is ended to (non-inclusive) extract from inputFloat32Array.buffer by init(). Where to extract next weights.
 * Only meaningful when ( this.bInitOk == true ). This is relative to the inputFloat32Array.buffer (not to the inputFloat32Array.byteOffset).
 *

//!!! ...unfinished... (2022/05/19) ValueDesc.SqueezeExcitationChannelCountDivisor.Singleton.Ids.Xxx

 * @member {number} nSqueezeExcitationChannelCountDivisor
 *   An integer represents the channel count divisor for squeeze-and-excitation's intermediate pointwise convolution channel count.
 * (Please see also SqueezeExcitation.Base.nSqueezeExcitationChannelCountDivisor explanation.)
 *
 * @member {number} inputHeight
 *   The height of the input tensor. (Please see also SqueezeExcitation.Base.bSqueeze explanation.)
 *
 * @member {number} inputWidth
 *   The width of the input tensor. (Please see also SqueezeExcitation.Base.bSqueeze explanation.)
 * *
 * @member {number} inputChannelCount
 *   The channel count of the input tensor. It must be greater than zero (> 0).
 *
 * @member {number} outputChannelCount
 *   The channel count of the output tensor.
 *
 * @member {ValueDesc.Pointwise_HigherHalfDifferent} nHigherHalfDifferent
 *   The HigherHalfDifferent type for pointwise convolution.
 *
 * @member {boolean} bExisted
 *   If true, this operation exists. If false, this object is a no-op (i.e. no squeeze-and-excitation, no pointwise).
 *
 * @member {boolean} bSqueezeExcitation
 *   If true, the squeeze-and-excitation exists. It will be false in the following cases:
 *
 *     - ( this.bExisted == false )
 *       - no squeeze, no excitation, no multiply, no pointwise.
 *
 *     - ( nSqueezeExcitationChannelCountDivisor == ValueDesc.SqueezeExcitationChannelCountDivisor.Singleton.Ids.NONE ) (-2)
 *       - no squeeze, no excitation, no multiply.
 *

//!!! ...unfinished... (2022/05/20) should return the SqueezeExcitation.Base.bSqueeze if ( bSqueezeExcitation == true ).

 * @member {boolean} bSqueeze
 *   Whether squeeze-and-excitation has squeeze. It is only meaningful when ( bSqueezeExcitation == true ). It is always false
 * if ( bSqueezeExcitation == false ). (Please see also SqueezeExcitation.Base.bSqueeze explanation.)
 *
 * @member {number} tensorWeightCountTotal
 *   The total wieght count used in tensors. Including inferenced weights, if they are used in tensors.
 *
 * @member {number} tensorWeightCountExtracted
 *   The wieght count extracted from inputFloat32Array and used in tensors. Not including inferenced weights (even if they are
 * used in tensors), because they are not extracted from inputFloat32Array.
 *
 * @member {function} apply
 *   A method accepts one parameter inputTensor (tf.tensor3d) and return an outputTensor (tf.tensor3d). All intermediate tensors
 * will be disposed. The inputTensor may or may not be disposed (according to setKeepInputTensor()). In fact, this method calls one

//!!! ...unfinished... (2022/05/19)

 * of Base.???() according to the parameters.
 *
 * @see SqueezeExcitation.Base
 * @see Pointwise.SameWhenPassThrough
 *
 */
class SameWhenPassThrough_PrefixSqueezeExcitation {

//!!! ...unfinished... (2022/05/20)

  /**
   */
  constructor(
    nSqueezeExcitationChannelCountDivisor, inputHeight, inputWidth,
    inputChannelCount, outputChannelCount, bBias, nActivationId,
    nHigherHalfDifferent, inputChannelCount_lowerHalf, outputChannelCount_lowerHalf, channelShuffler_outputGroupCount ) {

    this.nSqueezeExcitationChannelCountDivisor = nSqueezeExcitationChannelCountDivisor;
    this.inputHeight = inputHeight;
    this.inputWidth = inputWidth;
    this.inputChannelCount = inputChannelCount;
    this.outputChannelCount = outputChannelCount;
    this.bBias = bBias;
    this.nActivationId = nActivationId;
    this.nHigherHalfDifferent = nHigherHalfDifferent;
    this.inputChannelCount_lowerHalf = inputChannelCount_lowerHalf;
    this.outputChannelCount_lowerHalf = outputChannelCount_lowerHalf;
    this.channelShuffler_outputGroupCount = channelShuffler_outputGroupCount;
  }

  /**
   * @param {Float32Array} inputFloat32Array
   *   A Float32Array whose values will be interpreted as weights.
   *
   * @param {ActivationEscaping.ScaleBoundsArray} inputScaleBoundsArray
   *   The element value bounds (per channel) of input. Usually, it is The .output of the previous operation value bounds set
   * of this operation. It will be kept (not cloned) directly. So caller should not modify them.
   *
   * @return {boolean} Return true, if succeeded.
   */
  init( inputFloat32Array, byteOffsetBegin, inputScaleBoundsArray ) {

    this.disposeTensors();

    this.byteOffsetBegin = this.byteOffsetEnd = byteOffsetBegin;

    // 1. Determine operation functions.
    Base.setup_bExisted.call( this );
    Base.setup_bSqueezeExcitation.call( this );
    Base.setup_pfn.call( this );

//!!!
    if ( this.bExisted ) {

      // 2. Initialize sub-operations.

      // 2.1 squeezeExcitation
      let squeezeExcitation_boundsArraySet_output0;
      if ( this.bSqueezeExcitation ) {
        this.squeezeExcitation = new SqueezeExcitation.Base(
          this.nSqueezeExcitationChannelCountDivisor, this.inputHeight, this.inputWidth,
          this.inputChannelCount, this.nActivationId,
          this.nHigherHalfDifferent, this.inputChannelCount_lowerHalf, this.outputChannelCount_lowerHalf );

        if ( !this.squeezeExcitation.init( inputFloat32Array, this.byteOffsetEnd, inputScaleBoundsArray ) )
          return false;  // e.g. input array does not have enough data.
        this.byteOffsetEnd = this.squeezeExcitation.byteOffsetEnd;

        this.tensorWeightCountTotal += this.squeezeExcitation.tensorWeightCountTotal;
        this.tensorWeightCountExtracted += this.squeezeExcitation.tensorWeightCountExtracted;

        squeezeExcitation_boundsArraySet_output0 = this.squeezeExcitation.boundsArraySet.output0;
      } else {
        squeezeExcitation_boundsArraySet_output0 = inputScaleBoundsArray;
      }

      // 2.2 pointwise
      {
        this.pointwise = new SameWhenPassThrough(
          this.inputChannelCount, this.outputChannelCount, this.bBias, this.nActivationId,
          this.nHigherHalfDifferent,
          this.inputChannelCount_lowerHalf, this.outputChannelCount_lowerHalf,
          this.channelShuffler_outputGroupCount );

        if ( !this.pointwise.init( inputFloat32Array, this.byteOffsetEnd, squeezeExcitation_boundsArraySet_output0 ) )
          return false;  // e.g. input array does not have enough data.
        this.byteOffsetEnd = this.excitationPointwise.byteOffsetEnd;

        this.tensorWeightCountTotal += this.pointwise.tensorWeightCountTotal;
        this.tensorWeightCountExtracted += this.pointwise.tensorWeightCountExtracted;
      }

      // 3. BoundsArraySet
      {
        { // Build self BoundsArraySet.
          this.boundsArraySet = new BoundsArraySet.InputsOutputs( inputScaleBoundsArray, null,
            this.pointwise.boundsArraySet.output0.channelCount, 0 );

          this.boundsArraySet.set_outputs_all_byBoundsArraySet_Outputs( this.pointwise.boundsArraySet );
        }

        this.dispose_all_sub_BoundsArraySet(); // For reduce memory footprint.
      }
    }

    this.bInitOk = true;
    return this.bInitOk;
  }

  /** Release all tensors. */
  disposeTensors() {
    if ( this.squeezeExcitation ) {
      this.squeezeExcitation.disposeTensors();
      this.squeezeExcitation = null;
    }

    if ( this.pointwise ) {
      this.pointwise.disposeTensors();
      this.pointwise = null;
    }

    this.tensorWeightCountTotal = this.tensorWeightCountExtracted = 0;
    this.byteOffsetBegin = this.byteOffsetEnd = -1;
    this.bKeepInputTensor = false;  // Default will dispose input tensor.
    this.bInitOk = false;
  }

  /**
   * Release all BoundsArraySet of squeezeExcitation, pointwise.
   *
   * This could reduce memory footprint.
   *
   * (Note: This Pointwise.SameWhenPassThrough_PrefixSqueezeExcitation's BoundsArraySet is kept.)
   */
  dispose_all_sub_BoundsArraySet() {
    delete this.squeezeExcitation?.boundsArraySet;
    delete this.pointwise.boundsArraySet;
  }

//!!! ...unfinished... (2022/05/19)

  /**
   * The sub operations' setKeepInputTensor() will be called so that only the first operation is responsible for keeping inputTensor.
   * All other operations should always destroy inputTensor..
   *
   */
  setKeepInputTensor( bKeepInputTensor ) {
    if ( bKeepInputTensor == this.bKeepInputTensor )
      return;

    this.bKeepInputTensor = bKeepInputTensor;
    if ( bKeepInputTensor ) {

//!!! ...unfinished... (2022/05/19)

      // Note: The first operation is responsible for keep inputTensor. All other operations should always destroy inputTensor.
      if ( this.squeezeDepthwise ) {
        this.squeezeDepthwise.setKeepInputTensor( true );
        this.intermediatePointwise.setKeepInputTensor( false );
        this.excitationPointwise.setKeepInputTensor( false );
      } else {
        if ( this.intermediatePointwise ) {
          this.intermediatePointwise.setKeepInputTensor( true );
          this.excitationPointwise.setKeepInputTensor( false );
        } else {
          this.excitationPointwise.setKeepInputTensor( true );
        }
      }

    } else {
      this.squeezeDepthwise?.setKeepInputTensor( false );
      this.intermediatePointwise?.setKeepInputTensor( false );
      this.excitationPointwise.setKeepInputTensor( false );
    }
  }

  get bSqueeze() {
    if ( !this.squeezeExcitation )
      return false; // Since no squeeze-and-excitation, there will be no squeeze.
    return this.squeezeExcitation.bSqueeze;
  }

  /** Determine data member this.bExisted
   *
   * @param {Base} this  The Base object to be determined and modified.
   */
  static setup_bExisted() {

//!!! ...unfinished... (2022/05/20) bExisted
// If ( outputChannelCount <= 0 ), no squeeze-and-excitation and no pointwise.
//
// Problem: ( outputChannelCount <= 0 ) but ( channelShuffler_outputGroupCount > 0 ),
//          the pointwise still exists (all-pass-through-and-channel-shuffling).
//
//

    if ( this.outputChannelCount <= 0 ) {
      this.bExisted = false;
    } else {
      this.bExisted = true;
    }
  }

  /** Determine data member this.bSqueezeExcitation
   *
   * @param {Base} this  The Base object to be determined and modified.
   */
  static setup_bSqueezeExcitation() {
    if ( this.bExisted == false ) {
      this.bSqueezeExcitation = false;
    } else {
      if ( this.nSqueezeExcitationChannelCountDivisor == ValueDesc.SqueezeExcitationChannelCountDivisor.Singleton.Ids.NONE ) { // (-2)
        this.bSqueezeExcitation = false;
      } else {
        this.bSqueezeExcitation = true;
      }
    }
  }

  //!!! ...unfinished... (2022/05/19)

  /** Determine data member this.apply.
   *
   * @param {Base} this
   *   The Base object to be determined and modified.
   */
  static setup_pfn() {

//!!! ...unfinished... (2022/05/20) bExisted
// If ( bExisted == false ) (after pointwise is created), the squeezeExcitation should also be skipped.

//!!! ...unfinished... (2022/05/19)

    if ( this.squeezeDepthwise ) {
      if ( this.intermediatePointwise ) {
        this.apply = Base.squeeze_intermediate_excitation;
      } else {
        this.apply = Base.squeeze_excitation;
      }
    } else {
      if ( this.intermediatePointwise ) {
        this.apply = Base.intermediate_excitation;
      } else {
        this.apply = Base.excitation;
      }
    }
  }

//!!! ...unfinished... (2022/05/19)

  /** */
  static squeeze_intermediate_excitation( inputTensor ) {

//!!! ...unfinished... (2022/05/19)

    let t0, t1;
    t0 = this.squeezeDepthwise.apply( inputTensor );
    t1 = this.intermediatePointwise.apply( t0 );
    t0 = this.excitationPointwise.apply( t1 );

    t1 = tf.mul( inputTensor, t0 );
    t0.dispose();
    return t1;
  }

}
<commit_msg>Update Pointwise_SameWhenPassThrough_PrefixSqueezeExcitation.js<commit_after>export { SameWhenPassThrough_PrefixSqueezeExcitation };

import * as BoundsArraySet from "../BoundsArraySet.js";
import * as ReturnOrClone from "../ReturnOrClone.js";
import * as SqueezeExcitation from "../SqueezeExcitation.js";
import { SameWhenPassThrough } from "./Pointwise_SameWhenPassThrough.js";

//!!! ...unfinished... (2022/05/14)
// Q: Perhaps, let pointwise1 become squeeze and excitation before depthwise.
// A: It may not be possible because input and output channel count may be different.

//!!! ...unfinished... (2022/05/08) Add squeeze and excitation before pointwise.
// globale avg pooling - pointwise - pointwise - multiplyToInput
// And the, the original pointwise

//!!! ...unfinished... (2022/05/09) What if:
// pointwise1 ( bias, activation )
// depthwise ( channelMultipler > 1, bias / no bias, activation / no activation )
// pointwiseSE ( bias, activation )
// pointwise2 ( bias, activation )
//
// pointwise1 - depthwise - pointwiseSE - multiply - pointwise2
//                        \-------------/
//
// No global average pooloing.
//
//
//
//

/**
 * A Pointwise_SameWhenPassThrough with a SqueezeExcitation in front of it.
 *
 *
 * @member {number} byteOffsetBegin
 *   The position which is started (inclusive) to extract from inputFloat32Array.buffer by init(). This is relative to the
 * inputFloat32Array.buffer (not to the inputFloat32Array.byteOffset).
 *
 * @member {number} byteOffsetEnd
 *   The position which is ended to (non-inclusive) extract from inputFloat32Array.buffer by init(). Where to extract next weights.
 * Only meaningful when ( this.bInitOk == true ). This is relative to the inputFloat32Array.buffer (not to the inputFloat32Array.byteOffset).
 *

//!!! ...unfinished... (2022/05/19) ValueDesc.SqueezeExcitationChannelCountDivisor.Singleton.Ids.Xxx

 * @member {number} nSqueezeExcitationChannelCountDivisor
 *   An integer represents the channel count divisor for squeeze-and-excitation's intermediate pointwise convolution channel count.
 * (Please see also SqueezeExcitation.Base.nSqueezeExcitationChannelCountDivisor explanation.)
 *
 * @member {number} inputHeight
 *   The height of the input tensor. (Please see also SqueezeExcitation.Base.bSqueeze explanation.)
 *
 * @member {number} inputWidth
 *   The width of the input tensor. (Please see also SqueezeExcitation.Base.bSqueeze explanation.)
 * *
 * @member {number} inputChannelCount
 *   The channel count of the input tensor. It must be greater than zero (> 0).
 *
 * @member {number} outputChannelCount
 *   The channel count of the output tensor.
 *
 * @member {ValueDesc.Pointwise_HigherHalfDifferent} nHigherHalfDifferent
 *   The HigherHalfDifferent type for pointwise convolution.
 *
 * @member {boolean} bExisted
 *   If true, this operation exists. If false, this object is a no-op (i.e. no squeeze-and-excitation, no pointwise).
 *
 * @member {boolean} bSqueezeExcitation
 *   If true, the squeeze-and-excitation exists. It will be false in the following cases:
 *
 *     - ( this.bExisted == false )
 *       - no squeeze, no excitation, no multiply, no pointwise.
 *
 *     - ( nSqueezeExcitationChannelCountDivisor == ValueDesc.SqueezeExcitationChannelCountDivisor.Singleton.Ids.NONE ) (-2)
 *       - no squeeze, no excitation, no multiply.
 *

//!!! ...unfinished... (2022/05/20) should return the SqueezeExcitation.Base.bSqueeze if ( bSqueezeExcitation == true ).

 * @member {boolean} bSqueeze
 *   Whether squeeze-and-excitation has squeeze. It is only meaningful when ( bSqueezeExcitation == true ). It is always false
 * if ( bSqueezeExcitation == false ). (Please see also SqueezeExcitation.Base.bSqueeze explanation.)
 *
 * @member {number} tensorWeightCountTotal
 *   The total wieght count used in tensors. Including inferenced weights, if they are used in tensors.
 *
 * @member {number} tensorWeightCountExtracted
 *   The wieght count extracted from inputFloat32Array and used in tensors. Not including inferenced weights (even if they are
 * used in tensors), because they are not extracted from inputFloat32Array.
 *
 * @member {function} apply
 *   A method accepts one parameter inputTensor (tf.tensor3d) and return an outputTensor (tf.tensor3d). All intermediate tensors
 * will be disposed. The inputTensor may or may not be disposed (according to setKeepInputTensor()). In fact, this method calls one

//!!! ...unfinished... (2022/05/19)

 * of Base.???() according to the parameters.
 *
 * @see SqueezeExcitation.Base
 * @see Pointwise.SameWhenPassThrough
 *
 */
class SameWhenPassThrough_PrefixSqueezeExcitation extends ReturnOrClone.Base {

//!!! ...unfinished... (2022/05/20)

  /**
   */
  constructor(
    nSqueezeExcitationChannelCountDivisor, inputHeight, inputWidth,
    inputChannelCount, outputChannelCount, bBias, nActivationId,
    nHigherHalfDifferent, inputChannelCount_lowerHalf, outputChannelCount_lowerHalf, channelShuffler_outputGroupCount ) {

    this.nSqueezeExcitationChannelCountDivisor = nSqueezeExcitationChannelCountDivisor;
    this.inputHeight = inputHeight;
    this.inputWidth = inputWidth;
    this.inputChannelCount = inputChannelCount;
    this.outputChannelCount = outputChannelCount;
    this.bBias = bBias;
    this.nActivationId = nActivationId;
    this.nHigherHalfDifferent = nHigherHalfDifferent;
    this.inputChannelCount_lowerHalf = inputChannelCount_lowerHalf;
    this.outputChannelCount_lowerHalf = outputChannelCount_lowerHalf;
    this.channelShuffler_outputGroupCount = channelShuffler_outputGroupCount;
  }

  /**
   * @param {Float32Array} inputFloat32Array
   *   A Float32Array whose values will be interpreted as weights.
   *
   * @param {ActivationEscaping.ScaleBoundsArray} inputScaleBoundsArray
   *   The element value bounds (per channel) of input. Usually, it is The .output of the previous operation value bounds set
   * of this operation. It will be kept (not cloned) directly. So caller should not modify them.
   *
   * @return {boolean} Return true, if succeeded.
   */
  init( inputFloat32Array, byteOffsetBegin, inputScaleBoundsArray ) {

    this.disposeTensors();

    this.byteOffsetBegin = this.byteOffsetEnd = byteOffsetBegin;

    // 1. Determine operation functions.
    Base.setup_bExisted.call( this );
    Base.setup_bSqueezeExcitation.call( this );
    Base.setup_pfn.call( this );

//!!!
    if ( this.bExisted ) {

      // 2. Initialize sub-operations.

      // 2.1 squeezeExcitation
      let squeezeExcitation_boundsArraySet_output0;
      if ( this.bSqueezeExcitation ) {
        this.squeezeExcitation = new SqueezeExcitation.Base(
          this.nSqueezeExcitationChannelCountDivisor, this.inputHeight, this.inputWidth,
          this.inputChannelCount, this.nActivationId,
          this.nHigherHalfDifferent, this.inputChannelCount_lowerHalf, this.outputChannelCount_lowerHalf );

        if ( !this.squeezeExcitation.init( inputFloat32Array, this.byteOffsetEnd, inputScaleBoundsArray ) )
          return false;  // e.g. input array does not have enough data.
        this.byteOffsetEnd = this.squeezeExcitation.byteOffsetEnd;

        this.tensorWeightCountTotal += this.squeezeExcitation.tensorWeightCountTotal;
        this.tensorWeightCountExtracted += this.squeezeExcitation.tensorWeightCountExtracted;

        squeezeExcitation_boundsArraySet_output0 = this.squeezeExcitation.boundsArraySet.output0;
      } else {
        squeezeExcitation_boundsArraySet_output0 = inputScaleBoundsArray;
      }

      // 2.2 pointwise
      {
        this.pointwise = new SameWhenPassThrough(
          this.inputChannelCount, this.outputChannelCount, this.bBias, this.nActivationId,
          this.nHigherHalfDifferent,
          this.inputChannelCount_lowerHalf, this.outputChannelCount_lowerHalf,
          this.channelShuffler_outputGroupCount );

        if ( !this.pointwise.init( inputFloat32Array, this.byteOffsetEnd, squeezeExcitation_boundsArraySet_output0 ) )
          return false;  // e.g. input array does not have enough data.
        this.byteOffsetEnd = this.excitationPointwise.byteOffsetEnd;

        this.tensorWeightCountTotal += this.pointwise.tensorWeightCountTotal;
        this.tensorWeightCountExtracted += this.pointwise.tensorWeightCountExtracted;
      }

      // 3. BoundsArraySet
      {
        { // Build self BoundsArraySet.
          this.boundsArraySet = new BoundsArraySet.InputsOutputs( inputScaleBoundsArray, null,
            this.pointwise.boundsArraySet.output0.channelCount, 0 );

          this.boundsArraySet.set_outputs_all_byBoundsArraySet_Outputs( this.pointwise.boundsArraySet );
        }

        this.dispose_all_sub_BoundsArraySet(); // For reduce memory footprint.
      }
    }

    this.bInitOk = true;
    return this.bInitOk;
  }

  /** Release all tensors. */
  disposeTensors() {
    if ( this.squeezeExcitation ) {
      this.squeezeExcitation.disposeTensors();
      this.squeezeExcitation = null;
    }

    if ( this.pointwise ) {
      this.pointwise.disposeTensors();
      this.pointwise = null;
    }

    this.tensorWeightCountTotal = this.tensorWeightCountExtracted = 0;
    this.byteOffsetBegin = this.byteOffsetEnd = -1;
    this.bKeepInputTensor = false;  // Default will dispose input tensor.
    this.bInitOk = false;
  }

  /**
   * Release all BoundsArraySet of squeezeExcitation, pointwise.
   *
   * This could reduce memory footprint.
   *
   * (Note: This Pointwise.SameWhenPassThrough_PrefixSqueezeExcitation's BoundsArraySet is kept.)
   */
  dispose_all_sub_BoundsArraySet() {
    delete this.squeezeExcitation?.boundsArraySet;
    delete this.pointwise.boundsArraySet;
  }

//!!! ...unfinished... (2022/05/19)

  /**
   * The sub operations' setKeepInputTensor() will be called so that only the first operation is responsible for keeping inputTensor.
   * All other operations should always destroy inputTensor..
   *
   */
  setKeepInputTensor( bKeepInputTensor ) {
    if ( bKeepInputTensor == this.bKeepInputTensor )
      return;

    this.bKeepInputTensor = bKeepInputTensor;
    if ( bKeepInputTensor ) {

//!!! ...unfinished... (2022/05/19)

      // Note: The first operation is responsible for keep inputTensor. All other operations should always destroy inputTensor.
      if ( this.squeezeDepthwise ) {
        this.squeezeDepthwise.setKeepInputTensor( true );
        this.intermediatePointwise.setKeepInputTensor( false );
        this.excitationPointwise.setKeepInputTensor( false );
      } else {
        if ( this.intermediatePointwise ) {
          this.intermediatePointwise.setKeepInputTensor( true );
          this.excitationPointwise.setKeepInputTensor( false );
        } else {
          this.excitationPointwise.setKeepInputTensor( true );
        }
      }

    } else {
      this.squeezeDepthwise?.setKeepInputTensor( false );
      this.intermediatePointwise?.setKeepInputTensor( false );
      this.excitationPointwise.setKeepInputTensor( false );
    }
  }

  get bSqueeze() {
    if ( !this.squeezeExcitation )
      return false; // Since no squeeze-and-excitation, there will be no squeeze.
    return this.squeezeExcitation.bSqueeze;
  }

  /** Determine data member this.bExisted
   *
   * @param {Base} this  The Base object to be determined and modified.
   */
  static setup_bExisted() {

//!!! ...unfinished... (2022/05/20) bExisted
// If ( outputChannelCount <= 0 ), no squeeze-and-excitation and no pointwise.
//
// Problem: ( outputChannelCount <= 0 ) but ( channelShuffler_outputGroupCount > 0 ),
//          the pointwise still exists (all-pass-through-and-channel-shuffling).
//
//

    if ( this.outputChannelCount <= 0 ) {
      this.bExisted = false;
    } else {
      this.bExisted = true;
    }
  }

  /** Determine data member this.bSqueezeExcitation
   *
   * @param {Base} this  The Base object to be determined and modified.
   */
  static setup_bSqueezeExcitation() {
    if ( this.bExisted == false ) {
      this.bSqueezeExcitation = false;
    } else {
      if ( this.nSqueezeExcitationChannelCountDivisor == ValueDesc.SqueezeExcitationChannelCountDivisor.Singleton.Ids.NONE ) { // (-2)
        this.bSqueezeExcitation = false;
      } else {
        this.bSqueezeExcitation = true;
      }
    }
  }

  //!!! ...unfinished... (2022/05/19)

  /** Determine data member this.apply.
   *
   * @param {Base} this
   *   The Base object to be determined and modified.
   */
  static setup_pfn() {

//!!! ...unfinished... (2022/05/20) bExisted
// If ( bExisted == false ) (after pointwise is created), the squeezeExcitation should also be skipped.

//!!! ...unfinished... (2022/05/19)

    if ( this.bExisted ) {
      if ( this.bSqueeze ) {
        if ( this.intermediateChannelCount > 0 ) {
          this.apply = Base.squeeze_intermediate_excitation;
        } else {
          this.apply = Base.squeeze_excitation;
        }
      } else {
        if ( this.intermediateChannelCount > 0 ) {
          this.apply = Base.intermediate_excitation;
        } else {
          this.apply = Base.excitation;
        }
      }
    } else { // There is no operation at all.
      this.apply = Base.return_input_directly;
    }
  }

//!!! ...unfinished... (2022/05/19)

  /** */
  static squeeze_intermediate_excitation( inputTensor ) {

//!!! ...unfinished... (2022/05/19)

    let t0, t1;
    t0 = this.squeezeDepthwise.apply( inputTensor );
    t1 = this.intermediatePointwise.apply( t0 );
    t0 = this.excitationPointwise.apply( t1 );

    t1 = tf.mul( inputTensor, t0 );
    t0.dispose();
    return t1;
  }

}
<|endoftext|>


<commit_before>import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { $ } from 'meteor/jquery';
import { Session } from 'meteor/session';
import { gui } from '/lib/const';
import { TAPi18n } from 'meteor/tap:i18n';
import { ReactiveVar } from 'meteor/reactive-var';

import { sidebarWidth, sidebarPercentage, getDelegatesMenu, toggleSidebar } from '/imports/ui/modules/menu';
import { getFlag, getUser } from '/imports/ui/templates/components/identity/avatar/avatar';
import { getCoin } from '/imports/api/blockchain/modules/web3Util';
import { Collectives } from '/imports/api/collectives/Collectives';

import '/imports/ui/templates/layout/sidebar/sidebar.html';
import '/imports/ui/templates/components/collective/collective.js';
import '/imports/ui/templates/widgets/inbox/inbox.js';

/**
* @summary draws the sidebar if activated
*/
function drawSidebar() {
  if (Session.get('sidebar') === true && $('#menu').css('margin-left') === `-${sidebarPercentage()}%`) {
    Session.set('sidebar', false);
  }
}

function labelName(user) {
  let name = `${getFlag(user.profile, true)} ${user.username}`;
  if (user._id === Meteor.userId()) {
    name += ` <span class='sidebar-tag'>${TAPi18n.__('you')}</span>`;
  }
  return name;
}

/**
* @summary translates db object to a menu ux object
* @param {object} user database user object
*/
const _dataToMenu = (user) => {
  if (user) {
    return {
      id: user._id,
      label: labelName(user),
      icon: user.profile.picture,
      iconActivated: false,
      feed: 'user',
      value: true,
      separator: false,
      url: `/address/${user.username}`,
      selected: false,
    };
  }
  return undefined;
};

/**
* @summary for a given db result returns list with menu options
* @param {object} db data to parse for menu options
* @param {boolean} sort if do alphabetical sort or not
*/
function getList(db, sort) {
  const members = [];
  for (const i in db) {
    members.push(_dataToMenu(db[i]));
  }
  if (sort) {
    return _.sortBy(members, (user) => { return user.label; });
  }
  return members;
}

/**
* @summary gets list of delegats for current user
* @param {object} contractFeed
* @param {object} transactionFeed
*/
function getDelegates(contractFeed, transactionFeed) {
  const delegates = _.sortBy(getDelegatesMenu(contractFeed, transactionFeed), (user) => { return parseInt(0 - (user.sent + user.received), 10); });
  let delegateList = [];
  // let totalVotes = 0;
  for (const i in delegates) {
    if (!Meteor.users.find({ _id: delegates[i].userId }).fetch()[0]) {
      getUser(delegates[i].userId);
    } else {
      delegateList.push(Meteor.users.find({ _id: delegates[i].userId }).fetch()[0]);
    }
  }

  // remove duplicates
  let finalList = delegateList;
  for (let i = 0; i < delegateList.length; i += 1) {
    for (let k = 0; k < finalList.length; k += 1) {
      if (i !== k) {
        if (delegateList[k] && delegateList[i] && delegateList[i]._id === delegateList[k]._id) {
          finalList[k] = 'EMPTY';
        }
      }
    }
  }
  finalList = _.without(finalList, 'EMPTY');
  delegateList = finalList;

  return getList(delegateList, false);
}

/**
* @summary all members of the collective without the delegates
* @param {object} currentDelegates list of delegates
*/
const _otherMembers = (currentDelegates) => {
  const members = getList(Meteor.users.find({}, { limit: 10 }).fetch(), true);
  const delegates = currentDelegates;
  let finalList = [];
  let isDelegate;
  if (delegates !== undefined && delegates.length > 0) {
    for (const id in members) {
      isDelegate = false;
      for (const del in delegates) {
        if (delegates[del] !== undefined) {
          if (members[id].id === delegates[del].id) {
            isDelegate = true;
            break;
          }
        }
      }
      if (!isDelegate) {
        finalList.push(members[id]);
      }
    }
  } else {
    finalList = members;
  }
  return finalList;
};

/**
* @summary formats delegate list for sidebar menu
* @param {object} list list of delegates
*/
const _adapt = (list) => {
  const menu = [];
  for (let i = 0; i < list.length; i += 1) {
    menu.push(_dataToMenu(list[i]));
  }
  return menu;
};

/**
* @summary displays the sidebar if logged
*/
const _showSidebar = () => {
  const percentage = sidebarPercentage();
  // $('.left').width(`${percentage}%`);
  if (!Meteor.Device.isPhone()) {
    if ($(window).width() < gui.MOBILE_MAX_WIDTH) {
      $('.navbar').css('left', 0);
      Session.set('miniWindow', true);
    } else {
      $('.navbar').css('left', `${percentage}%`);
      Session.set('miniWindow', false);
    }
    if (($(window).width() < gui.MOBILE_MAX_WIDTH && Session.get('sidebar')) || ($(window).width() >= gui.MOBILE_MAX_WIDTH && !Session.get('sidebar'))) {
      toggleSidebar(true);
    }
  }
  if (!Session.get('sidebar')) {
    const newMargin = parseInt(0 - sidebarWidth(), 10);
    $('#menu').css('margin-left', `${newMargin}px`);
    if (newMargin < 0) {
      Session.set('removedSidebar', true);
    }
  } else {
    let newRight = 0;
    if ($(window).width() < gui.MOBILE_MAX_WIDTH) {
      newRight = parseInt(0 - sidebarWidth(), 10);
    }
    $('#content').css('left', '250px');
    // $('#content').css('right', newRight);

    if (Meteor.Device.isPhone()) {
      $('#menu').css('margin-left', '0px');
    }

    if (Session.get('removedSidebar') && !Meteor.Device.isPhone()) {
      $('#menu').css('margin-left', `${0}px`);
      Session.set('removedSidebar', false);
    }
  }
};

Template.sidebar.onCreated(function () {
  Template.instance().delegates = new ReactiveVar();
  Template.instance().members = new ReactiveVar(0);
  Template.instance().participants = new ReactiveVar();
  Template.instance().memberCount = new ReactiveVar(0);
  Template.instance().daoList = new ReactiveVar();

  const instance = this;

  Meteor.call('userCount', function (error, result) {
    instance.memberCount.set(result);
  });
  const collectives = instance.subscribe('collectives', { view: 'daoList' });

  instance.autorun(function () {
    let delegateList;
    if (collectives.ready()) {
      Template.instance().daoList.set(Collectives.find().fetch());
    }
    if (Meteor.user()) {
      if (Meteor.user().profile.delegations && Meteor.user().profile.delegations.length > 0) {
        const subscription = instance.subscribe('delegates', { view: 'delegateList', items: _.pluck(Meteor.user().profile.delegations, 'userId') });

        if (subscription.ready()) {
          const delegates = [];
          for (let i = 0; i < Meteor.user().profile.delegations.length; i += 1) {
            delegates.push({ _id: Meteor.user().profile.delegations[i].userId });
          }
          delegateList = _adapt(Meteor.users.find({ $or: delegates }).fetch());
          Template.instance().delegates.set(delegateList);
          Template.instance().participants.set(_otherMembers(delegateList));
          _showSidebar();
        }
      }
    }
    if (!delegateList) {
      Template.instance().participants.set(_otherMembers());
    }
  });
});

/**
* @summary draws main menu for logged user
* @param {object} user to parse
* @returns {object} menu
*/
const _getMenu = () => {
  // dao feeds
  const menu = [];
  const daoList = Template.instance().daoList.get();

  let daoMenu;
  if (daoList && daoList.length > 0) {
    for (let h = 0; h < daoList.length; h += 1) {
      if (daoList[h].profile.menu && daoList[h].profile.menu.length > 0) {
        for (let j = 0; j < daoList[h].profile.menu.length; j += 1) {
          daoMenu = daoList[h].profile.menu[j];
          daoMenu.id = parseInt(menu.length - 1, 10);
          menu.push(daoMenu);
        }
      }
    }
  }

  // subjectivity
  return menu;
};

Template.sidebar.onCreated(function () {
  Template.instance().resizing = false;
});

let resizeId;
const _doneResizing = (instance) => {
  const template = instance;
  // template.resizing = false;
};

Template.sidebar.onRendered(() => {
  // $('.left').width(`${sidebarPercentage()}%`);
  if (!Meteor.Device.isPhone()) {
    $('.navbar').css('left', `${sidebarPercentage()}%`);
  }
  Session.set('sidebar', true);
  Session.set('removedSidebar', true);
  drawSidebar();

  const instance = Template.instance();

  $(window).resize(() => {
    instance.resizing = true;
    clearTimeout(resizeId);
    resizeId = setTimeout(_doneResizing(instance), 5000);
    if (!Meteor.Device.isPhone()) {
      Session.set('sidebar', true);
      _showSidebar();
    }
  });
});

Template.sidebar.helpers({
  delegate() {
    return Template.instance().delegates.get();
  },
  participant() {
    return Template.instance().participants.get();
  },
  member() {
    return Template.instance().members.get();
  },
  members() {
    const count = Template.instance().memberCount.get();
    if (count === 1) {
      return `${count} ${TAPi18n.__('moloch-address')}`;
    }
    return `${count} ${TAPi18n.__('moloch-addresses')}`;
  },
  totalMembers() {
    if (Template.instance().members.get()) {
      return Template.instance().members.get().length;
    }
    return 0;
  },
  replicator() {
    return `<a href="${Meteor.settings.public.web.sites.tokens}" target="_blank" ontouchstart="">${TAPi18n.__('start-a-democracy')}</a>`;
  },
  totalDelegates() {
    if (Template.instance().delegates.get()) {
      return Template.instance().delegates.get().length;
    }
    return 0;
  },
  menu() {
    return _getMenu();
  },
  style() {
    if (!Meteor.Device.isPhone() && Meteor.user()) {
      return 'left-edit';
    }
    return '';
  },
  sidebarContext() {
    const instance = Template.instance();
    if (!Meteor.Device.isPhone() && !instance.resizing) {
      Session.set('sidebar', true);
      _showSidebar();
    }
    return true;
  },
  sidebarStyle() {
    if (!Meteor.Device.isPhone()) {
      return 'sidebar-desktop';
    }
    return '';
  },
});

export const showSidebar = _showSidebar;
<commit_msg>will improve with days<commit_after>import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { $ } from 'meteor/jquery';
import { Session } from 'meteor/session';
import { gui } from '/lib/const';
import { TAPi18n } from 'meteor/tap:i18n';
import { ReactiveVar } from 'meteor/reactive-var';

import { sidebarWidth, sidebarPercentage, getDelegatesMenu, toggleSidebar } from '/imports/ui/modules/menu';
import { getFlag, getUser } from '/imports/ui/templates/components/identity/avatar/avatar';
import { getCoin } from '/imports/api/blockchain/modules/web3Util';
import { Collectives } from '/imports/api/collectives/Collectives';

import '/imports/ui/templates/layout/sidebar/sidebar.html';
import '/imports/ui/templates/components/collective/collective.js';
import '/imports/ui/templates/widgets/inbox/inbox.js';

/**
* @summary draws the sidebar if activated
*/
function drawSidebar() {
  if (Session.get('sidebar') === true && $('#menu').css('margin-left') === `-${sidebarPercentage()}%`) {
    Session.set('sidebar', false);
  }
}

function labelName(user) {
  let name = `${getFlag(user.profile, true)} ${user.username}`;
  if (user._id === Meteor.userId()) {
    name += ` <span class='sidebar-tag'>${TAPi18n.__('you')}</span>`;
  }
  return name;
}

/**
* @summary translates db object to a menu ux object
* @param {object} user database user object
*/
const _dataToMenu = (user) => {
  if (user) {
    return {
      id: user._id,
      label: labelName(user),
      icon: user.profile.picture,
      iconActivated: false,
      feed: 'user',
      value: true,
      separator: false,
      url: `/address/${user.username}`,
      selected: false,
    };
  }
  return undefined;
};

/**
* @summary for a given db result returns list with menu options
* @param {object} db data to parse for menu options
* @param {boolean} sort if do alphabetical sort or not
*/
function getList(db, sort) {
  const members = [];
  for (const i in db) {
    members.push(_dataToMenu(db[i]));
  }
  if (sort) {
    return _.sortBy(members, (user) => { return user.label; });
  }
  return members;
}

/**
* @summary gets list of delegats for current user
* @param {object} contractFeed
* @param {object} transactionFeed
*/
function getDelegates(contractFeed, transactionFeed) {
  const delegates = _.sortBy(getDelegatesMenu(contractFeed, transactionFeed), (user) => { return parseInt(0 - (user.sent + user.received), 10); });
  let delegateList = [];
  // let totalVotes = 0;
  for (const i in delegates) {
    if (!Meteor.users.find({ _id: delegates[i].userId }).fetch()[0]) {
      getUser(delegates[i].userId);
    } else {
      delegateList.push(Meteor.users.find({ _id: delegates[i].userId }).fetch()[0]);
    }
  }

  // remove duplicates
  let finalList = delegateList;
  for (let i = 0; i < delegateList.length; i += 1) {
    for (let k = 0; k < finalList.length; k += 1) {
      if (i !== k) {
        if (delegateList[k] && delegateList[i] && delegateList[i]._id === delegateList[k]._id) {
          finalList[k] = 'EMPTY';
        }
      }
    }
  }
  finalList = _.without(finalList, 'EMPTY');
  delegateList = finalList;

  return getList(delegateList, false);
}

/**
* @summary all members of the collective without the delegates
* @param {object} currentDelegates list of delegates
*/
const _otherMembers = (currentDelegates) => {
  const members = getList(Meteor.users.find({}, { limit: 10 }).fetch(), true);
  const delegates = currentDelegates;
  let finalList = [];
  let isDelegate;
  if (delegates !== undefined && delegates.length > 0) {
    for (const id in members) {
      isDelegate = false;
      for (const del in delegates) {
        if (delegates[del] !== undefined) {
          if (members[id].id === delegates[del].id) {
            isDelegate = true;
            break;
          }
        }
      }
      if (!isDelegate) {
        finalList.push(members[id]);
      }
    }
  } else {
    finalList = members;
  }
  return finalList;
};

/**
* @summary formats delegate list for sidebar menu
* @param {object} list list of delegates
*/
const _adapt = (list) => {
  const menu = [];
  for (let i = 0; i < list.length; i += 1) {
    menu.push(_dataToMenu(list[i]));
  }
  return menu;
};

/**
* @summary displays the sidebar if logged
*/
const _showSidebar = () => {
  const percentage = sidebarPercentage();
  // $('.left').width(`${percentage}%`);
  if (!Meteor.Device.isPhone()) {
    if ($(window).width() < gui.MOBILE_MAX_WIDTH) {
      $('.navbar').css('left', 0);
      Session.set('miniWindow', true);
    } else {
      $('.navbar').css('left', `${percentage}%`);
      Session.set('miniWindow', false);
    }
    if (($(window).width() < gui.MOBILE_MAX_WIDTH && Session.get('sidebar')) || ($(window).width() >= gui.MOBILE_MAX_WIDTH && !Session.get('sidebar'))) {
      toggleSidebar(true);
    }
  }
  if (!Session.get('sidebar')) {
    const newMargin = parseInt(-10 - sidebarWidth(), 10);
    $('#menu').css('margin-left', `${newMargin}px`);
    if (newMargin < 0) {
      Session.set('removedSidebar', true);
    }
  } else {
    let newRight = 0;
    if ($(window).width() < gui.MOBILE_MAX_WIDTH) {
      newRight = parseInt(0 - sidebarWidth(), 10);
    }
    $('#content').css('left', '250px');
    // $('#content').css('right', newRight);

    if (Meteor.Device.isPhone()) {
      $('#menu').css('margin-left', '0px');
    }

    if (Session.get('removedSidebar') && !Meteor.Device.isPhone()) {
      $('#menu').css('margin-left', `${0}px`);
      Session.set('removedSidebar', false);
    }
  }
};

Template.sidebar.onCreated(function () {
  Template.instance().delegates = new ReactiveVar();
  Template.instance().members = new ReactiveVar(0);
  Template.instance().participants = new ReactiveVar();
  Template.instance().memberCount = new ReactiveVar(0);
  Template.instance().daoList = new ReactiveVar();

  const instance = this;

  Meteor.call('userCount', function (error, result) {
    instance.memberCount.set(result);
  });
  const collectives = instance.subscribe('collectives', { view: 'daoList' });

  instance.autorun(function () {
    let delegateList;
    if (collectives.ready()) {
      Template.instance().daoList.set(Collectives.find().fetch());
    }
    if (Meteor.user()) {
      if (Meteor.user().profile.delegations && Meteor.user().profile.delegations.length > 0) {
        const subscription = instance.subscribe('delegates', { view: 'delegateList', items: _.pluck(Meteor.user().profile.delegations, 'userId') });

        if (subscription.ready()) {
          const delegates = [];
          for (let i = 0; i < Meteor.user().profile.delegations.length; i += 1) {
            delegates.push({ _id: Meteor.user().profile.delegations[i].userId });
          }
          delegateList = _adapt(Meteor.users.find({ $or: delegates }).fetch());
          Template.instance().delegates.set(delegateList);
          Template.instance().participants.set(_otherMembers(delegateList));
          _showSidebar();
        }
      }
    }
    if (!delegateList) {
      Template.instance().participants.set(_otherMembers());
    }
  });
});

/**
* @summary draws main menu for logged user
* @param {object} user to parse
* @returns {object} menu
*/
const _getMenu = () => {
  // dao feeds
  const menu = [];
  const daoList = Template.instance().daoList.get();

  let daoMenu;
  if (daoList && daoList.length > 0) {
    for (let h = 0; h < daoList.length; h += 1) {
      if (daoList[h].profile.menu && daoList[h].profile.menu.length > 0) {
        for (let j = 0; j < daoList[h].profile.menu.length; j += 1) {
          daoMenu = daoList[h].profile.menu[j];
          daoMenu.id = parseInt(menu.length - 1, 10);
          menu.push(daoMenu);
        }
      }
    }
  }

  // subjectivity
  return menu;
};

Template.sidebar.onCreated(function () {
  Template.instance().resizing = false;
});

let resizeId;
const _doneResizing = (instance) => {
  const template = instance;
  // template.resizing = false;
};

Template.sidebar.onRendered(() => {
  // $('.left').width(`${sidebarPercentage()}%`);
  if (!Meteor.Device.isPhone()) {
    $('.navbar').css('left', `${sidebarPercentage()}%`);
  }
  Session.set('sidebar', true);
  Session.set('removedSidebar', true);
  drawSidebar();

  const instance = Template.instance();

  $(window).resize(() => {
    instance.resizing = true;
    clearTimeout(resizeId);
    resizeId = setTimeout(_doneResizing(instance), 5000);
    if (!Meteor.Device.isPhone()) {
      Session.set('sidebar', true);
      _showSidebar();
    }
  });
});

Template.sidebar.helpers({
  delegate() {
    return Template.instance().delegates.get();
  },
  participant() {
    return Template.instance().participants.get();
  },
  member() {
    return Template.instance().members.get();
  },
  members() {
    const count = Template.instance().memberCount.get();
    if (count === 1) {
      return `${count} ${TAPi18n.__('moloch-address')}`;
    }
    return `${count} ${TAPi18n.__('moloch-addresses')}`;
  },
  totalMembers() {
    if (Template.instance().members.get()) {
      return Template.instance().members.get().length;
    }
    return 0;
  },
  replicator() {
    return `<a href="${Meteor.settings.public.web.sites.tokens}" target="_blank" ontouchstart="">${TAPi18n.__('start-a-democracy')}</a>`;
  },
  totalDelegates() {
    if (Template.instance().delegates.get()) {
      return Template.instance().delegates.get().length;
    }
    return 0;
  },
  menu() {
    return _getMenu();
  },
  style() {
    if (!Meteor.Device.isPhone() && Meteor.user()) {
      return 'left-edit';
    }
    return '';
  },
  sidebarContext() {
    const instance = Template.instance();
    if (!Meteor.Device.isPhone() && !instance.resizing) {
      Session.set('sidebar', true);
      _showSidebar();
    }
    return true;
  },
  sidebarStyle() {
    if (!Meteor.Device.isPhone()) {
      return 'sidebar-desktop';
    }
    return '';
  },
});

export const showSidebar = _showSidebar;
<|endoftext|>


<commit_before>/*******************************************************************************
 * ENdoSnipe 5.0 - (https://github.com/endosnipe)
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2012 Acroquest Technology Co.,Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 ******************************************************************************/
ENS.NodeInfoParentView = wgp.AbstractView
		.extend({
			initialize : function(argument, treeSettings) {
				ENS.nodeinfo.viewList = [];

				this.viewtype = wgp.constants.VIEW_TYPE.VIEW;
				this.graphIds = [];
				this.treeSettings = treeSettings;
				var treeListView = new wgp.TreeView({
					id : "tree",
					rootView : this
				});
				var appView = new ENS.AppView();
				appView.addView(treeListView, "tree");

				this.divId = this.$el.attr("id");
				var id = argument["ids"];
				this.maxId = 0;
				this.viewList = {};

				this.graphPerPage = 12;
				this.noOfPage = 0;

				// 全ての子ノードのパスを取得し、グラフを表示する
				this.getChildTargetNodes(treeSettings.id);

				// dual slider area (add div and css, and make slider)
				$("#" + this.$el.attr("id")).append(
						'

');
				$('#' + id.dualSliderArea).css(
						ENS.nodeinfo.parent.css.dualSliderArea);
				$('#' + id.dualSliderArea).css(
						ENS.nodeinfo.parent.css.dualSliderArea);
				this.dualSliderView = new ENS.DualSliderView({
					id : id.dualSliderArea,
					rootView : this
				});

				var instance = this;

				this.dualSliderView.setScaleMovedEvent(function(from, to) {
					var viewList = ENS.nodeinfo.viewList;
					for ( var key in viewList) {
						var instance = viewList[key];
						// グラフの表示期間の幅を更新する
						instance.updateDisplaySpan(from, to);
						// グラフの表示データを更新する
						instance.updateGraphData(key, from, to);
					}
				});

				$("#" + this.$el.attr("id")).append(
						'

');

				this.render();
			},

			render : function() {
				console.log('call render');
			},
			onAdd : function(element) {
				console.log('call onAdd');
			},
			onChange : function(element) {
				console.log('called changeModel');
			},
			onRemove : function(element) {
				console.log('called removeModel');
			},
			_addGraphDivision : function(graphId) {
				var viewId = null;
				var viewClassName = "ENS.ResourceGraphElementView";
				var tempId = graphId.split("/");
				var dataId = tempId[tempId.length - 1];
				var treeSettings = {
					data : dataId,
					id : graphId,
					measurementUnit : "",
					parentTreeId : "",
					treeId : ""
				};
				var viewAttribute = {
					id : graphId,
					rootView : this,
					graphId : graphId,
					title : dataId,
					noTermData : false,
					term : 1800 * 2,
					width : 260,
					height : 200,
					displayNo : this.num_display,
					dateWindow : [ new Date() - 60 * 60 * 1000, new Date() ],
					attributes : {
						xlabel : "Time",
						ylabel : "value",
						labels : [ "time", "PC1", "PC2" ]
					}
				};

				if (viewId == null) {
					viewId = this.maxId;
					this.maxId++;
				} else {
					if (viewId > this.maxId) {
						this.maxId = viewId + 1;
					}
				}

				if ($("#pagingDivArea").length <= 0) {
					$("#" + this.divId)
							.append("

");
				}

				if ($("#page").length <= 0) {
					$("#pagingDivArea").append(
							"

");
				}
				var newDivAreaId = this.divId + "_" + viewId;

				var newDivArea = $("

");

				$("#page").append(newDivArea);

				newDivArea.width(300);
				newDivArea.height(300);

				$.extend(true, viewAttribute, {
					id : newDivAreaId
				});
				// 動的に生成するオブジェクトを切り替える必要があるため、やむを得ずeval()を使う
				var view = eval("new " + viewClassName
						+ "(viewAttribute, treeSettings)");
				var registerId = view.getRegisterId();
				ENS.nodeinfo.viewList[registerId] = view;
			},
			getTermData : function() {
				// データの成型
			},
			_setGraphIds : function(parseId, collection) {
				// console.log(parseId);
				var instance = this;
				_.each(collection.models, function(model) {
					var attr = {};
					var children = collection.where({
						parentTreeId : model.id
					});
					var childrenData = [];
					_.each(children, function(child, index) {
						childrenData.push(instance.createTreeData(child));
					});
					attr["Id"] = treeModel.get("id");

					// icon decided
					var icon = null;

				});
			},
			/**
			 * 指定されたIDの子要素のIDを全て取得する要求電文を送信する。

			 * この要求電文のコールバック関数の中で、グラフ表示を行う。
			 */
			getChildTargetNodes : function(parentId) {
				var sendData = {
					parentTreeId : parentId
				};
				var url = ENS.tree.GET_CHILD_TARGET_NODES;
				// Ajax通信用の設定
				var settings = {
					data : sendData,
					url : url
				};

				// 非同期通信でデータを送信する
				var ajaxHandler = new wgp.AjaxHandler();
				settings[wgp.ConnectionConstants.SUCCESS_CALL_OBJECT_KEY] = this;
				settings[wgp.ConnectionConstants.SUCCESS_CALL_FUNCTION_KEY] = "callbackGetChildTargetNodes";
				ajaxHandler.requestServerAsync(settings);
			},
			callbackGetChildTargetNodes : function(childNodes) {

				this.num_display = childNodes.length;
				this.noOfPage = Math.floor(this.num_display / 12) + 1;

				if ($("#pagingDemo").length <= 0) {
					$("#" + this.divId)
							.append(
									"

");
				}
				var instance = this;
				/*
				 * シグナルノードやレポートノードの上の階層にあるグラフノードを格納する配列
				 * 複数のシグナルノードやレポートノードがグラフノードの下にある際に、
				 * 同じグラフをいくつも表示してしまうことを防止するために使う。
				 */
				var parentGraphNameList = [];

				_.each(childNodes, function(graphName) {

					// すでに存在するグラフの場合は追加表示しない
					if (parentGraphNameList.indexOf(graphName) >= 0) {
						return;
					}
					parentGraphNameList.push(graphName);
				});

				this.childNodes = parentGraphNameList;
				this.pagingGraph();
			},
			createGraphOnPage : function(startVar, endVar) {

				for ( var i = startVar; i < endVar; i++) {
					this._addGraphDivision(this.childNodes[i])
				}
			},
			createParseData : function(parse, collection) {
				var jsonData = [];
				var instance = this;
				// find root tree
				var rootNodeList = collection.where({
					parentTreeId : ""
				});
				_.each(rootNodeList, function(treeModel, index) {
					jsonData.push(instance.createTreeData(parse, treeModel,
							collection));
				});
				return jsonData;
			},
			createTreeData : function(parse, treeModel, collection) {
				var instance = this;

				var attr = {};
				var data = treeModel.get("data");
				var children = collection.where({
					parentTreeId : treeModel.get("id")
				});
				var childrenData = [];
				_.each(children, function(child, index) {
					childrenData.push(instance.createTreeData(parse, child,
							collection));
				});
				attr["Id"] = treeModel.get("id");

				// icon decided
				var icon = null;
				if (children.length === 0) {
					if (treeModel.id.indexOf(parse) != -1) {
						this.graphIds.push(treeModel.get("id"));
					}
				} else {
				}
				var treeData = {
					data : {
						title : data,
						attr : attr,
						icon : icon
					},
					children : childrenData
				};
				return treeData;
			},
			pagingGraph : function() {

				var instance = this;
				$("#pagingDemo")
						.pagination(
								this.num_display,
								{
									items_per_page : this.graphPerPage,
									num_display_entries : 8,
									current_page : 0,
									num_edge_entries : 2,
									callback : function(page) {

										if ($("#page").length > 0) {
											$("#page").remove();
										}

										var startVar = page
												* instance.graphPerPage;
										var endVar = (page + 1)
												* instance.graphPerPage;
										if (endVar > instance.num_display) {
											endVar = endVar
													- (endVar - instance.num_display);
										}
										instance.createGraphOnPage(startVar,
												endVar);
										return false;
									}
								});
			},
			destroy : function() {
				var viewList = ENS.nodeinfo.viewList;
				var appView = ENS.AppView();
				for ( var key in viewList) {
					var instance = viewList[key];
					appView.removeView(instance);
				}
			}
		});
<commit_msg>issues #16<commit_after>/*******************************************************************************
 * ENdoSnipe 5.0 - (https://github.com/endosnipe)
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2012 Acroquest Technology Co.,Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 ******************************************************************************/
ENS.NodeInfoParentView = wgp.AbstractView
		.extend({
			initialize : function(argument, treeSettings) {
				ENS.nodeinfo.viewList = [];

				this.viewtype = wgp.constants.VIEW_TYPE.VIEW;
				this.graphIds = [];
				this.treeSettings = treeSettings;
				var treeListView = new wgp.TreeView({
					id : "tree",
					rootView : this
				});
				var appView = new ENS.AppView();
				appView.addView(treeListView, "tree");

				this.divId = this.$el.attr("id");
				var id = argument["ids"];
				this.maxId = 0;
				this.viewList = {};

				this.graphPerPage = 12;
				this.noOfPage = 0;
				this.moveScale = [];

				// 全ての子ノードのパスを取得し、グラフを表示する
				this.getChildTargetNodes(treeSettings.id);

				// dual slider area (add div and css, and make slider)
				$("#" + this.$el.attr("id")).append(
						'

');
				$('#' + id.dualSliderArea).css(
						ENS.nodeinfo.parent.css.dualSliderArea);
				$('#' + id.dualSliderArea).css(
						ENS.nodeinfo.parent.css.dualSliderArea);
				this.dualSliderView = new ENS.DualSliderView({
					id : id.dualSliderArea,
					rootView : this
				});

				var instance = this;

				this.dualSliderView.setScaleMovedEvent(function(from, to) {
					instance.moveScale["from"] = from;
					instance.moveScale["to"] = to;
					var viewList = ENS.nodeinfo.viewList;
					for ( var key in viewList) {
						var ins = viewList[key];
						// グラフの表示期間の幅を更新する
						ins.updateDisplaySpan(from, to);
						// グラフの表示データを更新する
						ins.updateGraphData(key, from, to);
					}
				});

				$("#" + this.$el.attr("id")).append(
						'

');

				this.render();
			},

			render : function() {
				console.log('call render');
			},
			onAdd : function(element) {
				console.log('call onAdd');
			},
			onChange : function(element) {
				console.log('called changeModel');
			},
			onRemove : function(element) {
				console.log('called removeModel');
			},
			_addGraphDivision : function(graphId) {
				var viewId = null;
				var viewClassName = "ENS.ResourceGraphElementView";
				var tempId = graphId.split("/");
				var dataId = tempId[tempId.length - 1];
				var treeSettings = {
					data : dataId,
					id : graphId,
					measurementUnit : "",
					parentTreeId : "",
					treeId : ""
				};
				var viewAttribute = {
					id : graphId,
					rootView : this,
					graphId : graphId,
					title : dataId,
					noTermData : false,
					term : 1800 * 2,
					width : 260,
					height : 200,
					displayNo : this.num_display,
					dateWindow : [ new Date() - 60 * 60 * 1000, new Date() ],
					attributes : {
						xlabel : "Time",
						ylabel : "value",
						labels : [ "time", "PC1", "PC2" ]
					}
				};

				if (viewId == null) {
					viewId = this.maxId;
					this.maxId++;
				} else {
					if (viewId > this.maxId) {
						this.maxId = viewId + 1;
					}
				}

				if ($("#pagingDivArea").length <= 0) {
					$("#" + this.divId)
							.append("

");
				}

				if ($("#page").length <= 0) {
					$("#pagingDivArea").append(
							"

");
				}
				var newDivAreaId = this.divId + "_" + viewId;

				var newDivArea = $("

");

				$("#page").append(newDivArea);

				newDivArea.width(300);
				newDivArea.height(300);

				$.extend(true, viewAttribute, {
					id : newDivAreaId
				});
				// 動的に生成するオブジェクトを切り替える必要があるため、やむを得ずeval()を使う
				var view = eval("new " + viewClassName
						+ "(viewAttribute, treeSettings)");
				var registerId = view.getRegisterId();
				ENS.nodeinfo.viewList[registerId] = view;
			},
			getTermData : function() {
				// データの成型
			},
			_setGraphIds : function(parseId, collection) {
				var instance = this;
				_.each(collection.models, function(model) {
					var attr = {};
					var children = collection.where({
						parentTreeId : model.id
					});
					var childrenData = [];
					_.each(children, function(child, index) {
						childrenData.push(instance.createTreeData(child));
					});
					attr["Id"] = treeModel.get("id");

					// icon decided
					var icon = null;

				});
			},
			/**
			 * 指定されたIDの子要素のIDを全て取得する要求電文を送信する。

			 * この要求電文のコールバック関数の中で、グラフ表示を行う。
			 */
			getChildTargetNodes : function(parentId) {
				var sendData = {
					parentTreeId : parentId
				};
				var url = ENS.tree.GET_CHILD_TARGET_NODES;
				// Ajax通信用の設定
				var settings = {
					data : sendData,
					url : url
				};

				// 非同期通信でデータを送信する
				var ajaxHandler = new wgp.AjaxHandler();
				settings[wgp.ConnectionConstants.SUCCESS_CALL_OBJECT_KEY] = this;
				settings[wgp.ConnectionConstants.SUCCESS_CALL_FUNCTION_KEY] = "callbackGetChildTargetNodes";
				ajaxHandler.requestServerAsync(settings);
			},
			callbackGetChildTargetNodes : function(childNodes) {

				this.num_display = childNodes.length;
				this.noOfPage = Math.floor(this.num_display / 12) + 1;

				if ($("#pagingDemo").length <= 0) {
					$("#" + this.divId)
							.append(
									"

");
				}
				var instance = this;
				/*
				 * シグナルノードやレポートノードの上の階層にあるグラフノードを格納する配列
				 * 複数のシグナルノードやレポートノードがグラフノードの下にある際に、
				 * 同じグラフをいくつも表示してしまうことを防止するために使う。
				 */
				var parentGraphNameList = [];

				_.each(childNodes, function(graphName) {

					// すでに存在するグラフの場合は追加表示しない
					if (parentGraphNameList.indexOf(graphName) >= 0) {
						return;
					}
					parentGraphNameList.push(graphName);
				});

				this.childNodes = parentGraphNameList;
				this.pagingGraph();
			},
			createGraphOnPage : function(startVar, endVar) {
				var from = this.moveScale["from"];
				var to = this.moveScale["to"];
				for ( var i = startVar; i < endVar; i++) {
					var viewName = this.childNodes[i];
					this._addGraphDivision(viewName);
					var instance = ENS.nodeinfo.viewList[viewName];
					if (from != undefined && to != undefined) {
						instance.updateDisplaySpan(from, to);
						instance.updateGraphData(viewName, from, to);
					}
				}
			},
			createParseData : function(parse, collection) {
				var jsonData = [];
				var instance = this;
				// find root tree
				var rootNodeList = collection.where({
					parentTreeId : ""
				});
				_.each(rootNodeList, function(treeModel, index) {
					jsonData.push(instance.createTreeData(parse, treeModel,
							collection));
				});
				return jsonData;
			},
			createTreeData : function(parse, treeModel, collection) {
				var instance = this;

				var attr = {};
				var data = treeModel.get("data");
				var children = collection.where({
					parentTreeId : treeModel.get("id")
				});
				var childrenData = [];
				_.each(children, function(child, index) {
					childrenData.push(instance.createTreeData(parse, child,
							collection));
				});
				attr["Id"] = treeModel.get("id");

				// icon decided
				var icon = null;
				if (children.length === 0) {
					if (treeModel.id.indexOf(parse) != -1) {
						this.graphIds.push(treeModel.get("id"));
					}
				} else {
				}
				var treeData = {
					data : {
						title : data,
						attr : attr,
						icon : icon
					},
					children : childrenData
				};
				return treeData;
			},
			pagingGraph : function() {

				var instance = this;
				$("#pagingDemo").pagination(this.num_display, {
					items_per_page : this.graphPerPage,
					num_display_entries : 8,
					current_page : 0,
					num_edge_entries : 2,
					callback : function(page) {

						if ($("#page").length > 0) {
							$("#page").remove();
						}

						var startVar = page * instance.graphPerPage;
						var endVar = (page + 1) * instance.graphPerPage;
						if (endVar > instance.num_display) {
							endVar = endVar - (endVar - instance.num_display);
						}
						instance.createGraphOnPage(startVar, endVar);
						return false;
					}
				});
			},
			destroy : function() {
				var viewList = ENS.nodeinfo.viewList;
				var appView = ENS.AppView();
				for ( var key in viewList) {
					var instance = viewList[key];
					appView.removeView(instance);
				}
			}
		});
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @flow
 */
'use strict';

const runJest = require('../runJest');
const path = require('path');

const testRootDir = path.resolve(__dirname, '..', '..');
expect.addSnapshotSerializer({
  print: val => val.replace(new RegExp(testRootDir, 'g'), '/MOCK_ABOLUTE_PATH'),
  test: val => typeof val === 'string' && val.includes(testRootDir),
});

describe('--listTests flag', () => {
  it('causes tests to be printed in different lines', () => {
    const {status, stdout} = runJest('list_tests', ['--listTests']);

    expect(status).toBe(0);
    expect(stdout.split('\n').sort().join('\n')).toMatchSnapshot();
  });

  it('causes tests to be printed out as JSON when using the --json flag', () => {
    const {status, stderr} = runJest('list_tests', ['--listTests', '--json']);

    expect(status).toBe(0);
    expect(() => JSON.parse(stderr)).not.toThrow();
    expect(JSON.stringify(JSON.parse(stderr).sort())).toMatchSnapshot();
  });
});
<commit_msg>Unbreak master.<commit_after>/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @flow
 */
'use strict';

const runJest = require('../runJest');
const path = require('path');

const testRootDir = path.resolve(__dirname, '..', '..');
// $FlowFixMe
expect.addSnapshotSerializer({
  print: val => val.replace(new RegExp(testRootDir, 'g'), '/MOCK_ABOLUTE_PATH'),
  test: val => typeof val === 'string' && val.includes(testRootDir),
});

describe('--listTests flag', () => {
  it('causes tests to be printed in different lines', () => {
    const {status, stdout} = runJest('list_tests', ['--listTests']);

    expect(status).toBe(0);
    expect(stdout.split('\n').sort().join('\n')).toMatchSnapshot();
  });

  it('causes tests to be printed out as JSON when using the --json flag', () => {
    const {status, stderr} = runJest('list_tests', ['--listTests', '--json']);

    expect(status).toBe(0);
    expect(() => JSON.parse(stderr)).not.toThrow();
    expect(JSON.stringify(JSON.parse(stderr).sort())).toMatchSnapshot();
  });
});
<|endoftext|>


<commit_before>/*
* utilities
* author: ronglin
* create date: 2014.6.21
*/

'use strict';

module.exports = {

    arg2arr: function() {
        var splice = Array.prototype.splice;
        return function(args, skip) {
            return splice.call(args, skip || 0);
        };
    }(),

    type: function() {
        var op = Object.prototype;
        var class2type = {}, natives = 'Boolean Number String Function Array Date RegExp Object Error'.split(' ');
        for (var i = 0; i < natives.length; i++) {class2type['[object ' + natives[i] + ']'] = natives[i].toLowerCase(); }
        return function(obj) {
            return obj == null ? String(obj) : class2type[op.toString.call(obj)] || 'object';
        };
    }(),

    isDate: function(obj) {
        return this.type(obj) === 'date';
    },

    isArray: function(obj) {
        return this.type(obj) === 'array';
    },

    isObject: function(obj) {
        return this.type(obj) === 'object';
    },

    isString: function(obj) {
        return this.type(obj) === 'string';
    },

    isFunction: function(obj) {
        return this.type(obj) === 'function';
    },

    isNumber: function(obj) {
        return this.type(obj) === 'number';
    },

    isNumeric: function (obj) {
        return !isNaN(parseFloat(obj)) && isFinite(obj);
    },

    isPlainObject: function (obj) {
        if (!obj || this.type(obj) !== "object" || obj.nodeType) {
            return false;
        }
        try {
            if (obj.constructor && !this.hasOwn(obj, "constructor") && !this.hasOwn(obj.constructor.prototype, "isPrototypeOf")) {
                return false;
            }
        } catch (e) {
            return false;
        }
        var key;
        for (key in obj) {}
        return key === undefined || this.hasOwn(obj, key);
    },

    hasOwn: function(o, prop){
        if ( o === null || o === undefined ) {
            return false;
        } else if ( o.hasOwnProperty ) {
            return o.hasOwnProperty( prop );
        } else {
            return ( this.type( o[prop] ) !== 'undefined' ) && o.constructor.prototype[prop] !== o[prop];
        }
    },

    each: function( obj, callback, args ) {
        if (!obj) { return; }
        //
        var name,
            i = 0,
            length = obj.length,
            isObj = length === undefined || this.isFunction( obj );

        if ( args ) {
            if ( isObj ) {
                for ( name in obj ) {
                    if ( callback.apply( obj[ name ], args ) === false ) {
                        break;
                    }
                }
            } else {
                for ( ; i < length; ) {
                    if ( callback.apply( obj[ i++ ], args ) === false ) {
                        break;
                    }
                }
            }

        // A special, fast, case for the most common use of each
        } else {
            if ( isObj ) {
                for ( name in obj ) {
                    if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) {
                        break;
                    }
                }
            } else {
                for ( ; i < length; ) {
                    if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) {
                        break;
                    }
                }
            }
        }

        return obj;
    },

    extend: function() {
        var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {},
            i = 1,
            length = arguments.length,
            deep = false;

        if (this.type(target) === "boolean") {
            deep = target;
            target = arguments[1] || {};
            i = 2;
        }
        if (this.type(target) !== "object" && !this.isFunction(target)) {
            target = {}
        }
        if (length === i) {
            target = this;
            --i;
        }
        for (i; i < length; i++) {
            if ((options = arguments[i]) != null) {
                for (name in options) {
                    src = target[name];
                    copy = options[name];
                    if (target === copy) {
                        continue;
                    }
                    if (deep && copy && (this.isPlainObject(copy) || (copyIsArray = this.isArray(copy)))) {
                        if (copyIsArray) {
                            copyIsArray = false;
                            clone = src && this.isArray(src) ? src : [];
                        } else {
                            clone = src && this.isPlainObject(src) ? src : {};
                        }
                        // WARNING: RECURSION
                        target[name] = this.extend(deep, clone, copy);
                    } else if (copy !== undefined) {
                        target[name] = copy;
                    }
                }
            }
        }
        return target;
    },

    inherit: function (subc, superc, overrides) {
        var F = function () { }, i;
        F.prototype = superc.prototype;
        subc.prototype = new F();
        subc.prototype.constructor = subc;
        subc.superclass = superc.prototype;
        if (superc.prototype.constructor == Object.prototype.constructor) {
            superc.prototype.constructor = superc;
        }
        if (overrides) {
            for (i in overrides) {
                if (this.hasOwn(overrides, i)) {
                    subc.prototype[i] = overrides[i];
                }
            }
        }
    },

    guid: function() {
        function s4() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); }
        return function(sep) {
            if (sep === true) { sep = '-'; } else { sep = sep || ''; }
            return (s4() + s4() + sep + s4() + sep + s4() + sep + s4() + sep + s4() + s4() + s4());
        };
    }(),

    unique: function(len) {
        return this.guid().substr(0, len);
    },

    padLeft: function(str, len, chr, reverse) {
        if (str !== null && str !== undefined) {
            str = str + ''; var num = len - str.length;
            if (num > 0) {
                for (var i = 0; i < num; i++) {
                    if (reverse === true) {
                        str = str + chr;
                    } else {
                        str = chr + str;
                    }
                }
            }
        }
        return str;
    },

    padRight: function(str, len, chr) {
        return this.padLeft(str, len, chr, true);
    },

    format: function (format) {
        var args = this.arg2arr(arguments, 1), arg;
        return format.replace(/\{(\d+)\}/g, function (m, i) {
            return (arg = args[i], (arg === null || arg === undefined) ? '' : arg);
        });
    },

    trim: function (str, set) {
        str = str || ''; set = set || {};
        if (set.find) {
            var exp = this.format('^{0}+|{0}+$', set.find);
            return str.replace(new RegExp(exp, 'g'), set.hold || '');
        } else if (set.findEnd) {
            var exp = this.format('{0}+$', set.findEnd);
            return str.replace(new RegExp(exp, 'g'), set.hold || '');
        } else if (set.findStart) {
            var exp = this.format('^{0}+', set.findStart);
            return str.replace(new RegExp(exp, 'g'), set.hold || '');
        } else {
            return str.replace(/^\s+|\s+$/g, set.hold || '');
        }
    },

    readObj: function(obj, namespace) {
        var names = namespace.split(/\.|\[|\]|\(/), ret = obj;
        this.each(names, function (i, key) { if (key && ret) { ret = (isNaN(key) ? (key === ')' ? ret() : ret[key]) : ret[parseInt(key, 10)]); } });
        return ret;
    },

    mapObj: function(obj, namespace, dft) {
        var parts = namespace.split(/\.|\[|\]/), names = [];
        this.each(parts, function (i, key) { if (key) { names.push(key); } });
        var lastName = names[names.length - 1], curr = obj = (obj || {}), prev;
        this.each(names, function (i, key) { prev = curr; curr = (curr[key] ? curr[key] : (curr[key] = isNaN(names[i + 1]) ? {} : [])); });
        if (prev) { prev[lastName] = dft; }
        return obj;
    },

    propCount: function(obj) {
        var count = 0;
        if (obj) {
            for (var key in obj) {
                if (this.hasOwn(obj, key)) {
                    count++;
                }
            }
        }
        return count;
    },

    appendQuery: function() {
        var allows = { 'boolean': true, 'number': true, 'string': true }; // object types: Boolean Number String Object Array Date RegExp Function
        return function(url, name, value) {
            if (url === null || url === undefined || (!name && name !== 0)) { return url; }
            if (this.type(name) === 'object' || this.type(name) === 'array') {
                var self = this;
                this.each(name, function (key, val) {// here 'key' fixed to simple type and will not loop again.
                    url = self.appendQuery(url, key, val);
                });
            } else if (allows[this.type(value)]) {
                url += ((url + '').indexOf('?') > -1) ? '' : '?';
                url += (/\?$/.test(url)) ? '' : '&';
                url += name + '=' + encodeURIComponent(String(value));
            }
            return url;
        };
    }(),

    setQuery: function(url, name, value) {
        if (url === null || url === undefined || (!name && name !== 0)) { return url; }
        var urlParams = this.getQuery(url), lowerParams = {}, keyMap = {}, params = {}, lower;
        params = 'object,array'.indexOf(this.type(name)) > -1 ? name : (params[name] = value, params);
        this.each(urlParams, function (key, val) {
            lowerParams[key.toLowerCase()] = val;
            keyMap[key] = key.toLowerCase();
        });
        this.each(params, function (key, val) {
            lower = (key + '').toLowerCase();
            if (lower in lowerParams) {
                lowerParams[lower] = val;
            } else {
                urlParams[key] = val;
            }
        });
        this.each(keyMap, function (f, t) {
            urlParams[f] = lowerParams[t];
        });
        //
        var sIndex = url.indexOf('?');
        sIndex = (sIndex === -1) ? url.length : sIndex;
        return this.appendQuery(url.substr(0, sIndex), urlParams);
    },

    getQuery: function(url, key) {
        var params = {};
        if (url === null || url === undefined) { return params; }
        var sIndex = url.indexOf('?');
        if (sIndex === -1) { return params; }
        //
        var query = url.substr(sIndex + 1);
        var pairs = query.replace(/\+/g, ' ').split('&');
        this.each(pairs, function(idx, pair) {
            var parts = pair.split('=');
            if (parts.length > 0) {
                params[parts[0]] = decodeURIComponent(parts[1] || '');
            }
        });
        //
        return key ? params[key] : params;
    }
};
<commit_msg>update<commit_after>/*
* utilities
* author: ronglin
* create date: 2014.6.21
*/

'use strict';

module.exports = {

    arg2arr: function() {
        var splice = Array.prototype.splice;
        return function(args, skip) {
            return splice.call(args, skip || 0);
        };
    }(),

    type: function() {
        var op = Object.prototype;
        var class2type = {}, natives = 'Boolean Number String Function Array Date RegExp Object Error'.split(' ');
        for (var i = 0; i < natives.length; i++) {class2type['[object ' + natives[i] + ']'] = natives[i].toLowerCase(); }
        return function(obj) {
            return obj == null ? String(obj) : class2type[op.toString.call(obj)] || 'object';
        };
    }(),

    isDate: function(obj) {
        return this.type(obj) === 'date';
    },

    isArray: function(obj) {
        return this.type(obj) === 'array';
    },

    isObject: function(obj) {
        return this.type(obj) === 'object';
    },

    isString: function(obj) {
        return this.type(obj) === 'string';
    },

    isBoolean: function(obj) {
        return this.type(obj) === 'boolean';
    },

    isFunction: function(obj) {
        return this.type(obj) === 'function';
    },

    isNumber: function(obj) {
        return this.type(obj) === 'number';
    },

    isNumeric: function (obj) {
        return !isNaN(parseFloat(obj)) && isFinite(obj);
    },

    isPlainObject: function (obj) {
        if (!obj || this.type(obj) !== "object" || obj.nodeType) {
            return false;
        }
        try {
            if (obj.constructor && !this.hasOwn(obj, "constructor") && !this.hasOwn(obj.constructor.prototype, "isPrototypeOf")) {
                return false;
            }
        } catch (e) {
            return false;
        }
        var key;
        for (key in obj) {}
        return key === undefined || this.hasOwn(obj, key);
    },

    hasOwn: function(o, prop){
        if ( o === null || o === undefined ) {
            return false;
        } else if ( o.hasOwnProperty ) {
            return o.hasOwnProperty( prop );
        } else {
            return ( this.type( o[prop] ) !== 'undefined' ) && o.constructor.prototype[prop] !== o[prop];
        }
    },

    each: function( obj, callback, args ) {
        if (!obj) { return; }
        //
        var name,
            i = 0,
            length = obj.length,
            isObj = length === undefined || this.isFunction( obj );

        if ( args ) {
            if ( isObj ) {
                for ( name in obj ) {
                    if ( callback.apply( obj[ name ], args ) === false ) {
                        break;
                    }
                }
            } else {
                for ( ; i < length; ) {
                    if ( callback.apply( obj[ i++ ], args ) === false ) {
                        break;
                    }
                }
            }

        // A special, fast, case for the most common use of each
        } else {
            if ( isObj ) {
                for ( name in obj ) {
                    if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) {
                        break;
                    }
                }
            } else {
                for ( ; i < length; ) {
                    if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) {
                        break;
                    }
                }
            }
        }

        return obj;
    },

    extend: function() {
        var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {},
            i = 1,
            length = arguments.length,
            deep = false;

        if (this.type(target) === "boolean") {
            deep = target;
            target = arguments[1] || {};
            i = 2;
        }
        if (this.type(target) !== "object" && !this.isFunction(target)) {
            target = {}
        }
        if (length === i) {
            target = this;
            --i;
        }
        for (i; i < length; i++) {
            if ((options = arguments[i]) != null) {
                for (name in options) {
                    src = target[name];
                    copy = options[name];
                    if (target === copy) {
                        continue;
                    }
                    if (deep && copy && (this.isPlainObject(copy) || (copyIsArray = this.isArray(copy)))) {
                        if (copyIsArray) {
                            copyIsArray = false;
                            clone = src && this.isArray(src) ? src : [];
                        } else {
                            clone = src && this.isPlainObject(src) ? src : {};
                        }
                        // WARNING: RECURSION
                        target[name] = this.extend(deep, clone, copy);
                    } else if (copy !== undefined) {
                        target[name] = copy;
                    }
                }
            }
        }
        return target;
    },

    inherit: function (subc, superc, overrides) {
        var F = function () { }, i;
        F.prototype = superc.prototype;
        subc.prototype = new F();
        subc.prototype.constructor = subc;
        subc.superclass = superc.prototype;
        if (superc.prototype.constructor == Object.prototype.constructor) {
            superc.prototype.constructor = superc;
        }
        if (overrides) {
            for (i in overrides) {
                if (this.hasOwn(overrides, i)) {
                    subc.prototype[i] = overrides[i];
                }
            }
        }
    },

    guid: function() {
        function s4() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); }
        return function(sep) {
            if (sep === true) { sep = '-'; } else { sep = sep || ''; }
            return (s4() + s4() + sep + s4() + sep + s4() + sep + s4() + sep + s4() + s4() + s4());
        };
    }(),

    unique: function(len) {
        return this.guid().substr(0, len);
    },

    padLeft: function(str, len, chr, reverse) {
        if (str !== null && str !== undefined) {
            str = str + ''; var num = len - str.length;
            if (num > 0) {
                for (var i = 0; i < num; i++) {
                    if (reverse === true) {
                        str = str + chr;
                    } else {
                        str = chr + str;
                    }
                }
            }
        }
        return str;
    },

    padRight: function(str, len, chr) {
        return this.padLeft(str, len, chr, true);
    },

    format: function (format) {
        var args = this.arg2arr(arguments, 1), arg;
        return format.replace(/\{(\d+)\}/g, function (m, i) {
            return (arg = args[i], (arg === null || arg === undefined) ? '' : arg);
        });
    },

    trim: function (str, set) {
        str = str || ''; set = set || {};
        if (set.find) {
            var exp = this.format('^{0}+|{0}+$', set.find);
            return str.replace(new RegExp(exp, 'g'), set.hold || '');
        } else if (set.findEnd) {
            var exp = this.format('{0}+$', set.findEnd);
            return str.replace(new RegExp(exp, 'g'), set.hold || '');
        } else if (set.findStart) {
            var exp = this.format('^{0}+', set.findStart);
            return str.replace(new RegExp(exp, 'g'), set.hold || '');
        } else {
            return str.replace(/^\s+|\s+$/g, set.hold || '');
        }
    },

    readObj: function(obj, namespace) {
        var names = namespace.split(/\.|\[|\]|\(/), ret = obj;
        this.each(names, function (i, key) { if (key && ret) { ret = (isNaN(key) ? (key === ')' ? ret() : ret[key]) : ret[parseInt(key, 10)]); } });
        return ret;
    },

    mapObj: function(obj, namespace, dft) {
        var parts = namespace.split(/\.|\[|\]/), names = [];
        this.each(parts, function (i, key) { if (key) { names.push(key); } });
        var lastName = names[names.length - 1], curr = obj = (obj || {}), prev;
        this.each(names, function (i, key) { prev = curr; curr = (curr[key] ? curr[key] : (curr[key] = isNaN(names[i + 1]) ? {} : [])); });
        if (prev) { prev[lastName] = dft; }
        return obj;
    },

    propCount: function(obj) {
        var count = 0;
        if (obj) {
            for (var key in obj) {
                if (this.hasOwn(obj, key)) {
                    count++;
                }
            }
        }
        return count;
    },

    appendQuery: function() {
        var allows = { 'boolean': true, 'number': true, 'string': true }; // object types: Boolean Number String Object Array Date RegExp Function
        return function(url, name, value) {
            if (url === null || url === undefined || (!name && name !== 0)) { return url; }
            if (this.type(name) === 'object' || this.type(name) === 'array') {
                var self = this;
                this.each(name, function (key, val) {// here 'key' fixed to simple type and will not loop again.
                    url = self.appendQuery(url, key, val);
                });
            } else if (allows[this.type(value)]) {
                url += ((url + '').indexOf('?') > -1) ? '' : '?';
                url += (/\?$/.test(url)) ? '' : '&';
                url += name + '=' + encodeURIComponent(String(value));
            }
            return url;
        };
    }(),

    setQuery: function(url, name, value) {
        if (url === null || url === undefined || (!name && name !== 0)) { return url; }
        var urlParams = this.getQuery(url), lowerParams = {}, keyMap = {}, params = {}, lower;
        params = 'object,array'.indexOf(this.type(name)) > -1 ? name : (params[name] = value, params);
        this.each(urlParams, function (key, val) {
            lowerParams[key.toLowerCase()] = val;
            keyMap[key] = key.toLowerCase();
        });
        this.each(params, function (key, val) {
            lower = (key + '').toLowerCase();
            if (lower in lowerParams) {
                lowerParams[lower] = val;
            } else {
                urlParams[key] = val;
            }
        });
        this.each(keyMap, function (f, t) {
            urlParams[f] = lowerParams[t];
        });
        //
        var sIndex = url.indexOf('?');
        sIndex = (sIndex === -1) ? url.length : sIndex;
        return this.appendQuery(url.substr(0, sIndex), urlParams);
    },

    getQuery: function(url, key) {
        var params = {};
        if (url === null || url === undefined) { return params; }
        var sIndex = url.indexOf('?');
        if (sIndex === -1) { return params; }
        //
        var query = url.substr(sIndex + 1);
        var pairs = query.replace(/\+/g, ' ').split('&');
        this.each(pairs, function(idx, pair) {
            var parts = pair.split('=');
            if (parts.length > 0) {
                params[parts[0]] = decodeURIComponent(parts[1] || '');
            }
        });
        //
        return key ? params[key] : params;
    }
};
<|endoftext|>