<commit_before>/**
 * Basic rotation through the available JSON provided by imagedex
 */

$(document).ready(function () {
  $show = $('.slideshow > p a.starter');

  var imagedex = function () {
    var type = $('p.current-slide').attr('slide-type');
    if (type in window && 'files' in window[type]) {
      return window[type].files;
    }
  }

  $show.click(function () {
    if ($(this).hasClass('started')) {
      return false;
    }
    else {
      $('.slideshow > p a.starter').each(function () {
        $(this).addClass('started');
      });
    }

    var slideType = $(this).attr('data-role');
    var $base = $('.slideshow > p.base-slide img.base').parents('p');
    var $origclone = $base.clone();
    $origclone
      .addClass('current-slide')
      .attr('slide-type', slideType);
    $('img', $origclone).attr('class', 'slide');

    var slideFromPath = function (path, i) {
      var $clone = $origclone.clone();
      $('img', $clone)
        .attr('src', path)
        .css({
          'max-height': '80%',
          'max-width': '80%'
          })
        .parents('a.full-size')
          .attr('href', path);
      $clone
        .attr('data-index', i)
        .addClass('slide-'+ i);

      return $clone;
    }

    var dialogOpts = {
      autoOpen: false,
      closeOnEscape: true,
      height: 'auto',
      maxHeight: 600,
      maxWidth: 800,
      draggable: false,
      beforeClose: function () {
        $('.slideshow a#start.started').removeClass('started');
      }
    };

    $current = slideFromPath(imagedex()[0], 0);
    $current.dialog(dialogOpts);
    $current.dialog('open');
    $origclone.remove();

    var $move = $('p.current-slide > a.move');
    var transition = function (index) {
      if ($current.attr('data-index') != index) {
        var path = imagedex()[index];
        $('img', $current)
          .attr('src', path)
          .parents('a.full-size')
          .attr('href', path);

        $current
          .attr('data-index', index)
          .addClass('slide-'+ index);
      }
    };

    $(window.document).keydown(function (e) {
      $slide = $('p.current-slide.ui-dialog-content');
      if ('length' in $slide && $slide.length == 1) {
        if (e.keyCode == 37) {
          action = 'prev';
        }
        else if (e.keyCode == 39) {
          action = 'next';
        }
        else {
          action = false;
        }

        if (action) {
          $('a.move[data-role="'+ action +'"]', $slide).trigger('click');
        }
      }
    });

    $move.click(function() {
      var move = $(this).attr('data-role');
      var moveto = $(this).parents('p.current-slide').attr('data-index');

      if (move == 'prev') {
        --moveto;
      }
      else if (move == 'next') {
        ++moveto;
      }

      //sanity check
      var max = imagedex().length - 1;
      if (moveto < 0) {
        moveto = 0;
      }
      else if (moveto > max) {
        moveto = max;
      }

      transition(moveto);
    });

  });
});
<commit_msg>proper stopper for js users<commit_after>/**
 * Basic rotation through the available JSON provided by imagedex
 */

$(document).ready(function () {
  $show = $('.slideshow > p a.starter');

  var imagedex = function () {
    var type = $('p.current-slide').attr('slide-type');
    if (type in window && 'files' in window[type]) {
      return window[type].files;
    }
  }

  $show.click(function (e) {
    if ($(this).hasClass('started')) {
      return false;
    }
    else {
      $('.slideshow > p a.starter').each(function () {
        $(this).addClass('started');
      });
    }

    var slideType = $(this).attr('data-role');
    var $base = $('.slideshow > p.base-slide img.base').parents('p');
    var $origclone = $base.clone();
    $origclone
      .addClass('current-slide')
      .attr('slide-type', slideType);
    $('img', $origclone).attr('class', 'slide');

    var slideFromPath = function (path, i) {
      var $clone = $origclone.clone();
      $('img', $clone)
        .attr('src', path)
        .css({
          'max-height': '80%',
          'max-width': '80%'
          })
        .parents('a.full-size')
          .attr('href', path);
      $clone
        .attr('data-index', i)
        .addClass('slide-'+ i);

      return $clone;
    }

    var dialogOpts = {
      autoOpen: false,
      closeOnEscape: true,
      height: 'auto',
      maxHeight: 600,
      maxWidth: 800,
      draggable: false,
      beforeClose: function () {
        $('.slideshow a#start.started').removeClass('started');
      }
    };

    $current = slideFromPath(imagedex()[0], 0);
    $current.dialog(dialogOpts);
    $current.dialog('open');
    $origclone.remove();

    var $move = $('p.current-slide > a.move');
    var transition = function (index) {
      if ($current.attr('data-index') != index) {
        var path = imagedex()[index];
        $('img', $current)
          .attr('src', path)
          .parents('a.full-size')
          .attr('href', path);

        $current
          .attr('data-index', index)
          .addClass('slide-'+ index);
      }
    };

    $(window.document).keydown(function (e) {
      $slide = $('p.current-slide.ui-dialog-content');
      if ('length' in $slide && $slide.length == 1) {
        if (e.keyCode == 37) {
          action = 'prev';
        }
        else if (e.keyCode == 39) {
          action = 'next';
        }
        else {
          action = false;
        }

        if (action) {
          $('a.move[data-role="'+ action +'"]', $slide).trigger('click');
        }
      }
    });

    $move.click(function() {
      var move = $(this).attr('data-role');
      var moveto = $(this).parents('p.current-slide').attr('data-index');

      if (move == 'prev') {
        --moveto;
      }
      else if (move == 'next') {
        ++moveto;
      }

      //sanity check
      var max = imagedex().length - 1;
      if (moveto < 0) {
        moveto = 0;
      }
      else if (moveto > max) {
        moveto = max;
      }

      transition(moveto);
    });

    return e.preventDefault();
  });
});
<|endoftext|>


<commit_before>config = (function () {
  var ds1 = {
    "ds1/Anor Londo.iv": false,
    "ds1/Ash Lake.iv": false,
    "ds1/Blighttown + Quelaag's Domain.iv": false,
    "ds1/Catacombs.iv": false,
    "ds1/Darkroot Garden + Basin.iv": false,
    "ds1/Demon Ruins + Lost Izalith.iv": false,
    "ds1/Depths.iv": false,
    "ds1/Duke's Archive + Crystal Caves.iv": false,
    "ds1/Firelink Shrine.iv": true,
    "ds1/Kiln of the First Flame.iv": false,
    "ds1/New Londo Ruins + Valley of Drakes.iv": false,
    "ds1/Oolacile.iv": false,
    "ds1/Painted World of Ariamis.iv": false,
    "ds1/Sen's Fortress.iv": false,
    "ds1/Tomb of the Giants.iv": false,
    "ds1/Undead Asylum.iv": false,
    "ds1/Undead Burg.iv": true,
  };

  var ds2 = {
    "ds2/Aldia's Keep.iv": false,
    "ds2/Brightstone Cove Tseldora + Lord's Private Chamber.iv": false,
    "ds2/Dark Chasm of Old.iv": false,
    "ds2/Doors of Pharros.iv": false,
    "ds2/Dragon Aerie & Dragon Shrine.iv": false,
    "ds2/Dragon Memories.iv": false,
    "ds2/Drangleic Castle + King's Passage + Throne of Want.iv": false,
    "ds2/Forest of Fallen Giants.iv": false,
    "ds2/Grave of Saints.iv": false,
    "ds2/Harvest Valley + Earthen Peak.iv": false,
    "ds2/Heide's Tower of Flame + Cathedral of Blue.iv": false,
    "ds2/Heide's Tower of Flame.iv": false,
    "ds2/Huntsman's Copse + Undead Purgatory.iv": false,
    "ds2/Iron Keep + Belfry Sol.iv": false,
    "ds2/Majula (1).iv": true,
    "ds2/Majula (2).iv": false,
    "ds2/Memory of Vammar, Orro, Jeigh.iv": false,
    "ds2/No-man's Wharf.iv": false,
    "ds2/Shaded Woods + Shrine of Winter.iv": false,
    "ds2/Shrine of Amana.iv": false,
    "ds2/The Gutter + Black Gulch.iv": false,
    "ds2/The Lost Bastille + Sinner's Rise + Belfry Luna.iv": false,
    "ds2/Things Betwixt.iv": false,
    "ds2/Undead Crypt.iv": false,
  };

  var current = ds1;

  var material = new THREE.MeshLambertMaterial({
    color: 0xffffff,
    wrapAround: true
  });

  var light1 = new THREE.DirectionalLight(0xffffff);
  light1.position.set(1, 1, 1).normalize();

  var cameraPosition = new THREE.Vector3(150, 150, -100);

  return {
    ds1: ds1,
    ds2: ds2,
    current: current,
    material: material,
    lights: [light1],
    cameraPosition: cameraPosition,
  };
})();<commit_msg>Add specular highlights<commit_after>config = (function () {
  var ds1 = {
    "ds1/Anor Londo.iv": false,
    "ds1/Ash Lake.iv": false,
    "ds1/Blighttown + Quelaag's Domain.iv": false,
    "ds1/Catacombs.iv": false,
    "ds1/Darkroot Garden + Basin.iv": false,
    "ds1/Demon Ruins + Lost Izalith.iv": false,
    "ds1/Depths.iv": false,
    "ds1/Duke's Archive + Crystal Caves.iv": false,
    "ds1/Firelink Shrine.iv": true,
    "ds1/Kiln of the First Flame.iv": false,
    "ds1/New Londo Ruins + Valley of Drakes.iv": false,
    "ds1/Oolacile.iv": false,
    "ds1/Painted World of Ariamis.iv": false,
    "ds1/Sen's Fortress.iv": false,
    "ds1/Tomb of the Giants.iv": false,
    "ds1/Undead Asylum.iv": false,
    "ds1/Undead Burg.iv": true,
  };

  var ds2 = {
    "ds2/Aldia's Keep.iv": false,
    "ds2/Brightstone Cove Tseldora + Lord's Private Chamber.iv": false,
    "ds2/Dark Chasm of Old.iv": false,
    "ds2/Doors of Pharros.iv": false,
    "ds2/Dragon Aerie & Dragon Shrine.iv": false,
    "ds2/Dragon Memories.iv": false,
    "ds2/Drangleic Castle + King's Passage + Throne of Want.iv": false,
    "ds2/Forest of Fallen Giants.iv": false,
    "ds2/Grave of Saints.iv": false,
    "ds2/Harvest Valley + Earthen Peak.iv": false,
    "ds2/Heide's Tower of Flame + Cathedral of Blue.iv": false,
    "ds2/Heide's Tower of Flame.iv": false,
    "ds2/Huntsman's Copse + Undead Purgatory.iv": false,
    "ds2/Iron Keep + Belfry Sol.iv": false,
    "ds2/Majula (1).iv": true,
    "ds2/Majula (2).iv": false,
    "ds2/Memory of Vammar, Orro, Jeigh.iv": false,
    "ds2/No-man's Wharf.iv": false,
    "ds2/Shaded Woods + Shrine of Winter.iv": false,
    "ds2/Shrine of Amana.iv": false,
    "ds2/The Gutter + Black Gulch.iv": false,
    "ds2/The Lost Bastille + Sinner's Rise + Belfry Luna.iv": false,
    "ds2/Things Betwixt.iv": false,
    "ds2/Undead Crypt.iv": false,
  };

  var current = ds1;

  var material = new THREE.MeshPhongMaterial({
    color: 0xffffff,
    wrapAround: true,
  });

  var light1 = new THREE.DirectionalLight(0xffffff);
  light1.position.set(1, 1, 1).normalize();

  var cameraPosition = new THREE.Vector3(150, 150, -100);

  return {
    ds1: ds1,
    ds2: ds2,
    current: current,
    material: material,
    lights: [light1],
    cameraPosition: cameraPosition,
  };
})();<|endoftext|>


<commit_before>/**
 * Component definition for the frost-range-picker component
 */

import {Component} from 'ember-frost-core'
import {PropTypes} from 'ember-prop-types'
import moment from 'moment'

import layout from '../templates/components/frost-range-picker'

export default Component.extend({

  // == Dependencies ==========================================================

  // == Keyword Properties ====================================================

  classNameBindings: ['isVertical:vertical:horizontal'],
  layout,

  // == PropTypes =============================================================

  propTypes: {
    // Options
    end: PropTypes.EmberComponent,
    endTitle: PropTypes.string,
    isVertical: PropTypes.bool,
    start: PropTypes.EmberComponent,
    startTitle: PropTypes.string,
    value: PropTypes.shape({
      end: PropTypes.string.isRequired,
      start: PropTypes.string.isRequired
    }).isRequired,

    // Events
    onChange: PropTypes.func.isRequired,

    // State
    _endValueInternal: PropTypes.string,
    _startValueInternal: PropTypes.string,
    _valueInvalid: PropTypes.bool
  },

  getDefaultProps () {
    return {
      isVertical: false,
      _valueInvalid: false
    }
  },

  // == Computed Properties ===================================================

  // == Functions =============================================================

  // == DOM Events ============================================================

  // == Lifecycle Hooks =======================================================

  // == Actions ===============================================================

  actions: {
    _onEndChange (endValue) {
      const momentEndValue = moment(endValue)
      const _startValueInternal = this.get('_startValueInternal') || this.get('value.start')

      if (moment(_startValueInternal).isSameOrBefore(momentEndValue)) {
        this.setProperties({
          _endValueInternal: endValue,
          _valueInvalid: false
        })
        this.onChange({
          end: endValue,
          start: _startValueInternal
        })
      } else {
        this.setProperties({
          _endValueInternal: endValue,
          _valueInvalid: true
        })
      }
    },

    _onStartChange (startValue) {
      const _endValueInternal = this.get('_endValueInternal') || this.get('value.end')
      const momentStartValue = moment(startValue)

      if (momentStartValue.isSameOrBefore(moment(_endValueInternal))) {
        this.setProperties({
          _startValueInternal: startValue,
          _valueInvalid: false
        })
        this.onChange({
          end: _endValueInternal,
          start: startValue
        })
      } else {
        this.setProperties({
          _startValueInternal: startValue,
          _valueInvalid: true
        })
      }
    }
  }
})
<commit_msg>Allow empty values for frost-range-picker<commit_after>/**
 * Component definition for the frost-range-picker component
 */

import {Component} from 'ember-frost-core'
import {PropTypes} from 'ember-prop-types'
import moment from 'moment'

import layout from '../templates/components/frost-range-picker'

export default Component.extend({

  // == Dependencies ==========================================================

  // == Keyword Properties ====================================================

  classNameBindings: ['isVertical:vertical:horizontal'],
  layout,

  // == PropTypes =============================================================

  propTypes: {
    // Options
    end: PropTypes.EmberComponent,
    endTitle: PropTypes.string,
    isVertical: PropTypes.bool,
    start: PropTypes.EmberComponent,
    startTitle: PropTypes.string,
    value: PropTypes.shape({
      end: PropTypes.string,
      start: PropTypes.string
    }),

    // Events
    onChange: PropTypes.func.isRequired,

    // State
    _endValueInternal: PropTypes.string,
    _startValueInternal: PropTypes.string,
    _valueInvalid: PropTypes.bool
  },

  getDefaultProps () {
    return {
      isVertical: false,
      _valueInvalid: false
    }
  },

  // == Computed Properties ===================================================

  // == Functions =============================================================

  // == DOM Events ============================================================

  // == Lifecycle Hooks =======================================================

  // == Actions ===============================================================

  actions: {
    _onEndChange (endValue) {
      const momentEndValue = moment(endValue)
      const _startValueInternal = this.get('_startValueInternal') || this.get('value.start')

      if (moment(_startValueInternal).isSameOrBefore(momentEndValue)) {
        this.setProperties({
          _endValueInternal: endValue,
          _valueInvalid: false
        })
        this.onChange({
          end: endValue,
          start: _startValueInternal
        })
      } else {
        this.setProperties({
          _endValueInternal: endValue,
          _valueInvalid: true
        })
      }
    },

    _onStartChange (startValue) {
      const _endValueInternal = this.get('_endValueInternal') || this.get('value.end')
      const momentStartValue = moment(startValue)

      if (momentStartValue.isSameOrBefore(moment(_endValueInternal))) {
        this.setProperties({
          _startValueInternal: startValue,
          _valueInvalid: false
        })
        this.onChange({
          end: _endValueInternal,
          start: startValue
        })
      } else {
        this.setProperties({
          _startValueInternal: startValue,
          _valueInvalid: true
        })
      }
    }
  }
})
<|endoftext|>


<commit_before>/**
 * ownCloud - sensorlogger
 *
 * This file is licensed under the Affero General Public License version 3 or
 * later. See the COPYING file.
 *
 * @author ELExG <elexgspot@gmail.com>
 * @copyright ELExG 2017
 */

(function ($, OC) {

	OCA.SensorLogger = OCA.SensorLogger || {};

	OCA.SensorLogger.Filter = {
		filter: undefined,
		$navigation: $('#app-navigation'),

		_onPopState: function(params) {
			params = _.extend({
				filter: 'all'
			}, params);

			this.setFilter(params.filter);
		},

		setFilter: function (filter) {
			if (filter === this.filter) {
				return;
			}
		}
	};

	$(document).ready(function () {
		var sidebar = $('#app-sidebar');

		var _onClickAction = function(event) {
			var $target = $(event.target);
			if (!$target.hasClass('menuItem')) {
				$target = $target.closest('.menuItem');
			}
			event.preventDefault();
			$target.closest('ul').find('.menuItem.active').removeClass('active');
			$target.addClass('active');
			sidebar.hide();
		};

		$('#showList').click(function (e) {
			_onClickAction(e);
			var url = OC.generateUrl('/apps/sensorlogger/showList');
			$.post(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
			});
		});

		$('#showDashboard').click(function (e) {
			_onClickAction(e);
			var url = OC.generateUrl('/apps/sensorlogger/showDashboard');
			$.post(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
			});

		});

		$('#deviceList').click(function (e) {
			_onClickAction(e);
			var url = OC.generateUrl('/apps/sensorlogger/deviceList');
			$.post(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
			});

		});

		$('#deviceTypeList').click(function (e) {
			_onClickAction(e);
			var url = OC.generateUrl('/apps/sensorlogger/deviceTypeList');
			$.post(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
			});

		});

		$('#deviceGroupList').click(function (e) {
			_onClickAction(e);
			var url = OC.generateUrl('/apps/sensorlogger/deviceGroupList');
			$.post(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
			});

		});

		$('#dataTypeList').click(function (e) {
			_onClickAction(e);
			var url = OC.generateUrl('/apps/sensorlogger/dataTypeList');
			$.post(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
			});

		});

		$('#app-content-wrapper').on('click','.deviceChart',function (e) {
			sidebar.hide();
			var id = $(this).data('id');
			var url = OC.generateUrl('/apps/sensorlogger/deviceChart/'+id);
			$.get(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
				loadChart();
			});
		});

		$('#app-content-wrapper').on('click','.deviceListData',function (e) {
			sidebar.hide();
			var id = $(this).data('id');
			var url = OC.generateUrl('/apps/sensorlogger/showDeviceData/'+id);
			$.post(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
			});
		});

		$('#app-content-wrapper').on('click','.icon-close',function(e) {
			sidebar.hide();
		});

		$('#app-content-wrapper').on('click','.deviceEdit',function(e) {
			var target = $(e.target);
			if(e.target.nodeName != 'TD') {
				return;
			}

			if(sidebar.is(':visible')) {
				sidebar.hide();
				return;
			}

			var id = $(this).data('id');
			var url = OC.generateUrl('/apps/sensorlogger/showDeviceDetails/'+id);
			$.post(url).success(function (response) {
				$.fn.editable.defaults.mode = 'inline';

				var sidebarBody = sidebar.find('.body');
				var sidebarTitle = sidebar.find('.title')

				var updateUrl = OC.generateUrl('/apps/sensorlogger/updateDevice/'+id);
				var createDeviceTypeUrl = OC.generateUrl('/apps/sensorlogger/createDeviceType');
				var createDeviceGroupUrl = OC.generateUrl('/apps/sensorlogger/createDeviceGroup');

				var title = $('<a/>',{
					'id':'name',
					'href': '#',
					'data-type': 'text',
					'data-field': 'name',
					'data-pk': id,
					'data-url': updateUrl,
					'data-title': 'response.name',
					'text': response.deviceDetails.name
				}).editable();

				var groupSource = [];
				for (group in response.groups) {
					groupSource.push({
						value : response.groups[group].id,
						text: response.groups[group].device_group_name,
						id : response.types[group].id
					}
					);
				}

				var typeSource = [];
				for (type in response.types) {
					typeSource.push({
						value: response.types[type].id,
						text: response.types[type].device_type_name,
						id : response.types[type].id
					}
					);

				}

				var groupSelect = $('<a/>',{
					'id':'group_id',
					'href': '#',
					'data-type': 'select2',
					'data-field': 'group',
					'data-pk': id,
					'data-url': updateUrl,
					'data-title': response.deviceGroupName
				}).editable({
					value: response.deviceDetails.group,
					source: groupSource,
					select2: {
						multiple: false,
						data: groupSource,
						dropdownAutoWidth: true,
						initSelection: function(element, callback) {
							callback({ 'id': response.deviceDetails.group, 'text': response.deviceDetails.deviceGroupName })
						},
						createSearchChoice: function(term, data) {
							if ($(data).filter(
									function() {
										return this.text.localeCompare(term)===0;
									}).length===0) {
								return {id:'create_'+term, text:term};
							}
						}
					}
				});

				var groupParentSelect = $('<a/>',{
					'id':'group_parent_id',
					'href': '#',
					'data-type': 'select2',
					'data-field': 'group',
					'data-pk': id,
					'data-url': updateUrl,
					'data-title': response.deviceGroupParentName
				}).editable({
					value: response.deviceDetails.groupParent,
					source: groupSource,
					select2: {
						multiple: false,
						data: groupSource,
						dropdownAutoWidth: true,
						initSelection: function(element, callback) {
							callback({ 'id': response.deviceDetails.groupParent, 'text': response.deviceDetails.deviceGroupParentName })
						},
						createSearchChoice: function(term, data) {
							if ($(data).filter(
									function() {
										return this.text.localeCompare(term)===0;
									}).length===0) {
								return {id:'create_'+term, text:term};
							}
						}
					}
				});

				var typeSelect = $('<a/>',{
					'id':'type_id',
					'href': '#',
					'data-type': 'select2',
					'data-field': 'type',
					'data-pk': id,
					'data-url': updateUrl,
					'data-title': response.deviceTypeName
				}).editable({
					value: response.deviceDetails.type,
					source: typeSource,
					select2: {
						multiple: false,
						data: typeSource,
						dropdownAutoWidth: true,
						initSelection: function(element, callback) {
							callback({ 'id': response.deviceDetails.type, 'text': response.deviceDetails.deviceTypeName })
						},
						createSearchChoice: function(term, data) {
							if ($(data).filter(
									function() {
										return this.text.localeCompare(term)===0;
									}).length===0) {
								return {id:'create_'+term, text:term};
							}
						}
					}
				});

				var bodyDetailsContainer = sidebar.find('.tpl_bodyDetails').clone();
				bodyDetailsContainer.removeClass('tpl_bodyDetails').addClass('bodyDetails');

				sidebar.find('.bodyDetails').remove();

				var uuid = bodyDetailsContainer.clone().append('UUID: '+response.deviceDetails.uuid);
				var group = bodyDetailsContainer.clone().append(groupSelect);
				var groupParent = bodyDetailsContainer.clone().append(groupParentSelect);
				var type = bodyDetailsContainer.clone().append(typeSelect);

				sidebarTitle.empty().append(title);
				sidebarBody.append(uuid);
				sidebarBody.append(group);
				sidebarBody.append(groupParent);
				sidebarBody.append(type);

				$(type).on('select2-selecting',function(e){
					var string = e.object.id,
						substring = "create_";
					if(string.includes(substring)) {
						$.post(createDeviceTypeUrl, {'device_id':id,'device_type_name':e.object.text} )
							.success(function (response) {
								$(e.target).val(response.deviceTypeId);
								typeSource.push({
									value: response.deviceTypeId,
									text: e.object.text,
									id : response.deviceTypeId
								})
							});
					}
				});

				$(groupParent).on('select2-selecting',function(e){
					var string = e.object.id,
						substring = "create_";
					if(string.includes(substring)) {
						$.post(createDeviceGroupUrl, {'device_id':id,'device_group_name':e.object.text} )
							.success(function (response) {
								$(e.target).val(response.deviceGroupId);
								groupSource.push({
									value: response.deviceGroupId,
									text: e.object.text,
									id : response.deviceGroupId
								})
							});
					}
				});

				$(group).on('select2-selecting',function(e){
					var string = e.object.id,
						substring = "create_";
					if(string.includes(substring)) {
						$.post(createDeviceGroupUrl, {'device_id':id,'device_group_name':e.object.text} )
							.success(function (response) {
								$(e.target).val(response.deviceGroupId);
								groupSource.push({
									value: response.deviceGroupId,
									text: e.object.text,
									id : response.deviceGroupId
								})
							});
					}
				});
				sidebar.show();
			});
		});

	});

	var loadChart = function() {
		var plotArea = $('div#chart');
		var id = $(plotArea).data('id');
		var url = OC.generateUrl('/apps/sensorlogger/chartData/' + id);
		$.getJSON(url,"json").success(function(data) {
			var line1 = [];
			var line2 = [];

			try {
			$.each(data, function (index, item) {
				line1.push([item.created_at, parseFloat(item.temperature)])
				line2.push([item.created_at, parseFloat(item.humidity)])
			});
			var plot1 = $.jqplot("chart",[line1,line2],{
				//title: 'GRAPT TITLE',
				axes: {
					xaxis:{
						//label:"x axis",
						renderer:$.jqplot.DateAxisRenderer,
						tickRenderer: $.jqplot.CanvasAxisTickRenderer ,
						tickOptions:{formatString:'%H:%M:%S', angle: -45}
					},
					yaxis:{
						tickOptions:{
							formatString:'%.2f'
						}
					}
				},
				highlighter: {
					show: true,
					sizeAdjust: 7.5
				},
				series: [
					{
						yaxis: 'yaxis',
						tickInterval: 0.5,
						showMarker:false
						//markerOptions: {size: 2, style: "x"}
					},{
						yaxis: 'y2axis',
						showMarker:false,
						tickInterval: 1,
						//markerOptions: {style:"circle"}
					},
					{yaxis: 'yaxis'},
					{yaxis: 'y2axis'}
				]
			});
			} catch (err) {
				$(plotArea).html(err);
			}
		});
	}

})(jQuery, OC);<commit_msg>Fix bug in groupSelect<commit_after>/**
 * ownCloud - sensorlogger
 *
 * This file is licensed under the Affero General Public License version 3 or
 * later. See the COPYING file.
 *
 * @author ELExG <elexgspot@gmail.com>
 * @copyright ELExG 2017
 */

(function ($, OC) {

	OCA.SensorLogger = OCA.SensorLogger || {};

	OCA.SensorLogger.Filter = {
		filter: undefined,
		$navigation: $('#app-navigation'),

		_onPopState: function(params) {
			params = _.extend({
				filter: 'all'
			}, params);

			this.setFilter(params.filter);
		},

		setFilter: function (filter) {
			if (filter === this.filter) {
				return;
			}
		}
	};

	$(document).ready(function () {
		var sidebar = $('#app-sidebar');

		var _onClickAction = function(event) {
			var $target = $(event.target);
			if (!$target.hasClass('menuItem')) {
				$target = $target.closest('.menuItem');
			}
			event.preventDefault();
			$target.closest('ul').find('.menuItem.active').removeClass('active');
			$target.addClass('active');
			sidebar.hide();
		};

		$('#showList').click(function (e) {
			_onClickAction(e);
			var url = OC.generateUrl('/apps/sensorlogger/showList');
			$.post(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
			});
		});

		$('#showDashboard').click(function (e) {
			_onClickAction(e);
			var url = OC.generateUrl('/apps/sensorlogger/showDashboard');
			$.post(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
			});

		});

		$('#deviceList').click(function (e) {
			_onClickAction(e);
			var url = OC.generateUrl('/apps/sensorlogger/deviceList');
			$.post(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
			});

		});

		$('#deviceTypeList').click(function (e) {
			_onClickAction(e);
			var url = OC.generateUrl('/apps/sensorlogger/deviceTypeList');
			$.post(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
			});

		});

		$('#deviceGroupList').click(function (e) {
			_onClickAction(e);
			var url = OC.generateUrl('/apps/sensorlogger/deviceGroupList');
			$.post(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
			});

		});

		$('#dataTypeList').click(function (e) {
			_onClickAction(e);
			var url = OC.generateUrl('/apps/sensorlogger/dataTypeList');
			$.post(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
			});

		});

		$('#app-content-wrapper').on('click','.deviceChart',function (e) {
			sidebar.hide();
			var id = $(this).data('id');
			var url = OC.generateUrl('/apps/sensorlogger/deviceChart/'+id);
			$.get(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
				loadChart();
			});
		});

		$('#app-content-wrapper').on('click','.deviceListData',function (e) {
			sidebar.hide();
			var id = $(this).data('id');
			var url = OC.generateUrl('/apps/sensorlogger/showDeviceData/'+id);
			$.post(url).success(function (response) {
				$('#app-content-wrapper').empty().append(response);
			});
		});

		$('#app-content-wrapper').on('click','.icon-close',function(e) {
			sidebar.hide();
		});

		$('#app-content-wrapper').on('click','.deviceEdit',function(e) {
			var target = $(e.target);
			if(e.target.nodeName != 'TD') {
				return;
			}

			if(sidebar.is(':visible')) {
				sidebar.hide();
				return;
			}

			var id = $(this).data('id');
			var url = OC.generateUrl('/apps/sensorlogger/showDeviceDetails/'+id);
			$.post(url).success(function (response) {
				$.fn.editable.defaults.mode = 'inline';

				var sidebarBody = sidebar.find('.body');
				var sidebarTitle = sidebar.find('.title')

				var updateUrl = OC.generateUrl('/apps/sensorlogger/updateDevice/'+id);
				var createDeviceTypeUrl = OC.generateUrl('/apps/sensorlogger/createDeviceType');
				var createDeviceGroupUrl = OC.generateUrl('/apps/sensorlogger/createDeviceGroup');

				var title = $('<a/>',{
					'id':'name',
					'href': '#',
					'data-type': 'text',
					'data-field': 'name',
					'data-pk': id,
					'data-url': updateUrl,
					'data-title': 'response.name',
					'text': response.deviceDetails.name
				}).editable();

				var groupSource = [];
				for (group in response.groups) {
					groupSource.push({
						value : response.groups[group].id,
						text: response.groups[group].device_group_name,
						id : response.groups[group].id
					}
					);
				}

				var typeSource = [];
				for (type in response.types) {
					typeSource.push({
						value: response.types[type].id,
						text: response.types[type].device_type_name,
						id : response.types[type].id
					}
					);

				}

				var groupSelect = $('<a/>',{
					'id':'group_id',
					'href': '#',
					'data-type': 'select2',
					'data-field': 'group',
					'data-pk': id,
					'data-url': updateUrl,
					'data-title': response.deviceGroupName
				}).editable({
					value: response.deviceDetails.group,
					source: groupSource,
					select2: {
						multiple: false,
						data: groupSource,
						dropdownAutoWidth: true,
						initSelection: function(element, callback) {
							callback({ 'id': response.deviceDetails.group, 'text': response.deviceDetails.deviceGroupName })
						},
						createSearchChoice: function(term, data) {
							if ($(data).filter(
									function() {
										return this.text.localeCompare(term)===0;
									}).length===0) {
								return {id:'create_'+term, text:term};
							}
						}
					}
				});

				var groupParentSelect = $('<a/>',{
					'id':'group_parent_id',
					'href': '#',
					'data-type': 'select2',
					'data-field': 'group',
					'data-pk': id,
					'data-url': updateUrl,
					'data-title': response.deviceGroupParentName
				}).editable({
					value: response.deviceDetails.groupParent,
					source: groupSource,
					select2: {
						multiple: false,
						data: groupSource,
						dropdownAutoWidth: true,
						initSelection: function(element, callback) {
							callback({ 'id': response.deviceDetails.groupParent, 'text': response.deviceDetails.deviceGroupParentName })
						},
						createSearchChoice: function(term, data) {
							if ($(data).filter(
									function() {
										return this.text.localeCompare(term)===0;
									}).length===0) {
								return {id:'create_'+term, text:term};
							}
						}
					}
				});

				var typeSelect = $('<a/>',{
					'id':'type_id',
					'href': '#',
					'data-type': 'select2',
					'data-field': 'type',
					'data-pk': id,
					'data-url': updateUrl,
					'data-title': response.deviceTypeName
				}).editable({
					value: response.deviceDetails.type,
					source: typeSource,
					select2: {
						multiple: false,
						data: typeSource,
						dropdownAutoWidth: true,
						initSelection: function(element, callback) {
							callback({ 'id': response.deviceDetails.type, 'text': response.deviceDetails.deviceTypeName })
						},
						createSearchChoice: function(term, data) {
							if ($(data).filter(
									function() {
										return this.text.localeCompare(term)===0;
									}).length===0) {
								return {id:'create_'+term, text:term};
							}
						}
					}
				});

				var bodyDetailsContainer = sidebar.find('.tpl_bodyDetails').clone();
				bodyDetailsContainer.removeClass('tpl_bodyDetails').addClass('bodyDetails');

				sidebar.find('.bodyDetails').remove();

				var uuid = bodyDetailsContainer.clone().append('UUID: '+response.deviceDetails.uuid);
				var group = bodyDetailsContainer.clone().append(groupSelect);
				var groupParent = bodyDetailsContainer.clone().append(groupParentSelect);
				var type = bodyDetailsContainer.clone().append(typeSelect);

				sidebarTitle.empty().append(title);
				sidebarBody.append(uuid);
				sidebarBody.append(group);
				sidebarBody.append(groupParent);
				sidebarBody.append(type);

				$(type).on('select2-selecting',function(e){
					var string = e.object.id,
						substring = "create_";
					if(string.includes(substring)) {
						$.post(createDeviceTypeUrl, {'device_id':id,'device_type_name':e.object.text} )
							.success(function (response) {
								$(e.target).val(response.deviceTypeId);
								typeSource.push({
									value: response.deviceTypeId,
									text: e.object.text,
									id : response.deviceTypeId
								})
							});
					}
				});

				$(groupParent).on('select2-selecting',function(e){
					var string = e.object.id,
						substring = "create_";
					if(string.includes(substring)) {
						$.post(createDeviceGroupUrl, {'device_id':id,'device_group_name':e.object.text} )
							.success(function (response) {
								$(e.target).val(response.deviceGroupId);
								groupSource.push({
									value: response.deviceGroupId,
									text: e.object.text,
									id : response.deviceGroupId
								})
							});
					}
				});

				$(group).on('select2-selecting',function(e){
					var string = e.object.id,
						substring = "create_";
					if(string.includes(substring)) {
						$.post(createDeviceGroupUrl, {'device_id':id,'device_group_name':e.object.text} )
							.success(function (response) {
								$(e.target).val(response.deviceGroupId);
								groupSource.push({
									value: response.deviceGroupId,
									text: e.object.text,
									id : response.deviceGroupId
								})
							});
					}
				});
				sidebar.show();
			});
		});

	});

	var loadChart = function() {
		var plotArea = $('div#chart');
		var id = $(plotArea).data('id');
		var url = OC.generateUrl('/apps/sensorlogger/chartData/' + id);
		$.getJSON(url,"json").success(function(data) {
			var line1 = [];
			var line2 = [];

			try {
			$.each(data, function (index, item) {
				line1.push([item.created_at, parseFloat(item.temperature)])
				line2.push([item.created_at, parseFloat(item.humidity)])
			});
			var plot1 = $.jqplot("chart",[line1,line2],{
				//title: 'GRAPT TITLE',
				axes: {
					xaxis:{
						//label:"x axis",
						renderer:$.jqplot.DateAxisRenderer,
						tickRenderer: $.jqplot.CanvasAxisTickRenderer ,
						tickOptions:{formatString:'%H:%M:%S', angle: -45}
					},
					yaxis:{
						tickOptions:{
							formatString:'%.2f'
						}
					}
				},
				highlighter: {
					show: true,
					sizeAdjust: 7.5
				},
				series: [
					{
						yaxis: 'yaxis',
						tickInterval: 0.5,
						showMarker:false
						//markerOptions: {size: 2, style: "x"}
					},{
						yaxis: 'y2axis',
						showMarker:false,
						tickInterval: 1,
						//markerOptions: {style:"circle"}
					},
					{yaxis: 'yaxis'},
					{yaxis: 'y2axis'}
				]
			});
			} catch (err) {
				$(plotArea).html(err);
			}
		});
	}

})(jQuery, OC);<|endoftext|>


<commit_before>/*
 * index.js: Top-level plugin exposing CLI features in flatiron
 *
 * (C) 2011, Nodejitsu Inc.
 * MIT LICENSE
 *
 */

var director = require('director'),
    optimist = require('optimist'),
    path = require('path');

//
// ### Name this plugin
//
exports.name = 'cli';

//
// ### function attach (options, done)
// #### @options {Object} Options for this plugin
// Initializes `this` (the application) with the core `cli` plugins consisting of:
// `argv`, `prompt`, `routing`, `commands` in that order.
//
exports.attach = function (options) {
  var app = this;
  options = options || {};

  //
  // Setup `this.argv` to use `optimist`.
  //
  exports.argv.call(this, options.argv);

  //
  // If `options.version` is truthy, `app.version` is defined and `-v` or
  // `--version` command line parameters were passed, print out `app.version`
  // and exit.
  //
  if (options.version && app.version && (this.argv.v || this.argv.version)) {
    console.log(app.version);
    process.exit(0);
  }

  //
  // Setup `this.prompt`.
  //
  exports.prompt.call(this, options.prompt);

  //
  // Setup `app.router` and associated core routing method.
  //
  app.cli    = {}
  app.router = new director.cli.Router().configure({
    async: app.async || options.async
  });

  app.start = function (options, callback) {
    if (!callback && typeof options === 'function') {
      callback = options;
      options = {};
    }

    callback = callback || function () {};
    app.init(options, function (err) {
      if (err) {
        return callback(err);
      }

      app.router.dispatch('on', app.argv._.join(' '), app.log, callback);
    });
  };

  app.cmd = function (path, handler) {
    app.router.on(path, handler);
  };

  exports.commands.call(this, options);
};

//
// ### function init (done)
// #### @done {function} Continuation to respond to when complete
// Initializes this plugin by setting `winston.cli` (i.e. `app.log.cli`)
// to enable colors and padded levels.
//
exports.init = function (done) {
  var app = this,
      logger;

  if (!app.log.help) {
    logger = app.log.get('default');
    logger.cli().extend(app.log);
  }

  if (app.config) {
    //
    // Create a literal store for argv to
    // avoid re-parsing CLI options.
    //
    app.config.use('argv', {
      type: 'literal',
      store: app.argv
    });

    app.config.env();
  }

  done();
};

//
// ### function argv (options)
// #### @options {Object} Pass-thru options for optimist
// Sets up `app.argv` using `optimist` and the specified options.
//
exports.argv = function (options) {
  var optimist;

  if (options && Object.keys(options).length) {
    optimist = require('optimist').options(options);
    this.help = optimist.help;
    this.argv = optimist.argv;
  }
  else {
    optimist = require('optimist');
    this.help = optimist.help;
    this.argv = optimist.argv;
  }
};

//
// ### function commands (options)
// #### @
//
exports.commands = function (options) {
  var app = this;

  function showUsage(target) {
    target = Array.isArray(target) ? target : target.split('\n');
    target.forEach(function (line) {
      app.log.help(line);
    });

    app.log.help('');
    app.help().split('\n').forEach(function (line) {
      app.log.help(line);
    });
  }

  //
  // Setup any pass-thru options to the
  // application instance but make them lazy
  //
  app.usage = options.usage;
  app.cli.dir = options.dir;
  app.commands = {};

  //
  // Helper function which loads the file for the
  // specified `name` into `app.commands`.
  //
  function loadCommand(name, silent) {
    if (app.cli.dir) {
      if (app.commands[name]) {
        return;
      }
      try {
        command = app.commands[name] = require(path.join(app.cli.dir, name));
        return true;
      }
      catch (err) {
        // If that file could not be found, error message should start with
        // "Cannot find module" and contain the name of the file we tried requiring.
        if (!err.message.match(/^Cannot find module/) || err.message.indexOf(name) === -1) {
          throw err;
        }

        if (!silent) {
          showUsage(app.usage || [
            'Cannot find commands for ' + name.magenta
          ]);
        }

        return false;
      }
    }
  }

  //
  // Helper function which executes the command
  // represented by the Array of `parts` passing
  // control to the `callback`.
  //
  function executeCommand(parts, callback) {
    if (app.cli.dir) {
      var name = parts.shift(),
          command,
          usage;

      if (!loadCommand(name)) {
        return callback();
      }

      command = app.commands[name];
      while (command) {
        usage = command.usage;

        if (!app.argv.h && !app.argv.help && typeof command === 'function') {
          while (parts.length + 1 < command.length) {
            parts.push(null);
          }

          command.apply(this, parts.concat(callback));
          return;
        }

        command = command[parts.shift()];
      }

      //
      // Since we have not resolved a needle, try and print out a usage message
      //
      if (usage || options.usage) {
        showUsage(usage || options.usage)
      }
    }
    else if (app.usage) {
      //
      // If there's no directory we're supposed to search for modules, simply
      // print out usage notice if it's provided.
      //
      showUsage(options.usage);
    }
  }

  //
  // Allow commands to be aliased to subcomponents. e.g.
  //
  //    app.alias('list', { resource: 'apps', command: 'list' });
  //
  app.alias = function (target, source) {
    app.commands.__defineGetter__(target, function () {
      loadCommand(source.resource, true);
      var resource = app.commands[source.resource];

      if (resource) {
        return resource[source.command];
      }
    });
  };

  //
  // Set the `loadCommand` function to run
  // whenever the router has not matched
  // the CLI arguments, `process.argv`.
  //
  app.router.notfound = function (callback) {
    executeCommand(app.argv._.slice(), callback);
  };
};

exports.prompt = function (options) {
  options = options || {};

  this.__defineGetter__('prompt', function () {
    if (!this._prompt) {
      //
      // Pass-thru any prompt specific options that are supplied.
      //
      var prompt = require('prompt'),
          self = this;

      prompt.allowEmpty = options.allowEmpty || prompt.allowEmpty;
      prompt.message    = options.message    || prompt.message;
      prompt.delimiter  = options.delimiter  || prompt.delimiter;
      prompt.properties = options.properties || prompt.properties;

      //
      // Hoist up any prompt specific events and re-emit them as
      // `prompt::*` events.
      //
      ['start', 'pause', 'resume', 'prompt', 'invalid'].forEach(function (ev) {
        prompt.on(ev, function () {
          var args = Array.prototype.slice.call(arguments);
          self.emit.apply(self, [['prompt', ev]].concat(args));
        });
      });

      //
      // Extend `this` (the application) with prompt functionality
      // and open `stdin`.
      //
      this._prompt = prompt;
      this._prompt.start().pause();
    }

    return this._prompt;
  });
};
<commit_msg>[fix] Only check indexOf name in error on lazy-loaded commands if name exists<commit_after>/*
 * index.js: Top-level plugin exposing CLI features in flatiron
 *
 * (C) 2011, Nodejitsu Inc.
 * MIT LICENSE
 *
 */

var director = require('director'),
    optimist = require('optimist'),
    path = require('path');

//
// ### Name this plugin
//
exports.name = 'cli';

//
// ### function attach (options, done)
// #### @options {Object} Options for this plugin
// Initializes `this` (the application) with the core `cli` plugins consisting of:
// `argv`, `prompt`, `routing`, `commands` in that order.
//
exports.attach = function (options) {
  var app = this;
  options = options || {};

  //
  // Setup `this.argv` to use `optimist`.
  //
  exports.argv.call(this, options.argv);

  //
  // If `options.version` is truthy, `app.version` is defined and `-v` or
  // `--version` command line parameters were passed, print out `app.version`
  // and exit.
  //
  if (options.version && app.version && (this.argv.v || this.argv.version)) {
    console.log(app.version);
    process.exit(0);
  }

  //
  // Setup `this.prompt`.
  //
  exports.prompt.call(this, options.prompt);

  //
  // Setup `app.router` and associated core routing method.
  //
  app.cli    = {}
  app.router = new director.cli.Router().configure({
    async: app.async || options.async
  });

  app.start = function (options, callback) {
    if (!callback && typeof options === 'function') {
      callback = options;
      options = {};
    }

    callback = callback || function () {};
    app.init(options, function (err) {
      if (err) {
        return callback(err);
      }

      app.router.dispatch('on', app.argv._.join(' '), app.log, callback);
    });
  };

  app.cmd = function (path, handler) {
    app.router.on(path, handler);
  };

  exports.commands.call(this, options);
};

//
// ### function init (done)
// #### @done {function} Continuation to respond to when complete
// Initializes this plugin by setting `winston.cli` (i.e. `app.log.cli`)
// to enable colors and padded levels.
//
exports.init = function (done) {
  var app = this,
      logger;

  if (!app.log.help) {
    logger = app.log.get('default');
    logger.cli().extend(app.log);
  }

  if (app.config) {
    //
    // Create a literal store for argv to
    // avoid re-parsing CLI options.
    //
    app.config.use('argv', {
      type: 'literal',
      store: app.argv
    });

    app.config.env();
  }

  done();
};

//
// ### function argv (options)
// #### @options {Object} Pass-thru options for optimist
// Sets up `app.argv` using `optimist` and the specified options.
//
exports.argv = function (options) {
  var optimist;

  if (options && Object.keys(options).length) {
    optimist = require('optimist').options(options);
    this.help = optimist.help;
    this.argv = optimist.argv;
  }
  else {
    optimist = require('optimist');
    this.help = optimist.help;
    this.argv = optimist.argv;
  }
};

//
// ### function commands (options)
// #### @
//
exports.commands = function (options) {
  var app = this;

  function showUsage(target) {
    target = Array.isArray(target) ? target : target.split('\n');
    target.forEach(function (line) {
      app.log.help(line);
    });

    app.log.help('');
    app.help().split('\n').forEach(function (line) {
      app.log.help(line);
    });
  }

  //
  // Setup any pass-thru options to the
  // application instance but make them lazy
  //
  app.usage = options.usage;
  app.cli.dir = options.dir;
  app.commands = {};

  //
  // Helper function which loads the file for the
  // specified `name` into `app.commands`.
  //
  function loadCommand(name, silent) {
    if (app.cli.dir) {
      if (app.commands[name]) {
        return;
      }
      try {
        command = app.commands[name] = require(path.join(app.cli.dir, name));
        return true;
      }
      catch (err) {
        // If that file could not be found, error message should start with
        // "Cannot find module" and contain the name of the file we tried requiring.
        if (!err.message.match(/^Cannot find module/) || (name && err.message.indexOf(name) === -1)) {
          throw err;
        }

        if (!silent) {
          showUsage(app.usage || [
            'Cannot find commands for ' + name.magenta
          ]);
        }

        return false;
      }
    }
  }

  //
  // Helper function which executes the command
  // represented by the Array of `parts` passing
  // control to the `callback`.
  //
  function executeCommand(parts, callback) {
    if (app.cli.dir) {
      var name = parts.shift(),
          command,
          usage;

      if (!loadCommand(name)) {
        return callback();
      }

      command = app.commands[name];
      while (command) {
        usage = command.usage;

        if (!app.argv.h && !app.argv.help && typeof command === 'function') {
          while (parts.length + 1 < command.length) {
            parts.push(null);
          }

          command.apply(this, parts.concat(callback));
          return;
        }

        command = command[parts.shift()];
      }

      //
      // Since we have not resolved a needle, try and print out a usage message
      //
      if (usage || options.usage) {
        showUsage(usage || options.usage)
      }
    }
    else if (app.usage) {
      //
      // If there's no directory we're supposed to search for modules, simply
      // print out usage notice if it's provided.
      //
      showUsage(options.usage);
    }
  }

  //
  // Allow commands to be aliased to subcomponents. e.g.
  //
  //    app.alias('list', { resource: 'apps', command: 'list' });
  //
  app.alias = function (target, source) {
    app.commands.__defineGetter__(target, function () {
      loadCommand(source.resource, true);
      var resource = app.commands[source.resource];

      if (resource) {
        return resource[source.command];
      }
    });
  };

  //
  // Set the `loadCommand` function to run
  // whenever the router has not matched
  // the CLI arguments, `process.argv`.
  //
  app.router.notfound = function (callback) {
    executeCommand(app.argv._.slice(), callback);
  };
};

exports.prompt = function (options) {
  options = options || {};

  this.__defineGetter__('prompt', function () {
    if (!this._prompt) {
      //
      // Pass-thru any prompt specific options that are supplied.
      //
      var prompt = require('prompt'),
          self = this;

      prompt.allowEmpty = options.allowEmpty || prompt.allowEmpty;
      prompt.message    = options.message    || prompt.message;
      prompt.delimiter  = options.delimiter  || prompt.delimiter;
      prompt.properties = options.properties || prompt.properties;

      //
      // Hoist up any prompt specific events and re-emit them as
      // `prompt::*` events.
      //
      ['start', 'pause', 'resume', 'prompt', 'invalid'].forEach(function (ev) {
        prompt.on(ev, function () {
          var args = Array.prototype.slice.call(arguments);
          self.emit.apply(self, [['prompt', ev]].concat(args));
        });
      });

      //
      // Extend `this` (the application) with prompt functionality
      // and open `stdin`.
      //
      this._prompt = prompt;
      this._prompt.start().pause();
    }

    return this._prompt;
  });
};
<|endoftext|>


<commit_before>var _ = require('underscore');
var print = console.log;

module.exports.quizme = function(list, count){
    if(!count) count = list.length;

    quizzes  = _.shuffle(list).slice(0,count);

    process.stdin.resume();
    process.stdin.setEncoding('utf8');
    var i = 0,
        mistakes = [];

    var quiz = function(){
	print(quizzes[i].en + ' :');
    }

    quiz();

    var congrat = function(){
	print('You made it!');
    }

    var relent = function(){
	print('I am sorry...');
    }

    var reachedEnd = function(){
	return i >= count;
    }

    var giveHint = function(){
	print(quizzes[i].fi);
    }

    var addMistake = function(word){
	mistakes.push(word);
    }

    process.stdin.on('data', function(chunk) {
	if(chunk.trim() == 'hint'){
	    giveHint();
	    addMistake(quizzes[i]);
	}
	else if(chunk.trim() == 'skip'){
	    addMistake(quizzes[i]);
	    i++;

	    if(reachedEnd()) {
		process.stdin.pause();
		print(mistakes);
		return;
	    }

	    quiz();
	}
	else if(quizzes[i].fi === chunk.trim()) {
	    congrat();
	    i++;

	    if(reachedEnd()) {
		process.stdin.pause();
		print(mistakes);
		return;
	    }

	    quiz();
	}
	else{
	    relent();
	}
    });

}
<commit_msg>new feature: mistakened words will be reexamined.<commit_after>var _ = require('underscore');
var print = console.log;

function quizme(list, count){
    if(!count) count = list.length;

    quizzes  = _.shuffle(list).slice(0,count);

    process.stdin.resume();
    process.stdin.setEncoding('utf8');

    var i = 0, mistakes = [];

    var quiz = function(){
	print(quizzes[i].en + ' :');
    }

    quiz();

    var congrat = function(){
	print('You made it!');
    }

    var relent = function(){
	print('I am sorry...');
    }

    var reachedEnd = function(){
	return i >= count;
    }

    var giveHint = function(){
	print(quizzes[i].fi);
    }

    var addMistake = function(word){
	mistakes.push(word);
    }

    var quizer = function(chunk) {
	if(chunk.trim() == 'hint'){
	    giveHint();
	    addMistake(quizzes[i]);
	}
	else if(chunk.trim() == 'skip'){

	    addMistake(quizzes[i]);
	    i++;

	    if(reachedEnd()) {
		process.stdin.pause();
		print(mistakes);

		if(mistakes.length > 0){
		    print('please fix the mistaken ones...')
		    process.stdin.removeAllListeners('data')
		    module.exports.quizme(mistakes)
		}
		return;
	    }

	    quiz();

	}
	else if(quizzes[i].fi === chunk.trim()) {
	    congrat();
	    i++;

	    if(reachedEnd()) {
		process.stdin.pause();
		print(mistakes);

		if(mistakes.length > 0){
		    print('please fix the mistaken ones...')
		    process.stdin.removeAllListeners('data')
		    module.exports.quizme(mistakes)
		}
		return;
	    }

	    quiz();
	}
	else{
	    relent();
	}
    }

    process.stdin.on('data', quizer);

}

module.exports.quizme = quizme
<|endoftext|>


<commit_before>// ==UserScript==
// @name        FUT Show Futbin player price
// @version     0.1.1
// @description Show the Futbin prices for players in the Search Results and Club Search
// @license     MIT
// @author      Tim Klingeleers
// @match       https://www.easports.com/fifa/ultimate-team/web-app/*
// @namespace   https://github.com/Mardaneus86
// @grant       GM_xmlhttpRequest
// @connect     *
// @updateURL   https://raw.githubusercontent.com/Mardaneus86/futwebapp-tampermonkey/master/show-futbin-player-price.user.js
// @downloadURL https://raw.githubusercontent.com/Mardaneus86/futwebapp-tampermonkey/master/show-futbin-player-price.user.js
// @supportURL  https://github.com/Mardaneus86/futwebapp-tampermonkey/issues
// ==/UserScript==
(function() {
  'use strict';

  $(document).bind('DOMNodeInserted', function(event) {
    if ($(event.target).hasClass("listFUTItem")) {
      // Get the player ID from the attached player image
      var playerImageUrl = $(event.target).find('.photo').attr('src');
      var playerId = playerImageUrl.substr(playerImageUrl.lastIndexOf('/') + 1).replace('.png', '');

      var futbinUrl = "https://www.futbin.com/18/playerPrices?player=" + playerId;

      var ret = GM_xmlhttpRequest({
        method: "GET",
        url: futbinUrl,
        onload: function(res) {
            console.log(res);
            var data = JSON.parse(res.response);
            console.log(futbinUrl, data[playerId].prices.ps);

            var target = null;
            if ($(event.target).parents('#MyClubSearch')) {
                $(".secondary.player-stats-data-component").css('float', 'left');
                target = $(event.target).find('.entityContainer');
                target.append('
Futbin BIN' + data[playerId].prices.ps.LCPrice + '
');
            } else if($(event.target).parents('.SearchResults')) {
                target = $(event.target).find('.auctionValue').parent();
                target.prepend('
Futbin BIN' + data[playerId].prices.ps.LCPrice + '
');
            }
        }
      });
    }
  });
})();<commit_msg>chore: remove verbose logging<commit_after>// ==UserScript==
// @name        FUT Show Futbin player price
// @version     0.1.1
// @description Show the Futbin prices for players in the Search Results and Club Search
// @license     MIT
// @author      Tim Klingeleers
// @match       https://www.easports.com/fifa/ultimate-team/web-app/*
// @namespace   https://github.com/Mardaneus86
// @grant       GM_xmlhttpRequest
// @connect     *
// @updateURL   https://raw.githubusercontent.com/Mardaneus86/futwebapp-tampermonkey/master/show-futbin-player-price.user.js
// @downloadURL https://raw.githubusercontent.com/Mardaneus86/futwebapp-tampermonkey/master/show-futbin-player-price.user.js
// @supportURL  https://github.com/Mardaneus86/futwebapp-tampermonkey/issues
// ==/UserScript==
(function() {
  'use strict';

  $(document).bind('DOMNodeInserted', function(event) {
    if ($(event.target).hasClass("listFUTItem")) {
      // Get the player ID from the attached player image
      var playerImageUrl = $(event.target).find('.photo').attr('src');
      var playerId = playerImageUrl.substr(playerImageUrl.lastIndexOf('/') + 1).replace('.png', '');

      var futbinUrl = "https://www.futbin.com/18/playerPrices?player=" + playerId;

      var ret = GM_xmlhttpRequest({
        method: "GET",
        url: futbinUrl,
        onload: function(res) {
            var data = JSON.parse(res.response);

            var target = null;
            if ($(event.target).parents('#MyClubSearch')) {
                $(".secondary.player-stats-data-component").css('float', 'left');
                target = $(event.target).find('.entityContainer');
                target.append('
Futbin BIN' + data[playerId].prices.ps.LCPrice + '
');
            } else if($(event.target).parents('.SearchResults')) {
                target = $(event.target).find('.auctionValue').parent();
                target.prepend('
Futbin BIN' + data[playerId].prices.ps.LCPrice + '
');
            }
        }
      });
    }
  });
})();<|endoftext|>


<commit_before>/*global React*/

var cachedFetch = require("./cachedfetch.js");
var dispatcher = require("./dispatcher.js");

var LeaderCountryRow = React.createClass({
  handleClick: function (e) {
    e.preventDefault();
    dispatcher.fire("updateSelection", {
      iso2: this.props.rank.country ? this.props.rank.country.iso2 : "",
      offset: Math.floor((this.props.rank.rank - 1) / 10) * 10,
      highlight: this.props.selection.profile
    });
  },

  render: function () {
    var countryName = this.props.rank.country != null ? this.props.rank.country.name : "All Countries";

    return (

        {this.props.rank.rank}
        {countryName}
        {this.props.rank.observations}

    );
  }
});

var LeaderProfile = React.createClass({
  getInitialState: function () {
    return {
      profile: {
        ranks: []
      }
    };
  },

  componentDidMount: function () {
    var profileKey = "profile:" + this.props.selection.profile;
    cachedFetch.get(profileKey).then((profile) => {
      this.setState({profile: profile});
    });
  },

  render: function () {
    return (

{this.state.profile.name}

              Rank
              Region
              Contributions

            {this.state.profile.ranks.map((rank) => {
              return (
                <LeaderCountryRow
                  key={this.props.selection.profile + rank.observations}
                  selection={this.props.selection}
                  rank={rank}
                />
              );
            })}

    );
  }
});

module.exports = {
  LeaderProfile: LeaderProfile
};
<commit_msg>'All Countries' not appearing for contributions to one country #263<commit_after>/*global React*/

var cachedFetch = require("./cachedfetch.js");
var dispatcher = require("./dispatcher.js");

var LeaderCountryRow = React.createClass({
  handleClick: function (e) {
    e.preventDefault();
    dispatcher.fire("updateSelection", {
      iso2: this.props.rank.country ? this.props.rank.country.iso2 : "",
      offset: Math.floor((this.props.rank.rank - 1) / 10) * 10,
      highlight: this.props.selection.profile
    });
  },

  render: function () {
    var countryName = this.props.rank.country != null ? this.props.rank.country.name : "All Countries";

    return (

        {this.props.rank.rank}
        {countryName}
        {this.props.rank.observations}

    );
  }
});

var LeaderProfile = React.createClass({
  getInitialState: function () {
    return {
      profile: {
        ranks: []
      }
    };
  },

  componentDidMount: function () {
    var profileKey = "profile:" + this.props.selection.profile;
    cachedFetch.get(profileKey).then((profile) => {
      this.setState({profile: profile});
    });
  },

  render: function () {
    return (

{this.state.profile.name}

              Rank
              Region
              Contributions

            {this.state.profile.ranks.map((rank) => {
              return (
                <LeaderCountryRow
                  key={this.props.selection.profile + rank.country}
                  selection={this.props.selection}
                  rank={rank}
                />
              );
            })}

    );
  }
});

module.exports = {
  LeaderProfile: LeaderProfile
};
<|endoftext|>


<commit_before>/**
 * This is the Ethereum interface that is exposed to the WASM instance which
 * enables to interact with the Ethereum Environment
 */
const constants = require('./constants.js')

// The interface exposed to the WebAessembly Core
module.exports = class Interface {
  constructor (environment) {
    this.environment = environment
  }

  get exportTable () {
    let exportMethods = [
      // include all the public methods according to the Ethereum Environment Interface (EEI)
      // FIXME: this currently doesn't match EEI r0
      'useGas',
      'gas',
      'address',
      'balance',
      'origin',
      'caller',
      'callValue',
      'callDataSize',
      'callDataCopy',
      'codeSize',
      'codeCopy',
      'extCodeSize',
      'extCodeCopy',
      'gasPrice',
      'blockHash',
      'coinbase',
      'timestamp',
      'number',
      'difficulty',
      'gasLimit',
      'log',
      'create',
      'call',
      'callDelegate',
      'sstore',
      'sload',
      'return',
      'suicide'
    ]
    let ret = {}
    exportMethods.forEach((method) => {
      ret[method] = this[method].bind(this)
    })
    return ret
  }

  setModule (mod) {
    this.module = mod
  }

  /**
   * Subtracts an amount to the gas counter
   * @param {integer} amount the amount to subtract to the gas counter
   */
  useGas (amount) {
    if (amount > 0) {
      if (this.environment.gasLimit < amount) {
        throw new Error('Ran out of gas')
      }
      this.environment.gasLimit -= amount
    }
  }

  /**
   * Returns the current amount of gas
   * @return {integer}
   */
  gas () {
    return this.environment.gasLimit
  }

  /**
   * Gets address of currently executing account and loads it into memory at
   * the given offset.
   * @param {integer} offset
   */
  address (offset) {
    this.setMemory(offset, constants.ADDRESS_SIZE_BYTES, this.environment.address)
  }

  /**
   * Gets balance of the given account and loads it into memory at the given
   * offset.
   * @param {integer} addressOffset the memory offset to laod the address
   * @param {integer} resultOffset
   */
  balance (addressOffset, offset) {
    const address = this.getMemory(addressOffset, constants.ADDRESS_SIZE_BYTES)
    // call the parent contract and ask for the balance of one of its child contracts
    const balance = this.environment.parent.environment.getBalance(address)
    this.setMemory(offset, constants.BALANCE_SIZE_BYTES, balance)
  }

  /**
   * Gets the execution's origination address and loads it into memory at the
   * given offset. This is the sender of original transaction; it is never an
   * account with non-empty associated code.
   * @param {integer} offset
   */
  origin (offset) {
    this.setMemory(offset, constants.ADDRESS_SIZE_BYTES, this.environment.origin)
  }

  /**
   * Gets caller address and loads it into memory at the given offset. This is
   * the address of the account that is directly responsible for this execution.
   * @param {integer} offset
   */
  caller (offset) {
    this.setMemory(offset, constants.ADDRESS_SIZE_BYTES, this.environment.caller)
  }

  /**
   * Gets the deposited value by the instruction/transaction responsible for
   * this execution and loads it into memory at the given location.
   * @param {integer} offset
   */
  callValue (offset) {
    this.setMemory(offset, constants.BALANCE_SIZE_BYTES, this.environment.callValue.toBuffer())
  }

  /**
   * Get size of input data in current environment. This pertains to the input
   * data passed with the message call instruction or transaction.
   * @return {integer}
   */
  callDataSize () {
    return this.environment.callData.length
  }

  /**
   * Copys the input data in current environment to memory. This pertains to
   * the input data passed with the message call instruction or transaction.
   * @param {integer} offset the offset in memory to load into
   * @param {integer} dataOffset the offset in the input data
   * @param {integer} length the length of data to copy
   */
  callDataCopy (offset, dataOffset, length) {
    const callData = Buffer.from(this.environment.callData.slice(dataOffset, dataOffset + length)).reverse()
    this.setMemory(offset, length, callData)
  }

  /**
   * Gets the size of code running in current environment.
   * @return {interger}
   */
  codeSize () {
    return this.environment.code.length
  }

  /**
   * Copys the code running in current environment to memory.
   * @param {integer} offset the memory offset
   * @param {integer} codeOffset the code offset
   * @param {integer} length the length of code to copy
   */
  codeCopy (offset, codeOffset, length) {
    const code = new Uint8Array(this.environment.code, codeOffset, length)
    this.setMemory(offset, length, code)
  }

  /**
   * Get size of an account’s code.
   * @param {integer} addressOffset the offset in memory to load the address from
   * @return {integer}
   */
  extCodeSize (addressOffset) {
    const address = this.getMemory(addressOffset, constants.ADDRESS_SIZE_BYTES)
    const code = this.environment.getCode(address)
    return code.length
  }

  /**
   * Copys the code of an account to memory.
   * @param {integer} addressOffset the memory offset of the address
   * @param {integer} offset the memory offset
   * @param {integer} codeOffset the code offset
   * @param {integer} length the length of code to copy
   */
  extCodeCopy (addressOffset, offset, codeOffset, length) {
    const address = this.getMemory(addressOffset, constants.ADDRESS_SIZE_BYTES)
    let code = this.environment.getCode(address)
   code = new Uint8Array(code, codeOffset, length)
    this.setMemory(offset, length, code)
  }

  /**
   * Gets price of gas in current environment.
   * @return {integer}
   */
  gasPrice () {
    return this.environment.gasPrice
  }

  /**
   * Gets the hash of one of the 256 most recent complete blocks.
   * @param {integer} number which block to load
   * @param {integer} offset the offset to load the hash into
   */
  blockHash (number, offset) {
    const hash = this.environment.getBlockHash(number)
    this.setMemory(offset, 32, hash)
  }

  /**
   * Gets the block’s beneficiary address and loads into memory.
   * @param offset
   */
  coinbase (offset) {
    this.setMemory(offset, constants.ADDRESS_SIZE_BYTES, this.environment.coinbase)
  }

  /**
   * Get the block’s timestamp.
   * @return {integer}
   */
  timestamp () {
    return this.environment.timestamp
  }

  /**
   * Get the block’s number.
   * @return {integer}
   */
  number () {
    return this.environment.number
  }

  /**
   * Get the block’s difficulty.
   * @return {integer}
   */
  difficulty () {
    return this.environment.difficulty
  }

  /**
   * Get the block’s gas limit.
   * @return {integer}
   */
  gasLimit () {
    return this.environment.gasLimit
  }

  /**
   * Creates a new log in the current environment
   * @param {integer} dataOffset the offset in memory to load the memory
   * @param {integer} length the data length
   * TODO: replace with variadic
   */
  log (dataOffset, length, topic1, topic2, topic3, topic4, topic5) {
    const data = this.getMemory(dataOffset, length)
    this.environment.logs.push({
      data: data,
      topics: [topic1, topic2, topic3, topic4, topic5]
    })
  }

  /**
   * Creates a new contract with a given value.
   * @param {integer} valueOffset the offset in memory to the value from
   * @param {integer} dataOffset the offset to load the code for the new contract from
   * @param {integer} length the data length
   */
  create (valueOffset, dataOffset, length) {
    const value = this.getMemory(valueOffset, constants.BALANCE_SIZE_BYTES)
    const data = this.getMemory(dataOffset, length)
    const result = this.environment.create(value, data)
    return result
  }

  /**
   * Sends a message with arbiatary data to a given address path
   * @param {integer} addressOffset the offset to load the address path from
   * @param {integer} valueOffset the offset to load the value from
   * @param {integer} dataOffset the offset to load data from
   * @param {integer} dataLength the length of data
   * @param {integer} resultOffset the offset to store the result data at
   * @param {integer} resultLength
   * @param {integer} gas
   * @return {integer} Returns 1 or 0 depending on if the VM trapped on the message or not
   * TODO: add proper gas counting
   */
  call (addressOffset, valueOffset, dataOffset, dataLength, resultOffset, resultLength, gas) {
    if (gas === undefined) {
      gas = this.gasLeft()
    }
    // Load the params from mem
    const address = this.getMemory(addressOffset, constants.ADDRESS_SIZE_BYTES)
    const value = this.getMemory(valueOffset, constants.BALANCE_SIZE_BYTES)
    const data = this.getMemory(dataOffset, dataLength)
    // Run the call
    const [result, errorCode] = this.environment.call(gas, address, value, data)
    this.setMemory(resultOffset, resultLength, result)
    return errorCode
  }

  /**
   * Message-call into this account with an alternative account’s code, but
   * persisting the current values for sender and value.
   * @param {integer} gas
   * @param {integer} addressOffset the offset to load the address path from
   * @param {integer} valueOffset the offset to load the value from
   * @param {integer} dataOffset the offset to load data from
   * @param {integer} dataLength the length of data
   * @param {integer} resultOffset the offset to store the result data at
   * @param {integer} resultLength
   * @return {integer} Returns 1 or 0 depending on if the VM trapped on the message or not
   */
  callDelegate (gas, addressOffset, dataOffset, dataLength, resultOffset, resultLength) {
    const data = this.getMemory(dataOffset, dataLength)
    const address = this.getMemory(addressOffset, constants.ADDRESS_SIZE_BYTES)
    const [result, errorCode] = this.environment.callDelegate(gas, address, data)
    this.setMemory(resultOffset, resultLength, result)
    return errorCode
  }

  /**
   * store a value at a given path in long term storage which are both loaded
   * from Memory
   * @param {interger} pathOffest the memory offset to load the the path from
   * @param {interger} valueOffset the memory offset to load the value from
   */
  sstore (pathOffset, valueOffset) {
    const path = new Buffer(this.getMemory(pathOffset, 32)).toString('hex')
    // copy the value
    const value = this.getMemory(valueOffset, 32).slice(0)
    const oldValue = this.environment.state.get(path)
    const valIsZero = value.every((i) => i === 0)

    // write
    if (!valIsZero && !oldValue) {
      this.environment.gasLimit -= 15000
    }

    // delete
    if (valIsZero && oldValue) {
      this.environment.gasRefund += 15000
      this.environment.state.delete(path)
    } else {
      this.environment.state.set(path, value)
    }
  }

  /**
   * reterives a value at a given path in long term storage
   * @param {interger} pathOffest the memory offset to load the the path from
   * @param {interger} resultOffset the memory offset to load the value from
   */
  sload (pathOffset, resultOffset) {
    const path = new Buffer(this.getMemory(pathOffset, 32)).toString('hex')
    const result = this.environment.state.get(path)
    this.setMemory(resultOffset, 32, result)
  }

  /**
   * Halt execution returning output data.
   * @param {integer} offset the offset of the output data.
   * @param {integer} length the length of the output data.
   */
  return (offset, length) {
    this.environment.returnValue = this.getMemory(offset, length)
  }

  /**
   * Halt execution and register account for later deletion giving the remaining
   * balance to an address path
   * @param {integer} offset the offset to load the address from
   */
  suicide (addressOffset) {
    this.environment.suicideAddress = this.getMemory(addressOffset, constants.ADDRESS_SIZE_BYTES)
  }

  getMemory (offset, length) {
    return new Uint8Array(this.module.exports.memory, offset, length)
  }

  setMemory (offset, length, value) {
    const memory = new Uint8Array(this.module.exports.memory, offset, length)
    memory.set(value)
  }
}

//
// Polyfill required unless this is sorted: https://bugs.chromium.org/p/chromium/issues/detail?id=633895
//
// Polyfill from: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
//
Function.prototype.bind = function (oThis) { // eslint-disable-line
  if (typeof this !== 'function') {
    // closest thing possible to the ECMAScript 5
    // internal IsCallable function
    throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable')
  }

  var aArgs = Array.prototype.slice.call(arguments, 1)
  var fToBind = this
  var fNOP = function () {}
  var fBound = function () {
    return fToBind.apply(this instanceof fNOP ? this : oThis,
     aArgs.concat(Array.prototype.slice.call(arguments)))
  }

  if (this.prototype) {
    // Function.prototype doesn't have a prototype property
    fNOP.prototype = this.prototype
  }

  fBound.prototype = new fNOP() // eslint-disable-line new-cap

  return fBound
}
<commit_msg>Interface: pad balances to 128 bits (and not 256 bits)<commit_after>/**
 * This is the Ethereum interface that is exposed to the WASM instance which
 * enables to interact with the Ethereum Environment
 */
const constants = require('./constants.js')

// The interface exposed to the WebAessembly Core
module.exports = class Interface {
  constructor (environment) {
    this.environment = environment
  }

  get exportTable () {
    let exportMethods = [
      // include all the public methods according to the Ethereum Environment Interface (EEI)
      // FIXME: this currently doesn't match EEI r0
      'useGas',
      'gas',
      'address',
      'balance',
      'origin',
      'caller',
      'callValue',
      'callDataSize',
      'callDataCopy',
      'codeSize',
      'codeCopy',
      'extCodeSize',
      'extCodeCopy',
      'gasPrice',
      'blockHash',
      'coinbase',
      'timestamp',
      'number',
      'difficulty',
      'gasLimit',
      'log',
      'create',
      'call',
      'callDelegate',
      'sstore',
      'sload',
      'return',
      'suicide'
    ]
    let ret = {}
    exportMethods.forEach((method) => {
      ret[method] = this[method].bind(this)
    })
    return ret
  }

  setModule (mod) {
    this.module = mod
  }

  /**
   * Subtracts an amount to the gas counter
   * @param {integer} amount the amount to subtract to the gas counter
   */
  useGas (amount) {
    if (amount > 0) {
      if (this.environment.gasLimit < amount) {
        throw new Error('Ran out of gas')
      }
      this.environment.gasLimit -= amount
    }
  }

  /**
   * Returns the current amount of gas
   * @return {integer}
   */
  gas () {
    return this.environment.gasLimit
  }

  /**
   * Gets address of currently executing account and loads it into memory at
   * the given offset.
   * @param {integer} offset
   */
  address (offset) {
    this.setMemory(offset, constants.ADDRESS_SIZE_BYTES, this.environment.address)
  }

  /**
   * Gets balance of the given account and loads it into memory at the given
   * offset.
   * @param {integer} addressOffset the memory offset to laod the address
   * @param {integer} resultOffset
   */
  balance (addressOffset, offset) {
    const address = this.getMemory(addressOffset, constants.ADDRESS_SIZE_BYTES)
    // call the parent contract and ask for the balance of one of its child contracts
    const balance = this.environment.parent.environment.getBalance(address)
    this.setMemory(offset, constants.BALANCE_SIZE_BYTES, balance)
  }

  /**
   * Gets the execution's origination address and loads it into memory at the
   * given offset. This is the sender of original transaction; it is never an
   * account with non-empty associated code.
   * @param {integer} offset
   */
  origin (offset) {
    this.setMemory(offset, constants.ADDRESS_SIZE_BYTES, this.environment.origin)
  }

  /**
   * Gets caller address and loads it into memory at the given offset. This is
   * the address of the account that is directly responsible for this execution.
   * @param {integer} offset
   */
  caller (offset) {
    this.setMemory(offset, constants.ADDRESS_SIZE_BYTES, this.environment.caller)
  }

  /**
   * Gets the deposited value by the instruction/transaction responsible for
   * this execution and loads it into memory at the given location.
   * @param {integer} offset
   */
  callValue (offset) {
    this.setMemory(offset, constants.BALANCE_SIZE_BYTES, this.environment.callValue.toBuffer(constants.BALANCE_SIZE_BYTES))
  }

  /**
   * Get size of input data in current environment. This pertains to the input
   * data passed with the message call instruction or transaction.
   * @return {integer}
   */
  callDataSize () {
    return this.environment.callData.length
  }

  /**
   * Copys the input data in current environment to memory. This pertains to
   * the input data passed with the message call instruction or transaction.
   * @param {integer} offset the offset in memory to load into
   * @param {integer} dataOffset the offset in the input data
   * @param {integer} length the length of data to copy
   */
  callDataCopy (offset, dataOffset, length) {
    const callData = Buffer.from(this.environment.callData.slice(dataOffset, dataOffset + length)).reverse()
    this.setMemory(offset, length, callData)
  }

  /**
   * Gets the size of code running in current environment.
   * @return {interger}
   */
  codeSize () {
    return this.environment.code.length
  }

  /**
   * Copys the code running in current environment to memory.
   * @param {integer} offset the memory offset
   * @param {integer} codeOffset the code offset
   * @param {integer} length the length of code to copy
   */
  codeCopy (offset, codeOffset, length) {
    const code = new Uint8Array(this.environment.code, codeOffset, length)
    this.setMemory(offset, length, code)
  }

  /**
   * Get size of an account’s code.
   * @param {integer} addressOffset the offset in memory to load the address from
   * @return {integer}
   */
  extCodeSize (addressOffset) {
    const address = this.getMemory(addressOffset, constants.ADDRESS_SIZE_BYTES)
    const code = this.environment.getCode(address)
    return code.length
  }

  /**
   * Copys the code of an account to memory.
   * @param {integer} addressOffset the memory offset of the address
   * @param {integer} offset the memory offset
   * @param {integer} codeOffset the code offset
   * @param {integer} length the length of code to copy
   */
  extCodeCopy (addressOffset, offset, codeOffset, length) {
    const address = this.getMemory(addressOffset, constants.ADDRESS_SIZE_BYTES)
    let code = this.environment.getCode(address)
   code = new Uint8Array(code, codeOffset, length)
    this.setMemory(offset, length, code)
  }

  /**
   * Gets price of gas in current environment.
   * @return {integer}
   */
  gasPrice () {
    return this.environment.gasPrice
  }

  /**
   * Gets the hash of one of the 256 most recent complete blocks.
   * @param {integer} number which block to load
   * @param {integer} offset the offset to load the hash into
   */
  blockHash (number, offset) {
    const hash = this.environment.getBlockHash(number)
    this.setMemory(offset, 32, hash)
  }

  /**
   * Gets the block’s beneficiary address and loads into memory.
   * @param offset
   */
  coinbase (offset) {
    this.setMemory(offset, constants.ADDRESS_SIZE_BYTES, this.environment.coinbase)
  }

  /**
   * Get the block’s timestamp.
   * @return {integer}
   */
  timestamp () {
    return this.environment.timestamp
  }

  /**
   * Get the block’s number.
   * @return {integer}
   */
  number () {
    return this.environment.number
  }

  /**
   * Get the block’s difficulty.
   * @return {integer}
   */
  difficulty () {
    return this.environment.difficulty
  }

  /**
   * Get the block’s gas limit.
   * @return {integer}
   */
  gasLimit () {
    return this.environment.gasLimit
  }

  /**
   * Creates a new log in the current environment
   * @param {integer} dataOffset the offset in memory to load the memory
   * @param {integer} length the data length
   * TODO: replace with variadic
   */
  log (dataOffset, length, topic1, topic2, topic3, topic4, topic5) {
    const data = this.getMemory(dataOffset, length)
    this.environment.logs.push({
      data: data,
      topics: [topic1, topic2, topic3, topic4, topic5]
    })
  }

  /**
   * Creates a new contract with a given value.
   * @param {integer} valueOffset the offset in memory to the value from
   * @param {integer} dataOffset the offset to load the code for the new contract from
   * @param {integer} length the data length
   */
  create (valueOffset, dataOffset, length) {
    const value = this.getMemory(valueOffset, constants.BALANCE_SIZE_BYTES)
    const data = this.getMemory(dataOffset, length)
    const result = this.environment.create(value, data)
    return result
  }

  /**
   * Sends a message with arbiatary data to a given address path
   * @param {integer} addressOffset the offset to load the address path from
   * @param {integer} valueOffset the offset to load the value from
   * @param {integer} dataOffset the offset to load data from
   * @param {integer} dataLength the length of data
   * @param {integer} resultOffset the offset to store the result data at
   * @param {integer} resultLength
   * @param {integer} gas
   * @return {integer} Returns 1 or 0 depending on if the VM trapped on the message or not
   * TODO: add proper gas counting
   */
  call (addressOffset, valueOffset, dataOffset, dataLength, resultOffset, resultLength, gas) {
    if (gas === undefined) {
      gas = this.gasLeft()
    }
    // Load the params from mem
    const address = this.getMemory(addressOffset, constants.ADDRESS_SIZE_BYTES)
    const value = this.getMemory(valueOffset, constants.BALANCE_SIZE_BYTES)
    const data = this.getMemory(dataOffset, dataLength)
    // Run the call
    const [result, errorCode] = this.environment.call(gas, address, value, data)
    this.setMemory(resultOffset, resultLength, result)
    return errorCode
  }

  /**
   * Message-call into this account with an alternative account’s code, but
   * persisting the current values for sender and value.
   * @param {integer} gas
   * @param {integer} addressOffset the offset to load the address path from
   * @param {integer} valueOffset the offset to load the value from
   * @param {integer} dataOffset the offset to load data from
   * @param {integer} dataLength the length of data
   * @param {integer} resultOffset the offset to store the result data at
   * @param {integer} resultLength
   * @return {integer} Returns 1 or 0 depending on if the VM trapped on the message or not
   */
  callDelegate (gas, addressOffset, dataOffset, dataLength, resultOffset, resultLength) {
    const data = this.getMemory(dataOffset, dataLength)
    const address = this.getMemory(addressOffset, constants.ADDRESS_SIZE_BYTES)
    const [result, errorCode] = this.environment.callDelegate(gas, address, data)
    this.setMemory(resultOffset, resultLength, result)
    return errorCode
  }

  /**
   * store a value at a given path in long term storage which are both loaded
   * from Memory
   * @param {interger} pathOffest the memory offset to load the the path from
   * @param {interger} valueOffset the memory offset to load the value from
   */
  sstore (pathOffset, valueOffset) {
    const path = new Buffer(this.getMemory(pathOffset, 32)).toString('hex')
    // copy the value
    const value = this.getMemory(valueOffset, 32).slice(0)
    const oldValue = this.environment.state.get(path)
    const valIsZero = value.every((i) => i === 0)

    // write
    if (!valIsZero && !oldValue) {
      this.environment.gasLimit -= 15000
    }

    // delete
    if (valIsZero && oldValue) {
      this.environment.gasRefund += 15000
      this.environment.state.delete(path)
    } else {
      this.environment.state.set(path, value)
    }
  }

  /**
   * reterives a value at a given path in long term storage
   * @param {interger} pathOffest the memory offset to load the the path from
   * @param {interger} resultOffset the memory offset to load the value from
   */
  sload (pathOffset, resultOffset) {
    const path = new Buffer(this.getMemory(pathOffset, 32)).toString('hex')
    const result = this.environment.state.get(path)
    this.setMemory(resultOffset, 32, result)
  }

  /**
   * Halt execution returning output data.
   * @param {integer} offset the offset of the output data.
   * @param {integer} length the length of the output data.
   */
  return (offset, length) {
    this.environment.returnValue = this.getMemory(offset, length)
  }

  /**
   * Halt execution and register account for later deletion giving the remaining
   * balance to an address path
   * @param {integer} offset the offset to load the address from
   */
  suicide (addressOffset) {
    this.environment.suicideAddress = this.getMemory(addressOffset, constants.ADDRESS_SIZE_BYTES)
  }

  getMemory (offset, length) {
    return new Uint8Array(this.module.exports.memory, offset, length)
  }

  setMemory (offset, length, value) {
    const memory = new Uint8Array(this.module.exports.memory, offset, length)
    memory.set(value)
  }
}

//
// Polyfill required unless this is sorted: https://bugs.chromium.org/p/chromium/issues/detail?id=633895
//
// Polyfill from: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
//
Function.prototype.bind = function (oThis) { // eslint-disable-line
  if (typeof this !== 'function') {
    // closest thing possible to the ECMAScript 5
    // internal IsCallable function
    throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable')
  }

  var aArgs = Array.prototype.slice.call(arguments, 1)
  var fToBind = this
  var fNOP = function () {}
  var fBound = function () {
    return fToBind.apply(this instanceof fNOP ? this : oThis,
     aArgs.concat(Array.prototype.slice.call(arguments)))
  }

  if (this.prototype) {
    // Function.prototype doesn't have a prototype property
    fNOP.prototype = this.prototype
  }

  fBound.prototype = new fNOP() // eslint-disable-line new-cap

  return fBound
}
<|endoftext|>