<commit_before>'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')

function resolve (dir) {
  return path.join(__dirname, '..', dir)
}

const createLintingRule = () => ({
  test: /\.(js|vue)$/,
  loader: 'eslint-loader',
  enforce: 'pre',
  include: [resolve('src'), resolve('test')],
  options: {
    formatter: require('eslint-friendly-formatter'),
    emitWarning: !config.dev.showEslintErrorsInOverlay
  }
})

module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    app: './src/main.js'
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  },
  module: {
    rules: [
      ...(config.dev.useEslint ? [createLintingRule()] : []),
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      }
    ]
  },
  node: {
    // prevent webpack from injecting useless setImmediate polyfill because Vue
    // source contains it (although only uses it if it's native).
    setImmediate: false,
    // prevent webpack from injecting mocks to Node native modules
    // that does not make sense for the client
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty'
  }
}
<commit_msg>Add jquery as a plugin<commit_after>'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
const webpack = require('webpack')

function resolve (dir) {
  return path.join(__dirname, '..', dir)
}

const createLintingRule = () => ({
  test: /\.(js|vue)$/,
  loader: 'eslint-loader',
  enforce: 'pre',
  include: [resolve('src'), resolve('test')],
  options: {
    formatter: require('eslint-friendly-formatter'),
    emitWarning: !config.dev.showEslintErrorsInOverlay
  }
})

module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    app: './src/main.js'
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  },
  module: {
    rules: [
      ...(config.dev.useEslint ? [createLintingRule()] : []),
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      }
    ]
  },
  node: {
    // prevent webpack from injecting useless setImmediate polyfill because Vue
    // source contains it (although only uses it if it's native).
    setImmediate: false,
    // prevent webpack from injecting mocks to Node native modules
    // that does not make sense for the client
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty'
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
      jquery: 'jquery',
      'window.jQuery': 'jquery',
      jQuery: 'jquery'
    })
  ]
}
<|endoftext|>


<commit_before>// import highchartsObj from 'chartObj.js';
// console.log(highchartsObj);

window.SMA = function (candleStickData, MAWindowSize) {
  console.log('Calculating SMA for chart with', MAWindowSize, 'window size.');
  // Calcuating interval between the dates, and the amount of values needed each day
  var interval = candleStickData[1][0] - candleStickData[0][0];
  var entryPerDay = 86400 / interval;
  var MATimeSeries = [];
  var prev = null;
  var avg = 0;
  // Looping through each entry in the candleStickData object
  for (var i = 0; i < candleStickData.length; i++) {
    // Initial set-up of the first SMA average that can be calculated
    if (i == MAWindowSize * entryPerDay - 1) {
      for (var j = 0; j < MAWindowSize * entryPerDay; j++) {
        avg += candleStickData[j][1];
      }
      avg = avg / (MAWindowSize * entryPerDay);
      MATimeSeries.push([candleStickData[i][0], avg]);
      prev = candleStickData[0][1];
    }
    // Each time after the initial set-up, the avg is subtracted by the prev, and is added to the newest value
    if (i > MAWindowSize * entryPerDay - 1) {
      avg = avg - prev / (MAWindowSize * entryPerDay) + candleStickData[i][1] / (MAWindowSize * entryPerDay);
      MATimeSeries.push([candleStickData[i][0], avg]);
      prev = candleStickData[i - (MAWindowSize * entryPerDay - 1)][1];
    }
  }
  return MATimeSeries;
};

/**
 * Creates object literal, given paramaters, and adds it to highchart
 * @param {HighChart} highchart self reference
 * @param {object} params parameters to add to series
 */
var createIndicatorSeries = function (highchart, name, spline) {
  var seriesObj = {};
  seriesObj.name = name;
  seriesObj.id = name;
  seriesObj.lineWidth = 1.25;
  seriesObj.marker = {
    enabled: false,
    radius: 3
  };
  if (spline === true) {
    seriesObj.type = 'spline';
  }
  seriesObj.tooltip = {
    valueDecimals: 5
  };
  highchart.addSeries(seriesObj, true);
};

/**
 * Adds a date and price as a tuple to a targetSeries
 * @param {HighChart.series} targetSeries reference
 * @param {int} date UTC formatted time
 * @param {int} price currency price
 */
const addDataPointToSeries = function (targetSeries, date, price) {
  targetSeries.addPoint([date, price], false);
};

/**
 * Adds data points to a certain series, given a data set (chartData)
 * @param {HighChart.series} targetSeries reference
 * @param {object} chartData
 */
const addTickerDatasetToSeries = function (targetSeries, tickerData) {
  for (let i = 0; i < tickerData.length; i++) {
    const date = tickerData[i][0] * 1000;
    const price = tickerData[i][1];
    // console.log(date, price);
    console.log('adding point...');
    addDataPointToSeries(targetSeries, date, price);
  }
};

/**
 * Creates object literal, given paramaters, and adds it to highchart
 * @param {HighChart} highchart self reference
 * @param {object} params parameters to add to series
 */
const createCandlestickSeries = function (highchart, name) {
  const seriesObj = {};
  seriesObj.name = name;
  seriesObj.id = name;
  seriesObj.data = [];
  seriesObj.marker = {
    enabled: true,
    radius: 2
  };
  seriesObj.tooltip = {
    valueDecimals: 5
  };

  highchart.addSeries(seriesObj, true);
};

/**
 * Connects and listens on two sockets to initialize and then update a chart.
 *     initializedChartData creates a series and adds historical data to it.
 *     updatedChartData listens for live data and adds it to a targetSeries
 * @param {HighChart} highchart self reference
 */
const loadStrategyTrades = function (highchart, chartData) {
  if (!chartData) { return; }
  highchart.showLoading('');

  // // INITALIZE CHART WITH HISTORICAL DATA
  console.log('### initializedChartData received...');
  console.log('### creating series...');

  createCandlestickSeries(highchart, 'Closing Price');
  /* Creating tickerData chart lines */
  const tickerData = chartData;
  console.log(tickerData);
  const targetSeries = highchart.get('Closing Price');
  addTickerDatasetToSeries(targetSeries, tickerData);
  highchart.hideLoading();
  $('.progress').hide();
  highchart.redraw();
};

function createHighChartsObj(ops) {
  let chartTitle; let A; let B; let data;
  // console.log(ops);
  chartTitle = 'Select to cryptocurrencies to view their chart!';
  if (ops) {
    A = ops.A;
    B = ops.B;
    chartTitle = `Historical Prices - ${A}/${B}`;
    data = ops.data;
  }
  return {
    plotOptions: {
      series: {
        dataGrouping: {
          enabled: true,
          groupPixelWidth: 4
        }
      }
    },
    rangeSelector: {
      buttons: [{
        type: 'day',
        count: 14,
        text: '14d'
      }, {
        type: 'month',
        count: 3,
        text: '3m'
      }, {
        type: 'month',
        count: 6,
        text: '6m'
      }, {
        type: 'ytd',
        text: 'YTD'
      }, {
        type: 'year',
        count: 1,
        text: '1y'
      }, {
        type: 'all',
        text: 'All'
      }],
      inputEnabled: false,
      selected: 1
    },
    lang: {
      noData: 'No data to display mann'
    },
    noData: {
      style: {
        fontWeight: 'bold',
        fontSize: '15px',
        color: '#303030'
      }
    },
    title: {
      text: chartTitle
    },
    xAxis: {
      type: 'datetime',
      ordinal: false
    },
    chart: {
      events: {
        load() {
          const self = this;
          loadStrategyTrades(self, data);
        }
      },
    },
    series: []
  };
}

$(document).ready(() => {
  let chartData = null;
  var mainChart = Highcharts.stockChart('hcharts-strategy', createHighChartsObj());
  // var mainChart = $('#hcharts-strategy').highcharts('StockChart', createHighChartsObj());
  // const chartData = null;
  // $('.progress').show();
  $('#chartButton').click(() => {
    $('.progress').show();
    const A = $('#baseCurrency').val();
    const B = $('#tradeCurrency').val();
    console.log(`Loading chart for ${A}_${B}...`);
    $.getJSON(`/data?currencyA=${A}&currencyB=${B}`, (data) => {
      console.log(data);
      const ops = {};
      ops.A = A; ops.B = B; ops.data = data; chartData = data;
      mainChart = Highcharts.stockChart('hcharts-strategy', createHighChartsObj(ops));
    });
  });
  $('#addIndicatorBtn_SMA').click(() => {
    console.log('### Inside addIndicator_SMA');
    const SMAParam = $('#addIndicator_SMA').val();

    // Parsing pattern for csv SMA values
    const pattern = /\s*,\s*/;
    const nameList = SMAParam.split(pattern);

    // Looping through each entered value and adding a SMA series
    for (let i=0; i < nameList.length; i++){
      let SMA = window.SMA(chartData, nameList[i]);
      // Creating a unique id for this indicator
      let id = "SMA - "+ nameList[i]

      // Creating indicator series for selected indicator
      createIndicatorSeries(mainChart, id, true);
      const targetSeries = mainChart.get(id);

      // Adding indicator series to the chart
      addTickerDatasetToSeries(targetSeries, SMA);
    }

    // Redrawing chart after adding indicators
    mainChart.redraw();
  });
  $('#removeIndicator').click(() => {
    // PARAM see which indicator to add
    // PARAM what indicator parameter to use
    const indicator = 'blah';
    const indicParam = 23;
    console.log('hi');
    // console.log(indicator);
    // console.log(indicParam);
    // read time series data
    // create new indicator time series
    // add new time series to highcharts graph
    // redraw chart

  });

});
<commit_msg>linting<commit_after>// import highchartsObj from 'chartObj.js';
// console.log(highchartsObj);

window.SMA = function (candleStickData, MAWindowSize) {
  console.log('Calculating SMA for chart with', MAWindowSize, 'window size.');
  // Calcuating interval between the dates, and the amount of values needed each day
  const interval = candleStickData[1][0] - candleStickData[0][0];
  const entryPerDay = 86400 / interval;
  const MATimeSeries = [];
  let prev = null;
  let avg = 0;
  // Looping through each entry in the candleStickData object
  for (let i = 0; i < candleStickData.length; i++) {
    // Initial set-up of the first SMA average that can be calculated
    if (i === (MAWindowSize * entryPerDay) - 1) {
      for (let j = 0; j < MAWindowSize * entryPerDay; j++) {
        avg += candleStickData[j][1];
      }
      avg /= (MAWindowSize * entryPerDay);
      MATimeSeries.push([candleStickData[i][0], avg]);
      prev = candleStickData[0][1];
    }
    // Each time after the initial set-up, the avg is subtracted by the prev, and is added to the newest value
    if (i > MAWindowSize * entryPerDay - 1) {
      avg = avg - prev / (MAWindowSize * entryPerDay) + candleStickData[i][1] / (MAWindowSize * entryPerDay);
      MATimeSeries.push([candleStickData[i][0], avg]);
      prev = candleStickData[i - (MAWindowSize * entryPerDay - 1)][1];
    }
  }
  return MATimeSeries;
};

/**
 * Creates object literal, given paramaters, and adds it to highchart
 * @param {HighChart} highchart self reference
 * @param {object} params parameters to add to series
 */
const createIndicatorSeries = function (highchart, name, spline) {
  const seriesObj = {};
  seriesObj.name = name;
  seriesObj.id = name;
  seriesObj.lineWidth = 1.25;
  seriesObj.marker = {
    enabled: false,
    radius: 3
  };
  if (spline === true) {
    seriesObj.type = 'spline';
  }
  seriesObj.tooltip = {
    valueDecimals: 5
  };
  highchart.addSeries(seriesObj, true);
};

/**
 * Adds a date and price as a tuple to a targetSeries
 * @param {HighChart.series} targetSeries reference
 * @param {int} date UTC formatted time
 * @param {int} price currency price
 */
const addDataPointToSeries = function (targetSeries, date, price) {
  targetSeries.addPoint([date, price], false);
};

/**
 * Adds data points to a certain series, given a data set (chartData)
 * @param {HighChart.series} targetSeries reference
 * @param {object} chartData
 */
const addTickerDatasetToSeries = function (targetSeries, tickerData) {
  for (let i = 0; i < tickerData.length; i++) {
    const date = tickerData[i][0] * 1000;
    const price = tickerData[i][1];
    // console.log(date, price);
    console.log('adding point...');
    addDataPointToSeries(targetSeries, date, price);
  }
};

/**
 * Creates object literal, given paramaters, and adds it to highchart
 * @param {HighChart} highchart self reference
 * @param {object} params parameters to add to series
 */
const createCandlestickSeries = function (highchart, name) {
  const seriesObj = {};
  seriesObj.name = name;
  seriesObj.id = name;
  seriesObj.data = [];
  seriesObj.marker = {
    enabled: true,
    radius: 2
  };
  seriesObj.tooltip = {
    valueDecimals: 5
  };

  highchart.addSeries(seriesObj, true);
};

/**
 * Connects and listens on two sockets to initialize and then update a chart.
 *     initializedChartData creates a series and adds historical data to it.
 *     updatedChartData listens for live data and adds it to a targetSeries
 * @param {HighChart} highchart self reference
 */
const loadStrategyTrades = function (highchart, chartData) {
  if (!chartData) { return; }
  highchart.showLoading('');

  // // INITALIZE CHART WITH HISTORICAL DATA
  console.log('### initializedChartData received...');
  console.log('### creating series...');

  createCandlestickSeries(highchart, 'Closing Price');
  /* Creating tickerData chart lines */
  const tickerData = chartData;
  console.log(tickerData);
  const targetSeries = highchart.get('Closing Price');
  addTickerDatasetToSeries(targetSeries, tickerData);
  highchart.hideLoading();
  $('.progress').hide();
  highchart.redraw();
};

function createHighChartsObj(ops) {
  let chartTitle; let A; let B; let data;
  // console.log(ops);
  chartTitle = 'Select to cryptocurrencies to view their chart!';
  if (ops) {
    A = ops.A;
    B = ops.B;
    chartTitle = `Historical Prices - ${A}/${B}`;
    data = ops.data;
  }
  return {
    plotOptions: {
      series: {
        dataGrouping: {
          enabled: true,
          groupPixelWidth: 4
        }
      }
    },
    rangeSelector: {
      buttons: [{
        type: 'day',
        count: 14,
        text: '14d'
      }, {
        type: 'month',
        count: 3,
        text: '3m'
      }, {
        type: 'month',
        count: 6,
        text: '6m'
      }, {
        type: 'ytd',
        text: 'YTD'
      }, {
        type: 'year',
        count: 1,
        text: '1y'
      }, {
        type: 'all',
        text: 'All'
      }],
      inputEnabled: false,
      selected: 1
    },
    lang: {
      noData: 'No data to display mann'
    },
    noData: {
      style: {
        fontWeight: 'bold',
        fontSize: '15px',
        color: '#303030'
      }
    },
    title: {
      text: chartTitle
    },
    xAxis: {
      type: 'datetime',
      ordinal: false
    },
    chart: {
      events: {
        load() {
          const self = this;
          loadStrategyTrades(self, data);
        }
      },
    },
    series: []
  };
}

$(document).ready(() => {
  let chartData = null;
  let mainChart = Highcharts.stockChart('hcharts-strategy', createHighChartsObj());
  // var mainChart = $('#hcharts-strategy').highcharts('StockChart', createHighChartsObj());
  // const chartData = null;
  // $('.progress').show();
  $('#chartButton').click(() => {
    $('.progress').show();
    const A = $('#baseCurrency').val();
    const B = $('#tradeCurrency').val();
    console.log(`Loading chart for ${A}_${B}...`);
    $.getJSON(`/data?currencyA=${A}&currencyB=${B}`, (data) => {
      console.log(data);
      const ops = {};
      ops.A = A; ops.B = B; ops.data = data; chartData = data;
      mainChart = Highcharts.stockChart('hcharts-strategy', createHighChartsObj(ops));
    });
  });
  $('#addIndicatorBtn_SMA').click(() => {
    console.log('### Inside addIndicator_SMA');
    const SMAParam = $('#addIndicator_SMA').val();

    // Parsing pattern for csv SMA values
    const pattern = /\s*,\s*/;
    const nameList = SMAParam.split(pattern);

    // Looping through each entered value and adding a SMA series
    for (let i=0; i < nameList.length; i++){
      const SMA = window.SMA(chartData, nameList[i]);
      // Creating a unique id for this indicator
      const id = "SMA - "+ nameList[i]

      // Creating indicator series for selected indicator
      createIndicatorSeries(mainChart, id, true);
      const targetSeries = mainChart.get(id);

      // Adding indicator series to the chart
      addTickerDatasetToSeries(targetSeries, SMA);
    }

    // Redrawing chart after adding indicators
    mainChart.redraw();
  });
  $('#removeIndicator').click(() => {
    // PARAM see which indicator to add
    // PARAM what indicator parameter to use
    const indicator = 'blah';
    const indicParam = 23;
    console.log('hi');
    // console.log(indicator);
    // console.log(indicParam);
    // read time series data
    // create new indicator time series
    // add new time series to highcharts graph
    // redraw chart

  });

});
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, describe, beforeEach, afterEach, it, runs, waits, waitsFor, waitsForDone, expect, $  */

define(function (require, exports, module) {
    "use strict";

    var Async = require("utils/Async"),
        PromiseQueue = Async.PromiseQueue;

    describe("Async", function () {

        describe("Chain", function () {

            function zeroArgThatSucceeds() {
                var d = $.Deferred();
                setTimeout(function () {
                    d.resolve();
                }, 1);
                return d.promise();
            }

            function zeroArgThatFails() {
                var d = $.Deferred();
                setTimeout(function () {
                    d.reject();
                }, 1);
                return d.promise();
            }

            function oneArgThatSucceeds(x) {
                var d = $.Deferred();
                setTimeout(function () {
                    d.resolveWith(null, [x]);
                }, 1);
                return d.promise();
            }

            function twoArgThatSucceeds(x, y) {
                var d = $.Deferred();
                setTimeout(function () {
                    d.resolveWith(null, [x, y]);
                }, 1);
                return d.promise();
            }

            function twoArgThatFails(x, y) {
                var d = $.Deferred();
                setTimeout(function () {
                    d.rejectWith(null, [x, y]);
                }, 1);
                return d.promise();
            }

            function syncAddTwoArg(x, y) {
                return x + y;
            }

            function syncException() {
                throw new Error("sync error");
            }

            function createArrayComparator(arrayOne) {
                return function (arrayTwo) {
                    var i, l;
                    expect(arrayOne.length).toBe(arrayTwo.length);
                    l = Math.min(arrayOne.length, arrayTwo.length);
                    for (i = 0; i < l; i++) {
                        expect(arrayOne[i]).toBe(arrayTwo[i]);
                    }
                };
            }

            function expectChainHelper(functions, args, shouldSucceed, responseComparator) {
                var done = false;
                var success = false;
                var response = null;
                runs(function () {
                    var result = Async.chain(
                        functions,
                        args
                    );
                    result.done(function () {
                        done = true;
                        success = true;
                        response = arguments;
                    });
                    result.fail(function () {
                        done = true;
                        success = false;
                        response = arguments;
                    });
                });
                waitsFor(function () {
                    return done;
                }, "The chain should complete", 100);
                runs(function () {
                    expect(success).toBe(shouldSucceed);
                    responseComparator(response);
                });
            }

            describe("Zero-argument deferreds", function () {
                it("[zero-arg] work with a null argument array", function () {
                    expectChainHelper(
                        [zeroArgThatSucceeds, zeroArgThatSucceeds, zeroArgThatSucceeds],
                        null,
                        true,
                        createArrayComparator([])
                    );
                });

                it("[zero-arg] call error callback when first deferred fails", function () {
                    expectChainHelper(
                        [zeroArgThatFails, zeroArgThatSucceeds, zeroArgThatSucceeds],
                        [],
                        false,
                        createArrayComparator([])
                    );
                });

                it("[zero-arg] call error callback when middle deferred fails", function () {
                    expectChainHelper(
                        [zeroArgThatSucceeds, zeroArgThatFails, zeroArgThatSucceeds],
                        [],
                        false,
                        createArrayComparator([])
                    );
                });

                it("[zero-arg] call error callback when last deferred fails", function () {
                    expectChainHelper(
                        [zeroArgThatSucceeds, zeroArgThatSucceeds, zeroArgThatFails],
                        [],
                        false,
                        createArrayComparator([])
                    );
                });

                it("[zero-arg] call success callback when all deferreds succeed", function () {
                    expectChainHelper(
                        [zeroArgThatSucceeds, zeroArgThatSucceeds, zeroArgThatSucceeds],
                        [],
                        true,
                        createArrayComparator([])
                    );
                });

                it("[zero-arg] call success callback immediately if there are no deferreds", function () {
                    expectChainHelper(
                        [],
                        [],
                        true,
                        createArrayComparator([])
                    );
                });
            });

            describe("Nonzero-argument deferreds", function () {
                it("[nonzero-arg] call error callback when first deferred fails", function () {
                    expectChainHelper(
                        [twoArgThatFails, twoArgThatSucceeds, twoArgThatSucceeds],
                        [1, 2],
                        false,
                        createArrayComparator([1, 2])
                    );
                });

                it("[nonzero-arg] call error callback when middle deferred fails", function () {
                    expectChainHelper(
                        [twoArgThatSucceeds, twoArgThatFails, twoArgThatSucceeds],
                        [1, 2],
                        false,
                        createArrayComparator([1, 2])
                    );
                });

                it("[nonzero-arg] call error callback when last deferred fails", function () {
                    expectChainHelper(
                        [twoArgThatSucceeds, twoArgThatSucceeds, twoArgThatFails],
                        [1, 2],
                        false,
                        createArrayComparator([1, 2])
                    );
                });

                it("[nonzero-arg] call success callback when all deferreds succeed", function () {
                    expectChainHelper(
                        [twoArgThatSucceeds, twoArgThatSucceeds, twoArgThatSucceeds],
                        [1, 2],
                        true,
                        createArrayComparator([1, 2])
                    );
                });

                it("[nonzero-arg] call success callback immediately if there are no deferreds", function () {
                    expectChainHelper(
                        [],
                        [1, 2],
                        true,
                        createArrayComparator([1, 2])
                    );
                });
            });

            describe("Async/sync mix", function () {
                it("[async/sync] succeed with sync command at beginning", function () {
                    expectChainHelper(
                        [syncAddTwoArg, oneArgThatSucceeds, oneArgThatSucceeds],
                        [1, 2],
                        true,
                        createArrayComparator([3])
                    );
                });

                it("[async/sync] succeed with sync command at middle", function () {
                    expectChainHelper(
                        [twoArgThatSucceeds, syncAddTwoArg, oneArgThatSucceeds],
                        [1, 2],
                        true,
                        createArrayComparator([3])
                    );
                });

                it("[async/sync] succeed with sync command at end", function () {
                    expectChainHelper(
                        [twoArgThatSucceeds, twoArgThatSucceeds, syncAddTwoArg],
                        [1, 2],
                        true,
                        createArrayComparator([3])
                    );
                });

                it("[async/sync] call error callback if sync command fails", function () {
                    expectChainHelper(
                        [twoArgThatSucceeds, syncException, twoArgThatSucceeds],
                        [1, 2],
                        false,
                        function (response) {
                            expect(response.length).toBe(1);
                            expect(response[0] instanceof Error).toBe(true);
                        }
                    );
                });

            });

        });

        describe("Async PromiseQueue", function () {
            var queue, calledFns;

            beforeEach(function () {
                queue = new PromiseQueue();
                calledFns = {};
            });

            function makeFn(id, resolveNow) {
                var result = new $.Deferred();
                return {
                    fn: function () {
                        calledFns[id] = true;
                        if (resolveNow) {
                            result.resolve();
                        }
                        return result.promise();
                    },
                    deferred: result
                };
            }

            it("should immediately execute a function when the queue is empty", function () {
                var fnInfo = makeFn("one");

                queue.add(fnInfo.fn);
                expect(calledFns.one).toBe(true);

                fnInfo.deferred.resolve();
                expect(queue._queue.length).toBe(0);
                expect(queue._curPromise).toBe(null);
            });

            it("should wait to execute the second added function", function () {
                var fnInfo1 = makeFn("one"),
                    fnInfo2 = makeFn("two");

                queue.add(fnInfo1.fn);
                expect(calledFns.one).toBe(true);

                queue.add(fnInfo2.fn);
                expect(calledFns.two).toBeUndefined();

                fnInfo1.deferred.resolve();
                expect(calledFns.two).toBe(true);

                fnInfo2.deferred.resolve();
                expect(queue._queue.length).toBe(0);
                expect(queue._curPromise).toBe(null);
            });

            it("should properly handle the case where the first function completes synchronously", function () {
                var fnInfo1 = makeFn("one", true),
                    fnInfo2 = makeFn("two");

                queue.add(fnInfo1.fn);
                expect(calledFns.one).toBe(true);

                queue.add(fnInfo2.fn);
                expect(calledFns.two).toBe(true);

                fnInfo2.deferred.resolve();
                expect(queue._queue.length).toBe(0);
                expect(queue._curPromise).toBe(null);
            });

            it("should sequentially execute a second and third function if they're both added while the first is executing", function () {
                var fnInfo1 = makeFn("one"),
                    fnInfo2 = makeFn("two"),
                    fnInfo3 = makeFn("three");

                queue.add(fnInfo1.fn);
                expect(calledFns.one).toBe(true);

                queue.add(fnInfo2.fn);
                queue.add(fnInfo3.fn);
                expect(calledFns.two).toBeUndefined();
                expect(calledFns.three).toBeUndefined();

                fnInfo1.deferred.resolve();
                expect(calledFns.two).toBe(true);
                expect(calledFns.three).toBeUndefined();

                fnInfo2.deferred.resolve();
                expect(calledFns.three).toBe(true);

                fnInfo3.deferred.resolve();
                expect(queue._queue.length).toBe(0);
                expect(queue._curPromise).toBe(null);
            });

            it("should sequentially execute a second and third function if the third is added while the second is executing", function () {
                var fnInfo1 = makeFn("one"),
                    fnInfo2 = makeFn("two"),
                    fnInfo3 = makeFn("three");

                queue.add(fnInfo1.fn);
                expect(calledFns.one).toBe(true);

                queue.add(fnInfo2.fn);
                expect(calledFns.two).toBeUndefined();

                fnInfo1.deferred.resolve();
                expect(calledFns.two).toBe(true);

                queue.add(fnInfo3.fn);
                expect(calledFns.three).toBeUndefined();

                fnInfo2.deferred.resolve();
                expect(calledFns.three).toBe(true);

                fnInfo3.deferred.resolve();
                expect(queue._queue.length).toBe(0);
                expect(queue._curPromise).toBe(null);
            });

            it("should execute a second function when added to the empty queue after the first function has completed", function () {
                var fnInfo1 = makeFn("one"),
                    fnInfo2 = makeFn("two");

                queue.add(fnInfo1.fn);
                expect(calledFns.one).toBe(true);

                fnInfo1.deferred.resolve();
                expect(queue._queue.length).toBe(0);
                expect(queue._curPromise).toBe(null);

                queue.add(fnInfo2.fn);
                expect(calledFns.two).toBe(true);

                fnInfo2.deferred.resolve();
                expect(queue._queue.length).toBe(0);
                expect(queue._curPromise).toBe(null);
            });
        });
    });
});<commit_msg>add unit test for Async.chain that ensures two sync functions are executed synchronously<commit_after>/*
 * Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, describe, beforeEach, afterEach, it, runs, waits, waitsFor, waitsForDone, expect, $  */

define(function (require, exports, module) {
    "use strict";

    var Async = require("utils/Async"),
        PromiseQueue = Async.PromiseQueue;

    describe("Async", function () {

        describe("Chain", function () {

            function zeroArgThatSucceeds() {
                var d = $.Deferred();
                setTimeout(function () {
                    d.resolve();
                }, 1);
                return d.promise();
            }

            function zeroArgThatFails() {
                var d = $.Deferred();
                setTimeout(function () {
                    d.reject();
                }, 1);
                return d.promise();
            }

            function oneArgThatSucceeds(x) {
                var d = $.Deferred();
                setTimeout(function () {
                    d.resolveWith(null, [x]);
                }, 1);
                return d.promise();
            }

            function twoArgThatSucceeds(x, y) {
                var d = $.Deferred();
                setTimeout(function () {
                    d.resolveWith(null, [x, y]);
                }, 1);
                return d.promise();
            }

            function twoArgThatFails(x, y) {
                var d = $.Deferred();
                setTimeout(function () {
                    d.rejectWith(null, [x, y]);
                }, 1);
                return d.promise();
            }

            function syncAddTwoArg(x, y) {
                return x + y;
            }

            function syncException() {
                throw new Error("sync error");
            }

            function createArrayComparator(arrayOne) {
                return function (arrayTwo) {
                    var i, l;
                    expect(arrayOne.length).toBe(arrayTwo.length);
                    l = Math.min(arrayOne.length, arrayTwo.length);
                    for (i = 0; i < l; i++) {
                        expect(arrayOne[i]).toBe(arrayTwo[i]);
                    }
                };
            }

            function expectChainHelper(functions, args, shouldSucceed, responseComparator) {
                var done = false;
                var success = false;
                var response = null;
                runs(function () {
                    var result = Async.chain(
                        functions,
                        args
                    );
                    result.done(function () {
                        done = true;
                        success = true;
                        response = arguments;
                    });
                    result.fail(function () {
                        done = true;
                        success = false;
                        response = arguments;
                    });
                });
                waitsFor(function () {
                    return done;
                }, "The chain should complete", 100);
                runs(function () {
                    expect(success).toBe(shouldSucceed);
                    responseComparator(response);
                });
            }

            describe("Zero-argument deferreds", function () {
                it("[zero-arg] work with a null argument array", function () {
                    expectChainHelper(
                        [zeroArgThatSucceeds, zeroArgThatSucceeds, zeroArgThatSucceeds],
                        null,
                        true,
                        createArrayComparator([])
                    );
                });

                it("[zero-arg] call error callback when first deferred fails", function () {
                    expectChainHelper(
                        [zeroArgThatFails, zeroArgThatSucceeds, zeroArgThatSucceeds],
                        [],
                        false,
                        createArrayComparator([])
                    );
                });

                it("[zero-arg] call error callback when middle deferred fails", function () {
                    expectChainHelper(
                        [zeroArgThatSucceeds, zeroArgThatFails, zeroArgThatSucceeds],
                        [],
                        false,
                        createArrayComparator([])
                    );
                });

                it("[zero-arg] call error callback when last deferred fails", function () {
                    expectChainHelper(
                        [zeroArgThatSucceeds, zeroArgThatSucceeds, zeroArgThatFails],
                        [],
                        false,
                        createArrayComparator([])
                    );
                });

                it("[zero-arg] call success callback when all deferreds succeed", function () {
                    expectChainHelper(
                        [zeroArgThatSucceeds, zeroArgThatSucceeds, zeroArgThatSucceeds],
                        [],
                        true,
                        createArrayComparator([])
                    );
                });

                it("[zero-arg] call success callback immediately if there are no deferreds", function () {
                    expectChainHelper(
                        [],
                        [],
                        true,
                        createArrayComparator([])
                    );
                });
            });

            describe("Nonzero-argument deferreds", function () {
                it("[nonzero-arg] call error callback when first deferred fails", function () {
                    expectChainHelper(
                        [twoArgThatFails, twoArgThatSucceeds, twoArgThatSucceeds],
                        [1, 2],
                        false,
                        createArrayComparator([1, 2])
                    );
                });

                it("[nonzero-arg] call error callback when middle deferred fails", function () {
                    expectChainHelper(
                        [twoArgThatSucceeds, twoArgThatFails, twoArgThatSucceeds],
                        [1, 2],
                        false,
                        createArrayComparator([1, 2])
                    );
                });

                it("[nonzero-arg] call error callback when last deferred fails", function () {
                    expectChainHelper(
                        [twoArgThatSucceeds, twoArgThatSucceeds, twoArgThatFails],
                        [1, 2],
                        false,
                        createArrayComparator([1, 2])
                    );
                });

                it("[nonzero-arg] call success callback when all deferreds succeed", function () {
                    expectChainHelper(
                        [twoArgThatSucceeds, twoArgThatSucceeds, twoArgThatSucceeds],
                        [1, 2],
                        true,
                        createArrayComparator([1, 2])
                    );
                });

                it("[nonzero-arg] call success callback immediately if there are no deferreds", function () {
                    expectChainHelper(
                        [],
                        [1, 2],
                        true,
                        createArrayComparator([1, 2])
                    );
                });
            });

            describe("Async/sync mix", function () {
                it("[async/sync] succeed with sync command at beginning", function () {
                    expectChainHelper(
                        [syncAddTwoArg, oneArgThatSucceeds, oneArgThatSucceeds],
                        [1, 2],
                        true,
                        createArrayComparator([3])
                    );
                });

                it("[async/sync] succeed with sync command at middle", function () {
                    expectChainHelper(
                        [twoArgThatSucceeds, syncAddTwoArg, oneArgThatSucceeds],
                        [1, 2],
                        true,
                        createArrayComparator([3])
                    );
                });

                it("[async/sync] succeed with sync command at end", function () {
                    expectChainHelper(
                        [twoArgThatSucceeds, twoArgThatSucceeds, syncAddTwoArg],
                        [1, 2],
                        true,
                        createArrayComparator([3])
                    );
                });

                it("[async/sync] call error callback if sync command fails", function () {
                    expectChainHelper(
                        [twoArgThatSucceeds, syncException, twoArgThatSucceeds],
                        [1, 2],
                        false,
                        function (response) {
                            expect(response.length).toBe(1);
                            expect(response[0] instanceof Error).toBe(true);
                        }
                    );
                });

                it("[async/sync] two sync commands in order are executed completely synchronously", function () {
                    var promise = null,
                        done = false,
                        success = false,
                        result = null,
                        flag = true;

                    runs(function () {

                        function negate(b) {
                            return !b;
                        }
                        function setFlag(b) {
                            flag = b;
                            return flag;
                        }

                        promise = Async.chain([negate, setFlag], [flag]);
                        promise.done(function (b) {
                            done = true;
                            success = true;
                            result = b;
                        });
                        promise.fail(function () {
                            done = true;
                            success = false;
                        });

                        // note, we WANT to test this synchronously. This is not a bug
                        // in the unit test. A series of synchronous functions should
                        // execute synchronously.
                        expect(flag).toBe(false);
                    });

                    // With (the current version) of jQuery promises, resolution and
                    // resolution handlers will get called synchronously. However, if we
                    // move to a different promise implementation (e.g. Q) then resolution
                    // handlers will get called asynchronously. So, we check completion
                    // of the promise on a separate pass.
                    waitsFor(function () { return done; }, "The chain to complete");

                    runs(function () {
                        expect(done).toBe(true);
                        expect(success).toBe(true);
                        expect(result).toBe(flag);
                    });

                });

            });

        });

        describe("Async PromiseQueue", function () {
            var queue, calledFns;

            beforeEach(function () {
                queue = new PromiseQueue();
                calledFns = {};
            });

            function makeFn(id, resolveNow) {
                var result = new $.Deferred();
                return {
                    fn: function () {
                        calledFns[id] = true;
                        if (resolveNow) {
                            result.resolve();
                        }
                        return result.promise();
                    },
                    deferred: result
                };
            }

            it("should immediately execute a function when the queue is empty", function () {
                var fnInfo = makeFn("one");

                queue.add(fnInfo.fn);
                expect(calledFns.one).toBe(true);

                fnInfo.deferred.resolve();
                expect(queue._queue.length).toBe(0);
                expect(queue._curPromise).toBe(null);
            });

            it("should wait to execute the second added function", function () {
                var fnInfo1 = makeFn("one"),
                    fnInfo2 = makeFn("two");

                queue.add(fnInfo1.fn);
                expect(calledFns.one).toBe(true);

                queue.add(fnInfo2.fn);
                expect(calledFns.two).toBeUndefined();

                fnInfo1.deferred.resolve();
                expect(calledFns.two).toBe(true);

                fnInfo2.deferred.resolve();
                expect(queue._queue.length).toBe(0);
                expect(queue._curPromise).toBe(null);
            });

            it("should properly handle the case where the first function completes synchronously", function () {
                var fnInfo1 = makeFn("one", true),
                    fnInfo2 = makeFn("two");

                queue.add(fnInfo1.fn);
                expect(calledFns.one).toBe(true);

                queue.add(fnInfo2.fn);
                expect(calledFns.two).toBe(true);

                fnInfo2.deferred.resolve();
                expect(queue._queue.length).toBe(0);
                expect(queue._curPromise).toBe(null);
            });

            it("should sequentially execute a second and third function if they're both added while the first is executing", function () {
                var fnInfo1 = makeFn("one"),
                    fnInfo2 = makeFn("two"),
                    fnInfo3 = makeFn("three");

                queue.add(fnInfo1.fn);
                expect(calledFns.one).toBe(true);

                queue.add(fnInfo2.fn);
                queue.add(fnInfo3.fn);
                expect(calledFns.two).toBeUndefined();
                expect(calledFns.three).toBeUndefined();

                fnInfo1.deferred.resolve();
                expect(calledFns.two).toBe(true);
                expect(calledFns.three).toBeUndefined();

                fnInfo2.deferred.resolve();
                expect(calledFns.three).toBe(true);

                fnInfo3.deferred.resolve();
                expect(queue._queue.length).toBe(0);
                expect(queue._curPromise).toBe(null);
            });

            it("should sequentially execute a second and third function if the third is added while the second is executing", function () {
                var fnInfo1 = makeFn("one"),
                    fnInfo2 = makeFn("two"),
                    fnInfo3 = makeFn("three");

                queue.add(fnInfo1.fn);
                expect(calledFns.one).toBe(true);

                queue.add(fnInfo2.fn);
                expect(calledFns.two).toBeUndefined();

                fnInfo1.deferred.resolve();
                expect(calledFns.two).toBe(true);

                queue.add(fnInfo3.fn);
                expect(calledFns.three).toBeUndefined();

                fnInfo2.deferred.resolve();
                expect(calledFns.three).toBe(true);

                fnInfo3.deferred.resolve();
                expect(queue._queue.length).toBe(0);
                expect(queue._curPromise).toBe(null);
            });

            it("should execute a second function when added to the empty queue after the first function has completed", function () {
                var fnInfo1 = makeFn("one"),
                    fnInfo2 = makeFn("two");

                queue.add(fnInfo1.fn);
                expect(calledFns.one).toBe(true);

                fnInfo1.deferred.resolve();
                expect(queue._queue.length).toBe(0);
                expect(queue._curPromise).toBe(null);

                queue.add(fnInfo2.fn);
                expect(calledFns.two).toBe(true);

                fnInfo2.deferred.resolve();
                expect(queue._queue.length).toBe(0);
                expect(queue._curPromise).toBe(null);
            });
        });
    });
});<|endoftext|>


<commit_before>let parts = staticData.iouri.split(':');
if (parts.length > 1) staticData.iouri = parts.iouri[parts.length - 2];
let socket = io.connect(staticData.iouri);

let ageValues = [];
for (let i = staticData.minAge; i < staticData.maxAge; i++) ageValues.push(i);

let app = new Vue({
	el: '#app',
	delimiters: [ ':[', ']' ],
	data: {
		page: staticData.defaultPage,
		lang: staticData.defaultLang,
		ageValues,
		searchStatus: null,
		endReason: null,
		externalTyping: false,
		usersOnline: 0,
		down_strangerGender: true,
		internalGender: null,
		internalAge: '-',
		internalLocation: '',
		externalMaleInclude: true,
		externalFemaleInclude: true,
		externalAgeFrom: '-',
		externalAgeTo: '-',
		externalLocation: '',
		messages: [],
	},
	methods: {
		dumpPrefs: function () {
			return {
				internalGender: this.internalGender,
				internalAge: this.internalAge,
				internalLocation: this.internalLocation,
				externalMaleInclude: this.externalMaleInclude,
				externalFemaleInclude: this.externalFemaleInclude,
				externalAgeFrom: this.externalAgeFrom,
				externalAgeTo: this.externalAgeTo,
				externalLocation: this.externalLocation,
			};
		},
		switchPage: function (page) {
			this.page = page;
		},
		switchLang: function (ev) {
			let lang = ev.target.selectedOptions[0].value.toLowerCase();
			this.lang = lang;
			this.updateTitle();
		},
		updateTitle: function () {
			document.title = staticData.title[this.lang];
		},
		clickInactive: function (ev, inactiveController) {
			if (this[inactiveController]) {
				ev.preventDefault();
				ev.stopPropagation();
			};
		},
		chooseInternalGender: function (gender) {
			this.down_strangerGender = gender ? false : true;
			this.internalGender = gender;
		},
		chooseInitialAge: function () {
			this.internalAge = '-';
		},
		chooseInitialLocation: function () {
			this.internalLocation = '';
		},
		connect: function () {
			let query = this.dumpPrefs();
			socket.emit('begin_looking', query);
			this.searchStatus = 'looking';
			this.switchPage('chat');
		},
		sendMessage: function () {
			let boxEl = document.getElementById('inputMessageBox');
			let message = boxEl.value;
			if ((message.length < 1) || (message.length > staticData.messageMaxLen)) return false;
			socket.emit('user_message', message);
			let time = new Date();
			let stamp = time.toLocaleTimeString();
			this.messages.push({
				internal: true,
				timestamp: stamp,
				text: message,
			});
			boxEl.value = '';
			boxEl.focus();
		},
		endChatInternal: function () {
			this.searchStatus = 'end';
			this.endReason = 'internal';
			socket.emit('stop_chat');
		},
		continueSearch: function () {
			this.switchPage('dummy');
			this.messages.splice(0, this.messages.length);
			this.searchStatus = null;
			this.endReason = null;
			let query = this.dumpPrefs();
			socket.emit('begin_looking', query);
			this.searchStatus = 'looking';
			this.switchPage('chat');
		},
		changePrefs: function () {
			this.messages.splice(0, this.messages.length);
			this.searchStatus = null;
			this.endReason = null;
			this.switchPage('welcome');
		},
	},
	created: function () {
		this.updateTitle();
	},
});

socket.on('user_message', (message) => {
	let time = new Date();
	let stamp = time.toLocaleTimeString();
	app.messages.push({
		internal: false,
		timestamp: stamp,
		text: message,
	});
});
socket.on('stop_chat_request', () => {
	socket.emit('stop_chat_response', () => {
		app.searchStatus = 'end';
		app.endReason = 'external';
	});
});
socket.on('match_found', () => {
	app.searchStatus = 'found';
});
socket.once('user_connected', () => {
//	console.log('user_connected');
});
socket.on('user_began_lookup', () => {
//	console.log('user_began_lookup');
});
socket.on('onlineUpdate', (data) => {
//	console.log(`onlineUpdate: ${data}`);
	app.usersOnline = data;
});<commit_msg>heroku working<commit_after>let parts = staticData.iouri.split(':');
if (parts.length > 1) staticData.iouri = parts[parts.length - 2];
let socket = io.connect(staticData.iouri);

let ageValues = [];
for (let i = staticData.minAge; i < staticData.maxAge; i++) ageValues.push(i);

let app = new Vue({
	el: '#app',
	delimiters: [ ':[', ']' ],
	data: {
		page: staticData.defaultPage,
		lang: staticData.defaultLang,
		ageValues,
		searchStatus: null,
		endReason: null,
		externalTyping: false,
		usersOnline: 0,
		down_strangerGender: true,
		internalGender: null,
		internalAge: '-',
		internalLocation: '',
		externalMaleInclude: true,
		externalFemaleInclude: true,
		externalAgeFrom: '-',
		externalAgeTo: '-',
		externalLocation: '',
		messages: [],
	},
	methods: {
		dumpPrefs: function () {
			return {
				internalGender: this.internalGender,
				internalAge: this.internalAge,
				internalLocation: this.internalLocation,
				externalMaleInclude: this.externalMaleInclude,
				externalFemaleInclude: this.externalFemaleInclude,
				externalAgeFrom: this.externalAgeFrom,
				externalAgeTo: this.externalAgeTo,
				externalLocation: this.externalLocation,
			};
		},
		switchPage: function (page) {
			this.page = page;
		},
		switchLang: function (ev) {
			let lang = ev.target.selectedOptions[0].value.toLowerCase();
			this.lang = lang;
			this.updateTitle();
		},
		updateTitle: function () {
			document.title = staticData.title[this.lang];
		},
		clickInactive: function (ev, inactiveController) {
			if (this[inactiveController]) {
				ev.preventDefault();
				ev.stopPropagation();
			};
		},
		chooseInternalGender: function (gender) {
			this.down_strangerGender = gender ? false : true;
			this.internalGender = gender;
		},
		chooseInitialAge: function () {
			this.internalAge = '-';
		},
		chooseInitialLocation: function () {
			this.internalLocation = '';
		},
		connect: function () {
			let query = this.dumpPrefs();
			socket.emit('begin_looking', query);
			this.searchStatus = 'looking';
			this.switchPage('chat');
		},
		sendMessage: function () {
			let boxEl = document.getElementById('inputMessageBox');
			let message = boxEl.value;
			if ((message.length < 1) || (message.length > staticData.messageMaxLen)) return false;
			socket.emit('user_message', message);
			let time = new Date();
			let stamp = time.toLocaleTimeString();
			this.messages.push({
				internal: true,
				timestamp: stamp,
				text: message,
			});
			boxEl.value = '';
			boxEl.focus();
		},
		endChatInternal: function () {
			this.searchStatus = 'end';
			this.endReason = 'internal';
			socket.emit('stop_chat');
		},
		continueSearch: function () {
			this.switchPage('dummy');
			this.messages.splice(0, this.messages.length);
			this.searchStatus = null;
			this.endReason = null;
			let query = this.dumpPrefs();
			socket.emit('begin_looking', query);
			this.searchStatus = 'looking';
			this.switchPage('chat');
		},
		changePrefs: function () {
			this.messages.splice(0, this.messages.length);
			this.searchStatus = null;
			this.endReason = null;
			this.switchPage('welcome');
		},
	},
	created: function () {
		this.updateTitle();
	},
});

socket.on('user_message', (message) => {
	let time = new Date();
	let stamp = time.toLocaleTimeString();
	app.messages.push({
		internal: false,
		timestamp: stamp,
		text: message,
	});
});
socket.on('stop_chat_request', () => {
	socket.emit('stop_chat_response', () => {
		app.searchStatus = 'end';
		app.endReason = 'external';
	});
});
socket.on('match_found', () => {
	app.searchStatus = 'found';
});
socket.once('user_connected', () => {
//	console.log('user_connected');
});
socket.on('user_began_lookup', () => {
//	console.log('user_began_lookup');
});
socket.on('onlineUpdate', (data) => {
//	console.log(`onlineUpdate: ${data}`);
	app.usersOnline = data;
});<|endoftext|>


<commit_before>var gMap;
function onGoogleMapsResponse() {
  var gLatLng = new window.google.maps.LatLng(37.760516, -122.413126);
  gMap = new window.google.maps.Map(document.getElementById('map'), {
    center: gLatLng,
    zoom: 13
  });
  var gMarker = new window.google.maps.Marker({
      draggable: true,
      map: gMap,
      position: gLatLng,
      title: 'Pickup Location'
  });
};
<commit_msg>added automatic geolocation<commit_after>var xhr = new XMLHttpRequest();
var gMap;
var gMarkerBegin;
var gMarkerEnd;

function getCurrentPosition(successCallback, failureCallback) {
  if (window.navigator.geolocation) {
    window.navigator.geolocation.getCurrentPosition(successCallback, failureCallback);
    return true;
  } else {
    return false;
  }
}

function initializeMap(lat, lng, element) {
  var gLatLng = new window.google.maps.LatLng(lat, lng);
  return new window.google.maps.Map(element, {
    center: gLatLng,
    zoom: 13
  });
}

function initializeMarker(lat, lng, map, label, title) {
  var gLatLng = new window.google.maps.LatLng(lat, lng);
  return new window.google.maps.Marker({
    draggable: true,
    label: label,
    map: map,
    position: gLatLng,
    title: title
  });
}

function onGoogleMapsResponse() {
  /* attempt automatic geolocation */
  getCurrentPosition(
    /* use detected location */
    function success(result) {
      gMap = initializeMap(result.coords.latitude, result.coords.longitude, window.document.getElementById('map'));
      gMarkerBegin = initializeMarker(result.coords.latitude, result.coords.longitude, gMap, 'A', 'Pick Up Location');
    },
    /* use default location */
    function failure() {
      gMap = initializeMap(37.760516, -122.413126, window.document.getElementById('map'));
      gMarkerBegin = initializeMarker(37.760516, -122.413126, gMap, 'A', 'Pick Up Location');
    }
  );
}
<|endoftext|>


<commit_before>(function (fluid, jqUnit) {
    "use strict";

    fluid.registerNamespace("sisiliano.tests.piano");

    jqUnit.test("Piano : basics of piano", function () {
        $(".test").empty();
        var piano = sisiliano.piano(".test");
        sisiliano.tests.piano.verifyPressedColor(piano, "#4CAF50");
        sisiliano.tests.piano.verifyActiveArea(piano, 0, 18);
        sisiliano.tests.piano.verifyLength(piano, 36);
    });

    jqUnit.test("Piano : Custimizations of piano", function () {
        $(".test").empty();
        var piano = sisiliano.piano(".test", {
            model: {
                color: "#FF0000",
                activeArea: {
                    start: 3,
                    end: 9
                },
                keyBoard: {
                    length: 20
                }
            }
        });
        sisiliano.tests.piano.verifyPressedColor(piano, "#FF0000");
        sisiliano.tests.piano.verifyActiveArea(piano, 5, 16);
        sisiliano.tests.piano.verifyLength(piano, 20);
    });

    sisiliano.tests.piano.verifyPressedColor = function (piano, expectedColor) {
        d3.select(piano.container.get(0)).selectAll(".sisiliano-piano-key").each(function () {
            var key = d3.select(this);
            var className = key.attr("class");
            key.attr("class", className + " sisiliano-piano-key-pressed");
            var fillColorWhenPressed = key.style("fill");
            jqUnit.assertEquals("color should be #4CAF50 - " + className, expectedColor, sisiliano.tests.helpers.toHex(fillColorWhenPressed));
            key.attr("class", className);
        });
    };

    sisiliano.tests.piano.verifyActiveArea = function (piano, expectedStart, expectedEnd) {
        d3.select(piano.container.get(0)).selectAll(".sisiliano-piano-key").each(function () {
            var key = d3.select(this);
            var className = key.attr("class");
            var index = parseInt(key.attr("index"), null);
            if (index >= expectedStart && index <= expectedEnd) {
                jqUnit.assertTrue(index + " should be active", className.indexOf("sisiliano-piano-key-active") >= 0);
            } else {
                jqUnit.assertFalse(index + " should be inactive", className.indexOf("sisiliano-piano-key-active") >= 0);
            }
        });
    };

    sisiliano.tests.piano.verifyLength = function (piano, expectedLength) {
        var numberOfKeys = d3.select(piano.container.get(0)).selectAll(".sisiliano-piano-key")[0].length;
        jqUnit.assertEquals("The length should be " + expectedLength, expectedLength, numberOfKeys);
    };

    sisiliano.tests.piano.verifyKeyStatus = function (piano, key, color, message, active, pressed) {
        var keyColor = key.css("fill");
        var expectedColor = null;
        if (color === "WHITE") {
            if (active) {
                expectedColor = "#FFFFFF";
            } else {
                expectedColor = "#D1CFCF";
            }
        } else {
            if (active) {
                expectedColor = "#000000";
            } else {
                expectedColor = "#504C4C";
            }
        }

        if (pressed) {
            expectedColor = piano.model.color;
        }

        jqUnit.assertEquals(message + " : pressed color should have" + (pressed ? "": " not") + " been applied",
            expectedColor,
            sisiliano.tests.helpers.toHex(keyColor));
    };

    sisiliano.tests.piano.getKeyColor = function (key) {
        var className = key.attr("class");
        if (className.indexOf("white") >= 0) {
            return "WHITE";
        } else {
            return "BLACK";
        }
    };

    /////////////////////////////////////////////////////////
    /////           Verifying mouse click
    /////////////////////////////////////////////////////////
    fluid.registerNamespace("sisiliano.tests.piano.mouseEvents");
    jqUnit.test("Piano : mouse click", function () {
        var soundBox = {
            playKey: function() {},
            releaseKey: function() {}
        };

        $(".test").empty();
        var piano = sisiliano.piano(".test", {
            listeners: {
                onKeyPress: function (key, frequency) {
                    soundBox.playKey(key, frequency);
                },
                onKeyRelease: function (key) {
                    soundBox.releaseKey(key);
                }
            }
        });
        sisiliano.tests.piano.verifyMouseEvents(piano, soundBox);
    });

    sisiliano.tests.piano.verifyMouseEvents = function (piano, soundBox) {
        var whiteKeys = piano.locate("whiteKeys");
        var keyElm;
        for (var i = 0; i < whiteKeys.length; i++) {
            keyElm = $(whiteKeys[i]);
            sisiliano.tests.piano.mouseEvents.verifyMouseDown(piano, "White key " + keyElm.attr("index"), keyElm,
                "WHITE", i, soundBox);
            sisiliano.tests.piano.mouseEvents.verifyMouseUp(piano, "White key " + keyElm.attr("index"), keyElm,
                "WHITE", i, soundBox);
        }

        var blackKeys = piano.locate("blackKeys");
        for (i = 0; i < blackKeys.length; i++) {
            keyElm = $(blackKeys[i]);
            sisiliano.tests.piano.mouseEvents.verifyMouseDown(piano, "Black key " + keyElm.attr("index"), keyElm,
                "BLACK", i, soundBox);
            sisiliano.tests.piano.mouseEvents.verifyMouseUp(piano, "Black key " + keyElm.attr("index"), keyElm,
                "BLACK", i, soundBox);
        }
    };

    sisiliano.tests.piano.mouseEvents.verifyMouseDown = function (piano, message, key, color, index, soundBox) {
        soundBox.playKey = function () {
            jqUnit.assert(message + " : soundbox should start playing when mousedown");
        };

        var isActive = key.attr("class").indexOf("inactive") < 0;
        key.simulate("mousedown");
        sisiliano.tests.piano.verifyKeyStatus(piano, key, color, message + " : Key style should be changed as clicked", isActive, true);
    };

    sisiliano.tests.piano.mouseEvents.verifyMouseUp = function (piano, message, key, color, index, soundBox) {
        soundBox.releaseKey = function () {
            jqUnit.assert(message + " : soundbox should stop playing when mouseup");
        };

        var isActive = key.attr("class").indexOf("inactive") < 0;
        key.simulate("mouseup");
        sisiliano.tests.piano.verifyKeyStatus(piano, key, color, message + " : Key style should be changed as clicked", isActive, false);
    };

    /////////////////////////////////////////////////////////
    /////           Verifying active area navigation
    /////////////////////////////////////////////////////////
    fluid.registerNamespace("sisiliano.tests.piano.activeArea");
    jqUnit.test("Piano : active area navigation", function () {
        $(".test").empty();
        var piano = sisiliano.piano(".test");

        sisiliano.tests.piano.verifyActiveAreaKeys(piano, "Default active area", {start: 0, end: 10});
        sisiliano.tests.piano.verifyActiveAreaNavigations(piano, "Active area navigations");
    });

    sisiliano.tests.piano.verifyActiveAreaNavigations = function (piano, message) {
        var whiteKeys = piano.locate("whiteKeys");
        var expectedActiveArea = {
            start: piano.model.activeArea.start,
            end: piano.model.activeArea.end
        };
        var testCaseMessage = "";

        for (var i = 1; i <= whiteKeys.length; i++) {
            sisiliano.tests.piano.activeArea.moveToRight(piano);
            if (expectedActiveArea.end === (whiteKeys.length - 1)) {
                testCaseMessage = "Active area shouldn't moved to right from the last white key";
            } else {
                testCaseMessage = "Active area should be moved to (" + expectedActiveArea.start + "," + expectedActiveArea.end + ")";
                expectedActiveArea.start++;
                expectedActiveArea.end++;
            }

            sisiliano.tests.piano.verifyActiveAreaKeys(piano, message + " : " + testCaseMessage, expectedActiveArea);
        }

        for (i = 1; i <= whiteKeys.length; i++) {
            sisiliano.tests.piano.activeArea.moveToLeft(piano);
            if (expectedActiveArea.start === 0) {
                testCaseMessage = "Active area shouldn't moved to left from zero";
            } else {
                testCaseMessage = "Active area should be moved to (" + expectedActiveArea.start + "," + expectedActiveArea.end + ")";
                expectedActiveArea.start--;
                expectedActiveArea.end--;
            }

            sisiliano.tests.piano.verifyActiveAreaKeys(piano, message + " : " + testCaseMessage, expectedActiveArea);
        }
    };

    sisiliano.tests.piano.activeArea.moveToLeft = function (piano) {
        sisiliano.tests.piano.keyEvents.pressKey(piano, 37);
    };

    sisiliano.tests.piano.activeArea.moveToRight = function (piano) {
        sisiliano.tests.piano.keyEvents.pressKey(piano, 39);
    };

    sisiliano.tests.piano.verifyActiveAreaKeys = function (piano, message, expectedActiveArea) {
        var keys = piano.locate("keys");
        var whiteKeys = piano.locate("whiteKeys");

        var activeStartWhiteKey= whiteKeys[expectedActiveArea.start];
        var activeEndWhiteKey = whiteKeys[expectedActiveArea.end];
        var activeStartIndex = parseInt($(activeStartWhiteKey).attr("index"), null);
        var activeEndIndex = parseInt($(activeEndWhiteKey).attr("index"), null);

        for (var i = 0; i < keys.length; i++) {
            var key = $(keys[i]);
            var keyColor = sisiliano.tests.piano.getKeyColor(key);
            var keyIndex = parseInt(key.attr("index"), null);
            var isActive = keyIndex >= activeStartIndex && keyIndex <= activeEndIndex;

            //Verifying whether the edge black keys are being activated
            if (keyColor === "BLACK") {
                if (keyIndex === (activeStartIndex - 1) || keyIndex === (activeEndIndex + 1)) {
                    isActive = true;
                }
            }

            sisiliano.tests.piano.verifyKeyStatus(piano, key, keyColor,
                message + " : Key " + (keyIndex + 1) + " should be " + (isActive ? "active" : "inactive"), isActive, false);
        }
    };

    /////////////////////////////////////////////////////////
    /////           Verifying Key Events
    /////////////////////////////////////////////////////////
    fluid.registerNamespace("sisiliano.tests.piano.keyEvents");
    //TODO

    sisiliano.tests.piano.keyEvents.pressKey = function (piano, keyCode) {
        piano.container.simulate("keydown", {
            keyCode: keyCode
        });
    };
})(fluid, jqUnit);<commit_msg>Task-16: [Piano] Added test cases for key events<commit_after>(function (fluid, jqUnit) {
    "use strict";

    fluid.registerNamespace("sisiliano.tests.piano");

    jqUnit.test("Piano : basics of piano", function () {
        $(".test").empty();
        var piano = sisiliano.piano(".test");
        sisiliano.tests.piano.verifyPressedColor(piano, "#4CAF50");
        sisiliano.tests.piano.verifyActiveArea(piano, 0, 18);
        sisiliano.tests.piano.verifyLength(piano, 36);
    });

    jqUnit.test("Piano : Custimizations of piano", function () {
        $(".test").empty();
        var piano = sisiliano.piano(".test", {
            model: {
                color: "#FF0000",
                activeArea: {
                    start: 3,
                    end: 9
                },
                keyBoard: {
                    length: 20
                }
            }
        });
        sisiliano.tests.piano.verifyPressedColor(piano, "#FF0000");
        sisiliano.tests.piano.verifyActiveArea(piano, 5, 16);
        sisiliano.tests.piano.verifyLength(piano, 20);
    });

    sisiliano.tests.piano.verifyPressedColor = function (piano, expectedColor) {
        d3.select(piano.container.get(0)).selectAll(".sisiliano-piano-key").each(function () {
            var key = d3.select(this);
            var className = key.attr("class");
            key.attr("class", className + " sisiliano-piano-key-pressed");
            var fillColorWhenPressed = key.style("fill");
            jqUnit.assertEquals("color should be #4CAF50 - " + className, expectedColor, sisiliano.tests.helpers.toHex(fillColorWhenPressed));
            key.attr("class", className);
        });
    };

    sisiliano.tests.piano.verifyActiveArea = function (piano, expectedStart, expectedEnd) {
        d3.select(piano.container.get(0)).selectAll(".sisiliano-piano-key").each(function () {
            var key = d3.select(this);
            var className = key.attr("class");
            var index = parseInt(key.attr("index"), null);
            if (index >= expectedStart && index <= expectedEnd) {
                jqUnit.assertTrue(index + " should be active", className.indexOf("sisiliano-piano-key-active") >= 0);
            } else {
                jqUnit.assertFalse(index + " should be inactive", className.indexOf("sisiliano-piano-key-active") >= 0);
            }
        });
    };

    sisiliano.tests.piano.verifyLength = function (piano, expectedLength) {
        var numberOfKeys = d3.select(piano.container.get(0)).selectAll(".sisiliano-piano-key")[0].length;
        jqUnit.assertEquals("The length should be " + expectedLength, expectedLength, numberOfKeys);
    };

    sisiliano.tests.piano.verifyKeyStatus = function (piano, key, color, message, active, pressed) {
        var keyColor = $(key).css("fill");
        var expectedColor = null;
        if (color === "WHITE") {
            if (active) {
                expectedColor = "#FFFFFF";
            } else {
                expectedColor = "#D1CFCF";
            }
        } else {
            if (active) {
                expectedColor = "#000000";
            } else {
                expectedColor = "#504C4C";
            }
        }

        if (pressed) {
            expectedColor = piano.model.color;
        }

        jqUnit.assertEquals(message + " : pressed color should have" + (pressed ? "": " not") + " been applied",
            expectedColor,
            sisiliano.tests.helpers.toHex(keyColor));
    };

    sisiliano.tests.piano.getKeyColor = function (key) {
        var className = $(key).attr("class");
        if (className.indexOf("white") >= 0) {
            return "WHITE";
        } else {
            return "BLACK";
        }
    };

    sisiliano.tests.piano.getKeyIndex = function (key) {
        return parseInt($(key).attr("index"), null);
    };

    sisiliano.tests.piano.getKeyByIndex = function (piano, index) {
        var keys = piano.locate("keys");
        var filteredKeys = keys.filter(function () {
            return (sisiliano.tests.piano.getKeyIndex($(this)) + "") === (index + "");
        });

        return filteredKeys.length === 0 ? null : filteredKeys[0];
    };

    sisiliano.tests.piano.isKeyActive = function (key) {
        return $(key).attr("class").indexOf("inactive") < 0;
    };

    /////////////////////////////////////////////////////////
    /////           Verifying mouse click
    /////////////////////////////////////////////////////////
    fluid.registerNamespace("sisiliano.tests.piano.mouseEvents");
    jqUnit.test("Piano : mouse click", function () {
        var soundBox = {
            playKey: function() {},
            releaseKey: function() {}
        };
        $(".test").empty();
        var piano = sisiliano.piano(".test", {
            listeners: {
                onKeyPress: function (key, frequency) {
                    soundBox.playKey(key, frequency);
                },
                onKeyRelease: function (key) {
                    soundBox.releaseKey(key);
                }
            }
        });
        sisiliano.tests.piano.verifyMouseEvents(piano, soundBox);
    });

    sisiliano.tests.piano.verifyMouseEvents = function (piano, soundBox) {
        var whiteKeys = piano.locate("whiteKeys");
        var keyElm;
        for (var i = 0; i < whiteKeys.length; i++) {
            keyElm = $(whiteKeys[i]);
            sisiliano.tests.piano.mouseEvents.verifyMouseDown(piano, "White key " + keyElm.attr("index"), keyElm,
                "WHITE", i, soundBox);
            sisiliano.tests.piano.mouseEvents.verifyMouseUp(piano, "White key " + keyElm.attr("index"), keyElm,
                "WHITE", i, soundBox);
        }

        var blackKeys = piano.locate("blackKeys");
        for (i = 0; i < blackKeys.length; i++) {
            keyElm = $(blackKeys[i]);
            sisiliano.tests.piano.mouseEvents.verifyMouseDown(piano, "Black key " + keyElm.attr("index"), keyElm,
                "BLACK", i, soundBox);
            sisiliano.tests.piano.mouseEvents.verifyMouseUp(piano, "Black key " + keyElm.attr("index"), keyElm,
                "BLACK", i, soundBox);
        }
    };

    sisiliano.tests.piano.mouseEvents.verifyMouseDown = function (piano, message, key, color, index, soundBox) {
        soundBox.playKey = function () {
            jqUnit.assert(message + " : soundbox should start playing when mousedown");
        };
        var isActive = sisiliano.tests.piano.isKeyActive(key);
        key.simulate("mousedown");
        sisiliano.tests.piano.verifyKeyStatus(piano, key, color, message + " : Key style should be changed as clicked", isActive, true);
    };

    sisiliano.tests.piano.mouseEvents.verifyMouseUp = function (piano, message, key, color, index, soundBox) {
        soundBox.releaseKey = function () {
            jqUnit.assert(message + " : soundbox should stop playing when mouseup");
        };
        var isActive = sisiliano.tests.piano.isKeyActive(key);
        key.simulate("mouseup");
        sisiliano.tests.piano.verifyKeyStatus(piano, key, color, message + " : Key style should be changed as clicked", isActive, false);
    };

    /////////////////////////////////////////////////////////
    /////           Verifying active area navigation
    /////////////////////////////////////////////////////////
    fluid.registerNamespace("sisiliano.tests.piano.activeArea");

    jqUnit.test("Piano : active area navigation", function () {
        $(".test").empty();
        var piano = sisiliano.piano(".test");

        sisiliano.tests.piano.verifyActiveAreaKeys(piano, "Default active area", {start: 0, end: 10});
        sisiliano.tests.piano.verifyActiveAreaNavigations(piano, "Active area navigations");
    });

    sisiliano.tests.piano.verifyActiveAreaNavigations = function (piano, message) {
        var whiteKeys = piano.locate("whiteKeys");
        var expectedActiveArea = {
            start: piano.model.activeArea.start,
            end: piano.model.activeArea.end
        };
        var testCaseMessage = "";
        for (var i = 1; i <= whiteKeys.length; i++) {
            sisiliano.tests.piano.activeArea.moveToRight(piano);
            if (expectedActiveArea.end === (whiteKeys.length - 1)) {
                testCaseMessage = "Active area shouldn't moved to right from the last white key";
            } else {
                testCaseMessage = "Active area should be moved to (" + expectedActiveArea.start + "," + expectedActiveArea.end + ")";
                expectedActiveArea.start++;
                expectedActiveArea.end++;
            }

            sisiliano.tests.piano.verifyActiveAreaKeys(piano, message + " : " + testCaseMessage, expectedActiveArea);
        }

        for (i = 1; i <= whiteKeys.length; i++) {
            sisiliano.tests.piano.activeArea.moveToLeft(piano);
            if (expectedActiveArea.start === 0) {
                testCaseMessage = "Active area shouldn't moved to left from zero";
            } else {
                testCaseMessage = "Active area should be moved to (" + expectedActiveArea.start + "," + expectedActiveArea.end + ")";
                expectedActiveArea.start--;
                expectedActiveArea.end--;
            }

            sisiliano.tests.piano.verifyActiveAreaKeys(piano, message + " : " + testCaseMessage, expectedActiveArea);
        }
    };

    sisiliano.tests.piano.activeArea.moveToLeft = function (piano) {
        sisiliano.tests.piano.keyEvents.pressKey(piano, 37);
    };

    sisiliano.tests.piano.activeArea.moveToRight = function (piano) {
        sisiliano.tests.piano.keyEvents.pressKey(piano, 39);
    };

    sisiliano.tests.piano.verifyActiveAreaKeys = function (piano, message, expectedActiveArea) {
        var keys = piano.locate("keys");
        var whiteKeys = piano.locate("whiteKeys");
        var activeStartWhiteKey= whiteKeys[expectedActiveArea.start];
        var activeEndWhiteKey = whiteKeys[expectedActiveArea.end];
        var activeStartIndex = parseInt($(activeStartWhiteKey).attr("index"), null);
        var activeEndIndex = parseInt($(activeEndWhiteKey).attr("index"), null);
        for (var i = 0; i < keys.length; i++) {
            var key = $(keys[i]);
            var keyColor = sisiliano.tests.piano.getKeyColor(key);
            var keyIndex = parseInt(key.attr("index"), null);
            var isActive = keyIndex >= activeStartIndex && keyIndex <= activeEndIndex;

            //Verifying whether the edge black keys are being activated
            if (keyColor === "BLACK") {
                if (keyIndex === (activeStartIndex - 1) || keyIndex === (activeEndIndex + 1)) {
                    isActive = true;
                }
            }

            sisiliano.tests.piano.verifyKeyStatus(piano, key, keyColor,
                message + " : Key " + (keyIndex + 1) + " should be " + (isActive ? "active" : "inactive"), isActive, false);
        }

        sisiliano.tests.piano.verifyKeyEvents(piano, message + " : key events", expectedActiveArea);
    };

    /////////////////////////////////////////////////////////
    /////           Verifying Key Events
    /////////////////////////////////////////////////////////
    fluid.registerNamespace("sisiliano.tests.piano.keyEvents");
    jqUnit.test("Piano : active area navigation", function () {
        $(".test").empty();
        var piano = sisiliano.piano(".test");
        sisiliano.tests.piano.verifyKeyEvents(piano, "Verifying key events", {start: 0, end: 10});
    });

    sisiliano.tests.piano.verifyKeyEvents = function (piano, message, expectedActiveArea) {
        var keyCodeMap = {
            Q: 81,
            A: 65,
            W: 87,
            S: 83,
            E: 69,
            D: 68,
            R: 82,
            F: 70,
            T: 84,
            G: 71,
            Y: 89,
            H: 72,
            U: 85,
            J: 74,
            I: 73,
            K: 75,
            O: 79,
            L: 76,
            P: 80,
            ":": 186,
            "{": 219,
            "\"": 222,
            "}": 221
        };

        var whiteKeys = piano.locate("whiteKeys");
        var keyLettersOrder = "QAWSEDRFTGYHUJIKOLP:{\"}";
        var expectedKeys = [];
        for (var i = expectedActiveArea.start; i <= expectedActiveArea.end + 1; i++) {
            var key = whiteKeys[i];
            var keyIndex = sisiliano.tests.piano.getKeyIndex(key);
            var prevKey = sisiliano.tests.piano.getKeyByIndex(piano, keyIndex - 1);
            if (prevKey && sisiliano.tests.piano.getKeyColor(prevKey) === "BLACK") {
                expectedKeys.push(prevKey);
            } else {
                expectedKeys.push(null);
            }

            expectedKeys.push(key);
        }

        for (i = 0; i < keyLettersOrder.length; i++) {
            var keyLetter = keyLettersOrder[i];
            var expectedKey = expectedKeys[i];
            if (expectedKey) {
                sisiliano.tests.piano.keyEvents.verifyKeyCodeAndKey(piano, keyCodeMap[keyLetter], expectedKey,
                    message + " : letter " + keyLetter + " should fire key " + sisiliano.tests.piano.getKeyIndex(expectedKey));
            }
        }
    };

    sisiliano.tests.piano.keyEvents.verifyKeyCodeAndKey = function (piano, keyCode, expectedKey, message) {
        //Verifying whether the key press of the specified key code presses the mapped key in the piano
        piano.container.simulate("keydown", {
            keyCode: keyCode
        });
        sisiliano.tests.piano.verifyKeyStatus(piano, expectedKey,
            sisiliano.tests.piano.getKeyColor(expectedKey),
            message + " : keydown", true, true);

        //Verifying whether the key release of the specified key code releases the mapped key in the piano
        piano.container.simulate("keyup", {
            keyCode: keyCode
        });
        sisiliano.tests.piano.verifyKeyStatus(piano, expectedKey,
            sisiliano.tests.piano.getKeyColor(expectedKey),
            message + " : keyup", true, false);
    };

    sisiliano.tests.piano.keyEvents.pressKey = function (piano, keyCode) {
        piano.container.simulate("keydown", {
            keyCode: keyCode
        });
    };
})(fluid, jqUnit);<|endoftext|>


<commit_before>'use strict'

const Logger = use('Logger');

const pluralize = require('pluralize');

const ExternalWordService = use('App/Services/ExternalWordService');
const WordService = use('App/Services/WordService');
const Word = use('App/Models/Word');

class WordStorageService {

  static get MAX_SYNONYM_DEPTH() { return 1; }

  constructor() {
    this.wordService = new WordService;
    this.externalWordService = new ExternalWordService;
    this.newWords = [];
  }

  async addNewWords(text) {
    let words = this.splitIntoUsableWords(text);
    await words.forEach(async name => {
      await this._addNewWordWithSynonyms(name);
    });
  }

  /**
   * Parses individual words in a block of text. Depluralizes, removes duplicates, and unusable words
   * @param text
   * @returns {string[]}
   */
  splitIntoUsableWords(text) {
    let words;

    // Remove punctuation and split by space or new line
    words = text.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()\d]/g, '').split(/[ \n]/);

    // Depluralize
    words = words.map((word) => {
      return pluralize.singular(word);
    });

    // Remove duplicates
    words = [...new Set(words)];

    // Remove empty entries
    words = words.filter(word => word)

    // Remove words with non-ascii characters
    // TODO: Should we really remove these?
    words = words.filter(word => !word.match(/[^\x00-\x7F]/g));

    // Remove words with punctuation
    // TODO: Should we really remove these?
    words = words.filter(word => !word.match(/['"]/g));

    Logger.info('Parsed words: ' + words);

    return words;
  }

  // Private methods

  async _addNewWordWithSynonyms(name) {

    let word = await Word.findBy('name', name);

    if (!word) {
      word = await this._addNewWord(name);
    }

    if (!word.hasCheckedSynonyms) {
      await this._recursivelyAddSynonyms(word);
    }
  }

  async _addNewWord(name) {
    let wordParams = await this.externalWordService.getSummary(name);
    if (!wordParams) {
      wordParams = WordService.EMPTY_WORD_PARAMS;
      wordParams.name = name;
    }

    this.newWords.push(name);

    return await Word.create(wordParams);
  }

  async _recursivelyAddSynonyms(word, currentDepth = 1) {
    let synonymNames = await this.externalWordService.getSynonyms(word.name);
    Logger.info(synonymNames);

    synonymNames.forEach(async synonymName => {
      let synonym = await Word.findBy('name', synonymName);
      if (!synonym) {
        synonym = await this._addNewWord(synonymName);

        // if (currentDepth < WordStorageService.MAX_SYNONYM_DEPTH) {
        //   this._recursivelyAddSynonyms(word, currentDepth+1);
        // }
      }

      // TODO: Really don't like that this is done for each synonym. Should do this as a bulk operation
      await word.synonyms().attach(synonym.id);
    });

    word.hasCheckedSynonyms = true;
    await word.save();

  }

}

module.exports = WordStorageService;
<commit_msg>Remove ? from words<commit_after>'use strict'

const Logger = use('Logger');

const pluralize = require('pluralize');

const ExternalWordService = use('App/Services/ExternalWordService');
const WordService = use('App/Services/WordService');
const Word = use('App/Models/Word');

class WordStorageService {

  static get MAX_SYNONYM_DEPTH() { return 1; }

  constructor() {
    this.wordService = new WordService;
    this.externalWordService = new ExternalWordService;
    this.newWords = [];
  }

  async addNewWords(text) {
    let words = this.splitIntoUsableWords(text);
    await words.forEach(async name => {
      await this._addNewWordWithSynonyms(name);
    });
  }

  /**
   * Parses individual words in a block of text. Depluralizes, removes duplicates, and unusable words
   * @param text
   * @returns {string[]}
   */
  splitIntoUsableWords(text) {
    let words;

    // Remove punctuation and split by space or new line
    words = text.replace(/[.,\/#!$%\^&\*\?;:{}=\-_`~()\d]/g, '').split(/[ \n]/);

    // Depluralize
    words = words.map((word) => {
      return pluralize.singular(word);
    });

    // Remove duplicates
    words = [...new Set(words)];

    // Remove empty entries
    words = words.filter(word => word)

    // Remove words with non-ascii characters
    // TODO: Should we really remove these?
    words = words.filter(word => !word.match(/[^\x00-\x7F]/g));

    // Remove words with punctuation
    // TODO: Should we really remove these?
    words = words.filter(word => !word.match(/['"]/g));

    Logger.info('Parsed words: ' + words);

    return words;
  }

  // Private methods

  async _addNewWordWithSynonyms(name) {

    let word = await Word.findBy('name', name);

    if (!word) {
      word = await this._addNewWord(name);
    }

    if (!word.hasCheckedSynonyms) {
      await this._recursivelyAddSynonyms(word);
    }
  }

  async _addNewWord(name) {
    let wordParams = await this.externalWordService.getSummary(name);
    if (!wordParams) {
      wordParams = WordService.EMPTY_WORD_PARAMS;
      wordParams.name = name;
    }

    this.newWords.push(name);

    return await Word.create(wordParams);
  }

  async _recursivelyAddSynonyms(word, currentDepth = 1) {
    let synonymNames = await this.externalWordService.getSynonyms(word.name);
    Logger.info(synonymNames);

    synonymNames.forEach(async synonymName => {
      let synonym = await Word.findBy('name', synonymName);
      if (!synonym) {
        synonym = await this._addNewWord(synonymName);

        // if (currentDepth < WordStorageService.MAX_SYNONYM_DEPTH) {
        //   this._recursivelyAddSynonyms(word, currentDepth+1);
        // }
      }

      // TODO: Really don't like that this is done for each synonym. Should do this as a bulk operation
      await word.synonyms().attach(synonym.id);
    });

    word.hasCheckedSynonyms = true;
    await word.save();

  }

}

module.exports = WordStorageService;
<|endoftext|>