<commit_before>import StaticClass from './StaticClass';

/**
 * UUID util class
 * @static
 * @private
 */
export default class Uuid extends StaticClass {
  /**
   * Generate a UUID4 string
   * @returns {string} - Uuid
   */
  static uuid4() {
    // Use the secure method if possible
    return typeof crypto !== 'undefined' && crypto.getRandomValues ? Uuid._uuid4Safe() : Uuid._uuid4Unsafe();
  }

  /**
   * Unsafe UUID4 generation using Math.random
   * @returns {string} - Uuid
   *
   * @see http://stackoverflow.com/a/8809472
   * @license MIT|Public Domain
   * @private
   */
  static _uuid4Unsafe() {
    let d = new Date().getTime();

    if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
      d += performance.now(); // use high-precision timer if available
    }

    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
      const r = (d + Math.random() * 16) % 16 | 0;

      d = Math.floor(d / 16);
      return (c === 'x' ? r : r & 0x3 | 0x8).toString(16);
    });
  }

  /**
   * Safe UUID4 generation using the crypto api
   * @returns {String} - Uuid
   * @private
   */
  static _uuid4Safe() {
    let data = new Uint8Array(16);

    crypto.getRandomValues(data);

    // cast to array so we can use pop()
    data = [].slice.call(data);

    // Replace 'xx' with a two width base 16 number
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/xx/g, () => {
      // Prepend 00 for padding and grab the last two characters
      return ('00' + data.pop().toString(16)).slice(-2);
    });
  }

  /**
   * Empty uuid as per spec
   * @returns {string} - Uuid
   */
  static nil() {
    return '0000000-0000-0000-0000-000000000000';
  }
}
<commit_msg>Remove crypto api uuid4 generator<commit_after>import StaticClass from './StaticClass';

/**
 * UUID util class
 * @static
 * @private
 */
export default class Uuid extends StaticClass {
  /**
   * Generate a UUID4 string
   * @returns {string} - Uuid
   */
  static uuid4() {
    let d = new Date().getTime();

    if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
      d += performance.now(); // use high-precision timer if available
    }

    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
      const r = (d + Math.random() * 16) % 16 | 0;

      d = Math.floor(d / 16);
      return (c === 'x' ? r : r & 0x3 | 0x8).toString(16);
    });
  }

  /**
   * Empty uuid as per spec
   * @returns {string} - Uuid
   */
  static nil() {
    return '0000000-0000-0000-0000-000000000000';
  }
}
<|endoftext|>


<commit_before>// Copyright 2015, University of Colorado Boulder

/**
 * Tandem is used to assign unique identifiers to instances in PhET simulations and register/unregister them in a
 * registry. It is used to support PhET-iO.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var tandemNamespace = require( 'TANDEM/tandemNamespace' );
  var toCamelCase = require( 'PHET_CORE/toCamelCase' );

  // text
  var packageString = require( 'text!REPOSITORY/package.json' );

  // constants
  var packageJSON = JSON.parse( packageString ); // Tandem can't depend on joist, so requiring packageJSON doesn't work
  var PHET_IO_ENABLED = !!( window.phet && window.phet.phetio );

  // Listeners that will be notified when items are registered/deregistered. See doc in addInstanceListener
  var instanceListeners = [];

  // variables
  // Before listeners are wired up, tandems are buffered.  When listeners are wired up, Tandem.launch() is called
  // and buffered tandems are flushed, then subsequent tandems are delivered to listeners directly
  var launched = false;
  var bufferedElements = [];

  // increment names of uninstrumented common code tandems to avoid collisions for uninstrumented sims with
  // phetioValidateTandems=false
  var uninstrumentedCodeIndex = 0;

  /**
   * Typically, sims will create tandems using `tandem.createTandem`.  This constructor is used internally or when
   * a tandem must be created from scratch.
   *
   * @param {string} phetioID - unique identifier as a string ('' for a root id)
   * @param {Object} [options]
   * @constructor
   */
  function Tandem( phetioID, options ) {

    // options (even subtype options) must be stored on the instance so they can be passed through to children
    // Note: Make sure that added options here are also added to options for inheritance and/or
    // for composition (createTandem/parentTandem) as they make sense.
    options = _.extend( {

      // if the tandem is not supplied and required, an error will be thrown.
      supplied: true,

      // required === false means it is an optional tandem
      required: true
    }, options );

    // @public (read-only)
    this.phetioID = ( phetioID !== undefined ) ? phetioID : '';

    // @private
    this.required = options.required;

    // @private
    this.supplied = options.supplied;
  }

  tandemNamespace.register( 'Tandem', Tandem );

  inherit( Object, Tandem, {

    /**
     * Adds an instance of any type.  For example, it could be an axon Property, scenery Node or Sun button.  Each
     * item should only be added to the registry once, but that is not enforced here in Tandem.  For PhET-iO, phetio.js
     * enforces one entry per ID in phetio.addInstance
     *
     * This is used to register instances with PhET-iO.
     * @param {PhetioObject} instance - the instance to add
     * @public
     */
    addInstance: function( instance ) {

      assert && assert( arguments.length === 1, 'Tandem.addInstance takes one argument' );

      // Check that the instrumented instance is an instance of PhetioObject, cannot use typical require statement for
      // PhetioObject because it creates a module loading loop
      assert && assert( instance instanceof tandemNamespace.PhetioObject, 'Instance should be of type PhetioObject' );

      if ( PHET_IO_ENABLED ) {

        // Throw an error if the tandem is required but not supplied
        if ( phet.phetio.queryParameters.phetioValidateTandems ) {
          assert && assert( !( this.required && !this.supplied ), 'Tandem was required but not supplied' );
        }

        // ValidateTandems is false and printMissingTandems flag is present for a tandem that is required but not supplied.
        if ( phet.phetio.queryParameters.printMissingTandems && ( this.required && !this.supplied ) ) {
          console.log( 'Required Tandem not supplied.\n' +
                       'this.phetioID = ' + this.phetioID + '\n' +
                       'Stack trace: ' + new Error().stack );
        }

        // If tandem is optional, then don't add the instance
        if ( !this.required && !this.supplied ) {
          if ( phet.phetio.queryParameters.printMissingTandems ) {
            var stackTrace = new Error().stack;

            // Generally Font is not desired because there are so many untandemized instances.
            if ( stackTrace.indexOf( 'PhetFont' ) === -1 ) {
              console.log( 'Optional Tandem not supplied.\n' +
                           'this.phetioID = ' + this.phetioID + '\n' +
                           'Stack trace: ' + stackTrace );
            }
          }

          // For optionally instrumented types that are not provided tandems, the instance isn't really "added"
          // but likewise, it in not an error
          return;
        }

        if ( !launched ) {
          bufferedElements.push( instance );
        }
        else {
          for ( var i = 0; i < instanceListeners.length; i++ ) {
            instanceListeners[ i ].addInstance( instance );
          }
        }
      }
    },

    /**
     * Removes an instance from the registry
     * @param {PhetioObject} instance - the instance to remove
     * @public
     */
    removeInstance: function( instance ) {
      if ( !this.required && !this.supplied ) {
        return;
      }

      // Only active when running as phet-io
      if ( PHET_IO_ENABLED ) {
        for ( var i = 0; i < instanceListeners.length; i++ ) {
          instanceListeners[ i ].removeInstance( instance );
        }
      }
    },

    /**
     * Create a new Tandem by appending the given id
     * @param {string} id
     * @param {Object} [options]
     * @returns {Tandem}
     * @public
     */
    createTandem: function( id, options ) {

      // Make sure the id was provided
      assert && assert( typeof id === 'string' && id.length > 0, 'id must be defined' );

      var string = ( this.phetioID.length > 0 ) ? phetio.PhetioIDUtils.append( this.phetioID, id ) : id;

      // Any child of something should be passed all inherited options. Make sure that this extend call includes all
      // that make sense from the constructor's extend call.
      options = _.extend( {
        supplied: this.supplied,
        required: this.required
      }, options );

      return new Tandem( string, options );
    },

    /**
     * Creates a group tandem for creating multiple indexed child tandems, such as:
     * sim.screen.model.electron_0
     * sim.screen.model.electron_1
     *
     * In this case, 'sim.screen.model.electron' is the string passed to createGroupTandem.
     *
     * Used for arrays, observable arrays, or when many elements of the same type are created and they do not otherwise
     * have unique identifiers.
     * @param id
     * @returns {GroupTandem}
     * @public
     */
    createGroupTandem: function( id ) {

      // Unfortunately we must resort to globals here since loading through the namespace would create a cycle
      return new GroupTandem( phetio.PhetioIDUtils.append( this.phetioID, id ) );
    },

    /**
     * Get the last part of the tandem (after the last .), used in Joist for creating button names dynamically based
     * on screen names
     * @returns {string} the tail of the tandem
     * @public
     */
    get tail() { // TODO: rename to getComponentName()
      return phetio.PhetioIDUtils.getComponentName( this.phetioID );
    },

    /**
     * Returns a Tandem for everything except the tail.
     * @returns {Tandem}
     * @public
     */
    get parentTandem() {
      var headID = phetio.PhetioIDUtils.getParentID( this.phetioID );

      return new Tandem( headID, {
        required: this.required,
        supplied: this.supplied
      } );
    }
  }, {

    /**
     * Adds a listener that will be notified when items are registered/deregistered
     * Listeners have the form
     * {
     *   addInstance(id,instance),
     *   removeInstance(id,instance)
     * }
     * where id is of type {string} and instance is of type {Object}
     *
     * @param {Object} instanceListener - described above
     * @public
     * @static
     */
    addInstanceListener: function( instanceListener ) {
      instanceListeners.push( instanceListener );
    },

    /**
     * When all listeners are listening, all buffered instances are registered.
     * @public
     * @static
     */
    launch: function() {
      assert && assert( !launched, 'Tandem was launched twice' );
      launched = true;
      while ( bufferedElements.length > 0 ) {
        var element = bufferedElements.shift();
        element.tandem.addInstance( element );
      }
    },

    /**
     * Catch cases where tandem is being supplied to a class that doesn't support tandem.
     * @param {Object} [options]
     * @public
     * @static
     */
    disallowTandem: function( options ) {

      if ( Tandem.validationEnabled() ) {
        assert && assert( !options.tandem, 'tandem is not allowed' );
      }
    },

    /**
     * When running in PhET-iO brand, some code (such as user interface components) must be instrumented for PhET-iO.
     * Uninstrumented files should call this function to indicate they still need to be instrumented, so they aren't
     * missed.  See https://github.com/phetsims/phet-io/issues/668
     * @public
     * @static
     */
    indicateUninstrumentedCode: function() {

      // Guard against undefined errors
      if ( PHET_IO_ENABLED ) {

        // Assert if validating tandems
        if ( phet.phetio.queryParameters.phetioValidateTandems ) {
          assert && assert( false, 'Uninstrumented code detected' );
        }

        // Print stack trace if query parameter supplied
        if ( phet.phetio.queryParameters.printMissingTandems ) {
          var stackTrace = new Error().stack;
          console.log( 'Uninstrumented Code! Tandem not supplied: ' + ( uninstrumentedCodeIndex++ ) + '.\n' +
                       'Stack trace: ' + stackTrace );
        }
      }
    },

    /**
     * Determine whether or not tandem validation is turned on for the sim.
     * @returns {Boolean} If tandems are being validated or not.
     * @public
     * @static
     */
    validationEnabled: function() {
      return PHET_IO_ENABLED && phet.phetio.queryParameters.phetioValidateTandems;
    },

    /**
     * Returns true if the bufferedElements contain the given phetioID.
     * @param {string} phetioID
     * @returns {boolean}
     * @public
     */
    containsBufferedID: function( phetioID ) {
      return bufferedElements.map( function( instance ) {return instance.tandem.phetioID;} ).indexOf( phetioID ) >= 0;
    }
  } );

  // The next few statics are created outside the static block because they instantiate Tandem instances.

  /**
   * The root tandem for a simulation
   * @public
   * @static
   * @type {Tandem}
   */
  Tandem.rootTandem = new Tandem( toCamelCase( packageJSON.name ) );

  /**
   * Used to indicate a common code component that supports tandem, but doesn't not require it.
   * If a tandem is not passed through to this instance, then it will not be instrumented.
   * @public
   * @static
   * @type {Tandem}
   */
  Tandem.optional = Tandem.rootTandem.createTandem( 'optionalTandem', {
    required: false,
    supplied: false
  } );

  /**
   * Some common code (such as Checkbox or RadioButton) must always be instrumented and hence requires a tandem to be
   * passed in.
   * @public
   * @static
   * @type {Tandem}
   */
  Tandem.required = Tandem.rootTandem.createTandem( 'requiredTandem', {
    required: PHET_IO_ENABLED && phet.phetio.queryParameters.phetioValidateTandems,
    supplied: false
  } );

  /**
   * Group Tandem -- Declared in the same file to avoid circular reference errors in module loading.
   * @param {string} id - id as a string (or '' for a root id)
   * @constructor
   * @private create with Tandem.createGroupTandem
   */
  function GroupTandem( id ) {

    Tandem.call( this, id );

    // @private for generating indices from a pool
    this.groupElementIndex = 0;
  }

  tandemNamespace.register( 'Tandem.GroupTandem', GroupTandem );

  inherit( Tandem, GroupTandem, {

    /**
     * Creates the next tandem in the group.
     * @returns {Tandem}
     * @public
     */
    createNextTandem: function() {
      return new Tandem( this.phetioID + '_' + ( this.groupElementIndex++ ) );
    }
  } );

  return Tandem;
} );<commit_msg>simplify logic, https://github.com/phetsims/tandem/issues/69 https://github.com/phetsims/tandem/issues/62#issuecomment-428812330<commit_after>// Copyright 2015, University of Colorado Boulder

/**
 * Tandem is used to assign unique identifiers to instances in PhET simulations and register/unregister them in a
 * registry. It is used to support PhET-iO.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var tandemNamespace = require( 'TANDEM/tandemNamespace' );
  var toCamelCase = require( 'PHET_CORE/toCamelCase' );

  // text
  var packageString = require( 'text!REPOSITORY/package.json' );

  // constants
  var packageJSON = JSON.parse( packageString ); // Tandem can't depend on joist, so requiring packageJSON doesn't work
  var PHET_IO_ENABLED = !!( window.phet && window.phet.phetio );

  // Listeners that will be notified when items are registered/deregistered. See doc in addInstanceListener
  var instanceListeners = [];

  // variables
  // Before listeners are wired up, tandems are buffered.  When listeners are wired up, Tandem.launch() is called
  // and buffered tandems are flushed, then subsequent tandems are delivered to listeners directly
  var launched = false;
  var bufferedElements = [];

  // increment names of uninstrumented common code tandems to avoid collisions for uninstrumented sims with
  // phetioValidateTandems=false
  var uninstrumentedCodeIndex = 0;

  /**
   * Typically, sims will create tandems using `tandem.createTandem`.  This constructor is used internally or when
   * a tandem must be created from scratch.
   *
   * @param {string} phetioID - unique identifier as a string ('' for a root id)
   * @param {Object} [options]
   * @constructor
   */
  function Tandem( phetioID, options ) {

    // options (even subtype options) must be stored on the instance so they can be passed through to children
    // Note: Make sure that added options here are also added to options for inheritance and/or
    // for composition (createTandem/parentTandem) as they make sense.
    options = _.extend( {

      // if the tandem is not supplied and required, an error will be thrown.
      supplied: true,

      // required === false means it is an optional tandem
      required: true
    }, options );

    // @public (read-only)
    this.phetioID = ( phetioID !== undefined ) ? phetioID : '';

    // @private
    this.required = options.required;

    // @private
    this.supplied = options.supplied;
  }

  tandemNamespace.register( 'Tandem', Tandem );

  inherit( Object, Tandem, {

    /**
     * Adds an instance of any type.  For example, it could be an axon Property, scenery Node or Sun button.  Each
     * item should only be added to the registry once, but that is not enforced here in Tandem.  For PhET-iO, phetio.js
     * enforces one entry per ID in phetio.addInstance
     *
     * This is used to register instances with PhET-iO.
     * @param {PhetioObject} instance - the instance to add
     * @public
     */
    addInstance: function( instance ) {

      assert && assert( arguments.length === 1, 'Tandem.addInstance takes one argument' );

      // Check that the instrumented instance is an instance of PhetioObject, cannot use typical require statement for
      // PhetioObject because it creates a module loading loop
      assert && assert( instance instanceof tandemNamespace.PhetioObject, 'Instance should be of type PhetioObject' );

      if ( PHET_IO_ENABLED ) {

        // Throw an error if the tandem is required but not supplied
        if ( phet.phetio.queryParameters.phetioValidateTandems ) {
          assert && assert( !( this.required && !this.supplied ), 'Tandem was required but not supplied' );
        }

        // ValidateTandems is false and printMissingTandems flag is present for a tandem that is required but not supplied.
        if ( phet.phetio.queryParameters.printMissingTandems && ( this.required && !this.supplied ) ) {
          console.log( 'Required Tandem not supplied.\n' +
                       'this.phetioID = ' + this.phetioID + '\n' +
                       'Stack trace: ' + new Error().stack );
        }

        // If tandem is optional, then don't add the instance
        if ( !this.required && !this.supplied ) {
          if ( phet.phetio.queryParameters.printMissingTandems ) {
            var stackTrace = new Error().stack;

            // Generally Font is not desired because there are so many untandemized instances.
            if ( stackTrace.indexOf( 'PhetFont' ) === -1 ) {
              console.log( 'Optional Tandem not supplied.\n' +
                           'this.phetioID = ' + this.phetioID + '\n' +
                           'Stack trace: ' + stackTrace );
            }
          }

          // For optionally instrumented types that are not provided tandems, the instance isn't really "added"
          // but likewise, it in not an error
          return;
        }

        if ( !launched ) {
          bufferedElements.push( instance );
        }
        else {
          for ( var i = 0; i < instanceListeners.length; i++ ) {
            instanceListeners[ i ].addInstance( instance );
          }
        }
      }
    },

    /**
     * Removes an instance from the registry
     * @param {PhetioObject} instance - the instance to remove
     * @public
     */
    removeInstance: function( instance ) {
      if ( !this.required && !this.supplied ) {
        return;
      }

      // Only active when running as phet-io
      if ( PHET_IO_ENABLED ) {
        for ( var i = 0; i < instanceListeners.length; i++ ) {
          instanceListeners[ i ].removeInstance( instance );
        }
      }
    },

    /**
     * Create a new Tandem by appending the given id
     * @param {string} id
     * @param {Object} [options]
     * @returns {Tandem}
     * @public
     */
    createTandem: function( id, options ) {

      // Make sure the id was provided
      assert && assert( typeof id === 'string' && id.length > 0, 'id must be defined' );

      var string = ( this.phetioID.length > 0 ) ? phetio.PhetioIDUtils.append( this.phetioID, id ) : id;

      // Any child of something should be passed all inherited options. Make sure that this extend call includes all
      // that make sense from the constructor's extend call.
      options = _.extend( {
        supplied: this.supplied,
        required: this.required
      }, options );

      return new Tandem( string, options );
    },

    /**
     * Creates a group tandem for creating multiple indexed child tandems, such as:
     * sim.screen.model.electron_0
     * sim.screen.model.electron_1
     *
     * In this case, 'sim.screen.model.electron' is the string passed to createGroupTandem.
     *
     * Used for arrays, observable arrays, or when many elements of the same type are created and they do not otherwise
     * have unique identifiers.
     * @param id
     * @returns {GroupTandem}
     * @public
     */
    createGroupTandem: function( id ) {

      // Unfortunately we must resort to globals here since loading through the namespace would create a cycle
      return new GroupTandem( phetio.PhetioIDUtils.append( this.phetioID, id ) );
    },

    /**
     * Get the last part of the tandem (after the last .), used in Joist for creating button names dynamically based
     * on screen names
     * @returns {string} the tail of the tandem
     * @public
     */
    get tail() { // TODO: rename to getComponentName()
      return phetio.PhetioIDUtils.getComponentName( this.phetioID );
    },

    /**
     * Returns a Tandem for everything except the tail.
     * @returns {Tandem}
     * @public
     */
    get parentTandem() {
      var headID = phetio.PhetioIDUtils.getParentID( this.phetioID );

      return new Tandem( headID, {
        required: this.required,
        supplied: this.supplied
      } );
    }
  }, {

    /**
     * Adds a listener that will be notified when items are registered/deregistered
     * Listeners have the form
     * {
     *   addInstance(id,instance),
     *   removeInstance(id,instance)
     * }
     * where id is of type {string} and instance is of type {Object}
     *
     * @param {Object} instanceListener - described above
     * @public
     * @static
     */
    addInstanceListener: function( instanceListener ) {
      instanceListeners.push( instanceListener );
    },

    /**
     * When all listeners are listening, all buffered instances are registered.
     * @public
     * @static
     */
    launch: function() {
      assert && assert( !launched, 'Tandem was launched twice' );
      launched = true;
      while ( bufferedElements.length > 0 ) {
        var element = bufferedElements.shift();
        element.tandem.addInstance( element );
      }
    },

    /**
     * Catch cases where tandem is being supplied to a class that doesn't support tandem.
     * @param {Object} [options]
     * @public
     * @static
     */
    disallowTandem: function( options ) {

      if ( Tandem.validationEnabled() ) {
        assert && assert( !options.tandem, 'tandem is not allowed' );
      }
    },

    /**
     * When running in PhET-iO brand, some code (such as user interface components) must be instrumented for PhET-iO.
     * Uninstrumented files should call this function to indicate they still need to be instrumented, so they aren't
     * missed.  See https://github.com/phetsims/phet-io/issues/668
     * @public
     * @static
     */
    indicateUninstrumentedCode: function() {

      // Guard against undefined errors
      if ( PHET_IO_ENABLED ) {

        // Assert if validating tandems
        if ( this.validationEnabled() ) {
          assert && assert( false, 'Uninstrumented code detected' );
        }

        // Print stack trace if query parameter supplied
        if ( phet.phetio.queryParameters.printMissingTandems ) {
          var stackTrace = new Error().stack;
          console.log( 'Uninstrumented Code! Tandem not supplied: ' + ( uninstrumentedCodeIndex++ ) + '.\n' +
                       'Stack trace: ' + stackTrace );
        }
      }
    },

    /**
     * Determine whether or not tandem validation is turned on for the sim.
     * @returns {Boolean} If tandems are being validated or not.
     * @public
     * @static
     */
    validationEnabled: function() {
      return PHET_IO_ENABLED && phet.phetio.queryParameters.phetioValidateTandems;
    },

    /**
     * Returns true if the bufferedElements contain the given phetioID.
     * @param {string} phetioID
     * @returns {boolean}
     * @public
     */
    containsBufferedID: function( phetioID ) {
      return bufferedElements.map( function( instance ) {return instance.tandem.phetioID;} ).indexOf( phetioID ) >= 0;
    }
  } );

  // The next few statics are created outside the static block because they instantiate Tandem instances.

  /**
   * The root tandem for a simulation
   * @public
   * @static
   * @type {Tandem}
   */
  Tandem.rootTandem = new Tandem( toCamelCase( packageJSON.name ) );

  /**
   * Used to indicate a common code component that supports tandem, but doesn't not require it.
   * If a tandem is not passed through to this instance, then it will not be instrumented.
   * @public
   * @static
   * @type {Tandem}
   */
  Tandem.optional = Tandem.rootTandem.createTandem( 'optionalTandem', {
    required: false,
    supplied: false
  } );

  /**
   * Some common code (such as Checkbox or RadioButton) must always be instrumented and hence requires a tandem to be
   * passed in.
   * @public
   * @static
   * @type {Tandem}
   */
  Tandem.required = Tandem.rootTandem.createTandem( 'requiredTandem', {
    required: PHET_IO_ENABLED && phet.phetio.queryParameters.phetioValidateTandems,
    supplied: false
  } );

  /**
   * Group Tandem -- Declared in the same file to avoid circular reference errors in module loading.
   * @param {string} id - id as a string (or '' for a root id)
   * @constructor
   * @private create with Tandem.createGroupTandem
   */
  function GroupTandem( id ) {

    Tandem.call( this, id );

    // @private for generating indices from a pool
    this.groupElementIndex = 0;
  }

  tandemNamespace.register( 'Tandem.GroupTandem', GroupTandem );

  inherit( Tandem, GroupTandem, {

    /**
     * Creates the next tandem in the group.
     * @returns {Tandem}
     * @public
     */
    createNextTandem: function() {
      return new Tandem( this.phetioID + '_' + ( this.groupElementIndex++ ) );
    }
  } );

  return Tandem;
} );<|endoftext|>


<commit_before>$(document).ready(function() {
  $('#calculator .input').click(function() {
    var input;
    if(this.dataset.keyType == "digit") {
      input = this.dataset.digit;
    } else if (this.dataset.keyType == "operator") {
      input = this.dataset.operator;
    } else if (this.dataset.keyType == "delete") {
      $('#preview').html($('#preview').html().slice(0, -1));
    } else if (this.dataset.keyType == "equals") {
      $('#result').html(eval($('#preview').html()));
    }
    if(typeof(input) != 'undefined') {
    $('#preview').html($('#preview').html() + input);
  }
});

  ('#calculator #delete').dblclick(function() {
    $('#preview').html('');
    $('#result').html('');
  });

  ['0','1','2','3','4','5','6','7','8','9'].forEach(function() {
    $(document).bind('keyup',digit,function() {
    $('#preview').html($('#preview').html() + digit);
    });
  });
});<commit_msg>Promoting orphan scripts to function<commit_after>function handleInput(input) {
    $('#preview').html($('#preview').html() + input);
}

function handleInput(input) {
    $('#preview').html($('#preview').html().slice(0, -1));
}

function handleInput(input) {
    $('#result').html(eval($('#preview').html()));
}

$(document).ready(function() {
  $('#calculator .input').click(function() {
    var input;
    if(this.dataset.keyType == "digit") {
      handleInput(this.dataset.digit);
    } else if (this.dataset.keyType == "operator") {
      handleInput(this.dataset.operator);
    } else if (this.dataset.keyType == "delete") {
      handleDelete();
    } else if (this.dataset.keyType == "equals") {
      evaluateResult();
    }
});

  ('#calculator #delete').dblclick(function() {
    $('#preview').html('');
    $('#result').html('');
  });

  ['0','1','2','3','4','5','6','7','8','9'].forEach(function() {
    $(document).bind('keyup', digit ,function() {
    handleInput(digit);
    });
  });
});<|endoftext|>


<commit_before>// Copyright 2015, University of Colorado Boulder

/**
 * Tandem is a general instance registry that can be used to track creation/disposal of instances in PhET Simulations.
 * It is used for phetio.js instrumentation for PhET-iO support.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var tandemNamespace = require( 'TANDEM/tandemNamespace' );
  var toCamelCase = require( 'PHET_CORE/toCamelCase' );

  // text
  var packageString = require( 'text!REPOSITORY/package.json' );

  // constants
  var packageJSON = JSON.parse( packageString );

  // variables
  var launched = false;

  // increment names of required tandems to avoid collisions for uninstrumented sims with phetioValidateTandems=false
  var requiredTandemIndex = 0;

  // increment names of optional tandems to avoid collisions for uninstrumented sims with phetioValidateTandems=false
  var optionalTandemIndex = 0;

  // increment names of uninstrumented common code tandems to avoid collisions for uninstrumented sims with phetioValidateTandems=false
  var uninstrumentedCodeIndex = 0;

  /**
   * @param {string} id - id as a string (or '' for a root id)
   * @param {Object} [options]
   * @constructor
   */
  function Tandem( id, options ) {

    // @private - these options are stored on the instance so they can be passed through the super type inheritance chain.
    // Note: Make sure that added options here are also added to options for inheritance (createSuperTypeTandem)
    // and/or for composition (createTandem) as they make sense.
    this.options = _.extend( {

      // Non-static tandems are registered as they are created. Static tandems are buffered, then the
      // buffer is flushed once the sim starts. Static tandems (for instances created outside of
      // SimLauncher) must be stored until listeners are attached so they won't be missed.
      static: false,

      // Enabled tandems notify listeners when they are added. Disabled tandems do not notify listeners,
      // but children of a disabled tandem may be enabled.
      enabled: true,

      supplied: true, // if the tandem is not supplied and required, an error will be thrown.
      required: true // require === false means it is an optional tandem
    }, options );

    // @public (read-only)
    this.id = ( id !== undefined ) ? id : '';
    this.required = this.options.required;
    this.supplied = this.options.supplied;

    // @private (read-only)
    this.static = this.options.static;
    this.enabled = this.options.enabled;
  }

  var staticInstances = [];

  tandemNamespace.register( 'Tandem', Tandem );

  // Listeners that will be notified when items are registered/deregistered
  var instanceListeners = [];

  inherit( Object, Tandem, {

    // @public (read-only) permit checking whether something is probably a Tandem instance for error checking
    isTandem: true,

    /**
     * Adds an instance of any type.  For example, it could be an axon Property, scenery Node or Sun button.  Each
     * item should only be added to the registry once, but that is not enforced here in Tandem.  For PhET-iO, phetio.js
     * enforces one entry per ID in phetio.addInstance
     *
     * This is used to register instances with PhET-iO.
     * @param {Object} instance - the instance to add
     * @param {function} type - the PhET-iO type function, such as TString or TProperty(TNumber)
     * @public
     */
    addInstance: function( instance, type ) {

      if ( window.phet && phet.phetio && this.enabled ) {

        // Throw an error if the tandem is tandemRequired() but not supplied
        if ( phet.phetio.queryParameters.phetioValidateTandems ) {
          assert && assert( !(this.required && !this.supplied), 'Tandem was required but not supplied' );
        }

        // ValidateTandems is false and printMissingTandems flag is present for a tandem that is required but not supplied.
        if ( phet.phetio.queryParameters.printMissingTandems && (this.required && !this.supplied) ) {
          console.log( 'Required Tandem not supplied.\n' +
                       'this.id = ' + this.id + '\n' +
                       'Stack trace: ' + new Error().stack );
        }

        // ifphetio returns a no-op function, so to test whether a valid "T" wrapper type was passed, we search for the typeName
        assert && assert( type && type.typeName, 'type must be specified and have a typeName for ' + this.id );

        // If tandem is tandemOptional, then don't add the instance
        if ( !this.required && !this.supplied ) {
          if ( phet.phetio.queryParameters.printMissingTandems ) {
            var stackTrace = new Error().stack;

            // Generally PhETFont is not desired because there are so many untandemized instances.
            if ( stackTrace.indexOf( 'PhetFont' ) === -1 ) {
              console.log( 'Optional Tandem not supplied.\n' +
                           'this.id = ' + this.id + '\n' +
                           'Stack trace: ' + stackTrace );
            }
          }

          // For optionally instrumented types that are not provided tandems, the instance isn't really "added"
          // but likewise, it in not an error
          return;
        }

        if ( this.static && !launched ) {
          staticInstances.push( { tandem: this, instance: instance, type: type } );
        }
        else {
          for ( var i = 0; i < instanceListeners.length; i++ ) {
            instanceListeners[ i ].addInstance( this.id, instance, type );
          }
        }
      }
    },

    /**
     * Removes an instance from the
     * @param {Object} instance - the instance to remove
     * @public
     */
    removeInstance: function( instance ) {

      // Only active when running as phet-io
      if ( window.phet && phet.phetio && this.enabled ) {
        for ( var i = 0; i < instanceListeners.length; i++ ) {
          instanceListeners[ i ].removeInstance( this.id, instance );
        }
      }
    },

    /**
     * Create a new Tandem by appending the given id
     * @param {string} id
     * @param {Object} [options]
     * @returns {Tandem}
     * @public
     */
    createTandem: function( id, options ) {

      // Make sure the id was provided
      assert && assert( typeof id === 'string' && id.length > 0, 'id must be defined' );

      var string = ( this.id.length > 0 ) ? ( this.id + '.' + id ) : id;

      // Any child of something should be passed these inherited options.
      options = _.extend( {
        static: this.static,
        enabled: this.enabled,
        supplied: this.supplied,
        required: this.required
      }, options );

      return new Tandem( string, options );
    },

    /**
     * Creates a group tandem for creating multiple indexed child tandems, such as:
     * sim.screen.model.electron_0
     * sim.screen.model.electron_1
     *
     * In this case, 'sim.screen.model.electron' is the group tandem id.
     *
     * Used for arrays, observable arrays, or when many elements of the same type are created and they do not otherwise
     * have unique identifiers.
     * @param id
     * @returns {GroupTandem}
     */
    createGroupTandem: function( id ) {

      // Unfortunately we must resort to globals here since loading through the namespace would create a cycle
      return new GroupTandem( this.id + '.' + id );
    },

    /**
     * Get the last part of the tandem (after the last .), used in Joist for creating button names dynamically based
     * on screen names
     * @returns {string} the tail of the tandem
     */
    get tail() {
      assert && assert( this.id.indexOf( '.' ) >= 0, 'tandem ID does not have a tail' );

      var lastIndexOfDot = this.id.lastIndexOf( '.' );
      var tail = this.id.substring( lastIndexOfDot + 1 );
      assert && assert( tail.length > 0, 'tandem ID did not have a tail' );
      return tail;
    },

    /**
     * Returns a Tandem for everything except the tail.
     * @returns {Tandem}
     */
    get parentTandem() {
      assert && assert( this.id.indexOf( '.' ) >= 0, 'tandem ID does not have a tail' );

      var lastIndexOfDot = this.id.lastIndexOf( '.' );
      var headID = this.id.substring( 0, lastIndexOfDot );

      return new Tandem( headID, {
        static: this.static,
        required: this.required,
        supplied: this.supplied,
        enabled: this.enabled
      } );
    },

    /**
     * When using subtyping, the instance listeners must only be notified once rather than once for every level
     * in the inheritance hierarchy.  When a subtype constructor has a tandem.addInstance call, it should
     * pass a supertype tandem to the parent constructor so that it won't try to register the item twice.
     * @returns {SupertypeTandem}
     */
    createSupertypeTandem: function() {
      return new SupertypeTandem( this.id, this.options );
    },

    /**
     * Return true if this tandem is legal and can be used by the phet-io system.
     * @returns {boolean}
     */
    isLegalAndUsable: function() {

      // A tandem is legal if it has been supplied or, if it hasn't been supplied, if it is optional.
      return this.supplied || (this.optional && !this.supplied);
    }
  }, {

    /**
     * Some common code (such as CheckBox or RadioButton) must always be instrumented and hence requires a tandem to be
     * passed in.  The options hash indicates this with {tandem: Tandem.tandemRequired()}
     * @returns {Tandem}
     */
    tandemRequired: function() {
      return rootTandem.createTandem( 'requiredTandem' + (requiredTandemIndex++), {
        required: true,
        supplied: false
      } );
    },

    /**
     *
     * Used to indicate a common code component that supports tandem, but doesn't not require it.
     * If a tandem is not passed through to this instance, then it will not be instrumented.
     * @returns {Tandem}
     */
    tandemOptional: function() {
      return rootTandem.createTandem( 'optionalTandem' + (optionalTandemIndex++), {
        required: false,
        supplied: false
      } );
    },

    /**
     * Adds a listener that will be notified when items are registered/deregistered
     * Listeners have the form
     * {
     *   addInstance(id,instance),
     *   removeInstance(id,instance)
     * }
     * where id is of type {string} and instance is of type {Object}
     *
     * @param {Object} instanceListener - described above
     * @public
     * @static
     */
    addInstanceListener: function( instanceListener ) {
      instanceListeners.push( instanceListener );
    },

    /**
     * Create a tandem based on the name of the running simulation.
     * @returns {Tandem}
     */
    createRootTandem: function() {
      return new Tandem( toCamelCase( packageJSON.name ) );
    },

    /**
     * Create a child of the root tandem.
     * @param {string} name
     * @returns {Tandem}
     */
    createStaticTandem: function( name ) {
      return Tandem.createRootTandem().createTandem( name, { static: true } );
    },

    /**
     * When the simulation is launched, all static instances are registered.
     */
    launch: function() {
      assert && assert( !launched, 'Tandem was launched twice' );
      launched = true;
      while ( staticInstances.length > 0 ) {
        var staticInstance = staticInstances.shift();
        staticInstance.tandem.addInstance( staticInstance.instance, staticInstance.type );
      }
    },

    /**
     * Catch cases where tandem is being supplied to a class that doesn't support tandem.
     * @param options
     */
    disallowTandem: function( options ) {

      if ( Tandem.validationEnabled() ) {
        assert && assert( !options.tandem, 'tandem is not allowed' );
      }
    },

    /**
     * When running in PhET-iO brand, some code (such as user interface components) must be instrumented for PhET-iO.
     * Uninstrumented files should call this function to indicate they still need to be instrumented, so they aren't
     * missed.  See https://github.com/phetsims/phet-io/issues/668
     */
    indicateUninstrumentedCode: function() {

      // Guard against undefined errors
      if ( window.phet && phet.phetio ) {

        // Assert if validating tandems
        if ( phet.phetio.queryParameters.phetioValidateTandems ) {
          assert && assert( false, 'Uninstrumented code detected' );
        }

        // Print stack trace if query parameter supplied
        if ( phet.phetio.queryParameters.printMissingTandems ) {
          var stackTrace = new Error().stack;
          console.log( 'Uninstrumented Code! Tandem not supplied: ' + (uninstrumentedCodeIndex++) + '.\n' +
                       'Stack trace: ' + stackTrace );
        }

      }
    },

    /**
     * Determine whether or not tandem validation is turned on for the sim.
     * @returns {Boolean} If tandems are being validated or not.
     */
    validationEnabled: function() {
      return window.phet && phet.phetio && phet.phetio.queryParameters.phetioValidateTandems;
    }
  } );

  var rootTandem = Tandem.createRootTandem();

  // Tandem checks for listeners added before the Tandem module was loaded.  This is necessary so that phetio.js can
  // receive notifications about items created during static initialization such as Solute.js
  // which is created before Sim.js runs.
  if ( window.tandemPreloadInstanceListeners ) {
    for ( var i = 0; i < window.tandemPreloadInstanceListeners.length; i++ ) {
      Tandem.addInstanceListener( window.tandemPreloadInstanceListeners[ i ] );
    }
  }

  /**
   * @param {string} id - id as a string (or '' for a root id)
   * @constructor
   * @private create with Tandem.createGroupTandem
   * Declared in the same file to avoid circular reference errors in module loading.
   */
  function GroupTandem( id ) {

    Tandem.call( this, id );

    // @private for generating indices from a pool
    this.groupElementIndex = 0;
  }

  tandemNamespace.register( 'Tandem.GroupTandem', GroupTandem );

  inherit( Tandem, GroupTandem, {

    // @public
    createNextTandem: function() {
      return new Tandem( this.id + '_' + ( this.groupElementIndex++ ) );
    }
  } );

  /**
   * @param {string} id - id as a string (or '' for a root id)
   * @param {Object} options
   * @constructor
   * @private create with Tandem.createSupertypeTandem
   */
  function SupertypeTandem( id, options ) {
    Tandem.call( this, id, options );
  }

  tandemNamespace.register( 'Tandem.SupertypeTandem', SupertypeTandem );

  inherit( Tandem, SupertypeTandem, {

    // @public - Override to make no-op, see createSupertypeTandem
    addInstance: function( instance, type ) {},

    // @public - Override to make no-op, see createSupertypeTandem
    removeInstance: function( instance ) {}
  } );

  return Tandem;
} );

<commit_msg>Reformatting, see https://github.com/phetsims/phet-io/issues/1134<commit_after>// Copyright 2015, University of Colorado Boulder

/**
 * Tandem is a general instance registry that can be used to track creation/disposal of instances in PhET Simulations.
 * It is used for phetio.js instrumentation for PhET-iO support.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var tandemNamespace = require( 'TANDEM/tandemNamespace' );
  var toCamelCase = require( 'PHET_CORE/toCamelCase' );

  // text
  var packageString = require( 'text!REPOSITORY/package.json' );

  // constants
  var packageJSON = JSON.parse( packageString );

  // variables
  var launched = false;

  // increment names of required tandems to avoid collisions for uninstrumented sims with phetioValidateTandems=false
  var requiredTandemIndex = 0;

  // increment names of optional tandems to avoid collisions for uninstrumented sims with phetioValidateTandems=false
  var optionalTandemIndex = 0;

  // increment names of uninstrumented common code tandems to avoid collisions for uninstrumented sims with phetioValidateTandems=false
  var uninstrumentedCodeIndex = 0;

  /**
   * @param {string} id - id as a string (or '' for a root id)
   * @param {Object} [options]
   * @constructor
   */
  function Tandem( id, options ) {

    // @private - these options are stored on the instance so they can be passed through the super type inheritance chain.
    // Note: Make sure that added options here are also added to options for inheritance (createSuperTypeTandem)
    // and/or for composition (createTandem) as they make sense.
    this.options = _.extend( {

      // Non-static tandems are registered as they are created. Static tandems are buffered, then the
      // buffer is flushed once the sim starts. Static tandems (for instances created outside of
      // SimLauncher) must be stored until listeners are attached so they won't be missed.
      static: false,

      // Enabled tandems notify listeners when they are added. Disabled tandems do not notify listeners,
      // but children of a disabled tandem may be enabled.
      enabled: true,

      supplied: true, // if the tandem is not supplied and required, an error will be thrown.
      required: true // require === false means it is an optional tandem
    }, options );

    // @public (read-only)
    this.id = (id !== undefined) ? id : '';
    this.required = this.options.required;
    this.supplied = this.options.supplied;

    // @private (read-only)
    this.static = this.options.static;
    this.enabled = this.options.enabled;
  }

  var staticInstances = [];

  tandemNamespace.register( 'Tandem', Tandem );

  // Listeners that will be notified when items are registered/deregistered
  var instanceListeners = [];

  inherit( Object, Tandem, {

    // @public (read-only) permit checking whether something is probably a Tandem instance for error checking
    isTandem: true,

    /**
     * Adds an instance of any type.  For example, it could be an axon Property, scenery Node or Sun button.  Each
     * item should only be added to the registry once, but that is not enforced here in Tandem.  For PhET-iO, phetio.js
     * enforces one entry per ID in phetio.addInstance
     *
     * This is used to register instances with PhET-iO.
     * @param {Object} instance - the instance to add
     * @param {function} type - the PhET-iO type function, such as TString or TProperty(TNumber)
     * @public
     */
    addInstance: function( instance, type ) {

      if ( window.phet && phet.phetio && this.enabled ) {

        // Throw an error if the tandem is tandemRequired() but not supplied
        if ( phet.phetio.queryParameters.phetioValidateTandems ) {
          assert && assert( !(this.required && !this.supplied), 'Tandem was required but not supplied' );
        }

        // ValidateTandems is false and printMissingTandems flag is present for a tandem that is required but not supplied.
        if ( phet.phetio.queryParameters.printMissingTandems && (this.required && !this.supplied) ) {
          console.log( 'Required Tandem not supplied.\n' +
                       'this.id = ' + this.id + '\n' +
                       'Stack trace: ' + new Error().stack );
        }

        // ifphetio returns a no-op function, so to test whether a valid "T" wrapper type was passed, we search for the typeName
        assert && assert( type && type.typeName, 'type must be specified and have a typeName for ' + this.id );

        // If tandem is tandemOptional, then don't add the instance
        if ( !this.required && !this.supplied ) {
          if ( phet.phetio.queryParameters.printMissingTandems ) {
            var stackTrace = new Error().stack;

            // Generally PhETFont is not desired because there are so many untandemized instances.
            if ( stackTrace.indexOf( 'PhetFont' ) === -1 ) {
              console.log( 'Optional Tandem not supplied.\n' +
                           'this.id = ' + this.id + '\n' +
                           'Stack trace: ' + stackTrace );
            }
          }

          // For optionally instrumented types that are not provided tandems, the instance isn't really "added"
          // but likewise, it in not an error
          return;
        }

        if ( this.static && !launched ) {
          staticInstances.push( { tandem: this, instance: instance, type: type } );
        }
        else {
          for ( var i = 0; i < instanceListeners.length; i++ ) {
            instanceListeners[ i ].addInstance( this.id, instance, type );
          }
        }
      }
    },

    /**
     * Removes an instance from the
     * @param {Object} instance - the instance to remove
     * @public
     */
    removeInstance: function( instance ) {

      // Only active when running as phet-io
      if ( window.phet && phet.phetio && this.enabled ) {
        for ( var i = 0; i < instanceListeners.length; i++ ) {
          instanceListeners[ i ].removeInstance( this.id, instance );
        }
      }
    },

    /**
     * Create a new Tandem by appending the given id
     * @param {string} id
     * @param {Object} [options]
     * @returns {Tandem}
     * @public
     */
    createTandem: function( id, options ) {

      // Make sure the id was provided
      assert && assert( typeof id === 'string' && id.length > 0, 'id must be defined' );

      var string = (this.id.length > 0) ? (this.id + '.' + id) : id;

      // Any child of something should be passed these inherited options.
      options = _.extend( {
        static: this.static,
        enabled: this.enabled,
        supplied: this.supplied,
        required: this.required
      }, options );

      return new Tandem( string, options );
    },

    /**
     * Creates a group tandem for creating multiple indexed child tandems, such as:
     * sim.screen.model.electron_0
     * sim.screen.model.electron_1
     *
     * In this case, 'sim.screen.model.electron' is the group tandem id.
     *
     * Used for arrays, observable arrays, or when many elements of the same type are created and they do not otherwise
     * have unique identifiers.
     * @param id
     * @returns {GroupTandem}
     */
    createGroupTandem: function( id ) {

      // Unfortunately we must resort to globals here since loading through the namespace would create a cycle
      return new GroupTandem( this.id + '.' + id );
    },

    /**
     * Get the last part of the tandem (after the last .), used in Joist for creating button names dynamically based
     * on screen names
     * @returns {string} the tail of the tandem
     */
    get tail() {
      assert && assert( this.id.indexOf( '.' ) >= 0, 'tandem ID does not have a tail' );

      var lastIndexOfDot = this.id.lastIndexOf( '.' );
      var tail = this.id.substring( lastIndexOfDot + 1 );
      assert && assert( tail.length > 0, 'tandem ID did not have a tail' );
      return tail;
    },

    /**
     * Returns a Tandem for everything except the tail.
     * @returns {Tandem}
     */
    get parentTandem() {
      assert && assert( this.id.indexOf( '.' ) >= 0, 'tandem ID does not have a tail' );

      var lastIndexOfDot = this.id.lastIndexOf( '.' );
      var headID = this.id.substring( 0, lastIndexOfDot );

      return new Tandem( headID, {
        static: this.static,
        required: this.required,
        supplied: this.supplied,
        enabled: this.enabled
      } );
    },

    /**
     * When using subtyping, the instance listeners must only be notified once rather than once for every level
     * in the inheritance hierarchy.  When a subtype constructor has a tandem.addInstance call, it should
     * pass a supertype tandem to the parent constructor so that it won't try to register the item twice.
     * @returns {SupertypeTandem}
     */
    createSupertypeTandem: function() {
      return new SupertypeTandem( this.id, this.options );
    },

    /**
     * Return true if this tandem is legal and can be used by the phet-io system.
     * @returns {boolean}
     */
    isLegalAndUsable: function() {

      // A tandem is legal if it has been supplied or, if it hasn't been supplied, if it is optional.
      return this.supplied || (this.optional && !this.supplied);
    }
  }, {

    /**
     * Some common code (such as CheckBox or RadioButton) must always be instrumented and hence requires a tandem to be
     * passed in.  The options hash indicates this with {tandem: Tandem.tandemRequired()}
     * @returns {Tandem}
     */
    tandemRequired: function() {
      return rootTandem.createTandem( 'requiredTandem' + (requiredTandemIndex++), {
        required: true,
        supplied: false
      } );
    },

    /**
     *
     * Used to indicate a common code component that supports tandem, but doesn't not require it.
     * If a tandem is not passed through to this instance, then it will not be instrumented.
     * @returns {Tandem}
     */
    tandemOptional: function() {
      return rootTandem.createTandem( 'optionalTandem' + (optionalTandemIndex++), {
        required: false,
        supplied: false
      } );
    },

    /**
     * Adds a listener that will be notified when items are registered/deregistered
     * Listeners have the form
     * {
     *   addInstance(id,instance),
     *   removeInstance(id,instance)
     * }
     * where id is of type {string} and instance is of type {Object}
     *
     * @param {Object} instanceListener - described above
     * @public
     * @static
     */
    addInstanceListener: function( instanceListener ) {
      instanceListeners.push( instanceListener );
    },

    /**
     * Create a tandem based on the name of the running simulation.
     * @returns {Tandem}
     */
    createRootTandem: function() {
      return new Tandem( toCamelCase( packageJSON.name ) );
    },

    /**
     * Create a child of the root tandem.
     * @param {string} name
     * @returns {Tandem}
     */
    createStaticTandem: function( name ) {
      return Tandem.createRootTandem().createTandem( name, { static: true } );
    },

    /**
     * When the simulation is launched, all static instances are registered.
     */
    launch: function() {
      assert && assert( !launched, 'Tandem was launched twice' );
      launched = true;
      while ( staticInstances.length > 0 ) {
        var staticInstance = staticInstances.shift();
        staticInstance.tandem.addInstance( staticInstance.instance, staticInstance.type );
      }
    },

    /**
     * Catch cases where tandem is being supplied to a class that doesn't support tandem.
     * @param options
     */
    disallowTandem: function( options ) {

      if ( Tandem.validationEnabled() ) {
        assert && assert( !options.tandem, 'tandem is not allowed' );
      }
    },

    /**
     * When running in PhET-iO brand, some code (such as user interface components) must be instrumented for PhET-iO.
     * Uninstrumented files should call this function to indicate they still need to be instrumented, so they aren't
     * missed.  See https://github.com/phetsims/phet-io/issues/668
     */
    indicateUninstrumentedCode: function() {

      // Guard against undefined errors
      if ( window.phet && phet.phetio ) {

        // Assert if validating tandems
        if ( phet.phetio.queryParameters.phetioValidateTandems ) {
          assert && assert( false, 'Uninstrumented code detected' );
        }

        // Print stack trace if query parameter supplied
        if ( phet.phetio.queryParameters.printMissingTandems ) {
          var stackTrace = new Error().stack;
          console.log( 'Uninstrumented Code! Tandem not supplied: ' + (uninstrumentedCodeIndex++) + '.\n' +
                       'Stack trace: ' + stackTrace );
        }

      }
    },

    /**
     * Determine whether or not tandem validation is turned on for the sim.
     * @returns {Boolean} If tandems are being validated or not.
     */
    validationEnabled: function() {
      return window.phet && phet.phetio && phet.phetio.queryParameters.phetioValidateTandems;
    }
  } );

  var rootTandem = Tandem.createRootTandem();

  // Tandem checks for listeners added before the Tandem module was loaded.  This is necessary so that phetio.js can
  // receive notifications about items created during static initialization such as Solute.js
  // which is created before Sim.js runs.
  if ( window.tandemPreloadInstanceListeners ) {
    for ( var i = 0; i < window.tandemPreloadInstanceListeners.length; i++ ) {
      Tandem.addInstanceListener( window.tandemPreloadInstanceListeners[ i ] );
    }
  }

  /**
   * @param {string} id - id as a string (or '' for a root id)
   * @constructor
   * @private create with Tandem.createGroupTandem
   * Declared in the same file to avoid circular reference errors in module loading.
   */
  function GroupTandem( id ) {

    Tandem.call( this, id );

    // @private for generating indices from a pool
    this.groupElementIndex = 0;
  }

  tandemNamespace.register( 'Tandem.GroupTandem', GroupTandem );

  inherit( Tandem, GroupTandem, {

    // @public
    createNextTandem: function() {
      return new Tandem( this.id + '_' + (this.groupElementIndex++) );
    }
  } );

  /**
   * @param {string} id - id as a string (or '' for a root id)
   * @param {Object} options
   * @constructor
   * @private create with Tandem.createSupertypeTandem
   */
  function SupertypeTandem( id, options ) {
    Tandem.call( this, id, options );
  }

  tandemNamespace.register( 'Tandem.SupertypeTandem', SupertypeTandem );

  inherit( Tandem, SupertypeTandem, {

    // @public - Override to make no-op, see createSupertypeTandem
    addInstance: function( instance, type ) {},

    // @public - Override to make no-op, see createSupertypeTandem
    removeInstance: function( instance ) {}
  } );

  return Tandem;
} );

<|endoftext|>


<commit_before>// JavaScript
var $ = require('jquery');

(function($) {
    "use strict"; // Start of use strict

    // jQuery for page scrolling feature - requires jQuery Easing plugin
    //$('a.page-scroll').bind('click', function(event) {
    //    var $anchor = $(this);
    //    $('html, body').stop().animate({
    //        scrollTop: ($($anchor.attr('href')).offset().top - 50)
    //    }, 1250, 'easeInOutExpo');
    //    event.preventDefault();
    //});

    // Highlight the top nav as scrolling occurs
    //$('body').scrollspy({
    //    target: '.navbar-fixed-top',
    //    offset: 51
    //});

    // Closes the Responsive Menu on Menu Item Click
    $('.navbar-collapse ul li a').click(function(){
            $('.navbar-toggle:visible').click();
    });

    // Offset for Main Navigation
    //$('#mainNav').affix({
    //    offset: {
    //        top: 100
    //    }
    //})
})($); // End of use strict

$(document).ready(function () {

    // Show PopUp
    function PopUpShow() {
        $("#popup1").show();
        $("#video_play")[0].play();
    }

    $(".text-video a").click(function () {

        PopUpShow();
        //var elementClick = $(this).attr("href");
        //var destination = $(elementClick).offset().top;
        //if ($.browser.safari) {
        //    $('body').animate({ scrollTop: destination }, 100); //1100 - speed
        //} else {
        //    $('html').animate({ scrollTop: destination }, 1100);
        //}
        //return false;

    });

     //Hide PopUp, when you run a page
    PopUpHide();

    // Hide PopUp
    function PopUpHide() {
        $("#video_play")[0].pause();
        $("#popup1").hide();
    }
});

window.onload = function() { // when page was uploaded

    var scrollUp = document.getElementById('scrollup'); // найти элемент

    scrollUp.onmouseover = function() { // add opacity
        scrollUp.style.opacity=0.3;
        scrollUp.style.filter  = 'alpha(opacity=30)';
    };

    scrollUp.onmouseout = function() { //remove opacity
        scrollUp.style.opacity = 0.5;
        scrollUp.style.filter  = 'alpha(opacity=50)';
    };

    scrollUp.onclick = function() { //hendler
        window.scrollTo(0,0);
    };

// show button

    window.onscroll = function () { // show or hide block
        if ( window.pageYOffset > 0 ) {
            scrollUp.style.display = 'block';
        } else {
            scrollUp.style.display = 'none';
        }
    };
};

<commit_msg>UPDATE<commit_after>// JavaScript
var $ = require('jquery');

(function($) {
    "use strict"; // Start of use strict

    // jQuery for page scrolling feature - requires jQuery Easing plugin
    //$('a.page-scroll').bind('click', function(event) {
    //    var $anchor = $(this);
    //    $('html, body').stop().animate({
    //        scrollTop: ($($anchor.attr('href')).offset().top - 50)
    //    }, 1250, 'easeInOutExpo');
    //    event.preventDefault();
    //});

    // Highlight the top nav as scrolling occurs
    //$('body').scrollspy({
    //    target: '.navbar-fixed-top',
    //    offset: 51
    //});

    // Closes the Responsive Menu on Menu Item Click
    $('.navbar-collapse ul li a').click(function(){
            $('.navbar-toggle:visible').click();
    });

    // Offset for Main Navigation
    //$('#mainNav').affix({
    //    offset: {
    //        top: 100
    //    }
    //})
})($); // End of use strict

$(document).ready(function () {

    // Show PopUp
    //function PopUpShow() {
    //    $("#popup1").show();
    //    $("#video_play")[0].play();
    //}

    $(".text-video a").click(function () {

        $("#popup1").show();
        $("#video_play")[0].play();
        //var elementClick = $(this).attr("href");
        //var destination = $(elementClick).offset().top;
        //if ($.browser.safari) {
        //    $('body').animate({ scrollTop: destination }, 100); //1100 - speed
        //} else {
        //    $('html').animate({ scrollTop: destination }, 1100);
        //}
        //return false;

    });

     //Hide PopUp, when you run a page
    PopUpHide();

    // Hide PopUp
    function PopUpHide() {
        $("#video_play")[0].pause();
        $("#popup1").hide();
    }
});

window.onload = function() { // when page was uploaded

    var scrollUp = document.getElementById('scrollup'); // найти элемент

    scrollUp.onmouseover = function() { // add opacity
        scrollUp.style.opacity=0.3;
        scrollUp.style.filter  = 'alpha(opacity=30)';
    };

    scrollUp.onmouseout = function() { //remove opacity
        scrollUp.style.opacity = 0.5;
        scrollUp.style.filter  = 'alpha(opacity=50)';
    };

    scrollUp.onclick = function() { //hendler
        window.scrollTo(0,0);
    };

// show button

    window.onscroll = function () { // show or hide block
        if ( window.pageYOffset > 0 ) {
            scrollUp.style.display = 'block';
        } else {
            scrollUp.style.display = 'none';
        }
    };
};

<|endoftext|>


<commit_before>"use strict";

var Ajaxer = {
  debug: 0,

  // Ajax setup for all requests, this snippet is added to jQuery setup at the end of this file
  ajaxSetup: {
    timeout: 6000, // anything longer is too long
    cache: false, // this little sentence killed a lot of little bugs that was actually one big bug
  },

  // Format of params:
  // params = {
  //   url: 'http://api.lol.com',
  //   data: {sth: 'something', lol: 'laugh out LOUD'}, // Only use if you want a POST request
  //   success: function(data) {
  //     // Do something wth data
  //   },
  //   error: function(jqXHR, text, err) {
  //     // console.log "something, something, error"
  //   },
  // }

  getPlainText: function(params) {
    params.dataType = 'text';
    return this.get(params);
  },

  getJson: function(params) {
    params.dataType = 'json';
    return this.get(params);
  },

  getXml: function(params) {
    params.dataType = 'xml';
    return this.get(params);
  },

  getHtml: function(params) {
    params.dataType = 'html';
    var html = this.get(params);
    html = html.trim(); // jQuery 1.9+ does not consider pages starting with a newline as HTML, first char should be "<"
    return html;
  },

  getCleanHtml: function(params) {
    params.dataType = 'html';
    params.dataFilter = Ajaxer.cleanHtml;
    return this.get(params);
  },

  get: function(params) {
    if (params == undefined) {
      console.log('ERROR: Params is required. Check ajaxer.js to see format of params.');
      return;
    }
    if (params.url == undefined) {
      console.log('ERROR: URL missing from params.');
      return;
    }
    if (params.dataType == undefined) {
      console.log('ERROR: Do not use Ajaxer.get() directly, use getXml, getJson or one of the others instead.');
      return;
    }
    if (params.success == undefined) {
     console.log('ERROR: Params is missing success function. The success function should use the results for something useful.');
      return;
    }
    if (params.error == undefined) {
     console.log('ERROR: Params is missing error function. Error handling must be in place.');
      return;
    }

    var self = this;
    return $.ajax({
      type: (params.data ? 'POST' : 'GET'),
      data: (params.data ? params.data : ''),
      url: params.url,
      dataFilter: params.dataFilter,
      dataType: params.dataType,
      success: params.success,
      error: params.error,
    });
  },

  // IMPORTANT: This function replaces all <img> tags with <pic>
  cleanHtml: function(html, type) {
    var size = html.length;

    // Remove head, links, metas, scripts, iframes, frames, framesets
    html = html.replace(/<head\b[^<]*(?:(?!<\/head>)<[^<]*)*<\/head>/gi, '');
    html = html.replace(/<link\b[^<]*(?:(?!<\/link>)<[^<]*)*<\/link>/gi, '');
    html = html.replace(/<meta\b[^<]*(?:(?!<\/meta>)<[^<]*)*<\/meta>/gi, '');
    html = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
    html = html.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '');
    html = html.replace(/<frame\b[^<]*(?:(?!<\/frame>)<[^<]*)*<\/frame>/gi, '');
    html = html.replace(/<frameset\b[^<]*(?:(?!<\/frameset>)<[^<]*)*<\/frameset>/gi, '');

    // Remove audio, video, object, canvas, applet, embed
    html = html.replace(/<audio\b[^<]*(?:(?!<\/audio>)<[^<]*)*<\/audio>/gi, '');
    html = html.replace(/<video\b[^<]*(?:(?!<\/video>)<[^<]*)*<\/video>/gi, '');
    html = html.replace(/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi, '');
    html = html.replace(/<canvas\b[^<]*(?:(?!<\/canvas>)<[^<]*)*<\/canvas>/gi, '');
    html = html.replace(/<applet\b[^<]*(?:(?!<\/applet>)<[^<]*)*<\/applet>/gi, '');
    html = html.replace(/<embed\b[^<]*(?:(?!<\/embed>)<[^<]*)*<\/embed>/gi, '');

    // Remove inline scripts
    html = html.replace(/on\w+\s*?=\s*?("[^"]*"|'[^']*')/gi, '');
    // If any inline scripts didn't use enclosing quotes, turn them into harmless titles
    html = html.replace(/on\w+\s*?=/gi, 'title='); // Note: a bit greedy, but won't cause anything but lulz

    // Rename <img> tags to <pic> tags to prevent jQuery from trying to fetch all images.
    // jQuerys behavior is not too problematic, but has some security concerns, also it
    // will most definitely slow down any slow computer running Notifier, like most
    // Infoscreen computers out there.
    // When parsing for images, we will just look for the <pic> tags.
    html = html.replace(/<[\s]*?img/gi, '<pic');
    html = html.replace(/<[\s]*?\/[\s]*?img/gi, '</pic');

    // jQuery 1.9+ does not consider pages starting with a newline as HTML, first char should be "<"
    html = html.trim();

    if (Ajaxer.debug) console.log('Ajaxer cleaned HTML, from', size, 'to', html.length);
    return html;
  },
}

// Applying Ajax setup
$.ajaxSetup(Ajaxer.ajaxSetup);
<commit_msg>Added 'From'-header in all Ajax-requests of the type GET<commit_after>"use strict";

var Ajaxer = {
  debug: 0,

  // Ajax setup for all requests, this snippet is added to jQuery setup at the end of this file
  ajaxSetup: {
    timeout: 6000, // anything longer is too long
    cache: false, // this little sentence killed a lot of little bugs that was actually one big bug
    beforeSend: function (request, fields) {
        if (fields.type === 'GET')
            request.setRequestHeader('From', 'https://github.com/appKom/notifier');
        return true;
    },
  },

  // Format of params:
  // params = {
  //   url: 'http://api.lol.com',
  //   data: {sth: 'something', lol: 'laugh out LOUD'}, // Only use if you want a POST request
  //   success: function(data) {
  //     // Do something wth data
  //   },
  //   error: function(jqXHR, text, err) {
  //     // console.log "something, something, error"
  //   },
  // }

  getPlainText: function(params) {
    params.dataType = 'text';
    return this.get(params);
  },

  getJson: function(params) {
    params.dataType = 'json';
    return this.get(params);
  },

  getXml: function(params) {
    params.dataType = 'xml';
    return this.get(params);
  },

  getHtml: function(params) {
    params.dataType = 'html';
    var html = this.get(params);
    html = html.trim(); // jQuery 1.9+ does not consider pages starting with a newline as HTML, first char should be "<"
    return html;
  },

  getCleanHtml: function(params) {
    params.dataType = 'html';
    params.dataFilter = Ajaxer.cleanHtml;
    return this.get(params);
  },

  get: function(params) {
    if (params == undefined) {
      console.log('ERROR: Params is required. Check ajaxer.js to see format of params.');
      return;
    }
    if (params.url == undefined) {
      console.log('ERROR: URL missing from params.');
      return;
    }
    if (params.dataType == undefined) {
      console.log('ERROR: Do not use Ajaxer.get() directly, use getXml, getJson or one of the others instead.');
      return;
    }
    if (params.success == undefined) {
     console.log('ERROR: Params is missing success function. The success function should use the results for something useful.');
      return;
    }
    if (params.error == undefined) {
     console.log('ERROR: Params is missing error function. Error handling must be in place.');
      return;
    }

    var self = this;
    return $.ajax({
      type: (params.data ? 'POST' : 'GET'),
      data: (params.data ? params.data : ''),
      url: params.url,
      dataFilter: params.dataFilter,
      dataType: params.dataType,
      success: params.success,
      error: params.error,
    });
  },

  // IMPORTANT: This function replaces all <img> tags with <pic>
  cleanHtml: function(html, type) {
    var size = html.length;

    // Remove head, links, metas, scripts, iframes, frames, framesets
    html = html.replace(/<head\b[^<]*(?:(?!<\/head>)<[^<]*)*<\/head>/gi, '');
    html = html.replace(/<link\b[^<]*(?:(?!<\/link>)<[^<]*)*<\/link>/gi, '');
    html = html.replace(/<meta\b[^<]*(?:(?!<\/meta>)<[^<]*)*<\/meta>/gi, '');
    html = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
    html = html.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, '');
    html = html.replace(/<frame\b[^<]*(?:(?!<\/frame>)<[^<]*)*<\/frame>/gi, '');
    html = html.replace(/<frameset\b[^<]*(?:(?!<\/frameset>)<[^<]*)*<\/frameset>/gi, '');

    // Remove audio, video, object, canvas, applet, embed
    html = html.replace(/<audio\b[^<]*(?:(?!<\/audio>)<[^<]*)*<\/audio>/gi, '');
    html = html.replace(/<video\b[^<]*(?:(?!<\/video>)<[^<]*)*<\/video>/gi, '');
    html = html.replace(/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi, '');
    html = html.replace(/<canvas\b[^<]*(?:(?!<\/canvas>)<[^<]*)*<\/canvas>/gi, '');
    html = html.replace(/<applet\b[^<]*(?:(?!<\/applet>)<[^<]*)*<\/applet>/gi, '');
    html = html.replace(/<embed\b[^<]*(?:(?!<\/embed>)<[^<]*)*<\/embed>/gi, '');

    // Remove inline scripts
    html = html.replace(/on\w+\s*?=\s*?("[^"]*"|'[^']*')/gi, '');
    // If any inline scripts didn't use enclosing quotes, turn them into harmless titles
    html = html.replace(/on\w+\s*?=/gi, 'title='); // Note: a bit greedy, but won't cause anything but lulz

    // Rename <img> tags to <pic> tags to prevent jQuery from trying to fetch all images.
    // jQuerys behavior is not too problematic, but has some security concerns, also it
    // will most definitely slow down any slow computer running Notifier, like most
    // Infoscreen computers out there.
    // When parsing for images, we will just look for the <pic> tags.
    html = html.replace(/<[\s]*?img/gi, '<pic');
    html = html.replace(/<[\s]*?\/[\s]*?img/gi, '</pic');

    // jQuery 1.9+ does not consider pages starting with a newline as HTML, first char should be "<"
    html = html.trim();

    if (Ajaxer.debug) console.log('Ajaxer cleaned HTML, from', size, 'to', html.length);
    return html;
  },
}

// Applying Ajax setup
$.ajaxSetup(Ajaxer.ajaxSetup);
<|endoftext|>


<commit_before>// Represent Newcoin amounts and currencies.
// - Numbers in hex are big-endian.

var utils   = require('./utils.js');
var jsbn    = require('./jsbn.js');

var BigInteger	= jsbn.BigInteger;

var UInt160 = function () {
  // Internal form:
  //   0, 1, 'iXXXXX', 20 byte string, or NaN.
  //   XXX Should standardize on 'i' format or 20 format.
  this.value  = NaN;
};

UInt160.from_json = function (j) {
  return (new UInt160()).parse_json(j);
};

UInt160.prototype.clone = function() {
  return this.copyTo(new UInt160());
};

// Returns copy.
UInt160.prototype.copyTo = function(d) {
  d.value = this.value;

  return d;
};

// value === NaN on error.
UInt160.prototype.parse_json = function (j) {
  // Canonicalize and validate

  switch (j) {
    case undefined:
    case "0":
    case exports.consts.address_xns:
    case exports.consts.uint160_xns:
    case exports.consts.hex_xns:
      this.value  = 0;
      break;

    case "1":
    case exports.consts.address_one:
    case exports.consts.uint160_one:
    case exports.consts.hex_one:
      this.value  = 1;
      break;

    default:
      if ('string' !== typeof j) {
	this.value  = NaN;
      }
      else if (20 === j.length) {
	this.value  = j;
      }
      else if (40 === j.length) {
	this.value  = utils.hexToString(j);
      }
      else if (j[0] === "i") {
	// XXX Do more checking convert to string.

	this.value  = j;
      }
      else {
	this.value  = NaN;
      }
  }

  return this;
};

// Convert from internal form.
// XXX Json form should allow 0 and 1, C++ doesn't currently allow it.
UInt160.prototype.to_json = function () {
  if ("0" === this.value) {
    return exports.consts.hex_xns;
  }
  else if ("1" === this.value)
  {
    return exports.consts.hex_one;
  }
  else if ('string' === typeof this.value && 20 === this.value.length) {
    return utils.stringToHex(this.value);
  }
  else
  {
    return this.value;
  }
};

var Currency = function () {
  // Internal form: 0 = XNS. 3 letter-code.
  // XXX Internal should be 0 or hex.

  // Json form:
  //  '', 'XNS', '0': 0
  //  3-letter code: ...
  // XXX Should support hex, C++ doesn't currently allow it.

  this.value  = NaN;
}

Currency.from_json = function (j) {
  return (new Currency()).parse_json(j);
};

Currency.prototype.clone = function() {
  return this.copyTo(new Currency());
};

// Returns copy.
Currency.prototype.copyTo = function(d) {
  d.value = this.value;

  return d;
};

// this.value === NaN on error.
Currency.prototype.parse_json = function(j) {
  if ("" === j || "0" === j || "XNS" === j) {
    this.value	= 0;
  }
  else if ('string' != typeof j || 3 !== j.length) {
    this.value	= NaN;
  }
  else {
    this.value	= j;
  }

  return this;
};

Currency.prototype.to_json = function () {
  return this.value ? this.value : "XNS";
};

Currency.prototype.to_human = function() {
  return this.value ? this.value : "XNS";
};

var Amount = function () {
  // Json format:
  //  integer : XNS
  //  { 'value' : ..., 'currency' : ..., 'issuer' : ...}

  this.value	    = new BigInteger();	// NaN for bad value. Always positive for non-XNS.
  this.offset	    = undefined;	// For non-XNS.
  this.is_native    = true;		// Default to XNS. Only valid if value is not NaN.
  this.is_negative  = undefined;	// Undefined for XNS.

  this.currency	    = new Currency();
  this.issuer	    = new UInt160();
};

Amount.from_json = function(j) {
  return (new Amount()).parse_json(j);
};

Amount.prototype.clone = function() {
  return this.copyTo(new Amount());
};

// Returns copy.
Amount.prototype.copyTo = function(d) {
  if ('object' === typeof this.value)
  {
    this.value.copyTo(d.value);
  }
  else
  {
    d.value   = this.value;
  }

  d.offset	= this.offset;
  d.is_native	= this.is_native;
  d.is_negative	= this.is_negative;

  this.currency.copyTo(d.currency);
  this.issuer.copyTo(d.issuer);

  return d;
};

// YYY Might also provide is_valid_json.
Amount.prototype.is_valid = function() {
  return NaN !== this.value;
};

// Convert only value to JSON wire format.
Amount.prototype.to_text = function(allow_nan) {
  if (NaN === this.value) {
    // Never should happen.
    return allow_nan ? NaN : "0";
  }
  else if (this.is_native) {
    if (this.value.compareTo(exports.consts.bi_xns_max) > 0 || this.value.compareTo(exports.consts.bi_xns_min) < 0)
    {
      // Never should happen.
      return allow_nan ? NaN : "0";
    }
    else
    {
      return this.value.toString();
    }
  }
  else if (this.value.equals(BigInteger.ZERO))
  {
    return "0";
  }
  else if (this.offset < -25 || this.offset > -5)
  {
    // Use e notation.
    // XXX Clamp output.

    return (this.is_negative ? "-" : "") + this.value.toString() + "e" + this.offset;
  }
  else
  {
    var val = "000000000000000000000000000" + this.value.toString() + "00000000000000000000000";
    var	pre = val.substring(0, this.offset + 43);
    var	post = val.substring(this.offset + 43);
    var	s_pre = pre.match(/[1-9].*$/);	  // Everything but leading zeros.
    var	s_post = post.match(/[1-9]0*$/);  // Last non-zero plus trailing zeros.

    return (this.is_negative ? "-" : "")
      + (s_pre ? s_pre[0] : "0")
      + (s_post ? "." + post.substring(0, 1+post.length-s_post[0].length) : "");
  }
};

Amount.prototype.canonicalize = function() {
  if (NaN === this.value || !this.currency) {
    // nothing
  }
  else if (this.value.equals(BigInteger.ZERO)) {
    this.offset	      = -100;
    this.is_negative  = false;
  }
  else
  {
    while (this.value.compareTo(exports.consts.bi_man_min_value) < 0) {
      this.value  = this.value.multiply(exports.consts.bi_10);
      this.offset -= 1;
    }

    while (this.value.compareTo(exports.consts.bi_man_max_value) > 0) {
      this.value  = this.value.divide(exports.consts.bi_10);
      this.offset += 1;
    }
  }
};

Amount.prototype.to_json = function() {
  if (this.is_native) {
    return this.to_text();
  }
  else
  {
    return {
      'value' : this.to_text(),
      'currency' : this.currency.to_json(),
      'issuer' : this.issuer.to_json(),
    };
  }
};

Amount.prototype.to_text_full = function() {
  return this.value === NaN
    ? NaN
    : this.is_native
      ? this.to_text() + "/XNS"
      : this.to_text() + "/" + this.currency.to_json() + "/" + this.issuer.to_json();
};

// Parse a XNS value from untrusted input.
// - integer = raw units
// - float = with precision 6
// XXX Improvements: disallow leading zeros.
Amount.prototype.parse_native = function(j) {
  var m;

  if ('string' === typeof j)
    m = j.match(/^(\d+)(\.\d{1,6})?$/);

  if (m) {
    if (undefined === m[2]) {
      // Integer notation

      this.value	  = new BigInteger(m[1]);
    }
    else {
      // Decimal notation

      var   int_part	  = (new BigInteger(m[1])).multiply(exports.consts.bi_xns_unit);
      var   fraction_part = (new BigInteger(m[2])).multiply(new BigInteger(String(Math.pow(10, 1+exports.consts.xns_precision-m[2].length))));

      this.value	  = int_part.add(fraction_part);
    }

    this.is_native    = true;
    this.offset	      = undefined;
    this.is_negative  = undefined;

    if (this.value.compareTo(exports.consts.bi_xns_max) > 0 || this.value.compareTo(exports.consts.bi_xns_min) < 0)
    {
      this.value	  = NaN;
    }
  }
  else {
    this.value	      = NaN;
  }

  return this;
};

// Parse a non-native value.
Amount.prototype.parse_value = function(j) {
  if ('number' === typeof j) {
    this.value	      = new BigInteger(j);
    this.offset	      = 0;
    this.is_native    = false;
    this.is_negative  = j < 0;

    this.canonicalize();
  }
  else if ('string' === typeof j) {
    var	e = j.match(/^(-?\d+)e(\d+)/);
    var	d = j.match(/^(-?\d+)\.(\d+)/);

    if (e) {
      // e notation

      this.value  = new BigInteger(e[1]);
      this.offset = parseInt(e[2]);
    }
    else if (d) {
      // float notation

      var integer   = new BigInteger(d[1]);
      var fraction  = new BigInteger(d[2]);
      this.value    = integer.multiply(exports.consts.bi_10.clone().pow(d[2].length)).add(fraction);
      this.offset   = -d[2].length;
    }
    else
    {
      // integer notation

      this.value  = new BigInteger(j);
      this.offset = 0;
    }

    this.is_native    = false;
    this.is_negative  = undefined;

    this.canonicalize();
  }
  else {
    this.value	      = NaN;
  }

  return this;
};

// <-> j
Amount.prototype.parse_json = function(j) {
  if ('string' === typeof j) {
    // .../.../... notation is not a wire format.  But allowed for easier testing.
    var	m = j.match(/^(.+)\/(...)\/(.+)$/);

    if (m) {
      this.parse_value(m[1]);
      this.currency = Currency.from_json(m[2]);
      this.issuer   = UInt160.from_json(m[3]);
    }
    else {
      this.parse_native(j);
      this.currency = new Currency();
      this.issuer   = new UInt160();
    }
  }
  else if ('object' === typeof j && j.currency) {
    // Never XNS.

    this.parse_value(j.value);
    this.currency.parse_json(j.currency);
    this.issuer.parse_json(j.issuer);
  }
  else {
    this.value	      = NaN;
  }

  return this;
};

exports.Amount	  = Amount;
exports.Currency  = Currency;
exports.UInt160	  = UInt160;

exports.consts	  = {
  'address_xns'	      : "iiiiiiiiiiiiiiiiiiiiihoLvTp",
  'address_one'	      : "iiiiiiiiiiiiiiiiiiiiBZbvjr",
  'currency_xns'      : 0,
  'currency_one'      : 1,
  'uint160_xns'	      : utils.hexToString("0000000000000000000000000000000000000000"),
  'uint160_one'	      : utils.hexToString("0000000000000000000000000000000000000001"),
  'hex_xns'	      : "0000000000000000000000000000000000000000",
  'hex_one'	      : "0000000000000000000000000000000000000001",
  'xns_precision'     : 6,

  // BigInteger values prefixed with bi_.
  'bi_10'	      : new BigInteger('10'),
  'bi_man_max_value'  : new BigInteger('9999999999999999'),
  'bi_man_min_value'  : new BigInteger('1000000000000000'),
  'bi_xns_max'	      : new BigInteger("9000000000000000000"),	  // Json wire limit.
  'bi_xns_min'	      : new BigInteger("-9000000000000000000"),	  // Json wire limit.
  'bi_xns_unit'	      : new BigInteger('1000000'),
};

// vim:sw=2:sts=2:ts=8
<commit_msg>JS: Adjust to new address encoding.<commit_after>// Represent Newcoin amounts and currencies.
// - Numbers in hex are big-endian.

var utils   = require('./utils.js');
var jsbn    = require('./jsbn.js');

var BigInteger	= jsbn.BigInteger;

var UInt160 = function () {
  // Internal form:
  //   0, 1, 'iXXXXX', 20 byte string, or NaN.
  //   XXX Should standardize on 'i' format or 20 format.
  this.value  = NaN;
};

UInt160.from_json = function (j) {
  return (new UInt160()).parse_json(j);
};

UInt160.prototype.clone = function() {
  return this.copyTo(new UInt160());
};

// Returns copy.
UInt160.prototype.copyTo = function(d) {
  d.value = this.value;

  return d;
};

// value === NaN on error.
UInt160.prototype.parse_json = function (j) {
  // Canonicalize and validate

  switch (j) {
    case undefined:
    case "0":
    case exports.consts.address_xns:
    case exports.consts.uint160_xns:
    case exports.consts.hex_xns:
      this.value  = 0;
      break;

    case "1":
    case exports.consts.address_one:
    case exports.consts.uint160_one:
    case exports.consts.hex_one:
      this.value  = 1;
      break;

    default:
      if ('string' !== typeof j) {
	this.value  = NaN;
      }
      else if (20 === j.length) {
	this.value  = j;
      }
      else if (40 === j.length) {
	this.value  = utils.hexToString(j);
      }
      else if (j[0] === "r") {
	// XXX Do more checking convert to string.

	this.value  = j;
      }
      else {
	this.value  = NaN;
      }
  }

  return this;
};

// Convert from internal form.
// XXX Json form should allow 0 and 1, C++ doesn't currently allow it.
UInt160.prototype.to_json = function () {
  if ("0" === this.value) {
    return exports.consts.hex_xns;
  }
  else if ("1" === this.value)
  {
    return exports.consts.hex_one;
  }
  else if ('string' === typeof this.value && 20 === this.value.length) {
    return utils.stringToHex(this.value);
  }
  else
  {
    return this.value;
  }
};

var Currency = function () {
  // Internal form: 0 = XNS. 3 letter-code.
  // XXX Internal should be 0 or hex.

  // Json form:
  //  '', 'XNS', '0': 0
  //  3-letter code: ...
  // XXX Should support hex, C++ doesn't currently allow it.

  this.value  = NaN;
}

Currency.from_json = function (j) {
  return (new Currency()).parse_json(j);
};

Currency.prototype.clone = function() {
  return this.copyTo(new Currency());
};

// Returns copy.
Currency.prototype.copyTo = function(d) {
  d.value = this.value;

  return d;
};

// this.value === NaN on error.
Currency.prototype.parse_json = function(j) {
  if ("" === j || "0" === j || "XNS" === j) {
    this.value	= 0;
  }
  else if ('string' != typeof j || 3 !== j.length) {
    this.value	= NaN;
  }
  else {
    this.value	= j;
  }

  return this;
};

Currency.prototype.to_json = function () {
  return this.value ? this.value : "XNS";
};

Currency.prototype.to_human = function() {
  return this.value ? this.value : "XNS";
};

var Amount = function () {
  // Json format:
  //  integer : XNS
  //  { 'value' : ..., 'currency' : ..., 'issuer' : ...}

  this.value	    = new BigInteger();	// NaN for bad value. Always positive for non-XNS.
  this.offset	    = undefined;	// For non-XNS.
  this.is_native    = true;		// Default to XNS. Only valid if value is not NaN.
  this.is_negative  = undefined;	// Undefined for XNS.

  this.currency	    = new Currency();
  this.issuer	    = new UInt160();
};

Amount.from_json = function(j) {
  return (new Amount()).parse_json(j);
};

Amount.prototype.clone = function() {
  return this.copyTo(new Amount());
};

// Returns copy.
Amount.prototype.copyTo = function(d) {
  if ('object' === typeof this.value)
  {
    this.value.copyTo(d.value);
  }
  else
  {
    d.value   = this.value;
  }

  d.offset	= this.offset;
  d.is_native	= this.is_native;
  d.is_negative	= this.is_negative;

  this.currency.copyTo(d.currency);
  this.issuer.copyTo(d.issuer);

  return d;
};

// YYY Might also provide is_valid_json.
Amount.prototype.is_valid = function() {
  return NaN !== this.value;
};

// Convert only value to JSON wire format.
Amount.prototype.to_text = function(allow_nan) {
  if (NaN === this.value) {
    // Never should happen.
    return allow_nan ? NaN : "0";
  }
  else if (this.is_native) {
    if (this.value.compareTo(exports.consts.bi_xns_max) > 0 || this.value.compareTo(exports.consts.bi_xns_min) < 0)
    {
      // Never should happen.
      return allow_nan ? NaN : "0";
    }
    else
    {
      return this.value.toString();
    }
  }
  else if (this.value.equals(BigInteger.ZERO))
  {
    return "0";
  }
  else if (this.offset < -25 || this.offset > -5)
  {
    // Use e notation.
    // XXX Clamp output.

    return (this.is_negative ? "-" : "") + this.value.toString() + "e" + this.offset;
  }
  else
  {
    var val = "000000000000000000000000000" + this.value.toString() + "00000000000000000000000";
    var	pre = val.substring(0, this.offset + 43);
    var	post = val.substring(this.offset + 43);
    var	s_pre = pre.match(/[1-9].*$/);	  // Everything but leading zeros.
    var	s_post = post.match(/[1-9]0*$/);  // Last non-zero plus trailing zeros.

    return (this.is_negative ? "-" : "")
      + (s_pre ? s_pre[0] : "0")
      + (s_post ? "." + post.substring(0, 1+post.length-s_post[0].length) : "");
  }
};

Amount.prototype.canonicalize = function() {
  if (NaN === this.value || !this.currency) {
    // nothing
  }
  else if (this.value.equals(BigInteger.ZERO)) {
    this.offset	      = -100;
    this.is_negative  = false;
  }
  else
  {
    while (this.value.compareTo(exports.consts.bi_man_min_value) < 0) {
      this.value  = this.value.multiply(exports.consts.bi_10);
      this.offset -= 1;
    }

    while (this.value.compareTo(exports.consts.bi_man_max_value) > 0) {
      this.value  = this.value.divide(exports.consts.bi_10);
      this.offset += 1;
    }
  }
};

Amount.prototype.to_json = function() {
  if (this.is_native) {
    return this.to_text();
  }
  else
  {
    return {
      'value' : this.to_text(),
      'currency' : this.currency.to_json(),
      'issuer' : this.issuer.to_json(),
    };
  }
};

Amount.prototype.to_text_full = function() {
  return this.value === NaN
    ? NaN
    : this.is_native
      ? this.to_text() + "/XNS"
      : this.to_text() + "/" + this.currency.to_json() + "/" + this.issuer.to_json();
};

// Parse a XNS value from untrusted input.
// - integer = raw units
// - float = with precision 6
// XXX Improvements: disallow leading zeros.
Amount.prototype.parse_native = function(j) {
  var m;

  if ('string' === typeof j)
    m = j.match(/^(\d+)(\.\d{1,6})?$/);

  if (m) {
    if (undefined === m[2]) {
      // Integer notation

      this.value	  = new BigInteger(m[1]);
    }
    else {
      // Decimal notation

      var   int_part	  = (new BigInteger(m[1])).multiply(exports.consts.bi_xns_unit);
      var   fraction_part = (new BigInteger(m[2])).multiply(new BigInteger(String(Math.pow(10, 1+exports.consts.xns_precision-m[2].length))));

      this.value	  = int_part.add(fraction_part);
    }

    this.is_native    = true;
    this.offset	      = undefined;
    this.is_negative  = undefined;

    if (this.value.compareTo(exports.consts.bi_xns_max) > 0 || this.value.compareTo(exports.consts.bi_xns_min) < 0)
    {
      this.value	  = NaN;
    }
  }
  else {
    this.value	      = NaN;
  }

  return this;
};

// Parse a non-native value.
Amount.prototype.parse_value = function(j) {
  if ('number' === typeof j) {
    this.value	      = new BigInteger(j);
    this.offset	      = 0;
    this.is_native    = false;
    this.is_negative  = j < 0;

    this.canonicalize();
  }
  else if ('string' === typeof j) {
    var	e = j.match(/^(-?\d+)e(\d+)/);
    var	d = j.match(/^(-?\d+)\.(\d+)/);

    if (e) {
      // e notation

      this.value  = new BigInteger(e[1]);
      this.offset = parseInt(e[2]);
    }
    else if (d) {
      // float notation

      var integer   = new BigInteger(d[1]);
      var fraction  = new BigInteger(d[2]);
      this.value    = integer.multiply(exports.consts.bi_10.clone().pow(d[2].length)).add(fraction);
      this.offset   = -d[2].length;
    }
    else
    {
      // integer notation

      this.value  = new BigInteger(j);
      this.offset = 0;
    }

    this.is_native    = false;
    this.is_negative  = undefined;

    this.canonicalize();
  }
  else {
    this.value	      = NaN;
  }

  return this;
};

// <-> j
Amount.prototype.parse_json = function(j) {
  if ('string' === typeof j) {
    // .../.../... notation is not a wire format.  But allowed for easier testing.
    var	m = j.match(/^(.+)\/(...)\/(.+)$/);

    if (m) {
      this.parse_value(m[1]);
      this.currency = Currency.from_json(m[2]);
      this.issuer   = UInt160.from_json(m[3]);
    }
    else {
      this.parse_native(j);
      this.currency = new Currency();
      this.issuer   = new UInt160();
    }
  }
  else if ('object' === typeof j && j.currency) {
    // Never XNS.

    this.parse_value(j.value);
    this.currency.parse_json(j.currency);
    this.issuer.parse_json(j.issuer);
  }
  else {
    this.value	      = NaN;
  }

  return this;
};

exports.Amount	  = Amount;
exports.Currency  = Currency;
exports.UInt160	  = UInt160;

exports.consts	  = {
  'address_xns'	      : "rrrrrrrrrrrrrrrrrrrrrhoLvTp",
  'address_one'	      : "rrrrrrrrrrrrrrrrrrrrBZbvji",
  'currency_xns'      : 0,
  'currency_one'      : 1,
  'uint160_xns'	      : utils.hexToString("0000000000000000000000000000000000000000"),
  'uint160_one'	      : utils.hexToString("0000000000000000000000000000000000000001"),
  'hex_xns'	      : "0000000000000000000000000000000000000000",
  'hex_one'	      : "0000000000000000000000000000000000000001",
  'xns_precision'     : 6,

  // BigInteger values prefixed with bi_.
  'bi_10'	      : new BigInteger('10'),
  'bi_man_max_value'  : new BigInteger('9999999999999999'),
  'bi_man_min_value'  : new BigInteger('1000000000000000'),
  'bi_xns_max'	      : new BigInteger("9000000000000000000"),	  // Json wire limit.
  'bi_xns_min'	      : new BigInteger("-9000000000000000000"),	  // Json wire limit.
  'bi_xns_unit'	      : new BigInteger('1000000'),
};

// vim:sw=2:sts=2:ts=8
<|endoftext|>