<commit_before>'use strict';

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

const ccxt = require ('ccxt');

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

module.exports = class ftx extends ccxt.binance {
    describe () {
        return this.deepExtend (super.describe (), {
            'has': {
                'ws': true,
                'watchOrderBook': true,
                'watchTicker': true,
                'watchTrades': true,
            },
            'urls': {
                'api': {
                    'ws': 'wss://ftx.com/ws/',
                },
            },
            'options': {
                'tradesLimit': 1000,
            },
            'streaming': {
                // ftx does not support built-in ws protocol-level ping-pong
                // instead it requires a custom text-based ping-pong
                'ping': this.ping,
                'keepAlive': 15000,
            },
        });
    }

    async watchPublic (symbol, channel, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const marketId = market['id'];
        const url = this.urls['api']['ws'];
        const request = {
            'op': 'subscribe',
            'channel': channel,
            'market': symbol,
        };
        const messageHash = channel + ':' + marketId;
        return await this.watch (url, messageHash, request, messageHash);
    }

    async watchTicker (symbol, params = {}) {
        return await this.watchPublic (symbol, 'ticker');
    }

    async watchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        const future = this.watchPublic (symbol, 'trades');
        return await this.after (future, this.filterBySinceLimit, since, limit, true);
    }

    async watchOrderBook (symbol, limit = undefined, params = {}) {
        const future = this.watchPublic (symbol, 'orderbook');
        return await this.after (future, this.limitOrderBook, symbol, limit, params);
    }

    signMessage (client, messageHash, message) {
        return message;
    }

    handlePartial (client, message) {
        const methods = {
            'orderbook': this.handleOrderBookSnapshot,
        };
        const methodName = this.safeString (message, 'channel');
        const method = this.safeValue (methods, methodName);
        if (method) {
            method.call (this, client, message);
        }
    }

    handleUpdate (client, message) {
        const methods = {
            'trades': this.handleTrades,
            'ticker': this.handleTicker,
            'orderbook': this.handleOrderBookUpdate,
        };
        const methodName = this.safeString (message, 'channel');
        const method = this.safeValue (methods, methodName);
        if (method) {
            method.call (this, client, message);
        }
    }

    handleMessage (client, message) {
        const methods = {
            'partial': this.handlePartial,
            'update': this.handleUpdate,
            'subscribed': this.handleSubscriptionStatus,
            'unsubscribed': this.handleUnsubscriptionStatus,
            'info': this.handleInfo,
            'error': this.handleError,
            'pong': this.handlePong,
        };
        const methodName = this.safeString (message, 'type');
        const method = this.safeValue (methods, methodName);
        if (method) {
            method.call (this, client, message);
        }
    }

    genMessageHashFromData (data) {
        const channel = this.safeString (data, 'channel');
        const market = this.safeString (data, 'market');
        const messageHash = channel + ':' + market;
        return messageHash;
    }

    handleTicker (client, message) {
        const data = this.safeValue (message, 'data', {});
        const rawTicker = this.safeValue (data, 'data', {});
        const ticker = this.parseTicker (rawTicker);
        const symbol = ticker['symbol'];
        this.tickers[symbol] = ticker;
        const messageHash = this.genMessageHashFromData (data);
        client.resolve (ticker, messageHash);
        return message;
    }

    handleOrderBookSnapshot (client, message) {
        // action: partial
        // bids
        // asks
        // checksum: see below
        // time: Timestamp
        const data = this.safeValue (message, 'data', {});
        const symbol = this.safeString (data, 'market');
        const options = this.safeValue (this.options, 'watchOrderBook', {});
        const limit = this.safeInteger (options, 'limit', 400);
        const orderbook = this.orderBook ({}, limit);
        this.orderbooks[symbol] = orderbook;
        const snapshot = this.parseOrderBook (data);
        orderbook.reset (snapshot);
        // const checksum = this.safeString (data, 'checksum');
        // todo: this.checkOrderBookChecksum (client, orderbook, checksum);
        this.orderbooks[symbol] = orderbook;
        const messageHash = this.genMessageHashFromData (data);
        client.resolve (orderbook, messageHash);
    }

    handleDelta (bookside, delta) {
        const price = this.safeFloat (delta, 0);
        const amount = this.safeFloat (delta, 1);
        bookside.store (price, amount);
    }

    handleDeltas (bookside, deltas) {
        for (let i = 0; i < deltas.length; i++) {
            this.handleDelta (bookside, deltas[i]);
        }
    }

    handleOrderBookUpdate (client, message) {
        // action: update
        // bids
        // asks
        // checksum: see below
        // time: Timestamp
        // const u = this.safeInteger (message, 'u');
        const data = this.safeValue (message, 'data', {});
        const symbol = this.safeString (data, 'market');
        const orderbook = this.orderbooks[symbol];
        this.handleDeltas (orderbook['asks'], this.safeValue (data, 'asks', []));
        this.handleDeltas (orderbook['bids'], this.safeValue (data, 'bids', []));
        // orderbook['nonce'] = u;
        const timestamp = this.safeInteger (message, 'time');
        orderbook['timestamp'] = timestamp;
        orderbook['datetime'] = this.iso8601 (timestamp);
        // const checksum = this.safeString (data, 'checksum');
        // todo: this.checkOrderBookChecksum (client, orderbook, checksum);
        this.orderbooks[symbol] = orderbook;
        const messageHash = this.genMessageHashFromData (data);
        client.resolve (orderbook, messageHash);
    }

    handleTrades (client, message) {
        const data = this.safeValue (message, 'data', {});
        const trade = this.parseTrade (data);
        const messageHash = this.genMessageHashFromData (data);
        const symbol = trade['symbol'];
        const array = this.safeValue (this.trades, symbol, []);
        array.push (trade);
        const length = array.length;
        if (length > this.options['tradesLimit']) {
            array.shift ();
        }
        this.trades[symbol] = array;
        client.resolve (array, messageHash);
        return message;
    }

    handleSubscriptionStatus (client, message) {
        // todo: handle unsubscription status
        // {'type': 'subscribed', 'channel': 'trades', 'market': 'BTC-PERP'}
        return message;
    }

    handleUnsubscriptionStatus (client, message) {
        // todo: handle unsubscription status
        // {'type': 'unsubscribed', 'channel': 'trades', 'market': 'BTC-PERP'}
        return message;
    }

    handleInfo (client, message) {
        // todo: handle info messages
        // Used to convey information to the user. Is accompanied by a code and msg field.
        // When our servers restart, you may see an info message with code 20001. If you do, please reconnect.
        return message;
    }

    handleError (client, message) {
        return message;
    }

    ping (client) {
        // ftx does not support built-in ws protocol-level ping-pong
        // instead it requires a custom json-based text ping-pong
        // https://docs.ftx.com/#websocket-api
        return {
            'op': 'ping',
        };
    }

    handlePong (client, message) {
        client.lastPong = this.milliseconds ();
        return message;
    }
};
<commit_msg>fix class inheritance to ftx and some parse issues<commit_after>'use strict';

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

const ccxt = require ('ccxt');

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

module.exports = class ftx extends ccxt.ftx {
    describe () {
        return this.deepExtend (super.describe (), {
            'has': {
                'ws': true,
                'watchOrderBook': true,
                'watchTicker': true,
                'watchTrades': true,
            },
            'urls': {
                'api': {
                    'ws': 'wss://ftx.com/ws/',
                },
            },
            'options': {
                'tradesLimit': 1000,
            },
            'streaming': {
                // ftx does not support built-in ws protocol-level ping-pong
                // instead it requires a custom text-based ping-pong
                'ping': this.ping,
                'keepAlive': 15000,
            },
        });
    }

    async watchPublic (symbol, channel, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const marketId = market['id'];
        const url = this.urls['api']['ws'];
        const request = {
            'op': 'subscribe',
            'channel': channel,
            'market': symbol,
        };
        const messageHash = channel + ':' + symbol;console.log(messageHash);
        return await this.watch (url, messageHash, request, messageHash);
    }

    async watchTicker (symbol, params = {}) {
        return await this.watchPublic (symbol, 'ticker');
    }

    async watchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        const future = this.watchPublic (symbol, 'trades');
        return await this.after (future, this.filterBySinceLimit, since, limit, true);
    }

    async watchOrderBook (symbol, limit = undefined, params = {}) {
        const future = this.watchPublic (symbol, 'orderbook');
        return await this.after (future, this.limitOrderBook, symbol, limit, params);
    }

    signMessage (client, messageHash, message) {
        return message;
    }

    handlePartial (client, message) {
        const methods = {
            'orderbook': this.handleOrderBookSnapshot,
            'trades': this.handleTrades,
        };
        const methodName = this.safeString (message, 'channel');if (methodName != 'orderbook'){
             console.log(methodName);
             console.log(message)
        }
        const method = this.safeValue (methods, methodName);
        if (method) {
            method.call (this, client, message);
        }
    }

    handleUpdate (client, message) {
        const methods = {
            'ticker': this.handleTicker,
            'orderbook': this.handleOrderBookUpdate,
        };
        const methodName = this.safeString (message, 'channel');if (methodName != 'ticker' && methodName != 'orderbook') console.log(methodName);
        const method = this.safeValue (methods, methodName);
        if (method) {
            method.call (this, client, message);
        }
    }

    handleMessage (client, message) {
        const methods = {
            'partial': this.handlePartial,
            'update': this.handleUpdate,
            'subscribed': this.handleSubscriptionStatus,
            'unsubscribed': this.handleUnsubscriptionStatus,
            'info': this.handleInfo,
            'error': this.handleError,
            'pong': this.handlePong,
        };
        const methodName = this.safeString (message, 'type');
        const method = this.safeValue (methods, methodName);
        if (method) {
            method.call (this, client, message);
        }
    }

    genMessageHashFromData (message) {
        const channel = this.safeString (message, 'channel');
        const symbol = this.safeString (message, 'market');
        const messageHash = channel + ':' + symbol;
        return messageHash;
    }

    handleTicker (client, message) {
        const rawTicker = this.safeValue (message, 'data', {});
        const symbol = this.safeString (message, 'market');
        const timestamp = this.safeTimestamp (rawTicker, 'time');
        const last = this.safeFloat (rawTicker, 'last');
        const ticker = {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': undefined,
            'low': undefined,
            'bid': this.safeFloat (rawTicker, 'bid'),
            'bidVolume': undefined,
            'ask': this.safeFloat (rawTicker, 'ask'),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': undefined,
            'quoteVolume': undefined,
            'info': rawTicker,
        };
        this.tickers[symbol] = ticker;
        const messageHash = this.genMessageHashFromData (message);
        client.resolve (ticker, messageHash);
        return message;
    }

    handleOrderBookSnapshot (client, message) {
        // action: partial
        // bids
        // asks
        // checksum: see below
        // time: Timestamp
        const data = this.safeValue (message, 'data', {});
        const symbol = this.safeString (data, 'market');
        const options = this.safeValue (this.options, 'watchOrderBook', {});
        const limit = this.safeInteger (options, 'limit', 400);
        const orderbook = this.orderBook ({}, limit);
        this.orderbooks[symbol] = orderbook;
        const snapshot = this.parseOrderBook (data);
        orderbook.reset (snapshot);
        // const checksum = this.safeString (data, 'checksum');
        // todo: this.checkOrderBookChecksum (client, orderbook, checksum);
        this.orderbooks[symbol] = orderbook;
        const messageHash = this.genMessageHashFromData (message);
        client.resolve (orderbook, messageHash);
    }

    handleDelta (bookside, delta) {
        const price = this.safeFloat (delta, 0);
        const amount = this.safeFloat (delta, 1);
        bookside.store (price, amount);
    }

    handleDeltas (bookside, deltas) {
        for (let i = 0; i < deltas.length; i++) {
            this.handleDelta (bookside, deltas[i]);
        }
    }

    handleOrderBookUpdate (client, message) {
        // action: update
        // bids
        // asks
        // checksum: see below
        // time: Timestamp
        // const u = this.safeInteger (message, 'u');
        const data = this.safeValue (message, 'data', {});
        const symbol = this.safeString (data, 'market');
        const orderbook = this.orderbooks[symbol];
        this.handleDeltas (orderbook['asks'], this.safeValue (data, 'asks', []));
        this.handleDeltas (orderbook['bids'], this.safeValue (data, 'bids', []));
        // orderbook['nonce'] = u;
        const timestamp = this.safeInteger (message, 'time');
        orderbook['timestamp'] = timestamp;
        orderbook['datetime'] = this.iso8601 (timestamp);
        // const checksum = this.safeString (data, 'checksum');
        // todo: this.checkOrderBookChecksum (client, orderbook, checksum);
        this.orderbooks[symbol] = orderbook;
        const messageHash = this.genMessageHashFromData (message);
        client.resolve (orderbook, messageHash);
    }

    handleTrades (client, message) {
        const data = this.safeValue (message, 'data', {});console.log(data);
        const trade = this.parseTrade (data);console.log(trade);
        const messageHash = this.genMessageHashFromData (message);
        const symbol = trade['symbol'];
        const array = this.safeValue (this.trades, symbol, []);
        array.push (trade);
        const length = array.length;
        if (length > this.options['tradesLimit']) {
            array.shift ();
        }
        this.trades[symbol] = array;
        client.resolve (array, messageHash);
        return message;
    }

    handleSubscriptionStatus (client, message) {
        // todo: handle unsubscription status
        // {'type': 'subscribed', 'channel': 'trades', 'market': 'BTC-PERP'}
        return message;
    }

    handleUnsubscriptionStatus (client, message) {
        // todo: handle unsubscription status
        // {'type': 'unsubscribed', 'channel': 'trades', 'market': 'BTC-PERP'}
        return message;
    }

    handleInfo (client, message) {
        // todo: handle info messages
        // Used to convey information to the user. Is accompanied by a code and msg field.
        // When our servers restart, you may see an info message with code 20001. If you do, please reconnect.
        return message;
    }

    handleError (client, message) {
        return message;
    }

    ping (client) {
        // ftx does not support built-in ws protocol-level ping-pong
        // instead it requires a custom json-based text ping-pong
        // https://docs.ftx.com/#websocket-api
        return {
            'op': 'ping',
        };
    }

    handlePong (client, message) {
        client.lastPong = this.milliseconds ();
        return message;
    }
};
<|endoftext|>


<commit_before>'use strict';

import './styles.postcss';
import _ from 'underscore';
import Backbone from 'backbone';
import TileLayer from './TileLayer';
import MarkerLayer from './layers/MarkerLayer';
import PopUpContentView from './../PopUp/PopUpContentView';
import layersCollection from '../../scripts/collections/layersCollection';
import filtersModel from '../../scripts/models/filtersModel';
import utils from '../../scripts/helpers/utils';

class MapView extends Backbone.View {

  initialize(settings) {
    // First configure mapbox
    L.mapbox.accessToken = config.mapboxToken;

    // Setting default options
    this.options = _.extend({}, this.defaults, settings.options);

    //Checking for device
    this.device = utils.checkDevice();

    // Setting first state
    this.state = new Backbone.Model(settings.state);
    this.state.attributes = _.extend({}, this.options, this.state.attributes);
    this.state.set({ 'filters': filtersModel.toJSON() }, { silent: true });
    this._checkMapInitialSettings();

    this._createMap();
    this._addLayer();
    this._setEvents();
  }

  _checkMapInitialSettings() {
    if (this.device.mobile || this.device.tablet) {
      this.state.attributes.zoom = 2;
    }

    // mobile
    if (this.device.mobile) {
      this.state.attributes.lat = 10;
      this.state.attributes.lon = -100;
    }

    // Ipad landscape
    if ( !this.device.tablet && this.device.device ) {
      this.state.attributes.lat = 40;
      this.state.attributes.lon = -120;
    }
  }

  drawDonationMarker(options) {
    this.donationMarker = new MarkerLayer(options);
    this.donationMarker.addLayer(this.map);

    this.myDonationPopUp = new PopUpContentView({
      currentMode: 'my-donation',
      currentLayer: 'my-donation',
      latLng: options.position,
      map: this.map,
      name: options.name
    })

    this.myDonationPopUp.getPopUp();
  }

  _createMap() {
    const mapOptions = {
      zoom: this.state.attributes.zoom,
      center: [this.state.attributes.lat, this.state.attributes.lon]
    };
    this.map = L.mapbox.map(this.el, this.options.style, mapOptions);

    this._addAttributions();
  }

  _addAttributions() {
    // Add attribution to Mapbox and OpenStreetMap.
    let attribution = L.control.attribution();
    attribution.setPrefix('');
    attribution.addAttribution('© Mapbox  | © OpenStreetMap | © CartoDB');
    attribution.addTo(this.map);
  }

  _setEvents() {
    this.map.on('click', this._infowindowSetUp.bind(this));

    this.state.on('change:zoom', () => {
      this.map.setZoom(this.state.attributes.zoom);
    });

    this.state.on('change:lat', () => {
      const center = this.map.getCenter();
      const latlng = L.latLng(this.state.attributes.lat, center.lng);
      this.map.setView(latlng, this.map.getZoom());
    });

    this.state.on('change:lon', () => {
      const center = this.map.getCenter();
      const latlng = L.latLng(center.lat, this.state.attributes.lon);
      this.map.setView(latlng, this.map.getZoom());
    });

    this.state.on('change:filters', () => this.changeLayer());
    this.state.on('change:timelineDates', () => this.changeLayerTimeline());

    this.state.on('change:mode', _.bind(this.changeLayer, this));
    layersCollection.on('change', _.bind(this.changeLayer, this));
    filtersModel.on('change', _.bind(this._updateFilters, this));

    this.map.on('zoomend', _.bind(this._setStateZoom, this));
    this.map.on('dragend', _.bind(this._setStatePosition, this));
  }

  _setStateZoom(e) {
    this.state.set({zoom: this.map.getZoom()});
  }

  _setStatePosition(e) {
    const position = this.map.getCenter();
    this.state.set({ lat: position.lat, lon: position.lng });
  }

  _updateFilters() {
    this.state.set({'filters': filtersModel.toJSON()}, {silent: true});
  }

  _infowindowSetUp(e) {
    this.popUp = new PopUpContentView({
      currentMode: this.state.get('mode'),
      currentLayer: this.state.get('currentLayer'),
      latLng: e.latlng,
      map: this.map,
      zoom: this.state.get('zoom')
    });

    this.popUp.getPopUp();
  }

  _setFilters() {
    if ( !(filtersModel.filtersIsEmpty()) ) {
      this.options.filters = filtersModel.toJSON();
    } else {
      this.options.filters = null;
    }
  }

  _addLayer() {
    //Remove current pop up
    if (this.popUp) {
      this.popUp.closeCurrentPopup();
    }

    //Remove donation stuff
    // if (this.donationMarker) {
    //   this.donationMarker.removeLayer(this.map);
    // }

    // if (this.myDonationPopUp) {
    //    this.myDonationPopUp.closeCurrentPopup();
    // }

    let layerConfig;
    //I will draw only active layers for each category;
    let activeLayers = layersCollection.filter(model => model.attributes.active && model.attributes.category === this.state.get('mode'));

    _.each(activeLayers, (activeLayer) => {
      layerConfig = activeLayer.toJSON();
      const newLayer = new TileLayer(layerConfig, this.state.toJSON());

      newLayer.createLayer().then(() => {
        /* We ensure to always display the latest tiles */
        if(!this.currentLayer || newLayer.timestamp > this.currentLayer.timestamp) {
          this._removeCurrentLayer();
          newLayer.addLayer(this.map)
          this.currentLayer = newLayer;
        }
      });

      this.state.set('currentLayer', layerConfig.slug);
    })
  }

  _removeCurrentLayer() {
    if (this.currentLayer && this.currentLayer.removeLayer) {
      this.currentLayer.removeLayer(this.map);
      this.currentLayer = null;
    }
  }

  changeLayer() {
    this._addLayer();
  }

};

MapView.prototype.changeLayerTimeline = (function() {
  return _.throttle(function() {
    this._addLayer();
  }, 200);
})();

MapView.prototype.defaults = {
  style: location.hostname === 'localhost' ? 'mapbox.streets' : 'jhanley.a25ffffe',
  lat: 35,
  lon: -80,
  zoom: 3
};

export default MapView;
<commit_msg>Fixes an issue where the map wouldn't update when the filters would<commit_after>'use strict';

import './styles.postcss';
import _ from 'underscore';
import Backbone from 'backbone';
import TileLayer from './TileLayer';
import MarkerLayer from './layers/MarkerLayer';
import PopUpContentView from './../PopUp/PopUpContentView';
import layersCollection from '../../scripts/collections/layersCollection';
import filtersModel from '../../scripts/models/filtersModel';
import utils from '../../scripts/helpers/utils';

class MapView extends Backbone.View {

  initialize(settings) {
    // First configure mapbox
    L.mapbox.accessToken = config.mapboxToken;

    // Setting default options
    this.options = _.extend({}, this.defaults, settings.options);

    //Checking for device
    this.device = utils.checkDevice();

    // Setting first state
    this.state = new Backbone.Model(settings.state);
    this.state.attributes = _.extend({}, this.options, this.state.attributes);
    this.state.set({ 'filters': filtersModel.toJSON() }, { silent: true });
    this._checkMapInitialSettings();

    this._createMap();
    this._addLayer();
    this._setEvents();
  }

  _checkMapInitialSettings() {
    if (this.device.mobile || this.device.tablet) {
      this.state.attributes.zoom = 2;
    }

    // mobile
    if (this.device.mobile) {
      this.state.attributes.lat = 10;
      this.state.attributes.lon = -100;
    }

    // Ipad landscape
    if ( !this.device.tablet && this.device.device ) {
      this.state.attributes.lat = 40;
      this.state.attributes.lon = -120;
    }
  }

  drawDonationMarker(options) {
    this.donationMarker = new MarkerLayer(options);
    this.donationMarker.addLayer(this.map);

    this.myDonationPopUp = new PopUpContentView({
      currentMode: 'my-donation',
      currentLayer: 'my-donation',
      latLng: options.position,
      map: this.map,
      name: options.name
    })

    this.myDonationPopUp.getPopUp();
  }

  _createMap() {
    const mapOptions = {
      zoom: this.state.attributes.zoom,
      center: [this.state.attributes.lat, this.state.attributes.lon]
    };
    this.map = L.mapbox.map(this.el, this.options.style, mapOptions);

    this._addAttributions();
  }

  _addAttributions() {
    // Add attribution to Mapbox and OpenStreetMap.
    let attribution = L.control.attribution();
    attribution.setPrefix('');
    attribution.addAttribution('© Mapbox  | © OpenStreetMap | © CartoDB');
    attribution.addTo(this.map);
  }

  _setEvents() {
    this.map.on('click', this._infowindowSetUp.bind(this));

    this.state.on('change:zoom', () => {
      this.map.setZoom(this.state.attributes.zoom);
    });

    this.state.on('change:lat', () => {
      const center = this.map.getCenter();
      const latlng = L.latLng(this.state.attributes.lat, center.lng);
      this.map.setView(latlng, this.map.getZoom());
    });

    this.state.on('change:lon', () => {
      const center = this.map.getCenter();
      const latlng = L.latLng(center.lat, this.state.attributes.lon);
      this.map.setView(latlng, this.map.getZoom());
    });

    this.state.on('change:filters', () => this.changeLayer());
    this.state.on('change:timelineDates', () => this.changeLayerTimeline());

    this.state.on('change:mode', _.bind(this.changeLayer, this));
    layersCollection.on('change', _.bind(this.changeLayer, this));
    filtersModel.on('change', _.bind(this._updateFilters, this));

    this.map.on('zoomend', _.bind(this._setStateZoom, this));
    this.map.on('dragend', _.bind(this._setStatePosition, this));
  }

  _setStateZoom(e) {
    this.state.set({zoom: this.map.getZoom()});
  }

  _setStatePosition(e) {
    const position = this.map.getCenter();
    this.state.set({ lat: position.lat, lon: position.lng });
  }

  _updateFilters() {
    this.state.set({'filters': filtersModel.toJSON()});
  }

  _infowindowSetUp(e) {
    this.popUp = new PopUpContentView({
      currentMode: this.state.get('mode'),
      currentLayer: this.state.get('currentLayer'),
      latLng: e.latlng,
      map: this.map,
      zoom: this.state.get('zoom')
    });

    this.popUp.getPopUp();
  }

  _setFilters() {
    if ( !(filtersModel.filtersIsEmpty()) ) {
      this.options.filters = filtersModel.toJSON();
    } else {
      this.options.filters = null;
    }
  }

  _addLayer() {
    //Remove current pop up
    if (this.popUp) {
      this.popUp.closeCurrentPopup();
    }

    //Remove donation stuff
    // if (this.donationMarker) {
    //   this.donationMarker.removeLayer(this.map);
    // }

    // if (this.myDonationPopUp) {
    //    this.myDonationPopUp.closeCurrentPopup();
    // }

    let layerConfig;
    //I will draw only active layers for each category;
    let activeLayers = layersCollection.filter(model => model.attributes.active && model.attributes.category === this.state.get('mode'));

    _.each(activeLayers, (activeLayer) => {
      layerConfig = activeLayer.toJSON();
      const newLayer = new TileLayer(layerConfig, this.state.toJSON());

      newLayer.createLayer().then(() => {
        /* We ensure to always display the latest tiles */
        if(!this.currentLayer || newLayer.timestamp > this.currentLayer.timestamp) {
          this._removeCurrentLayer();
          newLayer.addLayer(this.map)
          this.currentLayer = newLayer;
        }
      });

      this.state.set('currentLayer', layerConfig.slug);
    })
  }

  _removeCurrentLayer() {
    if (this.currentLayer && this.currentLayer.removeLayer) {
      this.currentLayer.removeLayer(this.map);
      this.currentLayer = null;
    }
  }

  changeLayer() {
    this._addLayer();
  }

};

MapView.prototype.changeLayerTimeline = (function() {
  return _.throttle(function() {
    this._addLayer();
  }, 200);
})();

MapView.prototype.defaults = {
  style: location.hostname === 'localhost' ? 'mapbox.streets' : 'jhanley.a25ffffe',
  lat: 35,
  lon: -80,
  zoom: 3
};

export default MapView;
<|endoftext|>


<commit_before>var db = require("../../server/db/db.js")

module.exports = {
    likeResource: function(req, res){
        console.log("in like server controller")
        console.log(req.body)
        var userLikes = req.body
        db.cypherQuery("MATCH (u:User {username:{username}}),(e:Episode {title:{ResourceName}}), (r: Resource {name: {ResourceName}}) MERGE (r)<-[:HAS_LIKED]-(u)-[:HAS_LIKED]->(e)-[:EPISODE_OF]->(r)", userLikes, function(err, query){
            if(err){
                res.sendStatus(404);
            } else{
                res.sendStatus(200);
            }
        });
    },
    dislikeResource: function(req, res){
        var userDislikes = req.body
        db.cypherQuery("MATCH (u:User {username:{username}}),(e:Episode {title:{ResourceName}}) MERGE (u)-[:HAS_DISLIKED]->(e)", userDislikes, function(err, query){
            if(err){
                res.sendStatus(404);
            } else{
                res.sendStatus(200);
            }
        });
    },
    markAsSeen: function(req, res){
        var userHasSeen = req.body
        db.cypherQuery("MATCH (u:User {username:{username}}),(e:Episode {title:{ResourceName}}) MERGE (u)-[:HAS_SEEN]->(e)", userHasSeen, function(err, query){
            if(err){
                res.sendStatus(404);
            } else{
                res.sendStatus(200);
            }
        });
    }
};<commit_msg>breaking breaking breaking<commit_after>var db = require("../../server/db/db.js")

module.exports = {
    likeResource: function(req, res){
        console.log("in like server controller")
        console.log(req.body)
        var userLikes = req.body
        db.cypherQuery("MATCH (u:User {username:{username}}),(e:Episode {title:{ResourceName}}), (r: Resource {name: {ResourceName}}) MERGE (r)<-[:HAS_LIKED]-(u)-[:HAS_LIKED]->(e)-[:EPISODE_OF]->(r) UNION ALL (u)-[:HAS_LIKED]-(r)", userLikes, function(err, query){
            if(err){
                res.sendStatus(404);
            } else{
                res.sendStatus(200);
            }
        });
    },
    dislikeResource: function(req, res){
        var userDislikes = req.body
        db.cypherQuery("MATCH (u:User {username:{username}}),(e:Episode {title:{ResourceName}}) MERGE (u)-[:HAS_DISLIKED]->(e)", userDislikes, function(err, query){
            if(err){
                res.sendStatus(404);
            } else{
                res.sendStatus(200);
            }
        });
    },
    markAsSeen: function(req, res){
        var userHasSeen = req.body
        db.cypherQuery("MATCH (u:User {username:{username}}),(e:Episode {title:{ResourceName}}) MERGE (u)-[:HAS_SEEN]->(e)", userHasSeen, function(err, query){
            if(err){
                res.sendStatus(404);
            } else{
                res.sendStatus(200);
            }
        });
    }
};<|endoftext|>


<commit_before>import React from 'react'
import Link from 'gatsby-link'
import styled from 'styled-components'

import { withPrefix } from 'gatsby-link'

import * as palette from '../../utils/styles'

const Hero = ({avatar}) => {

const NavBar = styled.div`
    height: 4rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    color: #000000;
`
const NavLeft = styled.div`
padding: 1rem;
position: relative;
opacity: 1;
align-self: self-start;
display: flex;
align-items: center;
justify-content: center;
a img {height:2rem;margin: 0;}
img{height: 100%;margin: 0;vertical-align:middle;}
h4 {margin:0 0 0 1rem;}
@media (max-width: 768px) {
  h4 {display: none;}
}
`
const NavRight = styled.div`
   padding: 1rem;
   position: relative;
   opacity: 1;
   align-self: self-end;
   display: flex;
   align-items: center;
   justify-content: center;
   img{height:1.618rem;margin:0 0 0 0;}
`

return (

  <NavBar>
    <NavLeft>

I AM MATTHIAS

    </NavLeft>
    <NavRight>

    </NavRight>
  </NavBar>

)
}

export default Hero;
<commit_msg>Update index.js<commit_after>import React from 'react'
import Link from 'gatsby-link'
import styled from 'styled-components'

import { withPrefix } from 'gatsby-link'

import * as palette from '../../utils/styles'

const Hero = ({avatar}) => {

const NavBar = styled.div`
    height: 4rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    color: ${palette.SECONDARY_COLOR };
`
const NavLeft = styled.div`
padding: 1rem;
position: relative;
opacity: 1;
align-self: self-start;
display: flex;
align-items: center;
justify-content: center;
a img {height:2rem;margin: 0;}
img{height: 100%;margin: 0;vertical-align:middle;}
h4 {margin:0 0 0 1rem;}
a h4 {color: ${palette.SECONDARY_COLOR };}
@media (max-width: 768px) {
  h4 {display: none;}
}
`
const NavRight = styled.div`
   padding: 1rem;
   position: relative;
   opacity: 1;
   align-self: self-end;
   display: flex;
   align-items: center;
   justify-content: center;
   img{height:1.618rem;margin:0 0 0 0;}
`

return (

  <NavBar>
    <NavLeft>

I AM MATTHIAS

    </NavLeft>
    <NavRight>

    </NavRight>
  </NavBar>

)
}

export default Hero;
<|endoftext|>


<commit_before>define([
    'jsiso/canvas/Control',
    'jsiso/canvas/Input',
    'jsiso/img/load',
    'jsiso/json/load',
    'jsiso/tile/Field',
    'jsiso/pathfind/pathfind',
    '../../player',
    '../../action'
  ],
  (CanvasControl, CanvasInput, imgLoader, jsonLoader, TileField, pathfind, Player, ActionExecutor) => {

  let requestAnimFrame = (function() {
    return window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame  ||
    window.mozRequestAnimationFrame     ||
    window.oRequestAnimationFrame       ||
    window.msRequestAnimationFrame      ||
    function(callback, element) {
      window.setTimeout(callback, 1000 / 60);
    };
  })();

  const ELEMENT_NAMES = {
    containerName: 'container',
    frameName: 'text-frame',
    messageName: 'text-message',
    indicatorName: 'text-indicator'
  };

  let appendHtml = (el, str) => {
    let div = document.createElement('div');
    div.innerHTML = str;
    while (div.children.length > 0) {
      el.appendChild(div.children[0]);
    }
  }

  let createElements = (container, names) => {
    let elements = '\

\

\
        \
        ▼\

\
    ';
    appendHtml(container, elements);
  }

  return function TileEngine(x, y, xrange, yrange, parent=document.body, overrides) {
    let self = this;
    overrides = Object.assign({}, overrides);

    let elementNames = Object.assign(ELEMENT_NAMES, overrides.elementNames);
    createElements(parent, elementNames);
    const container = document.getElementById(elementNames.containerName);

    let textMessages = [];
    const textMessageFrame = document.getElementById(elementNames.frameName);
    const textMessage = document.getElementById(elementNames.messageName);
    const textIndicator = document.getElementById(elementNames.indicatorName)

    const controlWidth = container.clientWidth;
    const controlHeight = container.clientHeight;
    const context = CanvasControl.create("canvas", controlWidth, controlHeight, {}, elementNames.containerName, true);

    let backgroundLayers = [];
    let foregroundLayers = [];

    let paused = false;
    let mapLayers = [];
    let players = [];

    let actionExecutor = new ActionExecutor();

    //CanvasControl.fullScreen();
    const input = new CanvasInput(document, CanvasControl());

    input.mouse_action(function(coords) {
      if (paused) {
        drawMessages()
      } else {
        let player = players[0];
        let layer = player.properties.layer;
        let t = layer.applyMouseFocus(coords.x, coords.y);
        player.goTo(t.x, t.y);
      }
    });

    input.keyboard(function(pressed, status) {
      let player = players[0];
      if (status) {
        if (paused) {
          if ([13, 32].indexOf(pressed) >= 0) {
            drawMessages();
          }
        } else {
          switch (pressed) {
            case 37: player.moveTo(player.getTile().x - 1, player.getTile().y); break;
            case 38: player.moveTo(player.getTile().x, player.getTile().y - 1); break;
            case 39: player.moveTo(player.getTile().x + 1, player.getTile().y); break;
            case 40: player.moveTo(player.getTile().x, player.getTile().y + 1); break;
            case 13: case 32: interact(player, player.getLookedAtTile()); break;
          }
        }
      }
    });

    let getActions = (player=null) => {
      let layers = mapLayers;
      if (player !== null) {
        layers = layers.filter((layer) => layer.zIndex === player.properties.zIndex);
      }
      let actions = [];
      layers.forEach((layer) => actions = actions.concat(layer.actions || []));
      return actions;
    }

    let interact = (player, tile) => {
      if (!player.isMoving()) {
        getActions(player)
          .filter((action) => action.type !== actionExecutor.TYPE_POSITIONAL)
          .filter((action) => action.x === tile.x && action.y == tile.y)
          .forEach((action) => actionExecutor.execute(action, self, player));
      }
    };

    let pause = () => {
      paused = true;
    }

    let unpause = () => {
      paused = false;
      draw();
    }

    let clearText = () => {
      textMessages = [];
      textMessageFrame.classList.remove("in");
      textMessage.innerHTML = "";
      textIndicator.classList.remove("in");
      if (paused) {
        unpause();
      }
    }

    this.displayText = (text) => {
      textMessages = textMessages.concat(text);
    }

    let drawMessages = () => {
      if (textMessages.length > 0) {
        pause();
        let text = textMessages.splice(0, 1)[0];
        textMessage.innerHTML = text;
        if (!("in" in textMessageFrame.classList)) {
          textMessageFrame.classList.add("in");
        }
        if (textMessages.length >= 1) {
          textIndicator.classList.add("in");
        } else {
          textIndicator.classList.remove("in");
        }
      } else {
        clearText();
      }
    }

    let drawLayers = (layers) => {
      for (let i = y; i < yrange; i++) {
        for (let j = x; j < xrange; j++) {
          layers.forEach((layer) => layer.draw(i, j));
        }
      }
    }

    let setPlayerLighting = (tile) => {
      mapLayers.forEach((layer) => layer.setLight(tile.x, tile.y));
    }

    let previousTime = 0;
    let timeToDraw = (time) => !overrides.lockedFrameRate || (time - previousTime) >= 1000 / overrides.lockedFrameRate;

    let draw = (time) => {
      if (!timeToDraw(time)) {
        requestAnimationFrame(draw);
      } else {
        previousTime = time;
        context.clearRect(0, 0, controlWidth, controlHeight);
        drawLayers(backgroundLayers);
        for (let player of players) {
          player.draw();
          player.move();
          setPlayerLighting(player.getTile());
        }
        drawLayers(foregroundLayers);
        drawMessages();
        if (!paused) {
          requestAnimationFrame(draw);
        }
      }
    }

    let initLayer = (layer) => {
      let mapLayer = new TileField(context, controlWidth, controlHeight);
      mapLayer.setup(layer);
      mapLayer.flip("horizontal");
      mapLayer.rotate("left");
      mapLayer.setLightmap(layer.lightmap);
      mapLayer = Object.assign(mapLayer, layer);
      return mapLayer;
    }

    this.init = (map) => {
      let playerOptions = map.characters["player"];
      imgLoader([{
        graphics: [playerOptions.sprites],
        spritesheet: {
          width: playerOptions.width,
          height: playerOptions.height
        }
      }]).then((playerImages) => {
        mapLayers = map.layers.sort((a, b) => a.zIndex > b.zIndex).map(initLayer);
        backgroundLayers = mapLayers.filter((layer) => layer.zIndex < playerOptions.zIndex && layer.visible);
        foregroundLayers = mapLayers.filter((layer) => layer.zIndex >= playerOptions.zIndex && layer.visible);

        playerOptions.files = playerImages[0].files;
        playerOptions.layer = mapLayers[0];
        playerOptions.pathfindingLayer = mapLayers[playerOptions.pathfindingLayer];
        playerOptions.tileWidth = map.tileWidth;
        playerOptions.tileHeight = map.tileHeight;

        let player = new Player(context, playerOptions, playerOptions.x, playerOptions.y, pathfind);
        player.on("changeTile", (p, tile) => {
          getActions().filter((action) => action.type === actionExecutor.TYPE_POSITIONAL).forEach((action) => {
            if (action.x === tile.x && action.y === tile.y) {
              actionExecutor.execute(action, self, p);
            }
          })
        });

        players.push(player);

        draw();
      });
    }
  }
});<commit_msg>Allow to interact with objects next to the player when using the mouse<commit_after>define([
    'jsiso/canvas/Control',
    'jsiso/canvas/Input',
    'jsiso/img/load',
    'jsiso/json/load',
    'jsiso/tile/Field',
    'jsiso/pathfind/pathfind',
    '../../player',
    '../../action'
  ],
  (CanvasControl, CanvasInput, imgLoader, jsonLoader, TileField, pathfind, Player, ActionExecutor) => {

  let requestAnimFrame = (function() {
    return window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame  ||
    window.mozRequestAnimationFrame     ||
    window.oRequestAnimationFrame       ||
    window.msRequestAnimationFrame      ||
    function(callback, element) {
      window.setTimeout(callback, 1000 / 60);
    };
  })();

  const ELEMENT_NAMES = {
    containerName: 'container',
    frameName: 'text-frame',
    messageName: 'text-message',
    indicatorName: 'text-indicator'
  };

  let appendHtml = (el, str) => {
    let div = document.createElement('div');
    div.innerHTML = str;
    while (div.children.length > 0) {
      el.appendChild(div.children[0]);
    }
  }

  let createElements = (container, names) => {
    let elements = '\

\

\
        \
        ▼\

\
    ';
    appendHtml(container, elements);
  }

  return function TileEngine(x, y, xrange, yrange, parent=document.body, overrides) {
    let self = this;
    overrides = Object.assign({}, overrides);

    let elementNames = Object.assign(ELEMENT_NAMES, overrides.elementNames);
    createElements(parent, elementNames);
    const container = document.getElementById(elementNames.containerName);

    let textMessages = [];
    const textMessageFrame = document.getElementById(elementNames.frameName);
    const textMessage = document.getElementById(elementNames.messageName);
    const textIndicator = document.getElementById(elementNames.indicatorName)

    const controlWidth = container.clientWidth;
    const controlHeight = container.clientHeight;
    const context = CanvasControl.create("canvas", controlWidth, controlHeight, {}, elementNames.containerName, true);

    let backgroundLayers = [];
    let foregroundLayers = [];

    let paused = false;
    let mapLayers = [];
    let players = [];

    let actionExecutor = new ActionExecutor();

    //CanvasControl.fullScreen();
    const input = new CanvasInput(document, CanvasControl());

    input.mouse_action(function(coords) {
      if (paused) {
        drawMessages()
      } else {
        let player = players[0];
        let layer = player.properties.layer;
        let t = layer.applyMouseFocus(coords.x, coords.y);
        player.goTo(t.x, t.y);
        if (Math.abs(t.x - player.getTile().x) + Math.abs(t.y - player.getTile().y) === 1) {
          interact(player, t);
        }
      }
    });

    input.keyboard(function(pressed, status) {
      let player = players[0];
      if (status) {
        if (paused) {
          if ([13, 32].indexOf(pressed) >= 0) {
            drawMessages();
          }
        } else {
          switch (pressed) {
            case 37: player.moveTo(player.getTile().x - 1, player.getTile().y); break;
            case 38: player.moveTo(player.getTile().x, player.getTile().y - 1); break;
            case 39: player.moveTo(player.getTile().x + 1, player.getTile().y); break;
            case 40: player.moveTo(player.getTile().x, player.getTile().y + 1); break;
            case 13: case 32: interact(player, player.getLookedAtTile()); break;
          }
        }
      }
    });

    let getActions = (player=null) => {
      let layers = mapLayers;
      if (player !== null) {
        layers = layers.filter((layer) => layer.zIndex === player.properties.zIndex);
      }
      let actions = [];
      layers.forEach((layer) => actions = actions.concat(layer.actions || []));
      return actions;
    }

    let interact = (player, tile) => {
      if (!player.isMoving()) {
        getActions(player)
          .filter((action) => action.type !== actionExecutor.TYPE_POSITIONAL)
          .filter((action) => action.x === tile.x && action.y == tile.y)
          .forEach((action) => actionExecutor.execute(action, self, player));
      }
    };

    let pause = () => {
      paused = true;
    }

    let unpause = () => {
      paused = false;
      draw();
    }

    let clearText = () => {
      textMessages = [];
      textMessageFrame.classList.remove("in");
      textMessage.innerHTML = "";
      textIndicator.classList.remove("in");
      if (paused) {
        unpause();
      }
    }

    this.displayText = (text) => {
      textMessages = textMessages.concat(text);
    }

    let drawMessages = () => {
      if (textMessages.length > 0) {
        pause();
        let text = textMessages.splice(0, 1)[0];
        textMessage.innerHTML = text;
        if (!("in" in textMessageFrame.classList)) {
          textMessageFrame.classList.add("in");
        }
        if (textMessages.length >= 1) {
          textIndicator.classList.add("in");
        } else {
          textIndicator.classList.remove("in");
        }
      } else {
        clearText();
      }
    }

    let drawLayers = (layers) => {
      for (let i = y; i < yrange; i++) {
        for (let j = x; j < xrange; j++) {
          layers.forEach((layer) => layer.draw(i, j));
        }
      }
    }

    let setPlayerLighting = (tile) => {
      mapLayers.forEach((layer) => layer.setLight(tile.x, tile.y));
    }

    let previousTime = 0;
    let timeToDraw = (time) => !overrides.lockedFrameRate || (time - previousTime) >= 1000 / overrides.lockedFrameRate;

    let draw = (time) => {
      if (!timeToDraw(time)) {
        requestAnimationFrame(draw);
      } else {
        previousTime = time;
        context.clearRect(0, 0, controlWidth, controlHeight);
        drawLayers(backgroundLayers);
        for (let player of players) {
          player.draw();
          player.move();
          setPlayerLighting(player.getTile());
        }
        drawLayers(foregroundLayers);
        drawMessages();
        if (!paused) {
          requestAnimationFrame(draw);
        }
      }
    }

    let initLayer = (layer) => {
      let mapLayer = new TileField(context, controlWidth, controlHeight);
      mapLayer.setup(layer);
      mapLayer.flip("horizontal");
      mapLayer.rotate("left");
      mapLayer.setLightmap(layer.lightmap);
      mapLayer = Object.assign(mapLayer, layer);
      return mapLayer;
    }

    this.init = (map) => {
      let playerOptions = map.characters["player"];
      imgLoader([{
        graphics: [playerOptions.sprites],
        spritesheet: {
          width: playerOptions.width,
          height: playerOptions.height
        }
      }]).then((playerImages) => {
        mapLayers = map.layers.sort((a, b) => a.zIndex > b.zIndex).map(initLayer);
        backgroundLayers = mapLayers.filter((layer) => layer.zIndex < playerOptions.zIndex && layer.visible);
        foregroundLayers = mapLayers.filter((layer) => layer.zIndex >= playerOptions.zIndex && layer.visible);

        playerOptions.files = playerImages[0].files;
        playerOptions.layer = mapLayers[0];
        playerOptions.pathfindingLayer = mapLayers[playerOptions.pathfindingLayer];
        playerOptions.tileWidth = map.tileWidth;
        playerOptions.tileHeight = map.tileHeight;

        let player = new Player(context, playerOptions, playerOptions.x, playerOptions.y, pathfind);
        player.on("changeTile", (p, tile) => {
          getActions().filter((action) => action.type === actionExecutor.TYPE_POSITIONAL).forEach((action) => {
            if (action.x === tile.x && action.y === tile.y) {
              actionExecutor.execute(action, self, p);
            }
          })
        });

        players.push(player);

        draw();
      });
    }
  }
});<|endoftext|>


<commit_before>import React from 'react';
import { values } from 'lodash';
import { Link } from 'react-router'
import { ListGroup, ListGroupItem, Image } from 'react-bootstrap';

class ShopsListItem extends React.Component {

    render(){
        return <Link to={`/shops/${this.props.id}`}>
                <ListGroupItem>

{this.props.name}

Maybe Some description here.

                        <Image className="pull-right responsive" src="http://lorempixel.com/150/100/city/" />

                </ListGroupItem>
            </Link>
    }
}

export default class ShopsList extends React.Component {

    render(){
        const shops = values(this.props.shops);
        return (

            {/*
Shops
*/}
            <ListGroup>
                { shops.map((shop) => {
                    return <ShopsListItem {...shop} key={shop.id} onShopClick={this.props.onShopClick} />
                    })
                }
            </ListGroup>

        )
    }

}<commit_msg>using placehold.it for image placeholders<commit_after>import React from 'react';
import { values } from 'lodash';
import { Link } from 'react-router'
import { ListGroup, ListGroupItem, Image } from 'react-bootstrap';

class ShopsListItem extends React.Component {

    render(){
        return <Link to={`/shops/${this.props.id}`}>
                <ListGroupItem>

{this.props.name}

Maybe Some description here.

                        <Image className="pull-right responsive" src="http://placehold.it/150x100" />

                </ListGroupItem>
            </Link>
    }
}

export default class ShopsList extends React.Component {

    render(){
        const shops = values(this.props.shops);
        return (

            {/*
Shops
*/}
            <ListGroup>
                { shops.map((shop) => {
                    return <ShopsListItem {...shop} key={shop.id} onShopClick={this.props.onShopClick} />
                    })
                }
            </ListGroup>

        )
    }

}<|endoftext|>


<commit_before>engine = {};
engine.canvas = null;
engine.runtime = null;
engine.draw = function(){};
engine.update = function(){};
engine.load = function(){
};

/*
Prints a value in console using "[engine]" prefix.

@value = a printable value
return nothing
 */
engine.msg = function( value ){
	console.log( "[engine] " + value );
};

/*
 Update canvas clearing the last draw.
return nothing
 */
engine.clear = function(){
	engine.canvas.width ++;
	engine.canvas.width --;
}

engine.events = {};
engine.events.VK_UP = 38;
engine.events.VK_DOWN = 40;
engine.events.VK_LEFT = 37;
engine.events.VK_RIGHT = 39;
engine.events.VK_A = 65;
engine.events.key_down = -1;
engine.events.key_up = -1;
document.onkeydown = key_down;
document.onkeyup = key_up;
function key_down( event ){
	event = event || window.event;
	engine.events.key_down = event.keyCode;
	engine.events.key_up = -1;

	//event.preventDefault();
};
function key_up( event ){
	event = event || window.event;
	engine.events.key_up = event.keyCode;
	if( engine.events.key_toogle == false ){
		engine.events.key_down = -1;
	}
	//event.preventDefault();
}
engine.events.key_toogle = false;

/*
Allow to know when a key is down.

@key: keys such as "up", "down", "left", "right", or letter.
Return boolean
 */
engine.events.iskeydown = function( key ){
	if( key == "up" && engine.events.key_down == engine.events.VK_UP ){
		return true;
	}else if( key == "down" && engine.events.key_down == engine.events.VK_DOWN ){
		return true;
	}else if( key == "left" && engine.events.key_down == engine.events.VK_LEFT ){
		return true;
	}else if( key == "right" && engine.events.key_down == engine.events.VK_RIGHT ){
		return true;
	}else if( key == "a"  && engine.events.key_down == engine.events.VK_A ){
		return true
	}

	return false;
};

engine.events.touch_x = 0;
engine.events.touch_y = 0;
engine.events.click_x = 0;
engine.events.click_y = 0;

/*
get x, y -absolute- positions through Click or Touch
*/
function doTouchStart( event ){
	event.preventDefault();
	engine.events.touch_x = event.targetTouches[0].pageX;
	engine.events.touch_y = event.targetTouches[0].pageY;
}
function doTouchEnd( event ){
	event.preventDefault();
	engine.events.touch_x = -1;
	engine.events.touch_y = -1;
}
function doClickStart( event ){
	engine.events.click_x = event.clientX;
	engine.events.click_y = event.clientY;
}
function doClickEnd( event ){
	engine.events.click_x = -1;
	engine.events.click_y = -1;
}

/*
 Object container drawable, updatable.

 @name: name to map
 @width, @height: width, height
 */
engine.map = function( name, width, height ){
	this.width = width;
	this.height = height;
	this.name = name;

	this.entity_list = [];
	this.push = function( item ){
		this.entity_list.push( item );
	};

	/*
	To get the first entity in an x,y point.

	@x: x position
	@y: y position
	Return an entity
	*/
	this.getAt = function( x, y ){
		var i = 0;
		for( ; i < this.entity_list.length; i++ ){
			var entity = this.entity_list[i];
			if( x >= entity.x && x <= entity.x + entity.w
				&& y >= entity.y && y <= entity.y + entity.h ){
				return entity;
			}
		}

		return null;
	};
	/*
	map draw.  Its draw all entity in the map.

	Return nothing.
	*/
	this.draw = function(){
		this.entity_list.forEach(
			function( item ){
				item.draw();
			}
		);

	};

	/*
	...

	Return nothing
	*/
	this.update = function(){
	};
};
engine.current_map = null;
engine.setMap = function( map ){
	engine.current_map  = map;
}

engine.viewport = {};
engine.viewport.enabled = false;
engine.viewport.width = 10;
engine.viewport.height = 10;
engine.viewport.x = 0;
engine.viewport.y = 0;
engine.viewport.dx = 1;
engine.viewport.dy = 1;
engine.viewport.acceleration = 0;
engine.viewport.update = function(){
	engine.viewport.x += engine.viewport.dx;
	engine.viewport.y += engine.viewport.dy;

	engine.viewport.dx *= engine.viewport.acceleration;
	engine.viewport.dy *= engine.viewport.acceleration;
}
engine.viewport.moveTo = function( x, y ){
	engine.viewport.x = x;
	engine.viewport.y = y;
};
engine.viewport.followTo = function( entity ){
	engine.viewport.x = entity.x;
	engine.viewport.y = entity.y;
	engine.viewport.x -= engine.viewport.width / 2;
	engine.viewport.y -= engine.viewport.height / 2;

	engine.viewport.dx = entity.dx;
	engine.viewport.dy = entity.dy;
	engine.viewport.acceleration = entity.acceleration;
};

engine.image = {};
engine.image.draw = function( key, x, y){
	var img = engine.image.get(key);

	engine.canvas.getContext("2d").drawImage( img.img, parseInt(x), parseInt(y) );
};
engine.image.sprites = [];
engine.image.sprites_loaded = 0;
engine.image.load_status = function(){
	engine.image.sprites_loaded ++;
	return "["+engine.image.sprites_loaded + "/" + engine.image.sprites.length+"]";
};
engine.image.load_them = function(){
	// loading
	engine.image.sprites.forEach(
		function( item ){
			var img = new Image();
			img.src = item.src;
			img.onload = function(){
							item.loaded = true;
							engine.msg( engine.image.load_status() + " " + item.src+" loaded. " );
							};
			item.img = img;
		}
	);
};
engine.image.get = function( key ){
	var i = 0;
	for( ; i < engine.image.sprites.length ; i ++ ){
		var item = engine.image.sprites[ i ];
		if( item.key == key ){
			// console.log("found "+key);
			return item;
		}
	}

	return null;
}
engine.image.load = function( src, key ){
	engine.image.sprites.push( { "src": src, "key": key, "img": new Image(), "loaded": false } );
};

engine.entity = function Entity(key, x, y){
	this.x = x;
	this.y = y;
	this.w = 32;
	this.h = 32;
	this.key = key;
	this.tag = "";

	this.dx = 0;
	this.dy = 0;
	this.friction = 0.05;
	this.acceleration = 0;
	this.visible = true;

	this.animation_frames = [];
	this.animation_dt = 0;
	this.animation_index = 0;
	this.animation_loop = -1;
	this.animation_running = false;

	this.addFrame = function( frame_key, dt ){
		if( this.animation_frames.length == 0 ){
			this.key = frame_key;
			this.animation_dt = dt;
			this.animation_index = 0;
			this.animation_running = false;
		}
		this.animation_frames.push({ "key":frame_key, "dt": dt });
	};

	this.draw = function(){
		if( this.visible == false ) return;

		if( engine.viewport.enabled == true ){
			var key = this.key;

			if( this.animation_frames.length > 0 ){

				engine.image.draw( this.key, this.x - engine.viewport.x, this.y - engine.viewport.y );
				if( this.animation_running == false ){
					var animation_index = this.animation_index + 1;
					if( animation_index >= this.animation_frames.length ){
						this.animation_index = -1;
						animation_index = 0;
					}
					var animation_frames = this.animation_frames[ animation_index ];
					var next_key = animation_frames.key;
					var self = this;

					setTimeout( function(){
						self.key = next_key;
						self.animation_index ++ ;

						self.animation_running = false;
					}, this.animation_dt );

					this.animation_running = true;
				}
			}else{
				engine.image.draw( key, this.x - engine.viewport.x, this.y - engine.viewport.y );
			}
		}else{
			engine.image.draw( this.key, this.x, this.y);
		}
	};
	this.update = function(){
		this.x += this.dx;
		this.y += this.dy;

		this.dx *= this.acceleration;
		this.dy *= this.acceleration;
	};
	this.collide = function( entity ){
		if( entity.visible == false ){
			return false;
		}

		var x_axis = false, y_axis = false;
		if( this.x >= entity.x && this.x <= ( entity.x + entity.w )
			|| ( this.x + this.w ) >= entity.x && ( this.x + this.w ) <= ( entity.x + entity.w ) ){
			x_axis = true;
		}
		if( this.y >= entity.y && this.y <= ( entity.y + entity.h )
			|| ( this.y + this.h ) >= entity.y && ( this.y + this.h ) <= ( entity.y + entity.h ) ){
			y_axis = true;
		}

		return ( x_axis && y_axis );
	}
}

engine.start = function(){
	engine.canvas = document.getElementById( "screen" );
	engine.canvas.addEventListener("touchstart", doTouchStart, false);
	engine.canvas.addEventListener("touchend", doTouchEnd, false);
	engine.canvas.addEventListener("mousedown", doClickStart, false);
	engine.canvas.addEventListener("mouseup", doClickEnd, false);

	engine.load();
	engine.image.load_them();

	engine.runtime = setInterval( function(){
		engine.clear();
		engine.update();
		engine.draw();
		//console.log("tick");
	}, 60/1000 );
	engine.msg("engine loaded");
};<commit_msg>rotation anchor<commit_after>engine = {};
engine.canvas = null;
engine.runtime = null;
engine.draw = function(){};
engine.update = function(){};
engine.load = function(){
};

/*
Prints a value in console using "[engine]" prefix.

@value = a printable value
return nothing
 */
engine.msg = function( value ){
	console.log( "[engine] " + value );
};

/*
 Update canvas clearing the last draw.
return nothing
 */
engine.clear = function(){
	engine.canvas.width ++;
	engine.canvas.width --;
}

engine.events = {};
engine.events.VK_UP = 38;
engine.events.VK_DOWN = 40;
engine.events.VK_LEFT = 37;
engine.events.VK_RIGHT = 39;
engine.events.VK_A = 65;
engine.events.key_down = -1;
engine.events.key_up = -1;
document.onkeydown = key_down;
document.onkeyup = key_up;
function key_down( event ){
	event = event || window.event;
	engine.events.key_down = event.keyCode;
	engine.events.key_up = -1;

	//event.preventDefault();
};
function key_up( event ){
	event = event || window.event;
	engine.events.key_up = event.keyCode;
	if( engine.events.key_toogle == false ){
		engine.events.key_down = -1;
	}
	//event.preventDefault();
}
engine.events.key_toogle = false;

/*
Allow to know when a key is down.

@key: keys such as "up", "down", "left", "right", or letter.
Return boolean
 */
engine.events.iskeydown = function( key ){
	if( key == "up" && engine.events.key_down == engine.events.VK_UP ){
		return true;
	}else if( key == "down" && engine.events.key_down == engine.events.VK_DOWN ){
		return true;
	}else if( key == "left" && engine.events.key_down == engine.events.VK_LEFT ){
		return true;
	}else if( key == "right" && engine.events.key_down == engine.events.VK_RIGHT ){
		return true;
	}else if( key == "a"  && engine.events.key_down == engine.events.VK_A ){
		return true
	}

	return false;
};

engine.events.touch_x = 0;
engine.events.touch_y = 0;
engine.events.click_x = 0;
engine.events.click_y = 0;

/*
get x, y -absolute- positions through Click or Touch
*/
function doTouchStart( event ){
	event.preventDefault();
	engine.events.touch_x = event.targetTouches[0].pageX;
	engine.events.touch_y = event.targetTouches[0].pageY;
}
function doTouchEnd( event ){
	event.preventDefault();
	engine.events.touch_x = -1;
	engine.events.touch_y = -1;
}
function doClickStart( event ){
	engine.events.click_x = event.clientX;
	engine.events.click_y = event.clientY;
}
function doClickEnd( event ){
	engine.events.click_x = -1;
	engine.events.click_y = -1;
}

/*
 Object container drawable, updatable.

 @name: name to map
 @width, @height: width, height
 */
engine.map = function( name, width, height ){
	this.width = width;
	this.height = height;
	this.name = name;

	this.entity_list = [];
	this.push = function( item ){
		this.entity_list.push( item );
	};

	/*
	To get the first entity in an x,y point.

	@x: x position
	@y: y position
	Return an entity
	*/
	this.getAt = function( x, y ){
		var i = 0;
		for( ; i < this.entity_list.length; i++ ){
			var entity = this.entity_list[i];
			if( x >= entity.x && x <= entity.x + entity.w
				&& y >= entity.y && y <= entity.y + entity.h ){
				return entity;
			}
		}

		return null;
	};
	/*
	map draw.  Its draw all entity in the map.

	Return nothing.
	*/
	this.draw = function(){
		this.entity_list.forEach(
			function( item ){
				item.draw();
			}
		);

	};

	/*
	...

	Return nothing
	*/
	this.update = function(){
	};
};
engine.current_map = null;
engine.setMap = function( map ){
	engine.current_map  = map;
}

engine.viewport = {};
engine.viewport.enabled = false;
engine.viewport.width = 10;
engine.viewport.height = 10;
engine.viewport.x = 0;
engine.viewport.y = 0;
engine.viewport.dx = 1;
engine.viewport.dy = 1;
engine.viewport.acceleration = 0;
engine.viewport.update = function(){
	engine.viewport.x += engine.viewport.dx;
	engine.viewport.y += engine.viewport.dy;

	engine.viewport.dx *= engine.viewport.acceleration;
	engine.viewport.dy *= engine.viewport.acceleration;
}
engine.viewport.moveTo = function( x, y ){
	engine.viewport.x = x;
	engine.viewport.y = y;
};
engine.viewport.followTo = function( entity ){
	engine.viewport.x = entity.x;
	engine.viewport.y = entity.y;
	engine.viewport.x -= engine.viewport.width / 2;
	engine.viewport.y -= engine.viewport.height / 2;

	engine.viewport.dx = entity.dx;
	engine.viewport.dy = entity.dy;
	engine.viewport.acceleration = entity.acceleration;
};

engine.image = {};
engine.image.draw = function( key, x, y, optional_angle, optional_width, optional_height){
	optional_angle = ( typeof optional_angle === 'undefined' ) ? 0 : optional_angle;
	optional_height = ( typeof optional_height === 'undefined' ) ? 0 : optional_height;
	optional_width = ( typeof optional_width === 'undefined' ) ? 0 : optional_width;

	var img = engine.image.get(key);

	// rotate here
	if( optional_angle != 0 ){
		engine.canvas.getContext("2d").save();

		if( optional_width != 0 && optional_height != 0 ){
			engine.canvas.getContext("2d").translate( parseInt(x), parseInt(y) );
		}

		engine.canvas.getContext("2d").rotate( optional_angle * Math.PI / 180 );
	}

	// draw here
	if( optional_angle != 0 ){
		engine.canvas.getContext("2d").drawImage( img.img, - parseInt(optional_width / 2), - parseInt(optional_height / 2));
		engine.canvas.getContext("2d").restore();
	}else{
		engine.canvas.getContext("2d").drawImage( img.img, parseInt(x), parseInt(y) );
	}
};
engine.image.sprites = [];
engine.image.sprites_loaded = 0;
engine.image.load_status = function(){
	engine.image.sprites_loaded ++;
	return "["+engine.image.sprites_loaded + "/" + engine.image.sprites.length+"]";
};
engine.image.load_them = function(){
	// loading
	engine.image.sprites.forEach(
		function( item ){
			var img = new Image();
			img.src = item.src;
			img.onload = function(){
							item.loaded = true;
							engine.msg( engine.image.load_status() + " " + item.src+" loaded. " );
							};
			item.img = img;
		}
	);
};
engine.image.get = function( key ){
	var i = 0;
	for( ; i < engine.image.sprites.length ; i ++ ){
		var item = engine.image.sprites[ i ];
		if( item.key == key ){
			// console.log("found "+key);
			return item;
		}
	}

	return null;
}
engine.image.load = function( src, key ){
	engine.image.sprites.push( { "src": src, "key": key, "img": new Image(), "loaded": false } );
};

engine.entity = function Entity(key, x, y){
	this.x = x;
	this.y = y;
	this.w = 32;
	this.h = 32;
	this.key = key;
	this.tag = "";
	this.angle = -1; // degrees!

	this.dx = 0;
	this.dy = 0;
	this.friction = 0.05;
	this.acceleration = 0;
	this.visible = true;

	this.animation_frames = [];
	this.animation_dt = 0;
	this.animation_index = 0;
	this.animation_loop = -1;
	this.animation_running = false;

	this.addFrame = function( frame_key, dt ){
		if( this.animation_frames.length == 0 ){
			this.key = frame_key;
			this.animation_dt = dt;
			this.animation_index = 0;
			this.animation_running = false;
		}
		this.animation_frames.push({ "key":frame_key, "dt": dt });
	};

	this.draw = function(){
		if( this.visible == false ) return;

		if( engine.viewport.enabled == true ){
			var key = this.key;

			if( this.animation_frames.length > 0 ){

				engine.image.draw( this.key, this.x - engine.viewport.x, this.y - engine.viewport.y );
				if( this.animation_running == false ){
					var animation_index = this.animation_index + 1;
					if( animation_index >= this.animation_frames.length ){
						this.animation_index = -1;
						animation_index = 0;
					}
					var animation_frames = this.animation_frames[ animation_index ];
					var next_key = animation_frames.key;
					var self = this;

					setTimeout( function(){
						self.key = next_key;
						self.animation_index ++ ;

						self.animation_running = false;
					}, this.animation_dt );

					this.animation_running = true;
				}
			}else{
				if( this.angle == 0 ){
					engine.image.draw( key, this.x - engine.viewport.x, this.y - engine.viewport.y );
				}else{
					engine.image.draw( key, this.x - engine.viewport.x, this.y - engine.viewport.y, this.angle, this.w, this.h );
				}
			}
		}else{

			if( this.angle != -1 ){
				engine.image.draw( this.key, this.x, this.y, this.angle, this.w, this.h);
			}else{
				engine.image.draw( this.key, this.x, this.y );
			}
		}
	};
	this.update = function(){
		this.x += this.dx;
		this.y += this.dy;

		this.dx *= this.acceleration;
		this.dy *= this.acceleration;
	};
	this.collide = function( entity ){
		if( entity.visible == false ){
			return false;
		}

		var x_axis = false, y_axis = false;
		if( this.x >= entity.x && this.x <= ( entity.x + entity.w )
			|| ( this.x + this.w ) >= entity.x && ( this.x + this.w ) <= ( entity.x + entity.w ) ){
			x_axis = true;
		}
		if( this.y >= entity.y && this.y <= ( entity.y + entity.h )
			|| ( this.y + this.h ) >= entity.y && ( this.y + this.h ) <= ( entity.y + entity.h ) ){
			y_axis = true;
		}

		return ( x_axis && y_axis );
	}
}

engine.start = function(){
	engine.canvas = document.getElementById( "screen" );
	engine.canvas.addEventListener("touchstart", doTouchStart, false);
	engine.canvas.addEventListener("touchend", doTouchEnd, false);
	engine.canvas.addEventListener("mousedown", doClickStart, false);
	engine.canvas.addEventListener("mouseup", doClickEnd, false);

	engine.load();
	engine.image.load_them();

	engine.runtime = setInterval( function(){
		engine.clear();
		engine.update();
		engine.draw();
		//console.log("tick");
	}, 1000/30 );
	engine.msg("engine loaded");
};<|endoftext|>


<commit_before>// dependencies
//
import React from 'react';
import uniqueId from 'lodash/uniqueId';
import Label from './Label';

/**
 * The TextInput component
 */
class TextInput extends React.Component {
    constructor(props) {
        super(props);

        // set a unique ID for this component's elements
        //
        this.id = uniqueId('TextInput-');

        this.validationMessage = `${props.description} is required`;

        const value = `${props.value || ''}`;

        const isValid = !props.required || !!value;

        // initialize the state
        //
        this.state = {
            value,
            isValid,
            validationMessage: isValid ? null : this.validationMessage,
            hasValidated:      false,
        };
    }

    componentWillMount() {
        if (this.props.onValidation) {
            this.props.onValidation(
                this.state.hasValidated,
                this.state.isValid,
                this.state.validationMessage
            );
        }
    }

    /**
     * Render the component
     * @return {React.Element} The React Element describing this component
     */
    render() {
        return (

                {this.props.label &&

                }
                <input
                    id={this.id}
                    type="text"
                    className="form-control"
                    placeholder={this.props.placeholder || ''}
                />

        );
    }

}

// set the property types for the TextInput component
//
TextInput.propTypes = {
    required:     React.PropTypes.bool,
    label:        React.PropTypes.string,
    description:  React.PropTypes.string,
    placeholder:  React.PropTypes.string,
    value:        React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.number,
    ]),
    onValidation: React.PropTypes.func,
};

// export the component
//
export default TextInput;
<commit_msg>imported update method<commit_after>// dependencies
//
import React from 'react';
import update from 'react-addons-update';
import uniqueId from 'lodash/uniqueId';
import Label from './Label';

/**
 * The TextInput component
 */
class TextInput extends React.Component {
    constructor(props) {
        super(props);

        // set a unique ID for this component's elements
        //
        this.id = uniqueId('TextInput-');

        this.validationMessage = `${props.description} is required`;

        const value = `${props.value || ''}`;

        const isValid = !props.required || !!value;

        // initialize the state
        //
        this.state = {
            value,
            isValid,
            validationMessage: isValid ? null : this.validationMessage,
            hasValidated:      false,
        };
    }

    componentWillMount() {
        if (this.props.onValidation) {
            this.props.onValidation(
                this.state.hasValidated,
                this.state.isValid,
                this.state.validationMessage
            );
        }
    }

    /**
     * Render the component
     * @return {React.Element} The React Element describing this component
     */
    render() {
        return (

                {this.props.label &&

                }
                <input
                    id={this.id}
                    type="text"
                    className="form-control"
                    placeholder={this.props.placeholder || ''}
                />

        );
    }

}

// set the property types for the TextInput component
//
TextInput.propTypes = {
    required:     React.PropTypes.bool,
    label:        React.PropTypes.string,
    description:  React.PropTypes.string,
    placeholder:  React.PropTypes.string,
    value:        React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.number,
    ]),
    onValidation: React.PropTypes.func,
};

// export the component
//
export default TextInput;
<|endoftext|>


<commit_before>require('extensions');

var TestFixture = require('nodeunit').testCase,
    exec  = require('child_process').exec,
    http = require('testExtensions').http,
    api = require('testExtensions').api,
    verify = require('testExtensions').verify;

exports['Server'] = TestFixture({
    'GET / returns base hypermedia': verify(function (test) {
        http.get('http://localhost:3000/', function (response) {
            test.strictEqual(response.headers['content-type'], 'application/vnd.httpmock+json');
            test.jsonEquals(response.body, {
                links: [{
                    href: 'http://localhost:3000/servers',
                    rel: 'http://localhost:3000/relations/servers'
                }]
            });
            test.done();
        });
    }),

    'hypermedia uses host header in links': verify(function (test) {
        http.get('http://127.0.0.1:3000/', function (response) {
            test.jsonEquals(response.body, {
                links: [{
                    href: 'http://127.0.0.1:3000/servers',
                    rel: 'http://127.0.0.1:3000/relations/servers'
                }]
            });
            test.done();
        });
    }),

    'POST /servers creates server at given port': verify(function (test) {
        http.post('http://localhost:3000/servers', {
            body: { port: 3001 },
            callback: function (response) {
                test.strictEqual(response.statusCode, 201);
                test.strictEqual(response.headers.location, 'http://localhost:3000/servers/3001');
                test.jsonEquals(response.body, {
                    url: 'http://localhost:3001/',
                    port: 3001,
                    links: [
                        {
                            href: 'http://localhost:3000/servers/3001',
                            rel: 'http://localhost:3000/relations/server'
                        },
                        {
                            href: 'http://localhost:3000/servers/3001/requests',
                            rel: 'http://localhost:3000/relations/request'
                        },
                        {
                            href: 'http://localhost:3000/server/3001/stubs',
                            rel: 'http://localhost:3000/relations/stub'
                        }
                    ]
                });

                http.get('http://localhost:3001/', function (stubbedResponse) {
                    test.strictEqual(stubbedResponse.statusCode, 200);
                    test.finish(3001);
                });
            }
        });
    }),

    'POST /servers creates stub that disallows default keepalive connections': verify(function (test) {
        api.createServerAtPort(3001, function () {
            http.get('http://localhost:3001/', function (response) {
                test.strictEqual(response.headers.connection, 'close');
                test.finish(3001);
            });
        });
    }),

    'POST /servers returns 409 if port already in use': verify(function (test) {
        api.createServerAtPort(3000, function (response) {
            test.strictEqual(response.statusCode, 409);
            test.done();
        });
    }),

    'POST /servers returns 400 if port missing': verify(function (test) {
        http.post('http://localhost:3000/servers', {
            body: { },
            callback: function (response) {
                test.strictEqual(response.statusCode, 400);
                test.jsonEquals(response.body, {
                    message: 'port is a required field'
                });
                test.done();
            }
        });
    }),

    'POST /servers returns 400 if port is not a number': verify(function (test) {
        http.post('http://localhost:3000/servers', {
            body: { port: 'test' },
            callback: function (response) {
                test.strictEqual(response.statusCode, 400);
                test.jsonEquals(response.body, {
                    message: 'port must be a valid integer between 1 and 65535'
                });
                test.done();
            }
        });
    }),

    'GET /servers shows servers created': verify(function (test) {
        api.createServerAtPort(3002, function () {
            http.get('http://localhost:3000/servers', function (response) {
                test.jsonEquals(response.body, {
                    servers: [{
                        url: 'http://localhost:3002/',
                        port: 3002,
                        links: [
                            {
                                href: 'http://localhost:3000/servers/3002',
                                rel: 'http://localhost:3000/relations/server'
                            },
                            {
                                href: 'http://localhost:3000/servers/3002/requests',
                                rel: 'http://localhost:3000/relations/request'
                            },
                            {
                                href: 'http://localhost:3000/server/3002/stubs',
                                rel: 'http://localhost:3000/relations/stub'
                            }
                        ]
                    }]
                });
                test.finish(3002);
            });
        });
    }),

    'GET /servers:port returns 404 if server not created': verify(function (test) {
        http.get('http://localhost:3000/servers/4000', function (response) {
            test.strictEqual(response.statusCode, 404);
            test.done();
        });
    }),

    'GET /servers/:port gets hypermedia for server': verify(function (test) {
        api.createServerAtPort(3001, function () {
            http.get('http://localhost:3000/servers/3001', function (response) {
                test.strictEqual(response.statusCode, 200);
                test.jsonEquals(response.body, {
                    url: 'http://localhost:3001/',
                    port: 3001,
                    links: [
                        {
                            href: 'http://localhost:3000/servers/3001',
                            rel: 'http://localhost:3000/relations/server'
                        },
                        {
                            href: 'http://localhost:3000/servers/3001/requests',
                            rel: 'http://localhost:3000/relations/request'
                        },
                        {
                            href: 'http://localhost:3000/server/3001/stubs',
                            rel: 'http://localhost:3000/relations/stub'
                        }
                    ]
                });
                test.finish(3001);
            });
        });
    }),

    'DELETE /servers/:port deletes stub at given port': verify(function (test) {
        api.createServerAtPort(3004, function () {
            http.del('http://localhost:3000/servers/3004', function (response) {
                test.strictEqual(response.statusCode, 204);
                exec('netstat -an | grep 3004 | grep LISTEN', function (error, stdout, stderr) {
                    test.strictEqual(stdout, '');
                    test.done();
                });
            });
        });
    }),

    'DELETE /servers/:port returns 404 if server never created': verify(function (test) {
        http.del('http://localhost:3000/servers/5000', function (response) {
            test.strictEqual(response.statusCode, 404);
            test.done();
        });
    })
});

<commit_msg>Cleaned up test<commit_after>require('extensions');

var testCase = require('nodeunit').testCase,
    exec  = require('child_process').exec,
    http = require('testExtensions').http,
    api = require('testExtensions').api,
    verify = require('testExtensions').verify;

exports['GET /'] = testCase({
    'returns base hypermedia': verify(function (test) {
        http.get('http://localhost:3000/', function (response) {
            test.strictEqual(response.headers['content-type'], 'application/vnd.httpmock+json');
            test.jsonEquals(response.body, {
                links: [{
                    href: 'http://localhost:3000/servers',
                    rel: 'http://localhost:3000/relations/servers'
                }]
            });
            test.done();
        });
    }),

    'uses host header in hypermedia links': verify(function (test) {
        http.get('http://127.0.0.1:3000/', function (response) {
            test.jsonEquals(response.body, {
                links: [{
                    href: 'http://127.0.0.1:3000/servers',
                    rel: 'http://127.0.0.1:3000/relations/servers'
                }]
            });
            test.done();
        });
    })
});

exports['POST /servers'] = testCase({
    'creates server at given port': verify(function (test) {
        http.post('http://localhost:3000/servers', {
            body: { port: 3001 },
            callback: function (response) {
                test.strictEqual(response.statusCode, 201);
                test.strictEqual(response.headers.location, 'http://localhost:3000/servers/3001');
                test.jsonEquals(response.body, {
                    url: 'http://localhost:3001/',
                    port: 3001,
                    links: [
                        {
                            href: 'http://localhost:3000/servers/3001',
                            rel: 'http://localhost:3000/relations/server'
                        },
                        {
                            href: 'http://localhost:3000/servers/3001/requests',
                            rel: 'http://localhost:3000/relations/request'
                        },
                        {
                            href: 'http://localhost:3000/server/3001/stubs',
                            rel: 'http://localhost:3000/relations/stub'
                        }
                    ]
                });

                http.get('http://localhost:3001/', function (stubbedResponse) {
                    test.strictEqual(stubbedResponse.statusCode, 200);
                    test.finish(3001);
                });
            }
        });
    }),

    'creates stub that disallows keepalive connections': verify(function (test) {
        api.createServerAtPort(3001, function () {
            http.get('http://localhost:3001/', function (response) {
                test.strictEqual(response.headers.connection, 'close');
                test.finish(3001);
            });
        });
    }),

    'returns 409 if port already in use': verify(function (test) {
        api.createServerAtPort(3000, function (response) {
            test.strictEqual(response.statusCode, 409);
            test.done();
        });
    }),

    'returns 400 if port missing': verify(function (test) {
        http.post('http://localhost:3000/servers', {
            body: { },
            callback: function (response) {
                test.strictEqual(response.statusCode, 400);
                test.jsonEquals(response.body, {
                    message: 'port is a required field'
                });
                test.done();
            }
        });
    }),

    'returns 400 if port is not a number': verify(function (test) {
        http.post('http://localhost:3000/servers', {
            body: { port: 'test' },
            callback: function (response) {
                test.strictEqual(response.statusCode, 400);
                test.jsonEquals(response.body, {
                    message: 'port must be a valid integer between 1 and 65535'
                });
                test.done();
            }
        });
    })
});

exports['GET /servers'] = testCase({
    'shows servers created': verify(function (test) {
        api.createServerAtPort(3002, function () {
            http.get('http://localhost:3000/servers', function (response) {
                test.jsonEquals(response.body, {
                    servers: [{
                        url: 'http://localhost:3002/',
                        port: 3002,
                        links: [
                            {
                                href: 'http://localhost:3000/servers/3002',
                                rel: 'http://localhost:3000/relations/server'
                            },
                            {
                                href: 'http://localhost:3000/servers/3002/requests',
                                rel: 'http://localhost:3000/relations/request'
                            },
                            {
                                href: 'http://localhost:3000/server/3002/stubs',
                                rel: 'http://localhost:3000/relations/stub'
                            }
                        ]
                    }]
                });
                test.finish(3002);
            });
        });
    })
});

exports['GET /servers:port'] = testCase({
    'returns 404 if server not created': verify(function (test) {
        http.get('http://localhost:3000/servers/4000', function (response) {
            test.strictEqual(response.statusCode, 404);
            test.done();
        });
    }),

    'gets hypermedia for server': verify(function (test) {
        api.createServerAtPort(3001, function () {
            http.get('http://localhost:3000/servers/3001', function (response) {
                test.strictEqual(response.statusCode, 200);
                test.jsonEquals(response.body, {
                    url: 'http://localhost:3001/',
                    port: 3001,
                    links: [
                        {
                            href: 'http://localhost:3000/servers/3001',
                            rel: 'http://localhost:3000/relations/server'
                        },
                        {
                            href: 'http://localhost:3000/servers/3001/requests',
                            rel: 'http://localhost:3000/relations/request'
                        },
                        {
                            href: 'http://localhost:3000/server/3001/stubs',
                            rel: 'http://localhost:3000/relations/stub'
                        }
                    ]
                });
                test.finish(3001);
            });
        });
    })
});

exports['DELETE /servers:port'] = testCase({
    'deletes stub at given port': verify(function (test) {
        api.createServerAtPort(3004, function () {
            http.del('http://localhost:3000/servers/3004', function (response) {
                test.strictEqual(response.statusCode, 204);
                exec('netstat -an | grep 3004 | grep LISTEN', function (error, stdout, stderr) {
                    test.strictEqual(stdout, '');
                    test.done();
                });
            });
        });
    }),

    'returns 404 if server never created': verify(function (test) {
        http.del('http://localhost:3000/servers/5000', function (response) {
            test.strictEqual(response.statusCode, 404);
            test.done();
        });
    })
});

<|endoftext|>