<commit_before>require('moonstone');

/**
* Contains the declaration for the {@link module:moonstone/ExpandableListItem~ExpandableListItem} kind.
* @module moonstone/ExpandableListItem
*/

var
	kind = require('enyo/kind'),
	Component = require('enyo/Component'),
	Control = require('enyo/Control'),
	Group = require('enyo/Group'),
	options = require('enyo/options');

var
	Spotlight = require('spotlight');

var
	Item = require('../Item'),
	Marquee = require('../Marquee'),
	MarqueeText = Marquee.Text;

var
	ExpandableListItemHeader = require('./ExpandableListItemHeader'),
	ExpandableListItemDrawer = require('./ExpandableListItemDrawer'),
	ExpandableListItemAccessibilitySupport = require('./ExpandableListItemAccessibilitySupport');

/**
* {@link module:moonstone/ExpandableListItem~ExpandableListItem}, which extends {@link module:moonstone/Item~Item}, displays a header
* while also allowing additional content to be stored in an {@link module:enyo/Drawer~Drawer}. When
* the header is selected, the drawer opens below. To close the drawer, tap on the
* header text or navigate (via 5-way) back to the top of the drawer.
*
* The control's child components may be of any kind; by default, they are
* instances of `moon.Item`.
*
* ```javascript
* var
* 	kind = require('enyo/kind'),
* 	ExpandableListItem = require('moonstone/ExpandableListItem');
*
* {kind: ExpandableListItem, content: 'A Countries', components: [
* 	{content: 'Algeria'},
* 	{content: 'Argentina'},
* 	{content: 'Australia'}
* ]},
* {kind: ExpandableListItem, content: 'B Countries', components: [
* 	{content: 'Belgium'},
* 	{content: 'Bolivia'},
* 	{content: 'Brazil'}
* ]}
* ```
*
* When multiple ExpandableListItems are used in a group, only one may be open at
* a given time.
*
* ```javascript
* var
* 	kind = require('enyo/kind'),
*	Group = require('enyo/Group'),
* 	ExpandableListItem = require('moonstone/ExpandableListItem');
*
* {kind: Group, highlander: true, components: [
* 	{kind: ExpandableListItem,  open: true,
* 		content: 'This is a grouped ExpandableListItem', components: [
* 			{content: 'Item One'},
* 			{content: 'Item Two'}
* 		]
* 	},
* 	{kind: ExpandableListItem,
* 		content: 'This is another grouped ExpandableListItem', components: [
* 			{content: 'Item Three'},
* 			{content: 'Item Four'}
* 		]
* 	},
* 	{kind: ExpandableListItem,
* 		content: 'This is yet another grouped ExpandableListItem', components: [
* 			{content: 'Item Five'},
* 			{content: 'Item Six'}
* 		]
* 	}
* ]}
* ```
*
* @class ExpandableListItem
* @extends module:enyo/Control~Control
* @ui
* @public
*/
module.exports = kind(
	/** @lends module:moonstone/ExpandableListItem~ExpandableListItem.prototype */ {

	/**
	* @private
	*/
	name: 'moon.ExpandableListItem',

	/**
	* @private
	*/
	kind: Control,

	/**
	* @private
	*/
	mixins: options.accessibility ? [ExpandableListItemAccessibilitySupport] : null,

	/**
	* @private
	* @lends module:moonstone/ExpandableListItem~ExpandableListItem.prototype
	*/
	published: {

		/**
		* If `true`, the drawer automatically closes when the user navigates to the top of the
		* control; if `false`, the user must select/tap the header to close the drawer.
		*
		* @type {Boolean}
		* @default false
		* @public
		*/
		autoCollapse: false,

		/**
		* If `true`, the drawer is expanded, showing this item's contents. Use this property
		* (rather than [active]{@link module:moonstone/ExpandableListItem~ExpandableListItem#active}) to set the item's
		* initial state.
		*
		* @type {Boolean}
		* @default false
		* @public
		*/
		open: false,

		/**
		* Boolean that reflects the value of the [open]{@link module:moonstone/ExpandableListItem~ExpandableListItem#open}
		* property; it is used to support the {@link module:enyo/Group~Group} API for grouping a set of
		* ExpandableListItems in which only one is expanded at a time. Note that the `open`
		* property (not the `active` property) controls the initial state of the picker.
		*
		* @type {Boolean}
		* @default false
		* @public
		*/
		active: false,

		/**
		* If `true`, the user is prevented from moving {@glossary Spotlight} past the bottom
		* of the drawer (when open) using 5-way controls.
		*
		* @type {Boolean}
		* @default false
		* @public
		*/
		lockBottom: false,

		/**
		* If `true`, item is shown as disabled and does not generate tap events.
		*
		* @type {Boolean}
		* @default false
		* @public
		*/
		disabled: false
	},

	/**
	* @private
	*/
	classes: 'moon-expandable-list-item',

	/**
	* @private
	*/
	spotlight: false,

	/**
	* @private
	*/
	defaultKind: Item,

	/**
	* @private
	*/
	drawerComponents: [
		{name: 'client', kind: Group, tag: null}
	],

	/**
	* @private
	*/
	components: [
		{name: 'header', kind: ExpandableListItemHeader, ontap: 'headerTapped'},
		{name: 'drawer', kind: ExpandableListItemDrawer, resizeContainer: false, classes: 'moon-expandable-list-item-client', defaultSpotlightUp: 'header', onSpotlightUp: 'drawerSpotUp', onSpotlightDown: 'drawerSpotDown', onDrawerAnimationEnd: 'drawerAnimationEnd'}
	],

	/**
	* @private
	*/
	bindings: [
		{from: 'active', to: 'open'},
		{from: 'allowHtml', to: '$.header.allowHtml'},
		{from: 'disabled', to: '$.header.disabled'},
		{from: 'content', to: '$.header.label'},
		{from: 'currentValueShowing', to: '$.header.textShowing'},
		{from: 'currentValueText', to: '$.header.text'}
	],

	/**
	* @private
	*/
	computed: {
		'currentValueShowing': ['open', 'value'],
		'currentValueText': ['value']
	},

	/**
	* @private
	*/
	create: function () {
		Control.prototype.create.apply(this, arguments);
		this.openChanged();
		this.disabledChanged();
		this.notifyObservers('value');
	},

	/**
	* @private
	*/
	initComponents: function () {
		var override = {drawer: {components: this.drawerComponents}};
		this.kindComponents = Component.overrideComponents(this.kindComponents, override);
		Control.prototype.initComponents.apply(this, arguments);
	},

	/**
	* Facade for drawer.
	*
	* @private
	*/
	openChanged: function () {
		var open = this.open;
		this.bubble('onActivate', {allowHighlanderDeactivate: true});
		this.addRemoveClass('open', open);
		this.$.drawer.set('open', open);
		this.$.drawer.spotlightDisabled = !open;
		this.set('active', open);
	},

	/**
	* @fires module:enyo/GroupItem~GroupItem#onActivate
	* @private
	*/
	activeChanged: function () {
		this.bubble('onActivate', {allowHighlanderDeactivate:true});
		this.set('open', this.active);
	},

	/**
	* @private
	*/
	disabledChanged: function () {
		var disabled = this.disabled;

		this.addRemoveClass('disabled', disabled);
		if (disabled) {
			this.set('active', false);
		}
	},

	/**
	* Returns `true` if the current value control should be displayed.
	*
	* Note: ExpandableListItem doesn't support currentValue but its subkinds do
	*
	* @private
	*/
	currentValueShowing: function () {
		var text = this.get('currentValueText');
		// If drawer is open or value is blank, don't bother to show the value.
		return (!this.open && (text || text === 0));
	},

	/**
	* Returns the text to be displayed within the current value control
	*
	* Note: ExpandableListItem doesn't support currentValue but its subkinds do
	*
	* @private
	*/
	currentValueText: function () {
		return '';
	},

	/**
	* If closed, opens drawer and highlights first spottable child.
	*
	* @private
	*/
	expandContract: function () {
		var spot;
		if (this.open) {
			this.closeDrawerAndHighlightHeader();
		} else {
			this.toggleActive();
			if (!Spotlight.getPointerMode() && !Spotlight.isFrozen()) {
				var first = Spotlight.getFirstChild(this.$.drawer);
				Spotlight.spot(first);
			}
		}
	},

	/**
	* @private
	*/
	toggleActive: function () {
		this.set('active', !this.open);
	},

	/**
	* @private
	*/
	closeDrawerAndHighlightHeader: function () {
		var mode = Spotlight.getPointerMode(),
			current = Spotlight.getCurrent();

		// If the spotlight is elsewhere, we don't want to hijack it (e.g. after the delay in
		// ExpandablePicker)
		if (!current || current.isDescendantOf(this)) {
			Spotlight.spot(this.$.header);
		}
		this.set('active', false);
	},

	/**
	* @private
	*/
	drawerSpotUp: function (sender, event) {
		if (this.autoCollapse && event.originator == this.$.drawer) {
			this.closeDrawerAndHighlightHeader();
			return true;
		}
	},

	/**
	* @private
	*/
	drawerSpotDown: function (sender, event) {
		if (this.lockBottom && event.originator == this.$.drawer && event._originator) {
			// Spotlight containers redispatch 5-way events with the original event originator
			// saved as _originator which we'll use to respot if lockBottom === true
			Spotlight.spot(event._originator);
			return true;
		}
	},

	/**
	* @private
	*/
	headerTapped: function (sender, event) {
		this.expandContract();
	},

	/**
	* When an expandable is in a group, we only want the opening control to scroll into view so that
	* event only fires when the drawer is open. Otherwise, we just request the scroller update its
	* bounds so that an expandable at the bottom of a scroller does not leave extra whitespace when
	* it closes.
	*
	* @fires module:moonstone/Scroller~Scroller#onRequestScrollIntoView
	* @fires module:moonstone/Scroller~Scroller#onRequestSetupBounds
	* @private
	*/
	drawerAnimationEnd: function () {
		if (this.$.drawer.open) {
			this.bubble('onRequestScrollIntoView', {scrollInPointerMode: true});
		} else {
			this.bubble('onRequestSetupBounds');
		}
		return true;
	}
});
<commit_msg>correct logic to show currentValue<commit_after>require('moonstone');

/**
* Contains the declaration for the {@link module:moonstone/ExpandableListItem~ExpandableListItem} kind.
* @module moonstone/ExpandableListItem
*/

var
	kind = require('enyo/kind'),
	Component = require('enyo/Component'),
	Control = require('enyo/Control'),
	Group = require('enyo/Group'),
	options = require('enyo/options');

var
	Spotlight = require('spotlight');

var
	Item = require('../Item'),
	Marquee = require('../Marquee'),
	MarqueeText = Marquee.Text;

var
	ExpandableListItemHeader = require('./ExpandableListItemHeader'),
	ExpandableListItemDrawer = require('./ExpandableListItemDrawer'),
	ExpandableListItemAccessibilitySupport = require('./ExpandableListItemAccessibilitySupport');

/**
* {@link module:moonstone/ExpandableListItem~ExpandableListItem}, which extends {@link module:moonstone/Item~Item}, displays a header
* while also allowing additional content to be stored in an {@link module:enyo/Drawer~Drawer}. When
* the header is selected, the drawer opens below. To close the drawer, tap on the
* header text or navigate (via 5-way) back to the top of the drawer.
*
* The control's child components may be of any kind; by default, they are
* instances of `moon.Item`.
*
* ```javascript
* var
* 	kind = require('enyo/kind'),
* 	ExpandableListItem = require('moonstone/ExpandableListItem');
*
* {kind: ExpandableListItem, content: 'A Countries', components: [
* 	{content: 'Algeria'},
* 	{content: 'Argentina'},
* 	{content: 'Australia'}
* ]},
* {kind: ExpandableListItem, content: 'B Countries', components: [
* 	{content: 'Belgium'},
* 	{content: 'Bolivia'},
* 	{content: 'Brazil'}
* ]}
* ```
*
* When multiple ExpandableListItems are used in a group, only one may be open at
* a given time.
*
* ```javascript
* var
* 	kind = require('enyo/kind'),
*	Group = require('enyo/Group'),
* 	ExpandableListItem = require('moonstone/ExpandableListItem');
*
* {kind: Group, highlander: true, components: [
* 	{kind: ExpandableListItem,  open: true,
* 		content: 'This is a grouped ExpandableListItem', components: [
* 			{content: 'Item One'},
* 			{content: 'Item Two'}
* 		]
* 	},
* 	{kind: ExpandableListItem,
* 		content: 'This is another grouped ExpandableListItem', components: [
* 			{content: 'Item Three'},
* 			{content: 'Item Four'}
* 		]
* 	},
* 	{kind: ExpandableListItem,
* 		content: 'This is yet another grouped ExpandableListItem', components: [
* 			{content: 'Item Five'},
* 			{content: 'Item Six'}
* 		]
* 	}
* ]}
* ```
*
* @class ExpandableListItem
* @extends module:enyo/Control~Control
* @ui
* @public
*/
module.exports = kind(
	/** @lends module:moonstone/ExpandableListItem~ExpandableListItem.prototype */ {

	/**
	* @private
	*/
	name: 'moon.ExpandableListItem',

	/**
	* @private
	*/
	kind: Control,

	/**
	* @private
	*/
	mixins: options.accessibility ? [ExpandableListItemAccessibilitySupport] : null,

	/**
	* @private
	* @lends module:moonstone/ExpandableListItem~ExpandableListItem.prototype
	*/
	published: {

		/**
		* If `true`, the drawer automatically closes when the user navigates to the top of the
		* control; if `false`, the user must select/tap the header to close the drawer.
		*
		* @type {Boolean}
		* @default false
		* @public
		*/
		autoCollapse: false,

		/**
		* If `true`, the drawer is expanded, showing this item's contents. Use this property
		* (rather than [active]{@link module:moonstone/ExpandableListItem~ExpandableListItem#active}) to set the item's
		* initial state.
		*
		* @type {Boolean}
		* @default false
		* @public
		*/
		open: false,

		/**
		* Boolean that reflects the value of the [open]{@link module:moonstone/ExpandableListItem~ExpandableListItem#open}
		* property; it is used to support the {@link module:enyo/Group~Group} API for grouping a set of
		* ExpandableListItems in which only one is expanded at a time. Note that the `open`
		* property (not the `active` property) controls the initial state of the picker.
		*
		* @type {Boolean}
		* @default false
		* @public
		*/
		active: false,

		/**
		* If `true`, the user is prevented from moving {@glossary Spotlight} past the bottom
		* of the drawer (when open) using 5-way controls.
		*
		* @type {Boolean}
		* @default false
		* @public
		*/
		lockBottom: false,

		/**
		* If `true`, item is shown as disabled and does not generate tap events.
		*
		* @type {Boolean}
		* @default false
		* @public
		*/
		disabled: false
	},

	/**
	* @private
	*/
	classes: 'moon-expandable-list-item',

	/**
	* @private
	*/
	spotlight: false,

	/**
	* @private
	*/
	defaultKind: Item,

	/**
	* @private
	*/
	drawerComponents: [
		{name: 'client', kind: Group, tag: null}
	],

	/**
	* @private
	*/
	components: [
		{name: 'header', kind: ExpandableListItemHeader, ontap: 'headerTapped'},
		{name: 'drawer', kind: ExpandableListItemDrawer, resizeContainer: false, classes: 'moon-expandable-list-item-client', defaultSpotlightUp: 'header', onSpotlightUp: 'drawerSpotUp', onSpotlightDown: 'drawerSpotDown', onDrawerAnimationEnd: 'drawerAnimationEnd'}
	],

	/**
	* @private
	*/
	bindings: [
		{from: 'active', to: 'open'},
		{from: 'allowHtml', to: '$.header.allowHtml'},
		{from: 'disabled', to: '$.header.disabled'},
		{from: 'content', to: '$.header.label'},
		{from: 'currentValueShowing', to: '$.header.textShowing'},
		{from: 'currentValueText', to: '$.header.text'}
	],

	/**
	* @private
	*/
	computed: {
		'currentValueShowing': ['open', 'currentValueText'],
		'currentValueText': ['value']
	},

	/**
	* @private
	*/
	create: function () {
		Control.prototype.create.apply(this, arguments);
		this.openChanged();
		this.disabledChanged();
		this.notifyObservers('value');
	},

	/**
	* @private
	*/
	initComponents: function () {
		var override = {drawer: {components: this.drawerComponents}};
		this.kindComponents = Component.overrideComponents(this.kindComponents, override);
		Control.prototype.initComponents.apply(this, arguments);
	},

	/**
	* Facade for drawer.
	*
	* @private
	*/
	openChanged: function () {
		var open = this.open;
		this.bubble('onActivate', {allowHighlanderDeactivate: true});
		this.addRemoveClass('open', open);
		this.$.drawer.set('open', open);
		this.$.drawer.spotlightDisabled = !open;
		this.set('active', open);
	},

	/**
	* @fires module:enyo/GroupItem~GroupItem#onActivate
	* @private
	*/
	activeChanged: function () {
		this.bubble('onActivate', {allowHighlanderDeactivate:true});
		this.set('open', this.active);
	},

	/**
	* @private
	*/
	disabledChanged: function () {
		var disabled = this.disabled;

		this.addRemoveClass('disabled', disabled);
		if (disabled) {
			this.set('active', false);
		}
	},

	/**
	* Returns `true` if the current value control should be displayed.
	*
	* Note: ExpandableListItem doesn't support currentValue but its subkinds do
	*
	* @private
	*/
	currentValueShowing: function () {
		var text = this.get('currentValueText');
		// If drawer is open or value is blank, don't bother to show the value.
		return (!this.open && (text || text === 0));
	},

	/**
	* Returns the text to be displayed within the current value control
	*
	* Note: ExpandableListItem doesn't support currentValue but its subkinds do
	*
	* @private
	*/
	currentValueText: function () {
		return '';
	},

	/**
	* If closed, opens drawer and highlights first spottable child.
	*
	* @private
	*/
	expandContract: function () {
		var spot;
		if (this.open) {
			this.closeDrawerAndHighlightHeader();
		} else {
			this.toggleActive();
			if (!Spotlight.getPointerMode() && !Spotlight.isFrozen()) {
				var first = Spotlight.getFirstChild(this.$.drawer);
				Spotlight.spot(first);
			}
		}
	},

	/**
	* @private
	*/
	toggleActive: function () {
		this.set('active', !this.open);
	},

	/**
	* @private
	*/
	closeDrawerAndHighlightHeader: function () {
		var mode = Spotlight.getPointerMode(),
			current = Spotlight.getCurrent();

		// If the spotlight is elsewhere, we don't want to hijack it (e.g. after the delay in
		// ExpandablePicker)
		if (!current || current.isDescendantOf(this)) {
			Spotlight.spot(this.$.header);
		}
		this.set('active', false);
	},

	/**
	* @private
	*/
	drawerSpotUp: function (sender, event) {
		if (this.autoCollapse && event.originator == this.$.drawer) {
			this.closeDrawerAndHighlightHeader();
			return true;
		}
	},

	/**
	* @private
	*/
	drawerSpotDown: function (sender, event) {
		if (this.lockBottom && event.originator == this.$.drawer && event._originator) {
			// Spotlight containers redispatch 5-way events with the original event originator
			// saved as _originator which we'll use to respot if lockBottom === true
			Spotlight.spot(event._originator);
			return true;
		}
	},

	/**
	* @private
	*/
	headerTapped: function (sender, event) {
		this.expandContract();
	},

	/**
	* When an expandable is in a group, we only want the opening control to scroll into view so that
	* event only fires when the drawer is open. Otherwise, we just request the scroller update its
	* bounds so that an expandable at the bottom of a scroller does not leave extra whitespace when
	* it closes.
	*
	* @fires module:moonstone/Scroller~Scroller#onRequestScrollIntoView
	* @fires module:moonstone/Scroller~Scroller#onRequestSetupBounds
	* @private
	*/
	drawerAnimationEnd: function () {
		if (this.$.drawer.open) {
			this.bubble('onRequestScrollIntoView', {scrollInPointerMode: true});
		} else {
			this.bubble('onRequestSetupBounds');
		}
		return true;
	}
});
<|endoftext|>


<commit_before>// These bundles are expected to be used together with existing non-browerified code.
// Define step here and add the "dest" value to a bundle defined in ./js_files.js
module.exports = {
  test_specs_for_browserify_modules: {
    src: [
      'lib/build/source-map-support.js',

      // Add specs for browserify module code here:
      'lib/assets/test/spec/cartodb/new_*/**/*.spec.js',
      'lib/assets/test/spec/cartodb/account/**/*.spec.js'
      'lib/assets/test/spec/cartodb/editor/**/*.spec.js'
    ],
    dest: '<%= browserify_modules.tests.dest %>'
  }
};
<commit_msg>Added necessary comma in browserify concat js file<commit_after>// These bundles are expected to be used together with existing non-browerified code.
// Define step here and add the "dest" value to a bundle defined in ./js_files.js
module.exports = {
  test_specs_for_browserify_modules: {
    src: [
      'lib/build/source-map-support.js',

      // Add specs for browserify module code here:
      'lib/assets/test/spec/cartodb/new_*/**/*.spec.js',
      'lib/assets/test/spec/cartodb/account/**/*.spec.js',
      'lib/assets/test/spec/cartodb/editor/**/*.spec.js'
    ],
    dest: '<%= browserify_modules.tests.dest %>'
  }
};
<|endoftext|>


<commit_before>var React = require('react');
var SingleSelect2 = require('./SingleSelect2.react');

var StatusPicker = React.createClass({
  getDefaultProps() {
    return {
      collection: [{name: 'Open'}, {name: 'Closed'}]
    }
  },
  getInitalState() {
    return{
      value: this.props.value || ['Open']
    }
  },
  render() {
    return(

        {this.props.editable ? this.renderSelect() : this.renderLabel()}

    );
  },
  renderSelect() {
    return(
      <SingleSelect2
        collection={this.props.collection}
        value={this.props.value}
        editable={this.props.editable}/>
    );
  },
  renderLabel() {
    return({this.props.value});
  }
});

module.exports = StatusPicker;
<commit_msg>View Header Status<commit_after>var React = require('react');
var SingleSelect2 = require('./SingleSelect2.react');

var StatusPicker = React.createClass({
  getDefaultProps() {
    return {
      collection: [{name: 'Open'}, {name: 'Closed'}]
    }
  },
  getInitalState() {
    return{
      value: this.props.value || ['Open']
    }
  },
  render() {
    return(

        {this.props.editable ? this.renderSelect() : this.renderLabel()}

    );
  },
  renderSelect() {
    return(
      <SingleSelect2
        collection={this.props.collection}
        value={this.props.data.status}
        editable={this.props.editable}/>
    );
  },
  renderLabel() {
    return({this.props.value});
  }
});

module.exports = StatusPicker;
<|endoftext|>


<commit_before>// AWS IoT Device app that continuously scans for and reports detected iBeacons

var version = "0.2.2";

//
// Parse command line arguments
//

var commandLineArgs = require('command-line-args');

var args = commandLineArgs([
  { name: 'verbose', alias: 'v', type: Boolean, defaultValue: false },
  { name: 'throttle', alias: 't', type: Boolean, defaultValue: true },
  { name: 'led', alias: 'l', type: Boolean, defaultValue: false },
])
function GetFormattedDate() {
    var todayTime = new Date();
    var month = todayTime .getMonth() + 1;
    var day = todayTime .getDate();
    var year = todayTime .getFullYear();
    var hours = todayTime .getHours();
    var minutes = todayTime .getMinutes();
    return month + "-" + day + "-" + year+"-"+hours+"_00";

}

function addLog(message) {
	var today = GetFormattedDate();
	var logFile = '/opt/aws-iot-ble-sensor-log/logs/'+sensor+'-log-'+today+'.log';
	var stream = fs.createWriteStream(logFile, {'flags': 'a'});
	stream.write(message+"\n");
	stream.end();
}
var options = args.parse()

const fs = require('fs');

//
// Status LED blinking
//

// which gpio pins correspond to the r, g & b leds
// rgb led recommended, eg: http://www.monkmakes.com/squid/
const led_r = 12;
const led_g = 16;
const led_b = 18;

// start with red
var led=led_r;

// to switch color, set this to the new one
var led_switch=0;

// set the blink frequency
var blink_on = 10;
var blink_off = 4990;
options.led = false;
if (options.led) {
  try {
     var gpio = require('rpi-gpio');
  } catch(err) {
     console.error("LED: Not found");
     options.led=false;
  }
}

if (options.led) {
  // setup gpio for the led
  gpio.setup(led_r, gpio.DIR_OUT);
  gpio.setup(led_g, gpio.DIR_OUT);
  gpio.setup(led_b, gpio.DIR_OUT);

  // start blinking LED
  led_on();

  function led_on() {
      setTimeout(function() {
          gpio.write(led, 1, led_off);
      }, blink_off);
  }

  function led_off() {
      setTimeout(function() {
        gpio.write(led, 0, led_on);
        if (led_switch !=0) {
            led=led_switch;
            led_switch=0;
        }
    }, blink_on);
  }
}

//
// AWS IoT connection
//

// use the hostname to identify this instance of the sensor
var os = require('os');
const sensor = os.hostname().split('.').shift();

// use this topic for heartbeats
const topicHeartbeat = 'heartbeat';

// use this topic for detections
const topicDetection = 'ble-wifi';

// connect to AWS IoT
var awsIot = require('aws-iot-device-sdk');

const aws = awsIot.device({
    keyPath: './certs/private.pem.key',
    certPath: './certs/certificate.pem.crt',
    caPath: './certs/root-CA.crt',
    region: 'eu-west-1',
    clientId: sensor,
    offlineQueueing: true,
    offlineQueueMaxSize: 0,
		//incomingStore: manager.incoming,
		//outgoingStore: manager.outgoing,
    drainTimeMs: 10
});

var HashMap = require('hashmap');
var log = new HashMap();
//update the log in file every 5 seconds
timeout = setInterval(function() {
	try {
		var today = GetFormattedDate();
		var logFile = '/opt/aws-iot-ble-sensor-log/logs/'+sensor+'-log-'+today+'.log';
		var stream = fs.createWriteStream(logFile, {'flags': 'a'});
    stream.on('error', function(err) {
      console.log(err);
    });
		log.forEach(function(message, discoverUuidmm) {
			stream.write(message+"\n");
			log.remove(discoverUuidmm);
		});
		stream.end();
	}catch (ex) {
		console.log(ex);
		console.log("Failed to write");
	}
}, 5000);

// publish a heartbeat every 60 seconds
timeout = setInterval(function() {

    // prepare JSON message
    var message = JSON.stringify({
        timestamp: new Date().toJSON(),
        type: 'pihb',
        version: version,
        uptime: os.uptime(),
        loadavg: os.loadavg(),
        sensor: sensor,
    })

    // publish to the heartbeat topic
    //aws.publish(topicHeartbeat, message, { qos: 1 });
    //write heartbeat message to log file
    var logFile = '/opt/aws-iot-ble-sensor-log/logs/heartbeat.log';
		var stream = fs.createWriteStream(logFile, {'flags': 'a'});
    stream.on('error', function(err) {
      console.log(err);
    });
		stream.write(message+"\n");
		stream.end();
		//console.log(aws.getOfflineOperations().length);
    if (options.verbose) {
      // also log to console
			//console.log(awsIot.offlineOperations);
			//console.log(aws.offlineOperations);
      console.log(message);
			//addLog(message)
    }
}, 60000);

// event handlers
aws
    .on('connect', function() {
        console.log('AWS IoT Device Gateway: Connected');
        if (options.led) {
          // switch led to blue
          led_switch=led_b;
        }
    });
aws
    .on('close', function() {
        console.log('AWS IoT Device Gateway: Closed');
        if (options.led) {
          // switch led to red
          led_switch=led_r;
        }
    });
aws
    .on('reconnect', function() {
        console.log('AWS IoT Device Gateway: Reconnected');
        if (options.led) {
          // switch led to blue
          led_switch=led_b;
        }
    });
aws
    .on('offline', function() {
        console.log('AWS IoT Device Gateway: Offline');
        if (options.led) {
          // switch led to red
          led_switch=led_r;
        }
    });
aws
    .on('error', function(error) {
        console.log('AWS IoT Device Gateway: Error -', error);
        if (options.led) {
          // switch led to red
          led_switch=led_r;
        }
    });
aws
    .on('message', function(topic, payload) {
       console.log(payload.toString());
    });

//
// iBeacon scanning
//

var ble = require('bleacon');
ble.startScanning();

if (options.throttle) {
	 var map = new HashMap();
}

// event handler
ble
    .on('discover', function(beacon) {

        discoverTimestamp = new Date();
        var discoverUuidmm = beacon.uuid.toUpperCase() + ':' + beacon.major + '/' + beacon.minor

        if ((options.throttle) && ((discoverTimestamp - map.get(discoverUuidmm)) < 10000)) {
          // ignore detections reported less than 10 seconds ago

          if (options.verbose) {
            // also log to console
            console.log('Ignoring ' + discoverUuidmm + ' last detected ' + (discoverTimestamp - map.get(discoverUuidmm)) + 'ms ago');
          }
        } else {
          // prepare JSON message
          var message = JSON.stringify({
              timestamp: discoverTimestamp.toJSON().replace("T", " "),
              type: 'pi',
              probetime:discoverTimestamp.toJSON().replace("T", " "),
              probetime_gmt:discoverTimestamp.toJSON().replace("T", " "),
              uuidmm: discoverUuidmm,
              measuredpower: beacon.measuredPower,
              rssi: beacon.rssi,
              accuracy: beacon.accuracy,
              proximity: beacon.proximity,
              sensor: sensor
          })
          // publish to the detection topic
          aws.publish(topicDetection, message, { qos: 1 });
					//addLog(message);
          if (options.throttle) {
            // update the timestamp of last publish for that uuidmm
            map.set(discoverUuidmm, discoverTimestamp);
            log.set(discoverUuidmm, message);
          };
          if (options.verbose) {
            // also log to console
            console.log(message);
          }
        }
    });
<commit_msg>modifying detection limit to 1 second<commit_after>// AWS IoT Device app that continuously scans for and reports detected iBeacons

var version = "0.2.2";

//
// Parse command line arguments
//

var commandLineArgs = require('command-line-args');

var args = commandLineArgs([
  { name: 'verbose', alias: 'v', type: Boolean, defaultValue: false },
  { name: 'throttle', alias: 't', type: Boolean, defaultValue: true },
  { name: 'led', alias: 'l', type: Boolean, defaultValue: false },
])
function GetFormattedDate() {
    var todayTime = new Date();
    var month = todayTime .getMonth() + 1;
    var day = todayTime .getDate();
    var year = todayTime .getFullYear();
    var hours = todayTime .getHours();
    var minutes = todayTime .getMinutes();
    return month + "-" + day + "-" + year+"-"+hours+"_00";

}

function addLog(message) {
	var today = GetFormattedDate();
	var logFile = '/opt/aws-iot-ble-sensor-log/logs/'+sensor+'-log-'+today+'.log';
	var stream = fs.createWriteStream(logFile, {'flags': 'a'});
	stream.write(message+"\n");
	stream.end();
}
var options = args.parse()

const fs = require('fs');

//
// Status LED blinking
//

// which gpio pins correspond to the r, g & b leds
// rgb led recommended, eg: http://www.monkmakes.com/squid/
const led_r = 12;
const led_g = 16;
const led_b = 18;

// start with red
var led=led_r;

// to switch color, set this to the new one
var led_switch=0;

// set the blink frequency
var blink_on = 10;
var blink_off = 4990;
options.led = false;
if (options.led) {
  try {
     var gpio = require('rpi-gpio');
  } catch(err) {
     console.error("LED: Not found");
     options.led=false;
  }
}

if (options.led) {
  // setup gpio for the led
  gpio.setup(led_r, gpio.DIR_OUT);
  gpio.setup(led_g, gpio.DIR_OUT);
  gpio.setup(led_b, gpio.DIR_OUT);

  // start blinking LED
  led_on();

  function led_on() {
      setTimeout(function() {
          gpio.write(led, 1, led_off);
      }, blink_off);
  }

  function led_off() {
      setTimeout(function() {
        gpio.write(led, 0, led_on);
        if (led_switch !=0) {
            led=led_switch;
            led_switch=0;
        }
    }, blink_on);
  }
}

//
// AWS IoT connection
//

// use the hostname to identify this instance of the sensor
var os = require('os');
const sensor = os.hostname().split('.').shift();

// use this topic for heartbeats
const topicHeartbeat = 'heartbeat';

// use this topic for detections
const topicDetection = 'ble-wifi';

// connect to AWS IoT
var awsIot = require('aws-iot-device-sdk');

const aws = awsIot.device({
    keyPath: './certs/private.pem.key',
    certPath: './certs/certificate.pem.crt',
    caPath: './certs/root-CA.crt',
    region: 'eu-west-1',
    clientId: sensor,
    offlineQueueing: true,
    offlineQueueMaxSize: 0,
		//incomingStore: manager.incoming,
		//outgoingStore: manager.outgoing,
    drainTimeMs: 10
});

var HashMap = require('hashmap');
var log = new HashMap();
//update the log in file every 5 seconds
timeout = setInterval(function() {
	try {
		var today = GetFormattedDate();
		var logFile = '/opt/aws-iot-ble-sensor-log/logs/'+sensor+'-log-'+today+'.log';
		var stream = fs.createWriteStream(logFile, {'flags': 'a'});
    stream.on('error', function(err) {
      console.log(err);
    });
		log.forEach(function(message, discoverUuidmm) {
			stream.write(message+"\n");
			log.remove(discoverUuidmm);
		});
		stream.end();
	}catch (ex) {
		console.log(ex);
		console.log("Failed to write");
	}
}, 5000);

// publish a heartbeat every 60 seconds
timeout = setInterval(function() {

    // prepare JSON message
    var message = JSON.stringify({
        timestamp: new Date().toJSON(),
        type: 'pihb',
        version: version,
        uptime: os.uptime(),
        loadavg: os.loadavg(),
        sensor: sensor,
    })

    // publish to the heartbeat topic
    //aws.publish(topicHeartbeat, message, { qos: 1 });
    //write heartbeat message to log file
    var logFile = '/opt/aws-iot-ble-sensor-log/logs/heartbeat.log';
		var stream = fs.createWriteStream(logFile, {'flags': 'a'});
    stream.on('error', function(err) {
      console.log(err);
    });
		stream.write(message+"\n");
		stream.end();
		//console.log(aws.getOfflineOperations().length);
    if (options.verbose) {
      // also log to console
			//console.log(awsIot.offlineOperations);
			//console.log(aws.offlineOperations);
      console.log(message);
			//addLog(message)
    }
}, 60000);

// event handlers
aws
    .on('connect', function() {
        console.log('AWS IoT Device Gateway: Connected');
        if (options.led) {
          // switch led to blue
          led_switch=led_b;
        }
    });
aws
    .on('close', function() {
        console.log('AWS IoT Device Gateway: Closed');
        if (options.led) {
          // switch led to red
          led_switch=led_r;
        }
    });
aws
    .on('reconnect', function() {
        console.log('AWS IoT Device Gateway: Reconnected');
        if (options.led) {
          // switch led to blue
          led_switch=led_b;
        }
    });
aws
    .on('offline', function() {
        console.log('AWS IoT Device Gateway: Offline');
        if (options.led) {
          // switch led to red
          led_switch=led_r;
        }
    });
aws
    .on('error', function(error) {
        console.log('AWS IoT Device Gateway: Error -', error);
        if (options.led) {
          // switch led to red
          led_switch=led_r;
        }
    });
aws
    .on('message', function(topic, payload) {
       console.log(payload.toString());
    });

//
// iBeacon scanning
//

var ble = require('bleacon');
ble.startScanning();

if (options.throttle) {
	 var map = new HashMap();
}

// event handler
ble
    .on('discover', function(beacon) {

        discoverTimestamp = new Date();
        var discoverUuidmm = beacon.uuid.toUpperCase() + ':' + beacon.major + '/' + beacon.minor

        if ((options.throttle) && ((discoverTimestamp - map.get(discoverUuidmm)) < 1000)) {
          // ignore detections reported less than 01 seconds ago

          if (options.verbose) {
            // also log to console
            console.log('Ignoring ' + discoverUuidmm + ' last detected ' + (discoverTimestamp - map.get(discoverUuidmm)) + 'ms ago');
          }
        } else {
          // prepare JSON message
          var message = JSON.stringify({
              timestamp: discoverTimestamp.toJSON().replace("T", " "),
              type: 'pi',
              probetime:discoverTimestamp.toJSON().replace("T", " "),
              probetime_gmt:discoverTimestamp.toJSON().replace("T", " "),
              uuidmm: discoverUuidmm,
              measuredpower: beacon.measuredPower,
              rssi: beacon.rssi,
              accuracy: beacon.accuracy,
              proximity: beacon.proximity,
              sensor: sensor
          })
          // publish to the detection topic
          aws.publish(topicDetection, message, { qos: 1 });
					//addLog(message);
          if (options.throttle) {
            // update the timestamp of last publish for that uuidmm
            map.set(discoverUuidmm, discoverTimestamp);
            log.set(discoverUuidmm, message);
          };
          if (options.verbose) {
            // also log to console
            console.log(message);
          }
        }
    });
<|endoftext|>


<commit_before>'use strict';
/**
 * Create A light observable with a set of options
 */

var _          = require('lodash'),
    rxUtil     = require('../util.rx'),
    noise      = require('../util.noise'),
    ColorLight = require('../light.color'),
    colorUtil  = require('../util.color');

module.exports = colorLightObservable;

colorLightObservable.defaults = {
    fps        : 60.0,
    length     : 10.0,
    waveLength : 1.0,

    transform : {
        scale  : 1,
        offset : 0
    },

    envelope : {
        attack  : 4.0,
        release : 6.0
    },

    light : {
        color    : 0xFF0000,
        hue      : {
            base      : 0.5,
            variation : 0.2,
            speed     : 0.5
        },
        position : {
            base      : 0.5,
            variation : 0,
            speed     : .012
        }
    }
};

function colorLightObservable (options) {
    let o = _.merge({}, colorLightObservable.defaults, options);

    return rxUtil.wave.sine(o)
        .map(rxUtil.transform.wave.transform(o.transform || {}))
        .map(rxUtil.transform.wave.envelope(o.envelope || {}))
        .map(waveToColorLight(o.light || {}))
}

/**
 * convert a wave to a color light
 * @param options
 * @returns {Function}
 */
function waveToColorLight (options) {
    var o = options || {};
    return function (wave) {
        var posNoise = noise.perlin2(0, wave.x * o.position.speed) * o.position.variation,
            hueNoise = noise.perlin2(0, (60 + wave.x) * o.hue.speed) * o.hue.variation,
            hsv      = {h : (((o.hue.base + hueNoise + 2) % 1) * 360), s : 70, v : 50},
            c        = colorUtil.hsvToInt(hsv);

        var settings = {
            color     : c,
            intensity : wave.y,
            position  : (o.position.base || 0.5) + posNoise
        };

        return new ColorLight(settings);
    }
}<commit_msg>comments<commit_after>'use strict';
/**
 * Create A light observable with a set of options
 */

var _          = require('lodash'),
    rxUtil     = require('../util.rx'),
    noise      = require('../util.noise'),
    ColorLight = require('../light.color'),
    colorUtil  = require('../util.color');

module.exports = colorLightObservable;

colorLightObservable.defaults = {
    fps        : 60.0,
    length     : 10.0,
    waveLength : 1.0,

    transform : {
        scale  : 1,
        offset : 0
    },

    // TODO: make sure that when no envelope is selected, the light will stay on forever
    envelope : {
        attack  : 4.0,
        release : 6.0
    },

    light : {
        color    : 0xFF0000,
        hue      : {
            base      : 0.5,
            variation : 0.2,
            speed     : 0.5
        },
        position : {
            base      : 0.5,
            variation : 0,
            speed     : .012
        }
    }
};

function colorLightObservable (options) {
    let o = _.merge({}, colorLightObservable.defaults, options);

    return rxUtil.wave.sine(o)
        .map(rxUtil.transform.wave.transform(o.transform || {}))
        // TODO: conditionally apply
        .map(rxUtil.transform.wave.envelope(o.envelope || {}))
        .map(waveToColorLight(o.light || {}))
}

/**
 * convert a wave to a color light
 * @param options
 * @returns {Function}
 */
function waveToColorLight (options) {
    var o = options || {};
    return function (wave) {
        var posNoise = noise.perlin2(0, wave.x * o.position.speed) * o.position.variation,
            hueNoise = noise.perlin2(0, (60 + wave.x) * o.hue.speed) * o.hue.variation,
            hsv      = {h : (((o.hue.base + hueNoise + 2) % 1) * 360), s : 70, v : 50},
            c        = colorUtil.hsvToInt(hsv);

        var settings = {
            color     : c,
            intensity : wave.y,
            position  : (o.position.base || 0.5) + posNoise
        };

        return new ColorLight(settings);
    }
}<|endoftext|>


<commit_before>'use strict';

const Promise = require('promise');
const facebookAnalyticsClient = require('../../clients/facebook/FacebookAnalyticsClient');
const cassandraConnector = require('../../clients/cassandra/CassandraConnector');
const withRunTime = require('../shared').withRunTime;

function cassandraRowToSite(row) {
  // Please note that the following properties in the SiteProperties are NOT in Cassandra's sitessetings:
  // storageConnectionString, featuresConnectionString, mapzenApiKey, fbToken.
  return {
    name: row.sitename,
    properties: {
      targetBbox: row.geofence,
      defaultZoomLevel: row.defaultzoom,
      logo: row.logo,
      title: row.title,
      defaultLocation: row.geofence,
      supportedLanguages: row.languages
    }
  };
}

/**
 * @param {{siteId: string}} args
 * @returns {Promise.<{runTime: string, sites: Array<{name: string, properties: {targetBbox: number[], defaultZoomLevel: number, logo: string, title: string, defaultLocation: number[], storageConnectionString: string, featuresConnectionString: string, mapzenApiKey: string, fbToken: string, supportedLanguages: string[]}}>}>}
 */
function sites(args, res) { // eslint-disable-line no-unused-vars
  return new Promise((resolve, reject) => {
    const siteId = args.siteId;
    if (!siteId) {
      return reject('No site id to fetch specified');
    }

    const siteById = 'SELECT * FROM fortis.sitesettings WHERE id = ?';
    cassandraConnector.executeQuery(siteById, [siteId])
    .catch(reject)
    .then(rows => {
      if (rows.length < 1) return reject(`Could not find site with id ${siteId}`);
      if (rows.length > 1) return reject(`Got more than one site (got ${rows.length}) with id '${siteId}'`);

      const site = cassandraRowToSite(rows[0]);
      resolve({sites:[site]});
    })
    .catch(reject)
    ;
  });
}

/**
 * @param {{siteId: string}} args
 * @returns {Promise.<{runTime: string, accounts: Array<{accountName: string, consumerKey: string, consumerSecret: string, token: string, tokenSecret: string}>}>}
 */
function twitterAccounts(args, res) { // eslint-disable-line no-unused-vars
}

/**
 * @param {{siteId: string}} args
 * @returns {Promise.<{runTime: string, accounts: Array<{RowKey: string, acctUrl: string}>}>}
 */
function trustedTwitterAccounts(args, res) { // eslint-disable-line no-unused-vars
}

/**
 * @param {{siteId: string}} args
 * @returns {Promise.<{runTime: string, pages: Array<{RowKey: string, pageUrl: string}>}>}
 */
function facebookPages(args, res) { // eslint-disable-line no-unused-vars
}

/**
 * @param {{siteId: string, days: number}} args
 * @returns {Promise.<{analytics: Array<{Name: string, Count: number, LastUpdated: string}>}>}
 */
function facebookAnalytics(args, res) { // eslint-disable-line no-unused-vars
  return new Promise((resolve, reject) => {
    const pageIds = ['aljazeera', 'microsoftvan']; // todo: fetch pages for args.siteId from sitesettings

    Promise.all(pageIds.map(pageId => ({Name: pageId, LastUpdated: facebookAnalyticsClient.fetchPageLastUpdatedAt(pageId), Count: -1})))
    .then(analytics => resolve({analytics}))
    .catch(err => reject(err));
  });
}

/**
 * @param {{siteId: string}} args
 * @returns {Promise.<{runTime: string, filters: Array<{filteredTerms: string[], lang: string, RowKey: string}>}>}
 */
function termBlacklist(args, res) { // eslint-disable-line no-unused-vars
}

module.exports = {
  sites: withRunTime(sites),
  twitterAccounts: withRunTime(twitterAccounts),
  trustedTwitterAccounts: withRunTime(trustedTwitterAccounts),
  facebookPages: withRunTime(facebookPages),
  facebookAnalytics: facebookAnalytics,
  termBlacklist: withRunTime(termBlacklist)
};
<commit_msg>Implemented Settings.trustedTwitterAccounts.<commit_after>'use strict';

const Promise = require('promise');
const facebookAnalyticsClient = require('../../clients/facebook/FacebookAnalyticsClient');
const cassandraConnector = require('../../clients/cassandra/CassandraConnector');
const withRunTime = require('../shared').withRunTime;

function cassandraRowToSite(row) {
  // Please note that the following properties in the SiteProperties are NOT in Cassandra's sitessetings:
  // storageConnectionString, featuresConnectionString, mapzenApiKey, fbToken.
  return {
    name: row.sitename,
    properties: {
      targetBbox: row.geofence,
      defaultZoomLevel: row.defaultzoom,
      logo: row.logo,
      title: row.title,
      defaultLocation: row.geofence,
      supportedLanguages: row.languages
    }
  };
}

/**
 * @param {{siteId: string}} args
 * @returns {Promise.<{runTime: string, sites: Array<{name: string, properties: {targetBbox: number[], defaultZoomLevel: number, logo: string, title: string, defaultLocation: number[], storageConnectionString: string, featuresConnectionString: string, mapzenApiKey: string, fbToken: string, supportedLanguages: string[]}}>}>}
 */
function sites(args, res) { // eslint-disable-line no-unused-vars
  return new Promise((resolve, reject) => {
    const siteId = args.siteId;
    if (!siteId) {
      return reject('No site id to fetch specified');
    }

    const siteById = 'SELECT * FROM fortis.sitesettings WHERE id = ?';
    cassandraConnector.executeQuery(siteById, [siteId])
    .catch(reject)
    .then(rows => {
      if (rows.length < 1) return reject(`Could not find site with id ${siteId}`);
      if (rows.length > 1) return reject(`Got more than one site (got ${rows.length}) with id '${siteId}'`);

      const site = cassandraRowToSite(rows[0]);
      resolve({sites:[site]});
    })
    .catch(reject)
    ;
  });
}

/**
 * @param {{siteId: string}} args
 * @returns {Promise.<{runTime: string, accounts: Array<{accountName: string, consumerKey: string, consumerSecret: string, token: string, tokenSecret: string}>}>}
 */
function twitterAccounts(args, res) { // eslint-disable-line no-unused-vars
}

function cassandraRowToTrustedTwitterAccount(row) {
  return {
    RowKey: `${row.connector},${row.sourceid},${row.sourcetype}`,
    acctUrl: row.sourceid
  };
}

/**
 * @param {{siteId: string}} args
 * @returns {Promise.<{runTime: string, accounts: Array<{RowKey: string, acctUrl: string}>}>}
 */
function trustedTwitterAccounts(args, res) { // eslint-disable-line no-unused-vars
  return new Promise((resolve, reject) => {
    const sourcesByConnector = 'SELECT * FROM fortis.trustedsources WHERE connector = ?';
    cassandraConnector.executeQuery(sourcesByConnector, ['twitter'])
    .catch(reject)
    .then(rows => {
      const accounts = rows.map(cassandraRowToTrustedTwitterAccount);
      resolve({accounts:accounts});
    })
    .catch(reject)
    ;
  });
}

/**
 * @param {{siteId: string}} args
 * @returns {Promise.<{runTime: string, pages: Array<{RowKey: string, pageUrl: string}>}>}
 */
function facebookPages(args, res) { // eslint-disable-line no-unused-vars
}

/**
 * @param {{siteId: string, days: number}} args
 * @returns {Promise.<{analytics: Array<{Name: string, Count: number, LastUpdated: string}>}>}
 */
function facebookAnalytics(args, res) { // eslint-disable-line no-unused-vars
  return new Promise((resolve, reject) => {
    const pageIds = ['aljazeera', 'microsoftvan']; // todo: fetch pages for args.siteId from sitesettings

    Promise.all(pageIds.map(pageId => ({Name: pageId, LastUpdated: facebookAnalyticsClient.fetchPageLastUpdatedAt(pageId), Count: -1})))
    .then(analytics => resolve({analytics}))
    .catch(err => reject(err));
  });
}

/**
 * @param {{siteId: string}} args
 * @returns {Promise.<{runTime: string, filters: Array<{filteredTerms: string[], lang: string, RowKey: string}>}>}
 */
function termBlacklist(args, res) { // eslint-disable-line no-unused-vars
}

module.exports = {
  sites: withRunTime(sites),
  twitterAccounts: withRunTime(twitterAccounts),
  trustedTwitterAccounts: withRunTime(trustedTwitterAccounts),
  facebookPages: withRunTime(facebookPages),
  facebookAnalytics: facebookAnalytics,
  termBlacklist: withRunTime(termBlacklist)
};
<|endoftext|>


<commit_before>const expect = require('chai').expect;
const path = require('path');
const fs = require('fs-extra-promise');
const tmp = require('tmp-promise');

const h = require('../test-helpers.js');
const unpm = require('../../lib/unity-npm-utils');

/**
 * Core setup and expected behaviours for updating the package template.
 *
 * This operation can be performed multiple ways, e.g. from cli or from a module call,
 * so better to have the expected behaviour defined in a sharable test function.
 *
 * @param {updateTemplate} updateTemplate
 *      callback to execute the update-template op however the tester defines it.
 *
 * @param {Boolean} options.install_required
 *      If true, will install the template package as part of beforeEach
 *
 */
const updateTemplateBehaviour = (updateTemplate, options) => {
    const pkgName = "my-pkg-foo";
    var pkgPath = null;
    var pkgDistNameSet = null;
    var distDepNames = null;
    var distScriptNames = null;
    var distFiles = null;

    var tmpPath = null;
    var pkgPath = null;

    options = options || {};

    const srcFiles = [{
            name: 'Foo.cs',
            content: 'public class Foo {}'
        },
        {
            name: 'Bar.cs',
            content: 'public class Bar {} '
        }
    ];

    beforeEach(async function() {
        this.timeout(300000);

        const test = this;

        const d = await tmp.dir()

        tmpPath = d.path;
        pkgPath = path.join(tmpPath, 'package-install');

        await fs.ensureDirAsync(pkgPath)

        await h.runBinCmd(`unpm init-package --package-name ${pkgName} -p ${pkgPath}`)

        test.test_config = {
            package_path: pkgPath
        };

        await unpm.unityPackage.addSrcFiles(pkgPath, srcFiles)

        if(!options.install_required) {
            return done();
        }

        await h.runPkgCmd('npm install', pkgPath)
    });

    require('./package-template-behaviour.js')({
        ...options,
        update_template_function: updateTemplate,
        package_src_files: srcFiles
    });

}

module.exports = updateTemplateBehaviour;
<commit_msg>fixed bad async code in sharted unpm-init-package-then-update-template-behaviour.js<commit_after>const expect = require('chai').expect;
const path = require('path');
const fs = require('fs-extra-promise');
const tmp = require('tmp-promise');

const h = require('../test-helpers.js');
const unpm = require('../../lib/unity-npm-utils');

/**
 * Core setup and expected behaviours for updating the package template.
 *
 * This operation can be performed multiple ways, e.g. from cli or from a module call,
 * so better to have the expected behaviour defined in a sharable test function.
 *
 * @param {updateTemplate} updateTemplate
 *      callback to execute the update-template op however the tester defines it.
 *
 * @param {Boolean} options.install_required
 *      If true, will install the template package as part of beforeEach
 *
 */
const updateTemplateBehaviour = (updateTemplate, options) => {
    const pkgName = "my-pkg-foo";
    var pkgPath = null;
    var pkgDistNameSet = null;
    var distDepNames = null;
    var distScriptNames = null;
    var distFiles = null;

    var tmpPath = null;
    var pkgPath = null;

    options = options || {};

    const srcFiles = [{
            name: 'Foo.cs',
            content: 'public class Foo {}'
        },
        {
            name: 'Bar.cs',
            content: 'public class Bar {} '
        }
    ];

    beforeEach(async function() {
        this.timeout(300000);

        const test = this;

        const d = await tmp.dir()

        tmpPath = d.path;
        pkgPath = path.join(tmpPath, 'package-install');

        await fs.ensureDirAsync(pkgPath)

        await h.runBinCmd(`unpm init-package --package-name ${pkgName} -p ${pkgPath}`)

        test.test_config = {
            package_path: pkgPath
        };

        await unpm.unityPackage.addSrcFiles(pkgPath, srcFiles)

        if(!options.install_required) {
            return;
        }

        await h.runPkgCmd('npm install', pkgPath)
    });

    require('./package-template-behaviour.js')({
        ...options,
        update_template_function: updateTemplate,
        package_src_files: srcFiles
    });

}

module.exports = updateTemplateBehaviour;
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */
var flaverr = require('flaverr');
var _ = require('@sailshq/lodash');

/**
 * ensureRedisConnection()
 *
 * Ensure that a connection has been made to the Redis server specified in the session
 * config, or else return an error that will cause the hook (and Sails lift) to fail.
 *
 * @param  {sailsApp}   app The current Sails app
 * @param  {Function} cb  Callback to call when the connection is established, or determined to have failed.
 */

module.exports = function ensureRedisConnection(app, cb) {

  // Future-proof by ensuring that there is a client object, and that it is an event emitter.
  // If not, we'll continue, but warn that we can't be sure that the session is really there.
  if (!app.config.session.store.client || !(app.config.session.store.client instanceof require('events').EventEmitter)) {

    app.log.debug('The version of connect-redis used does not have a `client` property that is an event emitter.');
    app.log.debug('It is therefore not possible to determine whether Redis is actually running.');
    app.log.debug('Continuing on, but be aware that the session store might not be online!\n');

    return cb();

  }

  // If the client is already connected (because it was provided in the config)
  // then just continue.
  if (app.config.session.store.client.connected) {return cb();}

  // Get a reference to the session store client, for use with the event handlers below.
  var client = app.config.session.store.client;

  // Adapted from machinepack-redis/get-connection
  // https://github.com/treelinehq/machinepack-redis/blob/f4dc7087df27694d5c723784e99a116213d4910e/machines/get-connection.js#L98
  ////////////////////////////////////////////////////////////////////////
  //
  // These two functions (`onPreConnectionError`, `onPreConnectionEnd`)
  // have to be defined ahead of time (otherwise, they are not in scope
  // from within each other's implementations; and so cannot be used as
  // the second argument to `removeListener()`)
  var redisConnectionError;
  function onPreConnectionError (err){
    redisConnectionError = err;
  }
  function onPreConnectionEnd(){
    client.removeListener('end', onPreConnectionEnd);
    client.removeListener('error', onPreConnectionError);

    // Prevent automatic reconnection attempts.
    client.end(true);

    var redisError = redisConnectionError || new Error('Redis client fired "end" event before it finished connecting.');
    return cb(flaverr('E_REDIS_CONNECTION_FAILED', new Error('Sails could not connect to the specified Redis session server.\n' + redisError.stack)));
  }

  ////////////////////////////////////////////////////////////////////////

  // Bind an "error" listener so that we can track errors that occur
  // during the connection process.
  client.on('error', onPreConnectionError);

  // Bind an "end" listener in case the client "ends" before
  // it successfully connects...
  client.on('end', onPreConnectionEnd);

  // Bind a "ready" listener so that we know when the client has connected.
  client.once('ready', function onConnectionReady(){
    client.removeListener('end', onPreConnectionEnd);
    client.removeListener('error', onPreConnectionError);
    client.on('end', function(){
      if (_.isFunction(app.config.session.onDisconnect)) {
        app.config.session.onDisconnect();
      }
      app.log.error('Redis session server went off-line...');
    });
    client.on('error', function(err){app.log.verbose('Redis session server reported error: ', err.stack);});
    client.on('ready', function(err){
      if (_.isFunction(app.config.session.onReconnect)) {
        app.config.session.onReconnect();
      }
      app.log.error('Redis session server came back on-line...');
    });
    return cb();
  });

};
<commit_msg>Disconnect Redis session client when Sails is lowering.<commit_after>/**
 * Module dependencies.
 */
var flaverr = require('flaverr');
var _ = require('@sailshq/lodash');

/**
 * ensureRedisConnection()
 *
 * Ensure that a connection has been made to the Redis server specified in the session
 * config, or else return an error that will cause the hook (and Sails lift) to fail.
 *
 * @param  {sailsApp}   app The current Sails app
 * @param  {Function} cb  Callback to call when the connection is established, or determined to have failed.
 */

module.exports = function ensureRedisConnection(app, cb) {

  // Future-proof by ensuring that there is a client object, and that it is an event emitter.
  // If not, we'll continue, but warn that we can't be sure that the session is really there.
  if (!app.config.session.store.client || !(app.config.session.store.client instanceof require('events').EventEmitter)) {

    app.log.debug('The version of connect-redis used does not have a `client` property that is an event emitter.');
    app.log.debug('It is therefore not possible to determine whether Redis is actually running.');
    app.log.debug('Continuing on, but be aware that the session store might not be online!\n');

    return cb();

  }

  // If the client is already connected (because it was provided in the config)
  // then just continue.
  if (app.config.session.store.client.connected) {return cb();}

  // Get a reference to the session store client, for use with the event handlers below.
  var client = app.config.session.store.client;

  // Adapted from machinepack-redis/get-connection
  // https://github.com/treelinehq/machinepack-redis/blob/f4dc7087df27694d5c723784e99a116213d4910e/machines/get-connection.js#L98
  ////////////////////////////////////////////////////////////////////////
  //
  // These two functions (`onPreConnectionError`, `onPreConnectionEnd`)
  // have to be defined ahead of time (otherwise, they are not in scope
  // from within each other's implementations; and so cannot be used as
  // the second argument to `removeListener()`)
  var redisConnectionError;
  function onPreConnectionError (err){
    redisConnectionError = err;
  }
  function onPreConnectionEnd(){
    client.removeListener('end', onPreConnectionEnd);
    client.removeListener('error', onPreConnectionError);

    // Prevent automatic reconnection attempts.
    client.end(true);

    var redisError = redisConnectionError || new Error('Redis client fired "end" event before it finished connecting.');
    return cb(flaverr('E_REDIS_CONNECTION_FAILED', new Error('Sails could not connect to the specified Redis session server.\n' + redisError.stack)));
  }

  ////////////////////////////////////////////////////////////////////////

  // Bind an "error" listener so that we can track errors that occur
  // during the connection process.
  client.on('error', onPreConnectionError);

  // Bind an "end" listener in case the client "ends" before
  // it successfully connects...
  client.on('end', onPreConnectionEnd);

  // Bind a "ready" listener so that we know when the client has connected.
  client.once('ready', function onConnectionReady(){
    // Remove the pre-connection handlers.
    client.removeListener('end', onPreConnectionEnd);
    client.removeListener('error', onPreConnectionError);
    // Add a new "end" handler.
    client.on('end', function(){
      if (_.isFunction(app.config.session.onDisconnect)) {
        app.config.session.onDisconnect();
      }
      app.log.error('Redis session server went off-line...');
    });
    // Add a new "error" handler.
    client.on('error', function(err){app.log.verbose('Redis session server reported error: ', err.stack);});
    // Add a new "ready" handler that will be triggered on a reconnect.
    client.on('ready', function(err){
      if (_.isFunction(app.config.session.onReconnect)) {
        app.config.session.onReconnect();
      }
      app.log.error('Redis session server came back on-line...');
    });

    // When Sails is lowering, disconnect the Redis client so that the process doesn't hang.
    app.on('lower', function() {
      client.end(true);
    });

    return cb();
  });

};
<|endoftext|>


<commit_before>//
// BetterClientSimulationBotFromRecording.js
//  examples
//
//  Created by Sam Gateau building on many others (November 2018).
//  Copyright 2017 High Fidelity, Inc.
//
//  Distributed under the Apache License, Version 2.0.
//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//

randFloat = function(low, high) {
    return low + Math.random() * (high - low);
}

var RECORDINGS_ARRAY = [
  "eventer1.hfr",
  // "cop1.hfr", // Bad Model
  // "cop2.hfr", // Bad Model
  "waiting1.hfr",
  "waiting2.hfr",
  // "waiting3.hfr", // Bad Model
  "waiting4.hfr",
  // "waiting5.hfr", // Moves downward
  "waiting6.hfr",
  // "waiting7.hfr", // Bad Model
  "waiting8.hfr",
  "waiting9.hfr",
  "waiting10.hfr",
  "bot1.hfr",
  "bot2.hfr",
  "bot3.hfr",
  "bot4.hfr",
  "check_12.hfr",
  "peanuts.hfr",
  "claude.hfr",
  "usher1.hfr",
  "usher2.hfr",
  "usher3.hfr",
  "jim.hfr"
];

var RECORDING_URL = "http://hifi-content.s3.amazonaws.com/DomainContent/Event%20/NPC%27s/" + RECORDINGS_ARRAY[Math.floor(Math.random() * RECORDINGS_ARRAY.length)];
print("RANDOM RECORDING SELECTED:" + RECORDING_URL);

var LOCATIONS_ARRAY = [{ min_x: 20, max_x: 21, y: 0.5, min_z: 20, max_z: 21}];

var LOCATION_PARAMS = LOCATIONS_ARRAY[Math.floor(Math.random() * LOCATIONS_ARRAY.length)];

var LOCATION = { x: randFloat(LOCATION_PARAMS.min_x, LOCATION_PARAMS.max_x) - 72.0, y: LOCATION_PARAMS.y - 22.0, z: randFloat(LOCATION_PARAMS.min_z, LOCATION_PARAMS.max_z) + 74.0 };

var LOCATION_ORIGIN = {x:-80.0, y:-22.0, z:83.0};
var LOCATION_POLAR = { min_yaw: 90, max_yaw: 180, min_radius: 5.0, max_radius: 10.0 }

function genLocation() {
    var seed = Math.random();
    var yaw = LOCATION_POLAR.min_yaw + seed * (LOCATION_POLAR.max_yaw - LOCATION_POLAR.min_yaw);
    var radiusShape = (1.0 - Math.abs(2 * seed - 1.0))

    var radius = randFloat(LOCATION_POLAR.min_radius, LOCATION_POLAR.min_radius + (LOCATION_POLAR.max_radius - LOCATION_POLAR.min_radius) *  radiusShape)

    var polar = { x: 0, y: yaw * Math.PI / 180, z: randFloat(LOCATION_POLAR.min_radius, LOCATION_POLAR.max_radius) };
    var p = Vec3.fromPolar(polar);

    return Vec3.sum(LOCATION_ORIGIN, p);
}
LOCATION = genLocation();

Vec3.print("RANDOM LOCATION SELECTED:", LOCATION);

// Disable the privacy bubble
Users.disableIgnoreRadius();

// Set position here if playFromCurrentLocation is true
Avatar.position = LOCATION;
Avatar.orientation = Quat.fromPitchYawRollDegrees(0, randFloat(0, 360), 0);
Avatar.scale = 1.0;
Agent.isAvatar = true;

// make the agent "listen" to the audio stream to cause additional audio-mixer load, technically this isn't needed when you're playing a recording
// but if you switch to a non-recording bot, you will need this, so we can leave this.
Agent.isListeningToAudioStream = true;

Recording.loadRecording(RECORDING_URL, function(success) {
    if (success) {
        Script.update.connect(update);
    } else {
        print("Failed to load recording from " + RECORDING_URL);
    }
});

var CHANCE_OF_SOUND = 0.05;

var sounds = [];
loadSounds();

function loadSounds() {
  var sound_filenames = ["AB1.wav", "Anchorman2.wav", "B1.wav", "B1.wav", "Bale1.wav", "Bandcamp.wav",
    "Big1.wav", "Big2.wav", "Brian1.wav", "Buster1.wav", "CES1.wav", "CES2.wav", "CES3.wav", "CES4.wav",
    "Carrie1.wav", "Carrie3.wav", "Charlotte1.wav", "EN1.wav", "EN2.wav", "EN3.wav", "Eugene1.wav", "Francesco1.wav",
    "Italian1.wav", "Japanese1.wav", "Leigh1.wav", "Lucille1.wav", "Lucille2.wav", "MeanGirls.wav", "Murray2.wav",
    "Nigel1.wav", "PennyLane.wav", "Pitt1.wav", "Ricardo.wav", "SN.wav", "Sake1.wav", "Samantha1.wav", "Samantha2.wav",
    "Spicoli1.wav", "Supernatural.wav", "Swearengen1.wav", "TheDude.wav", "Tony.wav", "Triumph1.wav", "Uma1.wav",
    "Walken1.wav", "Walken2.wav", "Z1.wav", "Z2.wav"
  ];

  var SOUND_BASE_URL = "https://s3.amazonaws.com/hifi-public/sounds/cocktail-party/";

  for (var i = 0; i < sound_filenames.length; i++) {
      sounds.push(SoundCache.getSound(SOUND_BASE_URL + sound_filenames[i]));
  }
}

//  Play a random sound from a list of conversational audio clips
function playRandomSound() {
  if (!Agent.isPlayingAvatarSound) {
    var whichSound = Math.floor((Math.random() * sounds.length) % sounds.length);
    Agent.playAvatarSound(sounds[whichSound]);
  }
}

count = 300; // Randomly wait some period of time before starting the recording
function update(event) {
    if (count > 0) {
        count--;
        return;
    }
    if (count == 0) {
        Recording.setPlayFromCurrentLocation(true);
        Recording.setPlayerLoop(true);
        Recording.startPlaying();
        Vec3.print("Playing from ", Avatar.position);
        count--;
    }

    EntityViewer.setPosition(Avatar.position);
    EntityViewer.setOrientation(Avatar.orientation);
    EntityViewer.queryOctree();

    if (Math.random() < CHANCE_OF_SOUND) {
 //     playRandomSound();
    }

    if (!Recording.isPlaying()) {
        Script.update.disconnect(update);
    }

    // Avatar.displayName = "Bot_RAND" + randFloat(LOCATION_PARAMS.min_x, LOCATION_PARAMS.max_x);
}
<commit_msg>Adjusting the values for futvrlands<commit_after>//
// BetterClientSimulationBotFromRecording.js
//  examples
//
//  Created by Sam Gateau building on many others (November 2018).
//  Copyright 2017 High Fidelity, Inc.
//
//  Distributed under the Apache License, Version 2.0.
//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//

randFloat = function(low, high) {
    return low + Math.random() * (high - low);
}

var RECORDINGS_ARRAY = [
  "eventer1.hfr",
  // "cop1.hfr", // Bad Model
  // "cop2.hfr", // Bad Model
  "waiting1.hfr",
  "waiting2.hfr",
  // "waiting3.hfr", // Bad Model
  "waiting4.hfr",
  // "waiting5.hfr", // Moves downward
  "waiting6.hfr",
  // "waiting7.hfr", // Bad Model
  "waiting8.hfr",
  "waiting9.hfr",
  "waiting10.hfr",
  "bot1.hfr",
  "bot2.hfr",
  "bot3.hfr",
  "bot4.hfr",
  "check_12.hfr",
  "peanuts.hfr",
  "claude.hfr",
  "usher1.hfr",
  "usher2.hfr",
  "usher3.hfr",
  "jim.hfr"
];

var RECORDING_URL = "http://hifi-content.s3.amazonaws.com/DomainContent/Event%20/NPC%27s/" + RECORDINGS_ARRAY[Math.floor(Math.random() * RECORDINGS_ARRAY.length)];
print("RANDOM RECORDING SELECTED:" + RECORDING_URL);

var LOCATIONS_ARRAY = [{ min_x: 20, max_x: 21, y: 0.5, min_z: 20, max_z: 21}];

var LOCATION_PARAMS = LOCATIONS_ARRAY[Math.floor(Math.random() * LOCATIONS_ARRAY.length)];

var LOCATION = { x: randFloat(LOCATION_PARAMS.min_x, LOCATION_PARAMS.max_x) - 72.0, y: LOCATION_PARAMS.y - 22.0, z: randFloat(LOCATION_PARAMS.min_z, LOCATION_PARAMS.max_z) + 74.0 };

var LOCATION_ORIGIN = {x:-80.5, y:-22.0, z:83.5};
var LOCATION_POLAR = { min_yaw: 60, max_yaw: 200, min_radius: 6.0, max_radius: 13.0 }

randFloat = function(low, high) {
    return low + Math.random() * (high - low);
}

clamp = function(x, lower, upper) {
    return Math.max(lower, Math.min(upper, x));
}

smoothstep = function(edge0, edge1, x) {
    var t = clamp( (x - edge0) / (edge1 - edge0), 0, 1);
    return t * t * (3.0 - 2.0 * t);
}

function genLocation(seed) {
    var sign = (seed >= 0.5 ? 1.0 : -1.0);
    var absSeed = 2.0 * Math.abs((seed - 0.5));
    //var param = smoothstep(1.0, 0.0, absSeed);
    var param = (1.0 - absSeed) * (1.0 - absSeed);
    var yawCoord = 0.5 + sign * 0.5 * param
    var yaw = LOCATION_POLAR.min_yaw + yawCoord * (LOCATION_POLAR.max_yaw - LOCATION_POLAR.min_yaw);

    var radiusCoord = (1.0 - Math.abs(2 * yawCoord - 1.0) * Math.abs(2 * yawCoord - 1.0))
   // var radiusCoord = Math.cos(Math.abs(2 * yawCoord - 1.0))
    var radiusNoise = Math.random()
    //var radiusNoise = 1.0
    radiusCoord = radiusCoord * radiusNoise;

    var radius = LOCATION_POLAR.min_radius + (LOCATION_POLAR.max_radius - LOCATION_POLAR.min_radius) *  radiusCoord;

    var polar = { x: 0, y: yaw * Math.PI / 180, z: radius };
    var p = Vec3.fromPolar(polar);

    var pos = Vec3.sum(LOCATION_ORIGIN, p);
    print(JSON.stringify(pos))
    return pos;
}
LOCATION = genLocation(Math.random());

Vec3.print("RANDOM LOCATION SELECTED:", LOCATION);

// Disable the privacy bubble
Users.disableIgnoreRadius();

// Set position here if playFromCurrentLocation is true
Avatar.position = LOCATION;
Avatar.orientation = Quat.fromPitchYawRollDegrees(0, randFloat(0, 360), 0);
Avatar.scale = 1.0;
Agent.isAvatar = true;

// make the agent "listen" to the audio stream to cause additional audio-mixer load, technically this isn't needed when you're playing a recording
// but if you switch to a non-recording bot, you will need this, so we can leave this.
Agent.isListeningToAudioStream = true;

Recording.loadRecording(RECORDING_URL, function(success) {
    if (success) {
        Script.update.connect(update);
    } else {
        print("Failed to load recording from " + RECORDING_URL);
    }
});

var CHANCE_OF_SOUND = 0.05;

var sounds = [];
loadSounds();

function loadSounds() {
  var sound_filenames = ["AB1.wav", "Anchorman2.wav", "B1.wav", "B1.wav", "Bale1.wav", "Bandcamp.wav",
    "Big1.wav", "Big2.wav", "Brian1.wav", "Buster1.wav", "CES1.wav", "CES2.wav", "CES3.wav", "CES4.wav",
    "Carrie1.wav", "Carrie3.wav", "Charlotte1.wav", "EN1.wav", "EN2.wav", "EN3.wav", "Eugene1.wav", "Francesco1.wav",
    "Italian1.wav", "Japanese1.wav", "Leigh1.wav", "Lucille1.wav", "Lucille2.wav", "MeanGirls.wav", "Murray2.wav",
    "Nigel1.wav", "PennyLane.wav", "Pitt1.wav", "Ricardo.wav", "SN.wav", "Sake1.wav", "Samantha1.wav", "Samantha2.wav",
    "Spicoli1.wav", "Supernatural.wav", "Swearengen1.wav", "TheDude.wav", "Tony.wav", "Triumph1.wav", "Uma1.wav",
    "Walken1.wav", "Walken2.wav", "Z1.wav", "Z2.wav"
  ];

  var SOUND_BASE_URL = "https://s3.amazonaws.com/hifi-public/sounds/cocktail-party/";

  for (var i = 0; i < sound_filenames.length; i++) {
      sounds.push(SoundCache.getSound(SOUND_BASE_URL + sound_filenames[i]));
  }
}

//  Play a random sound from a list of conversational audio clips
function playRandomSound() {
  if (!Agent.isPlayingAvatarSound) {
    var whichSound = Math.floor((Math.random() * sounds.length) % sounds.length);
    Agent.playAvatarSound(sounds[whichSound]);
  }
}

count = 300; // Randomly wait some period of time before starting the recording
function update(event) {
    if (count > 0) {
        count--;
        return;
    }
    if (count == 0) {
        Recording.setPlayFromCurrentLocation(true);
        Recording.setPlayerLoop(true);
        Recording.startPlaying();
        Vec3.print("Playing from ", Avatar.position);
        count--;
    }

    EntityViewer.setPosition(Avatar.position);
    EntityViewer.setOrientation(Avatar.orientation);
    EntityViewer.queryOctree();

    if (Math.random() < CHANCE_OF_SOUND) {
 //     playRandomSound();
    }

    if (!Recording.isPlaying()) {
        Script.update.disconnect(update);
    }

    // Avatar.displayName = "Bot_RAND" + randFloat(LOCATION_PARAMS.min_x, LOCATION_PARAMS.max_x);
}
<|endoftext|>


<commit_before>var questionnaire = angular.module('questionnaire', ['ui.router', 'formListCtrl', 'editPageCtrl', 'displayDataCtrl', 'surveyFormCtrl', 'thankyouCtl']);

questionnaire.config(function($stateProvider) {
  $stateProvider
    .state('index', {
      url: "",
      views: {
        "topBar": { templateUrl: "page/header.html"},
        "content": { templateUrl: "page/formList.html" }
      }
    })
    .state('formList', {
      url: "/formList",
      views: {
        "topBar": { templateUrl: "page/header.html"},
        "content": { templateUrl: "page/formList.html" }
      }
    })
    .state('editPage', {
      url: "/editPage",
      views: {
        "topBar": { templateUrl: "page/header.html"},
        "content": { templateUrl: "page/editPage.html" }
      }
    })
    .state('newForm', {
      url: "/newForm",
      views: {
        "topBar": { templateUrl: "page/header.html"},
        "content": { templateUrl: "page/newForm.html" }
      }
    })
    .state('surveyForm', {
      url: "/surveyForm",
      views: {
        "content": { templateUrl: "page/surveyForm.html" }
      }
    })
    .state('thankyou', {
      url: "/thankyou",
      views: {
        "content": { templateUrl: "page/thankyou.html" }
      }
    })
    .state('displayData', {
      url: "/displayData",
      views: {
        "topBar": { templateUrl: "page/header.html"},
        "content": { templateUrl: "page/displayData.html" }
      }
    });
});

questionnaire.controller('appCtrl', ['$rootScope', '$scope', '$http', 'locals', function($rootScope, $scope, $http, locals) {
  // 请求数据，返回到$rootScope
  $http({
    method: 'GET',
    url: 'dummyData.json'
  }).then(function successCallback(response) {
    if(typeof(Storage) !== undefined) {
      if (locals.getObject('forms') === undefined) {
        $rootScope.forms = locals.getObject('forms');
      } else {
        $rootScope.forms = response.data.forms;
        locals.setObject('forms', $rootScope.forms);
      }
    } else {
    }
  }, function errorCallback(response) {
  });
}]);

<commit_msg>fix localStorage bug<commit_after>var questionnaire = angular.module('questionnaire', ['ui.router', 'formListCtrl', 'editPageCtrl', 'displayDataCtrl', 'surveyFormCtrl', 'thankyouCtl']);

questionnaire.config(function($stateProvider) {
  $stateProvider
    .state('index', {
      url: "",
      views: {
        "topBar": { templateUrl: "page/header.html"},
        "content": { templateUrl: "page/formList.html" }
      }
    })
    .state('formList', {
      url: "/formList",
      views: {
        "topBar": { templateUrl: "page/header.html"},
        "content": { templateUrl: "page/formList.html" }
      }
    })
    .state('editPage', {
      url: "/editPage",
      views: {
        "topBar": { templateUrl: "page/header.html"},
        "content": { templateUrl: "page/editPage.html" }
      }
    })
    .state('newForm', {
      url: "/newForm",
      views: {
        "topBar": { templateUrl: "page/header.html"},
        "content": { templateUrl: "page/newForm.html" }
      }
    })
    .state('surveyForm', {
      url: "/surveyForm",
      views: {
        "content": { templateUrl: "page/surveyForm.html" }
      }
    })
    .state('thankyou', {
      url: "/thankyou",
      views: {
        "content": { templateUrl: "page/thankyou.html" }
      }
    })
    .state('displayData', {
      url: "/displayData",
      views: {
        "topBar": { templateUrl: "page/header.html"},
        "content": { templateUrl: "page/displayData.html" }
      }
    });
});

questionnaire.controller('appCtrl', ['$rootScope', '$scope', '$http', 'locals', function($rootScope, $scope, $http, locals) {
  // 请求数据，返回到$rootScope
  $http({
    method: 'GET',
    url: 'dummyData.json'
  }).then(function successCallback(response) {
    if(typeof(Storage) !== undefined) {
      if (locals.getObject('forms') !== undefined) {
        $rootScope.forms = locals.getObject('forms');
      } else {
        $rootScope.forms = response.data.forms;
        locals.setObject('forms', $rootScope.forms);
      }
    } else {
    }
  }, function errorCallback(response) {
  });
}]);

<|endoftext|>


<commit_before>/*
 * grunt-filerev-replace
 * https://github.com/solidusjs/grunt-filerev-replace
 *
 * Copyright (c) 2013 Sparkart Group, Inc.
 * Licensed under the MIT license.
 */

'use strict';

var path = require('path');
var slash = require('slash');

var STARTING_DELIMITER = '(\\\\?\'|\\\\?"|\\\\?\\()';
var ALLOWED_PATH_CHARS = '([^\'"\\(\\)\\?#]*?)'; // Lazy, in order not to eat the optional starting character of ENDING_DELIMITER
var ENDING_DELIMITER   = '(\\\\?\'|\\\\?"|\\\\?\\)|\\?|#)';

module.exports = function(grunt) {
  grunt.registerMultiTask('filerev_replace', 'Replace references to grunt-filerev files.', function() {
    var assets_root = this.options().assets_root;
    var views_root = this.options().views_root || assets_root;
    var assets_paths = filerev_summary_to_assets_paths( assets_root );

    this.files[0].src.forEach( function( view_src ){
      var changes = replace_assets_paths_in_view( assets_paths, view_src, views_root );
      log_view_changes( view_src, changes );
    });
  });

  function filerev_summary_to_assets_paths( assets_root ) {
    var assets = {};
    for( var filerev_path in grunt.filerev.summary ){
      var src = file_path_to_web_path( filerev_path, assets_root );
      var dest = path.basename( grunt.filerev.summary[filerev_path] );
      var regexp = asset_path_regexp( src );
      assets[src] = { dest: dest, regexp: regexp };
    }
    return assets;
  }

  // file_path => 'tmp/assets/images/ajax-loader.gif'
  // root => 'tmp/assets'
  // returns => '/images/ajax-loader.gif'
  function file_path_to_web_path( file_path, root ) {
    return slash( path.join( '/', path.relative( root, file_path ) ) );
  }

  function asset_path_regexp( asset_path ) {
    return new RegExp( STARTING_DELIMITER + // p1
                       ALLOWED_PATH_CHARS + // p2
                       '(' + escape_for_regexp( path.basename( asset_path ) ) + ')' + // p3
                       ALLOWED_PATH_CHARS + // p4
                       ENDING_DELIMITER, // p5
                       'ig' );
  }

  function escape_for_regexp( string ) {
    return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
  }

  function replace_assets_paths_in_view( assets_paths, view_src, views_root ) {
    var view = grunt.file.read( view_src );
    var changes = [];

    var replace_string = function( match, p1, p2, p3, p4, p5 ) {
      var asset_path = absolute_asset_path( p2 + p3 + p4, view_src, views_root );

      if( grunt.file.arePathsEquivalent( asset_path.toLowerCase(), asset_src.toLowerCase() ) ) {
        changed = true;
        return p1 + p2 + asset_dest + p4 + p5;
      } else {
        return match;
      }
    };

    for( var asset_src in assets_paths ){
      var asset_dest = assets_paths[asset_src].dest;
      var changed = false;

      view = view.replace( assets_paths[asset_src].regexp, replace_string );

      if( changed ){
        changes.push( asset_src +' changed to '.grey+ asset_dest );
      }
    }

    grunt.file.write( view_src, view );
    return changes;
  }

  function absolute_asset_path( string, view_src, views_root ) {
    var asset_path = string.trim();
    if( asset_path[0] !== '/' && asset_path[0] !== '\\' ) {
      asset_path = path.join( path.dirname( view_src ), asset_path );
      asset_path = file_path_to_web_path( asset_path, views_root );
    }
    return asset_path;
  }

  function log_view_changes( view_src, changes ) {
    if( changes.length > 0 ){
      grunt.log.writeln( '✔ '.green+ view_src );
      for( var i in changes ){
        grunt.log.writeln( '  '+ changes[i] );
      }
    }
  }
};
<commit_msg>Added CDN URl<commit_after>/*
 * grunt-filerev-replace
 * https://github.com/solidusjs/grunt-filerev-replace
 *
 * Copyright (c) 2013 Sparkart Group, Inc.
 * Licensed under the MIT license.
 */

'use strict';

var path = require('path');
var slash = require('slash');

var STARTING_DELIMITER = '(\\\\?\'|\\\\?"|\\\\?\\()';
var ALLOWED_PATH_CHARS = '([^\'"\\(\\)\\?#]*?)'; // Lazy, in order not to eat the optional starting character of ENDING_DELIMITER
var ENDING_DELIMITER   = '(\\\\?\'|\\\\?"|\\\\?\\)|\\?|#)';

module.exports = function(grunt) {
  grunt.registerMultiTask('filerev_replace', 'Replace references to grunt-filerev files.', function() {
    var assets_root = this.options().assets_root;
    var views_root = this.options().views_root || assets_root;
    var assets_paths = filerev_summary_to_assets_paths( assets_root );
		var cdn_url = this.options().cdn_url || '';

    this.files[0].src.forEach( function( view_src ){
      var changes = replace_assets_paths_in_view( assets_paths, view_src, views_root, cdn_url );
      log_view_changes( view_src, changes );
    });
  });

  function filerev_summary_to_assets_paths( assets_root ) {
    var assets = {};
    for( var filerev_path in grunt.filerev.summary ){
      var src = file_path_to_web_path( filerev_path, assets_root );
      var dest = path.basename( grunt.filerev.summary[filerev_path] );
      var regexp = asset_path_regexp( src );
      assets[src] = { dest: dest, regexp: regexp };
    }
    return assets;
  }

  // file_path => 'tmp/assets/images/ajax-loader.gif'
  // root => 'tmp/assets'
  // returns => '/images/ajax-loader.gif'
  function file_path_to_web_path( file_path, root ) {
    return slash( path.join( '/', path.relative( root, file_path ) ) );
  }

  function asset_path_regexp( asset_path ) {
    return new RegExp( STARTING_DELIMITER + // p1
                       ALLOWED_PATH_CHARS + // p2
                       '(' + escape_for_regexp( path.basename( asset_path ) ) + ')' + // p3
                       ALLOWED_PATH_CHARS + // p4
                       ENDING_DELIMITER, // p5
                       'ig' );
  }

  function escape_for_regexp( string ) {
    return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
  }

  function replace_assets_paths_in_view( assets_paths, view_src, views_root, cdn_url ) {
    var view = grunt.file.read( view_src );
    var changes = [];

    var replace_string = function( match, p1, p2, p3, p4, p5 ) {
      var asset_path = absolute_asset_path( p2 + p3 + p4, view_src, views_root );

      if( grunt.file.arePathsEquivalent( asset_path.toLowerCase(), asset_src.toLowerCase() ) ) {
        changed = true;
        return p1 + cdn_url + p2 + asset_dest + p4 + p5;
      } else {
        return match;
      }
    };

    for( var asset_src in assets_paths ){
      var asset_dest = assets_paths[asset_src].dest;
      var changed = false;

      view = view.replace( assets_paths[asset_src].regexp, replace_string );

      if( changed ){
        changes.push( asset_src +' changed to '.grey+ asset_dest );
      }
    }

    grunt.file.write( view_src, view );
    return changes;
  }

  function absolute_asset_path( string, view_src, views_root ) {
    var asset_path = string.trim();
    if( asset_path[0] !== '/' && asset_path[0] !== '\\' ) {
      asset_path = path.join( path.dirname( view_src ), asset_path );
      asset_path = file_path_to_web_path( asset_path, views_root );
    }
    return asset_path;
  }

  function log_view_changes( view_src, changes ) {
    if( changes.length > 0 ){
      grunt.log.writeln( '✔ '.green+ view_src );
      for( var i in changes ){
        grunt.log.writeln( '  '+ changes[i] );
      }
    }
  }
};
<|endoftext|>


<commit_before>module.exports = function (grunt) {
    'use strict';

    grunt.registerTask('livestyle', 'Description', function () {
        this.async();

        var config = grunt.config(this.name) || {},
            options = {
                root: config.root || 'app',
                port: config.port || 9000,
                proxy: config.proxy || null,
                jsx: config.jsx === false ? false : true,
                less: config.less === false ? false : true,
                scss: config.scss === false ? false : true,
                html: config.watchHtml === false ? false : true,
                cssImages: config.watchCssImages === false ? false : true,
                processimage: config.processimage === false ? false : true,
                debug: !!config.debug,
                mappings: config.mappings || {},
                browsers: config.browsers || [
                    '> 1%',
                    'last 2 versions',
                    'Firefox ESR',
                    'Opera 12.1'
                ]
            };

        var server = require('livestyle/lib/createLiveStyleApp')({
            watchHtml: options.html,
            watchCssImages: options.cssImages,
            dead: options.dead,
            debug: options.debug,
            root: options.root,
            compiless: options.less,
            compilesass: options.scss,
            autoprefixer: options.browsers,
            jsxtransform: options.jsx,
            processImage: options.processimage,
            mappings: options.mappings,
            proxy: options.proxy
        }).listen(options.port, '0.0.0.0', function (error) {
            if (error) {
                return grunt.log.writeln(error);
            }

            if (options.proxy) {
                grunt.log.writeln('Proxying to ' + options.proxy);
                if (options.root) {
                    grunt.log.writeln('Serving static CSS files from ' + options.root);
                }
            } else if (options.root) {
                grunt.log.writeln('Serving static files from ' + options.root);
            }

            grunt.log.writeln('Listening to http://' + '0.0.0.0' + ':' + options.port + '/');
            grunt.event.emit('serverListening', options.port);
        });

        if (!options.dead) {
            require('livestyle/lib/installLiveCssFileWatcherInServer')(server, {
                debug: options.debug,
                root: options.root,
                mtime: false,
                watchfile: true,
                mappings: options.mappings,
                watchCssImages: options.cssImages
            }, require('socket.io'));
        }

    });
};
<commit_msg>Properly resolve root path<commit_after>var Path = require('path');

module.exports = function (grunt) {
    'use strict';

    grunt.registerTask('livestyle', 'Description', function () {
        this.async();

        var config = grunt.config(this.name) || {},
            options = {
                root: Path.resolve(config.root || 'app'),
                port: config.port || 9000,
                proxy: config.proxy || null,
                jsx: config.jsx === false ? false : true,
                less: config.less === false ? false : true,
                scss: config.scss === false ? false : true,
                html: config.watchHtml === false ? false : true,
                cssImages: config.watchCssImages === false ? false : true,
                processimage: config.processimage === false ? false : true,
                debug: !!config.debug,
                mappings: config.mappings || {},
                browsers: config.browsers || [
                    '> 1%',
                    'last 2 versions',
                    'Firefox ESR',
                    'Opera 12.1'
                ]
            };

        var server = require('livestyle/lib/createLiveStyleApp')({
            watchHtml: options.html,
            watchCssImages: options.cssImages,
            dead: options.dead,
            debug: options.debug,
            root: options.root,
            compiless: options.less,
            compilesass: options.scss,
            autoprefixer: options.browsers,
            jsxtransform: options.jsx,
            processImage: options.processimage,
            mappings: options.mappings,
            proxy: options.proxy
        }).listen(options.port, '0.0.0.0', function (error) {
            if (error) {
                return grunt.log.writeln(error);
            }

            if (options.proxy) {
                grunt.log.writeln('Proxying to ' + options.proxy);
                if (options.root) {
                    grunt.log.writeln('Serving static CSS files from ' + options.root);
                }
            } else if (options.root) {
                grunt.log.writeln('Serving static files from ' + options.root);
            }

            grunt.log.writeln('Listening to http://' + '0.0.0.0' + ':' + options.port + '/');
            grunt.event.emit('serverListening', options.port);
        });

        if (!options.dead) {
            require('livestyle/lib/installLiveCssFileWatcherInServer')(server, {
                debug: options.debug,
                root: options.root,
                mtime: false,
                watchfile: true,
                mappings: options.mappings,
                watchCssImages: options.cssImages
            }, require('socket.io'));
        }

    });
};
<|endoftext|>


<commit_before>/* jshint node:true */
var _ = require('lodash');
var MarkupMarkdown = require('node-markup-markdown');
var htmlEscape = require('html-escape');

function processJSON (contents, options) {

  function recurseProcessJSON (contents) {
    _.each(contents, function (value, key) {
      if (_.isObject(value)) {
        contents[key] = recurseProcessJSON(value);
      }
      else {
        if (options.htmlSafe) {
          value = htmlEscape(value);
        }

        contents[key] = MarkupMarkdown.parse(value, options);
      }
    });
    return contents;
  }
  return recurseProcessJSON(contents);
}

module.exports = function (grunt) {
  'use strict';

  grunt.registerMultiTask(
    'markup-markdown',
    'A grunt wrapper for the node-markup-markdown task.',

    function() {
      var options = this.options({
        htmlSafe: true
      });

      this.files.forEach(function(fileDescription) {
        fileDescription.src.forEach(function (file) {

          grunt.log.writeln('Processing ' + file);

          var processed;

          if (/\.json$/.test(file)) {
            var contents = grunt.file.readJSON(file);
            processed = JSON.stringify(processJSON(contents, options));
          }
          else {
            var text = grunt.file.read(file);
            processed = MarkupMarkdown.parse(text, options);
          }

          grunt.file.write(fileDescription.dest, processed);
        });
      });
    }
  );
};<commit_msg>Adds null check for value.<commit_after>/* jshint node:true */
var _ = require('lodash');
var MarkupMarkdown = require('node-markup-markdown');
var htmlEscape = require('html-escape');

function processJSON (contents, options) {

  function recurseProcessJSON (contents) {
    _.each(contents, function (value, key) {
      if (_.isObject(value)) {
        contents[key] = recurseProcessJSON(value);
      }
      else {
        if (options.htmlSafe) {
          value = htmlEscape(value);
        }

        contents[key] = value ? MarkupMarkdown.parse(value, options) : value;
      }
    });
    return contents;
  }
  return recurseProcessJSON(contents);
}

module.exports = function (grunt) {
  'use strict';

  grunt.registerMultiTask(
    'markup-markdown',
    'A grunt wrapper for the node-markup-markdown task.',

    function() {
      var options = this.options({
        htmlSafe: true
      });

      this.files.forEach(function(fileDescription) {
        fileDescription.src.forEach(function (file) {

          grunt.log.writeln('Processing ' + file);

          var processed;

          if (/\.json$/.test(file)) {
            var contents = grunt.file.readJSON(file);
            processed = JSON.stringify(processJSON(contents, options));
          }
          else {
            var text = grunt.file.read(file);
            processed = MarkupMarkdown.parse(text, options);
          }

          grunt.file.write(fileDescription.dest, processed);
        });
      });
    }
  );
};
<|endoftext|>