<commit_before>"use strict";

import fs from "fs";
import path from "path";

import del from "del";
import exists from "exists-sync";
import { expect } from "chai";

import {
  configstore,
  dictionary,
  doubleItemFixture,
  fileStore
} from "./fixtures";

import Spelly from "../";

function readFile(filePath) {
  return JSON.parse(fs.readFile(path.resolve(__dirname, filePath)));
}

describe("Spelly", function () {
  let store, spelly;

  beforeEach(function () {
    let options = {
      cache: {
        type: "configstore",
        store: configstore
      }
    };

    spelly = new Spelly(dictionary, options);
  });

  it("requires a dictionary", function () {
    expect(function () {
      new Spelly();
    }).to.throw("Missing required dictionary");
  });

  describe("#cache", function () {
    describe("with configstore", function () {
      beforeEach(function () {
        configstore.set("wierd", [{ word: "wired", score: 1 }]);
      });

      afterEach(function () {
        configstore.del("wierd");
      });

      it("caches a spelling suggestion", function () {
        spelly.cache("wierd", { word: "weird", score: 1 });

        let cached = configstore.get("wierd");
        expect(cached).to.include({ word: "weird", score: 1 });
      });

      it("reorders suggestions based on new cached item", function () {
        spelly.cache("wierd", { word: "weird", score: 1 });

        let cached = configstore.get("wierd");
        expect(cached[0].word).to.eql("weird");
      });

      it("reorders suggestions if item exists");
    });
  });

  describe("#getCache", function () {
    beforeEach(function () {
      configstore.set("wierd", [{ word: "wired", score: 1 }]);
    });

    afterEach(function () {
      configstore.del("wierd");
    });

    it("returns cached suggestions", function () {
      expect(spelly.getCache()).to.eql({
        "wierd": [{ word: "wired", score: 1 }]
      });
    });

    it("returns cached suggestions for a single word", function () {
      expect(spelly.getCache("wierd")).to.eql([
          { word: "wired", score: 1 }
      ]);
    });
  });

  describe("#clearCache", function () {
    beforeEach(function () {
      configstore.set("wierd", doubleItemFixture);
      configstore.set("somting", [{ word: "something", score: 1 }]);
    });

    afterEach(function () {
      configstore.clear();
    });

    it("removes cached results", function () {
      spelly.clearCache();

      expect(configstore.get("wierd")).to.be.undefined;
      expect(configstore.get("somting")).to.be.undefined;
    });

    it("removes cached results for a single word", function () {
      spelly.clearCache("wierd");

      expect(configstore.get("wierd")).to.be.undefined;
      expect(configstore.get("somting")).to.eql([
          { word: "something", score: 1 }
      ]);
    });

    it("removes a single cached result for a mispelled word", function () {
      spelly.clearCache("wierd", "wired");

      expect(configstore.get("wierd")).to.eql([
          { word: "weird", score: 1 }
      ]);
    });
  });

  describe("#check", function () {
    it("uses a cached suggestion if found", function () {
      configstore.set("wierd", doubleItemFixture);

      let suggestions = spelly.check("wierd");

      expect(suggestions).to.eql([
          { word: "wired", score: 1 },
          { word: "weird", score: 2 }
      ]);

      configstore.del("wierd");
    });

    it("spell corrects a word", function () {
      let suggestions = spelly.check("wierd").suggestions;

      let weird = suggestions.filter(suggestion => {
        return suggestion.word === "weird";
      })[0];

      expect(weird.word).to.eql("weird");
    });

    it("offers multiple suggestions");

    it("caches suggestion results");
  });

  describe("streaming", function () {

  });
});
<commit_msg>test: add pending test for array dictionary<commit_after>"use strict";

import fs from "fs";
import path from "path";

import del from "del";
import exists from "exists-sync";
import { expect } from "chai";

import {
  configstore,
  dictionary,
  doubleItemFixture,
  fileStore
} from "./fixtures";

import Spelly from "../";

function readFile(filePath) {
  return JSON.parse(fs.readFile(path.resolve(__dirname, filePath)));
}

describe("Spelly", function () {
  let store, spelly;

  beforeEach(function () {
    let options = {
      cache: {
        type: "configstore",
        store: configstore
      }
    };

    spelly = new Spelly(dictionary, options);
  });

  it("requires a dictionary", function () {
    expect(function () {
      new Spelly();
    }).to.throw("Missing required dictionary");
  });

  describe("#cache", function () {
    describe("with configstore", function () {
      beforeEach(function () {
        configstore.set("wierd", [{ word: "wired", score: 1 }]);
      });

      afterEach(function () {
        configstore.del("wierd");
      });

      it("caches a spelling suggestion", function () {
        spelly.cache("wierd", { word: "weird", score: 1 });

        let cached = configstore.get("wierd");
        expect(cached).to.include({ word: "weird", score: 1 });
      });

      it("reorders suggestions based on new cached item", function () {
        spelly.cache("wierd", { word: "weird", score: 1 });

        let cached = configstore.get("wierd");
        expect(cached[0].word).to.eql("weird");
      });

      it("reorders suggestions if item exists");
    });
  });

  describe("#getCache", function () {
    beforeEach(function () {
      configstore.set("wierd", [{ word: "wired", score: 1 }]);
    });

    afterEach(function () {
      configstore.del("wierd");
    });

    it("returns cached suggestions", function () {
      expect(spelly.getCache()).to.eql({
        "wierd": [{ word: "wired", score: 1 }]
      });
    });

    it("returns cached suggestions for a single word", function () {
      expect(spelly.getCache("wierd")).to.eql([
          { word: "wired", score: 1 }
      ]);
    });
  });

  describe("#clearCache", function () {
    beforeEach(function () {
      configstore.set("wierd", doubleItemFixture);
      configstore.set("somting", [{ word: "something", score: 1 }]);
    });

    afterEach(function () {
      configstore.clear();
    });

    it("removes cached results", function () {
      spelly.clearCache();

      expect(configstore.get("wierd")).to.be.undefined;
      expect(configstore.get("somting")).to.be.undefined;
    });

    it("removes cached results for a single word", function () {
      spelly.clearCache("wierd");

      expect(configstore.get("wierd")).to.be.undefined;
      expect(configstore.get("somting")).to.eql([
          { word: "something", score: 1 }
      ]);
    });

    it("removes a single cached result for a mispelled word", function () {
      spelly.clearCache("wierd", "wired");

      expect(configstore.get("wierd")).to.eql([
          { word: "weird", score: 1 }
      ]);
    });
  });

  describe("#check", function () {
    it("uses a cached suggestion if found", function () {
      configstore.set("wierd", doubleItemFixture);

      let suggestions = spelly.check("wierd");

      expect(suggestions).to.eql([
          { word: "wired", score: 1 },
          { word: "weird", score: 2 }
      ]);

      configstore.del("wierd");
    });

    it("spell corrects a word", function () {
      let suggestions = spelly.check("wierd").suggestions;

      let weird = suggestions.filter(suggestion => suggestion.word === "weird")[0];

      expect(weird.word).to.eql("weird");
    });

    it("offers multiple suggestions");

    it("caches suggestion results");

    it("uses a provided dictionary array");
  });

  describe("streaming", function () {

  });
});
<|endoftext|>


<commit_before>/*
	TODO:
	* Start up vs. Up-time.
	* New user.
	* Options:
		* Collapsed results.
		* Custom validator URL.
		* Restricted validation.
		* Auto validation.
*/

var _gaq = _gaq || [];

var validity = (function(validity) {
	"use strict";
	var stats = {},
		ga_elm,
		purge_timeout,
		PURGE_INTERVAL = 60;

	_gaq.push(['_setAccount', '@gaid@']);
	_gaq.push(['_trackPageview', '/validity/@version@']);

	//	Load Google Analytics Script
	stats._init = function() {
		var ga = document.createElement('script');
		ga.type = 'text/javascript';
		ga.async = true;
		ga.src = 'https://ssl.google-analytics.com/ga.js';

		var s = document.getElementsByTagName('script')[0];
		s.parentNode.insertBefore(ga, s);

		ga_elm = ga;

		if (validity.opts.option('disableAnalytics')) {
			stats.disableAnalytics();
		}
	};

	stats.disableAnalytics = function() {
		window['ga-disable-@gaid@'] = true;

		//	Clear queue periodically.
		stats._purgeTrackingQueue();
		(function clearQueue() {
			purge_timeout = window.setTimeout(function() {
				stats._purgeTrackingQueue();
				clearQueue();
			}, 60 * 60 * 1000);
		})();
	};

	stats.enableAnalytics = function() {
		window.clearTimeout(purge_timeout);
		window['ag-disable-@gaid@'] = false;
	};

	stats._purgeTrackingQueue = function() {
		//	Remove only page and events, not _setAccount from queue.
		for (var i=0; i<=_gaq; i++) {
			if (/^\_track/.match(_gaq[i][0])) {
				_gaq.splice(i, 1);
			}
		}
	};

	stats.track = function(category, action, label, value) {
		var trackingEnabled = !validity.opts.option('disableAnalytics');

		//	Don't track if analytics are disabled.
		if (trackingEnabled) {
			_gaq.push(['_trackEvent', category, action, label, value]);
		}
	};

	document.addEventListener('DOMContentLoaded', stats._init, false);

	validity.stats = stats;
	return validity;
})(validity || {});
<commit_msg>Removed comment from stats.js.<commit_after>var _gaq = _gaq || [];

var validity = (function(validity) {
	"use strict";
	var stats = {},
		ga_elm,
		purge_timeout,
		PURGE_INTERVAL = 60;

	_gaq.push(['_setAccount', '@gaid@']);
	_gaq.push(['_trackPageview', '/validity/@version@']);

	//	Load Google Analytics Script
	stats._init = function() {
		var ga = document.createElement('script');
		ga.type = 'text/javascript';
		ga.async = true;
		ga.src = 'https://ssl.google-analytics.com/ga.js';

		var s = document.getElementsByTagName('script')[0];
		s.parentNode.insertBefore(ga, s);

		ga_elm = ga;

		if (validity.opts.option('disableAnalytics')) {
			stats.disableAnalytics();
		}
	};

	stats.disableAnalytics = function() {
		window['ga-disable-@gaid@'] = true;

		//	Clear queue periodically.
		stats._purgeTrackingQueue();
		(function clearQueue() {
			purge_timeout = window.setTimeout(function() {
				stats._purgeTrackingQueue();
				clearQueue();
			}, 60 * 60 * 1000);
		})();
	};

	stats.enableAnalytics = function() {
		window.clearTimeout(purge_timeout);
		window['ag-disable-@gaid@'] = false;
	};

	stats._purgeTrackingQueue = function() {
		//	Remove only page and events, not _setAccount from queue.
		for (var i=0; i<=_gaq; i++) {
			if (/^\_track/.match(_gaq[i][0])) {
				_gaq.splice(i, 1);
			}
		}
	};

	stats.track = function(category, action, label, value) {
		var trackingEnabled = !validity.opts.option('disableAnalytics');

		//	Don't track if analytics are disabled.
		if (trackingEnabled) {
			_gaq.push(['_trackEvent', category, action, label, value]);
		}
	};

	document.addEventListener('DOMContentLoaded', stats._init, false);

	validity.stats = stats;
	return validity;
})(validity || {});
<|endoftext|>


<commit_before>/*
 * See copyright file.
 */
import declare from 'dojo/_base/declare';
import lang from 'dojo/_base/lang';
import string from 'dojo/string';
import convert from 'argos/Convert';
import RelatedViewManager from 'argos/RelatedViewManager';
import DashboardWidget from '../../DashboardWidget';
import getResource from 'argos/I18n';

const resource = getResource('openDashboardWidget');

const __class = declare('crm.Integrations.BOE.Views.Account.OpenDashboardWidget', [DashboardWidget], {
  // Localization
  openSalesOrdersText: resource.openSalesOrdersText,
  openQuotesText: resource.openQuotesText,
  outstandingInvoicesText: resource.outstandingInvoicesText,
  lateInvoicesText: resource.lateInvoicesText,
  lateSalesOrdersText: resource.lateSalesOrdersText,
  agingInvoicesText: resource.agingInvoicesText,
  agingSalesOrdersText: resource.agingSalesOrdersText,
  agingQuotesText: resource.agingQuotesText,
  titleText: resource.titleText,
  categoryText: resource.categoryText,
  quotesTotalingText: resource.quotesTotalingText,
  ordersTotalingText: resource.ordersTotalingText,
  invoicesTotalingText: resource.invoicesTotalingText,

  // crm status for SalesOrder
  openOrderText: resource.openOrderText,
  salesOrderText: resource.salesOrderText,
  salesHoldText: resource.salesHoldText,
  creditHoldText: resource.creditHoldText,
  adminHoldText: resource.adminHoldText,
  holdText: resource.holdText,
  orderedText: resource.orderedText,
  partiallyShippedText: resource.partiallyShippedText,
  pendingText: resource.pendingText,
  newText: resource.newText,
  openText: resource.openText,
  approvedText: resource.approvedText,
  awardedText: resource.awardedText,
  // Override variables for _DashboardWidgetBase
  color: '#313236',
  selectedColor: '#50535a',
  dayValue: 0,

  // Codes used for the status of the entity
  newCode: 'New',
  openCode: 'Open',
  approvedCode: 'Approved',
  workingCode: 'Working',
  partialShipCode: 'PartiallyShipped',
  partialPaidCode: 'PartialPaid',
  closedCode: 'Closed',
  disputeCode: 'Dispute',
  holdCode: 'Hold',
  pendingCode: 'Pending',

  // Values for the metrics
  values: [{
    name: 'quotes',
    aggregate: 'sum',
    aggregateModule: 'crm/Aggregate',
    value: null,
    queryIndex: 0,
    count: true,
    dateDependent: true,
  }, {
    name: 'invoices',
    aggregate: 'sum',
    aggregateModule: 'crm/Aggregate',
    value: null,
    queryIndex: 1,
    count: true,
    dateDependent: true,
  }, {
    name: 'salesOrders',
    aggregate: 'sum',
    aggregateModule: 'crm/Aggregate',
    value: null,
    queryIndex: 2,
    count: true,
    dateDependent: false,
  }],

  resourceKind: 'accounts',
  querySelect: [
    'AccountName',
  ],
  getWhere: function getWhere() {
    return "Id eq '" + this.parentEntry.$key + "'";
  },
  // Creates the range widgets, value can have valueUnit to apply next to the number
  createRangeLayout: function createRangeLayout() {
    const rangeLayout = [{
      value: 0,
      valueUnit: '+',
    }, {
      value: 30,
      valueUnit: '+',
    }, {
      value: 60,
      valueUnit: '+',
    }, {
      value: 90,
      valueUnit: '+',
    }, {
      value: 180,
      valueUnit: '+',
    }];
    return rangeLayout;
  },
  createMetricLayout: function createMetricLayout(entry) {
    this.setQueryArgs(entry);

    const metricLayout = [{
      navTo: 'account_openquotes_related',
      formatter: 'bigNumber',
      formatterModule: 'crm/Format',
      title: this.agingQuotesText,
      countTitle: this.quotesTotalingText,
      valueNeeded: 'quotes',
    }, {
      navTo: 'account_lateinvoice_related',
      formatter: 'bigNumber',
      formatterModule: 'crm/Format',
      title: this.agingInvoicesText,
      countTitle: this.invoicesTotalingText,
      valueNeeded: 'invoices',
    }, {
      navTo: 'account_opensalesorders_related',
      formatter: 'bigNumber',
      formatterModule: 'crm/Format',
      title: this.agingSalesOrdersText,
      countTitle: this.ordersTotalingText,
      valueNeeded: 'salesOrders',
    }];

    return metricLayout;
  },
  setQueryArgs: function setQueryArgs(entry) {
    this.queryArgs = [];

    this.queryArgs.push([
      'quotes',
      {
        _activeFilter: 'Account.Id eq "' + entry.$key + '" and ' +
                '(' +
                  '(' +
                    '(ErpExtId ne null) and ' +
                       '(ErpStatus eq "' + this.openCode + '"' +
                        ' or ErpStatus eq "' + this.pendingCode + '"' +
                        ' or ErpStatus eq "' + this.approvedCode + '"' +
                     ') and (' + this.pastDays('DocumentDate') + ')' +
                  ')' +
                  ' or ' +
                  '(' +
                    '(ErpExtId eq null) and ' +
                      '(Status eq "' + this.newText + '"' +
                       ' or Status eq "' + this.openText + '"' +
                       ' or Status eq "' + this.approvedText + '"' +
                       ' or Status eq "' + this.pendingText + '"' +
                       ' or Status eq "' + this.awardedText + '"' +
                      ') and (' + this.pastDays('StartDate') + ')' +
                  ')' +
                ')',
        _filterName: 'AccountManager',
        _metricName: 'SumGrandTotal',
      },
    ], [
      'erpInvoices',
      {
        _activeFilter: 'Account.Id eq "' + entry.$key + '" and ' +
           '(' +
            '(ErpStatus eq "' + this.openCode + '"' +
              ' or ErpStatus eq "' + this.partialPaidCode + '"' +
              ' or ErpStatus eq "' + this.disputeCode + '"' +
             ')' +
           ') and ' + this.pastDays('ErpDocumentDate'),
        _filterName: 'ErpStatus',
        _metricName: 'SumGrandTotal',
      },
    ], [
      'salesOrders',
      {
        _activeFilter: 'Account.Id eq "' + entry.$key + '" and ' +
           '(' +
             '(' +
               '(ErpExtId ne null) and ' +
               '(' +
                 '(ERPSalesOrder.ERPStatus eq "' + this.openCode + '"' +
                  ' or ERPSalesOrder.ERPStatus eq "' + this.holdCode + '"' +
                  ' or ERPSalesOrder.ERPStatus eq "' + this.partialShipCode + '"' +
                  ' or ERPSalesOrder.ERPStatus eq "' + this.approvedCode + '"' +
                 ') and ' + this.pastDays('ErpDocumentDate') + // ' and ' +
                 // '(SalesOrderItems.ErpStatus eq "' + this.openCode + '"' + // This does not work since it creates a cartesion duplicate result for each line
                 //    ' or SalesOrderItems.ErpStatus eq "' + this.partialShipCode + '"' +
                 //    ' or SalesOrderItems.ErpStatus eq "' + this.holdCode + '"' +
                 //  ') and ' +
                 //  this.pastDays('SalesOrderItems.ErpRequiredDeliveryDate') +
                ')' +
             ') or ' +
             '((ErpExtId eq null) and ' +
             '(Status eq "' + this.openOrderText + '"' +
             ' or Status eq "' + this.salesOrderText + '"' +
             ' or Status eq "' + this.salesHoldText + '"' +
             ' or Status eq "' + this.creditHoldText + '"' +
             ' or Status eq "' + this.adminHoldText + '"' +
             ' or Status eq "' + this.holdText + '"' +
             ' or Status eq "' + this.orderedText + '"' +
             ' or Status eq "' + this.partiallyShippedText + '"' +
             ' or Status eq "' + this.pendingText + '"' +
             ') and (' + this.pastDays('OrderDate') + ')' +
             ')' +
           ')',
        _filterName: 'AccountManager',
        _metricName: 'SumGrandTotal',
      },
    ] );
    this.setCountTitles();
  },
  setCountTitles: function setCountTitles() {
  },
  pastDays: function pastDays(property) {
    const now = moment();

    if (this.dayValue === 0) {
      return '1 eq 1';
    }
    const pastDay = now.clone().subtract(this.dayValue, 'days').startOf('day');

    const query = string.substitute(
            '(' + property + ' lt @${0}@ or (' + property + ' lt @${1}@))',
            [
            convert.toIsoStringFromDate(pastDay.toDate()),
            pastDay.format('YYYY-MM-DDT00:00:00[Z]'),
            ]
    );
    return query;
  },
});
const rvm = new RelatedViewManager();
rvm.registerType('account_open_dashboard_widget', __class);
lang.setObject('icboe.Views.Account.OpenDashboardWidget', __class);
export default __class;
<commit_msg>INFORCRM-10036: Updated the Aging Invoices to use DueDate instead of ErpDocumentDate.<commit_after>/*
 * See copyright file.
 */
import declare from 'dojo/_base/declare';
import lang from 'dojo/_base/lang';
import string from 'dojo/string';
import convert from 'argos/Convert';
import RelatedViewManager from 'argos/RelatedViewManager';
import DashboardWidget from '../../DashboardWidget';
import getResource from 'argos/I18n';

const resource = getResource('openDashboardWidget');

const __class = declare('crm.Integrations.BOE.Views.Account.OpenDashboardWidget', [DashboardWidget], {
  // Localization
  openSalesOrdersText: resource.openSalesOrdersText,
  openQuotesText: resource.openQuotesText,
  outstandingInvoicesText: resource.outstandingInvoicesText,
  lateInvoicesText: resource.lateInvoicesText,
  lateSalesOrdersText: resource.lateSalesOrdersText,
  agingInvoicesText: resource.agingInvoicesText,
  agingSalesOrdersText: resource.agingSalesOrdersText,
  agingQuotesText: resource.agingQuotesText,
  titleText: resource.titleText,
  categoryText: resource.categoryText,
  quotesTotalingText: resource.quotesTotalingText,
  ordersTotalingText: resource.ordersTotalingText,
  invoicesTotalingText: resource.invoicesTotalingText,

  // crm status for SalesOrder
  openOrderText: resource.openOrderText,
  salesOrderText: resource.salesOrderText,
  salesHoldText: resource.salesHoldText,
  creditHoldText: resource.creditHoldText,
  adminHoldText: resource.adminHoldText,
  holdText: resource.holdText,
  orderedText: resource.orderedText,
  partiallyShippedText: resource.partiallyShippedText,
  pendingText: resource.pendingText,
  newText: resource.newText,
  openText: resource.openText,
  approvedText: resource.approvedText,
  awardedText: resource.awardedText,
  // Override variables for _DashboardWidgetBase
  color: '#313236',
  selectedColor: '#50535a',
  dayValue: 0,

  // Codes used for the status of the entity
  newCode: 'New',
  openCode: 'Open',
  approvedCode: 'Approved',
  workingCode: 'Working',
  partialShipCode: 'PartiallyShipped',
  partialPaidCode: 'PartialPaid',
  closedCode: 'Closed',
  disputeCode: 'Dispute',
  holdCode: 'Hold',
  pendingCode: 'Pending',

  // Values for the metrics
  values: [{
    name: 'quotes',
    aggregate: 'sum',
    aggregateModule: 'crm/Aggregate',
    value: null,
    queryIndex: 0,
    count: true,
    dateDependent: true,
  }, {
    name: 'invoices',
    aggregate: 'sum',
    aggregateModule: 'crm/Aggregate',
    value: null,
    queryIndex: 1,
    count: true,
    dateDependent: true,
  }, {
    name: 'salesOrders',
    aggregate: 'sum',
    aggregateModule: 'crm/Aggregate',
    value: null,
    queryIndex: 2,
    count: true,
    dateDependent: false,
  }],

  resourceKind: 'accounts',
  querySelect: [
    'AccountName',
  ],
  getWhere: function getWhere() {
    return "Id eq '" + this.parentEntry.$key + "'";
  },
  // Creates the range widgets, value can have valueUnit to apply next to the number
  createRangeLayout: function createRangeLayout() {
    const rangeLayout = [{
      value: 0,
      valueUnit: '+',
    }, {
      value: 30,
      valueUnit: '+',
    }, {
      value: 60,
      valueUnit: '+',
    }, {
      value: 90,
      valueUnit: '+',
    }, {
      value: 180,
      valueUnit: '+',
    }];
    return rangeLayout;
  },
  createMetricLayout: function createMetricLayout(entry) {
    this.setQueryArgs(entry);

    const metricLayout = [{
      navTo: 'account_openquotes_related',
      formatter: 'bigNumber',
      formatterModule: 'crm/Format',
      title: this.agingQuotesText,
      countTitle: this.quotesTotalingText,
      valueNeeded: 'quotes',
    }, {
      navTo: 'account_lateinvoice_related',
      formatter: 'bigNumber',
      formatterModule: 'crm/Format',
      title: this.agingInvoicesText,
      countTitle: this.invoicesTotalingText,
      valueNeeded: 'invoices',
    }, {
      navTo: 'account_opensalesorders_related',
      formatter: 'bigNumber',
      formatterModule: 'crm/Format',
      title: this.agingSalesOrdersText,
      countTitle: this.ordersTotalingText,
      valueNeeded: 'salesOrders',
    }];

    return metricLayout;
  },
  setQueryArgs: function setQueryArgs(entry) {
    this.queryArgs = [];

    this.queryArgs.push([
      'quotes',
      {
        _activeFilter: 'Account.Id eq "' + entry.$key + '" and ' +
                '(' +
                  '(' +
                    '(ErpExtId ne null) and ' +
                       '(ErpStatus eq "' + this.openCode + '"' +
                        ' or ErpStatus eq "' + this.pendingCode + '"' +
                        ' or ErpStatus eq "' + this.approvedCode + '"' +
                     ') and (' + this.pastDays('DocumentDate') + ')' +
                  ')' +
                  ' or ' +
                  '(' +
                    '(ErpExtId eq null) and ' +
                      '(Status eq "' + this.newText + '"' +
                       ' or Status eq "' + this.openText + '"' +
                       ' or Status eq "' + this.approvedText + '"' +
                       ' or Status eq "' + this.pendingText + '"' +
                       ' or Status eq "' + this.awardedText + '"' +
                      ') and (' + this.pastDays('StartDate') + ')' +
                  ')' +
                ')',
        _filterName: 'AccountManager',
        _metricName: 'SumGrandTotal',
      },
    ], [
      'erpInvoices',
      {
        _activeFilter: 'Account.Id eq "' + entry.$key + '" and ' +
           '(' +
            '(ErpStatus eq "' + this.openCode + '"' +
              ' or ErpStatus eq "' + this.partialPaidCode + '"' +
              ' or ErpStatus eq "' + this.disputeCode + '"' +
             ')' +
           ') and ' + this.pastDays('DueDate'),
        _filterName: 'ErpStatus',
        _metricName: 'SumGrandTotal',
      },
    ], [
      'salesOrders',
      {
        _activeFilter: 'Account.Id eq "' + entry.$key + '" and ' +
           '(' +
             '(' +
               '(ErpExtId ne null) and ' +
               '(' +
                 '(ERPSalesOrder.ERPStatus eq "' + this.openCode + '"' +
                  ' or ERPSalesOrder.ERPStatus eq "' + this.holdCode + '"' +
                  ' or ERPSalesOrder.ERPStatus eq "' + this.partialShipCode + '"' +
                  ' or ERPSalesOrder.ERPStatus eq "' + this.approvedCode + '"' +
                 ') and ' + this.pastDays('ErpDocumentDate') + // ' and ' +
                 // '(SalesOrderItems.ErpStatus eq "' + this.openCode + '"' + // This does not work since it creates a cartesion duplicate result for each line
                 //    ' or SalesOrderItems.ErpStatus eq "' + this.partialShipCode + '"' +
                 //    ' or SalesOrderItems.ErpStatus eq "' + this.holdCode + '"' +
                 //  ') and ' +
                 //  this.pastDays('SalesOrderItems.ErpRequiredDeliveryDate') +
                ')' +
             ') or ' +
             '((ErpExtId eq null) and ' +
             '(Status eq "' + this.openOrderText + '"' +
             ' or Status eq "' + this.salesOrderText + '"' +
             ' or Status eq "' + this.salesHoldText + '"' +
             ' or Status eq "' + this.creditHoldText + '"' +
             ' or Status eq "' + this.adminHoldText + '"' +
             ' or Status eq "' + this.holdText + '"' +
             ' or Status eq "' + this.orderedText + '"' +
             ' or Status eq "' + this.partiallyShippedText + '"' +
             ' or Status eq "' + this.pendingText + '"' +
             ') and (' + this.pastDays('OrderDate') + ')' +
             ')' +
           ')',
        _filterName: 'AccountManager',
        _metricName: 'SumGrandTotal',
      },
    ] );
    this.setCountTitles();
  },
  setCountTitles: function setCountTitles() {
  },
  pastDays: function pastDays(property) {
    const now = moment();

    if (this.dayValue === 0) {
      return '1 eq 1';
    }
    const pastDay = now.clone().subtract(this.dayValue, 'days').startOf('day');

    const query = string.substitute(
            '(' + property + ' lt @${0}@ or (' + property + ' lt @${1}@))',
            [
            convert.toIsoStringFromDate(pastDay.toDate()),
            pastDay.format('YYYY-MM-DDT00:00:00[Z]'),
            ]
    );
    return query;
  },
});
const rvm = new RelatedViewManager();
rvm.registerType('account_open_dashboard_widget', __class);
lang.setObject('icboe.Views.Account.OpenDashboardWidget', __class);
export default __class;
<|endoftext|>


<commit_before>describe('sanity test', function () {
    var _ = require('lodash'),
        proxy = require('http-proxy'),

        server,
        testrun;

    before(function (done) {
        var port = 9090, // @todo: configure port dynamically via random number generation
            fakeProxyManager = {
                getProxyConfiguration: function (url, callback) {
                    callback(null, {
                        proxy: 'http://localhost:' + port,
                        tunnel: false
                    });
                }
            };

        server = new proxy.createProxyServer({
            target: 'http://echo.getpostman.com',
            headers: {
                'x-postman-proxy': 'true'
            }
        });

        server.listen(port);

        this.run({
            collection: {
                item: {
                    request: 'http://echo.getpostman.com/get'
                }
            },
            requester: {
                proxyManager: fakeProxyManager
            }
        }, function (err, results) {
            testrun = results;
            done(err);
        });
    });

    it('must have started and completed the test run', function () {
        expect(testrun).be.ok();
        expect(testrun.done.calledOnce).be.ok();
        expect(testrun.start.calledOnce).be.ok();
    });

    it('must receive response from the proxy', function () {
        var response = testrun.request.getCall(0).args[2].json();

        expect(testrun.request.calledOnce).be.ok(); // one request
        expect(_.get(response, 'headers.x-postman-proxy')).to.be('true');
    });

    after(function () {
        server.close();
    });
});
<commit_msg>Fixed the tests for proxyList over the proxyManager<commit_after>describe('sanity test', function () {
    var _ = require('lodash'),
        proxy = require('http-proxy'),

        server,
        testrun;

    before(function (done) {
        var port = 9090,
            proxyList = [{match: '*://*.getpostman.com/*', server: 'http://localhost:' + port, tunnel: false}];

        server = new proxy.createProxyServer({
            target: 'http://echo.getpostman.com',
            headers: {
                'x-postman-proxy': 'true'
            }
        });
        console.log(proxyList);
        server.listen(port);

        this.run({
            collection: {
                item: {
                    request: 'http://echo.getpostman.com/get'
                }
            },
            requester: {
                proxyList: proxyList
            }
        }, function (err, results) {
            testrun = results;
            done(err);
        });
    });

    it('must have started and completed the test run', function () {
        expect(testrun).be.ok();
        expect(testrun.done.calledOnce).be.ok();
        expect(testrun.start.calledOnce).be.ok();
    });

    it('must receive response from the proxy', function () {
        var response = testrun.request.getCall(0).args[2].json();

        expect(testrun.request.calledOnce).be.ok(); // one request
        expect(_.get(response, 'headers.x-postman-proxy')).to.be('true');
    });

    after(function () {
        server.close();
    });
});
<|endoftext|>


<commit_before>
var db = require('../../../system/database');

function *users(next) {

	var client = db.get();
	var body = this.request.body;
	var merchantId = body.merchantId;
	var tableId = body.tableId;

	this.body.msg = 'you suck';
	return yield next;
	var sql = 'SELECT * FROM tables WHERE merchantid = $1 AND uid = $2';
	var params = [ merchantId, tableId ];

	var results = yield client.queryPromise(sql, params);
	var result = results.rows.pop();
	var table = result.data;
	var users = table.users;

	this.body = {
		users: users
	};

	return yield next;

	var sql = 'SELECT uid, data FROM users WHERE uid IN (';

	var frag = [];
	params = [];

	for (var i = 0, len = users.length; i < len; i += 1) {
		frag.push('$' + (i + 1));
		params.push(users[i]);
	}

	sql += frag.join(',');
	sql += ')';

	var results = yield client.queryPromise(sql, params);
	users = results.rows;

	this.body = {
		users: users
	};

	return yield next;

}

/** exports **/

module.exports = users;

<commit_msg>lkjdsf<commit_after>
var db = require('../../../system/database');

function *users(next) {

	var client = db.get();
	var body = this.request.body;
	var merchantId = body.merchantId;
	var tableId = body.tableId;

	var sql = 'SELECT * FROM tables WHERE merchantId = $1 AND uid = $2';
	var params = [ merchantId, tableId ];

	var results = yield client.queryPromise(sql, params);
	var result = results.rows.pop();
	var table = result.data;
	var users = table.users;

	this.body = {
		users: users
	};

	return yield next;

	var sql = 'SELECT uid, data FROM users WHERE uid IN (';

	var frag = [];
	params = [];

	for (var i = 0, len = users.length; i < len; i += 1) {
		frag.push('$' + (i + 1));
		params.push(users[i]);
	}

	sql += frag.join(',');
	sql += ')';

	var results = yield client.queryPromise(sql, params);
	users = results.rows;

	this.body = {
		users: users
	};

	return yield next;

}

/** exports **/

module.exports = users;

<|endoftext|>


<commit_before>app.config(function ($routeProvider) {

    /** This checks if the user is authenticated for a route and what the isRequired is set to.
        Depending on whether isRequired = true, it first check if the user is authenticated and will resolve successfully
        otherwise the route will fail and the $routeChangeError event will execute, in that handler we will redirect to the rejected
        path that is resolved from this method and prevent default (prevent the route from executing) */
    var canRoute = function(isRequired) {

        return {
            /** Checks that the user is authenticated, then ensures that are requires assets are loaded */
            isAuthenticatedAndReady: function ($q, userService, $route, assetsService, appState) {
                var deferred = $q.defer();

                //don't need to check if we've redirected to login and we've already checked auth
                if (!$route.current.params.section
                    && ($route.current.params.check === false || $route.current.params.check === "false")) {
                    deferred.resolve(true);
                    return deferred.promise;
                }

                userService.isAuthenticated()
                    .then(function () {

                        assetsService._loadInitAssets().then(function() {

                            //This could be the first time has loaded after the user has logged in, in this case
                            // we need to broadcast the authenticated event - this will be handled by the startup (init)
                            // handler to set/broadcast the ready state
                            var broadcast = appState.getGlobalState("isReady") !== true;

                            userService.getCurrentUser({ broadcastEvent: broadcast }).then(function (user) {
                                //is auth, check if we allow or reject
                                if (isRequired) {

                                    //This checks the current section and will force a redirect to 'content' as the default
                                    if ($route.current.params.section.toLowerCase() === "default" || $route.current.params.section.toLowerCase() === "umbraco" || $route.current.params.section === "") {
                                        $route.current.params.section = "content";
                                    }

                                    // U4-5430, Benjamin Howarth
                                    // We need to change the current route params if the user only has access to a single section
                                    // To do this we need to grab the current user's allowed sections, then reject the promise with the correct path.
                                    if (user.allowedSections.indexOf($route.current.params.section) > -1) {
                                        //this will resolve successfully so the route will continue
                                        deferred.resolve(true);
                                    } else {
                                        deferred.reject({ path: "/" + user.allowedSections[0] });
                                    }
                                }
                                else {
                                    deferred.reject({ path: "/" });
                                }
                            });

                        });

                    }, function () {
                        //not auth, check if we allow or reject
                        if (isRequired) {
                            //the check=false is checked above so that we don't have to make another http call to check
                            //if they are logged in since we already know they are not.
                            deferred.reject({ path: "/login/false" });
                        }
                        else {
                            //this will resolve successfully so the route will continue
                            deferred.resolve(true);
                        }
                    });
                return deferred.promise;
            }
        };
    };

    /** When this is used to resolve it will attempt to log the current user out */
    var doLogout = function() {
        return {
            isLoggedOut: function ($q, userService) {
                var deferred = $q.defer();
                userService.logout().then(function () {
                    //success so continue
                    deferred.resolve(true);
                }, function() {
                    //logout failed somehow ? we'll reject with the login page i suppose
                    deferred.reject({ path: "/login/false" });
                });
                return deferred.promise;
            }
        }
    }

    $routeProvider
        .when('/login', {
            templateUrl: 'views/common/login.html',
            //ensure auth is *not* required so it will redirect to /
            resolve: canRoute(false)
        })
        .when('/login/:check', {
            templateUrl: 'views/common/login.html',
            //ensure auth is *not* required so it will redirect to /
            resolve: canRoute(false)
        })
        .when('/logout', {
             redirectTo: '/login/false',
            resolve: doLogout()
        })
        .when('/:section', {

            //This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method.
            template: "

",
            //This controller will execute for this route, then we can execute some code in order to set the template Url
            controller: function ($scope, $route, $routeParams, $location, sectionService) {

                //We are going to check the currently loaded sections for the user and if the section we are navigating
                //to has a custom route path we'll use that
                sectionService.getSectionsForUser().then(function(sections) {
                    //find the one we're requesting
                    var found = _.find(sections, function(s) {
                        return s.alias === $routeParams.section;
                    })
                    if (found && found.routePath) {
                        //there's a custom route path so redirect
                        $location.path(found.routePath);
                    }
                    else {
                        //there's no custom route path so continue as normal
                        $routeParams.url = "dashboard.aspx?app=" + $routeParams.section;
                        $scope.templateUrl = 'views/common/dashboard.html';
                    }
                });
            },
            resolve: canRoute(true)
        })
        .when('/:section/framed/:url', {
            //This occurs when we need to launch some content in an iframe
            templateUrl: function (rp) {
                if (!rp.url)
                    throw "A framed resource must have a url route parameter";

                return 'views/common/legacy.html';
            },
            resolve: canRoute(true)
        })
        .when('/:section/:tree/:method', {
            templateUrl: function (rp) {

                //if there is no method registered for this then show the dashboard
                if (!rp.method)
                    return "views/common/dashboard.html";

                return ('views/' + rp.tree + '/' + rp.method + '.html');
            },
            resolve: canRoute(true)
        })
        .when('/:section/:tree/:method/:id', {
            //This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method.
            template: "

",
            //This controller will execute for this route, then we replace the template dynamnically based on the current tree.
            controller: function ($scope, $route, $routeParams, treeService) {

                if (!$routeParams.tree || !$routeParams.method) {
                    $scope.templateUrl = "views/common/dashboard.html";
                }

                // Here we need to figure out if this route is for a package tree and if so then we need
                // to change it's convention view path to:
                // /App_Plugins/{mypackage}/backoffice/{treetype}/{method}.html

                // otherwise if it is a core tree we use the core paths:
                // views/{treetype}/{method}.html

                var packageTreeFolder = treeService.getTreePackageFolder($routeParams.tree);

                if (packageTreeFolder) {
                    $scope.templateUrl = (Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath +
                        "/" + packageTreeFolder +
                        "/backoffice/" + $routeParams.tree + "/" + $routeParams.method + ".html");
                }
                else {
                    $scope.templateUrl = ('views/' + $routeParams.tree + '/' + $routeParams.method + '.html');
                }

            },
            resolve: canRoute(true)
        })
        .otherwise({ redirectTo: '/login' });
    }).config(function ($locationProvider) {

        //$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off
        // $locationProvider.html5Mode(true);         //turn html5 mode on
    });
<commit_msg>U4-11275<commit_after>app.config(function ($routeProvider) {

    /** This checks if the user is authenticated for a route and what the isRequired is set to.
        Depending on whether isRequired = true, it first check if the user is authenticated and will resolve successfully
        otherwise the route will fail and the $routeChangeError event will execute, in that handler we will redirect to the rejected
        path that is resolved from this method and prevent default (prevent the route from executing) */
    var canRoute = function(isRequired) {

        return {
            /** Checks that the user is authenticated, then ensures that are requires assets are loaded */
            isAuthenticatedAndReady: function ($q, userService, $route, assetsService, appState) {
                var deferred = $q.defer();

                //don't need to check if we've redirected to login and we've already checked auth
                if (!$route.current.params.section
                    && ($route.current.params.check === false || $route.current.params.check === "false")) {
                    deferred.resolve(true);
                    return deferred.promise;
                }

                userService.isAuthenticated()
                    .then(function () {

                        assetsService._loadInitAssets().then(function() {

                            //This could be the first time has loaded after the user has logged in, in this case
                            // we need to broadcast the authenticated event - this will be handled by the startup (init)
                            // handler to set/broadcast the ready state
                            var broadcast = appState.getGlobalState("isReady") !== true;

                            userService.getCurrentUser({ broadcastEvent: broadcast }).then(function (user) {
                                //is auth, check if we allow or reject
                                if (isRequired) {

                                    //This checks the current section and will force a redirect to 'content' as the default
                                    if ($route.current.params.section.toLowerCase() === "default" || $route.current.params.section.toLowerCase() === "umbraco" || $route.current.params.section === "") {
                                        $route.current.params.section = "content";
                                    }

                                    // U4-5430, Benjamin Howarth
                                    // We need to change the current route params if the user only has access to a single section
                                    // To do this we need to grab the current user's allowed sections, then reject the promise with the correct path.
                                    if (user.allowedSections.indexOf($route.current.params.section) > -1) {
                                        //this will resolve successfully so the route will continue
                                        deferred.resolve(true);
                                    } else {
                                        deferred.reject({ path: "/" + user.allowedSections[0] });
                                    }
                                }
                                else {
                                    deferred.reject({ path: "/" });
                                }
                            });

                        });

                    }, function () {
                        //not auth, check if we allow or reject
                        if (isRequired) {
                            //the check=false is checked above so that we don't have to make another http call to check
                            //if they are logged in since we already know they are not.
                            deferred.reject({ path: "/login/false" });
                        }
                        else {
                            //this will resolve successfully so the route will continue
                            deferred.resolve(true);
                        }
                    });
                return deferred.promise;
            }
        };
    };

    /** When this is used to resolve it will attempt to log the current user out */
    var doLogout = function() {
        return {
            isLoggedOut: function ($q, userService) {
                var deferred = $q.defer();
                userService.logout().then(function () {
                    //success so continue
                    deferred.resolve(true);
                }, function() {
                    //logout failed somehow ? we'll reject with the login page i suppose
                    deferred.reject({ path: "/login/false" });
                });
                return deferred.promise;
            }
        }
    }

    $routeProvider
        .when('/login', {
            templateUrl: 'views/common/login.html',
            //ensure auth is *not* required so it will redirect to /
            resolve: canRoute(false)
        })
        .when('/login/:check', {
            templateUrl: 'views/common/login.html',
            //ensure auth is *not* required so it will redirect to /
            resolve: canRoute(false)
        })
        .when('/logout', {
             redirectTo: '/login/false',
            resolve: doLogout()
        })
        .when('/:section', {

            //This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method.
            template: "

",
            //This controller will execute for this route, then we can execute some code in order to set the template Url
            controller: function ($scope, $route, $routeParams, $location, sectionService) {

                //We are going to check the currently loaded sections for the user and if the section we are navigating
                //to has a custom route path we'll use that
                sectionService.getSectionsForUser().then(function(sections) {
                    //find the one we're requesting
                    var found = _.find(sections, function(s) {
                        return s.alias === $routeParams.section;
                    })
                    if (found && found.routePath) {
                        //there's a custom route path so redirect
                        $location.path(found.routePath);
                    }
                    else {
                        //there's no custom route path so continue as normal
                        $routeParams.url = "dashboard.aspx?app=" + $routeParams.section;
                        $scope.templateUrl = 'views/common/dashboard.html';
                    }
                });
            },
            resolve: canRoute(true)
        })
        .when('/:section/framed/:url', {
            //This occurs when we need to launch some content in an iframe
            templateUrl: function (rp) {
                if (!rp.url)
                    throw "A framed resource must have a url route parameter";

                return 'views/common/legacy.html';
            },
            resolve: canRoute(true)
        })
        .when('/:section/:tree/:method', {
            //This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method.
            template: "

",
            //This controller will execute for this route, then we replace the template dynamnically based on the current tree.
            controller: function ($scope, $route, $routeParams, treeService) {

                if (!$routeParams.tree || !$routeParams.method) {
                    $scope.templateUrl = "views/common/dashboard.html";
                }

                // Here we need to figure out if this route is for a package tree and if so then we need
                // to change it's convention view path to:
                // /App_Plugins/{mypackage}/backoffice/{treetype}/{method}.html

                // otherwise if it is a core tree we use the core paths:
                // views/{treetype}/{method}.html

                var packageTreeFolder = treeService.getTreePackageFolder($routeParams.tree);

                if (packageTreeFolder) {
                    $scope.templateUrl = (Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath +
                        "/" + packageTreeFolder +
                        "/backoffice/" + $routeParams.tree + "/" + $routeParams.method + ".html");
                }
                else {
                    $scope.templateUrl = ('views/' + $routeParams.tree + '/' + $routeParams.method + '.html');
                }
            },
            resolve: canRoute(true)
        })
        .when('/:section/:tree/:method/:id', {
            //This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method.
            template: "

",
            //This controller will execute for this route, then we replace the template dynamnically based on the current tree.
            controller: function ($scope, $route, $routeParams, treeService) {

                if (!$routeParams.tree || !$routeParams.method) {
                    $scope.templateUrl = "views/common/dashboard.html";
                }

                // Here we need to figure out if this route is for a package tree and if so then we need
                // to change it's convention view path to:
                // /App_Plugins/{mypackage}/backoffice/{treetype}/{method}.html

                // otherwise if it is a core tree we use the core paths:
                // views/{treetype}/{method}.html

                var packageTreeFolder = treeService.getTreePackageFolder($routeParams.tree);

                if (packageTreeFolder) {
                    $scope.templateUrl = (Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath +
                        "/" + packageTreeFolder +
                        "/backoffice/" + $routeParams.tree + "/" + $routeParams.method + ".html");
                }
                else {
                    $scope.templateUrl = ('views/' + $routeParams.tree + '/' + $routeParams.method + '.html');
                }

            },
            resolve: canRoute(true)
        })
        .otherwise({ redirectTo: '/login' });
    }).config(function ($locationProvider) {

        //$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off
        // $locationProvider.html5Mode(true);         //turn html5 mode on
    });
<|endoftext|>


<commit_before>import Module from 'Parser/Core/Module';
import SPELLS from 'common/SPELLS';

import Combatants from 'Parser/Core/Modules/Combatants';

const debug = false;

class AlwaysBeCasting extends Module {
  static dependencies = {
    combatants: Combatants,
  };

  static ABILITIES_ON_GCD = [
    // Extend this class and override this property in your spec class to implement this module.
  ];
  static FULLGCD_ABILITIES = [
    //Override this property in your spec class
  ];

  /* eslint-disable no-useless-computed-key */
  static HASTE_BUFFS = { // This includes debuffs
    [SPELLS.BLOODLUST.id]: 0.3,
    [SPELLS.HEROISM.id]: 0.3,
    [SPELLS.TIME_WARP.id]: 0.3,
    [SPELLS.ANCIENT_HYSTERIA.id]: 0.3, // Hunter pet BL
    [SPELLS.NETHERWINDS.id]: 0.3, // Hunter pet BL
    [SPELLS.DRUMS_OF_FURY.id]: 0.25,
    [SPELLS.DRUMS_OF_THE_MOUNTAIN.id]: 0.25,
    [SPELLS.DRUMS_OF_RAGE.id]: 0.25,
    [SPELLS.HOLY_AVENGER_TALENT.id]: 0.3,
    [SPELLS.BERSERKING.id]: 0.15,
    [202842]: 0.1, // Rapid Innervation (Balance Druid trait increasing Haste from Innervate)
    [SPELLS.POWER_INFUSION_TALENT.id]: 0.25,
    [240673]: 800 / 37500, // Shadow Priest artifact trait that shared with 4 allies: http://www.wowhead.com/spell=240673/mind-quickening
    [SPELLS.WARLOCK_AFFLI_T20_4P_BUFF.id]: 0.15,
    [SPELLS.TRUESHOT.id]: 0.4, //MM Hunter main CD
    [242543]: 3619 / 37500, // Chalice of Moonlight Haste buff (900 item level since we can't scale with item level yet)
    // Boss abilities:
    [209166]: 0.3, // DEBUFF - Fast Time from Elisande
    [209165]: -0.3, // DEBUFF - Slow Time from Elisande
    // [208944]: -Infinity, // DEBUFF - Time Stop from Elisande
  };

  static STACKABLE_HASTE_BUFFS = {
    //Stackable haste buffs - Set Haste per stack and MaxStacks (0 for no max) - See example in Balance Druid ABC
    //[id] : {
    //  Haste: (combatant) => (),
    //  CurrentStacks: 0,
    //  MaxStacks: 0,
    //},
  }

  totalTimeWasted = 0;
  totalHealingTimeWasted = 0;

  lastCastFinishedTimestamp = null;
  lastHealingCastFinishedTimestamp = null;

  _currentlyCasting = null;
  on_byPlayer_begincast(event) {
    const cast = {
      begincast: event,
      cast: null,
    };

    this._currentlyCasting = cast;
  }
  on_byPlayer_cast(event) {
    const spellId = event.ability.guid;
    const isOnGcd = this.constructor.ABILITIES_ON_GCD.indexOf(spellId) !== -1;
    // This fixes a crash when boss abilities are registered as casts which could even happen while channeling. For example on Trilliax: http://i.imgur.com/7QAFy1q.png
    if (!isOnGcd) {
      return;
    }

    if (this._currentlyCasting && this._currentlyCasting.begincast.ability.guid !== event.ability.guid) {
      // This is a different spell then registered in `begincast`, previous cast was interrupted
      this._currentlyCasting = null;
    }

    const logEntry = this._currentlyCasting || {
      begincast: null,
    };
    logEntry.cast = event;

    this.processCast(logEntry);
    this._currentlyCasting = null;
  }

  processCast({ begincast, cast }) {
    if (!cast) {
      return;
    }
    const spellId = cast.ability.guid;
    const isOnGcd = this.constructor.ABILITIES_ON_GCD.indexOf(spellId) !== -1;
    const isFullGcd = this.constructor.FULLGCD_ABILITIES.indexOf(spellId) !== -1;

    if (!isOnGcd) {
      debug && console.log(`%cABC: ${cast.ability.name} (${spellId}) ignored`, 'color: gray');
      return;
    }

    const globalCooldown = isFullGcd ? 1500 : this.constructor.calculateGlobalCooldown(this.currentHaste) * 1000;

    const castStartTimestamp = (begincast ? begincast : cast).timestamp;

    this.recordCastTime(
      castStartTimestamp,
      globalCooldown,
      begincast,
      cast,
      spellId
    );
  }
  recordCastTime(
    castStartTimestamp,
    globalCooldown,
    begincast,
    cast,
    spellId
  ) {
    const timeWasted = castStartTimestamp - (this.lastCastFinishedTimestamp || this.owner.fight.start_time);
    this.totalTimeWasted += timeWasted;

    debug && console.log(`ABC: tot.:${Math.floor(this.totalTimeWasted)}\tthis:${Math.floor(timeWasted)}\t%c${cast.ability.name} (${spellId}): ${begincast ? 'channeled' : 'instant'}\t%cgcd:${Math.floor(globalCooldown)}\t%ccasttime:${cast.timestamp - castStartTimestamp}\tfighttime:${castStartTimestamp - this.owner.fight.start_time}`, 'color:red', 'color:green', 'color:black');

    this.lastCastFinishedTimestamp = Math.max(castStartTimestamp + globalCooldown, cast.timestamp);
  }
  baseHaste = null;
  currentHaste = null;
  on_initialized() {
    const combatant = this.combatants.selected;
    this.baseHaste = combatant.hastePercentage;
    this.currentHaste = this.baseHaste;

    debug && console.log(`ABC: Current haste: ${this.currentHaste}`);
  }
  on_toPlayer_applybuff(event) {
    this.applyActiveBuff(event);
  }
  //Added event listener for buff stacks applied
  on_toPlayer_applybuffstack(event){
    this.applyBuffStack(event);
  }
  on_toPlayer_removebuff(event) {
    this.removeActiveBuff(event);
  }
  on_toPlayer_applydebuff(event) {
    this.applyActiveBuff(event);
  }
  on_toPlayer_removedebuff(event) {
    this.removeActiveBuff(event);
  }
  applyActiveBuff(event) {
    const spellId = event.ability.guid;
    let hasteGain;

    //Added check so it gets the correct one, and adds stacks if necessary
    if (this.constructor.HASTE_BUFFS[spellId]){
      hasteGain = this.constructor.HASTE_BUFFS[spellId];
    }
    else if (this.constructor.STACKABLE_HASTE_BUFFS[spellId]){
      hasteGain = this.constructor.STACKABLE_HASTE_BUFFS[spellId].Haste(this.combatants.selected);
      this.constructor.STACKABLE_HASTE_BUFFS[spellId].CurrentStacks ++;
    }

    if (hasteGain) {
      this.applyHasteGain(hasteGain);

      debug && console.log(`ABC: Current haste: ${this.currentHaste} (gained ${hasteGain} from ${spellId})`);
    }
  }
  //Added apply buff stack event for stackable haste buffs
  applyBuffStack(event) {
    const spellId = event.ability.guid;
    const stackInfo = this.constructor.STACKABLE_HASTE_BUFFS[spellId];
    let hasteGain;

    if (stackInfo){
      hasteGain = stackInfo.Haste(this.combatants.selected);
    }

    if (hasteGain) {
      //Only add haste stack if max stacks not already reached
      if (stackInfo.MaxStacks === 0 || stackInfo.CurrentStacks < stackInfo.MaxStacks){
        this.applyHasteGain(hasteGain);
        stackInfo.CurrentStacks ++;
      }

      debug && console.log(`ABC: Current haste: ${this.currentHaste} (gained ${hasteGain} from ${spellId})`);
    }
  }
  removeActiveBuff(event) {
    const spellId = event.ability.guid;
    let hasteLoss;

    //Added check so it gets the correct one
    if (this.constructor.HASTE_BUFFS[spellId]){
      hasteLoss = this.constructor.HASTE_BUFFS[spellId];
    }
    else if (this.constructor.STACKABLE_HASTE_BUFFS[spellId]){
      //When buff loss, it should lose haste equal to base buff haste * number of stacks
      hasteLoss = this.constructor.STACKABLE_HASTE_BUFFS[spellId].Haste(this.combatants.selected) * this.constructor.STACKABLE_HASTE_BUFFS[spellId].CurrentStacks;
      this.constructor.STACKABLE_HASTE_BUFFS[spellId].CurrentStacks = 0;
    }

    if (hasteLoss) {
      this.applyHasteLoss(hasteLoss);

      debug && console.log(`ABC: Current haste: ${this.currentHaste} (lost ${hasteLoss} from ${spellId})`);
    }
  }

  static calculateGlobalCooldown(haste) {
    const gcd = 1.5 / (1 + haste);
    //Check the gcd doesnt go under the limit
    return gcd > 0.75 ? gcd : 0.75;
  }
  static applyHasteGain(baseHaste, hasteGain) {
    return baseHaste * (1 + hasteGain) + hasteGain;
  }
  applyHasteGain(hasteGain) {
    this.currentHaste = this.constructor.applyHasteGain(this.currentHaste, hasteGain);
  }
  static applyHasteLoss(baseHaste, hasteLoss) {
    return (baseHaste - hasteLoss) / (1 + hasteLoss);
  }
  applyHasteLoss(hasteGain) {
    this.currentHaste = this.constructor.applyHasteLoss(this.currentHaste, hasteGain);
  }
}

export default AlwaysBeCasting;
<commit_msg>Remove a bunch of useless Comments :)<commit_after>import Module from 'Parser/Core/Module';
import SPELLS from 'common/SPELLS';

import Combatants from 'Parser/Core/Modules/Combatants';

const debug = false;

class AlwaysBeCasting extends Module {
  static dependencies = {
    combatants: Combatants,
  };

  static ABILITIES_ON_GCD = [
    // Extend this class and override this property in your spec class to implement this module.
  ];
  static FULLGCD_ABILITIES = [
    //Override this property in your spec class
  ];

  /* eslint-disable no-useless-computed-key */
  static HASTE_BUFFS = { // This includes debuffs
    [SPELLS.BLOODLUST.id]: 0.3,
    [SPELLS.HEROISM.id]: 0.3,
    [SPELLS.TIME_WARP.id]: 0.3,
    [SPELLS.ANCIENT_HYSTERIA.id]: 0.3, // Hunter pet BL
    [SPELLS.NETHERWINDS.id]: 0.3, // Hunter pet BL
    [SPELLS.DRUMS_OF_FURY.id]: 0.25,
    [SPELLS.DRUMS_OF_THE_MOUNTAIN.id]: 0.25,
    [SPELLS.DRUMS_OF_RAGE.id]: 0.25,
    [SPELLS.HOLY_AVENGER_TALENT.id]: 0.3,
    [SPELLS.BERSERKING.id]: 0.15,
    [202842]: 0.1, // Rapid Innervation (Balance Druid trait increasing Haste from Innervate)
    [SPELLS.POWER_INFUSION_TALENT.id]: 0.25,
    [240673]: 800 / 37500, // Shadow Priest artifact trait that shared with 4 allies: http://www.wowhead.com/spell=240673/mind-quickening
    [SPELLS.WARLOCK_AFFLI_T20_4P_BUFF.id]: 0.15,
    [SPELLS.TRUESHOT.id]: 0.4, //MM Hunter main CD
    [242543]: 3619 / 37500, // Chalice of Moonlight Haste buff (900 item level since we can't scale with item level yet)
    // Boss abilities:
    [209166]: 0.3, // DEBUFF - Fast Time from Elisande
    [209165]: -0.3, // DEBUFF - Slow Time from Elisande
    // [208944]: -Infinity, // DEBUFF - Time Stop from Elisande
  };

  static STACKABLE_HASTE_BUFFS = {
    //Stackable haste buffs - Set Haste per stack and MaxStacks (0 for no max) - See example in Balance Druid ABC
    //[id] : {
    //  Haste: (combatant) => (),
    //  CurrentStacks: 0,
    //  MaxStacks: 0,
    //},
  }

  totalTimeWasted = 0;
  totalHealingTimeWasted = 0;

  lastCastFinishedTimestamp = null;
  lastHealingCastFinishedTimestamp = null;

  _currentlyCasting = null;
  on_byPlayer_begincast(event) {
    const cast = {
      begincast: event,
      cast: null,
    };

    this._currentlyCasting = cast;
  }
  on_byPlayer_cast(event) {
    const spellId = event.ability.guid;
    const isOnGcd = this.constructor.ABILITIES_ON_GCD.indexOf(spellId) !== -1;
    // This fixes a crash when boss abilities are registered as casts which could even happen while channeling. For example on Trilliax: http://i.imgur.com/7QAFy1q.png
    if (!isOnGcd) {
      return;
    }

    if (this._currentlyCasting && this._currentlyCasting.begincast.ability.guid !== event.ability.guid) {
      // This is a different spell then registered in `begincast`, previous cast was interrupted
      this._currentlyCasting = null;
    }

    const logEntry = this._currentlyCasting || {
      begincast: null,
    };
    logEntry.cast = event;

    this.processCast(logEntry);
    this._currentlyCasting = null;
  }

  processCast({ begincast, cast }) {
    if (!cast) {
      return;
    }
    const spellId = cast.ability.guid;
    const isOnGcd = this.constructor.ABILITIES_ON_GCD.indexOf(spellId) !== -1;
    const isFullGcd = this.constructor.FULLGCD_ABILITIES.indexOf(spellId) !== -1;

    if (!isOnGcd) {
      debug && console.log(`%cABC: ${cast.ability.name} (${spellId}) ignored`, 'color: gray');
      return;
    }

    const globalCooldown = isFullGcd ? 1500 : this.constructor.calculateGlobalCooldown(this.currentHaste) * 1000;

    const castStartTimestamp = (begincast ? begincast : cast).timestamp;

    this.recordCastTime(
      castStartTimestamp,
      globalCooldown,
      begincast,
      cast,
      spellId
    );
  }
  recordCastTime(
    castStartTimestamp,
    globalCooldown,
    begincast,
    cast,
    spellId
  ) {
    const timeWasted = castStartTimestamp - (this.lastCastFinishedTimestamp || this.owner.fight.start_time);
    this.totalTimeWasted += timeWasted;

    debug && console.log(`ABC: tot.:${Math.floor(this.totalTimeWasted)}\tthis:${Math.floor(timeWasted)}\t%c${cast.ability.name} (${spellId}): ${begincast ? 'channeled' : 'instant'}\t%cgcd:${Math.floor(globalCooldown)}\t%ccasttime:${cast.timestamp - castStartTimestamp}\tfighttime:${castStartTimestamp - this.owner.fight.start_time}`, 'color:red', 'color:green', 'color:black');

    this.lastCastFinishedTimestamp = Math.max(castStartTimestamp + globalCooldown, cast.timestamp);
  }
  baseHaste = null;
  currentHaste = null;
  on_initialized() {
    const combatant = this.combatants.selected;
    this.baseHaste = combatant.hastePercentage;
    this.currentHaste = this.baseHaste;

    debug && console.log(`ABC: Current haste: ${this.currentHaste}`);
  }
  on_toPlayer_applybuff(event) {
    this.applyActiveBuff(event);
  }
  on_toPlayer_applybuffstack(event){
    this.applyBuffStack(event);
  }
  on_toPlayer_removebuff(event) {
    this.removeActiveBuff(event);
  }
  on_toPlayer_applydebuff(event) {
    this.applyActiveBuff(event);
  }
  on_toPlayer_removedebuff(event) {
    this.removeActiveBuff(event);
  }
  applyActiveBuff(event) {
    const spellId = event.ability.guid;
    let hasteGain;

    if (this.constructor.HASTE_BUFFS[spellId]){
      hasteGain = this.constructor.HASTE_BUFFS[spellId];
    }
    else if (this.constructor.STACKABLE_HASTE_BUFFS[spellId]){
      hasteGain = this.constructor.STACKABLE_HASTE_BUFFS[spellId].Haste(this.combatants.selected);
      this.constructor.STACKABLE_HASTE_BUFFS[spellId].CurrentStacks ++;
    }

    if (hasteGain) {
      this.applyHasteGain(hasteGain);

      debug && console.log(`ABC: Current haste: ${this.currentHaste} (gained ${hasteGain} from ${spellId})`);
    }
  }
  applyBuffStack(event) {
    const spellId = event.ability.guid;
    const stackInfo = this.constructor.STACKABLE_HASTE_BUFFS[spellId];
    let hasteGain;

    if (stackInfo){
      hasteGain = stackInfo.Haste(this.combatants.selected);
    }

    if (hasteGain) {
      //Only add haste stack if max stacks not already reached
      if (stackInfo.MaxStacks === 0 || stackInfo.CurrentStacks < stackInfo.MaxStacks){
        this.applyHasteGain(hasteGain);
        stackInfo.CurrentStacks ++;
      }

      debug && console.log(`ABC: Current haste: ${this.currentHaste} (gained ${hasteGain} from ${spellId})`);
    }
  }
  removeActiveBuff(event) {
    const spellId = event.ability.guid;
    let hasteLoss;

    if (this.constructor.HASTE_BUFFS[spellId]){
      hasteLoss = this.constructor.HASTE_BUFFS[spellId];
    }
    else if (this.constructor.STACKABLE_HASTE_BUFFS[spellId]){
      //When buff loss, it should lose haste equal to base buff haste * number of stacks
      hasteLoss = this.constructor.STACKABLE_HASTE_BUFFS[spellId].Haste(this.combatants.selected) * this.constructor.STACKABLE_HASTE_BUFFS[spellId].CurrentStacks;
      this.constructor.STACKABLE_HASTE_BUFFS[spellId].CurrentStacks = 0;
    }

    if (hasteLoss) {
      this.applyHasteLoss(hasteLoss);

      debug && console.log(`ABC: Current haste: ${this.currentHaste} (lost ${hasteLoss} from ${spellId})`);
    }
  }

  static calculateGlobalCooldown(haste) {
    const gcd = 1.5 / (1 + haste);
    //Check the gcd doesnt go under the limit
    return gcd > 0.75 ? gcd : 0.75;
  }
  static applyHasteGain(baseHaste, hasteGain) {
    return baseHaste * (1 + hasteGain) + hasteGain;
  }
  applyHasteGain(hasteGain) {
    this.currentHaste = this.constructor.applyHasteGain(this.currentHaste, hasteGain);
  }
  static applyHasteLoss(baseHaste, hasteLoss) {
    return (baseHaste - hasteLoss) / (1 + hasteLoss);
  }
  applyHasteLoss(hasteGain) {
    this.currentHaste = this.constructor.applyHasteLoss(this.currentHaste, hasteGain);
  }
}

export default AlwaysBeCasting;
<|endoftext|>


<commit_before>const fs = require('fs-extra');
const prettyBytes = require('pretty-bytes');
const moment = require('moment');

const sourceDir = process.argv[2];
const indexFile = 'index.html';
const indexTpl = indexFile + '.tpl';
const tableTpl = 'table.html.tpl';
const styleFile = 'style.css';
const listFile = 'list.txt';

const clockSince = moment('2017-04');

function numberFormat(n) {
  return new Intl.NumberFormat().format(n);
}

function fileInfo(gameCounts, variant, n) {
  const path = sourceDir + '/' + variant + '/' + n;
  return fs.stat(path).then(s => {
    const dateStr = n.replace(/.+(\d{4}-\d{2})\.pgn\.bz2/, '$1');
    const m = moment(dateStr);
    const shortName = n.replace(/.+(\d{4}-\d{2}.+)$/, '$1');
    const hasClock = m.unix() >= clockSince.unix();
    return {
      name: n,
      shortName: shortName,
      path: path,
      size: s.size,
      date: m,
      clock: hasClock,
      games: parseInt(gameCounts[n]) || 0
    };
  });
}

function getGameCounts(variant) {
  return fs.readFile(sourceDir + '/' + variant + '/counts.txt', { encoding: 'utf8' }).then(c => {
    var gameCounts = {};
    c.split('\n').map(l => l.trim()).forEach(line => {
      if (line !== '') gameCounts[line.split(' ')[0]] = line.split(' ')[1];
    });
    return gameCounts;
  });
}

function getFiles(variant) {
  return function(gameCounts) {
    return fs.readdir(sourceDir + '/' + variant).then(items => {
      return Promise.all(
        items.filter(n => n.includes('.pgn.bz2')).map(n => fileInfo(gameCounts, variant, n))
      );
    }).then(items => items.sort((a, b) => b.date.unix() - a.date.unix()));
  }
}

function renderTable(files, variant) {
  return files.map(f => {
    return `

    ${f.date.format('MMMM YYYY')}
    ${prettyBytes(f.size)}
    ${f.games ? numberFormat(f.games) : '?'}
    ${f.clock ? '✔' : ''}
    ${f.shortName}

`;
  }).join('\n');
}

function renderTotal(files) {
  return `

  Total: ${files.length} files
  ${prettyBytes(files.map(f => f.size).reduce((a, b) => a + b))}
  ${numberFormat(files.map(f => f.games).reduce((a, b) => a + b))}

`;
}

function renderList(files, variant) {
  return files.map(f => {
    return `https://database.lichess.org/${variant}/${f.name}`;
  }).join('\n');
}

function processVariantAndReturnTable(variant, template) {
    return getGameCounts(variant).then(getFiles(variant)).then(files => {
        return fs.writeFile(sourceDir + '/' + variant + '/' + listFile, renderList(files, variant)).then(_ => {
          return template
            .replace(//, numberFormat(files.map(f => f.games).reduce((a, b) => a + b)))
            .replace(//, renderTable(files, variant))
            .replace(//, renderTotal(files))
            .replace(//g, variant);
        });
    });
}

function replaceVariant(variant, tableTemplate) {
    return function(fullTemplate) {
        return processVariantAndReturnTable(variant, tableTemplate).then(tbl => {
            return fullTemplate.replace('', tbl);
        });
    };
}

process.on('unhandledRejection', r => console.log(r));

Promise.all([
  fs.readFile(indexTpl, { encoding: 'utf8' }),
  fs.readFile(tableTpl, { encoding: 'utf8' }),
  fs.readFile(styleFile, { encoding: 'utf8' })
]).then(arr => {
  const rv = function(variant) { return replaceVariant(variant, arr[1]); };
  return rv('standard')(arr[0])
    .then(rv('antichess'))
    .then(rv('atomic'))
    .then(rv('chess960'))
    .then(rv('crazyhouse'))
    .then(rv('horde'))
    .then(rv('kingOfTheHill'))
    .then(rv('racingKings'))
    .then(rv('threeCheck'))
    .then(rendered => {
        return fs.writeFile(sourceDir + '/' + indexFile, rendered.replace(//, arr[2]));
    });
});
<commit_msg>fix formatting<commit_after>const fs = require('fs-extra');
const prettyBytes = require('pretty-bytes');
const moment = require('moment');

const sourceDir = process.argv[2];
const indexFile = 'index.html';
const indexTpl = indexFile + '.tpl';
const tableTpl = 'table.html.tpl';
const styleFile = 'style.css';
const listFile = 'list.txt';

const clockSince = moment('2017-04');

function numberFormat(n) {
  return new Intl.NumberFormat().format(n);
}

function fileInfo(gameCounts, variant, n) {
  const path = sourceDir + '/' + variant + '/' + n;
  return fs.stat(path).then(s => {
    const dateStr = n.replace(/.+(\d{4}-\d{2})\.pgn\.bz2/, '$1');
    const m = moment(dateStr);
    const shortName = n.replace(/.+(\d{4}-\d{2}.+)$/, '$1');
    const hasClock = m.unix() >= clockSince.unix();
    return {
      name: n,
      shortName: shortName,
      path: path,
      size: s.size,
      date: m,
      clock: hasClock,
      games: parseInt(gameCounts[n]) || 0
    };
  });
}

function getGameCounts(variant) {
  return fs.readFile(sourceDir + '/' + variant + '/counts.txt', { encoding: 'utf8' }).then(c => {
    var gameCounts = {};
    c.split('\n').map(l => l.trim()).forEach(line => {
      if (line !== '') gameCounts[line.split(' ')[0]] = line.split(' ')[1];
    });
    return gameCounts;
  });
}

function getFiles(variant) {
  return function(gameCounts) {
    return fs.readdir(sourceDir + '/' + variant).then(items => {
      return Promise.all(
        items.filter(n => n.includes('.pgn.bz2')).map(n => fileInfo(gameCounts, variant, n))
      );
    }).then(items => items.sort((a, b) => b.date.unix() - a.date.unix()));
  }
}

function renderTable(files, variant) {
  return files.map(f => {
    return `

    ${f.date.format('MMMM YYYY')}
    ${prettyBytes(f.size)}
    ${f.games ? numberFormat(f.games) : '?'}
    ${f.clock ? '✔' : ''}
    ${f.shortName}

`;
  }).join('\n');
}

function renderTotal(files) {
  return `

  Total: ${files.length} files
  ${prettyBytes(files.map(f => f.size).reduce((a, b) => a + b))}
  ${numberFormat(files.map(f => f.games).reduce((a, b) => a + b))}

`;
}

function renderList(files, variant) {
  return files.map(f => {
    return `https://database.lichess.org/${variant}/${f.name}`;
  }).join('\n');
}

function processVariantAndReturnTable(variant, template) {
  return getGameCounts(variant).then(getFiles(variant)).then(files => {
    return fs.writeFile(sourceDir + '/' + variant + '/' + listFile, renderList(files, variant)).then(_ => {
      return template
        .replace(//, numberFormat(files.map(f => f.games).reduce((a, b) => a + b)))
        .replace(//, renderTable(files, variant))
        .replace(//, renderTotal(files))
        .replace(//g, variant);
    });
  });
}

function replaceVariant(variant, tableTemplate) {
  return function(fullTemplate) {
    return processVariantAndReturnTable(variant, tableTemplate).then(tbl => {
      return fullTemplate.replace('', tbl);
    });
  };
}

process.on('unhandledRejection', r => console.log(r));

Promise.all([
  fs.readFile(indexTpl, { encoding: 'utf8' }),
  fs.readFile(tableTpl, { encoding: 'utf8' }),
  fs.readFile(styleFile, { encoding: 'utf8' })
]).then(arr => {
  const rv = function(variant) { return replaceVariant(variant, arr[1]); };
  return rv('standard')(arr[0])
    .then(rv('antichess'))
    .then(rv('atomic'))
    .then(rv('chess960'))
    .then(rv('crazyhouse'))
    .then(rv('horde'))
    .then(rv('kingOfTheHill'))
    .then(rv('racingKings'))
    .then(rv('threeCheck'))
    .then(rendered => {
      return fs.writeFile(sourceDir + '/' + indexFile, rendered.replace(//, arr[2]));
    });
});
<|endoftext|>


<commit_before>'use strict';

var test = require('tape');
var inspect = require('object-inspect');
var SaferBuffer = require('safer-buffer').Buffer;
var forEach = require('for-each');
var utils = require('../lib/utils');

test('merge()', function (t) {
    t.deepEqual(utils.merge(null, true), [null, true], 'merges true into null');

    t.deepEqual(utils.merge(null, [42]), [null, 42], 'merges null into an array');

    t.deepEqual(utils.merge({ a: 'b' }, { a: 'c' }), { a: ['b', 'c'] }, 'merges two objects with the same key');

    var oneMerged = utils.merge({ foo: 'bar' }, { foo: { first: '123' } });
    t.deepEqual(oneMerged, { foo: ['bar', { first: '123' }] }, 'merges a standalone and an object into an array');

    var twoMerged = utils.merge({ foo: ['bar', { first: '123' }] }, { foo: { second: '456' } });
    t.deepEqual(twoMerged, { foo: { 0: 'bar', 1: { first: '123' }, second: '456' } }, 'merges a standalone and two objects into an array');

    var sandwiched = utils.merge({ foo: ['bar', { first: '123', second: '456' }] }, { foo: 'baz' });
    t.deepEqual(sandwiched, { foo: ['bar', { first: '123', second: '456' }, 'baz'] }, 'merges an object sandwiched by two standalones into an array');

    var nestedArrays = utils.merge({ foo: ['baz'] }, { foo: ['bar', 'xyzzy'] });
    t.deepEqual(nestedArrays, { foo: ['baz', 'bar', 'xyzzy'] });

    var noOptionsNonObjectSource = utils.merge({ foo: 'baz' }, 'bar');
    t.deepEqual(noOptionsNonObjectSource, { foo: 'baz', bar: true });

    t.test(
        'avoids invoking array setters unnecessarily',
        { skip: typeof Object.defineProperty !== 'function' },
        function (st) {
            var setCount = 0;
            var getCount = 0;
            var observed = [];
            Object.defineProperty(observed, 0, {
                get: function () {
                    getCount += 1;
                    return { bar: 'baz' };
                },
                set: function () { setCount += 1; }
            });
            utils.merge(observed, [null]);
            st.equal(setCount, 0);
            st.equal(getCount, 1);
            observed[0] = observed[0]; // eslint-disable-line no-self-assign
            st.equal(setCount, 1);
            st.equal(getCount, 2);
            st.end();
        }
    );

    t.end();
});

test('assign()', function (t) {
    var target = { a: 1, b: 2 };
    var source = { b: 3, c: 4 };
    var result = utils.assign(target, source);

    t.equal(result, target, 'returns the target');
    t.deepEqual(target, { a: 1, b: 3, c: 4 }, 'target and source are merged');
    t.deepEqual(source, { b: 3, c: 4 }, 'source is untouched');

    t.end();
});

test('combine()', function (t) {
    t.test('both arrays', function (st) {
        var a = [1];
        var b = [2];
        var combined = utils.combine(a, b);

        st.deepEqual(a, [1], 'a is not mutated');
        st.deepEqual(b, [2], 'b is not mutated');
        st.notEqual(a, combined, 'a !== combined');
        st.notEqual(b, combined, 'b !== combined');
        st.deepEqual(combined, [1, 2], 'combined is a + b');

        st.end();
    });

    t.test('one array, one non-array', function (st) {
        var aN = 1;
        var a = [aN];
        var bN = 2;
        var b = [bN];

        var combinedAnB = utils.combine(aN, b);
        st.deepEqual(b, [bN], 'b is not mutated');
        st.notEqual(aN, combinedAnB, 'aN + b !== aN');
        st.notEqual(a, combinedAnB, 'aN + b !== a');
        st.notEqual(bN, combinedAnB, 'aN + b !== bN');
        st.notEqual(b, combinedAnB, 'aN + b !== b');
        st.deepEqual([1, 2], combinedAnB, 'first argument is array-wrapped when not an array');

        var combinedABn = utils.combine(a, bN);
        st.deepEqual(a, [aN], 'a is not mutated');
        st.notEqual(aN, combinedABn, 'a + bN !== aN');
        st.notEqual(a, combinedABn, 'a + bN !== a');
        st.notEqual(bN, combinedABn, 'a + bN !== bN');
        st.notEqual(b, combinedABn, 'a + bN !== b');
        st.deepEqual([1, 2], combinedABn, 'second argument is array-wrapped when not an array');

        st.end();
    });

    t.test('neither is an array', function (st) {
        var combined = utils.combine(1, 2);
        st.notEqual(1, combined, '1 + 2 !== 1');
        st.notEqual(2, combined, '1 + 2 !== 2');
        st.deepEqual([1, 2], combined, 'both arguments are array-wrapped when not an array');

        st.end();
    });

    t.end();
});

test('isBuffer()', function (t) {
    forEach([null, undefined, true, false, '', 'abc', 42, 0, NaN, {}, [], function () {}, /a/g], function (x) {
        t.equal(utils.isBuffer(x), false, inspect(x) + ' is not a buffer');
    });

    var fakeBuffer = { constructor: Buffer };
    t.equal(utils.isBuffer(fakeBuffer), false, 'fake buffer is not a buffer');

    var saferBuffer = SaferBuffer.from('abc');
    t.equal(utils.isBuffer(saferBuffer), true, 'SaferBuffer instance is a buffer');

    var buffer = Buffer.from('abc');
    t.equal(utils.isBuffer(buffer), true, 'real Buffer instance is a buffer');
    t.end();
});
<commit_msg>[Tests] fix Buffer tests to work in node < 4.5 and node < 5.10<commit_after>'use strict';

var test = require('tape');
var inspect = require('object-inspect');
var SaferBuffer = require('safer-buffer').Buffer;
var forEach = require('for-each');
var utils = require('../lib/utils');

test('merge()', function (t) {
    t.deepEqual(utils.merge(null, true), [null, true], 'merges true into null');

    t.deepEqual(utils.merge(null, [42]), [null, 42], 'merges null into an array');

    t.deepEqual(utils.merge({ a: 'b' }, { a: 'c' }), { a: ['b', 'c'] }, 'merges two objects with the same key');

    var oneMerged = utils.merge({ foo: 'bar' }, { foo: { first: '123' } });
    t.deepEqual(oneMerged, { foo: ['bar', { first: '123' }] }, 'merges a standalone and an object into an array');

    var twoMerged = utils.merge({ foo: ['bar', { first: '123' }] }, { foo: { second: '456' } });
    t.deepEqual(twoMerged, { foo: { 0: 'bar', 1: { first: '123' }, second: '456' } }, 'merges a standalone and two objects into an array');

    var sandwiched = utils.merge({ foo: ['bar', { first: '123', second: '456' }] }, { foo: 'baz' });
    t.deepEqual(sandwiched, { foo: ['bar', { first: '123', second: '456' }, 'baz'] }, 'merges an object sandwiched by two standalones into an array');

    var nestedArrays = utils.merge({ foo: ['baz'] }, { foo: ['bar', 'xyzzy'] });
    t.deepEqual(nestedArrays, { foo: ['baz', 'bar', 'xyzzy'] });

    var noOptionsNonObjectSource = utils.merge({ foo: 'baz' }, 'bar');
    t.deepEqual(noOptionsNonObjectSource, { foo: 'baz', bar: true });

    t.test(
        'avoids invoking array setters unnecessarily',
        { skip: typeof Object.defineProperty !== 'function' },
        function (st) {
            var setCount = 0;
            var getCount = 0;
            var observed = [];
            Object.defineProperty(observed, 0, {
                get: function () {
                    getCount += 1;
                    return { bar: 'baz' };
                },
                set: function () { setCount += 1; }
            });
            utils.merge(observed, [null]);
            st.equal(setCount, 0);
            st.equal(getCount, 1);
            observed[0] = observed[0]; // eslint-disable-line no-self-assign
            st.equal(setCount, 1);
            st.equal(getCount, 2);
            st.end();
        }
    );

    t.end();
});

test('assign()', function (t) {
    var target = { a: 1, b: 2 };
    var source = { b: 3, c: 4 };
    var result = utils.assign(target, source);

    t.equal(result, target, 'returns the target');
    t.deepEqual(target, { a: 1, b: 3, c: 4 }, 'target and source are merged');
    t.deepEqual(source, { b: 3, c: 4 }, 'source is untouched');

    t.end();
});

test('combine()', function (t) {
    t.test('both arrays', function (st) {
        var a = [1];
        var b = [2];
        var combined = utils.combine(a, b);

        st.deepEqual(a, [1], 'a is not mutated');
        st.deepEqual(b, [2], 'b is not mutated');
        st.notEqual(a, combined, 'a !== combined');
        st.notEqual(b, combined, 'b !== combined');
        st.deepEqual(combined, [1, 2], 'combined is a + b');

        st.end();
    });

    t.test('one array, one non-array', function (st) {
        var aN = 1;
        var a = [aN];
        var bN = 2;
        var b = [bN];

        var combinedAnB = utils.combine(aN, b);
        st.deepEqual(b, [bN], 'b is not mutated');
        st.notEqual(aN, combinedAnB, 'aN + b !== aN');
        st.notEqual(a, combinedAnB, 'aN + b !== a');
        st.notEqual(bN, combinedAnB, 'aN + b !== bN');
        st.notEqual(b, combinedAnB, 'aN + b !== b');
        st.deepEqual([1, 2], combinedAnB, 'first argument is array-wrapped when not an array');

        var combinedABn = utils.combine(a, bN);
        st.deepEqual(a, [aN], 'a is not mutated');
        st.notEqual(aN, combinedABn, 'a + bN !== aN');
        st.notEqual(a, combinedABn, 'a + bN !== a');
        st.notEqual(bN, combinedABn, 'a + bN !== bN');
        st.notEqual(b, combinedABn, 'a + bN !== b');
        st.deepEqual([1, 2], combinedABn, 'second argument is array-wrapped when not an array');

        st.end();
    });

    t.test('neither is an array', function (st) {
        var combined = utils.combine(1, 2);
        st.notEqual(1, combined, '1 + 2 !== 1');
        st.notEqual(2, combined, '1 + 2 !== 2');
        st.deepEqual([1, 2], combined, 'both arguments are array-wrapped when not an array');

        st.end();
    });

    t.end();
});

test('isBuffer()', function (t) {
    forEach([null, undefined, true, false, '', 'abc', 42, 0, NaN, {}, [], function () {}, /a/g], function (x) {
        t.equal(utils.isBuffer(x), false, inspect(x) + ' is not a buffer');
    });

    var fakeBuffer = { constructor: Buffer };
    t.equal(utils.isBuffer(fakeBuffer), false, 'fake buffer is not a buffer');

    var saferBuffer = SaferBuffer.from('abc');
    t.equal(utils.isBuffer(saferBuffer), true, 'SaferBuffer instance is a buffer');

    var buffer = Buffer.from ? Buffer.from('abc') : new Buffer('abc');
    t.equal(utils.isBuffer(buffer), true, 'real Buffer instance is a buffer');
    t.end();
});
<|endoftext|>


<commit_before>import {introJs} from 'intro.js';
import 'intro.js/introjs.css';

module.exports = function () {
  const steps = [];
  const elems = document.getElementsByClassName('help-dialog');

  for (let elem of elems) {
    steps.push(Object.assign({
      element: elem.parentElement,
      intro: elem.innerHTML
    }, elem.dataset));
  }

  const i = introJs();
  i.addSteps(steps);

  i.setOptions({
    nextLabel: 'Suivant →',
    prevLabel: '← Précédent',
    skipLabel: 'Passer',
    doneLabel: 'Terminé'
  });

  if (steps.length > 0) {
    const buttons = document.getElementsByClassName('help-button');
    for (let button of buttons) {
      button.addEventListener('click', showHints);
      button.style.display = 'initial';
    }
  }

  function showHints(e) {
    i.start();
    e.preventDefault();
  }
};
<commit_msg>fix help button css display value<commit_after>import {introJs} from 'intro.js';
import 'intro.js/introjs.css';

module.exports = function () {
  const steps = [];
  const elems = document.getElementsByClassName('help-dialog');

  for (let elem of elems) {
    steps.push(Object.assign({
      element: elem.parentElement,
      intro: elem.innerHTML
    }, elem.dataset));
  }

  const i = introJs();
  i.addSteps(steps);

  i.setOptions({
    nextLabel: 'Suivant →',
    prevLabel: '← Précédent',
    skipLabel: 'Passer',
    doneLabel: 'Terminé'
  });

  if (steps.length > 0) {
    const buttons = document.getElementsByClassName('help-button');
    for (let button of buttons) {
      button.addEventListener('click', showHints);
      button.style.display = 'inherit';
    }
  }

  function showHints(e) {
    i.start();
    e.preventDefault();
  }
};
<|endoftext|>