<commit_before>// @flow

const fs = require('fs')
const { JQTransform } = require('../../../metadata/jqStream')
const objectPath = require('object-path')
const RestClient = require('../../api/RestClient')
const { println, subcommand } = require('../util')
const { validate, validateSelfDescribingSchema, isSelfDescribingRecord } = require('../../../metadata/schema')
import type { Readable } from 'stream'
import type { SelfDescribingSchema } from '../../../metadata/schema'

const BATCH_SIZE = 1000

type HandlerOptions = {
  namespace: string,
  schemaReference?: string,
  client: RestClient,
  jqFilter: string,
  idFilter: string,
  filename?: string,
  batchSize: number,
  compound?: number,
  dryRun: boolean,
  skipSchemaValidation: boolean
}

module.exports = {
  command: 'publish [filename]',
  description: 'Publish a batch of statements from a batch of newline-delimited json. ' +
    'Statements will be read from `filename` or stdin.\n',
  builder: {
    batchSize: { default: BATCH_SIZE },
    namespace: {
      required: true,
      type: 'string',
      description: 'The mediachain namespace to publish statements to.\n'
    },
    idFilter: {
      required: true,
      type: 'string',
      description: 'A jq filter that produces a mediachain identifier from your input object.  ' +
      'Will be applied after `jqFilter`, and does not modify the object itself.\n'
    },
    jqFilter: {
      type: 'string',
      description: 'A jq filter string to use to pre-process your input data.\n',
      default: '.'
    },
    dryRun: {
      type: 'boolean',
      default: false,
      description: 'Only extract ids and print to the console.\n'
    },
    schemaReference: {
      description: 'A multihash reference to a schema object used to validate objects before publishing. ' +
        'Including a schema reference will result in "self-describing" objects that link to their schema. ' +
        'The schema object must exist on the local node before running the publish command.\n',
      type: 'string'
    },
    skipSchemaValidation: {
      type: 'boolean',
      default: false,
      description: "Don't validate records against referenced schema before publishing.  Use only if you've " +
        'pre-validated your records! \n'
    },
    compound: {
      type: 'int',
      required: false,
      description: 'If present, publish compound statements of `compound` number of records. \n'
    }
  },

  handler: subcommand((opts: HandlerOptions) => {
    const {client, namespace, schemaReference, batchSize, filename, dryRun, skipSchemaValidation, jqFilter, idFilter, compound} = opts
    const publishOpts = {namespace, compound}

    let stream: Readable
    let streamName = 'standard input'
    if (filename) {
      stream = fs.createReadStream(filename)
      streamName = filename
    } else {
      stream = process.stdin
    }

    let schemaPromise: Promise<?SelfDescribingSchema>
    if (schemaReference == null || skipSchemaValidation) {
      schemaPromise = Promise.resolve(null)
    } else {
      schemaPromise = client.getData(schemaReference)
        .catch(err => {
          throw new Error(`Failed to retrieve schema with object id ${schemaReference}: ${err.message}`)
        })
        .then((schema) => {
          try {
            return validateSelfDescribingSchema(schema)
          } catch (err) {
            throw new Error(
              `Schema with object id ${schemaReference} is not a valid self-describing schema: ${err.message}`
            )
          }
        })
    }

    return schemaPromise
      .then(schema =>
        publishStream({
          stream,
          streamName,
          client,
          batchSize,
          dryRun,
          skipSchemaValidation,
          publishOpts,
          schemaReference,
          schema,
          jqFilter: composeJQFilters(jqFilter, idFilter)})
      )
  })
}

function publishStream (opts: {
  stream: Readable,
  streamName: string,
  client: RestClient,
  batchSize: number,
  dryRun: boolean,
  skipSchemaValidation: boolean,
  publishOpts: {namespace: string, compound?: number},
  schemaReference?: string,
  schema: ?SelfDescribingSchema,
  jqFilter: string
}): Promise<*> {
  const {
    stream,
    streamName,
    client,
    publishOpts,
    batchSize,
    dryRun,
    skipSchemaValidation,
    schemaReference,
    schema,
    jqFilter
  } = opts

  let statementBodies: Array<Object> = []
  let statements: Array<Object> = []
  const jq = new JQTransform(jqFilter)
  let wki: string
  let obj: Object

  // We want to know when all of our batches have been published,
  // so we can complete the subcommand handler and exit the process.
  // Rather than use Promise.all(), which requires us to keep
  // (potentially) thousands of Promise objects around, we add
  // Promises for in-flight batches to this map, keyed by a
  // unique id.  Then we remove them when the batch completes.
  const pendingBatches: Map<string, Promise<void>> = new Map()
  let batchCounter = 0
  function addBatchPromise (batchPromise: Promise<void>) {
    const batchId = 'batch-' + batchCounter.toString()
    batchCounter++
    pendingBatches.set(batchId, batchPromise
      .then(() => {
        pendingBatches.delete(batchId)
      })
    )
  }

  // Called when the input stream completes, after all batch
  // promises have been added.  Will resolve when all pending
  // batch promises have resolved
  function waitForCompletion (): Promise<void> {
    return new Promise((resolve) => {
      function check () {
        if (pendingBatches.size === 0) return resolve()
        setTimeout(check, 100)
      }

      check()
    })
  }

  return new Promise((resolve, reject) => {
    // cleanup before rejecting the promise on failure
    function publishFailed (err: Error) {
      stream.unpipe()
      jq.kill()
      reject(err)
    }

    stream.pipe(jq)
      .on('data', jsonString => {
        try {
          const parsed = JSON.parse(jsonString)
          wki = parsed.wki
          obj = parsed.obj
        } catch (err) {
          return publishFailed(new Error(`Error parsing jq output: ${err}\njq output: ${jsonString}`))
        }

        if (schema != null && !skipSchemaValidation) {
          const result = validate(schema, obj)
          if (!result.success) {
            return publishFailed(new Error(`Record failed validation: ${result.error.message}. Failed object: ${JSON.stringify(obj, null, 2)}`))
          }
        }

        if (wki == null || wki.length < 1) {
          throw new Error(
            `Unable to extract id. Input record: \n` +
            JSON.stringify(obj, null, 2)
          )
        }

        wki = wki.toString()

        const refs = [ wki ]
        const tags = [] // TODO: support extracting tags
        const deps = []

        if (schemaReference != null) {
          deps.push(schemaReference)

          if (isSelfDescribingRecord(obj)) {
            const ref = objectPath.get(obj, 'schema', '/')
            if (ref !== schemaReference) {
              return publishFailed(new Error(
                `Record contains reference to a different schema (${ref}) than the one specified ${schemaReference}`
              ))
            }
          } else {
            obj = {
              schema: { '/': schemaReference },
              data: obj
            }
          }
        }

        if (dryRun) {
          println(`refs: ${JSON.stringify(refs)}, tags: ${JSON.stringify(tags)}, deps: ${JSON.stringify(deps)}`)
          return
        }

        const stmt = { object: obj, refs, tags, deps }

        statementBodies.push(obj)
        statements.push(stmt)

        if (statementBodies.length >= batchSize) {
          addBatchPromise(
            publishBatch(client, publishOpts, statementBodies, statements)
              .catch(publishFailed)
          )
          statementBodies = []
          statements = []
        }
      })
      .on('end', () => {
        if (statementBodies.length > 0) {
          addBatchPromise(
            publishBatch(client, publishOpts, statementBodies, statements)
              .catch(publishFailed)
          )
        }
        waitForCompletion()
          .then(() => {
            if (!dryRun) {
              println('All statements published successfully')
            }
            resolve()
          })
      })
      .on('error', err => {
        publishFailed(new Error(`Error reading from ${streamName}: ${err.message}`))
      })
  })
}

function publishBatch (client: RestClient,
                       publishOpts: {namespace: string, compound?: number},
                       statementBodies: Array<Object>,
                       statements: Array<Object>): Promise<*> {
  return client.putData(...statementBodies)
    .then(bodyHashes => {
      if (bodyHashes.length !== statements.length) {
        throw new Error(`Expected ${statements.length} results from putting data blobs, received ${bodyHashes.length}`)
      }
      statements = statements.map((s, i) => {
        s.object = bodyHashes[i]
        return s
      })

      return client.publish(publishOpts, ...statements)
        .then(statementIds => [bodyHashes, statementIds])
    })
    .then(([bodyHashes, statementIds]) => {
      printBatchResults(bodyHashes, statementIds, statements, publishOpts.compound || 1)
    })
}

function composeJQFilters (contentFilter: string, idFilter: string): string {
  return `${contentFilter} as $output | {wki: ($output | ${idFilter}), obj: $output}`
}

function printBatchResults (bodyHashes: Array<string>, statementIds: Array<string>, statements: Array<Object>,
                            compoundSize: number) {
  for (let i = 0; i < statementIds.length; i++) {
    println(`\nstatement id: ${statementIds[i]}`)
    const statementInfos = []

    for (let j = i; j < i + compoundSize; j++) {
      const object = bodyHashes[j]
      const {refs, tags, deps} = statements[j]
      statementInfos.push({object, refs, tags, deps})
    }

    println(JSON.stringify(statementInfos, null, 2))
  }
}

<commit_msg>Accept and require WKI prefix<commit_after>// @flow

const fs = require('fs')
const { JQTransform } = require('../../../metadata/jqStream')
const objectPath = require('object-path')
const RestClient = require('../../api/RestClient')
const { println, subcommand } = require('../util')
const { validate, validateSelfDescribingSchema, isSelfDescribingRecord } = require('../../../metadata/schema')
import type { Readable } from 'stream'
import type { SelfDescribingSchema } from '../../../metadata/schema'

const BATCH_SIZE = 1000

type HandlerOptions = {
  namespace: string,
  schemaReference?: string,
  client: RestClient,
  jqFilter: string,
  idFilter: string,
  filename?: string,
  batchSize: number,
  compound?: number,
  dryRun: boolean,
  skipSchemaValidation: boolean
}

module.exports = {
  command: 'publish [filename]',
  description: 'Publish a batch of statements from a batch of newline-delimited json. ' +
    'Statements will be read from `filename` or stdin.\n',
  builder: {
    batchSize: { default: BATCH_SIZE },
    namespace: {
      required: true,
      type: 'string',
      description: 'The mediachain namespace to publish statements to.\n'
    },
    idFilter: {
      required: true,
      type: 'string',
      description: 'A jq filter that produces a mediachain identifier from your input object.  ' +
      'Will be applied after `jqFilter`, and does not modify the object itself.\n'
    },
    prefix: {
      required: true,
      type: 'string',
      description: 'Prefix for the WKI.  ' +
      'The WKI is formed by joining the `prefix` (e.g. "moma") and the identifier extracted by `idFilter` with a colon (e.g. "moma:67350")'
    },
    jqFilter: {
      type: 'string',
      description: 'A jq filter string to use to pre-process your input data.\n',
      default: '.'
    },
    dryRun: {
      type: 'boolean',
      default: false,
      description: 'Only extract ids and print to the console.\n'
    },
    schemaReference: {
      description: 'A multihash reference to a schema object used to validate objects before publishing. ' +
        'Including a schema reference will result in "self-describing" objects that link to their schema. ' +
        'The schema object must exist on the local node before running the publish command.\n',
      type: 'string'
    },
    skipSchemaValidation: {
      type: 'boolean',
      default: false,
      description: "Don't validate records against referenced schema before publishing.  Use only if you've " +
        'pre-validated your records! \n'
    },
    compound: {
      type: 'int',
      required: false,
      description: 'If present, publish compound statements of `compound` number of records. \n'
    }
  },

  handler: subcommand((opts: HandlerOptions) => {
    const {client, namespace, schemaReference, batchSize, filename, dryRun, skipSchemaValidation, jqFilter, prefix, idFilter, compound} = opts
    const publishOpts = {namespace, compound}

    let stream: Readable
    let streamName = 'standard input'
    if (filename) {
      stream = fs.createReadStream(filename)
      streamName = filename
    } else {
      stream = process.stdin
    }

    let schemaPromise: Promise<?SelfDescribingSchema>
    if (schemaReference == null || skipSchemaValidation) {
      schemaPromise = Promise.resolve(null)
    } else {
      schemaPromise = client.getData(schemaReference)
        .catch(err => {
          throw new Error(`Failed to retrieve schema with object id ${schemaReference}: ${err.message}`)
        })
        .then((schema) => {
          try {
            return validateSelfDescribingSchema(schema)
          } catch (err) {
            throw new Error(
              `Schema with object id ${schemaReference} is not a valid self-describing schema: ${err.message}`
            )
          }
        })
    }

    return schemaPromise
      .then(schema =>
        publishStream({
          stream,
          streamName,
          client,
          batchSize,
          dryRun,
          skipSchemaValidation,
          publishOpts,
          schemaReference,
          schema,
          prefix,
          jqFilter: composeJQFilters(jqFilter, idFilter)})
      )
  })
}

function publishStream (opts: {
  stream: Readable,
  streamName: string,
  client: RestClient,
  batchSize: number,
  dryRun: boolean,
  skipSchemaValidation: boolean,
  publishOpts: {namespace: string, compound?: number},
  schemaReference?: string,
  schema: ?SelfDescribingSchema,
  prefix: string,
  jqFilter: string
}): Promise<*> {
  const {
    stream,
    streamName,
    client,
    publishOpts,
    batchSize,
    dryRun,
    skipSchemaValidation,
    schemaReference,
    schema,
    prefix,
    jqFilter
  } = opts

  let statementBodies: Array<Object> = []
  let statements: Array<Object> = []
  const jq = new JQTransform(jqFilter)
  let wki: string
  let obj: Object

  // We want to know when all of our batches have been published,
  // so we can complete the subcommand handler and exit the process.
  // Rather than use Promise.all(), which requires us to keep
  // (potentially) thousands of Promise objects around, we add
  // Promises for in-flight batches to this map, keyed by a
  // unique id.  Then we remove them when the batch completes.
  const pendingBatches: Map<string, Promise<void>> = new Map()
  let batchCounter = 0
  function addBatchPromise (batchPromise: Promise<void>) {
    const batchId = 'batch-' + batchCounter.toString()
    batchCounter++
    pendingBatches.set(batchId, batchPromise
      .then(() => {
        pendingBatches.delete(batchId)
      })
    )
  }

  // Called when the input stream completes, after all batch
  // promises have been added.  Will resolve when all pending
  // batch promises have resolved
  function waitForCompletion (): Promise<void> {
    return new Promise((resolve) => {
      function check () {
        if (pendingBatches.size === 0) return resolve()
        setTimeout(check, 100)
      }

      check()
    })
  }

  return new Promise((resolve, reject) => {
    // cleanup before rejecting the promise on failure
    function publishFailed (err: Error) {
      stream.unpipe()
      jq.kill()
      reject(err)
    }

    stream.pipe(jq)
      .on('data', jsonString => {
        try {
          const parsed = JSON.parse(jsonString)
          wki = parsed.wki
          obj = parsed.obj
        } catch (err) {
          return publishFailed(new Error(`Error parsing jq output: ${err}\njq output: ${jsonString}`))
        }

        if (schema != null && !skipSchemaValidation) {
          const result = validate(schema, obj)
          if (!result.success) {
            return publishFailed(new Error(`Record failed validation: ${result.error.message}. Failed object: ${JSON.stringify(obj, null, 2)}`))
          }
        }

        if (wki == null || wki.length < 1) {
          throw new Error(
            `Unable to extract id. Input record: \n` +
            JSON.stringify(obj, null, 2)
          )
        }

        wki = wki.toString()

        wkiWithPrefix = [ prefix, wki ].join(':')

        const refs = [ wkiWithPrefix ]
        const tags = [] // TODO: support extracting tags
        const deps = []

        if (schemaReference != null) {
          deps.push(schemaReference)

          if (isSelfDescribingRecord(obj)) {
            const ref = objectPath.get(obj, 'schema', '/')
            if (ref !== schemaReference) {
              return publishFailed(new Error(
                `Record contains reference to a different schema (${ref}) than the one specified ${schemaReference}`
              ))
            }
          } else {
            obj = {
              schema: { '/': schemaReference },
              data: obj
            }
          }
        }

        if (dryRun) {
          println(`refs: ${JSON.stringify(refs)}, tags: ${JSON.stringify(tags)}, deps: ${JSON.stringify(deps)}`)
          return
        }

        const stmt = { object: obj, refs, tags, deps }

        statementBodies.push(obj)
        statements.push(stmt)

        if (statementBodies.length >= batchSize) {
          addBatchPromise(
            publishBatch(client, publishOpts, statementBodies, statements)
              .catch(publishFailed)
          )
          statementBodies = []
          statements = []
        }
      })
      .on('end', () => {
        if (statementBodies.length > 0) {
          addBatchPromise(
            publishBatch(client, publishOpts, statementBodies, statements)
              .catch(publishFailed)
          )
        }
        waitForCompletion()
          .then(() => {
            if (!dryRun) {
              println('All statements published successfully')
            }
            resolve()
          })
      })
      .on('error', err => {
        publishFailed(new Error(`Error reading from ${streamName}: ${err.message}`))
      })
  })
}

function publishBatch (client: RestClient,
                       publishOpts: {namespace: string, compound?: number},
                       statementBodies: Array<Object>,
                       statements: Array<Object>): Promise<*> {
  return client.putData(...statementBodies)
    .then(bodyHashes => {
      if (bodyHashes.length !== statements.length) {
        throw new Error(`Expected ${statements.length} results from putting data blobs, received ${bodyHashes.length}`)
      }
      statements = statements.map((s, i) => {
        s.object = bodyHashes[i]
        return s
      })

      return client.publish(publishOpts, ...statements)
        .then(statementIds => [bodyHashes, statementIds])
    })
    .then(([bodyHashes, statementIds]) => {
      printBatchResults(bodyHashes, statementIds, statements, publishOpts.compound || 1)
    })
}

function composeJQFilters (contentFilter: string, idFilter: string): string {
  return `${contentFilter} as $output | {wki: ($output | ${idFilter}), obj: $output}`
}

function printBatchResults (bodyHashes: Array<string>, statementIds: Array<string>, statements: Array<Object>,
                            compoundSize: number) {
  for (let i = 0; i < statementIds.length; i++) {
    println(`\nstatement id: ${statementIds[i]}`)
    const statementInfos = []

    for (let j = i; j < i + compoundSize; j++) {
      const object = bodyHashes[j]
      const {refs, tags, deps} = statements[j]
      statementInfos.push({object, refs, tags, deps})
    }

    println(JSON.stringify(statementInfos, null, 2))
  }
}

<|endoftext|>


<commit_before>const React = require('react');
const h = require('react-hyperscript');
const Table = require('react-table').default;

const queryString = require('query-string');
const color = require('color');
const _ = require('lodash');
const classNames = require('classnames');
const matchSorter = require('match-sorter').default;

const make_cytoscape = require('../../common/cy');
const cysearch = require('../../common/cy/search');

const Icon = require('../../common/components').Icon;
const { apiCaller, PathwayCommonsService } = require('../../services');

const analysisFunctions = [
  {
    name: 'mean',
    func: _.mean,
  },
  {
    name: 'count',
    func: _.countBy,
  },
  {
    name: 'min',
    func: _.min
  },
  {
    name: 'max',
    func: _.max
  }
];

class OmniBar extends React.Component {
  render() {
    const props = this.props;
    return h('div.paint-omnibar', [
      h('a', { onClick: e => props.onMenuClick(e) }, [
        h(Icon, { icon: 'menu' }, 'click')
      ]),
      h('h5', `${props.name} | ${props.datasource}`)
    ]);
  }
}

// props
// expression table
// cy
class Network extends React.Component {
  componentWillUnmount() {
    this.state.cy.destroy();
  }

  componentDidMount() {
    const props = this.props;
    const container = document.getElementById('cy-container');
    props.cy.mount(container);
  }

  colourMap(val, min, max) {
    const distToMax = Math.abs(val - max);
    const distToMin = Math.abs(val - min);

    let hVal, lVal;
    if (distToMax > distToMin) {
      hVal = 240;
      lVal = ( val / Math.abs(max) ) * 100 + 20;
    } else {
      hVal = 0;
      lVal = ( val / Math.abs(max) ) * 100 - 20;
    }
    return color.hsl(hVal, 100, lVal).string();
  }

  percentToColour(percent) {
    const hslValue = ( 1 - percent ) * 240;

    return color.hsl(hslValue, 100, 50).string();
  }

  componentWillReceiveProps(nextProps) {
    if (!_.isEmpty(nextProps.expressionTable)) {
      this.applyExpressionData(nextProps);
    }
  }

  applyExpressionData(props) {
    const expressionTable = props.expressionTable;
    const networkNodes = _.uniq(props.cy.nodes('[class="macromolecule"]').map(node => node.data('label'))).sort();

    const expressionsInNetwork = expressionTable.rows.filter(row => networkNodes.includes(row.geneName));
    const maxVal = _.max(expressionsInNetwork.map(row => _.max(row.classValues)).map((k, v) => parseFloat(k)));
    const minVal = _.min(expressionsInNetwork.map(row => _.min(row.classValues)).map((k, v) => parseFloat(k)));

    expressionsInNetwork.forEach(expression => {
      // probably more efficient to add the expression data to the node field instead of interating twice
      props.cy.nodes().filter(node => node.data('label') === expression.geneName).forEach(node => {

        const numSlices = expression.classValues.length > 16 ? 16 : expression.classValues.length;

        const pieStyle = {
          'pie-size': '100%'
        };
        for (let i = 1; i <= numSlices; i++) {

          pieStyle['pie-' + i + '-background-size'] = 100 / numSlices;
          pieStyle['pie-' + i + '-background-opacity'] = 1;
          pieStyle['pie-' + i + '-background-color'] = this.percentToColour(expression.classValues[i-1] / maxVal);
        }

        node.style(pieStyle);
      });
    });
  }

  render() {
    return h('div.paint-graph', [ h(`div.#cy-container`, {style: {width: '100vw', height: '100vh'}}) ]);
  }

}

class Paint extends React.Component {
  constructor(props) {
    super(props);

    const cy = make_cytoscape({headless: true});

    this.state = {
      rawEnrichmentData: {},
      expressionTable: {},
      cy: cy,
      name: '',
      datasource: '',
      drawerOpen: false
    };

    const query = queryString.parse(props.location.search);
    const enrichmentsURI = query.uri ? query.uri : null;

    if (enrichmentsURI != null) {
      fetch(enrichmentsURI)
        .then(response => response.json())
        .then(json => {
          this.setState({rawEnrichmentData: json});

          const expressionClasses = _.get(json.dataSetClassList, '0.classes', []);
          const expressions = _.get(json.dataSetExpressionList, '0.expressions', []);
          const searchParam = query.q;
          this.initPainter(expressions, expressionClasses, searchParam);

        });
    }
  }

  componentWillUnmount() {
    this.state.cy.destroy();
  }

  // only call this after you know component is mounted
  initPainter(expressions, expressionClasses, queryParam) {
    const state = this.state;
    const query = {
      q: queryParam,
      type: 'Pathway'
    };

    apiCaller.querySearch(query)
      .then(searchResults => {
        const uri = _.get(searchResults, '0.uri', null);

        if (uri != null) {
          apiCaller.getGraphAndLayout(uri, 'latest').then(response => {
            this.setState({
              name: _.get(response, 'graph.pathwayMetadata.title', 'N/A'),
              datasource: _.get(response, 'graph.pathwayMetadata.dataSource.0', 'N/A'),
            });

            state.cy.remove('*');
            state.cy.add({
              nodes: _.get(response, 'graph.nodes', []),
              edges: _.get(response, 'graph.edges', [])
            });

            state.cy.layout({
              name: 'cose-bilkent',
              randomize: false,
              nodeDimensionsIncludeLabels: true
            }).run();

            const expressionTable = {};

            const header = _.uniq(expressionClasses);

            expressionTable.header = header;
            expressionTable.rows = expressions.map(expression => {
              const geneName = expression.geneName;
              const values = expression.values;

              const class2ValuesMap = new Map();

              for (let expressionClass of header) {
                class2ValuesMap.set(expressionClass, []);
              }

              for (let i = 0; i < values.length; i++) {
                class2ValuesMap.get(expressionClasses[i]).push(values[i]);
              }

              return { geneName: geneName, classValues: Array.from(class2ValuesMap.entries()).map((entry =>  _.mean(entry[1]).toFixed(2))) };
            });

            this.setState({
              expressionTable: expressionTable
            });
          });
        }
    });
  }

  toggleDrawer() {
    this.setState({drawerOpen: !this.state.drawerOpen});
  }

  render() {
    const state = this.state;

    const expressionTable = state.expressionTable;

    const networkNodes = state.cy.nodes().map(node => node.data('label'));
    const enrichmentsInNetwork = _.get(expressionTable, 'rows', []).filter(row => networkNodes.includes(row.geneName));

    const maxVal = _.max(enrichmentsInNetwork.map(row => _.max(row.classValues)).map((k, v) => parseFloat(k)));
    const minVal = _.min(enrichmentsInNetwork.map(row => _.min(row.classValues)).map((k, v) => parseFloat(k)));

    const expressionHeader = _.get(expressionTable, 'header', []);
    const expressionRows = _.get(expressionTable, 'rows', []);

    const columns = [
      {
        Header: 'Gene Name',
        accessor: 'geneName',
        filterMethod: (filter, rows) => {
          return matchSorter(rows, filter.value, { keys: ["geneName"] });
        },
        filterAll: true
      }
    ].concat(expressionHeader.map((className, index) => {
      return {
        Header: className,
        id: className,
        accessor: row => row.classValues[index]
      };
    }));
    return h('div.paint', [
      h('div.paint-content', [
        h('div', { className: classNames('paint-drawer', { 'closed': !state.drawerOpen }) }, [
          h('a', { onClick: e => this.toggleDrawer()}, [
            h(Icon, { icon: 'close'}),
          ]),
          h('div.paint-legend', [
            h('p', `low ${minVal}`),
            h('p', `high ${maxVal}`)
          ]),
          h(Table, {
            className:'-striped -highlight',
            data: expressionRows,
            columns: columns,
            filterable: true,
            defaultPageSize: 150,
            getTdProps: (state, rowInfo, column, instance) => {
              return {
                onMouseEnter: e => {
                  const geneName = rowInfo.original.geneName;
                  const debouncedSearch = _.debounce(cysearch, 300);
                  debouncedSearch(geneName, this.state.cy);
                }
              };
            }
           })
        ]),
        h(OmniBar, { name: state.name, datasource: state.datasource, onMenuClick: (e) => this.toggleDrawer() }),
        h(Network, { cy: state.cy, expressionTable: state.expressionTable })
      ])
    ]);
  }
}

module.exports = Paint;<commit_msg>Sort genes by whether or not they are found in the network<commit_after>const React = require('react');
const h = require('react-hyperscript');
const Table = require('react-table').default;

const queryString = require('query-string');
const color = require('color');
const _ = require('lodash');
const classNames = require('classnames');
const matchSorter = require('match-sorter').default;

const make_cytoscape = require('../../common/cy');
const cysearch = require('../../common/cy/search');

const Icon = require('../../common/components').Icon;
const { apiCaller, PathwayCommonsService } = require('../../services');

const analysisFunctions = [
  {
    name: 'mean',
    func: _.mean,
  },
  {
    name: 'count',
    func: _.countBy,
  },
  {
    name: 'min',
    func: _.min
  },
  {
    name: 'max',
    func: _.max
  }
];

class OmniBar extends React.Component {
  render() {
    const props = this.props;
    return h('div.paint-omnibar', [
      h('a', { onClick: e => props.onMenuClick(e) }, [
        h(Icon, { icon: 'menu' }, 'click')
      ]),
      h('h5', `${props.name} | ${props.datasource}`)
    ]);
  }
}

// props
// expression table
// cy
class Network extends React.Component {
  componentWillUnmount() {
    this.state.cy.destroy();
  }

  componentDidMount() {
    const props = this.props;
    const container = document.getElementById('cy-container');
    props.cy.mount(container);
  }

  colourMap(val, min, max) {
    const distToMax = Math.abs(val - max);
    const distToMin = Math.abs(val - min);

    let hVal, lVal;
    if (distToMax > distToMin) {
      hVal = 240;
      lVal = ( val / Math.abs(max) ) * 100 + 20;
    } else {
      hVal = 0;
      lVal = ( val / Math.abs(max) ) * 100 - 20;
    }
    return color.hsl(hVal, 100, lVal).string();
  }

  percentToColour(percent) {
    const hslValue = ( 1 - percent ) * 240;

    return color.hsl(hslValue, 100, 50).string();
  }

  componentWillReceiveProps(nextProps) {
    if (!_.isEmpty(nextProps.expressionTable)) {
      this.applyExpressionData(nextProps);
    }
  }

  applyExpressionData(props) {
    const expressionTable = props.expressionTable;
    const networkNodes = _.uniq(props.cy.nodes('[class="macromolecule"]').map(node => node.data('label'))).sort();

    const expressionsInNetwork = expressionTable.rows.filter(row => networkNodes.includes(row.geneName));
    const maxVal = _.max(expressionsInNetwork.map(row => _.max(row.classValues)).map((k, v) => parseFloat(k)));
    const minVal = _.min(expressionsInNetwork.map(row => _.min(row.classValues)).map((k, v) => parseFloat(k)));

    expressionsInNetwork.forEach(expression => {
      // probably more efficient to add the expression data to the node field instead of interating twice
      props.cy.nodes().filter(node => node.data('label') === expression.geneName).forEach(node => {

        const numSlices = expression.classValues.length > 16 ? 16 : expression.classValues.length;

        const pieStyle = {
          'pie-size': '100%'
        };
        for (let i = 1; i <= numSlices; i++) {

          pieStyle['pie-' + i + '-background-size'] = 100 / numSlices;
          pieStyle['pie-' + i + '-background-opacity'] = 1;
          pieStyle['pie-' + i + '-background-color'] = this.percentToColour(expression.classValues[i-1] / maxVal);
        }

        node.style(pieStyle);
      });
    });
  }

  render() {
    return h('div.paint-graph', [ h(`div.#cy-container`, {style: {width: '100vw', height: '100vh'}}) ]);
  }

}

class Paint extends React.Component {
  constructor(props) {
    super(props);

    const cy = make_cytoscape({headless: true});

    this.state = {
      rawEnrichmentData: {},
      expressionTable: {},
      cy: cy,
      name: '',
      datasource: '',
      drawerOpen: false
    };

    const query = queryString.parse(props.location.search);
    const enrichmentsURI = query.uri ? query.uri : null;

    if (enrichmentsURI != null) {
      fetch(enrichmentsURI)
        .then(response => response.json())
        .then(json => {
          this.setState({rawEnrichmentData: json});

          const expressionClasses = _.get(json.dataSetClassList, '0.classes', []);
          const expressions = _.get(json.dataSetExpressionList, '0.expressions', []);
          const searchParam = query.q;
          this.initPainter(expressions, expressionClasses, searchParam);

        });
    }
  }

  componentWillUnmount() {
    this.state.cy.destroy();
  }

  // only call this after you know component is mounted
  initPainter(expressions, expressionClasses, queryParam) {
    const state = this.state;
    const query = {
      q: queryParam,
      type: 'Pathway'
    };

    apiCaller.querySearch(query)
      .then(searchResults => {
        const uri = _.get(searchResults, '0.uri', null);

        if (uri != null) {
          apiCaller.getGraphAndLayout(uri, 'latest').then(response => {
            this.setState({
              name: _.get(response, 'graph.pathwayMetadata.title', 'N/A'),
              datasource: _.get(response, 'graph.pathwayMetadata.dataSource.0', 'N/A'),
            });

            state.cy.remove('*');
            state.cy.add({
              nodes: _.get(response, 'graph.nodes', []),
              edges: _.get(response, 'graph.edges', [])
            });

            state.cy.layout({
              name: 'cose-bilkent',
              randomize: false,
              nodeDimensionsIncludeLabels: true
            }).run();

            const expressionTable = {};

            const header = _.uniq(expressionClasses);

            expressionTable.header = header;
            expressionTable.rows = expressions.map(expression => {
              const geneName = expression.geneName;
              const values = expression.values;

              const class2ValuesMap = new Map();

              for (let expressionClass of header) {
                class2ValuesMap.set(expressionClass, []);
              }

              for (let i = 0; i < values.length; i++) {
                class2ValuesMap.get(expressionClasses[i]).push(values[i]);
              }

              return { geneName: geneName, classValues: Array.from(class2ValuesMap.entries()).map((entry =>  _.mean(entry[1]).toFixed(2))) };
            });

            this.setState({
              expressionTable: expressionTable
            });
          });
        }
    });
  }

  toggleDrawer() {
    this.setState({drawerOpen: !this.state.drawerOpen});
  }

  render() {
    const state = this.state;

    const expressionTable = state.expressionTable;
    const expressions = _.get(expressionTable, 'rows', []);

    const networkNodes = state.cy.nodes().map(node => node.data('label'));
    const expressionsInNetwork = expressions.filter(row => networkNodes.includes(row.geneName));
    const expressionsNotInNetwork = _.difference(expressions, expressionsInNetwork);

    const maxVal = _.max(expressionsInNetwork.map(row => _.max(row.classValues)).map((k, v) => parseFloat(k)));
    const minVal = _.min(expressionsInNetwork.map(row => _.min(row.classValues)).map((k, v) => parseFloat(k)));

    const expressionHeader = _.get(expressionTable, 'header', []);
    const expressionRows = expressionsInNetwork.concat(expressionsNotInNetwork);

    const columns = [
      {
        Header: 'Gene Name',
        accessor: 'geneName',
        filterMethod: (filter, rows) => {
          return matchSorter(rows, filter.value, { keys: ["geneName"] });
        },
        filterAll: true
      }
    ].concat(expressionHeader.map((className, index) => {
      return {
        Header: className,
        id: className,
        accessor: row => row.classValues[index]
      };
    }));
    return h('div.paint', [
      h('div.paint-content', [
        h('div', { className: classNames('paint-drawer', { 'closed': !state.drawerOpen }) }, [
          h('a', { onClick: e => this.toggleDrawer()}, [
            h(Icon, { icon: 'close'}),
          ]),
          h('div.paint-legend', [
            h('p', `low ${minVal}`),
            h('p', `high ${maxVal}`)
          ]),
          h(Table, {
            className:'-striped -highlight',
            data: expressionRows,
            columns: columns,
            filterable: true,
            defaultPageSize: 150,
            getTdProps: (state, rowInfo, column, instance) => {
              return {
                onMouseEnter: e => {
                  const geneName = _.get(rowInfo, 'original.geneName', '');
                  const debouncedSearch = _.debounce(cysearch, 700);
                  debouncedSearch(geneName, this.state.cy);
                }
              };
            }
           })
        ]),
        h(OmniBar, { name: state.name, datasource: state.datasource, onMenuClick: (e) => this.toggleDrawer() }),
        h(Network, { cy: state.cy, expressionTable: state.expressionTable })
      ])
    ]);
  }
}

module.exports = Paint;<|endoftext|>


<commit_before>var formManager = formManager || {};

var forms = {};

formManager.digestForms = function() {
    var key, form, formSelectorClass, targets;

    for (key in window.reforms) {
        form = window.reforms[key];
        forms[key] = form;
    }
};

formManager.getForm = function (name, opts) {
    var form = forms[name];
    opts = opts || {};
    var formKey = opts.key || "form-" + Date.now();
    var initial = opts.initial;
    var create = opts.create;
    var update = opts.update;
    var parent = opts.parent;
    return form;
};

formManager.digestForms();

module.exports = {
    getForm: formManager.getForm
};
<commit_msg>Clone the form rather than edit the original<commit_after>var formManager = formManager || {};

var forms = {};

formManager.digestForms = function() {
    var key, form, formSelectorClass, targets;

    for (key in window.reforms) {
        form = window.reforms[key];
        forms[key] = form;
    }
};

formManager.getForm = function (name, opts) {
    var form = forms[name]
    //opts = opts || {};
    //var formKey = opts.key || "form-" + Date.now();
    //var initial = opts.initial;
    //var create = opts.create;
    //var update = opts.update;
    //var parent = opts.parent;
    //
    //if (opts.initial !== undefined) {
    //    var initial = JSON.parse(JSON.stringify(opts.initial)); // <-- Clone the initial
    //}

    if (form === undefined) {
        return form;
    }

    return JSON.parse(JSON.stringify(forms[name]));
};

formManager.digestForms();

module.exports = {
    getForm: formManager.getForm
};
<|endoftext|>


<commit_before><script id="mathjaxscript_pelican_#%@#$@#"
        type="text/javascript"
        src="{{source}}" >
    var align = "{{align}}",
    var indent = "{{indent}}",
    var linebreak = "{{linebreak_automatic}}";

    if ({{responsive}}) {
        align = (screen.width < {{responsive_break}}) ? "left" : align;
        indent = (screen.width < {{responsive_break}}) ? "0em" : indent;
        linebreak = (screen.width < {{responsive_break}}) ? 'true' : linebreak;
    }
    MathJax.Hub.Config({
        config: ['MMLorHTML.js'],
        TeX: {
            extensions: {{tex_extensions|join(',')}}],
            equationNumbers: { autoNumber: 'AMS' } },
        jax: ['input/TeX','input/MathML','output/HTML-CSS'],
        extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js'],
        displayAlign: align,
        displayIndent: indent,
        showMathMenu: '{{show_menu}}',
        messageStyle: '{{mesage_style}}',
        tex2jax: {
            inlineMath: [ ['\\(','\\)'] ],
            displayMath: [ ['$$','$$'] ],
            processEscapes: {{process_escapes}},
            preview: '{{latex_preview}}',
        },
        HTML-CSS: {
            styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: '{{color}} !important'} },
            linebreaks: { automatic: linebreak, width: '90% container' },
        },
    });
    if ('{{mathjax_font}}' !== 'default') {
        MathJax.Hub.Register.StartupHook('HTML-CSS Jax Ready',function () {
            var VARIANT = MathJax.OutputJax['HTML-C}'].FONTDATA.VARIANT;
            VARIANT['normal'].fonts.unshift('MathJax_{{mathjax_font}}');
            VARIANT['bold'].fonts.unshift('MathJax_{{mathjax_font}}-bold');
            VARIANT['italic'].fonts.unshift('MathJax_{{mathjax_font}}-italic');
            VARIANT['-tex-mathit'].fonts.unshift('MathJax_{{mathjax_font}}-italic');
        });
        MathJax.Hub.Register.StartupHook('SVG Jax Ready',function () {
            var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;
            VARIANT['normal'].fonts.unshift('MathJax_{{mathjax_font}}');
            VARIANT['bold'].fonts.unshift('MathJax_{{mathjax_font}}-bold');
            VARIANT['italic'].fonts.unshift('MathJax_{{mathjax_font}}-italic');
            VARIANT['-tex-mathit'].fonts.unshift('MathJax_{{mathjax_font}}-italic');
        });
    }
</script><commit_msg>remove inline script configuration of MAthJax for render_math<commit_after><script id="mathjaxscript_pelican_#%@#$@#" type="text/javascript">
//see https://docs.mathjax.org/en/v2.5-latest/configuration.html#using-plain-javascript
    var align = "{{align}}",
    var indent = "{{indent}}",
    var linebreak = "{{linebreak_automatic}}";

    if ({{responsive}}) {
        align = (screen.width < {{responsive_break}}) ? "left" : align;
        indent = (screen.width < {{responsive_break}}) ? "0em" : indent;
        linebreak = (screen.width < {{responsive_break}}) ? 'true' : linebreak;
    }
    window.MathJax = {
        config: ['MMLorHTML.js'],
        TeX: {
            extensions: {{tex_extensions|join(',')}}],
            equationNumbers: { autoNumber: 'AMS' } },
        jax: ['input/TeX','input/MathML','output/HTML-CSS'],
        extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js'],
        displayAlign: align,
        displayIndent: indent,
        showMathMenu: '{{show_menu}}',
        messageStyle: '{{mesage_style}}',
        tex2jax: {
            inlineMath: [ ['\\(','\\)'] ],
            displayMath: [ ['$$','$$'] ],
            processEscapes: {{process_escapes}},
            preview: '{{latex_preview}}',
        },
        "HTML-CSS": {
            styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: '{{color}} !important'} },
            linebreaks: { automatic: linebreak, width: '90% container' },
        },
    };
    if ('{{mathjax_font}}' !== 'default') {
        window.MathJax.AuthorInit = function() {
            MathJax.Hub.Register.StartupHook('HTML-CSS Jax Ready',function () {
                var VARIANT = MathJax.OutputJax['HTML-C}'].FONTDATA.VARIANT;
                VARIANT['normal'].fonts.unshift('MathJax_{{mathjax_font}}');
                VARIANT['bold'].fonts.unshift('MathJax_{{mathjax_font}}-bold');
                VARIANT['italic'].fonts.unshift('MathJax_{{mathjax_font}}-italic');
                VARIANT['-tex-mathit'].fonts.unshift('MathJax_{{mathjax_font}}-italic');
            });
            MathJax.Hub.Register.StartupHook('SVG Jax Ready',function () {
                var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;
                VARIANT['normal'].fonts.unshift('MathJax_{{mathjax_font}}');
                VARIANT['bold'].fonts.unshift('MathJax_{{mathjax_font}}-bold');
                VARIANT['italic'].fonts.unshift('MathJax_{{mathjax_font}}-italic');
                VARIANT['-tex-mathit'].fonts.unshift('MathJax_{{mathjax_font}}-italic');
            });
        }
    }
</script>
<script id="mathjaxscript_pelican_#%@#$@#"
        type="text/javascript"
        src="{{source}}" >
</script><|endoftext|>


<commit_before>"use strict";
// Polyfills for Array Functions
SmartPolyfill.register('Array.isArray', {
  Chrome: '1 - 4',
  Firefox: '1 - 3',
  IE: '1 - 8',
  Safari: '1 - 4',
  Opera: '1 - 10'
}, function(o){
  return Object.prototype.toString.call(o) === '[object Array]';
});<commit_msg>:new: Add Array.prototype.indexOf polyfill<commit_after>"use strict";
// Polyfills for Array Functions
SmartPolyfill.register('Array.isArray', {
  Chrome: '1 - 4',
  Firefox: '1 - 3',
  IE: '1 - 8',
  Safari: '1 - 4',
  Opera: '1 - 10'
}, function(o){
  return Object.prototype.toString.call(o) === '[object Array]';
});
SmartPolyfill.register('Array.prototype.indexOf', {
  IE: '1 - 8'
}, function(searchElement, fromIndex) {
  fromIndex = fromIndex || 0;
  if(fromIndex < this.length){
    for(var i = fromIndex; i < this.length; ++i){
      if(this[i] === searchElement) return i;
    }
  }
  return -1;
});<|endoftext|>


<commit_before>function Camera(gl,d,modelUp) // Compute a camera from model's bounding box dimensions
{
	var center = [(d.min[0]+d.max[0])/2,(d.min[1]+d.max[1])/2,(d.min[2]+d.max[2])/2];
	var diagonal = Math.sqrt(Math.pow((d.max[0]-d.min[0]),2)+Math.pow((d.max[1]-d.min[1]),2)+Math.pow((d.max[2]-d.min[2]),2));

	var name = "auto";
	var at = center;
	var eye = [center[0], center[1]+diagonal*0.5, center[2]+diagonal*1.5];
	var up = [modelUp[0],modelUp[1],modelUp[2]];
	var near = diagonal*0.1;
	var far = diagonal*3;
	var FOV = 32;

	var delta = diagonal * 0.01; // movement step length
	var rotationAngle = 3; 		 // rotation step angle (degrees)

	// update matrices for draw()
	this.getViewMatrix=function(e){
		if (e==undefined) e = eye;
		return new Matrix4().setLookAt(e[0],e[1],e[2],at[0],at[1],at[2],up[0],up[1],up[2]);
	};
	this.getProjMatrix=function(){
		return new Matrix4().setPerspective(FOV, gl.canvas.width / gl.canvas.height, near , far);
	};
	this.getCameraPosition=function(){
		return [eye[0], eye[1], eye[2]];
	};
	this.getLookAtPoint = function() {
		return [at[0], at[1], at[2]];
	}

	// Calculate adjusted u,v,w axis in world space
	this.uAxis = function() {
		return cross(up, this.wAxis());
	};
	this.vAxis = function() {
		return cross(this.wAxis(), this.uAxis());
	};
	this.wAxis = function() {
		return normalize(subtractVectors(eye, at));
	};

	// PAN: rotate camera around Y-axis (V-axis) - left, right
	this.pan = function(direction){
		var angle = (direction)?rotationAngle:rotationAngle*-1;
		var V = this.vAxis();
		var m = new Matrix4().setTranslate(at[0],at[1],at[2]).rotate(-angle,V[0],V[1],V[2]);
		m.translate(-at[0],-at[1],-at[2]);
		var e = m.multiplyVector4(new Vector4([eye[0],eye[1],eye[2],1])).elements;
		eye[0]=e[0]; eye[1]=e[1]; eye[2]=e[2];
	};

	// TILT: Rotate around x-axis (U-axis) - up,down
	this.tilt = function(direction) {
		var angle = (direction)?rotationAngle:rotationAngle*-1;
		var step = eye[2];
		var U = this.uAxis();
		var m = new Matrix4().setTranslate(at[0],at[1],at[2]).rotate(-angle,U[0],U[1],U[2]).translate(-at[0],-at[1],-at[2]);
		var e = m.multiplyVector4(new Vector4([eye[0],eye[1],eye[2],1])).elements;
		step = Math.abs(step - e[2]);
		if(e[2] > step || e[2] < step*-1) { // prevent crossing up vector (flipping over)
			eye[0]=e[0]; eye[1]=e[1]; eye[2]=e[2];
		}
	};

	// ZOOM: in and out
	this.zoom = function(direction) {
		FOV = (direction)?FOV-1:FOV+1;
		// Prevent null frustrum & large FOV causing model to flip vertically
		if(FOV==0) FOV++;
		if(FOV==180) FOV--;
	};

	// DOLLY: Move camera closer or farther back (W axis)
	this.dolly = function(direction) {
		var d = (direction)?delta:delta*-1;
		var W = this.wAxis();
		var m = new Matrix4().setTranslate(W[0]*-d, W[1]*-d, W[2]*-d);
		var e = m.multiplyVector4(new Vector4([eye[0],eye[1],eye[2],1])).elements;
		eye[0]=e[0]; eye[1]=e[1]; eye[2]=e[2];
		var d = new Matrix4().setTranslate(W[0]*-d, W[1]*-d, W[2]*-d);
		var a = d.multiplyVector4(new Vector4([at[0],at[1],at[2],1])).elements;
		at[0]=a[0]; at[1]=a[1]; at[2]=a[2];
	};

	// PEDESTAL: Move camera up or down (V axis)
	this.pedestal = function(direction) {
		var d = (direction)?delta:delta*-1;
		var V = this.vAxis();
		var m = new Matrix4().setTranslate(V[0]*d, V[1]*d, V[2]*d);
		var e = m.multiplyVector4(new Vector4([eye[0],eye[1],eye[2],1])).elements;
		eye[0]=e[0]; eye[1]=e[1]; eye[2]=e[2];
		var a = m.multiplyVector4(new Vector4([at[0],at[1],at[2],1])).elements;
		at[0]=a[0]; at[1]=a[1]; at[2]=a[2];
	};

	// TRUCK: Move camera left or right  (U axis)
	this.truck = function(direction) {
		var d = (direction)?delta:delta*-1;
		var U = this.uAxis();
		var m = new Matrix4().setTranslate(U[0]*-d, U[1]*-d, U[2]*-d);
		var e = m.multiplyVector4(new Vector4([eye[0],eye[1],eye[2],1])).elements;
		eye[0]=e[0]; eye[1]=e[1]; eye[2]=e[2];
		var a = m.multiplyVector4(new Vector4([at[0],at[1],at[2],1])).elements;
		at[0]=a[0]; at[1]=a[1]; at[2]=a[2];
	};
}

// vector math functions
function normalize(v) {
  var length = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
  // make sure we don't divide by 0.
  if (length > 0.00001) {
    return [v[0] / length, v[1] / length, v[2] / length];
  } else {
    return [0, 0, 0];
  }
}

function cross(a, b) {
  return [a[1] * b[2] - a[2] * b[1],
          a[2] * b[0] - a[0] * b[2],
          a[0] * b[1] - a[1] * b[0]];
}

function subtractVectors(a, b) {
  return [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
}

<commit_msg>Fixed camera movement to match regular FPS camera movement<commit_after>function Camera(gl,d,modelUp) // Compute a camera from model's bounding box dimensions
{
	var center = [(d.min[0]+d.max[0])/2,(d.min[1]+d.max[1])/2,(d.min[2]+d.max[2])/2];
	var diagonal = Math.sqrt(Math.pow((d.max[0]-d.min[0]),2)+Math.pow((d.max[1]-d.min[1]),2)+Math.pow((d.max[2]-d.min[2]),2));

	var name = "auto";
	var at = center;
	var eye = [center[0], center[1]+diagonal*0.5, center[2]+diagonal*1.5];
	var up = [modelUp[0],modelUp[1],modelUp[2]];
	var near = diagonal*0.1;
	var far = diagonal*3;
	var FOV = 32;

	var delta = diagonal * 0.01; // movement step length
	var rotationAngle = 3; 		 // rotation step angle (degrees)

	// update matrices for draw()
	this.getViewMatrix=function(e){
		if (e==undefined) e = eye;
		return new Matrix4().setLookAt(e[0],e[1],e[2],at[0],at[1],at[2],up[0],up[1],up[2]);
	};
	this.getProjMatrix=function(){
		return new Matrix4().setPerspective(FOV, gl.canvas.width / gl.canvas.height, near , far);
	};
	this.getCameraPosition=function(){
		return [eye[0], eye[1], eye[2]];
	};
	this.getLookAtPoint = function() {
		return [at[0], at[1], at[2]];
	}

	// Calculate adjusted u,v,w axis in world space
	this.uAxis = function() {
		return cross(up, this.wAxis());
	};
	this.vAxis = function() {
		return cross(this.wAxis(), this.uAxis());
	};
	this.wAxis = function() {
		return normalize(subtractVectors(eye, at));
	};

	// PAN: rotate camera around Y-axis (V-axis) - left, right
	this.pan = function(direction){
		var angle = (direction)?rotationAngle*-1:rotationAngle;
		var V = this.vAxis();
		var m = new Matrix4().setTranslate(eye[0],eye[1],eye[2]).rotate(-angle,V[0],V[1],V[2]);
		m.translate(-eye[0],-eye[1],-eye[2]);
		var e = m.multiplyVector4(new Vector4([at[0],at[1],at[2],1])).elements;
		at[0]=e[0]; at[1]=e[1]; at[2]=e[2];
	};

	// TILT: Rotate around x-axis (U-axis) - up,down
	this.tilt = function(direction) {
		var angle = (direction)?rotationAngle:rotationAngle*-1;
		var step = at[2];
		var U = this.uAxis();
		var m = new Matrix4().setTranslate(eye[0],eye[1],eye[2]).rotate(-angle,U[0],U[1],U[2]).translate(-eye[0],-eye[1],-eye[2]);
		var e = m.multiplyVector4(new Vector4([at[0],at[1],at[2],1])).elements;
		step = Math.abs(step - e[2]);
		if(e[2] > step || e[2] < step*-1) { // prevent crossing up vector (flipping over)
			at[0]=e[0]; at[1]=e[1]; at[2]=e[2];
		}
	};

	// ZOOM: in and out
	this.zoom = function(direction) {
		FOV = (direction)?FOV-1:FOV+1;
		// Prevent null frustrum & large FOV causing model to flip vertically
		if(FOV==0) FOV++;
		if(FOV==180) FOV--;
	};

	// DOLLY: Move camera closer or farther back (W axis)
	this.dolly = function(direction) {
		var d = (direction)?delta:delta*-1;
		var W = this.wAxis();
		var m = new Matrix4().setTranslate(W[0]*-d, W[1]*-d, W[2]*-d);
		var e = m.multiplyVector4(new Vector4([eye[0],eye[1],eye[2],1])).elements;
		eye[0]=e[0]; eye[1]=e[1]; eye[2]=e[2];
		var d = new Matrix4().setTranslate(W[0]*-d, W[1]*-d, W[2]*-d);
		var a = d.multiplyVector4(new Vector4([at[0],at[1],at[2],1])).elements;
		at[0]=a[0]; at[1]=a[1]; at[2]=a[2];
	};

	// PEDESTAL: Move camera up or down (V axis)
	this.pedestal = function(direction) {
		var d = (direction)?delta:delta*-1;
		var V = this.vAxis();
		var m = new Matrix4().setTranslate(V[0]*d, V[1]*d, V[2]*d);
		var e = m.multiplyVector4(new Vector4([eye[0],eye[1],eye[2],1])).elements;
		eye[0]=e[0]; eye[1]=e[1]; eye[2]=e[2];
		var a = m.multiplyVector4(new Vector4([at[0],at[1],at[2],1])).elements;
		at[0]=a[0]; at[1]=a[1]; at[2]=a[2];
	};

	// TRUCK: Move camera left or right  (U axis)
	this.truck = function(direction) {
		var d = (direction)?delta:delta*-1;
		var U = this.uAxis();
		var m = new Matrix4().setTranslate(U[0]*-d, U[1]*-d, U[2]*-d);
		var e = m.multiplyVector4(new Vector4([eye[0],eye[1],eye[2],1])).elements;
		eye[0]=e[0]; eye[1]=e[1]; eye[2]=e[2];
		var a = m.multiplyVector4(new Vector4([at[0],at[1],at[2],1])).elements;
		at[0]=a[0]; at[1]=a[1]; at[2]=a[2];
	};
}

// vector math functions
function normalize(v) {
  var length = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
  // make sure we don't divide by 0.
  if (length > 0.00001) {
    return [v[0] / length, v[1] / length, v[2] / length];
  } else {
    return [0, 0, 0];
  }
}

function cross(a, b) {
  return [a[1] * b[2] - a[2] * b[1],
          a[2] * b[0] - a[0] * b[2],
          a[0] * b[1] - a[1] * b[0]];
}

function subtractVectors(a, b) {
  return [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
}

<|endoftext|>


<commit_before>'use strict'

var lodash = require('lodash')
var str = 'kiko beats huele mal'

var result = str.split(' ').reduce(function (accumulator, str, index) {
  var separator = index === 0 ? '' : ' '
  return accumulator + separator + lodash.capitalize(str)
}, '')

console.log("'" + result + "'")
<commit_msg>Remove unnecessary<commit_after><|endoftext|>


<commit_before>import {Container, inject} from 'aurelia-dependency-injection';
import {ArrayCollectionStrategy} from './array-collection-strategy';
import {MapCollectionStrategy} from './map-collection-strategy';
import {NumberStrategy} from './number-strategy';

@inject(Container)
export class CollectionStrategyLocator {
  constructor(container) {
    this.container = container;
  }

  getStrategy(items){
    let strategy;
    if (items instanceof Array) {
      strategy = this.container.get(ArrayCollectionStrategy);
    } else if (items instanceof Map) {
      strategy = this.container.get(MapCollectionStrategy);
    } else if (items instanceof Number) {
      strategy = this.container.get(NumberStrategy);
    } else {
      throw new Error('Object in "repeat" must be of type Array, Map or Number');
    }

    return strategy;
  }
}
<commit_msg>fix(collection-strategy-locator): correctly check for number<commit_after>import {Container, inject} from 'aurelia-dependency-injection';
import {ArrayCollectionStrategy} from './array-collection-strategy';
import {MapCollectionStrategy} from './map-collection-strategy';
import {NumberStrategy} from './number-strategy';

@inject(Container)
export class CollectionStrategyLocator {
  constructor(container) {
    this.container = container;
  }

  getStrategy(items){
    let strategy;
    if (items instanceof Array) {
      strategy = this.container.get(ArrayCollectionStrategy);
    } else if (items instanceof Map) {
      strategy = this.container.get(MapCollectionStrategy);
    } else if ((typeof items === 'number')) {
      strategy = this.container.get(NumberStrategy);
    } else {
      throw new Error('Object in "repeat" must be of type Array, Map or Number');
    }

    return strategy;
  }
}
<|endoftext|>


<commit_before>;(function($$){ 'use strict';

  // Collection functions that toggle a boolean value
  ////////////////////////////////////////////////////////////////////////////////////////////////////

  function defineSwitchFunction(params){
    return function(){
      var args = arguments;

      // e.g. cy.nodes().select( data, handler )
      if( args.length === 2 ){
        var data = args[0];
        var handler = args[1];
        this.bind( params.event, data, handler );
      }

      // e.g. cy.nodes().select( handler )
      else if( args.length === 1 ){
        var handler = args[0];
        this.bind( params.event, handler );
      }

      // e.g. cy.nodes().select()
      else if( args.length === 0 ){
        for( var i = 0; i < this.length; i++ ){
          var ele = this[i];
          var able = !params.ableField || ele._private[params.ableField];

          if( params.overrideAble ){
            var overrideAble = params.overrideAble(ele);

            if( overrideAble !== undefined ){
              able = overrideAble;

              if( !overrideAble ){ return this; } // to save cycles assume not able for all on override
            }
          }

          if( able ){
            ele._private[params.field] = params.value;
          }
        }
        this.updateStyle(); // change of state => possible change of style
        this.trigger( params.event );
      }

      return this;
    };
  }

  function defineSwitchSet( params ){
    $$.elesfn[ params.field ] = function(){
      var ele = this[0];

      if( ele ){
        if( params.overrideField ){
          var val = params.overrideField(ele);

          if( val !== undefined ){
            return val;
          }
        }

        return ele._private[ params.field ];
      }
    };

    $$.elesfn[ params.on ] = defineSwitchFunction({
      event: params.on,
      field: params.field,
      ableField: params.ableField,
      overrideAble: params.overrideAble,
      value: true
    });

    $$.elesfn[ params.off ] = defineSwitchFunction({
      event: params.off,
      field: params.field,
      ableField: params.ableField,
      overrideAble: params.overrideAble,
      value: false
    });
  }

  defineSwitchSet({
    field: 'locked',
    overrideField: function(ele){
      return ele.cy().autolock() ? true : undefined;
    },
    on: 'lock',
    off: 'unlock'
  });

  defineSwitchSet({
    field: 'grabbable',
    overrideField: function(ele){
      return ele.cy().autoungrabify() ? false : undefined;
    },
    on: 'grabify',
    off: 'ungrabify'
  });

  defineSwitchSet({
    field: 'selected',
    ableField: 'selectable',
    overrideAble: function(ele){
      return ele.cy().autounselectify() ? false : undefined;
    },
    on: 'select',
    off: 'unselect'
  });

  defineSwitchSet({
    field: 'selectable',
    overrideField: function(ele){
      return ele.cy().autounselectify() ? false : undefined;
    },
    on: 'selectify',
    off: 'unselectify'
  });

  $$.elesfn.deselect = $$.elesfn.unselect;

  $$.elesfn.grabbed = function(){
    var ele = this[0];
    if( ele ){
      return ele._private.grabbed;
    }
  };

  defineSwitchSet({
    field: 'active',
    on: 'activate',
    off: 'unactivate'
  });

  $$.elesfn.inactive = function(){
    var ele = this[0];
    if( ele ){
      return !ele._private.active;
    }
  };

})( cytoscape );
<commit_msg> Switch functions should be scoped on changed eles for style and event updates #832<commit_after>;(function($$){ 'use strict';

  // Collection functions that toggle a boolean value
  ////////////////////////////////////////////////////////////////////////////////////////////////////

  function defineSwitchFunction(params){
    return function(){
      var args = arguments;
      var changedEles = [];

      // e.g. cy.nodes().select( data, handler )
      if( args.length === 2 ){
        var data = args[0];
        var handler = args[1];
        this.bind( params.event, data, handler );
      }

      // e.g. cy.nodes().select( handler )
      else if( args.length === 1 ){
        var handler = args[0];
        this.bind( params.event, handler );
      }

      // e.g. cy.nodes().select()
      else if( args.length === 0 ){
        for( var i = 0; i < this.length; i++ ){
          var ele = this[i];
          var able = !params.ableField || ele._private[params.ableField];
          var changed = ele._private[params.field] != params.value;

          if( params.overrideAble ){
            var overrideAble = params.overrideAble(ele);

            if( overrideAble !== undefined ){
              able = overrideAble;

              if( !overrideAble ){ return this; } // to save cycles assume not able for all on override
            }
          }

          if( able ){
            ele._private[params.field] = params.value;

            if( changed ){
              changedEles.push( ele );
            }
          }
        }

        var changedColl = $$.Collection( this.cy(), changedEles );
        changedColl.updateStyle(); // change of state => possible change of style
        changedColl.trigger( params.event );
      }

      return this;
    };
  }

  function defineSwitchSet( params ){
    $$.elesfn[ params.field ] = function(){
      var ele = this[0];

      if( ele ){
        if( params.overrideField ){
          var val = params.overrideField(ele);

          if( val !== undefined ){
            return val;
          }
        }

        return ele._private[ params.field ];
      }
    };

    $$.elesfn[ params.on ] = defineSwitchFunction({
      event: params.on,
      field: params.field,
      ableField: params.ableField,
      overrideAble: params.overrideAble,
      value: true
    });

    $$.elesfn[ params.off ] = defineSwitchFunction({
      event: params.off,
      field: params.field,
      ableField: params.ableField,
      overrideAble: params.overrideAble,
      value: false
    });
  }

  defineSwitchSet({
    field: 'locked',
    overrideField: function(ele){
      return ele.cy().autolock() ? true : undefined;
    },
    on: 'lock',
    off: 'unlock'
  });

  defineSwitchSet({
    field: 'grabbable',
    overrideField: function(ele){
      return ele.cy().autoungrabify() ? false : undefined;
    },
    on: 'grabify',
    off: 'ungrabify'
  });

  defineSwitchSet({
    field: 'selected',
    ableField: 'selectable',
    overrideAble: function(ele){
      return ele.cy().autounselectify() ? false : undefined;
    },
    on: 'select',
    off: 'unselect'
  });

  defineSwitchSet({
    field: 'selectable',
    overrideField: function(ele){
      return ele.cy().autounselectify() ? false : undefined;
    },
    on: 'selectify',
    off: 'unselectify'
  });

  $$.elesfn.deselect = $$.elesfn.unselect;

  $$.elesfn.grabbed = function(){
    var ele = this[0];
    if( ele ){
      return ele._private.grabbed;
    }
  };

  defineSwitchSet({
    field: 'active',
    on: 'activate',
    off: 'unactivate'
  });

  $$.elesfn.inactive = function(){
    var ele = this[0];
    if( ele ){
      return !ele._private.active;
    }
  };

})( cytoscape );
<|endoftext|>


<commit_before>var log = require('./logger').config({ level: 0 });

log.debug('hello?');

log.info('hello world!');

log.warn('careful there, world');

log.error('WHOA WHOA WHOA world!');
<commit_msg>Update example to show message formatting with util.format<commit_after>var log = require('./logger').config({ level: 0 });

log.debug('hello?');

log.info('hello world!');

log.warn('careful there, world');

log.error('WHOA WHOA WHOA world!');

log.info("I see", "3", "bananas!") // Outputs "I see 3 bananas!"

log.config({
	messageFormatting: true
});

log.info("I see %d %s!", 3, "bananas"); // Outputs "I see 3 bananas!"
<|endoftext|>


<commit_before>export default class GLUtils {
  static createProgram(gl, vertexShaderStr, fragmentShaderStr) {
    let vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader, vertexShaderStr);
    gl.compileShader(vertexShader);
    if(!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
      console.error("Error compiling shader:", gl.getShaderInfoLog(vertexShader));
    }

    let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader, fragmentShaderStr);
    gl.compileShader(fragmentShader);
    if(!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
      console.error("Error compiling shader:", gl.getShaderInfoLog(fragmentShader));
    }

    let program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);

    return program;
  }
}
<commit_msg>add shader src in error logs<commit_after>export default class GLUtils {
  static createProgram(gl, vertexShaderStr, fragmentShaderStr) {
    let vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader, vertexShaderStr);
    gl.compileShader(vertexShader);
    if(!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
      console.error("Error compiling shader:", gl.getShaderInfoLog(vertexShader), vertexShaderStr);
    }

    let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader, fragmentShaderStr);
    gl.compileShader(fragmentShader);
    if(!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
      console.error("Error compiling shader:", gl.getShaderInfoLog(fragmentShader), fragmentShaderStr);
    }

    let program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);

    return program;
  }
}
<|endoftext|>


<commit_before>/* @flow */

import GLBoost from '../globals';

export default class AnimationPlayer {
  __animationLastTime: number;

  constructor() {
  }

  init(group:any) {
    this.__FpsForPlaying = (group.animationFps !== void 0) ? group.animationFps:60;

    this.__animationStartTime = group.getStartAnimationInputValue('time');
    this.__animationEndTime = group.getEndAnimationInputValue('time');
    this.__animationStartRange = this.__animationStartTime;
    this.__animationEndRange = this.__animationEndTime;
    this.__animationCurrentTime = this.__animationStartTime;
    this.__animationLength = group.getEndAnimationInputValue('time');
    this.__animationLastTime = 0;

    this.__currentMillisecondAtStart = 0;
    this.__isPlaying = 0;
    this.__currentMotion = "All";
    this.__animationMotions = [];

    this.__setupMultiMotions(group);
  }

  play() {
    this.__isPlaying = true;
    this.__currentMillisecondAtStart = Date.now();
  }

  calcAnimationTime(speedRatio = 1) {
    if (!this.__isPlaying) {
      this.__currentMillisecondAtStart = Date.now();
      return this.__animationCurrentTime;
    }

    let currentMillisecondFromStart = Date.now()
    this.__animationCurrentTime = (currentMillisecondFromStart - this.__currentMillisecondAtStart)/1000 + this.__animationLastTime;
    let localAnimationCurrentTime = this.__animationCurrentTime * speedRatio;

    if (localAnimationCurrentTime > this.__animationEndRange) {
      this.moveToTheTime(this.__animationStartRange);
    } else if (localAnimationCurrentTime < this.__animationStartRange) {
      this.moveToTheTime(this.__animationStartRange);
    }

    if (this.__animationStartRange > this.__animationLength) {
      this.moveToTheTime(this.__animationStartRange);
    }

    this.__animationCurrentTime = localAnimationCurrentTime / speedRatio;

    return localAnimationCurrentTime;
  }

  __setupMultiMotions(group:any) {
    const json = {
      "name": "All",
      "start": group.getStartAnimationInputValue('time') * this.__FpsForPlaying,
      "end": group.getEndAnimationInputValue('time') * this.__FpsForPlaying
    };

    this.animationMotions.push(json);

    if (!group.animationTracks) {
      return;
    }

    if (group.animationTracks) {
      Array.prototype.push.apply(this.animationMotions, group.animationTracks);
    }

    this.__currentMotion = group.animationTracks[0].name;
  }

  moveToTheTime(time:number) {
    this.__currentMillisecondAtStart = Date.now();
    this.__animationCurrentTime = time;
    this.__animationLastTime = this.__animationCurrentTime;
  }

  changeMotion(motionName:string) {
    for(let motion of this.__animationMotions) {
      if (motion.name === motionName) {
        this.changeRange(motion.start / this.__FpsForPlaying, motion.end / this.__FpsForPlaying);
        this.moveToTheTime(motion.start / this.__FpsForPlaying);
      }
    }
  }

  changeRange(start:number, end:number) {
    this.__animationStartRange = start;
    this.__animationEndRange = end;
    const time = this.__animationCurrentTime;
    this.moveToTheTime(time);
  };

  get animationMotions() {
    return this.__animationMotions;
  }

  set animationMotions(motions) {
    this.__animationMotions = motions;
  }
}

GLBoost['AnimationPlayer'] = AnimationPlayer;
<commit_msg>Rebase<commit_after>/* @flow */

import GLBoost from '../globals';

export default class AnimationPlayer {
  __FpsForPlaying: number;
  __animationStartTime: number;
  __animationEndTime: number;
  __animationStartRange: number;
  __animationEndRange: number;
  __animationCurrentTime: number;
  __animationLength: number;
  __animationLastTime: number;
  __currentMillisecondAtStart: number;
  __isPlaying: boolean;
  __currentMotion: string;

  __animationMotions: Array<any>;

  constructor() {
  }

  init(group:any) {
    this.__FpsForPlaying = (group.animationFps !== void 0) ? group.animationFps:60;

    this.__animationStartTime = group.getStartAnimationInputValue('time');
    this.__animationEndTime = group.getEndAnimationInputValue('time');
    this.__animationStartRange = this.__animationStartTime;
    this.__animationEndRange = this.__animationEndTime;
    this.__animationCurrentTime = this.__animationStartTime;
    this.__animationLength = group.getEndAnimationInputValue('time');
    this.__animationLastTime = 0;

    this.__currentMillisecondAtStart = 0;
    this.__isPlaying = false;
    this.__currentMotion = "All";
    this.__animationMotions = [];

    this.__setupMultiMotions(group);
  }

  play() {
    this.__isPlaying = true;
    this.__currentMillisecondAtStart = Date.now();
  }

  calcAnimationTime(speedRatio:number = 1) {
    if (!this.__isPlaying) {
      this.__currentMillisecondAtStart = Date.now();
      return this.__animationCurrentTime;
    }

    let currentMillisecondFromStart = Date.now()
    this.__animationCurrentTime = (currentMillisecondFromStart - this.__currentMillisecondAtStart)/1000 + this.__animationLastTime;
    let localAnimationCurrentTime = this.__animationCurrentTime * speedRatio;

    if (localAnimationCurrentTime > this.__animationEndRange) {
      this.moveToTheTime(this.__animationStartRange);
    } else if (localAnimationCurrentTime < this.__animationStartRange) {
      this.moveToTheTime(this.__animationStartRange);
    }

    if (this.__animationStartRange > this.__animationLength) {
      this.moveToTheTime(this.__animationStartRange);
    }

    this.__animationCurrentTime = localAnimationCurrentTime / speedRatio;

    return localAnimationCurrentTime;
  }

  __setupMultiMotions(group:any) {
    const json = {
      "name": "All",
      "start": group.getStartAnimationInputValue('time') * this.__FpsForPlaying,
      "end": group.getEndAnimationInputValue('time') * this.__FpsForPlaying
    };

    this.animationMotions.push(json);

    if (!group.animationTracks) {
      return;
    }

    if (group.animationTracks) {
      Array.prototype.push.apply(this.animationMotions, group.animationTracks);
    }

    this.__currentMotion = group.animationTracks[0].name;
  }

  moveToTheTime(time:number) {
    this.__currentMillisecondAtStart = Date.now();
    this.__animationCurrentTime = time;
    this.__animationLastTime = this.__animationCurrentTime;
  }

  changeMotion(motionName:string) {
    for(let motion of this.__animationMotions) {
      if (motion.name === motionName) {
        this.changeRange(motion.start / this.__FpsForPlaying, motion.end / this.__FpsForPlaying);
        this.moveToTheTime(motion.start / this.__FpsForPlaying);
      }
    }
  }

  changeRange(start:number, end:number) {
    this.__animationStartRange = start;
    this.__animationEndRange = end;
    const time = this.__animationCurrentTime;
    this.moveToTheTime(time);
  };

  get animationMotions() {
    return this.__animationMotions;
  }

  set animationMotions(motions) {
    this.__animationMotions = motions;
  }
}

GLBoost['AnimationPlayer'] = AnimationPlayer;
<|endoftext|>


<commit_before>describe('ax5.util.date TEST', function () {
    /* ax5.util.date */
    //Usage 01
    it('ax5.util.date("2013-01-01")', function () {
        var date = new Date(2013, 0, 1);
        date.setHours(12);
        date.setMinutes(0);
        should.deepEqual(ax5.util.date('2013-01-01'), date);
    });

    //Usage 02
    it('ax5.util.date((new Date()) , {add:{d:10} , return:"yyyy/MM/dd"})', function () {
        var date = new Date();
        date.setDate(date.getDate() + 10);
        var str = date.getFullYear() + "/" + ax5.util.setDigit(date.getMonth() + 1, 2) + "/" + ax5.util.setDigit(date.getDate(), 2);

        should.deepEqual(ax5.util.date((new Date()), {add: {d: 10}, return: 'yyyy/MM/dd'}), str);
    });

    //Usage 03
    it('ax5.util.date("1919-03-01", {add:{d:10}, return:"yyyy/MM/dd hh:mm:ss"})', function () {
        should.deepEqual(ax5.util.date("1919-03-01", {add: {d: 10}, return: "yyyy/MM/dd hh:mm:ss"}), '1919/03/11 12:00:00');
    });

    //Usage 04
    it('ax5.util.date((new Date()) , {set:"firstDayOfMonth", return:"yyyy/MM/dd"})', function () {
        var date = new Date();
        var str = date.getFullYear() + "/" + ax5.util.setDigit(date.getMonth() + 1, 2) + "/01";
        should.deepEqual(ax5.util.date((new Date()), {set: "firstDayOfMonth", return: 'yyyy/MM/dd'}), str);
    });

    //Usage 05
    it('ax5.util.date((new Date()) , {set:"lastDayOfMonth", return:"yyyy/MM/dd"})', function () {
        var date = new Date();
        var str = date.getFullYear() + "/" + ax5.util.setDigit(date.getMonth() + 1, 2) + "/" + ax5.util.daysOfMonth(date.getFullYear(), date.getMonth());
        should.deepEqual(ax5.util.date((new Date()), {set: "lastDayOfMonth", return: 'yyyy/MM/dd'}), str);
    });

    //Usage 06
    it('ax5.util.date("20170411103317") [string.length == 14]', function () {
        var date = new Date(2017, 3, 11);
        date.setHours(10);
        date.setMinutes(33);
        date.setSeconds(17);
        should.deepEqual(ax5.util.date("20170411103317"), date);
    });

    //Usage 07
    it('ax5.util.date("201704") [string.length == 7]', function () {
        var date = new Date(2017, 3);
        date.setHours(12);
        should.deepEqual(ax5.util.date("201704"), date);
    });

    /* end ax5.util.date */
});

describe('ax5.util.dday TEST', function () {
    /* ax5.util.dday*/
    //Usage 01
    it('ax5.util.dday(new Date())', function () {
        should.deepEqual(ax5.util.dday(new Date()), 0);
    });

    //Usage 02
    it('ax5.util.dday("2016-01-29" , {today:"2016-01-28"})', function () {
        should.deepEqual(ax5.util.dday("2016-01-29", {today: "2016-01-28"}), 1);
    });

    //Usage 03
    it('ax5.util.dday("1977-03-29" , {today:"2016-01-28" , age:true})', function () {
        should.deepEqual(ax5.util.dday("1977-03-29", {today: "2016-01-28", age: true}), 39);
    });
    /* end ax5.util.dday*/
});

describe('ax5.util.weeksOfMonth TEST', function () {
    /* ax5.util.weeksOfMonth */
    //Usage 01
    it('ax5.util.weeksOfMonth("2015-10-01")', function () {
        var obj = {
            year: 2015,
            month: 10,
            count: 1
        }
        should.deepEqual(ax5.util.weeksOfMonth("2015-10-01"), obj);
    });

    //Usage02
    it('ax5.util.weeksOfMonth("2015-09-19")', function () {
        var obj = {
            year: 2015,
            month: 9,
            count: 3
        }
        should.deepEqual(ax5.util.weeksOfMonth("2015-09-19"), obj);
    });

    //Usage03
    it('ax5.util.weeksOfMonth("2016-04-30")', function () {
        var obj = {
            year: 2016,
            month: 4,
            count: 5
        }
        should.deepEqual(ax5.util.weeksOfMonth("2016-04-30"), obj);
    });
    /* end ax5.util.weeksOfMonth */
});

describe('ax5.util.daysOfMonth TEST', function () {
    /* ax5.util.daysOfMonth*/
    //Usage 01
    it('ax5.util.daysOfMonth(2015,11)', function () {
        should.deepEqual(ax5.util.daysOfMonth(2015, 11), 31);
    });

    //Usage 02
    it('ax5.util.daysOfMonth(2015,1)', function () {
        should.deepEqual(ax5.util.daysOfMonth(2015, 1), 28);
    });

    //Usage 03
    it('ax5.util.daysOfMonth(2016,1)', function () {
        should.deepEqual(ax5.util.daysOfMonth(2016, 1), 29);
    });
    /* end ax5.util.daysOfMonth*/
});<commit_msg>update test code<commit_after>describe('ax5.util.date TEST', function () {
    /* ax5.util.date */
    //Usage 01
    it('ax5.util.date("2013-01-01")', function () {
        var date = new Date(2013, 0, 1);
        date.setHours(12);
        date.setMinutes(0);
        should.deepEqual(ax5.util.date('2013-01-01'), date);
    });

    //Usage 02
    it('ax5.util.date((new Date()) , {add:{d:10} , return:"yyyy/MM/dd"})', function () {
        var date = new Date();
        date.setDate(date.getDate() + 10);
        var str = date.getFullYear() + "/" + ax5.util.setDigit(date.getMonth() + 1, 2) + "/" + ax5.util.setDigit(date.getDate(), 2);

        should.deepEqual(ax5.util.date((new Date()), {add: {d: 10}, return: 'yyyy/MM/dd'}), str);
    });

    //Usage 03
    it('ax5.util.date("1919-03-01", {add:{d:10}, return:"yyyy/MM/dd hh:mm:ss"})', function () {
        should.deepEqual(ax5.util.date("1919-03-01", {add: {d: 10}, return: "yyyy/MM/dd hh:mm:ss"}), '1919/03/11 12:00:00');
    });

    //Usage 04
    it('ax5.util.date((new Date()) , {set:"firstDayOfMonth", return:"yyyy/MM/dd"})', function () {
        var date = new Date();
        var str = date.getFullYear() + "/" + ax5.util.setDigit(date.getMonth() + 1, 2) + "/01";
        should.deepEqual(ax5.util.date((new Date()), {set: "firstDayOfMonth", return: 'yyyy/MM/dd'}), str);
    });

    //Usage 05
    it('ax5.util.date((new Date()) , {set:"lastDayOfMonth", return:"yyyy/MM/dd"})', function () {
        var date = new Date();
        var str = date.getFullYear() + "/" + ax5.util.setDigit(date.getMonth() + 1, 2) + "/" + ax5.util.daysOfMonth(date.getFullYear(), date.getMonth());
        should.deepEqual(ax5.util.date((new Date()), {set: "lastDayOfMonth", return: 'yyyy/MM/dd'}), str);
    });

    //Usage 06
    it('ax5.util.date("20170411103317") [string.length == 14]', function () {
        var date = new Date(2017, 3, 11);
        date.setHours(10);
        date.setMinutes(33);
        date.setSeconds(17);
        should.deepEqual(ax5.util.date("20170411103317"), date);
    });

    //Usage 07
    it('ax5.util.date("201704") [string.length > 7]', function () {
        var date = new Date(2017, 3, 12);
        date.setHours(12);
        should.deepEqual(ax5.util.date("20170412"), date);
    });

    //Usage 08
    it('ax5.util.date("201704") [string.length > 4]', function () {
        var date = new Date(2017, 3);
        date.setHours(12);
        should.deepEqual(ax5.util.date("201704"), date);
    });

    /* end ax5.util.date */
});

describe('ax5.util.dday TEST', function () {
    /* ax5.util.dday*/
    //Usage 01
    it('ax5.util.dday(new Date())', function () {
        should.deepEqual(ax5.util.dday(new Date()), 0);
    });

    //Usage 02
    it('ax5.util.dday("2016-01-29" , {today:"2016-01-28"})', function () {
        should.deepEqual(ax5.util.dday("2016-01-29", {today: "2016-01-28"}), 1);
    });

    //Usage 03
    it('ax5.util.dday("1977-03-29" , {today:"2016-01-28" , age:true})', function () {
        should.deepEqual(ax5.util.dday("1977-03-29", {today: "2016-01-28", age: true}), 39);
    });
    /* end ax5.util.dday*/
});

describe('ax5.util.weeksOfMonth TEST', function () {
    /* ax5.util.weeksOfMonth */
    //Usage 01
    it('ax5.util.weeksOfMonth("2015-10-01")', function () {
        var obj = {
            year: 2015,
            month: 10,
            count: 1
        }
        should.deepEqual(ax5.util.weeksOfMonth("2015-10-01"), obj);
    });

    //Usage02
    it('ax5.util.weeksOfMonth("2015-09-19")', function () {
        var obj = {
            year: 2015,
            month: 9,
            count: 3
        }
        should.deepEqual(ax5.util.weeksOfMonth("2015-09-19"), obj);
    });

    //Usage03
    it('ax5.util.weeksOfMonth("2016-04-30")', function () {
        var obj = {
            year: 2016,
            month: 4,
            count: 5
        }
        should.deepEqual(ax5.util.weeksOfMonth("2016-04-30"), obj);
    });
    /* end ax5.util.weeksOfMonth */
});

describe('ax5.util.daysOfMonth TEST', function () {
    /* ax5.util.daysOfMonth*/
    //Usage 01
    it('ax5.util.daysOfMonth(2015,11)', function () {
        should.deepEqual(ax5.util.daysOfMonth(2015, 11), 31);
    });

    //Usage 02
    it('ax5.util.daysOfMonth(2015,1)', function () {
        should.deepEqual(ax5.util.daysOfMonth(2015, 1), 28);
    });

    //Usage 03
    it('ax5.util.daysOfMonth(2016,1)', function () {
        should.deepEqual(ax5.util.daysOfMonth(2016, 1), 29);
    });
    /* end ax5.util.daysOfMonth*/
});<|endoftext|>


<commit_before>describe('ax5.util.param TEST', function() {
    it('ax5.util.param({a: 1, b: \'123\'"2&\'}, "param") expect "a=1&b=123%27%222%26"', function() {
        var actual = ax5.util.param({a: 1, b: '123\'"2&'}, 'param');

        actual.should.equal('a=1&b=123%27%222%26');
    });
    it('ax5.util.param("a=1&b=12\'"32", "param") expect "a=1&b=12\'"32"', function() {
        var actual = ax5.util.param("a=1&b=12'\"32", 'param');

        actual.should.equal('a=1&b=12\'"32');
    });
    it('ax5.util.param("a=1&b=1232") expect {"a":"1","b":"1232"}', function() {
        var actual = ax5.util.param("a=1&b=1232");

        _.isEqual(actual, {"a":"1","b":"1232"}).should.equal(true);
    });
});

describe('ax5.util.parseJson TEST', function() {
    it('ax5.util.util.parseJson("[{"a":"99"},"2","3"]") expect [{"a":"99"},"2","3"]', function() {
        var actual = ax5.util.parseJson('[{"a":"99"},"2","3"]');

        actual.should.deepEqual([{"a":"99"},"2","3"]);
    });
    it('ax5.util.parseJson("{"a":1, "b":function(){return 1;}}", false) expect {"error": 500, "msg": "syntax error"}', function() {
        var actual = ax5.util.parseJson('{"a":1, "b":function(){return 1;}}', false);

        actual.should.deepEqual({"error": 500, "msg": "syntax error"});
    });
    it('ax5.util.parseJson("{"a":1, "b":function(){return 1;}}", true) expect {"a": 1, "b": "{Function}"}', function() {
        var actual = ax5.util.parseJson('{"a":1, "b":function(){return 1;}}', true);

        actual.a.should.equal(1);
        actual.b.should.Function();
    });
});

describe('ax5.util.toJson TEST', function() {
    var testCases = [
        {
            args: 1,
            expect: 1
        },
        {
            args: "A",
            expect: '"A"'
        },
        {
            args: [1, 2, 3, "A"],
            expect: '[1,2,3,"A"]'
        },
        {
            args: {a: "a", x: "x"},
            expect: '{"a": "a", "x": "x"}'
        },
        {
            args: [1,{"a": "a", "x": "x"}],
            expect: '[1,{"a": "a", "x": "x"}]'
        },
        {
            args: {"a": "a", "x": "x", "list": [1,2,3]},
            expect: '{"a": "a", "x": "x", "list": [1,2,3]}'
        },
        {
            args: function func() {},
            expect: '"{Function}"'
        }
    ];

    _.each(testCases, function(testCase){
        it('ax5.util.toJson(' + (JSON.stringify(testCase.args) || testCase.args.toString()) + ') expect ' + testCase.expect, function() {
            var actual = ax5.util.toJson(testCase.args);

            actual.should.deepEqual(testCase.expect);
        });
    });
});

describe('ax5.util.toArray TEST', function() {
    it('ax5.util.toArray converts [Array-like objects] to [Array]', function() {
        function something() {
            return ax5.util.toArray(arguments);
        }
        var actual = something("A", "X", "I", "S", "J");

        actual.should.deepEqual(["A", "X", "I", "S", "J"]);
    });
});

describe('ax5.util.setCookie TEST', function() {
    it('ax5.util.setCookie("ax5-cookie-path", "abcde", 2, {path: "/"})', function() {
        ax5.util.setCookie("ax5-cookie-path", "abcde", 2, {path: "/"});

        document.cookie.indexOf('ax5-cookie-path=abcde').should.above(-1);
    });
});

describe('ax5.util.getCookie TEST', function() {
    it('ax5.util.getCookie("ax5-cookie-path") expect "abcde"', function() {
        var actual = ax5.util.getCookie('ax5-cookie-path');

        actual.should.equal('abcde');
    });
});
<commit_msg>add ax5.util.xxxCookie TEST<commit_after>describe('ax5.util.param TEST', function() {
    it('ax5.util.param({a: 1, b: \'123\'"2&\'}, "param") expect "a=1&b=123%27%222%26"', function() {
        var actual = ax5.util.param({a: 1, b: '123\'"2&'}, 'param');

        actual.should.equal('a=1&b=123%27%222%26');
    });
    it('ax5.util.param("a=1&b=12\'"32", "param") expect "a=1&b=12\'"32"', function() {
        var actual = ax5.util.param("a=1&b=12'\"32", 'param');

        actual.should.equal('a=1&b=12\'"32');
    });
    it('ax5.util.param("a=1&b=1232") expect {"a":"1","b":"1232"}', function() {
        var actual = ax5.util.param("a=1&b=1232");

        should.deepEqual(actual, {"a":"1","b":"1232"});
    });
});

describe('ax5.util.parseJson TEST', function() {
    it('ax5.util.util.parseJson("[{"a":"99"},"2","3"]") expect [{"a":"99"},"2","3"]', function() {
        var actual = ax5.util.parseJson('[{"a":"99"},"2","3"]');

        actual.should.deepEqual([{"a":"99"},"2","3"]);
    });
    it('ax5.util.parseJson("{"a":1, "b":function(){return 1;}}", false) expect {"error": 500, "msg": "syntax error"}', function() {
        var actual = ax5.util.parseJson('{"a":1, "b":function(){return 1;}}', false);

        actual.should.deepEqual({"error": 500, "msg": "syntax error"});
    });
    it('ax5.util.parseJson("{"a":1, "b":function(){return 1;}}", true) expect {"a": 1, "b": "{Function}"}', function() {
        var actual = ax5.util.parseJson('{"a":1, "b":function(){return 1;}}', true);

        actual.a.should.equal(1);
        actual.b.should.Function();
    });
});

describe('ax5.util.toJson TEST', function() {
    var testCases = [
        {
            args: 1,
            expect: 1
        },
        {
            args: "A",
            expect: '"A"'
        },
        {
            args: [1, 2, 3, "A"],
            expect: '[1,2,3,"A"]'
        },
        {
            args: {a: "a", x: "x"},
            expect: '{"a": "a", "x": "x"}'
        },
        {
            args: [1,{"a": "a", "x": "x"}],
            expect: '[1,{"a": "a", "x": "x"}]'
        },
        {
            args: {"a": "a", "x": "x", "list": [1,2,3]},
            expect: '{"a": "a", "x": "x", "list": [1,2,3]}'
        },
        {
            args: function func() {},
            expect: '"{Function}"'
        }
    ];

    _.each(testCases, function(testCase){
        it('ax5.util.toJson(' + (JSON.stringify(testCase.args) || testCase.args.toString()) + ') expect ' + testCase.expect, function() {
            var actual = ax5.util.toJson(testCase.args);

            actual.should.deepEqual(testCase.expect);
        });
    });
});

describe('ax5.util.toArray TEST', function() {
    it('ax5.util.toArray converts [Array-like objects] to [Array]', function() {
        function something() {
            return ax5.util.toArray(arguments);
        }
        var actual = something("A", "X", "I", "S", "J");

        actual.should.deepEqual(["A", "X", "I", "S", "J"]);
    });
});

describe('ax5.util.xxxCookie TEST', function() {

    ax5.util.setCookie('ax5-cookie', null); // reset ax5-cookie value

    describe('ax5.util.setCookie TEST', function() {
        it('ax5.util.setCookie("ax5-cookie", "abcde")', function() {
            ax5.util.setCookie('ax5-cookie', 'abcde');

            document.cookie.indexOf('ax5-cookie=abcde').should.above(-1);
        });
    });

    describe('ax5.util.getCookie TEST', function() {
        it('ax5.util.getCookie("ax5-cookie") expect "abcde"', function() {
            var actual = ax5.util.getCookie('ax5-cookie');

            actual.should.equal('abcde');
        });
    });

});
<|endoftext|>