<commit_before>define([
    'App'
], function (App) {
    'use strict';

    var path = require('path'),
        child_process = require('child_process'),
        fs = require('fs'),
        tfPath = getTfPath();

    var self = {
        getChanges: function (logStatus) {
            logStatus('Retrieving TFS workspaces...');
            return new Promise(function (resolve, reject) {
                if (!tfPath) {
                    reject('Visual Studio not found on the system! Visual Studio 2015, 2013, 2012, or 2010 is required to get changes from TFS.');
                } else {
                    resolve(getWorkspaces());
                }
            }).then(function (workspaces) {
                if (!workspaces.length) {
                    throw 'No TFS workspaces found';
                }

                logStatus('Disovering changes...');
                return Promise.all(workspaces.map(function (workspaceName) {
                    return getChangesForWorkspace(workspaceName);
                }));
            }).then(function (values) {
                values.sort(function (left, right) {
                    return left.name < right.name ? -1 : left.name > right.name ? 1 : 0;
                });
                return values;
            });
        }
    };

    // Looks for an install of Visual Studio and returns the path to tf.exe if found
    function getTfPath() {
        var varsToCheck = ['VS130COMNTOOLS', 'VS120COMNTOOLS', 'VS110COMNTOOLS', 'VS100COMNTOOLS'],
            potentialPath;

        for (const varName of varsToCheck) {
            if (process.env[varName]) {
                potentialPath = path.normalize(process.env[varName] + '../IDE/tf.exe');
                try {
                    if (fs.statSync(potentialPath).isFile()) {
                        return potentialPath;
                    }
                } catch(e) { }
            }
        }
    }

    // Retrieves the list of active workspaces from TFS that we need to grab file diffs
    function getWorkspaces() {
        return new Promise(function (resolve, reject) {
            if (App.TEST_MODE) {
                setTimeout(function () {
                    var sampleOutput = fs.readFileSync('test/tf-workspaces.txt').toString();
                    resolve(parseWorkspaces(sampleOutput));
                }, 500);
            } else {
                var ls = child_process.execFile(tfPath, ['workspaces'], function (err, stdout, stderr) {
                    if (err || stderr) {
                        reject(err || stderr);
                    } else {
                        resolve(parseWorkspaces(stdout));
                    }
                });
            }
        });
    }

    // Parses TFS workspace names out of the `tf workspaces` command output
    function parseWorkspaces(tfOutput) {
        var workspaceNames = [],
            nameEndIndex;

        for (const line of tfOutput.replace('\r\n', '\n').split('\n')) {
            if (!nameEndIndex) {
                if (line.startsWith('---')) {
                    nameEndIndex = line.indexOf('- -') + 1;
                }
            } else {
                if (line) {
                    workspaceNames.push(line.substring(0, nameEndIndex).trim());
                }
            }
        }
        return workspaceNames;
    }

    // Returns change information for the given workspace
    function getChangesForWorkspace(workspaceName) {
        return new Promise(function (resolve, reject) {
            if (App.TEST_MODE) {
                setTimeout(function () {
                    var sampleOutput = fs.readFileSync('test/tf-changes.txt').toString();
                    resolve(parseChanges(sampleOutput, workspaceName));
                }, 500);
            } else {
                var ls = child_process.execFile(tfPath, ['status', `/workspace:${workspaceName}`], function (err, stdout, stderr) {
                    if (err || stderr) {
                        reject(err || stderr);
                    } else {
                        resolve(parseChanges(stdout, workspaceName));
                    }
                });
            }
        });
    }

    // Parses file changes out of the `tf status` command output
    function parseChanges(tfOutput, workspaceName) {
        var changes = [],
            nameEndIndex,
            pathStartIndex,
            activeNode;

        for (const line of tfOutput.replace(/\r\n/g, '\n').split('\n')) {
            if (line.startsWith('---')) {
                if (!nameEndIndex) {
                    nameEndIndex = line.indexOf('- -') + 1;
                    pathStartIndex = line.lastIndexOf('- -') + 2;
                }
            } else if (line) {
                if (line.startsWith('$/')) {
                    changes.push(activeNode = {
                        name: line.trim(),
                        children: []
                    });
                } else {
                    if (line.startsWith('File name') || line.startsWith('Detected Changes:') || /\d+ change\(s\),/.test(line)) {
                        continue;
                    }

                    const name = line.substring(0, nameEndIndex).trim(),
                          tfsPath = `${activeNode.name}/${name}`;

                    if (!name) {
                        continue;
                    }

                    activeNode.children.push({
                        name: name,
                        basePath: tfsPath,
                        iterationPath: line.substring(pathStartIndex),
                        displayPath: tfsPath
                    });
                }
            }
        }

        return {
            name: workspaceName,
            children: changes
        };
    }

    return self;
});<commit_msg>adding start of loading change file contents<commit_after>define([
    'App'
], function (App) {
    'use strict';

    var path = require('path'),
        child_process = require('child_process'),
        fs = require('fs'),
        tfPath = getTfPath();

    var self = {
        getChanges: function (logStatus) {
            logStatus('Retrieving TFS workspaces...');
            return new Promise(function (resolve, reject) {
                if (!tfPath) {
                    reject('Visual Studio not found on the system! Visual Studio 2015, 2013, 2012, or 2010 is required to get changes from TFS.');
                } else {
                    resolve(getWorkspaces());
                }
            }).then(function (workspaces) {
                if (!workspaces.length) {
                    throw 'No TFS workspaces found';
                }

                logStatus('Disovering changes...');
                return Promise.all(workspaces.map(function (workspaceName) {
                    return getChangesForWorkspace(workspaceName);
                }));
            }).then(function (values) {
                values.sort(function (left, right) {
                    return left.name < right.name ? -1 : left.name > right.name ? 1 : 0;
                });
                return values;
            });
        },

        getChangeFiles: function (workspaceName, fileRecords) {

        }
    };

    // Looks for an install of Visual Studio and returns the path to tf.exe if found
    function getTfPath() {
        var varsToCheck = ['VS130COMNTOOLS', 'VS120COMNTOOLS', 'VS110COMNTOOLS', 'VS100COMNTOOLS'],
            potentialPath;

        for (const varName of varsToCheck) {
            if (process.env[varName]) {
                potentialPath = path.normalize(process.env[varName] + '../IDE/tf.exe');
                try {
                    if (fs.statSync(potentialPath).isFile()) {
                        return potentialPath;
                    }
                } catch(e) { }
            }
        }
    }

    // Retrieves the list of active workspaces from TFS that we need to grab file diffs
    function getWorkspaces() {
        return new Promise(function (resolve, reject) {
            if (App.TEST_MODE) {
                setTimeout(function () {
                    var sampleOutput = fs.readFileSync('test/tf-workspaces.txt').toString();
                    resolve(parseWorkspaces(sampleOutput));
                }, 500);
            } else {
                var ls = child_process.execFile(tfPath, ['workspaces'], function (err, stdout, stderr) {
                    if (err || stderr) {
                        reject(err || stderr);
                    } else {
                        resolve(parseWorkspaces(stdout));
                    }
                });
            }
        });
    }

    // Parses TFS workspace names out of the `tf workspaces` command output
    function parseWorkspaces(tfOutput) {
        var workspaceNames = [],
            nameEndIndex;

        for (const line of tfOutput.replace('\r\n', '\n').split('\n')) {
            if (!nameEndIndex) {
                if (line.startsWith('---')) {
                    nameEndIndex = line.indexOf('- -') + 1;
                }
            } else {
                if (line) {
                    workspaceNames.push(line.substring(0, nameEndIndex).trim());
                }
            }
        }
        return workspaceNames;
    }

    // Returns change information for the given workspace
    function getChangesForWorkspace(workspaceName) {
        return new Promise(function (resolve, reject) {
            if (App.TEST_MODE) {
                setTimeout(function () {
                    var sampleOutput = fs.readFileSync('test/tf-changes.txt').toString();
                    resolve(parseChanges(sampleOutput, workspaceName));
                }, 500);
            } else {
                child_process.execFile(tfPath, ['status', `/workspace:${workspaceName}`], function (err, stdout, stderr) {
                    if (err || stderr) {
                        reject(err || stderr);
                    } else {
                        resolve(parseChanges(stdout, workspaceName));
                    }
                });
            }
        });
    }

    // Parses file changes out of the `tf status` command output
    function parseChanges(tfOutput, workspaceName) {
        var changes = [],
            nameEndIndex,
            pathStartIndex,
            activeNode;

        for (const line of tfOutput.replace(/\r\n/g, '\n').split('\n')) {
            if (line.startsWith('---')) {
                if (!nameEndIndex) {
                    nameEndIndex = line.indexOf('- -') + 1;
                    pathStartIndex = line.lastIndexOf('- -') + 2;
                }
            } else if (line) {
                if (line.startsWith('$/')) {
                    changes.push(activeNode = {
                        name: line.trim(),
                        children: []
                    });
                } else {
                    if (line.startsWith('File name') || line.startsWith('Detected Changes:') || /\d+ change\(s\),/.test(line)) {
                        continue;
                    }

                    const name = line.substring(0, nameEndIndex).trim(),
                          tfsPath = `${activeNode.name}/${name}`;

                    if (!name) {
                        continue;
                    }

                    activeNode.children.push({
                        name: name,
                        basePath: tfsPath,
                        iterationPath: line.substring(pathStartIndex),
                        displayPath: tfsPath
                    });
                }
            }
        }

        return {
            name: workspaceName,
            children: changes
        };
    }

    function getLocalFile(localPath) {
        return new Promise(function (resolve, reject) {
            fs.readFile(localPath, function (err, data) {
                if (err) {
                    reject(err);
                } else {
                    resolve(data);
                }
            });
        });
    }

    // Returns change information for the given workspace
    function getFileFromTfs(workspaceName, tfsPath) {
        return new Promise(function (resolve, reject) {
            child_process.execFile(tfPath, ['view', `${tfsPath};W${workspaceName}`, '/console'], function (err, stdout, stderr) {
                if (err) {
                    reject(err);
                } else if (stderr) {
                    if (stderr.endsWith(': No file matches.\n')) {
                        resolve(null);
                    } else {
                        reject(stderr);
                    }
                } else {
                    resolve(stdout);
                }
            });
        });
    }

    return self;
});<|endoftext|>


<commit_before>'use strict';
/* @flow */

var mean = require('./mean');
var chiSquaredDistributionTable = require('./chi_squared_distribution_table');

/**
 * The [χ2 (Chi-Squared) Goodness-of-Fit Test](http://en.wikipedia.org/wiki/Goodness_of_fit#Pearson.27s_chi-squared_test)
 * uses a measure of goodness of fit which is the sum of differences between observed and expected outcome frequencies
 * (that is, counts of observations), each squared and divided by the number of observations expected given the
 * hypothesized distribution. The resulting χ2 statistic, `chiSquared`, can be compared to the chi-squared distribution
 * to determine the goodness of fit. In order to determine the degrees of freedom of the chi-squared distribution, one
 * takes the total number of observed frequencies and subtracts the number of estimated parameters. The test statistic
 * follows, approximately, a chi-square distribution with (k − c) degrees of freedom where `k` is the number of non-empty
 * cells and `c` is the number of estimated parameters for the distribution.
 *
 * @param {Array<number>} data
 * @param {Function} distributionType a function that returns a point in a distribution:
 * for instance, binomial, bernoulli, or poisson
 * @param {number} significance
 * @returns {number} chi squared goodness of fit
 * @example
 * // Data from Poisson goodness-of-fit example 10-19 in William W. Hines & Douglas C. Montgomery,
 * // "Probability and Statistics in Engineering and Management Science", Wiley (1980).
 * var data1019 = [
 *     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 *     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 *     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 *     2, 2, 2, 2, 2, 2, 2, 2, 2,
 *     3, 3, 3, 3
 * ];
 * ss.chiSquaredGoodnessOfFit(data1019, ss.poissonDistribution, 0.05)); //= false
 */
function chiSquaredGoodnessOfFit(
    data/*: Array<number> */,
    distributionType/*: Function */,
    significance/*: number */)/*: boolean */ {
    // Estimate from the sample data, a weighted mean.
    var inputMean = mean(data),
        // Calculated value of the χ2 statistic.
        chiSquared = 0,
        // Degrees of freedom, calculated as (number of class intervals -
        // number of hypothesized distribution parameters estimated - 1)
        degreesOfFreedom,
        // Number of hypothesized distribution parameters estimated, expected to be supplied in the distribution test.
        // Lose one degree of freedom for estimating `lambda` from the sample data.
        c = 1,
        // The hypothesized distribution.
        // Generate the hypothesized distribution.
        hypothesizedDistribution = distributionType(inputMean),
        observedFrequencies = [],
        expectedFrequencies = [],
        k;

    // Create an array holding a histogram from the sample data, of
    // the form `{ value: numberOfOcurrences }`
    for (var i = 0; i < data.length; i++) {
        if (observedFrequencies[data[i]] === undefined) {
            observedFrequencies[data[i]] = 0;
        }
        observedFrequencies[data[i]]++;
    }

    // The histogram we created might be sparse - there might be gaps
    // between values. So we iterate through the histogram, making
    // sure that instead of undefined, gaps have 0 values.
    for (i = 0; i < observedFrequencies.length; i++) {
        if (observedFrequencies[i] === undefined) {
            observedFrequencies[i] = 0;
        }
    }

    // Create an array holding a histogram of expected data given the
    // sample size and hypothesized distribution.
    for (k in hypothesizedDistribution) {
        if (k in observedFrequencies) {
            expectedFrequencies[+k] = hypothesizedDistribution[k] * data.length;
        }
    }

    // Working backward through the expected frequencies, collapse classes
    // if less than three observations are expected for a class.
    // This transformation is applied to the observed frequencies as well.
    for (k = expectedFrequencies.length - 1; k >= 0; k--) {
        if (expectedFrequencies[k] < 3) {
            expectedFrequencies[k - 1] += expectedFrequencies[k];
            expectedFrequencies.pop();

            observedFrequencies[k - 1] += observedFrequencies[k];
            observedFrequencies.pop();
        }
    }

    // Iterate through the squared differences between observed & expected
    // frequencies, accumulating the `chiSquared` statistic.
    for (k = 0; k < observedFrequencies.length; k++) {
        chiSquared += Math.pow(
            observedFrequencies[k] - expectedFrequencies[k], 2) /
            expectedFrequencies[k];
    }

    // Calculate degrees of freedom for this test and look it up in the
    // `chiSquaredDistributionTable` in order to
    // accept or reject the goodness-of-fit of the hypothesized distribution.
    degreesOfFreedom = observedFrequencies.length - c - 1;
    return chiSquaredDistributionTable[degreesOfFreedom][significance] < chiSquared;
}

module.exports = chiSquaredGoodnessOfFit;
<commit_msg>docs: fix spurious parenthesis (#232)<commit_after>'use strict';
/* @flow */

var mean = require('./mean');
var chiSquaredDistributionTable = require('./chi_squared_distribution_table');

/**
 * The [χ2 (Chi-Squared) Goodness-of-Fit Test](http://en.wikipedia.org/wiki/Goodness_of_fit#Pearson.27s_chi-squared_test)
 * uses a measure of goodness of fit which is the sum of differences between observed and expected outcome frequencies
 * (that is, counts of observations), each squared and divided by the number of observations expected given the
 * hypothesized distribution. The resulting χ2 statistic, `chiSquared`, can be compared to the chi-squared distribution
 * to determine the goodness of fit. In order to determine the degrees of freedom of the chi-squared distribution, one
 * takes the total number of observed frequencies and subtracts the number of estimated parameters. The test statistic
 * follows, approximately, a chi-square distribution with (k − c) degrees of freedom where `k` is the number of non-empty
 * cells and `c` is the number of estimated parameters for the distribution.
 *
 * @param {Array<number>} data
 * @param {Function} distributionType a function that returns a point in a distribution:
 * for instance, binomial, bernoulli, or poisson
 * @param {number} significance
 * @returns {number} chi squared goodness of fit
 * @example
 * // Data from Poisson goodness-of-fit example 10-19 in William W. Hines & Douglas C. Montgomery,
 * // "Probability and Statistics in Engineering and Management Science", Wiley (1980).
 * var data1019 = [
 *     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 *     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 *     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 *     2, 2, 2, 2, 2, 2, 2, 2, 2,
 *     3, 3, 3, 3
 * ];
 * ss.chiSquaredGoodnessOfFit(data1019, ss.poissonDistribution, 0.05); //= false
 */
function chiSquaredGoodnessOfFit(
    data/*: Array<number> */,
    distributionType/*: Function */,
    significance/*: number */)/*: boolean */ {
    // Estimate from the sample data, a weighted mean.
    var inputMean = mean(data),
        // Calculated value of the χ2 statistic.
        chiSquared = 0,
        // Degrees of freedom, calculated as (number of class intervals -
        // number of hypothesized distribution parameters estimated - 1)
        degreesOfFreedom,
        // Number of hypothesized distribution parameters estimated, expected to be supplied in the distribution test.
        // Lose one degree of freedom for estimating `lambda` from the sample data.
        c = 1,
        // The hypothesized distribution.
        // Generate the hypothesized distribution.
        hypothesizedDistribution = distributionType(inputMean),
        observedFrequencies = [],
        expectedFrequencies = [],
        k;

    // Create an array holding a histogram from the sample data, of
    // the form `{ value: numberOfOcurrences }`
    for (var i = 0; i < data.length; i++) {
        if (observedFrequencies[data[i]] === undefined) {
            observedFrequencies[data[i]] = 0;
        }
        observedFrequencies[data[i]]++;
    }

    // The histogram we created might be sparse - there might be gaps
    // between values. So we iterate through the histogram, making
    // sure that instead of undefined, gaps have 0 values.
    for (i = 0; i < observedFrequencies.length; i++) {
        if (observedFrequencies[i] === undefined) {
            observedFrequencies[i] = 0;
        }
    }

    // Create an array holding a histogram of expected data given the
    // sample size and hypothesized distribution.
    for (k in hypothesizedDistribution) {
        if (k in observedFrequencies) {
            expectedFrequencies[+k] = hypothesizedDistribution[k] * data.length;
        }
    }

    // Working backward through the expected frequencies, collapse classes
    // if less than three observations are expected for a class.
    // This transformation is applied to the observed frequencies as well.
    for (k = expectedFrequencies.length - 1; k >= 0; k--) {
        if (expectedFrequencies[k] < 3) {
            expectedFrequencies[k - 1] += expectedFrequencies[k];
            expectedFrequencies.pop();

            observedFrequencies[k - 1] += observedFrequencies[k];
            observedFrequencies.pop();
        }
    }

    // Iterate through the squared differences between observed & expected
    // frequencies, accumulating the `chiSquared` statistic.
    for (k = 0; k < observedFrequencies.length; k++) {
        chiSquared += Math.pow(
            observedFrequencies[k] - expectedFrequencies[k], 2) /
            expectedFrequencies[k];
    }

    // Calculate degrees of freedom for this test and look it up in the
    // `chiSquaredDistributionTable` in order to
    // accept or reject the goodness-of-fit of the hypothesized distribution.
    degreesOfFreedom = observedFrequencies.length - c - 1;
    return chiSquaredDistributionTable[degreesOfFreedom][significance] < chiSquared;
}

module.exports = chiSquaredGoodnessOfFit;
<|endoftext|>


<commit_before>const React = require('react');
const h = require('react-hyperscript');
const Table = require('react-table').default;
const { Tab, Tabs, TabList, TabPanel } = require('react-tabs');

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

const make_cytoscape = require('../../common/cy');
const cysearch = _.debounce(require('../../common/cy/search'), 500);

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

const {createExpressionTable, minRelativeTo, maxRelativeTo, applyAggregateFn} = require('./expression-model');
const OmniBar = require('./omnibar');
const Network = require('./network');

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

    const cy = make_cytoscape({headless: true});
    const query = queryString.parse(props.location.search);
    const enrichmentsURI = query.uri ? query.uri : null;

    this.state = {
      // enrichment data state
      rawEnrichmentData: {},
      expressionTable: {},
      selectedClass: '',
      selectedFunction: this.analysisFns().mean,

      // sbgn / cy network state
      cy: cy,
      name: '',
      datasource: '',

      // search results state
      query: '',
      searchResults: [],

      // drawer
      drawerOpen: false
    };

    if (enrichmentsURI != null) {
      fetch(enrichmentsURI)
        .then(response => response.json())
        .then(json => {
          const expressionClasses = _.get(json.dataSetClassList, '0.classes', []);
          const expressions = _.get(json.dataSetExpressionList, '0.expressions', []);
          const searchParam = query.q;

          this.setState({
            rawEnrichmentData: json,
            query: query.q
          });
          this.initPainter(expressions, expressionClasses, searchParam);

        });
    }
  }

  loadSbgn(uri) {
    const state = this.state;
    apiCaller.getGraphAndLayout(uri, 'latest').then(response => {
      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,
        nodeRepulsion: 5000 * state.cy.nodes().size()
      }).run();

      this.setState({
        name: _.get(response, 'graph.pathwayMetadata.title', 'N/A'),
        datasource: _.get(response, 'graph.pathwayMetadata.dataSource.0', 'N/A'),
      }, () => this.applyExpressionData());
    });
  }

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

    // const uri = 'http://identifiers.org/reactome/R-HSA-5389840';

    // if (uri != null) {
    //   const expressionTable = createExpressionTable(expressions, expressionClasses);
    //   const header = expressionTable.header;

    //   apiCaller.getGraphAndLayout(uri, 'latest').then(response => {
    //     state.cy.remove('*');
    //     state.cy.add({
    //       nodes: _.get(response, 'graph.nodes', []),
    //       edges: _.get(response, 'graph.edges', [])
    //     });

    //     if (!_.isEmpty(response.layout)) {
    //       state.cy.layout({
    //         name: 'preset',
    //         positions: node => response.layout[node.id()],
    //         animate: true,
    //         animationDuration: 500

    //       }).run();
    //     } else {
    //       state.cy.layout({
    //         name: 'cose-bilkent',
    //         randomize: false,
    //         nodeDimensionsIncludeLabels: true,
    //         nodeRepulsion: 5000 * state.cy.nodes().size()
    //       }).run();
    //     }

    //     this.setState({
    //       selectedClass: _.get(header, '0', null),
    //       expressionTable: expressionTable,
    //       name: _.get(response, 'graph.pathwayMetadata.title', 'N/A'),
    //       datasource: _.get(response, 'graph.pathwayMetadata.dataSource.0', 'N/A'),
    //       // searchResults: searchResults
    //     }, () => this.applyExpressionData());
    //   });
    // }

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

      if (uri != null) {
        const expressionTable = createExpressionTable(expressions, expressionClasses);
        const header = expressionTable.header;

        apiCaller.getGraphAndLayout(uri, 'latest').then(response => {
          state.cy.remove('*');
          state.cy.add({
            nodes: _.get(response, 'graph.nodes', []),
            edges: _.get(response, 'graph.edges', [])
          });

          if (!_.isEmpty(response.layout)) {
            state.cy.layout({
              name: 'preset',
              positions: node => response.layout[node.id()],
              animate: true,
              animationDuration: 500

            }).run();
          } else {
            state.cy.layout({
              name: 'cose-bilkent',
              randomize: false,
              nodeDimensionsIncludeLabels: true,
              nodeRepulsion: 5000 * state.cy.nodes().size()
            }).run();
          }

          this.setState({
            selectedClass: _.get(header, '0', null),
            expressionTable: expressionTable,
            name: _.get(response, 'graph.pathwayMetadata.title', 'N/A'),
            datasource: _.get(response, 'graph.pathwayMetadata.dataSource.0', 'N/A'),
            searchResults: searchResults
          }, () => this.applyExpressionData());
        });
      }
    });
  }

  expressionDataToNodeStyle(value, range) {
    const [, max] = range;
    const style = {};

    if ((0 - max / 3) <= value < (0 + max / 3)) {
      style['background-color'] = 'white';
      style['background-opacity'] = 1;
      style['color'] = 'black';
    }

    if (value < (0 - max / 3)) {
      style['background-opacity'] = `${1 + (value / max)}`;
      style['background-color'] = 'green';
      style['color'] = 'white';
      style['text-outline-color'] = 'black';
    }

    if ((0 + max / 3) <= value ) {
      style['background-color'] = 'purple';
      style['background-opacity'] = `${value / max}`;
      style['color'] = 'white';
      style['text-outline-color'] = 'black';

    }
    return style;
  }

  computeFoldChange(expression, selectedFunction) {
    const classValues = Object.entries(expression.classValues);
    const c1Val = selectedFunction(classValues[0][1]);

    let c2Val = selectedFunction(classValues[1][1]);
    c2Val = c2Val === 0 ? c2Val = 1 : c2Val;

    let foldChange = Math.log2(c1Val / c2Val);

    return {
      geneName: expression.geneName,
      value: parseFloat(foldChange.toFixed(2))
    };
  }

  applyExpressionData() {
    const state = this.state;

    const selectedFunction = state.selectedFunction.func;
    const expressionTable = state.expressionTable;

    const geneNodes = state.cy.nodes('[class="macromolecule"]');
    const geneNodeLabels = _.uniq(geneNodes.map(node => node.data('label'))).sort();

    const expressionsInNetwork = expressionTable.rows.filter(row => geneNodeLabels.includes(row.geneName));

    const expressionLabels = expressionsInNetwork.map(expression => expression.geneName);
    geneNodes.filter(node => !expressionLabels.includes(node.data('label'))).style({
      'background-color': 'grey',
      'color': 'grey',
      'opacity': 0.4
    });

    const foldValues = expressionsInNetwork.map(expression => this.computeFoldChange(expression, selectedFunction));
    const fvs = foldValues.map(fv => fv.value);
    const maxMagnitude = Math.max(Math.max(...fvs), Math.abs(Math.min(...fvs)));
    const range = [-maxMagnitude, maxMagnitude];
    foldValues.forEach(fv => {
      const matchedNodes = state.cy.nodes().filter(node => node.data('label') === fv.geneName);
      const style = this.expressionDataToNodeStyle(fv.value, range);

      state.cy.batch(() => matchedNodes.style(style));
    });

  }

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

  analysisFns() {
    return {
      mean: {
        name: 'mean',
        func: _.mean
      },
      max: {
        name: 'max',
        func: _.max
      },
      min: {
        name: 'min',
        func: _.min
      }
    };
  }

  render() {
    const state = this.state;

    const selectedFunction = state.selectedFunction.func;
    const selectedClass = state.selectedClass;
    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 foldValues = expressionsInNetwork.map(expression => this.computeFoldChange(expression, selectedFunction));
    const fvs = foldValues.map(fv => fv.value);
    const maxMagnitude = Math.max(Math.max(...fvs), Math.abs(Math.min(...fvs)));
    const max =  maxMagnitude;
    const min = -maxMagnitude;

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

    const columns = [
      {
        Header: 'Gene',
        accessor: 'geneName',
        filterMethod: (filter, rows) => matchSorter(rows, filter.value, { keys: ['geneName'] }),
        filterable: true,
        filterAll: true
      },
      {
        Header: 'log2 Fold-Change',
        id: 'foldChange',
        accessor: row => this.computeFoldChange(row, selectedFunction).value
      }
    ];

    const functionSelector = h('select.paint-select',
      {
        value: state.selectedFunction.name,
        onChange: e => this.setState({
          selectedFunction: _.find(this.analysisFns(), (fn) => fn.name === e.target.value)
        }, () => this.applyExpressionData())
      },
      Object.entries(this.analysisFns()).map(entry => h('option', {value: entry[0]}, entry[0]))
    );

    const classSelector = h('select.paint-select',
      {
        value: selectedClass,
        onChange: e => this.setState({
          selectedClass: e.target.value
        }, () => this.applyExpressionData())
      },
      expressionHeader.map(exprClass => h('option', { value: exprClass }, exprClass))
    );

    const tabbedContent = h(Tabs, [
      h('div.paint-drawer-header', [
        h(TabList, [
          h(Tab, 'Expression Data'),
          // h(Tab, 'Search Results')
        ]),
        h('a', { onClick: e => this.toggleDrawer()}, [
          h(Icon, { icon: 'close'}),
        ])
      ]),
      h(TabPanel, [
        h('div.paint-legend', [
          h('p', `low ${min}`),
          h('p', `high ${max}`)
        ]),
        h('div.paint-expression-controls', [
        h('div.paint-function-selector', [
          'Class: ',
          functionSelector
        ]),
        h('div.paint-compare-selector', [
          `Compare: ${expressionHeader[0]} vs ${expressionHeader[1]}`,
        ]),
      ]),
      h(Table, {
        className:'-striped -highlight',
        data: expressionRows,
        columns: columns,
        defaultPageSize: 150,
        showPagination: false,
        onFilteredChange: (column, value) => {
          cysearch(_.get(column, '0.value', ''), this.state.cy, false, {'border-width': 8, 'border-color': 'red'});
        }
      })
      ]),
      // h(TabPanel, state.searchResults.map(searchResult => {
      //     const uri = _.get(searchResult, 'uri', null);
      //     const name = _.get(searchResult, 'name', 'N/A');
      //     return h('div.paint-search-result', [
      //       h('a.plain-link', {onClick: e => this.loadSbgn(uri)}, name)
      //     ]);
      //   })
      // )
    ]);

    return h('div.paint', [
      h('div.paint-content', [
        h('div', { className: classNames('paint-drawer', { 'closed': !state.drawerOpen }) }, [
          tabbedContent
        ]),
        h(OmniBar, { title: `${state.name} | ${state.datasource}`, onMenuClick: (e) => this.toggleDrawer() }),
        h(Network, { cy: state.cy })
      ])
    ]);
  }
}

module.exports = Paint;<commit_msg>Fix bug with min values not being mapped correctly<commit_after>const React = require('react');
const h = require('react-hyperscript');
const Table = require('react-table').default;
const { Tab, Tabs, TabList, TabPanel } = require('react-tabs');

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

const make_cytoscape = require('../../common/cy');
const cysearch = _.debounce(require('../../common/cy/search'), 500);

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

const {createExpressionTable, minRelativeTo, maxRelativeTo, applyAggregateFn} = require('./expression-model');
const OmniBar = require('./omnibar');
const Network = require('./network');

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

    const cy = make_cytoscape({headless: true});
    const query = queryString.parse(props.location.search);
    const enrichmentsURI = query.uri ? query.uri : null;

    this.state = {
      // enrichment data state
      rawEnrichmentData: {},
      expressionTable: {},
      selectedClass: '',
      selectedFunction: this.analysisFns().mean,

      // sbgn / cy network state
      cy: cy,
      name: '',
      datasource: '',

      // search results state
      query: '',
      searchResults: [],

      // drawer
      drawerOpen: false
    };

    if (enrichmentsURI != null) {
      fetch(enrichmentsURI)
        .then(response => response.json())
        .then(json => {
          const expressionClasses = _.get(json.dataSetClassList, '0.classes', []);
          const expressions = _.get(json.dataSetExpressionList, '0.expressions', []);
          const searchParam = query.q;

          this.setState({
            rawEnrichmentData: json,
            query: query.q
          });
          this.initPainter(expressions, expressionClasses, searchParam);

        });
    }
  }

  loadSbgn(uri) {
    const state = this.state;
    apiCaller.getGraphAndLayout(uri, 'latest').then(response => {
      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,
        nodeRepulsion: 5000 * state.cy.nodes().size()
      }).run();

      this.setState({
        name: _.get(response, 'graph.pathwayMetadata.title', 'N/A'),
        datasource: _.get(response, 'graph.pathwayMetadata.dataSource.0', 'N/A'),
      }, () => this.applyExpressionData());
    });
  }

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

    // const uri = 'http://identifiers.org/reactome/R-HSA-5389840';

    // if (uri != null) {
    //   const expressionTable = createExpressionTable(expressions, expressionClasses);
    //   const header = expressionTable.header;

    //   apiCaller.getGraphAndLayout(uri, 'latest').then(response => {
    //     state.cy.remove('*');
    //     state.cy.add({
    //       nodes: _.get(response, 'graph.nodes', []),
    //       edges: _.get(response, 'graph.edges', [])
    //     });

    //     if (!_.isEmpty(response.layout)) {
    //       state.cy.layout({
    //         name: 'preset',
    //         positions: node => response.layout[node.id()],
    //         animate: true,
    //         animationDuration: 500

    //       }).run();
    //     } else {
    //       state.cy.layout({
    //         name: 'cose-bilkent',
    //         randomize: false,
    //         nodeDimensionsIncludeLabels: true,
    //         nodeRepulsion: 5000 * state.cy.nodes().size()
    //       }).run();
    //     }

    //     this.setState({
    //       selectedClass: _.get(header, '0', null),
    //       expressionTable: expressionTable,
    //       name: _.get(response, 'graph.pathwayMetadata.title', 'N/A'),
    //       datasource: _.get(response, 'graph.pathwayMetadata.dataSource.0', 'N/A'),
    //       // searchResults: searchResults
    //     }, () => this.applyExpressionData());
    //   });
    // }

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

      if (uri != null) {
        const expressionTable = createExpressionTable(expressions, expressionClasses);
        const header = expressionTable.header;

        apiCaller.getGraphAndLayout(uri, 'latest').then(response => {
          state.cy.remove('*');
          state.cy.add({
            nodes: _.get(response, 'graph.nodes', []),
            edges: _.get(response, 'graph.edges', [])
          });

          if (!_.isEmpty(response.layout)) {
            state.cy.layout({
              name: 'preset',
              positions: node => response.layout[node.id()],
              animate: true,
              animationDuration: 500

            }).run();
          } else {
            state.cy.layout({
              name: 'cose-bilkent',
              randomize: false,
              nodeDimensionsIncludeLabels: true,
              nodeRepulsion: 5000 * state.cy.nodes().size()
            }).run();
          }

          this.setState({
            selectedClass: _.get(header, '0', null),
            expressionTable: expressionTable,
            name: _.get(response, 'graph.pathwayMetadata.title', 'N/A'),
            datasource: _.get(response, 'graph.pathwayMetadata.dataSource.0', 'N/A'),
            searchResults: searchResults
          }, () => this.applyExpressionData());
        });
      }
    });
  }

  expressionDataToNodeStyle(value, range) {
    const [, max] = range;
    const style = {};

    if ((0 - max / 3) <= value < (0 + max / 3)) {
      style['background-color'] = 'white';
      style['background-opacity'] = 1;
      style['color'] = 'black';
    }

    if (value < (0 - max / 3)) {
      style['background-opacity'] = `${Math.abs(value / max)}`;
      style['background-color'] = 'green';
      style['color'] = 'white';
      style['text-outline-color'] = 'black';
    }

    if ((0 + max / 3) <= value ) {
      style['background-color'] = 'purple';
      style['background-opacity'] = `${value / max}`;
      style['color'] = 'white';
      style['text-outline-color'] = 'black';

    }
    return style;
  }

  computeFoldChange(expression, selectedFunction) {
    const classValues = Object.entries(expression.classValues);
    const c1Val = selectedFunction(classValues[0][1]);

    let c2Val = selectedFunction(classValues[1][1]);
    c2Val = c2Val === 0 ? c2Val = 1 : c2Val;

    let foldChange = Math.log2(c1Val / c2Val);

    return {
      geneName: expression.geneName,
      value: parseFloat(foldChange.toFixed(2))
    };
  }

  applyExpressionData() {
    const state = this.state;

    const selectedFunction = state.selectedFunction.func;
    const expressionTable = state.expressionTable;

    const geneNodes = state.cy.nodes('[class="macromolecule"]');
    const geneNodeLabels = _.uniq(geneNodes.map(node => node.data('label'))).sort();

    const expressionsInNetwork = expressionTable.rows.filter(row => geneNodeLabels.includes(row.geneName));

    const expressionLabels = expressionsInNetwork.map(expression => expression.geneName);
    geneNodes.filter(node => !expressionLabels.includes(node.data('label'))).style({
      'background-color': 'grey',
      'color': 'grey',
      'opacity': 0.4
    });

    const foldValues = expressionsInNetwork.map(expression => this.computeFoldChange(expression, selectedFunction));
    const fvs = foldValues.map(fv => fv.value);
    const maxMagnitude = Math.max(Math.max(...fvs), Math.abs(Math.min(...fvs)));
    const range = [-maxMagnitude, maxMagnitude];
    foldValues.forEach(fv => {
      const matchedNodes = state.cy.nodes().filter(node => node.data('label') === fv.geneName);
      const style = this.expressionDataToNodeStyle(fv.value, range);

      state.cy.batch(() => matchedNodes.style(style));
    });

  }

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

  analysisFns() {
    return {
      mean: {
        name: 'mean',
        func: _.mean
      },
      max: {
        name: 'max',
        func: _.max
      },
      min: {
        name: 'min',
        func: _.min
      }
    };
  }

  render() {
    const state = this.state;

    const selectedFunction = state.selectedFunction.func;
    const selectedClass = state.selectedClass;
    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 foldValues = expressionsInNetwork.map(expression => this.computeFoldChange(expression, selectedFunction));
    const fvs = foldValues.map(fv => fv.value);
    const maxMagnitude = Math.max(Math.max(...fvs), Math.abs(Math.min(...fvs)));
    const max =  maxMagnitude;
    const min = -maxMagnitude;

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

    const columns = [
      {
        Header: 'Gene',
        accessor: 'geneName',
        filterMethod: (filter, rows) => matchSorter(rows, filter.value, { keys: ['geneName'] }),
        filterable: true,
        filterAll: true
      },
      {
        Header: 'log2 Fold-Change',
        id: 'foldChange',
        accessor: row => this.computeFoldChange(row, selectedFunction).value
      }
    ];

    const functionSelector = h('select.paint-select',
      {
        value: state.selectedFunction.name,
        onChange: e => this.setState({
          selectedFunction: _.find(this.analysisFns(), (fn) => fn.name === e.target.value)
        }, () => this.applyExpressionData())
      },
      Object.entries(this.analysisFns()).map(entry => h('option', {value: entry[0]}, entry[0]))
    );

    const classSelector = h('select.paint-select',
      {
        value: selectedClass,
        onChange: e => this.setState({
          selectedClass: e.target.value
        }, () => this.applyExpressionData())
      },
      expressionHeader.map(exprClass => h('option', { value: exprClass }, exprClass))
    );

    const tabbedContent = h(Tabs, [
      h('div.paint-drawer-header', [
        h(TabList, [
          h(Tab, 'Expression Data'),
          // h(Tab, 'Search Results')
        ]),
        h('a', { onClick: e => this.toggleDrawer()}, [
          h(Icon, { icon: 'close'}),
        ])
      ]),
      h(TabPanel, [
        h('div.paint-legend', [
          h('p', `low ${min}`),
          h('p', `high ${max}`)
        ]),
        h('div.paint-expression-controls', [
        h('div.paint-function-selector', [
          'Class: ',
          functionSelector
        ]),
        h('div.paint-compare-selector', [
          `Compare: ${expressionHeader[0]} vs ${expressionHeader[1]}`,
        ]),
      ]),
      h(Table, {
        className:'-striped -highlight',
        data: expressionRows,
        columns: columns,
        defaultPageSize: 150,
        showPagination: false,
        onFilteredChange: (column, value) => {
          cysearch(_.get(column, '0.value', ''), this.state.cy, false, {'border-width': 8, 'border-color': 'red'});
        }
      })
      ]),
      // h(TabPanel, state.searchResults.map(searchResult => {
      //     const uri = _.get(searchResult, 'uri', null);
      //     const name = _.get(searchResult, 'name', 'N/A');
      //     return h('div.paint-search-result', [
      //       h('a.plain-link', {onClick: e => this.loadSbgn(uri)}, name)
      //     ]);
      //   })
      // )
    ]);

    return h('div.paint', [
      h('div.paint-content', [
        h('div', { className: classNames('paint-drawer', { 'closed': !state.drawerOpen }) }, [
          tabbedContent
        ]),
        h(OmniBar, { title: `${state.name} | ${state.datasource}`, onMenuClick: (e) => this.toggleDrawer() }),
        h(Network, { cy: state.cy })
      ])
    ]);
  }
}

module.exports = Paint;<|endoftext|>


<commit_before>import Velocity from 'velocity-animate';
import Promise from 'bluebird';

import BandInfo from './components/BandInfo';
import Selection from './selection';

const animateTitle = () =>
  Velocity.animate(
    document.querySelector('.band-name'),
    {
      fontSize: '60px',
      translateY: -180,
    },
    { duration: 500 });

const reverseTitle = () =>
  Velocity.animate(
    document.querySelector('.band-name'),
    {
      fontSize: '100px',
      translateY: 0,
    },
    { duration: 500 });

const hideNextButton = () =>
  Velocity.animate(
    document.querySelector('.bottom-button'),
    {
      opacity: 0,
    },
    { duration: 500 });

const showNextButton = () =>
  Velocity.animate(
    document.querySelector('.bottom-button'),
    {
      opacity: 1,
    },
    { duration: 500 });

export const fadeToText = (id, newText) => {
  if (document.querySelector(id).innerHTML !== newText) {
    return Velocity(
      document.querySelector(id),
      { colorAlpha: 0 },
      { duration: 600 })
    .then(() => {
      const textArea = document.querySelector(id);
      textArea.innerHTML = newText;

      return Velocity(textArea, { colorAlpha: 1 }, { delay: 100, duration: 600 });
    });
  }

  else return Promise.resolve(false);
};

const changeCardSize = (size, time) => element =>
  Velocity(element, { width: size }, time);

export const selectCard = id => () => {
  const changeSize = changeCardSize('400px', 500);

  Velocity(
    document.querySelector(`#card-${id}`),
    {
      width: '400px',
      translateY: -50,
    },
    500
  )
  .then(() => {
    const ctrl = document.querySelector(`#preview-control-${id}`);
    if (ctrl) ctrl.style.display = 'block';
  });
  Velocity(document.querySelector(`#info-${id}`), { height: '400px' }, 500);

  changeSize(document.querySelector(`#flip-box-${id}`));
  changeSize(document.querySelector(`#front-${id}`));
  changeSize(document.querySelector(`#back-${id}`));
};

export const deselectCard = id => () => {
  const changeSize = changeCardSize('300px', 500);

  Velocity(
    document.querySelector(`#card-${id}`),
    {
      width: '300px',
      translateY: 0,
    },
    500
  )
  .then(() => {
    const ctrl = document.querySelector(`#preview-control-${id}`);
    if (ctrl) ctrl.style.display = 'none';
  });

  Velocity(document.querySelector(`#info-${id}`), { height: '300px' }, 500);
  changeSize(document.querySelector(`#flip-box-${id}`));
  changeSize(document.querySelector(`#front-${id}`));
  changeSize(document.querySelector(`#back-${id}`));
};

export const fadeOutElement = id =>
  Velocity(document.querySelector(id), { opacity: 0 }, 500);

export const fadeCardOut = id =>
  Velocity(
    document.querySelector(`#card-${id}`),
    { opacity: 0, width: 0, translateY: -60 },
    500)

    .then(() => document.querySelector(`#card-${id}`).style.display = 'none');

export const moveAddedCard = id =>
  Velocity(
    document.querySelector(`#card-${id}`),
    { translateY: -100 },
    1000)

  .then(e => {
    const changeSize = element =>
      Velocity(element, { width: '200px' }, { delay: 100, duration: 300 });

    changeSize(document.querySelector(`#flip-box-${id}`));
    changeSize(document.querySelector(`#front-${id}`));
    changeSize(document.querySelector(`#back-${id}`));

    Velocity(
      document.querySelector('#rfid-feedback'),
      { opacity: 1 },
      { delay: 200, duration: 300 });
    return Velocity(e, { width: '200px', translateY: 100 }, { delay: 100, duration: 300 });
  });

export const animateSlideOut = () => {
  const removeWidth = element =>
    Velocity(
      element,
      {
        width: 0,
        translateX: -100,
        marginLeft: '3px',
        marginRight: '3px',
      },
      300)
    .then(e => Velocity(e, { translateY: 40 }, { delay: 50, duration: 200 }))
    .then(e => Velocity(e, { translateY: 3000 }, { delay: 150, duration: 400 }));

  return Promise.all([
    removeWidth(document.querySelector(`#card-0`)),
    removeWidth(document.querySelector(`#card-1`)),
    removeWidth(document.querySelector(`#card-2`)),
  ])

  .then(() => fadeToText('#rfid-feedback', 'Added!'));
};

// MAIN TRANSITIONS
export const transition1 = () =>
  Promise.all([
    BandInfo.animate(),
    animateTitle(),
    fadeToText('#next-button-text', 'NEXT'),
    Velocity(document.querySelector('#back-button'), { opacity: 1 }, 200),
  ]);

export const frontPageIn = () =>
  Promise.all([
    BandInfo.reverseAnimate(),
    reverseTitle(),
    Velocity(document.querySelector('#back-button'), { opacity: 0 }, 200),
  ]);

export const reversePageTwo = () =>
  Promise.all([
    Promise.resolve('test'),
  ]);

export const reversePageThree = () =>
  Promise.all([
    Selection.reverseAnimateCardAdd(),
    showNextButton(),
    Velocity(document.querySelector('#rfid-feedback'), { opacity: 0 }, 500),
  ]);

export const transition2 = () =>
  Promise.all([
    Selection.animateCardAdd(),
    hideNextButton(),
    fadeToText('.bottom-button', 'FINISH'),
  ]);

export const transition3 = () =>
  Promise.all([
    animateSlideOut(),
  ]);

export const transition4 = () =>
  Promise.all([
    fadeCardOut('artist-0'),
    fadeCardOut('artist-1'),
    fadeCardOut('artist-2'),
    fadeOutElement('.bottom-button')
      .then(() => document.querySelector('.bottom-button').style.display = 'none'),
    fadeOutElement('.pg1-title'),
  ]);
<commit_msg>Hide back button on last page<commit_after>import Velocity from 'velocity-animate';
import Promise from 'bluebird';

import BandInfo from './components/BandInfo';
import Selection from './selection';

const animateTitle = () =>
  Velocity.animate(
    document.querySelector('.band-name'),
    {
      fontSize: '60px',
      translateY: -180,
    },
    { duration: 500 });

const reverseTitle = () =>
  Velocity.animate(
    document.querySelector('.band-name'),
    {
      fontSize: '100px',
      translateY: 0,
    },
    { duration: 500 });

const hideNextButton = () =>
  Velocity.animate(
    document.querySelector('.bottom-button'),
    {
      opacity: 0,
    },
    { duration: 500 });

const showNextButton = () =>
  Velocity.animate(
    document.querySelector('.bottom-button'),
    {
      opacity: 1,
    },
    { duration: 500 });

export const fadeToText = (id, newText) => {
  if (document.querySelector(id).innerHTML !== newText) {
    return Velocity(
      document.querySelector(id),
      { colorAlpha: 0 },
      { duration: 600 })
    .then(() => {
      const textArea = document.querySelector(id);
      textArea.innerHTML = newText;

      return Velocity(textArea, { colorAlpha: 1 }, { delay: 100, duration: 600 });
    });
  }

  else return Promise.resolve(false);
};

const changeCardSize = (size, time) => element =>
  Velocity(element, { width: size }, time);

export const selectCard = id => () => {
  const changeSize = changeCardSize('400px', 500);

  Velocity(
    document.querySelector(`#card-${id}`),
    {
      width: '400px',
      translateY: -50,
    },
    500
  )
  .then(() => {
    const ctrl = document.querySelector(`#preview-control-${id}`);
    if (ctrl) ctrl.style.display = 'block';
  });
  Velocity(document.querySelector(`#info-${id}`), { height: '400px' }, 500);

  changeSize(document.querySelector(`#flip-box-${id}`));
  changeSize(document.querySelector(`#front-${id}`));
  changeSize(document.querySelector(`#back-${id}`));
};

export const deselectCard = id => () => {
  const changeSize = changeCardSize('300px', 500);

  Velocity(
    document.querySelector(`#card-${id}`),
    {
      width: '300px',
      translateY: 0,
    },
    500
  )
  .then(() => {
    const ctrl = document.querySelector(`#preview-control-${id}`);
    if (ctrl) ctrl.style.display = 'none';
  });

  Velocity(document.querySelector(`#info-${id}`), { height: '300px' }, 500);
  changeSize(document.querySelector(`#flip-box-${id}`));
  changeSize(document.querySelector(`#front-${id}`));
  changeSize(document.querySelector(`#back-${id}`));
};

export const fadeOutElement = id =>
  Velocity(document.querySelector(id), { opacity: 0 }, 500);

export const fadeCardOut = id =>
  Velocity(
    document.querySelector(`#card-${id}`),
    { opacity: 0, width: 0, translateY: -60 },
    500)

    .then(() => document.querySelector(`#card-${id}`).style.display = 'none');

export const moveAddedCard = id =>
  Velocity(
    document.querySelector(`#card-${id}`),
    { translateY: -100 },
    1000)

  .then(e => {
    const changeSize = element =>
      Velocity(element, { width: '200px' }, { delay: 100, duration: 300 });

    changeSize(document.querySelector(`#flip-box-${id}`));
    changeSize(document.querySelector(`#front-${id}`));
    changeSize(document.querySelector(`#back-${id}`));

    Velocity(
      document.querySelector('#rfid-feedback'),
      { opacity: 1 },
      { delay: 200, duration: 300 });
    return Velocity(e, { width: '200px', translateY: 100 }, { delay: 100, duration: 300 });
  });

export const animateSlideOut = () => {
  const removeWidth = element =>
    Velocity(
      element,
      {
        width: 0,
        translateX: -100,
        marginLeft: '3px',
        marginRight: '3px',
      },
      300)
    .then(e => Velocity(e, { translateY: 40 }, { delay: 50, duration: 200 }))
    .then(e => Velocity(e, { translateY: 3000 }, { delay: 150, duration: 400 }));

  return Promise.all([
    removeWidth(document.querySelector(`#card-0`)),
    removeWidth(document.querySelector(`#card-1`)),
    removeWidth(document.querySelector(`#card-2`)),
  ])

  .then(() => fadeToText('#rfid-feedback', 'Added!'));
};

// MAIN TRANSITIONS
export const transition1 = () =>
  Promise.all([
    BandInfo.animate(),
    animateTitle(),
    fadeToText('#next-button-text', 'NEXT'),
    Velocity(document.querySelector('#back-button'), { opacity: 1 }, 200),
  ]);

export const frontPageIn = () =>
  Promise.all([
    BandInfo.reverseAnimate(),
    reverseTitle(),
    Velocity(document.querySelector('#back-button'), { opacity: 0 }, 200),
  ]);

export const reversePageTwo = () =>
  Promise.all([
    Promise.resolve('test'),
  ]);

export const reversePageThree = () =>
  Promise.all([
    Selection.reverseAnimateCardAdd(),
    showNextButton(),
    Velocity(document.querySelector('#rfid-feedback'), { opacity: 0 }, 500),
  ]);

export const transition2 = () =>
  Promise.all([
    Selection.animateCardAdd(),
    hideNextButton(),
    fadeToText('.bottom-button', 'FINISH'),
    fadeOutElement('#back-button'),
  ]);

export const transition3 = () =>
  Promise.all([
    animateSlideOut(),
  ]);

export const transition4 = () =>
  Promise.all([
    fadeCardOut('artist-0'),
    fadeCardOut('artist-1'),
    fadeCardOut('artist-2'),
    fadeOutElement('.bottom-button')
      .then(() => document.querySelector('.bottom-button').style.display = 'none'),
    fadeOutElement('.pg1-title'),
  ]);
<|endoftext|>


<commit_before>(function ( global ) {

'use strict';

var Ractive,

doc = global.document || null,

proto = {},

// properties of the public Ractive object
adaptors = {},
eventDefinitions = {},
easing,
extend,
interpolate,
interpolators,
transitions = {},

// internal utils
splitKeypath,
toString,
isArray,
isObject,
isNumeric,
isEqual,
getEl,
requestAnimationFrame,
cancelAnimationFrame,
defineProperty,
defineProperties,
create,
createFromNull,
noop = function () {},

// internally used caches
keypathCache = {},

// internally used constructors
DomFragment,
TextFragment,
Evaluator,
Animation,

// internally used regexes
leadingWhitespace = /^\s+/,
trailingWhitespace = /\s+$/,

// other bits and pieces
initMustache,
updateMustache,
resolveMustache,
evaluateMustache,

initFragment,
updateSection,

animationCollection,

// array modification
registerKeypathToArray,
unregisterKeypathFromArray,

// parser and tokenizer
stripCommentTokens,
stripHtmlComments,
stripStandalones,

// error messages
missingParser = 'Missing Ractive.parse - cannot parse template. Either preparse or use the version that includes the parser',

// constants
TEXT              = 1,
INTERPOLATOR      = 2,
TRIPLE            = 3,
SECTION           = 4,
INVERTED          = 5,
CLOSING           = 6,
ELEMENT           = 7,
PARTIAL           = 8,
COMMENT           = 9,
DELIMCHANGE       = 10,
MUSTACHE          = 11,
TAG               = 12,
ATTR_VALUE_TOKEN  = 13,
EXPRESSION        = 14,

NUMBER_LITERAL    = 20,
STRING_LITERAL    = 21,
ARRAY_LITERAL     = 22,
OBJECT_LITERAL    = 23,
BOOLEAN_LITERAL   = 24,
LITERAL           = 25,
GLOBAL            = 26,

REFERENCE         = 30,
REFINEMENT        = 31,
MEMBER            = 32,
PREFIX_OPERATOR   = 33,
BRACKETED         = 34,
CONDITIONAL       = 35,
INFIX_OPERATOR    = 36,

INVOCATION        = 40,

UNSET             = { unset: true },

// namespaces
namespaces = {
	html:   'http://www.w3.org/1999/xhtml',
	mathml: 'http://www.w3.org/1998/Math/MathML',
	svg:    'http://www.w3.org/2000/svg',
	xlink:  'http://www.w3.org/1999/xlink',
	xml:    'http://www.w3.org/XML/1998/namespace',
	xmlns:  'http://www.w3.org/2000/xmlns/'
};

// we're creating a defineProperty function here - we don't want to add
// this to _legacy.js since it's not a polyfill. It won't allow us to set
// non-enumerable properties. That shouldn't be a problem, unless you're
// using for...in on a (modified) array, in which case you deserve what's
// coming anyway
try {
	Object.defineProperty({}, 'test', { value: 0 });
	Object.defineProperties({}, { test: { value: 0 } });

	defineProperty = Object.defineProperty;
	defineProperties = Object.defineProperties;
} catch ( err ) {
	// Object.defineProperty doesn't exist, or we're in IE8 where you can
	// only use it with DOM objects (what the fuck were you smoking, MSFT?)
	defineProperty = function ( obj, prop, desc ) {
		obj[ prop ] = desc.value;
	};

	defineProperties = function ( obj, props ) {
		var prop;

		for ( prop in props ) {
			if ( props.hasOwnProperty( prop ) ) {
				defineProperty( obj, prop, props[ prop ] );
			}
		}
	};
}

try {
	Object.create( null );

	create = Object.create;

	createFromNull = function () {
		return Object.create( null );
	};
} catch ( err ) {
	// sigh
	create = (function () {
		var F = function () {};

		return function ( proto, props ) {
			var obj;

			F.prototype = proto;
			obj = new F();

			if ( props ) {
				Object.defineProperties( obj, props );
			}

			return obj;
		};
	}());

	createFromNull = function () {
		return {}; // hope you're not modifying the Object prototype
	};
}

var hyphenate = function ( str ) {
	return str.replace( /[A-Z]/g, function ( match ) {
		return '-' + match.toLowerCase();
	});
};

// determine some facts about our environment
var cssTransitionsEnabled, transition, transitionend;

(function () {

	var testDiv;

	if ( !doc ) {
		return;
	}

	testDiv = doc.createElement( 'div' );

	if ( testDiv.style.transition !== undefined ) {
		transition = 'transition';
		transitionend = 'transitionend';
		cssTransitionsEnabled = true;
	} else if ( testDiv.style.webkitTransition !== undefined ) {
		transition = 'webkitTransition';
		transitionend = 'webkitTransitionEnd';
		cssTransitionsEnabled = true;
	} else {
		cssTransitionsEnabled = false;
	}

}());<commit_msg>add internal render function to initial var declaration<commit_after>(function ( global ) {

'use strict';

var Ractive,

doc = global.document || null,

proto = {},

// properties of the public Ractive object
adaptors = {},
eventDefinitions = {},
easing,
extend,
interpolate,
interpolators,
transitions = {},

// internal utils
splitKeypath,
toString,
isArray,
isObject,
isNumeric,
isEqual,
getEl,
requestAnimationFrame,
cancelAnimationFrame,
defineProperty,
defineProperties,
create,
createFromNull,
noop = function () {},

// internally used caches
keypathCache = {},

// internally used constructors
DomFragment,
TextFragment,
Evaluator,
Animation,

// internally used regexes
leadingWhitespace = /^\s+/,
trailingWhitespace = /\s+$/,

// other bits and pieces
render,

initMustache,
updateMustache,
resolveMustache,
evaluateMustache,

initFragment,
updateSection,

animationCollection,

// array modification
registerKeypathToArray,
unregisterKeypathFromArray,

// parser and tokenizer
stripCommentTokens,
stripHtmlComments,
stripStandalones,

// error messages
missingParser = 'Missing Ractive.parse - cannot parse template. Either preparse or use the version that includes the parser',

// constants
TEXT              = 1,
INTERPOLATOR      = 2,
TRIPLE            = 3,
SECTION           = 4,
INVERTED          = 5,
CLOSING           = 6,
ELEMENT           = 7,
PARTIAL           = 8,
COMMENT           = 9,
DELIMCHANGE       = 10,
MUSTACHE          = 11,
TAG               = 12,
ATTR_VALUE_TOKEN  = 13,
EXPRESSION        = 14,

NUMBER_LITERAL    = 20,
STRING_LITERAL    = 21,
ARRAY_LITERAL     = 22,
OBJECT_LITERAL    = 23,
BOOLEAN_LITERAL   = 24,
LITERAL           = 25,
GLOBAL            = 26,

REFERENCE         = 30,
REFINEMENT        = 31,
MEMBER            = 32,
PREFIX_OPERATOR   = 33,
BRACKETED         = 34,
CONDITIONAL       = 35,
INFIX_OPERATOR    = 36,

INVOCATION        = 40,

UNSET             = { unset: true },

// namespaces
namespaces = {
	html:   'http://www.w3.org/1999/xhtml',
	mathml: 'http://www.w3.org/1998/Math/MathML',
	svg:    'http://www.w3.org/2000/svg',
	xlink:  'http://www.w3.org/1999/xlink',
	xml:    'http://www.w3.org/XML/1998/namespace',
	xmlns:  'http://www.w3.org/2000/xmlns/'
};

// we're creating a defineProperty function here - we don't want to add
// this to _legacy.js since it's not a polyfill. It won't allow us to set
// non-enumerable properties. That shouldn't be a problem, unless you're
// using for...in on a (modified) array, in which case you deserve what's
// coming anyway
try {
	Object.defineProperty({}, 'test', { value: 0 });
	Object.defineProperties({}, { test: { value: 0 } });

	defineProperty = Object.defineProperty;
	defineProperties = Object.defineProperties;
} catch ( err ) {
	// Object.defineProperty doesn't exist, or we're in IE8 where you can
	// only use it with DOM objects (what the fuck were you smoking, MSFT?)
	defineProperty = function ( obj, prop, desc ) {
		obj[ prop ] = desc.value;
	};

	defineProperties = function ( obj, props ) {
		var prop;

		for ( prop in props ) {
			if ( props.hasOwnProperty( prop ) ) {
				defineProperty( obj, prop, props[ prop ] );
			}
		}
	};
}

try {
	Object.create( null );

	create = Object.create;

	createFromNull = function () {
		return Object.create( null );
	};
} catch ( err ) {
	// sigh
	create = (function () {
		var F = function () {};

		return function ( proto, props ) {
			var obj;

			F.prototype = proto;
			obj = new F();

			if ( props ) {
				Object.defineProperties( obj, props );
			}

			return obj;
		};
	}());

	createFromNull = function () {
		return {}; // hope you're not modifying the Object prototype
	};
}

var hyphenate = function ( str ) {
	return str.replace( /[A-Z]/g, function ( match ) {
		return '-' + match.toLowerCase();
	});
};

// determine some facts about our environment
var cssTransitionsEnabled, transition, transitionend;

(function () {

	var testDiv;

	if ( !doc ) {
		return;
	}

	testDiv = doc.createElement( 'div' );

	if ( testDiv.style.transition !== undefined ) {
		transition = 'transition';
		transitionend = 'transitionend';
		cssTransitionsEnabled = true;
	} else if ( testDiv.style.webkitTransition !== undefined ) {
		transition = 'webkitTransition';
		transitionend = 'webkitTransitionEnd';
		cssTransitionsEnabled = true;
	} else {
		cssTransitionsEnabled = false;
	}

}());<|endoftext|>


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

var success = function(message) {
    console.log("BMSLogger: Success: " + message);
};
var failure = function(message) {
    console.log("BMSLogger: Failure: " + message);
};

/**
 *
 * @param name
 * @constructor
 */
var Logger = function (name){
    this.name = name; // instance variable
};

Logger.prototype = function(){
    /**
     *
     * @param message
     */
    var debug = function (message) {
        cordova.exec(success, failure, "BMSLogger", "debug", [this.name, message]);
    };
    /**
     *
     * @param message
     */
    var info = function (message) {
        cordova.exec(success, failure, "BMSLogger", "info", [this.name, message]);
    };
    /**
     *
     * @param message
     */
    var error = function (message) {
        cordova.exec(success, failure, "BMSLogger", "error", [this.name, message]);
    };
    /**
     *
     * @param message
     */
    var fatal = function (message) {
        cordova.exec(success, failure, "BMSLogger", "fatal", [this.name, message]);
    };
    /**
     *
     * @param message
     */
    var warn = function (message) {
        cordova.exec(success, failure, "BMSLogger", "warn", [this.name, message]);
    };
    /**
     *
     * @returns {*}
     */
    var getName = function () {
        return this.name;
    };

    return {
        debug : debug,
        info : info,
        error : error,
        fatal : fatal,
        warn : warn,
        getName : getName
    };
}();

var BMSLogger = (function () {
    var instances = {};

    /**
     * Private Method for creating logger instances
     * @param name
     * @returns {Logger}
     */
    function createInstance(name) {
        var logger = new Logger(name);
        return logger;
    }

    function boolWrap(callback, result) {
        /*   For now, it seems that Java cannot
         return boolean values to their callbacks.
         So we intercept the callback, check if it's a string
         and convert the result to a boolean.
        */
        if(typeof(result) == "string") {
            result = (result === "true");
        }
        callback(result);
    }

    return {
        /**
         *  Returns a named Logger Instance
         * @param name - the name for the logger
         * @returns {*} a Logger instance
         */
        getInstance: function (name) {
            if (!instances[name]) {
                instances[name] = createInstance(name);
            }
            return instances[name];
        },
        /**
         * Gets the current setting for determining if log data should be saved persistently
         * @param {Boolean} enabled - Boolean used to indicate whether the log data must be saved persistently
         */
        storeLogs : function (enabled) {
            cordova.exec(boolWrap.bind(null, success), failure, "BMSLogger", "storeLogs", [enabled]);
        },
        /**
         * Gets the current setting for the maximum storage size threshold
         * @param success - single parameter receives Integer indicating the maximum storage size threshold
         * @param failure
         */
        getMaxLogStoreSize : function (success, failure) {
            cordova.exec(success , failure, "BMSLogger", "getMaxLogStoreSize", []);
        },
        /**
         * Sets the maximum size of the local persistent storage for queuing log data.
         * When the maximum storage size is reached, no more data is queued. This content of the storage is sent to a server.
         * @param {integer} intSize
         */
        setMaxLogStoreSize : function (intSize) {
            cordova.exec(success , failure, "BMSLogger", "setMaxLogStoreSize", [intSize]);
        },
        /** Determines if logs are currently being store
         * @param success - single parameter receives Integer indicating the maximum storage size threshold
         * @param failure
         */
        isStoringLogs : function(success, failure){
            cordova.exec(success , failure, "BMSLogger", "isStoringLogs", []);
        },
        /**
         * Enable displaying all Bluemix Mobile Services SDK debug logs in Logcat. By default, no debug messages are displayed.
         * @param enabled Determines whether to display Bluemix Mobile Services SDK debug logs in Logcat.
         */
        setSDKDebugLoggingEnabled : function (enabled) {
            cordova.exec(boolWrap(null, success), failure, "BMSLogger", "setSDKDebugLoggingEnabled", [enabled]);
        },
        /** Check if displaying all Bluemix Mobile Services SDK debug logs in Logcat is enabled.
         * @param success - single parameter receives Integer indicating the maximum storage size threshold
         * @param failure
         */
        isSDKDebugLoggingEnabled : function (success, failure ) {
            cordova.exec(success , failure, "BMSLogger", "isSDKDebugLoggingEnabled", []);
        },
        /**
         * Gets the currently configured Log Level
         * @param success callback receives  {integer} indicating Log Level
         * @param failure
         */
        getLogLevel : function (success, failure) {
            cordova.exec(success , failure, "BMSLogger", "getLogLevel", []);
        },
        /**
         * Sets the level from which log messages must be saved and printed.
         * For example, passing BMSLogger.INFO logs INFO, WARN, and ERROR.

         * @param { integer or symbolic level definde below} logLevel
         */
        setLogLevel : function (logLevel) {
            cordova.exec(success , failure, "BMSLogger", "setLogLevel", [logLevel]);
        },
        /**
         * Indicates that an uncaught exception was detected.
         * The indicator is cleared on successful send.
         * @param success callback receives Boolean that indicates an uncaught exception was detected (true) or not (false)
         * @param failure
         */
        isUncaughtExceptionDetected : function (success, failure) {
            cordova.exec(success , failure, "BMSLogger", "isUncaughtExceptionDetected", []);
        },
        /**
         * Sends the log file when the log store exists and is not empty.
         * If the send fails, the local store is preserved. If the send succeeds, the local store is deleted.
         * @param success callback
         * @param failure callback
         */
        send : function (success, failure) {
            cordova.exec(success , failure, "BMSLogger", "send", []);
        }
    };
})();

/** Trace level */
BMSLogger.FATAL = "FATAL";
BMSLogger.ERROR = "ERROR";
BMSLogger.WARN  = "WARN";
BMSLogger.INFO  = "INFO";
BMSLogger.DEBUG = "DEBUG";

module.exports = BMSLogger;<commit_msg>remove boolWrap instead of returning bool just return 0 or 1 int<commit_after>/*
    Copyright 2015 IBM Corp.
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at
        http://www.apache.org/licenses/LICENSE-2.0
    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/
var exec = require("cordova/exec");

var success = function(message) {
    console.log("BMSLogger: Success: " + message);
};
var failure = function(message) {
    console.log("BMSLogger: Failure: " + message);
};

/**
 *
 * @param name
 * @constructor
 */
var Logger = function (name){
    this.name = name; // instance variable
};

Logger.prototype = function(){
    /**
     *
     * @param message
     */
    var debug = function (message) {
        cordova.exec(success, failure, "BMSLogger", "debug", [this.name, message]);
    };
    /**
     *
     * @param message
     */
    var info = function (message) {
        cordova.exec(success, failure, "BMSLogger", "info", [this.name, message]);
    };
    /**
     *
     * @param message
     */
    var error = function (message) {
        cordova.exec(success, failure, "BMSLogger", "error", [this.name, message]);
    };
    /**
     *
     * @param message
     */
    var fatal = function (message) {
        cordova.exec(success, failure, "BMSLogger", "fatal", [this.name, message]);
    };
    /**
     *
     * @param message
     */
    var warn = function (message) {
        cordova.exec(success, failure, "BMSLogger", "warn", [this.name, message]);
    };
    /**
     *
     * @returns {*}
     */
    var getName = function () {
        return this.name;
    };

    return {
        debug : debug,
        info : info,
        error : error,
        fatal : fatal,
        warn : warn,
        getName : getName
    };
}();

var BMSLogger = (function () {
    var instances = {};

    /**
     * Private Method for creating logger instances
     * @param name
     * @returns {Logger}
     */
    function createInstance(name) {
        var logger = new Logger(name);
        return logger;
    }

    return {
        /**
         *  Returns a named Logger Instance
         * @param name - the name for the logger
         * @returns {*} a Logger instance
         */
        getInstance: function (name) {
            if (!instances[name]) {
                instances[name] = createInstance(name);
            }
            return instances[name];
        },
        /**
         * Gets the current setting for determining if log data should be saved persistently
         * @param {Boolean} enabled - Boolean used to indicate whether the log data must be saved persistently
         */
        storeLogs : function (enabled) {
            cordova.exec(success, failure, "BMSLogger", "storeLogs", [enabled]);
        },
        /**
         * Gets the current setting for the maximum storage size threshold
         * @param success - single parameter receives Integer indicating the maximum storage size threshold
         * @param failure
         */
        getMaxLogStoreSize : function (success, failure) {
            cordova.exec(success , failure, "BMSLogger", "getMaxLogStoreSize", []);
        },
        /**
         * Sets the maximum size of the local persistent storage for queuing log data.
         * When the maximum storage size is reached, no more data is queued. This content of the storage is sent to a server.
         * @param {integer} intSize
         */
        setMaxLogStoreSize : function (intSize) {
            cordova.exec(success , failure, "BMSLogger", "setMaxLogStoreSize", [intSize]);
        },
        /** Determines if logs are currently being store
         * @param success - single parameter receives Integer indicating the maximum storage size threshold
         * @param failure
         */
        isStoringLogs : function(success, failure){
            cordova.exec(success , failure, "BMSLogger", "isStoringLogs", []);
        },
        /**
         * Enable displaying all Bluemix Mobile Services SDK debug logs in Logcat. By default, no debug messages are displayed.
         * @param enabled Determines whether to display Bluemix Mobile Services SDK debug logs in Logcat.
         */
        setSDKDebugLoggingEnabled : function (enabled) {
            cordova.exec(success, failure, "BMSLogger", "setSDKDebugLoggingEnabled", [enabled]);
        },
        /** Check if displaying all Bluemix Mobile Services SDK debug logs in Logcat is enabled.
         * @param success - single parameter receives Integer indicating the maximum storage size threshold
         * @param failure
         */
        isSDKDebugLoggingEnabled : function (success, failure ) {
            cordova.exec(success , failure, "BMSLogger", "isSDKDebugLoggingEnabled", []);
        },
        /**
         * Gets the currently configured Log Level
         * @param success callback receives  {integer} indicating Log Level
         * @param failure
         */
        getLogLevel : function (success, failure) {
            cordova.exec(success , failure, "BMSLogger", "getLogLevel", []);
        },
        /**
         * Sets the level from which log messages must be saved and printed.
         * For example, passing BMSLogger.INFO logs INFO, WARN, and ERROR.

         * @param { integer or symbolic level definde below} logLevel
         */
        setLogLevel : function (logLevel) {
            cordova.exec(success , failure, "BMSLogger", "setLogLevel", [logLevel]);
        },
        /**
         * Indicates that an uncaught exception was detected.
         * The indicator is cleared on successful send.
         * @param success callback receives Boolean that indicates an uncaught exception was detected (true) or not (false)
         * @param failure
         */
        isUncaughtExceptionDetected : function (success, failure) {
            cordova.exec(success , failure, "BMSLogger", "isUncaughtExceptionDetected", []);
        },
        /**
         * Sends the log file when the log store exists and is not empty.
         * If the send fails, the local store is preserved. If the send succeeds, the local store is deleted.
         * @param success callback
         * @param failure callback
         */
        send : function (success, failure) {
            cordova.exec(success , failure, "BMSLogger", "send", []);
        }
    };
})();

/** Trace level */
BMSLogger.FATAL = "FATAL";
BMSLogger.ERROR = "ERROR";
BMSLogger.WARN  = "WARN";
BMSLogger.INFO  = "INFO";
BMSLogger.DEBUG = "DEBUG";

module.exports = BMSLogger;<|endoftext|>


<commit_before>

var DialogGPS = function(message,description,callback,title,buttons){

	var _title = (title || "Usar local?");
	var _message = (message || "Este app deseja alterar as configurações do seu dispotivo:");
	var _description = (description || "Use Wi-Fi e redes celulares para localização");
	var _buttons = (buttons || ["Não","Sim"]);

	if(Object.prototype.toString.call(_buttons) === "[object Array]") {

		cordova.exec(callback,null,'DialogGPS','DISPLAY',[_title,_message,_description,_buttons]);

	}
};

DialogGPS.gpsActive = function(successCallback,failCallback){
}

module.exports = DialogGPS;
<commit_msg>Update DialogGPS.js<commit_after>

var DialogGPS = function(message,description,callback,title,buttons){

	var _title = (title || "Usar local?");
	var _message = (message || "Este app deseja alterar as configuracoes do seu dispotivo:");
	var _description = (description || "Use Wi-Fi e redes celulares para localizacao");
	var _buttons = (buttons || ["Não","Sim"]);

	if(Object.prototype.toString.call(_buttons) === "[object Array]") {

		cordova.exec(callback,null,'DialogGPS','DISPLAY',[_title,_message,_description,_buttons]);

	}
};

DialogGPS.gpsActive = function(successCallback,failCallback){
}

module.exports = DialogGPS;
<|endoftext|>


<commit_before>'use strict';

/**
 * Constants definition.
 *
 * author: Michael Liao
 */

module.exports = {
    // user role:
    role: {
        ADMIN:       0,
        EDITOR:      10,
        CONTRIBUTOR: 100,
        SUBSCRIBER:  10000,
        GUEST:       100000000
    },

    signin: {
        LOCAL: 'local'
    },

    // cache keys:
    cache: {
        NAVIGATIONS: '__navigations__',
        WEBSITE: '__website__',
        SNIPPETS: '__snippet__',
        SETTINGS: '__settings__'
    },

    // queue name:
    queue: {
        MAIL: 'queueMail',
        SNS: 'queueSNS'
    }
};
<commit_msg>remove unused const<commit_after>'use strict';

/**
 * Constants definition.
 *
 * author: Michael Liao
 */

module.exports = {
    // user role:
    role: {
        ADMIN:       0,
        EDITOR:      10,
        CONTRIBUTOR: 100,
        SUBSCRIBER:  10000,
        GUEST:       100000000
    },

    signin: {
        LOCAL: 'local'
    },

    // cache keys:
    cache: {
        NAVIGATIONS: '__navigations__',
        WEBSITE: '__website__',
        SNIPPETS: '__snippet__'
    },

    // queue name:
    queue: {
        MAIL: 'queueMail',
        SNS: 'queueSNS'
    }
};
<|endoftext|>


<commit_before>'use strict';

// Logitech Harmony Remote Platform Shim for HomeBridge
// Based on the Domoticz Platform Shim for HomeBridge by Joep Verhaeg (http://www.joepverhaeg.nl)
// Wriiten by John Wells (https://github.com/madmod)
//
// Remember to add platform to config.json. Example:
// "platforms": [
//     {
//         "platform": "LogitechHarmony",
//         "name": "Logitech Harmony"
//     }
// ],
//
// When you attempt to add a device, it will ask for a "PIN code".
// The default code for all HomeBridge accessories is 031-45-154.
//

var types = require('HAP-NodeJS/accessories/types.js');

var harmonyDiscover = require('harmonyhubjs-discover');
var harmony = require('harmonyhubjs-client');

var _harmonyHubPort = 61991;

var Service = require("hap-nodejs").Service;
var Characteristic = require("hap-nodejs").Characteristic;
var Accessory = require("hap-nodejs").Accessory;
var uuid = require("hap-nodejs").uuid;
var inherits = require('util').inherits;

function sortByKey (array, key) {
  return array.sort(function(a, b) {
    var x = a[key]; var y = b[key];
    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  });
};

function LogitechHarmonyPlatform (log, config) {
  this.log = log;
  this.ip_address = config['ip_address'];
};

LogitechHarmonyPlatform.prototype = {

  // Find one Harmony remote hub (only support one for now)
  locateHub: function (callback) {
    var self = this;

    // Connect to a Harmony hub
    var createClient = function (ipAddress) {
      self.log("Connecting to Logitech Harmony remote hub...");

      harmony(ipAddress)
        .then(function (client) {
          self.log("Connected to Logitech Harmony remote hub");

          // prevent connection from closing
          setTimeout(function() {
            setInterval(function() {
              self.log("Sending command to prevent timeout");
              client.getCurrentActivity();
            }, 20000);
          }, 5000);

          callback(null, client);
        });
    };

    // Use the ip address in configuration if available
    if (this.ip_address) {
      console.log("Using Logitech Harmony hub ip address from configuration");

      return createClient(this.ip_address)
    }

    this.log("Searching for Logitech Harmony remote hubs...");

    // Discover the harmony hub with bonjour
    var discover = new harmonyDiscover(_harmonyHubPort);

    // TODO: Support update event with some way to add accessories
    // TODO: Have some kind of timeout with an error message. Right now this searches forever until it finds one hub.
    discover.on('online', function (hubInfo) {
      self.log("Found Logitech Harmony remote hub: " + hubInfo.ip);

      // Stop looking for hubs once we find the first one
      // TODO: Support multiple hubs
      discover.stop();

      createClient(hubInfo.ip);
    });

    // Start looking for hubs
    discover.start();
  },

  accessories: function (callback) {
    var self = this;
    var foundAccessories = [];

    // Get the first hub
    this.locateHub(function (err, hub) {
      if (err) throw err;

      self.log("Fetching Logitech Harmony devices and activites...");

      //getDevices(hub);
      getActivities(hub);
    });

    // Get Harmony Devices
    /*
    var getDevices = function(hub) {
      self.log("Fetching Logitech Harmony devices...");

      hub.getDevices()
        .then(function (devices) {
          self.log("Found devices: ", devices);

          var sArray = sortByKey(json['result'],"Name");

          sArray.map(function(s) {
            accessory = new LogitechHarmonyActivityAccessory(self.log, self.server, self.port, false, s.idx, s.Name, s.HaveDimmer, s.MaxDimLevel, (s.SubType=="RGB")||(s.SubType=="RGBW"));
            foundAccessories.push(accessory);
          });

          callback(foundAccessories);
        });
    };
    */

    // Get Harmony Activities
    var getActivities = function(hub) {
      self.log("Fetching Logitech Harmony activities...");

      hub.getActivities()
        .then(function (activities) {
          self.log("Found activities: \n" + activities.map(function (a) { return "\t" + a.label; }).join("\n"));

          var sArray = sortByKey(activities, "label");

          sArray.map(function(s) {
            var accessory = new LogitechHarmonyActivityAccessory(self.log, hub, s);
            // TODO: Update the initial power state
            foundAccessories.push(accessory);
          });

          callback(foundAccessories);
        });
    };

  }

};

function LogitechHarmonyActivityAccessory (log, hub, details) {
  this.log = log;
  this.hub = hub;
  this.details = details;
  this.id = details.id;
  this.name = details.label;
  Accessory.call(this, this.name, uuid.generate(this.id));

  this.getService(Service.AccessoryInformation)
      .setCharacteristic(Characteristic.Manufacturer, "Logitech")
      .setCharacteristic(Characteristic.Model, "Harmony")
      // TODO: Add hub unique id to this for people with multiple hubs so that it is really a guid.
      .setCharacteristic(Characteristic.SerialNumber, this.id);

  this.addService(Service.Switch)
      .getCharacteristic(Characteristic.On)
      .on('get', this.getPowerState)
      .on('set', this.setPowerState);
};
inherits(LogitechHarmonyActivityAccessory, Accessory);
LogitechHarmonyActivityAccessory.prototype.parent = Accessory.prototype;
LogitechHarmonyActivityAccessory.prototype.getServices = function() {
  return this.services;
};

  // TODO: Somehow make this event driven so that it tells the user what activity is on
  LogitechHarmonyActivityAccessory.prototype.getPowerState = function (callback) {
    var self = this;

      this.hub.getCurrentActivity().then(function (currentActivity) {
        callback(currentActivity === self.id);
      }).catch(function (err) {
        self.log('Unable to get current activity with error', err);
        callback(false);
      });
  };

  LogitechHarmonyActivityAccessory.prototype.setPowerState = function (state) {
    var self = this;

      this.log('Set activity ' + this.name + ' power state to ' + state);

      this.hub.startActivity(self.id)
        .then(function () {
          self.log('Finished setting activity ' + self.name + ' power state to ' + state);
        })
        .catch(function (err) {
          self.log('Failed setting activity ' + self.name + ' power state to ' + state + ' with error ' + err);
        });
  };

module.exports.platform = LogitechHarmonyPlatform;

<commit_msg>Added handling to keep track of activity state<commit_after>'use strict';

// Logitech Harmony Remote Platform Shim for HomeBridge
// Based on the Domoticz Platform Shim for HomeBridge by Joep Verhaeg (http://www.joepverhaeg.nl)
// Wriiten by John Wells (https://github.com/madmod)
//
// Remember to add platform to config.json. Example:
// "platforms": [
//     {
//         "platform": "LogitechHarmony",
//         "name": "Logitech Harmony"
//     }
// ],
//
// When you attempt to add a device, it will ask for a "PIN code".
// The default code for all HomeBridge accessories is 031-45-154.
//

var types = require('HAP-NodeJS/accessories/types.js');

var harmonyDiscover = require('harmonyhubjs-discover');
var harmony = require('harmonyhubjs-client');

var _harmonyHubPort = 61991;

var Service = require("hap-nodejs").Service;
var Characteristic = require("hap-nodejs").Characteristic;
var Accessory = require("hap-nodejs").Accessory;
var uuid = require("hap-nodejs").uuid;
var inherits = require('util').inherits;

function sortByKey (array, key) {
  return array.sort(function(a, b) {
    var x = a[key]; var y = b[key];
    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  });
};

function LogitechHarmonyPlatform (log, config) {
  this.log = log;
  this.ip_address = config['ip_address'];
};

LogitechHarmonyPlatform.prototype = {

  // Find one Harmony remote hub (only support one for now)
  locateHub: function (callback) {
    var self = this;

    // Connect to a Harmony hub
    var createClient = function (ipAddress) {
      self.log("Connecting to Logitech Harmony remote hub...");

      harmony(ipAddress)
        .then(function (client) {
          self.log("Connected to Logitech Harmony remote hub");

          // prevent connection from closing
          setTimeout(function() {
            setInterval(function() {
              self.log("Sending command to prevent timeout");
              client.getCurrentActivity().then(self.updateCurrentActivity.bind(self));
            }, 20000);
          }, 5000);

          callback(null, client);
        });
    };

    // Use the ip address in configuration if available
    if (this.ip_address) {
      console.log("Using Logitech Harmony hub ip address from configuration");

      return createClient(this.ip_address)
    }

    this.log("Searching for Logitech Harmony remote hubs...");

    // Discover the harmony hub with bonjour
    var discover = new harmonyDiscover(_harmonyHubPort);

    // TODO: Support update event with some way to add accessories
    // TODO: Have some kind of timeout with an error message. Right now this searches forever until it finds one hub.
    discover.on('online', function (hubInfo) {
      self.log("Found Logitech Harmony remote hub: " + hubInfo.ip);

      // Stop looking for hubs once we find the first one
      // TODO: Support multiple hubs
      discover.stop();

      createClient(hubInfo.ip);
    });

    // Start looking for hubs
    discover.start();
  },

  updateCurrentActivity: function(currentActivity) {
    var actAccessories = this.activityAccessories;
    if (actAccessories instanceof Array) {
      actAccessories.map(function(a) { a.updateActivityState(currentActivity); });
    }
  },

  accessories: function (callback) {
    var self = this;
    var foundAccessories = [];

    // Get the first hub
    this.locateHub(function (err, hub) {
      if (err) throw err;

      self.log("Fetching Logitech Harmony devices and activites...");

      //getDevices(hub);
      getActivities(hub);
    });

    // Get Harmony Devices
    /*
    var getDevices = function(hub) {
      self.log("Fetching Logitech Harmony devices...");

      hub.getDevices()
        .then(function (devices) {
          self.log("Found devices: ", devices);

          var sArray = sortByKey(json['result'],"Name");

          sArray.map(function(s) {
            accessory = new LogitechHarmonyActivityAccessory(self.log, self.server, self.port, false, s.idx, s.Name, s.HaveDimmer, s.MaxDimLevel, (s.SubType=="RGB")||(s.SubType=="RGBW"));
            foundAccessories.push(accessory);
          });

          callback(foundAccessories);
        });
    };
    */

    // Get Harmony Activities
    var getActivities = function(hub) {
      self.log("Fetching Logitech Harmony activities...");

      hub.getActivities()
        .then(function (activities) {
          self.log("Found activities: \n" + activities.map(function (a) { return "\t" + a.label; }).join("\n"));

          hub.getCurrentActivity().then(function (currentActivity) {
            var actAccessories = [];
            var sArray = sortByKey(activities, "label");
            sArray.map(function(s) {
              var accessory = new LogitechHarmonyActivityAccessory(self.log, hub, s, self.updateCurrentActivity.bind(self));
              accessory.updateActivityState(currentActivity);
              actAccessories.push(accessory);
              foundAccessories.push(accessory);
            });
            self.activityAccessories = actAccessories;
            callback(foundAccessories);
          }).catch(function (err) {
            self.log('Unable to get current activity with error', err);
            callback(false);
          });
        });
    };
  }
};

function LogitechHarmonyActivityAccessory (log, hub, details, updateCurrentActivity) {
  this.log = log;
  this.hub = hub;
  this.details = details;
  this.id = details.id;
  this.name = details.label;
  this.isOn = false;
  this.updateCurrentActivity = updateCurrentActivity;
  Accessory.call(this, this.name, uuid.generate(this.id));
  var self = this;

  this.getService(Service.AccessoryInformation)
      .setCharacteristic(Characteristic.Manufacturer, "Logitech")
      .setCharacteristic(Characteristic.Model, "Harmony")
      // TODO: Add hub unique id to this for people with multiple hubs so that it is really a guid.
      .setCharacteristic(Characteristic.SerialNumber, this.id);

  this.addService(Service.Switch)
      .getCharacteristic(Characteristic.On)
      .on('get', function(callback) {
        // Refreshed automatically by platform
        callback(null, self.isOn);
      })
      .on('set', this.setPowerState.bind(this));

};
inherits(LogitechHarmonyActivityAccessory, Accessory);
LogitechHarmonyActivityAccessory.prototype.parent = Accessory.prototype;
LogitechHarmonyActivityAccessory.prototype.getServices = function() {
  return this.services;
};

LogitechHarmonyActivityAccessory.prototype.updateActivityState = function (currentActivity) {
  this.isOn = (currentActivity === this.id);
  // Force get to trigger 'change' if needed
  this.getService(Service.Switch)
      .getCharacteristic(Characteristic.On)
      .getValue();
};

LogitechHarmonyActivityAccessory.prototype.setPowerState = function (state, callback) {

  var self = this;

  this.log('Set activity ' + this.name + ' power state to ' + state);

  var nextActivity = self.id;
  this.hub.startActivity(nextActivity)
    .then(function () {
      self.log('Finished setting activity ' + self.name + ' power state to ' + state);
        self.updateCurrentActivity(nextActivity);
        if (callback) callback(null, state);
    })
    .catch(function (err) {
      self.log('Failed setting activity ' + self.name + ' power state to ' + state + ' with error ' + err);
        if (callback) callback(err);
    });
};

module.exports.platform = LogitechHarmonyPlatform;

<|endoftext|>