<commit_before>'use strict';

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

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

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

module.exports = class btcalpha extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'btcalpha',
            'name': 'BTC-Alpha',
            'countries': 'US',
            'version': 'v1',
            'has': {
                'fetchTicker': false,
                'fetchOHLCV': true,
                'fetchOrders': true,
                'fetchOpenOrders': true,
                'fetchClosedOrders': true,
                'fetchMyTrades': true,
            },
            'timeframes': {
                '1m': '1',
                '5m': '5',
                '15m': '15',
                '30m': '30',
                '1h': '60',
                '4h': '240',
                '1d': 'D',
            },
            'urls': {
                'logo': 'https://btc-alpha.com/static/img/logo.png',
                'api': 'https://btc-alpha.com/api',
                'www': 'https://btcalpha.com/',
                'doc': 'https://btc-alpha.github.io/api-docs/',
                'fees': 'https://btc-alpha.com/fees/',
            },
            'api': {
                'public': {
                    'get': [
                        'currencies/',
                        'pairs/',
                        'orderbook/{pair_name}/',
                        'exchanges/',
                        'charts/{pair}/{type}/chart/',
                    ],
                },
                'private': {
                    'get': [
                        'wallets/',
                        'orders/own/',
                        'order/{id}/',
                        'exchanges/own/',
                        'deposits/',
                        'withdraws/',
                    ],
                    'post': [
                        'order/',
                        'order-cancel/',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'maker': 0.2 / 100,
                    'taker': 0.2 / 100,
                },
                'funding': {
                    'withdraw': {
                        'BTC': 0.00135,
                        'LTC': 0.0035,
                        'XMR': 0.018,
                        'ZEC': 0.002,
                        'ETH': 0.01,
                        'ETC': 0.01,
                        'SIB': 1.5,
                        'CCRB': 4,
                        'PZM': 0.05,
                        'ITI': 0.05,
                        'DCY': 5,
                        'R': 5,
                        'ATB': 0.05,
                        'BRIA': 0.05,
                        'KZC': 0.05,
                        'HWC': 1,
                        'SPA': 1,
                        'SMS': 0.001,
                        'REC': 0.01,
                        'SUP': 1,
                        'BQ': 100,
                        'GDS': 0.1,
                        'EVN': 300,
                        'TRKC': 0.01,
                        'UNI': 1,
                        'STN': 1,
                        'BCH': undefined,
                        'QBIC': 0.5,
                    },
                },
            },
        });
    }

    async fetchMarkets () {
        let markets = await this.publicGetPairs ();
        let result = [];
        for (let i = 0; i < markets.length; i++) {
            let market = markets[i];
            let id = market['name'];
            let base = this.commonCurrencyCode (market['currency1']);
            let quote = this.commonCurrencyCode (market['currency2']);
            let symbol = base + '/' + quote;
            let precision = {
                'amount': 8,
                'price': parseInt (market['price_precision']),
            };
            let lot = Math.pow (10, -precision['amount']);
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'active': true,
                'lot': lot,
                'precision': precision,
                'limits': {
                    'amount': {
                        'min': parseFloat (market['minimum_order_size']),
                        'max': parseFloat (market['maximum_order_size']),
                    },
                    'price': {
                        'min': Math.pow (10, -precision['price']),
                        'max': Math.pow (10, precision['price']),
                    },
                    'cost': {
                        'min': undefined,
                        'max': undefined,
                    },
                },
                'info': market,
            });
        }
        return result;
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'pair_name': this.marketId (symbol),
        };
        if (limit) {
            request['limit_sell'] = limit;
            request['limit_buy'] = limit;
        }
        let reponse = await this.publicGetOrderbookPairName (this.extend (request, params));
        return this.parseOrderBook (reponse, undefined, 'buy', 'sell', 'price', 'amount');
    }

    parseTrade (trade, market = undefined) {
        let symbol = undefined;
        if (!market)
            market = this.safeValue (this.marketsById, trade['pair']);
        if (market)
            symbol = market['symbol'];
        let timestamp = parseInt (trade['timestamp'] * 1000);
        let price = parseFloat (trade['price']);
        let amount = parseFloat (trade['amount']);
        let cost = this.costToPrecision (symbol, price * amount);
        let id = this.safeString (trade, 'id');
        if (!id)
            id = this.safeString (trade, 'tid');
        return {
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'id': id,
            'order': this.safeString (trade, 'o_id'),
            'type': 'limit',
            'side': trade['type'],
            'price': price,
            'amount': amount,
            'cost': parseFloat (cost),
            'fee': undefined,
            'info': trade,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = undefined;
        let request = {};
        if (typeof symbol !== 'undefined') {
            market = this.market (symbol);
            request['pair'] = market['id'];
        }
        if (limit)
            request['limit'] = limit;
        let trades = await this.publicGetExchanges (this.extend (request, params));
        return this.parseTrades (trades, market, since, limit);
    }

    parseOHLCV (ohlcv, market = undefined, timeframe = '5m', since = undefined, limit = undefined) {
        return [
            ohlcv['time'] * 1000,
            ohlcv['open'],
            ohlcv['high'],
            ohlcv['low'],
            ohlcv['close'],
            ohlcv['volume'],
        ];
    }

    async fetchOHLCV (symbol, timeframe = '5m', since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'pair': market['id'],
            'type': this.timeframes[timeframe],
        };
        if (limit)
            request['limit'] = limit;
        if (since)
            request['since'] = parseInt (since / 1000);
        let response = await this.publicGetChartsPairTypeChart (this.extend (request, params));
        return this.parseOHLCVs (response, market, timeframe, since, limit);
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balances = await this.privateGetWallets (params);
        let result = { 'info': balances };
        for (let i = 0; i < balances.length; i++) {
            let balance = balances[i];
            let currency = this.commonCurrencyCode (balance['currency']);
            let account = {
                'free': parseFloat (balance['balance']),
                'used': parseFloat (balance['reserve']),
                'total': 0.0,
            };
            account['total'] = this.sum (account['free'], account['used']);
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    parseOrder (order, market = undefined) {
        let symbol = undefined;
        if (!market)
            market = this.safeValue (this.marketsById, order['pair']);
        if (market)
            symbol = market['symbol'];
        let timestamp = parseInt (order['date'] * 1000);
        let price = parseFloat (order['price']);
        let amount = this.safeFloat (order, 'amount');
        let status = this.safeString (order, 'status');
        let statuses = {
            '1': 'open',
            '2': 'canceled',
            '3': 'closed',
        };
        let id = this.safeString (order, 'oid');
        if (!id)
            id = this.safeString (order, 'id');
        let trades = this.safeValue (order, 'trades');
        if (trades)
            trades = this.parseTrades (trades, market);
        return {
            'id': id,
            'datetime': this.iso8601 (timestamp),
            'timestamp': timestamp,
            'status': this.safeString (statuses, status),
            'symbol': symbol,
            'type': 'limit',
            'side': order['type'],
            'price': price,
            'cost': undefined,
            'amount': amount,
            'filled': undefined,
            'remaining': undefined,
            'trades': trades,
            'fee': undefined,
            'info': order,
        };
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.privatePostOrders (this.extend ({
            'pair': market['id'],
            'type': side,
            'amount': amount,
            'price': this.priceToPrecision (symbol, price),
        }, params));
        if (!response['success'])
            throw new InvalidOrder (this.id + ' ' + this.json (response));
        return this.parseOrder (response, market);
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        let response = await this.privatePostOrderCancel (this.extend ({
            'order': id,
        }, params));
        return response;
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let order = await this.privateGetOrderId (this.extend ({
            'id': id,
        }, params));
        return this.parseOrder (order);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {};
        let market = undefined;
        if (symbol) {
            market = this.market (symbol);
            request['pair'] = market['id'];
        }
        if (limit)
            request['limit'] = limit;
        let orders = await this.privateGetOrdersOwn (this.extend (request, params));
        return this.parseOrders (orders, market, since, limit);
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let orders = await this.fetchOrders (symbol, since, limit, this.extend ({
            'status': '1',
        }, params));
        return orders;
    }

    async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let orders = await this.fetchOrders (symbol, since, limit, this.extend ({
            'status': '3',
        }, params));
        return orders;
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {};
        if (symbol) {
            let market = this.market (symbol);
            request['pair'] = market['id'];
        }
        if (limit)
            request['limit'] = limit;
        let trades = await this.privateGetTrades (this.extend (request, params));
        return this.parseTrades (trades, undefined, since, limit);
    }

    nonce () {
        return this.milliseconds ();
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let query = this.urlencode (this.keysort (this.omit (params, this.extractParams (path))));
        let url = this.urls['api'] + '/';
        if (path !== 'charts/{pair}/{type}/chart/') {
            url += 'v1/';
        }
        url += this.implodeParams (path, params);
        headers = { 'Accept': 'application/json' };
        if (api === 'public') {
            if (query.length)
                url += '?' + query;
        } else {
            this.checkRequiredCredentials ();
            let payload = this.apiKey + query;
            headers['Content-Type'] = 'application/x-www-form-urlencoded';
            headers['X-KEY'] = this.apiKey;
            headers['X-SIGN'] = this.hmac (this.encode (payload), this.encode (this.secret));
            headers['X-NONCE'] = this.nonce ();
            body = query;
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (code, reason, url, method, headers, body) {
        if (code < 400) {
            return;
        }
        let response = this.unjson (body);
        let message = this.id + ' ' + this.safeValue (response, 'detail', body);
        if (code === 401 || code === 403) {
            throw new AuthenticationError (message);
        } else if (code === 429) {
            throw new DDoSProtection (message);
        }
        throw new ExchangeError (message);
    }
};
<commit_msg>btcalpha: fix API method names<commit_after>'use strict';

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

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

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

module.exports = class btcalpha extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'btcalpha',
            'name': 'BTC-Alpha',
            'countries': 'US',
            'version': 'v1',
            'has': {
                'fetchTicker': false,
                'fetchOHLCV': true,
                'fetchOrders': true,
                'fetchOpenOrders': true,
                'fetchClosedOrders': true,
                'fetchMyTrades': true,
            },
            'timeframes': {
                '1m': '1',
                '5m': '5',
                '15m': '15',
                '30m': '30',
                '1h': '60',
                '4h': '240',
                '1d': 'D',
            },
            'urls': {
                'logo': 'https://btc-alpha.com/static/img/logo.png',
                'api': 'https://btc-alpha.com/api',
                'www': 'https://btcalpha.com/',
                'doc': 'https://btc-alpha.github.io/api-docs/',
                'fees': 'https://btc-alpha.com/fees/',
            },
            'api': {
                'public': {
                    'get': [
                        'currencies/',
                        'pairs/',
                        'orderbook/{pair_name}/',
                        'exchanges/',
                        'charts/{pair}/{type}/chart/',
                    ],
                },
                'private': {
                    'get': [
                        'wallets/',
                        'orders/own/',
                        'order/{id}/',
                        'exchanges/own/',
                        'deposits/',
                        'withdraws/',
                    ],
                    'post': [
                        'order/',
                        'order-cancel/',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'maker': 0.2 / 100,
                    'taker': 0.2 / 100,
                },
                'funding': {
                    'withdraw': {
                        'BTC': 0.00135,
                        'LTC': 0.0035,
                        'XMR': 0.018,
                        'ZEC': 0.002,
                        'ETH': 0.01,
                        'ETC': 0.01,
                        'SIB': 1.5,
                        'CCRB': 4,
                        'PZM': 0.05,
                        'ITI': 0.05,
                        'DCY': 5,
                        'R': 5,
                        'ATB': 0.05,
                        'BRIA': 0.05,
                        'KZC': 0.05,
                        'HWC': 1,
                        'SPA': 1,
                        'SMS': 0.001,
                        'REC': 0.01,
                        'SUP': 1,
                        'BQ': 100,
                        'GDS': 0.1,
                        'EVN': 300,
                        'TRKC': 0.01,
                        'UNI': 1,
                        'STN': 1,
                        'BCH': undefined,
                        'QBIC': 0.5,
                    },
                },
            },
        });
    }

    async fetchMarkets () {
        let markets = await this.publicGetPairs ();
        let result = [];
        for (let i = 0; i < markets.length; i++) {
            let market = markets[i];
            let id = market['name'];
            let base = this.commonCurrencyCode (market['currency1']);
            let quote = this.commonCurrencyCode (market['currency2']);
            let symbol = base + '/' + quote;
            let precision = {
                'amount': 8,
                'price': parseInt (market['price_precision']),
            };
            let lot = Math.pow (10, -precision['amount']);
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'active': true,
                'lot': lot,
                'precision': precision,
                'limits': {
                    'amount': {
                        'min': parseFloat (market['minimum_order_size']),
                        'max': parseFloat (market['maximum_order_size']),
                    },
                    'price': {
                        'min': Math.pow (10, -precision['price']),
                        'max': Math.pow (10, precision['price']),
                    },
                    'cost': {
                        'min': undefined,
                        'max': undefined,
                    },
                },
                'info': market,
            });
        }
        return result;
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'pair_name': this.marketId (symbol),
        };
        if (limit) {
            request['limit_sell'] = limit;
            request['limit_buy'] = limit;
        }
        let reponse = await this.publicGetOrderbookPairName (this.extend (request, params));
        return this.parseOrderBook (reponse, undefined, 'buy', 'sell', 'price', 'amount');
    }

    parseTrade (trade, market = undefined) {
        let symbol = undefined;
        if (!market)
            market = this.safeValue (this.marketsById, trade['pair']);
        if (market)
            symbol = market['symbol'];
        let timestamp = parseInt (trade['timestamp'] * 1000);
        let price = parseFloat (trade['price']);
        let amount = parseFloat (trade['amount']);
        let cost = this.costToPrecision (symbol, price * amount);
        let id = this.safeString (trade, 'id');
        if (!id)
            id = this.safeString (trade, 'tid');
        return {
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'id': id,
            'order': this.safeString (trade, 'o_id'),
            'type': 'limit',
            'side': trade['type'],
            'price': price,
            'amount': amount,
            'cost': parseFloat (cost),
            'fee': undefined,
            'info': trade,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = undefined;
        let request = {};
        if (typeof symbol !== 'undefined') {
            market = this.market (symbol);
            request['pair'] = market['id'];
        }
        if (limit)
            request['limit'] = limit;
        let trades = await this.publicGetExchanges (this.extend (request, params));
        return this.parseTrades (trades, market, since, limit);
    }

    parseOHLCV (ohlcv, market = undefined, timeframe = '5m', since = undefined, limit = undefined) {
        return [
            ohlcv['time'] * 1000,
            ohlcv['open'],
            ohlcv['high'],
            ohlcv['low'],
            ohlcv['close'],
            ohlcv['volume'],
        ];
    }

    async fetchOHLCV (symbol, timeframe = '5m', since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'pair': market['id'],
            'type': this.timeframes[timeframe],
        };
        if (limit)
            request['limit'] = limit;
        if (since)
            request['since'] = parseInt (since / 1000);
        let response = await this.publicGetChartsPairTypeChart (this.extend (request, params));
        return this.parseOHLCVs (response, market, timeframe, since, limit);
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balances = await this.privateGetWallets (params);
        let result = { 'info': balances };
        for (let i = 0; i < balances.length; i++) {
            let balance = balances[i];
            let currency = this.commonCurrencyCode (balance['currency']);
            let account = {
                'free': parseFloat (balance['balance']),
                'used': parseFloat (balance['reserve']),
                'total': 0.0,
            };
            account['total'] = this.sum (account['free'], account['used']);
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    parseOrder (order, market = undefined) {
        let symbol = undefined;
        if (!market)
            market = this.safeValue (this.marketsById, order['pair']);
        if (market)
            symbol = market['symbol'];
        let timestamp = parseInt (order['date'] * 1000);
        let price = parseFloat (order['price']);
        let amount = this.safeFloat (order, 'amount');
        let status = this.safeString (order, 'status');
        let statuses = {
            '1': 'open',
            '2': 'canceled',
            '3': 'closed',
        };
        let id = this.safeString (order, 'oid');
        if (!id)
            id = this.safeString (order, 'id');
        let trades = this.safeValue (order, 'trades');
        if (trades)
            trades = this.parseTrades (trades, market);
        return {
            'id': id,
            'datetime': this.iso8601 (timestamp),
            'timestamp': timestamp,
            'status': this.safeString (statuses, status),
            'symbol': symbol,
            'type': 'limit',
            'side': order['type'],
            'price': price,
            'cost': undefined,
            'amount': amount,
            'filled': undefined,
            'remaining': undefined,
            'trades': trades,
            'fee': undefined,
            'info': order,
        };
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.privatePostOrder (this.extend ({
            'pair': market['id'],
            'type': side,
            'amount': amount,
            'price': this.priceToPrecision (symbol, price),
        }, params));
        if (!response['success'])
            throw new InvalidOrder (this.id + ' ' + this.json (response));
        return this.parseOrder (response, market);
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        let response = await this.privatePostOrderCancel (this.extend ({
            'order': id,
        }, params));
        return response;
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let order = await this.privateGetOrderId (this.extend ({
            'id': id,
        }, params));
        return this.parseOrder (order);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {};
        let market = undefined;
        if (symbol) {
            market = this.market (symbol);
            request['pair'] = market['id'];
        }
        if (limit)
            request['limit'] = limit;
        let orders = await this.privateGetOrdersOwn (this.extend (request, params));
        return this.parseOrders (orders, market, since, limit);
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let orders = await this.fetchOrders (symbol, since, limit, this.extend ({
            'status': '1',
        }, params));
        return orders;
    }

    async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let orders = await this.fetchOrders (symbol, since, limit, this.extend ({
            'status': '3',
        }, params));
        return orders;
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {};
        if (symbol) {
            let market = this.market (symbol);
            request['pair'] = market['id'];
        }
        if (limit)
            request['limit'] = limit;
        let trades = await this.privateGetExchangesOwn (this.extend (request, params));
        return this.parseTrades (trades, undefined, since, limit);
    }

    nonce () {
        return this.milliseconds ();
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let query = this.urlencode (this.keysort (this.omit (params, this.extractParams (path))));
        let url = this.urls['api'] + '/';
        if (path !== 'charts/{pair}/{type}/chart/') {
            url += 'v1/';
        }
        url += this.implodeParams (path, params);
        headers = { 'Accept': 'application/json' };
        if (api === 'public') {
            if (query.length)
                url += '?' + query;
        } else {
            this.checkRequiredCredentials ();
            let payload = this.apiKey + query;
            headers['Content-Type'] = 'application/x-www-form-urlencoded';
            headers['X-KEY'] = this.apiKey;
            headers['X-SIGN'] = this.hmac (this.encode (payload), this.encode (this.secret));
            headers['X-NONCE'] = this.nonce ();
            body = query;
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (code, reason, url, method, headers, body) {
        if (code < 400) {
            return;
        }
        let response = this.unjson (body);
        let message = this.id + ' ' + this.safeValue (response, 'detail', body);
        if (code === 401 || code === 403) {
            throw new AuthenticationError (message);
        } else if (code === 429) {
            throw new DDoSProtection (message);
        }
        throw new ExchangeError (message);
    }
};
<|endoftext|>


<commit_before>

//funciones de calculadora en Js

/* si se tiene  una estacion terrena con una antena de 4 mts de diametro alimentado por una potencia de 100 w frecuencia de subida de
14 GHz, esta radiada al satelite GEO a 36.000 km, el angulo de recepcion es la antena del satelite que es O3db=2°
La frecuencia del satelite es de 55% y la estacion terrena de 65% en  el satelite la potencia es 20w, frecuencia de trabajo es igual a 12 Ghz que se irradia
con un O3db=4°, la antena de la estacion terrena tiene un diametro de 6 mts con eficiencia de 60% la del satelite es 55%

Enlace de subida
Calcular la ganancia de la antena

*/

/* Formulas
 *
 * Free Space Path Loss (FSPL)
 * (4*PI*D*F/C)elevado al cuadrado
 * D: es la distancia del receptor al transmisor (metros)
 * F: intensidad en frecuencia (Hertz)
 * C: velocidad de la luz en el vacio (metros por segundos) */

var calculos_result={};

Object.defineProperty(calculos_result,'fspldecibels', {value: '0', writable:true, enumerable:true, configurable:true});
Object.defineProperty(calculos_result,'pire', {value: '0', writable:true, enumerable:true, configurable:true});
Object.defineProperty(calculos_result,'densidad', {value: '0', writable:true, enumerable:true, configurable:true});
Object.defineProperty(calculos_result,'fsl1', {value: '0', writable:true, enumerable:true, configurable:true});
Object.defineProperty(calculos_result,'gan_anten_reci', {value: '0', writable:true, enumerable:true, configurable:true});
Object.defineProperty(calculos_result,'pot_recept', {value: '0', writable:true, enumerable:true, configurable:true});
Object.defineProperty(calculos_result,'figura', {value: '0', writable:true, enumerable:true, configurable:true});
Object.defineProperty(calculos_result,'c_no', {value: '0', writable:true, enumerable:true, configurable:true});

/*Object.defineProperty(calculos_result, 'temp', {value:'0',
  get: function() { return temp; },
  set: function(newValue) { bValue = newValue; },
  enumerable: true,
  configurable: true
});*/

function fspl_decibels(){
	var pi=Math.PI;
	var velocidad_luz=300000000;
	var distancia = document.getElementById('distmts').value;
	var frecuencia=document.getElementById('frecuehz').value;
	var eficiencia_sat=document.getElementById('eficisate1').value;
	eficiencia_sat=eficiencia_sat/100;
	var valor=eficiencia_sat*Math.pow((pi*distancia*frecuencia/velocidad_luz),2);
	var valordb=10*Math.log10(valor);
	valordb=valordb.toFixed(3);

	valordbf=valordb.toString().concat(' db');
	calculos_result.fspldecibels=valordbf;
	localStorage["gtx"] =valordb;// esto sirve para guardar
	document.getElementById("gainpx1").innerHTML=calculos_result.fspldecibels;
	//return valor;

}

/* function ganancia_antena(efictierra,diametro,frecuencia_up,frecuencia_up_hz){
//var pi = 3.1416;
var pi=Math.PI;
//var efictierra =efictierra; //eficiencia antena en tierra
frecuencia_up; //frecuencia de subida
diametro;//metros del diametro
frecuencia_up_hz;//unidad de la frecuencia de subida
var valorFrecuencia= escala_hertz(frecuencia_up,frecuencia_up_hz); //transformo el valor segun la unidad correspondiente
var velocidad_luz=300000000;
var ganancia=efictierra*(Math.pow((pi*diametro*valorFrecuencia/velocidad_luz),2));

var ganancia_total= 10*Math.log10(ganancia);
return ganancia_total;

} */

function potenciatx(pot){

var potenciatotal=10*Math.log10(pot);
return potenciatotal;
}

//Calculadora EIRP
/* http://www.pasternack.com/t-calculator-eirp.aspx */
function getPire(){
	var potenciatx=document.getElementById('potx').value;
	var ganancia=document.getElementById('gananc').value;
	var losscable=document.getElementById('lossc').value;

	indice=document.form_pire.units.selectedIndex;
	unidad=document.form_pire.units.options[indice].value;
	var potenciafinal=escala_watts(potenciatx,unidad);
	//alert(potenciafinal);
	potenciafinal1=potenciafinal*1;
	losscable1=losscable*1;
	ganancia1=ganancia*1;
	var val_pire=potenciafinal1-losscable1+ganancia1;
	//-losscable;
	val_pire=val_pire.toFixed(3);
	calculos_result.pire=val_pire;
	localStorage["pire"]=calculos_result.pire;
	document.getElementById("valpire").innerHTML=calculos_result.pire;

//return pire;

}

/* Power Density Calculator
 * http://www.pasternack.com/t-calculator-power-density.aspx
 *     */

function densidadmaxima(){
	var pi=Math.PI;
	var potenciatx=document.getElementById('potantena').value;
	var ganancia=document.getElementById('gain').value;
	var distancia=document.getElementById('distancia').value;
	var val1=4*pi*Math.pow(distancia,2);
	var val2=potenciatx*ganancia;
	var val3=val2/val1;
	//var val_densidad=(potenciatx*ganancia/4*pi*Math.pow(distancia,2));
	//val3=val3.toFixed(3);
	//alert(val3);
	localStorage["density"]=val3;
	valor3f=val3.toString().concat(' Watts/mts'.concat('2'.sup()));//.concat('2').sup();
	calculos_result.densidad=valor3f;
	document.getElementById('valdensity').innerHTML=calculos_result.densidad;

}

//Calculo potencia de recepcion
//punto 5 ejercicio 1
/*function potencia_recepcion(variable,distancia,frecuencia){
	var fsl0=variable+20*Math.log(distancia);
	var fsl1=20*Math.log(frecuencia);
	var fsl=fsl0+fsl1;

	return fsl;

}*/

//Funcion que esta en el punto 5
function fsl_segundo(){

	var distancia_kms=document.getElementById('distancia1').value;
		//alert(document.getElementById('units').options[document.getElementById('units').selectedIndex].text);
	//indice=document.formulario.units.selectedIndex;
	//unidad=document.formulario.units.options[indice].value;
	//var distanciafinal=conversion_longitud(distancia_kms,unidad);
	//alert(distancafinal);
	var frecuencia_mhz=document.getElementById('frecuencia1').value;
	var valor = 20*Math.log10(distancia_kms)+20*Math.log10(frecuencia_mhz)+32.45;
	valor=valor.toFixed(3);
	localStorage["fsl"]=valor;
	valorf=valor.toString().concat(' db');
	calculos_result.fsl1=valorf;
	document.getElementById('vfsl1').innerHTML=calculos_result.fsl1;
//return valor;

}

function conversion_longitud(valor,unidad){
	if (unidad=="Kms"){
		result=valor*1;
	}
	if (unidad=="Meters"){
		result=valor*0.001;
	}

	if (unidad=="Miles"){
		result=valor*1.60934;
	}

	if (unidad=="Feet"){
		result=valor*0.0003048;
	}

	return result;
}
//punto 6
function ganancia_antena_receptora(){
	//var valor_pie=3.28*valmts; //valor de metro a pie

	valmts=document.getElementById('distpies').value;
	frecuencia=document.getElementById('frecuemhz').value;
	eficiencia_sat=document.getElementById('eficisate2').value;
	eficiencia_sat=eficiencia_sat/100;
	//alert(eficiencia_sat);
	var gp1=20*Math.log10(valmts)+20*Math.log10(frecuencia)+10*Math.log10(eficiencia_sat)- 49.92;

	var gpx=gp1;
	 gpx=gpx.toFixed(3);
	 localStorage["grx"]=gpx;
    gpxf=gpx.toString().concat(' dbi');
    calculos_result.gan_anten_reci=gpxf;
    //localStorage["gain_recep"]=calculos_result.gan_anten_reci;
	document.form_potrecept.ganancia_recept.value=gpx;
	document.form_figura.gain2.value=gpx;
	document.getElementById('gainpx').innerHTML=calculos_result.gan_anten_reci;
//return gpx;
}

//punto 7
function potencia_recepcion(){
	//var psl=pire+(-fsl)+gpx;

	fsl=document.getElementById('perdida').value;
	gpx=document.getElementById('ganancia_recept').value;
	pire=document.getElementById('pire').value;
	pire1=pire*1;
	fsl1=fsl*1;
	gpx1=gpx*1;
	var psl=pire1+(-fsl1)+gpx1;
	psl1=psl.toFixed(3);
	calculos_result.pot_recept=psl1;
	localStorage["rsl"]=psl1;
	pslstr=psl1.toString().concat(' db');
	document.getElementById('gainrecept').innerHTML=pslstr;
	//return psl;
}
function pasar(){
    window.location="up-two.html";
	//document.form_potrecept.pire.value=localStorage["pire"];
	//document.form_potrecept.perdida.value=localStorage["fsl"];
	//document.getElementById('pire').value=localStorage["pire"];
	//document.getElementById('perdida').value=localStorage["fsl"];
	//document.getElementById('ganancia_recept').value=localStorage["gain_recep"];
}
function carga(){
	document.form_potrecept.pire.value=localStorage["pire"];
	document.form_potrecept.perdida.value=localStorage["fsl"];
	document.form_cnr.pirecnr.value=localStorage["pire"];
	document.form_cnr.perdidacnr.value=localStorage["fsl"];
}

//Aqui cargamos los datos en la tabla1
function carga_resultados_up(){
	document.getElementById('gtxresult').innerHTML=localStorage["gtx"];
	document.getElementById('pireresult').innerHTML=localStorage["pire"];
	document.getElementById('densidadresult').innerHTML=localStorage["density"];
document.getElementById('fslresult').innerHTML=localStorage["fsl"];
document.getElementById('grxresult').innerHTML= localStorage["grx"];
document.getElementById('rslresult').innerHTML= localStorage["rsl"];
document.getElementById('gtresult').innerHTML= localStorage["gt"];
document.getElementById('cnresult').innerHTML= localStorage["cn"];

}
//punto 8
//calculamos figura merito
function calculo_figura(){
	//temp = system noise temperature
	gprec=document.getElementById('gain2').value;
	temperatura=document.getElementById('temp').value;
	var calc_figura=gprec-10*Math.log10(temperatura);
	calc_figura1=calc_figura.toFixed(3);
	figurastr=calc_figura1.toString().concat(' db/k');
	localStorage["gt"]=calc_figura1;
	document.form_cnr.figuracnr.value=calc_figura1;
	document.getElementById('figuramerito').innerHTML=figurastr;
	//return calc_figura;
}

//punto 9
//C/NO

function last(){
	var k=Math.pow(10,-23);
	pirecnr=document.getElementById('pirecnr').value;
	fslcnr=document.getElementById('perdidacnr').value;
	figuracnr=document.getElementById('figuracnr').value;
var boltzman=1.3806*k;
pirecnr1=pirecnr*1;
fslcnr1=fslcnr*1;
figuracnr1=figuracnr*1;
boltzman1=boltzman*1;

 var cnr=pirecnr1-fslcnr1+figuracnr1-boltzman1;
 cnrfin=cnr.toFixed(3);
 localStorage["cn"]=cnrfin;
 cnrstr=cnrfin.toString().concat(' db/Hz');
 document.getElementById('valcnr').innerHTML=cnrstr;

}

function escala_hertz(valor,unidad){
	if(unidad=="hertz"){
			var valortotal=valor*1;
		}

	if (unidad=="kilohertz"){

    	var valortotal=valor*1000;
		}

	if (unidad=="megahertz"){

    	var valortotal=valor*1000000;
		}

if (unidad=="gigahertz"){

    var valortotal=valor*1000000000;
		}

	if (unidad=="terahertz"){

    	var valortotal=valor*1000000000000;
		}

		if (unidad=="petahertz"){

    var valortotal=valor*1000000000000000;
			}

return valortotal;
}

function escala_watts(valor, unidad){
	if(unidad=="Watts"){
		var valortotal=valor*1;
	}

	if(unidad=="Milliwatts"){
		var valortotal=valor*1000;
	}

	if(unidad=="dBm"){
		var valortotal=10*Math.log10(1000*valor);
	}

	if(unidad=="dbw"){
		var valortotal=10*Math.log10(valor);
	}

	return valortotal;
}

<commit_msg>Tabla up con resultados fixed<commit_after>

//funciones de calculadora en Js

/* si se tiene  una estacion terrena con una antena de 4 mts de diametro alimentado por una potencia de 100 w frecuencia de subida de
14 GHz, esta radiada al satelite GEO a 36.000 km, el angulo de recepcion es la antena del satelite que es O3db=2°
La frecuencia del satelite es de 55% y la estacion terrena de 65% en  el satelite la potencia es 20w, frecuencia de trabajo es igual a 12 Ghz que se irradia
con un O3db=4°, la antena de la estacion terrena tiene un diametro de 6 mts con eficiencia de 60% la del satelite es 55%

Enlace de subida
Calcular la ganancia de la antena

*/

/* Formulas
 *
 * Free Space Path Loss (FSPL)
 * (4*PI*D*F/C)elevado al cuadrado
 * D: es la distancia del receptor al transmisor (metros)
 * F: intensidad en frecuencia (Hertz)
 * C: velocidad de la luz en el vacio (metros por segundos) */

var calculos_result={};

Object.defineProperty(calculos_result,'fspldecibels', {value: '0', writable:true, enumerable:true, configurable:true});
Object.defineProperty(calculos_result,'pire', {value: '0', writable:true, enumerable:true, configurable:true});
Object.defineProperty(calculos_result,'densidad', {value: '0', writable:true, enumerable:true, configurable:true});
Object.defineProperty(calculos_result,'fsl1', {value: '0', writable:true, enumerable:true, configurable:true});
Object.defineProperty(calculos_result,'gan_anten_reci', {value: '0', writable:true, enumerable:true, configurable:true});
Object.defineProperty(calculos_result,'pot_recept', {value: '0', writable:true, enumerable:true, configurable:true});
Object.defineProperty(calculos_result,'figura', {value: '0', writable:true, enumerable:true, configurable:true});
Object.defineProperty(calculos_result,'c_no', {value: '0', writable:true, enumerable:true, configurable:true});

/*Object.defineProperty(calculos_result, 'temp', {value:'0',
  get: function() { return temp; },
  set: function(newValue) { bValue = newValue; },
  enumerable: true,
  configurable: true
});*/

function fspl_decibels(){
	var pi=Math.PI;
	var velocidad_luz=300000000;
	var distancia = document.getElementById('distmts').value;
	var frecuencia=document.getElementById('frecuehz').value;
	var eficiencia_sat=document.getElementById('eficisate1').value;
	eficiencia_sat=eficiencia_sat/100;
	var valor=eficiencia_sat*Math.pow((pi*distancia*frecuencia/velocidad_luz),2);
	var valordb=10*Math.log10(valor);
	valordb=valordb.toFixed(3);

	valordbf=valordb.toString().concat(' db');
	calculos_result.fspldecibels=valordbf;
	localStorage["gtx"] =valordb;// esto sirve para guardar
	document.getElementById("gainpx1").innerHTML=calculos_result.fspldecibels;
	//return valor;

}

/* function ganancia_antena(efictierra,diametro,frecuencia_up,frecuencia_up_hz){
//var pi = 3.1416;
var pi=Math.PI;
//var efictierra =efictierra; //eficiencia antena en tierra
frecuencia_up; //frecuencia de subida
diametro;//metros del diametro
frecuencia_up_hz;//unidad de la frecuencia de subida
var valorFrecuencia= escala_hertz(frecuencia_up,frecuencia_up_hz); //transformo el valor segun la unidad correspondiente
var velocidad_luz=300000000;
var ganancia=efictierra*(Math.pow((pi*diametro*valorFrecuencia/velocidad_luz),2));

var ganancia_total= 10*Math.log10(ganancia);
return ganancia_total;

} */

function potenciatx(pot){

var potenciatotal=10*Math.log10(pot);
return potenciatotal;
}

//Calculadora EIRP
/* http://www.pasternack.com/t-calculator-eirp.aspx */
function getPire(){
	var potenciatx=document.getElementById('potx').value;
	var ganancia=document.getElementById('gananc').value;
	var losscable=document.getElementById('lossc').value;

	indice=document.form_pire.units.selectedIndex;
	unidad=document.form_pire.units.options[indice].value;
	var potenciafinal=escala_watts(potenciatx,unidad);
	//alert(potenciafinal);
	potenciafinal1=potenciafinal*1;
	losscable1=losscable*1;
	ganancia1=ganancia*1;
	var val_pire=potenciafinal1-losscable1+ganancia1;
	//-losscable;
	val_pire=val_pire.toFixed(3);
	calculos_result.pire=val_pire;
	localStorage["pire"]=calculos_result.pire;
	document.getElementById("valpire").innerHTML=calculos_result.pire;

//return pire;

}

/* Power Density Calculator
 * http://www.pasternack.com/t-calculator-power-density.aspx
 *     */

function densidadmaxima(){
	var pi=Math.PI;
	var potenciatx=document.getElementById('potantena').value;
	var ganancia=document.getElementById('gain').value;
	var distancia=document.getElementById('distancia').value;
	var val1=4*pi*Math.pow(distancia,2);
	var val2=potenciatx*ganancia;
	var val3=val2/val1;
	var valfin=10*Math.log10(val3);
	//var val_densidad=(potenciatx*ganancia/4*pi*Math.pow(distancia,2));
	val4=valfin.toFixed(3);
	//alert(val3);
	localStorage["density"]=val4;
	//valor3f=val3.toString().concat(' Watts/mts'.concat('2'.sup()));//.concat('2').sup();
	calculos_result.densidad=val4;
	document.getElementById('valdensity').innerHTML=calculos_result.densidad;

}

//Calculo potencia de recepcion
//punto 5 ejercicio 1
/*function potencia_recepcion(variable,distancia,frecuencia){
	var fsl0=variable+20*Math.log(distancia);
	var fsl1=20*Math.log(frecuencia);
	var fsl=fsl0+fsl1;

	return fsl;

}*/

//Funcion que esta en el punto 5
function fsl_segundo(){

	var distancia_kms=document.getElementById('distancia1').value;
		//alert(document.getElementById('units').options[document.getElementById('units').selectedIndex].text);
	//indice=document.formulario.units.selectedIndex;
	//unidad=document.formulario.units.options[indice].value;
	//var distanciafinal=conversion_longitud(distancia_kms,unidad);
	//alert(distancafinal);
	var frecuencia_mhz=document.getElementById('frecuencia1').value;
	var valor = 20*Math.log10(distancia_kms)+20*Math.log10(frecuencia_mhz)+32.45;
	valor=valor.toFixed(3);
	localStorage["fsl"]=valor;
	valorf=valor.toString().concat(' db');
	calculos_result.fsl1=valorf;
	document.getElementById('vfsl1').innerHTML=calculos_result.fsl1;
//return valor;

}

function conversion_longitud(valor,unidad){
	if (unidad=="Kms"){
		result=valor*1;
	}
	if (unidad=="Meters"){
		result=valor*0.001;
	}

	if (unidad=="Miles"){
		result=valor*1.60934;
	}

	if (unidad=="Feet"){
		result=valor*0.0003048;
	}

	return result;
}
//punto 6
function ganancia_antena_receptora(){
	//var valor_pie=3.28*valmts; //valor de metro a pie

	valmts=document.getElementById('distpies').value;
	frecuencia=document.getElementById('frecuemhz').value;
	eficiencia_sat=document.getElementById('eficisate2').value;
	eficiencia_sat=eficiencia_sat/100;
	//alert(eficiencia_sat);
	var gp1=20*Math.log10(valmts)+20*Math.log10(frecuencia)+10*Math.log10(eficiencia_sat)- 49.92;

	var gpx=gp1;
	 gpx=gpx.toFixed(3);
	 localStorage["grx"]=gpx;
    gpxf=gpx.toString().concat(' dbi');
    calculos_result.gan_anten_reci=gpxf;
    //localStorage["gain_recep"]=calculos_result.gan_anten_reci;
	document.form_potrecept.ganancia_recept.value=gpx;
	document.form_figura.gain2.value=gpx;
	document.getElementById('gainpx').innerHTML=calculos_result.gan_anten_reci;
//return gpx;
}

//punto 7
function potencia_recepcion(){
	//var psl=pire+(-fsl)+gpx;

	fsl=document.getElementById('perdida').value;
	gpx=document.getElementById('ganancia_recept').value;
	pire=document.getElementById('pire').value;
	pire1=pire*1;
	fsl1=fsl*1;
	gpx1=gpx*1;
	var psl=pire1+(-fsl1)+gpx1;
	psl1=psl.toFixed(3);
	calculos_result.pot_recept=psl1;
	localStorage["rsl"]=psl1;
	pslstr=psl1.toString().concat(' db');
	document.getElementById('gainrecept').innerHTML=pslstr;
	//return psl;
}
function pasar(){
    window.location="up-two.html";
	//document.form_potrecept.pire.value=localStorage["pire"];
	//document.form_potrecept.perdida.value=localStorage["fsl"];
	//document.getElementById('pire').value=localStorage["pire"];
	//document.getElementById('perdida').value=localStorage["fsl"];
	//document.getElementById('ganancia_recept').value=localStorage["gain_recep"];
}
function carga(){
	document.form_potrecept.pire.value=localStorage["pire"];
	document.form_potrecept.perdida.value=localStorage["fsl"];
	document.form_cnr.pirecnr.value=localStorage["pire"];
	document.form_cnr.perdidacnr.value=localStorage["fsl"];
}

//Aqui cargamos los datos en la tabla1
function carga_resultados_up(){
	document.getElementById('gtxresult').innerHTML=localStorage["gtx"];
	document.getElementById('pireresult').innerHTML=localStorage["pire"];
	document.getElementById('densidadresult').innerHTML=localStorage["density"];
document.getElementById('fslresult').innerHTML=localStorage["fsl"];
document.getElementById('grxresult').innerHTML= localStorage["grx"];
document.getElementById('rslresult').innerHTML= localStorage["rsl"];
document.getElementById('gtresult').innerHTML= localStorage["gt"];
document.getElementById('cnresult').innerHTML= localStorage["cn"];

}
//punto 8
//calculamos figura merito
function calculo_figura(){
	//temp = system noise temperature
	gprec=document.getElementById('gain2').value;
	temperatura=document.getElementById('temp').value;
	var calc_figura=gprec-10*Math.log10(temperatura);
	calc_figura1=calc_figura.toFixed(3);
	figurastr=calc_figura1.toString().concat(' db/k');
	localStorage["gt"]=calc_figura1;
	document.form_cnr.figuracnr.value=calc_figura1;
	document.getElementById('figuramerito').innerHTML=figurastr;
	//return calc_figura;
}

//punto 9
//C/NO

function last(){
	var k=Math.pow(10,-23);
	pirecnr=document.getElementById('pirecnr').value;
	fslcnr=document.getElementById('perdidacnr').value;
	figuracnr=document.getElementById('figuracnr').value;
var boltzman=1.3806*k;
pirecnr1=pirecnr*1;
fslcnr1=fslcnr*1;
figuracnr1=figuracnr*1;
boltzman1=boltzman*1;

 var cnr=pirecnr1-fslcnr1+figuracnr1-boltzman1;
 cnrfin=cnr.toFixed(3);
 localStorage["cn"]=cnrfin;
 cnrstr=cnrfin.toString().concat(' db/Hz');
 document.getElementById('valcnr').innerHTML=cnrstr;

}

function escala_hertz(valor,unidad){
	if(unidad=="hertz"){
			var valortotal=valor*1;
		}

	if (unidad=="kilohertz"){

    	var valortotal=valor*1000;
		}

	if (unidad=="megahertz"){

    	var valortotal=valor*1000000;
		}

if (unidad=="gigahertz"){

    var valortotal=valor*1000000000;
		}

	if (unidad=="terahertz"){

    	var valortotal=valor*1000000000000;
		}

		if (unidad=="petahertz"){

    var valortotal=valor*1000000000000000;
			}

return valortotal;
}

function escala_watts(valor, unidad){
	if(unidad=="Watts"){
		var valortotal=valor*1;
	}

	if(unidad=="Milliwatts"){
		var valortotal=valor*1000;
	}

	if(unidad=="dBm"){
		var valortotal=10*Math.log10(1000*valor);
	}

	if(unidad=="dbw"){
		var valortotal=10*Math.log10(valor);
	}

	return valortotal;
}

<|endoftext|>


<commit_before>// A carousel of items for the stream. Only supports tweets right now.
//
// Optional params:
//
//  max: max number of items. Entries will be deleted on overflow.

function Carousel(options) {
  var historyQueue = new StoredQueue('carousel.history', options);
  var upcomingQueue = new StoredQueue('carousel.upcoming', options);

  var unboundedLength = true;
  var maxItems;
  if(options !== undefined && options['max']) {
    maxItems = options['max'];
    unboundedLength = false;
  }

  this.push = function (item) {
    upcomingQueue.push(item);
    this.trim();
  };

  this.next = function () {
    var item = undefined;
    if(!upcomingQueue.isEmpty()) {
      item = upcomingQueue.peek();
      historyQueue.push(upcomingQueue.pop());
    } else if(!historyQueue.isEmpty()) {
      // Nothing in upcoming queue.
      item = historyQueue.pop();
      historyQueue.push(item);
    }
    return item;
  };

  this.isEmpty = function () {
    return historyQueue.isEmpty() && upcomingQueue.isEmpty();
  };

  this.length = function () {
    return historyQueue.length() + upcomingQueue.length();
  };

  // Removes items if number of items is above maxItems.
  // Deletion order is semi-arbitrary; it deletes the items in front of the
  // historyQueue.
  //
  // TODO to delete always the earliest-pushed items, we can use three queues.
  this.trim = function (max) {
    if(max === undefined) {
      max = maxItems;
    }
    if(this.length() > max) {
      // Delete stuff from the historyQueue first.
      var toDelete = this.length() - max;
      var toDeleteFromUpcoming = toDelete - historyQueue.length();
      while(toDelete > 0 && !historyQueue.isEmpty()) {
        historyQueue.pop();
        --toDelete;
      }
      while(toDelete > 0 && !upcomingQueue.isEmpty()) {
        upcomingQueue.pop();
        --toDelete;
      }
    }
  };

  this.clear = function () {
    historyQueue.clear();
    upcomingQueue.clear();
  }

  this._pushToHistory = function (item) {
    historyQueue.push(item);
  }
};

// Queue implementation using LocalStorage.

function StoredQueue(name, options) {
  if(name === undefined) {
    name = (new Date()).getTime();
  }

  // Default options
  if(options === undefined) {
    options = {};
  }
  if(options.clearExistingData === undefined) {
    options.clearExistingData = false;
  }

  var storage = new LocalStorage('StoredQueue.' + name);

  if(options.clearExistingData || storage.json('queue') === undefined) {
    storage.set('queue', []);
  }

  this.queue = function () {
    return storage.json('queue');
  };

  this.length = function () {
    return this.queue().length;
  };

  this.isEmpty = function () {
    return this.length() === 0;
  };

  this.push = function (item) {
    var queue = this.queue();
    queue.push(item);
    storage.set('queue', queue);
  };

  this.peek = function () {
    if(this.isEmpty()) return undefined;
    return this.queue()[0];
  };

  this.pop = function () {
    // TODO this is inefficient because shift() is O(n). We can do amortized
    // O(1) using offsets. Check out Queue.js.
    var queue = this.queue();
    var item = queue.shift();
    storage.set('queue', queue);
    return item;
  };

  this.clear = function () {
    storage.set('queue', []);
  };
}

// LocalStorage is a wrapper around window.localStorage.
function LocalStorage(name) {

  this._key = function (attribute) {
    if(attribute && attribute !== '') {
      return "LocalStorage." + name + "." + attribute;
    }
    return "LocalStorage." + name;
  };

  this.get = function (attribute) {
    var key = this._key(attribute);
    return window.localStorage[key];
  };

  this.set = function (attribute, value) {
    if(typeof(value) !== "string") {
      value = JSON.stringify(value);
    }
    var key = this._key(attribute);
    window.localStorage[key] = value;
  };

  this.json = function (attribute) {
    var value = this.get(attribute);
    if(!value) return undefined;
    return JSON.parse(value);
  }

  this.int = function (attribute) {
    var value = this.get(attribute);
    if(!value) return undefined;
    return parseInt(value);
  }

  this.incr = function (attribute, incrValue) {
    if(incrValue === undefined) {
      incrValue = 1;
    }

    var value = this.get(attribute);
    if(!value) return undefined;

    value = parseFloat(this.get(attribute));
    this.set(attribute, value+incrValue);
    return value + incrValue;
  };

  this.clear = function (attribute) {
    var len = this._key().length;
    var namespace = this._key();
    var deletedKeys = [];

    for(var key in window.localStorage) {
      if(window.localStorage.hasOwnProperty(key)) {
        var substr = key.substring(0, len);
        if(substr === namespace) {
          deletedKeys.push(key);
          delete window.localStorage[key];
        }
      }
    }
    return deletedKeys;
  };

  this._allLocalStorageKeys = function () {
    var keys = [];
    for(var key in window.localStorage) {
      if(window.localStorage.hasOwnProperty(key)) {
        keys.push(key);
      }
    }
    return keys;
  };
}
<commit_msg>added a generic Queue object that has constant-time enqueue/dequeue/clear, refactored code to use 4-space tabs<commit_after>// A carousel of items for the stream. Only supports tweets right now.
//
// Optional params:
//
//  max: max number of items. Entries will be deleted on overflow.

function Carousel(options) {
    var historyQueue = new StoredQueue('carousel.history', options);
    var upcomingQueue = new StoredQueue('carousel.upcoming', options);

    var unboundedLength = true;
    var maxItems;
    if(options !== undefined && options['max']) {
        maxItems = options['max'];
        unboundedLength = false;
    }

    this.push = function (item) {
        upcomingQueue.push(item);
        this.trim();
    };

    this.next = function () {
        var item = undefined;
        if(!upcomingQueue.isEmpty()) {
            item = upcomingQueue.peek();
            historyQueue.push(upcomingQueue.pop());
        } else if(!historyQueue.isEmpty()) {
            // Nothing in upcoming queue.
            item = historyQueue.pop();
            historyQueue.push(item);
        }
        return item;
    };

    this.isEmpty = function () {
        return historyQueue.isEmpty() && upcomingQueue.isEmpty();
    };

    this.length = function () {
        return historyQueue.length() + upcomingQueue.length();
    };

    // Removes items if number of items is above maxItems.
    // Deletion order is semi-arbitrary; it deletes the items in front of the
    // historyQueue.
    //
    // TODO to delete always the earliest-pushed items, we can use three queues.
    this.trim = function (max) {
        if(max === undefined) {
            max = maxItems;
        }
        if(this.length() > max) {
            // Delete stuff from the historyQueue first.
            var toDelete = this.length() - max;
            var toDeleteFromUpcoming = toDelete - historyQueue.length();
            while(toDelete > 0 && !historyQueue.isEmpty()) {
                historyQueue.pop();
                --toDelete;
            }
            while(toDelete > 0 && !upcomingQueue.isEmpty()) {
                upcomingQueue.pop();
                --toDelete;
            }
        }
    };

    this.clear = function () {
        historyQueue.clear();
        upcomingQueue.clear();
    }

    this._pushToHistory = function (item) {
        historyQueue.push(item);
    }
};

// a queue object that, internally, uses an array and tracks pointers to the
// head/tail so we can acheive constant-time modification. defaults to a maximum
// size of 10, but this can be specified.
function Queue (init) {
    // the list where we internally store elements. defaults to a size of 10.
    this.queue = undefined;

    // if we were given an array, create an array of that size and copy its
    // members into it.
    if (init instanceof Array) {
        this.queue = new Array(init.length);

        // copy the elements into the internal queue
        for (var i = 0; i < init.length; i++) {
            this.queue[i] = init[i];
        }

        // set the size to the size of the queue
        this.size = this.queue.length;
    }
    // if we were given a number, create an array of that size
    else if (!isNaN(init)) {
        // make sure the object is a basic number before passing it to Array
        this.queue = new Array(Number(init));
    }

    // if we were given nothing, create an array of the default size
    else if (init === undefined) {
        this.queue = new Array(10);
    }

    // we manually track the queue's head, tail, and size so we can get
    // constant-time modification.
    this.size = 0; // the number of items in the queue
    this.headIndex = 0; // index of the least recent item in the queue
    this.tailIndex = 0; // index of the most recent item in the queue, points to an empty index by default

    // wraps a number forwards in the range [0, size)
    var wrap = function (num, size) {
        if (num >= size - 1) {
            return 0;
        }

        return ++num;
    }

    // adds an item to the end of the queue. returns true if the add was
    // successful, false if the queue was full and the add didn't succeed.
    this.enqueue = function (item) {
        // don't allow an add if the queue is full
        if (this.size >= this.queue.length) {
            return false;
        }

        // put the item into the queue as the newest tail, increase the size
        this.queue[this.tailIndex] = item;
        this.size++;

        // wrap the tail
        this.tailIndex = wrap(this.tailIndex, this.queue.length);

        // return that we sucessfully inserted the item
        return true;
    }

    // dequeues an item from the queue and returns it. returns null if there
    // were no items to dequeue.
    this.dequeue = function () {
        if (this.size <= 0) {
            return null;
        }

        // store the head item away so we can return it later
        var headItem = this.queue[this.headIndex];

        // wrap the head
        this.headIndex = wrap(this.headIndex, this.queue.length);

        // decrease the size of the queue
        this.size--;

        // return the original head of the queue
        return headItem;
    }

    // returns the first item in the queue without dequeuing it. if there are no
    // items in the queue, returns null.
    this.peek = function () {
        if (this.size <= 0) {
            return null;
        }

        return this.queue[this.headIndex];
    }

    // removes all the items from the internal queue, emptying it.
    this.clear = function () {
        // reset the index pointers, effectively clearing the queue
        this.size = 0;
        this.headIndex = 0;
        this.tailIndex = 0;
    }
}

// Queue implementation using LocalStorage.

function StoredQueue(name, options) {
    if(name === undefined) {
        name = (new Date()).getTime();
    }

    // Default options
    if(options === undefined) {
        options = {};
    }
    if(options.clearExistingData === undefined) {
        options.clearExistingData = false;
    }

    var storage = new LocalStorage('StoredQueue.' + name);

    if(options.clearExistingData || storage.json('queue') === undefined) {
        storage.set('queue', []);
    }

    this.queue = function () {
        return storage.json('queue');
    };

    this.length = function () {
        return this.queue().length;
    };

    this.isEmpty = function () {
        return this.length() === 0;
    };

    this.push = function (item) {
        var queue = this.queue();
        queue.push(item);
        storage.set('queue', queue);
    };

    this.peek = function () {
        if(this.isEmpty()) return undefined;
        return this.queue()[0];
    };

    this.pop = function () {
        // TODO this is inefficient because shift() is O(n). We can do amortized
        // O(1) using offsets. Check out Queue.js.
        var queue = this.queue();
        var item = queue.shift();
        storage.set('queue', queue);
        return item;
    };

    this.clear = function () {
        storage.set('queue', []);
    };
}

// LocalStorage is a wrapper around window.localStorage.
function LocalStorage(name) {

    this._key = function (attribute) {
        if(attribute && attribute !== '') {
            return "LocalStorage." + name + "." + attribute;
        }
        return "LocalStorage." + name;
    };

    this.get = function (attribute) {
        var key = this._key(attribute);
        return window.localStorage[key];
    };

    this.set = function (attribute, value) {
        if(typeof(value) !== "string") {
            value = JSON.stringify(value);
        }
        var key = this._key(attribute);
        window.localStorage[key] = value;
    };

    this.json = function (attribute) {
        var value = this.get(attribute);
        if(!value) return undefined;
        return JSON.parse(value);
    }

    this.int = function (attribute) {
        var value = this.get(attribute);
        if(!value) return undefined;
        return parseInt(value);
    }

    this.incr = function (attribute, incrValue) {
        if(incrValue === undefined) {
            incrValue = 1;
        }

        var value = this.get(attribute);
        if(!value) return undefined;

        value = parseFloat(this.get(attribute));
        this.set(attribute, value+incrValue);
        return value + incrValue;
    };

    this.clear = function (attribute) {
        var len = this._key().length;
        var namespace = this._key();
        var deletedKeys = [];

        for(var key in window.localStorage) {
            if(window.localStorage.hasOwnProperty(key)) {
                var substr = key.substring(0, len);
                if(substr === namespace) {
                    deletedKeys.push(key);
                    delete window.localStorage[key];
                }
            }
        }
        return deletedKeys;
    };

    this._allLocalStorageKeys = function () {
        var keys = [];
        for(var key in window.localStorage) {
            if(window.localStorage.hasOwnProperty(key)) {
                keys.push(key);
            }
        }
        return keys;
    };
}
<|endoftext|>


<commit_before>var fig1_1 = require('./figures/fig1-1.js');
var fig1_2 = require('./figures/fig1-2.js');
var fig1_3 = require('./figures/fig1-3.js');
var fig1_4 = require('./figures/fig1-4.js');

var fig2_1 = require('./figures/fig2-1.js');

var fig3_1 = require('./figures/fig3-1.js');

var fig4_1 = require('./figures/fig4-1.js');

module.exports = [
  {
    id: 1,
    name: "Scott Murray's tutorial",
    figures: [
      {
        id: 1,
        description: "Data in divs.",
        script: fig1_1
      },
      {
        id: 2,
        description: "Enter svg.",
        script: fig1_2
      },
      {
        id: 3,
        description: "Let's do that again.",
        script: fig1_3
      },
      {
        id: 4,
        description: "Scatter!",
        script: fig1_4
      }
    ]
  },
  {
    id: 2,
    name: "Perpetual motion",
    figures: [
      {
        id: 1,
        description: "Floating droplets.",
        script: fig2_1
      }
    ]
  },
  {
    id: 3,
    name: "Cellular Automata",
    figures: [
      {
        id: 1,
        description: "Cellular Automata.",
        script: fig3_1
      }
    ]
  },
  {
    id: 4,
    name: "Charts from external data",
    figures: [
      {
        id: 1,
        description: "Let's look at some data...",
        script: fig4_1
      }
    ]
  }
];
<commit_msg>Add date to chapters<commit_after>var fig1_1 = require('./figures/fig1-1.js');
var fig1_2 = require('./figures/fig1-2.js');
var fig1_3 = require('./figures/fig1-3.js');
var fig1_4 = require('./figures/fig1-4.js');

var fig2_1 = require('./figures/fig2-1.js');

var fig3_1 = require('./figures/fig3-1.js');

var fig4_1 = require('./figures/fig4-1.js');

module.exports = [
  {
    id: 1,
    name: "Scott Murray's tutorial",
    date: "2015-07-10",
    figures: [
      {
        id: 1,
        description: "Data in divs.",
        script: fig1_1
      },
      {
        id: 2,
        description: "Enter svg.",
        script: fig1_2
      },
      {
        id: 3,
        description: "Let's do that again.",
        script: fig1_3
      },
      {
        id: 4,
        description: "Scatter!",
        script: fig1_4
      }
    ]
  },
  {
    id: 2,
    name: "Perpetual motion",
    date: "2015-07-12",
    figures: [
      {
        id: 1,
        description: "Floating droplets.",
        script: fig2_1
      }
    ]
  },
  {
    id: 3,
    name: "Cellular Automata",
    date: "2015-07-18",
    figures: [
      {
        id: 1,
        description: "Cellular Automata.",
        script: fig3_1
      }
    ]
  },
  {
    id: 4,
    name: "Charts from external data",
    date: "2015-07-19",
    figures: [
      {
        id: 1,
        description: "Let's look at some data...",
        script: fig4_1
      }
    ]
  }
];
<|endoftext|>


<commit_before>'use strict';

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

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

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

module.exports = class coinbase extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'coinbase',
            'name': 'coinbase',
            'countries': 'US',
            'rateLimit': 400, // 10k calls per hour
            'version': 'v2',
            'userAgent': this.userAgents['chrome'],
            'has': {
                'CORS': true,
                'cancelOrder': false,
                'createDepositAddress': false,
                'createOrder': false,
                'deposit': false,
                'fetchBalance': true,
                'fetchClosedOrders': false,
                'fetchCurrencies': true,
                'fetchDepositAddress': false,
                'fetchMarkets': false,
                'fetchMyTrades': false,
                'fetchOHLCV': false,
                'fetchOpenOrders': false,
                'fetchOrder': false,
                'fetchOrderBook': false,
                'fetchOrders': false,
                'fetchTicker': true,
                'fetchTickers': false,
                'fetchBidsAsks': false,
                'fetchTrades': false,
                'withdraw': false,
                'fetchTransactions': false,
                'fetchDeposits': false,
                'fetchWithdrawals': false,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/40811661-b6eceae2-653a-11e8-829e-10bfadb078cf.jpg',
                'api': 'https://api.coinbase.com',
                'www': 'https://www.coinbase.com',
                'doc': 'https://developers.coinbase.com/api/v2',
                'fees': 'https://support.coinbase.com/customer/portal/articles/2109597-buy-sell-bank-transfer-fees',
            },
            'requiredCredentials': {
                'apiKey': true,
                'secret': true,
            },
            'api': {
                'public': {
                    'get': [
                        'currencies',
                        'time',
                        'exchange-rates',
                        'users/{user_id}',
                        'prices/{symbol}/buy',
                        'prices/{symbol}/sell',
                        'prices/{symbol}/spot',
                    ],
                },
                'private': {
                    'get': [
                        'accounts',
                        'accounts/{account_id}',
                        'accounts/{account_id}/addresses',
                        'accounts/{account_id}/addresses/{address_id}',
                        'accounts/{account_id}/addresses/{address_id}/transactions',
                        'accounts/{account_id}/transactions',
                        'accounts/{account_id}/transactions/{transaction_id}',
                        'accounts/{account_id}/buys',
                        'accounts/{account_id}/buys/{buy_id}',
                        'accounts/{account_id}/sells',
                        'accounts/{account_id}/sells/{sell_id}',
                        'accounts/{account_id}/deposits',
                        'accounts/{account_id}/deposits/{deposit_id}',
                        'accounts/{account_id}/withdrawals',
                        'accounts/{account_id}/withdrawals/{withdrawal_id}',
                        'payment-methods',
                        'payment-methods/{payment_method_id}',
                        'user',
                        'user/auth',
                    ],
                    'post': [
                        'accounts',
                        'accounts/{account_id}/primary',
                        'accounts/{account_id}/addresses',
                        'accounts/{account_id}/transactions',
                        'accounts/{account_id}/transactions/{transaction_id}/complete',
                        'accounts/{account_id}/transactions/{transaction_id}/resend',
                        'accounts/{account_id}/buys',
                        'accounts/{account_id}/buys/{buy_id}/commit',
                        'accounts/{account_id}/sells',
                        'accounts/{account_id}/sells/{sell_id}/commit',
                        'accounts/{account_id}/deposists',
                        'accounts/{account_id}/deposists/{deposit_id}/commit',
                        'accounts/{account_id}/withdrawals',
                        'accounts/{account_id}/withdrawals/{withdrawal_id}/commit',
                    ],
                    'put': [
                        'accounts/{account_id}',
                        'user',
                    ],
                    'delete': [
                        'accounts/{id}',
                        'accounts/{account_id}/transactions/{transaction_id}',
                    ],
                },
            },
            'exceptions': {
                'two_factor_required': AuthenticationError, // 402 When sending money over 2fa limit
                'param_required': ExchangeError, // 400 Missing parameter
                'validation_error': ExchangeError, // 400 Unable to validate POST/PUT
                'invalid_request': ExchangeError, // 400 Invalid request
                'personal_details_required': AuthenticationError, // 400 User’s personal detail required to complete this request
                'identity_verification_required': AuthenticationError, // 400 Identity verification is required to complete this request
                'jumio_verification_required': AuthenticationError, // 400 Document verification is required to complete this request
                'jumio_face_match_verification_required': AuthenticationError, // 400 Document verification including face match is required to complete this request
                'unverified_email': AuthenticationError, // 400 User has not verified their email
                'authentication_error': AuthenticationError, // 401 Invalid auth (generic)
                'invalid_token': AuthenticationError, // 401 Invalid Oauth token
                'revoked_token': AuthenticationError, // 401 Revoked Oauth token
                'expired_token': AuthenticationError, // 401 Expired Oauth token
                'invalid_scope': AuthenticationError, // 403 User hasn’t authenticated necessary scope
                'not_found': ExchangeError, // 404 Resource not found
                'rate_limit_exceeded': DDoSProtection, // 429 Rate limit exceeded
                'internal_server_error': ExchangeError, // 500 Internal server error
            },
            'markets': {
                'BTC/USD': { 'id': 'btc-usd', 'symbol': 'BTC/USD', 'base': 'BTC', 'quote': 'USD' },
                'LTC/USD': { 'id': 'ltc-usd', 'symbol': 'LTC/USD', 'base': 'LTC', 'quote': 'USD' },
                'ETH/USD': { 'id': 'eth-usd', 'symbol': 'ETH/USD', 'base': 'ETH', 'quote': 'USD' },
                'BCH/USD': { 'id': 'bch-usd', 'symbol': 'BCH/USD', 'base': 'BCH', 'quote': 'USD' },
            },
            'options': {
                'coinbase_version': '2018-05-30',
            },
        });
    }

    async fetchTime () {
        let response = await this.publicGetTime ();
        let data = response['data'];
        return this.parse8601 (data['iso']);
    }

    async fetchCurrencies (params = {}) {
        let response = await this.publicGetCurrencies (params);
        let currencies = response['data'];
        let result = {};
        for (let c = 0; c < currencies.length; c++) {
            let currency = currencies[c];
            let id = currency['id'];
            let name = currency['name'];
            let code = this.commonCurrencyCode (id);
            let minimum = this.safeFloat (currency, 'min_size');
            result[code] = {
                'id': id,
                'code': code,
                'info': currency, // the original payload
                'name': name,
                'active': true,
                'status': 'ok',
                'fee': undefined,
                'precision': undefined,
                'limits': {
                    'amount': {
                        'min': minimum,
                        'max': undefined,
                    },
                    'price': {
                        'min': undefined,
                        'max': undefined,
                    },
                    'cost': {
                        'min': undefined,
                        'max': undefined,
                    },
                    'withdraw': {
                        'min': undefined,
                        'max': undefined,
                    },
                },
            };
        }
        return result;
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let timestamp = this.seconds ();
        let market = this.market (symbol);
        let request = this.extend ({
            'symbol': market['id'],
        }, params);
        let response_buy = await this.publicGetPricesSymbolBuy (request);
        let response_sell = await this.publicGetPricesSymbolSell (request);
        let response_spot = await this.publicGetPricesSymbolSpot (request);
        let buy_data = response_buy['data'];
        let sell_data = response_sell['data'];
        let spot_data = response_spot['data'];
        let buy = this.safeFloat (buy_data, 'amount');
        let sell = this.safeFloat (sell_data, 'amount');
        let spot = this.safeFloat (spot_data, 'amount');
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'bid': sell,
            'ask': buy,
            'last': spot,
            'high': undefined,
            'low': undefined,
            'bidVolume': undefined,
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': undefined,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': undefined,
            'quoteVolume': undefined,
            'info': {
                'buy': response_buy,
                'sell': response_sell,
                'spot': response_spot,
            },
        };
    }

    async fetchBalance (params = {}) {
        let response = await this.privateGetAccounts ();
        let balances = response['data'];
        let result = { 'info': response };
        for (let b = 0; b < balances.length; b++) {
            let balance = balances[b];
            let currency = balance['balance']['currency'];
            let account = {
                'free': this.safeFloat (balance['balance'], 'amount'),
                'used': undefined,
                'total': this.safeFloat (balance['balance'], 'amount'),
            };
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let request = '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        headers = { 'CB-VERSION': this.options['coinbase_version'] };
        if (method === 'GET') {
            if (Object.keys (query).length)
                request += '?' + this.urlencode (query);
        }
        let url = this.urls['api'] + '/' + this.version + request;
        if (api === 'private') {
            this.checkRequiredCredentials ();
            let nonce = this.nonce ().toString ();
            let payload = '';
            if (method !== 'GET') {
                if (Object.keys (query).length) {
                    body = this.json (query);
                    payload = body;
                }
            }
            let what = nonce + method + '/' + this.version + request + payload;
            let signature = this.hmac (this.encode (what), this.encode (this.secret));
            headers = this.extend ({
                'CB-ACCESS-KEY': this.apiKey,
                'CB-ACCESS-SIGN': signature,
                'CB-ACCESS-TIMESTAMP': nonce,
                'Content-Type': 'application/json',
            }, headers);
        }
        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;
            //
            //    {"error": "invalid_request", "error_description": "The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed."}
            //
            // or
            //
            //    {
            //      "errors": [
            //        {
            //          "id": "not_found",
            //          "message": "Not found"
            //        }
            //      ]
            //    }
            //
            let exceptions = this.exceptions;
            let errorCode = this.safeString (response, 'error');
            if (typeof errorCode !== 'undefined') {
                if (errorCode in exceptions) {
                    throw new exceptions[errorCode] (feedback);
                } else {
                    throw new ExchangeError (feedback);
                }
            }
            let errors = this.safeValue (response, 'errors');
            if (typeof errors !== 'undefined') {
                if (Array.isArray (errors)) {
                    let numErrors = errors.length;
                    if (numErrors > 0) {
                        errorCode = this.safeString (errors[0], 'id');
                        if (typeof errorCode !== 'undefined') {
                            if (errorCode in exceptions) {
                                throw new exceptions[errorCode] (feedback);
                            } else {
                                throw new ExchangeError (feedback);
                            }
                        }
                    }
                }
            }
            let data = this.safeValue (response, 'data');
            if (typeof data === 'undefined')
                throw new ExchangeError (this.id + ' failed due to a malformed response ' + this.json (response));
        }
    }
};

<commit_msg>simplified coinbase fetchTicker even further #3063 #3062<commit_after>'use strict';

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

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

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

module.exports = class coinbase extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'coinbase',
            'name': 'coinbase',
            'countries': 'US',
            'rateLimit': 400, // 10k calls per hour
            'version': 'v2',
            'userAgent': this.userAgents['chrome'],
            'has': {
                'CORS': true,
                'cancelOrder': false,
                'createDepositAddress': false,
                'createOrder': false,
                'deposit': false,
                'fetchBalance': true,
                'fetchClosedOrders': false,
                'fetchCurrencies': true,
                'fetchDepositAddress': false,
                'fetchMarkets': false,
                'fetchMyTrades': false,
                'fetchOHLCV': false,
                'fetchOpenOrders': false,
                'fetchOrder': false,
                'fetchOrderBook': false,
                'fetchOrders': false,
                'fetchTicker': true,
                'fetchTickers': false,
                'fetchBidsAsks': false,
                'fetchTrades': false,
                'withdraw': false,
                'fetchTransactions': false,
                'fetchDeposits': false,
                'fetchWithdrawals': false,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/40811661-b6eceae2-653a-11e8-829e-10bfadb078cf.jpg',
                'api': 'https://api.coinbase.com',
                'www': 'https://www.coinbase.com',
                'doc': 'https://developers.coinbase.com/api/v2',
                'fees': 'https://support.coinbase.com/customer/portal/articles/2109597-buy-sell-bank-transfer-fees',
            },
            'requiredCredentials': {
                'apiKey': true,
                'secret': true,
            },
            'api': {
                'public': {
                    'get': [
                        'currencies',
                        'time',
                        'exchange-rates',
                        'users/{user_id}',
                        'prices/{symbol}/buy',
                        'prices/{symbol}/sell',
                        'prices/{symbol}/spot',
                    ],
                },
                'private': {
                    'get': [
                        'accounts',
                        'accounts/{account_id}',
                        'accounts/{account_id}/addresses',
                        'accounts/{account_id}/addresses/{address_id}',
                        'accounts/{account_id}/addresses/{address_id}/transactions',
                        'accounts/{account_id}/transactions',
                        'accounts/{account_id}/transactions/{transaction_id}',
                        'accounts/{account_id}/buys',
                        'accounts/{account_id}/buys/{buy_id}',
                        'accounts/{account_id}/sells',
                        'accounts/{account_id}/sells/{sell_id}',
                        'accounts/{account_id}/deposits',
                        'accounts/{account_id}/deposits/{deposit_id}',
                        'accounts/{account_id}/withdrawals',
                        'accounts/{account_id}/withdrawals/{withdrawal_id}',
                        'payment-methods',
                        'payment-methods/{payment_method_id}',
                        'user',
                        'user/auth',
                    ],
                    'post': [
                        'accounts',
                        'accounts/{account_id}/primary',
                        'accounts/{account_id}/addresses',
                        'accounts/{account_id}/transactions',
                        'accounts/{account_id}/transactions/{transaction_id}/complete',
                        'accounts/{account_id}/transactions/{transaction_id}/resend',
                        'accounts/{account_id}/buys',
                        'accounts/{account_id}/buys/{buy_id}/commit',
                        'accounts/{account_id}/sells',
                        'accounts/{account_id}/sells/{sell_id}/commit',
                        'accounts/{account_id}/deposists',
                        'accounts/{account_id}/deposists/{deposit_id}/commit',
                        'accounts/{account_id}/withdrawals',
                        'accounts/{account_id}/withdrawals/{withdrawal_id}/commit',
                    ],
                    'put': [
                        'accounts/{account_id}',
                        'user',
                    ],
                    'delete': [
                        'accounts/{id}',
                        'accounts/{account_id}/transactions/{transaction_id}',
                    ],
                },
            },
            'exceptions': {
                'two_factor_required': AuthenticationError, // 402 When sending money over 2fa limit
                'param_required': ExchangeError, // 400 Missing parameter
                'validation_error': ExchangeError, // 400 Unable to validate POST/PUT
                'invalid_request': ExchangeError, // 400 Invalid request
                'personal_details_required': AuthenticationError, // 400 User’s personal detail required to complete this request
                'identity_verification_required': AuthenticationError, // 400 Identity verification is required to complete this request
                'jumio_verification_required': AuthenticationError, // 400 Document verification is required to complete this request
                'jumio_face_match_verification_required': AuthenticationError, // 400 Document verification including face match is required to complete this request
                'unverified_email': AuthenticationError, // 400 User has not verified their email
                'authentication_error': AuthenticationError, // 401 Invalid auth (generic)
                'invalid_token': AuthenticationError, // 401 Invalid Oauth token
                'revoked_token': AuthenticationError, // 401 Revoked Oauth token
                'expired_token': AuthenticationError, // 401 Expired Oauth token
                'invalid_scope': AuthenticationError, // 403 User hasn’t authenticated necessary scope
                'not_found': ExchangeError, // 404 Resource not found
                'rate_limit_exceeded': DDoSProtection, // 429 Rate limit exceeded
                'internal_server_error': ExchangeError, // 500 Internal server error
            },
            'markets': {
                'BTC/USD': { 'id': 'btc-usd', 'symbol': 'BTC/USD', 'base': 'BTC', 'quote': 'USD' },
                'LTC/USD': { 'id': 'ltc-usd', 'symbol': 'LTC/USD', 'base': 'LTC', 'quote': 'USD' },
                'ETH/USD': { 'id': 'eth-usd', 'symbol': 'ETH/USD', 'base': 'ETH', 'quote': 'USD' },
                'BCH/USD': { 'id': 'bch-usd', 'symbol': 'BCH/USD', 'base': 'BCH', 'quote': 'USD' },
            },
            'options': {
                'CB-VERSION': '2018-03-05',
            },
        });
    }

    async fetchTime () {
        let response = await this.publicGetTime ();
        let data = response['data'];
        return this.parse8601 (data['iso']);
    }

    async fetchCurrencies (params = {}) {
        let response = await this.publicGetCurrencies (params);
        let currencies = response['data'];
        let result = {};
        for (let c = 0; c < currencies.length; c++) {
            let currency = currencies[c];
            let id = currency['id'];
            let name = currency['name'];
            let code = this.commonCurrencyCode (id);
            let minimum = this.safeFloat (currency, 'min_size');
            result[code] = {
                'id': id,
                'code': code,
                'info': currency, // the original payload
                'name': name,
                'active': true,
                'status': 'ok',
                'fee': undefined,
                'precision': undefined,
                'limits': {
                    'amount': {
                        'min': minimum,
                        'max': undefined,
                    },
                    'price': {
                        'min': undefined,
                        'max': undefined,
                    },
                    'cost': {
                        'min': undefined,
                        'max': undefined,
                    },
                    'withdraw': {
                        'min': undefined,
                        'max': undefined,
                    },
                },
            };
        }
        return result;
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let timestamp = this.seconds ();
        let market = this.market (symbol);
        let request = this.extend ({
            'symbol': market['id'],
        }, params);
        let buy = await this.publicGetPricesSymbolBuy (request);
        let sell = await this.publicGetPricesSymbolSell (request);
        let spot = await this.publicGetPricesSymbolSpot (request);
        let ask = this.safeFloat (buy['data'], 'amount');
        let bid = this.safeFloat (sell['data'], 'amount');
        let last = this.safeFloat (spot['data'], 'amount');
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'bid': bid,
            'ask': ask,
            'last': last,
            'high': undefined,
            'low': undefined,
            'bidVolume': undefined,
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': undefined,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': undefined,
            'quoteVolume': undefined,
            'info': {
                'buy': buy,
                'sell': sell,
                'spot': spot,
            },
        };
    }

    async fetchBalance (params = {}) {
        let response = await this.privateGetAccounts ();
        let balances = response['data'];
        let result = { 'info': response };
        for (let b = 0; b < balances.length; b++) {
            let balance = balances[b];
            let currency = balance['balance']['currency'];
            let account = {
                'free': this.safeFloat (balance['balance'], 'amount'),
                'used': undefined,
                'total': this.safeFloat (balance['balance'], 'amount'),
            };
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let request = '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        headers = {
            'CB-VERSION': this.options['CB-VERSION'],
        };
        if (method === 'GET') {
            if (Object.keys (query).length)
                request += '?' + this.urlencode (query);
        }
        let url = this.urls['api'] + '/' + this.version + request;
        if (api === 'private') {
            this.checkRequiredCredentials ();
            let nonce = this.nonce ().toString ();
            let payload = '';
            if (method !== 'GET') {
                if (Object.keys (query).length) {
                    body = this.json (query);
                    payload = body;
                }
            }
            let what = nonce + method + '/' + this.version + request + payload;
            let signature = this.hmac (this.encode (what), this.encode (this.secret));
            headers = this.extend ({
                'CB-ACCESS-KEY': this.apiKey,
                'CB-ACCESS-SIGN': signature,
                'CB-ACCESS-TIMESTAMP': nonce,
                'Content-Type': 'application/json',
            }, headers);
        }
        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;
            //
            //    {"error": "invalid_request", "error_description": "The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed."}
            //
            // or
            //
            //    {
            //      "errors": [
            //        {
            //          "id": "not_found",
            //          "message": "Not found"
            //        }
            //      ]
            //    }
            //
            let exceptions = this.exceptions;
            let errorCode = this.safeString (response, 'error');
            if (typeof errorCode !== 'undefined') {
                if (errorCode in exceptions) {
                    throw new exceptions[errorCode] (feedback);
                } else {
                    throw new ExchangeError (feedback);
                }
            }
            let errors = this.safeValue (response, 'errors');
            if (typeof errors !== 'undefined') {
                if (Array.isArray (errors)) {
                    let numErrors = errors.length;
                    if (numErrors > 0) {
                        errorCode = this.safeString (errors[0], 'id');
                        if (typeof errorCode !== 'undefined') {
                            if (errorCode in exceptions) {
                                throw new exceptions[errorCode] (feedback);
                            } else {
                                throw new ExchangeError (feedback);
                            }
                        }
                    }
                }
            }
            let data = this.safeValue (response, 'data');
            if (typeof data === 'undefined')
                throw new ExchangeError (this.id + ' failed due to a malformed response ' + this.json (response));
        }
    }
};

<|endoftext|>