<commit_before>/**
 * A utility class to help make it easier to access the data stores
 * @extends {Map}
 */
class Collection extends Map {
  /**
   * Returns an ordered array of the values of this collection.
   * @returns {Array}
   * @example
   * // identical to:
   * Array.from(collection.values());
   */
  array() {
    return Array.from(this.values());
  }

  /**
   * Returns an ordered array of the keys of this collection.
   * @returns {Array}
   * @example
   * // identical to:
   * Array.from(collection.keys());
   */
  keyArray() {
    return Array.from(this.keys());
  }

  /**
   * Returns the first item in this collection.
   * @returns {*}
   */
  first() {
    return this.values().next().value;
  }

  /**
   * Returns the first key in this collection.
   * @returns {*}
   */
  firstKey() {
    return this.keys().next().value;
  }

  /**
   * Returns the last item in this collection. This is a relatively slow operation,
   * since an array copy of the values must be made to find the last element.
   * @returns {*}
   */
  last() {
    const arr = this.array();
    return arr[arr.length - 1];
  }

  /**
   * Returns the last key in this collection. This is a relatively slow operation,
   * since an array copy of the keys must be made to find the last element.
   * @returns {*}
   */
  lastKey() {
    const arr = this.keyArray();
    return arr[arr.length - 1];
  }

  /**
   * Returns a random item from this collection. This is a relatively slow operation,
   * since an array copy of the values must be made to find a random element.
   * @returns {*}
   */
  random() {
    const arr = this.array();
    return arr[Math.floor(Math.random() * arr.length)];
  }

  /**
   * Returns a random key from this collection. This is a relatively slow operation,
   * since an array copy of the keys must be made to find a random element.
   * @returns {*}
   */
  randomKey() {
    const arr = this.keyArray();
    return arr[Math.floor(Math.random() * arr.length)];
  }

  /**
   * Returns an array of items where `item[prop] === value` of the collection
   * @param {string} prop The property to test against
   * @param {*} value The expected value
   * @returns {array}
   * @example
   * collection.findAll('username', 'Bob');
   */
  findAll(prop, value) {
    if (typeof prop !== 'string') throw new TypeError('Key must be a string.');
    if (typeof value === 'undefined') throw new Error('Value must be specified.');
    const results = [];
    for (const item of this.values()) {
      if (item[prop] === value) results.push(item);
    }
    return results;
  }

  /**
   * Returns a single item where `item[prop] === value`, or the given function returns `true`.
   * In the latter case, this is identical to
   * [Array.find()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find).
   * @param {string|function} propOrFn The property to test against, or the function to test with
   * @param {*} [value] The expected value - only applicable and required if using a property for the first argument
   * @returns {*}
   * @example
   * collection.find('username', 'Bob');
   * @example
   * collection.find(val => val.username === 'Bob');
   */
  find(propOrFn, value) {
    if (typeof propOrFn === 'string') {
      if (typeof value === 'undefined') throw new Error('Value must be specified.');
      for (const item of this.values()) {
        if (item[propOrFn] === value) return item;
      }
      return null;
    } else if (typeof propOrFn === 'function') {
      for (const [key, val] of this) {
        if (propOrFn(val, key, this)) return val;
      }
      return null;
    } else {
      throw new Error('First argument must be a property string or a function.');
    }
  }

  /* eslint-disable max-len */
  /**
   * Returns the key of the item where `item[prop] === value`, or the given function returns `true`.
   * In the latter case, this is identical to
   * [Array.findIndex()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex).
   * @param {string|function} propOrFn The property to test against, or the function to test with
   * @param {*} [value] The expected value - only applicable and required if using a property for the first argument
   * @returns {*}
   * @example
   * collection.findKey('username', 'Bob');
   * @example
   * collection.findKey(val => val.username === 'Bob');
   */
  /* eslint-enable max-len */
  findKey(propOrFn, value) {
    if (typeof propOrFn === 'string') {
      if (typeof value === 'undefined') throw new Error('Value must be specified.');
      for (const [key, val] of this) {
        if (val[propOrFn] === value) return key;
      }
      return null;
    } else if (typeof propOrFn === 'function') {
      for (const [key, val] of this) {
        if (propOrFn(val, key, this)) return key;
      }
      return null;
    } else {
      throw new Error('First argument must be a property string or a function.');
    }
  }

  /**
   * Returns true if the collection has an item where `item[prop] === value`
   * @param {string} prop The property to test against
   * @param {*} value The expected value
   * @returns {boolean}
   * @example
   * if (collection.exists('username', 'Bob')) {
   *  console.log('user here!');
   * }
   */
  exists(prop, value) {
    return Boolean(this.find(prop, value));
  }

  /**
   * Identical to
   * [Array.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter),
   * but returns a Collection instead of an Array.
   * @param {function} fn Function used to test (should return a boolean)
   * @param {Object} [thisArg] Value to use as `this` when executing function
   * @returns {Collection}
   */
  filter(fn, thisArg) {
    if (thisArg) fn = fn.bind(thisArg);
    const collection = new Collection();
    for (const [key, val] of this) {
      if (fn(val, key, this)) collection.set(key, val);
    }
    return collection;
  }

  /**
   * Identical to
   * [Array.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).
   * @param {function} fn Function that produces an element of the new array, taking three arguments
   * @param {*} [thisArg] Value to use as `this` when executing function
   * @returns {array}
   */
  map(fn, thisArg) {
    if (thisArg) fn = fn.bind(thisArg);
    const arr = new Array(this.size);
    let i = 0;
    for (const [key, val] of this) arr[i++] = fn(val, key, this);
    return arr;
  }

  /**
   * Identical to
   * [Array.some()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some).
   * @param {function} fn Function used to test (should return a boolean)
   * @param {Object} [thisArg] Value to use as `this` when executing function
   * @returns {boolean}
   */
  some(fn, thisArg) {
    if (thisArg) fn = fn.bind(thisArg);
    for (const [key, val] of this) {
      if (fn(val, key, this)) return true;
    }
    return false;
  }

  /**
   * Identical to
   * [Array.every()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every).
   * @param {function} fn Function used to test (should return a boolean)
   * @param {Object} [thisArg] Value to use as `this` when executing function
   * @returns {boolean}
   */
  every(fn, thisArg) {
    if (thisArg) fn = fn.bind(thisArg);
    for (const [key, val] of this) {
      if (!fn(val, key, this)) return false;
    }
    return true;
  }

  /**
   * Identical to
   * [Array.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce).
   * @param {function} fn Function used to reduce
   * @param {*} [startVal] The starting value
   * @returns {*}
   */
  reduce(fn, startVal) {
    let currentVal = startVal;
    for (const [key, val] of this) currentVal = fn(currentVal, val, key, this);
    return currentVal;
  }

  /**
   * If the items in this collection have a delete method (e.g. messages), invoke
   * the delete method. Returns an array of promises
   * @returns {Promise[]}
   */
  deleteAll() {
    const returns = [];
    for (const item of this.values()) {
      if (item.delete) returns.push(item.delete());
    }
    return returns;
  }
}

module.exports = Collection;
<commit_msg>Cache array and keyArray in Collection (#771)<commit_after>/**
 * A utility class to help make it easier to access the data stores
 * @extends {Map}
 */
class Collection extends Map {
  set(key, value) {
    super.set(key, value);
    this.changed = true;
  }

  delete(key) {
    super.delete(key);
    this.changed = true;
  }

  /**
   * Returns an ordered array of the values of this collection.
   * @returns {Array}
   * @example
   * // identical to:
   * Array.from(collection.values());
   */
  array() {
    return Array.from(this.values());
  }

  /**
   * Returns an ordered array of the keys of this collection.
   * @returns {Array}
   * @example
   * // identical to:
   * Array.from(collection.keys());
   */
  keyArray() {
    return Array.from(this.keys());
  }

  /**
   * Returns the first item in this collection.
   * @returns {*}
   */
  first() {
    return this.values().next().value;
  }

  /**
   * Returns the first key in this collection.
   * @returns {*}
   */
  firstKey() {
    return this.keys().next().value;
  }

  /**
   * Returns the last item in this collection. This is a relatively slow operation,
   * since an array copy of the values must be made to find the last element.
   * @returns {*}
   */
  last() {
    const arr = this.array();
    return arr[arr.length - 1];
  }

  /**
   * Returns the last key in this collection. This is a relatively slow operation,
   * since an array copy of the keys must be made to find the last element.
   * @returns {*}
   */
  lastKey() {
    const arr = this.keyArray();
    return arr[arr.length - 1];
  }

  /**
   * Returns a random item from this collection. This is a relatively slow operation,
   * since an array copy of the values must be made to find a random element.
   * @returns {*}
   */
  random() {
    if (!this.cachedArray || this.cachedArray.length !== this.size || this.changed) {
      this.cachedArray = this.array();
      this.changed = false;
    }
    return this.cachedArray[Math.floor(Math.random() * this.cachedArray.length)];
  }

  /**
   * Returns a random key from this collection. This is a relatively slow operation,
   * since an array copy of the keys must be made to find a random element.
   * @returns {*}
   */
  randomKey() {
    if (!this.cachedKeyArray || this.cachedKeyArray.length !== this.size || this.changed) {
      this.cachedKeyArray = this.keyArray();
      this.changed = false;
    }
    return this.cachedKeyArray[Math.floor(Math.random() * this.cachedKeyArray.length)];
  }

  /**
   * Returns an array of items where `item[prop] === value` of the collection
   * @param {string} prop The property to test against
   * @param {*} value The expected value
   * @returns {array}
   * @example
   * collection.findAll('username', 'Bob');
   */
  findAll(prop, value) {
    if (typeof prop !== 'string') throw new TypeError('Key must be a string.');
    if (typeof value === 'undefined') throw new Error('Value must be specified.');
    const results = [];
    for (const item of this.values()) {
      if (item[prop] === value) results.push(item);
    }
    return results;
  }

  /**
   * Returns a single item where `item[prop] === value`, or the given function returns `true`.
   * In the latter case, this is identical to
   * [Array.find()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find).
   * @param {string|function} propOrFn The property to test against, or the function to test with
   * @param {*} [value] The expected value - only applicable and required if using a property for the first argument
   * @returns {*}
   * @example
   * collection.find('username', 'Bob');
   * @example
   * collection.find(val => val.username === 'Bob');
   */
  find(propOrFn, value) {
    if (typeof propOrFn === 'string') {
      if (typeof value === 'undefined') throw new Error('Value must be specified.');
      for (const item of this.values()) {
        if (item[propOrFn] === value) return item;
      }
      return null;
    } else if (typeof propOrFn === 'function') {
      for (const [key, val] of this) {
        if (propOrFn(val, key, this)) return val;
      }
      return null;
    } else {
      throw new Error('First argument must be a property string or a function.');
    }
  }

  /* eslint-disable max-len */
  /**
   * Returns the key of the item where `item[prop] === value`, or the given function returns `true`.
   * In the latter case, this is identical to
   * [Array.findIndex()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex).
   * @param {string|function} propOrFn The property to test against, or the function to test with
   * @param {*} [value] The expected value - only applicable and required if using a property for the first argument
   * @returns {*}
   * @example
   * collection.findKey('username', 'Bob');
   * @example
   * collection.findKey(val => val.username === 'Bob');
   */
  /* eslint-enable max-len */
  findKey(propOrFn, value) {
    if (typeof propOrFn === 'string') {
      if (typeof value === 'undefined') throw new Error('Value must be specified.');
      for (const [key, val] of this) {
        if (val[propOrFn] === value) return key;
      }
      return null;
    } else if (typeof propOrFn === 'function') {
      for (const [key, val] of this) {
        if (propOrFn(val, key, this)) return key;
      }
      return null;
    } else {
      throw new Error('First argument must be a property string or a function.');
    }
  }

  /**
   * Returns true if the collection has an item where `item[prop] === value`
   * @param {string} prop The property to test against
   * @param {*} value The expected value
   * @returns {boolean}
   * @example
   * if (collection.exists('username', 'Bob')) {
   *  console.log('user here!');
   * }
   */
  exists(prop, value) {
    return Boolean(this.find(prop, value));
  }

  /**
   * Identical to
   * [Array.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter),
   * but returns a Collection instead of an Array.
   * @param {function} fn Function used to test (should return a boolean)
   * @param {Object} [thisArg] Value to use as `this` when executing function
   * @returns {Collection}
   */
  filter(fn, thisArg) {
    if (thisArg) fn = fn.bind(thisArg);
    const collection = new Collection();
    for (const [key, val] of this) {
      if (fn(val, key, this)) collection.set(key, val);
    }
    return collection;
  }

  /**
   * Identical to
   * [Array.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).
   * @param {function} fn Function that produces an element of the new array, taking three arguments
   * @param {*} [thisArg] Value to use as `this` when executing function
   * @returns {array}
   */
  map(fn, thisArg) {
    if (thisArg) fn = fn.bind(thisArg);
    const arr = new Array(this.size);
    let i = 0;
    for (const [key, val] of this) arr[i++] = fn(val, key, this);
    return arr;
  }

  /**
   * Identical to
   * [Array.some()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some).
   * @param {function} fn Function used to test (should return a boolean)
   * @param {Object} [thisArg] Value to use as `this` when executing function
   * @returns {boolean}
   */
  some(fn, thisArg) {
    if (thisArg) fn = fn.bind(thisArg);
    for (const [key, val] of this) {
      if (fn(val, key, this)) return true;
    }
    return false;
  }

  /**
   * Identical to
   * [Array.every()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every).
   * @param {function} fn Function used to test (should return a boolean)
   * @param {Object} [thisArg] Value to use as `this` when executing function
   * @returns {boolean}
   */
  every(fn, thisArg) {
    if (thisArg) fn = fn.bind(thisArg);
    for (const [key, val] of this) {
      if (!fn(val, key, this)) return false;
    }
    return true;
  }

  /**
   * Identical to
   * [Array.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce).
   * @param {function} fn Function used to reduce
   * @param {*} [startVal] The starting value
   * @returns {*}
   */
  reduce(fn, startVal) {
    let currentVal = startVal;
    for (const [key, val] of this) currentVal = fn(currentVal, val, key, this);
    return currentVal;
  }

  /**
   * If the items in this collection have a delete method (e.g. messages), invoke
   * the delete method. Returns an array of promises
   * @returns {Promise[]}
   */
  deleteAll() {
    const returns = [];
    for (const item of this.values()) {
      if (item.delete) returns.push(item.delete());
    }
    return returns;
  }
}

module.exports = Collection;
<|endoftext|>


<commit_before>'use strict';

/**
 * Allows for the extension of built-in Discord.js structures that are instantiated by {@link BaseManager Managers}.
 */
class Structures {
  constructor() {
    throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
  }

  /**
   * Retrieves a structure class.
   * @param {string} structure Name of the structure to retrieve
   * @returns {Function}
   */
  static get(structure) {
    if (typeof structure === 'string') return structures[structure];
    throw new TypeError(`"structure" argument must be a string (received ${typeof structure})`);
  }

  /**
   * Extends a structure.
   * <warn> Make sure to extend all structures before instantiating your client.
   * Extending after doing so may not work as expected. </warn>
   * @param {string} structure Name of the structure class to extend
   * @param {Function} extender Function that takes the base class to extend as its only parameter and returns the
   * extended class/prototype
   * @returns {Function} Extended class/prototype returned from the extender
   * @example
   * const { Structures } = require('discord.js');
   *
   * Structures.extend('Guild', Guild => {
   *   class CoolGuild extends Guild {
   *     constructor(client, data) {
   *       super(client, data);
   *       this.cool = true;
   *     }
   *   }
   *
   *   return CoolGuild;
   * });
   */
  static extend(structure, extender) {
    if (!structures[structure]) throw new RangeError(`"${structure}" is not a valid extensible structure.`);
    if (typeof extender !== 'function') {
      const received = `(received ${typeof extender})`;
      throw new TypeError(
        `"extender" argument must be a function that returns the extended structure class/prototype ${received}.`,
      );
    }

    const extended = extender(structures[structure]);
    if (typeof extended !== 'function') {
      const received = `(received ${typeof extended})`;
      throw new TypeError(`The extender function must return the extended structure class/prototype ${received}.`);
    }

    if (!(extended.prototype instanceof structures[structure])) {
      const prototype = Object.getPrototypeOf(extended);
      const received = `${extended.name || 'unnamed'}${prototype.name ? ` extends ${prototype.name}` : ''}`;
      throw new Error(
        'The class/prototype returned from the extender function must extend the existing structure class/prototype' +
          ` (received function ${received}; expected extension of ${structures[structure].name}).`,
      );
    }

    structures[structure] = extended;
    return extended;
  }
}

const structures = {
  GuildEmoji: require('../structures/GuildEmoji'),
  DMChannel: require('../structures/DMChannel'),
  TextChannel: require('../structures/TextChannel'),
  VoiceChannel: require('../structures/VoiceChannel'),
  CategoryChannel: require('../structures/CategoryChannel'),
  NewsChannel: require('../structures/NewsChannel'),
  StoreChannel: require('../structures/StoreChannel'),
  GuildMember: require('../structures/GuildMember'),
  Guild: require('../structures/Guild'),
  Message: require('../structures/Message'),
  MessageReaction: require('../structures/MessageReaction'),
  Presence: require('../structures/Presence').Presence,
  ClientPresence: require('../structures/ClientPresence'),
  VoiceState: require('../structures/VoiceState'),
  Role: require('../structures/Role'),
  User: require('../structures/User'),
};

module.exports = Structures;
<commit_msg>docs(Structures): add ExtendableStructure typedef (#3908)<commit_after>'use strict';

/**
 * An extendable structure:
 * * **`GuildEmoji`**
 * * **`DMChannel`**
 * * **`TextChannel`**
 * * **`VoiceChannel`**
 * * **`CategoryChannel`**
 * * **`NewsChannel`**
 * * **`StoreChannel`**
 * * **`GuildMember`**
 * * **`Guild`**
 * * **`Message`**
 * * **`MessageReaction`**
 * * **`Presence`**
 * * **`ClientPresence`**
 * * **`VoiceState`**
 * * **`Role`**
 * * **`User`**
 * @typedef {string} ExtendableStructure
 */

/**
 * Allows for the extension of built-in Discord.js structures that are instantiated by {@link BaseManager Managers}.
 */
class Structures {
  constructor() {
    throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
  }

  /**
   * Retrieves a structure class.
   * @param {string} structure Name of the structure to retrieve
   * @returns {Function}
   */
  static get(structure) {
    if (typeof structure === 'string') return structures[structure];
    throw new TypeError(`"structure" argument must be a string (received ${typeof structure})`);
  }

  /**
   * Extends a structure.
   * <warn> Make sure to extend all structures before instantiating your client.
   * Extending after doing so may not work as expected. </warn>
   * @param {ExtendableStructure} structure Name of the structure class to extend
   * @param {Function} extender Function that takes the base class to extend as its only parameter and returns the
   * extended class/prototype
   * @returns {Function} Extended class/prototype returned from the extender
   * @example
   * const { Structures } = require('discord.js');
   *
   * Structures.extend('Guild', Guild => {
   *   class CoolGuild extends Guild {
   *     constructor(client, data) {
   *       super(client, data);
   *       this.cool = true;
   *     }
   *   }
   *
   *   return CoolGuild;
   * });
   */
  static extend(structure, extender) {
    if (!structures[structure]) throw new RangeError(`"${structure}" is not a valid extensible structure.`);
    if (typeof extender !== 'function') {
      const received = `(received ${typeof extender})`;
      throw new TypeError(
        `"extender" argument must be a function that returns the extended structure class/prototype ${received}.`,
      );
    }

    const extended = extender(structures[structure]);
    if (typeof extended !== 'function') {
      const received = `(received ${typeof extended})`;
      throw new TypeError(`The extender function must return the extended structure class/prototype ${received}.`);
    }

    if (!(extended.prototype instanceof structures[structure])) {
      const prototype = Object.getPrototypeOf(extended);
      const received = `${extended.name || 'unnamed'}${prototype.name ? ` extends ${prototype.name}` : ''}`;
      throw new Error(
        'The class/prototype returned from the extender function must extend the existing structure class/prototype' +
          ` (received function ${received}; expected extension of ${structures[structure].name}).`,
      );
    }

    structures[structure] = extended;
    return extended;
  }
}

const structures = {
  GuildEmoji: require('../structures/GuildEmoji'),
  DMChannel: require('../structures/DMChannel'),
  TextChannel: require('../structures/TextChannel'),
  VoiceChannel: require('../structures/VoiceChannel'),
  CategoryChannel: require('../structures/CategoryChannel'),
  NewsChannel: require('../structures/NewsChannel'),
  StoreChannel: require('../structures/StoreChannel'),
  GuildMember: require('../structures/GuildMember'),
  Guild: require('../structures/Guild'),
  Message: require('../structures/Message'),
  MessageReaction: require('../structures/MessageReaction'),
  Presence: require('../structures/Presence').Presence,
  ClientPresence: require('../structures/ClientPresence'),
  VoiceState: require('../structures/VoiceState'),
  Role: require('../structures/Role'),
  User: require('../structures/User'),
};

module.exports = Structures;
<|endoftext|>


<commit_before>
/** This class manages listeners for given events, for a variable number of arguments.
 *
 *  It holds a map from event names to listeners. The event names can be managed
 *  through add/removeListenerTypes() and isListenerType(). Also derived classes
 *  may define a property "listenerTypes", that will be automatically parsed during
 *  the Observable's constructor.
 *
 *  To register an event, addListener() should be called with the associated event
 *  name and a callback method.
 *
 *  All listeners of an event type can be called with notifyListeners(), which expects the
 *  corresponding event name.
 */
XMOT.util.Observable = new XMOT.Class({

    /**
     *  @this {XMOT.util.Observable}
     *
     *  @param listenerTypes a single name or an array of names for
     *        listener types
     */
    initialize: function()
    {
        /** @private */
        this._listeners = {};
        /** @private */
        this._listenerTypes = {};

        // initialize types from derived classes
        if(this.listenerTypes)
            this.addListenerTypes(this.listenerTypes);
    },

    /** Remembers the given (array of) event name as valid event names.
     *
     *  @this {XMOT.util.Observable}
     */
    addListenerTypes: function(listenerTypes)
    {
        if(!listenerTypes)
            return;

        if(listenerTypes.constructor == Array)
        {
            for(var i = 0; i < listenerTypes.length; i++)
            {
                var type = listenerTypes[i];
                if(this._listenerTypes[type] === true)
                    throw "XMOT.util.Observable: type already registered: '" + type + "'!";

                this._listenerTypes[type] = true;
            }
        }
        else if(this._listenerTypes[listenerTypes] === true)
        {
            throw "XMOT.util.Observable: type already registered: '" + listenerTypes + "'!";
        }
        else
            this._listenerTypes[listenerTypes] = true;
    },

    /** Remove the given listener types from the array. The listeners will not be
     *  removed!
     *
     *  @this {XMOT.util.Observable}
     */
    removeListenerTypes: function(listenerTypes)
    {
        if(!listenerTypes)
            return;

        if(listenerTypes.constructor == Array)
        {
            for(var i = 0; i < listenerTypes.length; i++)
                this._listenerTypes[listenerTypes[i]] = false;
        }
        else
            this._listenerTypes[listenerTypes] = false;
    },

    /** Add a listener for the given event type
     *
     *  @this {XMOT.util.Observable}
     *
     *  @param {string} evtname
     *  @param {function()} listener
     */
    addListener: function(evtname, listener)
    {
        if(this.isListenerType(evtname))
        {
            if(!this._listeners[evtname])
                this._listeners[evtname] = [];

            this._listeners[evtname].push(listener);
        }
    },

    /** Remove first occurence of given element.
     *
     *  @this {XMOT.util.Observable}
     *  @param {string} evtname
     *  @param {function()} listener
     */
    removeListener: function(evtname, listener)
    {
        if(this.isListenerType(evtname))
        {
            if(!this._listeners[evtname])
                return;

            for(var i = 0; i < this._listeners[evtname].length; i++)
            {
                if(this._listeners[evtname][i] === listener)
                {
                    this._listeners[evtname].slice(i, 1);
                    return;
                }
            }
        }
    },

    /** Notifies all listeners. Arguments can be given to this function that get
     *     forwarded to each listener.
     *
     *  @this {XMOT.util.Observable}
     *  @param {string} evtname
     */
    notifyListeners: function(evtname)
    {
        if(this.isListenerType(evtname)
        && this._listeners[evtname])
        {
            var args = Array.prototype.slice.call(arguments);
            for(var i = 0; i < this._listeners[evtname].length; i++)
                this._listeners[evtname][i].apply(this, args.slice(1));
        }
    },

    /** Returns whether this listener manager manages the given event name.
     *
     *  @this {XMOT.util.Observable}
     *  @param {string} evtname
     *  @return {boolean} true if evtname is registered as a listener type.
     */
    isListenerType: function(evtname)
    {
        return (this._listenerTypes[evtname] === true);
    }
});
<commit_msg>observable: removed incorrect comment<commit_after>
/** This class manages listeners for given events, for a variable number of arguments.
 *
 *  It holds a map from event names to listeners. The event names can be managed
 *  through add/removeListenerTypes() and isListenerType(). Also derived classes
 *  may define a property "listenerTypes", that will be automatically parsed during
 *  the Observable's constructor.
 *
 *  To register an event, addListener() should be called with the associated event
 *  name and a callback method.
 *
 *  All listeners of an event type can be called with notifyListeners(), which expects the
 *  corresponding event name.
 */
XMOT.util.Observable = new XMOT.Class({

    /**
     *  @this {XMOT.util.Observable}
     */
    initialize: function()
    {
        /** @private */
        this._listeners = {};
        /** @private */
        this._listenerTypes = {};

        // initialize types from derived classes
        if(this.listenerTypes)
            this.addListenerTypes(this.listenerTypes);
    },

    /** Remembers the given (array of) event name as valid event names.
     *
     *  @this {XMOT.util.Observable}
     */
    addListenerTypes: function(listenerTypes)
    {
        if(!listenerTypes)
            return;

        if(listenerTypes.constructor == Array)
        {
            for(var i = 0; i < listenerTypes.length; i++)
            {
                var type = listenerTypes[i];
                if(this._listenerTypes[type] === true)
                    throw "XMOT.util.Observable: type already registered: '" + type + "'!";

                this._listenerTypes[type] = true;
            }
        }
        else if(this._listenerTypes[listenerTypes] === true)
        {
            throw "XMOT.util.Observable: type already registered: '" + listenerTypes + "'!";
        }
        else
            this._listenerTypes[listenerTypes] = true;
    },

    /** Remove the given listener types from the array. The listeners will not be
     *  removed!
     *
     *  @this {XMOT.util.Observable}
     */
    removeListenerTypes: function(listenerTypes)
    {
        if(!listenerTypes)
            return;

        if(listenerTypes.constructor == Array)
        {
            for(var i = 0; i < listenerTypes.length; i++)
                this._listenerTypes[listenerTypes[i]] = false;
        }
        else
            this._listenerTypes[listenerTypes] = false;
    },

    /** Add a listener for the given event type
     *
     *  @this {XMOT.util.Observable}
     *
     *  @param {string} evtname
     *  @param {function()} listener
     */
    addListener: function(evtname, listener)
    {
        if(this.isListenerType(evtname))
        {
            if(!this._listeners[evtname])
                this._listeners[evtname] = [];

            this._listeners[evtname].push(listener);
        }
    },

    /** Remove first occurence of given element.
     *
     *  @this {XMOT.util.Observable}
     *  @param {string} evtname
     *  @param {function()} listener
     */
    removeListener: function(evtname, listener)
    {
        if(this.isListenerType(evtname))
        {
            if(!this._listeners[evtname])
                return;

            for(var i = 0; i < this._listeners[evtname].length; i++)
            {
                if(this._listeners[evtname][i] === listener)
                {
                    this._listeners[evtname].slice(i, 1);
                    return;
                }
            }
        }
    },

    /** Notifies all listeners. Arguments can be given to this function that get
     *     forwarded to each listener.
     *
     *  @this {XMOT.util.Observable}
     *  @param {string} evtname
     */
    notifyListeners: function(evtname)
    {
        if(this.isListenerType(evtname)
        && this._listeners[evtname])
        {
            var args = Array.prototype.slice.call(arguments);
            for(var i = 0; i < this._listeners[evtname].length; i++)
                this._listeners[evtname][i].apply(this, args.slice(1));
        }
    },

    /** Returns whether this listener manager manages the given event name.
     *
     *  @this {XMOT.util.Observable}
     *  @param {string} evtname
     *  @return {boolean} true if evtname is registered as a listener type.
     */
    isListenerType: function(evtname)
    {
        return (this._listenerTypes[evtname] === true);
    }
});
<|endoftext|>


<commit_before>import * as $j from 'jquery';
import { isEmpty, getGameConfig } from '../script';

export class GameLog {
	constructor(id, game) {
		this.game = game;
		this.data = [];
		this.playing = false;
		this.timeCursor = -1;
		// Set this to null so we can properly decide between form based config or log based config.
		this.gameConfig = null;
	}

	reset() {
		this.data = [];
		this.playing = false;
		this.timeCursor = -1;
		this.gameConfig = null;
	}

	add(action) {
		this.data.push(action);
	}

	config(config) {
		let game = this.game;

		if (game.gameState != 'initialized') {
			alert('To set the game config, you need to be in the setup screen');
		} else {
			game.loadGame(config);
			this.gameConfig = config;

			// TODO: We should be able to initiate this w/o manipulating the DOM -- However,
			// currently "random" BG is processed on Submit. -- ktiedt
			let btn = $j('#startButton');
			if (btn.length === 1) {
				btn.click();
			}
		}
	}

	play(log) {
		let game = this.game,
			config,
			data;

		if (typeof log == 'object' && !log.length) {
			data = log.log;
			config = log.config;
			this.data = data;
			return this.config(config);
		} else if (typeof log == 'string') {
			let results = log.match(/^AB-(dev|[0-9.]+):(.+)$/);
			if (results) {
				log = JSON.parse(atob(results[2]));
				return this.play(log);
			}
		}

		if (log) {
			this.data = log;
		}

		let fun = () => {
			this.timeCursor++;

			if (game.debugMode) {
				console.log(this.timeCursor + '/' + this.data.length);
			}

			if (this.timeCursor > this.data.length - 1) {
				// game.activeCreature.queryMove(); // Avoid bug // called twice breaks opening UI. May need to revisit.
				return;
			}

			let interval = setInterval(() => {
				if (!game.freezedInput && !game.turnThrottle) {
					clearInterval(interval);
					game.activeCreature.queryMove();
					game.action(this.data[this.timeCursor], {
						callback: fun,
					});
				}
			}, 100);
		};

		fun();
	}

	next() {
		let game = this.game;

		if (game.freezedInput || game.turnThrottle) {
			return false;
		}

		this.timeCursor++;
		if (game.debugMode) {
			console.log(this.timeCursor + '/' + this.data.length);
		}

		if (this.timeCursor > this.data.length - 1) {
			game.activeCreature.queryMove(); // Avoid bug
			return;
		}

		let interval = setInterval(() => {
			if (!game.freezedInput && !game.turnThrottle) {
				clearInterval(interval);
				game.activeCreature.queryMove(); // Avoid bug
				game.action(this.data[this.timeCursor], {
					callback: function () {
						game.activeCreature.queryMove();
					},
				});
			}
		}, 100);
	}

	get(state) {
		let config = isEmpty(this.gameConfig) ? getGameConfig() : this.gameConfig,
			dict = {
				config: config,
				log: this.data,
			},
			json = JSON.stringify(dict),
			hash = 'AB-' + this.game.version + ':' + btoa(JSON.stringify(dict)),
			output,
			strOutput;

		let today = new Date().toISOString().slice(0, 10);
		let fileName = `AB-${this.game.version}:${today}`;

		switch (state) {
			case 'json':
				output = dict;
				strOutput = json;
				break;
			case 'save':
				// Do not allow this to happen more than once per second.
				if (this._debounce) {
					return;
				}

				this.saveFile(JSON.stringify(dict.log), `${fileName}.AB`);
				break;
			case 'hash':
				output = hash;
				strOutput = hash;
				break;
			case 'simple':
			default:
				output = `AB.restoreGame('${hash}')`;
				strOutput = output;
		}

		console.log('GameData: ' + strOutput);
		return output;
	}

	saveFile(data, fileName) {
		// Set a trap to block consecutive calls within one second.
		this._debounce = new Date().valueOf();
		let a = document.createElement('a');
		let file = new Blob([data]);
		let url = URL.createObjectURL(file);
		a.href = url;
		a.download = fileName;
		document.body.appendChild(a);
		a.click();
		setTimeout(() => {
			document.body.removeChild(a);
			window.URL.revokeObjectURL(url);
			// Remove trap to allow future save calls.
			this._debounce = null;
		}, 1000);
	}
}
<commit_msg>add config data to saved log file<commit_after>import * as $j from 'jquery';
import { isEmpty, getGameConfig } from '../script';

export class GameLog {
	constructor(id, game) {
		this.game = game;
		this.data = [];
		this.playing = false;
		this.timeCursor = -1;
		// Set this to null so we can properly decide between form based config or log based config.
		this.gameConfig = null;
	}

	reset() {
		this.data = [];
		this.playing = false;
		this.timeCursor = -1;
		this.gameConfig = null;
	}

	add(action) {
		this.data.push(action);
	}

	config(config) {
		let game = this.game;

		if (game.gameState != 'initialized') {
			alert('To set the game config, you need to be in the setup screen');
		} else {
			game.loadGame(config);
			this.gameConfig = config;

			// TODO: We should be able to initiate this w/o manipulating the DOM -- However,
			// currently "random" BG is processed on Submit. -- ktiedt
			let btn = $j('#startButton');
			if (btn.length === 1) {
				btn.click();
			}
		}
	}

	play(log) {
		let game = this.game,
			config,
			data;

		if (typeof log == 'object' && !log.length) {
			data = log.log;
			config = log.config;
			this.data = data;
			return this.config(config);
		} else if (typeof log == 'string') {
			let results = log.match(/^AB-(dev|[0-9.]+):(.+)$/);
			if (results) {
				log = JSON.parse(atob(results[2]));
				return this.play(log);
			}
		}

		if (log) {
			this.data = log;
		}

		let fun = () => {
			this.timeCursor++;

			if (game.debugMode) {
				console.log(this.timeCursor + '/' + this.data.length);
			}

			if (this.timeCursor > this.data.length - 1) {
				// game.activeCreature.queryMove(); // Avoid bug // called twice breaks opening UI. May need to revisit.
				return;
			}

			let interval = setInterval(() => {
				if (!game.freezedInput && !game.turnThrottle) {
					clearInterval(interval);
					game.activeCreature.queryMove();
					game.action(this.data[this.timeCursor], {
						callback: fun,
					});
				}
			}, 100);
		};

		fun();
	}

	next() {
		let game = this.game;

		if (game.freezedInput || game.turnThrottle) {
			return false;
		}

		this.timeCursor++;
		if (game.debugMode) {
			console.log(this.timeCursor + '/' + this.data.length);
		}

		if (this.timeCursor > this.data.length - 1) {
			game.activeCreature.queryMove(); // Avoid bug
			return;
		}

		let interval = setInterval(() => {
			if (!game.freezedInput && !game.turnThrottle) {
				clearInterval(interval);
				game.activeCreature.queryMove(); // Avoid bug
				game.action(this.data[this.timeCursor], {
					callback: function () {
						game.activeCreature.queryMove();
					},
				});
			}
		}, 100);
	}

	get(state) {
		let config = isEmpty(this.gameConfig) ? getGameConfig() : this.gameConfig,
			dict = {
				config: config,
				log: this.data,
			},
			json = JSON.stringify(dict),
			hash = 'AB-' + this.game.version + ':' + btoa(JSON.stringify(dict)),
			output,
			strOutput;

		let today = new Date().toISOString().slice(0, 10);
		let fileName = `AB-${this.game.version}:${today}`;

		switch (state) {
			case 'json':
				output = dict;
				strOutput = json;
				break;
			case 'save':
				// Do not allow this to happen more than once per second.
				if (this._debounce) {
					return;
				}

				this.saveFile(JSON.stringify(dict), `${fileName}.AB`);
				break;
			case 'hash':
				output = hash;
				strOutput = hash;
				break;
			case 'simple':
			default:
				output = `AB.restoreGame('${hash}')`;
				strOutput = output;
		}

		console.log('GameData: ' + strOutput);
		return output;
	}

	saveFile(data, fileName) {
		// Set a trap to block consecutive calls within one second.
		this._debounce = new Date().valueOf();
		let a = document.createElement('a');
		let file = new Blob([data]);
		let url = URL.createObjectURL(file);
		a.href = url;
		a.download = fileName;
		document.body.appendChild(a);
		a.click();
		setTimeout(() => {
			document.body.removeChild(a);
			window.URL.revokeObjectURL(url);
			// Remove trap to allow future save calls.
			this._debounce = null;
		}, 1000);
	}
}
<|endoftext|>


<commit_before>/**
 * Created by Amar on 21.11.2016.
 */

"use strict";

class SceneInit {

    constructor(domtarget = "anchart3d",fov = 45,camera,scene,controls,renderer,INTERSECTED)
    {
        this.domtarget = domtarget;
        this.camera = camera;
        this.scene = scene;
        this.controls = controls;
        this.renderer = renderer;
        this.fov = fov;
        this.mouse = new THREE.Vector2();
        this.INTERSECTED = INTERSECTED;
        this.raycaster = new THREE.Raycaster();

    }

    initScene() {
        this.camera = new THREE.PerspectiveCamera(this.fov, window.innerWidth / window.innerHeight, 1, 1000);
        this.camera.position.z = 15;

        this.controls = new THREE.TrackballControls( this.camera );
        this.controls.addEventListener('change', this.render.bind(this));

        this.scene = new THREE.Scene();

        //specify a canvas which is already created in the HTML file and tagged by an id        //aliasing enabled
        this.renderer = new THREE.WebGLRenderer({canvas: document.getElementById(this.domtarget) , antialias: true});
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(this.renderer.domElement);

        //ambient light which is for the whole scene
        let ambientLight = new THREE.AmbientLight(0xffffff, 0.7);
        ambientLight.castShadow = false;
        this.scene.add(ambientLight);

        //spot light which is illuminating the chart directly
        let spotLight = new THREE.SpotLight(0xffffff, 0.55);
        spotLight.castShadow = true;
        spotLight.position.set(0,40,10);
        this.scene.add(spotLight);

        document.addEventListener('mousedown', this.onDocumentMouseAction.bind(this), false);
        document.addEventListener('mousemove', this.onDocumentMouseAction.bind(this), false);
        document.ondblclick = this.onDocumentDblClick.bind(this);

        //if window resizes
        window.addEventListener('resize', this.onWindowResize.bind(this) , false);
    }

    animate(){
        requestAnimationFrame( this.animate.bind(this) );
        this.render();
        this.controls.update();
    }

    render(){
        this.renderer.render( this.scene, this.camera );
    }

    onWindowResize() {
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(window.innerWidth, window.innerHeight);
    }

    findIntersections(event) {

        event.preventDefault();

        this.mouse.x = ( event.clientX / this.renderer.domElement.clientWidth ) * 2 - 1;
        this.mouse.y = - ( event.clientY / this.renderer.domElement.clientHeight ) * 2 + 1;
        this.raycaster.setFromCamera( this.mouse, this.camera );
        //search for our object by name which we declared before and return it
        return this.raycaster.intersectObjects(this.scene.getObjectByName("groupedPieChart", true).children);
    }

    onDocumentMouseAction(event){
        //call function which finds intersected objects
        let intersects = this.findIntersections(event);

        if (intersects[0] !== undefined && event.type === "mousedown") {//if the event type is a mouse click (one click)
            //print percentage of the clicked section + the name of the object assigned in the 'create3DPieChart' function
            //intersects[0] because we want the first intersected object and every other object which may lies in the background is unnecessary
            console.log(intersects[0].object);
            document.getElementById("details").innerHTML = intersects[0].object.details;
        }
        else if (intersects[0] !== undefined && event.type == "mousemove") {//if the event type is a mouse move (hover)

            if ( this.INTERSECTED != intersects[ 0 ].object ) {
                if ( this.INTERSECTED ) this.INTERSECTED.material.emissive.setHex( this.INTERSECTED.currentHex );
                this.INTERSECTED = intersects[ 0 ].object;
                this.currentHex = this.INTERSECTED.material.emissive.getHex();
                this.INTERSECTED.material.emissive.setHex(0xa9a8a8);
            }
        }
        else {
            if ( this.INTERSECTED ) this.INTERSECTED.material.emissive.setHex( this.INTERSECTED.currentHex );
            this.INTERSECTED = null;
        }

    }

    onDocumentDblClick() {
        //IMPLEMENT DOUBLE CLICK FUNCTION HERE
    }

}

//export {SceneInit}<commit_msg>added label on mousehover<commit_after>/**
 * Created by Amar on 21.11.2016.
 */

"use strict";

class SceneInit {

    constructor(domtarget = "anchart3d",fov = 45,camera,scene,controls,renderer,INTERSECTED,canvas,context,texture,spriteMat)
    {
        this.domtarget = domtarget;
        this.camera = camera;
        this.scene = scene;
        this.controls = controls;
        this.renderer = renderer;
        this.fov = fov;
        this.mouse = new THREE.Vector2();
        this.INTERSECTED = INTERSECTED;
        this.raycaster = new THREE.Raycaster();
        this.cavas = canvas;
        this.context = context;
        this.texture = texture;
        this.spriteMat = spriteMat;

    }

    initScene() {
        this.camera = new THREE.PerspectiveCamera(this.fov, window.innerWidth / window.innerHeight, 1, 1000);
        this.camera.position.z = 15;

        this.controls = new THREE.TrackballControls( this.camera );
        this.controls.addEventListener('change', this.render.bind(this));

        this.scene = new THREE.Scene();

        //specify a canvas which is already created in the HTML file and tagged by an id        //aliasing enabled
        this.renderer = new THREE.WebGLRenderer({canvas: document.getElementById(this.domtarget) , antialias: true});
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(this.renderer.domElement);

        //ambient light which is for the whole scene
        let ambientLight = new THREE.AmbientLight(0xffffff, 0.7);
        ambientLight.castShadow = false;
        this.scene.add(ambientLight);

        //spot light which is illuminating the chart directly
        let spotLight = new THREE.SpotLight(0xffffff, 0.55);
        spotLight.castShadow = true;
        spotLight.position.set(0,40,10);
        this.scene.add(spotLight);

        /////// draw text on canvas /////////
        // create a canvas element
        this.canvas = document.createElement('canvas');
        this.context = this.canvas.getContext('2d');
        this.context.font = "Bold 20px Arial";
        this.context.fillStyle = "rgba(0,0,0,0.95)";

        // canvas contents will be used for a texture
        this.texture = new THREE.Texture(this.canvas);
        this.texture.needsUpdate = true;

        ////////////////////////////////////////

        this.spriteMat = new THREE.SpriteMaterial( { map: this.texture /*, useScreenCoordinates: true*/ } );

        this.sprite = new THREE.Sprite( this.spriteMat );
        this.sprite.scale.set(200,100,1.0);
        this.scene.add( this.sprite );
        //////////////////////////////////////////

        document.addEventListener('mousedown', this.onDocumentMouseAction.bind(this), false);
        document.addEventListener('mousemove', this.onDocumentMouseAction.bind(this), false);
        document.ondblclick = this.onDocumentDblClick.bind(this);

        //if window resizes
        window.addEventListener('resize', this.onWindowResize.bind(this) , false);
    }

    animate(){
        requestAnimationFrame( this.animate.bind(this) );
        this.render();
        this.controls.update();
    }

    render(){
        this.renderer.render( this.scene, this.camera );
    }

    onWindowResize() {
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(window.innerWidth, window.innerHeight);
    }

    findIntersections(event) {

        this.mouse.x = ( event.clientX / this.renderer.domElement.clientWidth ) * 2 - 1;
        this.mouse.y = - ( event.clientY / this.renderer.domElement.clientHeight ) * 2 + 1;
        this.raycaster.setFromCamera( this.mouse, this.camera );

        //convert screen coordinates to world position
        let vector = new THREE.Vector3(this.mouse.x, this.mouse.y, 0.5);
        vector.unproject( this.camera );
        let dir = vector.sub( this.camera.position ).normalize();
        let distance =  this.camera.position.z / dir.z +500;
        let pos = this.camera.position.clone().add( dir.multiplyScalar( distance ) );
        //set the label at the mouse position
        this.sprite.position.copy(pos);

        //search for our object by name which we declared before and return it
        return this.raycaster.intersectObjects(this.scene.getObjectByName("groupedPieChart", true).children);
    }

    onDocumentMouseAction(event){
        //call function which finds intersected objects
        let intersects = this.findIntersections(event);

        if (intersects[0] !== undefined && event.type === "mousedown") {//if the event type is a mouse click (one click)
            //print percentage of the clicked section + the name of the object assigned in the 'create3DPieChart' function
            //intersects[0] because we want the first intersected object and every other object which may lies in the background is unnecessary
            console.log(intersects[0].object.name);
            document.getElementById("details").innerHTML = intersects[0].object.details;
        }
        else if (intersects[0] !== undefined && event.type == "mousemove") {//if the event type is a mouse move (hover)

            if ( this.INTERSECTED != intersects[ 0 ].object ) {
                if ( this.INTERSECTED ) this.INTERSECTED.material.emissive.setHex( this.INTERSECTED.currentHex );
                this.INTERSECTED = intersects[ 0 ].object;
                this.currentHex = this.INTERSECTED.material.emissive.getHex();
                this.INTERSECTED.material.emissive.setHex(0xa9a8a8);

                // update text, if it has a "name" field.
                if ( intersects[ 0 ].object.name )
                {
                    this.context.clearRect(0,0,640,480);
                    let message = intersects[ 0 ].object.name;
                    let metrics = this.context.measureText(message);
                    let width = metrics.width;
                    this.context.fillStyle = "rgba(0,0,0,0.95)"; // black border
                    this.context.fillRect( 0,0, width+8,20+8);
                    this.context.fillStyle = "rgba(255,255,255,0.95)"; // white filler
                    this.context.fillRect( 2,2, width+4,20+4 );
                    this.context.fillStyle = "rgba(0,0,0,1)"; // text color
                    this.context.fillText( message, 4,20 );
                    this.texture.needsUpdate = true;
                }
                else
                {
                    this.context.clearRect(0,0,300,300);
                    this.texture.needsUpdate = true;
                }

            }
        }
        else {
            if ( this.INTERSECTED ) this.INTERSECTED.material.emissive.setHex( this.INTERSECTED.currentHex );
            this.INTERSECTED = null;

            this.context.clearRect(0,0,300,300);
            this.texture.needsUpdate = true;
        }

    }

    onDocumentDblClick() {
        //IMPLEMENT DOUBLE CLICK FUNCTION HERE
    }

    /*
     makeTextSprite(message, fontsize) {
     let ctx, texture, sprite, spriteMaterial,
     canvas = document.createElement('canvas');
     ctx = canvas.getContext('2d');
     ctx.font = fontsize + "px Arial";

     // setting canvas width/height before ctx draw, else canvas is empty
     canvas.width = ctx.measureText(message).width;
     canvas.height = fontsize * 2; // fontsize * 1.5

     ctx.font = fontsize + "px Arial";
     ctx.fillStyle = "rgba(255,255,255,0.95)"; // white filler
     ctx.fillRect( 2, 2, canvas.width + 5, 20+4);
     ctx.fillStyle = "rgba(0,0,0,1)";
     ctx.fillText(message, 4, fontsize);

     texture = new THREE.Texture(canvas);
     texture.minFilter = THREE.LinearFilter; // NearestFilter;
     texture.needsUpdate = true;

     spriteMaterial = new THREE.SpriteMaterial({map : texture});
     sprite = new THREE.Sprite(spriteMaterial);
     return sprite;
     }
     */

}

//export {SceneInit}<|endoftext|>


<commit_before>import Promise from 'bluebird';
import config from 'config';
import {auth, Client, types as CassandraTypes} from 'dse-driver';
import {logger} from './logging';
import {lookupServiceAsync} from './lookup-service';
import {Filesystem} from 'fs'

/**
 * An array of CQL table strings to use for the schema.
 */
const schema = [
  // Keeps track of sample users added
  `
  CREATE TABLE IF NOT EXISTS users (
    userid uuid,
    PRIMARY KEY(userid)
  );`,

  // Keeps track of sample videos added
  `
  CREATE TABLE IF NOT EXISTS videos (
    videoid uuid,
    PRIMARY KEY (videoid)
  );`,

  // Keeps track of the available YouTube videos
  `
  CREATE TABLE IF NOT EXISTS youtube_videos (
    sourceid text,
    published_at timestamp,
    youtube_video_id text,
    name text,
    description text,
    used boolean,
    PRIMARY KEY (sourceid, published_at, youtube_video_id)
  ) WITH CLUSTERING ORDER BY (published_at DESC, youtube_video_id ASC);`
];

// Get cassandra configuration options
function getCassandraConfig() {
  const { keyspace, replication, dseUsername, dsePassword } = config.get('cassandra');
  return { keyspace, replication, dseUsername, dsePassword };
}

// Client promises by keyspace
const clientPromises = new Map();

/**
 * Gets a Cassandra client instance that is connected to the specified keyspace.
 */
export function getCassandraClientAsync(keyspace, dseUsername, dsePassword) {
  if (clientPromises.has(keyspace)) {
    return clientPromises.get(keyspace);
  }

  const promise = lookupServiceAsync('cassandra')
    .then(contactPoints => {
      let clientOpts = {
        contactPoints,
        queryOptions: {
          prepare: true,
          consistency: CassandraTypes.consistencies.localQuorum
        }
      };

      if (keyspace) {
        clientOpts.keyspace = keyspace;
      }

      /**
      * Check for both KILLRVIDEO_DSE_USERNAME and KILLRVIDEO_DSE_PASSWORD environment
      * variables.  If they both exist use the values set within them.  If not,
      * use default values for authentication.
      */
      if (dseUsername && dsePassword) {
        let passwordLength = dsePassword.length;
        logger.info('Using supplied DSE username: "' + dseUsername + '" and password: "***' + dsePassword.substring(passwordLength - 4, passwordLength) + '" from environment variables');

        // Use the values passed in from the config
        clientOpts.authProvider = new auth.DsePlainTextAuthProvider(dseUsername, dsePassword);

      } else {
        logger.info('No detected username/password combination was passed in. DSE cluster authentication method was NOT executed.');
      }

      let sslStat = process.env.KILLRVIDEO_ENABLE_SSL;
      logger.info(sslStat);

      if (sslStat === "true") {
        logger.info('SSL is configured to be on.');
        if (Filesystem.existsSync('cassandra.cert')) {
          clientOpts.sslOptions = {
            ca: [Filesystem.readFileSync('cassandra.cert')]
          };
          logger.info('Found cert, read file sync.')
        } else {
          logger.info('No cert found, SSL not enabled.')
        }
      } else if (sslStat === "false") {
        logger.info('SSL is configured to be off.')
      } else {
        logger.info('SSL is not configured, should it be set?')
      }

      // Create a client and promisify it
      let client = new Client(clientOpts);
      client = Promise.promisifyAll(client);

      // Connect and return the connected client
      return client.connectAsync().return(client);
    })
    .catch(err => {
      clientPromises.delete(keyspace);
      throw err;
    });

  clientPromises.set(keyspace, promise);
  return promise;
}
/**
 * Creates a keyspace in Cassandra if it doesn't already exist. Pass the name of the keyspace and the
 * string to be used as the REPLICATION setting (i.e. after WITH REPLIACTION = ...).
 */
function createKeyspaceIfNotExistsAsync(keyspace, replication, dseUsername, dsePassword) {
  // Create CQL
  const cql = `CREATE KEYSPACE IF NOT EXISTS ${keyspace} WITH REPLICATION = ${replication}`;

  // Get a client, then create the keyspace
  return getCassandraClientAsync(null, dseUsername, dsePassword).then(client => client.executeAsync(cql));
}
/**
 * Create the tables if they don't already exist.
 */
function createTablesAsync(client) {
  // Run each CQL statement in the schema array one at a time and then return the client
  return Promise.mapSeries(schema, cql => client.executeAsync(cql)).return(client);
}

// Singleton client instance for app
let clientInstance = null;

/**
 * Get a Cassandra client instance.
 */
export function getCassandraClient() {
  if (clientInstance == null) {
    throw new Error('No client instance found. Did you forget to call initCassandraAsync?');
  }
  return clientInstance;
}
/**
 * Initializes the Cassandra keyspace and schema needed.
 */
export async function initCassandraAsync() {
  // Create keyspace
  let config = getCassandraConfig();
  await createKeyspaceIfNotExistsAsync(config.keyspace, config.replication, config.dseUsername, config.dsePassword);

  // Create tables
  let client = await getCassandraClientAsync(config.keyspace, config.dseUsername, config.dsePassword);
  await createTablesAsync(client);

  // Save client instance
  clientInstance = client;
}
<commit_msg>Changed to let statement for filesystem.<commit_after>import Promise from 'bluebird';
import config from 'config';
import {auth, Client, types as CassandraTypes} from 'dse-driver';
import {logger} from './logging';
import {lookupServiceAsync} from './lookup-service';

/**
 * An array of CQL table strings to use for the schema.
 */
const schema = [
  // Keeps track of sample users added
  `
  CREATE TABLE IF NOT EXISTS users (
    userid uuid,
    PRIMARY KEY(userid)
  );`,

  // Keeps track of sample videos added
  `
  CREATE TABLE IF NOT EXISTS videos (
    videoid uuid,
    PRIMARY KEY (videoid)
  );`,

  // Keeps track of the available YouTube videos
  `
  CREATE TABLE IF NOT EXISTS youtube_videos (
    sourceid text,
    published_at timestamp,
    youtube_video_id text,
    name text,
    description text,
    used boolean,
    PRIMARY KEY (sourceid, published_at, youtube_video_id)
  ) WITH CLUSTERING ORDER BY (published_at DESC, youtube_video_id ASC);`
];

// Get cassandra configuration options
function getCassandraConfig() {
  const { keyspace, replication, dseUsername, dsePassword } = config.get('cassandra');
  return { keyspace, replication, dseUsername, dsePassword };
}

// Client promises by keyspace
const clientPromises = new Map();

/**
 * Gets a Cassandra client instance that is connected to the specified keyspace.
 */
export function getCassandraClientAsync(keyspace, dseUsername, dsePassword) {
  if (clientPromises.has(keyspace)) {
    return clientPromises.get(keyspace);
  }

  const promise = lookupServiceAsync('cassandra')
    .then(contactPoints => {
      let clientOpts = {
        contactPoints,
        queryOptions: {
          prepare: true,
          consistency: CassandraTypes.consistencies.localQuorum
        }
      };

      if (keyspace) {
        clientOpts.keyspace = keyspace;
      }

      /**
      * Check for both KILLRVIDEO_DSE_USERNAME and KILLRVIDEO_DSE_PASSWORD environment
      * variables.  If they both exist use the values set within them.  If not,
      * use default values for authentication.
      */
      if (dseUsername && dsePassword) {
        let passwordLength = dsePassword.length;
        logger.info('Using supplied DSE username: "' + dseUsername + '" and password: "***' + dsePassword.substring(passwordLength - 4, passwordLength) + '" from environment variables');

        // Use the values passed in from the config
        clientOpts.authProvider = new auth.DsePlainTextAuthProvider(dseUsername, dsePassword);

      } else {
        logger.info('No detected username/password combination was passed in. DSE cluster authentication method was NOT executed.');
      }

      let Filesystem = require("fs");
      let sslStat = process.env.KILLRVIDEO_ENABLE_SSL;
      logger.info(sslStat);

      if (sslStat === "true") {
        logger.info('SSL is configured to be on.');
        if (Filesystem.existsSync('cassandra.cert')) {
          clientOpts.sslOptions = {
            ca: [Filesystem.readFileSync('cassandra.cert')]
          };
          logger.info('Found cert, read file sync.')
        } else {
          logger.info('No cert found, SSL not enabled.')
        }
      } else if (sslStat === "false") {
        logger.info('SSL is configured to be off.')
      } else {
        logger.info('SSL is not configured, should it be set?')
      }

      // Create a client and promisify it
      let client = new Client(clientOpts);
      client = Promise.promisifyAll(client);

      // Connect and return the connected client
      return client.connectAsync().return(client);
    })
    .catch(err => {
      clientPromises.delete(keyspace);
      throw err;
    });

  clientPromises.set(keyspace, promise);
  return promise;
}
/**
 * Creates a keyspace in Cassandra if it doesn't already exist. Pass the name of the keyspace and the
 * string to be used as the REPLICATION setting (i.e. after WITH REPLIACTION = ...).
 */
function createKeyspaceIfNotExistsAsync(keyspace, replication, dseUsername, dsePassword) {
  // Create CQL
  const cql = `CREATE KEYSPACE IF NOT EXISTS ${keyspace} WITH REPLICATION = ${replication}`;

  // Get a client, then create the keyspace
  return getCassandraClientAsync(null, dseUsername, dsePassword).then(client => client.executeAsync(cql));
}
/**
 * Create the tables if they don't already exist.
 */
function createTablesAsync(client) {
  // Run each CQL statement in the schema array one at a time and then return the client
  return Promise.mapSeries(schema, cql => client.executeAsync(cql)).return(client);
}

// Singleton client instance for app
let clientInstance = null;

/**
 * Get a Cassandra client instance.
 */
export function getCassandraClient() {
  if (clientInstance == null) {
    throw new Error('No client instance found. Did you forget to call initCassandraAsync?');
  }
  return clientInstance;
}
/**
 * Initializes the Cassandra keyspace and schema needed.
 */
export async function initCassandraAsync() {
  // Create keyspace
  let config = getCassandraConfig();
  await createKeyspaceIfNotExistsAsync(config.keyspace, config.replication, config.dseUsername, config.dsePassword);

  // Create tables
  let client = await getCassandraClientAsync(config.keyspace, config.dseUsername, config.dsePassword);
  await createTablesAsync(client);

  // Save client instance
  clientInstance = client;
}
<|endoftext|>


<commit_before>export const defaultState = {
  contracts: {
    token: {},
    crowdsale: {addr:[], abiConstructor:[]},
    pricingStrategy: {addr:[], abiConstructor:[]},
    multisig: {},
    nullFinalizeAgent: {addr:[], abiConstructor:[]},
    finalizeAgent: {addr:[], abiConstructor:[]},
    tokenTransferProxy: {}
  },
  token: {
    name: '',
    ticker: '',
    supply: 0,
    decimals: '',
    reservedTokens: [],
    reservedTokensElements: [],
    reservedTokensInput: {dim: "tokens"}
  },
  crowdsale: [{
    startTime: '',
    endTime: '',
    walletAddress: '',
    supply: '',
    whitelist: [],
    whitelistElements: [],
    whitelistInput: {}
  }],
  pricingStrategy: [{rate: ''}],
  blockTimeGeneration: 17,
  compilerVersion: "0.4.11",
  optimized: true,
  contractName: "MintedTokenCappedCrowdsaleExt",
  contractType: "white-list-with-cap",
  contractTypes: {
    standard: "standard",
    capped: "capped",
    whitelistwithcap: "white-list-with-cap"
  }
}

export const defaultTiers = [{
  startTime: '',
  endTime: '',
  walletAddress: '',
  supply: '',
  whitelist: [],
  whitelistElements: [],
  whitelistInput: {}
}]

export const CONTRACT_TYPES = {
  standard: "standard",
  capped: "capped",
  whitelistwithcap: "white-list-with-cap"
}

export const TRUNC_TO_DECIMALS = {
  DECIMALS18: -18
}

export const GAS_PRICE = {
  SLOW: {
    ID: 'slow',
    PRICE: 5000000000,
    DESCRIPTION: 'Slow and Cheap (5 Gwei)'
  },
  NORMAL: {
    ID: 'normal',
    PRICE: 10000000000,
    DESCRIPTION: 'Normal (10 Gwei)'
  },
  FAST: {
    ID: 'fast',
    PRICE: 15000000000,
    DESCRIPTION: 'Fast and Expensive (15 Gwei)'
  },
  CUSTOM: {
    ID: 'custom',
    PRICE: 0,
    DESCRIPTION: 'Custom'
  }
}
export const UNKNOWN = "Unknown"
export const CHAINS = {
  UNKNOWN: 'Unknown',
  MAINNET: 'Mainnet',
  MORDEN: 'Morden',
  ROPSTEN: 'Ropsten',
  RINKEBY: 'Rinkeby',
  KOVAN: 'Kovan',
  ORACLES: 'Oracles dev test'
}

export const NAVIGATION_STEPS = {
  CROWDSALE_CONTRACT: 'Crowdsale Contract',
  TOKEN_SETUP: 'Token Setup',
  CROWDSALE_SETUP: 'Crowdsale Setup',
  PUBLISH: 'Publish',
  CROWDSALE_PAGE: 'Crowdsale Page'
}

export const VALIDATION_MESSAGES = {
  TIER: 'Please enter a valid tier name between 1-30 characters',
  NAME: 'Please enter a valid name between 1-30 characters',
  TICKER: 'Please enter a valid Ticker that is less than three characters',
  SUPPLY: 'Please enter a valid number greater than 0',
  DECIMALS: 'Please enter a number greater than or equal to zero',
  WALLET_ADDRESS: 'Please enter a valid address',
  START_TIME: 'Please enter a valid date later than now',
  END_TIME: 'Please enter a valid date later than start time',
  MULTIPLE_TIERS_START_TIME: 'Please enter a valid date not less than the end time of the previous tier',
  EDITED_END_TIME: 'Please enter a valid date later than start time and previous than start time of next tier',
  EDITED_START_TIME: 'Please enter a valid date later than now, less than end time and later than the end time of the previous tier',
  RATE: 'Please enter a valid number greater than 0'
}

export const TEXT_FIELDS = {
  NAME: 'Name',
  TICKER: 'Ticker',
  SUPPLY: 'Supply',
  DECIMALS: 'Decimals',
  RATE: 'Rate',
  WALLET_ADDRESS: 'Wallet Address',
  START_TIME: 'Start Time',
  END_TIME: 'End Time',
  CROWDSALE_SETUP_NAME: 'Crowdsale setup name',
  ADDRESS: 'Address',
  MIN: 'Min',
  MAX: 'Max',
  MINCAP: 'Investor min cap',
  DIMENSION: 'Dimension',
  VALUE: 'Value',
  MAX_CAP: 'Max cap',
  ALLOWMODIFYING: 'Allow modifying',
  DISABLEWHITELISTING: 'Disable whitelisting',
  GAS_PRICE: 'Gas Price'
}

export const VALIDATION_TYPES = {
  VALID: "VALIDATED",
  EMPTY: 'EMPTY',
  INVALID: 'INVALID'
}
const { VALID, EMPTY } = VALIDATION_TYPES

export const intitialStepTwoValidations = {
  validations: {
    name: EMPTY,
    decimals: EMPTY,
    ticker: EMPTY
  }
}

export const initialStepTwoValues = {
  token: {
    name: '',
    supply: 0,
    ticker: '',
    decimals: '',
    reservedTokens: [],
    reservedTokensElements: [],
    reservedTokensInput: {dim: "tokens"}
  }
}

export const intitialStepThreeValidations = {
  validations: [{
    tier: VALID,
    startTime: VALID,
    endTime: VALID,
    walletAddress: EMPTY,
    supply: VALID,
    rate: EMPTY
  }]
}

export const initialStepThreeValues = {
  crowdsale: [{
    tier: '',
    startTime: '',
    endTime: '',
    walletAddress: '',
    supply: ''
  }]
}

export const FILE_CONTENTS = {
  common: [
    { field: 'name', value: 'Token name: ', parent: 'tokenStore' },
    { field: 'ticker', value: 'Token ticker: ', parent: 'tokenStore' },
    { field: 'decimals', value: 'Token decimals: ', parent: 'tokenStore' },
    { field: 'walletAddress', value: 'Multisig wallet address: ', parent: 'tierStore' },
    { value: '*****************************', parent: 'none', fileValue: '' },
    { field: 'rate', value: 'Crowdsale rate: ', parent: 'tierStore' },
    { field: 'startTime', value: 'Crowdsale start time: ', parent: 'tierStore' },
    { field: 'endTime', value: 'Crowdsale end time: ', parent: 'tierStore' },
    { value: 'Compiler Version: ', parent: 'none', fileValue: '0.4.11' },
    { value: 'Is optimization enabled?: ', parent: 'none', fileValue: 'true' },
    { value: '*****************************', parent: 'none', fileValue: '' }
  ],
  files: {
    order: [
      'safeMathLib',
      'token',
      'pricingStrategy',
      'crowdsale',
      'nullFinalizeAgent',
      'finalizeAgent'
    ],
    safeMathLib: {
      name: 'SafeMathLibExt',
      txt: [
        { value: 'SafeMathLib library name: ', parent: 'none', fileValue: 'SafeMathLibExt' },
        { field: 'addr', value: 'SafeMathLib library address: ', parent: 'contracts', child: 'safeMathLib' },
        { value: '*****************************', parent: 'none', fileValue: '' },
        { field: 'abi', value: '****SafeMathLib contract ABI:**** \n\n', parent: 'contracts', child: 'safeMathLib' }
      ],
      sol: {
        field: 'src',
        value: '****SafeMathLib contract source:**** \n\n',
        parent: 'contracts',
        child: 'safeMathLib'
      }

    },
    token: {
      name: 'CrowdsaleTokenExt',
      txt: [
        { value: 'Token contract name: ', parent: 'none', fileValue: 'CrowdsaleTokenExt' },
        { field: 'addr', value: 'Token contract address: ', parent: 'contracts', child: 'token' },
        { value: '*****************************', parent: 'none', fileValue: '' },
        { field: 'abi', value: '****Token contract ABI:**** \n\n', parent: 'contracts', child: 'token' },
        {
          field: 'abiConstructor',
          value: '****Token contract ABI encoded constructor arguments',
          parent: 'contracts',
          child: 'token'
        }
      ],
      sol: { field: 'src', value: '****Token contract source:**** \n\n', parent: 'contracts', child: 'token' }

    },
    pricingStrategy: {
      name: 'FlatPricingExt',
      txt: [
        { value: 'Pricing strategy contract name: ', parent: 'none', fileValue: 'FlatPricingExt' },
        { field: 'addr', value: 'Pricing strategy contract address', parent: 'contracts', child: 'pricingStrategy' },
        { value: '*****************************', parent: 'none', fileValue: '' },
        {
          field: 'abi',
          value: '****Pricing strategy contract ABI:**** \n\n',
          parent: 'contracts',
          child: 'pricingStrategy'
        },
        {
          field: 'abiConstructor',
          value: '****Pricing strategy contract ABI encoded constructor arguments',
          parent: 'contracts',
          child: 'pricingStrategy'
        }
      ],
      sol: {
        field: 'src',
        value: '****Pricing strategy contract source:**** \n\n',
        parent: 'contracts',
        child: 'pricingStrategy'
      }

    },
    crowdsale: {
      name: 'MintedTokenCappedCrowdsaleExt',
      txt: [
        { value: 'Crowdsale contract name: ', parent: 'none', fileValue: 'MintedTokenCappedCrowdsaleExt' },
        { field: 'addr', value: 'Crowdsale contract address', parent: 'contracts', child: 'crowdsale' },
        { value: '*****************************', parent: 'none', fileValue: '' },
        { field: 'abi', value: '****Crowdsale contract ABI:**** \n\n', parent: 'contracts', child: 'crowdsale' },
        {
          field: 'abiConstructor',
          value: '****Crowdsale contract ABI encoded constructor arguments',
          parent: 'contracts',
          child: 'crowdsale'
        }
      ],
      sol: { field: 'src', value: '****Crowdsale contract source:**** \n\n', parent: 'contracts', child: 'crowdsale' }

    },
    nullFinalizeAgent: {
      name: 'NullFinalizeAgentExt',
      txt: [
        { value: 'Null finalize agent contract name: ', parent: 'none', fileValue: 'NullFinalizeAgentExt' },
        {
          field: 'addr',
          value: 'Null finalize agent contract address',
          parent: 'contracts',
          child: 'finalizeAgent'
        },
        { value: '*****************************', parent: 'none', fileValue: '' },
        {
          field: 'abi',
          value: '****Null Finalize agent contract ABI:**** \n\n',
          parent: 'contracts',
          child: 'nullFinalizeAgent'
        },
        {
          field: 'abiConstructor',
          value: '****Null Finalize agent contract ABI encoded constructor arguments',
          parent: 'contracts',
          child: 'finalizeAgent'
        }
      ],
      sol: {
        field: 'src',
        value: '****Null Finalize agent contract source:**** \n\n',
        parent: 'contracts',
        child: 'nullFinalizeAgent'
      }

    },
    finalizeAgent: {
      name: 'ReservedTokensFinalizeAgent',
      txt: [
        { value: 'Finalize agent contract name: ', parent: 'none', fileValue: 'ReservedTokensFinalizeAgent' },
        { field: 'addr', value: 'Finalize agent contract address', parent: 'contracts', child: 'finalizeAgent' },
        { value: '*****************************', parent: 'none', fileValue: '' },
        {
          field: 'abi',
          value: '****Finalize agent contract ABI:**** \n\n',
          parent: 'contracts',
          child: 'finalizeAgent'
        },
        {
          field: 'abiConstructor',
          value: '****Finalize agent contract ABI encoded constructor arguments',
          parent: 'contracts',
          child: 'finalizeAgent'
        }
      ],
      sol: {
        field: 'src',
        value: '****Finalize agent contract source:**** \n\n',
        parent: 'contracts',
        child: 'finalizeAgent'
      }

    }
  }
}

export const DOWNLOAD_NAME = 'icowizard'
export const DOWNLOAD_TYPE = {
  text: 'text/plain',
  blob: 'blob'
}

export const INVESTMENT_OPTIONS = {
  METAMASK: 'metamask',
  QR: 'qr'
}
export const TOAST = {
  TYPE: {
    ERROR: 'error',
    INFO: 'info',
    SUCCESS: 'warning'
  },
  MESSAGE: {
    TRANSACTION_FAILED: 'Transaction has failed, please retry',
    CONTRACT_DOWNLOAD_FAILED: 'Contract Download failed',
    CONTRACT_DOWNLOAD_SUCCESS: 'A file with contracts and metadata downloaded on your computer',
    FINALIZE_FAIL: 'Was not able to finalize Crowdsale. Please be sure that Crowdsale has ended already'
  },
  DEFAULT_OPTIONS: {
    position: 'top right',
    offset: '80px 14',
    time: 10000
  }
}
<commit_msg>Remove react-alert warning<commit_after>export const defaultState = {
  contracts: {
    token: {},
    crowdsale: {addr:[], abiConstructor:[]},
    pricingStrategy: {addr:[], abiConstructor:[]},
    multisig: {},
    nullFinalizeAgent: {addr:[], abiConstructor:[]},
    finalizeAgent: {addr:[], abiConstructor:[]},
    tokenTransferProxy: {}
  },
  token: {
    name: '',
    ticker: '',
    supply: 0,
    decimals: '',
    reservedTokens: [],
    reservedTokensElements: [],
    reservedTokensInput: {dim: "tokens"}
  },
  crowdsale: [{
    startTime: '',
    endTime: '',
    walletAddress: '',
    supply: '',
    whitelist: [],
    whitelistElements: [],
    whitelistInput: {}
  }],
  pricingStrategy: [{rate: ''}],
  blockTimeGeneration: 17,
  compilerVersion: "0.4.11",
  optimized: true,
  contractName: "MintedTokenCappedCrowdsaleExt",
  contractType: "white-list-with-cap",
  contractTypes: {
    standard: "standard",
    capped: "capped",
    whitelistwithcap: "white-list-with-cap"
  }
}

export const defaultTiers = [{
  startTime: '',
  endTime: '',
  walletAddress: '',
  supply: '',
  whitelist: [],
  whitelistElements: [],
  whitelistInput: {}
}]

export const CONTRACT_TYPES = {
  standard: "standard",
  capped: "capped",
  whitelistwithcap: "white-list-with-cap"
}

export const TRUNC_TO_DECIMALS = {
  DECIMALS18: -18
}

export const GAS_PRICE = {
  SLOW: {
    ID: 'slow',
    PRICE: 5000000000,
    DESCRIPTION: 'Slow and Cheap (5 Gwei)'
  },
  NORMAL: {
    ID: 'normal',
    PRICE: 10000000000,
    DESCRIPTION: 'Normal (10 Gwei)'
  },
  FAST: {
    ID: 'fast',
    PRICE: 15000000000,
    DESCRIPTION: 'Fast and Expensive (15 Gwei)'
  },
  CUSTOM: {
    ID: 'custom',
    PRICE: 0,
    DESCRIPTION: 'Custom'
  }
}
export const UNKNOWN = "Unknown"
export const CHAINS = {
  UNKNOWN: 'Unknown',
  MAINNET: 'Mainnet',
  MORDEN: 'Morden',
  ROPSTEN: 'Ropsten',
  RINKEBY: 'Rinkeby',
  KOVAN: 'Kovan',
  ORACLES: 'Oracles dev test'
}

export const NAVIGATION_STEPS = {
  CROWDSALE_CONTRACT: 'Crowdsale Contract',
  TOKEN_SETUP: 'Token Setup',
  CROWDSALE_SETUP: 'Crowdsale Setup',
  PUBLISH: 'Publish',
  CROWDSALE_PAGE: 'Crowdsale Page'
}

export const VALIDATION_MESSAGES = {
  TIER: 'Please enter a valid tier name between 1-30 characters',
  NAME: 'Please enter a valid name between 1-30 characters',
  TICKER: 'Please enter a valid Ticker that is less than three characters',
  SUPPLY: 'Please enter a valid number greater than 0',
  DECIMALS: 'Please enter a number greater than or equal to zero',
  WALLET_ADDRESS: 'Please enter a valid address',
  START_TIME: 'Please enter a valid date later than now',
  END_TIME: 'Please enter a valid date later than start time',
  MULTIPLE_TIERS_START_TIME: 'Please enter a valid date not less than the end time of the previous tier',
  EDITED_END_TIME: 'Please enter a valid date later than start time and previous than start time of next tier',
  EDITED_START_TIME: 'Please enter a valid date later than now, less than end time and later than the end time of the previous tier',
  RATE: 'Please enter a valid number greater than 0'
}

export const TEXT_FIELDS = {
  NAME: 'Name',
  TICKER: 'Ticker',
  SUPPLY: 'Supply',
  DECIMALS: 'Decimals',
  RATE: 'Rate',
  WALLET_ADDRESS: 'Wallet Address',
  START_TIME: 'Start Time',
  END_TIME: 'End Time',
  CROWDSALE_SETUP_NAME: 'Crowdsale setup name',
  ADDRESS: 'Address',
  MIN: 'Min',
  MAX: 'Max',
  MINCAP: 'Investor min cap',
  DIMENSION: 'Dimension',
  VALUE: 'Value',
  MAX_CAP: 'Max cap',
  ALLOWMODIFYING: 'Allow modifying',
  DISABLEWHITELISTING: 'Disable whitelisting',
  GAS_PRICE: 'Gas Price'
}

export const VALIDATION_TYPES = {
  VALID: "VALIDATED",
  EMPTY: 'EMPTY',
  INVALID: 'INVALID'
}
const { VALID, EMPTY } = VALIDATION_TYPES

export const intitialStepTwoValidations = {
  validations: {
    name: EMPTY,
    decimals: EMPTY,
    ticker: EMPTY
  }
}

export const initialStepTwoValues = {
  token: {
    name: '',
    supply: 0,
    ticker: '',
    decimals: '',
    reservedTokens: [],
    reservedTokensElements: [],
    reservedTokensInput: {dim: "tokens"}
  }
}

export const intitialStepThreeValidations = {
  validations: [{
    tier: VALID,
    startTime: VALID,
    endTime: VALID,
    walletAddress: EMPTY,
    supply: VALID,
    rate: EMPTY
  }]
}

export const initialStepThreeValues = {
  crowdsale: [{
    tier: '',
    startTime: '',
    endTime: '',
    walletAddress: '',
    supply: ''
  }]
}

export const FILE_CONTENTS = {
  common: [
    { field: 'name', value: 'Token name: ', parent: 'tokenStore' },
    { field: 'ticker', value: 'Token ticker: ', parent: 'tokenStore' },
    { field: 'decimals', value: 'Token decimals: ', parent: 'tokenStore' },
    { field: 'walletAddress', value: 'Multisig wallet address: ', parent: 'tierStore' },
    { value: '*****************************', parent: 'none', fileValue: '' },
    { field: 'rate', value: 'Crowdsale rate: ', parent: 'tierStore' },
    { field: 'startTime', value: 'Crowdsale start time: ', parent: 'tierStore' },
    { field: 'endTime', value: 'Crowdsale end time: ', parent: 'tierStore' },
    { value: 'Compiler Version: ', parent: 'none', fileValue: '0.4.11' },
    { value: 'Is optimization enabled?: ', parent: 'none', fileValue: 'true' },
    { value: '*****************************', parent: 'none', fileValue: '' }
  ],
  files: {
    order: [
      'safeMathLib',
      'token',
      'pricingStrategy',
      'crowdsale',
      'nullFinalizeAgent',
      'finalizeAgent'
    ],
    safeMathLib: {
      name: 'SafeMathLibExt',
      txt: [
        { value: 'SafeMathLib library name: ', parent: 'none', fileValue: 'SafeMathLibExt' },
        { field: 'addr', value: 'SafeMathLib library address: ', parent: 'contracts', child: 'safeMathLib' },
        { value: '*****************************', parent: 'none', fileValue: '' },
        { field: 'abi', value: '****SafeMathLib contract ABI:**** \n\n', parent: 'contracts', child: 'safeMathLib' }
      ],
      sol: {
        field: 'src',
        value: '****SafeMathLib contract source:**** \n\n',
        parent: 'contracts',
        child: 'safeMathLib'
      }

    },
    token: {
      name: 'CrowdsaleTokenExt',
      txt: [
        { value: 'Token contract name: ', parent: 'none', fileValue: 'CrowdsaleTokenExt' },
        { field: 'addr', value: 'Token contract address: ', parent: 'contracts', child: 'token' },
        { value: '*****************************', parent: 'none', fileValue: '' },
        { field: 'abi', value: '****Token contract ABI:**** \n\n', parent: 'contracts', child: 'token' },
        {
          field: 'abiConstructor',
          value: '****Token contract ABI encoded constructor arguments',
          parent: 'contracts',
          child: 'token'
        }
      ],
      sol: { field: 'src', value: '****Token contract source:**** \n\n', parent: 'contracts', child: 'token' }

    },
    pricingStrategy: {
      name: 'FlatPricingExt',
      txt: [
        { value: 'Pricing strategy contract name: ', parent: 'none', fileValue: 'FlatPricingExt' },
        { field: 'addr', value: 'Pricing strategy contract address', parent: 'contracts', child: 'pricingStrategy' },
        { value: '*****************************', parent: 'none', fileValue: '' },
        {
          field: 'abi',
          value: '****Pricing strategy contract ABI:**** \n\n',
          parent: 'contracts',
          child: 'pricingStrategy'
        },
        {
          field: 'abiConstructor',
          value: '****Pricing strategy contract ABI encoded constructor arguments',
          parent: 'contracts',
          child: 'pricingStrategy'
        }
      ],
      sol: {
        field: 'src',
        value: '****Pricing strategy contract source:**** \n\n',
        parent: 'contracts',
        child: 'pricingStrategy'
      }

    },
    crowdsale: {
      name: 'MintedTokenCappedCrowdsaleExt',
      txt: [
        { value: 'Crowdsale contract name: ', parent: 'none', fileValue: 'MintedTokenCappedCrowdsaleExt' },
        { field: 'addr', value: 'Crowdsale contract address', parent: 'contracts', child: 'crowdsale' },
        { value: '*****************************', parent: 'none', fileValue: '' },
        { field: 'abi', value: '****Crowdsale contract ABI:**** \n\n', parent: 'contracts', child: 'crowdsale' },
        {
          field: 'abiConstructor',
          value: '****Crowdsale contract ABI encoded constructor arguments',
          parent: 'contracts',
          child: 'crowdsale'
        }
      ],
      sol: { field: 'src', value: '****Crowdsale contract source:**** \n\n', parent: 'contracts', child: 'crowdsale' }

    },
    nullFinalizeAgent: {
      name: 'NullFinalizeAgentExt',
      txt: [
        { value: 'Null finalize agent contract name: ', parent: 'none', fileValue: 'NullFinalizeAgentExt' },
        {
          field: 'addr',
          value: 'Null finalize agent contract address',
          parent: 'contracts',
          child: 'finalizeAgent'
        },
        { value: '*****************************', parent: 'none', fileValue: '' },
        {
          field: 'abi',
          value: '****Null Finalize agent contract ABI:**** \n\n',
          parent: 'contracts',
          child: 'nullFinalizeAgent'
        },
        {
          field: 'abiConstructor',
          value: '****Null Finalize agent contract ABI encoded constructor arguments',
          parent: 'contracts',
          child: 'finalizeAgent'
        }
      ],
      sol: {
        field: 'src',
        value: '****Null Finalize agent contract source:**** \n\n',
        parent: 'contracts',
        child: 'nullFinalizeAgent'
      }

    },
    finalizeAgent: {
      name: 'ReservedTokensFinalizeAgent',
      txt: [
        { value: 'Finalize agent contract name: ', parent: 'none', fileValue: 'ReservedTokensFinalizeAgent' },
        { field: 'addr', value: 'Finalize agent contract address', parent: 'contracts', child: 'finalizeAgent' },
        { value: '*****************************', parent: 'none', fileValue: '' },
        {
          field: 'abi',
          value: '****Finalize agent contract ABI:**** \n\n',
          parent: 'contracts',
          child: 'finalizeAgent'
        },
        {
          field: 'abiConstructor',
          value: '****Finalize agent contract ABI encoded constructor arguments',
          parent: 'contracts',
          child: 'finalizeAgent'
        }
      ],
      sol: {
        field: 'src',
        value: '****Finalize agent contract source:**** \n\n',
        parent: 'contracts',
        child: 'finalizeAgent'
      }

    }
  }
}

export const DOWNLOAD_NAME = 'icowizard'
export const DOWNLOAD_TYPE = {
  text: 'text/plain',
  blob: 'blob'
}

export const INVESTMENT_OPTIONS = {
  METAMASK: 'metamask',
  QR: 'qr'
}
export const TOAST = {
  TYPE: {
    ERROR: 'error',
    INFO: 'info',
    SUCCESS: 'warning'
  },
  MESSAGE: {
    TRANSACTION_FAILED: 'Transaction has failed, please retry',
    CONTRACT_DOWNLOAD_FAILED: 'Contract Download failed',
    CONTRACT_DOWNLOAD_SUCCESS: 'A file with contracts and metadata downloaded on your computer',
    FINALIZE_FAIL: 'Was not able to finalize Crowdsale. Please be sure that Crowdsale has ended already'
  },
  DEFAULT_OPTIONS: {
    position: 'top right',
    offset: 80,
    time: 10000
  }
}
<|endoftext|>


<commit_before>var Q = require('q');
var async = require('async');

var tableSql = [
  "CREATE TABLE IF NOT EXISTS `api_app` (\
  `id` int(12) NOT NULL AUTO_INCREMENT,\
  `appid` int(12) NOT NULL,\
  `appname` varchar(120) NOT NULL,\
  `apptype` varchar(120) NOT NULL,\
  `appkey` varchar(120) NOT NULL,\
  `secretkey` varchar(120) NOT NULL,\
  `appenvironment` varchar(120) NOT NULL,\
  `approot` varchar(120) NOT NULL,\
  `createAt` int(32) NOT NULL,\
  `updateAt` int(32) NOT NULL,\
  `delflag` int(12) NOT NULL,\
  `status` int(12) NOT NULL DEFAULT '1',\
  `about` varchar(250) NOT NULL,\
  `appurl` varchar(500) DEFAULT NULL,\
  PRIMARY KEY (`id`),\
  UNIQUE KEY `appid` (`appid`)\
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;"
,
  "CREATE TABLE IF NOT EXISTS `api_record` (\
  `id` bigint(20) NOT NULL AUTO_INCREMENT,\
  `appkey` varchar(100) NOT NULL,\
  `createAt` bigint(20) NOT NULL,\
  `timestamp` bigint(20) NOT NULL,\
  `param` varchar(1000) NOT NULL,\
  `sign` varchar(100) NOT NULL,\
  `v` varchar(100) NOT NULL,\
  `method` varchar(100) NOT NULL,\
  `updateAt` bigint(20) NOT NULL,\
  `delflag` tinyint(4) NOT NULL DEFAULT '0',\
  PRIMARY KEY (`id`)\
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;"
];
var dataSql = [
  "INSERT INTO `api_app` (`id`, `appid`, `appname`, `apptype`, `appkey`, `secretkey`, `appenvironment`, `approot`, `createAt`, `updateAt`, `delflag`, `status`, `about`, `appurl`) VALUES\
(1, 10001, 'YFDemoKey', 'PC', 'a81bc1bb1122323b', '3fc4h39d3ed9b33b67fcbc359131e7ee', 'DEV', '*', 1462610156, 1462773916, 0, 1, 'YF所有，抄袭必究', NULL)"
];

module.exports = function(M){

  function exec(){
    var q = Q.defer();
    async.series([
      function(callback){
        async.eachSeries(tableSql,function(sql,cb){
          M.adapter.command(sql,function(err,result){
            if(err){
              cb(err);
            }else{
              cb(null,result);
            }
          });
        },function(err,result){
          callback(err,result);
        });
      },
      function(callback){
        async.eachSeries(dataSql,function(sql,cb){
          M.adapter.query(sql,function(err,result){
            if(err){
              cb(err);
            }else{
              cb(null,result);
            }
          });
        },function(err,result){
          callback(err,result);
        });
      }
    ],function(err,result){
      if(err){
        q.reject(err);
      }else{
        q.resolve(result);
      }
    });

    return q.promise;
  }
  return {exec:exec};
};
<commit_msg>remove unusable file<commit_after><|endoftext|>