<commit_before>/**
 * @file react-anything-sortable
 * @author jasonslyvia
 */

/* eslint new-cap:0, consistent-return: 0, react/prefer-es6-class: 0, react/sort-comp: 0 */
/**
 * @dependency
 */
import React from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import ReactDOM from 'react-dom';
import { on, off, isFunction, isNumeric, position, closest, get,
        assign, findMostOften } from './utils';
import SortableItemMixin from './SortableItemMixin';

const doc = typeof window === 'object' ? window.document : {};

const STACK_SIZE = 6;
const getSortTarget = (child) => {
  // `onSortableItemReadyToMove` only exist when using mixins or decorators
  return child && child.props && isFunction(child.props.onSortableItemReadyToMove);
};

/**
 * @class Sortable
 */
const Sortable = createReactClass({
  propTypes: {
    /**
     * callback fires after sort operation finish
     * function (dataSet){
     *   //dataSet sorted
     * }
     */
    onSort: PropTypes.func,
    className: PropTypes.string,
    sortHandle: PropTypes.string,
    containment: PropTypes.bool,
    dynamic: PropTypes.bool,
    direction: PropTypes.string,
    children: PropTypes.arrayOf(PropTypes.node)
  },

  setArrays(currentChildren) {
    const children = Array.isArray(currentChildren) ?
                     currentChildren :
                     [currentChildren];

    const sortChildren = children.filter(getSortTarget);
    this.sortChildren = sortChildren;

    // keep tracking the dimension and coordinates of all children
    this._dimensionArr = sortChildren.map(() => ({}));

    // keep tracking the order of all children
    this._orderArr = [];
    let i = 0;
    while (i < this._dimensionArr.length) {
      this._orderArr.push(i++);
    }
  },

  getInitialState() {
    this.setArrays(this.props.children);

    return {
      isDragging: false,
      placeHolderIndex: null,
      left: null,
      top: null
    };
  },

  componentDidUpdate() {
    const container = ReactDOM.findDOMNode(this);
    const rect = container.getBoundingClientRect();

    const scrollTop = (doc.docElement && doc.docElement.scrollTop) || doc.body.scrollTop;
    const scrollLeft = (doc.docElement && doc.docElement.scrollLeft) || doc.body.scrollLeft;

    this._top = rect.top + scrollTop;
    this._left = rect.left + scrollLeft;
    this._bottom = this._top + rect.height;
    this._right = this._left + rect.width;
  },

  componentWillReceiveProps(nextProps) {
    const { children, dynamic } = this.props;
    if (dynamic && nextProps.children !== children) {
      this.setArrays(nextProps.children);
    }
  },

  componentWillUnmount() {
    this.unbindEvent();
  },

  bindEvent() {
    // so that the focus won't be lost if cursor moving too fast
    this.__mouseMoveHandler = (e) => {
      /**
       * Since Chrome may trigger redundant mousemove event evne if
       * we didn't really move the mouse, we should make sure that
       * mouse coordinates really changed then respond to mousemove
       * event
       * @see https://code.google.com/p/chromium/issues/detail?id=327114
       */
      if (((e.pageX || e.clientX) === this._prevX && (e.pageY || e.clientY) === this._prevY) ||
          (this._prevX === null && this._prevY === null)) {
        return false;
      }

      this.handleMouseMove.call(this, e);
    };

    this.__mouseUpHandler = (e) => {
      this.handleMouseUp.call(this, e);
    };

    this.__touchMoveHandler = (e) => {
      // blocks the default scrolling as we sort an element
      e.preventDefault();

      this.handleMouseMove.call(this, {
        target: e.target,
        clientX: e.touches[0].clientX,
        clientY: e.touches[0].clientY,
        pageX: e.touches[0].pageX,
        pageY: e.touches[0].pageY
      });
    };

    this.__touchEndOrCancelHandler = (e) => {
      this.handleMouseUp.call(this, e);
    };

    on(doc, 'touchmove', this.__touchMoveHandler);
    on(doc, 'touchend', this.__touchEndOrCancelHandler);
    on(doc, 'touchcancel', this.__touchEndOrCancelHandler);
    on(doc, 'mousemove', this.__mouseMoveHandler);
    on(doc, 'mouseup', this.__mouseUpHandler);
  },

  unbindEvent() {
    off(doc, 'touchmove', this.__touchMoveHandler);
    off(doc, 'touchend', this.__touchEndOrCancelHandler);
    off(doc, 'touchcancel', this.__touchEndOrCancelHandler);
    off(doc, 'mousemove', this.__mouseMoveHandler);
    off(doc, 'mouseup', this.__mouseUpHandler);

    this.__mouseMoveHandler = null;
    this.__mouseUpHandler = null;
    this.__touchMoveHandler = null;
    this.__touchEndOrCancelHandler = null;
  },

  /**
   * getting ready for dragging
   * @param  {object} e     React event
   * @param  {numbner} index index of pre-dragging item
   */
  handleMouseDown(e, index) {
    this._draggingIndex = index;
    this._prevX = (e.pageX || e.clientX);
    this._prevY = (e.pageY || e.clientY);
    this._initOffset = e.offset;
    this._isReadyForDragging = true;
    this._hasInitDragging = false;

    // start listening mousemove and mouseup
    this.bindEvent();
  },

  /**
   * `add` a dragging item and re-calculating position of placeholder
   * @param  {object} e     React event
   */
  handleMouseMove(e) {
    this._isMouseMoving = true;

    if (!this._isReadyForDragging) {
      return false;
    }

    if (!this._hasInitDragging) {
      this._dimensionArr[this._draggingIndex].isPlaceHolder = true;
      this._hasInitDragging = true;
    }

    if (this.props.containment) {
      const x = e.pageX || e.clientX;
      const y = e.pageY || e.clientY;

      if (x < this._left || x > this._right || y < this._top || y > this._bottom) {
        return false;
      }
    }

    const newOffset = this.calculateNewOffset(e);
    const newIndex = this.calculateNewIndex(e);

    this._draggingIndex = newIndex;

    this.setState({
      isDragging: true,
      top: this.props.direction === 'horizontal' ? this._initOffset.top : newOffset.top,
      left: this.props.direction === 'vertical' ? this._initOffset.left : newOffset.left,
      placeHolderIndex: newIndex
    });

    this._prevX = (e.pageX || e.clientX);
    this._prevY = (e.pageY || e.clientY);
  },

  /**
   * replace placeholder with dragging item
   * @param  {object} e     React event
   */
  handleMouseUp() {
    const _hasMouseMoved = this._isMouseMoving;
    this.unbindEvent();

    const draggingIndex = this._draggingIndex;
    // reset temp lets
    this._draggingIndex = null;
    this._isReadyForDragging = false;
    this._isMouseMoving = false;
    this._initOffset = null;
    this._prevX = null;
    this._prevY = null;

    if (this.state.isDragging) {
      this._dimensionArr[this.state.placeHolderIndex].isPlaceHolder = false;

      if (_hasMouseMoved) {
        this.setState({
          isDragging: false,
          placeHolderIndex: null,
          left: null,
          top: null
        });
      }

      // sort finished, callback fires
      if (isFunction(this.props.onSort)) {
        const sortData = this.getSortData();
        this.props.onSort(sortData, sortData[draggingIndex], draggingIndex);
      }
    }
  },

  /**
   * when children mounted, return its size(handled by SortableItemMixin)
   * @param  {object} offset {top:1, left:2}
   * @param  {number} width
   * @param  {number} height
   * @param  {number} fullWidth  (with margin)
   * @param  {number} fullHeight (with margin)
   * @param  {number} index
   */
  handleChildUpdate(offset, width, height, fullWidth, fullHeight, index) {
    assign(this._dimensionArr[index], {
      top: offset.top,
      left: offset.left,
      width,
      height,
      fullWidth,
      fullHeight
    });
  },

  /**
   * get new index of all items by cursor position
   * @param {object} offset {left: 12, top: 123}
   * @param {string} direction cursor moving direction, used to aviod blinking when
   *                 interchanging position of different width elements
   * @return {number}
   */
  getIndexByOffset(offset, direction) {
    if (!offset || !isNumeric(offset.top) || !isNumeric(offset.left)) {
      return 0;
    }

    const _dimensionArr = this._dimensionArr;
    const offsetX = offset.left;
    const offsetY = offset.top;
    const prevIndex = this.state.placeHolderIndex !== null ?
                   this.state.placeHolderIndex :
                   this._draggingIndex;
    let newIndex;

    _dimensionArr.every((item, index) => {
      const relativeLeft = offsetX - item.left;
      const relativeTop = offsetY - item.top;

      if (relativeLeft < item.fullWidth && relativeTop < item.fullHeight) {
        if (relativeLeft < item.fullWidth / 2 && direction === 'left') {
          newIndex = index;
        } else if (relativeLeft > item.fullWidth / 2 && direction === 'right') {
          newIndex = Math.min(index + 1, _dimensionArr.length - 1);
        } else if (relativeTop < item.fullHeight / 2 && direction === 'up') {
          newIndex = index;
        } else if (relativeTop > item.fullHeight / 2 && direction === 'down') {
          newIndex = Math.min(index + 1, _dimensionArr.length - 1);
        } else {
          return true;
        }

        return false;
      }
      return true;
    });

    return newIndex !== undefined ? newIndex : prevIndex;
  },

  /**
   * untility function
   * @param  {array} arr
   * @param  {number} src
   * @param  {number} to
   * @return {array}
   */
  swapArrayItemPosition(arr, src, to) {
    if (!arr || !isNumeric(src) || !isNumeric(to)) {
      return arr;
    }

    const srcEl = arr.splice(src, 1)[0];
    arr.splice(to, 0, srcEl);
    return arr;
  },

  /**
   * calculate new offset
   * @param  {object} e MouseMove event
   * @return {object}   {left: 1, top: 1}
   */
  calculateNewOffset(e) {
    const deltaX = this._prevX - (e.pageX || e.clientX);
    const deltaY = this._prevY - (e.pageY || e.clientY);

    const prevLeft = this.state.left !== null ? this.state.left : this._initOffset.left;
    const prevTop = this.state.top !== null ? this.state.top : this._initOffset.top;
    const newLeft = prevLeft - deltaX;
    const newTop = prevTop - deltaY;

    return {
      left: newLeft,
      top: newTop
    };
  },

  /**
   * calculate new index and do swapping
   * @param  {object} e MouseMove event
   * @return {number}
   */
  calculateNewIndex(e) {
    const placeHolderIndex = this.state.placeHolderIndex !== null ?
                           this.state.placeHolderIndex :
                           this._draggingIndex;

    // Since `mousemove` is listened on document, when cursor move too fast,
    // `e.target` may be `body` or some other stuff instead of
    // `.ui-sortable-item`
    const target = get('.ui-sortable-dragging') ||
                   closest((e.target || e.srcElement), '.ui-sortable-item');
    const offset = position(target);

    const currentX = e.pageX || e.clientX;
    const currentY = e.pageY || e.clientY;

    const deltaX = Math.abs(this._prevX - currentX);
    const deltaY = Math.abs(this._prevY - currentY);

    let direction;
    if (deltaX > deltaY) {
      // tend to move left/right
      direction = this._prevX > currentX ? 'left' : 'right';
    } else {
      // tend to move up/down
      direction = this._prevY > currentY ? 'up' : 'down';
    }

    const newIndex = this.getIndexByOffset(offset, this.getPossibleDirection(direction));
    if (newIndex !== placeHolderIndex) {
      this._dimensionArr = this.swapArrayItemPosition(this._dimensionArr,
                                                      placeHolderIndex,
                                                      newIndex);
      this._orderArr = this.swapArrayItemPosition(this._orderArr, placeHolderIndex, newIndex);
    }

    return newIndex;
  },

  getSortData() {
    return this._orderArr.map((itemIndex) => {
      const item = this.sortChildren[itemIndex];
      if (!item) {
        return undefined;
      }

      return item.props.sortData;
    });
  },

  getPossibleDirection(direction) {
    this._stack = this._stack || [];
    this._stack.push(direction);
    if (this._stack.length > STACK_SIZE) {
      this._stack.shift();
    }

    if (this._stack.length < STACK_SIZE) {
      return direction;
    }

    return findMostOften(this._stack);
  },

  /**
   * render all sortable children which mixined with SortableItemMixin
   */
  renderItems() {
    const { _dimensionArr, _orderArr } = this;
    let draggingItem;

    const items = _orderArr.map((itemIndex, index) => {
      const item = this.sortChildren[itemIndex];
      if (!item) {
        return;
      }

      if (index === this._draggingIndex && this.state.isDragging) {
        draggingItem = this.renderDraggingItem(item);
      }

      const isPlaceHolder = _dimensionArr[index].isPlaceHolder;
      const itemClassName = `ui-sortable-item
                             ${isPlaceHolder && 'ui-sortable-placeholder'}
                             ${this.state.isDragging && isPlaceHolder && 'visible'}`;

      const sortableProps = {
        sortableClassName: `${item.props.className} ${itemClassName}`,
        sortableIndex: index,
        onSortableItemReadyToMove: isPlaceHolder ? undefined : (e) => {
          this.handleMouseDown.call(this, e, index);
        },
        onSortableItemMount: this.handleChildUpdate,
        sortHandle: this.props.sortHandle
      };

      if (item.key === undefined) {
        sortableProps.key = index;
      }

      return React.cloneElement(item, sortableProps);
    });

    const children = Array.isArray(this.props.children) ?
                     this.props.children :
                     [this.props.children];

    const result = children.map(child => {
      if (getSortTarget(child)) {
        return items.shift();
      }
      return child;
    }).concat([draggingItem]);

    return result;
  },

  /**
   * render the item that being dragged
   * @param  {object} item a reference of this.props.children
   */
  renderDraggingItem(item) {
    if (!item) {
      return;
    }

    const style = {
      top: this.state.top,
      left: this.state.left,
      width: this._dimensionArr[this._draggingIndex].width,
      height: this._dimensionArr[this._draggingIndex].height
    };
    return React.cloneElement(item, {
      sortableClassName: `${item.props.className} ui-sortable-item ui-sortable-dragging`,
      key: '_dragging',
      sortableStyle: style,
      isDragging: true,
      sortHandle: this.props.sortHandle
    });
  },

  render() {
    const className = `ui-sortable ${this.props.className || ''}`;

    return (
      <div className={className}>
        {this.renderItems()}
      </div>
    );
  }
});

const SortableContainer = ({
  className, style, onMouseDown, onTouchStart, children,
}) => {
  if (React.isValidElement(children)) {
    return React.cloneElement(children, {
      className, style, onMouseDown, onTouchStart
    });
  } else {
    return React.createElement('div', {
      className, style, onMouseDown, onTouchStart, children
    });
  }
};

Sortable.SortableItemMixin = SortableItemMixin();
Sortable.sortable = SortableItemMixin;
Sortable.SortableContainer = SortableItemMixin(SortableContainer);

export default Sortable;
<commit_msg>Fix reference to document.documentElement and doc warnings (#90)<commit_after>/**
 * @file react-anything-sortable
 * @author jasonslyvia
 */

/* eslint new-cap:0, consistent-return: 0, react/prefer-es6-class: 0, react/sort-comp: 0 */
/**
 * @dependency
 */
import React from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import ReactDOM from 'react-dom';
import { on, off, isFunction, isNumeric, position, closest, get,
        assign, findMostOften } from './utils';
import SortableItemMixin from './SortableItemMixin';

const doc = typeof window === 'object' ? window.document : {};

const STACK_SIZE = 6;
const getSortTarget = (child) => {
  // `onSortableItemReadyToMove` only exist when using mixins or decorators
  return child && child.props && isFunction(child.props.onSortableItemReadyToMove);
};

/**
 * @class Sortable
 */
const Sortable = createReactClass({
  propTypes: {
    /**
     * callback fires after sort operation finish
     * function (dataSet){
     *   //dataSet sorted
     * }
     */
    onSort: PropTypes.func,
    className: PropTypes.string,
    sortHandle: PropTypes.string,
    containment: PropTypes.bool,
    dynamic: PropTypes.bool,
    direction: PropTypes.string,
    children: PropTypes.arrayOf(PropTypes.node)
  },

  setArrays(currentChildren) {
    const children = Array.isArray(currentChildren) ?
                     currentChildren :
                     [currentChildren];

    const sortChildren = children.filter(getSortTarget);
    this.sortChildren = sortChildren;

    // keep tracking the dimension and coordinates of all children
    this._dimensionArr = sortChildren.map(() => ({}));

    // keep tracking the order of all children
    this._orderArr = [];
    let i = 0;
    while (i < this._dimensionArr.length) {
      this._orderArr.push(i++);
    }
  },

  getInitialState() {
    this.setArrays(this.props.children);

    return {
      isDragging: false,
      placeHolderIndex: null,
      left: null,
      top: null
    };
  },

  componentDidUpdate() {
    const container = ReactDOM.findDOMNode(this);
    const rect = container.getBoundingClientRect();

    const scrollTop = (doc.documentElement && doc.documentElement.scrollTop) || doc.body.scrollTop;
    const scrollLeft = (doc.documentElement && doc.documentElement.scrollLeft) || doc.body.scrollLeft;

    this._top = rect.top + scrollTop;
    this._left = rect.left + scrollLeft;
    this._bottom = this._top + rect.height;
    this._right = this._left + rect.width;
  },

  componentWillReceiveProps(nextProps) {
    const { children, dynamic } = this.props;
    if (dynamic && nextProps.children !== children) {
      this.setArrays(nextProps.children);
    }
  },

  componentWillUnmount() {
    this.unbindEvent();
  },

  bindEvent() {
    // so that the focus won't be lost if cursor moving too fast
    this.__mouseMoveHandler = (e) => {
      /**
       * Since Chrome may trigger redundant mousemove event evne if
       * we didn't really move the mouse, we should make sure that
       * mouse coordinates really changed then respond to mousemove
       * event
       * @see https://code.google.com/p/chromium/issues/detail?id=327114
       */
      if (((e.pageX || e.clientX) === this._prevX && (e.pageY || e.clientY) === this._prevY) ||
          (this._prevX === null && this._prevY === null)) {
        return false;
      }

      this.handleMouseMove.call(this, e);
    };

    this.__mouseUpHandler = (e) => {
      this.handleMouseUp.call(this, e);
    };

    this.__touchMoveHandler = (e) => {
      // blocks the default scrolling as we sort an element
      e.preventDefault();

      this.handleMouseMove.call(this, {
        target: e.target,
        clientX: e.touches[0].clientX,
        clientY: e.touches[0].clientY,
        pageX: e.touches[0].pageX,
        pageY: e.touches[0].pageY
      });
    };

    this.__touchEndOrCancelHandler = (e) => {
      this.handleMouseUp.call(this, e);
    };

    on(doc, 'touchmove', this.__touchMoveHandler);
    on(doc, 'touchend', this.__touchEndOrCancelHandler);
    on(doc, 'touchcancel', this.__touchEndOrCancelHandler);
    on(doc, 'mousemove', this.__mouseMoveHandler);
    on(doc, 'mouseup', this.__mouseUpHandler);
  },

  unbindEvent() {
    off(doc, 'touchmove', this.__touchMoveHandler);
    off(doc, 'touchend', this.__touchEndOrCancelHandler);
    off(doc, 'touchcancel', this.__touchEndOrCancelHandler);
    off(doc, 'mousemove', this.__mouseMoveHandler);
    off(doc, 'mouseup', this.__mouseUpHandler);

    this.__mouseMoveHandler = null;
    this.__mouseUpHandler = null;
    this.__touchMoveHandler = null;
    this.__touchEndOrCancelHandler = null;
  },

  /**
   * getting ready for dragging
   * @param  {object} e     React event
   * @param  {index} index of pre-dragging item
   */
  handleMouseDown(e, index) {
    this._draggingIndex = index;
    this._prevX = (e.pageX || e.clientX);
    this._prevY = (e.pageY || e.clientY);
    this._initOffset = e.offset;
    this._isReadyForDragging = true;
    this._hasInitDragging = false;

    // start listening mousemove and mouseup
    this.bindEvent();
  },

  /**
   * `add` a dragging item and re-calculating position of placeholder
   * @param  {object} e     React event
   */
  handleMouseMove(e) {
    this._isMouseMoving = true;

    if (!this._isReadyForDragging) {
      return false;
    }

    if (!this._hasInitDragging) {
      this._dimensionArr[this._draggingIndex].isPlaceHolder = true;
      this._hasInitDragging = true;
    }

    if (this.props.containment) {
      const x = e.pageX || e.clientX;
      const y = e.pageY || e.clientY;

      if (x < this._left || x > this._right || y < this._top || y > this._bottom) {
        return false;
      }
    }

    const newOffset = this.calculateNewOffset(e);
    const newIndex = this.calculateNewIndex(e);

    this._draggingIndex = newIndex;

    this.setState({
      isDragging: true,
      top: this.props.direction === 'horizontal' ? this._initOffset.top : newOffset.top,
      left: this.props.direction === 'vertical' ? this._initOffset.left : newOffset.left,
      placeHolderIndex: newIndex
    });

    this._prevX = (e.pageX || e.clientX);
    this._prevY = (e.pageY || e.clientY);
  },

  /**
   * replace placeholder with dragging item
   */
  handleMouseUp() {
    const _hasMouseMoved = this._isMouseMoving;
    this.unbindEvent();

    const draggingIndex = this._draggingIndex;
    // reset temp lets
    this._draggingIndex = null;
    this._isReadyForDragging = false;
    this._isMouseMoving = false;
    this._initOffset = null;
    this._prevX = null;
    this._prevY = null;

    if (this.state.isDragging) {
      this._dimensionArr[this.state.placeHolderIndex].isPlaceHolder = false;

      if (_hasMouseMoved) {
        this.setState({
          isDragging: false,
          placeHolderIndex: null,
          left: null,
          top: null
        });
      }

      // sort finished, callback fires
      if (isFunction(this.props.onSort)) {
        const sortData = this.getSortData();
        this.props.onSort(sortData, sortData[draggingIndex], draggingIndex);
      }
    }
  },

  /**
   * when children mounted, return its size(handled by SortableItemMixin)
   * @param  {object} offset {top:1, left:2}
   * @param  {number} width
   * @param  {number} height
   * @param  {number} fullWidth  (with margin)
   * @param  {number} fullHeight (with margin)
   * @param  {number} index
   */
  handleChildUpdate(offset, width, height, fullWidth, fullHeight, index) {
    assign(this._dimensionArr[index], {
      top: offset.top,
      left: offset.left,
      width,
      height,
      fullWidth,
      fullHeight
    });
  },

  /**
   * get new index of all items by cursor position
   * @param {object} offset {left: 12, top: 123}
   * @param {string} direction cursor moving direction, used to aviod blinking when
   *                 interchanging position of different width elements
   * @return {number}
   */
  getIndexByOffset(offset, direction) {
    if (!offset || !isNumeric(offset.top) || !isNumeric(offset.left)) {
      return 0;
    }

    const _dimensionArr = this._dimensionArr;
    const offsetX = offset.left;
    const offsetY = offset.top;
    const prevIndex = this.state.placeHolderIndex !== null ?
                   this.state.placeHolderIndex :
                   this._draggingIndex;
    let newIndex;

    _dimensionArr.every((item, index) => {
      const relativeLeft = offsetX - item.left;
      const relativeTop = offsetY - item.top;

      if (relativeLeft < item.fullWidth && relativeTop < item.fullHeight) {
        if (relativeLeft < item.fullWidth / 2 && direction === 'left') {
          newIndex = index;
        } else if (relativeLeft > item.fullWidth / 2 && direction === 'right') {
          newIndex = Math.min(index + 1, _dimensionArr.length - 1);
        } else if (relativeTop < item.fullHeight / 2 && direction === 'up') {
          newIndex = index;
        } else if (relativeTop > item.fullHeight / 2 && direction === 'down') {
          newIndex = Math.min(index + 1, _dimensionArr.length - 1);
        } else {
          return true;
        }

        return false;
      }
      return true;
    });

    return newIndex !== undefined ? newIndex : prevIndex;
  },

  /**
   * untility function
   * @param  {array} arr
   * @param  {number} src
   * @param  {number} to
   * @return {array}
   */
  swapArrayItemPosition(arr, src, to) {
    if (!arr || !isNumeric(src) || !isNumeric(to)) {
      return arr;
    }

    const srcEl = arr.splice(src, 1)[0];
    arr.splice(to, 0, srcEl);
    return arr;
  },

  /**
   * calculate new offset
   * @param  {object} e MouseMove event
   * @return {object}   {left: 1, top: 1}
   */
  calculateNewOffset(e) {
    const deltaX = this._prevX - (e.pageX || e.clientX);
    const deltaY = this._prevY - (e.pageY || e.clientY);

    const prevLeft = this.state.left !== null ? this.state.left : this._initOffset.left;
    const prevTop = this.state.top !== null ? this.state.top : this._initOffset.top;
    const newLeft = prevLeft - deltaX;
    const newTop = prevTop - deltaY;

    return {
      left: newLeft,
      top: newTop
    };
  },

  /**
   * calculate new index and do swapping
   * @param  {object} e MouseMove event
   * @return {number}
   */
  calculateNewIndex(e) {
    const placeHolderIndex = this.state.placeHolderIndex !== null ?
                           this.state.placeHolderIndex :
                           this._draggingIndex;

    // Since `mousemove` is listened on document, when cursor move too fast,
    // `e.target` may be `body` or some other stuff instead of
    // `.ui-sortable-item`
    const target = get('.ui-sortable-dragging') ||
                   closest((e.target || e.srcElement), '.ui-sortable-item');
    const offset = position(target);

    const currentX = e.pageX || e.clientX;
    const currentY = e.pageY || e.clientY;

    const deltaX = Math.abs(this._prevX - currentX);
    const deltaY = Math.abs(this._prevY - currentY);

    let direction;
    if (deltaX > deltaY) {
      // tend to move left/right
      direction = this._prevX > currentX ? 'left' : 'right';
    } else {
      // tend to move up/down
      direction = this._prevY > currentY ? 'up' : 'down';
    }

    const newIndex = this.getIndexByOffset(offset, this.getPossibleDirection(direction));
    if (newIndex !== placeHolderIndex) {
      this._dimensionArr = this.swapArrayItemPosition(this._dimensionArr,
                                                      placeHolderIndex,
                                                      newIndex);
      this._orderArr = this.swapArrayItemPosition(this._orderArr, placeHolderIndex, newIndex);
    }

    return newIndex;
  },

  getSortData() {
    return this._orderArr.map((itemIndex) => {
      const item = this.sortChildren[itemIndex];
      if (!item) {
        return undefined;
      }

      return item.props.sortData;
    });
  },

  getPossibleDirection(direction) {
    this._stack = this._stack || [];
    this._stack.push(direction);
    if (this._stack.length > STACK_SIZE) {
      this._stack.shift();
    }

    if (this._stack.length < STACK_SIZE) {
      return direction;
    }

    return findMostOften(this._stack);
  },

  /**
   * render all sortable children which mixined with SortableItemMixin
   */
  renderItems() {
    const { _dimensionArr, _orderArr } = this;
    let draggingItem;

    const items = _orderArr.map((itemIndex, index) => {
      const item = this.sortChildren[itemIndex];
      if (!item) {
        return;
      }

      if (index === this._draggingIndex && this.state.isDragging) {
        draggingItem = this.renderDraggingItem(item);
      }

      const isPlaceHolder = _dimensionArr[index].isPlaceHolder;
      const itemClassName = `ui-sortable-item
                             ${isPlaceHolder && 'ui-sortable-placeholder'}
                             ${this.state.isDragging && isPlaceHolder && 'visible'}`;

      const sortableProps = {
        sortableClassName: `${item.props.className} ${itemClassName}`,
        sortableIndex: index,
        onSortableItemReadyToMove: isPlaceHolder ? undefined : (e) => {
          this.handleMouseDown.call(this, e, index);
        },
        onSortableItemMount: this.handleChildUpdate,
        sortHandle: this.props.sortHandle
      };

      if (item.key === undefined) {
        sortableProps.key = index;
      }

      return React.cloneElement(item, sortableProps);
    });

    const children = Array.isArray(this.props.children) ?
                     this.props.children :
                     [this.props.children];

    const result = children.map(child => {
      if (getSortTarget(child)) {
        return items.shift();
      }
      return child;
    }).concat([draggingItem]);

    return result;
  },

  /**
   * render the item that being dragged
   * @param  {object} item a reference of this.props.children
   */
  renderDraggingItem(item) {
    if (!item) {
      return;
    }

    const style = {
      top: this.state.top,
      left: this.state.left,
      width: this._dimensionArr[this._draggingIndex].width,
      height: this._dimensionArr[this._draggingIndex].height
    };
    return React.cloneElement(item, {
      sortableClassName: `${item.props.className} ui-sortable-item ui-sortable-dragging`,
      key: '_dragging',
      sortableStyle: style,
      isDragging: true,
      sortHandle: this.props.sortHandle
    });
  },

  render() {
    const className = `ui-sortable ${this.props.className || ''}`;

    return (
      <div className={className}>
        {this.renderItems()}
      </div>
    );
  }
});

const SortableContainer = ({
  className, style, onMouseDown, onTouchStart, children,
}) => {
  if (React.isValidElement(children)) {
    return React.cloneElement(children, {
      className, style, onMouseDown, onTouchStart
    });
  } else {
    return React.createElement('div', {
      className, style, onMouseDown, onTouchStart, children
    });
  }
};

Sortable.SortableItemMixin = SortableItemMixin();
Sortable.sortable = SortableItemMixin;
Sortable.SortableContainer = SortableItemMixin(SortableContainer);

export default Sortable;
<|endoftext|>


<commit_before>var fs = require('fs');

exports.parseFromText = function(diffText, callback) {
  // each match indicates a separate file in the diff
  var fileIndicies = [], fileEx = /(\w+: [\w\.\/]+\n=+)/g, fileMatch;
  while ((fileMatch = fileEx.exec(diffText))) {
    fileIndicies.push(fileMatch.index);
  }

  // pull out each file diff
  var fileDiffs = [];
  for (var i = 0; i < fileIndicies.length; i++) {
    if (i + 1 < fileIndicies.length) {
      fileDiffs.push(diffText.substring(fileIndicies[i], fileIndicies[i+1]));
    } else {
      fileDiffs.push(diffText.substring(fileIndicies[i]));
    }
  }

  var diffs = {};
  fileDiffs.forEach(function(fileDiffText) {
    // pick out the file name
    var firstLine = fileDiffText.split('\n')[0]
      , filePath = firstLine.substring(firstLine.indexOf(':')+1, firstLine.length).trim();

    // pick out all the hunk markers
    var hunkIndicies = [], hunkEx = /@@/gi, hunkMatch;
    while ((hunkMatch = hunkEx.exec(fileDiffText))) {
      hunkIndicies.push(hunkMatch.index);
    }

    // sanity check :: hunk markers come in pairs
    if ((hunkIndicies.length % 2) != 0) {
      callback(new Error('Sanity check failed: Hunk markers should come in pairs.'));
    }

    // parse out hunk properties
    var hunks = []
      , hunkMarkerLength = 2;

    for (var i = 0; i+hunkMarkerLength <= hunkIndicies.length; i+=hunkMarkerLength) {
      var startIdx = hunkIndicies[i]+hunkMarkerLength
        , endIdx = hunkIndicies[i+1]
        , hunkPropsParts = fileDiffText.substring(startIdx, endIdx).trim().split(' ');

      var hunkContent = (endIdx < hunkIndicies.length-1)
        ? fileDiffText.substring(endIdx+hunkMarkerLength, hunkIndicies[endIdx+1])
        : fileDiffText.substring(endIdx+hunkMarkerLength);

      var oldFilePropsParts = hunkPropsParts[0].split(',')
        , newFilePropsParts = hunkPropsParts[1].split(',');

      var hunkLines = hunkContent.split('\n')
        , filteredHunkLines = [];

      hunkLines.forEach(function(line) {
        if (line.length > 0 && line[0] != '\\') { // no blank empty lines or end of file marker
          filteredHunkLines.push({
            action: line[0].trim(),
            text: line.substring(1).trim()
          });
        }
      });

      hunks.push({
        old: {
          from: parseInt(oldFilePropsParts[0].substring(1)),
          numLines: parseInt(oldFilePropsParts[1])
        },
        new: {
          from: parseInt(newFilePropsParts[0].substring(1)),
          numLines: parseInt(newFilePropsParts[1])
        },
        lines: filteredHunkLines
      });

      diffs[filePath] = {
        hunks: hunks
      };
    }
  });

  callback(null, diffs);
};

exports.parseFromFile = function(diffFile, callback) {
  fs.exists(diffFile, function (exists) {
    if (!exists) {
      return callback('No diff file located at ' + diffFile);
    }

    fs.readFile(diffFile, 'utf-8', function(err, contents) {
      exports.parseFromText(contents, callback);
    });
  });
};<commit_msg>Fix newline characters when running on windows<commit_after>var os = require('os');
var fs = require('fs');

exports.parseFromText = function(diffText, callback) {
  // each match indicates a separate file in the diff
  var fileMatch;
  var fileIndicies = [];
  var fileEx = new RegExp('(\\w+: [\\w\\.\\/]+' + os.EOL + '=+)', 'g');
  while ((fileMatch = fileEx.exec(diffText))) {
    fileIndicies.push(fileMatch.index);
  }

  // pull out each file diff
  var fileDiffs = [];
  for (var i = 0; i < fileIndicies.length; i++) {
    if (i + 1 < fileIndicies.length) {
      fileDiffs.push(diffText.substring(fileIndicies[i], fileIndicies[i+1]));
    } else {
      fileDiffs.push(diffText.substring(fileIndicies[i]));
    }
  }

  var diffs = {};
  fileDiffs.forEach(function(fileDiffText) {
    // pick out the file name
    var firstLine = fileDiffText.split(os.EOL)[0]
      , filePath = firstLine.substring(firstLine.indexOf(':')+1, firstLine.length).trim();

    // pick out all the hunk markers
    var hunkIndicies = [], hunkEx = /@@/gi, hunkMatch;
    while ((hunkMatch = hunkEx.exec(fileDiffText))) {
      hunkIndicies.push(hunkMatch.index);
    }

    // sanity check :: hunk markers come in pairs
    if ((hunkIndicies.length % 2) != 0) {
      callback(new Error('Sanity check failed: Hunk markers should come in pairs.'));
    }

    // parse out hunk properties
    var hunks = []
      , hunkMarkerLength = 2;

    for (var i = 0; i+hunkMarkerLength <= hunkIndicies.length; i+=hunkMarkerLength) {
      var startIdx = hunkIndicies[i]+hunkMarkerLength
        , endIdx = hunkIndicies[i+1]
        , hunkPropsParts = fileDiffText.substring(startIdx, endIdx).trim().split(' ');

      var hunkContent = (endIdx < hunkIndicies.length-1)
        ? fileDiffText.substring(endIdx+hunkMarkerLength, hunkIndicies[endIdx+1])
        : fileDiffText.substring(endIdx+hunkMarkerLength);

      var oldFilePropsParts = hunkPropsParts[0].split(',')
        , newFilePropsParts = hunkPropsParts[1].split(',');

      var hunkLines = hunkContent.split(os.EOL)
        , filteredHunkLines = [];

      hunkLines.forEach(function(line) {
        if (line.length > 0 && line[0] != '\\') { // no blank empty lines or end of file marker
          filteredHunkLines.push({
            action: line[0].trim(),
            text: line.substring(1).trim()
          });
        }
      });

      hunks.push({
        old: {
          from: parseInt(oldFilePropsParts[0].substring(1)),
          numLines: parseInt(oldFilePropsParts[1])
        },
        new: {
          from: parseInt(newFilePropsParts[0].substring(1)),
          numLines: parseInt(newFilePropsParts[1])
        },
        lines: filteredHunkLines
      });

      diffs[filePath] = {
        hunks: hunks
      };
    }
  });

  callback(null, diffs);
};

exports.parseFromFile = function(diffFile, callback) {
  fs.exists(diffFile, function (exists) {
    if (!exists) {
      return callback('No diff file located at ' + diffFile);
    }

    fs.readFile(diffFile, 'utf-8', function(err, contents) {
      exports.parseFromText(contents, callback);
    });
  });
};<|endoftext|>


<commit_before>'use strict';

const coinstacSimulator = require('coinstac-simulator');
const constants = require('./constants.json');
const cp = require('child_process');
const fs = require('fs');
const mkdirp = require('mkdirp');
const parseNumber = require('./parse-number');
const path = require('path');
const pify = require('pify');
const pkg = require('../package.json');
const program = require('commander');
const rimraf = require('rimraf');

const tmpPath = path.join(__dirname, '..', '.tmp');

function cleanup() {
  return pify(rimraf)(tmpPath);
}

program
  .version(pkg.version)
  .description(pkg.description)
  .option(
    '-c, --clients [value]',
    'Number of clients',
    parseNumber,
    constants.DEFAULT_CLIENT_COUNT)
  .option(
    '-i, --iterations [value]',
    'Number of computation iterations',
    parseNumber,
    constants.DEFAULT_ITERATION_COUNT
  )
  .parse(process.argv);

cleanup()
  .then(() => pify(mkdirp)(tmpPath))
  .then(() => {
    const writeFile = pify(fs.writeFile);

    return Promise.all([
      writeFile(path.join(tmpPath, 'clientCount'), program.clients),
      writeFile(path.join(tmpPath, 'iterationCount'), program.iterations),
      pify(cp.exec)(`mkfile -n 1m ${path.join(tmpPath, 'randomBytes')}`),
    ]);
  })
  .then(() => coinstacSimulator.run(path.join(__dirname, 'declaration.js')))
  .then(cleanup)
  .catch(error => console.error(error));

<commit_msg>Ensure temp dir cleanup happens on process exit.<commit_after>'use strict';

const coinstacSimulator = require('coinstac-simulator');
const constants = require('./constants.json');
const cp = require('child_process');
const fs = require('fs');
const mkdirp = require('mkdirp');
const parseNumber = require('./parse-number');
const path = require('path');
const pify = require('pify');
const pkg = require('../package.json');
const program = require('commander');
const rimraf = require('rimraf');

const tmpPath = path.join(__dirname, '..', '.tmp');

process.on('exit', () => rimraf.sync(tmpPath));

program
  .version(pkg.version)
  .description(pkg.description)
  .option(
    '-c, --clients [value]',
    'Number of clients',
    parseNumber,
    constants.DEFAULT_CLIENT_COUNT)
  .option(
    '-i, --iterations [value]',
    'Number of computation iterations',
    parseNumber,
    constants.DEFAULT_ITERATION_COUNT
  )
  .parse(process.argv);

pify(rimraf)(tmpPath)
  .then(() => pify(mkdirp)(tmpPath))
  .then(() => {
    const writeFile = pify(fs.writeFile);

    return Promise.all([
      writeFile(path.join(tmpPath, 'clientCount'), program.clients),
      writeFile(path.join(tmpPath, 'iterationCount'), program.iterations),
      pify(cp.exec)(`mkfile -n 1m ${path.join(tmpPath, 'randomBytes')}`),
    ]);
  })
  .then(() => coinstacSimulator.run(path.join(__dirname, 'declaration.js')))
  .catch(error => console.error(error));

<|endoftext|>


<commit_before>'use strict';

var EntitySchema = require('./EntitySchema'),
    ArraySchema = require('./ArraySchema'),
    isObject = require('lodash/lang/isObject'),
    isEqual = require('lodash/lang/isEqual');

function visitObject(obj, schema, bag) {
  var normalized = {};

  for (var prop in obj) {
    if (obj.hasOwnProperty(prop)) {
      normalized[prop] = visit(obj[prop], schema[prop], bag);
    }
  }

  return normalized;
}

function visitArray(obj, arraySchema, bag) {
  var itemSchema = arraySchema.getItemSchema(),
      normalized;

  normalized = obj.map(function (childObj) {
    return visit(childObj, itemSchema, bag);
  });

  return normalized;
}

function mergeIntoEntity(entityA, entityB, entityKey) {
  for (var prop in entityB) {
    if (!entityB.hasOwnProperty(prop)) {
      continue;
    }

    if (!entityA.hasOwnProperty(prop) || isEqual(entityA[prop], entityB[prop])) {
      entityA[prop] = entityB[prop];
      continue;
    }

    console.warn(
      'When merging two ' + entityKey + ', found shallowly unequal data in their "' + prop + '" values. Using the earlier value.',
      entityA[prop], entityB[prop]
    );
  }
}

function visitEntity(entity, entitySchema, bag) {
  var entityKey = entitySchema.getKey(),
      idAttribute = entitySchema.getIdAttribute(),
      id = entity[idAttribute],
      stored,
      normalized;

  if (!bag[entityKey]) {
    bag[entityKey] = {};
  }

  if (!bag[entityKey][id]) {
    bag[entityKey][id] = {};
  }

  stored = bag[entityKey][id];
  normalized = visitObject(entity, entitySchema, bag);

  mergeIntoEntity(stored, normalized, entityKey);

  return id;
}

function visit(obj, schema, bag) {
  if (!isObject(obj) || !isObject(schema)) {
    return obj;
  }

  if (schema instanceof EntitySchema) {
    return visitEntity(obj, schema, bag);
  } else if (schema instanceof ArraySchema) {
    return visitArray(obj, schema, bag);
  } else {
    return visitObject(obj, schema, bag);
  }
}

function normalize(obj, schema) {
  if (!isObject(obj) && !Array.isArray(obj)) {
    throw new Error('Normalize accepts an object or an array as its input.');
  }

  if (!isObject(schema) || Array.isArray(schema)) {
    throw new Error('Normalize accepts an object for schema.');
  }

  var bag = {},
      result = visit(obj, schema, bag);

  return {
    entities: bag,
    result: result
  };
}

function arrayOf(schema) {
  return new ArraySchema(schema);
}

module.exports = {
  Schema: EntitySchema,
  arrayOf: arrayOf,
  normalize: normalize
};
<commit_msg>Fix incorrect comment<commit_after>'use strict';

var EntitySchema = require('./EntitySchema'),
    ArraySchema = require('./ArraySchema'),
    isObject = require('lodash/lang/isObject'),
    isEqual = require('lodash/lang/isEqual');

function visitObject(obj, schema, bag) {
  var normalized = {};

  for (var prop in obj) {
    if (obj.hasOwnProperty(prop)) {
      normalized[prop] = visit(obj[prop], schema[prop], bag);
    }
  }

  return normalized;
}

function visitArray(obj, arraySchema, bag) {
  var itemSchema = arraySchema.getItemSchema(),
      normalized;

  normalized = obj.map(function (childObj) {
    return visit(childObj, itemSchema, bag);
  });

  return normalized;
}

function mergeIntoEntity(entityA, entityB, entityKey) {
  for (var prop in entityB) {
    if (!entityB.hasOwnProperty(prop)) {
      continue;
    }

    if (!entityA.hasOwnProperty(prop) || isEqual(entityA[prop], entityB[prop])) {
      entityA[prop] = entityB[prop];
      continue;
    }

    console.warn(
      'When merging two ' + entityKey + ', found unequal data in their "' + prop + '" values. Using the earlier value.',
      entityA[prop], entityB[prop]
    );
  }
}

function visitEntity(entity, entitySchema, bag) {
  var entityKey = entitySchema.getKey(),
      idAttribute = entitySchema.getIdAttribute(),
      id = entity[idAttribute],
      stored,
      normalized;

  if (!bag[entityKey]) {
    bag[entityKey] = {};
  }

  if (!bag[entityKey][id]) {
    bag[entityKey][id] = {};
  }

  stored = bag[entityKey][id];
  normalized = visitObject(entity, entitySchema, bag);

  mergeIntoEntity(stored, normalized, entityKey);

  return id;
}

function visit(obj, schema, bag) {
  if (!isObject(obj) || !isObject(schema)) {
    return obj;
  }

  if (schema instanceof EntitySchema) {
    return visitEntity(obj, schema, bag);
  } else if (schema instanceof ArraySchema) {
    return visitArray(obj, schema, bag);
  } else {
    return visitObject(obj, schema, bag);
  }
}

function normalize(obj, schema) {
  if (!isObject(obj) && !Array.isArray(obj)) {
    throw new Error('Normalize accepts an object or an array as its input.');
  }

  if (!isObject(schema) || Array.isArray(schema)) {
    throw new Error('Normalize accepts an object for schema.');
  }

  var bag = {},
      result = visit(obj, schema, bag);

  return {
    entities: bag,
    result: result
  };
}

function arrayOf(schema) {
  return new ArraySchema(schema);
}

module.exports = {
  Schema: EntitySchema,
  arrayOf: arrayOf,
  normalize: normalize
};
<|endoftext|>


<commit_before>
(function () {

  'use strict';

  function ColorChanger(elem, opt) {

    var originalData = getData(elem);
    var toData = getData(elem);
    var fromOpt = (typeof opt.from !== 'undefined') ? opt.from : { };
    var toOpt = (typeof opt.to !== 'undefined') ? opt.to : { };
    var extname = elem.src.split('.')[elem.src.split('.').length - 1];

    var rgba = ['r', 'g', 'b', 'a'];
    while(rgba.length) {
      var current = rgba.shift();
      if (!fromOpt.hasOwnProperty(current)) fromOpt[current] = {great: -1};
      if (!toOpt.hasOwnProperty(current)) toOpt[current] = {plus: 0};
    }

    var toData = getToData(toData, fromOpt, toOpt);

    this.changeColor = function () {
      setData(elem, toData, extname);
    }

    this.changeOriginal = function () {
      setData(elem, originalData, extname);
    }

  }

  function isInRange(d, from) {

    var rgba = ['r', 'g', 'b', 'a'];
    while(rgba.length) {

      var current = rgba.shift();
      var currentData = d[current];
      var currentFrom = from[current];

      if (typeof currentFrom === 'number') {
        if (currentData != currentFrom) return false;
      }
      else {
        if (currentFrom.hasOwnProperty('great')) {
          if (!(currentData > currentFrom.great)) return false;
        }
        if (currentFrom.hasOwnProperty('less')) {
          if (!(currentData < currentFrom.less)) return false;
        }
      }

    }

    return true;
  }

  function getD(d, t) {

    if(typeof t !== 'object') {
      return t;
    }
    else {

      var result = d;

      if (two.hasOwnProperty('plus')) result = result + t.plus;
      if (two.hasOwnProperty('minus')) result = result - t.minus;

      return result;
    }

  }

  function getToData(toData, fromOpt, toOpt) {

    for (var i = 0, l = toData.data.length; i < l; i = i + 4) {

      var d = {
        r: toData.data[i],
        g: toData.data[i + 1],
        b: toData.data[i + 2],
        a: toData.data[i + 3]
      };

      if (isInRange(d, fromOpt)) {
        toData.data[i] = setTemp(toData.data[i], toOpt.r);
        toData.data[i + 1] = getD(toData.data[i + 1], toOpt.g);
        toData.data[i + 2] = getD(toData.data[i + 2], toOpt.b);
        toData.data[i + 3] = getD(toData.data[i + 3], toOpt.a);
      }

    }

    return toData;
  }

  function getData(elem) {

    var data;

    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');

    canvas.width = elem.width;
    canvas.height = elem.height;

    ctx.drawImage(elem, 0, 0, elem.naturalWidth, elem.naturalHeight, 0, 0, elem.width, elem.height);
    data = ctx.getImageData(0, 0, elem.width, elem.height);

    elem.onload = false;

    return data;
  }

  function setData(elem, data, extname) {

    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');

    canvas.width = elem.width;
    canvas.height = elem.height;

    ctx.putImageData(data, 0, 0);
    elem.src = canvas.toDataURL('image/' + extname);

  }

  window.ColorChanger = ColorChanger;

})();
<commit_msg>fixed type errors<commit_after>
(function () {

  'use strict';

  function ColorChanger(elem, opt) {

    var originalData = getData(elem);
    var toData = getData(elem);
    var fromOpt = (typeof opt.from !== 'undefined') ? opt.from : { };
    var toOpt = (typeof opt.to !== 'undefined') ? opt.to : { };
    var extname = elem.src.split('.')[elem.src.split('.').length - 1];

    var rgba = ['r', 'g', 'b', 'a'];
    while(rgba.length) {
      var current = rgba.shift();
      if (!fromOpt.hasOwnProperty(current)) fromOpt[current] = {great: -1};
      if (!toOpt.hasOwnProperty(current)) toOpt[current] = {plus: 0};
    }

    var toData = getToData(toData, fromOpt, toOpt);

    this.changeColor = function () {
      setData(elem, toData, extname);
    }

    this.changeOriginal = function () {
      setData(elem, originalData, extname);
    }

  }

  function isInRange(d, from) {

    var rgba = ['r', 'g', 'b', 'a'];
    while(rgba.length) {

      var current = rgba.shift();
      var currentData = d[current];
      var currentFrom = from[current];

      if (typeof currentFrom === 'number') {
        if (currentData != currentFrom) return false;
      }
      else {
        if (currentFrom.hasOwnProperty('great')) {
          if (!(currentData > currentFrom.great)) return false;
        }
        if (currentFrom.hasOwnProperty('less')) {
          if (!(currentData < currentFrom.less)) return false;
        }
      }

    }

    return true;
  }

  function getD(d, t) {

    if(typeof t !== 'object') {
      return t;
    }
    else {

      var result = d;

      if (t.hasOwnProperty('plus')) result = result + t.plus;
      if (t.hasOwnProperty('minus')) result = result - t.minus;

      return result;
    }

  }

  function getToData(toData, fromOpt, toOpt) {

    for (var i = 0, l = toData.data.length; i < l; i = i + 4) {

      var d = {
        r: toData.data[i],
        g: toData.data[i + 1],
        b: toData.data[i + 2],
        a: toData.data[i + 3]
      };

      if (isInRange(d, fromOpt)) {
        toData.data[i] = getD(toData.data[i], toOpt.r);
        toData.data[i + 1] = getD(toData.data[i + 1], toOpt.g);
        toData.data[i + 2] = getD(toData.data[i + 2], toOpt.b);
        toData.data[i + 3] = getD(toData.data[i + 3], toOpt.a);
      }

    }

    return toData;
  }

  function getData(elem) {

    var data;

    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');

    canvas.width = elem.width;
    canvas.height = elem.height;

    ctx.drawImage(elem, 0, 0, elem.naturalWidth, elem.naturalHeight, 0, 0, elem.width, elem.height);
    data = ctx.getImageData(0, 0, elem.width, elem.height);

    elem.onload = false;

    return data;
  }

  function setData(elem, data, extname) {

    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');

    canvas.width = elem.width;
    canvas.height = elem.height;

    ctx.putImageData(data, 0, 0);
    elem.src = canvas.toDataURL('image/' + extname);

  }

  window.ColorChanger = ColorChanger;

})();
<|endoftext|>


<commit_before>'use strict';

var validator = require('ajv');
var debug = require('debug')('canornot');
//var validator = require('is-my-json-valid');
//var validator = require('jsen');

var _ = {
    defaultsDeep: require('lodash.defaultsdeep'),
    omit: require('lodash.omit')
};

function PermissionError(message) {
    Error.captureStackTrace(this, this.constructor);
    this.name = this.constructor.name;
    this.message = message;
}

require('util').inherits(PermissionError, Error);

module.exports = function Canoronot(options) {

    options = _.defaultsDeep(options || {}, {
        rejectOnError: true,
        rejectOnPermissionDenied: true
    });

    /**
     * @returns {Promise<Object>}
     */
    function getPolicySchema() {
        if (typeof options.policySchema === 'function') {

            // accepts a callback arguments
            if (options.policySchema.length === 1) {
                return new Promise(function (resolve, reject) {

                    return options.policySchema(function (result) {
                        if (result instanceof Error) {
                            reject(result);
                        } else {
                            resolve(result);
                        }
                    });
                });
            } else {
                return Promise.resolve(options.policySchema());
            }

        } else if (typeof options.policySchema === 'object' && typeof options.policySchema.then === 'function') {
            return options.policySchema;
        } else {
            return Promise.resolve(options.policySchema);
        }
    }

    /**
     * @returns {Promise<Object>}
     */
    function getActorSchema() {
        if (typeof options.actorSchema === 'function') {

            // accepts a callback arguments
            if (options.actorSchema.length === 1) {
                return new Promise(function (resolve, reject) {

                    return options.actorSchema(function (result) {
                        if (result instanceof Error) {
                            reject(result);
                        } else {
                            resolve(result);
                        }
                    });
                });
            } else {
                return Promise.resolve(options.actorSchema());
            }

        } else if (typeof options.actorSchema === 'object' && typeof options.actorSchema.then === 'function') {
            return options.actorSchema;
        } else {
            return Promise.resolve(options.actorSchema);
        }
    }

    /**
     * @returns {Promise}
     */
    function init() {

        return Promise.resolve();

        // return Promise.all([getActorSchema(), getPolicySchema()])
        //     .then(function (results) {
        //
        //         var actorSchema = results[0];
        //         var policySchema = results[1];
        //
        //         if (typeof actorSchema !== 'object') {
        //             throw new TypeError('Actor Schema must be an object or a function/promise that returns an object. Saw ' + typeof actorSchema);
        //         }
        //
        //         if (typeof policySchema !== 'object') {
        //             throw new TypeError('Policy Schema must be an object or a function/promise that returns an object. Saw ' + typeof policySchema);
        //         }
        //
        //         if (!loaded) {
        //             try {
        //                 console.log('adding actor schema');
        //                 validator.addSchema(actorSchema, 'actor');
        //                 console.log('adding policy schema');
        //                 validator.addSchema(policySchema, 'policy');
        //                 loaded = true;
        //             } catch (err) {
        //                 console.log('kakked it', err.message);
        //                 throw new Error('Failed to add policy or actor schema: ' + err.message);
        //
        //             }
        //         } else {
        //             console.log('policies already loaded');
        //         }
        //
        //     });
    }

    /**
     * @param {String} permission
     * @param {*} data
     * @returns {Promise.<Boolean>}
     */
    this.can = function (permission, data) {

        if (typeof permission !== 'string') {
            return Promise.reject(new TypeError('Permission must be a string'));
        }

        return init()
            .then(function () {

                // AJV
                return Promise.all([getActorSchema(), getPolicySchema()])
                    .then(function (results) {

                        var actorSchema = results[0];
                        var policySchema = results[1];

                        if (typeof actorSchema !== 'object') {
                            throw new TypeError('Actor Schema must be an object or a function/promise that returns an object. Saw ' + typeof actorSchema);
                        }

                        if (typeof policySchema !== 'object') {
                            throw new TypeError('Policy Schema must be an object or a function/promise that returns an object. Saw ' + typeof policySchema);
                        }

                        var ajv = validator({
                            breakOnError: true
                            //allErrors: true,
                            //v5: true
                        });

                        ajv.addSchema(actorSchema, 'actor');
                        ajv.addSchema(policySchema, 'policy');

                        var validate = ajv.compile({
                            $ref: 'policy#/properties/' + permission
                        });

                        var valid = validate(data);

                        debug('Permission `%s` against data `%s` - allowed: `%s`', permission, JSON.stringify(data), valid);

                        debug('rejectOnPermissionDenied: `%s`', options.rejectOnPermissionDenied);

                        if (options.rejectOnPermissionDenied === true) {
                            if (!valid) {
                                debug('Throwing PermissionError', validate.errors);
                                var err = new PermissionError('Permission Denied for `' + permission + '` against `' + JSON.stringify(data) + '`');
                                err.errors = validate.errors;
                                throw err;
                            } else {
                                return valid;
                            }
                        } else {
                            debug('Returning `%s` result: %s', permission, valid);
                            return valid;
                        }

                    });

                // IS MY JSON VALID
                // return Promise.all([getPolicySchema(), getActorSchema()])
                //     .then(function (results) {
                //
                //         var actorSchema = results[0];
                //         var policySchema = results[1];
                //
                //         var validate = validator({
                //             $ref: 'policy#/properties/' + permission
                //         }, {
                //             // verbose: true,
                //             // greedy: true,
                //             schemas: {
                //                 policy: policySchema,
                //                 actor: actorSchema
                //             }
                //         });
                //
                //         console.log('validating', data);
                //         console.info('config', {
                //             $ref: 'policy#/properties/' + permission
                //         }, {
                //             // verbose: true,
                //             // greedy: true,
                //             schemas: {
                //                 policy: policySchema,
                //                 actor: actorSchema
                //             }
                //         });
                //
                //         return validate(data);
                //
                //     });

                // JSEN
                // return Promise.all([getPolicySchema(), getActorSchema()])
                //     .then(function (results) {
                //
                //         var actorSchema = results[0];
                //         var policySchema = results[1];
                //
                //         var validate = validator({
                //             $ref: '#policy/properties/' + permission
                //         }, {
                //             missing$Ref: true,
                //             schemas: {
                //                 policy: policySchema,
                //                 actor: actorSchema
                //             }
                //         });
                //
                //         var valid = validate(data);
                //
                //         return valid;
                //
                //     });

            })
            .catch(function (err) {

                // it's not a basic permission error;
                if (err instanceof PermissionError && options.rejectOnPermissionDenied === true) {
                    throw err;
                } else {
                    if (options.rejectOnError === true) {
                        throw err;
                    } else {
                        return false;
                    }
                }

            });
    };

    this.has = this.can;

};

// so we can access the validator from outside the scope - nice for testing.
module.exports.validator = validator;
<commit_msg>Support for returning schemas when permission is allowed<commit_after>'use strict';

var validator = require('ajv');
var debug = require('debug')('canornot');
//var validator = require('is-my-json-valid');
//var validator = require('jsen');

var _ = {
    defaultsDeep: require('lodash.defaultsdeep'),
    omit: require('lodash.omit')
};

function PermissionError(message) {
    Error.captureStackTrace(this, this.constructor);
    this.name = this.constructor.name;
    this.message = message;
}

require('util').inherits(PermissionError, Error);

module.exports = function Canoronot(options) {

    options = _.defaultsDeep(options || {}, {
        rejectOnError: true,
        rejectOnPermissionDenied: true,
        returnSchemas: false
    });

    /**
     * @returns {Promise<Object>}
     */
    function getPolicySchema() {
        if (typeof options.policySchema === 'function') {

            // accepts a callback arguments
            if (options.policySchema.length === 1) {
                return new Promise(function (resolve, reject) {

                    return options.policySchema(function (result) {
                        if (result instanceof Error) {
                            reject(result);
                        } else {
                            resolve(result);
                        }
                    });
                });
            } else {
                return Promise.resolve(options.policySchema());
            }

        } else if (typeof options.policySchema === 'object' && typeof options.policySchema.then === 'function') {
            return options.policySchema;
        } else {
            return Promise.resolve(options.policySchema);
        }
    }

    /**
     * @returns {Promise<Object>}
     */
    function getActorSchema() {
        if (typeof options.actorSchema === 'function') {

            // accepts a callback arguments
            if (options.actorSchema.length === 1) {
                return new Promise(function (resolve, reject) {

                    return options.actorSchema(function (result) {
                        if (result instanceof Error) {
                            reject(result);
                        } else {
                            resolve(result);
                        }
                    });
                });
            } else {
                return Promise.resolve(options.actorSchema());
            }

        } else if (typeof options.actorSchema === 'object' && typeof options.actorSchema.then === 'function') {
            return options.actorSchema;
        } else {
            return Promise.resolve(options.actorSchema);
        }
    }

    /**
     * @returns {Promise}
     */
    function init() {

        return Promise.resolve();

        // return Promise.all([getActorSchema(), getPolicySchema()])
        //     .then(function (results) {
        //
        //         var actorSchema = results[0];
        //         var policySchema = results[1];
        //
        //         if (typeof actorSchema !== 'object') {
        //             throw new TypeError('Actor Schema must be an object or a function/promise that returns an object. Saw ' + typeof actorSchema);
        //         }
        //
        //         if (typeof policySchema !== 'object') {
        //             throw new TypeError('Policy Schema must be an object or a function/promise that returns an object. Saw ' + typeof policySchema);
        //         }
        //
        //         if (!loaded) {
        //             try {
        //                 console.log('adding actor schema');
        //                 validator.addSchema(actorSchema, 'actor');
        //                 console.log('adding policy schema');
        //                 validator.addSchema(policySchema, 'policy');
        //                 loaded = true;
        //             } catch (err) {
        //                 console.log('kakked it', err.message);
        //                 throw new Error('Failed to add policy or actor schema: ' + err.message);
        //
        //             }
        //         } else {
        //             console.log('policies already loaded');
        //         }
        //
        //     });
    }

    /**
     * @param {String} permission
     * @param {*} data
     * @returns {Promise.<Boolean>}
     */
    this.can = function (permission, data) {

        if (typeof permission !== 'string') {
            return Promise.reject(new TypeError('Permission must be a string'));
        }

        return init()
            .then(function () {

                // AJV
                return Promise.all([getActorSchema(), getPolicySchema()])
                    .then(function (schemas) {

                        var actorSchema = schemas[0];
                        var policySchema = schemas[1];

                        if (typeof actorSchema !== 'object') {
                            throw new TypeError('Actor Schema must be an object or a function/promise that returns an object. Saw ' + typeof actorSchema);
                        }

                        if (typeof policySchema !== 'object') {
                            throw new TypeError('Policy Schema must be an object or a function/promise that returns an object. Saw ' + typeof policySchema);
                        }

                        var ajv = validator({
                            breakOnError: true
                        });

                        ajv.addSchema(actorSchema, 'actor');
                        ajv.addSchema(policySchema, 'policy');

                        var validate = ajv.compile({
                            $ref: 'policy#/properties/' + permission
                        });

                        var valid = validate(data);

                        debug('Permission `%s` against data `%s` - allowed: `%s`', permission, JSON.stringify(data), valid);

                        debug('rejectOnPermissionDenied: `%s`', options.rejectOnPermissionDenied);

                        if (options.rejectOnPermissionDenied === true) {
                            if (!valid) {
                                debug('Throwing PermissionError', validate.errors);
                                var err = new PermissionError('Permission Denied for `' + permission + '` against `' + JSON.stringify(data) + '`');
                                err.errors = validate.errors;
                                throw err;
                            } else {
                                return options.returnSchemas ? schemas : valid;
                            }
                        } else {
                            debug('Returning `%s` result: %s', permission, valid);
                            return valid;
                        }

                    });

                // IS MY JSON VALID
                // return Promise.all([getPolicySchema(), getActorSchema()])
                //     .then(function (results) {
                //
                //         var actorSchema = results[0];
                //         var policySchema = results[1];
                //
                //         var validate = validator({
                //             $ref: 'policy#/properties/' + permission
                //         }, {
                //             // verbose: true,
                //             // greedy: true,
                //             schemas: {
                //                 policy: policySchema,
                //                 actor: actorSchema
                //             }
                //         });
                //
                //         console.log('validating', data);
                //         console.info('config', {
                //             $ref: 'policy#/properties/' + permission
                //         }, {
                //             // verbose: true,
                //             // greedy: true,
                //             schemas: {
                //                 policy: policySchema,
                //                 actor: actorSchema
                //             }
                //         });
                //
                //         return validate(data);
                //
                //     });

                // JSEN
                // return Promise.all([getPolicySchema(), getActorSchema()])
                //     .then(function (results) {
                //
                //         var actorSchema = results[0];
                //         var policySchema = results[1];
                //
                //         var validate = validator({
                //             $ref: '#policy/properties/' + permission
                //         }, {
                //             missing$Ref: true,
                //             schemas: {
                //                 policy: policySchema,
                //                 actor: actorSchema
                //             }
                //         });
                //
                //         var valid = validate(data);
                //
                //         return valid;
                //
                //     });

            })
            .catch(function (err) {

                // it's not a basic permission error;
                if (err instanceof PermissionError && options.rejectOnPermissionDenied === true) {
                    throw err;
                } else {
                    if (options.rejectOnError === true) {
                        throw err;
                    } else {
                        return false;
                    }
                }

            });
    };

    this.has = this.can;

};

// so we can access the validator from outside the scope - nice for testing.
module.exports.validator = validator;
<|endoftext|>


<commit_before>'use strict';

var url          = require('url');
var path         = require('path');
var http         = require('http');
var fs           = require('fs');
var unzip        = require('unzip');
var postgresdb   = require('pg');
var ip           = require("ip");
var useOracle    = false;
var program      = require('commander');
var drivers      = new Object();
var connections  = new Object();
var express      = require('express')
var app          = express()
var timeout      = 0;
var init_drivers = false;
var port;
var hostaddress;
var typeOfSystem;
var centralHostAddress;
var centralHostPort;
var request      = require("request");

path.join(__dirname, '../public/blockly/blockly_compressed.js')
path.join(__dirname, '../public/blockly/blocks_compressed.js')
path.join(__dirname, '../public/yazz_blockly_blocks.js')
path.join(__dirname, '../public/yazz_blockly_generator.js')
path.join(__dirname, '../public/yazz_blockly_output_code.js')
path.join(__dirname, '../public/blockly/msg/js/en.js')
path.join(__dirname, '../public/jquery-1.9.1.min.js')
path.join(__dirname, '../public/jquery.zoomooz.js')
path.join(__dirname, '../public/blockly_helper.js')
path.join(__dirname, '../public/blockly.png')
path.join(__dirname, '../public/polyfill.min.js')
path.join(__dirname, '../src/oracle.js')
path.join(__dirname, '../src/postgres.js')
path.join(__dirname, '../public/blockly_setup.js')
path.join(__dirname, '../public/tether.min.js')
path.join(__dirname, '../public/bootstrap.min.js')
path.join(__dirname, '../public/bootstrap.min.css')
path.join(__dirname, '../public/es6-shim.js')
path.join(__dirname, '../public/vue_app.css')
path.join(__dirname, '../public/dist/build.js')
path.join(__dirname, '../oracle_driver.zip')

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

program
  .version('0.0.1')
  .option('-t, --type [type]', 'Add the specified type of app [type]', 'client')
  .option('-p, --port [port]', 'Which port should I listen on? [port]', parseInt)
  .option('-h, --host [host]', 'Server address of the central host [host]', 'yazz.com')
  .option('-s, --hostport [hostport]', 'Server port of the central host [hostport]', parseInt)
  .parse(process.argv);

  port = program.port;
  if (!isNumber(port)) {port = 80;};
  typeOfSystem = program.type;
  centralHostAddress = program.host;
  centralHostPort = program.hostport;
  if (!isNumber(centralHostPort)) {centralHostPort = 80;};

  if (!(typeOfSystem == 'client' || typeOfSystem == 'server')) {
      console.log('-------* Invalid system type: ' + typeOfSystem);
      process.exit();
  };
  console.log('-------* System type: ' + typeOfSystem);
  console.log('-------* Port: ' + port);
  console.log('-------* Central host: ' + centralHostAddress);
  console.log('-------* Central host port: ' + centralHostPort);

console.dir ( ip.address() );

console.log('addr: '+ ip.address());
hostaddress = ip.address();

//------------------------------------------------------------
// copy the oracle files if they exist
//------------------------------------------------------------
if (fs.existsSync(path.join(__dirname, '../oracle_driver.zip'))) {
    useOracle = true;
}
if (useOracle) {
    if (!fs.existsSync(process.cwd() + '\\oracle_driver\\instantclient32')) {
      fs.createReadStream(path.join(__dirname, '../oracle_driver.zip')).pipe(unzip.Extract({ path: process.cwd() + '\\.' }));
      timeout = 3000;
      console.log('Creating oracle_driver');
    } else {
      console.log('oracle_driver already exists');
    };
}
var toeval = fs.readFileSync(path.join(__dirname, './oracle.js')).toString();
if (useOracle) {
    process.env['PATH'] = process.cwd() + '\\oracle_driver\\instantclient32' + ';' + process.env['PATH'];
}

//------------------------------------------------------------
// postgres
//------------------------------------------------------------
var pgeval = fs.readFileSync(path.join(__dirname, './postgres.js')).toString();

//------------------------------------------------------------
// wait three seconds for stuff to initialize
//------------------------------------------------------------
setTimeout(startYazz, timeout);
console.log('Creating timeout: ' + timeout);

//------------------------------------------------------------
// wait three seconds for stuff to initialize
//------------------------------------------------------------
function startYazz() {
  //
  // start the server
  //
  var Gun = require('gun');
  var gun = Gun({
    file: 'data.json',
    s3: {
      key: '', // AWS Access Key
      secret: '', // AWS Secret Token
      bucket: '' // The bucket you want to save into
    }
  });

  gun.wsp(app);

  console.log(typeOfSystem + ' started on port ' + port + ' with /gun');

  app.get('/', function (req, res) {
      if (!init_drivers) {
        init_drivers = true;
        if (useOracle) {
             eval(toeval);
        }
        eval(pgeval);

      };

      if (typeOfSystem == 'client') {
          res.end(fs.readFileSync(path.join(__dirname, '../public/index.html')));
      }
      if (typeOfSystem == 'server') {
          res.end(fs.readFileSync(path.join(__dirname, '../public/index_server.html')));
      }
  })

app.use(express.static(path.join(__dirname, '../public/')))

  app.get('/getresult', function (req, res) {
    var queryData = url.parse(req.url, true).query;
    //console.log('request received: ' + queryData.sql);
    if (connections[queryData.source]) {
        //console.log('query driver: ' + connections[queryData.source].driver);
        drivers[connections[queryData.source].driver]['get'](connections[queryData.source],queryData.sql,function(ordata) {
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.end(JSON.stringify(ordata));
        });
    } else {
        console.log('query driver not found: ' + connections[queryData.source]);
    };
})

var requestClientInternalHostAddress = '';
var requestClientInternalPort        = -1;
var requestClientPublicIp            = '';
var requestClientPublicHostName      = '';

//------------------------------------------------------------------------------
// This is called by the central server to get the details of the last
// client that connected tp the central server
//------------------------------------------------------------------------------
app.get('/get_connect', function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end(
            JSON.stringify(
                {
                    requestClientInternalHostAddress: requestClientInternalHostAddress
                    ,
                    requestClientInternalPort:        requestClientInternalPort
                    ,
                    requestClientPublicIp:            requestClientPublicIp
                    ,
                    requestClientPublicHostName:      requestClientPublicHostName
                    ,
                    version:      1
                }
          ));
})

//app.enable('trust proxy')

//------------------------------------------------------------------------------
// This is where the client sends its details to the central server
//------------------------------------------------------------------------------
app.get('/client_connect', function (req, res) {
    var queryData = url.parse(req.url, true).query;

    requestClientInternalHostAddress = req.query.requestClientInternalHostAddress;
    requestClientInternalPort        = req.query.requestClientInternalPort;
    requestClientPublicIp            = req.ip;
    //requestClientPublicHostName      = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
    requestClientPublicHostName      = req.headers['x-forwarded-for'] || req.connection.remoteAddress;

    console.log('Client attempting to connect from:');
    console.log('client internal host address:    ' + requestClientInternalHostAddress)
    console.log('client internal port:            ' + requestClientInternalPort)
    console.log('client public IP address:        ' + requestClientPublicIp)
    console.log('client public IP host name:      ' + requestClientPublicHostName)

})

app.listen(port, hostaddress, function () {
    console.log('Example app listening on port ' + port + '!')
})

  //
  // open the app in a web browser
  //
  //console.log('Ran postgres too');

  var open = require('open');

  open('http://' + hostaddress  + ":" + port);

  //process.env['PATH'] = path.join(__dirname, '/instantclient') + ';' + process.env['PATH'];
  //var oracledb = require('oracledb');
  //console.log('Start oracle');

  //eval("oracledb= require('oracledb');");

  console.log('addr: '+ hostaddress + ":" + port);

  //console.log(toeval);
  //setTimeout(function(){eval(toeval)},1000);

  //  console.log('Done.');

  console.log("*********** CHECKING CONNECTIONS *****************8");
  var connectionrows        = new Object();
  gun.get("connections").on().map(function(a,b){
    delete a["_"];
    if (!connectionrows[a.id]) {
      //data_connections_list.push(a);
      connectionrows[a.id] = a;
      //console.log(a);
      connections[a.id] = a;
    }

  },true);

    if (typeOfSystem == 'client') {
        var urlToConnectTo = "http://" + centralHostAddress + ":" + centralHostPort + '/client_connect';
        console.log('-------* urlToConnectTo: ' + urlToConnectTo);
        console.log('trying to connect to central server...');
        request({
              uri: urlToConnectTo,
              method: "GET",
              timeout: 10000,
              followRedirect: true,
              maxRedirects: 10,
              qs: {
                  requestClientInternalHostAddress: hostaddress
                  ,
                  requestClientInternalPort:        port
              }
            },
            function(error, response, body) {
                console.log(body);
            });
    }

}
<commit_msg>try just the remote address<commit_after>'use strict';

var url          = require('url');
var path         = require('path');
var http         = require('http');
var fs           = require('fs');
var unzip        = require('unzip');
var postgresdb   = require('pg');
var ip           = require("ip");
var useOracle    = false;
var program      = require('commander');
var drivers      = new Object();
var connections  = new Object();
var express      = require('express')
var app          = express()
var timeout      = 0;
var init_drivers = false;
var port;
var hostaddress;
var typeOfSystem;
var centralHostAddress;
var centralHostPort;
var request      = require("request");

path.join(__dirname, '../public/blockly/blockly_compressed.js')
path.join(__dirname, '../public/blockly/blocks_compressed.js')
path.join(__dirname, '../public/yazz_blockly_blocks.js')
path.join(__dirname, '../public/yazz_blockly_generator.js')
path.join(__dirname, '../public/yazz_blockly_output_code.js')
path.join(__dirname, '../public/blockly/msg/js/en.js')
path.join(__dirname, '../public/jquery-1.9.1.min.js')
path.join(__dirname, '../public/jquery.zoomooz.js')
path.join(__dirname, '../public/blockly_helper.js')
path.join(__dirname, '../public/blockly.png')
path.join(__dirname, '../public/polyfill.min.js')
path.join(__dirname, '../src/oracle.js')
path.join(__dirname, '../src/postgres.js')
path.join(__dirname, '../public/blockly_setup.js')
path.join(__dirname, '../public/tether.min.js')
path.join(__dirname, '../public/bootstrap.min.js')
path.join(__dirname, '../public/bootstrap.min.css')
path.join(__dirname, '../public/es6-shim.js')
path.join(__dirname, '../public/vue_app.css')
path.join(__dirname, '../public/dist/build.js')
path.join(__dirname, '../oracle_driver.zip')

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

program
  .version('0.0.1')
  .option('-t, --type [type]', 'Add the specified type of app [type]', 'client')
  .option('-p, --port [port]', 'Which port should I listen on? [port]', parseInt)
  .option('-h, --host [host]', 'Server address of the central host [host]', 'yazz.com')
  .option('-s, --hostport [hostport]', 'Server port of the central host [hostport]', parseInt)
  .parse(process.argv);

  port = program.port;
  if (!isNumber(port)) {port = 80;};
  typeOfSystem = program.type;
  centralHostAddress = program.host;
  centralHostPort = program.hostport;
  if (!isNumber(centralHostPort)) {centralHostPort = 80;};

  if (!(typeOfSystem == 'client' || typeOfSystem == 'server')) {
      console.log('-------* Invalid system type: ' + typeOfSystem);
      process.exit();
  };
  console.log('-------* System type: ' + typeOfSystem);
  console.log('-------* Port: ' + port);
  console.log('-------* Central host: ' + centralHostAddress);
  console.log('-------* Central host port: ' + centralHostPort);

console.dir ( ip.address() );

console.log('addr: '+ ip.address());
hostaddress = ip.address();

//------------------------------------------------------------
// copy the oracle files if they exist
//------------------------------------------------------------
if (fs.existsSync(path.join(__dirname, '../oracle_driver.zip'))) {
    useOracle = true;
}
if (useOracle) {
    if (!fs.existsSync(process.cwd() + '\\oracle_driver\\instantclient32')) {
      fs.createReadStream(path.join(__dirname, '../oracle_driver.zip')).pipe(unzip.Extract({ path: process.cwd() + '\\.' }));
      timeout = 3000;
      console.log('Creating oracle_driver');
    } else {
      console.log('oracle_driver already exists');
    };
}
var toeval = fs.readFileSync(path.join(__dirname, './oracle.js')).toString();
if (useOracle) {
    process.env['PATH'] = process.cwd() + '\\oracle_driver\\instantclient32' + ';' + process.env['PATH'];
}

//------------------------------------------------------------
// postgres
//------------------------------------------------------------
var pgeval = fs.readFileSync(path.join(__dirname, './postgres.js')).toString();

//------------------------------------------------------------
// wait three seconds for stuff to initialize
//------------------------------------------------------------
setTimeout(startYazz, timeout);
console.log('Creating timeout: ' + timeout);

//------------------------------------------------------------
// wait three seconds for stuff to initialize
//------------------------------------------------------------
function startYazz() {
  //
  // start the server
  //
  var Gun = require('gun');
  var gun = Gun({
    file: 'data.json',
    s3: {
      key: '', // AWS Access Key
      secret: '', // AWS Secret Token
      bucket: '' // The bucket you want to save into
    }
  });

  gun.wsp(app);

  console.log(typeOfSystem + ' started on port ' + port + ' with /gun');

  app.get('/', function (req, res) {
      if (!init_drivers) {
        init_drivers = true;
        if (useOracle) {
             eval(toeval);
        }
        eval(pgeval);

      };

      if (typeOfSystem == 'client') {
          res.end(fs.readFileSync(path.join(__dirname, '../public/index.html')));
      }
      if (typeOfSystem == 'server') {
          res.end(fs.readFileSync(path.join(__dirname, '../public/index_server.html')));
      }
  })

app.use(express.static(path.join(__dirname, '../public/')))

  app.get('/getresult', function (req, res) {
    var queryData = url.parse(req.url, true).query;
    //console.log('request received: ' + queryData.sql);
    if (connections[queryData.source]) {
        //console.log('query driver: ' + connections[queryData.source].driver);
        drivers[connections[queryData.source].driver]['get'](connections[queryData.source],queryData.sql,function(ordata) {
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.end(JSON.stringify(ordata));
        });
    } else {
        console.log('query driver not found: ' + connections[queryData.source]);
    };
})

var requestClientInternalHostAddress = '';
var requestClientInternalPort        = -1;
var requestClientPublicIp            = '';
var requestClientPublicHostName      = '';

//------------------------------------------------------------------------------
// This is called by the central server to get the details of the last
// client that connected tp the central server
//------------------------------------------------------------------------------
app.get('/get_connect', function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end(
            JSON.stringify(
                {
                    requestClientInternalHostAddress: requestClientInternalHostAddress
                    ,
                    requestClientInternalPort:        requestClientInternalPort
                    ,
                    requestClientPublicIp:            requestClientPublicIp
                    ,
                    requestClientPublicHostName:      requestClientPublicHostName
                    ,
                    version:      2
                }
          ));
})

//app.enable('trust proxy')

//------------------------------------------------------------------------------
// This is where the client sends its details to the central server
//------------------------------------------------------------------------------
app.get('/client_connect', function (req, res) {
    var queryData = url.parse(req.url, true).query;

    requestClientInternalHostAddress = req.query.requestClientInternalHostAddress;
    requestClientInternalPort        = req.query.requestClientInternalPort;
    requestClientPublicIp            = req.ip;
    //requestClientPublicHostName      = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
    requestClientPublicHostName      = req.connection.remoteAddress;

    console.log('Client attempting to connect from:');
    console.log('client internal host address:    ' + requestClientInternalHostAddress)
    console.log('client internal port:            ' + requestClientInternalPort)
    console.log('client public IP address:        ' + requestClientPublicIp)
    console.log('client public IP host name:      ' + requestClientPublicHostName)

})

app.listen(port, hostaddress, function () {
    console.log('Example app listening on port ' + port + '!')
})

  //
  // open the app in a web browser
  //
  //console.log('Ran postgres too');

  var open = require('open');

  open('http://' + hostaddress  + ":" + port);

  //process.env['PATH'] = path.join(__dirname, '/instantclient') + ';' + process.env['PATH'];
  //var oracledb = require('oracledb');
  //console.log('Start oracle');

  //eval("oracledb= require('oracledb');");

  console.log('addr: '+ hostaddress + ":" + port);

  //console.log(toeval);
  //setTimeout(function(){eval(toeval)},1000);

  //  console.log('Done.');

  console.log("*********** CHECKING CONNECTIONS *****************8");
  var connectionrows        = new Object();
  gun.get("connections").on().map(function(a,b){
    delete a["_"];
    if (!connectionrows[a.id]) {
      //data_connections_list.push(a);
      connectionrows[a.id] = a;
      //console.log(a);
      connections[a.id] = a;
    }

  },true);

    if (typeOfSystem == 'client') {
        var urlToConnectTo = "http://" + centralHostAddress + ":" + centralHostPort + '/client_connect';
        console.log('-------* urlToConnectTo: ' + urlToConnectTo);
        console.log('trying to connect to central server...');
        request({
              uri: urlToConnectTo,
              method: "GET",
              timeout: 10000,
              followRedirect: true,
              maxRedirects: 10,
              qs: {
                  requestClientInternalHostAddress: hostaddress
                  ,
                  requestClientInternalPort:        port
              }
            },
            function(error, response, body) {
                console.log(body);
            });
    }

}
<|endoftext|>


<commit_before>import Model from './Model';
import StateTracker from './StateTracker';

export {
  Model,
  StateTracker,
};
<commit_msg>add Scenario export<commit_after>import Model from './Model';
import StateTracker from './StateTracker';
import Scenario from './Scenario';

export {
  Model,
  StateTracker,
  Scenario
};
<|endoftext|>