<commit_before>import Formatters from 'messageformat-formatters';
import Compiler from './compiler';
import { funcname, propname } from './utils';
import { getAllPlurals, getPlural } from './plurals';
import Runtime from './runtime';

export default class MessageFormat {
  /**
   * The default locale
   *
   * Used by the constructor when no `locale` has been set to initialise the value
   * of its instance counterpart, `MessageFormat#defaultLocale`.
   *
   * @memberof MessageFormat
   * @default 'en'
   */
  static defaultLocale = 'en';

  /** Escape special characaters
   *
   *  Surround the characters `{` and `}` in the input string with 'quotes'.
   *  This will allow those characters to not be considered as MessageFormat
   *  control characters.
   *
   * @memberof MessageFormat
   * @param {string} str - The input string
   * @param {boolean} [octothorpe=false] - Include `#` in the escaped characters
   * @returns {string} The escaped string
   */
  static escape(str, octothorpe) {
    const esc = octothorpe ? /[#{}]/g : /[{}]/g;
    return String(str).replace(esc, "'$&'");
  }

  /**
   * Create a new MessageFormat compiler
   *
   * If set, the `locale` parameter limits the compiler to use a subset of the 204
   * languages' pluralisation rules made available by the Unicode CLDR.
   *
   * Leaving `locale` undefined or using an array of strings will create a
   * MessageFormat instance with multi-language support. To select which to use,
   * use the second parameter of `{@link MessageFormat#compile compile()}`, or use
   * message keys corresponding to your locales. The default locale will be the
   * first entry of the array, or `{@link MessageFormat.defaultLocale defaultLocale}`
   * if not set.
   *
   * A string `locale` will create a single-locale MessageFormat instance.
   *
   * Using an object `locale` with all properties of type `function` allows for
   * the use of custom or externally defined pluralisation rules; in this case
   *
   * @class MessageFormat
   * @classdesc MessageFormat-to-JavaScript compiler
   * @param {string|string[]|Object} [locale] - The locale(s) to use
   * @param {Object} [options] - Compiler options
   * @param {boolean} [options.biDiSupport=false] - Add Unicode control
   *   characters to all input parts to preserve the integrity of the output
   *   when mixing LTR and RTL text
   * @param {Object} [options.customFormatters] - Map of custom formatting
   *   functions to include. See the {@tutorial guide} for more details.
   * @param {boolean} [options.strictNumberSign=false] - Allow `#` only directly
   *   within a plural or selectordinal case, rather than in any inner select
   *   case as well.
   *
   * ```
   * import MessageFormat from 'messageformat'
   * ```
   */
  constructor(locale, options) {
    this.options = Object.assign(
      {
        biDiSupport: false,
        customFormatters: {},
        strictNumberSign: false
      },
      options
    );
    this.pluralFuncs = {};
    if (typeof locale === 'string') {
      this.pluralFuncs[locale] = getPlural(locale);
      this.defaultLocale = locale;
    } else if (Array.isArray(locale)) {
      locale.forEach(lc => {
        this.pluralFuncs[lc] = getPlural(lc);
      });
      this.defaultLocale = locale[0];
    } else {
      if (locale) {
        const lcKeys = Object.keys(locale);
        for (let i = 0; i < lcKeys.length; ++i) {
          const lc = lcKeys[i];
          if (typeof locale[lc] !== 'function') {
            const errMsg = 'Expected function value for locale ' + String(lc);
            throw new Error(errMsg);
          }
          this.pluralFuncs[lc] = locale[lc];
          if (!this.defaultLocale) this.defaultLocale = lc;
        }
      }
      if (this.defaultLocale) {
        this.hasCustomPluralFuncs = true;
      } else {
        this.defaultLocale = MessageFormat.defaultLocale;
        this.hasCustomPluralFuncs = false;
      }
    }
  }

  /** @private */
  getFormatter(key) {
    const cf = this.options.customFormatters[key];
    if (cf) return cf;
    const df = Formatters[key];
    if (df) return df(this);
    throw new Error(`Formatting function ${JSON.stringify(key)} not found`);
  }

  /**
   * Compile messages into storable functions
   *
   * If `messages` is a single string including ICU MessageFormat declarations,
   * the result of `compile()` is a function taking a single Object parameter
   * `d` representing each of the input's defined variables.
   *
   * If `messages` is a hierarchical structure of such strings, the output of
   * `compile()` will match that structure, with each string replaced by its
   * corresponding JavaScript function.
   *
   * If the input `messages` -- and therefore the output -- of `compile()` is an
   * object, the output object will have a `toString(global)` method that may be
   * used to store or cache the compiled functions to disk, for later inclusion
   * in any JS environment, without a local MessageFormat instance required. If
   * its `global` parameter is null or undefined, the result is an ES6 module
   * with a default export. If `global` is a string containing `.`, the result
   * will be a script setting its value. Otherwise, the output defaults to an UMD
   * pattern that sets the value of `global` if used outside of AMD and CommonJS
   * loaders.
   *
   * If `locale` is not set, it will default to
   * `{@link MessageFormat.defaultLocale defaultLocale}`; using a key at any
   * depth of `messages` that is a declared locale will set its child elements to
   * use that locale.
   *
   * If `locale` is set, it is used for all messages, ignoring any otherwise
   * matching locale keys. If the constructor declared any locales, `locale`
   * needs to be one of them.
   *
   * If `compile()` is called with a `messages` object on a MessageFormat
   * instance that does not specify any locales, it will match keys to *all* 204
   * available locales. This is really useful if you want your messages to be
   * completely determined by your data, but may provide surprising results if
   * your input includes any 2-3 letter strings that are not locale identifiers.
   *
   * @memberof MessageFormat
   * @instance
   * @param {string|Object} messages - The input message(s) to be compiled, in ICU MessageFormat
   * @param {string} [locale] - A locale to use for the messages
   * @returns {function|Object} The first match found for the given locale(s)
   *
   * @example
   * const mf = new MessageFormat('en')
   * const msg = mf.compile('A {TYPE} example.')
   *
   * msg({ TYPE: 'simple' })  // 'A simple example.'
   *
   * @example
   * const mf = new MessageFormat(['en', 'fi'])
   * const messages = mf.compile({
   *   en: { a: 'A {TYPE} example.',
   *         b: 'This is the {COUNT, selectordinal, one{#st} two{#nd} few{#rd} other{#th}} example.' },
   *   fi: { a: '{TYPE} esimerkki.',
   *         b: 'Tämä on {COUNT, selectordinal, other{#.}} esimerkki.' }
   * })
   *
   * messages.en.b({ COUNT: 2 })  // 'This is the 2nd example.'
   * messages.fi.b({ COUNT: 2 })  // 'Tämä on 2. esimerkki.'
   *
   * @example
   * const fs = require('fs')
   * const mf = new MessageFormat('en')
   * const msgSet = {
   *   a: 'A {TYPE} example.',
   *   b: 'This has {COUNT, plural, one{one member} other{# members}}.',
   *   c: 'We have {P, number, percent} code coverage.'
   * }
   * const msgStr = mf.compile(msgSet).toString('module.exports')
   * fs.writeFileSync('messages.js', msgStr)
   *
   * ...
   *
   * const messages = require('./messages')
   *
   * messages.a({ TYPE: 'more complex' })  // 'A more complex example.'
   * messages.b({ COUNT: 3 })              // 'This has 3 members.'
   */
  compile(messages, locale) {
    function _stringify(obj, level) {
      if (!level) level = 0;
      if (typeof obj != 'object') return obj;
      let indent = '';
      for (let i = 0; i < level; ++i) indent += '  ';
      const o = [];
      for (const k in obj) {
        const v = _stringify(obj[k], level + 1);
        o.push(`\n${indent}  ${propname(k)}: ${v}`);
      }
      return `{${o.join(',')}\n${indent}}`;
    }

    let pf = {};
    if (Object.keys(this.pluralFuncs).length === 0) {
      if (locale) {
        const pfn0 = getPlural(locale);
        if (!pfn0) {
          const lcs = JSON.stringify(locale);
          throw new Error(`Locale ${lcs} not found!`);
        }
        pf[locale] = pfn0;
      } else {
        locale = this.defaultLocale;
        pf = getAllPlurals();
      }
    } else if (locale) {
      const pfn1 = this.pluralFuncs[locale];
      if (!pfn1) {
        const lcs = JSON.stringify(locale);
        const pfs = JSON.stringify(this.pluralFuncs);
        throw new Error(`Locale ${lcs} not found in ${pfs}!`);
      }
      pf[locale] = pfn1;
    } else {
      locale = this.defaultLocale;
      pf = this.pluralFuncs;
    }

    const compiler = new Compiler(this);
    const obj = compiler.compile(messages, locale, pf);
    const runtime = new Runtime(this.options, compiler, pf);

    if (typeof messages != 'object') {
      const fn = new Function(
        'number, plural, select, fmt',
        funcname(locale),
        'return ' + obj
      );
      return fn(
        runtime.number,
        runtime.plural,
        runtime.select,
        compiler.formatters,
        pf[locale]
      );
    }

    const rtStr = String(runtime) + '\n';
    const objStr = _stringify(obj);
    const result = new Function(rtStr + 'return ' + objStr)();
    // eslint-disable-next-line no-prototype-builtins
    if (result.hasOwnProperty('toString'))
      throw new Error('The top-level message key `toString` is reserved');

    result.toString = function(global) {
      if (!global || global === 'export default') {
        return rtStr + 'export default ' + objStr;
      } else if (global.indexOf('.') > -1) {
        return rtStr + global + ' = ' + objStr;
      } else {
        return (
          rtStr +
          [
            '(function (root, G) {',
            '  if (typeof define === "function" && define.amd) { define(G); }',
            '  else if (typeof exports === "object") { module.exports = G; }',
            '  else { ' + propname(global, 'root') + ' = G; }',
            '})(this, ' + objStr + ');'
          ].join('\n')
        );
      }
    };
    return result;
  }
}
<commit_msg>feat(messageformat): Refactor/clean up compile() internals<commit_after>import Formatters from 'messageformat-formatters';
import Compiler from './compiler';
import { funcname, propname } from './utils';
import { getAllPlurals, getPlural } from './plurals';
import Runtime from './runtime';

function stringifyObject(obj, level) {
  if (!level) level = 0;
  if (typeof obj != 'object') return obj;
  let indent = '';
  for (let i = 0; i < level; ++i) indent += '  ';
  const o = [];
  for (const k in obj) {
    const v = stringifyObject(obj[k], level + 1);
    o.push(`\n${indent}  ${propname(k)}: ${v}`);
  }
  return `{${o.join(',')}\n${indent}}`;
}

export default class MessageFormat {
  /**
   * The default locale
   *
   * Used by the constructor when no `locale` has been set to initialise the value
   * of its instance counterpart, `MessageFormat#defaultLocale`.
   *
   * @memberof MessageFormat
   * @default 'en'
   */
  static defaultLocale = 'en';

  /** Escape special characaters
   *
   *  Surround the characters `{` and `}` in the input string with 'quotes'.
   *  This will allow those characters to not be considered as MessageFormat
   *  control characters.
   *
   * @memberof MessageFormat
   * @param {string} str - The input string
   * @param {boolean} [octothorpe=false] - Include `#` in the escaped characters
   * @returns {string} The escaped string
   */
  static escape(str, octothorpe) {
    const esc = octothorpe ? /[#{}]/g : /[{}]/g;
    return String(str).replace(esc, "'$&'");
  }

  /**
   * Create a new MessageFormat compiler
   *
   * If set, the `locale` parameter limits the compiler to use a subset of the 204
   * languages' pluralisation rules made available by the Unicode CLDR.
   *
   * Leaving `locale` undefined or using an array of strings will create a
   * MessageFormat instance with multi-language support. To select which to use,
   * use the second parameter of `{@link MessageFormat#compile compile()}`, or use
   * message keys corresponding to your locales. The default locale will be the
   * first entry of the array, or `{@link MessageFormat.defaultLocale defaultLocale}`
   * if not set.
   *
   * A string `locale` will create a single-locale MessageFormat instance.
   *
   * Using an object `locale` with all properties of type `function` allows for
   * the use of custom or externally defined pluralisation rules; in this case
   *
   * @class MessageFormat
   * @classdesc MessageFormat-to-JavaScript compiler
   * @param {string|string[]|Object} [locale] - The locale(s) to use
   * @param {Object} [options] - Compiler options
   * @param {boolean} [options.biDiSupport=false] - Add Unicode control
   *   characters to all input parts to preserve the integrity of the output
   *   when mixing LTR and RTL text
   * @param {Object} [options.customFormatters] - Map of custom formatting
   *   functions to include. See the {@tutorial guide} for more details.
   * @param {boolean} [options.strictNumberSign=false] - Allow `#` only directly
   *   within a plural or selectordinal case, rather than in any inner select
   *   case as well.
   *
   * ```
   * import MessageFormat from 'messageformat'
   * ```
   */
  constructor(locale, options) {
    this.options = Object.assign(
      {
        biDiSupport: false,
        customFormatters: {},
        strictNumberSign: false
      },
      options
    );
    this.pluralFuncs = {};
    if (typeof locale === 'string') {
      this.pluralFuncs[locale] = getPlural(locale);
      this.defaultLocale = locale;
    } else if (Array.isArray(locale)) {
      locale.forEach(lc => {
        this.pluralFuncs[lc] = getPlural(lc);
      });
      this.defaultLocale = locale[0];
    } else {
      if (locale) {
        const lcKeys = Object.keys(locale);
        for (let i = 0; i < lcKeys.length; ++i) {
          const lc = lcKeys[i];
          if (typeof locale[lc] !== 'function') {
            const errMsg = 'Expected function value for locale ' + String(lc);
            throw new Error(errMsg);
          }
          this.pluralFuncs[lc] = locale[lc];
          if (!this.defaultLocale) this.defaultLocale = lc;
        }
      }
      if (this.defaultLocale) {
        this.hasCustomPluralFuncs = true;
      } else {
        this.defaultLocale = MessageFormat.defaultLocale;
        this.hasCustomPluralFuncs = false;
      }
    }
  }

  /** @private */
  getFormatter(key) {
    const cf = this.options.customFormatters[key];
    if (cf) return cf;
    const df = Formatters[key];
    if (df) return df(this);
    throw new Error(`Formatting function ${JSON.stringify(key)} not found`);
  }

  /** @private */
  getPluralFuncs(locale) {
    if (Object.keys(this.pluralFuncs).length === 0) {
      if (locale) {
        // no locale in ctor, but given as compile() arg
        const pf = getPlural(locale);
        if (!pf) throw new Error(`Locale ${JSON.stringify(locale)} not found`);
        return { locale, pluralFuncs: { [locale]: pf } };
      } else {
        // no locale at all
        return { locale: this.defaultLocale, pluralFuncs: getAllPlurals() };
      }
    } else if (locale) {
      // locales defined in ctor as well as compile() args
      const pf = this.pluralFuncs[locale];
      if (!pf) {
        const pfk = JSON.stringify(Object.keys(this.pluralFuncs));
        throw new Error(`Locale ${JSON.stringify(locale)} not found in ${pfk}`);
      }
      return { locale, pluralFuncs: { [locale]: pf } };
    } else {
      // locales defined in ctor but not in compile() args
      return { locale: this.defaultLocale, pluralFuncs: this.pluralFuncs };
    }
  }

  /**
   * Compile messages into storable functions
   *
   * If `messages` is a single string including ICU MessageFormat declarations,
   * the result of `compile()` is a function taking a single Object parameter
   * `d` representing each of the input's defined variables.
   *
   * If `messages` is a hierarchical structure of such strings, the output of
   * `compile()` will match that structure, with each string replaced by its
   * corresponding JavaScript function.
   *
   * If the input `messages` -- and therefore the output -- of `compile()` is an
   * object, the output object will have a `toString(global)` method that may be
   * used to store or cache the compiled functions to disk, for later inclusion
   * in any JS environment, without a local MessageFormat instance required. If
   * its `global` parameter is null or undefined, the result is an ES6 module
   * with a default export. If `global` is a string containing `.`, the result
   * will be a script setting its value. Otherwise, the output defaults to an UMD
   * pattern that sets the value of `global` if used outside of AMD and CommonJS
   * loaders.
   *
   * If `locale` is not set, it will default to
   * `{@link MessageFormat.defaultLocale defaultLocale}`; using a key at any
   * depth of `messages` that is a declared locale will set its child elements to
   * use that locale.
   *
   * If `locale` is set, it is used for all messages, ignoring any otherwise
   * matching locale keys. If the constructor declared any locales, `locale`
   * needs to be one of them.
   *
   * If `compile()` is called with a `messages` object on a MessageFormat
   * instance that does not specify any locales, it will match keys to *all* 204
   * available locales. This is really useful if you want your messages to be
   * completely determined by your data, but may provide surprising results if
   * your input includes any 2-3 letter strings that are not locale identifiers.
   *
   * @memberof MessageFormat
   * @instance
   * @param {string|Object} messages - The input message(s) to be compiled, in ICU MessageFormat
   * @param {string} [locale] - A locale to use for the messages
   * @returns {function|Object} The first match found for the given locale(s)
   *
   * @example
   * const mf = new MessageFormat('en')
   * const msg = mf.compile('A {TYPE} example.')
   *
   * msg({ TYPE: 'simple' })  // 'A simple example.'
   *
   * @example
   * const mf = new MessageFormat(['en', 'fi'])
   * const messages = mf.compile({
   *   en: { a: 'A {TYPE} example.',
   *         b: 'This is the {COUNT, selectordinal, one{#st} two{#nd} few{#rd} other{#th}} example.' },
   *   fi: { a: '{TYPE} esimerkki.',
   *         b: 'Tämä on {COUNT, selectordinal, other{#.}} esimerkki.' }
   * })
   *
   * messages.en.b({ COUNT: 2 })  // 'This is the 2nd example.'
   * messages.fi.b({ COUNT: 2 })  // 'Tämä on 2. esimerkki.'
   *
   * @example
   * const fs = require('fs')
   * const mf = new MessageFormat('en')
   * const msgSet = {
   *   a: 'A {TYPE} example.',
   *   b: 'This has {COUNT, plural, one{one member} other{# members}}.',
   *   c: 'We have {P, number, percent} code coverage.'
   * }
   * const msgStr = mf.compile(msgSet).toString('module.exports')
   * fs.writeFileSync('messages.js', msgStr)
   *
   * ...
   *
   * const messages = require('./messages')
   *
   * messages.a({ TYPE: 'more complex' })  // 'A more complex example.'
   * messages.b({ COUNT: 3 })              // 'This has 3 members.'
   */
  compile(messages, lc) {
    const { locale, pluralFuncs } = this.getPluralFuncs(lc);
    const compiler = new Compiler(this);
    const obj = compiler.compile(messages, locale, pluralFuncs);
    const runtime = new Runtime(this.options, compiler, pluralFuncs);

    if (typeof messages != 'object') {
      const fn = new Function(
        'number, plural, select, fmt',
        funcname(locale),
        'return ' + obj
      );
      return fn(
        runtime.number,
        runtime.plural,
        runtime.select,
        compiler.formatters,
        pluralFuncs[locale]
      );
    }

    const rtStr = runtime.toString();
    const objStr = stringifyObject(obj);
    const result = new Function(`${rtStr}\nreturn ${objStr}`)();
    // eslint-disable-next-line no-prototype-builtins
    if (result.hasOwnProperty('toString'))
      throw new Error('The top-level message key `toString` is reserved');

    result.toString = function(global) {
      if (!global || global === 'export default') {
        return `${rtStr}\nexport default ${objStr}`;
      } else if (global.indexOf('.') > -1) {
        return `${rtStr}\n${global} = ${objStr}`;
      } else {
        return `${rtStr}
(function (root, G) {
  if (typeof define === "function" && define.amd) { define(G); }
  else if (typeof exports === "object") { module.exports = G; }
  else { ${propname(global, 'root')} = G; }
})(this, ${objStr});`;
      }
    };
    return result;
  }
}
<|endoftext|>


<commit_before>// displayed when a server is selected
import './corpus-list'

import React, { PropTypes } from 'react'
import { Link } from 'react-router'
import { connect } from 'react-redux'
import { routerActions } from 'react-router-redux'
import { FormattedMessage as T, FormattedRelative as D, intlShape } from 'react-intl'

import { selectCorpus } from '../../actions/corpora'
import Spinner from '../../components/Spinner'

class CorpusListItem extends React.Component {

  render () {
    const { server, corpus, selectCorpus, routerPush } = this.props
    const { password, name, status, webentities_in, created_at, last_activity } = corpus

    const handleSelectCorpus = () => {
      const path = corpus.password ? '/login/corpus-login-form' : 'browser'
      selectCorpus(server, corpus)
      routerPush(path)
    }
    return (

          { password &&  }
          { name }
          { status === 'ready' &&  }

<T id="webentities" values={ { count: webentities_in } } />

          <T id="created-ago" values={ { relative: <D value={ created_at } /> } } />
           -
          <T id="used-ago" values={ { relative: <D value={ last_activity } /> } } />

    )
  }
}

CorpusListItem.propTypes = {
  corpus: PropTypes.object.isRequired,
  server: PropTypes.object.isRequired,

  // actions
  routerPush: PropTypes.func,
  selectCorpus: PropTypes.func,
}

class CorpusList extends React.Component {
  constructor (props) {
    super(props)
    this.state = { filter: '' }
  }

  render () {
    const { formatMessage } = this.context.intl
    const { server, status, ui, selectCorpus, routerPush } = this.props
    const hypheFull = false

    if (ui.loaders.corpora) return <Spinner textId="loading-corpora" />
    if (!server) return null

    let corpora = Object.keys(this.props.corpora)
      .sort()
      .map((k) => this.props.corpora[k])

    corpora = corpora.filter(it => it.name.toLowerCase().includes(this.state.filter.toLowerCase()))

    // only display corpora already started
    if (hypheFull) corpora = corpora.filter(it => it.status === 'ready')

    const hypheStatus = status && Boolean(status.corpus_running) &&
      (

          ,
          <T id="running-corpora" values={ { count: status.corpus_running } } />

      )

    return (

          <T id="available-corpora" values={ { count: corpora.length } } />
          { hypheStatus }

        { ui.error === true &&
<T id="error.loading-corpora" />
 }
        { !!Object.keys(this.props.corpora).length &&

          <input  value={ this.state.filter } placeholder={ formatMessage({ id: 'corpus-list-placeholder' }) }
            onChange={ ({ target }) => this.setState({ filter: target.value }) } />

 }

            { corpora.map((corpus) =>

                <CorpusListItem corpus={ corpus } server={ server }
                  selectCorpus={ selectCorpus } routerPush={ routerPush } />

            ) }

        { !hypheFull &&

          <Link className="btn btn-primary" to="/login/corpus-form"><T id="create-corpus" /></Link>

 }

    )
  }
}

CorpusList.contextTypes = {
  intl: intlShape
}

CorpusList.propTypes = {
  corpora: PropTypes.object.isRequired,
  locale: PropTypes.string.isRequired,
  server: PropTypes.object,
  status: PropTypes.object,
  ui: PropTypes.object.isRequired,

  // actions
  routerPush: PropTypes.func,
  selectCorpus: PropTypes.func,
}

const mapStateToProps = ({ corpora, servers, intl: { locale }, ui }) => ({
  corpora: corpora.list,
  locale,
  server: servers.selected,
  status: corpora.status && corpora.status.hyphe,
  ui
})

export default connect(mapStateToProps, {
  routerPush: routerActions.push,
  selectCorpus
})(CorpusList)
<commit_msg>remove warning<commit_after>// displayed when a server is selected
import './corpus-list'

import React, { PropTypes } from 'react'
import { Link } from 'react-router'
import { connect } from 'react-redux'
import { routerActions } from 'react-router-redux'
import { FormattedMessage as T, FormattedRelative as D, intlShape } from 'react-intl'

import { selectCorpus } from '../../actions/corpora'
import Spinner from '../../components/Spinner'

class CorpusListItem extends React.Component {

  render () {
    const { server, corpus, selectCorpus, routerPush } = this.props
    const { password, name, status, webentities_in, created_at, last_activity } = corpus

    const handleSelectCorpus = () => {
      const path = corpus.password ? '/login/corpus-login-form' : 'browser'
      selectCorpus(server, corpus)
      routerPush(path)
    }
    return (

          { password &&  }
          { name }
          { status === 'ready' &&  }

<T id="webentities" values={ { count: webentities_in } } />

          <T id="created-ago" values={ { relative: <D value={ created_at } /> } } />
           -
          <T id="used-ago" values={ { relative: <D value={ last_activity } /> } } />

    )
  }
}

CorpusListItem.propTypes = {
  corpus: PropTypes.object.isRequired,
  server: PropTypes.object.isRequired,

  // actions
  routerPush: PropTypes.func,
  selectCorpus: PropTypes.func,
}

class CorpusList extends React.Component {
  constructor (props) {
    super(props)
    this.state = { filter: '' }
  }

  render () {
    const { formatMessage } = this.context.intl
    const { server, status, ui, selectCorpus, routerPush } = this.props
    const hypheFull = false

    if (ui.loaders.corpora) return <Spinner textId="loading-corpora" />
    if (!server) return null

    let corpora = Object.keys(this.props.corpora)
      .sort()
      .map((k) => this.props.corpora[k])

    corpora = corpora.filter(it => it.name.toLowerCase().includes(this.state.filter.toLowerCase()))

    // only display corpora already started
    if (hypheFull) corpora = corpora.filter(it => it.status === 'ready')

    const hypheStatus = status && Boolean(status.corpus_running) &&
      (

          ,
          <T id="running-corpora" values={ { count: status.corpus_running } } />

      )

    return (

          <T id="available-corpora" values={ { count: corpora.length } } />
          { hypheStatus }

        { ui.error === true &&
<T id="error.loading-corpora" />
 }
        { !!Object.keys(this.props.corpora).length &&

          <input  value={ this.state.filter } placeholder={ formatMessage({ id: 'corpus-list-placeholder' }) }
            onChange={ ({ target }) => this.setState({ filter: target.value }) } />

 }

            { corpora.map((corpus) =>

                <CorpusListItem corpus={ corpus } server={ server }
                  selectCorpus={ selectCorpus } routerPush={ routerPush } />

            ) }

        { !hypheFull &&

          <Link className="btn btn-primary" to="/login/corpus-form"><T id="create-corpus" /></Link>

 }

    )
  }
}

CorpusList.contextTypes = {
  intl: intlShape
}

CorpusList.propTypes = {
  corpora: PropTypes.object,
  locale: PropTypes.string.isRequired,
  server: PropTypes.object,
  status: PropTypes.object,
  ui: PropTypes.object.isRequired,

  // actions
  routerPush: PropTypes.func,
  selectCorpus: PropTypes.func,
}

const mapStateToProps = ({ corpora, servers, intl: { locale }, ui }) => ({
  corpora: corpora.list,
  locale,
  server: servers.selected,
  status: corpora.status && corpora.status.hyphe,
  ui
})

export default connect(mapStateToProps, {
  routerPush: routerActions.push,
  selectCorpus
})(CorpusList)
<|endoftext|>


<commit_before>alert("Welcome to Jack Bonner's 'About Me App'!");

var mainWindow = Ti.UI.createWindow({
	backgroundColor: "#1C1C1C",
	barColor: '#1C1C1C',
	title: "Home",
	titleAttributes:  {
        color:'#fff',
        font: {fontFamily:'Roboto', fontSize:24},
        shadow:{color:'#5959c3', offset:{width:2,height:2}}
   },
	borderWidth: 1,
	statusBarStyle: Titanium.UI.iPhone.StatusBar.LIGHT_CONTENT
});

var nav = Titanium.UI.iOS.createNavigationWindow({
	window: mainWindow,
});

nav.open();

<commit_msg>Added About Me button to navigation bar<commit_after>alert("Welcome to Jack Bonner's 'About Me App'!");

// Main Window
var mainWindow = Ti.UI.createWindow({
	backgroundColor: "#1C1C1C",
	barColor: '#1C1C1C',
	title: "Home",
	titleAttributes:  {
        color:'#fff',
        font: {fontFamily:'Roboto', fontSize:24},
        shadow:{color:'#5959c3', offset:{width:2,height:2}}
   },
	borderWidth: 1,
	statusBarStyle: Titanium.UI.iPhone.StatusBar.LIGHT_CONTENT
});

// Navigation Window
var nav = Titanium.UI.iOS.createNavigationWindow({
	window: mainWindow
});

// Button - to - Questionss
var questions = Ti.UI.createButton({
	title: 'About Me'
});

// Adding Questions button
mainWindow.rightNavButton = questions;

// Open Nav Window
nav.open();

<|endoftext|>


<commit_before><commit_msg>adding requirejs r.js for building/compressing app<commit_after><|endoftext|>


<commit_before>//シングルコンテキストを理解する
Titanium.UI.setBackgroundColor('#000');
//tableViewTestで挑戦

//グローバルな変数を定義
var App = {};
App.ui = require('App/ui');
require('App/cell');

(function() {

App.tabGroup = App.ui.createAppsTabGroup();
App.tabGroup.open();

})();
<commit_msg>delete comment<commit_after>Titanium.UI.setBackgroundColor('#000');

var App = {};
App.ui = require('App/ui');
require('App/cell');

(function() {

App.tabGroup = App.ui.createAppsTabGroup();
App.tabGroup.open();

})();
<|endoftext|>


<commit_before>var locomotive = require('locomotive');
var Controller = locomotive.Controller;
var Download = require('download');
var plato = require('plato');
var glob = require("glob");
var mkdirp = require('mkdirp');
var ProjectModel = require('../model/project_model');

var PROJECT_SOURCES = "/../public/sources";
var PROJECT_REPORTS = "/";

var PagesController = new Controller();

PagesController.runTest = function() {
    var self = this;
    var id = this.param("id");
    ProjectModel.findOne({_id:id}).exec(function(err, item) {
        var url = item.url;
        mkdirp("/../public/" + item.name + "/sources", function(err) {
            var download = new Download({ extract: true, strip: 1 })
                .get(url, "./public/" + item.name + "/sources");

            download.run(function(err, files, stream) {
                console.log(files);
                if (err) {
                    throw err;
                }

                // options is optional
                glob("./public/" + item.name + "/sources" + "/**/*.js", null, function (er, files) {
                    var outputDir = './public/' + item.name;
                    // null options for this example
                    var options = {
                        title: 'Your title here'
                    };

                    var callback = function (report){
                        // once done the analysis,
                        // execute this
                        console.log(report);
                        self.render('./../../public/' + item.name + "/index");
                    };

                    plato.inspect(files, outputDir, {}, callback);
                });

                console.log('File downloaded successfully!');
            });
        });

    });

};

PagesController.create = function() {
    var url = this.body.url,
        name = this.body.name;
    var self = this;

    ProjectModel.create({name:name, url:url}, function(err) {
        self.__res.send({success:err});
    });
};

PagesController.list = function() {
    var page = this.param('page');
    var self = this;
    page = page || 0;
    console.log(page);
    ProjectModel.find({})
        .skip((page-1)*20)
        .limit(20)
        .exec(function(err, items) {
            self.__res.send(items);
        })
};

PagesController.delete = function() {
    var id = this.param("id");
    var self = this;
    ProjectModel.findOne({_id: id}).remove(function(err) {
        self.__res.send({err:err});
    });
}

module.exports = PagesController;
<commit_msg>Fix paging issue<commit_after>var locomotive = require('locomotive');
var Controller = locomotive.Controller;
var Download = require('download');
var plato = require('plato');
var glob = require("glob");
var mkdirp = require('mkdirp');
var ProjectModel = require('../model/project_model');

var PROJECT_SOURCES = "/../public/sources";
var PROJECT_REPORTS = "/";

var PagesController = new Controller();

PagesController.runTest = function() {
    var self = this;
    var id = this.param("id");
    ProjectModel.findOne({_id:id}).exec(function(err, item) {
        var url = item.url;
        mkdirp("/../public/" + item.name + "/sources", function(err) {
            var download = new Download({ extract: true, strip: 1 })
                .get(url, "./public/" + item.name + "/sources");

            download.run(function(err, files, stream) {
                console.log(files);
                if (err) {
                    throw err;
                }

                // options is optional
                glob("./public/" + item.name + "/sources" + "/**/*.js", null, function (er, files) {
                    var outputDir = './public/' + item.name;
                    // null options for this example
                    var options = {
                        title: 'Your title here'
                    };

                    var callback = function (report){
                        // once done the analysis,
                        // execute this
                        console.log(report);
                        self.render('./../../public/' + item.name + "/index");
                    };

                    plato.inspect(files, outputDir, {}, callback);
                });

                console.log('File downloaded successfully!');
            });
        });

    });

};

PagesController.create = function() {
    var url = this.body.url,
        name = this.body.name;
    var self = this;

    ProjectModel.create({name:name, url:url}, function(err) {
        self.__res.send({success:err});
    });
};

PagesController.list = function() {
    var page = this.param('page');
    var self = this;
    page = page || 1;
    console.log(page);
    ProjectModel.find({})
        .skip((page-1)*20)
        .limit(20)
        .exec(function(err, items) {
            self.__res.send(items);
        })
};

PagesController.delete = function() {
    var id = this.param("id");
    var self = this;
    ProjectModel.findOne({_id: id}).remove(function(err) {
        self.__res.send({err:err});
    });
}

module.exports = PagesController;
<|endoftext|>


<commit_before>import Ember from 'ember';

var findAllObject = Ember.Object.create({});
var findObject = Ember.Object.create({});
var findQueryObject = Ember.Object.create({});

var syncLoads = Ember.Object.create({
  findAll: findAllObject,
  find: findObject,
  findQuery: findQueryObject
});

export function initialize(instance) {

  let store = instance.container.lookup('store:main');
  let queue = instance.container.lookup('queue:main');

  store.reopen({
    queue: queue,
    syncLoads: syncLoads,

    adapterFor: function(typeClass) {
      let superResp = this._super.apply(this, arguments);

      return superResp.get('offlineAdapter');
    },
    //this can be removed, it is only for make error more silent
    find() {
      return this._super.apply(this, arguments).then(record => {
        return record;
      }).catch(console.log.bind(console));
    }
  });
};

export default {
  name: 'queue-in-store',
  initialize: initialize
};
<commit_msg>try remove find from store<commit_after>import Ember from 'ember';

var findAllObject = Ember.Object.create({});
var findObject = Ember.Object.create({});
var findQueryObject = Ember.Object.create({});

var syncLoads = Ember.Object.create({
  findAll: findAllObject,
  find: findObject,
  findQuery: findQueryObject
});

export function initialize(instance) {

  let store = instance.container.lookup('store:main');
  let queue = instance.container.lookup('queue:main');

  store.reopen({
    queue: queue,
    syncLoads: syncLoads,

    adapterFor: function(typeClass) {
      let superResp = this._super.apply(this, arguments);

      return superResp.get('offlineAdapter');
    },
  });
};

export default {
  name: 'queue-in-store',
  initialize: initialize
};
<|endoftext|>


<commit_before>import request from 'utils/request';

const INDICATORS = [
  3110, // (Carbon) Young Secondary Forest
  3111, // (Carbon) Mid-Age Secondary Forests
  3112, // (Carbon) Pasture
  3113, // (Carbon) Crops
  3114, // C02 Young Secondary Forest
  3115, // C02 Mid-Age Secondary Forests
  3116, // C02 Pasture
  3117 // C02 Crops
];

const SQL_QUERIES = {
  globalAndCountry:
    'SELECT iso, SUM(biomass) as totalbiomass, SUM(biomassdensity) as biomassdensity FROM biomass_whrc_gadm36 GROUP BY iso',
  adm1:
    "SELECT iso, admin_1, SUM(biomass) as totalbiomass, SUM(biomassdensity) as biomassdensity FROM biomass_whrc_gadm36 WHERE iso = '{adm0}' GROUP BY iso, admin_1",
  adm2:
    "SELECT iso, admin_1, admin_2, SUM(biomass) as totalbiomass, SUM(biomassdensity) as biomassdensity FROM biomass_whrc_gadm36 WHERE iso = '{adm0}' AND admin_1 = {adm1} GROUP BY iso, admin_1, admin_2"
};

export const getEmissions = ({ threshold, adm0 }) =>
  INDICATORS.map(indicator => {
    const url = `${process.env.CARTO_API}/sql?q=`;
    const query = `SELECT indicator_id,
values.cartodb_id AS cartodb_id,
values.iso,
values.sub_nat_id,
values.boundary_code,
values.thresh,
values.the_geom,
values.the_geom_webmercator,
values.country AS country_name,
values.country AS admin0_name,
values.year,
CAST(values.value AS double precision) AS value,
values.value AS text_value,
subnat.name_1 AS sub_nat_name,
boundaries.boundary_name${' '}
FROM gfw_climate_country_pages_indicator_values_2017_data_20180913 AS values${' '}
LEFT JOIN gadm28_adm1 AS subnat ON values.sub_nat_id = subnat.id_1${' '}
AND values.iso = subnat.iso LEFT JOIN gfw_climate_country_pages_boundary_info_2017_data${' '}
AS boundaries ON values.boundary_code = boundaries.boundary_code${' '}
WHERE indicator_id = ${indicator} AND value IS NOT NULL AND thresh =
${threshold || 0} AND values.iso = UPPER('${
  adm0
}') AND values.sub_nat_id IS NULL AND values.boundary_code = 'admin' ORDER BY year`;

    return request.get(encodeURI(`${url}${query}`));
  });

export const getBiomassRanking = ({ adm0, adm1, adm2, variable }) => {
  let query;

  if (!adm1) {
    query = SQL_QUERIES.globalAndCountry.replace('{variable}', variable);
  } else if (adm1 && !adm2) {
    query = SQL_QUERIES.adm1
      .replace('{variable}', variable)
      .replace('{adm0}', adm0);
  } else if (adm1 && adm2) {
    query = SQL_QUERIES.adm2
      .replace('{variable}', variable)
      .replace('{adm0}', adm0)
      .replace('{adm1}', adm1);
  }
  const url = `${process.env.CARTO_API}/sql?q=${query}`;

  return request.get(url);
};
<commit_msg>Added threshold to query<commit_after>import request from 'utils/request';

const INDICATORS = [
  3110, // (Carbon) Young Secondary Forest
  3111, // (Carbon) Mid-Age Secondary Forests
  3112, // (Carbon) Pasture
  3113, // (Carbon) Crops
  3114, // C02 Young Secondary Forest
  3115, // C02 Mid-Age Secondary Forests
  3116, // C02 Pasture
  3117 // C02 Crops
];

const SQL_QUERIES = {
  globalAndCountry:
    'SELECT iso, SUM(biomass) as totalbiomass, SUM(biomassdensity) as biomassdensity FROM biomass_whrc_gadm36 WHERE threshold = {threshold} GROUP BY iso',
  adm1:
    "SELECT iso, admin_1, SUM(biomass) as totalbiomass, SUM(biomassdensity) as biomassdensity FROM biomass_whrc_gadm36 WHERE iso = '{adm0}' AND threshold = {threshold} GROUP BY iso, admin_1",
  adm2:
    "SELECT iso, admin_1, admin_2, SUM(biomass) as totalbiomass, SUM(biomassdensity) as biomassdensity FROM biomass_whrc_gadm36 WHERE iso = '{adm0}' AND admin_1 = {adm1} AND threshold = {threshold} GROUP BY iso, admin_1, admin_2"
};

export const getEmissions = ({ threshold, adm0 }) =>
  INDICATORS.map(indicator => {
    const url = `${process.env.CARTO_API}/sql?q=`;
    const query = `SELECT indicator_id,
values.cartodb_id AS cartodb_id,
values.iso,
values.sub_nat_id,
values.boundary_code,
values.thresh,
values.the_geom,
values.the_geom_webmercator,
values.country AS country_name,
values.country AS admin0_name,
values.year,
CAST(values.value AS double precision) AS value,
values.value AS text_value,
subnat.name_1 AS sub_nat_name,
boundaries.boundary_name${' '}
FROM gfw_climate_country_pages_indicator_values_2017_data_20180913 AS values${' '}
LEFT JOIN gadm28_adm1 AS subnat ON values.sub_nat_id = subnat.id_1${' '}
AND values.iso = subnat.iso LEFT JOIN gfw_climate_country_pages_boundary_info_2017_data${' '}
AS boundaries ON values.boundary_code = boundaries.boundary_code${' '}
WHERE indicator_id = ${indicator} AND value IS NOT NULL AND thresh =
${threshold || 0} AND values.iso = UPPER('${
  adm0
}') AND values.sub_nat_id IS NULL AND values.boundary_code = 'admin' ORDER BY year`;

    return request.get(encodeURI(`${url}${query}`));
  });

export const getBiomassRanking = ({
  adm0,
  adm1,
  adm2,
  variable,
  threshold
}) => {
  let query;

  if (!adm1) {
    query = SQL_QUERIES.globalAndCountry
      .replace('{variable}', variable)
      .replace('{threshold}', threshold);
  } else if (adm1 && !adm2) {
    query = SQL_QUERIES.adm1
      .replace('{variable}', variable)
      .replace('{adm0}', adm0)
      .replace('{threshold}', threshold);
  } else if (adm1 && adm2) {
    query = SQL_QUERIES.adm2
      .replace('{variable}', variable)
      .replace('{adm0}', adm0)
      .replace('{adm1}', adm1)
      .replace('{threshold}', threshold);
  }
  const url = `${process.env.CARTO_API}/sql?q=${query}`;

  return request.get(url);
};
<|endoftext|>


<commit_before>/**
 * Zoinks SCUBA Dive Planner Project for ICS 414.
 *
 * DISCLAIMER: This system is a PROTOTYPE and should NOT be used to plan real dives!
 *
 * @author William Gaul, Micah Ruth Angeles
 * @repository https://github.com/willyg302/zoinks
 * @license MIT
 */
'use strict';

jest.dontMock('../index');
jest.dontMock('../padi');

describe('Algorithm', function() {
	beforeEach(function() {
		algo = require('../index');
	});

	it('correctly determines if a dive is bad', function() {
		expect(algo.isBadDive(40, 20)).toBe(false);
		expect(algo.isBadDive(220, 20)).toBe(true);
		expect(algo.isBadDive(60, 18)).toBe(true);
		expect(algo.isBadDive(25, 30)).toBe(true);
		expect(algo.isBadDive(15, 42)).toBe(true);
	});

	it('correctly determines if a dive is warning', function() {
		expect(algo.isWarningDive(180, 10)).toBe(true);
		expect(algo.isWarningDive(55, 16)).toBe(false);
		expect(algo.isWarningDive(35, 22)).toBe(true);
		expect(algo.isWarningDive(0, 35)).toBe(true);
	});

	it('correctly determines the status of a repeat dive', function() {
		expect(algo.getStatus({
			dives: [
				{depth: 20, time: 20},
				{depth: 15, time: 45}
			],
			surfaceIntervals: [{time: 60}]
		}, 1)).toEqual(algo.status.GOOD);
		expect(algo.getStatus({
			dives: [
				{depth: 20, time: 20},
				{depth: 20, time: 30}
			],
			surfaceIntervals: [{time: 60}]
		}, 1)).toEqual(algo.status.WARNING);
		expect(algo.getStatus({
			dives: [
				{depth: 20, time: 20},
				{depth: 20, time: 20},
				{depth: 20, time: 20}
			],
			surfaceIntervals: [{time: 60}, {time: 0}]
		}, 2)).toEqual(algo.status.BAD);
	});

	it('correctly calculates the time to fly', function() {
		expect(algo.getTimeToFly({
			dives: ['dive']
		})).toEqual(12);
		expect(algo.getTimeToFly({
			dives: ['dive', 'another dive']
		})).toEqual(18);
	});

	it('correctly maximizes the depth of a dive', function() {
		expect(Math.round(algo.calcMaximumDepth(0))).toEqual(30);
		expect(Math.round(algo.calcMaximumDepth(20))).toEqual(27);
		expect(Math.round(algo.calcMaximumDepth(70))).toEqual(15);
		// @TODO Repeat dive
	});

	it('correctly maximizes the time of a dive', function() {
		expect(Math.round(algo.calcMaximumTime(10))).toEqual(157);
		expect(Math.round(algo.calcMaximumTime(40))).toEqual(0);
		expect(Math.round(algo.calcMaximumTime(25))).toEqual(23);
		// @TODO Repeat dive
	});

	it('correctly minimizes a surface interval', function() {
		// @TODO
	});
});
<commit_msg>add a couple more test cases<commit_after>/**
 * Zoinks SCUBA Dive Planner Project for ICS 414.
 *
 * DISCLAIMER: This system is a PROTOTYPE and should NOT be used to plan real dives!
 *
 * @author William Gaul, Micah Ruth Angeles
 * @repository https://github.com/willyg302/zoinks
 * @license MIT
 */
'use strict';

jest.dontMock('../index');
jest.dontMock('../padi');

describe('Algorithm', function() {
	beforeEach(function() {
		algo = require('../index');
	});

	it('correctly determines if a dive is bad', function() {
		expect(algo.isBadDive(40, 20)).toBe(false);
		expect(algo.isBadDive(13, 60)).toBe(false);
		expect(algo.isBadDive(220, 20)).toBe(true);
		expect(algo.isBadDive(60, 18)).toBe(true);
		expect(algo.isBadDive(25, 30)).toBe(true);
		expect(algo.isBadDive(15, 42)).toBe(true);
		expect(algo.isBadDive(42, 10)).toBe(true);
	});

	it('correctly determines if a dive is warning', function() {
		expect(algo.isWarningDive(180, 10)).toBe(true);
		expect(algo.isWarningDive(55, 16)).toBe(false);
		expect(algo.isWarningDive(35, 22)).toBe(true);
		expect(algo.isWarningDive(0, 35)).toBe(true);
	});

	it('correctly determines the status of a repeat dive', function() {
		expect(algo.getStatus({
			dives: [
				{depth: 20, time: 20},
				{depth: 15, time: 45}
			],
			surfaceIntervals: [{time: 60}]
		}, 1)).toEqual(algo.status.GOOD);
		expect(algo.getStatus({
			dives: [
				{depth: 20, time: 20},
				{depth: 20, time: 30}
			],
			surfaceIntervals: [{time: 60}]
		}, 1)).toEqual(algo.status.WARNING);
		expect(algo.getStatus({
			dives: [
				{depth: 20, time: 20},
				{depth: 20, time: 20},
				{depth: 20, time: 20}
			],
			surfaceIntervals: [{time: 60}, {time: 0}]
		}, 2)).toEqual(algo.status.BAD);
	});

	it('correctly calculates the time to fly', function() {
		expect(algo.getTimeToFly({
			dives: ['dive']
		})).toEqual(12);
		expect(algo.getTimeToFly({
			dives: ['dive', 'another dive']
		})).toEqual(18);
	});

	it('correctly maximizes the depth of a dive', function() {
		expect(Math.round(algo.calcMaximumDepth(0))).toEqual(30);
		expect(Math.round(algo.calcMaximumDepth(20))).toEqual(27);
		expect(Math.round(algo.calcMaximumDepth(70))).toEqual(15);
		// @TODO Repeat dive
	});

	it('correctly maximizes the time of a dive', function() {
		expect(Math.round(algo.calcMaximumTime(10))).toEqual(157);
		expect(Math.round(algo.calcMaximumTime(40))).toEqual(0);
		expect(Math.round(algo.calcMaximumTime(25))).toEqual(23);
		// @TODO Repeat dive
	});

	it('correctly minimizes a surface interval', function() {
		// @TODO
	});
});
<|endoftext|>


<commit_before>/**
 * Zoinks SCUBA Dive Planner Project for ICS 414.
 *
 * DISCLAIMER: This system is a PROTOTYPE and should NOT be used to plan real dives!
 *
 * @author William Gaul, Micah Ruth Angeles
 * @repository https://github.com/willyg302/zoinks
 * @license MIT
 */
'use strict';

jest.dontMock('../index');
jest.dontMock('../padi');

describe('Algorithm', function() {
	beforeEach(function() {
		algo = require('../index');
	});

	it('correctly determines if a dive is bad', function() {
		expect(algo.isBadDive(40, 20)).toBe(false);
		expect(algo.isBadDive(13, 60)).toBe(false);
		expect(algo.isBadDive(220, 20)).toBe(true);
		expect(algo.isBadDive(60, 18)).toBe(true);
		expect(algo.isBadDive(25, 30)).toBe(true);
		expect(algo.isBadDive(15, 42)).toBe(true);
		expect(algo.isBadDive(42, 10)).toBe(true);
	});

	it('correctly determines if a dive is warning', function() {
		expect(algo.isWarningDive(180, 10)).toBe(true);
		expect(algo.isWarningDive(55, 16)).toBe(false);
		expect(algo.isWarningDive(35, 22)).toBe(true);
		expect(algo.isWarningDive(0, 35)).toBe(true);
		expect(algo.isWarningDive(25, 28)).toBe(true);
		expect(algo.isWarningDive(14, 87)).toBe(true);
	});

	it('correctly determines the status of a repeat dive', function() {
		//testing for the good dive
		expect(algo.getStatus({
			dives: [
				{depth: 25, time: 25},
				{depth: 20, time: 55}
			],
			surfaceIntervals: [{time: 60}]
		}, 1)).toEqual(algo.status.GOOD);
		expect(algo.getStatus({
			dives: [≠
				{depth: 20, time: 20},
				{depth: 15, time: 45}
			],
			surfaceIntervals: [{time: 60}]
		}, 1)).toEqual(algo.status.GOOD);

		//testing for the warning dive
		expect(algo.getStatus({
			dives: [
				{depth: 20, time: 20},
				{depth: 20, time: 30}
			],
			surfaceIntervals: [{time: 60}]
		}, 1)).toEqual(algo.status.WARNING);

		//testing for bad dives
		expect(algo.getStatus({
			dives: [
				{depth: 20, time: 20},
				{depth: 20, time: 20},
				{depth: 20, time: 20}
			],
			surfaceIntervals: [{time: 60}, {time: 0}]
		}, 2)).toEqual(algo.status.BAD);
	});

	it('correctly calculates the time to fly', function() {
		expect(algo.getTimeToFly({
			dives: ['dive']
		})).toEqual(12);
		expect(algo.getTimeToFly({
			dives: ['dive', 'another dive']
		})).toEqual(18);
	});

	it('correctly maximizes the depth of a dive', function() {
		expect(Math.round(algo.calcMaximumDepth(0))).toEqual(30);
		expect(Math.round(algo.calcMaximumDepth(20))).toEqual(27);
		expect(Math.round(algo.calcMaximumDepth(70))).toEqual(15);
		// @TODO Repeat dive
	});

	it('correctly maximizes the time of a dive', function() {
		expect(Math.round(algo.calcMaximumTime(10))).toEqual(157);
		expect(Math.round(algo.calcMaximumTime(40))).toEqual(0);
		expect(Math.round(algo.calcMaximumTime(25))).toEqual(23);
		// @TODO Repeat dive
	});

	it('correctly minimizes a surface interval', function() {
		// @TODO
		expect(algo.minimizeSurfaceInterval({
			dives: [
				{depth: 20, time: 20},
				{depth: 15, time: 45}
			],
			surfaceIntervals: [{time: 100}]
		}, 1)).toEqual(100);

		expect(algo.getStatus({
			dives: [
				{depth: 20, time: 20},
				{depth: 20, time: 30}
			],
			surfaceIntervals: [{time: 200}]
		}, 1)).toEqual(100);
	});
});
<commit_msg>more changes<commit_after>/**
 * Zoinks SCUBA Dive Planner Project for ICS 414.
 *
 * DISCLAIMER: This system is a PROTOTYPE and should NOT be used to plan real dives!
 *
 * @author William Gaul, Micah Ruth Angeles
 * @repository https://github.com/willyg302/zoinks
 * @license MIT
 */
'use strict';

jest.dontMock('../index');
jest.dontMock('../padi');

describe('Algorithm', function() {
	beforeEach(function() {
		algo = require('../index');
	});

	it('correctly determines if a dive is bad', function() {
		expect(algo.isBadDive(40, 20)).toBe(false);
		expect(algo.isBadDive(13, 60)).toBe(true);
		expect(algo.isBadDive(220, 20)).toBe(true);
		expect(algo.isBadDive(60, 18)).toBe(true);
		expect(algo.isBadDive(25, 30)).toBe(true);
		expect(algo.isBadDive(15, 42)).toBe(true);
		expect(algo.isBadDive(42, 10)).toBe(false);
	});

	it('correctly determines if a dive is warning', function() {
		expect(algo.isWarningDive(180, 10)).toBe(true);
		expect(algo.isWarningDive(55, 16)).toBe(false);
		expect(algo.isWarningDive(35, 22)).toBe(true);
		expect(algo.isWarningDive(0, 35)).toBe(true);
		expect(algo.isWarningDive(25, 28)).toBe(true);
		expect(algo.isWarningDive(14, 87)).toBe(true);
	});

	it('correctly determines the status of a repeat dive', function() {
		//testing for the good dive
		/*expect(algo.getStatus({
			dives: [
				{depth: 25, time: 25},
				{depth: 20, time: 55}
			],
			surfaceIntervals: [{time: 60}]
		}, 1)).toEqual(algo.status.GOOD);*/
		expect(algo.getStatus({
			dives: [
				{depth: 20, time: 20},
				{depth: 15, time: 45}
			],
			surfaceIntervals: [{time: 60}]
		}, 1)).toEqual(algo.status.GOOD);

		//testing for the warning dive
		expect(algo.getStatus({
			dives: [
				{depth: 20, time: 20},
				{depth: 20, time: 30}
			],
			surfaceIntervals: [{time: 60}]
		}, 1)).toEqual(algo.status.WARNING);

		//testing for bad dives
		expect(algo.getStatus({
			dives: [
				{depth: 20, time: 20},
				{depth: 20, time: 20},
				{depth: 20, time: 20}
			],
			surfaceIntervals: [{time: 60}, {time: 0}]
		}, 2)).toEqual(algo.status.BAD);
	});

	it('correctly calculates the time to fly', function() {
		expect(algo.getTimeToFly({
			dives: ['dive']
		})).toEqual(12);
		expect(algo.getTimeToFly({
			dives: ['dive', 'another dive']
		})).toEqual(18);
	});

	it('correctly maximizes the depth of a dive', function() {
		expect(Math.round(algo.calcMaximumDepth(0))).toEqual(30);
		expect(Math.round(algo.calcMaximumDepth(20))).toEqual(27);
		expect(Math.round(algo.calcMaximumDepth(70))).toEqual(15);
		// @TODO Repeat dive
	});

	it('correctly maximizes the time of a dive', function() {
		expect(Math.round(algo.calcMaximumTime(10))).toEqual(157);
		expect(Math.round(algo.calcMaximumTime(40))).toEqual(0);
		expect(Math.round(algo.calcMaximumTime(25))).toEqual(23);
		// @TODO Repeat dive
	});

	it('correctly minimizes a surface interval', function() {
		// @TODO
		/*
		expect(algo.minimizeSurfaceInterval({
			dives: [
				{depth: 20, time: 20},
				{depth: 15, time: 45}
			],
			surfaceIntervals: [{time: 100}]
		}, 1)).toEqual(100);

		expect(algo.getStatus({
			dives: [
				{depth: 20, time: 20},
				{depth: 20, time: 30}
			],
			surfaceIntervals: [{time: 200}]
		}, 1)).toEqual(100);*/
	});
});
<|endoftext|>


<commit_before>'use strict';
/**
 * @ngdoc service
 * @name arethusa.history.history
 *
 * @description
 * Tracks and stores all changes happening through the
 * {@link arethusa.core.state state} API.
 *
 * Provides means to undo and redo such changes.
 *
 *
 * @requires arethusa.core.configurator
 * @requires arethusa.core.keyCapture
 * @requires arethusa.core.state
 */
angular.module('arethusa.history').service('history', [
  'configurator',
  'keyCapture',
  'state',
  function (configurator, keyCapture, state) {
    var self = this;
    this.name = "history";

    function configure() {
      configurator.getConfAndDelegate(self);

      /**
       * @ngdoc property
       * @name maxSize
       * @propertyOf arethusa.history.history
       *
       * @description
       * ***Configurable property***
       *
       * Maximum number of saved events. Defaults to 50.
       */
      self.maxSize = self.maxSize || 50;
    }

    function doSilent(fn) {
      state.doSilent(fn);
      checkAvailability();
    }

    function current() {
      return self.events[self.position];
    }

    function checkAvailability() {
      var any = self.events.length > 0;
      self.canUndo = any && self.position < self.events.length;
      self.canRedo = any && self.position > 0;
    }

    function HistEvent(token, type) {
      var id = token.id;

      this.token = token;
      this.type = type;
      this.time = new Date();

      if (type === 'add') {
        this.exec = function() {
          state.addToken(token, id);
        };
        this.undo = function() {
          state.removeToken(id);
        };
      } else { // type === removed
        this.exec = function() {
          state.removeToken(id);
        };
        this.undo = function() {
          state.addToken(token, id);
        };
      }
    }

/***************************************************************************
 *                            Public Functions                             *
 ***************************************************************************/

    /**
     * @ngdoc function
     * @name arethusa.history.history#undo
     * @methodOf arethusa.history.history
     *
     * @description
     * Undoes the last event.
     *
     * Calls the current event's `undo` function and advances the
     * {@link arethusa.history.history#properties_position pointer } to the
     * {@link arethusa.history.history#properties_events history events}.
     *
     * Mind that no new event is added to the
     * {@link arethusa.history.history#properties_events events} stack.
     */
    this.undo = function() {
      if (self.canUndo) {
        doSilent(function() {
          current().undo();
          self.position++;
        });
      }
    };

    /**
     * @ngdoc function
     * @name arethusa.history.history#redo
     * @methodOf arethusa.history.history
     *
     * @description
     * Redoes the last event.
     *
     * Decreases the
     * {@link arethusa.history.history#properties_position pointer} to the
     * {@link arethusa.history.history#properties_events history events}
     * and calls the `exec` function of the next event.
     *
     * Mind that no new event is added to the
     * {@link arethusa.history.history#properties_events events} stack.
     */
    this.redo = function() {
      if (self.canRedo) {
        doSilent(function() {
          self.position--;
          current().exec();
        });
      }
    };

    function BatchEvent() {
      var self = this;
      this.events = [];
      this.type = 'batch';

      this.push = function(event) {
        self.events.push(event);
      };

      this.count = function() { return self.events.length; };

      this.pop = function() {
        return self.events.pop();
      };

      function multiExec() {
        angular.forEach(self.events, function(event, i) {
          event.exec();
        });
      }

      function multiUndo() {
        angular.forEach(self.events, function(event, i) {
          event.undo();
        });
      }

      this.exec = function() { state.doBatched(multiExec); };
      this.undo = function() { state.doBatched(multiUndo); };
    }

    /**
     * @ngdoc function
     * @name arethusa.history.history#saveEvent
     * @methodOf arethusa.history.history
     *
     * @description
     * Adds a new event to the history.
     *
     * Typically not called directly. The history service listen to
     * all changes happening through the
     * {@link arethusa.core.state#methods_change state.change} API
     * as well as to the {@link arethusa.core.state#events_tokenRemoved tokenRemoved }
     * and {@link arethusa.core.state#events_tokenAdded tokenAdded } events.
     *
     * Events pushed onto the {@link arethusa.history.history#properties_events events}
     * stack need to conform with the API of
     * {@link arethusa.core.StateChange StateChange} objects.
     *
     * When {@link arethusa.core.state state's} `batchMode` is active, all events will
     * be collected and pushed to the stack as a **single** event, that can be undone
     * and redone in a single step. This is achieved by wrapping all events in a custom
     * object (cf. the constructor of `BatchEvent` in the source code), which is
     * polymorphic to {@link arethusa.core.StateChange StateChange}, as it also
     * provides an `undo` and an `exec` function.
     *
     * @param {*} event A {@link arethusa.core.StateChange StateChange} event
     *   or a polymorphic equivalent.
     */
    var batchedEvent = new BatchEvent();
    this.saveEvent = function(event) {
      if (state.silent) return;
      if (state.batchChange) {
        batchedEvent.push(event);
        return;
      }

      var events = self.events;
      if (events.length === self.maxSize) events.pop();
      events.splice(0, self.position);
      self.position = 0;
      events.unshift(event);
      checkAvailability();
    };

/***************************************************************************
 *                          Watches and Listeners                          *
 ***************************************************************************/

    state.watch('*', function(n, o, event) {
      self.saveEvent(event);
    });

    state.on('tokenAdded', function(event, token) {
      var histEvent = new HistEvent(token, 'add');
      self.saveEvent(histEvent);
    });

    state.on('tokenRemoved', function(event, token) {
      var histEvent = new HistEvent(token, 'remove');
      self.saveEvent(histEvent);
    });

    state.on('batchChangeStop', function() {
      // We don't want to listen for batchUndo/batchRedo
      if (state.silent) return;

      // We are a little careless with setting the batch mode -
      // if the batch event has only a single event anyway,
      // we save this and not the whole BatchEvent.
      var e = batchedEvent.count() === 1 ? batchedEvent.pop() : batchedEvent;
      self.saveEvent(e);
      batchedEvent = new BatchEvent();
    });

/***************************************************************************
 *                                  Init                                   *
 ***************************************************************************/

    function keyCaptures() {
      var keys = keyCapture.initCaptures(function(kC) {
        return {
          history: [
            kC.create('undo', self.undo, ':'),
            kC.create('redo', self.redo, "'")
          ]
        };
      });
      self.activeKeys = angular.extend({}, keys.history);
    }

    this.init = function() {
      keyCaptures();
      configure();

      /**
       * @ngdoc property
       * @name canRedo
       * @propertyOf arethusa.history.history
       *
       * @description
       * Determines if an {@link arethusa.history.history#methods_redo redo}
       * operation can be done.
       */
      self.canRedo = false;

      /**
       * @ngdoc property
       * @name canUndo
       * @propertyOf arethusa.history.history
       *
       * @description
       * Determines if an {@link arethusa.history.history#methods_undo undo}
       * operation can be done.
       */
      self.canUndo = false;

      /**
       * @ngdoc property
       * @name events
       * @propertyOf arethusa.history.history
       *
       * @description
       * Array of all stored history events.
       */
      self.events = [];

      /**
       * @ngdoc property
       * @name position
       * @propertyOf arethusa.history.history
       *
       * @description
       * Current position in the
       * {@link arethusa.history.history#properties_events events} container.
       */
      self.position = 0;
    };
  }
]);
<commit_msg>Notify user when undo/redo is triggered<commit_after>'use strict';
/**
 * @ngdoc service
 * @name arethusa.history.history
 *
 * @description
 * Tracks and stores all changes happening through the
 * {@link arethusa.core.state state} API.
 *
 * Provides means to undo and redo such changes.
 *
 *
 * @requires arethusa.core.configurator
 * @requires arethusa.core.keyCapture
 * @requires arethusa.core.state
 */
angular.module('arethusa.history').service('history', [
  'configurator',
  'keyCapture',
  'state',
  'translator',
  'notifier',
  function (configurator, keyCapture, state, translator, notifier) {
    var self = this;
    this.name = "history";

    var trsls = translator({
      'history.undoSuccess': 'undoSuccess',
      'history.redoSuccess': 'redoSuccess'
    });

    function configure() {
      configurator.getConfAndDelegate(self);

      /**
       * @ngdoc property
       * @name maxSize
       * @propertyOf arethusa.history.history
       *
       * @description
       * ***Configurable property***
       *
       * Maximum number of saved events. Defaults to 50.
       */
      self.maxSize = self.maxSize || 50;
    }

    function doSilent(fn) {
      state.doSilent(fn);
      checkAvailability();
    }

    function current() {
      return self.events[self.position];
    }

    function checkAvailability() {
      var any = self.events.length > 0;
      self.canUndo = any && self.position < self.events.length;
      self.canRedo = any && self.position > 0;
    }

    function HistEvent(token, type) {
      var id = token.id;

      this.token = token;
      this.type = type;
      this.time = new Date();

      if (type === 'add') {
        this.exec = function() {
          state.addToken(token, id);
        };
        this.undo = function() {
          state.removeToken(id);
        };
      } else { // type === removed
        this.exec = function() {
          state.removeToken(id);
        };
        this.undo = function() {
          state.addToken(token, id);
        };
      }
    }

/***************************************************************************
 *                            Public Functions                             *
 ***************************************************************************/

    /**
     * @ngdoc function
     * @name arethusa.history.history#undo
     * @methodOf arethusa.history.history
     *
     * @description
     * Undoes the last event.
     *
     * Calls the current event's `undo` function and advances the
     * {@link arethusa.history.history#properties_position pointer } to the
     * {@link arethusa.history.history#properties_events history events}.
     *
     * Mind that no new event is added to the
     * {@link arethusa.history.history#properties_events events} stack.
     */
    this.undo = function() {
      if (self.canUndo) {
        doSilent(function() {
          current().undo();
          self.position++;
        });
        notifier.success(trsls.undoSuccess());
      }
    };

    /**
     * @ngdoc function
     * @name arethusa.history.history#redo
     * @methodOf arethusa.history.history
     *
     * @description
     * Redoes the last event.
     *
     * Decreases the
     * {@link arethusa.history.history#properties_position pointer} to the
     * {@link arethusa.history.history#properties_events history events}
     * and calls the `exec` function of the next event.
     *
     * Mind that no new event is added to the
     * {@link arethusa.history.history#properties_events events} stack.
     */
    this.redo = function() {
      if (self.canRedo) {
        doSilent(function() {
          self.position--;
          current().exec();
        });
        notifier.success(trsls.redoSuccess());
      }
    };

    function BatchEvent() {
      var self = this;
      this.events = [];
      this.type = 'batch';

      this.push = function(event) {
        self.events.push(event);
      };

      this.count = function() { return self.events.length; };

      this.pop = function() {
        return self.events.pop();
      };

      function multiExec() {
        angular.forEach(self.events, function(event, i) {
          event.exec();
        });
      }

      function multiUndo() {
        angular.forEach(self.events, function(event, i) {
          event.undo();
        });
      }

      this.exec = function() { state.doBatched(multiExec); };
      this.undo = function() { state.doBatched(multiUndo); };
    }

    /**
     * @ngdoc function
     * @name arethusa.history.history#saveEvent
     * @methodOf arethusa.history.history
     *
     * @description
     * Adds a new event to the history.
     *
     * Typically not called directly. The history service listen to
     * all changes happening through the
     * {@link arethusa.core.state#methods_change state.change} API
     * as well as to the {@link arethusa.core.state#events_tokenRemoved tokenRemoved }
     * and {@link arethusa.core.state#events_tokenAdded tokenAdded } events.
     *
     * Events pushed onto the {@link arethusa.history.history#properties_events events}
     * stack need to conform with the API of
     * {@link arethusa.core.StateChange StateChange} objects.
     *
     * When {@link arethusa.core.state state's} `batchMode` is active, all events will
     * be collected and pushed to the stack as a **single** event, that can be undone
     * and redone in a single step. This is achieved by wrapping all events in a custom
     * object (cf. the constructor of `BatchEvent` in the source code), which is
     * polymorphic to {@link arethusa.core.StateChange StateChange}, as it also
     * provides an `undo` and an `exec` function.
     *
     * @param {*} event A {@link arethusa.core.StateChange StateChange} event
     *   or a polymorphic equivalent.
     */
    var batchedEvent = new BatchEvent();
    this.saveEvent = function(event) {
      if (state.silent) return;
      if (state.batchChange) {
        batchedEvent.push(event);
        return;
      }

      var events = self.events;
      if (events.length === self.maxSize) events.pop();
      events.splice(0, self.position);
      self.position = 0;
      events.unshift(event);
      checkAvailability();
    };

/***************************************************************************
 *                          Watches and Listeners                          *
 ***************************************************************************/

    state.watch('*', function(n, o, event) {
      self.saveEvent(event);
    });

    state.on('tokenAdded', function(event, token) {
      var histEvent = new HistEvent(token, 'add');
      self.saveEvent(histEvent);
    });

    state.on('tokenRemoved', function(event, token) {
      var histEvent = new HistEvent(token, 'remove');
      self.saveEvent(histEvent);
    });

    state.on('batchChangeStop', function() {
      // We don't want to listen for batchUndo/batchRedo
      if (state.silent) return;

      // We are a little careless with setting the batch mode -
      // if the batch event has only a single event anyway,
      // we save this and not the whole BatchEvent.
      var e = batchedEvent.count() === 1 ? batchedEvent.pop() : batchedEvent;
      self.saveEvent(e);
      batchedEvent = new BatchEvent();
    });

/***************************************************************************
 *                                  Init                                   *
 ***************************************************************************/

    function keyCaptures() {
      var keys = keyCapture.initCaptures(function(kC) {
        return {
          history: [
            kC.create('undo', self.undo, ':'),
            kC.create('redo', self.redo, "'")
          ]
        };
      });
      self.activeKeys = angular.extend({}, keys.history);
    }

    this.init = function() {
      keyCaptures();
      configure();

      /**
       * @ngdoc property
       * @name canRedo
       * @propertyOf arethusa.history.history
       *
       * @description
       * Determines if an {@link arethusa.history.history#methods_redo redo}
       * operation can be done.
       */
      self.canRedo = false;

      /**
       * @ngdoc property
       * @name canUndo
       * @propertyOf arethusa.history.history
       *
       * @description
       * Determines if an {@link arethusa.history.history#methods_undo undo}
       * operation can be done.
       */
      self.canUndo = false;

      /**
       * @ngdoc property
       * @name events
       * @propertyOf arethusa.history.history
       *
       * @description
       * Array of all stored history events.
       */
      self.events = [];

      /**
       * @ngdoc property
       * @name position
       * @propertyOf arethusa.history.history
       *
       * @description
       * Current position in the
       * {@link arethusa.history.history#properties_events events} container.
       */
      self.position = 0;
    };
  }
]);
<|endoftext|>


<commit_before>var data        = require('data'),
    eventData   = data.get('eventData'),
    ui          = require('ui');

var listHeight = Ti.UI.FILL,
    listItemWidth = ui.screenWidth() - 20;

exports.add = function (label, items, onClick, navigationWindow, backgroundColor, openerWindow) {

    var listTemplate = {
        childTemplates: [
            {
                type: 'Ti.UI.Label',
                bindId: 'info',
                properties: {
                    borderWidth: 0,
                    backgroundColor: eventData.styles.button_background,
                    color: eventData.styles.button_foreground,
                    left: 10,
                    font: { fontSize: 18 },
                    height: Ti.UI.FILL,
                    width: listItemWidth,
                }
            }
        ]
    };

    function init(label, items, onClick, navigationWindow, openerWindow) {
        createWindow(
            label,
            backgroundColor,
            createListView(items, onClick, navigationWindow),
            openerWindow
        );
    }

    function createWindow(title, backgroundColor, viewChildren, localOpenerWindow) {
        var window = null;

        if (localOpenerWindow) {
            window = localOpenerWindow;

            window.setBackgroundColor(backgroundColor);

            if (window.setTitle) {
            	window.setTitle(title);
            }
        } else {
            window = Titanium.UI.createWindow({
                backgroundColor: backgroundColor,
                title: title
            });
        }

        var view = Titanium.UI.createView({
           layout: 'vertical',
           backgroundColor: backgroundColor,
           width: '100%',
           left: 0,
           top: 20,
           height: Ti.UI.FILL
        });

        view.add(viewChildren);

        window.add(view);

        return window;
    }

    function createListView(items, onClick, navigationWindow)
    {
        var isFinalList         = false,
            sectionParameters   = {},
            sections            = [],
            section             = null,
            dataSet             = [],
            title               = '',
            hasChildren         = false,
            itemId              = null;

        var listView = Ti.UI.createListView({
        	id: "listNavigationList",
            backgroundColor: eventData.styles.button_background,
            templates: { 'template': listTemplate },
            defaultItemTemplate: 'template',
            height: listHeight,
            width: '100%'
        });

        sections.push(
            addItemsToListView(items)
        );

        listView.setSections(sections);

        function addItemsToListView(items) {
            if (items.headerTitle) {
                sectionParameters = { headerTitle: items.headerTitle };
            } else if ((typeof items[0] != 'undefined') && (items[0].startTime)) {
                isFinalList = false;
            }
            else {
                isFinalList = true;
            }

            section = Ti.UI.createListSection(sectionParameters);
            dataSet = [];
            title = '';
            hasChildren = false;
            itemId = null;

            for (var i in items) {
                title = items[i].title;
                itemId = items[i].id;

                dataSet.push({
                    info: {
                        text: title
                    },
                    properties: {
                        id: itemId,
                        title: title,
                        subItems: items[i],
                        backgroundColor: eventData.styles.button_background,
                        color: eventData.styles.button_foreground,
                        font: {
                        	fontSize: 20
                        }
                    }
                });
            }

            section.setItems(dataSet);

            return section;
        };

        listView.addEventListener('itemclick', function (e) {
            var item = e.section.getItemAt(e.itemIndex);

            var id      = item.properties.id;
            var title   = item.properties.title;

            onClick(id, title);
        });

        return listView;
    }

    return init(label, items, onClick, navigationWindow, openerWindow);
};<commit_msg>Add list-with-image support<commit_after>var data        = require('data'),
    eventData   = data.get('eventData'),
    ui          = require('ui');

var listHeight = Ti.UI.FILL,
    listItemWidth = ui.screenWidth() - 20;

exports.add = function (label, items, onClick, navigationWindow, backgroundColor, openerWindow) {

    var listTemplate;

    if (false) {
		listTemplate = {
	        childTemplates: [
	            {
	                type: 'Ti.UI.Label',
	                bindId: 'info',
	                properties: {
	                    borderWidth: 0,
	                    backgroundColor: eventData.styles.button_background,
	                    color: eventData.styles.button_foreground,
	                    left: 10,
	                    font: { fontSize: 18 },
	                    height: Ti.UI.FILL,
	                    width: listItemWidth,
	                }
	            }
	        ]
	    };
	} else {
		listTemplate = {
	        childTemplates: [
		        {
		            type: 'Ti.UI.ImageView',
		            bindId: 'pic',
		            properties: {
		                width: 35,
		                height: 35,
		                left: 5,
		                top: 5
		            }
		        },
	            {
	                type: 'Ti.UI.Label',
	                bindId: 'info',
	                properties: {
	                    borderWidth: 0,
	                    backgroundColor: eventData.styles.button_background,
	                    color: eventData.styles.button_foreground,
	                    left: 50,
	                    height: 50,
	                    font: { fontSize: 18 },
	                    height: Ti.UI.FILL,
	                    width: listItemWidth - 50
	                }
	            }
	        ]
	    };
	}

    function init(label, items, onClick, navigationWindow, openerWindow) {
        createWindow(
            label,
            backgroundColor,
            createListView(items, onClick, navigationWindow),
            openerWindow
        );
    }

    function createWindow(title, backgroundColor, viewChildren, localOpenerWindow) {
        var window = null;

        if (localOpenerWindow) {
            window = localOpenerWindow;

            window.setBackgroundColor(backgroundColor);

            if (window.setTitle) {
            	window.setTitle(title);
            }
        } else {
            window = Titanium.UI.createWindow({
                backgroundColor: backgroundColor,
                title: title
            });
        }

        var view = Titanium.UI.createView({
           layout: 'vertical',
           backgroundColor: backgroundColor,
           width: '100%',
           left: 0,
           top: 20,
           height: Ti.UI.FILL
        });

        view.add(viewChildren);

        window.add(view);

        return window;
    }

    function createListView(items, onClick, navigationWindow)
    {
        var sections = [],
            section  = null,
            dataSet  = [],
            title    = '',
            itemId   = null;

        var listView = Ti.UI.createListView({
        	id: "listNavigationList",
            backgroundColor: eventData.styles.button_background,
            templates: { 'template': listTemplate },
            defaultItemTemplate: 'template',
            height: listHeight,
            width: '100%'
        });

        sections.push(
            addItemsToListView(items)
        );

        listView.setSections(sections);

        function addItemsToListView(items) {
            section = Ti.UI.createListSection();
            dataSet = [];
            title = '';
            itemId = null;

            var image;

            for (var i in items) {
                title = items[i].title;
                itemId = items[i].id;

                image = items[i].image || '/icons/silhouette_light.png';

                dataSet.push({
                    info: {
                        text: title
                    },
                    pic: {
						image: image
                    },
                    properties: {
                        id: itemId,
                        title: title,
                        subItems: items[i],
                        backgroundColor: eventData.styles.button_background,
                        color: eventData.styles.button_foreground,
                        font: {
                        	fontSize: 20
                        }
                    }
                });
            }

            section.setItems(dataSet);

            return section;
        };

        listView.addEventListener('itemclick', function (e) {
            var item = e.section.getItemAt(e.itemIndex);

            var id      = item.properties.id;
            var title   = item.properties.title;

            onClick(id, title);
        });

        return listView;
    }

    return init(label, items, onClick, navigationWindow, openerWindow);
};<|endoftext|>


<commit_before>import Ember from 'ember';

// Pre-loading user roles minimizes the number of HTTP
// requests we have to make later when checking a user's ability
// to read/manage/etc a stack
function loadUserRoles(route){
  var user = route.session.get('currentUser');
  return user.get('roles');
}

export default Ember.Mixin.create({
  requireAuthentication: true, // default to requiring authentication
  accessDenied() {
    this.transitionTo('login');
  },

  beforeModel(transition) {
    if (this.get('requireAuthentication')) {
      return this._requireAuthentication(transition);
    } else {
      return this._checkLogin();
    }
  },

  // redirect if the user is not signed in
  _requireAuthentication(transition) {
    var route = this;
    var isAuthenticated = this.get('session.isAuthenticated');
    if (isAuthenticated === undefined) {
      this.session.attemptedTransition = transition;
      return this.session.fetch('aptible').then(function(){
        return loadUserRoles(route);
      }).catch( () => {
        this.accessDenied();
      });
    } else if (isAuthenticated) {
      return loadUserRoles(route);
    } else {
      this.accessDenied();
    }
  },

  // check if the user is signed in, but do nothing if they are not
  _checkLogin() {
    var isAuthenticated = this.get('session.isAuthenticated');
    if (isAuthenticated === undefined) {
      return this.session.fetch('aptible').catch(function(){
        // no-op; it's ok if we are not logged in
      });
    } else {
      return Ember.RSVP.resolve();
    }
  }
});
<commit_msg>Return accessDenied return value to routes<commit_after>import Ember from 'ember';

// Pre-loading user roles minimizes the number of HTTP
// requests we have to make later when checking a user's ability
// to read/manage/etc a stack
function loadUserRoles(route){
  var user = route.session.get('currentUser');
  return user.get('roles');
}

export default Ember.Mixin.create({
  requireAuthentication: true, // default to requiring authentication
  accessDenied() {
    this.transitionTo('login');
  },

  beforeModel(transition) {
    if (this.get('requireAuthentication')) {
      return this._requireAuthentication(transition);
    } else {
      return this._checkLogin();
    }
  },

  // redirect if the user is not signed in
  _requireAuthentication(transition) {
    var route = this;
    var isAuthenticated = this.get('session.isAuthenticated');
    if (isAuthenticated === undefined) {
      this.session.attemptedTransition = transition;
      return this.session.fetch('aptible').then(function(){
        return loadUserRoles(route);
      }).catch( () => {
        return this.accessDenied();
      });
    } else if (isAuthenticated) {
      return loadUserRoles(route);
    } else {
      return this.accessDenied();
    }
  },

  // check if the user is signed in, but do nothing if they are not
  _checkLogin() {
    var isAuthenticated = this.get('session.isAuthenticated');
    if (isAuthenticated === undefined) {
      return this.session.fetch('aptible').catch(function(){
        // no-op; it's ok if we are not logged in
      });
    } else {
      return Ember.RSVP.resolve();
    }
  }
});
<|endoftext|>


<commit_before>var pagination = require('hexo-pagination');
var _ = require('lodash');

hexo.extend.generator.register('category', function(locals) {
	var config = this.config;
	var categories = locals.data.categories;
	if (config.category_generator) {
		var perPage = config.category_generator.per_page;
	} else {
		var perPage = 10;
	}
	var paginationDir = config.pagination_dir || 'page';
	var result = [];

	_.each(categories, function(category, title) {
		_.each(category, function(data, lang) {
			result = result.concat(
				pagination(lang + '/' + data.slug, getCategoryByName(
					locals.categories,
					data.category).posts, {
					perPage: perPage,
					layout: ['category', 'archive', 'index'],
					format: paginationDir + '/%d/',
					data: {
						lang: lang,
						title: data.name,
						category: data.category,
						alternates: getAlternateCategories(category)
					}
				})
			);
		});
	});

	return result;
});

hexo.extend.generator.register('posts', function(locals) {
	var posts = locals.posts.sort('-date').toArray();
	var length = posts.length;

	return posts.map(function(post, i) {
		var layout = post.layout;
		var path = post.path;

		if (!layout || layout === 'false') {
			return {
				path: path,
				data: post.content
			};
		} else {
			if (i) post.prev = posts[i - 1];
			if (i < length - 1) post.next = posts[i + 1];

			var layouts = ['post', 'page', 'index'];
			if (layout !== 'post') layouts.unshift(layout);

			if (post.label && post.lang) {
				post.alternates = getAlternatePosts(posts, post.label)
			}

			return {
				path: path,
				layout: layouts,
				data: post
			};
		}
	});
});

hexo.extend.generator.register('index', function(locals) {
	var result = [];
	var config = this.config;
	_.forEach(config.language, function(lang, n) {
		if (n == 0) {
			result = result.concat(
				{
					path: '',
					data: {
						redirect: lang
					},
					layout: ['redirect']
				}
			);
		}
		if (lang != 'default') {
			result = result.concat(
				pagination(lang, locals.posts.sort('-date').toArray().filter(
					function(post) {
						return post.lang == lang;
					}), {
					perPage: config.per_page,
					layout: ['index'],
					format: '/%d/',
					data: {
						lang: lang,
						title: config.title,
						alternates: getAlternateIndices(config)
					}
				})
			);
		}
	});
	return result;
});

hexo.extend.generator.register('feed', function(locals) {
	var result = [];
	var config = this.config;
	_.forEach(config.language, function(lang) {
		if (lang != 'default') {
			result.push(
				{
					path: lang + '/feed.xml',
					data: {
						title: config.title,
						lang: lang,
						posts: locals.posts.sort('-updated').filter(function(post) {
							return post.lang == lang;
						})
					},
					layout: ['rss2']
				}
			)
		}
	});
	return result;
});

function getCategoryByName(categories, name) {
	return categories.toArray().filter(function(category) {
		return category.name == name;
	})[0];
}

function getAlternateCategories(category) {
	var result = [];
	_.each(category, function(data, lang) {
		result.push({
			title: data.name,
			lang: lang,
			path: lang + '/' + data.slug
		});
	});
	return result;
}

function getAlternatePosts(posts, label) {
	var alternates = posts.filter(function(post) {
		return post.label == label;
	});
	var result = [];
	_.each(alternates, function(post) {
		result.push({
			title: post.title,
			lang: post.lang,
			path: post.path
		});
	});
	return result;
}

function getAlternateIndices(config) {
	var result = [];
	_.each(config.language, function(lang) {
		if (lang != 'default') {
			result.push({
				title: config.title,
				lang: lang,
				path: lang
			});
		}
	});
	return result;
}
<commit_msg>Add function for translated configuration values<commit_after>var pagination = require('hexo-pagination');
var _ = require('lodash');

hexo.extend.generator.register('category', function(locals) {
	var config = this.config;
	var categories = locals.data.categories;
	if (config.category_generator) {
		var perPage = config.category_generator.per_page;
	} else {
		var perPage = 10;
	}
	var paginationDir = config.pagination_dir || 'page';
	var result = [];

	_.each(categories, function(category, title) {
		_.each(category, function(data, lang) {
			result = result.concat(
				pagination(lang + '/' + data.slug, getCategoryByName(
					locals.categories,
					data.category).posts, {
					perPage: perPage,
					layout: ['category', 'archive', 'index'],
					format: paginationDir + '/%d/',
					data: {
						lang: lang,
						title: data.name,
						category: data.category,
						alternates: getAlternateCategories(category)
					}
				})
			);
		});
	});

	return result;
});

hexo.extend.generator.register('posts', function(locals) {
	var posts = locals.posts.sort('-date').toArray();
	var length = posts.length;

	return posts.map(function(post, i) {
		var layout = post.layout;
		var path = post.path;

		if (!layout || layout === 'false') {
			return {
				path: path,
				data: post.content
			};
		} else {
			if (i) post.prev = posts[i - 1];
			if (i < length - 1) post.next = posts[i + 1];

			var layouts = ['post', 'page', 'index'];
			if (layout !== 'post') layouts.unshift(layout);

			if (post.label && post.lang) {
				post.alternates = getAlternatePosts(posts, post.label)
			}

			return {
				path: path,
				layout: layouts,
				data: post
			};
		}
	});
});

hexo.extend.generator.register('index', function(locals) {
	var result = [];
	var context = this;
	context.locals = locals;
	_.forEach(context.config.language, function(lang, n) {
		if (n == 0) {
			result = result.concat(
				{
					path: '',
					data: {
						redirect: lang
					},
					layout: ['redirect']
				}
			);
		}
		if (lang != 'default') {
			result = result.concat(
				pagination(lang, locals.posts.sort('-date').toArray().filter(
					function(post) {
						return post.lang == lang;
					}), {
					perPage: context.config.per_page,
					layout: ['index'],
					format: '/%d/',
					data: {
						lang: lang,
						title: _c('title', lang, context),
						alternates: getAlternateIndices(context)
					}
				})
			);
		}
	});
	return result;
});

hexo.extend.generator.register('feed', function(locals) {
	var result = [];
	var config = this.config;
	_.forEach(config.language, function(lang) {
		if (lang != 'default') {
			result.push(
				{
					path: lang + '/feed.xml',
					data: {
						title: config.title,
						lang: lang,
						posts: locals.posts.sort('-updated').filter(function(post) {
							return post.lang == lang;
						})
					},
					layout: ['rss2']
				}
			)
		}
	});
	return result;
});

function getCategoryByName(categories, name) {
	return categories.toArray().filter(function(category) {
		return category.name == name;
	})[0];
}

function getAlternateCategories(category) {
	var result = [];
	_.each(category, function(data, lang) {
		result.push({
			title: data.name,
			lang: lang,
			path: lang + '/' + data.slug
		});
	});
	return result;
}

function getAlternatePosts(posts, label) {
	var alternates = posts.filter(function(post) {
		return post.label == label;
	});
	var result = [];
	_.each(alternates, function(post) {
		result.push({
			title: post.title,
			lang: post.lang,
			path: post.path
		});
	});
	return result;
}

function getAlternateIndices(context) {
	var result = [];
	_.each(context.config.language, function(lang) {
		if (lang != 'default') {
			result.push({
				title: _c('title', lang, context),
				lang: lang,
				path: lang
			});
		}
	});
	return result;
}

function _c(string, lang, context) {
	return context.locals.data['config_' + lang][string] || context.config[string];
}
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	Schema = mongoose.Schema;

/**
 * Project Schema
 */
var ProjectSchema = new Schema({
	title: {
		type: String,
		default: '',
		required: 'Please fill Project name',
		trim: true
	},
	description: {
		type: String,
		default: '',
		required: 'Please fill Project description',
		trim: true
	},
	industry: {
		type: String,
		default: '',
		trim: true
	},
	referred: {
		type: Boolean,
		default: '',
		trim: true
	},
	created: {
		type: Date,
		default: Date.now
	},
	user: {
		type: Schema.ObjectId,
		ref: 'User'
	}
});

mongoose.model('Project', ProjectSchema);
<commit_msg>added tags to model<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	Schema = mongoose.Schema;

/**
 * Project Schema
 */
var ProjectSchema = new Schema({
	title: {
		type: String,
		default: '',
		required: 'Please fill Project name',
		trim: true
	},
	description: {
		type: String,
		default: '',
		required: 'Please fill Project description',
		trim: true
	},
	industry: {
		type: String,
		default: '',
		trim: true
	},
	referred: {
		type: Boolean,
		default: '',
		trim: true
	},
	created: {
		type: Date,
		default: Date.now
	},
	tags:{
	        type: String,
	        default: '',
	        trim: true
    },
	user: {
		type: Schema.ObjectId,
		ref: 'User'
	}
});

mongoose.model('Project', ProjectSchema);
<|endoftext|>