<commit_before>const Device = require('../model/Device');
const Constants = require('../constants');
/**
 * DeviceModels utility
 *
 * @internal
 */
class DeviceModels {
  /**
   *
   * @param {string} type
   * @param {string} model
   *
   * @return {Device}
   */
  static identify(type, model) {
    const modelsName = `${type.toUpperCase()}_MODELS`;
    DeviceModels[modelsName] = require(`../../data/models-${type}`)[modelsName];
    if (type !== 'blackberry' && type !== 'ios') {
      const indicesName = `${type.toUpperCase()}_INDEX`;
      DeviceModels[indicesName] = require(`../../data/indices/models-${type}`)[indicesName];
    }
    switch (type) {
      case 'android':
        return DeviceModels.identifyAndroid(model);
      case 'asha':
        return DeviceModels.identifyList(DeviceModels.ASHA_INDEX, DeviceModels.ASHA_MODELS, model);
      case 'bada':
        return DeviceModels.identifyList(DeviceModels.BADA_INDEX, DeviceModels.BADA_MODELS, model);
      case 'blackberry':
        return DeviceModels.identifyBlackBerry(model);
      case 'brew':
        return DeviceModels.identifyList(DeviceModels.BREW_INDEX, DeviceModels.BREW_MODELS, model);
      case 'firefoxos':
        return DeviceModels.identifyList(DeviceModels.FIREFOXOS_INDEX, DeviceModels.FIREFOXOS_MODELS, model, false);
      case 'ios':
        return DeviceModels.identifyIOS(model);
      case 'tizen':
        return DeviceModels.identifyList(DeviceModels.TIZEN_INDEX, DeviceModels.TIZEN_MODELS, model);
      case 'touchwiz':
        return DeviceModels.identifyList(DeviceModels.TOUCHWIZ_INDEX, DeviceModels.TOUCHWIZ_MODELS, model);
      case 'wm':
        return DeviceModels.identifyWindowsMobile(model);
      case 'wp':
        return DeviceModels.identifyList(DeviceModels.WP_INDEX, DeviceModels.WP_MODELS, model);
      case 's30plus':
        return DeviceModels.identifyList(DeviceModels.S30PLUS_INDEX, DeviceModels.S30PLUS_MODELS, model);
      case 's40':
        return DeviceModels.identifyList(DeviceModels.S40_INDEX, DeviceModels.S40_MODELS, model);
      case 'symbian':
        return DeviceModels.identifyList(DeviceModels.SYMBIAN_INDEX, DeviceModels.SYMBIAN_MODELS, model);
      case 'palmos':
        return DeviceModels.identifyList(DeviceModels.PALMOS_INDEX, DeviceModels.PALMOS_MODELS, model);
      case 'kddi':
        return DeviceModels.identifyList(DeviceModels.KDDI_INDEX, DeviceModels.KDDI_MODELS, model);
    }

    DeviceModels.FEATURE_MODELS = require('../../data/models-feature').FEATURE_MODELS;
    DeviceModels.FEATURE_INDEX = require('../../data/indices/models-feature').FEATURE_INDEX;
    return DeviceModels.identifyList(DeviceModels.FEATURE_INDEX, DeviceModels.FEATURE_MODELS, model);
  }

  /**
   *
   * @param {string} model
   *
   * @return {Device}
   */
  static identifyWindowsMobile(model) {
    model = model.replace(/^(HTC|SAMSUNG|SHARP|Toshiba)\//u, '');
    return DeviceModels.identifyList(DeviceModels.WM_INDEX, DeviceModels.WM_MODELS, model);
  }

  /**
   *
   * @param {string} model
   *
   * @return {Device}
   */
  static identifyIOS(model) {
    const original = model;
    model = model.replace('Unknown ', '');
    model = model.replace(/iPh([0-9],[0-9])/, 'iPhone$1');
    model = model.replace(/iPd([0-9],[0-9])/, 'iPod$1');
    const device = new Device({
      type: Constants.deviceType.MOBILE,
      identified: Constants.id.NONE,
      manufacturer: null,
      model: model,
      identifier: original,
      generic: false,
    });
    if (DeviceModels.IOS_MODELS[model]) {
      const match = DeviceModels.IOS_MODELS[model];
      device.manufacturer = match[0];
      device.model = match[1];
      device.identified = Constants.id.MATCH_UA;
      if (isDefined(match[2]) || isDefined(match['type'])) {
        device.type = isDefined(match[2]) ? match[2] : match['type'];
      }
      return device;
    }
    return device;
  }

  /**
   *
   * @param {string} model
   *
   * @return {Device}
   */
  static identifyBlackBerry(model) {
    const original = model;
    let match;
    if ((match = model.match(/BlackBerry ?([0-9]+)/iu))) {
      model = match[1];
    }
    const device = new Device({
      type: Constants.deviceType.MOBILE,
      identified: Constants.id.NONE,
      manufacturer: null,
      model: model,
      identifier: original,
      generic: false,
    });
    if (/^[1-9][0-9][0-9][0-9][ei]?$/u.test(model)) {
      device.manufacturer = 'RIM';
      device.model = `BlackBerry ${model}`;
      device.identified = Constants.id.PATTERN;
      if (DeviceModels.BLACKBERRY_MODELS[model]) {
        device.model = `BlackBerry ${DeviceModels.BLACKBERRY_MODELS[model]} ${model}`;
        device.identified = Constants.id.MATCH_UA;
      }
    }
    return device;
  }

  /**
   *
   * @param {string} model
   *
   * @return {Device}
   */
  static identifyAndroid(model) {
    const result = DeviceModels.identifyList(DeviceModels.ANDROID_INDEX, DeviceModels.ANDROID_MODELS, model);
    if (!result.identified) {
      model = DeviceModels.cleanup(model);
      if (
        /AndroVM/iu.test(model) ||
        model === 'Emulator' ||
        model === 'x86 Emulator' ||
        model === 'x86 VirtualBox' ||
        model === 'vm'
      ) {
        return new Device({
          type: Constants.deviceType.EMULATOR,
          identified: Constants.id.PATTERN,
          manufacturer: null,
          model: null,
          generic: false,
        });
      }
    }
    return result;
  }

  /**
   *
   * @param {object} index
   * @param {object} list
   * @param {string} model
   * @param {boolean} cleanup
   *
   * @return {Device}
   */
  static identifyList(index, list, model, cleanup = true) {
    const original = model;
    if (cleanup) {
      model = DeviceModels.cleanup(model);
    }
    const device = new Device({
      type: Constants.deviceType.MOBILE,
      identified: Constants.id.NONE,
      manufacturer: null,
      model: model,
      identifier: original,
      generic: false,
    });
    const keys = [`@${model.substring(0, 2).toUpperCase()}`, '@'];
    let pattern = null;
    let match = null;
    for (let key of keys) {
      if (index[key]) {
        for (let v of index[key]) {
          if (DeviceModels.hasMatch(v, model)) {
            if (v) {
              if (v.endsWith('!!')) {
                for (let m2 of Object.keys(list[v])) {
                  const v2 = list[v][m2];
                  if (DeviceModels.hasMatch(m2, model)) {
                    match = v2;
                    pattern = m2;
                    break;
                  }
                }
              } else {
                match = list[v];
                pattern = v;
              }
            }
            if (match) {
              device.manufacturer = match[0];
              device.model = DeviceModels.applyMatches(match[1], model, pattern);
              device.identified = Constants.id.MATCH_UA;
              if (isDefined(match[2]) || isDefined(match['type'])) {
                const type = isDefined(match[2]) ? match[2] : match['type'];
                if (Array.isArray(type)) {
                  device.type = type[0];
                  device.subtype = type[1];
                } else {
                  device.type = type;
                }
              }
              if (isDefined(match[3]) || isDefined(match['flag'])) {
                device.flag = isDefined(match[3]) ? match[3] : match['flag'];
              }
              if (isDefined(match['carrier'])) {
                device.carrier = match['carrier'];
              }
              if (device.manufacturer === null && device.model === null) {
                device.identified = Constants.id.PATTERN;
              }
              return device;
            }
          }
        }
      }
    }
    return device;
  }

  /**
   *
   * @param {string} model
   * @param {string} original
   * @param {string} pattern
   *
   * @return {string}
   */
  static applyMatches(model, original, pattern) {
    if (model.includes('$') && pattern.endsWith('!')) {
      const matches = new RegExp(`^${pattern.substring(0, pattern.length - 1)}`, 'iu').test(original);
      if (matches) {
        matches.forEach((v, k) => {
          model = model.replace(`$${k}`, v);
        });
      }
    }
    return model;
  }

  /**
   *
   * @param {string} pattern
   * @param {string} model
   *
   * @return {boolean}
   */
  static hasMatch(pattern, model) {
    if (pattern.endsWith('!!')) {
      const regex2 = new RegExp(`^${pattern.substring(0, pattern.length - 2)}`, 'iu');
      return regex2.test(model);
    } else if (pattern.endsWith('!')) {
      const regex1 = new RegExp(`^${pattern.substring(0, pattern.length - 1)}`, 'iu');
      return regex1.test(model);
    } else {
      return pattern.toLowerCase() === model.toLowerCase();
    }
  }

  /**
   *
   * @param {string} s
   *
   * @return {boolean}
   */
  static cleanup(s = '') {
    // var_dump(s);
    s = s.replace(/^phone\//, '');
    s = s.replace(/^(\/|; |;)/u, '');
    s = s.replace(/\/[^/]+$/u, '');
    s = s.replace(/\/[^/]+ Android\/.*/u, '');
    s = s.replace(/UCBrowser$/u, '');
    s = s.replace(/(_TD|_LTE|_GPRS|_BLEU|_CMCC|_CMCC_TD|_CUCC)$/u, '');
    s = s.replace(/(-BREW| MIDP).+$/u, '');
    s = s.replace(/ AU-MIC.+$/u, '');
    s = s.replace(/ (AU|UP)\.Browser$/u, '');
    s = s.replace(/_/u, ' ');
    s = s.replace(/^\*+/u, '');
    s = s.replace(/^\s+|\s+$/u, '');
    s = s.replace(/^De-Sensed /u, '');
    s = s.replace(/^Full JellyBean( on )?/u, '');
    s = s.replace(/^(Android|Generic Android|Baidu Yi|Buildroid|Gingerbread|ICS AOSP|AOSPA?|tita) (on |for )/u, '');
    s = s.replace(
      /^Full (AOSP on |Android on |Base for |Cappuccino on |MIPS Android on |Webdroid on |JellyBean on |Android)/u,
      ''
    );
    s = s.replace(/^Acer( |-)?/iu, '');
    s = s.replace(/^Iconia( Tab)? /u, '');
    s = s.replace(/^ASUS ?/u, '');
    s = s.replace(/^Ainol /u, '');
    s = s.replace(/^Coolpad-?Coolpad/iu, 'Coolpad');
    s = s.replace(/^Coolpad ?/iu, 'Coolpad ');
    s = s.replace(/^Alcatel[_ ]OT[_-](.*)/iu, 'One Touch $1');
    s = s.replace(/^ALCATEL /u, '');
    s = s.replace(/^YL-/u, '');
    s = s.replace(/^TY-K[_\- ]Touch/iu, 'K-Touch');
    s = s.replace(/^K-Touch[_-]/u, 'K-Touch ');
    s = s.replace(/^Novo7 ?/iu, 'Novo7 ');
    s = s.replace(/^HW-HUAWEI/u, 'HUAWEI');
    s = s.replace(/^Huawei[ -]/iu, 'Huawei ');
    s = s.replace(/^SAMSUNG SAMSUNG-/iu, '');
    s = s.replace(/^SAMSUNG[ -]/iu, '');
    s = s.replace(/^(Sony ?Ericsson|Sony)/u, '');
    s = s.replace(/^(Lenovo Lenovo|LNV-Lenovo|LENOVO-Lenovo)/u, 'Lenovo');
    s = s.replace(/^Lenovo-/u, 'Lenovo');
    s = s.replace(/^Lenovo/u, 'Lenovo ');
    s = s.replace(/^ZTE-/u, 'ZTE ');
    s = s.replace(/^(LG)[ _/]/u, '$1-');
    s = s.replace(/^(HTC.+)\s[v|V][0-9.]+$/u, '$1');
    s = s.replace(/^(HTC)[-/]/u, '$1 ');
    s = s.replace(/^(HTC)([A-Z][0-9][0-9][0-9])/u, '$1 $2');
    s = s.replace(/^(Motorola MOT-|MOT-|Motorola[\s|-])/u, '');
    s = s.replace(/^Moto([^\s])/u, '$1');
    s = s.replace(/^(UTStar-)/u, '');
    s = s.replace(/^VZW:/iu, '');
    s = s.replace(/^(Swisscom|Vodafone)\/1.0\//iu, '');
    s = s.replace(/-?(orange(-ls)?|vodafone|bouygues|parrot|Kust)$/iu, '');
    s = s.replace(/[ -](Mozilla|Opera|Obigo|Java|PPC)$/iu, '');
    s = s.replace(/ ?Build$/iu, '');
    s = s.replace(/ \(compatible$/iu, '');
    s = s.replace(/http:\/\/.+$/iu, '');
    s = s.replace(/^\s+|\s+$/u, '');
    s = s.replace(/\s+/u, ' ');
    return s;
  }
}
const isDefined = (test) => typeof test !== 'undefined';

DeviceModels.ANDROID_MODELS = [];
DeviceModels.ASHA_MODELS = [];
DeviceModels.BADA_MODELS = [];
DeviceModels.BREW_MODELS = [];
DeviceModels.FIREFOXOS_MODELS = [];
DeviceModels.TIZEN_MODELS = [];
DeviceModels.TOUCHWIZ_MODELS = [];
DeviceModels.WM_MODELS = [];
DeviceModels.WP_MODELS = [];
DeviceModels.PALMOS_MODELS = [];
DeviceModels.S30PLUS_MODELS = [];
DeviceModels.S40_MODELS = [];
DeviceModels.SYMBIAN_MODELS = [];
DeviceModels.FEATURE_MODELS = [];
DeviceModels.BLACKBERRY_MODELS = [];
DeviceModels.IOS_MODELS = [];
DeviceModels.KDDI_MODELS = [];

DeviceModels.ANDROID_INDEX = [];
DeviceModels.ASHA_INDEX = [];
DeviceModels.BADA_INDEX = [];
DeviceModels.BREW_INDEX = [];
DeviceModels.FIREFOXOS_INDEX = [];
DeviceModels.TIZEN_INDEX = [];
DeviceModels.TOUCHWIZ_INDEX = [];
DeviceModels.WM_INDEX = [];
DeviceModels.WP_INDEX = [];
DeviceModels.PALMOS_INDEX = [];
DeviceModels.S30PLUS_INDEX = [];
DeviceModels.S40_INDEX = [];
DeviceModels.SYMBIAN_INDEX = [];
DeviceModels.FEATURE_INDEX = [];
DeviceModels.KDDI_INDEX = [];

module.exports = DeviceModels;
<commit_msg>Fix problem of \- inside regex<commit_after>const Device = require('../model/Device');
const Constants = require('../constants');
/**
 * DeviceModels utility
 *
 * @internal
 */
class DeviceModels {
  /**
   *
   * @param {string} type
   * @param {string} model
   *
   * @return {Device}
   */
  static identify(type, model) {
    const modelsName = `${type.toUpperCase()}_MODELS`;
    DeviceModels[modelsName] = require(`../../data/models-${type}`)[modelsName];
    if (type !== 'blackberry' && type !== 'ios') {
      const indicesName = `${type.toUpperCase()}_INDEX`;
      DeviceModels[indicesName] = require(`../../data/indices/models-${type}`)[indicesName];
    }
    switch (type) {
      case 'android':
        return DeviceModels.identifyAndroid(model);
      case 'asha':
        return DeviceModels.identifyList(DeviceModels.ASHA_INDEX, DeviceModels.ASHA_MODELS, model);
      case 'bada':
        return DeviceModels.identifyList(DeviceModels.BADA_INDEX, DeviceModels.BADA_MODELS, model);
      case 'blackberry':
        return DeviceModels.identifyBlackBerry(model);
      case 'brew':
        return DeviceModels.identifyList(DeviceModels.BREW_INDEX, DeviceModels.BREW_MODELS, model);
      case 'firefoxos':
        return DeviceModels.identifyList(DeviceModels.FIREFOXOS_INDEX, DeviceModels.FIREFOXOS_MODELS, model, false);
      case 'ios':
        return DeviceModels.identifyIOS(model);
      case 'tizen':
        return DeviceModels.identifyList(DeviceModels.TIZEN_INDEX, DeviceModels.TIZEN_MODELS, model);
      case 'touchwiz':
        return DeviceModels.identifyList(DeviceModels.TOUCHWIZ_INDEX, DeviceModels.TOUCHWIZ_MODELS, model);
      case 'wm':
        return DeviceModels.identifyWindowsMobile(model);
      case 'wp':
        return DeviceModels.identifyList(DeviceModels.WP_INDEX, DeviceModels.WP_MODELS, model);
      case 's30plus':
        return DeviceModels.identifyList(DeviceModels.S30PLUS_INDEX, DeviceModels.S30PLUS_MODELS, model);
      case 's40':
        return DeviceModels.identifyList(DeviceModels.S40_INDEX, DeviceModels.S40_MODELS, model);
      case 'symbian':
        return DeviceModels.identifyList(DeviceModels.SYMBIAN_INDEX, DeviceModels.SYMBIAN_MODELS, model);
      case 'palmos':
        return DeviceModels.identifyList(DeviceModels.PALMOS_INDEX, DeviceModels.PALMOS_MODELS, model);
      case 'kddi':
        return DeviceModels.identifyList(DeviceModels.KDDI_INDEX, DeviceModels.KDDI_MODELS, model);
    }

    DeviceModels.FEATURE_MODELS = require('../../data/models-feature').FEATURE_MODELS;
    DeviceModels.FEATURE_INDEX = require('../../data/indices/models-feature').FEATURE_INDEX;
    return DeviceModels.identifyList(DeviceModels.FEATURE_INDEX, DeviceModels.FEATURE_MODELS, model);
  }

  /**
   *
   * @param {string} model
   *
   * @return {Device}
   */
  static identifyWindowsMobile(model) {
    model = model.replace(/^(HTC|SAMSUNG|SHARP|Toshiba)\//u, '');
    return DeviceModels.identifyList(DeviceModels.WM_INDEX, DeviceModels.WM_MODELS, model);
  }

  /**
   *
   * @param {string} model
   *
   * @return {Device}
   */
  static identifyIOS(model) {
    const original = model;
    model = model.replace('Unknown ', '');
    model = model.replace(/iPh([0-9],[0-9])/, 'iPhone$1');
    model = model.replace(/iPd([0-9],[0-9])/, 'iPod$1');
    const device = new Device({
      type: Constants.deviceType.MOBILE,
      identified: Constants.id.NONE,
      manufacturer: null,
      model: model,
      identifier: original,
      generic: false,
    });
    if (DeviceModels.IOS_MODELS[model]) {
      const match = DeviceModels.IOS_MODELS[model];
      device.manufacturer = match[0];
      device.model = match[1];
      device.identified = Constants.id.MATCH_UA;
      if (isDefined(match[2]) || isDefined(match['type'])) {
        device.type = isDefined(match[2]) ? match[2] : match['type'];
      }
      return device;
    }
    return device;
  }

  /**
   *
   * @param {string} model
   *
   * @return {Device}
   */
  static identifyBlackBerry(model) {
    const original = model;
    let match;
    if ((match = model.match(/BlackBerry ?([0-9]+)/iu))) {
      model = match[1];
    }
    const device = new Device({
      type: Constants.deviceType.MOBILE,
      identified: Constants.id.NONE,
      manufacturer: null,
      model: model,
      identifier: original,
      generic: false,
    });
    if (/^[1-9][0-9][0-9][0-9][ei]?$/u.test(model)) {
      device.manufacturer = 'RIM';
      device.model = `BlackBerry ${model}`;
      device.identified = Constants.id.PATTERN;
      if (DeviceModels.BLACKBERRY_MODELS[model]) {
        device.model = `BlackBerry ${DeviceModels.BLACKBERRY_MODELS[model]} ${model}`;
        device.identified = Constants.id.MATCH_UA;
      }
    }
    return device;
  }

  /**
   *
   * @param {string} model
   *
   * @return {Device}
   */
  static identifyAndroid(model) {
    const result = DeviceModels.identifyList(DeviceModels.ANDROID_INDEX, DeviceModels.ANDROID_MODELS, model);
    if (!result.identified) {
      model = DeviceModels.cleanup(model);
      if (
        /AndroVM/iu.test(model) ||
        model === 'Emulator' ||
        model === 'x86 Emulator' ||
        model === 'x86 VirtualBox' ||
        model === 'vm'
      ) {
        return new Device({
          type: Constants.deviceType.EMULATOR,
          identified: Constants.id.PATTERN,
          manufacturer: null,
          model: null,
          generic: false,
        });
      }
    }
    return result;
  }

  /**
   *
   * @param {object} index
   * @param {object} list
   * @param {string} model
   * @param {boolean} cleanup
   *
   * @return {Device}
   */
  static identifyList(index, list, model, cleanup = true) {
    const original = model;
    if (cleanup) {
      model = DeviceModels.cleanup(model);
    }
    const device = new Device({
      type: Constants.deviceType.MOBILE,
      identified: Constants.id.NONE,
      manufacturer: null,
      model: model,
      identifier: original,
      generic: false,
    });
    const keys = [`@${model.substring(0, 2).toUpperCase()}`, '@'];
    let pattern = null;
    let match = null;
    for (let key of keys) {
      if (index[key]) {
        for (let v of index[key]) {
          if (DeviceModels.hasMatch(v, model)) {
            if (v) {
              if (v.endsWith('!!')) {
                for (let m2 of Object.keys(list[v])) {
                  const v2 = list[v][m2];
                  if (DeviceModels.hasMatch(m2, model)) {
                    match = v2;
                    pattern = m2;
                    break;
                  }
                }
              } else {
                match = list[v];
                pattern = v;
              }
            }
            if (match) {
              device.manufacturer = match[0];
              device.model = DeviceModels.applyMatches(match[1], model, pattern);
              device.identified = Constants.id.MATCH_UA;
              if (isDefined(match[2]) || isDefined(match['type'])) {
                const type = isDefined(match[2]) ? match[2] : match['type'];
                if (Array.isArray(type)) {
                  device.type = type[0];
                  device.subtype = type[1];
                } else {
                  device.type = type;
                }
              }
              if (isDefined(match[3]) || isDefined(match['flag'])) {
                device.flag = isDefined(match[3]) ? match[3] : match['flag'];
              }
              if (isDefined(match['carrier'])) {
                device.carrier = match['carrier'];
              }
              if (device.manufacturer === null && device.model === null) {
                device.identified = Constants.id.PATTERN;
              }
              return device;
            }
          }
        }
      }
    }
    return device;
  }

  /**
   *
   * @param {string} model
   * @param {string} original
   * @param {string} pattern
   *
   * @return {string}
   */
  static applyMatches(model, original, pattern) {
    if (model.includes('$') && pattern.endsWith('!')) {
      const matches = new RegExp(`^${pattern.substring(0, pattern.length - 1)}`, 'iu').test(original);
      if (matches) {
        matches.forEach((v, k) => {
          model = model.replace(`$${k}`, v);
        });
      }
    }
    return model;
  }

  /**
   *
   * @param {string} pattern
   * @param {string} model
   *
   * @return {boolean}
   */
  static hasMatch(pattern, model) {
    pattern = DeviceModels.cleanUpPattern(pattern);
    if (pattern.endsWith('!!')) {
      const regex2 = new RegExp(`^${pattern.substring(0, pattern.length - 2)}`, 'iu');
      return regex2.test(model);
    } else if (pattern.endsWith('!')) {
      const regex1 = new RegExp(`^${pattern.substring(0, pattern.length - 1)}`, 'iu');
      return regex1.test(model);
    } else {
      return pattern.toLowerCase() === model.toLowerCase();
    }
  }

  /**
   * Make the pattern compatible with JavaScript
   *
   * @param {string} pattern
   *
   * @return {string}
   */
  static cleanUpPattern(pattern) {
    return pattern.replace('(?i)', '').replace('\\-', '-');
  }

  /**
   *
   * @param {string} s
   *
   * @return {boolean}
   */
  static cleanup(s = '') {
    // var_dump(s);
    s = s.replace(/^phone\//, '');
    s = s.replace(/^(\/|; |;)/u, '');
    s = s.replace(/\/[^/]+$/u, '');
    s = s.replace(/\/[^/]+ Android\/.*/u, '');
    s = s.replace(/UCBrowser$/u, '');
    s = s.replace(/(_TD|_LTE|_GPRS|_BLEU|_CMCC|_CMCC_TD|_CUCC)$/u, '');
    s = s.replace(/(-BREW| MIDP).+$/u, '');
    s = s.replace(/ AU-MIC.+$/u, '');
    s = s.replace(/ (AU|UP)\.Browser$/u, '');
    s = s.replace(/_/u, ' ');
    s = s.replace(/^\*+/u, '');
    s = s.replace(/^\s+|\s+$/u, '');
    s = s.replace(/^De-Sensed /u, '');
    s = s.replace(/^Full JellyBean( on )?/u, '');
    s = s.replace(/^(Android|Generic Android|Baidu Yi|Buildroid|Gingerbread|ICS AOSP|AOSPA?|tita) (on |for )/u, '');
    s = s.replace(
      /^Full (AOSP on |Android on |Base for |Cappuccino on |MIPS Android on |Webdroid on |JellyBean on |Android)/u,
      ''
    );
    s = s.replace(/^Acer( |-)?/iu, '');
    s = s.replace(/^Iconia( Tab)? /u, '');
    s = s.replace(/^ASUS ?/u, '');
    s = s.replace(/^Ainol /u, '');
    s = s.replace(/^Coolpad-?Coolpad/iu, 'Coolpad');
    s = s.replace(/^Coolpad ?/iu, 'Coolpad ');
    s = s.replace(/^Alcatel[_ ]OT[_-](.*)/iu, 'One Touch $1');
    s = s.replace(/^ALCATEL /u, '');
    s = s.replace(/^YL-/u, '');
    s = s.replace(/^TY-K[_\- ]Touch/iu, 'K-Touch');
    s = s.replace(/^K-Touch[_-]/u, 'K-Touch ');
    s = s.replace(/^Novo7 ?/iu, 'Novo7 ');
    s = s.replace(/^HW-HUAWEI/u, 'HUAWEI');
    s = s.replace(/^Huawei[ -]/iu, 'Huawei ');
    s = s.replace(/^SAMSUNG SAMSUNG-/iu, '');
    s = s.replace(/^SAMSUNG[ -]/iu, '');
    s = s.replace(/^(Sony ?Ericsson|Sony)/u, '');
    s = s.replace(/^(Lenovo Lenovo|LNV-Lenovo|LENOVO-Lenovo)/u, 'Lenovo');
    s = s.replace(/^Lenovo-/u, 'Lenovo');
    s = s.replace(/^Lenovo/u, 'Lenovo ');
    s = s.replace(/^ZTE-/u, 'ZTE ');
    s = s.replace(/^(LG)[ _/]/u, '$1-');
    s = s.replace(/^(HTC.+)\s[v|V][0-9.]+$/u, '$1');
    s = s.replace(/^(HTC)[-/]/u, '$1 ');
    s = s.replace(/^(HTC)([A-Z][0-9][0-9][0-9])/u, '$1 $2');
    s = s.replace(/^(Motorola MOT-|MOT-|Motorola[\s|-])/u, '');
    s = s.replace(/^Moto([^\s])/u, '$1');
    s = s.replace(/^(UTStar-)/u, '');
    s = s.replace(/^VZW:/iu, '');
    s = s.replace(/^(Swisscom|Vodafone)\/1.0\//iu, '');
    s = s.replace(/-?(orange(-ls)?|vodafone|bouygues|parrot|Kust)$/iu, '');
    s = s.replace(/[ -](Mozilla|Opera|Obigo|Java|PPC)$/iu, '');
    s = s.replace(/ ?Build$/iu, '');
    s = s.replace(/ \(compatible$/iu, '');
    s = s.replace(/http:\/\/.+$/iu, '');
    s = s.replace(/^\s+|\s+$/u, '');
    s = s.replace(/\s+/u, ' ');
    return s;
  }
}
const isDefined = (test) => typeof test !== 'undefined';

DeviceModels.ANDROID_MODELS = [];
DeviceModels.ASHA_MODELS = [];
DeviceModels.BADA_MODELS = [];
DeviceModels.BREW_MODELS = [];
DeviceModels.FIREFOXOS_MODELS = [];
DeviceModels.TIZEN_MODELS = [];
DeviceModels.TOUCHWIZ_MODELS = [];
DeviceModels.WM_MODELS = [];
DeviceModels.WP_MODELS = [];
DeviceModels.PALMOS_MODELS = [];
DeviceModels.S30PLUS_MODELS = [];
DeviceModels.S40_MODELS = [];
DeviceModels.SYMBIAN_MODELS = [];
DeviceModels.FEATURE_MODELS = [];
DeviceModels.BLACKBERRY_MODELS = [];
DeviceModels.IOS_MODELS = [];
DeviceModels.KDDI_MODELS = [];

DeviceModels.ANDROID_INDEX = [];
DeviceModels.ASHA_INDEX = [];
DeviceModels.BADA_INDEX = [];
DeviceModels.BREW_INDEX = [];
DeviceModels.FIREFOXOS_INDEX = [];
DeviceModels.TIZEN_INDEX = [];
DeviceModels.TOUCHWIZ_INDEX = [];
DeviceModels.WM_INDEX = [];
DeviceModels.WP_INDEX = [];
DeviceModels.PALMOS_INDEX = [];
DeviceModels.S30PLUS_INDEX = [];
DeviceModels.S40_INDEX = [];
DeviceModels.SYMBIAN_INDEX = [];
DeviceModels.FEATURE_INDEX = [];
DeviceModels.KDDI_INDEX = [];

module.exports = DeviceModels;
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

foam.CLASS({
  package: 'foam.comics',
  name: 'DAOUpdateControllerView',
  extends: 'foam.u2.View',

  requires: [
    'foam.comics.DAOUpdateController',
    'foam.u2.ControllerMode',
    'foam.u2.DisplayMode',
    'foam.u2.dialog.NotificationMessage'
  ],

  imports: [
    'stack',
    'dao? as importedDAO'
  ],

  exports: [
    'controllerMode',
    'data'
  ],

  css: `
    ^ {
      max-width: 1024px;
      margin: auto;
    }
    ^action-container {
      display: flex;
      justify-content: space-between;
      margin: 8px 0;
    }
    ^action-container > div > div > * + * {
      margin-left: 8px;
    }
    ^detail-container {
      overflow-x: scroll;
    }
  `,

  properties: [
    {
      name: 'key'
    },
    {
      class: 'foam.dao.DAOProperty',
      name: 'dao',
      factory: function() {
        return this.importedDAO;
      }
    },
    {
      class: 'FObjectProperty',
      of: 'foam.comics.DAOUpdateController',
      name: 'data',
      factory: function() {
        return this.DAOUpdateController.create({
          data: this.key,
          dao: this.dao
        });
      }
    },
    {
      class: 'String',
      name: 'title',
      expression: function(data$dao$of) {
        return 'Edit ' + data$dao$of.name;
      }
    },
    {
      class: 'foam.u2.ViewSpec',
      name: 'detailView'
    },
    {
      name: 'controllerMode',
      factory: function() {
        return this.ControllerMode.VIEW;
      }
    },
    {
      class: 'Boolean',
      name: 'editEnabled'
    },
    {
      class: 'FObjectProperty',
      of: 'foam.u2.Element',
      name: 'container_'
    },
    {
      class: 'FObjectProperty',
      of: 'foam.u2.Element',
      name: 'detailViewElement_'
    }
  ],

  reactions: [
    [ 'data', 'finished', 'onFinished' ],
    [ 'data', 'throwError', 'onThrowError' ]
  ],

  methods: [
    function initE() {
      /* Doesn't work because obj isn't known yet.
      this.startContext({data: this.data.obj})
        .add(this.data.dao.of.getAxiomsByClass(foam.core.Action))
      .endContext()
      */
      this
        .addClass(this.myClass())

        // Container for the actions
        .start()
          .addClass(this.myClass('action-container'))

          // Actions grouped to the left
          .start()
            .startContext({ data: this })
              .tag(this.CANCEL, { buttonStyle: 'SECONDARY' })
            .endContext()
          .end()

          // Actions grouped to the right
          .start()
            .start()
              .show(this.mode$.map((m) => m === this.DisplayMode.RW))
              .add(this.data.cls_.getAxiomsByClass(foam.core.Action))
            .end()
            .start()
              .show(this.mode$.map((m) => m === this.DisplayMode.RO))
              .startContext({ data: this })
                .add(this.EDIT)
              .endContext()
            .end()
          .end()
        .end()

        // Container for the detailview
        .start('div', [], this.container_$)
          .addClass(this.myClass('detail-container'))
          .tag(this.detailView, {
            of: this.dao.of,
            data$: this.data$.dot('obj'),
            showActions: true
          }, this.detailViewElement_$)
        .end();
    }
  ],

  actions: [
    {
      name: 'cancel',
      code: function() {
        this.stack.back();
      }
    },
    {
      name: 'edit',
      isAvailable: function(controllerMode, editEnabled) {
        return editEnabled && controllerMode === this.ControllerMode.VIEW;
      },
      code: function() {
        this.controllerMode = this.ControllerMode.EDIT;
        var newE = this.container_.createChild_(this.detailView, {
          of: this.dao.of,
          data$: this.data$.dot('obj'),
          showActions: true
        });
        this.container_.replaceChild(newE, this.detailViewElement_);
        this.detailViewElement_ = newE;
      }
    }
  ],

  listeners: [
    function onFinished() {
      this.stack.back();
    },
    function onThrowError() {
      var self = this;
      this.add(this.NotificationMessage.create({
        message: self.data.exception.message,
        type: 'error'
     }));
    }
  ]
});
<commit_msg>Show edit action on RW mode only<commit_after>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

foam.CLASS({
  package: 'foam.comics',
  name: 'DAOUpdateControllerView',
  extends: 'foam.u2.View',

  requires: [
    'foam.comics.DAOUpdateController',
    'foam.u2.ControllerMode',
    'foam.u2.DisplayMode',
    'foam.u2.dialog.NotificationMessage'
  ],

  imports: [
    'stack',
    'dao? as importedDAO'
  ],

  exports: [
    'controllerMode',
    'data'
  ],

  css: `
    ^ {
      max-width: 1024px;
      margin: auto;
    }
    ^action-container {
      display: flex;
      justify-content: space-between;
      margin: 8px 0;
    }
    ^action-container > div > div > * + * {
      margin-left: 8px;
    }
    ^detail-container {
      overflow-x: scroll;
    }
  `,

  properties: [
    {
      name: 'key'
    },
    {
      class: 'foam.dao.DAOProperty',
      name: 'dao',
      factory: function() {
        return this.importedDAO;
      }
    },
    {
      class: 'FObjectProperty',
      of: 'foam.comics.DAOUpdateController',
      name: 'data',
      factory: function() {
        return this.DAOUpdateController.create({
          data: this.key,
          dao: this.dao
        });
      }
    },
    {
      class: 'String',
      name: 'title',
      expression: function(data$dao$of) {
        return 'Edit ' + data$dao$of.name;
      }
    },
    {
      class: 'foam.u2.ViewSpec',
      name: 'detailView'
    },
    {
      name: 'controllerMode',
      factory: function() {
        return this.ControllerMode.VIEW;
      }
    },
    {
      class: 'Boolean',
      name: 'editEnabled'
    },
    {
      class: 'FObjectProperty',
      of: 'foam.u2.Element',
      name: 'container_'
    },
    {
      class: 'FObjectProperty',
      of: 'foam.u2.Element',
      name: 'detailViewElement_'
    }
  ],

  reactions: [
    [ 'data', 'finished', 'onFinished' ],
    [ 'data', 'throwError', 'onThrowError' ]
  ],

  methods: [
    function initE() {
      /* Doesn't work because obj isn't known yet.
      this.startContext({data: this.data.obj})
        .add(this.data.dao.of.getAxiomsByClass(foam.core.Action))
      .endContext()
      */
      this
        .addClass(this.myClass())

        // Container for the actions
        .start()
          .addClass(this.myClass('action-container'))

          // Actions grouped to the left
          .start()
            .startContext({ data: this })
              .tag(this.CANCEL, { buttonStyle: 'SECONDARY' })
            .endContext()
          .end()

          // Actions grouped to the right
          .start()
            .start()
              .show(this.mode$.map((m) => m === this.DisplayMode.RW))
              .add(this.data.cls_.getAxiomsByClass(foam.core.Action))
            .end()
            .start()
              .show(this.mode$.map((m) => m === this.DisplayMode.RW))
              .startContext({ data: this })
                .add(this.EDIT)
              .endContext()
            .end()
          .end()
        .end()

        // Container for the detailview
        .start('div', [], this.container_$)
          .addClass(this.myClass('detail-container'))
          .tag(this.detailView, {
            of: this.dao.of,
            data$: this.data$.dot('obj'),
            showActions: true
          }, this.detailViewElement_$)
        .end();
    }
  ],

  actions: [
    {
      name: 'cancel',
      code: function() {
        this.stack.back();
      }
    },
    {
      name: 'edit',
      isAvailable: function(controllerMode, editEnabled) {
        return editEnabled && controllerMode === this.ControllerMode.VIEW;
      },
      code: function() {
        this.controllerMode = this.ControllerMode.EDIT;
        var newE = this.container_.createChild_(this.detailView, {
          of: this.dao.of,
          data$: this.data$.dot('obj'),
          showActions: true
        });
        this.container_.replaceChild(newE, this.detailViewElement_);
        this.detailViewElement_ = newE;
      }
    }
  ],

  listeners: [
    function onFinished() {
      this.stack.back();
    },
    function onThrowError() {
      var self = this;
      this.add(this.NotificationMessage.create({
        message: self.data.exception.message,
        type: 'error'
     }));
    }
  ]
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

 foam.INTERFACE({
  package: 'foam.nanos.approval',
  name: 'ApprovableAware',
  implements: [
    'foam.comics.v2.userfeedback.UserFeedbackAware',
    'foam.core.ContextAware',
    'foam.nanos.auth.LifecycleAware',
  ],

  javaImports: [
    'foam.core.FObject',
    'foam.core.X',
    'foam.nanos.logger.Logger',
    'foam.nanos.approval.ApprovableAware',
    'foam.nanos.ruler.Operations',
    'java.util.Iterator',
    'java.util.ArrayList',
    'java.util.Arrays',
    'java.util.List',
    'java.util.Map',
  ],

  methods: [
    {
      name: 'getStringId',
      type: 'String'
    }
  ],

  axioms: [
    {
      name: 'javaExtras',
      buildJavaClass: function(cls) {
        cls.methods.push(
          foam.java.Method.create({
            name: 'getApprovableHashKey',
            type: 'String',
            static: true,
            visibility: 'public',
            args: [
              { name: 'x', type: 'X' },
              { name: 'obj', type: 'FObject' },
              { name: 'operation', type: 'Operations' }
            ],
            body: `
              FObject oldObj = null;
              try {
                oldObj = (obj.getClass()).newInstance();
              } catch ( Exception e ) {
                Logger logger = (Logger) x.get("logger");
                logger.error("Error instantiating : ", obj.getClass().getSimpleName(), e);
              }
              Map diff = oldObj == null ? null : oldObj.diff(obj);
              StringBuilder hash_sb = new StringBuilder(obj.getClass().getSimpleName());
              if ( operation == Operations.UPDATE) hash_sb.append(((ApprovableAware) obj).getStringId());

              if ( diff != null ) {
                // remove ids, timestamps and userfeedback
                if ( operation == Operations.CREATE ) diff.remove("id");
                diff.remove("created");
                diff.remove("lastModified");
                diff.remove("userFeedback");

                // convert array properties to list to get consistent hash
                // and create hash
                Iterator it = diff.entrySet().iterator();

                while( it.hasNext() ) {
                  Map.Entry next = (Map.Entry) it.next();
                  Object nextValue = next.getValue();
                  if ( nextValue instanceof Object[] ) {
                    next.setValue(Arrays.asList((Object[]) nextValue));
                  }
                  hash_sb.append(":").append(String.valueOf(next.hashCode()));
                }
              }

              String key = diff == null || diff.size() == 0 ? ((ApprovableAware) obj).getStringId() : hash_sb.toString();
              return key;
            `
          })
        );
      }
    }
  ]
});
<commit_msg>added fix for hash of fobjectproperties<commit_after>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

 foam.INTERFACE({
  package: 'foam.nanos.approval',
  name: 'ApprovableAware',
  implements: [
    'foam.comics.v2.userfeedback.UserFeedbackAware',
    'foam.core.ContextAware',
    'foam.nanos.auth.LifecycleAware',
  ],

  javaImports: [
    'foam.core.FObject',
    'foam.core.X',
    'foam.nanos.logger.Logger',
    'foam.nanos.approval.ApprovableAware',
    'foam.nanos.ruler.Operations',
    'java.util.Iterator',
    'java.util.ArrayList',
    'java.util.Arrays',
    'java.util.List',
    'java.util.Map',
  ],

  methods: [
    {
      name: 'getStringId',
      type: 'String'
    }
  ],

  axioms: [
    {
      name: 'javaExtras',
      buildJavaClass: function(cls) {
        cls.methods.push(
          foam.java.Method.create({
            name: 'getApprovableHashKey',
            type: 'String',
            static: true,
            visibility: 'public',
            args: [
              { name: 'x', type: 'X' },
              { name: 'obj', type: 'FObject' },
              { name: 'operation', type: 'Operations' }
            ],
            body: `
              FObject oldObj = null;
              try {
                oldObj = (obj.getClass()).newInstance();
              } catch ( Exception e ) {
                Logger logger = (Logger) x.get("logger");
                logger.error("Error instantiating : ", obj.getClass().getSimpleName(), e);
              }
              Map diff = oldObj == null ? null : oldObj.diff(obj);
              StringBuilder hash_sb = new StringBuilder(obj.getClass().getSimpleName());
              if ( operation == Operations.UPDATE && obj instanceof ApprovableAware )
                hash_sb.append(((ApprovableAware) obj).getStringId());

              if ( diff != null ) {
                // remove ids, timestamps and userfeedback
                if ( operation == Operations.CREATE ) diff.remove("id");
                diff.remove("created");
                diff.remove("lastModified");
                diff.remove("userFeedback");

                // convert array properties to list to get consistent hash
                // and create hash
                Iterator it = diff.entrySet().iterator();

                while( it.hasNext() ) {
                  Map.Entry next = (Map.Entry) it.next();
                  Object nextValue = next.getValue();
                  if ( nextValue instanceof Object[] ) {
                    next.setValue(Arrays.asList((Object[]) nextValue));
                  }
                  if ( nextValue instanceof FObject ) {
                    String hashedKey = getApprovableHashKey(x, (FObject) nextValue, Operations.CREATE);
                    if ( hashedKey.toLowerCase().equals(nextValue.getClass().getSimpleName().toLowerCase()) ) continue;
                    next.setValue(hashedKey);
                  }

                  hash_sb.append(":").append(String.valueOf(next.hashCode()));
                }
              }

              String key = ( diff == null || diff.size() == 0 ) && obj instanceof ApprovableAware ?
                ((ApprovableAware) obj).getStringId() :
                hash_sb.toString();

              return key;
            `
          })
        );
      }
    }
  ]
});
<|endoftext|>


<commit_before>import React from 'react'
import Relay from 'react-relay'
import {Styles, Divider, RaisedButton, FlatButton, Card, CardHeader, CardText, CardActions, FontIcon} from 'material-ui'
import GCForm from './forms/GCForm'
import Form from 'react-formal'
import yup from 'yup'
import moment from 'moment'
import {BernieTheme} from './styles/bernie-theme'
import {BernieText, BernieColors} from './styles/bernie-css'
import stripScripts from '../helpers/stripScripts'

const style = {
  marginLeft: 20,
}

class EventsDashboard extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      windowWidth: window.innerWidth,
      windowHeight: window.innerHeight
    }

    window.addEventListener('resize', this._handleResize)
  }

  _handleResize = (e) => {
    this.setState({
      windowWidth: window.innerWidth,
      windowHeight: window.innerHeight
    })
  }

  renderEvents() {
    const events = this.props.listContainer.events.edges || []
    return events.map((event) => {
      event = event.node
      const utcOffset = event.localUTCOffset || 0
      const timezone = event.localTimezone || 'UTC'
      const offsetDate = moment(event.startDate).utcOffset(utcOffset)
      const formattedDate = offsetDate.format('l LT')
      return (
        <Card key={event.id} style={{width: '100%'}}>
          <CardHeader
            title={event.name}
            subtitle={formattedDate}
            actAsExpander={true}
            showExpandableButton={true}
          />
          <CardText expandable={true}>

          </CardText>
          <CardActions expandable={true}>
            <FlatButton label="Open"/>
            <FlatButton label="Edit"/>
            <FlatButton label="Delete"/>
            <FlatButton label="Upload Sign In Sheets"/>
          </CardActions>
        </Card>
      )
    })
  }

  render() {
    console.log(this.props.listContainer)
    return (

        {this.renderEvents()}

    )
  }
}

export default Relay.createContainer(EventsDashboard, {
  initialVariables: {
    numEvents: 100,
    sortField: 'startDate',
    sortDirection: 'ASC',
    status: 'PENDING_REVIEW',
    filters: {},
    hostFilters: {}
  },
  fragments: {
    currentUser: () => Relay.QL`
      fragment on User {
        id
        email
      }
    `,
    listContainer: () => Relay.QL`
      fragment on ListContainer {
        events(
          first: $numEvents
          eventFilterOptions: $filters
          hostFilterOptions: $hostFilters
          status: $status
          sortField: $sortField
          sortDirection: $sortDirection
        ) {
          edges {
            cursor
            node {
              name
              id
              host {
                id
                firstName
                lastName
                email
              }
              eventType {
                id
                name
              }
              eventIdObfuscated
              flagApproval
              isOfficial
              description
              venueName
              latitude
              longitude
              venueZip
              venueCity
              venueState
              venueAddr1
              venueAddr2
              venueCountry
              venueDirections
              createDate
              startDate
              localTimezone
              localUTCOffset
              duration
              capacity
              attendeeVolunteerShow
              attendeeVolunteerMessage
              isSearchable
              publicPhone
              contactPhone
              hostReceiveRsvpEmails
              rsvpUseReminderEmail
              rsvpEmailReminderHours
              attendeesCount
              attendees {
                firstName
                lastName
                phone
                email
                address {
                  city
                  state
                  zip
                }
              }
            }
          }
        }
      }
    `
  }
})<commit_msg>Use CardTitle<commit_after>import React from 'react'
import Relay from 'react-relay'
import {Styles, Divider, RaisedButton, FlatButton, Card, CardTitle, CardText, CardActions, FontIcon} from 'material-ui'
import GCForm from './forms/GCForm'
import Form from 'react-formal'
import yup from 'yup'
import moment from 'moment'
import {BernieTheme} from './styles/bernie-theme'
import {BernieText, BernieColors} from './styles/bernie-css'
import stripScripts from '../helpers/stripScripts'

const style = {
  marginLeft: 20,
}

class EventsDashboard extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      windowWidth: window.innerWidth,
      windowHeight: window.innerHeight
    }

    window.addEventListener('resize', this._handleResize)
  }

  _handleResize = (e) => {
    this.setState({
      windowWidth: window.innerWidth,
      windowHeight: window.innerHeight
    })
  }

  renderEvents() {
    const events = this.props.listContainer.events.edges || []
    return events.map((event) => {
      event = event.node
      const utcOffset = event.localUTCOffset || 0
      const timezone = event.localTimezone || 'UTC'
      const offsetDate = moment(event.startDate).utcOffset(utcOffset)
      const formattedDate = offsetDate.format('l LT')
      return (
        <Card key={event.id} style={{width: '100%'}}>
          <CardTitle
            title={event.name}
            subtitle={formattedDate}
            actAsExpander={true}
            showExpandableButton={true}
          />
          <CardText expandable={true}>

          </CardText>
          <CardActions expandable={true}>
            <FlatButton label="Open"/>
            <FlatButton label="Edit"/>
            <FlatButton label="Delete"/>
            <FlatButton label="Upload Sign In Sheets"/>
          </CardActions>
        </Card>
      )
    })
  }

  render() {
    console.log(this.props.listContainer)
    return (

        {this.renderEvents()}

    )
  }
}

export default Relay.createContainer(EventsDashboard, {
  initialVariables: {
    numEvents: 100,
    sortField: 'startDate',
    sortDirection: 'ASC',
    status: 'PENDING_REVIEW',
    filters: {},
    hostFilters: {}
  },
  fragments: {
    currentUser: () => Relay.QL`
      fragment on User {
        id
        email
      }
    `,
    listContainer: () => Relay.QL`
      fragment on ListContainer {
        events(
          first: $numEvents
          eventFilterOptions: $filters
          hostFilterOptions: $hostFilters
          status: $status
          sortField: $sortField
          sortDirection: $sortDirection
        ) {
          edges {
            cursor
            node {
              name
              id
              host {
                id
                firstName
                lastName
                email
              }
              eventType {
                id
                name
              }
              eventIdObfuscated
              flagApproval
              isOfficial
              description
              venueName
              latitude
              longitude
              venueZip
              venueCity
              venueState
              venueAddr1
              venueAddr2
              venueCountry
              venueDirections
              createDate
              startDate
              localTimezone
              localUTCOffset
              duration
              capacity
              attendeeVolunteerShow
              attendeeVolunteerMessage
              isSearchable
              publicPhone
              contactPhone
              hostReceiveRsvpEmails
              rsvpUseReminderEmail
              rsvpEmailReminderHours
              attendeesCount
              attendees {
                firstName
                lastName
                phone
                email
                address {
                  city
                  state
                  zip
                }
              }
            }
          }
        }
      }
    `
  }
})<|endoftext|>


<commit_before>/*global jessieNamespace,html,isHostMethod */
/*
Description:
Relies on Microsoft's `el.attachEvent`
*/

/*
Degrades:
IE10, IE9, IE4, IE3, Opera 8+, Chrome, FF, Safari
*/

/*
Author:
David Mark
*/

var attachListener;

if(html && isHostMethod(html, 'attachEvent')) {

	// The "theseObjects" variable must be global
	// or a property of a global object (e.g. a "namespace" object).
	// Stores references to objects used for - this - object in listeners
	jessieNamespace.theseObjects = [];

	var theseObjectsIndex = 0;

	attachListener = function(el, eventType, fn) {
		var thisObjectIndex = theseObjectsIndex++;

		// Store reference to object used for - this - in listener
		jessieNamespace.theseObjects[thisObjectIndex] = el;

		var listener = function() {
			var e = window.event;
			fn.call(el, e);
		};

		el.attachEvent('on'+eventType, listener);

		// Discard unneeded references
		// Prevents circular references with host objects (e.g. the element)
		// Prevents IE leaks related to such circular references
		// No unload event cleanup required
		el = null;

		return listener;
	};
}<commit_msg>Update rendition2.js<commit_after>/*global jessieNamespace,html,isHostMethod */
/*
Description:
Relies on Microsoft's `el.attachEvent`
*/

/*
Degrades:
IE10, IE9, IE4, IE3, Opera 8+, Chrome, FF, Safari
*/

/*
Author:
David Mark
*/

var attachListener;

if(html && isHostMethod(html, 'attachEvent')) {

	// The "theseObjects" variable must be global
	// or a property of a global object (e.g. a "namespace" object).
	// Stores references to objects used for - this - object in listeners
	jessieNamespace.theseObjects = [];

	var theseObjectsIndex = 0;

	attachListener = function(el, eventType, fn) {
		var thisObjectIndex = theseObjectsIndex++;

		// Store reference to object used for - this - in listener
		jessieNamespace.theseObjects[thisObjectIndex] = el;

		var listener = function() {
			var e = window.event;
			fn.call(jessieNamespace.theseObjects[thisObjectIndex], e);
		};

		el.attachEvent('on'+eventType, listener);

		// Discard unneeded references
		// Prevents circular references with host objects (e.g. the element)
		// Prevents IE leaks related to such circular references
		// No unload event cleanup required
		el = null;

		return listener;
	};
}
<|endoftext|>


<commit_before>'use strict';

const Application = require('../../documentModels/application');
const ApplicationAccess = require('../../documentModels/applicationAccess');

module.exports = (request, response, next) => {
	(async () => {
		try {
			const route = request.directoryRouter.findRoute(request.method, request.route.path);
			const extensions = route.extensions;

			if ('permissions' in extensions && extensions.permissions.length !== 0) {
				const applicationKey = request.get('X-Application-Key');
				const accessKey = request.get('X-Access-Key');

				if (applicationKey == null) {
					response.status(400).send({error: {message: 'X-Application-Key header is empty'}});
					return;
				}

				if (accessKey == null) {
					response.status(400).send({error: {message: 'X-Access-Key header is empty'}});
					return;
				}

				if (!await Application.verifyKeyAsync(applicationKey, request.db, request.config)) {
					response.status(400).send({error: {message: 'X-Application-Key header is invalid'}});
					return;
				}

				if (!await ApplicationAccess.verifyKeyAsync(accessKey, request.db, request.config)) {
					response.status(400).send({error: {message: 'X-Access-Key header is invalid'}});
					return;
				}

				const applicationId = Application.splitKey(applicationKey, request.db, request.config).applicationId;
				const userId = ApplicationAccess.splitKey(accessKey, request.db, request.config).userId;

				const application = (await request.db.applications.findIdAsync(applicationId));
				request.application = application.document;
				request.user = (await request.db.users.findIdAsync(userId)).document;

				for (const permission of extensions.permissions) {
					if (!application.hasPermission(permission)) {
						response.status(403).send({error: {message: 'you do not have any permissions'}});
						return;
					}
				}

				next();
			}
			else {
				next();
			}
		}
		catch(err) {
			console.log(`checkPermission failed (${err})`);
			throw err;
		}
	})();
};
<commit_msg>refactoring<commit_after>'use strict';

const Application = require('../../documentModels/application');
const ApplicationAccess = require('../../documentModels/applicationAccess');

module.exports = (request, response, next) => {
	(async () => {
		try {
			const route = request.directoryRouter.findRoute(request.method, request.route.path);
			const extensions = route.extensions;

			if ('permissions' in extensions && extensions.permissions.length !== 0) {
				const applicationKey = request.get('X-Application-Key');
				const accessKey = request.get('X-Access-Key');

				if (applicationKey == null) {
					response.status(400).send({error: {message: 'X-Application-Key header is empty'}});
					return;
				}

				if (accessKey == null) {
					response.status(400).send({error: {message: 'X-Access-Key header is empty'}});
					return;
				}

				if (!await Application.verifyKeyAsync(applicationKey, request.db, request.config)) {
					response.status(400).send({error: {message: 'X-Application-Key header is invalid'}});
					return;
				}

				if (!await ApplicationAccess.verifyKeyAsync(accessKey, request.db, request.config)) {
					response.status(400).send({error: {message: 'X-Access-Key header is invalid'}});
					return;
				}

				const applicationId = Application.splitKey(applicationKey, request.db, request.config).applicationId;
				const userId = ApplicationAccess.splitKey(accessKey, request.db, request.config).userId;

				request.application = (await request.db.applications.findIdAsync(applicationId));
				request.user = (await request.db.users.findIdAsync(userId));

				const hasPermissions = extensions.permissions.every(p => request.application.hasPermission(p));
				if (!hasPermissions) {
					response.status(403).send({error: {message: 'you do not have any permissions'}});
					return;
				}
			}
			next();
		}
		catch(err) {
			console.log(`checkPermission failed (${err})`);
			throw err;
		}
	})();
};
<|endoftext|>


<commit_before>import React from 'react'
import {StyleSheet} from 'react-native'
import {CHANNEL} from './constants'
import getStyles from './get-styles'
import PropTypes from './react-compat'

function prepareStyles(styles) {
  return styles.filter(style => {
    if (typeof style === 'object') {
      return Object.keys(style).length > 0
    }
    return true
  })
  .map(style => {
    if (typeof style === 'object') {
      return StyleSheet.create({style}).style
    }
    return style
  })
}

export default function createGlamorous(splitProps) {
  return function glamorous(
    comp,
    {rootEl, displayName, forwardProps = []} = {},
  ) {
    return glamorousComponentFactory

    function glamorousComponentFactory(...unpreparedStyles) {
      const styles = prepareStyles(unpreparedStyles)

      class GlamorousComponent extends React.Component {
        state = {theme: null}
        setTheme = theme => this.setState({theme})

        constructor(props, context) {
          super(props, context)
          this.onRef = this.onRef.bind(this)
        }

        componentWillMount() {
          const {theme} = this.props

          if (this.context[CHANNEL]) {
            this.setTheme(theme ? theme : this.context[CHANNEL].getState())
          } else {
            this.setTheme(theme || {})
          }
        }

        componentWillReceiveProps(nextProps) {
          if (this.props.theme !== nextProps.theme) {
            this.setTheme(nextProps.theme)
          }
        }

        componentDidMount() {
          if (this.context[CHANNEL] && !this.props.theme) {
            this.unsubscribe = this.context[CHANNEL].subscribe(this.setTheme)
          }
        }

        componentWillUnmount() {
          this.unsubscribe && this.unsubscribe()
        }

        setNativeProps(nativeProps) {
          if (this.innerComponent) {
            this.innerComponent.setNativeProps(nativeProps)
          }
        }

        onRef(innerComponent) {
          this.innerComponent = innerComponent
          if (this.props.innerRef) {
            this.props.innerRef(innerComponent)
          }
        }

        render() {
          const props = this.props

          const {toForward, styleOverrides} = splitProps(
            props,
            GlamorousComponent,
          )

          const theme = __DEV__ ?
            Object.freeze(this.state.theme) :
            this.state.theme

          const fullStyles = getStyles(
            GlamorousComponent.styles,
            props,
            styleOverrides,
            theme,
            this.context,
          )

          return React.createElement(GlamorousComponent.comp, {
            ...toForward,
            ref: this.onRef,
            style: fullStyles.length > 0 ? fullStyles : null,
          })
        }
      }

      GlamorousComponent.comp = comp

      GlamorousComponent.propTypes = {
        innerRef: PropTypes.func,
        theme: PropTypes.object,
      }

      const defaultContextTypes = {
        [CHANNEL]: PropTypes.object,
      }
      let userDefinedContextTypes = null

      // configure the contextTypes to be settable by the user,
      // however also retaining the glamorous channel.
      Object.defineProperty(GlamorousComponent, 'contextTypes', {
        enumerable: true,
        configurable: true,
        set(value) {
          userDefinedContextTypes = value
        },
        get() {
          // if the user has provided a contextTypes definition,
          // merge the default context types with the provided ones.
          if (userDefinedContextTypes) {
            return {
              ...defaultContextTypes,
              ...userDefinedContextTypes,
            }
          }
          return defaultContextTypes
        },
      })

      Object.assign(
        GlamorousComponent,
        getGlamorousComponentMetadata({
          comp,
          styles,
          rootEl,
          forwardProps,
          displayName,
        }),
      )

      return GlamorousComponent
    }
  }
}

function getGlamorousComponentMetadata({
  comp,
  styles,
  rootEl,
  forwardProps,
  displayName,
}) {
  const componentsComp = comp.comp ? comp.comp : comp

  return {
    styles: when(comp.styles, styles),
    comp: componentsComp,
    rootEl: rootEl || componentsComp,
    forwardProps: when(comp.forwardProps, forwardProps),
    displayName: displayName || `glamorous(${getDisplayName(comp)})`,
  }
}

function when(comp, prop) {
  return comp ? comp.concat(prop) : prop
}

function getDisplayName(comp) {
  return typeof comp === 'string' ?
    comp :
    comp.displayName || comp.name || 'unknown'
}
<commit_msg>fix(glamorous): Do not give refs to stateless function components (#57)<commit_after>import React from 'react'
import {StyleSheet} from 'react-native'
import {CHANNEL} from './constants'
import getStyles from './get-styles'
import PropTypes from './react-compat'

function prepareStyles(styles) {
  return styles.filter(style => {
    if (typeof style === 'object') {
      return Object.keys(style).length > 0
    }
    return true
  })
  .map(style => {
    if (typeof style === 'object') {
      return StyleSheet.create({style}).style
    }
    return style
  })
}

export default function createGlamorous(splitProps) {
  return function glamorous(
    comp,
    {rootEl, displayName, forwardProps = []} = {},
  ) {
    return glamorousComponentFactory

    function glamorousComponentFactory(...unpreparedStyles) {
      const styles = prepareStyles(unpreparedStyles)

      class GlamorousComponent extends React.Component {
        state = {theme: null}
        setTheme = theme => this.setState({theme})

        constructor(props, context) {
          super(props, context)
          this.onRef = this.onRef.bind(this)
        }

        componentWillMount() {
          const {theme} = this.props

          if (this.context[CHANNEL]) {
            this.setTheme(theme ? theme : this.context[CHANNEL].getState())
          } else {
            this.setTheme(theme || {})
          }
        }

        componentWillReceiveProps(nextProps) {
          if (this.props.theme !== nextProps.theme) {
            this.setTheme(nextProps.theme)
          }
        }

        componentDidMount() {
          if (this.context[CHANNEL] && !this.props.theme) {
            this.unsubscribe = this.context[CHANNEL].subscribe(this.setTheme)
          }
        }

        componentWillUnmount() {
          this.unsubscribe && this.unsubscribe()
        }

        setNativeProps(nativeProps) {
          if (this.innerComponent) {
            this.innerComponent.setNativeProps(nativeProps)
          }
        }

        onRef(innerComponent) {
          this.innerComponent = innerComponent
          if (this.props.innerRef) {
            this.props.innerRef(innerComponent)
          }
        }

        render() {
          const props = this.props

          const {toForward, styleOverrides} = splitProps(
            props,
            GlamorousComponent,
          )

          const theme = __DEV__ ?
            Object.freeze(this.state.theme) :
            this.state.theme

          const fullStyles = getStyles(
            GlamorousComponent.styles,
            props,
            styleOverrides,
            theme,
            this.context,
          )

          const isStatelessFunction =
            typeof GlamorousComponent.comp === 'function' &&
            !GlamorousComponent.comp.prototype.render

          return React.createElement(GlamorousComponent.comp, {
            ...toForward,
            ref: isStatelessFunction ? undefined : this.onRef,
            style: fullStyles.length > 0 ? fullStyles : null,
          })
        }
      }

      GlamorousComponent.comp = comp

      GlamorousComponent.propTypes = {
        innerRef: PropTypes.func,
        theme: PropTypes.object,
      }

      const defaultContextTypes = {
        [CHANNEL]: PropTypes.object,
      }
      let userDefinedContextTypes = null

      // configure the contextTypes to be settable by the user,
      // however also retaining the glamorous channel.
      Object.defineProperty(GlamorousComponent, 'contextTypes', {
        enumerable: true,
        configurable: true,
        set(value) {
          userDefinedContextTypes = value
        },
        get() {
          // if the user has provided a contextTypes definition,
          // merge the default context types with the provided ones.
          if (userDefinedContextTypes) {
            return {
              ...defaultContextTypes,
              ...userDefinedContextTypes,
            }
          }
          return defaultContextTypes
        },
      })

      Object.assign(
        GlamorousComponent,
        getGlamorousComponentMetadata({
          comp,
          styles,
          rootEl,
          forwardProps,
          displayName,
        }),
      )

      return GlamorousComponent
    }
  }
}

function getGlamorousComponentMetadata({
  comp,
  styles,
  rootEl,
  forwardProps,
  displayName,
}) {
  const componentsComp = comp.comp ? comp.comp : comp

  return {
    styles: when(comp.styles, styles),
    comp: componentsComp,
    rootEl: rootEl || componentsComp,
    forwardProps: when(comp.forwardProps, forwardProps),
    displayName: displayName || `glamorous(${getDisplayName(comp)})`,
  }
}

function when(comp, prop) {
  return comp ? comp.concat(prop) : prop
}

function getDisplayName(comp) {
  return typeof comp === 'string' ?
    comp :
    comp.displayName || comp.name || 'unknown'
}
<|endoftext|>


<commit_before>import { timer } from 'd3-timer';
import getStyleValues from './style-values';

// particle animation used under GPL license from https://bl.ocks.org/mbostock/280d83080497c8c13152 and http://mustafasaifee.com/

export default function initAnimation(port) {
  port.subscribe(([ id, isSplashScreen ]) => {

    //wait until element is rendered
    let counter = 0;
    const timeoutId = setInterval(function () {
      counter += 1;

      const el = document.getElementById(id);

      if (el) {
        clearTimeout(timeoutId);
        init(el);
      } else if (counter > 10) {
        clearTimeout(timeoutId);
      }
    }, 20);

    function init(canvas) {
      var context = canvas.getContext("2d");

      const { navbarHeight, pink, green, white } = getStyleValues();

      const offset = isSplashScreen ? 0 : navbarHeight
      const color = isSplashScreen ? [ white, white ] : [pink, green];
      const stk = color;

      canvas.onclick = create;

      canvas.width  = window.innerWidth;
      canvas.height  = window.innerHeight - offset;
      var width = canvas.width,
          height = canvas.height,
          rad = 1.5,
          minDistance = 40,
          maxDistance = 150,
          minDistance2 = minDistance * minDistance,
          maxDistance2 = maxDistance * maxDistance;
      var tau = 2 * Math.PI,
          n = 20,
          particles = new Array(n);

      for (var i = 0; i < n; ++i) {
        var color_index = Math.floor(Math.random() * 2)
        var stk_index = Math.floor(Math.random() * 2)
        particles[i] = {
          x: Math.random() * width,
          y: Math.random() * height,
          vx: 0,
          vy: 0,
          radius: Math.ceil((Math.abs(Math.random() - .5)*10)+1),
          col: color[color_index],
          stroke: stk[stk_index]
        };
      }

      timer(function(elapsed) {
        context.save();
        context.clearRect(0, 0, width, height);

        for (let i = 0; i < n; ++i) {
          for (var j = i + 1; j < n; ++j) {
            var pi = particles[i],
                   pj = particles[j],
                   dx = pi.x - pj.x,
                   dy = pi.y - pj.y,
                   d2 = dx * dx + dy * dy;
            if (d2 < maxDistance2) {
              context.globalAlpha = d2 > minDistance2 ? ((maxDistance2 - d2) / (maxDistance2 - minDistance2))/2 : 1;
              context.beginPath();
              context.moveTo(pi.x, pi.y);
              context.lineTo(pj.x, pj.y);
              context.strokeStyle = pi.stroke;
              context.stroke();
            }
          }
        }

        for (let i = 0; i < n; ++i) {
          var p = particles[i];

          p.x += p.vx;
          if (p.x < -maxDistance)
            p.x += width + maxDistance * 2;
          else if (p.x > width + maxDistance)
            p.x -= width + maxDistance * 2;

          p.y += p.vy;
          if (p.y < -maxDistance)
            p.y += height + maxDistance * 2;
          else if (p.y > height + maxDistance)
            p.y -= height + maxDistance * 2;

          p.vx += 0.1 * (Math.random() - .5) - 0.01 * p.vx;
          p.vy += 0.1 * (Math.random() - .5) - 0.01 * p.vy;

          context.beginPath();

          context.globalAlpha = 1;

          context.arc(p.x, p.y, p.radius, 0, tau);

          context.fillStyle = p.col;

          context.fill();

          context.restore();
        }
      });

      function create(event){
        var x1 = event.clientX;
        var y1 = event.clientY - offset + window.pageYOffset;
        n = n + 1;
        var color_index = Math.floor(Math.random() * 5)
        var stk_index = Math.floor(Math.random() * 4)
        particles.push({
          x: x1,
          y: y1,
          vx: 0,
          vy: 0,
          radius: Math.ceil((Math.abs(Math.random() - .5)*10)+1),
          col: color[color_index],
          stroke: stk[stk_index]
        });
      }

    }
  })
}

<commit_msg>Scale animation on window resize<commit_after>import { timer } from 'd3-timer';
import getStyleValues from './style-values';

// particle animation used under GPL license from https://bl.ocks.org/mbostock/280d83080497c8c13152 and http://mustafasaifee.com/

export default function initAnimation(port) {
  port.subscribe(([ id, isSplashScreen ]) => {

    //wait until element is rendered
    let counter = 0;
    const timeoutId = setInterval(function () {
      counter += 1;

      const el = document.getElementById(id);

      if (el) {
        clearTimeout(timeoutId);
        init(el);
      } else if (counter > 10) {
        clearTimeout(timeoutId);
      }
    }, 20);

    function init(canvas) {
      var context = canvas.getContext("2d");

      const { navbarHeight, pink, green, white } = getStyleValues();

      const offset = isSplashScreen ? 0 : navbarHeight
      const color = isSplashScreen ? [ white, white ] : [pink, green];
      const stk = color;

      canvas.onclick = create;

      canvas.width  = window.innerWidth;
      canvas.height  = window.innerHeight - offset;
      var width = canvas.width,
          height = canvas.height,
          rad = 1.5,
          minDistance = 40,
          maxDistance = 150,
          minDistance2 = minDistance * minDistance,
          maxDistance2 = maxDistance * maxDistance;
      var tau = 2 * Math.PI,
          n = 20,
          particles = new Array(n);

      for (var i = 0; i < n; ++i) {
        var color_index = Math.floor(Math.random() * 2)
        var stk_index = Math.floor(Math.random() * 2)
        particles[i] = {
          x: Math.random() * width,
          y: Math.random() * height,
          vx: 0,
          vy: 0,
          radius: Math.ceil((Math.abs(Math.random() - .5)*10)+1),
          col: color[color_index],
          stroke: stk[stk_index]
        };
      }

      timer(function(elapsed) {
        context.save();
        context.clearRect(0, 0, width, height);

        for (let i = 0; i < n; ++i) {
          for (var j = i + 1; j < n; ++j) {
            var pi = particles[i],
                   pj = particles[j],
                   dx = pi.x - pj.x,
                   dy = pi.y - pj.y,
                   d2 = dx * dx + dy * dy;
            if (d2 < maxDistance2) {
              context.globalAlpha = d2 > minDistance2 ? ((maxDistance2 - d2) / (maxDistance2 - minDistance2))/2 : 1;
              context.beginPath();
              context.moveTo(pi.x, pi.y);
              context.lineTo(pj.x, pj.y);
              context.strokeStyle = pi.stroke;
              context.stroke();
            }
          }
        }

        for (let i = 0; i < n; ++i) {
          var p = particles[i];

          p.x += p.vx;
          if (p.x < -maxDistance)
            p.x += width + maxDistance * 2;
          else if (p.x > width + maxDistance)
            p.x -= width + maxDistance * 2;

          p.y += p.vy;
          if (p.y < -maxDistance)
            p.y += height + maxDistance * 2;
          else if (p.y > height + maxDistance)
            p.y -= height + maxDistance * 2;

          p.vx += 0.1 * (Math.random() - .5) - 0.01 * p.vx;
          p.vy += 0.1 * (Math.random() - .5) - 0.01 * p.vy;

          context.beginPath();

          context.globalAlpha = 1;

          context.arc(p.x, p.y, p.radius, 0, tau);

          context.fillStyle = p.col;

          context.fill();

          context.restore();
        }
      });

      function onResize() {
        const { navbarHeight } = getStyleValues();
        const offset = isSplashScreen ? 0 : navbarHeight

        canvas.width  = window.innerWidth;
        const widthRatio = width / canvas.width;
        width = canvas.width;

        canvas.height  = window.innerHeight - offset;
        const heightRatio = height / canvas.height;
        height = canvas.height;

        particles.forEach(particle => {
          particle.x /= widthRatio;
          particle.y /= heightRatio;
        })
      }

      // from MDN
      (function() {
        window.addEventListener("resize", resizeThrottler, false);

        var resizeTimeout;
        function resizeThrottler() {
          // ignore resize events as long as an actualResizeHandler execution is in the queue
          if ( !resizeTimeout ) {
            resizeTimeout = setTimeout(function() {
              resizeTimeout = null;
              onResize();

              // The actualResizeHandler will execute at a rate of 15fps
            }, 66);
          }
        }
      }());

      function create(event){
        var x1 = event.clientX;
        var y1 = event.clientY - offset + window.pageYOffset;
        n = n + 1;
        var color_index = Math.floor(Math.random() * 5)
        var stk_index = Math.floor(Math.random() * 4)
        particles.push({
          x: x1,
          y: y1,
          vx: 0,
          vy: 0,
          radius: Math.ceil((Math.abs(Math.random() - .5)*10)+1),
          col: color[color_index],
          stroke: stk[stk_index]
        });
      }

    }
  })
}
<|endoftext|>


<commit_before>var fs        = require('fs');
var normalize = require("../lib/timings_normalize.js");
var validate  = require("../lib/timings_validate.js");

module.exports = function(app) {
    app.post("/", function(req, res) {
        var performance = req.body;

        if (validate(performance.timing)) {
            performance.timing = normalize(performance.timing);
            app.emit('data', {
                performance: performance,
                userAgent: req.headers["user-agent"],
                referer: req.headers.referer,
                remoteAddress: req.connection.remoteAddress
            });

            res.send(204);
        } else {
            res.send(400);
        }
    });
    app.options("/", function(req, res) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Headers", "X-Requested-With, origin, Content-Type");
        res.send();
    });

    app.get("/client.js", function(req, res) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header("Content-Type", "application/javascript");
        fs.createReadStream(__dirname + "/../public/client.js").pipe(res);
    });
};
<commit_msg>remove headers because they are sent through the moddleware<commit_after>var fs        = require('fs');
var normalize = require("../lib/timings_normalize.js");
var validate  = require("../lib/timings_validate.js");

module.exports = function(app) {
    app.post("/", function(req, res) {
        var performance = req.body;

        if (validate(performance.timing)) {
            performance.timing = normalize(performance.timing);
            app.emit('data', {
                performance: performance,
                userAgent: req.headers["user-agent"],
                referer: req.headers.referer,
                remoteAddress: req.connection.remoteAddress
            });

            res.send(204);
        } else {
            res.send(400);
        }
    });
    app.options("/", function(req, res) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Headers", "X-Requested-With, origin, Content-Type");
        res.send();
    });

    app.get("/client.js", function(req, res) {
        fs.createReadStream(__dirname + "/../public/client.js").pipe(res);
    });
};
<|endoftext|>


<commit_before>/* eslint-env browser, jquery */
/* eslint quotes: [2, "single"], strict: 0 */
/* global Handlebars:false */

var cardTemplate;

function card (title, image, location, price, power, registration, mileage, consumption) {
    return {
        title: title,
        image: image,
        location: location,
        price: price,
        power: power,
        registration: registration,
        mileage: mileage,
        consumption: consumption
    };
}

var cards = [
    card('Audi A6', 'http://lorempixel.com/400/300/transport/', 'August-Bebel-Str. 4, 14482 Potsdam', '34000', '140', '2006', '23000', '7'),
    card('VW Polo', 'http://i.ebayimg.com/00/s/NjAwWDgwMA==/z/IVgAAOSwPhdU-FPW/$_8.jpg', 'August-Bebel-Str. 12, 15345 Rehfelde', '5600', '90', '1997', '230000', '6'),
    card('Kaputte Karre', 'http://i.ebayimg.com/00/s/NDgwWDY0MA==/$T2eC16VHJGYFFlLe3qSvBReifcZW2!~~48_8.jpg', 'Großer Stern, 10355 Berlin', '300', '80', '2000', '104000', '14')
];

function templates () {
    cardTemplate = Handlebars.compile($('#card-template').html());
}

function UI () {
    var self = this;
    self.player = {
        name: ''
    };
    self.position = null;

    self.$allViews = $('.startView, .compareView, .cardView, .waitingView');

    $('#usernameForm').submit(function (e) {
        e.preventDefault();
        var data = {
            action: 'init',
            name: '',
            data: {
                lat: self.position.lat,
                long: self.position.lng
            }
        };

        if ($.trim($('#usernameForm #username').val()) === '') {
            alert('kein Username eingegeben');
        } else {
            data.name = $.trim($('#usernameForm #username').val());
            self.player.name = data.name;
            self.socket.send(JSON.stringify(data));
        }
    });

    $('.cardView').on('click', 'button', function () {
        self.disableCardButtons();
        var attributeToCompare = $(this).data('attribute');
        window.setInterval(function () {
            console.log('send selected attribute');
            self.socket.send(JSON.stringify({
                action: 'attributeSelected',
                name: self.player.name,
                data: {
                    attributeToCompare: attributeToCompare
                }
            }));
        }, 1000);
    });

    navigator.geolocation.getCurrentPosition(
        function (position) {
            self.setPosition(position);
        },
        self.positionError
    );

    templates();

    self.socket = new WebSocket('ws://localhost:8080', []);

    self.socket.onopen = function () {
        console.info('connected to server');
    };

    // Log errors
    self.socket.onerror = function (error) {
        console.log('WebSocket Error ' + error);
    };

    // Log messages from the server
    self.socket.onmessage = function (e) {
        // e is event object
        // server message is in e.data
        console.log('Server: ', e.data);

        var response = JSON.parse(e.data);
        switch (response.action) {
            case 'accepted':
                self.activateView('.waitingView');
                break;
            case 'start':
            case 'next':
                if (response.data.winnerCard) {
                    self.createCompareView(response.data.all_cards, response.data.winnerCard, response.data.card);
                } else {
                    self.startNextRound(response.data.card, response.data.turn);
                }
                break;
            default:
                break;
        }
    };
}

UI.prototype.setPosition = function (position) {
    this.position = {
        lat: position.coords.latitude,
        lng: position.coords.longitude
    };
    $('#locationMessage').hide();
    $('#usernameForm').show();
};

UI.prototype.positionError = function (err) {
    var message = '';
    if (err.code === 1) {
        message = 'Du musst deinen Standort mitteilen, um spielen zu k\u00f6nnen.';
    } else if (err.code === 2) {
        message = 'Dein Standort konnte nicht ermittelt werden.';
    }
    $('#locationMessage')
        .removeClass('panel-default')
        .addClass('panel-danger');
    $('#locationMessage .panel-body').html(message);
    console.log(err.code);
};

UI.prototype.createCompareView = function (cards, winnerCard, nextCard) {
    this.activateView('.compareView');
    $('.compareView').html('');

    cards.forEach(function (e) {
        $('.compareView').append(cardTemplate(e));
    });

    if (nextCard !== undefined) {
        var nextButton = $('<button>Weiter</button>');
        nextButton.addClass('nextRoundButton');
        nextButton.click(function () {
            this.createCardView(nextCard);
        });
        $('.compareView').append(nextButton);
    }
};

UI.prototype.createCardView = function (card) {
    this.activateView('.cardView');

    $('.cardView').html(cardTemplate(JSON.parse(card)));
};

UI.prototype.activateView = function (view) {
    this.$allViews.hide();
    $(view).show();
};

UI.prototype.setActivePlayer = function (playerName) {
    if (playerName !== this.player.name) {
        this.disableCardButtons();
    }
};

UI.prototype.disableCardButtons = function () {
    $('.card button').addClass('disabled');
};

UI.prototype.startNextRound = function (card, turn) {
    this.createCardView(card);
    this.setActivePlayer(turn);
};

var userInterface = new UI();
<commit_msg>send selected attribute once only<commit_after>/* eslint-env browser, jquery */
/* eslint quotes: [2, "single"], strict: 0 */
/* global Handlebars:false */

var cardTemplate;

function card (title, image, location, price, power, registration, mileage, consumption) {
    return {
        title: title,
        image: image,
        location: location,
        price: price,
        power: power,
        registration: registration,
        mileage: mileage,
        consumption: consumption
    };
}

var cards = [
    card('Audi A6', 'http://lorempixel.com/400/300/transport/', 'August-Bebel-Str. 4, 14482 Potsdam', '34000', '140', '2006', '23000', '7'),
    card('VW Polo', 'http://i.ebayimg.com/00/s/NjAwWDgwMA==/z/IVgAAOSwPhdU-FPW/$_8.jpg', 'August-Bebel-Str. 12, 15345 Rehfelde', '5600', '90', '1997', '230000', '6'),
    card('Kaputte Karre', 'http://i.ebayimg.com/00/s/NDgwWDY0MA==/$T2eC16VHJGYFFlLe3qSvBReifcZW2!~~48_8.jpg', 'Großer Stern, 10355 Berlin', '300', '80', '2000', '104000', '14')
];

function templates () {
    cardTemplate = Handlebars.compile($('#card-template').html());
}

function UI () {
    var self = this;
    self.player = {
        name: ''
    };
    self.position = null;

    self.$allViews = $('.startView, .compareView, .cardView, .waitingView');

    $('#usernameForm').submit(function (e) {
        e.preventDefault();
        var data = {
            action: 'init',
            name: '',
            data: {
                lat: self.position.lat,
                long: self.position.lng
            }
        };

        if ($.trim($('#usernameForm #username').val()) === '') {
            alert('kein Username eingegeben');
        } else {
            data.name = $.trim($('#usernameForm #username').val());
            self.player.name = data.name;
            self.socket.send(JSON.stringify(data));
        }
    });

    $('.cardView').on('click', 'button', function () {
        self.disableCardButtons();
        var attributeToCompare = $(this).data('attribute');
        console.log('send selected attribute');
        self.socket.send(JSON.stringify({
            action: 'attributeSelected',
            name: self.player.name,
            data: {
                attributeToCompare: attributeToCompare
            }
        }));
    });

    navigator.geolocation.getCurrentPosition(
        function (position) {
            self.setPosition(position);
        },
        self.positionError
    );

    templates();

    self.socket = new WebSocket('ws://localhost:8080', []);

    self.socket.onopen = function () {
        console.info('connected to server');
    };

    // Log errors
    self.socket.onerror = function (error) {
        console.log('WebSocket Error ' + error);
    };

    // Log messages from the server
    self.socket.onmessage = function (e) {
        // e is event object
        // server message is in e.data
        console.log('Server: ', e.data);

        var response = JSON.parse(e.data);
        switch (response.action) {
            case 'accepted':
                self.activateView('.waitingView');
                break;
            case 'start':
            case 'next':
                if (response.data.winnerCard) {
                    self.createCompareView(response.data.all_cards, response.data.winnerCard, response.data.card);
                } else {
                    self.startNextRound(response.data.card, response.data.turn);
                }
                break;
            default:
                break;
        }
    };
}

UI.prototype.setPosition = function (position) {
    this.position = {
        lat: position.coords.latitude,
        lng: position.coords.longitude
    };
    $('#locationMessage').hide();
    $('#usernameForm').show();
};

UI.prototype.positionError = function (err) {
    var message = '';
    if (err.code === 1) {
        message = 'Du musst deinen Standort mitteilen, um spielen zu k\u00f6nnen.';
    } else if (err.code === 2) {
        message = 'Dein Standort konnte nicht ermittelt werden.';
    }
    $('#locationMessage')
        .removeClass('panel-default')
        .addClass('panel-danger');
    $('#locationMessage .panel-body').html(message);
    console.log(err.code);
};

UI.prototype.createCompareView = function (cards, winnerCard, nextCard) {
    this.activateView('.compareView');
    $('.compareView').html('');

    cards.forEach(function (e) {
        $('.compareView').append(cardTemplate(e));
    });

    if (nextCard !== undefined) {
        var nextButton = $('<button>Weiter</button>');
        nextButton.addClass('nextRoundButton');
        nextButton.click(function () {
            this.createCardView(nextCard);
        });
        $('.compareView').append(nextButton);
    }
};

UI.prototype.createCardView = function (card) {
    this.activateView('.cardView');

    $('.cardView').html(cardTemplate(JSON.parse(card)));
};

UI.prototype.activateView = function (view) {
    this.$allViews.hide();
    $(view).show();
};

UI.prototype.setActivePlayer = function (playerName) {
    if (playerName !== this.player.name) {
        this.disableCardButtons();
    }
};

UI.prototype.disableCardButtons = function () {
    $('.card button').addClass('disabled');
};

UI.prototype.startNextRound = function (card, turn) {
    this.createCardView(card);
    this.setActivePlayer(turn);
};

var userInterface = new UI();
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var exec = require('child_process').exec;

var assert = module.exports = exports = require('assert');

var overwrite = false;

assert.imageEqualsFile = function(buffer, file_b, callback) {
    if (overwrite) {
        var err = fs.writeFileSync(file_b, buffer);
        if (err) throw err;
        callback(null);
    }
    if (!callback) callback = function(err) { if (err) throw err; };
    file_b = path.resolve(file_b);
    var file_a = '/tmp/' + (Math.random() * 1e16 + path.extname(file_b));
    var diff = file_a + '-diff.png';
    var err = fs.writeFileSync(file_a, buffer);
    if (err) throw err;

    exec('compare -metric PSNR "' + file_a + '" "' +
            file_b + '" "' + diff + '"', function(err, stdout, stderr) {
        if (err) {
            fs.unlinkSync(file_a);
            callback(err);
        } else {
            stderr = stderr.trim();
            if (stderr === 'inf') {
                fs.unlinkSync(file_a);
                callback(null);
            } else {
                var similarity = parseFloat(stderr);
                if (similarity < 65) {
                    var err = new Error('Images not equal(' + similarity + '):\n\t' +
                            file_a  + '\n\t' + file_b + '\n\t' + diff);
                    err.similarity = similarity;
                    callback(err);
                } else {
                    fs.unlinkSync(file_a);
                    callback(null);
                }
            }
        }
    });
};
<commit_msg>compare returns non-zero when images differ<commit_after>var fs = require('fs');
var path = require('path');
var exec = require('child_process').exec;

var assert = module.exports = exports = require('assert');

var overwrite = false;

assert.imageEqualsFile = function(buffer, file_b, callback) {
    if (overwrite) {
        var err = fs.writeFileSync(file_b, buffer);
        if (err) throw err;
        callback(null);
    }
    if (!callback) callback = function(err) { if (err) throw err; };
    file_b = path.resolve(file_b);
    var file_a = '/tmp/' + (Math.random() * 1e16 + path.extname(file_b));
    var diff = file_a + '-diff.png';
    var err = fs.writeFileSync(file_a, buffer);
    if (err) throw err;

    exec('compare -metric PSNR "' + file_a + '" "' +
            file_b + '" "' + diff + '"', function(err, stdout, stderr) {
        fs.unlinkSync(file_a);
        fs.unlinkSync(diff);

        stderr = stderr.trim();
        if (stderr === 'inf') {
            callback(null);
        } else {
            var similarity = parseFloat(stderr);
            if (similarity < 65) {
                var err = new Error('Images not equal(' + similarity + '):\n\t' +
                        file_a  + '\n\t' + file_b + '\n\t' + diff);
                err.similarity = similarity;
                callback(err);
            } else {
                callback(null);
            }
        }
    });
};
<|endoftext|>


<commit_before>const http = require('http')
const url = require('url')
const path = require('path')
const fs = require('fs')
const mimeTypes = {
  html: 'text/html',
  jpeg: 'image/jpeg',
  jpg: 'image/jpeg',
  png: 'image/png',
  js: 'text/javascript',
  css: 'text/css'
}

const server = http.createServer((req, res) => {
  let uri = url.parse(req.url).pathname

  if (uri === '/') uri = '/index.html'

  const filename = path.join(__dirname, uri)
  fs.exists(filename, (exists) => {
    if (!exists) {
      res.writeHead(404, {'Content-Type': 'text/plain'})
      res.write('404 Not Found\n')
      res.end()
      return
    }
    var mimeType = mimeTypes[path.extname(filename).split('.')[1]]
    res.writeHead(200, {'Content-Type': mimeType})

    var fileStream = fs.createReadStream(filename)
    fileStream.pipe(res)
  })
})

function start () {
  server.listen(8087)
}

function stop () {
  server.close()
}

if (require.main === module) {
  console.log('Server listening on port 8087')
  start()
}

module.exports = {
  start,
  stop
}
<commit_msg>chore(test app): Scrict mode enebled in test app server<commit_after>'use strict'

const http = require('http')
const url = require('url')
const path = require('path')
const fs = require('fs')
const mimeTypes = {
  html: 'text/html',
  jpeg: 'image/jpeg',
  jpg: 'image/jpeg',
  png: 'image/png',
  js: 'text/javascript',
  css: 'text/css'
}

const server = http.createServer((req, res) => {
  let uri = url.parse(req.url).pathname

  if (uri === '/') uri = '/index.html'

  const filename = path.join(__dirname, uri)
  fs.exists(filename, (exists) => {
    if (!exists) {
      res.writeHead(404, {'Content-Type': 'text/plain'})
      res.write('404 Not Found\n')
      res.end()
      return
    }
    var mimeType = mimeTypes[path.extname(filename).split('.')[1]]
    res.writeHead(200, {'Content-Type': mimeType})

    var fileStream = fs.createReadStream(filename)
    fileStream.pipe(res)
  })
})

function start () {
  server.listen(8087)
}

function stop () {
  server.close()
}

if (require.main === module) {
  console.log('Server listening on port 8087')
  start()
}

module.exports = {
  start,
  stop
}
<|endoftext|>


<commit_before>var fs = require('fs');
var assert = require('assert');
var config = require('./config.json');
var zmq = require('zmq');
var constants = require('../constants');

if(!config.chaski.ip) {
    console.log('Must give chaski info');
    process.exit(9);
}

describe('Array', function() {
    describe('#indexOf()', function() {
        it('should return -1 when the value is not present', function() {
            assert.equal(-1, [1, 2, 3].indexOf(5));
            assert.equal(-1, [1, 2, 3].indexOf(0));
        });
    });
});

describe('Request a chaski worker', function() {
    it('message response IP should be equal to CHASKI given IP', function (done) {

        var chaskiNotifier = require('../worker/chaskiNotifier')
        ({
            "ipChaski": config.chaski.ip,
            "verbose" : constants.LOG_LEVEL_ERROR
        });
        var chaskiAssigner = require('../worker/chaskiAssigner')
        ({
            "ipChaski": config.chaski.ip,
            "chaskiNotifier": chaskiNotifier,
            "verbose" : constants.LOG_LEVEL_ERROR
        });

        var chaski = zmq.socket('rep');
        chaski.bind('tcp://'+ config.chaski.ip + ':' + constants.PORT_CHASKI_CHANNEL_NOTIFIER);
        chaski.on('message', function(result, data) {
            var parsedResponse = JSON.parse(data);
            console.log(result, data);
        });

        var client = zmq.socket('req');
        client.connect('tcp://'+ config.client.ip + ':' + constants.PORT_CHASKI_ASSIGNER);
        var dataToSend = { id: config.client.id };
        client.send(JSON.stringify(dataToSend));

        client.on('message', function(result, data) {
            var parsedResponse = JSON.parse(data);
            assert.equal(result, 200);
            assert.equal(parsedResponse.ip, config.chaski.ip);
            done();
        });
    });
});<commit_msg>modified test<commit_after>var fs = require('fs');
var assert = require('assert');
var config = require('./config.json');
var zmq = require('zmq');
var constants = require('../constants');

if(!config.chaski.ip) {
    console.log('Must give chaski info');
    process.exit(9);
}

describe('Array', function() {
    describe('#indexOf()', function() {
        it('should return -1 when the value is not present', function() {
            assert.equal(-1, [1, 2, 3].indexOf(5));
            assert.equal(-1, [1, 2, 3].indexOf(0));
        });
    });
});

describe('Request a chaski worker', function() {
    var chaski = zmq.socket('rep');
    var client = zmq.socket('req');

    it('message response IP should be equal to CHASKI given IP', function (done) {

        var chaskiNotifier = require('../worker/chaskiNotifier')
        ({
            "ipChaski": config.chaski.ip,
            "verbose" : constants.LOG_LEVEL_ERROR
        });
        var chaskiAssigner = require('../worker/chaskiAssigner')
        ({
            "ipChaski": config.chaski.ip,
            "chaskiNotifier": chaskiNotifier,
            "verbose" : constants.LOG_LEVEL_ERROR
        });

        chaski.bind('tcp://'+ config.chaski.ip + ':' + constants.PORT_CHASKI_CHANNEL_NOTIFIER);
        chaski.on('message', function(result, data) {
            var parsedResponse = JSON.parse(data);
            console.log(result, data);
        });

        client.connect('tcp://'+ config.client.ip + ':' + constants.PORT_CHASKI_ASSIGNER);
        var dataToSend = { id: config.client.id };
        client.send(JSON.stringify(dataToSend));

        client.on('message', function(result, data) {
            var parsedResponse = JSON.parse(data);
            assert.equal(result, 200);
            assert.equal(parsedResponse.ip, config.chaski.ip);
            done();
        });
    });

    after( function (done) {
        console.log('after test');
        chaski.close();
        done();
    });
});<|endoftext|>