<commit_before>import Emitter from 'component-emitter';
import find from 'component-find';
import Promise from 'promise';
import SubscriptionPricing from '../subscription';
import dom from '../../../util/dom';
import flatten from '../../../util/flatten';
import groupBy from '../../../util/group-by';
import uuid from '../../../util/uuid';
import {ignoreNotFound} from '../subscription/attachment';

const debug = require('debug')('recurly:pricing:checkout:attachment');

const INIT_RUN = 'init-all';

/**
 * Binds a DOM tree to CheckoutPricing values
 *
 * @param {CheckoutPricing} pricing
 * @param {HTMLElement} container Element on which to attach
 */

export default class Attachment extends Emitter {
  constructor (pricing, container) {
    super();
    this.pricing = pricing;
    this.recurly = pricing.recurly;
    this.container = dom.element(container);

    if (!this.container) throw new Error('invalid dom element');

    this.onInputChange = this.onInputChange.bind(this);
    this.updateOutput = this.updateOutput.bind(this);

    this.pricing.on('change', this.updateOutput);

    this.elements.all.forEach(elem => {
      elem.addEventListener('change', this.onInputChange);
      elem.addEventListener('propertychange', this.onInputChange);
    });

    this.onInputChange(INIT_RUN);
  }

  get elements () {
    if (this._elements) return this._elements;

    let elements = { all: [].slice.call(this.container.querySelectorAll('[data-recurly]')) };

    elements.all.forEach(node => {
      const name = dom.data(node, 'recurly');
      if (!(name in elements)) elements[name] = [];
      elements[name].push(node);
    });

    this._elements = elements;
    return elements;
  }

  /**
   * Handles input element changes
   */

  onInputChange (event) {
    debug('onInputChange');

    const elems = this.elements;

    // Collect subscription properties that are not given a subscription id,
    // and assign them one, assuming they are all meant to apply to one
    // subscription
    const orphanedSubscriptionId = uuid();
    flatten([elems.plan, elems.plan_quantity, elems.addon, elems.tax_code]).forEach(el => {
      if (!el) return;
      if (dom.data(el, 'recurlySubscription')) return;
      dom.data(el, 'recurlySubscription', orphanedSubscriptionId);
    });

    // Collect subscription elements, grouped by their ids,
    // then removes elements not paired to a subscription
    const subscriptionGroups = groupBy(elems.all, el => dom.data(el, 'recurlySubscription'));
    delete subscriptionGroups.undefined;

    // Removes all subscriptions and adjustments, as there is not a clean
    // way to detect individual item removal without using observers
    this.pricing.clearSubscriptions();
    this.pricing.clearAdjustments();

    // Builds a SubscriptionPricing instance per subscription element group
    Promise.all(Object.keys(subscriptionGroups).map(id => {
      const subscriptionElems = groupBy(subscriptionGroups[id], el => dom.data(el, 'recurly'));

      // Look for an existing subscription for this code
      let subscription = this.pricing.findSubscriptionById(id);

      if (!subscription) {
        subscription = new SubscriptionPricing(this.recurly, { id });
        this.pricing.subscription(subscription);
      }

      const quantity = dom.value(subscriptionElems.plan_quantity) || 1;

      return subscription
        // Plan
        .plan(dom.value(subscriptionElems.plan), { quantity })
        .then(() => {
          // Add-ons
          if (!subscriptionElems.addon) return;
          return Promise.all(subscriptionElems.addon.map(addonElem => {
            const code = dom.data(addonElem, 'recurlyAddon');
            const addonQuantity = dom.value(addonElem);

            return subscription
              .addon(code, { quantity: addonQuantity })
              .catch(e => this.pricing.error(e));
          }));
        })
        .then(() => {
          // Tax code
          if (!subscriptionElems.tax_code) return;
          return subscription.tax({ tax_code: dom.value(subscriptionElems.tax_code)});
        })
        .reprice();
    }))
    .then(() => {
      // Adjustments
      if (!elems.adjustment) return;
      return Promise.all(elems.adjustment.map(adjustmentElem => {
        const code = dom.data(adjustmentElem, 'recurlyAdjustment');
        const amount = dom.data(adjustmentElem, 'recurlyAdjustmentAmount');
        const quantity = dom.value(adjustmentElem);
        const currency = dom.data(adjustmentElem, 'recurlyAdjustmentCurrency');
        const taxCode = dom.data(adjustmentElem, 'recurlyAdjustmentTaxCode');
        const taxExempt = dom.data(adjustmentElem, 'recurlyAdjustmentTaxExempt')

        return this.pricing.adjustment({ code, amount, quantity, currency, taxCode, taxExempt });
      }));
    })
    .then(() => {
      // Currency
      if (!elems.currency) return;
      return this.pricing.currency(dom.value(elems.currency));
    })
    .then(() => {
      // Coupon
      if (!elems.coupon) return;
      return this.pricing
        .coupon(dom.value(elems.coupon).trim())
        .then(null, ignoreNotFound);
    })
    .then(() => {
      // Gift card
      if (!elems.gift_card) return;
      return this.pricing
        .giftCard(dom.value(elems.gift_card).trim())
        .then(null, ignoreNotFound);
    })
    .then(() => {
      // Address
      if (elems.country || elems.postal_code) {
        return this.pricing.address({
          country: dom.value(elems.country),
          postal_code: dom.value(elems.postal_code)
        });
      }
    })
    .then(() => {
      // Shipping Address
      if (elems['shipping_address.country'] || elems['shipping_address.postal_code']) {
        return this.pricing.shippingAddress({
          country: dom.value(elems['shipping_address.country']),
          postal_code: dom.value(elems['shipping_address.postal_code'])
        });
      }
    })
    .then(() => {
      if (!elems.vat_number) return;
      return this.pricing.tax({ vat_number: dom.value(elems.vat_number) });
    })
    .then(() => {
      return this.pricing.reprice();
    })
    .then(() => {
      if (event === INIT_RUN) this.emit('ready');
    })
    .done();
  }

  /**
   * Updates output elements
   *
   * - TODO: Should there be output elements for each item in `price[when].items`?
   *
   */
  updateOutput (price) {
    const elems = this.elements;

    dom.value(elems.currency_code, price.currency.code);
    dom.value(elems.currency_symbol, price.currency.symbol);

    ['subscriptions', 'adjustments', 'discount', 'subtotal', 'taxes', 'total'].forEach(value => {
      dom.value(elems[value + '_now'], price.now[value]);
      dom.value(elems[value + '_next'], price.next[value]);
    });

    dom.value(elems['gift_card_now'], price.now.giftCard);
    dom.value(elems['gift_card_next'], price.next.giftCard);

    if (elems.addon_price) {
      elems.addon_price.forEach(elem => {
        const addonPrice = price.base.addons[dom.data(elem, 'recurlyAddon')];
        if (addonPrice) dom.value(elem, addonPrice);
      });
    }
  }

  detach () {
    this.pricing.off('change', this.updateOutput);

    this.elements.all.forEach(elem => {
      elem.removeEventListener('change', this.onInputChange);
      elem.removeEventListener('propertychange', this.onInputChange);
    });
  }
}
<commit_msg>Fixes CheckoutPricing/Attachment addon output<commit_after>import Emitter from 'component-emitter';
import find from 'component-find';
import Promise from 'promise';
import SubscriptionPricing from '../subscription';
import dom from '../../../util/dom';
import flatten from '../../../util/flatten';
import groupBy from '../../../util/group-by';
import uuid from '../../../util/uuid';
import {ignoreNotFound} from '../subscription/attachment';

const debug = require('debug')('recurly:pricing:checkout:attachment');

const INIT_RUN = 'init-all';

/**
 * Binds a DOM tree to CheckoutPricing values
 *
 * @param {CheckoutPricing} pricing
 * @param {HTMLElement} container Element on which to attach
 */

export default class Attachment extends Emitter {
  constructor (pricing, container) {
    super();
    this.pricing = pricing;
    this.recurly = pricing.recurly;
    this.container = dom.element(container);

    if (!this.container) throw new Error('invalid dom element');

    this.onInputChange = this.onInputChange.bind(this);
    this.updateOutput = this.updateOutput.bind(this);

    this.pricing.on('change', this.updateOutput);

    this.elements.all.forEach(elem => {
      elem.addEventListener('change', this.onInputChange);
      elem.addEventListener('propertychange', this.onInputChange);
    });

    this.onInputChange(INIT_RUN);
  }

  get elements () {
    if (this._elements) return this._elements;

    let elements = { all: [].slice.call(this.container.querySelectorAll('[data-recurly]')) };

    elements.all.forEach(node => {
      const name = dom.data(node, 'recurly');
      if (!(name in elements)) elements[name] = [];
      elements[name].push(node);
    });

    this._elements = elements;
    return elements;
  }

  /**
   * Handles input element changes
   */

  onInputChange (event) {
    debug('onInputChange');

    const elems = this.elements;

    // Collect subscription properties that are not given a subscription id,
    // and assign them one, assuming they are all meant to apply to one
    // subscription
    const orphanedSubscriptionId = uuid();
    flatten([elems.plan, elems.plan_quantity, elems.addon, elems.tax_code]).forEach(el => {
      if (!el) return;
      if (dom.data(el, 'recurlySubscription')) return;
      dom.data(el, 'recurlySubscription', orphanedSubscriptionId);
    });

    // Collect subscription elements, grouped by their ids,
    // then removes elements not paired to a subscription
    const subscriptionGroups = groupBy(elems.all, el => dom.data(el, 'recurlySubscription'));
    delete subscriptionGroups.undefined;

    // Removes all subscriptions and adjustments, as there is not a clean
    // way to detect individual item removal without using observers
    this.pricing.clearSubscriptions();
    this.pricing.clearAdjustments();

    // Builds a SubscriptionPricing instance per subscription element group
    Promise.all(Object.keys(subscriptionGroups).map(id => {
      const subscriptionElems = groupBy(subscriptionGroups[id], el => dom.data(el, 'recurly'));

      // Look for an existing subscription for this code
      let subscription = this.pricing.findSubscriptionById(id);

      if (!subscription) {
        subscription = new SubscriptionPricing(this.recurly, { id });
        this.pricing.subscription(subscription);
      }

      const quantity = dom.value(subscriptionElems.plan_quantity) || 1;

      return subscription
        // Plan
        .plan(dom.value(subscriptionElems.plan), { quantity })
        .then(() => {
          // Add-ons
          if (!subscriptionElems.addon) return;
          return Promise.all(subscriptionElems.addon.map(addonElem => {
            const code = dom.data(addonElem, 'recurlyAddon');
            const addonQuantity = dom.value(addonElem);

            return subscription
              .addon(code, { quantity: addonQuantity })
              .catch(e => this.pricing.error(e));
          }));
        })
        .then(() => {
          // Tax code
          if (!subscriptionElems.tax_code) return;
          return subscription.tax({ tax_code: dom.value(subscriptionElems.tax_code)});
        })
        .reprice();
    }))
    .then(() => {
      // Adjustments
      if (!elems.adjustment) return;
      return Promise.all(elems.adjustment.map(adjustmentElem => {
        const code = dom.data(adjustmentElem, 'recurlyAdjustment');
        const amount = dom.data(adjustmentElem, 'recurlyAdjustmentAmount');
        const quantity = dom.value(adjustmentElem);
        const currency = dom.data(adjustmentElem, 'recurlyAdjustmentCurrency');
        const taxCode = dom.data(adjustmentElem, 'recurlyAdjustmentTaxCode');
        const taxExempt = dom.data(adjustmentElem, 'recurlyAdjustmentTaxExempt')

        return this.pricing.adjustment({ code, amount, quantity, currency, taxCode, taxExempt });
      }));
    })
    .then(() => {
      // Currency
      if (!elems.currency) return;
      return this.pricing.currency(dom.value(elems.currency));
    })
    .then(() => {
      // Coupon
      if (!elems.coupon) return;
      return this.pricing
        .coupon(dom.value(elems.coupon).trim())
        .then(null, ignoreNotFound);
    })
    .then(() => {
      // Gift card
      if (!elems.gift_card) return;
      return this.pricing
        .giftCard(dom.value(elems.gift_card).trim())
        .then(null, ignoreNotFound);
    })
    .then(() => {
      // Address
      if (elems.country || elems.postal_code) {
        return this.pricing.address({
          country: dom.value(elems.country),
          postal_code: dom.value(elems.postal_code)
        });
      }
    })
    .then(() => {
      // Shipping Address
      if (elems['shipping_address.country'] || elems['shipping_address.postal_code']) {
        return this.pricing.shippingAddress({
          country: dom.value(elems['shipping_address.country']),
          postal_code: dom.value(elems['shipping_address.postal_code'])
        });
      }
    })
    .then(() => {
      if (!elems.vat_number) return;
      return this.pricing.tax({ vat_number: dom.value(elems.vat_number) });
    })
    .then(() => {
      return this.pricing.reprice();
    })
    .then(() => {
      if (event === INIT_RUN) this.emit('ready');
    })
    .done();
  }

  /**
   * Updates output elements
   *
   * - TODO: Should there be output elements for each item in `price[when].items`?
   *
   */
  updateOutput (price) {
    const elems = this.elements;

    dom.value(elems.currency_code, price.currency.code);
    dom.value(elems.currency_symbol, price.currency.symbol);

    ['subscriptions', 'adjustments', 'discount', 'subtotal', 'taxes', 'total'].forEach(value => {
      dom.value(elems[value + '_now'], price.now[value]);
      dom.value(elems[value + '_next'], price.next[value]);
    });

    dom.value(elems['gift_card_now'], price.now.giftCard);
    dom.value(elems['gift_card_next'], price.next.giftCard);

    if (elems.addon_price) {
      elems.addon_price.forEach(elem => {
        const subscriptionId = dom.data(elem, 'recurlySubscription');
        const subscription = subscriptionId && this.pricing.findSubscriptionById(subscriptionId);
        if (!subscription) return;
        if (!subscription.isValid) return;
        const addonPrice = subscription.price.base.addons[dom.data(elem, 'recurlyAddon')];
        if (addonPrice) dom.value(elem, addonPrice);
      });
    }
  }

  detach () {
    this.pricing.off('change', this.updateOutput);

    this.elements.all.forEach(elem => {
      elem.removeEventListener('change', this.onInputChange);
      elem.removeEventListener('propertychange', this.onInputChange);
    });
  }
}
<|endoftext|>


<commit_before>define(function(require, exports, module) {
    "use strict";
    main.consumes = [
        "Plugin", "commands", "menus", "ace"
    ];
    main.provides = ["emmet"];
    return main;

    function main(options, imports, register) {
        var Plugin = imports.Plugin;
        var commands = imports.commands;
        var menus = imports.menus;

        var emmetExt = require("ace/ext/emmet");
        emmetExt.setCore("lib/emmet/emmet");
        emmetExt.updateCommands = function() {};

        /***** Initialization *****/

        var plugin = new Plugin("Ajax.org", main.consumes);
        var emit = plugin.getEmitter();

        var loaded = false;
        function load() {
            if (loaded) return false;
            loaded = true;

            var keymap = {
                expand_abbreviation: {mac: "ctrl+alt+e", win: "ctrl+alt+e"},
                match_pair_outward: {}, // {mac: "ctrl+d", win: "ctrl+,"},
                match_pair_inward: {}, // {mac: "ctrl+j", win: "ctrl+shift+0"},
                matching_pair:  {}, // {mac: "ctrl+alt+j", win: "alt+j"},
                next_edit_point:  {}, // "alt+right",
                prev_edit_point:  {}, // "alt+left",
                toggle_comment: {mac: "command+/", win: "ctrl+/"},
                split_join_tag:  {}, // {mac: "shift+command+'", win: "shift+ctrl+`"},
                remove_tag:  {}, // {mac: "command+'", win: "shift+ctrl+;"},
                evaluate_math_expression:  {mac: "shift+command+y", win: "shift+ctrl+y"},
                increment_number_by_1:  {}, // "ctrl+up",
                decrement_number_by_1:  {}, // "ctrl+down",
                increment_number_by_01:  {}, // "alt+up",
                decrement_number_by_01:  {}, // "alt+down",
                increment_number_by_10:  {}, // {mac: "alt+command+up", win: "shift+alt+up"},
                decrement_number_by_10:  {}, // {mac: "alt+command+down", win: "shift+alt+down"},
                select_next_item: {mac: "shift+command+.", win: "shift+ctrl+."},
                select_previous_item: {mac: "shift+command+,", win: "shift+ctrl+,"},
                reflect_css_value:  {}, // {mac: "shift+command+r", win: "shift+ctrl+r"},

                // encode_decode_data_url:  {}, // {mac: "shift+ctrl+d", win: "ctrl+'"},
                // update_image_size: {mac: "shift+ctrl+i", win: "ctrl+u"},
                // expand_as_you_type: "ctrl+alt+enter",
                // wrap_as_you_type: {mac: "shift+ctrl+g", win: "shift+ctrl+g"},
                expand_abbreviation_with_tab: {mac: "Tab", win: "Tab"},
                wrap_with_abbreviation: {mac: "shift+ctrl+a", win: "shift+ctrl+a"}
            };

            for (var i in keymap) {
                commands.addCommand({
                    name: i,
                    action: i,
                    group: "emmet",
                    bindKey: keymap[i],
                    exec: emmetExt.runEmmetCommand,
                    isAvailable: isAvailable,
                    findEditor: findEditor
                }, plugin);
            }
        }

        var drawn = false;
        function draw() {
            if (drawn) return;
            drawn = true;

            // TODO add menu items?

            emit("draw");
        }

        /***** Methods *****/

        function show() {
            draw();
        }

        function isAvailable(editor, args, event) {
            if (!editor || !editor.ace) return false;

            // using this instead of editor.type == "ace" to make
            // commands avaliable in editors inheriting from ace
            if (event instanceof KeyboardEvent && (!editor.ace.isFocused()))
                return false;

            return emmetExt.isSupportedMode(editor.ace.session.$modeId);
        }

        function findEditor(editor) {
            if (editor && editor.ace)
                return editor.ace;
            return editor;
        }

        /***** Lifecycle *****/

        plugin.on("load", function() {
            load();
        });
        plugin.on("enable", function() {

        });
        plugin.on("disable", function() {

        });
        plugin.on("unload", function() {
            loaded = false;
            drawn = false;
        });

        /***** Register and define API *****/

        /**
         *
         **/
        plugin.freezePublicAPI({
        });

        register(null, {
            emmet: plugin
        });
    }
});<commit_msg>keep using ace toggle comment instead of emmet one<commit_after>define(function(require, exports, module) {
    "use strict";
    main.consumes = [
        "Plugin", "commands", "menus", "ace"
    ];
    main.provides = ["emmet"];
    return main;

    function main(options, imports, register) {
        var Plugin = imports.Plugin;
        var commands = imports.commands;
        var menus = imports.menus;

        var emmetExt = require("ace/ext/emmet");
        emmetExt.setCore("lib/emmet/emmet");
        emmetExt.updateCommands = function() {};

        /***** Initialization *****/

        var plugin = new Plugin("Ajax.org", main.consumes);
        var emit = plugin.getEmitter();

        var loaded = false;
        function load() {
            if (loaded) return false;
            loaded = true;

            var keymap = {
                expand_abbreviation: {mac: "ctrl+alt+e", win: "ctrl+alt+e"},
                match_pair_outward: {}, // {mac: "ctrl+d", win: "ctrl+,"},
                match_pair_inward: {}, // {mac: "ctrl+j", win: "ctrl+shift+0"},
                matching_pair:  {}, // {mac: "ctrl+alt+j", win: "alt+j"},
                next_edit_point:  {}, // "alt+right",
                prev_edit_point:  {}, // "alt+left",
                toggle_comment: {}, // {mac: "command+/", win: "ctrl+/"},
                split_join_tag:  {}, // {mac: "shift+command+'", win: "shift+ctrl+`"},
                remove_tag:  {}, // {mac: "command+'", win: "shift+ctrl+;"},
                evaluate_math_expression:  {mac: "shift+command+y", win: "shift+ctrl+y"},
                increment_number_by_1:  {}, // "ctrl+up",
                decrement_number_by_1:  {}, // "ctrl+down",
                increment_number_by_01:  {}, // "alt+up",
                decrement_number_by_01:  {}, // "alt+down",
                increment_number_by_10:  {}, // {mac: "alt+command+up", win: "shift+alt+up"},
                decrement_number_by_10:  {}, // {mac: "alt+command+down", win: "shift+alt+down"},
                select_next_item: {mac: "shift+command+.", win: "shift+ctrl+."},
                select_previous_item: {mac: "shift+command+,", win: "shift+ctrl+,"},
                reflect_css_value:  {}, // {mac: "shift+command+r", win: "shift+ctrl+r"},

                // encode_decode_data_url:  {}, // {mac: "shift+ctrl+d", win: "ctrl+'"},
                // update_image_size: {mac: "shift+ctrl+i", win: "ctrl+u"},
                // expand_as_you_type: "ctrl+alt+enter",
                // wrap_as_you_type: {mac: "shift+ctrl+g", win: "shift+ctrl+g"},
                expand_abbreviation_with_tab: {mac: "Tab", win: "Tab"},
                wrap_with_abbreviation: {mac: "shift+ctrl+a", win: "shift+ctrl+a"}
            };

            for (var i in keymap) {
                commands.addCommand({
                    name: i,
                    action: i,
                    group: "emmet",
                    bindKey: keymap[i],
                    exec: emmetExt.runEmmetCommand,
                    isAvailable: isAvailable,
                    findEditor: findEditor
                }, plugin);
            }
        }

        var drawn = false;
        function draw() {
            if (drawn) return;
            drawn = true;

            // TODO add menu items?

            emit("draw");
        }

        /***** Methods *****/

        function show() {
            draw();
        }

        function isAvailable(editor, args, event) {
            if (!editor || !editor.ace) return false;

            // using this instead of editor.type == "ace" to make
            // commands avaliable in editors inheriting from ace
            if (event instanceof KeyboardEvent && (!editor.ace.isFocused()))
                return false;

            return emmetExt.isSupportedMode(editor.ace.session.$modeId);
        }

        function findEditor(editor) {
            if (editor && editor.ace)
                return editor.ace;
            return editor;
        }

        /***** Lifecycle *****/

        plugin.on("load", function() {
            load();
        });
        plugin.on("enable", function() {

        });
        plugin.on("disable", function() {

        });
        plugin.on("unload", function() {
            loaded = false;
            drawn = false;
        });

        /***** Register and define API *****/

        /**
         *
         **/
        plugin.freezePublicAPI({
        });

        register(null, {
            emmet: plugin
        });
    }
});<|endoftext|>


<commit_before>var express = require('express'),
	app = express(),
	port = process.env.PORT || 5000,
	bodyParser = require('body-parser')

//app.use(bodyParser()j
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

var sensorStates = [0, 0]
var locationId = 0
var MAX_SENSOR_RANGE = 1,
	 MIN_SENSOR_RANGE = 0

app.route('/').get(function(req, res) {
	console.log('Hit /')
	res.json({"hello": "world"})
})

app.route('/echo').post(function(req, res) {
	console.log('POST /echo')
	res.send(req.body.data)
	console.log(JSON.stringify(req.body.data))
})

app.route('/location/all').get(function(req, res) {
	console.log('GOT /location/all')
	returnVal = {"status": "OK",
					"locationId": "all",
					"sensorState": sensorStates}
	res.json(returnVal)
	console.log(returnVal)
	returnVal = {}
})

app.route('/location/:id').get(function(req, res) {
	locationId = req.params.id
	console.log('GOT /location/' + locationId)
	returnVal = {"status": "OK",
					"locationId": locationId,
					"sensorState": sensorStates[locationId]}
	res.json(returnVal)
	console.log(returnVal)
	returnVal = {}
})

app.route('/location/:id').post(function(req, res) {
	console.log('POST /location/' + req.params.id)
	var data = JSON.parse(req.body.data)
	locationId = data.locationId
	if(locationId > ((sensorStates.length)-1)) {
		returnVal = {"status": "ILLEGALLOCATION"}
	} else {
		sensorState = data.sensorState
		if((sensorState > MAX_SENSOR_RANGE) || (sensorState < MIN_SENSOR_RANGE)) {
			returnVal = {"status": "SENSOROUTOFRANGE"}
		} else {
			if(locationId == 0) {
				returnVal = sensorStates[1]
			} else {
				returnVal = sensorStates[0]
			}
			sensorStates[locationId] = sensorState
			/*returnVal = {"status": "OK",
							"locationId": locationId,
							"sensorStates": sensorStates}*/
		}
	}
	res.json(returnVal)
	console.log(returnVal)
})

app.listen(port)
console.log('API server started on: ' + port);

<commit_msg>Add another API route<commit_after>var express = require('express'),
	app = express(),
	port = process.env.PORT || 5000,
	bodyParser = require('body-parser')

//app.use(bodyParser()j
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

var sensorStates = [0, 0]
var locationId = 0
var MAX_SENSOR_RANGE = 1,
	 MIN_SENSOR_RANGE = 0

app.route('/').get(function(req, res) {
	console.log('Hit /')
	res.json({"hello": "world"})
})

app.route('/echo').post(function(req, res) {
	console.log('POST /echo')
	res.send(req.body.data)
	console.log(JSON.stringify(req.body.data))
})

app.route('/location/all').get(function(req, res) {
	console.log('GOT /location/all')
	returnVal = {"status": "OK",
					"locationId": "all",
					"sensorState": sensorStates}
	res.json(returnVal)
	console.log(returnVal)
	returnVal = {}
})

app.route('/location/:id').get(function(req, res) {
	locationId = req.params.id
	console.log('GOT /location/' + locationId)
	returnVal = {"status": "OK",
					"locationId": locationId,
					"sensorState": sensorStates[locationId]}
	res.json(returnVal)
	console.log(returnVal)
	returnVal = {}
})

app.route('/location/').post(function(req, res) {
	console.log('POST /location/')
	var data = JSON.parse(req.body.data)
	locationId = data.locationId
	if(locationId > ((sensorStates.length)-1)) {
		returnVal = {"status": "ILLEGALLOCATION"}
	} else {
		if(locationId == 0) {
			returnVal = sensorStates[1]
		} else {
			returnVal = sensorStates[0]
		}
		sensorStates[locationId] = sensorState
	}
	res.json(returnVal)
	console.log(returnVal)
})

app.route('/location/:id').post(function(req, res) {
	console.log('POST /location/' + req.params.id)
	var data = JSON.parse(req.body.data)
	locationId = data.locationId
	if(locationId > ((sensorStates.length)-1)) {
		returnVal = {"status": "ILLEGALLOCATION"}
	} else {
		sensorState = data.sensorState
		if((sensorState > MAX_SENSOR_RANGE) || (sensorState < MIN_SENSOR_RANGE)) {
			returnVal = {"status": "SENSOROUTOFRANGE"}
		} else {
			if(locationId == 0) {
				returnVal = sensorStates[1]
			} else {
				returnVal = sensorStates[0]
			}
			sensorStates[locationId] = sensorState
			/*returnVal = {"status": "OK",
							"locationId": locationId,
							"sensorStates": sensorStates}*/
		}
	}
	res.json(returnVal)
	console.log(returnVal)
})

app.listen(port)
console.log('API server started on: ' + port);

<|endoftext|>


<commit_before>var unirest = require('unirest');
var moment = require('moment');

var sections = [];
var classes = {};
var innerFlag = 0;
var please = "11";

/*

{
    className: [
        {
            section: CMSC132-0101
            times: [
                {
                    days: MWF,
                    start: fdsa,
                    end: fewage
                },
                ...
            ]
        },
        ...
    ],
    ...
}

*/

testFunction = function(classNames) {
    for (let k = 0; k < classNames.length; k++) {
        unirest
        .get('http://api.umd.io/v0/courses/' + classNames[k])
        .end((response) => {
            sections = response.body['sections'];
            //console.log(response.body['sections']);
            var className = response.body['course_id'];
            innerFlag += sections.length;
            classes[className] = [];
            sections.map(function(section) {
                unirest
                .get('http://api.umd.io/v0/courses/sections/' + section)
                .end(function(response) {
                    //console.log(response.body);
                    //console.log(response.body['section_id']);
                    //console.log(response.body['meetings'][0]['start_time']);
                    //console.log(response.body['meetings'][0]['end_time']);

                    var sectionName = response.body['section_id'];
                    var meetingTimes = [];
                    response.body['meetings'].map((meeting) => {
                        var startTime = meeting['start_time'];
                        if (startTime == "")
                            return;

                        var endTime = meeting['end_time']
                        var startTimeFormatted = moment(startTime, ["h:mmA"]).format("HHmm");
                        var endTimeFormatted = moment(endTime, ["h:mmA"]).format("HHmm");
                        //console.log(response.body['meetings'][0]['days']);

                        var dayString = response.body['meetings'][0]['days'].toString();
                        for (let i = 0; i < dayString.length; i++) {
                            var dayChar = "";
                            if (dayString[i] != 'T') {
                                dayChar = dayString[i];
                            } else {
                                dayChar = dayString[i] + dayString[i + 1];
                                i++;
                            }
                            var sectionObj = {
                                days: dayChar,
                                start: startTimeFormatted,
                                end: endTimeFormatted
                            }
                            //console.log(sectionObj);

                            meetingTimes.push(sectionObj);
                        }
                    });

                    classes[className].push({
                        section: sectionName,
                        times: meetingTimes
                    });

                    innerFlag--;
                    if (innerFlag == 0) {
                        //console.log(classes)
                        validateFirst(classes);
                        return classes;
                    }
                });
            });
        });
    }
};

/*
while (flag != 0) {
    console.log(flag);
}
console.log(classes);*/

asdf = function(classes1) {
    console.log(classes1);
}

// Contains functions to help filter one person
validateFirst = function(classes1) {
    var goodOnes = [];
    var notPossible = false;
    var isFirst = true;

    //Go through all classes
    for (let c in classes1) {
        var newGoodOnes = [];
        //console.log("Class");
        //console.log(c);
        //Give classname c, get all of c's sections as an array
        //each section is passed in the forEach
        classes1[c].forEach((section) => {
            var foundMatch = false;
            //sections for the first class, add them all to goodOnes
            if (isFirst) {
                //console.log("First");
                var tmp = [];
                tmp.push(section);
                goodOnes.push(tmp);
                //console.log(goodOnes.length);
                //console.log(goodOnes);
            } else {
                //Current set of already compatible section times in goodOnes
                //console.log(goodOnes.length);
                goodOnes.forEach((goodSchedule) => {
                    //no conflicts with this combination
                    if (!hasConflict(section, goodSchedule)) {
                        var combined = goodSchedule.concat(section); //add section number that fits
                        newGoodOnes.push(combined); //now add the sections to the newGoodOnes
                        foundMatch = true;
                        //console.log("Putting!");
                    }
                });
            }
            //console.log("After");

        });
        if (isFirst) {
            goodOnes = newGoodOnes;
        }
        //console.log(goodOnes);
        isFirst = false;

    }

    console.log(goodOnes);
}

//Determines if a meeting conflicts with a set of already validated meetings
hasConflict = function(curr, sections) {
    let returnValue = false;
    sections.forEach((section) => {
        section.times.forEach((st) => {
            curr.times.forEach((currTimesObj) => {
                if (currTimesObj.day == st.day) {
                    if ((currTimesObj.start > st.start && currTimesObj.start < st.end) || (currTimesObj.end > st.start && currTimesObj.end < st.end)) {
                        console.log("i got here")
                        returnValue = true;
                    }
                }
            });
        });
    });
    return returnValue;
}

/* TEST CASES FOR hasConflict

var tempCurr = {
    day: "M",
    start: 1100,
    end: 1150
}

var tempSections = [
    {
        section: "Myclass100",
        times: [{
            day: "Tu",
            start: 1000,
            end: 1050
        },
        {
            day: "Th",
            start: 1100,
            end: 1150
        },
        {
            day: "M",
            start: 1000,
            end: 1050
        }]
    },
    {
        section: "Myclass101",
        times: [{
            day: "Tu",
            start: 1030,
            end: 1130
        },
        {
            day: "Th",
            start: 1100,
            end: 1150
        },
        {
            day: "M",
            start: 1200,
            end: 1230
        }]
    }
]

console.log(hasConflict(tempCurr, tempSections));
*/
testFunction(['HACS208N', 'HACS202']);

<commit_msg>getOverlaps, numClassesinCommon, and makePair<commit_after>var unirest = require('unirest');
var moment = require('moment');

var sections = [];
var classes = {};
var innerFlag = 0;
var please = "11";

/*

{
    className: [
        {
            section: CMSC132-0101
            times: [
                {
                    days: MWF,
                    start: fdsa,
                    end: fewage
                },
                ...
            ]
        },
        ...
    ],
    ...
}

*/

testFunction = function(classNames) {
    for (let k = 0; k < classNames.length; k++) {
        unirest
        .get('http://api.umd.io/v0/courses/' + classNames[k])
        .end((response) => {
            sections = response.body['sections'];
            //console.log(response.body['sections']);
            var className = response.body['course_id'];
            innerFlag += sections.length;
            classes[className] = [];
            sections.map(function(section) {
                unirest
                .get('http://api.umd.io/v0/courses/sections/' + section)
                .end(function(response) {
                    //console.log(response.body);
                    //console.log(response.body['section_id']);
                    //console.log(response.body['meetings'][0]['start_time']);
                    //console.log(response.body['meetings'][0]['end_time']);

                    var sectionName = response.body['section_id'];
                    var meetingTimes = [];
                    response.body['meetings'].map((meeting) => {
                        var startTime = meeting['start_time'];
                        if (startTime == "")
                            return;

                        var endTime = meeting['end_time']
                        var startTimeFormatted = moment(startTime, ["h:mmA"]).format("HHmm");
                        var endTimeFormatted = moment(endTime, ["h:mmA"]).format("HHmm");
                        //console.log(response.body['meetings'][0]['days']);

                        var dayString = response.body['meetings'][0]['days'].toString();
                        for (let i = 0; i < dayString.length; i++) {
                            var dayChar = "";
                            if (dayString[i] != 'T') {
                                dayChar = dayString[i];
                            } else {
                                dayChar = dayString[i] + dayString[i + 1];
                                i++;
                            }
                            var sectionObj = {
                                days: dayChar,
                                start: startTimeFormatted,
                                end: endTimeFormatted
                            }
                            //console.log(sectionObj);

                            meetingTimes.push(sectionObj);
                        }
                    });

                    classes[className].push({
                        section: sectionName,
                        times: meetingTimes
                    });

                    innerFlag--;
                    if (innerFlag == 0) {
                        //console.log(classes)
                        validateFirst(classes);
                        return classes;
                    }
                });
            });
        });
    }
};

/*
while (flag != 0) {
    console.log(flag);
}
console.log(classes);*/

asdf = function(classes1) {
    console.log(classes1);
}

// Contains functions to help filter one person
validateFirst = function(classes1) {
    var goodOnes = [];
    var notPossible = false;
    var isFirst = true;

    //Go through all classes
    for (let c in classes1) {
        var newGoodOnes = [];
        //console.log("Class");
        //console.log(c);
        //Give classname c, get all of c's sections as an array
        //each section is passed in the forEach
        classes1[c].forEach((section) => {
            var foundMatch = false;
            //sections for the first class, add them all to goodOnes
            if (isFirst) {
                //console.log("First");
                var tmp = [];
                tmp.push(section);
                goodOnes.push(tmp);
                //console.log(goodOnes.length);
                //console.log(goodOnes);
            } else {
                //Current set of already compatible section times in goodOnes
                //console.log(goodOnes.length);
                goodOnes.forEach((goodSchedule) => {
                    //no conflicts with this combination
                    if (!hasConflict(section, goodSchedule)) {
                        var combined = goodSchedule.concat(section); //add section number that fits
                        newGoodOnes.push(combined); //now add the sections to the newGoodOnes
                        foundMatch = true;
                        //console.log("Putting!");
                    }
                });
            }
            //console.log("After");

        });
        if (isFirst) {
            goodOnes = newGoodOnes;
        }
        //console.log(goodOnes);
        isFirst = false;

    }

    console.log(goodOnes);
}

//Determines if a meeting conflicts with a set of already validated meetings
hasConflict = function(curr, sections) {
    let returnValue = false;
    sections.forEach((section) => {
        section.times.forEach((st) => {
            curr.times.forEach((currTimesObj) => {
                if (currTimesObj.day == st.day) {
                    if ((currTimesObj.start > st.start && currTimesObj.start < st.end) || (currTimesObj.end > st.start && currTimesObj.end < st.end)) {
                        console.log("i got here")
                        returnValue = true;
                    }
                }
            });
        });
    });
    return returnValue;
}

getOverlaps = function(scheduleArr1, schedulesArr2) {
    //schedules is an array of "schedule"
    //A schedule is an array of sections
    var absoluteMax = 1;
    var perfectPairs;
    //Go through all schedules in first student

    scheduleArr1.forEach((schedule1) => {
        scheduleArr2.forEach((schedule2) => {
            var localMax = numClassesInCommon(schedule1, schedule2);

            if (localMax <= 0) {
                continue; //no classes in common so move on to next schedule2
            }
            else if (localMax == absoluteMax) {
                perfectPairs.push(makePair(schedule1, schedule2));
            }
            else { //case when localMax > absMax, it's the new absMax
                absoluteMax = localMax;
                perfectPairs = []; //empty to make room
                perfectPairs.push(makePair(schedule1, schedule2));
            }
        });

    });

    return perfectPairs;
}

numClassesInCommon = function(schedule1, schedule2) {
    var common = 0; // # of classes in common
    schedule1.forEach((sections1) => {      // Each section in the first student's schedule
        schedule2.forEach((sections2) => {  // Each section in the second student's schedule
            if (sections1.section === sections2.section) // Compare the names
                common++;
        });
    });
    return common;
}

makePair = function(schedule1, schedule2) {
    var pair;
    pair.s1 = schedule1;
    pair.s2 = schedule2;
    return pair;
}

/* TEST CASES FOR hasConflict

var tempCurr = {
    day: "M",
    start: 1100,
    end: 1150
}

var tempSections = [
    {
        section: "Myclass100",
        times: [{
            day: "Tu",
            start: 1000,
            end: 1050
        },
        {
            day: "Th",
            start: 1100,
            end: 1150
        },
        {
            day: "M",
            start: 1000,
            end: 1050
        }]
    },
    {
        section: "Myclass101",
        times: [{
            day: "Tu",
            start: 1030,
            end: 1130
        },
        {
            day: "Th",
            start: 1100,
            end: 1150
        },
        {
            day: "M",
            start: 1200,
            end: 1230
        }]
    }
]

console.log(hasConflict(tempCurr, tempSections));
*/
testFunction(['HACS208N', 'HACS202']);

<|endoftext|>


<commit_before>var util = require('util');
var Q = require('q');
var semver = require('semver');
var mout = require('mout');
var Resolver = require('./Resolver');
var cmd = require('../../util/cmd');
var createError = require('../../util/createError');

var GitRemoteResolver = function (source, options) {
    Resolver.call(this, source, options);
};

util.inherits(GitRemoteResolver, Resolver);

// -----------------

GitRemoteResolver.prototype.hasNew = function (oldTarget, oldResolution) {
    return this._resolveTarget(this._target)
    .then(function (resolution) {
        // Resolution types are different
        if (oldResolution.type !== resolution.type) {
            return true;
        }

        // If resolved to a tag
        // There is new content if the tags are not equal
        if (resolution.type === 'tag') {
            return semver.neq(resolution.tag, oldResolution.tag);
        }

        // If resolved to a commit hash, just check if they are different
        // Use the same strategy if it the resolution is to a branch
        return resolution.commit !== oldResolution.commit;
    });
};

GitRemoteResolver.prototype._resolveSelf = function () {
    var promise;

    promise = this._resolveTarget()
    .then(this._checkout.bind(this));

    return promise;
};

GitRemoteResolver.prototype._resolveTarget = function () {
    var target = this._target,
        source = this._source,
        promise,
        branches,
        errorMessage,
        errorDetails;

    // Target is a range/version
    if (semver.valid(target) || semver.validRange(target)) {
        return GitRemoteResolver._fetchVersions(this._source)
        .then(function (versions) {
            // Find the highest one that satifies the target
            var version = mout.array.find(versions, function (version) {
                return semver.satisfies(version, target);
            });

            if (!version) {
                errorMessage = !semver.validRange(target) ?
                    'Tag "' + target + '" does not exist' :
                    'No tag found that was able to satisfy "' + target + '"';
                errorDetails = !versions.length ?
                    'No tags found in "' + source + '"' :
                    'Available tags in "' + source + '" are: ' + versions.join(', ');
                throw createError(errorMessage, 'ENORESTARGET', errorDetails);
            }

            return { type: 'tag', tag: version };
        });
    }

    // Resolve the rest to a commit version
    promise = GitRemoteResolver._fetchHeads(this._source);

    // Target is a commit, so it's a stale target (not a moving target)
    // There's nothing to do in this case
    if ((/^[a-f0-9]{40}$/).test(target)) {
        return Q.resolve({ type: 'commit', commit: target });
    }

    // If target is *, use master branch
    if (target === '*') {
        target = 'master';
    }

    // Target is a branch
    return promise.then(function (heads) {
        if (!heads[target]) {
            branches = Object.keys(heads);
            errorDetails = !branches.length ?
                'No branches found in "' + source + '"' :
                'Available branches in "' + source + '" are ' + branches.join(', ');

            throw createError('Branch "' + target + '" does not exist', 'ENORESTARGET', errorDetails);
        }

        return { type: 'branch', branch: target, commit: heads[target] };
    });
};

GitRemoteResolver.prototype._checkout = function (resolution) {
    var dir = this._tempDir,
        branch;

    console.log(resolution);
    if (resolution.type === 'commit') {
        return Q.nfcall(cmd, 'git', ['clone', this._source, dir])
        .then(function () {
            return Q.nfcall(cmd, 'git', ['checkout', resolution.commit], { cwd: dir });
        });
    } else {
        branch = resolution.tag || resolution.branch;
        return Q.nfcall(cmd, 'git', ['clone',  this._source, '-b', branch, '--depth', 1], { cwd: dir });
    }
};

// ------------------------------

GitRemoteResolver._fetchRefs = function (source) {
    if (this._refs && this._refs[source]) {
        return Q.resolve(this._refs[source]);
    }

    return Q.nfcall(cmd, 'git', ['ls-remote', '--tags', '--heads', source])
    .then(function (stdout) {
        // Make them an array
        var refs = stdout.toString().split('\n');

        this._refs = this._refs  || {};
        return this._refs[source] = refs;
    }.bind(this));
};

GitRemoteResolver._fetchVersions = function (source) {
    if (this._versions && this._versions[source]) {
        return Q.resolve(this._versions[source]);
    }

    return this._fetchRefs(source)
    .then(function (refs) {
        var versions = [];

        // Parse each ref line, extracting the tag
        refs.forEach(function (line) {
            var match = line.match(/^[a-f0-9]{40}\s+refs\/tags\/(\S+)$/),
                cleaned;

            // Ensure it's valid
            if (match) {
                cleaned = semver.clean(match[1]);
                if (cleaned) {
                    versions.push(cleaned);
                }
            }
        });

        // Sort them by desc order
        versions = versions.sort(function (a, b) {
            return semver.gt(a, b) ? -1 : 1;
        });

        this._versions = this._versions  || {};
        return this._versions[source] = versions;
    }.bind(this));
};

GitRemoteResolver._fetchHeads = function (source) {
    if (this._heads && this._heads[source]) {
        return Q.resolve(this._heads[source]);
    }

    // Request heads of the source of only the specified branch
    return  this._fetchRefs(source)
    .then(function (refs) {
        this._heads = this._heads || {};
        var heads = this._heads[source] = this._heads[source] || {};

        // Foreach line in the refs, extract only the heads
        // Organize them in an object where keys are branches and values
        // the commit hash
        mout.array.forEach(refs, function (line) {
            var match = line.match(/^([a-f0-9]{40})\s+refs\/heads\/(\S+)$/);

            if (match) {
                heads[match[2]] = match[1];
            }
        });

        return heads;
    }.bind(this));
};

module.exports = GitRemoteResolver;
<commit_msg>Doc typos.<commit_after>var util = require('util');
var Q = require('q');
var semver = require('semver');
var mout = require('mout');
var Resolver = require('./Resolver');
var cmd = require('../../util/cmd');
var createError = require('../../util/createError');

var GitRemoteResolver = function (source, options) {
    Resolver.call(this, source, options);
};

util.inherits(GitRemoteResolver, Resolver);

// -----------------

GitRemoteResolver.prototype.hasNew = function (oldTarget, oldResolution) {
    return this._resolveTarget(this._target)
    .then(function (resolution) {
        // Resolution types are different
        if (oldResolution.type !== resolution.type) {
            return true;
        }

        // If resolved to a tag
        // There is new content if the tags are not equal
        if (resolution.type === 'tag') {
            return semver.neq(resolution.tag, oldResolution.tag);
        }

        // If resolved to a commit hash, just check if they are different
        // Use the same strategy if it the resolution is to a branch
        return resolution.commit !== oldResolution.commit;
    });
};

GitRemoteResolver.prototype._resolveSelf = function () {
    var promise;

    promise = this._resolveTarget()
    .then(this._checkout.bind(this));

    return promise;
};

GitRemoteResolver.prototype._resolveTarget = function () {
    var target = this._target,
        source = this._source,
        promise,
        branches,
        errorMessage,
        errorDetails;

    // Target is a range/version
    if (semver.valid(target) || semver.validRange(target)) {
        return GitRemoteResolver._fetchVersions(this._source)
        .then(function (versions) {
            // Find the highest one that satifies the target
            var version = mout.array.find(versions, function (version) {
                return semver.satisfies(version, target);
            });

            if (!version) {
                errorMessage = !semver.validRange(target) ?
                    'Tag "' + target + '" does not exist' :
                    'No tag found that was able to satisfy "' + target + '"';
                errorDetails = !versions.length ?
                    'No tags found in "' + source + '"' :
                    'Available tags in "' + source + '" are: ' + versions.join(', ');
                throw createError(errorMessage, 'ENORESTARGET', errorDetails);
            }

            return { type: 'tag', tag: version };
        });
    }

    // Resolve the rest to a commit version
    promise = GitRemoteResolver._fetchHeads(this._source);

    // Target is a commit, so it's a stale target (not a moving target)
    // There's nothing to do in this case
    if ((/^[a-f0-9]{40}$/).test(target)) {
        return Q.resolve({ type: 'commit', commit: target });
    }

    // If target is *, use master branch
    if (target === '*') {
        target = 'master';
    }

    // Target is a branch
    return promise.then(function (heads) {
        if (!heads[target]) {
            branches = Object.keys(heads);
            errorDetails = !branches.length ?
                'No branches found in "' + source + '"' :
                'Available branches in "' + source + '" are: ' + branches.join(', ');

            throw createError('Branch "' + target + '" does not exist', 'ENORESTARGET', errorDetails);
        }

        return { type: 'branch', branch: target, commit: heads[target] };
    });
};

GitRemoteResolver.prototype._checkout = function (resolution) {
    var dir = this._tempDir,
        branch;

    console.log(resolution);
    if (resolution.type === 'commit') {
        return Q.nfcall(cmd, 'git', ['clone', this._source, dir])
        .then(function () {
            return Q.nfcall(cmd, 'git', ['checkout', resolution.commit], { cwd: dir });
        });
    } else {
        branch = resolution.tag || resolution.branch;
        return Q.nfcall(cmd, 'git', ['clone',  this._source, '-b', branch, '--depth', 1], { cwd: dir });
    }
};

// ------------------------------

GitRemoteResolver._fetchRefs = function (source) {
    if (this._refs && this._refs[source]) {
        return Q.resolve(this._refs[source]);
    }

    return Q.nfcall(cmd, 'git', ['ls-remote', '--tags', '--heads', source])
    .then(function (stdout) {
        // Make them an array
        var refs = stdout.toString().split('\n');

        this._refs = this._refs  || {};
        return this._refs[source] = refs;
    }.bind(this));
};

GitRemoteResolver._fetchVersions = function (source) {
    if (this._versions && this._versions[source]) {
        return Q.resolve(this._versions[source]);
    }

    return this._fetchRefs(source)
    .then(function (refs) {
        var versions = [];

        // Parse each ref line, extracting the tag
        refs.forEach(function (line) {
            var match = line.match(/^[a-f0-9]{40}\s+refs\/tags\/(\S+)$/),
                cleaned;

            // Ensure it's valid
            if (match) {
                cleaned = semver.clean(match[1]);
                if (cleaned) {
                    versions.push(cleaned);
                }
            }
        });

        // Sort them by desc order
        versions = versions.sort(function (a, b) {
            return semver.gt(a, b) ? -1 : 1;
        });

        this._versions = this._versions  || {};
        return this._versions[source] = versions;
    }.bind(this));
};

GitRemoteResolver._fetchHeads = function (source) {
    if (this._heads && this._heads[source]) {
        return Q.resolve(this._heads[source]);
    }

    return  this._fetchRefs(source)
    .then(function (refs) {
        this._heads = this._heads || {};
        var heads = this._heads[source] = this._heads[source] || {};

        // Foreach line in the refs, extract only the heads
        // Organize them in an object where keys are branches and values
        // the commit hash
        mout.array.forEach(refs, function (line) {
            var match = line.match(/^([a-f0-9]{40})\s+refs\/heads\/(\S+)$/);

            if (match) {
                heads[match[2]] = match[1];
            }
        });

        return heads;
    }.bind(this));
};

module.exports = GitRemoteResolver;
<|endoftext|>


<commit_before>import { Block, initApp, find, isNil } from './dwayne';
import AppTemplate from './templates/App.pug';
import Block1Template from './templates/Block1.pug';
import Block2Template from './templates/Block2.pug';

class Block1 extends Block {
  static template = Block1Template();
  static defaultArgs = {
    value: 'no caption'
  };
}

let id = 0;

console.cond = (cond, ...args) => {
  if (cond) {
    console.log(...args);
  }
};

class App extends Block {
  static template = AppTemplate();

  newTodo = null;
  todos = [];

  addTodo() {
    this.todos = [
      ...this.todos,
      {
        id: ++id,
        finished: false,
        message: this.newTodo
      }
    ];
    this.newTodo = '';
  }

  findIndexByID(id) {
    return this.todos.findIndex(({ id: ID }) => id === ID);
  }

  toggleTodo(id) {
    const index = this.findIndexByID(id);

    this.todos = [
      ...this.todos.slice(0, index),
      {
        ...this.todos[index],
        finished: !this.todos[index].finished
      },
      ...this.todos.slice(index + 1)
    ];
  }

  removeTodo(id) {
    const index = this.findIndexByID(id);

    this.todos = [
      ...this.todos.slice(0, index),
      ...this.todos.slice(index + 1)
    ];
  }

  sortUp() {
    this.sortFunction = ({ message: m1 }, { message: m2 }) => (
      /* eslint no-nested-ternary: 0 */
      m1 > m2
        ? 1
        : m2 > m1
          ? -1
          : 0
    );
  }

  sortDown() {
    this.sortFunction = ({ message: m1 }, { message: m2 }) => (
      m2 > m1
        ? 1
        : m1 > m2
          ? -1
          : 0
    );
  }
}

class Link extends Block {
  static template = '<d-block/>';

  afterConstruct() {
    this.watch('args', () => {
      const {
        class: cls,
        route,
        active,
        ...rest
      } = this.args;

      this.cls = cls;
      this.route = route;
      this.active = active;
      this.rest = rest;
    });
  }
}

Block.block('App', App);
Block.block('Block1', Block1);
Block.block('Block2', Block2Template());
Block.block('Link', Link);
Block.mixin('html', (newValue, oldValue, mixin) => {
  mixin.elem.html(isNil(newValue) ? '' : `${ newValue }`);
});
initApp('App', find('.root'));
<commit_msg>Empty entry.js.<commit_after><|endoftext|>


<commit_before>'use strict';
var test = require('ava');
var ellipsis = require('./');

test('should cut off a string and add an ellipsis', function (t) {
	t.is(ellipsis('unicorn', 1), 'u…');
	t.is(ellipsis('unicorn', 3), 'uni…');
	t.is(ellipsis('unicorn', 7), 'unicorn…');
	t.is(ellipsis('unicorn', 100), 'unicorn…');

	t.end();
});

test('The length should default to taking the whole string', function (t) {
	t.is(ellipsis('unicorn'), 'unicorn…');
	t.end();
});

test('should throw on nonsense input', function (t) {
	[function () {}, 123, [], null].forEach(function (input) {
		t.throws(function () {
			ellipsis(input, 30);
		});
	});

	t.end();
});
<commit_msg>ES2015ify tests<commit_after>import test from 'ava';
import ellipsis from './';

test('should cut off a string and add an ellipsis', t => {
	t.is(ellipsis('unicorn', 1), 'u…');
	t.is(ellipsis('unicorn', 3), 'uni…');
	t.is(ellipsis('unicorn', 7), 'unicorn…');
	t.is(ellipsis('unicorn', 100), 'unicorn…');

	t.end();
});

test('The length should default to taking the whole string', t => {
	t.is(ellipsis('unicorn'), 'unicorn…');
	t.end();
});

test('should throw on nonsense input', t => {
	[123, [], null].forEach(input => {
		t.throws(() => {
			ellipsis(input, 30);
		});
	});

	t.end();
});
<|endoftext|>


<commit_before>var Path = require("path");
var Dust = require("dustjs-linkedin");
var LoaderUtils = require("loader-utils");
var Async = require("async");
var FS = require("fs");

// Use the `paths` option to generate a template name based on the
// path of the .dust file.
//
// E.g. if paths is ["C:\MyApp\dust"] and resourcePath is
// "C:\MyApp\dust\home\widgets\welcome.dust" then the template name
// will be "home-widgets-welcome".
var uniqueNumber = 1;
var moduleMapping = {};

function getTemplateName(paths, resourcePath) {
    // We want to loop through each path and see if it matches part of the file path.
    for (var i = 0; i < paths.length; i++) {
        var path = paths[i];

        if (resourcePath.indexOf(path) == 0) {
            if (Path.basename(resourcePath) == "index.dust")
                resourcePath = Path.dirname(resourcePath);
            else
                resourcePath = resourcePath.replace(/\.dust$/i, "");

            return resourcePath
                .replace(path + Path.sep, "")
                // If the path includes slashes or spaces, replace them with hyphens.
                .replace(/[\\\/\s]+/g, "-");
        }
    }

    // If it's not in a known path, which means it's just not a partial, and
    // therefore doesn't need a name. (We just return "anonymous123", where
    // each .dust file gets a different number.)

    // Don't generate different template names for the same template.
    resourcePath = Path.resolve(resourcePath);
    if (resourcePath in moduleMapping)
        return moduleMapping[resourcePath];

    return moduleMapping[resourcePath] = "anonymousTemplate" + (uniqueNumber++);
}

function resolveDependency(ctx, dep, paths, callback) {
    if (dep.partialName) {
        resolvePartialName(dep.partialName, paths, callback);
    } else {
        ctx.resolve(ctx.context, dep.moduleName + ".dust", function(err, path) {
            if (err)
                return ctx.resolve(ctx.context, dep.moduleName + "/index.dust", callback);

            return callback(null, path);
        });
    }
}

function resolvePartialNameInPath(name, path, callback) {
    //console.log("Looking for", name, "in", path)

    if (name.length === 0)
        name = ["index"];

    var head = name[0],
        dustFile = Path.join(path, (head || "index") + ".dust"),
        subPath = Path.join(path, head);

    FS.exists(dustFile, function(hasDust) {
        // Found it!
        if (hasDust)
            return callback(null, dustFile);

        if (!head)
            return callback(null, false);

        FS.exists(subPath, function(folderExists) {
            // Found a matching folder! We must go deeper.
            if (folderExists) {
                return resolvePartialNameInPath(name.slice(1), subPath, callback);
            }

            // Not found. However, we might just need to try a longer path component.
            // E.g. framework-item-grading-list could be framework/item/grading-list
            // or framework-item/grading/list...
            if (name.length > 1) {
                var newName = name.slice(2);
                newName.unshift(name[0] + "-" + name[1]);
                //name = (name[0] + "-" + name[1]).concat(name.slice(2));
                return resolvePartialNameInPath(newName, path, callback);
            }

            // Not found, or possible to find.
            return callback(null, false);
        });
    });
}

function resolvePartialName(name, paths, callback) {
    if (typeof name === "string")
        return resolvePartialName(name.split(/-/), paths, callback);

    Async.eachSeries(paths, function(path, cb) {
        resolvePartialNameInPath(name, path, function(err, result) {
            if (err)
                return cb(err);

            // Found it (early return)
            if (result)
                return callback(null, result);

            // Try the next path
            return cb();
        });
    }, function(err) {
        if (err)
            return callback(err);

        // If we get here, we didn't find it.
        return callback(undefined);
    });
}

// Find {>".path/to/partial"/} references using a regular expression, and
// record where it was found (so that we can rewrite it later).
//
// This cannot possibly support interpolated template names, because the
// partial name isn't actually known until runtime.
//
// (A solution to this involving `require.context` is left as an exercise
// to the reader.)
function findDependencies(content) {
    var partials = [];
    var partialRegExp = /\{>\s*(?:([\w\d\-]+)|[^"]*"([^"]*)")/g;
    var match;

    while ((match = partialRegExp.exec(content))) {
        var partialName = match[1],
            moduleName = match[2];

        // Ignore interpolated template names, which have to use quotes
        if (moduleName && (moduleName.indexOf('{') > -1))
            continue;

        partials.push({
            partialName: partialName,
            moduleName: moduleName,
            index: match.index,
            length: match[0].length
        });
    }

    return partials;
}

// Replaces {>"./path/to/template"/} references with whatever the template's name
// should be (taking the `paths` option into account).
function rewriteDependencies(content, deps) {
    var index = 0, // Current position in the content string
        chunks = [];

    deps.forEach(function(dep) {
        chunks.push(content.substring(index, dep.index));
        chunks.push('{>' + dep.newName);
        index = dep.index + dep.length;
    });

    if (index < content.length)
        chunks.push(content.substring(index));

    return chunks.join("");
}

// Generate some require statements, so that the partials get loaded when the template
// is required.
function getDependenciesJS(deps) {
    return deps.map(function(dep) {
        return "require(" + JSON.stringify(dep.rawPath) + ");";
    }).join("\n");
}

module.exports = function(content) {
    var query = LoaderUtils.parseQuery(this.query);

    this.cacheable && this.cacheable();

    // Resolving module references is asynchronous.
    var cb = this.async();

    // Partial paths
    var paths = [];
    if (query.path)
        paths.push(query.path);

    if (query.paths)
        paths.push.apply(paths, query.paths);

    var deps = findDependencies(content);

    Async.eachSeries(deps, function(dep, callback) {
        resolveDependency(this, dep, paths, function(err, rawPath) {
            if (err)
                return callback(err);

            if (!rawPath)
                return callback(new Error("Unable to resolve dust partial: " + (dep.partialName || dep.moduleName)));

            if (query.verbose)
                console.log("Resolved", (dep.partialName || dep.moduleName), "to", rawPath);

            dep.rawPath = rawPath;
            this.addDependency(rawPath);

            var newName = getTemplateName(paths, rawPath);
            if (dep.partialName && dep.partialName != newName)
                return callback(new Error("Partial name doesn't resolve to itself: " + dep.partialName + " -> " + newName));
            dep.newName = newName;

            return callback();
        }.bind(this));
    }.bind(this), function(err) {
        if (err)
            return cb(err);

        content = rewriteDependencies(content, deps);
        var templateName = getTemplateName(paths, this.resourcePath);

        var compiled;
        try {
            compiled = Dust.compile(content, templateName);
        } catch(e) {
            return cb(e);
        }

        var output = [
            // The output of the compile function requires that the variable 'dust' exists. Without a module system, 'dust'
            // would exist on the window, making it a global variable.
            "var dust = require('dustjs-linkedin');\n",

            // Any require() statements for partials.
            getDependenciesJS(deps),

            // Compile the template returning an stringified IIFE registering the template under the name in 'templateName'.
            "\n" + compiled + "\n",

            // Return the template name to make the require statement more meaningful.
            "module.exports = " + JSON.stringify(templateName) + ";"
        ].join("");

        return cb(null, output);
    }.bind(this));

};
<commit_msg>Fix issue where partial may resolve to an incorrect path if one of the intermediate paths exists.<commit_after>var Path = require("path");
var Dust = require("dustjs-linkedin");
var LoaderUtils = require("loader-utils");
var Async = require("async");
var FS = require("fs");

// Use the `paths` option to generate a template name based on the
// path of the .dust file.
//
// E.g. if paths is ["C:\MyApp\dust"] and resourcePath is
// "C:\MyApp\dust\home\widgets\welcome.dust" then the template name
// will be "home-widgets-welcome".
var uniqueNumber = 1;
var moduleMapping = {};

function getTemplateName(paths, resourcePath) {
    // We want to loop through each path and see if it matches part of the file path.
    for (var i = 0; i < paths.length; i++) {
        var path = paths[i];

        if (resourcePath.indexOf(path) == 0) {
            if (Path.basename(resourcePath) == "index.dust")
                resourcePath = Path.dirname(resourcePath);
            else
                resourcePath = resourcePath.replace(/\.dust$/i, "");

            return resourcePath
                .replace(path + Path.sep, "")
                // If the path includes slashes or spaces, replace them with hyphens.
                .replace(/[\\\/\s]+/g, "-");
        }
    }

    // If it's not in a known path, which means it's just not a partial, and
    // therefore doesn't need a name. (We just return "anonymous123", where
    // each .dust file gets a different number.)

    // Don't generate different template names for the same template.
    resourcePath = Path.resolve(resourcePath);
    if (resourcePath in moduleMapping)
        return moduleMapping[resourcePath];

    return moduleMapping[resourcePath] = "anonymousTemplate" + (uniqueNumber++);
}

function resolveDependency(ctx, dep, paths, callback) {
    if (dep.partialName) {
        resolvePartialName(dep.partialName, paths, callback);
    } else {
        ctx.resolve(ctx.context, dep.moduleName + ".dust", function(err, path) {
            if (err)
                return ctx.resolve(ctx.context, dep.moduleName + "/index.dust", callback);

            return callback(null, path);
        });
    }
}

function resolvePartialNameInPath(name, path, callback) {
    //console.log("Looking for", name, "in", path);

    if (name.length === 0)
        name = ["index"];

    var head = name[0],
        dustFile = Path.join.apply(Path, [path].concat(name)) + ".dust",
        subPath = Path.join(path, head);

    FS.exists(dustFile, function(hasDust) {
        // Found it!
        if (hasDust)
            return callback(null, dustFile);

        if (!head)
            return callback(null, false);

        FS.exists(subPath, function(folderExists) {
            // Found a matching folder! We must go deeper.
            if (folderExists) {
                return resolvePartialNameInPath(name.slice(1), subPath, callback);
            }

            // Not found. However, we might just need to try a longer path component.
            // E.g. framework-item-grading-list could be framework/item/grading-list
            // or framework-item/grading/list...
            if (name.length > 1) {
                var newName = name.slice(2);
                newName.unshift(name[0] + "-" + name[1]);
                //name = (name[0] + "-" + name[1]).concat(name.slice(2));
                return resolvePartialNameInPath(newName, path, callback);
            }

            // Not found, or possible to find.
            return callback(null, false);
        });
    });
}

function resolvePartialName(name, paths, callback) {
    if (typeof name === "string")
        return resolvePartialName(name.split(/-/), paths, callback);

    Async.eachSeries(paths, function(path, cb) {
        resolvePartialNameInPath(name, path, function(err, result) {
            if (err)
                return cb(err);

            // Found it (early return)
            if (result)
                return callback(null, result);

            // Try the next path
            return cb();
        });
    }, function(err) {
        if (err)
            return callback(err);

        // If we get here, we didn't find it.
        return callback(undefined);
    });
}

// Find {>".path/to/partial"/} references using a regular expression, and
// record where it was found (so that we can rewrite it later).
//
// This cannot possibly support interpolated template names, because the
// partial name isn't actually known until runtime.
//
// (A solution to this involving `require.context` is left as an exercise
// to the reader.)
function findDependencies(content) {
    var partials = [];
    var partialRegExp = /\{>\s*(?:([\w\d\-]+)|[^"]*"([^"]*)")/g;
    var match;

    while ((match = partialRegExp.exec(content))) {
        var partialName = match[1],
            moduleName = match[2];

        // Ignore interpolated template names, which have to use quotes
        if (moduleName && (moduleName.indexOf('{') > -1))
            continue;

        partials.push({
            partialName: partialName,
            moduleName: moduleName,
            index: match.index,
            length: match[0].length
        });
    }

    return partials;
}

// Replaces {>"./path/to/template"/} references with whatever the template's name
// should be (taking the `paths` option into account).
function rewriteDependencies(content, deps) {
    var index = 0, // Current position in the content string
        chunks = [];

    deps.forEach(function(dep) {
        chunks.push(content.substring(index, dep.index));
        chunks.push('{>' + dep.newName);
        index = dep.index + dep.length;
    });

    if (index < content.length)
        chunks.push(content.substring(index));

    return chunks.join("");
}

// Generate some require statements, so that the partials get loaded when the template
// is required.
function getDependenciesJS(deps) {
    return deps.map(function(dep) {
        return "require(" + JSON.stringify(dep.rawPath) + ");";
    }).join("\n");
}

module.exports = function(content) {
    var query = LoaderUtils.parseQuery(this.query);

    this.cacheable && this.cacheable();

    // Resolving module references is asynchronous.
    var cb = this.async();

    // Partial paths
    var paths = [];
    if (query.path)
        paths.push(query.path);

    if (query.paths)
        paths.push.apply(paths, query.paths);

    var deps = findDependencies(content);

    Async.eachSeries(deps, function(dep, callback) {
        resolveDependency(this, dep, paths, function(err, rawPath) {
            if (err)
                return callback(err);

            if (!rawPath)
                return callback(new Error("Unable to resolve dust partial: " + (dep.partialName || dep.moduleName)));

            if (query.verbose)
                console.log("Resolved", (dep.partialName || dep.moduleName), "to", rawPath);

            dep.rawPath = rawPath;
            this.addDependency(rawPath);

            var newName = getTemplateName(paths, rawPath);
            if (dep.partialName && dep.partialName != newName)
                return callback(new Error("Partial name doesn't resolve to itself: " + dep.partialName + " -> " + newName));
            dep.newName = newName;

            return callback();
        }.bind(this));
    }.bind(this), function(err) {
        if (err)
            return cb(err);

        content = rewriteDependencies(content, deps);
        var templateName = getTemplateName(paths, this.resourcePath);

        var compiled;
        try {
            compiled = Dust.compile(content, templateName);
        } catch(e) {
            return cb(e);
        }

        var output = [
            // The output of the compile function requires that the variable 'dust' exists. Without a module system, 'dust'
            // would exist on the window, making it a global variable.
            "var dust = require('dustjs-linkedin');\n",

            // Any require() statements for partials.
            getDependenciesJS(deps),

            // Compile the template returning an stringified IIFE registering the template under the name in 'templateName'.
            "\n" + compiled + "\n",

            // Return the template name to make the require statement more meaningful.
            "module.exports = " + JSON.stringify(templateName) + ";"
        ].join("");

        return cb(null, output);
    }.bind(this));

};
<|endoftext|>


<commit_before>var _ = require('lodash'),
    Cursor = require('../cursor'),
    VariableScope = require('postman-collection').VariableScope,

    prepareLookupHash,
    extractSNR;

/**
 * Returns a hash of IDs and Names of items in an array
 *
 * @param {Array} items
 * @returns {Object}
 */
prepareLookupHash = function (items) {
    var hash = {
        ids: {},
        names: {},
        obj: {}
    };

    _.each(items, function (item, index) {
        if (item) {
            item.id && (hash.ids[item.id] = index);
            item.name && (hash.names[item.name] = index);
        }
    });

    return hash;
};

extractSNR = function (executions, previous) {
    var snr = previous || {};

    _.isArray(executions) && executions.forEach(function (execution) {
        _.has(_.get(execution, 'result.return'), 'nextRequest') && (
            (snr.defined = true),
            (snr.value = execution.result.return.nextRequest)
        );
    });

    return snr;
};

/**
 * Adds options
 * disableSNR:Boolean
 *
 * @type {Object}
 */
module.exports = {
    init: function (done) {
        var state = this.state;

        // ensure that the environment and globals are in VariableScope instance format
        state.environment = VariableScope.isVariableScope(state.environment) ? state.environment :
            new VariableScope(state.environment);
        state.globals = VariableScope.isVariableScope(state.globals) ? state.globals :
            new VariableScope(state.globals);

        // ensure that the items and iteration data set is in place
        !_.isArray(state.items) && (state.items = []);
        !_.isArray(state.data) && (state.data = []);
        !_.isObject(state.data[0]) && (state.data[0] = {});

        // if the location in state is already normalised then go ahead and queue iteration, else normalise the
        // location
        state.cursor = Cursor.box(state.cursor, { // we pass bounds to ensure there is no stale state
            cycles: state.data.length,
            length: state.items.length
        });
        this.waterfall = state.cursor; // copy the location object to instance for quick access

        // queue the iteration command on start
        this.queue('waterfall', {
            coords: this.waterfall.current(),
            static: true,
            start: true
        });

        // clear the variable that is supposed to store item name and id lookup hash for easy setNextRequest
        this.snrHash = null; // we populate it in the first SNR call

        done();
    },

    triggers: ['beforeIteration', 'iteration'],

    process: {
        /**
         * This processor simply queues scripts and requests in a linear chain.
         *
         * @param {Object} payload
         * @param {Object} payload.coords
         * @param {Boolean} [payload.static=false]
         * @param {Function} next
         */
        waterfall: function (payload, next) {
            // we procure the coordinates that we have to pick item and data from. the data is
            var coords = payload.static ? payload.coords : this.waterfall.whatnext(payload.coords),
                item = this.state.items[coords.position],
                delay;

            // if there is nothing to process, we bail out from here, even before we enter the iteration cycle
            if (coords.empty) {
                return next();
            }

            if (payload.stopRunNow) {
                this.triggers.iteration(null, payload.coords);
                return next();
            }

            // if it is a beginning of a run, we need to raise events for iteration start
            if (payload.start) {
                this.triggers.beforeIteration(null, coords);
            }

            // if this is a new iteration, we close the previous one and start new
            if (coords.cr) {
                // getting the iteration delay here ensures that delay is only called between two iterations
                delay = _.get(this.options, 'delay.iteration', 0);

                this.triggers.iteration(null, payload.coords);
                this.triggers.beforeIteration(null, coords);
            }

            // if this is end of waterfall, it is an end of iteration and also end of run
            if (coords.eof) {
                this.triggers.iteration(null, coords);
                return next();
            }

            this.queueDelay(function () {
                this.queue('item', {
                    item: item,
                    coords: coords,
                    data: this.state.data[coords.iteration],
                    environment: this.state.environment,
                    globals: this.state.globals
                }, function (executionError, executions) {
                    var snr = {},
                        nextCoords,
                        seekingToStart,
                        stopRunNow,

                        stopOnFailure = this.options.stopOnFailure;

                    if (!executionError) {
                        // extract set next request
                        snr = extractSNR(executions.prerequest);
                        snr = extractSNR(executions.test, snr);
                    }

                    if (!this.options.disableSNR && snr.defined) {
                        // prepare the snr lookup hash if it is not already provided
                        // @todo - figure out a way to reset this post run complete
                        !this.snrHash && (this.snrHash = prepareLookupHash(this.state.items));

                        // if it is null, we do not proceed further and move on
                        // see if a request is found in the hash and then reset the coords position to the lookup
                        // value.
                        (snr.value !== null) && (snr.position =
                            this.snrHash[_.has(this.snrHash.ids, snr.value) ? 'ids' :
                                (_.has(this.snrHash.names, snr.value) ? 'names' : 'obj')][snr.value]);

                        snr.valid = _.isNumber(snr.position);
                    }

                    nextCoords = _.clone(coords);

                    if (snr.valid) {
                        // if the position was detected, we set the position to the one previous to the desired location
                        // this ensures that the next call to .whatnext() will return the desired position.
                        nextCoords.position = snr.position - 1;
                    }
                    else {
                        // if snr was requested, but not valid, we stop this iteration.
                        // stopping an iteration is equivalent to seeking the last position of the current
                        // iteration, so that the next call to .whatnext() will automatically move to the next
                        // iteration.
                        (snr.defined || executionError) && (nextCoords.position = nextCoords.length - 1);

                        // If we need to stop on a run, we set the stop flag to true.
                        (stopOnFailure && executionError) && (stopRunNow = true);
                    }

                    // @todo - do this in unhacky way
                    if (nextCoords.position === -1) {
                        nextCoords.position = 0;
                        seekingToStart = true;
                    }

                    this.waterfall.seek(nextCoords.position, nextCoords.iteration, function (err, chngd, coords) {
                        // this condition should never arise, so better throw error when this happens
                        if (err) {
                            throw err;
                        }

                        this.queue('waterfall', {
                            coords: coords,
                            static: seekingToStart,
                            stopRunNow: stopRunNow
                        });
                    }, this);
                });
            }.bind(this), {
                time: delay,
                source: 'iteration',
                cursor: coords
            }, next);
        }
    }
};
<commit_msg>Restored SNR source to legacy structure<commit_after>var _ = require('lodash'),
    Cursor = require('../cursor'),
    VariableScope = require('postman-collection').VariableScope,

    prepareLookupHash,
    extractSNR;

/**
 * Returns a hash of IDs and Names of items in an array
 *
 * @param {Array} items
 * @returns {Object}
 */
prepareLookupHash = function (items) {
    var hash = {
        ids: {},
        names: {},
        obj: {}
    };

    _.each(items, function (item, index) {
        if (item) {
            item.id && (hash.ids[item.id] = index);
            item.name && (hash.names[item.name] = index);
        }
    });

    return hash;
};

extractSNR = function (executions, previous) {
    var snr = previous || {};

    _.isArray(executions) && executions.forEach(function (execution) {
        _.has(_.get(execution, 'result.masked'), 'nextRequest') && (
            (snr.defined = true),
            (snr.value = execution.result.masked.nextRequest)
        );
    });

    return snr;
};

/**
 * Adds options
 * disableSNR:Boolean
 *
 * @type {Object}
 */
module.exports = {
    init: function (done) {
        var state = this.state;

        // ensure that the environment and globals are in VariableScope instance format
        state.environment = VariableScope.isVariableScope(state.environment) ? state.environment :
            new VariableScope(state.environment);
        state.globals = VariableScope.isVariableScope(state.globals) ? state.globals :
            new VariableScope(state.globals);

        // ensure that the items and iteration data set is in place
        !_.isArray(state.items) && (state.items = []);
        !_.isArray(state.data) && (state.data = []);
        !_.isObject(state.data[0]) && (state.data[0] = {});

        // if the location in state is already normalised then go ahead and queue iteration, else normalise the
        // location
        state.cursor = Cursor.box(state.cursor, { // we pass bounds to ensure there is no stale state
            cycles: state.data.length,
            length: state.items.length
        });
        this.waterfall = state.cursor; // copy the location object to instance for quick access

        // queue the iteration command on start
        this.queue('waterfall', {
            coords: this.waterfall.current(),
            static: true,
            start: true
        });

        // clear the variable that is supposed to store item name and id lookup hash for easy setNextRequest
        this.snrHash = null; // we populate it in the first SNR call

        done();
    },

    triggers: ['beforeIteration', 'iteration'],

    process: {
        /**
         * This processor simply queues scripts and requests in a linear chain.
         *
         * @param {Object} payload
         * @param {Object} payload.coords
         * @param {Boolean} [payload.static=false]
         * @param {Function} next
         */
        waterfall: function (payload, next) {
            // we procure the coordinates that we have to pick item and data from. the data is
            var coords = payload.static ? payload.coords : this.waterfall.whatnext(payload.coords),
                item = this.state.items[coords.position],
                delay;

            // if there is nothing to process, we bail out from here, even before we enter the iteration cycle
            if (coords.empty) {
                return next();
            }

            if (payload.stopRunNow) {
                this.triggers.iteration(null, payload.coords);
                return next();
            }

            // if it is a beginning of a run, we need to raise events for iteration start
            if (payload.start) {
                this.triggers.beforeIteration(null, coords);
            }

            // if this is a new iteration, we close the previous one and start new
            if (coords.cr) {
                // getting the iteration delay here ensures that delay is only called between two iterations
                delay = _.get(this.options, 'delay.iteration', 0);

                this.triggers.iteration(null, payload.coords);
                this.triggers.beforeIteration(null, coords);
            }

            // if this is end of waterfall, it is an end of iteration and also end of run
            if (coords.eof) {
                this.triggers.iteration(null, coords);
                return next();
            }

            this.queueDelay(function () {
                this.queue('item', {
                    item: item,
                    coords: coords,
                    data: this.state.data[coords.iteration],
                    environment: this.state.environment,
                    globals: this.state.globals
                }, function (executionError, executions) {
                    var snr = {},
                        nextCoords,
                        seekingToStart,
                        stopRunNow,

                        stopOnFailure = this.options.stopOnFailure;

                    if (!executionError) {
                        // extract set next request
                        snr = extractSNR(executions.prerequest);
                        snr = extractSNR(executions.test, snr);
                    }

                    if (!this.options.disableSNR && snr.defined) {
                        // prepare the snr lookup hash if it is not already provided
                        // @todo - figure out a way to reset this post run complete
                        !this.snrHash && (this.snrHash = prepareLookupHash(this.state.items));

                        // if it is null, we do not proceed further and move on
                        // see if a request is found in the hash and then reset the coords position to the lookup
                        // value.
                        (snr.value !== null) && (snr.position =
                            this.snrHash[_.has(this.snrHash.ids, snr.value) ? 'ids' :
                                (_.has(this.snrHash.names, snr.value) ? 'names' : 'obj')][snr.value]);

                        snr.valid = _.isNumber(snr.position);
                    }

                    nextCoords = _.clone(coords);

                    if (snr.valid) {
                        // if the position was detected, we set the position to the one previous to the desired location
                        // this ensures that the next call to .whatnext() will return the desired position.
                        nextCoords.position = snr.position - 1;
                    }
                    else {
                        // if snr was requested, but not valid, we stop this iteration.
                        // stopping an iteration is equivalent to seeking the last position of the current
                        // iteration, so that the next call to .whatnext() will automatically move to the next
                        // iteration.
                        (snr.defined || executionError) && (nextCoords.position = nextCoords.length - 1);

                        // If we need to stop on a run, we set the stop flag to true.
                        (stopOnFailure && executionError) && (stopRunNow = true);
                    }

                    // @todo - do this in unhacky way
                    if (nextCoords.position === -1) {
                        nextCoords.position = 0;
                        seekingToStart = true;
                    }

                    this.waterfall.seek(nextCoords.position, nextCoords.iteration, function (err, chngd, coords) {
                        // this condition should never arise, so better throw error when this happens
                        if (err) {
                            throw err;
                        }

                        this.queue('waterfall', {
                            coords: coords,
                            static: seekingToStart,
                            stopRunNow: stopRunNow
                        });
                    }, this);
                });
            }.bind(this), {
                time: delay,
                source: 'iteration',
                cursor: coords
            }, next);
        }
    }
};
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var should = require('should');
var barracks = require('./index.js');

/**
 * Test
 */

describe('dispatcher()', function() {

  it('should catch errors', function() {

    barracks.bind(barracks)
      .should.throw('An \'actions\' object should be passed as an argument');

    var arg = 123;
    barracks.bind(barracks, arg)
      .should.throw('Actions should be an object');

    arg = {users: 123};
    barracks.bind(barracks, arg)
      .should.throw('Action should be a function');

    arg = {users: {add: 123}}
    barracks.bind(barracks, arg)
      .should.throw('Action should be a function');

    arg = {users: {add: {veryMuch: 123}}}
    barracks.bind(barracks, arg)
      .should.throw('Namespaces should not be nested');
  });

  it('should return a function', function() {
    var dispatcher = barracks({
      users: {
        add: function() {},
        remove: function() {}
      },
      courses: {
        get: function() {},
        put: function() {done()}
      }
    });

    dispatcher.should.be.type('function');
  });
});

describe('dispatcher()()', function() {

  it('should catch errors', function() {
    var dispatcher = barracks({});

    dispatcher.bind(dispatcher, {})
      .should.throw('Action should be a string');

    dispatcher.bind(dispatcher, 'something_is_odd')
      .should.throw('Namespaces should not be nested');

    dispatcher.bind(dispatcher, 'something')
      .should.throw('Action \'something\' is not registered');
  });

  it('should call actions', function(done) {

    var dispatcher = barracks({
      users: {
        add: function() {},
        remove: function() {}
      },
      courses: {
        get: function() {},
        put: function(fn) {fn()}
      }
    });

    dispatcher('courses_put', done);
  });

  it('should call a callback when done', function(done) {

    var dispatcher = barracks({
      users: {
        add: function() {},
        remove: function() {}
      },
      courses: {
        get: function() {},
        put: function(value, cb) {cb(value)}
      }
    });

    dispatcher('courses_put', done, doneHandler);

    function doneHandler(fn) {
      fn();
    }
  });
});
<commit_msg>test: fix test coverage<commit_after>/**
 * Module dependencies
 */

var should = require('should');
var barracks = require('./index.js');

/**
 * Test
 */

describe('dispatcher()', function() {

  it('should catch errors', function() {

    barracks.bind(barracks)
      .should.throw('An \'actions\' object should be passed as an argument');

    var arg = 123;
    barracks.bind(barracks, arg)
      .should.throw('Actions should be an object');

    arg = {users: 123};
    barracks.bind(barracks, arg)
      .should.throw('Action should be a function');

    arg = {users: {add: 123}}
    barracks.bind(barracks, arg)
      .should.throw('Action should be a function');

    arg = {users: {add: {veryMuch: 123}}}
    barracks.bind(barracks, arg)
      .should.throw('Namespaces should not be nested');
  });

  it('should return a function', function() {
    var dispatcher = barracks({
      users: {
        add: function() {},
        remove: function() {}
      },
      courses: {
        get: function() {},
        put: function() {}
      }
    });

    dispatcher.should.be.type('function');
  });
});

describe('dispatcher()()', function() {

  it('should catch errors', function() {
    var dispatcher = barracks({});

    dispatcher.bind(dispatcher, {})
      .should.throw('Action should be a string');

    dispatcher.bind(dispatcher, 'something_is_odd')
      .should.throw('Namespaces should not be nested');

    dispatcher.bind(dispatcher, 'something')
      .should.throw('Action \'something\' is not registered');
  });

  it('should call actions', function(done) {

    var dispatcher = barracks({
      users: {
        add: function() {},
        remove: function() {}
      },
      courses: {
        get: function() {},
        put: function(fn) {fn()}
      }
    });

    dispatcher('courses_put', done);
  });

  it('should call a callback when done', function(done) {

    var dispatcher = barracks({
      users: {
        add: function() {},
        remove: function() {}
      },
      courses: {
        get: function() {},
        put: function(value, cb) {cb(value)}
      }
    });

    dispatcher('courses_put', done, doneHandler);

    function doneHandler(fn) {
      fn();
    }
  });
});
<|endoftext|>