<commit_before>

function sortIx( a, b ) { return b.parameter - a.parameter; }

function splitPath( _ixs, other ) {
	other = other || false;
	var i, j, k, l, len, ixs, ix, path, crv, vals;
	var ixPoint, nuSeg;
	var paths = [], lastPathId = null;
	for (i = 0, l = _ixs.length; i < l; i++) {
		ix = ( other )? _ixs[i]._ixPair : _ixs[i];
		if( ix.path.id !== lastPathId ){
			paths.push( ix.path );
			lastPathId = ix.path.id;
		}
		if( !ix.curve._ixParams ){ix.curve._ixParams = []; }
		ix.curve._ixParams.push( { parameter: ix.parameter, pair: ix._ixPair } );
	}
	for (k = 0, len = paths.length; k < len; k++) {
		path = paths[k];
		var lastNode = path.lastSegment, firstNode = path.firstSegment;
		var nextNode = null, left = null, right = null, parts = null, isLinear;
		var handleIn, handleOut;
		while( nextNode !== firstNode){
			nextNode = ( nextNode )? nextNode.previous: lastNode;
			if( nextNode.curve._ixParams ){
				ixs = nextNode.curve._ixParams;
				ixs.sort( sortIx );
				crv = nextNode.curve;
				isLinear = crv.isLinear();
				crv = vals = null;
				for (i = 0, l = ixs.length; i < l; i++) {
					ix = ixs[i];
					crv = nextNode.curve;
					if( !vals ) vals = crv.getValues();
					parts = Curve.subdivide( vals, ix.parameter );
					left = parts[0];
					right = parts[1];
					handleIn = handleOut = null;
					if( !isLinear ){
						crv.segment1.handleOut = new Point( left[2] - left[0], left[3] - left[1] );
						crv.segment2.handleIn = new Point( right[4] - right[6], right[5] - right[7] );
						handleIn = new Point( left[4] - ixPoint.x, left[5] - ixPoint.y );
						handleOut = new Point( right[2] - ixPoint.x, right[3] - ixPoint.y );
					}
					ixPoint = new Point( right[0], right[1] );
					nuSeg = new Segment( ixPoint, handleIn, handleOut );
					nuSeg._ixPair = ix.pair;
					nuSeg._ixPair._segment = nuSeg;

					path.insert( nextNode.index + 1,  nuSeg );
					// nextNode = nuSeg;
					for (j = i + 1; j < l; j++) {
						ixs[j].parameter = ixs[j].parameter / ix.parameter;
					}
					vals = left;
				}
			}
		}
	}
}

/**
 * To deal with a HTML canvas requirement where CompoundPaths' child contours
 * has to be of different winding direction for correctly filling holes.
 * But if some individual countours are disjoint, i.e. islands, we have to
 * reorient them so that
 *   the holes have opposit winding direction ( already handled by paperjs )
 *   islands has to have same winding direction ( as the first child of the path )
 *
 * Does NOT handle selfIntersecting CompoundPaths.
 *
 * @param  {CompoundPath} path - Input CompoundPath, Note: This path could be modified if need be.
 * @return {boolean}      the winding direction of the base contour( true if clockwise )
 */
 function reorientCompoundPath( path ){
	if( !(path instanceof CompoundPath) ){ return path.clockwise; }
	var children = path.children, len = children.length, baseWinding;
	var bounds = new Array( len );
	var tmparray = new Array( len );
	baseWinding = children[0].clockwise;
	// Omit the first path
	for (i = 0; i < len; i++) {
		bounds[i] = children[i].bounds;
		tmparray[i] = 0;
	}
	for (i = 0; i < len; i++) {
		var p1 = children[i];
		for (j = 0; j < len; j++) {
			var p2 = children[j];
			if( i !== j && bounds[i].contains( bounds[j] ) ){
				tmparray[j]++;
			}
		}
	}
	for (i = 1; i < len; i++) {
		if ( tmparray[i] % 2 === 0 ) {
			children[i].clockwise = baseWinding;
		}
	}
	return baseWinding;
}

function computeBoolean( _path1, _path2, operator ){
	var path1Clockwise = reorientCompoundPath( _path1 );
	var path2Clockwise = reorientCompoundPath( _path2 );

	var ixs = _path1.getIntersections( _path2 );
	var path1Id = _path1.id;
	var path2Id = _path2.id;
	splitPath( ixs );
	splitPath( ixs, true );

	var i, j, len, path, crv;
	var paths;
	if( _path1 instanceof CompoundPath ){
		paths = _path1.children;
	} else {
		paths = [ _path1 ];
	}
	if( _path2 instanceof CompoundPath ){
		paths = paths.concat( _path2.children );
	} else {
		paths.push( _path2 );
	}

	// step 1: discard invalid links according to the boolean operator
	for (i = 0, len = paths.length; i < len; i++) {
		path = paths[i];
		var thisId = ( path.parent instanceof CompoundPath )? path.parent.id : path.id;
		var thisWinding = path.clockwise;
		var lastNode = path.lastSegment, firstNode = path.firstSegment;
		var nextNode = null, midPoint, insidePath1, insidePath2;
		while( nextNode !== firstNode){
			nextNode = ( nextNode )? nextNode.previous: lastNode;
			crv = nextNode.curve;
			midPoint = crv.getPoint( 0.5 );
			if( thisId !== path1Id ){
				contains = _path1.contains( midPoint );
				insidePath1 = (thisWinding === path1Clockwise)? contains :
				contains && !testOnCurve( _path1, midPoint );
			}
			if( thisId !== path2Id ){
				contains = _path2.contains( midPoint );
				insidePath2 = (thisWinding === path2Clockwise)? contains :
				contains && !testOnCurve( _path2, midPoint );
			}
			if( !operator( thisId === path1Id, insidePath1, insidePath2 ) ){
				crv._INVALID = true;
			}
		}
	}
}

function testOnCurve( path, point ){
  var res = 0;
  var crv = path.getCurves();
  var i = 0;
  var bounds = path._bounds;
  if( bounds && bounds.contains( point ) ){
    for( i = 0; i < crv.length && !res; i++ ){
      var crvi = crv[i];
      if( crvi.bounds.contains( point ) && crvi.getParameterOf( point ) ){
        res = 1;
      }
    }
  }
  return res;
}

function unite( path1, path2 ){
	var unionOp = function( isPath1, isInsidePath1, isInsidePath2 ){
	    return ( isInsidePath1 || isInsidePath2 )? false : true;
	};
	return computeBoolean( path1, path2, unionOp );
}
<commit_msg>Union kinda working. Need to figureout the base path<commit_after>

function sortIx( a, b ) { return b.parameter - a.parameter; }

function splitPath( _ixs, other ) {
	other = other || false;
	var i, j, k, l, len, ixs, ix, path, crv, vals;
	var ixPoint, nuSeg;
	var paths = [], lastPathId = null;
	for (i = 0, l = _ixs.length; i < l; i++) {
		ix = ( other )? _ixs[i]._ixPair : _ixs[i];
		if( ix.path.id !== lastPathId ){
			paths.push( ix.path );
			lastPathId = ix.path.id;
		}
		if( !ix.curve._ixParams ){ix.curve._ixParams = []; }
		ix.curve._ixParams.push( { parameter: ix.parameter, pair: ix._ixPair } );
	}
	for (k = 0, len = paths.length; k < len; k++) {
		path = paths[k];
		var lastNode = path.lastSegment, firstNode = path.firstSegment;
		var nextNode = null, left = null, right = null, parts = null, isLinear;
		var handleIn, handleOut;
		while( nextNode !== firstNode){
			nextNode = ( nextNode )? nextNode.previous: lastNode;
			if( nextNode.curve._ixParams ){
				ixs = nextNode.curve._ixParams;
				ixs.sort( sortIx );
				crv = nextNode.curve;
				isLinear = crv.isLinear();
				crv = vals = null;
				for (i = 0, l = ixs.length; i < l; i++) {
					ix = ixs[i];
					crv = nextNode.curve;
					if( !vals ) vals = crv.getValues();
					parts = Curve.subdivide( vals, ix.parameter );
					left = parts[0];
					right = parts[1];
					handleIn = handleOut = null;
					if( !isLinear ){
						crv.segment1.handleOut = new Point( left[2] - left[0], left[3] - left[1] );
						crv.segment2.handleIn = new Point( right[4] - right[6], right[5] - right[7] );
						handleIn = new Point( left[4] - ixPoint.x, left[5] - ixPoint.y );
						handleOut = new Point( right[2] - ixPoint.x, right[3] - ixPoint.y );
					}
					ixPoint = new Point( right[0], right[1] );
					nuSeg = new Segment( ixPoint, handleIn, handleOut );
					nuSeg._ixPair = ix.pair;
					nuSeg._ixPair._segment = nuSeg;

					path.insert( nextNode.index + 1,  nuSeg );
					// nextNode = nuSeg;
					for (j = i + 1; j < l; j++) {
						ixs[j].parameter = ixs[j].parameter / ix.parameter;
					}
					vals = left;
				}
			}
		}
	}
}

/**
 * To deal with a HTML canvas requirement where CompoundPaths' child contours
 * has to be of different winding direction for correctly filling holes.
 * But if some individual countours are disjoint, i.e. islands, we have to
 * reorient them so that
 *   the holes have opposit winding direction ( already handled by paperjs )
 *   islands has to have same winding direction ( as the first child of the path )
 *
 * Does NOT handle selfIntersecting CompoundPaths.
 *
 * @param  {CompoundPath} path - Input CompoundPath, Note: This path could be modified if need be.
 * @return {boolean}      the winding direction of the base contour( true if clockwise )
 */
 function reorientCompoundPath( path ){
 	if( !(path instanceof CompoundPath) ){ return path.clockwise; }
 	var children = path.children, len = children.length, baseWinding;
 	var bounds = new Array( len );
 	var tmparray = new Array( len );
 	baseWinding = children[0].clockwise;
	// Omit the first path
	for (i = 0; i < len; i++) {
		bounds[i] = children[i].bounds;
		tmparray[i] = 0;
	}
	for (i = 0; i < len; i++) {
		var p1 = children[i];
		for (j = 0; j < len; j++) {
			var p2 = children[j];
			if( i !== j && bounds[i].contains( bounds[j] ) ){
				tmparray[j]++;
			}
		}
	}
	for (i = 1; i < len; i++) {
		if ( tmparray[i] % 2 === 0 ) {
			children[i].clockwise = baseWinding;
		}
	}
	return baseWinding;
}

function computeBoolean( _path1, _path2, operator ){
	var path1Clockwise = reorientCompoundPath( _path1 );
	var path2Clockwise = reorientCompoundPath( _path2 );

	var ixs = _path1.getIntersections( _path2 );
	var path1Id = _path1.id;
	var path2Id = _path2.id;
	splitPath( ixs );
	splitPath( ixs, true );

	var i, j, len, path, crv;
	var paths;
	if( _path1 instanceof CompoundPath ){
		paths = _path1.children;
	} else {
		paths = [ _path1 ];
	}
	if( _path2 instanceof CompoundPath ){
		paths = paths.concat( _path2.children );
	} else {
		paths.push( _path2 );
	}

	// step 1: discard invalid links according to the boolean operator
	var lastNode, firstNode, nextNode, midPoint, insidePath1, insidePath2;
	var thisId, thisWinding;
	for (i = 0, len = paths.length; i < len; i++) {
		path = paths[i];
		thisId = ( path.parent instanceof CompoundPath )? path.parent.id : path.id;
		thisWinding = path.clockwise;
		lastNode = path.lastSegment;
		firstNode = path.firstSegment;
		nextNode = null;
		console.log( thisId, path1Id, path2Id )
		while( nextNode !== firstNode){
			nextNode = ( nextNode )? nextNode.previous: lastNode;
			crv = nextNode.curve;
			midPoint = crv.getPoint( 0.5 );
			if( thisId !== path1Id ){
				contains = _path1.contains( midPoint );
				insidePath1 = (thisWinding === path1Clockwise)? contains :
				contains && !testOnCurve( _path1, midPoint );
			}
			if( thisId !== path2Id ){
				contains = _path2.contains( midPoint );
				insidePath2 = (thisWinding === path2Clockwise)? contains :
				contains && !testOnCurve( _path2, midPoint );
			}
			if( !operator( thisId === path1Id, insidePath1, insidePath2 ) ){
				crv._INVALID = true;
			}
		}
	}

	// Final step: Retrieve the resulting paths from the graph
	var boolResult = new CompoundPath();
	boolResult.style = booleanStyle;
	var node, nuNode, nuPath, nodeList = [], handle;
	for (i = 0, len = paths.length; i < len; i++) {
		nodeList = nodeList.concat( paths[i].segments );
	}
	for (i = 0, len = nodeList.length; i < len; i++) {
		node = nodeList[i];
		if( node.curve._INVALID || node._visited ){ continue; }
		path = node.path;
		thisId = ( path.parent instanceof CompoundPath )? path.parent.id : path.id;
		thisWinding = path.clockwise;
		nuPath = new Path();
	// nuPath.selected = true;
		firstNode = null;
		while( node && !node._visited ){
			node._visited = true;
			firstNode = ( firstNode )? firstNode: node;
			if( node._ixPair ) {
				// node._ixPair is this node's intersection CurveLocation object
				// node._ixPair._ixPair is the other CurveLocation object this node intersects with
				nextNode = ( node.curve._INVALID )? node._ixPair._ixPair._segment : node;
				nextNode._visited = true;
				nuNode = new Segment( node.point, node.handleIn, nextNode.handleOut );
				nuPath.add( nuNode );
				node = nextNode;
				path = node.path;
				thisWinding = path.clockwise;
			} else {
				nuPath.add( node );
			}
			node = node.next;
			view.draw();
		}
		nuPath.closed = true;
		boolResult.addChild( nuPath );
	}

	window.pp = boolResult.reduce();

	return boolResult.reduce();
}

function testOnCurve( path, point ){
	var res = 0;
	var crv = path.getCurves();
	var i = 0;
	var bounds = path._bounds;
	if( bounds && bounds.contains( point ) ){
		for( i = 0; i < crv.length && !res; i++ ){
			var crvi = crv[i];
			if( crvi.bounds.contains( point ) && crvi.getParameterOf( point ) ){
				res = 1;
			}
		}
	}
	return res;
}

function unite( path1, path2 ){
	var unionOp = function( isPath1, isInsidePath1, isInsidePath2 ){
		this.type = 1;
		return ( isInsidePath1 || isInsidePath2 )? false : true;
	};
	return computeBoolean( path1, path2, unionOp );
}
<|endoftext|>


<commit_before>/* global BigNumber, tsUtils */
(function () {
    'use strict';

    /**
     *
     * @param {Base} Base
     * @param {IPollCreate} createPoll
     * @param {JQuery} $element
     * @param {Waves} waves
     * @param {DexDataService} dexDataService
     * @param {app.utils} utils
     * @param {$rootScope.Scope} $scope
     * @param {function(path: string): Promise<string>} $templateRequest
     * @param {DataFeed} dataFeed
     * @return {OrderBook}
     */
    const controller = function (Base, createPoll, $element, waves, dexDataService, utils, $scope, $templateRequest,
                                 dataFeed) {

        const SECTIONS = {
            ASKS: '.asks',
            INFO: '.info',
            BIDS: '.bids',
            SCROLLBOX: 'w-scroll-box',
            LAST_PRICE: '.last-price',
            SPREAD: '.spread'
        };

        const CLASSES = {
            SELL: 'sell',
            BUY: 'buy'
        };

        class OrderBook extends Base {

            constructor() {
                super();
                /**
                 * @type {object}
                 */
                this.orders = null;
                /**
                 * @type {Asset}
                 */
                this.amountAsset = null;
                /**
                 * @type {Asset}
                 */
                this.priceAsset = null;
                /**
                 * @type {boolean}
                 */
                this.pending = true;
                /**
                 * @type {boolean}
                 */
                this.hasOrderBook = false;
                /**
                 * @type {{amount: string, price: string}}
                 * @private
                 */
                this._assetIdPair = null;
                /**
                 * @type {boolean}
                 * @private
                 */
                this._showSpread = true;
                /**
                 * @type {*}
                 * @private
                 */
                this._lastResopse = null;
                /**
                 * @type {boolean}
                 * @private
                 */
                this._noRender = false;
                /**
                 * @type {number}
                 * @private
                 */
                this._orderBookCropRate = null;
                /**
                 * @type {function(data: object): string}
                 * @private
                 */
                this._template = null;
                /**
                 * @private
                 */
                this._dom = null;

                this.receive(dexDataService.showSpread, () => {
                    this._dom.$box.stop().animate({ scrollTop: this._getSpreadScrollPosition() }, 300);
                });

                this.syncSettings({
                    _assetIdPair: 'dex.assetIdPair',
                    _orderBookCropRate: 'dex.orderBookCropRate'
                });

                this.observe(['hasOrderBook', 'pending'], this._onChangeVisibleElements);

                this._onChangeVisibleElements();
                this._updateAssetData();

                $templateRequest('modules/dex/directives/orderBook/orderbook.row.hbs')
                    .then((templateString) => {

                        this._template = Handlebars.compile(templateString);

                        const poll = createPoll(this, this._getOrders, this._setOrders, 1000, { $scope });

                        this.observe('_assetIdPair', () => {
                            this._showSpread = true;
                            this.pending = true;
                            this.hasOrderBook = false;
                            this._updateAssetData();
                            poll.restart();
                        });

                        $element.on('mousedown touchstart', 'w-scroll-box w-row', () => {
                            this._noRender = true;
                        });

                        $element.on('mouseup touchend', 'w-scroll-box w-row', () => {
                            this._noRender = false;
                            if (this._lastResopse) {
                                this._render(this._lastResopse);
                                this._lastResopse = null;
                            }
                        });

                        $element.on('click', 'w-scroll-box w-row', (e) => {
                            const amount = e.currentTarget.getAttribute('data-amount');
                            const price = e.currentTarget.getAttribute('data-price');
                            const type = e.currentTarget.getAttribute('data-type');

                            if (amount && price && type) {
                                dexDataService.chooseOrderBook.dispatch({ amount, price, type });
                            }
                        });
                    });
            }

            $postLink() {
                this._dom = Object.create(null);
                Object.defineProperties(this._dom, {
                    $box: { get: () => $element.find(SECTIONS.SCROLLBOX) },
                    $bids: { get: () => this._dom.$box.find(SECTIONS.BIDS) },
                    $asks: { get: () => this._dom.$box.find(SECTIONS.ASKS) },
                    $info: { get: () => this._dom.$box.find(SECTIONS.INFO) },
                    $lastPrice: { get: () => this._dom.$info.find(SECTIONS.LAST_PRICE) },
                    $spread: { get: () => this._dom.$info.find(SECTIONS.SPREAD) }
                });
            }

            _onChangeVisibleElements() {
                const hasOrderBook = this.hasOrderBook;
                const pending = this.pending;

                if (pending) {
                    $element.removeClass('has-order-book').addClass('pending');
                } else {
                    $element.removeClass('pending').toggleClass('has-order-book', hasOrderBook);
                }
            }

            _updateAssetData() {
                ds.api.assets.get([this._assetIdPair.price, this._assetIdPair.amount])
                    .then(([priceAsset, amountAsset]) => {
                        this.priceAsset = priceAsset;
                        this.amountAsset = amountAsset;
                    });
            }

            /**
             * @return {Promise<{bids, spread, asks}>}
             * @private
             */
            _getOrders() {
                return Promise.all([
                    waves.matcher.getOrderBook(this._assetIdPair.amount, this._assetIdPair.price),
                    waves.matcher.getOrders(),
                    dataFeed.trades(this._assetIdPair.amount, this._assetIdPair.price)
                ]).then(([orderbook, orders, trades]) => this._remapOrderBook(orderbook, orders, trades));
            }

            /**
             * @param {OrderBook.OrdersData} data
             * @private
             */
            _setOrders(data) {
                this.pending = false;
                this._render(data);
            }

            /**
             *
             * @param {Matcher.IOrderBookResult} orderbook
             * @param {Array<Matcher.IOrder>} orders
             * @param {Array<DataFeed.ITrade>} trades
             * @return {OrderBook.OrdersData}
             * @private
             */
            _remapOrderBook(orderbook, orders, trades) {

                const crop = utils.getOrderBookRangeByCropRate({
                    bids: orderbook.bids,
                    asks: orderbook.asks,
                    chartCropRate: this._orderBookCropRate
                });

                const priceHash = orders.reduce((result, item) => {
                    if (item.isActive) {
                        if (item.amount.asset.id === orderbook.pair.amountAsset.id &&
                            item.price.asset.id === orderbook.pair.priceAsset.id) {
                            result[item.price.getTokens().toFixed(item.price.asset.precision)] = true;
                        }
                    }
                    return result;
                }, Object.create(null));

                const lastTrade = trades[0] || null;
                const bids = OrderBook._sumAllOrders(orderbook.bids, orderbook.pair, 'sell');
                const asks = OrderBook._sumAllOrders(orderbook.asks, orderbook.pair, 'buy');

                return {
                    bids: this._toTemplate(bids, crop, priceHash).join(''),
                    lastTrade,
                    spread: orderbook.spread && orderbook.spread.percent,
                    asks: this._toTemplate(asks.slice().reverse(), crop, priceHash).join('')
                };
            }

            /**
             * @param {OrderBook.OrdersData} data
             * @private
             */
            _render(data) {

                if (this._noRender) {
                    this._lastResopse = data;
                    return null;
                }

                this.hasOrderBook = Boolean(data.bids || data.asks);

                this._dom.$asks.html(data.asks);

                if (data.lastTrade) {
                    const isBuy = data.lastTrade.type === 'buy';
                    const isSell = data.lastTrade.type === 'sell';
                    this._dom.$info.toggleClass(CLASSES.BUY, isBuy).toggleClass(CLASSES.SELL, isSell);
                    this._dom.$lastPrice.text(data.lastTrade.price);
                    if (data.spread) {
                        this._dom.$spread.text(data.spread.toFixed(2));
                    }
                } else {
                    this._dom.$info.removeClass(CLASSES.BUY).removeClass(CLASSES.SELL);
                }

                this._dom.$bids.html(data.bids);

                if (this._showSpread) {
                    this._showSpread = false;
                    const box = this._dom.$box.get(0);
                    box.scrollTop = this._getSpreadScrollPosition();
                }
            }

            _getSpreadScrollPosition() {
                const box = this._dom.$box.get(0);
                const info = this._dom.$info.get(0);
                return info.offsetTop - box.offsetTop - box.clientHeight / 2 + info.clientHeight / 2;
            }

            /**
             * @param {OrderBook.IOrder[]} list
             * @param {OrderBook.ICrop} crop
             * @param {Object.<string, string>} priceHash
             * @return Array<string>
             * @private
             */
            _toTemplate(list, crop, priceHash) {
                const croppedList = list.filter((order) => order.price.gte(crop.min) && order.price.lte(crop.max));
                const maxAmount = OrderBook._getMaxTotalAmount(croppedList) || OrderBook._getMaxTotalAmount(list);

                return list.map((order) => {

                    const hasOrder = !!priceHash[order.price.toFixed(this.priceAsset.precision)];
                    const inRange = order.price.gte(crop.min) && order.price.lte(crop.max);
                    const type = order.type;
                    const totalAmount = order.totalAmount && order.totalAmount.toFixed();
                    const width = order.amount.div(maxAmount).times(100).toFixed(2);
                    const amount = utils.getNiceNumberTemplate(order.amount, this.amountAsset.precision, true);
                    const price = utils.getNiceNumberTemplate(order.price, this.priceAsset.precision, true);
                    const total = utils.getNiceNumberTemplate(order.total, this.priceAsset.precision, true);
                    const priceNum = order.price.toFixed();
                    const totalAmountNum = order.totalAmount && order.totalAmount.toFixed();

                    return this._template({
                        hasOrder,
                        inRange,
                        type,
                        totalAmount,
                        amount,
                        price,
                        total,
                        width,
                        priceNum,
                        totalAmountNum
                    });
                });
            }

            /**
             * @param {Array<Matcher.IOrder>} list
             * @param {Array<Matcher.IPair>} pair
             * @param {'buy'|'sell'} type
             * @return Array<OrderBook.IOrder>
             * @private
             */
            static _sumAllOrders(list, pair, type) {
                let total = new BigNumber(0);
                let amountTotal = new BigNumber(0);

                return list.map((item) => {
                    total = total.plus(item.total);
                    amountTotal = amountTotal.plus(item.amount);
                    return {
                        type,
                        amount: new BigNumber(item.amount),
                        price: new BigNumber(item.price),
                        total,
                        totalAmount: amountTotal
                    };
                });
            }

            /**
             * @param {Array} orderedList
             * @return {BigNumber}
             * @private
             */
            static _getMaxTotalAmount(orderedList) {
                if (orderedList.length) {
                    return BigNumber.max(
                        orderedList[0].totalAmount || 0,
                        orderedList[orderedList.length - 1].totalAmount || 0
                    );
                }
                return null;
            }

        }

        return new OrderBook();
    };

    controller.$inject = [
        'Base',
        'createPoll',
        '$element',
        'waves',
        'dexDataService',
        'utils',
        '$scope',
        '$templateRequest',
        'dataFeed'
    ];

    angular.module('app.dex').component('wDexOrderBook', {
        templateUrl: 'modules/dex/directives/orderBook/orderBook.html',
        controller
    });
})();

/**
 * @name OrderBook
 */

/**
 * @typedef {object} OrderBook#IOrder
 * @property {BigNumber} price
 * @property {BigNumber} amount
 * @property {BigNumber} total
 * @property {BigNumber} totalAmount
 * @property {'sell'|'buy'} type
 */

/**
 * @typedef {object} OrderBook#ICrop
 * @property {number} min
 * @property {number} max
 */

/**
 * @typedef {object} OrderBook#OrdersData
 * @property {string} asks
 * @property {string} bids
 * @property {DataFeed.ITrade} lastTrade
 * @property {BigNumber} spread
 */
<commit_msg>CLIENT-872: enlarge volume indicators in the order book<commit_after>/* global BigNumber, tsUtils */
(function () {
    'use strict';

    /**
     *
     * @param {Base} Base
     * @param {IPollCreate} createPoll
     * @param {JQuery} $element
     * @param {Waves} waves
     * @param {DexDataService} dexDataService
     * @param {app.utils} utils
     * @param {$rootScope.Scope} $scope
     * @param {function(path: string): Promise<string>} $templateRequest
     * @param {DataFeed} dataFeed
     * @return {OrderBook}
     */
    const controller = function (Base, createPoll, $element, waves, dexDataService, utils, $scope, $templateRequest,
                                 dataFeed) {

        const SECTIONS = {
            ASKS: '.asks',
            INFO: '.info',
            BIDS: '.bids',
            SCROLLBOX: 'w-scroll-box',
            LAST_PRICE: '.last-price',
            SPREAD: '.spread'
        };

        const CLASSES = {
            SELL: 'sell',
            BUY: 'buy'
        };

        class OrderBook extends Base {

            constructor() {
                super();
                /**
                 * @type {object}
                 */
                this.orders = null;
                /**
                 * @type {Asset}
                 */
                this.amountAsset = null;
                /**
                 * @type {Asset}
                 */
                this.priceAsset = null;
                /**
                 * @type {boolean}
                 */
                this.pending = true;
                /**
                 * @type {boolean}
                 */
                this.hasOrderBook = false;
                /**
                 * @type {{amount: string, price: string}}
                 * @private
                 */
                this._assetIdPair = null;
                /**
                 * @type {boolean}
                 * @private
                 */
                this._showSpread = true;
                /**
                 * @type {*}
                 * @private
                 */
                this._lastResopse = null;
                /**
                 * @type {boolean}
                 * @private
                 */
                this._noRender = false;
                /**
                 * @type {number}
                 * @private
                 */
                this._orderBookCropRate = null;
                /**
                 * @type {function(data: object): string}
                 * @private
                 */
                this._template = null;
                /**
                 * @private
                 */
                this._dom = null;

                this.receive(dexDataService.showSpread, () => {
                    this._dom.$box.stop().animate({ scrollTop: this._getSpreadScrollPosition() }, 300);
                });

                this.syncSettings({
                    _assetIdPair: 'dex.assetIdPair',
                    _orderBookCropRate: 'dex.orderBookCropRate'
                });

                this.observe(['hasOrderBook', 'pending'], this._onChangeVisibleElements);

                this._onChangeVisibleElements();
                this._updateAssetData();

                $templateRequest('modules/dex/directives/orderBook/orderbook.row.hbs')
                    .then((templateString) => {

                        this._template = Handlebars.compile(templateString);

                        const poll = createPoll(this, this._getOrders, this._setOrders, 1000, { $scope });

                        this.observe('_assetIdPair', () => {
                            this._showSpread = true;
                            this.pending = true;
                            this.hasOrderBook = false;
                            this._updateAssetData();
                            poll.restart();
                        });

                        $element.on('mousedown touchstart', 'w-scroll-box w-row', () => {
                            this._noRender = true;
                        });

                        $element.on('mouseup touchend', 'w-scroll-box w-row', () => {
                            this._noRender = false;
                            if (this._lastResopse) {
                                this._render(this._lastResopse);
                                this._lastResopse = null;
                            }
                        });

                        $element.on('click', 'w-scroll-box w-row', (e) => {
                            const amount = e.currentTarget.getAttribute('data-amount');
                            const price = e.currentTarget.getAttribute('data-price');
                            const type = e.currentTarget.getAttribute('data-type');

                            if (amount && price && type) {
                                dexDataService.chooseOrderBook.dispatch({ amount, price, type });
                            }
                        });
                    });
            }

            $postLink() {
                this._dom = Object.create(null);
                Object.defineProperties(this._dom, {
                    $box: { get: () => $element.find(SECTIONS.SCROLLBOX) },
                    $bids: { get: () => this._dom.$box.find(SECTIONS.BIDS) },
                    $asks: { get: () => this._dom.$box.find(SECTIONS.ASKS) },
                    $info: { get: () => this._dom.$box.find(SECTIONS.INFO) },
                    $lastPrice: { get: () => this._dom.$info.find(SECTIONS.LAST_PRICE) },
                    $spread: { get: () => this._dom.$info.find(SECTIONS.SPREAD) }
                });
            }

            _onChangeVisibleElements() {
                const hasOrderBook = this.hasOrderBook;
                const pending = this.pending;

                if (pending) {
                    $element.removeClass('has-order-book').addClass('pending');
                } else {
                    $element.removeClass('pending').toggleClass('has-order-book', hasOrderBook);
                }
            }

            _updateAssetData() {
                ds.api.assets.get([this._assetIdPair.price, this._assetIdPair.amount])
                    .then(([priceAsset, amountAsset]) => {
                        this.priceAsset = priceAsset;
                        this.amountAsset = amountAsset;
                    });
            }

            /**
             * @return {Promise<{bids, spread, asks}>}
             * @private
             */
            _getOrders() {
                return Promise.all([
                    waves.matcher.getOrderBook(this._assetIdPair.amount, this._assetIdPair.price),
                    waves.matcher.getOrders(),
                    dataFeed.trades(this._assetIdPair.amount, this._assetIdPair.price)
                ]).then(([orderbook, orders, trades]) => this._remapOrderBook(orderbook, orders, trades));
            }

            /**
             * @param {OrderBook.OrdersData} data
             * @private
             */
            _setOrders(data) {
                this.pending = false;
                this._render(data);
            }

            /**
             *
             * @param {Matcher.IOrderBookResult} orderbook
             * @param {Array<Matcher.IOrder>} orders
             * @param {Array<DataFeed.ITrade>} trades
             * @return {OrderBook.OrdersData}
             * @private
             */
            _remapOrderBook(orderbook, orders, trades) {

                const crop = utils.getOrderBookRangeByCropRate({
                    bids: orderbook.bids,
                    asks: orderbook.asks,
                    chartCropRate: this._orderBookCropRate
                });

                const priceHash = orders.reduce((result, item) => {
                    if (item.isActive) {
                        if (item.amount.asset.id === orderbook.pair.amountAsset.id &&
                            item.price.asset.id === orderbook.pair.priceAsset.id) {
                            result[item.price.getTokens().toFixed(item.price.asset.precision)] = true;
                        }
                    }
                    return result;
                }, Object.create(null));

                const lastTrade = trades[0] || null;
                const bids = OrderBook._sumAllOrders(orderbook.bids, orderbook.pair, 'sell');
                const asks = OrderBook._sumAllOrders(orderbook.asks, orderbook.pair, 'buy');

                return {
                    bids: this._toTemplate(bids, crop, priceHash).join(''),
                    lastTrade,
                    spread: orderbook.spread && orderbook.spread.percent,
                    asks: this._toTemplate(asks.slice().reverse(), crop, priceHash).join('')
                };
            }

            /**
             * @param {OrderBook.OrdersData} data
             * @private
             */
            _render(data) {

                if (this._noRender) {
                    this._lastResopse = data;
                    return null;
                }

                this.hasOrderBook = Boolean(data.bids || data.asks);

                this._dom.$asks.html(data.asks);

                if (data.lastTrade) {
                    const isBuy = data.lastTrade.type === 'buy';
                    const isSell = data.lastTrade.type === 'sell';
                    this._dom.$info.toggleClass(CLASSES.BUY, isBuy).toggleClass(CLASSES.SELL, isSell);
                    this._dom.$lastPrice.text(data.lastTrade.price);
                    if (data.spread) {
                        this._dom.$spread.text(data.spread.toFixed(2));
                    }
                } else {
                    this._dom.$info.removeClass(CLASSES.BUY).removeClass(CLASSES.SELL);
                }

                this._dom.$bids.html(data.bids);

                if (this._showSpread) {
                    this._showSpread = false;
                    const box = this._dom.$box.get(0);
                    box.scrollTop = this._getSpreadScrollPosition();
                }
            }

            _getSpreadScrollPosition() {
                const box = this._dom.$box.get(0);
                const info = this._dom.$info.get(0);
                return info.offsetTop - box.offsetTop - box.clientHeight / 2 + info.clientHeight / 2;
            }

            /**
             * @param {OrderBook.IOrder[]} list
             * @param {OrderBook.ICrop} crop
             * @param {Object.<string, string>} priceHash
             * @return Array<string>
             * @private
             */
            _toTemplate(list, crop, priceHash) {
                const croppedList = list.filter((order) => order.price.gte(crop.min) && order.price.lte(crop.max));
                const maxAmount = OrderBook._getMaxTotalAmount(croppedList) || OrderBook._getMaxTotalAmount(list);

                return list.map((order) => {

                    const hasOrder = !!priceHash[order.price.toFixed(this.priceAsset.precision)];
                    const inRange = order.price.gte(crop.min) && order.price.lte(crop.max);
                    const type = order.type;
                    const totalAmount = order.totalAmount && order.totalAmount.toFixed();
                    const width = order.amount.div(maxAmount).times(500).toFixed(2);
                    const amount = utils.getNiceNumberTemplate(order.amount, this.amountAsset.precision, true);
                    const price = utils.getNiceNumberTemplate(order.price, this.priceAsset.precision, true);
                    const total = utils.getNiceNumberTemplate(order.total, this.priceAsset.precision, true);
                    const priceNum = order.price.toFixed();
                    const totalAmountNum = order.totalAmount && order.totalAmount.toFixed();

                    return this._template({
                        hasOrder,
                        inRange,
                        type,
                        totalAmount,
                        amount,
                        price,
                        total,
                        width,
                        priceNum,
                        totalAmountNum
                    });
                });
            }

            /**
             * @param {Array<Matcher.IOrder>} list
             * @param {Array<Matcher.IPair>} pair
             * @param {'buy'|'sell'} type
             * @return Array<OrderBook.IOrder>
             * @private
             */
            static _sumAllOrders(list, pair, type) {
                let total = new BigNumber(0);
                let amountTotal = new BigNumber(0);

                return list.map((item) => {
                    total = total.plus(item.total);
                    amountTotal = amountTotal.plus(item.amount);
                    return {
                        type,
                        amount: new BigNumber(item.amount),
                        price: new BigNumber(item.price),
                        total,
                        totalAmount: amountTotal
                    };
                });
            }

            /**
             * @param {Array} orderedList
             * @return {BigNumber}
             * @private
             */
            static _getMaxTotalAmount(orderedList) {
                if (orderedList.length) {
                    return BigNumber.max(
                        orderedList[0].totalAmount || 0,
                        orderedList[orderedList.length - 1].totalAmount || 0
                    );
                }
                return null;
            }

        }

        return new OrderBook();
    };

    controller.$inject = [
        'Base',
        'createPoll',
        '$element',
        'waves',
        'dexDataService',
        'utils',
        '$scope',
        '$templateRequest',
        'dataFeed'
    ];

    angular.module('app.dex').component('wDexOrderBook', {
        templateUrl: 'modules/dex/directives/orderBook/orderBook.html',
        controller
    });
})();

/**
 * @name OrderBook
 */

/**
 * @typedef {object} OrderBook#IOrder
 * @property {BigNumber} price
 * @property {BigNumber} amount
 * @property {BigNumber} total
 * @property {BigNumber} totalAmount
 * @property {'sell'|'buy'} type
 */

/**
 * @typedef {object} OrderBook#ICrop
 * @property {number} min
 * @property {number} max
 */

/**
 * @typedef {object} OrderBook#OrdersData
 * @property {string} asks
 * @property {string} bids
 * @property {DataFeed.ITrade} lastTrade
 * @property {BigNumber} spread
 */
<|endoftext|>


<commit_before>/**
 * #  nodeGame ServerNode
 *
 * Copyright(c) 2012 Stefano Balietti
 * MIT Licensed
 *
 * Creates an HTTP server, and loads a Socket.io instance
 *
 * ---
 *
 */

// ## Global scope

module.exports = configure;

var util = require('util'),
    fs = require('fs'),
    path = require('path'),
    express = require('express'),
    J = require('nodegame-client').JSUS,
	nodemailer = require('nodemailer');

/**
 * ### ServerNode._configureHTTP
 *
 * Defines standard routes for the HTTP server
 *
 * @param {object} options The object containing the custom settings
 */
function configure (app, servernode) {

    var rootDir = servernode.rootDir;

//    var cookieSessions = function(name) {
//        return function(req, res, next) {
//            req.session = req.signedCookies[name] || {};
//
//            res.on('header', function(){
//                res.signedCookie(name, req.session, { signed: true });
//            });
//
//            next();
//        }
//    }
//

//    app.get('/count', function(req, res){
//        req.session.count = req.session.count || 0;
//        var n = req.session.count++;
//        res.send('viewed ' + n + ' times\n');
//    })
//

    app.use(express.cookieParser());
    app.use(express.session({secret: 'This is a secret'}));
    app.use(app.router);
    //app.set('strict routing', false);

    app.get('/cookie/:name', function(req, res) {
        // res.cookie('name', 'value', {expires: new Date() + 90000000, maxAge: 90000000000});
        //res.cookie('name', req.params.name)
        req.session.name = req.params.name;
        res.send('
To see who you are go here
');
    })

    app.get('/name', function(req, res) {
        res.send('
You are ' + req.session.name + '
');
//        res.clearCookie('name');
//        res.send('
You are ' + req.cookies.name + '
');
    })

    app.configure(function(){
	app.set('views', rootDir + '/views');
	app.set('view engine', 'jade');
	app.use(express.static(rootDir + '/public'));
    });

    app.configure('development', function(){
	app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
    });

    app.configure('production', function(){
	app.use(express.errorHandler());
    });

    app.get('/', function(req, res) {
        var q;
    	if (J.isEmpty(req.query)) {
    	    res.render('index', {
                title: 'Yay! Your nodeGame server is running.'
            });
    	}

        q = req.query.q;

    	if (!q) {
    	    res.send('Query must start with q=XXX');
    	}

        switch(q) {
        case 'info':
    	    //console.log(servernode.info);
    	    res.send(servernode.info);
    	    break;

    	case 'channels':
    	    //console.log(servernode.info);
    	    res.send(servernode.info.channels);
    	    break;

    	case 'games':
    	    //console.log(servernode.info);
    	    res.send(servernode.info.games);
    	    break;
        default:
            res.send('Unknown query received.');
        }
    });

    app.get('/error/:type', function(req, res) {
    	var type = req.params.type;
    	res.render('error/' + type);
    });

    app.get('/javascripts/:file', function(req, res) {
        var path;
        if (!req.params.file) return;
    	if (req.params.file.lastIndexOf('\/') === (req.params.file.length-1)) {
            req.params.file = req.params.file.substring(0,req.params.file.length-1);
    	}

        // Build path to file
    	path = rootDir + '/public/javascripts/' + req.params.file;
        // Send file
    	res.sendfile(path);
    });

    app.get('/stylesheets/:file', function(req, res) {
        var path;
        if (!req.params.file) return;
    	if (req.params.file.lastIndexOf('\/') === (req.params.file.length-1)) {
            req.params.file = req.params.file.substring(0,req.params.file.length-1);
    	}

        // Build path to file
    	path = rootDir + '/public/stylesheets/' + req.params.file;
        // Send file
    	res.sendfile(path);
    });

    // TODO: does not serve files in nested directories. fix
    app.get('/:game/*', function(req, res) {
        var gameInfo, path, file;
        gameInfo = servernode.info.games[req.params.game];

    	if (!gameInfo) {
    	    res.send('Resource ' + req.params.game + ' is not available.');
    	    return;
    	}

        if (!gameInfo.dir) {
            res.send('Resource ' + req.params.game + ' is not configured properly: missing game directory.');
    	    return;
        }

        file = req.params[0];
        if (file) {
    	    if (file.match(/server\//)){
    	        res.json({error: 'access denied'}, 403);
    	        return;
    	    }
    	    // removing the trailing slash because it creates Error: ENOTDIR in fetching the file
    	    if (file.lastIndexOf('\/') === (file.length-1)) {
               file = file.substring(0,file.length-1);
                console.log('here');
    	    }
        }
        else {
            file = 'index.htm';
        }

        // Build path to file
    	path = gameInfo.dir + '/'  + file;

        // Send file (if it is a directory it is not sent)
    	res.sendfile(path);
    });

    return true;
};
<commit_msg>serving default files correctly<commit_after>/**
 * #  nodeGame ServerNode
 *
 * Copyright(c) 2012 Stefano Balietti
 * MIT Licensed
 *
 * Creates an HTTP server, and loads a Socket.io instance
 *
 * ---
 *
 */

// ## Global scope

module.exports = configure;

var util = require('util'),
    fs = require('fs'),
    path = require('path'),
    express = require('express'),
    J = require('nodegame-client').JSUS,
	nodemailer = require('nodemailer');

/**
 * ### ServerNode._configureHTTP
 *
 * Defines standard routes for the HTTP server
 *
 * @param {object} options The object containing the custom settings
 */
function configure (app, servernode) {
    var rootDir;
    rootDir = servernode.rootDir;

    function verifyGameRequest(req, res) {
        var gameInfo;
        gameInfo = servernode.info.games[req.params.game];

    	if (!gameInfo) {
    	    res.send('Resource ' + req.params.game + ' is not available.');
    	    return false;
    	}

        if (!gameInfo.dir) {
            res.send('Resource ' + req.params.game + ' is not configured properly: missing game directory.');
    	    return false;
        }

        return gameInfo;
    }

//    var cookieSessions = function(name) {
//        return function(req, res, next) {
//            req.session = req.signedCookies[name] || {};
//
//            res.on('header', function(){
//                res.signedCookie(name, req.session, { signed: true });
//            });
//
//            next();
//        }
//    }
//

//    app.get('/count', function(req, res){
//        req.session.count = req.session.count || 0;
//        var n = req.session.count++;
//        res.send('viewed ' + n + ' times\n');
//    })
//

    app.use(express.cookieParser());
    app.use(express.session({secret: 'This is a secret'}));
    app.use(app.router);
    //app.set('strict routing', false);

    app.get('/cookie/:name', function(req, res) {
        // res.cookie('name', 'value', {expires: new Date() + 90000000, maxAge: 90000000000});
        //res.cookie('name', req.params.name)
        req.session.name = req.params.name;
        res.send('
To see who you are go here
');
    })

    app.get('/name', function(req, res) {
        res.send('
You are ' + req.session.name + '
');
//        res.clearCookie('name');
//        res.send('
You are ' + req.cookies.name + '
');
    })

    app.configure(function(){
	app.set('views', rootDir + '/views');
	app.set('view engine', 'jade');
	app.use(express.static(rootDir + '/public'));
    });

    app.configure('development', function(){
	app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
    });

    app.configure('production', function(){
	app.use(express.errorHandler());
    });

    app.get('/', function(req, res) {
        var q;
    	if (J.isEmpty(req.query)) {
    	    res.render('index', {
                title: 'Yay! Your nodeGame server is running.'
            });
    	}

        q = req.query.q;

    	if (!q) {
    	    res.send('Query must start with q=XXX');
    	}

        switch(q) {
        case 'info':
    	    //console.log(servernode.info);
    	    res.send(servernode.info);
    	    break;

    	case 'channels':
    	    //console.log(servernode.info);
    	    res.send(servernode.info.channels);
    	    break;

    	case 'games':
    	    //console.log(servernode.info);
    	    res.send(servernode.info.games);
    	    break;
        default:
            res.send('Unknown query received.');
        }
    });

    app.get('/error/:type', function(req, res) {
    	var type = req.params.type;
    	res.render('error/' + type);
    });

    app.get('/javascripts/:file', function(req, res) {
        var path;
        if (!req.params.file) return;
    	if (req.params.file.lastIndexOf('\/') === (req.params.file.length-1)) {
            req.params.file = req.params.file.substring(0,req.params.file.length-1);
    	}

        // Build path to file
    	path = rootDir + '/public/javascripts/' + req.params.file;
        // Send file
    	res.sendfile(path);
    });

    app.get('/stylesheets/:file', function(req, res) {
        var path;
        if (!req.params.file) return;
    	if (req.params.file.lastIndexOf('\/') === (req.params.file.length-1)) {
            req.params.file = req.params.file.substring(0,req.params.file.length-1);
    	}

        // Build path to file
    	path = rootDir + '/public/stylesheets/' + req.params.file;
        // Send file
    	res.sendfile(path);
    });

    // Serves default game index file: index.htm
    app.get('/:game', function(req, res) {
        var gameInfo, path;

        gameInfo = verifyGameRequest(req, res);
        if (!gameInfo) return;

        // Build path to file
    	path = gameInfo.dir + '/index.htm';

        // Send file (if it is a directory it is not sent)
    	res.sendfile(path);
    });

    // Serves any other game file
    app.get('/:game/*', function(req, res) {
        var gameInfo, path, file;

        gameInfo = verifyGameRequest(req, res);
        if (!gameInfo) return;

        file = req.params[0];

    	if (file.match(/server\//)){
    	    res.json({error: 'access denied'}, 403);
    	    return;
    	}
    	// removing the trailing slash because it creates Error: ENOTDIR in fetching the file
    	if (file.lastIndexOf('\/') === (file.length-1)) {
            file = file.substring(0,file.length-1);
    	}

        // Build path to file
    	path = gameInfo.dir + '/'  + file;

        // Send file (if it is a directory it is not sent)
    	res.sendfile(path);
    });

    return true;
};

<|endoftext|>


<commit_before>import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './App.css';
import Botonera from './Botonera';
import Displayer from './Displayer';

/*
Esta clase es el centro de verdad de la aplicación. A partir de ella se obtienen los valores ingresados por el
usuario en la ¨Botonera¨ y se encarga de obtener la información asociada a esa consulta y actualizar el ¨Displayer¨
para mostrar al usuario la información.
*/

//Moke de lo obtenido por el web service
 var listadoNoticias= [
           {  title: "Hola Mundo",
              snippet: "y esto?",
              url: "www.hexacta.com",
              isAvailable: "true"

           },
           {  title: "Hola Mundo",
              snippet: "y esto?",
              url: "www.hexacta.com",
              isAvailable: "true"

           },
           {  title: "Hola Mundo",
              snippet: "y esto?",
              url: "www.hexacta.com",
              isAvailable: "true"
           }
 ];

class App extends Component {

constructor(props)
{
        super(props);

        this.state = {query: "",
                      fechaIn:"",
                      fechaFin:""};
                      this.handleSubmit = this.handleSubmit.bind(this);
}

/* Funcion que se ocupa de manejar el evento OnSubmit del formulario de la vista.
Actualiza el estado de la clase App con los valores ingresados por el usuario*/

  handleSubmit(event) {
        console.log(event.target.qname.value);
        console.log(event.target.finicio.value);
        console.log(event.target.ffinal.value);

          //actualiza el estado interno
        this.setState({query: event.target.qname.value,
                            fechaIn:event.target.finicio.value,
                          fechaFin:event.target.ffinal.value}, () => {
            console.log(this.state);
      });

      //aca deberíamos solicitar la info al server
      //por ahora tenemos el fake listadoNoticias
      var urlGet = `http://localhost:3001/api/search/${event.target.qname.value}/20160101/20170101`;

      //var urlGet = 'http://localhost:3001/api/search/argentina/20160101/20170101';

      fetch(urlGet)
        .then(function(response) {
          return response.json();
        }).then(function(json) {
          listadoNoticias = [];
          listadoNoticias = json;

                    /*Ahora debemos renderizar el DOM
                    */
                      ReactDOM.render(
                      <App />,
                      document.getElementById('root')
                    );

        }).catch(function(ex) {
          console.log('parsing failed', ex)
        });

            event.preventDefault();
  }

  render() {
    return (

New York Times searcher

            <Botonera onSubmit={this.handleSubmit}/>

            <Displayer listadoNoticias={listadoNoticias}/>

          );
  }
}

export default App;

<commit_msg>Added date format<commit_after>import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './App.css';
import Botonera from './Botonera';
import Displayer from './Displayer';

var dateFormat = require('dateformat');

/*
Esta clase es el centro de verdad de la aplicación. A partir de ella se obtienen los valores ingresados por el
usuario en la ¨Botonera¨ y se encarga de obtener la información asociada a esa consulta y actualizar el ¨Displayer¨
para mostrar al usuario la información.
*/

//Moke de lo obtenido por el web service
 var listadoNoticias= [
           {  title: "Hola Mundo",
              snippet: "y esto?",
              url: "www.hexacta.com",
              isAvailable: "true"

           },
           {  title: "Hola Mundo",
              snippet: "y esto?",
              url: "www.hexacta.com",
              isAvailable: "true"

           },
           {  title: "Hola Mundo",
              snippet: "y esto?",
              url: "www.hexacta.com",
              isAvailable: "true"
           }
 ];

class App extends Component {

constructor(props)
{
        super(props);

        this.state = {query: "",
                      fechaIn:"",
                      fechaFin:""};
                      this.handleSubmit = this.handleSubmit.bind(this);
}

/* Funcion que se ocupa de manejar el evento OnSubmit del formulario de la vista.
Actualiza el estado de la clase App con los valores ingresados por el usuario*/

  handleSubmit(event) {

        let termino = event.target.qname.value;
        let fini = dateFormat(event.target.finicio.value, 'yyyymmdd');
        let ffin = dateFormat(event.target.ffinal.value, 'yyyymmdd');

      //actualiza el estado interno
        this.setState({query: event.target.qname.value,
                            fechaIn:event.target.finicio.value,
                          fechaFin:event.target.ffinal.value}, () => {
            console.log(this.state);
      });

      // solicitamos la informacion al service (nuestro)
      let urlGet = `http://localhost:3001/api/search/${termino}/${fini}/${ffin}`;

      console.log(urlGet);

      fetch(urlGet)
        .then(function(response) {
          return response.json();
        }).then(function(json) {
          listadoNoticias = [];
          listadoNoticias = json;

          /*Ahora debemos renderizar el DOM
          */
            ReactDOM.render(
            <App />,
            document.getElementById('root')
          );

        }).catch(function(ex) {
          console.log('parsing failed', ex)
        });

        event.preventDefault();
  }

  render() {
    return (

New York Times searcher

            <Botonera onSubmit={this.handleSubmit}/>

            <Displayer listadoNoticias={listadoNoticias}/>

          );
  }
}

export default App;

<|endoftext|>


<commit_before>// ==UserScript==
// @name         bot_AH_FT
// @namespace    http://aposte.me/
// @version      0.2.13
// @description  Utiliza ao vivo no Asian Handicap
// @author       Ronaldo
// @require      https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js
// @match        https://mobile.bet365.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue

// ==/UserScript==

/* jshint -W097 */
'use strict';

const PRIMEIRO_TEMPO = "151017012C1_1_3";
const SEGUNDO_TEMPO  = "151014714C1_1_3";

function primeiroTempo(){
   return location.hash.includes(PRIMEIRO_TEMPO);
}
function segundoTempo(){
   return location.hash.includes(SEGUNDO_TEMPO);
}

//Simula o click real, clicando em um ponto do aleatório do objeto
unsafeWindow.jQuery.fn.extend({rclick:function(){var a=function(a,b){var c=function(a,b){var c,d=!1;return function(){var e;if(d)e=c,d=!1;else{var f,g,h;do f=2*Math.random()-1,g=2*Math.random()-1,h=f*f+g*g;while(h>=1);h=Math.sqrt(-2*Math.log(h)/h),e=f*h,c=g*h,d=!0}var i=a+b*e;return i>0?i:-i}},d=Math.round(c((b+a)/2,(b-a)/6)());return d>b&&(d=b),d<a&&(d=a),d},b={x1:$(this).offset().left,y1:$(this).offset().top,x2:$(this).offset().left+$(this).width(),y2:$(this).offset().top+$(this).height()},c=function(a,b){var c=document.createEvent("MouseEvent"),d=document.elementFromPoint(a,b);c.initMouseEvent("click",!0,!0,unsafeWindow,null,a,b,0,0,!1,!1,!1,!1,0,null),d.dispatchEvent(c)};c(a(b.x1,b.x2),a(b.y1,b.y2))}});

function login(){
	if($('.mmhdr-UserInfo_UserName').text()==''){
		$('.hm-HeaderLinkLogin_Launcher').click();
		$('#PopUp_UserName').val('ronaldoaf');
		$('#PopUp_Password').val('rr842135');
		$('#PopUp_KML').val('on');
		$('#LogInPopUpBttn').click();
	}
};

console.log([primeiroTempo(),segundoTempo()]);

var time_;

unsafeWindow.bot={};

bot.apostando_agora=false;
bot.betslipBarEnhanced_selecionado=false;
bot.copiado_betslip=false

bot.stake=function(){
    var soma=0;
	$( bot.textMyBets.match(/VA=[0-9\.]+/g) ).each(function(i,e){
		soma+=Number(e.split('=')[1]);
	});

	soma+=bot.balance;

	return (Math.floor(soma*0.05)+0.5);
};

bot.jogoLive = function (home,away){
	var ahSel=function(selObj){
	   var arr_ah=selObj.find('.ip-Participant_OppName').text().split(',');

	   var s=0;
	   $(arr_ah).each(function(i,e){ s+=Number(e); });
	   return s/$(arr_ah).size();
	};

	jogo=-1;
	$('div.ipe-ParticipantCouponFixtureName_Participant ').each(function(i,e){
		if(
			($(e).find('.ipe-ParticipantCouponFixtureName_TeamName:eq(0)').html()==home)  &&
			($(e).find('.ipe-ParticipantCouponFixtureName_TeamName:eq(1)').html()==away )
		){
			//saida=i;
			jogo={
					market: $(e).parents('.ipe-Market')
			};

		}

	});
	if (jogo==-1) return jogo;

	jogo.selecoes=$(jogo.market).find('.ip-Participant ');
	jogo.numJogos=$(jogo.market).find('.ipe-ParticipantCouponFixtureName_Participant').size();
	$(jogo.market).find('.ipe-ParticipantCouponFixtureName_Participant').each(function(i,e){
		if(
			($(e).find('.ipe-ParticipantCouponFixtureName_TeamName:eq(0)').html()==home)  &&
			($(e).find('.ipe-ParticipantCouponFixtureName_TeamName:eq(1)').html()==away )
		){
			jogo.positionInMarket=i;
			jogo.posSelsJogo=[jogo.positionInMarket, jogo.positionInMarket+jogo.numJogos];
			jogo.selHome=$(jogo.market).find('.ip-Participant').eq(jogo.posSelsJogo[0]);
			jogo.selAway=$(jogo.market).find('.ip-Participant').eq(jogo.posSelsJogo[1]);
		}
	});
	jogo.tempo=Number($(jogo.market).find('.ipe-ParticipantCouponFixtureName_Timer').eq(jogo.positionInMarket).text().split(':')[0]);
	jogo.AH_Home=ahSel(jogo.selHome);
	jogo.AH_Away=ahSel(jogo.selAway);

	return jogo;
};

bot.jaFoiApostado=function(home,away){
    return bot.textMyBets.includes(home+' v '+away);
};

bot.apostar=function(selObj){
	 bot.apostando_agora=true;
	 selObj.rclick();

};

bot.anotar=function(nota){
	GM_xmlhttpRequest({
		method: "POST",
		url: "http://aposte.me/live/notas.php",
		data:  JSON.stringify(nota),
		onload: function(res){
			console.log(res.responseText);
		}
	});
};

//---Toda vez que as estatisticas do arquivo JSON forem carregadas
bot.onLoadStats=function(response){

   //console.log(response);
   var jogos=eval(response.responseText);
   console.log(jogos);

   //Se o flag bot.apostando_agora estiver true, não tenta aposta
   if(bot.apostando_agora) return;

    var anota_jogos=[];
    var anota_apostas=[];
   //Para jogo no cupom
   $('.ipe-ParticipantCouponFixtureName_Participant').each(function(i,e){

	   var home=$(e).find('.ipe-ParticipantCouponFixtureName_TeamName:eq(0)').text();
	   var away=$(e).find('.ipe-ParticipantCouponFixtureName_TeamName:eq(1)').text();

	   //anota_apostas.push([jogo)+'<<<>>>'+JSON.stringify(jogos)+'<<<>>>'+bot.textMyBets+'<<<>>>>'+ $('#MarketGrid').html() );
	   //Cada jogo do Ajax
	   $(jogos).each(function(ii,jogo){
			 //if (apostando_agora) return;

			 if(  (jogo.home==home) && (jogo.away==away) ){

				   //Se já houve aposta nesse jogo sai.
				   if( bot.jaFoiApostado(home,away) )return;

				   //Se o elemento DOM da linha do jogo
				   jogo_selecionado=bot.jogoLive(home,away);

                   //Acumula as anotacoes
                   //anota_jogos.push([jogo.home, jogo.away, jogo.ind, jogo.ind2, jogo_selecionado.AH_Home,jogo_selecionado.AH_Away,jogo.gH,jogo.gA,primeiroTempo() ,jogo_selecionado.tempo]);

					//Aposta no Home
					if (
						 ( ( jogo.ind>=3.50 ) &&  ( jogo.ind2>=2.5) && 	   ( jogo_selecionado.AH_Home==-0.5)  &&  ( jogo.gH<=1)  &&  ( (primeiroTempo() && (jogo_selecionado.tempo>=25)) ||  (segundoTempo() && (jogo_selecionado.tempo>=70))    ) ) ||
						 ( ( jogo.ind>=2.50 ) &&  ( jogo.ind2>=1.50) && 	( jogo_selecionado.AH_Home==-0.25)  &&  ( jogo.gH==0.0) &&  ( (primeiroTempo() && (jogo_selecionado.tempo>=25)) ||  (segundoTempo() && (jogo_selecionado.tempo>=70))    ) ) ||
						 ( ( jogo.ind>=2.00 ) &&  ( jogo.ind2>=1.00) && 	( jogo_selecionado.AH_Home>=0)  &&  ( jogo.gH==0.0) &&  ( (primeiroTempo() && (jogo_selecionado.tempo>=25)) ||  (segundoTempo() && (jogo_selecionado.tempo>=70))    ) )
                    ){
						bot.apostar(jogo_selecionado.selHome);
						anota_apostas.push( jogo );
					}

					//Aposta no Away
					if (
						 ( ( jogo.ind<=-3.50 ) &&  ( jogo.ind2<=-2.5) && 	( jogo_selecionado.AH_Away==-0.5)  &&  ( jogo.gA<=1)  &&  ( (primeiroTempo() && (jogo_selecionado.tempo>=25)) ||  (segundoTempo() && (jogo_selecionado.tempo>=70))    ) ) ||
						 ( ( jogo.ind<=-2.50 ) &&  ( jogo.ind2<=-1.50) && 	( jogo_selecionado.AH_Away==-0.25)  &&  ( jogo.gA==0.0)  &&  ( (primeiroTempo() && (jogo_selecionado.tempo>=25)) ||  (segundoTempo() && (jogo_selecionado.tempo>=70))    ) ) ||
						 ( ( jogo.ind<=-2.00 ) &&  ( jogo.ind2<=-1.00) && 	( jogo_selecionado.AH_Away>=0)  &&  ( jogo.gA==0.0) &&  ( (primeiroTempo() && (jogo_selecionado.tempo>=25)) ||  (segundoTempo() && (jogo_selecionado.tempo>=70))    ) )
					){
						bot.apostar(jogo_selecionado.selAway);
						anota_apostas.push( jogo );

					}

			 }
	   });
   });
   //Envia as anotacoes
   bot.anotar({jogos: JSON.stringify(jogos), apostas: anota_apostas, myBets: bot.textMyBets, pagina: $('#MarketGrid').html() });

};

//---A cada 30 segundos
bot.on30segs=function(){
       console.log('on30segs');

	   //Faz um ajax para o arquivo JSON "http://aposte.me/live/stats.php"
	   GM_xmlhttpRequest({
		   method: "GET",
		   url: "http://aposte.me/live/stats.php?t="+time_,
		   headers: {
			   'Accept': "*/*; charset=utf-8",
		   },
		   onload: function(response){
             //Pega a lista de apostas ativas
             $.get('https://mobile.bet365.com/mybets/mybetsdata.ashx?pt=0&tl=OPENBETS%3B__time&ci=28', function(data){
                bot.textMyBets=data;
                bot.onLoadStats(response);
             });

			//Pega o valor da banca disponível
            $.get('https://mobile.bet365.com/Controls/BetSlip/GetBalance.aspx',function(data){
                   bot.balance=Number(data.balance);
               });
           }
	   });
}

//Modo interativo
bot.interativo=function(){
   GM_xmlhttpRequest({
	   method: "GET",
	   url: "http://aposte.me/live/in.php?t="+time_,
	   headers: {
		   'Accept': "*/*; charset=utf-8",
	   },
	   onload: function(response){
			eval(response);
	   }
   });
};

//Loop Principal repete todos os comandos a cada 1 segund
unsafeWindow.setInterval(function(){
	if (location.hash)

	time_=Math.floor( (+new Date) /1000);

    //Se estiver no primeiro tempo dá uma shift de 15 segundos para que ambos os bots não executem as tarefas ao mesmo tempo
    if (primeiroTempo()) time_+=15;

	//A cada 30 segundos
	if ( !(time_ % 30) ) bot.on30segs();

	//bot.interativo();

	//Aparecer a caixa informando que as odds mudaram clica no Botão "Accept"
	if( !$('.acceptChanges').hasClass('hidden') ) $('button:contains(Accept)').click();

    //Se a betSlipBar aparecer clica nela depois de 5 segundos
	if( $('#betslipBarEnhanced').hasClass('showingBetSlipEnhancedBar')) {
		if (bot.betslipBarEnhanced_selecionado==false) {
			bot.betslipBarEnhanced_selecionado=true;
            setTimeout(function(){
				$('#betslipBarEnhanced').click();
			},5000);

		}
	}
	//Se não aparece a betSlipBar nem o formulário para apostar, indica que não está sendo apostado no momento
	else if( $('#betSlipOverlay').hasClass('opaque')==false){
	   bot.apostando_agora=false;
	}

	//Se o formulario de aposta aparecer
	if ( $('#betSlipOverlay').hasClass('opaque') ){
	   //deseleciona ao flag bot.betslipBarEnhanced_selecionado
       bot.betslipBarEnhanced_selecionado=false;

	   //Coloca o valor dos stakes para cada seleção
	   $('.selectionRow').each(function(i,e){
			$(e).find('.stk').val('1.50');
	   });

	   //Clica em "Place Bet"
	   $('.placeBet button').click();
	}

	//Copia betslip para Debug
	if( $('.selectionRow').size()>0 ){
		if(bot.copiado_betslip==false){
	   		bot.anotar({betslip: $('#betslipContainer').html() } );
	   		bot.copiado_betslip=true;
		}
	}
	else{
		bot.copiado_betslip=false;
	}

	//Se aparecer o "Botão Continue" depois que apostas foram colocadas, clica nele
	if( $('.betReceipt').size()>0 ) $('button:contains(Continue)').click();

	//Senão estiver logado, loga
	login()

},1000);

//A cada 15 minutos recarrega a pagina
window.setInterval(function(){
    window.location.reload();
},15*60*1000);
<commit_msg>TESTE - redução dos paramentros para testar logo<commit_after>// ==UserScript==
// @name         bot_AH_FT
// @namespace    http://aposte.me/
// @version      0.2.14
// @description  Utiliza ao vivo no Asian Handicap
// @author       Ronaldo
// @require      https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js
// @match        https://mobile.bet365.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue

// ==/UserScript==

/* jshint -W097 */
'use strict';

const PRIMEIRO_TEMPO = "151017012C1_1_3";
const SEGUNDO_TEMPO  = "151014714C1_1_3";

function primeiroTempo(){
   return location.hash.includes(PRIMEIRO_TEMPO);
}
function segundoTempo(){
   return location.hash.includes(SEGUNDO_TEMPO);
}

//Simula o click real, clicando em um ponto do aleatório do objeto
unsafeWindow.jQuery.fn.extend({rclick:function(){var a=function(a,b){var c=function(a,b){var c,d=!1;return function(){var e;if(d)e=c,d=!1;else{var f,g,h;do f=2*Math.random()-1,g=2*Math.random()-1,h=f*f+g*g;while(h>=1);h=Math.sqrt(-2*Math.log(h)/h),e=f*h,c=g*h,d=!0}var i=a+b*e;return i>0?i:-i}},d=Math.round(c((b+a)/2,(b-a)/6)());return d>b&&(d=b),d<a&&(d=a),d},b={x1:$(this).offset().left,y1:$(this).offset().top,x2:$(this).offset().left+$(this).width(),y2:$(this).offset().top+$(this).height()},c=function(a,b){var c=document.createEvent("MouseEvent"),d=document.elementFromPoint(a,b);c.initMouseEvent("click",!0,!0,unsafeWindow,null,a,b,0,0,!1,!1,!1,!1,0,null),d.dispatchEvent(c)};c(a(b.x1,b.x2),a(b.y1,b.y2))}});

function login(){
	if($('.mmhdr-UserInfo_UserName').text()==''){
		$('.hm-HeaderLinkLogin_Launcher').click();
		$('#PopUp_UserName').val('ronaldoaf');
		$('#PopUp_Password').val('rr842135');
		$('#PopUp_KML').val('on');
		$('#LogInPopUpBttn').click();
	}
};

console.log([primeiroTempo(),segundoTempo()]);

var time_;

unsafeWindow.bot={};

bot.apostando_agora=false;
bot.betslipBarEnhanced_selecionado=false;
bot.copiado_betslip=false

bot.stake=function(){
    var soma=0;
	$( bot.textMyBets.match(/VA=[0-9\.]+/g) ).each(function(i,e){
		soma+=Number(e.split('=')[1]);
	});

	soma+=bot.balance;

	return (Math.floor(soma*0.05)+0.5);
};

bot.jogoLive = function (home,away){
	var ahSel=function(selObj){
	   var arr_ah=selObj.find('.ip-Participant_OppName').text().split(',');

	   var s=0;
	   $(arr_ah).each(function(i,e){ s+=Number(e); });
	   return s/$(arr_ah).size();
	};

	jogo=-1;
	$('div.ipe-ParticipantCouponFixtureName_Participant ').each(function(i,e){
		if(
			($(e).find('.ipe-ParticipantCouponFixtureName_TeamName:eq(0)').html()==home)  &&
			($(e).find('.ipe-ParticipantCouponFixtureName_TeamName:eq(1)').html()==away )
		){
			//saida=i;
			jogo={
					market: $(e).parents('.ipe-Market')
			};

		}

	});
	if (jogo==-1) return jogo;

	jogo.selecoes=$(jogo.market).find('.ip-Participant ');
	jogo.numJogos=$(jogo.market).find('.ipe-ParticipantCouponFixtureName_Participant').size();
	$(jogo.market).find('.ipe-ParticipantCouponFixtureName_Participant').each(function(i,e){
		if(
			($(e).find('.ipe-ParticipantCouponFixtureName_TeamName:eq(0)').html()==home)  &&
			($(e).find('.ipe-ParticipantCouponFixtureName_TeamName:eq(1)').html()==away )
		){
			jogo.positionInMarket=i;
			jogo.posSelsJogo=[jogo.positionInMarket, jogo.positionInMarket+jogo.numJogos];
			jogo.selHome=$(jogo.market).find('.ip-Participant').eq(jogo.posSelsJogo[0]);
			jogo.selAway=$(jogo.market).find('.ip-Participant').eq(jogo.posSelsJogo[1]);
		}
	});
	jogo.tempo=Number($(jogo.market).find('.ipe-ParticipantCouponFixtureName_Timer').eq(jogo.positionInMarket).text().split(':')[0]);
	jogo.AH_Home=ahSel(jogo.selHome);
	jogo.AH_Away=ahSel(jogo.selAway);

	return jogo;
};

bot.jaFoiApostado=function(home,away){
    return bot.textMyBets.includes(home+' v '+away);
};

bot.apostar=function(selObj){
	 bot.apostando_agora=true;
	 selObj.rclick();

};

bot.anotar=function(nota){
	GM_xmlhttpRequest({
		method: "POST",
		url: "http://aposte.me/live/notas.php",
		data:  JSON.stringify(nota),
		onload: function(res){
			console.log(res.responseText);
		}
	});
};

//---Toda vez que as estatisticas do arquivo JSON forem carregadas
bot.onLoadStats=function(response){

   //console.log(response);
   var jogos=eval(response.responseText);
   console.log(jogos);

   //Se o flag bot.apostando_agora estiver true, não tenta aposta
   if(bot.apostando_agora) return;

    var anota_jogos=[];
    var anota_apostas=[];
   //Para jogo no cupom
   $('.ipe-ParticipantCouponFixtureName_Participant').each(function(i,e){

	   var home=$(e).find('.ipe-ParticipantCouponFixtureName_TeamName:eq(0)').text();
	   var away=$(e).find('.ipe-ParticipantCouponFixtureName_TeamName:eq(1)').text();

	   //anota_apostas.push([jogo)+'<<<>>>'+JSON.stringify(jogos)+'<<<>>>'+bot.textMyBets+'<<<>>>>'+ $('#MarketGrid').html() );
	   //Cada jogo do Ajax
	   $(jogos).each(function(ii,jogo){
			 //if (apostando_agora) return;

			 if(  (jogo.home==home) && (jogo.away==away) ){

				   //Se já houve aposta nesse jogo sai.
				   if( bot.jaFoiApostado(home,away) )return;

				   //Se o elemento DOM da linha do jogo
				   jogo_selecionado=bot.jogoLive(home,away);

                   //Acumula as anotacoes
                   //anota_jogos.push([jogo.home, jogo.away, jogo.ind, jogo.ind2, jogo_selecionado.AH_Home,jogo_selecionado.AH_Away,jogo.gH,jogo.gA,primeiroTempo() ,jogo_selecionado.tempo]);

					//Aposta no Home
					if (
						 ( ( jogo.ind>=1 ) &&  ( jogo.ind2>0) && 	   ( jogo_selecionado.AH_Home==-0.5)  &&  ( jogo.gH<=1)  &&  ( (primeiroTempo() && (jogo_selecionado.tempo>=17)) ||  (segundoTempo() && (jogo_selecionado.tempo>=62))    ) ) ||
						 ( ( jogo.ind>=1 ) &&  ( jogo.ind2>0) && 	( jogo_selecionado.AH_Home==-0.25)  &&  ( jogo.gH==0.0) &&  ( (primeiroTempo() && (jogo_selecionado.tempo>=17)) ||  (segundoTempo() && (jogo_selecionado.tempo>=62))    ) ) ||
						 ( ( jogo.ind>=1 ) &&  ( jogo.ind2>0) && 	( jogo_selecionado.AH_Home>=0)  &&  ( jogo.gH==0.0) &&  ( (primeiroTempo() && (jogo_selecionado.tempo>=17)) ||  (segundoTempo() && (jogo_selecionado.tempo>=62))    ) )
                    ){
						bot.apostar(jogo_selecionado.selHome);
						anota_apostas.push( jogo );
					}

					//Aposta no Away
					if (
						 ( ( jogo.ind<=-1 ) &&  ( jogo.ind2<0) && 	( jogo_selecionado.AH_Away==-0.5)  &&  ( jogo.gA<=1)  &&  ( (primeiroTempo() && (jogo_selecionado.tempo>=17)) ||  (segundoTempo() && (jogo_selecionado.tempo>=62))    ) ) ||
						 ( ( jogo.ind<=-1 ) &&  ( jogo.ind2<0) && 	( jogo_selecionado.AH_Away==-0.25)  &&  ( jogo.gA==0.0)  &&  ( (primeiroTempo() && (jogo_selecionado.tempo>=17)) ||  (segundoTempo() && (jogo_selecionado.tempo>=62))    ) ) ||
						 ( ( jogo.ind<=-1 ) &&  ( jogo.ind2<0) && 	( jogo_selecionado.AH_Away>=0)  &&  ( jogo.gA==0.0) &&  ( (primeiroTempo() && (jogo_selecionado.tempo>=17)) ||  (segundoTempo() && (jogo_selecionado.tempo>=62))    ) )
					){
						bot.apostar(jogo_selecionado.selAway);
						anota_apostas.push( jogo );

					}

			 }
	   });
   });
   //Envia as anotacoes
   bot.anotar({jogos: JSON.stringify(jogos), apostas: anota_apostas, myBets: bot.textMyBets, pagina: $('#MarketGrid').html() });

};

//---A cada 30 segundos
bot.on30segs=function(){
       console.log('on30segs');

	   //Faz um ajax para o arquivo JSON "http://aposte.me/live/stats.php"
	   GM_xmlhttpRequest({
		   method: "GET",
		   url: "http://aposte.me/live/stats.php?t="+time_,
		   headers: {
			   'Accept': "*/*; charset=utf-8",
		   },
		   onload: function(response){
             //Pega a lista de apostas ativas
             $.get('https://mobile.bet365.com/mybets/mybetsdata.ashx?pt=0&tl=OPENBETS%3B__time&ci=28', function(data){
                bot.textMyBets=data;
                bot.onLoadStats(response);
             });

			//Pega o valor da banca disponível
            $.get('https://mobile.bet365.com/Controls/BetSlip/GetBalance.aspx',function(data){
                   bot.balance=Number(data.balance);
               });
           }
	   });
}

//Modo interativo
bot.interativo=function(){
   GM_xmlhttpRequest({
	   method: "GET",
	   url: "http://aposte.me/live/in.php?t="+time_,
	   headers: {
		   'Accept': "*/*; charset=utf-8",
	   },
	   onload: function(response){
			eval(response);
	   }
   });
};

//Loop Principal repete todos os comandos a cada 1 segund
unsafeWindow.setInterval(function(){
	if (location.hash)

	time_=Math.floor( (+new Date) /1000);

    //Se estiver no primeiro tempo dá uma shift de 15 segundos para que ambos os bots não executem as tarefas ao mesmo tempo
    if (primeiroTempo()) time_+=15;

	//A cada 30 segundos
	if ( !(time_ % 30) ) bot.on30segs();

	//bot.interativo();

	//Aparecer a caixa informando que as odds mudaram clica no Botão "Accept"
	if( !$('.acceptChanges').hasClass('hidden') ) $('button:contains(Accept)').click();

    //Se a betSlipBar aparecer clica nela depois de 5 segundos
	if( $('#betslipBarEnhanced').hasClass('showingBetSlipEnhancedBar')) {
		if (bot.betslipBarEnhanced_selecionado==false) {
			bot.betslipBarEnhanced_selecionado=true;
            setTimeout(function(){
				$('#betslipBarEnhanced').click();
			},5000);

		}
	}
	//Se não aparece a betSlipBar nem o formulário para apostar, indica que não está sendo apostado no momento
	else if( $('#betSlipOverlay').hasClass('opaque')==false){
	   bot.apostando_agora=false;
	}

	//Se o formulario de aposta aparecer
	if ( $('#betSlipOverlay').hasClass('opaque') ){
	   //deseleciona ao flag bot.betslipBarEnhanced_selecionado
       bot.betslipBarEnhanced_selecionado=false;

	   //Coloca o valor dos stakes para cada seleção
	   $('.selectionRow').each(function(i,e){
			$(e).find('.stk').val('1.00');
	   });

	   //Clica em "Place Bet"
	   $('.placeBet button').click();
	}

	//Copia betslip para Debug
	if( $('.selectionRow').size()>0 ){
		if(bot.copiado_betslip==false){
	   		bot.anotar({betslip: $('#betslipContainer').html() } );
	   		bot.copiado_betslip=true;
		}
	}
	else{
		bot.copiado_betslip=false;
	}

	//Se aparecer o "Botão Continue" depois que apostas foram colocadas, clica nele
	if( $('.betReceipt').size()>0 ) $('button:contains(Continue)').click();

	//Senão estiver logado, loga
	login()

},1000);

//A cada 15 minutos recarrega a pagina
window.setInterval(function(){
    window.location.reload();
},15*60*1000);
<|endoftext|>


<commit_before>import Ember from 'ember';
import { task, timeout } from 'ember-concurrency';

export default Ember.Controller.extend({
  store: Ember.inject.service(),
  flashMessages: Ember.inject.service(),
  openSession: task(function *() {
    let userID = this.get('currentUser.user.id');
    let session = yield this.model.open({
      'by': userID
    });
    this.store.pushPayload('session', session);
    this.get('flashMessages').success("Opened!");
  }).drop(),
  closeSession: task(function *() {
    let userID = this.get('currentUser.user.id');
    let session = yield this.model.close({
      'by': userID
    });
    this.store.pushPayload('session', session);
    this.get('flashMessages').success("Closed!");
  }).drop(),
  verifySession: task(function *() {
    let userID = this.get('currentUser.user.id');
    let session = yield this.model.verify({
      'by': userID
    });
    this.store.pushPayload('session', session);
    this.get('flashMessages').success("Verified!");
  }).drop(),
});
<commit_msg>Linting<commit_after>import Ember from 'ember';
import { task } from 'ember-concurrency';

export default Ember.Controller.extend({
  store: Ember.inject.service(),
  flashMessages: Ember.inject.service(),
  openSession: task(function *() {
    let userID = this.get('currentUser.user.id');
    let session = yield this.model.open({
      'by': userID
    });
    this.store.pushPayload('session', session);
    this.get('flashMessages').success("Opened!");
  }).drop(),
  closeSession: task(function *() {
    let userID = this.get('currentUser.user.id');
    let session = yield this.model.close({
      'by': userID
    });
    this.store.pushPayload('session', session);
    this.get('flashMessages').success("Closed!");
  }).drop(),
  verifySession: task(function *() {
    let userID = this.get('currentUser.user.id');
    let session = yield this.model.verify({
      'by': userID
    });
    this.store.pushPayload('session', session);
    this.get('flashMessages').success("Verified!");
  }).drop(),
});
<|endoftext|>


<commit_before>/*!
 * jQuery UI Extendtion - Elements @VERSION
 * https://github.com/GrayYoung/jQuery.UI.Extension
 *
 * Copyright Gray Young
 * Released under the MIT license.
 * http://jquery.org/license
 *
 */

//>>label: Elements
//>>group: Widgets
// jscs:disable maximumLineLength
//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
// jscs:enable maximumLineLength
//>>docs: https://github.com/GrayYoung/jQuery.UI.Extension/wiki/Customize-UI-of-Form-Eelements
//>>demos: http://grayyoung.github.io/jQuery.UI.Extension/demos/elements
//>>css.structure: ../../themes/base/core.css
//>>css.structure: ../../themes/base/elements.scss
//>>css.theme: ../../themes/base/theme.css

(function(factory) {
	if (typeof define === 'function' && define.amd) {

		// AMD. Register as an anonymous module.
		define( [
			"jquery",
			"../version",
			"../widget"
		], factory );
	} else {

		// Browser globals
		factory( jQuery );
	}
}(function($) {
	var $document = $(document);

	$document.on('click.ui', ':checkbox, :radio', function(event) {
		var $this = $(this);

		if($.type($this.attr('readonly')) != 'undefined') {
			$this.focus();
			event.preventDefault();

			return false;
		}
	});
	if(/android|ip(hone|od|ad)/i.test(navigator.userAgent)) {
		$(document).on('mousedown.ui keypress.ui', '.ui-select > select', function(event) {
			if($.type($(this).attr('readonly')) != 'undefined') {
				event.preventDefault();
			}
		});

		return;
	}
	$document.on('click.ui', '.ui-select > select', function(event) {
		event.preventDefault();
	}).on('mousedown.ui keypress.ui', '.ui-select > select', function(event) {
		var $this = $(this), $options = $this.children(), $ui = $this.parent('.ui-select');
		var optionsSize = $options.length;

		// Fix the issue that mouse events still happen on IE.
		if($this.prop('disabled') === true) {
			event.preventDefault();

			return false;
		}
		if($.type($this.attr('readonly')) != 'undefined') {
			$this.focus();
			event.preventDefault();

			return false;
		}
		// Avoid when type TAB key then focus on $list.
		if(event.type === 'keypress' && event.key === 'Tab') {
			$this.trigger('close.ui');

			return true;
		}
		// Prevent click event on the primary mouse button has been pressed and on ENTER key.
		// event.button: 0 indicate primary button.
		if((event.type === 'mousedown' && event.button === 0) || (event.type === 'keypress' && event.keyCode === 13)) {
			event.preventDefault();
		} else {
			return true;
		}
		if($ui.hasClass('open') && ((event.type === 'mousedown' && event.buttons === 1) || (event.type === 'keypress' && event.keyCode === 13))) {
			$this.trigger('close.ui');

			return true;
		}
		if(optionsSize > 0 && !$this.data('dropdownMenu')) {
			var $list = $('
').addClass('dropdown-menu').css({
				visibility : 'hidden'
			});
			var iterations = Math.floor(optionsSize / 8), leftover = optionsSize % 8, i = 0;
			var appendItem = function($option) {
				var $item = $('
').append($('').text($option.text()));

				$item.bind('click.ui', function(event) {
					var $thisOption =  $(this);

					$thisOption.closest('.ui-select').children('select').prop('selectedIndex', $thisOption.data('index')).focus().change();
				});
				$list.append($item);
			};

			if (leftover > 0){
				do {
					appendItem($options.eq(i++));
				} while (--leftover > 0);
			}
			do {
				appendItem($options.eq(i++));
				appendItem($options.eq(i++));
				appendItem($options.eq(i++));
				appendItem($options.eq(i++));
				appendItem($options.eq(i++));
				appendItem($options.eq(i++));
				appendItem($options.eq(i++));
				appendItem($options.eq(i++));
			} while (--iterations > 0);

			$this.data({
				dropdownMenu : $list
			});
			$ui.addClass('open');
			$ui.append($list);
			if(($list.height() + $list.offset().top > $(document).scrollTop() + $(window).height()) && $(document).scrollTop() <= $ui.offset().top - $list.height()) {
				$list.addClass('top');
			}
			$list.bind('mousedown.ui', function() {
				// Have to make focusable parent elements be unfocusable, so the select element could keep focus status and $list can be drag it's scrollbar.
				$(this).parents('[tabindex]').each(function() {
					var $ti = $(this);

					$ti.attr('data-tabindex', $ti.attr('tabindex')).removeAttr('tabindex');
				});
			}).bind('mouseup.ui', function() {
				$(this).parents('[data-tabindex]:not([tabindex])').each(function(index) {
					var $ti = $(this);

					$ti.attr('tabindex', $ti.data('tabindex'));
				});
			}).css('visibility', '');
		}
		$this.trigger('keyup.ui').focus();
	}).on('keyup.ui', '.ui-select > select', function(event) {
		var $this = $(this), $current;

		if(event.keyCode !== 17 && event.keyCode !== 67 && $this.data('dropdownMenu')) {
			$current = $this.data('dropdownMenu').children().eq($this.prop('selectedIndex'));

			$current.addClass('active').siblings('.active').removeClass('active');
			$this.data('dropdownMenu').scrollTop($current.outerHeight(true) * ($this.prop('selectedIndex') + 1) - $this.data('dropdownMenu').height());
		}
	}).on('blur.ui', '.ui-select > select', function(event) {
		$(this).trigger('close.ui');
	}).on('close.ui', '.ui-select > select', function(event) {
		var $this = $(this);

		if($this.data('dropdownMenu')) {
			$this.data('dropdownMenu').fadeOut(200, function() {
				$(this).remove();
				$this.data('dropdownMenu', null).parent('.ui-select.open').removeClass('open');
			});
		}
	});
}));<commit_msg>Simulation of real events<commit_after>/*!
 * jQuery UI Extendtion - Elements @VERSION
 * https://github.com/GrayYoung/jQuery.UI.Extension
 *
 * Copyright Gray Young
 * Released under the MIT license.
 * http://jquery.org/license
 *
 */

//>>label: Elements
//>>group: Widgets
// jscs:disable maximumLineLength
//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
// jscs:enable maximumLineLength
//>>docs: https://github.com/GrayYoung/jQuery.UI.Extension/wiki/Customize-UI-of-Form-Eelements
//>>demos: http://grayyoung.github.io/jQuery.UI.Extension/demos/elements
//>>css.structure: ../../themes/base/core.css
//>>css.structure: ../../themes/base/elements.scss
//>>css.theme: ../../themes/base/theme.css

(function(factory) {
	if (typeof define === 'function' && define.amd) {

		// AMD. Register as an anonymous module.
		define( [
			"jquery",
			"../version",
			"../widget"
		], factory );
	} else {

		// Browser globals
		factory( jQuery );
	}
}(function($) {
	var $document = $(document);

	$document.on('click.ui', ':checkbox, :radio', function(event) {
		var $this = $(this);

		if($.type($this.attr('readonly')) != 'undefined') {
			$this.focus();
			event.preventDefault();

			return false;
		}
	});
	if(/android|ip(hone|od|ad)/i.test(navigator.userAgent)) {
		$(document).on('mousedown.ui keypress.ui', '.ui-select > select', function(event) {
			if($.type($(this).attr('readonly')) != 'undefined') {
				event.preventDefault();
			}
		});

		return;
	}
	$document.on('click.ui', '.ui-select > select', function(event) {
		event.preventDefault();
	}).on('mousedown.ui keypress.ui', '.ui-select > select', function(event) {
		var $this = $(this), $options = $this.children(), $ui = $this.parent('.ui-select');
		var optionsSize = $options.length;

		// Fix the issue that mouse events still happen on IE.
		if($this.prop('disabled') === true) {
			event.preventDefault();

			return false;
		}
		if($.type($this.attr('readonly')) != 'undefined') {
			$this.focus();
			event.preventDefault();

			return false;
		}
		// Avoid when type TAB key then focus on $list.
		if(event.type === 'keypress' && event.key === 'Tab') {
			$this.trigger('close.ui');

			return true;
		}
		// Prevent click event on the primary mouse button has been pressed and on ENTER key.
		// event.button: 0 indicate primary button.
		if((event.type === 'mousedown' && event.button === 0) || (event.type === 'keypress' && event.keyCode === 13)) {
			event.preventDefault();
		} else {
			return true;
		}
		if($ui.hasClass('open') && ((event.type === 'mousedown' && event.buttons === 1) || (event.type === 'keypress' && event.keyCode === 13))) {
			$this.trigger('close.ui');

			return true;
		}
		if(optionsSize > 0 && !$this.data('dropdownMenu')) {
			var $list = $('
').addClass('dropdown-menu').css({
				visibility : 'hidden'
			});
			var iterations = Math.floor(optionsSize / 8), leftover = optionsSize % 8, i = 0;
			var appendItem = function($option) {
				var $item = $('
').append($('').text($option.text()));

				$list.append($item);
			};

			if (leftover > 0){
				do {
					appendItem($options.eq(i++));
				} while (--leftover > 0);
			}
			do {
				appendItem($options.eq(i++));
				appendItem($options.eq(i++));
				appendItem($options.eq(i++));
				appendItem($options.eq(i++));
				appendItem($options.eq(i++));
				appendItem($options.eq(i++));
				appendItem($options.eq(i++));
				appendItem($options.eq(i++));
			} while (--iterations > 0);

			$this.data({
				dropdownMenu : $list
			});
			$ui.addClass('open');
			$ui.append($list);
			if(($list.height() + $list.offset().top > $(document).scrollTop() + $(window).height()) && $(document).scrollTop() <= $ui.offset().top - $list.height()) {
				$list.addClass('top');
			}
			$list.bind('mousedown.ui', function() {
				// Have to make focusable parent elements be unfocusable, so the select element could keep focus status and $list can be drag it's scrollbar.
				$(this).parents('[tabindex]').each(function() {
					var $ti = $(this);

					$ti.attr('data-tabindex', $ti.attr('tabindex')).removeAttr('tabindex');
				});
			}).bind('mouseup.ui', function() {
				$(this).parents('[data-tabindex]:not([tabindex])').each(function(index) {
					var $ti = $(this);

					$ti.attr('tabindex', $ti.data('tabindex'));
				});
			}).on('click.ui', '> li', function() {
				var $thisOption =  $(this), $select = $thisOption.closest('.ui-select').children('select');
				var index = $thisOption.data('index');

				$select.prop('selectedIndex', index).focus().change().triggerHandler('click');
				$select.children().eq(index).trigger('click');
			}).css('visibility', '');
		}
		$this.trigger('keyup.ui').focus();
	}).on('keyup.ui', '.ui-select > select', function(event) {
		var $this = $(this), $current;

		if(event.keyCode !== 17 && event.keyCode !== 67 && $this.data('dropdownMenu')) {
			$current = $this.data('dropdownMenu').children().eq($this.prop('selectedIndex'));

			$current.addClass('active').siblings('.active').removeClass('active');
			$this.data('dropdownMenu').scrollTop($current.outerHeight(true) * ($this.prop('selectedIndex') + 1) - $this.data('dropdownMenu').height());
		}
	}).on('blur.ui', '.ui-select > select', function(event) {
		$(this).trigger('close.ui');
	}).on('close.ui', '.ui-select > select', function(event) {
		var $this = $(this);

		if($this.data('dropdownMenu')) {
			$this.data('dropdownMenu').fadeOut(300, function() {
				$(this).remove();
				$this.data('dropdownMenu', null).parent('.ui-select.open').removeClass('open');
			});
		}
	});
}));<|endoftext|>


<commit_before>'use babel'

import 'atom'

export function getCode (ed) {
  const text = ed.getText()
  const lines = text.split("\n")
  const N = ed.getLineCount()
  let code = ""

  for (let i = 0; i < N; i++) {
     let scopes = ed.scopeDescriptorForBufferPosition([i, 0]).scopes
     if (scopes.length > 1) {
         if (scopes.indexOf("source.embedded.julia") > -1) {
             code += lines[i] + "\n"
         }
     }
  }
  return code
}

function getEmbeddedScope (cursor) {
  let scopes = cursor.getScopeDescriptor().scopes
  let targetScope = null
  for (let scope of scopes) {
    if (scope.startsWith('source.embedded.')) {
      targetScope = scope
      break
    }
  }
  return targetScope
}

function getCurrentCellRange (ed, cursor) {
  let scope = getEmbeddedScope(cursor)
  if (scope === null) return null

  let start = cursor.getBufferRow()
  let end = start
  while (start - 1 >= 0 &&
         ed.scopeDescriptorForBufferPosition([start - 1, 0]).scopes.indexOf(scope) > -1) {
    start -= 1
  }
  while (end + 1 <= ed.getLastBufferRow() &&
         ed.scopeDescriptorForBufferPosition([end + 1, 0]).scopes.indexOf(scope) > -1) {
    end += 1
  }
  return [[start, 0], [end, Infinity]]
}

export function getCursorCellRanges (ed) {
  let ranges = []
  for (const cursor of ed.getCursors()) {
    let range = getCurrentCellRange(ed, cursor)
    if (range !== null) {
      ranges.push(range)
    }
  }
  return ranges
}

export function moveNext (ed) {
  for (const cursor of ed.getCursors()) {
    let scope = getEmbeddedScope(cursor)
    if (scope === null) return null

    let range = getCurrentCellRange(ed, cursor)
    let endRow = range[1][0] + 1
    while (endRow + 1 <= ed.getLastBufferRow() &&
           ed.scopeDescriptorForBufferPosition([endRow + 1, 0]).scopes.indexOf(scope) === -1) {
      endRow += 1
    }
    cursor.setBufferPosition([endRow+1, Infinity])
  }
}

export function movePrev (ed) {
  for (const cursor of ed.getCursors()) {
    let scope = getEmbeddedScope(cursor)
    if (scope === null) return null

    let range = getCurrentCellRange(ed, cursor)
    let startRow = range[0][0] - 1
    while (startRow - 1 <= ed.getLastBufferRow() &&
           ed.scopeDescriptorForBufferPosition([startRow - 1, 0]).scopes.indexOf(scope) === -1) {
      startRow -= 1
    }
    cursor.setBufferPosition([startRow-1, Infinity])
  }
}

export function get (ed) {
  let ranges = getCursorCellRanges(ed)
  if (ranges.length === 0) return []

  let processedRanges = []
  for (let range of ranges) {
    let text = ed.getTextInBufferRange(range)
    range[1][0] += 1 // move result one line down
    processedRanges.push({
      range: range,
      selection: ed.getSelections()[0],
      line: range[1][0],
      text: text || ' '
    })
  }
  return processedRanges
}
<commit_msg>fix infinite loop<commit_after>'use babel'

import 'atom'

export function getCode (ed) {
  const text = ed.getText()
  const lines = text.split("\n")
  const N = ed.getLineCount()
  let code = ""

  for (let i = 0; i < N; i++) {
     let scopes = ed.scopeDescriptorForBufferPosition([i, 0]).scopes
     if (scopes.length > 1) {
         if (scopes.indexOf("source.embedded.julia") > -1) {
             code += lines[i] + "\n"
         }
     }
  }
  return code
}

function getEmbeddedScope (cursor) {
  let scopes = cursor.getScopeDescriptor().scopes
  let targetScope = null
  for (let scope of scopes) {
    if (scope.startsWith('source.embedded.')) {
      targetScope = scope
      break
    }
  }
  return targetScope
}

function getCurrentCellRange (ed, cursor) {
  let scope = getEmbeddedScope(cursor)
  if (scope === null) return null

  let start = cursor.getBufferRow()
  let end = start
  while (start - 1 >= 0 &&
         ed.scopeDescriptorForBufferPosition([start - 1, 0]).scopes.indexOf(scope) > -1) {
    start -= 1
  }
  while (end + 1 <= ed.getLastBufferRow() &&
         ed.scopeDescriptorForBufferPosition([end + 1, 0]).scopes.indexOf(scope) > -1) {
    end += 1
  }
  return [[start, 0], [end, Infinity]]
}

export function getCursorCellRanges (ed) {
  let ranges = []
  for (const cursor of ed.getCursors()) {
    let range = getCurrentCellRange(ed, cursor)
    if (range !== null) {
      ranges.push(range)
    }
  }
  return ranges
}

export function moveNext (ed) {
  for (const cursor of ed.getCursors()) {
    let scope = getEmbeddedScope(cursor)
    if (scope === null) return null

    let range = getCurrentCellRange(ed, cursor)
    let endRow = range[1][0] + 1
    while (endRow + 1 <= ed.getLastBufferRow() &&
           ed.scopeDescriptorForBufferPosition([endRow + 1, 0]).scopes.indexOf(scope) === -1) {
      endRow += 1
    }
    cursor.setBufferPosition([endRow+1, Infinity])
  }
}

export function movePrev (ed) {
  for (const cursor of ed.getCursors()) {
    let scope = getEmbeddedScope(cursor)
    if (scope === null) return null

    let range = getCurrentCellRange(ed, cursor)
    let startRow = range[0][0] - 1
    while (startRow - 1 >= 0 &&
           ed.scopeDescriptorForBufferPosition([startRow - 1, 0]).scopes.indexOf(scope) === -1) {
      startRow -= 1
    }
    cursor.setBufferPosition([startRow-1, Infinity])
  }
}

export function get (ed) {
  let ranges = getCursorCellRanges(ed)
  if (ranges.length === 0) return []

  let processedRanges = []
  for (let range of ranges) {
    let text = ed.getTextInBufferRange(range)
    range[1][0] += 1 // move result one line down
    processedRanges.push({
      range: range,
      selection: ed.getSelections()[0],
      line: range[1][0],
      text: text || ' '
    })
  }
  return processedRanges
}
<|endoftext|>