<commit_before>'use strict';

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

const Exchange = require ('./base/Exchange');
const { ExchangeError, AuthenticationError, InsufficientFunds } = require ('./base/errors');

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

module.exports = class bcex extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'bcex',
            'name': 'BCEX',
            'countries': [ 'CN', 'CA' ],
            'version': '1',
            'has': {
                'fetchBalance': true,
                'fetchMarkets': true,
                'createOrder': true,
                'cancelOrder': true,
                'fetchTicker': true,
                'fetchTickers': false,
                'fetchTrades': true,
                'fetchOrder': true,
                'fetchOrders': true,
                'fetchOpenOrders': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/43362240-21c26622-92ee-11e8-9464-5801ec526d77.jpg',
                'api': 'https://www.bcex.top',
                'www': 'https://www.bcex.top',
                'doc': 'https://www.bcex.top/api_market/market/',
                'fees': 'http://bcex.udesk.cn/hc/articles/57085',
                'referral': 'https://www.bcex.top/user/reg/type/2/pid/758978',
            },
            'api': {
                'public': {
                    'get': [
                        'Api_Market/getPriceList', // tickers
                        'Api_Order/ticker', // last ohlcv candle (ticker)
                        'Api_Order/depth', // orderbook
                        'Api_Market/getCoinTrade', // ticker
                        'Api_Order/marketOrder', // trades...
                    ],
                    'post': [
                        'Api_Market/getPriceList', // tickers
                        'Api_Order/ticker', // last ohlcv candle (ticker)
                        'Api_Order/depth', // orderbook
                        'Api_Market/getCoinTrade', // ticker
                        'Api_Order/marketOrder', // trades...
                    ],
                },
                'private': {
                    'post': [
                        'Api_Order/cancel',
                        'Api_Order/coinTrust', // limit order
                        'Api_Order/orderList', // open / all orders (my trades?)
                        'Api_Order/orderInfo',
                        'Api_Order/tradeList', // open / all orders
                        'Api_Order/trustList', // ?
                        'Api_User/userBalance',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'tierBased': false,
                    'percentage': true,
                    'maker': 0.0,
                    'taker': 0.2 / 100,
                },
                'funding': {
                    'tierBased': false,
                    'percentage': false,
                    'withdraw': {
                        'ckusd': 0.0,
                        'other': 0.05 / 100,
                    },
                    'deposit': {},
                },
            },
            'exceptions': {
                '该币不存在,非法操作': ExchangeError, // { code: 1, msg: "该币不存在,非法操作" } - returned when a required symbol parameter is missing in the request (also, maybe on other types of errors as well)
                '公钥不合法': AuthenticationError, // { code: 1, msg: '公钥不合法' } - wrong public key
                '您的可用余额不足': InsufficientFunds, // { code: 1, msg: '您的可用余额不足' } - your available balance is insufficient
            },
        });
    }

    async fetchMarkets () {
        let response = await this.publicGetApiMarketGetPriceList ();
        let result = [];
        let keys = Object.keys (response);
        for (let i = 0; i < keys.length; i++) {
            let currentMarketId = keys[i];
            let currentMarkets = response[currentMarketId];
            for (let j = 0; j < currentMarkets.length; j++) {
                let market = currentMarkets[j];
                let baseId = market['coin_from'];
                let quoteId = market['coin_to'];
                let base = baseId.toUpperCase ();
                let quote = quoteId.toUpperCase ();
                base = this.commonCurrencyCode (base);
                quote = this.commonCurrencyCode (quote);
                let id = baseId + '2' + quoteId;
                let symbol = base + '/' + quote;
                let active = true;
                let precision = {
                    'amount': 8, // todo: Look for a way to find a value.
                    'price': self.precisionFromString (market['current']), // todo: Look for a better way. For the moment, get number of decimals from last price
                };
                let limits = {
                    'amount': {
                        'min': undefined, // todo
                        'max': undefined,
                    },
                    'price': {
                        'min': undefined, // todo
                        'max': undefined,
                    },
                    'cost': {
                        'min': undefined, // todo
                        'max': undefined,
                    },
                };
                result.push ({
                    'id': id,
                    'symbol': symbol,
                    'base': base,
                    'quote': quote,
                    'baseId': baseId,
                    'quoteId': quoteId,
                    'active': active,
                    'precision': precision,
                    'limits': limits,
                    'info': market,
                });
            }
        }
        return result;
    }

    parseTrade (trade, market = undefined) {
        let symbol = undefined;
        if (typeof market !== 'undefined') {
            symbol = market['symbol'];
        }
        let timestamp = this.safeInteger2 (trade, 'date', 'created');
        if (typeof timestamp !== 'undefined') {
            timestamp = timestamp * 1000;
        }
        let id = this.safeString (trade, 'tid');
        let orderId = this.safeString (trade, 'order_id');
        let amount = this.safeFloat2 (trade, 'number', 'amount');
        let price = this.safeFloat (trade, 'price');
        let cost = undefined;
        if (typeof price !== 'undefined') {
            if (typeof amount !== 'undefined') {
                cost = amount * price;
            }
        }
        let side = this.safeString (trade, 'type');
        return {
            'info': trade,
            'id': id,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'type': undefined,
            'side': side,
            'price': price,
            'amount': amount,
            'cost': cost,
            'order': orderId,
            'fee': undefined,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'symbol': this.marketId (symbol),
        };
        if (typeof limit !== 'undefined') {
            request['limit'] = limit;
        }
        let market = this.market (symbol);
        let response = await this.publicPostApiOrderMarketOrder (this.extend (request, params));
        return this.parseTrades (response['data'], market, since, limit);
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let response = await this.privatePostApiUserUserBalance (params);
        let data = response['data'];
        let keys = Object.keys (data);
        let result = { };
        for (let i = 0; i < keys.length; i++) {
            let key = keys[i];
            let amount = this.safeFloat (data, key);
            let parts = key.split ('_');
            let currencyId = parts[0];
            let lockOrOver = parts[1];
            let code = currencyId.toUpperCase ();
            if (currencyId in this.currencies_by_id) {
                code = this.currencies_by_id[currencyId]['code'];
            } else {
                code = this.commonCurrencyCode (code);
            }
            if (!(code in result)) {
                let account = this.account ();
                result[code] = account;
            }
            if (lockOrOver === 'lock') {
                result[code]['used'] = parseFloat (amount);
            } else {
                result[code]['free'] = parseFloat (amount);
            }
        }
        keys = Object.keys (result);
        for (let i = 0; i < keys.length; i++) {
            let key = keys[i];
            let total = this.sum (result[key]['used'], result[key]['total']);
            result[key]['total'] = total;
        }
        result['info'] = data;
        return this.parseBalance (result);
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.markets[symbol];
        let request = {
            'part': market['quoteId'],
            'coin': market['baseId'],
        };
        let response = await this.publicPostApiMarketGetCoinTrade (this.extend (request, params));
        let timestamp = this.milliseconds ();
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (response, 'max'),
            'low': this.safeFloat (response, 'min'),
            'bid': this.safeFloat (response, 'buy'),
            'bidVolume': undefined,
            'ask': this.safeFloat (response, 'sale'),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': this.safeFloat (response, 'price'),
            'last': this.safeFloat (response, 'price'),
            'previousClose': undefined,
            'change': undefined,
            'percentage': this.safeFloat (response, 'change_24h'),
            'average': undefined,
            'baseVolume': this.safeFloat (response, 'volume_24h'),
            'quoteVolume': undefined,
            'info': response,
        };
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let marketId = this.marketId (symbol);
        let request = {
            'symbol': marketId,
        };
        let response = await this.publicPostApiOrderDepth (this.extend (request, params));
        let data = response['data'];
        let orderbook = this.parseOrderBook (data, data['date'] * 1000);
        return orderbook;
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'symbol': market['id'],
        };
        let response = await this.privatePostApiOrderOrderList (this.extend (request, params));
        return this.parseTrades (response['data'], market, since, limit);
    }

    parseOrderStatus (status) {
        let statuses = {
            '0': 'open',
            '1': 'open', // partially filled
            '2': 'closed',
            '3': 'canceled',
        };
        if (status in statuses) {
            return statuses[status];
        }
        return status;
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'symbol': this.marketId (symbol),
            'trust_id': id,
        };
        let response = await this.privatePostApiOrderOrderInfo (this.extend (request, params));
        let order = response['data'];
        let timestamp = order['created'] * 1000;
        let status = this.parseOrderStatus (order['status']);
        let result = {
            'info': order,
            'id': id,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'lastTradeTimestamp': undefined,
            'symbol': symbol,
            'type': order['flag'],
            'side': undefined,
            'price': order['price'],
            'cost': undefined,
            'average': undefined,
            'amount': order['number'],
            'filled': order['numberdeal'],
            'remaining': order['numberover'],
            'status': status,
            'fee': undefined,
        };
        return result;
    }

    parseOrder (order, market = undefined) {
        let id = this.safeString (order, 'id');
        let timestamp = order['datetime'] * 1000;
        let iso8601 = this.iso8601 (timestamp);
        let symbol = market['symbol'];
        let type = undefined;
        let side = order['type'];
        let price = order['price'];
        let average = order['avg_price'];
        let amount = order['amount'];
        let remaining = order['amount_outstanding'];
        let filled = amount - remaining;
        let status = this.safeString (order, 'status');
        status = this.parseOrderStatus (status);
        let cost = filled * price;
        let fee = undefined;
        let result = {
            'info': order,
            'id': id,
            'timestamp': timestamp,
            'datetime': iso8601,
            'lastTradeTimestamp': undefined,
            'symbol': symbol,
            'type': type,
            'side': side,
            'price': price,
            'cost': cost,
            'average': average,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'status': status,
            'fee': fee,
        };
        return result;
    }

    async fetchOrdersByType (type, symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'type': type,
        };
        let market = undefined;
        if (typeof symbol !== 'undefined') {
            market = this.market (symbol);
            request['symbol'] = market['id'];
        }
        let response = await this.privatePostApiOrderTradeList (this.extend (request, params));
        if ('data' in response) {
            return this.parseOrders (response['data'], market, since, limit);
        }
        return [];
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrdersByType ('open', symbol, since, limit, params);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrdersByType ('all', symbol, since, limit, params);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let order = {
            'symbol': this.marketId (symbol),
            'type': side,
            'price': self.priceToPrecision (symbol, price),
            'number': self.amountToPrecision (symbol, amount),
        };
        let response = await this.privatePostApiOrderCoinTrust (this.extend (order, params));
        let data = response['data'];
        return {
            'info': response,
            'id': this.safeString (data, 'order_id'),
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {};
        if (typeof symbol !== 'undefined') {
            request['symbol'] = this.marketId (symbol);
        }
        if (typeof id !== 'undefined') {
            request['order_id'] = id;
        }
        let response = await this.privatePostApiOrderCancel (this.extend (request, params));
        return response;
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'] + '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        if (api === 'public') {
            if (Object.keys (query).length) {
                url += '?' + this.urlencode (query);
            }
        } else {
            this.checkRequiredCredentials ();
            let payload = this.urlencode ({ 'api_key': this.apiKey });
            if (Object.keys (query).length) {
                payload += '&' + this.urlencode (this.keysort (query));
            }
            let auth = payload + '&secret_key=' + this.secret;
            let signature = this.hash (this.encode (auth));
            body = payload + '&sign=' + signature;
            headers = {
                'Content-Type': 'application/x-www-form-urlencoded',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (code, reason, url, method, headers, body) {
        if (typeof body !== 'string')
            return; // fallback to default error handler
        if (body.length < 2)
            return; // fallback to default error handler
        if ((body[0] === '{') || (body[0] === '[')) {
            let response = JSON.parse (body);
            let feedback = this.id + ' ' + body;
            let code = this.safeValue (response, 'code');
            if (typeof code !== 'undefined') {
                if (code !== 0) {
                    //
                    // { code: 1, msg: "该币不存在,非法操作" } - returned when a required symbol parameter is missing in the request (also, maybe on other types of errors as well)
                    // { code: 1, msg: '公钥不合法' } - wrong public key
                    //
                    let message = this.safeString (response, 'msg');
                    let exceptions = this.exceptions;
                    if (message in exceptions) {
                        throw new exceptions[message] (feedback);
                    } else {
                        throw new ExchangeError (feedback);
                    }
                }
            }
        }
    }
};
<commit_msg>'this', not 'self'<commit_after>'use strict';

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

const Exchange = require ('./base/Exchange');
const { ExchangeError, AuthenticationError, InsufficientFunds } = require ('./base/errors');

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

module.exports = class bcex extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'bcex',
            'name': 'BCEX',
            'countries': [ 'CN', 'CA' ],
            'version': '1',
            'has': {
                'fetchBalance': true,
                'fetchMarkets': true,
                'createOrder': true,
                'cancelOrder': true,
                'fetchTicker': true,
                'fetchTickers': false,
                'fetchTrades': true,
                'fetchOrder': true,
                'fetchOrders': true,
                'fetchOpenOrders': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/43362240-21c26622-92ee-11e8-9464-5801ec526d77.jpg',
                'api': 'https://www.bcex.top',
                'www': 'https://www.bcex.top',
                'doc': 'https://www.bcex.top/api_market/market/',
                'fees': 'http://bcex.udesk.cn/hc/articles/57085',
                'referral': 'https://www.bcex.top/user/reg/type/2/pid/758978',
            },
            'api': {
                'public': {
                    'get': [
                        'Api_Market/getPriceList', // tickers
                        'Api_Order/ticker', // last ohlcv candle (ticker)
                        'Api_Order/depth', // orderbook
                        'Api_Market/getCoinTrade', // ticker
                        'Api_Order/marketOrder', // trades...
                    ],
                    'post': [
                        'Api_Market/getPriceList', // tickers
                        'Api_Order/ticker', // last ohlcv candle (ticker)
                        'Api_Order/depth', // orderbook
                        'Api_Market/getCoinTrade', // ticker
                        'Api_Order/marketOrder', // trades...
                    ],
                },
                'private': {
                    'post': [
                        'Api_Order/cancel',
                        'Api_Order/coinTrust', // limit order
                        'Api_Order/orderList', // open / all orders (my trades?)
                        'Api_Order/orderInfo',
                        'Api_Order/tradeList', // open / all orders
                        'Api_Order/trustList', // ?
                        'Api_User/userBalance',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'tierBased': false,
                    'percentage': true,
                    'maker': 0.0,
                    'taker': 0.2 / 100,
                },
                'funding': {
                    'tierBased': false,
                    'percentage': false,
                    'withdraw': {
                        'ckusd': 0.0,
                        'other': 0.05 / 100,
                    },
                    'deposit': {},
                },
            },
            'exceptions': {
                '该币不存在,非法操作': ExchangeError, // { code: 1, msg: "该币不存在,非法操作" } - returned when a required symbol parameter is missing in the request (also, maybe on other types of errors as well)
                '公钥不合法': AuthenticationError, // { code: 1, msg: '公钥不合法' } - wrong public key
                '您的可用余额不足': InsufficientFunds, // { code: 1, msg: '您的可用余额不足' } - your available balance is insufficient
            },
        });
    }

    async fetchMarkets () {
        let response = await this.publicGetApiMarketGetPriceList ();
        let result = [];
        let keys = Object.keys (response);
        for (let i = 0; i < keys.length; i++) {
            let currentMarketId = keys[i];
            let currentMarkets = response[currentMarketId];
            for (let j = 0; j < currentMarkets.length; j++) {
                let market = currentMarkets[j];
                let baseId = market['coin_from'];
                let quoteId = market['coin_to'];
                let base = baseId.toUpperCase ();
                let quote = quoteId.toUpperCase ();
                base = this.commonCurrencyCode (base);
                quote = this.commonCurrencyCode (quote);
                let id = baseId + '2' + quoteId;
                let symbol = base + '/' + quote;
                let active = true;
                let precision = {
                    'amount': 8, // todo: Look for a way to find a value.
                    'price': this.precisionFromString (market['current']), // todo: Look for a better way. For the moment, get number of decimals from last price
                };
                let limits = {
                    'amount': {
                        'min': undefined, // todo
                        'max': undefined,
                    },
                    'price': {
                        'min': undefined, // todo
                        'max': undefined,
                    },
                    'cost': {
                        'min': undefined, // todo
                        'max': undefined,
                    },
                };
                result.push ({
                    'id': id,
                    'symbol': symbol,
                    'base': base,
                    'quote': quote,
                    'baseId': baseId,
                    'quoteId': quoteId,
                    'active': active,
                    'precision': precision,
                    'limits': limits,
                    'info': market,
                });
            }
        }
        return result;
    }

    parseTrade (trade, market = undefined) {
        let symbol = undefined;
        if (typeof market !== 'undefined') {
            symbol = market['symbol'];
        }
        let timestamp = this.safeInteger2 (trade, 'date', 'created');
        if (typeof timestamp !== 'undefined') {
            timestamp = timestamp * 1000;
        }
        let id = this.safeString (trade, 'tid');
        let orderId = this.safeString (trade, 'order_id');
        let amount = this.safeFloat2 (trade, 'number', 'amount');
        let price = this.safeFloat (trade, 'price');
        let cost = undefined;
        if (typeof price !== 'undefined') {
            if (typeof amount !== 'undefined') {
                cost = amount * price;
            }
        }
        let side = this.safeString (trade, 'type');
        return {
            'info': trade,
            'id': id,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'type': undefined,
            'side': side,
            'price': price,
            'amount': amount,
            'cost': cost,
            'order': orderId,
            'fee': undefined,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'symbol': this.marketId (symbol),
        };
        if (typeof limit !== 'undefined') {
            request['limit'] = limit;
        }
        let market = this.market (symbol);
        let response = await this.publicPostApiOrderMarketOrder (this.extend (request, params));
        return this.parseTrades (response['data'], market, since, limit);
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let response = await this.privatePostApiUserUserBalance (params);
        let data = response['data'];
        let keys = Object.keys (data);
        let result = { };
        for (let i = 0; i < keys.length; i++) {
            let key = keys[i];
            let amount = this.safeFloat (data, key);
            let parts = key.split ('_');
            let currencyId = parts[0];
            let lockOrOver = parts[1];
            let code = currencyId.toUpperCase ();
            if (currencyId in this.currencies_by_id) {
                code = this.currencies_by_id[currencyId]['code'];
            } else {
                code = this.commonCurrencyCode (code);
            }
            if (!(code in result)) {
                let account = this.account ();
                result[code] = account;
            }
            if (lockOrOver === 'lock') {
                result[code]['used'] = parseFloat (amount);
            } else {
                result[code]['free'] = parseFloat (amount);
            }
        }
        keys = Object.keys (result);
        for (let i = 0; i < keys.length; i++) {
            let key = keys[i];
            let total = this.sum (result[key]['used'], result[key]['total']);
            result[key]['total'] = total;
        }
        result['info'] = data;
        return this.parseBalance (result);
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.markets[symbol];
        let request = {
            'part': market['quoteId'],
            'coin': market['baseId'],
        };
        let response = await this.publicPostApiMarketGetCoinTrade (this.extend (request, params));
        let timestamp = this.milliseconds ();
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (response, 'max'),
            'low': this.safeFloat (response, 'min'),
            'bid': this.safeFloat (response, 'buy'),
            'bidVolume': undefined,
            'ask': this.safeFloat (response, 'sale'),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': this.safeFloat (response, 'price'),
            'last': this.safeFloat (response, 'price'),
            'previousClose': undefined,
            'change': undefined,
            'percentage': this.safeFloat (response, 'change_24h'),
            'average': undefined,
            'baseVolume': this.safeFloat (response, 'volume_24h'),
            'quoteVolume': undefined,
            'info': response,
        };
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let marketId = this.marketId (symbol);
        let request = {
            'symbol': marketId,
        };
        let response = await this.publicPostApiOrderDepth (this.extend (request, params));
        let data = response['data'];
        let orderbook = this.parseOrderBook (data, data['date'] * 1000);
        return orderbook;
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'symbol': market['id'],
        };
        let response = await this.privatePostApiOrderOrderList (this.extend (request, params));
        return this.parseTrades (response['data'], market, since, limit);
    }

    parseOrderStatus (status) {
        let statuses = {
            '0': 'open',
            '1': 'open', // partially filled
            '2': 'closed',
            '3': 'canceled',
        };
        if (status in statuses) {
            return statuses[status];
        }
        return status;
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'symbol': this.marketId (symbol),
            'trust_id': id,
        };
        let response = await this.privatePostApiOrderOrderInfo (this.extend (request, params));
        let order = response['data'];
        let timestamp = order['created'] * 1000;
        let status = this.parseOrderStatus (order['status']);
        let result = {
            'info': order,
            'id': id,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'lastTradeTimestamp': undefined,
            'symbol': symbol,
            'type': order['flag'],
            'side': undefined,
            'price': order['price'],
            'cost': undefined,
            'average': undefined,
            'amount': order['number'],
            'filled': order['numberdeal'],
            'remaining': order['numberover'],
            'status': status,
            'fee': undefined,
        };
        return result;
    }

    parseOrder (order, market = undefined) {
        let id = this.safeString (order, 'id');
        let timestamp = order['datetime'] * 1000;
        let iso8601 = this.iso8601 (timestamp);
        let symbol = market['symbol'];
        let type = undefined;
        let side = order['type'];
        let price = order['price'];
        let average = order['avg_price'];
        let amount = order['amount'];
        let remaining = order['amount_outstanding'];
        let filled = amount - remaining;
        let status = this.safeString (order, 'status');
        status = this.parseOrderStatus (status);
        let cost = filled * price;
        let fee = undefined;
        let result = {
            'info': order,
            'id': id,
            'timestamp': timestamp,
            'datetime': iso8601,
            'lastTradeTimestamp': undefined,
            'symbol': symbol,
            'type': type,
            'side': side,
            'price': price,
            'cost': cost,
            'average': average,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'status': status,
            'fee': fee,
        };
        return result;
    }

    async fetchOrdersByType (type, symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'type': type,
        };
        let market = undefined;
        if (typeof symbol !== 'undefined') {
            market = this.market (symbol);
            request['symbol'] = market['id'];
        }
        let response = await this.privatePostApiOrderTradeList (this.extend (request, params));
        if ('data' in response) {
            return this.parseOrders (response['data'], market, since, limit);
        }
        return [];
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrdersByType ('open', symbol, since, limit, params);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrdersByType ('all', symbol, since, limit, params);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let order = {
            'symbol': this.marketId (symbol),
            'type': side,
            'price': self.priceToPrecision (symbol, price),
            'number': self.amountToPrecision (symbol, amount),
        };
        let response = await this.privatePostApiOrderCoinTrust (this.extend (order, params));
        let data = response['data'];
        return {
            'info': response,
            'id': this.safeString (data, 'order_id'),
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {};
        if (typeof symbol !== 'undefined') {
            request['symbol'] = this.marketId (symbol);
        }
        if (typeof id !== 'undefined') {
            request['order_id'] = id;
        }
        let response = await this.privatePostApiOrderCancel (this.extend (request, params));
        return response;
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'] + '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        if (api === 'public') {
            if (Object.keys (query).length) {
                url += '?' + this.urlencode (query);
            }
        } else {
            this.checkRequiredCredentials ();
            let payload = this.urlencode ({ 'api_key': this.apiKey });
            if (Object.keys (query).length) {
                payload += '&' + this.urlencode (this.keysort (query));
            }
            let auth = payload + '&secret_key=' + this.secret;
            let signature = this.hash (this.encode (auth));
            body = payload + '&sign=' + signature;
            headers = {
                'Content-Type': 'application/x-www-form-urlencoded',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (code, reason, url, method, headers, body) {
        if (typeof body !== 'string')
            return; // fallback to default error handler
        if (body.length < 2)
            return; // fallback to default error handler
        if ((body[0] === '{') || (body[0] === '[')) {
            let response = JSON.parse (body);
            let feedback = this.id + ' ' + body;
            let code = this.safeValue (response, 'code');
            if (typeof code !== 'undefined') {
                if (code !== 0) {
                    //
                    // { code: 1, msg: "该币不存在,非法操作" } - returned when a required symbol parameter is missing in the request (also, maybe on other types of errors as well)
                    // { code: 1, msg: '公钥不合法' } - wrong public key
                    //
                    let message = this.safeString (response, 'msg');
                    let exceptions = this.exceptions;
                    if (message in exceptions) {
                        throw new exceptions[message] (feedback);
                    } else {
                        throw new ExchangeError (feedback);
                    }
                }
            }
        }
    }
};
<|endoftext|>


<commit_before>/** @ignore */
const https = require('https');
const Discord = require('discord.js');
const config = require('../config/config.json');
const twitchClass = require('../classes/twitch.js');

const twitch = new twitchClass(config.CLIENTID);
exports.run = async (client, msg, args) => {
    if (!args[0]) {
        return msg.channel.send('Please give a valid argument.');
    }
    let arg = args[0].toLowerCase();
    if (arg === 'register') {

      /**
      * Checking for a channel in the message content (twitch)
      */
      if (!args[1]) return msg.reply('Please type a name of a twitch channel');

      try {
        // Register a new channel (Get data)
        let status = await twitch.register(args[1]);

        /**
        * Check if the response status aint 404
        * Else, return invalid twitch channel
        */
        if (status.body.status !== 404) {
          let ifRowExists = await r.table("livestreams").getAll(msg.guild.id, {index : "guildID"}).run()

          //If a row does not exists create one.
          if (!ifRowExists[0]) {
            await r.table("livestreams").insert({
              guildID: msg.guild.id,
              streams: false,
              channelID: null,
              livestreams: []
            }).run();

            // Success message
            return msg.channel.send('I\'ve inserted you to the database please do the command again.');
          }

          // check if the guild is already inside the DB
          if (!ifRowExists[0] || !ifRowExists[0].streams) {
            return msg.channel.send('You have stream announcements turned off. Turn them on to add streamers. use `-twitch enable #textChannel`');
          }

          let streams = ifRowExists[0].livestreams

          // Check if the channel was already inserted
          if (streams.filter(o => o.name === args[1])[0]) {
            return msg.channel.send('This channel was already inserted!');
          }

          /**
          * Push the new streamer right into the array.
          * @param {String} table - The table name
          * @param {String} uArray - The name of the array to update
          * @param {Object} doc - The updated object to insert
          */
          let appendToArray = (table, uArray, doc) => r.table(table)
          .getAll(msg.guild.id, {index: "guildID"})
          .update(object => ({ [uArray]: object(uArray)
          .default([]).append(doc) }))
          .run();
          appendToArray('livestreams', 'livestreams', {
              game: null,
              views: null,
              image: null,
              mature: null,
              lang: null,
              name: args[1],
              url: null,
              online: false,
              msgID: null
          });

          // Success message.
         msg.channel.send(`I've added the streamer **${args[1]}** to the list`);

        } else {

          // Else send an error message.
          return msg.reply('We could not find that channel when quering.');

        }

      } catch (e) {

        // Catch any error.
        logger.debug(e);
        return msg.reply('We could not find that channel when quering.');

      }
    }

    if (arg === 'enable') {

      // Check if a text channel is being mentioned.
      if (!args || !msg.mentions.channels.first()) {
        return msg.reply('Please be sure to mention the text channel, `-twitch enable #channelOfChoice`');
      }

      // If any error's happening in the process handle it.
      try {

        // Filter the row
        let checkIfExists = await r.table("livestreams").getAll(msg.guild.id, {index: "guildID"}).run();

        // if does not exists create a document AKA row.
        if (!checkIfExists[0]) {
          await r.table("livestreams").insert({
            guildID: msg.guild.id,
            streams: false,
            channelID: null,
            livestreams: []
          }).run();

          // Success message
          return msg.channel.send('I\'ve inserted you to the database please do the command again.');
        }

        // Check if a channel is already exists in the database and update if so.
        if (checkIfExists[0].streams === true) {

          // Update the databse to the new channel
          await r.table('livestreams').getAll(msg.guild.id, {index: "guildID"}).update({channelID: msg.mentions.channels.first().id}).run();
          await msg.channel.send('You already enabled the stream announcements, I\'ve updated the channel for you :)')

        } else {

          // Else, Insert rows into the database and in Queue.
          await r.table('livestreams').getAll(msg.guild.id, {index: "guildID"})
          .update({streams : true, channelID: msg.mentions.channels.first().id})
          .run();

          /**
          * Push the new info right into the array which will be used to loop through.
          * @param {String} table - The table name
          * @param {String} uArray - The name of the array to update
          * @param {Object} doc - The updated object to insert
          */

          let appendToArray = (table, uArray, doc) => r.table(table)  // choose the table
          .getAll("NONE", {index: "guildID"}) //Filter with your custom choice
          .update(object => ({ [uArray]: object(uArray) // Get the array name
          .default([]).append(doc) })) // append the array and update
          .run();

          // call the function
          appendToArray('livestreams', 'inQueue', {guildID : msg.guild.id})

        }

      } catch (e) {
        logger.error(e)
      }
    }

    if (arg === 'disable') {

      let exists = await r.table('livestreams').getAll(msg.guild.id, {index : "guildID"}).run();

      // check if the guild has a document
      // Check if streams is already off.
      if (exists[0].streams === 'false' || !exists[0]) {
        return msg.reply('Streams already turned off!')
      }

    }
};

exports.help = {
    category: 'util',
    usage: '[register/enable/remove/disable] [stream:only needed with register & remove/channel:Used for enable]',
    description: 'Enabled and add Twitch streams',
    detail: 'Enable: Add the channel where you want to receive stream announcements | Register: Add a new channel to the announcements | Remove: Remove a channel from announcements | Disable: Disable the function (default)',
    botPerm: ['SEND_MESSAGES', 'EMBED_LINKS'],
    authorPerm: ["ADMINISTRATOR"],
    alias: [
        null
    ]
};
<commit_msg>Wrote disable and list sub-commands<commit_after>/** @ignore */
const https = require('https');
const Discord = require('discord.js');
const config = require('../config/config.json');
const twitchClass = require('../classes/twitch.js');

const twitch = new twitchClass(config.CLIENTID);
exports.run = async (client, msg, args) => {
    if (!args[0]) {
        return msg.channel.send('Please give a valid argument.');
    }
    let arg = args[0].toLowerCase();
    if (arg === 'register') {

      /**
      * Checking for a channel in the message content (twitch)
      */
      if (!args[1]) return msg.reply('Please type a name of a twitch channel');

      try {
        // Register a new channel (Get data)
        let status = await twitch.register(args[1]);

        /**
        * Check if the response status aint 404
        * Else, return invalid twitch channel
        */
        if (status.body.status !== 404) {
          let ifRowExists = await r.table("livestreams").getAll(msg.guild.id, {index : "guildID"}).run()

          //If a row does not exists create one.
          if (!ifRowExists[0]) {
            await r.table("livestreams").insert({
              guildID: msg.guild.id,
              streams: false,
              channelID: null,
              livestreams: []
            }).run();

            // Success message
            return msg.channel.send('I\'ve inserted you to the database please do the command again.');
          }

          // check if the guild is already inside the DB
          if (!ifRowExists[0] || !ifRowExists[0].streams) {
            return msg.channel.send('You have stream announcements turned off. Turn them on to add streamers. use `-twitch enable #textChannel`');
          }

          let streams = ifRowExists[0].livestreams

          // Check if the channel was already inserted
          if (streams.filter(o => o.name === args[1])[0]) {
            return msg.channel.send('This channel was already inserted!');
          }

          /**
          * Push the new streamer right into the array.
          * @param {String} table - The table name
          * @param {String} uArray - The name of the array to update
          * @param {Object} doc - The updated object to insert
          */
          let appendToArray = (table, uArray, doc) => r.table(table)
          .getAll(msg.guild.id, {index: "guildID"})
          .update(object => ({ [uArray]: object(uArray)
          .default([]).append(doc) }))
          .run();
          appendToArray('livestreams', 'livestreams', {
              game: null,
              views: null,
              image: null,
              mature: null,
              lang: null,
              name: args[1],
              url: null,
              online: false,
              msgID: null
          });

          // Success message.
         msg.channel.send(`I've added the streamer **${args[1]}** to the list`);

        } else {

          // Else send an error message.
          return msg.reply('We could not find that channel when quering.');

        }

      } catch (e) {

        // Catch any error.
        logger.debug(e);
        return msg.reply('We could not find that channel when quering.');

      }
    }

    if (arg === 'enable') {

      // Check if a text channel is being mentioned.
      if (!args || !msg.mentions.channels.first()) {
        return msg.reply('Please be sure to mention the text channel, `-twitch enable #channelOfChoice`');
      }

      // If any error's happening in the process handle it.
      try {

        // Filter the row
        let checkIfExists = await r.table("livestreams").getAll(msg.guild.id, {index: "guildID"}).run();

        // if does not exists create a document AKA row.
        if (!checkIfExists[0]) {
          await r.table("livestreams").insert({
            guildID: msg.guild.id,
            streams: false,
            channelID: null,
            livestreams: []
          }).run();

          // Success message
          return msg.channel.send('I\'ve inserted you to the database please do the command again.');
        }

        // Check if a channel is already exists in the database and update if so.
        if (checkIfExists[0].streams === true) {

          // Update the databse to the new channel
          await r.table('livestreams').getAll(msg.guild.id, {index: "guildID"}).update({channelID: msg.mentions.channels.first().id}).run();
          await msg.channel.send('You already enabled the stream announcements, I\'ve updated the channel for you :)')

        } else {

          // Else, Insert rows into the database and in Queue.
          await r.table('livestreams').getAll(msg.guild.id, {index: "guildID"})
          .update({streams : true, channelID: msg.mentions.channels.first().id})
          .run();

          /**
          * Push the new info right into the array which will be used to loop through.
          * @param {String} table - The table name
          * @param {String} uArray - The name of the array to update
          * @param {Object} doc - The updated object to insert
          */
          let arr = await r.table("livestreams").getAll("NONE", {index : "guildID"}).run()
          if (!arr.filter(o => o.guildID === msg.guild.id)[0]) {
            let appendToArray = (table, uArray, doc) => r.table(table)  // choose the table
            .getAll("NONE", {index: "guildID"}) //Filter with your custom choice
            .update(object => ({ [uArray]: object(uArray) // Get the array name
            .default([]).append(doc) })) // append the array and update
            .run();

            // call the function
            appendToArray('livestreams', 'inQueue', {guildID : msg.guild.id})
          }

        }

      } catch (e) {
        logger.error(e)
      }
    }

    if (arg === 'disable') {

      let exists = await r.table('livestreams').getAll(msg.guild.id, {index : "guildID"}).run();

      // check if the guild has a document
      // Check if streams is already off.
      if (exists[0].streams === false || !exists[0]) {
        return msg.reply('Streams already turned off!')
      }

      // Update the database.
      await r.table('livestreams')
      .getAll(msg.guild.id, {index : "guildID"})
      .update({channelID: null, streams: false, livestreams : []})
      .run();

    }

    if (arg === 'list') {

      // Get the guild object from the database
      let list = await r.table("livestreams").getAll(msg.guild.id, {index : "guildID"}).run();

      // Check if livestreams exists for this list.
      if (!list[0] || !list[0].livestreams[0]) {
        return msg.reply('This guild does not have any streamers hooked up.');
      }

      //Loop through all of the streamers
      let c = 1;
      let strms = [];
      list[0].livestreams.forEach(oo => {
        strms.push(`${c++}). ${oo.name}`);
      });

      let textarr = [
        '```asciidoc',
        `= Streamers List For ${msg.guild.name} = `,
        `${strms.join('\n')}`,
        '```'
      ]
      //handle any error
      // Fetch the list
      try{await msg.channel.send(textarr.join('\n'))} catch(e) {logger.error(e)}

    }

};

exports.help = {
    category: 'util',
    usage: '[register/enable/remove/disable] [stream:only needed with register & remove/channel:Used for enable]',
    description: 'Enabled and add Twitch streams',
    detail: 'Enable: Add the channel where you want to receive stream announcements | Register: Add a new channel to the announcements | Remove: Remove a channel from announcements | Disable: Disable the function (default)',
    botPerm: ['SEND_MESSAGES', 'EMBED_LINKS'],
    authorPerm: ["ADMINISTRATOR"],
    alias: [
        null
    ]
};
<|endoftext|>


<commit_before>enchant();
var gbraverDebug = {};
var assert;

/**
 * テストデータ
 */
gbraverDebug.statusArray = {
    2 : {
        name : 'ランドーザ',
        pictName : 'Landozer.PNG',
        hp : 4700,
        speed : 150,
        active : 0,
        battery : 5,
        weapons : {
            1 : {
                name : 'ブレイクパンチ',
                power : 1200
            },
            2 : {
                name : 'ブレイクパンチ',
                power : 1700
            },
            3 : {
                name : 'ブレイクパンチ',
                power : 2300
            },
            4 : {
                name : 'ブレイクパンチ',
                power : 2900
            },
            5 : {
                name : 'ブレイクパンチ',
                power : 3800
            }
        }
    },
    1 : {
        name : '最強ブレイバー',
        pictName : 'GranBraver.PNG',
        hp : 3200,
        speed : 250,
        active : 0,
        battery : 5,
        weapons : {
            1 : {
                name : 'バスターナックル',
                power : 5000
            },
            2 : {
                name : 'バスターナックル',
                power : 5000
            },
            3 : {
                name : 'バスターナックル',
                power : 5000
            },
            4 : {
                name : 'バスターナックル',
                power : 5000
            },
            5 : {
                name : 'バスターナックル',
                power : 5000
            }
        }
    }
};

window.onload = function(){
    assert = chai.assert;
    firstPlayerAtack_asDefenther();
};

/**
 * 敵が攻撃を選択する
 */
function firstPlayerAtack_asDefenther(){
    var Game = game({
        userId : '1'});
    Game.start();
    Game.onload = function(){
        Game.changeBattleScene({
            statusArray : gbraverDebug.statusArray,
            userId : '1'
        });
        waitPhase();
    };

    function waitPhase(){
        var waitPhaseData = {
            phase : 'wait',
            atackUserId : '1',
            turn : 20,
            statusArray : {
                2 : {
                    hp : 4700,
                    battery : 5,
                    active : 3000
                },
                1 : {
                    hp : 3200,
                    battery : 5,
                    active : 5000
                }
            }
        };
        Game.emitServerResp('resp',waitPhaseData);
        Game.onSendMessage(function(message,data){
            //message,dataはplayerChargeTestで確認済み
            atackCommandPhase();
        });
    }

    function atackCommandPhase(){
        var atackCommandPhaseData = {
            phase : 'atackCommand',
            statusArray : {
                1 : {
                    hp : 3200,
                    battery : 5,
                    active : 5000
                },
                2 : {
                    hp : 4700,
                    battery : 5,
                    active : 3000
                }
            }
        };
        Game.emitServerResp('resp',atackCommandPhaseData);
        selectCommand();
    }

    function selectCommand(){
        touch(Game.battleScene.atackIcon);
        touch(Game.battleScene.plusIcon);
        touch(Game.battleScene.plusIcon);
        touch(Game.battleScene.okIcon);

        Game.onSendMessage(function(message,data){
            //message,dataはplayerAtackTestで確認済み
            defenthCommandPhase();
        });
    }

    function defenthCommandPhase(){
        var defenthCommandData = {
            phase : 'defenthCommand',
            statusArray : {
                1 : {
                    hp : 3200,
                    battery : 5,
                    active : 5000
                },
                2 : {
                    hp : 4700,
                    battery : 5,
                    active : 3000
                }
            }
        };
        Game.emitServerResp('resp',defenthCommandData);
        Game.onSendMessage(function(message,data){
            //message,dataはplayerAtackTestで確認済み
            damagePhase();
        });
    }

    function damagePhase(){
        var damagePhaseData = {
            phase : 'damage',
            hit : 1,
            damage : 5000,
            atackBattery : 3,
            defenthBattery : 2,
            statusArray : {
                1 : {
                    hp : 3200,
                    battery : 2,
                    active : 0
                },
                2 : {
                    hp : -300,
                    battery : 3,
                    active : 3000
                }
            }
        };
        Game.emitServerResp('resp',damagePhaseData);
        Game.onSendMessage(function(message,data){
            //message,dataはplayerAtackTestで確認済み
            gameEnd();
        });
    }

    function gameEnd(){
        var gameEndData = {
            phase : 'gameEnd',
            winner : '1',
            statusArray : {
                1 : {
                    hp : 3200,
                    battery : 2,
                    active : 0
                },
                2 : {
                    hp : -300,
                    battery : 3,
                    active : 3000
                }
            }
        };
        Game.emitServerResp('resp',gameEndData);
        Game.onSendMessage(assertOfGameEnd);
    }

    function assertOfGameEnd(message,data){
        var expectData = {
            method : 'ok'
        };
        assert.equal(message,'command','ゲーム終了時のサーバ送信メッセージが正しい');
        assert.deepEqual(data,expectData,'ゲーム終了時のサーバ送信データが正しい');
        doDissolveRoom();
    }

    function doDissolveRoom(){
        Game.onChangeScene(function(scene){
            assert.equal(scene,'top','トップ画面へ遷移する');
            console.log('finish');
            $('title').text('finish');
        });
        Game.emitServerResp('dissolveRoom',null);
    }
}<commit_msg>battleToTopTest_winの関数名がおかしかったので修正した。<commit_after>enchant();
var gbraverDebug = {};
var assert;

/**
 * テストデータ
 */
gbraverDebug.statusArray = {
    2 : {
        name : 'ランドーザ',
        pictName : 'Landozer.PNG',
        hp : 4700,
        speed : 150,
        active : 0,
        battery : 5,
        weapons : {
            1 : {
                name : 'ブレイクパンチ',
                power : 1200
            },
            2 : {
                name : 'ブレイクパンチ',
                power : 1700
            },
            3 : {
                name : 'ブレイクパンチ',
                power : 2300
            },
            4 : {
                name : 'ブレイクパンチ',
                power : 2900
            },
            5 : {
                name : 'ブレイクパンチ',
                power : 3800
            }
        }
    },
    1 : {
        name : '最強ブレイバー',
        pictName : 'GranBraver.PNG',
        hp : 3200,
        speed : 250,
        active : 0,
        battery : 5,
        weapons : {
            1 : {
                name : 'バスターナックル',
                power : 5000
            },
            2 : {
                name : 'バスターナックル',
                power : 5000
            },
            3 : {
                name : 'バスターナックル',
                power : 5000
            },
            4 : {
                name : 'バスターナックル',
                power : 5000
            },
            5 : {
                name : 'バスターナックル',
                power : 5000
            }
        }
    }
};

window.onload = function(){
    assert = chai.assert;
    battleToTop_win();
};

function battleToTop_win(){
    var Game = game({
        userId : '1'});
    Game.start();
    Game.onload = function(){
        Game.changeBattleScene({
            statusArray : gbraverDebug.statusArray,
            userId : '1'
        });
        waitPhase();
    };

    function waitPhase(){
        var waitPhaseData = {
            phase : 'wait',
            atackUserId : '1',
            turn : 20,
            statusArray : {
                2 : {
                    hp : 4700,
                    battery : 5,
                    active : 3000
                },
                1 : {
                    hp : 3200,
                    battery : 5,
                    active : 5000
                }
            }
        };
        Game.emitServerResp('resp',waitPhaseData);
        Game.onSendMessage(function(message,data){
            //message,dataはplayerChargeTestで確認済み
            atackCommandPhase();
        });
    }

    function atackCommandPhase(){
        var atackCommandPhaseData = {
            phase : 'atackCommand',
            statusArray : {
                1 : {
                    hp : 3200,
                    battery : 5,
                    active : 5000
                },
                2 : {
                    hp : 4700,
                    battery : 5,
                    active : 3000
                }
            }
        };
        Game.emitServerResp('resp',atackCommandPhaseData);
        selectCommand();
    }

    function selectCommand(){
        touch(Game.battleScene.atackIcon);
        touch(Game.battleScene.plusIcon);
        touch(Game.battleScene.plusIcon);
        touch(Game.battleScene.okIcon);

        Game.onSendMessage(function(message,data){
            //message,dataはplayerAtackTestで確認済み
            defenthCommandPhase();
        });
    }

    function defenthCommandPhase(){
        var defenthCommandData = {
            phase : 'defenthCommand',
            statusArray : {
                1 : {
                    hp : 3200,
                    battery : 5,
                    active : 5000
                },
                2 : {
                    hp : 4700,
                    battery : 5,
                    active : 3000
                }
            }
        };
        Game.emitServerResp('resp',defenthCommandData);
        Game.onSendMessage(function(message,data){
            //message,dataはplayerAtackTestで確認済み
            damagePhase();
        });
    }

    function damagePhase(){
        var damagePhaseData = {
            phase : 'damage',
            hit : 1,
            damage : 5000,
            atackBattery : 3,
            defenthBattery : 2,
            statusArray : {
                1 : {
                    hp : 3200,
                    battery : 2,
                    active : 0
                },
                2 : {
                    hp : -300,
                    battery : 3,
                    active : 3000
                }
            }
        };
        Game.emitServerResp('resp',damagePhaseData);
        Game.onSendMessage(function(message,data){
            //message,dataはplayerAtackTestで確認済み
            gameEnd();
        });
    }

    function gameEnd(){
        var gameEndData = {
            phase : 'gameEnd',
            winner : '1',
            statusArray : {
                1 : {
                    hp : 3200,
                    battery : 2,
                    active : 0
                },
                2 : {
                    hp : -300,
                    battery : 3,
                    active : 3000
                }
            }
        };
        Game.emitServerResp('resp',gameEndData);
        Game.onSendMessage(assertOfGameEnd);
    }

    function assertOfGameEnd(message,data){
        var expectData = {
            method : 'ok'
        };
        assert.equal(message,'command','ゲーム終了時のサーバ送信メッセージが正しい');
        assert.deepEqual(data,expectData,'ゲーム終了時のサーバ送信データが正しい');
        doDissolveRoom();
    }

    function doDissolveRoom(){
        Game.onChangeScene(function(scene){
            assert.equal(scene,'top','トップ画面へ遷移する');
            console.log('finish');
            $('title').text('finish');
        });
        Game.emitServerResp('dissolveRoom',null);
    }
}<|endoftext|>


<commit_before>module.exports = (ctx) => ({
    plugins: {
      'postcss-smart-import': null,
      'postcss-cssnext': null,
      'postcss-font-smoothing': null,
      'cssnano': null,
      'postcss-reporter': null,
      'postcss-browser-reporter': null
    }
})
<commit_msg>style: correct indentation<commit_after>module.exports = (ctx) => ({
  plugins: {
    'postcss-smart-import': null,
    'postcss-cssnext': null,
    'postcss-font-smoothing': null,
    'cssnano': null,
    'postcss-reporter': null,
    'postcss-browser-reporter': null
  }
})
<|endoftext|>


<commit_before>var shift = Array.prototype.shift,
    has = Object.prototype.hasOwnProperty;

function EventObject(listener, ctx) {
    this.listener = listener;
    this.ctx = ctx;
}

function EventEmitter() {

    this._events = {};
    this._maxListeners = EventEmitter.defaultMaxListeners;
}

EventEmitter.defaultMaxListeners = 10;

EventEmitter.prototype.on = function(type, listener, ctx) {
    if (typeof(listener) !== "function") throw new TypeError("EventEmitter.on(type, listener[, ctx]) listener must be a function");
    var events = this._events,
        eventList = (events[type] || (events[type] = [])),
        maxListeners = this._maxListeners;

    eventList.push(new EventObject(listener, ctx || this));

    if (maxListeners !== -1 && eventList.length > maxListeners) {
        console.error("EventEmitter.on(type, listener, ctx) possible EventEmitter memory leak detected. " + maxListeners + " listeners added");
    }

    return this;
};

EventEmitter.prototype.addListener = EventEmitter.prototype.on;

EventEmitter.prototype.once = function(type, listener, ctx) {
    var _this = this;
    ctx || (ctx = this);

    function once() {
        _this.off(type, once, ctx);
        var length = arguments.length;

        if (length === 0) {
            return listener.call(ctx);
        } else if (length === 1) {
            return listener.call(ctx, arguments[0]);
        } else if (length === 2) {
            return listener.call(ctx, arguments[0], arguments[1]);
        } else if (length === 3) {
            return listener.call(ctx, arguments[0], arguments[1], arguments[2]);
        } else if (length === 4) {
            return listener.call(ctx, arguments[0], arguments[1], arguments[2], arguments[3]);
        } else if (length === 5) {
            return listener.call(ctx, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
        }

        return listener.apply(ctx, arguments);
    }

    return this.on(type, once, ctx);
};

EventEmitter.prototype.listenTo = function(obj, type, listener, ctx) {
    if (!(has.call(obj, "on") && typeof(obj.on) === "function")) {
        throw new TypeError("EventEmitter.listenTo(obj, type, listener, ctx) obj must have a on function taking (type, listener[, ctx])");
    }

    obj.on(type, listener, ctx || this);
    return this;
};

EventEmitter.prototype.off = function(type, listener, ctx) {
    var events = this._events,
        eventList, event, i;

    if (!type) return this.removeAllListeners();

    eventList = events[type];
    if (!eventList) return this;

    if (!listener) {
        i = eventList.length;
        while (i--) {
            event = eventList[i];
            this.emit("removeListener", type, event.listener, event.ctx);
        }
        eventList.length = 0;
        delete events[type];
    } else {
        ctx = ctx || this;
        i = eventList.length;
        while (i--) {
            event = eventList[i];

            if (event.listener === listener) {
                this.emit("removeListener", type, event.listener, event.ctx);
                eventList.splice(i, 1);
            }
        }
        if (eventList.length === 0) delete events[type];
    }

    return this;
};

EventEmitter.prototype.removeListener = EventEmitter.prototype.off;

EventEmitter.prototype.removeAllListeners = function() {
    var events = this._events,
        eventList, event, i;

    for (var key in events) {
        if ((eventList = events[key])) {
            i = eventList.length;
            while (i--) {
                event = eventList[i];
                this.emit("removeListener", type, event.listener, event.ctx);
            }
            eventList.length = 0;
            delete events[key];
        }
    }

    return this;
};

EventEmitter.prototype.emit = function(type) {
    var eventList = this._events[type],
        a1, a2, a3, a4,
        length, event,
        i;

    if (!eventList || !eventList.length) return this;
    length = arguments.length;

    if (length === 1) {
        i = eventList.length;
        while (i--) {
            if ((event = eventList[i])) event.listener.call(event.ctx);
        }
    } else if (length === 2) {
        a1 = arguments[1];
        i = eventList.length;
        while (i--) {
            if ((event = eventList[i])) event.listener.call(event.ctx, a1);
        }
    } else if (length === 3) {
        a1 = arguments[1];
        a2 = arguments[2];
        i = eventList.length;
        while (i--) {
            if ((event = eventList[i])) event.listener.call(event.ctx, a1, a2);
        }
    } else if (length === 4) {
        a1 = arguments[1];
        a2 = arguments[2];
        a3 = arguments[3];
        i = eventList.length;
        while (i--) {
            if ((event = eventList[i])) event.listener.call(event.ctx, a1, a2, a3);
        }
    } else if (length === 5) {
        a1 = arguments[1];
        a2 = arguments[2];
        a3 = arguments[3];
        a4 = arguments[4];
        i = eventList.length;
        while (i--) {
            if ((event = eventList[i])) event.listener.call(event.ctx, a1, a2, a3, a4);
        }
    } else {
        shift.apply(arguments);
        i = eventList.length;
        while (i--) {
            if ((event = eventList[i])) event.listener.apply(event.ctx, arguments);
        }
    }

    return this;
};

EventEmitter.prototype.listeners = function(type) {
    if (typeof(type) !== "string") throw new TypeError("EventEmitter.listeners(type) must be a string");
    var eventList = this._events[type];

    return eventList ? eventList.length : 0;
};

EventEmitter.prototype.setMaxListeners = function(value) {
    if ((value = +value) !== value) throw new TypeError("EventEmitter.setMaxListeners(value) must be a number");

    this._maxListeners = value < 0 ? -1 : value;
    return this;
};

EventEmitter.extend = function(child, parent) {
    if (!parent) parent = this;

    child.prototype = Object.create(parent.prototype);
    child.prototype.constructor = child;
    child.prototype._super = parent.prototype;
    child.extend = parent.extend;
    child._super = parent;

    return child;
};

module.exports = EventEmitter;
<commit_msg>updates<commit_after>var shift = Array.prototype.shift,
    has = Object.prototype.hasOwnProperty;

function EventObject(listener, ctx) {
    this.listener = listener;
    this.ctx = ctx;
}

function EventEmitter() {

    this._events = {};
    this._maxListeners = EventEmitter.defaultMaxListeners;
}

EventEmitter.prototype.on = function(type, listener, ctx) {
    if (typeof(listener) !== "function") throw new TypeError("EventEmitter.on(type, listener[, ctx]) listener must be a function");
    var events = this._events,
        eventList = (events[type] || (events[type] = [])),
        maxListeners = this._maxListeners;

    eventList.push(new EventObject(listener, ctx || this));

    if (maxListeners !== -1 && eventList.length > maxListeners) {
        console.error("EventEmitter.on(type, listener, ctx) possible EventEmitter memory leak detected. " + maxListeners + " listeners added");
    }

    return this;
};

EventEmitter.prototype.addListener = EventEmitter.prototype.on;

EventEmitter.prototype.once = function(type, listener, ctx) {
    var _this = this;
    ctx || (ctx = this);

    function once() {
        _this.off(type, once, ctx);
        var length = arguments.length;

        if (length === 0) {
            return listener.call(ctx);
        } else if (length === 1) {
            return listener.call(ctx, arguments[0]);
        } else if (length === 2) {
            return listener.call(ctx, arguments[0], arguments[1]);
        } else if (length === 3) {
            return listener.call(ctx, arguments[0], arguments[1], arguments[2]);
        } else if (length === 4) {
            return listener.call(ctx, arguments[0], arguments[1], arguments[2], arguments[3]);
        } else if (length === 5) {
            return listener.call(ctx, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
        }

        return listener.apply(ctx, arguments);
    }

    return this.on(type, once, ctx);
};

EventEmitter.prototype.listenTo = function(obj, type, listener, ctx) {
    if (!(has.call(obj, "on") && typeof(obj.on) === "function")) {
        throw new TypeError("EventEmitter.listenTo(obj, type, listener, ctx) obj must have a on function taking (type, listener[, ctx])");
    }

    obj.on(type, listener, ctx || this);
    return this;
};

EventEmitter.prototype.off = function(type, listener, ctx) {
    var events = this._events,
        eventList, event, i;

    if (!type) return this.removeAllListeners();

    eventList = events[type];
    if (!eventList) return this;

    if (!listener) {
        i = eventList.length;
        while (i--) {
            event = eventList[i];
            this.emit("removeListener", type, event.listener, event.ctx);
        }
        eventList.length = 0;
        delete events[type];
    } else {
        ctx = ctx || this;
        i = eventList.length;
        while (i--) {
            event = eventList[i];

            if (event.listener === listener) {
                this.emit("removeListener", type, event.listener, event.ctx);
                eventList.splice(i, 1);
            }
        }
        if (eventList.length === 0) delete events[type];
    }

    return this;
};

EventEmitter.prototype.removeListener = EventEmitter.prototype.off;

EventEmitter.prototype.removeAllListeners = function() {
    var events = this._events,
        eventList, event, i;

    for (var key in events) {
        if ((eventList = events[key])) {
            i = eventList.length;
            while (i--) {
                event = eventList[i];
                this.emit("removeListener", type, event.listener, event.ctx);
            }
            eventList.length = 0;
            delete events[key];
        }
    }

    return this;
};

EventEmitter.prototype.emit = function(type) {
    var eventList = this._events[type],
        a1, a2, a3, a4,
        length, event,
        i;

    if (!eventList || !eventList.length) return this;
    length = arguments.length;

    if (length === 1) {
        i = eventList.length;
        while (i--) {
            if ((event = eventList[i])) event.listener.call(event.ctx);
        }
    } else if (length === 2) {
        a1 = arguments[1];
        i = eventList.length;
        while (i--) {
            if ((event = eventList[i])) event.listener.call(event.ctx, a1);
        }
    } else if (length === 3) {
        a1 = arguments[1];
        a2 = arguments[2];
        i = eventList.length;
        while (i--) {
            if ((event = eventList[i])) event.listener.call(event.ctx, a1, a2);
        }
    } else if (length === 4) {
        a1 = arguments[1];
        a2 = arguments[2];
        a3 = arguments[3];
        i = eventList.length;
        while (i--) {
            if ((event = eventList[i])) event.listener.call(event.ctx, a1, a2, a3);
        }
    } else if (length === 5) {
        a1 = arguments[1];
        a2 = arguments[2];
        a3 = arguments[3];
        a4 = arguments[4];
        i = eventList.length;
        while (i--) {
            if ((event = eventList[i])) event.listener.call(event.ctx, a1, a2, a3, a4);
        }
    } else {
        shift.apply(arguments);
        i = eventList.length;
        while (i--) {
            if ((event = eventList[i])) event.listener.apply(event.ctx, arguments);
        }
    }

    return this;
};

EventEmitter.prototype.listeners = function(type) {
    var eventList = this._events[type];

    return eventList ? eventList.slice() : [];
};

EventEmitter.prototype.listenerCount = function(type) {
    var eventList = this._events[type];

    return eventList ? eventList.length : 0;
};

EventEmitter.prototype.setMaxListeners = function(value) {
    if ((value = +value) !== value) throw new TypeError("EventEmitter.setMaxListeners(value) value must be a number");

    this._maxListeners = value < 0 ? -1 : value;
    return this;
};

EventEmitter.defaultMaxListeners = 10;

EventEmitter.listeners = function(obj, type) {
    if (obj == null) throw new TypeError("EventEmitter.listeners(obj, type) obj required");
    var eventList = obj._events && obj._events[type];

    return eventList ? eventList.slice() : [];
};

EventEmitter.listenerCount = function(obj, type) {
    if (obj == null) throw new TypeError("EventEmitter.listenerCount(obj, type) obj required");
    var eventList = obj._events && obj._events[type];

    return eventList ? eventList.length : 0;
};

EventEmitter.setMaxListeners = function(value) {
    if ((value = +value) !== value) throw new TypeError("EventEmitter.setMaxListeners(value) value must be a number");

    EventEmitter.defaultMaxListeners = value < 0 ? -1 : value;
    return value;
};

EventEmitter.extend = function(child, parent) {
    if (!parent) parent = this;

    child.prototype = Object.create(parent.prototype);
    child.prototype.constructor = child;
    child.prototype._super = parent.prototype;
    child.extend = parent.extend;
    child._super = parent;

    return child;
};

module.exports = EventEmitter;
<|endoftext|>