<commit_before>/**

@property LIB_EventTarget

@description
A constructor function for creating event target objects.

var et = new LIB_EventTarget();

The methods of an event target object are inspired by the DOM2 standard.

*/
var LIB_EventTarget = function() {};

(function() {

    function hasOwnProperty(o, p) {
        return Object.prototype.hasOwnProperty.call(o, p);
    }

    var create = (function() {
        function F() {}
        return function(o) {
            F.prototype = o;
            return new F();
        };
    }());

    function addEventListener(listeners, listener, auxArg) {
        listeners.push({listener:listener, auxArg:auxArg});
    }

    function removeEventListener(listeners, listener, auxArg) {
        // Loop backwards through the array so adjacent references
        // to "listener" are all removed.
        for (var i = listeners.length; i--; ) {
            if ((listeners[i].listener === listener) &&
                (listeners[i].auxArg === auxArg)) {
                listeners.splice(i, 1);
            }
        }
    }

    function dispatchEvent(listeners, evt) {
        // Copy the list of listeners in case one of the
        // listeners modifies the list while we are
        // iterating over the list.
        //
        // Without making a copy, one listener removing
        // an already-called listener would result in skipping
        // a not-yet-called listener. One listener removing
        // a not-yet-called listener would result in skipping that
        // not-yet-called listner. The worst case scenario
        // is a listener adding itself again which would
        // create an infinite loop.
        //
        listeners = listeners.slice(0);
        for (var i = 0, ilen = listeners.length; i < ilen; i++) {
            var listener = listeners[i].listener;
            var auxArg = listeners[i].auxArg;
            if (typeof listener === 'function') {
                listener.call(auxArg, evt);
            }
            else {
                listener[auxArg || 'handleEvent'](evt);
            }
        }
    }

/**

@property LIB_EventTarget.prototype.addEventListener

@parameter type {string} The name of the event.

@parameter listener {object|function} The listener object or callback function.

@parameter auxArg {string|object} Optional. See description.

@description

If the listener is an object then when a matching event type is dispatched on
the event target, the listener object's handleEvent method will be called.
Using the auxArg you can specify the name of the method to be called.

If the listener is a function then when a matching event type is dispatched on
the event target, the listener function is called with global object set as
the "this" object. Using the auxArg you can specifiy a different object to be
the "this" object.

One listener (or listener/auxArg pair to be more precise) can be added
multiple times.

et.addEventListener('change', {handleEvent:function(){}});
et.addEventListener('change', {handleChange:function(){}}, 'handleChange');
et.addEventListener('change', function(){});
et.addEventListener('change', this.handleChange, this);

*/
    LIB_EventTarget.prototype.addEventListener = function(type, listener, /*optional*/ auxArg) {
        hasOwnProperty(this, '_LIB_listeners') || (this._LIB_listeners = {});
        hasOwnProperty(this._LIB_listeners, type) || (this._LIB_listeners[type] = []);
        addEventListener(this._LIB_listeners[type], listener, auxArg);
    };

/**

@property LIB_EventTarget.prototype.addAllEventListener

@parameter listener {object|function} The listener object or callback function.

@parameter auxArg {string|object} Optional. See description.

@description

If the listener is an object then when any event type is dispatched on
the event target, the listener object's handleEvent method will be called.
Using the auxArg you can specify the name of the method to be called.

If the listener is a function then when any event type is dispatched on
the event target, the listener function is called with global object set as
the "this" object. Using the auxArg you can specifiy a different object to be
the "this" object.

One listener (or listener/auxArg pair to be more precise) can be added
multiple times.

et.addAllEventListener({handleEvent:function(){}});
et.addAllEventListener({handleChange:function(){}}, 'handleChange');
et.addAllEventListener(function(){});
et.addAllEventListener(this.handleChange, this);

*/
    LIB_EventTarget.prototype.addAllEventListener = function(listener, /*optional*/ auxArg) {
        hasOwnProperty(this, '_LIB_allListeners') || (this._LIB_allListeners = []);
        addEventListener(this._LIB_allListeners, listener, auxArg);
    };

/**

@property LIB_EventTarget.prototype.removeEventListener

@parameter type {string} The name of the event.

@parameter listener {object|function} The listener object or callback function.

@parameter auxArg {string|object} Optional.

@description

Removes all added listeners matching the type/listener/auxArg combination exactly.
If this combination is not found there are no errors. If this combination is found
more than once all are removed.

var o = {handleEvent:function(){}, handleChange:function(){}};
et.removeEventListener('change', o);
et.removeEventListener('change', o, 'handleChange');
et.removeEventListener('change', fn);
et.removeEventListener('change', this.handleChange, this);

*/
    LIB_EventTarget.prototype.removeEventListener = function(type, listener, /*optional*/ auxArg) {
        if (hasOwnProperty(this, '_LIB_listeners') &&
            hasOwnProperty(this._LIB_listeners, type)) {
            removeEventListener(this._LIB_listeners[type], listener, auxArg);
        }
    };

/**

@property LIB_EventTarget.prototype.removeAllEventListener

@parameter listener {object|function} The listener object or callback function.

@parameter auxArg {string|object} Optional.

@description

Removes all listeners added with addAllEventListener matching the listener/auxArg combination exactly.
If this combination is not found there are no errors. If this combination is found
more than once all are removed.

var o = {handleEvent:function(){}, handleChange:function(){}};
et.removeAllEventListener(o);
et.removeAllEventListener(o, 'handleChange');
et.removeAllEventListener(fn);
et.removeAllEventListener(this.handleChange, this);

*/
    LIB_EventTarget.prototype.removeAllEventListener = function(listener, /*optional*/ auxArg) {
        if (hasOwnProperty(this, '_LIB_allListeners')) {
            removeEventListener(this._LIB_allListeners, listener, auxArg);
        }
    };

/**

@property LIB_EventTarget.prototype.dispatchEvent

@parameter evt {object} The event object to dispatch to all listeners.

@description

The evt.type property is required. All listeners registered for this
event type are called with evt passed as an argument to the listeners.

If not set, the evt.target property will be set to be the event target.

The evt.currentTarget will be set to be the event target.

et.dispatchEvent({type:'change'});
et.dispatchEvent({type:'change', extraData:'abc'});

*/
    LIB_EventTarget.prototype.dispatchEvent = function(evt) {
        // Want to ensure we don't alter the evt object passed in as it
        // may be a bubbling event. So clone it and then setting currentTarget
        // won't break some event that is already being dispatched.
        evt = create(evt);
        ('target' in evt) || (evt.target = this); // don't change target on bubbling event
        evt.currentTarget = this; // change currentTarget on a bubbling event
        if (hasOwnProperty(this, '_LIB_listeners') &&
            hasOwnProperty(this._LIB_listeners, evt.type)) {
            dispatchEvent(this._LIB_listeners[evt.type], evt);
        }
        if (hasOwnProperty(this, '_LIB_allListeners')) {
            dispatchEvent(this._LIB_allListeners, evt);
        }
    };

}());

/**

@property LIB_mixinEventTarget

@parameter obj {object} The object to be made into an event target.

@description

Mixes in the event target methods into any object.

var o = {}
LIB_mixinEventTarget(o);
o.addEventListener('change', function(){alert('change');});
o.dispatchEvent({type:'change'});

*/
var LIB_mixinEventTarget = function(obj) {
    for (var p in LIB_EventTarget.prototype) {
        if (Object.prototype.hasOwnProperty.call(LIB_EventTarget.prototype, p) &&
            // Don't want to copy LIB_EventTarget.prototype._LIB_listeners object. Want the obj object
            // to have its own listeners and not share listeners with LIB_EventTarget.prototype.
            (typeof LIB_EventTarget.prototype[p] === 'function')) {
            obj[p] = LIB_EventTarget.prototype[p];
        }
    }
};

/**

@property LIB_implementsEventTarget

@parameter obj {object} The object to verify as an event target.

@description

Check that the obj parameter is an event target.

*/
var LIB_implementsEventTarget = function(obj) {
    return !!(obj.addEventListener &&
              obj.addAllEventListener &&
              obj.removeEventListener &&
              obj.removeAllEventListener &&
              obj.dispatchEvent);
};
<commit_msg>whitespace<commit_after>/**

@property LIB_EventTarget

@description
A constructor function for creating event target objects.

var et = new LIB_EventTarget();

The methods of an event target object are inspired by the DOM2 standard.

*/
var LIB_EventTarget = function() {};

(function() {

    function hasOwnProperty(o, p) {
        return Object.prototype.hasOwnProperty.call(o, p);
    }

    var create = (function() {
        function F() {}
        return function(o) {
            F.prototype = o;
            return new F();
        };
    }());

    function addEventListener(listeners, listener, auxArg) {
        listeners.push({listener:listener, auxArg:auxArg});
    }

    function removeEventListener(listeners, listener, auxArg) {
        // Loop backwards through the array so adjacent references
        // to "listener" are all removed.
        for (var i = listeners.length; i--; ) {
            if ((listeners[i].listener === listener) &&
                (listeners[i].auxArg === auxArg)) {
                listeners.splice(i, 1);
            }
        }
    }

    function dispatchEvent(listeners, evt) {
        // Copy the list of listeners in case one of the
        // listeners modifies the list while we are
        // iterating over the list.
        //
        // Without making a copy, one listener removing
        // an already-called listener would result in skipping
        // a not-yet-called listener. One listener removing
        // a not-yet-called listener would result in skipping that
        // not-yet-called listner. The worst case scenario
        // is a listener adding itself again which would
        // create an infinite loop.
        //
        listeners = listeners.slice(0);
        for (var i = 0, ilen = listeners.length; i < ilen; i++) {
            var listener = listeners[i].listener;
            var auxArg = listeners[i].auxArg;
            if (typeof listener === 'function') {
                listener.call(auxArg, evt);
            }
            else {
                listener[auxArg || 'handleEvent'](evt);
            }
        }
    }

/**

@property LIB_EventTarget.prototype.addEventListener

@parameter type {string} The name of the event.

@parameter listener {object|function} The listener object or callback function.

@parameter auxArg {string|object} Optional. See description.

@description

If the listener is an object then when a matching event type is dispatched on
the event target, the listener object's handleEvent method will be called.
Using the auxArg you can specify the name of the method to be called.

If the listener is a function then when a matching event type is dispatched on
the event target, the listener function is called with global object set as
the "this" object. Using the auxArg you can specifiy a different object to be
the "this" object.

One listener (or listener/auxArg pair to be more precise) can be added
multiple times.

et.addEventListener('change', {handleEvent:function(){}});
et.addEventListener('change', {handleChange:function(){}}, 'handleChange');
et.addEventListener('change', function(){});
et.addEventListener('change', this.handleChange, this);

*/
    LIB_EventTarget.prototype.addEventListener = function(type, listener, /*optional*/ auxArg) {
        hasOwnProperty(this, '_LIB_listeners') || (this._LIB_listeners = {});
        hasOwnProperty(this._LIB_listeners, type) || (this._LIB_listeners[type] = []);
        addEventListener(this._LIB_listeners[type], listener, auxArg);
    };

/**

@property LIB_EventTarget.prototype.addAllEventListener

@parameter listener {object|function} The listener object or callback function.

@parameter auxArg {string|object} Optional. See description.

@description

If the listener is an object then when any event type is dispatched on
the event target, the listener object's handleEvent method will be called.
Using the auxArg you can specify the name of the method to be called.

If the listener is a function then when any event type is dispatched on
the event target, the listener function is called with global object set as
the "this" object. Using the auxArg you can specifiy a different object to be
the "this" object.

One listener (or listener/auxArg pair to be more precise) can be added
multiple times.

et.addAllEventListener({handleEvent:function(){}});
et.addAllEventListener({handleChange:function(){}}, 'handleChange');
et.addAllEventListener(function(){});
et.addAllEventListener(this.handleChange, this);

*/
    LIB_EventTarget.prototype.addAllEventListener = function(listener, /*optional*/ auxArg) {
        hasOwnProperty(this, '_LIB_allListeners') || (this._LIB_allListeners = []);
        addEventListener(this._LIB_allListeners, listener, auxArg);
    };

/**

@property LIB_EventTarget.prototype.removeEventListener

@parameter type {string} The name of the event.

@parameter listener {object|function} The listener object or callback function.

@parameter auxArg {string|object} Optional.

@description

Removes all added listeners matching the type/listener/auxArg combination exactly.
If this combination is not found there are no errors. If this combination is found
more than once all are removed.

var o = {handleEvent:function(){}, handleChange:function(){}};
et.removeEventListener('change', o);
et.removeEventListener('change', o, 'handleChange');
et.removeEventListener('change', fn);
et.removeEventListener('change', this.handleChange, this);

*/
    LIB_EventTarget.prototype.removeEventListener = function(type, listener, /*optional*/ auxArg) {
        if (hasOwnProperty(this, '_LIB_listeners') &&
            hasOwnProperty(this._LIB_listeners, type)) {
            removeEventListener(this._LIB_listeners[type], listener, auxArg);
        }
    };

/**

@property LIB_EventTarget.prototype.removeAllEventListener

@parameter listener {object|function} The listener object or callback function.

@parameter auxArg {string|object} Optional.

@description

Removes all listeners added with addAllEventListener matching the listener/auxArg combination exactly.
If this combination is not found there are no errors. If this combination is found
more than once all are removed.

var o = {handleEvent:function(){}, handleChange:function(){}};
et.removeAllEventListener(o);
et.removeAllEventListener(o, 'handleChange');
et.removeAllEventListener(fn);
et.removeAllEventListener(this.handleChange, this);

*/
    LIB_EventTarget.prototype.removeAllEventListener = function(listener, /*optional*/ auxArg) {
        if (hasOwnProperty(this, '_LIB_allListeners')) {
            removeEventListener(this._LIB_allListeners, listener, auxArg);
        }
    };

/**

@property LIB_EventTarget.prototype.dispatchEvent

@parameter evt {object} The event object to dispatch to all listeners.

@description

The evt.type property is required. All listeners registered for this
event type are called with evt passed as an argument to the listeners.

If not set, the evt.target property will be set to be the event target.

The evt.currentTarget will be set to be the event target.

et.dispatchEvent({type:'change'});
et.dispatchEvent({type:'change', extraData:'abc'});

*/
    LIB_EventTarget.prototype.dispatchEvent = function(evt) {
        // Want to ensure we don't alter the evt object passed in as it
        // may be a bubbling event. So clone it and then setting currentTarget
        // won't break some event that is already being dispatched.
        evt = create(evt);
        ('target' in evt) || (evt.target = this); // don't change target on bubbling event
        evt.currentTarget = this; // change currentTarget on a bubbling event
        if (hasOwnProperty(this, '_LIB_listeners') &&
            hasOwnProperty(this._LIB_listeners, evt.type)) {
            dispatchEvent(this._LIB_listeners[evt.type], evt);
        }
        if (hasOwnProperty(this, '_LIB_allListeners')) {
            dispatchEvent(this._LIB_allListeners, evt);
        }
    };

}());

/**

@property LIB_mixinEventTarget

@parameter obj {object} The object to be made into an event target.

@description

Mixes in the event target methods into any object.

var o = {}
LIB_mixinEventTarget(o);
o.addEventListener('change', function(){alert('change');});
o.dispatchEvent({type:'change'});

*/
var LIB_mixinEventTarget = function(obj) {
    for (var p in LIB_EventTarget.prototype) {
        if (Object.prototype.hasOwnProperty.call(LIB_EventTarget.prototype, p) &&
            // Don't want to copy LIB_EventTarget.prototype._LIB_listeners object. Want the obj object
            // to have its own listeners and not share listeners with LIB_EventTarget.prototype.
            (typeof LIB_EventTarget.prototype[p] === 'function')) {
            obj[p] = LIB_EventTarget.prototype[p];
        }
    }
};

/**

@property LIB_implementsEventTarget

@parameter obj {object} The object to verify as an event target.

@description

Check that the obj parameter is an event target.

*/
var LIB_implementsEventTarget = function(obj) {
    return !!(obj.addEventListener &&
              obj.addAllEventListener &&
              obj.removeEventListener &&
              obj.removeAllEventListener &&
              obj.dispatchEvent);
};
<|endoftext|>


<commit_before>import React from 'react';
import { render } from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import net from 'net';
import Root from './containers/Root';
import { configureStore, history } from './store/configureStore';
import './app.global.scss';

import { changeCoin } from './helpers/global';

const store = configureStore();
console.log('process.env', process.env);

class Server {
  baht1;
  baht5;
  baht10;
  constructor() {
    this.baht1 = 10;
    this.baht5 = 10;
    this.baht10 = 10;
  }
  getCoinOneBaht() {
    return this.baht1;
  }
  getCoinFiveBaht() {
    return this.baht5;
  }
  getCoinTenBaht() {
    return this.baht10;
  }
  addCoinOneBaht(number) {
    this.baht1 += number;
  }
  addCoinFiveBaht(number) {
    this.baht5 += number;
  }
  addCoinTenBaht(number) {
    this.baht10 += number;
  }
  minusCoinOneBaht(number) {
    this.baht1 += number;
  }
  minusCoinFiveBaht(number) {
    this.baht5 += number;
  }
  minusCoinTenBaht(number) {
    this.baht10 += number;
  }
  canChange(changeCoins) {
    const minimumExistingCoin = 3;
    // {baht1: 0, baht5: 1, baht10: 4}
    if (changeCoins.baht1 > 0 && this.getCoinOneBaht() <= minimumExistingCoin) return false;
    if (changeCoins.baht5 > 0 && this.getCoinFiveBaht() <= minimumExistingCoin) return false;
    if (changeCoins.baht10 > 0 && this.getCoinTenBaht() <= minimumExistingCoin) return false;
    return true;
  }
}

const serverLog = 'background: blue; color: #fff';

if (process.env.NODE_ENV !== 'production') {
  console.log('development:createServer at 127.0.0.1:1337');
  const server = net.createServer(socket => {
    const sv = new Server();
    console.log('%c Init Server:', serverLog, sv);
    setTimeout(() => {
      socket.write(
        JSON.stringify({
          action: 4,
          initialized: 0,
        }),
      );
    }, 500);
    setTimeout(() => {
      socket.write(
        JSON.stringify({
          action: 4,
          initialized: 1,
        }),
      );
    }, 2000);

    // socket.pipe(socket);
    // setInterval(() => {
    //   socket.write(
    //     JSON.stringify({
    //       action: 0,
    //       sensor: 'temp',
    //       msg: {
    //         temp: 4.3,
    //       },
    //     }),
    //   );
    // }, 20000);
    // setInterval(() => {
    //   socket.write(
    //     JSON.stringify({
    //       action: 2,
    //       msg: 50,
    //     }),
    //   );
    // }, 10000);
    socket.on('data', data => {
      // ======================================================
      // Received data from client.write
      // ======================================================
      const dataChunk = data.toString('utf8');
      console.log('%c Server: Received: ', serverLog, dataChunk);
      const objectData = JSON.parse(dataChunk);
      // ======================================================
      // Declare Protocols
      // ======================================================
      if (objectData.action === 1 && objectData.msg !== 'failed') {
        console.log('%c Server: Drop product', serverLog, data);
        const successPercent = Math.floor(((Math.random() * 10))) + 1;
        console.log('successPercent', successPercent);
        if (successPercent <= 7) {
          setTimeout(() => {
            socket.write(
              JSON.stringify({
                action: 1,
                result: 'success',
                description: 'Item XX delivered',
              }),
            );
          }, 2000);
        } else {
          setTimeout(() => {
            socket.write(
              JSON.stringify({
                action: 1,
                result: 'fail',
                description: 'Item delivered failed',
              }),
            );
          }, 2000);
        }
      }
      if (objectData.action === 2 && objectData.mode === 'coin') {
        console.log('%c Server: Cash Change', serverLog, Number(objectData.msg), changeCoin(Number(objectData.msg)));
        const changeCoins = changeCoin(Number(objectData.msg));
        if (sv.canChange(changeCoins)) {
          socket.write(
            JSON.stringify({
              action: 2,
              result: 'success',
              description: 'cash change completed',
            }),
          );
        } else {
          socket.write(
            JSON.stringify({
              action: 2,
              result: 'fail',
              description: 'cash change failed',
            }),
          );
        }
      }
      if (objectData.action === 2 && objectData.mode === 'remain') {
        console.log('%c Server: Cash remaining', serverLog, sv);
        socket.write(
          JSON.stringify({
            action: 2,
            result: 'success',
            remain: {
              baht1: sv.getCoinOneBaht(),
              baht5: sv.getCoinFiveBaht(),
              baht10: sv.getCoinTenBaht(),
            },
          }),
        );
      }
      if (objectData.action === 2 && objectData.mode === 'bill' && objectData.msg === '01') {
        // reset TAIKO
        socket.write(
          JSON.stringify({
            action: 2,
            msg: '01',
            result: 'success',
            description: 'reset completed'
          }),
        );
      }
      // insert coin
      if (objectData.action === 999) {
        const insertedValue = Number(objectData.msg);
        if (insertedValue === 1) {
          sv.addCoinOneBaht(1);
        } else if (insertedValue === 5) {
          sv.addCoinFiveBaht(1);
        } else if (insertedValue === 10) {
          sv.addCoinTenBaht(1);
        }
        socket.write(
          JSON.stringify({
            action: 2,
            msg: insertedValue,
          }),
        );
      }
    });
    socket.on('error', err => {
      console.error(err);
    });
  });
  // server.listen(8080, '192.168.1.41');
  server.listen(1337, '127.0.0.1');
}
render(
  <AppContainer>
    <Root store={store} history={history} />
  </AppContainer>,
  document.getElementById('root'),
);

if (module.hot) {
  module.hot.accept('./containers/Root', () => {
    const NextRoot = require('./containers/Root'); // eslint-disable-line global-require
    render(
      <AppContainer>
        <NextRoot store={store} history={history} />
      </AppContainer>,
      document.getElementById('root'),
    );
  });
}

export default store;
<commit_msg>update server<commit_after>import React from 'react';
import { render } from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import net from 'net';
import Root from './containers/Root';
import { configureStore, history } from './store/configureStore';
import './app.global.scss';

import { changeCoin } from './helpers/global';

const store = configureStore();
console.log('process.env', process.env);

class Server {
  baht1;
  baht5;
  baht10;
  constructor() {
    this.baht1 = 10;
    this.baht5 = 10;
    this.baht10 = 10;
  }
  getCoinOneBaht() {
    return this.baht1;
  }
  getCoinFiveBaht() {
    return this.baht5;
  }
  getCoinTenBaht() {
    return this.baht10;
  }
  addCoinOneBaht(number) {
    this.baht1 += number;
  }
  addCoinFiveBaht(number) {
    this.baht5 += number;
  }
  addCoinTenBaht(number) {
    this.baht10 += number;
  }
  minusCoinOneBaht(number) {
    this.baht1 += number;
  }
  minusCoinFiveBaht(number) {
    this.baht5 += number;
  }
  minusCoinTenBaht(number) {
    this.baht10 += number;
  }
  canChange(changeCoins) {
    const minimumExistingCoin = 3;
    // {baht1: 0, baht5: 1, baht10: 4}
    if (changeCoins.baht1 > 0 && this.getCoinOneBaht() <= minimumExistingCoin) return false;
    if (changeCoins.baht5 > 0 && this.getCoinFiveBaht() <= minimumExistingCoin) return false;
    if (changeCoins.baht10 > 0 && this.getCoinTenBaht() <= minimumExistingCoin) return false;
    return true;
  }
}

const serverLog = 'background: blue; color: #fff';

if (process.env.NODE_ENV !== 'production') {
  console.log('development:createServer at 127.0.0.1:1337');
  const server = net.createServer(socket => {
    const sv = new Server();
    console.log('%c Init Server:', serverLog, sv);
    setTimeout(() => {
      socket.write(
        JSON.stringify({
          action: 4,
          initialized: 0,
        }),
      );
    }, 500);
    setTimeout(() => {
      socket.write(
        JSON.stringify({
          action: 4,
          initialized: 1,
        }),
      );
    }, 2000);

    // socket.pipe(socket);
    // setInterval(() => {
    //   socket.write(
    //     JSON.stringify({
    //       action: 0,
    //       sensor: 'temp',
    //       msg: {
    //         temp: 4.3,
    //       },
    //     }),
    //   );
    // }, 20000);
    // setInterval(() => {
    //   socket.write(
    //     JSON.stringify({
    //       action: 2,
    //       msg: 50,
    //     }),
    //   );
    // }, 10000);
    socket.on('data', data => {
      // ======================================================
      // Received data from client.write
      // ======================================================
      const dataChunk = data.toString('utf8');
      console.log('%c Server: Received: ', serverLog, dataChunk);
      const objectData = JSON.parse(dataChunk);
      // ======================================================
      // Declare Protocols
      // ======================================================
      if (objectData.action === 1 && objectData.msg !== 'failed') {
        console.log('%c Server: Drop product', serverLog, data);
        const successPercent = Math.floor(((Math.random() * 10))) + 1;
        console.log('successPercent', successPercent);
        if (successPercent <= 7) {
          setTimeout(() => {
            socket.write(
              JSON.stringify({
                action: 1,
                result: 'success',
                description: 'Item XX delivered',
              }),
            );
          }, 2000);
        } else {
          setTimeout(() => {
            socket.write(
              JSON.stringify({
                action: 1,
                result: 'fail',
                description: 'Item delivered failed',
              }),
            );
          }, 2000);
        }
      }
      if (objectData.action === 2 && objectData.mode === 'coin') {
        console.log('%c Server: Cash Change', serverLog, Number(objectData.msg), changeCoin(Number(objectData.msg)));
        const changeCoins = changeCoin(Number(objectData.msg));
        if (sv.canChange(changeCoins)) {
          socket.write(
            JSON.stringify({
              action: 2,
              result: 'success',
              description: 'cash change completed',
            }),
          );
        } else {
          socket.write(
            JSON.stringify({
              action: 2,
              result: 'fail',
              description: 'cash change failed',
            }),
          );
        }
      }
      if (objectData.action === 2 && objectData.mode === 'remain') {
        console.log('%c Server: Cash remaining', serverLog, sv);
        socket.write(
          JSON.stringify({
            action: 2,
            result: 'success',
            remain: {
              baht1: sv.getCoinOneBaht(),
              baht5: sv.getCoinFiveBaht(),
              baht10: sv.getCoinTenBaht(),
            },
          }),
        );
      }
      if (objectData.action === 2 && objectData.mode === 'bill' && objectData.msg === '01') {
        // reset TAIKO
        socket.write(
          JSON.stringify({
            action: 2,
            msg: '01',
            result: 'success',
            description: 'reset completed'
          }),
        );
      }
      if (objectData.action === 2 && objectData.mode === 'both' && objectData.msg === '020') {
        // enable money box
        socket.write(
          JSON.stringify({
            action: 2,
            msg: '020',
            result: 'success',
            description: 'Disable Off.'
          }),
        );
      }
      if (objectData.action === 2 && objectData.mode === 'both' && objectData.msg === '021') {
        // enable money box
        socket.write(
          JSON.stringify({
            action: 2,
            msg: '021',
            result: 'success',
            description: 'Disable On.'
          }),
        );
      }
      // insert coin
      if (objectData.action === 999) {
        const insertedValue = Number(objectData.msg);
        if (insertedValue === 1) {
          sv.addCoinOneBaht(1);
        } else if (insertedValue === 5) {
          sv.addCoinFiveBaht(1);
        } else if (insertedValue === 10) {
          sv.addCoinTenBaht(1);
        }
        socket.write(
          JSON.stringify({
            action: 2,
            msg: insertedValue,
          }),
        );
      }
    });
    socket.on('error', err => {
      console.error(err);
    });
  });
  // server.listen(8080, '192.168.1.41');
  server.listen(1337, '127.0.0.1');
}
render(
  <AppContainer>
    <Root store={store} history={history} />
  </AppContainer>,
  document.getElementById('root'),
);

if (module.hot) {
  module.hot.accept('./containers/Root', () => {
    const NextRoot = require('./containers/Root'); // eslint-disable-line global-require
    render(
      <AppContainer>
        <NextRoot store={store} history={history} />
      </AppContainer>,
      document.getElementById('root'),
    );
  });
}

export default store;
<|endoftext|>


<commit_before>'use strict';
var generators = require('yeoman-generator');
var yosay = require('yosay');
var chalk = require('chalk');
var mkdirp = require('mkdirp');

module.exports = generators.Base.extend({
  constructor: function () {

    generators.Base.apply(this, arguments);

    this.option('skip-welcome-message', {
      desc: 'Skips the welcome message',
      type: Boolean
    });

    this.option('skip-install-message', {
      desc: 'Skips the message after the installation of dependencies',
      type: Boolean
    });

    this.option('appname', {
      desc: 'Name of the app',
      type: String,
      defaults: 'tvml-app'
    });

    this.option('appid', {
      desc: 'Id of the app',
      type: String,
      defaults: 'org.sample.tvml-app'
    });
  },

  initializing: function () {
    this.pkg = require('../package.json');
  },

  prompting: function () {
    var done = this.async();

    if (!this.options['skip-welcome-message']) {
      this.log(yosay('I create a scaffold for creating JavasScript-based TVML tvOS Apps.  '));
    }

    var prompts = [{
      type: 'input',
      name: 'name',
      message: 'Your App name',
      default: 'tvmlApp'
    }, {
      type: 'input',
      name: 'id',
      message: 'Your App ID',
      default: 'org.sample.tvml-app'
    }];

    this.prompt(prompts, function (answers) {
      this.appname = answers.name;
      this.appid = answers.id;
      done();
    }.bind(this));
  },

  writing: {

    xcode: function () {
      mkdirp(this.appname + '/dist');

      // Xcode
      this.fs.copyTpl(
        this.templatePath('TvmlApp.xcodeproj/project.pbxproj'),
        this.destinationPath(this.appname + '.xcodeproj/project.pbxproj'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
      this.fs.copyTpl(
        this.templatePath('TvmlApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata'),
        this.destinationPath(this.appname + '.xcodeproj/project.xcworkspace/contents.xcworkspacedata'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );

      // App
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Back.imagestacklayer/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Back.imagestacklayer/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Back.imagestacklayer/Content.imageset/')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Front.imagestacklayer/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Front.imagestacklayer/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Front.imagestacklayer/Content.imageset/')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Middle.imagestacklayer/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Middle.imagestacklayer/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Middle.imagestacklayer/Content.imageset/')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Back.imagestacklayer/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Back.imagestacklayer/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Back.imagestacklayer/Content.imageset/')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Front.imagestacklayer/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Front.imagestacklayer/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Front.imagestacklayer/Content.imageset/')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Middle.imagestacklayer/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Middle.imagestacklayer/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/LaunchImage.launchimage/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/LaunchImage.launchimage/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/Contents.json')
      );

      this.fs.copyTpl(
        this.templatePath('TvmlApp/AppDelegate.swift'),
        this.destinationPath(this.appname + '/AppDelegate.swift'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
      this.fs.copyTpl(
        this.templatePath('TvmlApp/ResourceLoader.swift'),
        this.destinationPath(this.appname + '/ResourceLoader.swift'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
      this.fs.copyTpl(
        this.templatePath('TvmlApp/Info.plist'),
        this.destinationPath(this.appname + '/Info.plist'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
      // Tests
      this.fs.copyTpl(
        this.templatePath('TvmlAppTests/TvmlAppTests.swift'),
        this.destinationPath(this.appname + 'Tests/' + this.appname + 'Tests.swift'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
      this.fs.copyTpl(
        this.templatePath('TvmlAppTests/Info.plist'),
        this.destinationPath(this.appname + 'Tests/Info.plist'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
      // UITests
      this.fs.copyTpl(
        this.templatePath('TvmlAppUITests/TvmlAppUITests.swift'),
        this.destinationPath(this.appname + 'UITests/' + this.appname + 'UITests.swift'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
      this.fs.copyTpl(
        this.templatePath('TvmlAppUITests/Info.plist'),
        this.destinationPath(this.appname + 'UITests/Info.plist'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
    },

    gruntfile: function () {
      this.fs.copyTpl(
        this.templatePath('TvmlApp/Gruntfile.js'),
        this.destinationPath(this.appname + '/Gruntfile.js'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
    },

    webpack: function () {
      this.fs.copyTpl(
        this.templatePath('TvmlApp/webpack.config.js'),
        this.destinationPath(this.appname + '/webpack.config.js'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
    },

    packageJSON: function () {
      this.fs.copyTpl(
        this.templatePath('TvmlApp/_package.json'),
        this.destinationPath(this.appname + '/package.json'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
    },

    git: function () {
      this.fs.copyTpl(
        this.templatePath('gitignore'),
        this.destinationPath('.gitignore'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );

      this.fs.copy(
        this.templatePath('gitattributes'),
        this.destinationPath('.gitattributes')
      );
    },

    editorConfig: function () {
      this.fs.copy(
        this.templatePath('editorconfig'),
        this.destinationPath('.editorconfig')
      );
    },

    scripts: function () {
      this.fs.copy(
        this.templatePath('TvmlApp/src/application.js'),
        this.destinationPath(this.appname + '/src/application.js')
      );
    },

    templates: function () {
      this.fs.copy(
        this.templatePath('TvmlApp/src/templates/loading.jade'),
        this.destinationPath(this.appname + '/src/templates/loading.jade')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/src/templates/list.jade'),
        this.destinationPath(this.appname + '/src/templates/list.jade')
      );
    }
  },

  install: function () {
    this.installDependencies({
      bower: false,
      npm: true,
      skipMessage: this.options['skip-install-message'],
      skipInstall: this.options['skip-install']
    });
  },

  end: function () {
    var howToInstall =
      '\nPlease run ' +
      chalk.yellow.bold('npm install') +
      '.';

    if (this.options['skip-install']) {
      this.log(howToInstall);
      return;
    }
    this.log(yosay('Run ' + chalk.yellow.bold('npm start') + ' to start local dev server with reload. Then Start the app from Xcode.'));
  }
});
<commit_msg>Fix install error<commit_after>'use strict';
var generators = require('yeoman-generator');
var yosay = require('yosay');
var chalk = require('chalk');
var mkdirp = require('mkdirp');

module.exports = generators.Base.extend({
  constructor: function () {

    generators.Base.apply(this, arguments);

    this.option('skip-welcome-message', {
      desc: 'Skips the welcome message',
      type: Boolean
    });

    this.option('skip-install-message', {
      desc: 'Skips the message after the installation of dependencies',
      type: Boolean
    });

    this.option('appname', {
      desc: 'Name of the app',
      type: String,
      defaults: 'tvml-app'
    });

    this.option('appid', {
      desc: 'Id of the app',
      type: String,
      defaults: 'org.sample.tvml-app'
    });
  },

  initializing: function () {
    this.pkg = require('../package.json');
  },

  prompting: function () {
    var done = this.async();

    if (!this.options['skip-welcome-message']) {
      this.log(yosay('I create a scaffold for creating JavasScript-based TVML tvOS Apps.  '));
    }

    var prompts = [{
      type: 'input',
      name: 'name',
      message: 'Your App name',
      default: 'tvmlApp'
    }, {
      type: 'input',
      name: 'id',
      message: 'Your App ID',
      default: 'org.sample.tvml-app'
    }];

    this.prompt(prompts, function (answers) {
      this.appname = answers.name;
      this.appid = answers.id;
      done();
    }.bind(this));
  },

  writing: {

    xcode: function () {
      mkdirp(this.appname + '/dist');

      // Xcode
      this.fs.copyTpl(
        this.templatePath('TvmlApp.xcodeproj/project.pbxproj'),
        this.destinationPath(this.appname + '.xcodeproj/project.pbxproj'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
      this.fs.copyTpl(
        this.templatePath('TvmlApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata'),
        this.destinationPath(this.appname + '.xcodeproj/project.xcworkspace/contents.xcworkspacedata'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );

      // App
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Back.imagestacklayer/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Back.imagestacklayer/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Back.imagestacklayer/Content.imageset/')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Front.imagestacklayer/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Front.imagestacklayer/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Front.imagestacklayer/Content.imageset/')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Middle.imagestacklayer/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Middle.imagestacklayer/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Large.imagestack/Middle.imagestacklayer/Content.imageset/')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Back.imagestacklayer/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Back.imagestacklayer/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Back.imagestacklayer/Content.imageset/')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Front.imagestacklayer/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Front.imagestacklayer/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Front.imagestacklayer/Content.imageset/')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Middle.imagestacklayer/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Middle.imagestacklayer/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/App\ Icon\ \&\ Top\ Shelf\ Image.brandassets/App\ Icon\ -\ Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/LaunchImage.launchimage/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/LaunchImage.launchimage/Contents.json')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/Assets.xcassets/Contents.json'),
        this.destinationPath(this.appname + '/Assets.xcassets/Contents.json')
      );

      this.fs.copyTpl(
        this.templatePath('TvmlApp/AppDelegate.swift'),
        this.destinationPath(this.appname + '/AppDelegate.swift'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
      this.fs.copyTpl(
        this.templatePath('TvmlApp/ResourceLoader.swift'),
        this.destinationPath(this.appname + '/ResourceLoader.swift'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
      this.fs.copyTpl(
        this.templatePath('TvmlApp/Info.plist'),
        this.destinationPath(this.appname + '/Info.plist'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
      // Tests
      this.fs.copyTpl(
        this.templatePath('TvmlAppTests/TvmlAppTests.swift'),
        this.destinationPath(this.appname + 'Tests/' + this.appname + 'Tests.swift'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
      this.fs.copyTpl(
        this.templatePath('TvmlAppTests/Info.plist'),
        this.destinationPath(this.appname + 'Tests/Info.plist'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
      // UITests
      this.fs.copyTpl(
        this.templatePath('TvmlAppUITests/TvmlAppUITests.swift'),
        this.destinationPath(this.appname + 'UITests/' + this.appname + 'UITests.swift'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
      this.fs.copyTpl(
        this.templatePath('TvmlAppUITests/Info.plist'),
        this.destinationPath(this.appname + 'UITests/Info.plist'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
    },

    gruntfile: function () {
      this.fs.copyTpl(
        this.templatePath('TvmlApp/Gruntfile.js'),
        this.destinationPath(this.appname + '/Gruntfile.js'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
    },

    webpack: function () {
      this.fs.copyTpl(
        this.templatePath('TvmlApp/webpack.config.js'),
        this.destinationPath(this.appname + '/webpack.config.js'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
    },

    packageJSON: function () {
      this.fs.copyTpl(
        this.templatePath('TvmlApp/_package.json'),
        this.destinationPath(this.appname + '/package.json'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );
    },

    git: function () {
      this.fs.copyTpl(
        this.templatePath('gitignore'),
        this.destinationPath('.gitignore'),
        {
          appname: this.appname,
          appid: this.appid
        }
      );

      this.fs.copy(
        this.templatePath('gitattributes'),
        this.destinationPath('.gitattributes')
      );
    },

    editorConfig: function () {
      this.fs.copy(
        this.templatePath('editorconfig'),
        this.destinationPath('.editorconfig')
      );
    },

    scripts: function () {
      this.fs.copy(
        this.templatePath('TvmlApp/src/application.js'),
        this.destinationPath(this.appname + '/src/application.js')
      );
    },

    templates: function () {
      this.fs.copy(
        this.templatePath('TvmlApp/src/templates/loading.jade'),
        this.destinationPath(this.appname + '/src/templates/loading.jade')
      );
      this.fs.copy(
        this.templatePath('TvmlApp/src/templates/list.jade'),
        this.destinationPath(this.appname + '/src/templates/list.jade')
      );
    }
  },

  install: function () {
    var elementDir = process.cwd() + '/' + this.appname;
    process.chdir(elementDir);
    this.installDependencies({
      bower: false,
      npm: true,
      skipMessage: this.options['skip-install-message'],
      skipInstall: this.options['skip-install']
    });
  },

  end: function () {
    var howToInstall =
      '\nPlease run ' +
      chalk.yellow.bold('npm install') +
      '.';

    if (this.options['skip-install']) {
      this.log(howToInstall);
      return;
    }
    this.log(yosay('Run ' + chalk.yellow.bold('cd ' + this.appname + ' && npm start') + ' to start local dev server with reload. Then Start the app from Xcode.'));
  }
});
<|endoftext|>


<commit_before>'use strict';
var util = require('util');
var path = require('path');
var yeoman = require('yeoman-generator');

var DavteamGenerator = module.exports = function DavteamGenerator(args, options, config) {
  yeoman.generators.Base.apply(this, arguments);

  this.on('end', function () {
    this.installDependencies({ skipInstall: options['skip-install'] });
  });

  this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
};

util.inherits(DavteamGenerator, yeoman.generators.Base);

DavteamGenerator.prototype.askFor = function askFor() {
  var cb = this.async();

  // have Yeoman greet the user.
  console.log(this.yeoman);

  var prompts = [
  {
    name: 'projectName',
    message: 'What do you want to call your project?'
  },
  {
    name: 'projectDescription',
    message: 'Describe your project in a few words'
  }
  ];

  this.prompt(prompts, function (props) {
    this.projectName = props.projectName;
    this.projectDescription = props.projectDescription;

    cb();
  }.bind(this));
};

DavteamGenerator.prototype.app = function app() {
  // create the directories
  this.mkdir('app');
  this.mkdir('app/templates');
  this.mkdir('app/scripts');
  this.mkdir('app/styles');
  this.mkdir('app/img');

  // create the templated files
  this.tempalte('index.html', 'app/index.html');
  this.template('Gruntfile.js', 'Gruntfile.js');

  this.template('_bower.json', 'bower.json');
  this.template('_package.json', 'package.json');

  this.tempalate('_README.md', 'README.md')

  // copy the next of the things
  this.copy('_changelog.md', 'changelog.md')
  this.copy('404.html', 'app/404.html');
  this.copy('robots.txt', 'app/robots.txt')
};

DavteamGenerator.prototype.test = function app() {
  // create the scaffolding
  this.mkdir('test');
  this.mkdir('test/spec');
  this.mkdir('test/lib');

  this.copy('')

}

DavteamGenerator.prototype.projectfiles = function projectfiles() {
  this.copy('editorconfig', '.editorconfig');
  this.copy('jshintrc', '.jshintrc');
  this.copy('gitignore', '.gitignore');
  this.copy('npmignore', '.npmignore');
};
<commit_msg>better generator<commit_after>'use strict';
var util = require('util');
var path = require('path');
var yeoman = require('yeoman-generator');

var DavteamGenerator = module.exports = function DavteamGenerator(args, options, config) {
  yeoman.generators.Base.apply(this, arguments);

  this.on('end', function () {
    this.installDependencies({ skipInstall: options['skip-install'] });
  });

  this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
};

util.inherits(DavteamGenerator, yeoman.generators.Base);

DavteamGenerator.prototype.askFor = function askFor() {
  var cb = this.async();

  // have Yeoman greet the user.
  console.log(this.yeoman);

  var prompts = [
  {
    name: 'projectName',
    message: 'What do you want to call your project?'
  },
  {
    name: 'projectDescription',
    message: 'Describe your project in a few words'
  }
  ];

  this.prompt(prompts, function (props) {
    this.projectName = props.projectName;
    this.projectDescription = props.projectDescription;

    cb();
  }.bind(this));
};

DavteamGenerator.prototype.app = function app() {
  // create the directories
  this.mkdir('app');
  this.mkdir('app/templates');
  this.mkdir('app/scripts');
  this.mkdir('app/styles');
  this.mkdir('app/img');

  // create the templated files
  this.tempalte('index.html', 'app/index.html');

  this.copy('404.html', 'app/404.html');
  this.copy('robots.txt', 'app/robots.txt')
};

DavteamGenerator.prototype.test = function app() {
  // create the scaffolding
  this.mkdir('test');
  this.mkdir('test/spec');

  // copy the test
  this.copy('test/index.html', 'test/index.html');
  this.copy('test/specRunner.js', 'test/specRunner.js');
  this.copy('test/spec/app.js', 'test/spec/app.js');

}

DavteamGenerator.prototype.projectfiles = function projectfiles() {
  this.template('Gruntfile.js', 'Gruntfile.js');

  this.template('_bower.json', 'bower.json');
  this.template('_package.json', 'package.json');

  this.tempalate('_README.md', 'README.md')

  // copy the next of the things
  this.copy('_changelog.md', 'changelog.md')
  this.copy('editorconfig', '.editorconfig');
  this.copy('jshintrc', '.jshintrc');
  this.copy('gitignore', '.gitignore');
  this.copy('npmignore', '.npmignore');
};
<|endoftext|>


<commit_before>/**
 * Copyright 2013-2014 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule DOMChildrenOperations
 * @typechecks static-only
 */

"use strict";

var Danger = require('Danger');
var ReactMultiChildUpdateTypes = require('ReactMultiChildUpdateTypes');

var getTextContentAccessor = require('getTextContentAccessor');

/**
 * The DOM property to use when setting text content.
 *
 * @type {string}
 * @private
 */
var textContentAccessor = getTextContentAccessor();

/**
 * Inserts `childNode` as a child of `parentNode` at the `index`.
 *
 * @param {DOMElement} parentNode Parent node in which to insert.
 * @param {DOMElement} childNode Child node to insert.
 * @param {number} index Index at which to insert the child.
 * @internal
 */
function insertChildAt(parentNode, childNode, index) {
  var childNodes = parentNode.childNodes;
  if (childNodes[index] === childNode) {
    return;
  }
  // If `childNode` is already a child of `parentNode`, remove it so that
  // computing `childNodes[index]` takes into account the removal.
  if (childNode.parentNode === parentNode) {
    parentNode.removeChild(childNode);
  }
  if (index >= childNodes.length) {
    parentNode.appendChild(childNode);
  } else {
    parentNode.insertBefore(childNode, childNodes[index]);
  }
}

var updateTextContent;
if (textContentAccessor === 'textContent') {
  /**
   * Sets the text content of `node` to `text`.
   *
   * @param {DOMElement} node Node to change
   * @param {string} text New text content
   */
  updateTextContent = function(node, text) {
    node.textContent = text;
  };
} else {
  /**
   * Sets the text content of `node` to `text`.
   *
   * @param {DOMElement} node Node to change
   * @param {string} text New text content
   */
  updateTextContent = function(node, text) {
    // In order to preserve newlines correctly, we can't use .innerText to set
    // the contents (see #1080), so we empty the element then append a text node
    while (node.firstChild) {
      node.removeChild(node.firstChild);
    }
    if (text) {
      var doc = node.ownerDocument || document;
      node.appendChild(doc.createTextNode(text));
    }
  };
}

/**
 * Operations for updating with DOM children.
 */
var DOMChildrenOperations = {

  dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup,

  updateTextContent: updateTextContent,

  /**
   * Updates a component's children by processing a series of updates. The
   * update configurations are each expected to have a `parentNode` property.
   *
   * @param {array<object>} updates List of update configurations.
   * @param {array<string>} markupList List of markup strings.
   * @internal
   */
  processUpdates: function(updates, markupList) {
    var update;
    // Mapping from parent IDs to initial child orderings.
    var initialChildren = null;
    // List of children that will be moved or removed.
    var updatedChildren = null;

    for (var i = 0; update = updates[i]; i++) {
      if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING ||
          update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) {
        var updatedIndex = update.fromIndex;
        var updatedChild = update.parentNode.childNodes[updatedIndex];
        var parentID = update.parentID;

        initialChildren = initialChildren || {};
        initialChildren[parentID] = initialChildren[parentID] || [];
        initialChildren[parentID][updatedIndex] = updatedChild;

        updatedChildren = updatedChildren || [];
        updatedChildren.push(updatedChild);
      }
    }

    var renderedMarkup = Danger.dangerouslyRenderMarkup(markupList);

    // Remove updated children first so that `toIndex` is consistent.
    if (updatedChildren) {
      for (var j = 0; j < updatedChildren.length; j++) {
        updatedChildren[j].parentNode.removeChild(updatedChildren[j]);
      }
    }

    for (var k = 0; update = updates[k]; k++) {
      switch (update.type) {
        case ReactMultiChildUpdateTypes.INSERT_MARKUP:
          insertChildAt(
            update.parentNode,
            renderedMarkup[update.markupIndex],
            update.toIndex
          );
          break;
        case ReactMultiChildUpdateTypes.MOVE_EXISTING:
          insertChildAt(
            update.parentNode,
            initialChildren[update.parentID][update.fromIndex],
            update.toIndex
          );
          break;
        case ReactMultiChildUpdateTypes.TEXT_CONTENT:
          updateTextContent(
            update.parentNode,
            update.textContent
          );
          break;
        case ReactMultiChildUpdateTypes.REMOVE_NODE:
          // Already removed by the for-loop above.
          break;
      }
    }
  }

};

module.exports = DOMChildrenOperations;
<commit_msg>Add clearer invariant in processUpdates<commit_after>/**
 * Copyright 2013-2014 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule DOMChildrenOperations
 * @typechecks static-only
 */

"use strict";

var Danger = require('Danger');
var ReactMultiChildUpdateTypes = require('ReactMultiChildUpdateTypes');

var getTextContentAccessor = require('getTextContentAccessor');
var invariant = require('invariant');

/**
 * The DOM property to use when setting text content.
 *
 * @type {string}
 * @private
 */
var textContentAccessor = getTextContentAccessor();

/**
 * Inserts `childNode` as a child of `parentNode` at the `index`.
 *
 * @param {DOMElement} parentNode Parent node in which to insert.
 * @param {DOMElement} childNode Child node to insert.
 * @param {number} index Index at which to insert the child.
 * @internal
 */
function insertChildAt(parentNode, childNode, index) {
  var childNodes = parentNode.childNodes;
  if (childNodes[index] === childNode) {
    return;
  }
  // If `childNode` is already a child of `parentNode`, remove it so that
  // computing `childNodes[index]` takes into account the removal.
  if (childNode.parentNode === parentNode) {
    parentNode.removeChild(childNode);
  }
  if (index >= childNodes.length) {
    parentNode.appendChild(childNode);
  } else {
    parentNode.insertBefore(childNode, childNodes[index]);
  }
}

var updateTextContent;
if (textContentAccessor === 'textContent') {
  /**
   * Sets the text content of `node` to `text`.
   *
   * @param {DOMElement} node Node to change
   * @param {string} text New text content
   */
  updateTextContent = function(node, text) {
    node.textContent = text;
  };
} else {
  /**
   * Sets the text content of `node` to `text`.
   *
   * @param {DOMElement} node Node to change
   * @param {string} text New text content
   */
  updateTextContent = function(node, text) {
    // In order to preserve newlines correctly, we can't use .innerText to set
    // the contents (see #1080), so we empty the element then append a text node
    while (node.firstChild) {
      node.removeChild(node.firstChild);
    }
    if (text) {
      var doc = node.ownerDocument || document;
      node.appendChild(doc.createTextNode(text));
    }
  };
}

/**
 * Operations for updating with DOM children.
 */
var DOMChildrenOperations = {

  dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup,

  updateTextContent: updateTextContent,

  /**
   * Updates a component's children by processing a series of updates. The
   * update configurations are each expected to have a `parentNode` property.
   *
   * @param {array<object>} updates List of update configurations.
   * @param {array<string>} markupList List of markup strings.
   * @internal
   */
  processUpdates: function(updates, markupList) {
    var update;
    // Mapping from parent IDs to initial child orderings.
    var initialChildren = null;
    // List of children that will be moved or removed.
    var updatedChildren = null;

    for (var i = 0; update = updates[i]; i++) {
      if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING ||
          update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) {
        var updatedIndex = update.fromIndex;
        var updatedChild = update.parentNode.childNodes[updatedIndex];
        var parentID = update.parentID;

        invariant(
          updatedChild,
          'processUpdates(): Unable to find child %s of element. This ' +
          'probably means the DOM was unexpectedly mutated (e.g., by the ' +
          'browser), usually due to forgetting a <tbody> when using tables ' +
          'or nesting <p> or <a> tags. Try inspecting the child nodes of the ' +
          'element with React ID `%s`.',
          updatedIndex,
          parentID
        );

        initialChildren = initialChildren || {};
        initialChildren[parentID] = initialChildren[parentID] || [];
        initialChildren[parentID][updatedIndex] = updatedChild;

        updatedChildren = updatedChildren || [];
        updatedChildren.push(updatedChild);
      }
    }

    var renderedMarkup = Danger.dangerouslyRenderMarkup(markupList);

    // Remove updated children first so that `toIndex` is consistent.
    if (updatedChildren) {
      for (var j = 0; j < updatedChildren.length; j++) {
        updatedChildren[j].parentNode.removeChild(updatedChildren[j]);
      }
    }

    for (var k = 0; update = updates[k]; k++) {
      switch (update.type) {
        case ReactMultiChildUpdateTypes.INSERT_MARKUP:
          insertChildAt(
            update.parentNode,
            renderedMarkup[update.markupIndex],
            update.toIndex
          );
          break;
        case ReactMultiChildUpdateTypes.MOVE_EXISTING:
          insertChildAt(
            update.parentNode,
            initialChildren[update.parentID][update.fromIndex],
            update.toIndex
          );
          break;
        case ReactMultiChildUpdateTypes.TEXT_CONTENT:
          updateTextContent(
            update.parentNode,
            update.textContent
          );
          break;
        case ReactMultiChildUpdateTypes.REMOVE_NODE:
          // Already removed by the for-loop above.
          break;
      }
    }
  }

};

module.exports = DOMChildrenOperations;
<|endoftext|>


<commit_before>import sourceAutocomplete   from './sourceAutocomplete'
import sourceOption   from './sourceOption'
import {
  abeExtend
  ,User
} from '../../../'

export function getAttributes(params) {
  var attributes = ''
  if(params.key != null) attributes += `id="${params.key}" data-id="${params.key}"`
  if(params.value != null) attributes += ` value="${params.value}"`
  if(params['max-length'] != null) attributes += ` data-maxlength="${params['max-length']}"`
  if(params.reload != null) attributes += ` reload="${params.reload}"`
  if(params.order != null) attributes += ` tabIndex="${params.order}"`
  if(params.required != null) attributes += ` data-required="${params.required}"`
  if(params.display != null) attributes += ` data-display="${params.display}"`
  if(params.visible != null) attributes += ` data-visible="${params.visible}"`
  if(params.autocomplete != null) attributes += ` data-autocomplete="${params.autocomplete}"`
  if(params.placeholder != null) attributes += ` placeholder="${params.placeholder}"`
  if(params.thumbs != null) attributes += ` data-size="${params.thumbs}"`
  if(params.multiple != null) attributes += ` ${params.multiple}`
  if(params.disabled != null) attributes += ` ${params.disabled}`
  return attributes
}

export function getLabel(params) {
  var desc = params.desc + ((params.required) ? ' *' : '')
  return `
            ${desc}
          `
}

export function createInputSource(attributes, inputClass, params) {
  var inputSource = ''
  var lastValues
  if(params.autocomplete != null && params.autocomplete === 'true') {
    if(params.sourceString.indexOf('http') === 0) lastValues = params.source
    else lastValues = JSON.stringify(params.source).replace(/\'/g, '&quote;')
    inputSource += '
'
    if(params.autocomplete != null && params.autocomplete === 'true' && params.prefill === 'true') {
      inputSource += `

`
    }
    Array.prototype.forEach.call(params.value, (val) => {
      inputSource += sourceAutocomplete(val, params)
    })
    inputSource += `</div><input value="" type="text" autocomplete="off" data-value='${lastValues}' ${attributes} class="${inputClass}" />`
  }
  else {
    lastValues = JSON.stringify(params.value).replace(/\'/g, '&quote;')
    inputSource += `<select ${attributes} class="${inputClass}" last-values='${lastValues}'>`

    if (!params.required) inputSource += '<option value=\'\'></option>'
    if(typeof params.source === 'object' && Object.prototype.toString.call(params.source) === '[object Array]') {
      Array.prototype.forEach.call(params.source, (val) => {
        inputSource += sourceOption(val, params)
      })
    }
    else inputSource += sourceOption(params.source, params)
    inputSource += '</select>'
  }
  return inputSource
}

export function createInputRich(attributes, inputClass, params) {
  return `

                U

            <textarea class="${inputClass} form-rich" ${attributes} rows="4">${params.value}</textarea>

`
}

export function createInputFile(attributes, inputClass, params) {
  return `<input class="form-control" ${attributes} name="${params.key}" type="file" />

          <input type="text" ${attributes} class="${inputClass} hidden" />`
}

export function createInputTextarea(attributes, inputClass, params) {
  return `<textarea class="${inputClass}" ${attributes} rows="4">${params.value}</textarea>`
}

export function createInputLink(attributes, inputClass, params) {
  return `

            <input type="text" ${attributes} class="${inputClass}" />

`
}

export function createInputImage(attributes, inputClass, params) {
  return `

            <input type="text" ${attributes} class="${inputClass} image-input" />

              <input class="form-control" ${attributes} name="${params.key}" type="file" title="upload an image"/>

`
}

export function createInputText(attributes, inputClass, params) {
  return `

            <input type="text" ${attributes} class="${inputClass}" />

`
}

/**
 * Print form input based on input data type {Textarea | text | meta | link | image | ...}
 * && add appropriate attributs / data-attributs
 * @return {String|html} input / input group ...
 */
export function printInput (params, root) {
  params = abeExtend.hooks.instance.trigger('beforeEditorInput', params)
  var userWorkflow = (root.user != null) ? root.user.role.workflow : ''
  var res = `<div class="form-group" data-precontrib-templates="${params.precontribTemplate}">`
  var inputClass = 'form-control form-abe'
  res += getLabel(params)

  params.placeholder = params.placeholder || ''
  params.value = params.value || ''

  if(typeof params.value === 'string') params.value = params.value.replace(/\"/g, '"')

  params.disabled = ''
  if (params.tab !== 'slug' && !User.utils.isUserAllowedOnRoute(userWorkflow, `/abe/operations/${params.status}/edit`)) {
    params.disabled = 'disabled="disabled"'
  }
  var attributes = getAttributes(params)

  if(params.source != null) {
    params.multiple = ((params['max-length'] == null || params['max-length'] > 1) && params.source.length > 0) ? 'multiple' : ''
    params.disabled = (params.source.length <= 0) ? 'disabled' : ''
    res += createInputSource(getAttributes(params), inputClass, params)
  }
  else if (params.type.indexOf('rich') >= 0) res += createInputRich(attributes, inputClass, params)
  else if (params.type.indexOf('file') >= 0) res += createInputFile(attributes, inputClass, params)
  else if (params.type.indexOf('textarea') >= 0) res += createInputTextarea(attributes, inputClass, params)
  else if (params.type.indexOf('link') >= 0) res += createInputLink(attributes, inputClass, params)
  else if (params.type.indexOf('image') >= 0) res += createInputImage(attributes, inputClass, params)
  else res += createInputText(attributes, inputClass, params)

  res += '
'
  res = abeExtend.hooks.instance.trigger('afterEditorInput', res, params)

  return res
}<commit_msg>bug: url user authorize abe/operations/edit<commit_after>import sourceAutocomplete   from './sourceAutocomplete'
import sourceOption   from './sourceOption'
import {
  abeExtend
  ,User
} from '../../../'

export function getAttributes(params) {
  var attributes = ''
  if(params.key != null) attributes += `id="${params.key}" data-id="${params.key}"`
  if(params.value != null) attributes += ` value="${params.value}"`
  if(params['max-length'] != null) attributes += ` data-maxlength="${params['max-length']}"`
  if(params.reload != null) attributes += ` reload="${params.reload}"`
  if(params.order != null) attributes += ` tabIndex="${params.order}"`
  if(params.required != null) attributes += ` data-required="${params.required}"`
  if(params.display != null) attributes += ` data-display="${params.display}"`
  if(params.visible != null) attributes += ` data-visible="${params.visible}"`
  if(params.autocomplete != null) attributes += ` data-autocomplete="${params.autocomplete}"`
  if(params.placeholder != null) attributes += ` placeholder="${params.placeholder}"`
  if(params.thumbs != null) attributes += ` data-size="${params.thumbs}"`
  if(params.multiple != null) attributes += ` ${params.multiple}`
  if(params.disabled != null) attributes += ` ${params.disabled}`
  return attributes
}

export function getLabel(params) {
  var desc = params.desc + ((params.required) ? ' *' : '')
  return `
            ${desc}
          `
}

export function createInputSource(attributes, inputClass, params) {
  var inputSource = ''
  var lastValues
  if(params.autocomplete != null && params.autocomplete === 'true') {
    if(params.sourceString.indexOf('http') === 0) lastValues = params.source
    else lastValues = JSON.stringify(params.source).replace(/\'/g, '&quote;')
    inputSource += '
'
    if(params.autocomplete != null && params.autocomplete === 'true' && params.prefill === 'true') {
      inputSource += `

`
    }
    Array.prototype.forEach.call(params.value, (val) => {
      inputSource += sourceAutocomplete(val, params)
    })
    inputSource += `</div><input value="" type="text" autocomplete="off" data-value='${lastValues}' ${attributes} class="${inputClass}" />`
  }
  else {
    lastValues = JSON.stringify(params.value).replace(/\'/g, '&quote;')
    inputSource += `<select ${attributes} class="${inputClass}" last-values='${lastValues}'>`

    if (!params.required) inputSource += '<option value=\'\'></option>'
    if(typeof params.source === 'object' && Object.prototype.toString.call(params.source) === '[object Array]') {
      Array.prototype.forEach.call(params.source, (val) => {
        inputSource += sourceOption(val, params)
      })
    }
    else inputSource += sourceOption(params.source, params)
    inputSource += '</select>'
  }
  return inputSource
}

export function createInputRich(attributes, inputClass, params) {
  return `

                U

            <textarea class="${inputClass} form-rich" ${attributes} rows="4">${params.value}</textarea>

`
}

export function createInputFile(attributes, inputClass, params) {
  return `<input class="form-control" ${attributes} name="${params.key}" type="file" />

          <input type="text" ${attributes} class="${inputClass} hidden" />`
}

export function createInputTextarea(attributes, inputClass, params) {
  return `<textarea class="${inputClass}" ${attributes} rows="4">${params.value}</textarea>`
}

export function createInputLink(attributes, inputClass, params) {
  return `

            <input type="text" ${attributes} class="${inputClass}" />

`
}

export function createInputImage(attributes, inputClass, params) {
  return `

            <input type="text" ${attributes} class="${inputClass} image-input" />

              <input class="form-control" ${attributes} name="${params.key}" type="file" title="upload an image"/>

`
}

export function createInputText(attributes, inputClass, params) {
  return `

            <input type="text" ${attributes} class="${inputClass}" />

`
}

/**
 * Print form input based on input data type {Textarea | text | meta | link | image | ...}
 * && add appropriate attributs / data-attributs
 * @return {String|html} input / input group ...
 */
export function printInput (params, root) {
  params = abeExtend.hooks.instance.trigger('beforeEditorInput', params)
  var userWorkflow = (root.user != null) ? root.user.role.workflow : ''
  var res = `<div class="form-group" data-precontrib-templates="${params.precontribTemplate}">`
  var inputClass = 'form-control form-abe'
  res += getLabel(params)

  params.placeholder = params.placeholder || ''
  params.value = params.value || ''

  if(typeof params.value === 'string') params.value = params.value.replace(/\"/g, '"')

  params.disabled = ''
  if (params.tab !== 'slug' && !User.utils.isUserAllowedOnRoute(userWorkflow, `/abe/operations/edit/${params.status}`)) {
    params.disabled = 'disabled="disabled"'
  }
  var attributes = getAttributes(params)

  if(params.source != null) {
    params.multiple = ((params['max-length'] == null || params['max-length'] > 1) && params.source.length > 0) ? 'multiple' : ''
    params.disabled = (params.source.length <= 0) ? 'disabled' : ''
    res += createInputSource(getAttributes(params), inputClass, params)
  }
  else if (params.type.indexOf('rich') >= 0) res += createInputRich(attributes, inputClass, params)
  else if (params.type.indexOf('file') >= 0) res += createInputFile(attributes, inputClass, params)
  else if (params.type.indexOf('textarea') >= 0) res += createInputTextarea(attributes, inputClass, params)
  else if (params.type.indexOf('link') >= 0) res += createInputLink(attributes, inputClass, params)
  else if (params.type.indexOf('image') >= 0) res += createInputImage(attributes, inputClass, params)
  else res += createInputText(attributes, inputClass, params)

  res += '
'
  res = abeExtend.hooks.instance.trigger('afterEditorInput', res, params)

  return res
}<|endoftext|>


<commit_before>import React from 'react';
import CurrencyPair from './currency-pair';
import Header from './header';
import _ from 'lodash';

import rt from '../classes/services/reactive-trader';

//todo: hook up socket stream
let pairs = [];

const STALE_TIMEOUT = 4000;

/**
 * @class CurrencyPairs
 * @extends {React.Component}
 */
class CurrencyPairs extends React.Component {

  /**
   * @constructs CurrencyPair
   * @param {Object=} props
   * @param {Object=} context
   */
  constructor(props, context){
    super(props, context);
    this.state = {
      pairs: [],
      connected: false,
      services: {

      }
    };

    this.subscribed = [];
  }

  /**
   * Deals with socket comms for pairs - gets reference data, subscribes to each pair.
   */
  attachSubs(){

    this.setState({
      connected: rt.transport.isOpen,
      services: rt.transport.getStatus()
    });

    const updatePairs = _.debounce((src) => {
      const pairs = src || this.state.pairs;

      pairs.forEach((pair) => {
        const timeOutState = Date.now() - (pair.lastUpdated || 0) > STALE_TIMEOUT ? 'stale' : 'listening';
        pair.state = this.state.services.pricing ? timeOutState : 'stale';
      });

      this.setState({
        pairs: pairs
      });
    }, 5);

    rt.reference.getCurrencyPairUpdatesStream((referenceData) => {
      // normalise the currency pair reference data
      const pairs = _.map(referenceData.Updates, (updatedPair) => {
        const pair = updatedPair.CurrencyPair;

        if (updatedPair.UpdateType == 'Added'){
          return {
            //todo: accept rawPair.PipPosition and rawPair.RatePrecision
            pip: pair.PipsPosition,
            precision: pair.RatePrecision,
            pair: pair.Symbol,
            id: pair.Symbol,
            buy: undefined,
            sell: undefined
          };
        }
        else {
          // removed?
          // console.log(updatedPair.UpdateType);
          updatePairs(this.state.pairs.filter((p) => p.id != pair.Symbol));
          rt.pricing.unsubscribe(existing.pricingSub);
        }
      }, this);

      this.setState({
        pairs: pairs
      });

      // subscribe to individual streams
      this.state.pairs.forEach((pair) => {
        pair.pricingSub = rt.pricing.getPriceUpdates(pair.id, (priceData) => {
          let existingPair = _.findWhere(this.state.pairs, {id: priceData.symbol});

          if (!existingPair){
            //todo: we should unsubscribe!
            return;
          }

          existingPair.buy = Number(priceData.bid);
          existingPair.sell = Number(priceData.ask);
          existingPair.mid = Number(priceData.mid);

          existingPair.lastUpdated = Date.now();

          updatePairs();
        });
      });
    });

    const self = this;
    rt.transport
      .on('open', ()=> self.setState({connected: true}))
      .on('close', ()=> self.setState({connected: false}))
      .on('statusUpdate', (services) => {
        // update ui indicators
        self.setState({
          services
        });
        updatePairs();
      });
  }

  componentWillMount(){
    this.attachSubs();

    this.setState({
      pairs: pairs
    });
  }

  onACK(payload){
    const pairs = this.state.pairs,
          pair = _.findWhere(pairs, {pair: payload.pair});

    pair.state = 'listening';
    pair.response = payload;

    this.setState({
      pairs
    });
  }

  componentDidUpdate(){
    // silently remove last response
    this.state.pairs.forEach((pair)=>{
      delete pair.response;
    });
  }

  onExecute(payload){
    //todo: send to socket.
    if (this.props.onExecute){
      const pair = _.findWhere(this.state.pairs, {pair: payload.pair});
      pair.state = 'executing';

      payload.onACK = (...args) => this.onACK(...args);

      this.props.onExecute(payload);
    }
  }

  render(){
    // filter cps that have got price data only.
    const p = this.state.pairs.filter((a) => {
      return a.buy && a.sell;
    });

    return

        {p.length ? p.map((cp) => <CurrencyPair onExecute={(payload) => this.onExecute(payload)}
                               pair={cp.pair}
                               size="100m"
                               key={cp.id}
                               buy={cp.buy}
                               sell={cp.sell}
                               mid={cp.mid}
                               precision={cp.precision}
                               pip={cp.pip}
                               state={cp.state}
                               response={cp.response} />) :

 }

;
  }
}

export default CurrencyPairs;
<commit_msg>better way of dealing with reference data going up and down<commit_after>import React from 'react';
import CurrencyPair from './currency-pair';
import Header from './header';
import _ from 'lodash';

import rt from '../classes/services/reactive-trader';

//todo: hook up socket stream
let pairs = [];

const STALE_TIMEOUT = 4000;

/**
 * @class CurrencyPairs
 * @extends {React.Component}
 */
class CurrencyPairs extends React.Component {

  /**
   * @constructs CurrencyPair
   * @param {Object=} props
   * @param {Object=} context
   */
  constructor(props, context){
    super(props, context);
    this.state = {
      pairs: [],
      connected: false,
      services: {}
    };

    this.subscribed = [];
  }

  /**
   * Deals with socket comms for pairs - gets reference data, subscribes to each pair.
   */
  attachSubs(){

    this.setState({
      connected: rt.transport.isOpen,
      services: rt.transport.getStatus()
    });

    const updatePairs = (src) =>{
      const pairs = src || this.state.pairs;

      pairs.forEach((pair) =>{
        const timeOutState = Date.now() - (pair.lastUpdated || 0) > STALE_TIMEOUT ? 'stale' : 'listening';
        // if either pricing or execution reports down, we cannot trade.
        pair.state = this.state.services.pricing && this.state.services.execution ? timeOutState : 'stale';
      });

      this.setState({
        pairs: pairs
      });
    };

    rt.reference.getCurrencyPairUpdatesStream((referenceData) =>{
      const pairs = this.state.pairs;
      let hasUpdates = false;

      // loop through updates
      _.forEach(referenceData.Updates, (updatedPair) =>{
        const pairData = updatedPair.CurrencyPair;

        // added new?
        if (updatedPair.UpdateType == 'Added'){
          let localPair = {
            pip: pairData.PipsPosition,
            precision: pairData.RatePrecision,
            pair: pairData.Symbol,
            id: pairData.Symbol,
            buy: undefined,
            sell: undefined
          };

          let existingPair = _.findWhere(pairs, {id: localPair.id});

          // only subscribe if we don't already listen for prices
          if (!existingPair){
            localPair.pricingSub = rt.pricing.getPriceUpdates(localPair.id, (priceData) =>{
              // console.info(priceData, localPair);
              localPair.buy = Number(priceData.bid);
              localPair.sell = Number(priceData.ask);
              localPair.mid = Number(priceData.mid);

              localPair.lastUpdated = Date.now();
              updatePairs();
            });

            hasUpdates = true;
            pairs.push(localPair);
          }
          else {
            console.warn('already exists', this.state.pairs, existingPair);
          }
        }
        else {
          // removed existing?
          rt.pricing.unsubscribe(existingPair.pricingSub);
          pairs.splice(_.indexOf(pairs, existingPair), 1);
          hasUpdates = true;
        }
      });

      // update state if we detected changes
      hasUpdates && updatePairs();
    });

    const self = this;

    rt.transport
      .on('open', ()=> self.setState({connected: true}))
      .on('close', ()=> self.setState({connected: false}))
      .on('statusUpdate', (services) =>{
        // update ui indicators
        self.setState({
          services
        });
        // also update pairs in case pricing has gone down
        updatePairs();
      });
  }

  componentWillMount(){
    this.attachSubs();

    this.setState({
      pairs: pairs
    });
  }

  onACK(payload){
    const pairs = this.state.pairs,
          pair  = _.findWhere(pairs, {pair: payload.pair});

    pair.state = 'listening';
    pair.response = payload;

    this.setState({
      pairs
    });
  }

  componentDidUpdate(){
    // silently remove last response
    this.state.pairs.forEach((pair)=>{
      delete pair.response;
    });
  }

  onExecute(payload){
    //todo: send to socket.
    if (this.props.onExecute){
      const pair = _.findWhere(this.state.pairs, {pair: payload.pair});
      pair.state = 'executing';

      payload.onACK = (...args) => this.onACK(...args);

      this.props.onExecute(payload);
    }
  }

  render(){
    // filter cps that have got price data only.
    const p = this.state.pairs.filter((a) =>{
      return a.buy && a.sell;
    });

    return

        {p.length ? p.map((cp) => <CurrencyPair onExecute={(payload) => this.onExecute(payload)}
                                                pair={cp.pair}
                                                size="100m"
                                                key={cp.id}
                                                buy={cp.buy}
                                                sell={cp.sell}
                                                mid={cp.mid}
                                                precision={cp.precision}
                                                pip={cp.pip}
                                                state={cp.state}
                                                response={cp.response}/>) :

 }

;
  }
}

export default CurrencyPairs;
<|endoftext|>


<commit_before>/****
 * Grapnel.js
 * https://github.com/gregsabia/Grapnel.js
 *
 * @author Greg Sabia Tucker
 * @link http://gregsabia.com
 * @version 0.3.1
 *
 * Released under MIT License. See LICENSE.txt or http://opensource.org/licenses/MIT
*/

(function(e){function t(e){"use strict";var t=this;this._actions=[];this._events=[];this.action=null;this.hook=e||":";this.value=null;this.params=[];this.anchor={defaultHash:window.location.hash};this.state=null;this.version="0.3.1";this.add=function(e,n){var r=function(){var r=t.action&&e instanceof RegExp?t.anchor.get().match(e):false;if(r||e===t.action||t.anchor.get()==e){var i={name:e,value:t.anchor.get(),handler:n,params:t.params,regex:r,previousState:t.state};t._trigger("change",i);t._actions.push({name:e,handler:n});t.state=i;n.call(t,t.value,t.params,i)}return t};return r().on(["initialized","hashchange"],r)};this._trigger=function(e){var n=Array.prototype.slice.call(arguments,1);t._forEach(t._events,function(r){if(r.event==e)r.handler.apply(t,n)});return t};this._map=function(e,t){if(typeof Array.prototype.map==="function")return Array.prototype.map.call(e,t);return function(e,t){var n=new Array(this.length);for(var r=0,i=this.length;r<i;r++){if(r in this)n[r]=e.call(t,this[r],r,this)}return n}.call(e,t)};this._forEach=function(e,t){if(typeof Array.prototype.forEach==="function")return Array.prototype.forEach.call(e,t);return function(e,t){for(var n=0,r=this.length;n<r;++n){e.call(t,this[n],n,this)}}.call(e,t)};this._routeRegExp=function(e,t,n,r){if(e instanceof RegExp)return e;if(e instanceof Array)e="("+e.join("|")+")";e=e.concat(r?"":"/?").replace(/\/\(/g,"(?:/").replace(/\+/g,"__plus__").replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?/g,function(e,n,r,i,s,o){t.push({name:i,optional:!!o});n=n||"";return""+(o?"":n)+"(?:"+(o?n:"")+(r||"")+(s||r&&"([^/.]+?)"||"([^/]+?)")+")"+(o||"")}).replace(/([\/.])/g,"\\$1").replace(/__plus__/g,"(.+)").replace(/\*/g,"(.*)");return new RegExp("^"+e+"$",n?"":"i")};this.anchor.get=function(){return window.location.hash?window.location.hash.split("#")[1]:""};this.anchor.set=function(e){window.location.hash=!e?"":e;return t};this.anchor.clear=function(){return this.set(false)};this.on(["initialized","hashchange"],function(){var e=this.parse();this.action=e.action;this.value=e.value;this.params=e.params;this._actions=[]});if(typeof window.onhashchange==="function")this.on("hashchange",window.onhashchange);window.onhashchange=function(){t._trigger("hashchange")};return this._trigger("initialized")}t.prototype.on=t.prototype.bind=function(e,t){var n=typeof e==="string"?e.split():e,r=this;this._forEach(n,function(e){r._events.push({event:e,handler:t})});return this};t.prototype.parse=function(){var e=this.anchor.get(),t=e.split(this.hook),n=e.match(this.hook),r=t[0],i=[],s;if(this.anchor.get().match(this.hook)){i=t.slice(1);s=i.join(n[0])}var o={pieces:t};this._trigger("parse",o);return{value:s,action:r,params:i}};t.prototype.matches=function(){var e=[];this._forEach(this._actions,function(t){var n=t.name instanceof RegExp&&self.action.match(t.name);if(n||t.name===self.action){e.push(t)}});return e};t.prototype.router=function(){return t.Router()};t.Router=function(){var e=new t(/\//gi);e.get=function(t,n){var r=[];var i=new this._routeRegExp(t,r);e.add(i,function(t,i,s){var o={params:{},keys:r,matches:s.regex.slice(1)};e._forEach(o.matches,function(e,t){var n=r[t]&&r[t].name?r[t].name:t;o.params[n]=e?decodeURIComponent(e):undefined});n.call(e,o,s)});return e};return e._trigger("initialized")};if("function"===typeof e.define){e.define(function(e){return t})}else if("object"===typeof exports){exports.Grapnel=t}else{e.Grapnel=t}}).call({},window)
<commit_msg>Minified source<commit_after>/****
 * Grapnel.js
 * https://github.com/gregsabia/Grapnel.js
 *
 * @author Greg Sabia Tucker
 * @link http://gregsabia.com
 * @version 0.3.1
 *
 * Released under MIT License. See LICENSE.txt or http://opensource.org/licenses/MIT
*/

(function(e){function t(e){"use strict";var t=this;this._actions=[];this._events=[];this.action=null;this.hook=e||":";this.value=null;this.params=[];this.anchor={defaultHash:window.location.hash};this.state=null;this.version="0.3.1";this.add=function(e,n){var r=function(){var r=t.action&&e instanceof RegExp?t.anchor.get().match(e):false;if(r||e===t.action||t.anchor.get()==e){var i={name:e,value:t.anchor.get(),handler:n,params:t.params,regex:r,previousState:t.state};t._trigger("change",i);t._actions.push({name:e,handler:n});t.state=i;n.call(t,t.value,t.params,i)}return t};return r().on(["initialized","hashchange"],r)};this._trigger=function(e){var n=Array.prototype.slice.call(arguments,1);t._forEach(t._events,function(r){if(r.event==e)r.handler.apply(t,n)});return t};this._map=function(e,t){if(typeof Array.prototype.map==="function")return Array.prototype.map.call(e,t);return function(e,t){var n=new Array(this.length);for(var r=0,i=this.length;r<i;r++){if(r in this)n[r]=e.call(t,this[r],r,this)}return n}.call(e,t)};this._forEach=function(e,t){if(typeof Array.prototype.forEach==="function")return Array.prototype.forEach.call(e,t);return function(e,t){for(var n=0,r=this.length;n<r;++n){e.call(t,this[n],n,this)}}.call(e,t)};this._routeRegExp=function(e,t,n,r){if(e instanceof RegExp)return e;if(e instanceof Array)e="("+e.join("|")+")";e=e.concat(r?"":"/?").replace(/\/\(/g,"(?:/").replace(/\+/g,"__plus__").replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?/g,function(e,n,r,i,s,o){t.push({name:i,optional:!!o});n=n||"";return""+(o?"":n)+"(?:"+(o?n:"")+(r||"")+(s||r&&"([^/.]+?)"||"([^/]+?)")+")"+(o||"")}).replace(/([\/.])/g,"\\$1").replace(/__plus__/g,"(.+)").replace(/\*/g,"(.*)");return new RegExp("^"+e+"$",n?"":"i")};this.anchor.get=function(){return window.location.hash?window.location.hash.split("#")[1]:""};this.anchor.set=function(e){window.location.hash=!e?"":e;return t};this.anchor.clear=function(){return this.set(false)};this.on(["initialized","hashchange"],function(){var e=this.parse();this.action=e.action;this.value=e.value;this.params=e.params;this._actions=[]});if(typeof window.onhashchange==="function")this.on("hashchange",window.onhashchange);window.onhashchange=function(){t._trigger("hashchange")};return this._trigger("initialized")}t.prototype.on=t.prototype.bind=function(e,t){var n=typeof e==="string"?e.split():e,r=this;this._forEach(n,function(e){r._events.push({event:e,handler:t})});return this};t.prototype.parse=function(){var e=this.anchor.get(),t=e.split(this.hook),n=e.match(this.hook),r=t[0],i=[],s;if(this.anchor.get().match(this.hook)){i=t.slice(1);s=i.join(n[0])}var o={pieces:t};this._trigger("parse",o);return{value:s,action:r,params:i}};t.prototype.matches=function(){var e=[],t=this;this._forEach(this._actions,function(n){var r=n.name instanceof RegExp&&t.action.match(n.name);if(r||n.name===t.action){e.push(n)}});return e};t.prototype.router=function(){return t.Router()};t.Router=function(){var e=new t(/\//gi);e.get=function(t,n){var r=[];var i=new this._routeRegExp(t,r);e.add(i,function(t,i,s){var o={params:{},keys:r,matches:s.regex.slice(1)};e._forEach(o.matches,function(e,t){var n=r[t]&&r[t].name?r[t].name:t;o.params[n]=e?decodeURIComponent(e):undefined});n.call(e,o,s)});return e};return e._trigger("initialized")};if("function"===typeof e.define){e.define(function(e){return t})}else if("object"===typeof exports){exports.Grapnel=t}else{e.Grapnel=t}}).call({},window)
<|endoftext|>