<commit_before>'use strict'

/*
 * Copyright (c) 2013-2021 node-coap contributors.
 *
 * node-coap is licensed under an MIT +no-false-attribs license.
 * All rights not explicitly granted in the MIT license are reserved.
 * See the included LICENSE file for more details.
 */

const crypto = require('crypto')
const events = require('events')
const dgram = require('dgram')
const parse = require('coap-packet').parse
const generate = require('coap-packet').generate
const IncomingMessage = require('./incoming_message')
const OutgoingMessage = require('./outgoing_message')
const ObserveStream = require('./observe_read_stream')
const RetrySend = require('./retry_send')
const parseBlock2 = require('./helpers').parseBlock2
const createBlock2 = require('./helpers').createBlock2
const getOption = require('./helpers').getOption
const removeOption = require('./helpers').removeOption
const maxToken = Math.pow(2, 32)
const maxMessageId = Math.pow(2, 16)
const pf = require('./polyfill')
const SegmentedTransmission = require('./segmentation').SegmentedTransmission
const parseBlockOption = require('./block').parseBlockOption

class Agent extends events.EventEmitter {
    constructor (opts) {
        super()

        if (!opts) {
            opts = {}
        }

        if (!opts.type) {
            opts.type = 'udp4'
        }

        if (opts.socket) {
            opts.type = opts.socket.type
            delete opts.port
        }

        this._opts = opts

        this._init(opts.socket)
    }

    _init (socket) {
        this._closing = false

        if (this._sock) {
            return
        }

        this._sock = socket || dgram.createSocket(this._opts.type)
        this._sock.on('message', (msg, rsinfo) => {
            let packet
            try {
                packet = parse(msg)
            } catch (err) {
                return
            }

            if (packet.code[0] === '0' && packet.code !== '0.00') {
                // ignore this packet since it's not a response.
                return
            }

            const outSocket = this._sock.address()
            this._handle(msg, rsinfo, outSocket)
        })

        if (this._opts.port) {
            this._sock.bind(this._opts.port)
        }

        this._sock.on('error', (err) => {
            this.emit('error', err)
        })

        this._msgIdToReq = {}
        this._tkToReq = {}
        this._tkToMulticastResAddr = {}

        this._lastToken = Math.floor(Math.random() * (maxToken - 1))
        this._lastMessageId = Math.floor(Math.random() * (maxMessageId - 1))

        this._msgInFlight = 0
        this._requests = 0
    }

    _cleanUp () {
        if (--this._requests !== 0) {
            return
        }

        if (!this._opts.socket) {
            this._closing = true
        }

        if (this._msgInFlight !== 0) {
            return
        }

        this._doClose()
    }

    _doClose () {
        for (const k in this._msgIdToReq) {
            this._msgIdToReq[k].sender.reset()
        }

        if (this._opts.socket) {
            return
        }

        this._sock.close()
        this._sock = null
    }

    _handle (msg, rsinfo, outSocket) {
        const packet = parse(msg)
        let buf
        let response
        let req = this._msgIdToReq[packet.messageId]
        const ackSent = (err) => {
            if (err && req) {
                req.emit('error', err)
            }

            this._msgInFlight--
            if (this._closing && this._msgInFlight === 0) {
                this._doClose()
            }
        }
        if (!req) {
            if (packet.token.length > 0) {
                req = this._tkToReq[packet.token.toString('hex')]
            }

            if ((packet.ack || packet.reset) && !req) {
                // Nothing to do on unknown or duplicate ACK/RST packet
                return
            }

            if (!req) {
                buf = generate({
                    code: '0.00',
                    reset: true,
                    messageId: packet.messageId
                })

                this._msgInFlight++
                this._sock.send(buf, 0, buf.length, rsinfo.port, rsinfo.address, ackSent)
                return
            }
        }

        if (packet.confirmable) {
            buf = generate({
                code: '0.00',
                ack: true,
                messageId: packet.messageId
            })

            this._msgInFlight++
            this._sock.send(buf, 0, buf.length, rsinfo.port, rsinfo.address, ackSent)
        }

        if (packet.code !== '0.00' && (req._packet.token.length !== packet.token.length || pf.compareBuffers(req._packet.token, packet.token) !== 0)) {
        // The tokens don't match, ignore the message since it is a malformed response
            return
        }

        const block1Buff = getOption(packet.options, 'Block1')
        let block1
        if (block1Buff) {
            block1 = parseBlockOption(block1Buff)
            // check for error
            if (!block1) {
                req.sender.reset()
                return req.emit('error', new Error('Failed to parse block1'))
            }
        }

        req.sender.reset()

        if (block1 && packet.ack) {
        // var initialRequest = this._msgIdToReq[packet.messageId];
        // If the client takes too long to respond then the retry sender will send
        // another packet with the previous messageId, which we've already removed.
            const segmentedSender = req.segmentedSender
            if (segmentedSender) {
                // If there's more to send/receive, then carry on!
                if (segmentedSender.remaining() > 0) {
                    if (segmentedSender.isCorrectACK(packet, block1)) {
                        delete this._msgIdToReq[req._packet.messageId]
                        req._packet.messageId = this._nextMessageId()
                        this._msgIdToReq[req._packet.messageId] = req
                        segmentedSender.receiveACK(packet, block1)
                    } else {
                        segmentedSender.resendPreviousPacket()
                    }
                    return
                } else {
                    // console.log("Packet received done");
                    removeOption(req._packet.options, 'Block1')
                    delete req.segmentedSender
                }
            }
        }

        if (!packet.confirmable && !req.multicast) {
            delete this._msgIdToReq[packet.messageId]
        }

        // Drop empty messages (ACKs), but process RST
        if (packet.code === '0.00' && !packet.reset) {
            return
        }

        const block2Buff = getOption(packet.options, 'Block2')
        let block2
        // if we got blockwise (2) response
        if (block2Buff) {
            block2 = parseBlock2(block2Buff)
            // check for error
            if (!block2) {
                req.sender.reset()
                return req.emit('error', new Error('failed to parse block2'))
            }
        }
        if (block2) {
            if (req.multicast) {
                req = this._convertMulticastToUnicastRequest(req, rsinfo)
                if (!req) {
                    return
                }
            }

            // accumulate payload
            req._totalPayload = Buffer.concat([req._totalPayload, packet.payload])

            if (block2.moreBlock2) {
                // increase message id for next request
                delete this._msgIdToReq[req._packet.messageId]
                req._packet.messageId = this._nextMessageId()
                this._msgIdToReq[req._packet.messageId] = req

                // next block2 request
                const block2Val = createBlock2({
                    moreBlock2: false,
                    num: block2.num + 1,
                    size: block2.size
                })
                if (!block2Val) {
                    req.sender.reset()
                    return req.emit('error', new Error('failed to create block2'))
                }
                req.setOption('Block2', block2Val)
                req._packet.payload = null
                req.sender.send(generate(req._packet))

                return
            } else {
                // get full payload
                packet.payload = req._totalPayload
                // clear the payload incase of block2
                req._totalPayload = Buffer.alloc(0)
            }
        }

        if (req.response) {
            if (req.response.append) {
                // it is an observe request
                // and we are already streaming
                return req.response.append(packet)
            } else {
                // TODO There is a previous response but is not an ObserveStream !
                return
            }
        } else if (block2) {
            delete this._tkToReq[req._packet.token.toString('hex')]
        } else if (!req.url.observe && !req.multicast) {
        // it is not, so delete the token
            delete this._tkToReq[packet.token.toString('hex')]
        }

        if (req.url.observe && packet.code !== '4.04') {
            response = new ObserveStream(packet, rsinfo, outSocket)
            response.on('close', () => {
                delete this._tkToReq[packet.token.toString('hex')]
                this._cleanUp()
            })
            response.on('deregister', () => {
                const deregisterUrl = Object.assign({}, req.url)
                deregisterUrl.observe = 1
                deregisterUrl.token = req._packet.token

                const deregisterReq = this.request(deregisterUrl)
                // If the request fails, we'll deal with it with a RST message anyway.
                deregisterReq.on('error', () => {})
                deregisterReq.end()
            })
        } else {
            response = new IncomingMessage(packet, rsinfo, outSocket)
        }

        if (!req.multicast) {
            req.response = response
        }

        req.emit('response', response)
    }

    _nextToken () {
        const buf = Buffer.alloc(8)

        if (++this._lastToken === maxToken) {
            this._lastToken = 0
        }

        buf.writeUInt32BE(this._lastToken, 0)
        crypto.randomBytes(4).copy(buf, 4)

        return buf
    }

    _nextMessageId () {
        if (++this._lastMessageId === maxMessageId) {
            this._lastMessageId = 0
        }

        return this._lastMessageId
    }

    /**
     * Entry point for a new client-side request.
     * @param {*} url A String representing a CoAP URL, or an object with the appropriate parameters.
     */
    request (url) {
        this._init()

        const options = url.options || url.headers
        let option
        const multicastTimeout = url.multicastTimeout !== undefined ? parseInt(url.multicastTimeout) : 20000

        const req = new OutgoingMessage({}, (req, packet) => {
            let buf

            if (url.confirmable !== false) {
                packet.confirmable = true
            }

            // multicast message should be forced non-confirmable
            if (url.multicast === true) {
                req.multicast = true
                packet.confirmable = false
            }

            let token
            if (!(packet.ack || packet.reset)) {
                packet.messageId = this._nextMessageId()
                if ((url.token instanceof Buffer) && (url.token.length > 0)) {
                    if (url.token.length > 8) {
                        return req.emit('error', new Error('Token may be no longer than 8 bytes.'))
                    }
                    packet.token = url.token
                } else {
                    packet.token = this._nextToken()
                }
                token = packet.token.toString('hex')
                this._tkToMulticastResAddr[token] = []
                if (req.multicast) {
                    this._tkToMulticastResAddr[token] = []
                }
            }

            this._msgIdToReq[packet.messageId] = req
            if (token) {
                this._tkToReq[token] = req
            }

            const block1Buff = getOption(packet.options, 'Block1')
            if (block1Buff) {
                // Setup for a segmented transmission
                req.segmentedSender = new SegmentedTransmission(block1Buff[0], req, packet)
                req.segmentedSender.sendNext()
            } else {
                try {
                    buf = generate(packet)
                } catch (err) {
                    req.sender.reset()
                    return req.emit('error', err)
                }
                req.sender.send(buf, !packet.confirmable)
            }
        })

        req.sender = new RetrySend(this._sock, url.port, url.hostname || url.host, url.retrySend)

        req.url = url

        req.statusCode = url.method || 'GET'

        this.urlPropertyToPacketOption(url, req, 'pathname', 'Uri-Path', '/')
        this.urlPropertyToPacketOption(url, req, 'query', 'Uri-Query', '&')

        if (options) {
            for (option in options) {
                if (Object.prototype.hasOwnProperty.call(options, option)) {
                    req.setOption(option, options[option])
                }
            }
        }

        if (url.proxyUri) {
            req.setOption('Proxy-Uri', url.proxyUri)
        }

        req.sender.on('error', req.emit.bind(req, 'error'))

        req.sender.on('sending', () => {
            this._msgInFlight++
        })

        req.sender.on('timeout', (err) => {
            req.emit('timeout', err)
            this.abort(req)
        })

        req.sender.on('sent', () => {
            if (req.multicast) return

            this._msgInFlight--
            if (this._closing && this._msgInFlight === 0) {
                this._doClose()
            }
        })

        // Start multicast monitoring timer in case of multicast request
        if (url.multicast === true) {
            req.multicastTimer = setTimeout(() => {
                if (req._packet.token) {
                    const token = req._packet.token.toString('hex')
                    delete this._tkToReq[token]
                    delete this._tkToMulticastResAddr[token]
                }
                delete this._msgIdToReq[req._packet.messageId]
                this._msgInFlight--
                if (this._msgInFlight === 0 && this._closing) {
                    this._doClose()
                }
            }, multicastTimeout)
        }

        if (typeof (url.observe) === 'number') {
            req.setOption('Observe', url.observe)
        } else if (url.observe) {
            req.setOption('Observe', null)
        } else {
            req.on('response', this._cleanUp.bind(this))
        }

        this._requests++

        req._totalPayload = Buffer.alloc(0)

        return req
    }

    abort (req) {
        req.sender.removeAllListeners()
        req.sender.reset()
        this._cleanUp()
        delete this._msgIdToReq[req._packet.messageId]
        if (req._packet.token) {
            delete this._tkToReq[req._packet.token.toString('hex')]
        }
    }

    urlPropertyToPacketOption (url, req, property, option, separator) {
        if (url[property]) {
            req.setOption(option, url[property].normalize('NFC').split(separator)
                .filter((part) => { return part !== '' })
                .map((part) => {
                    const buf = Buffer.alloc(Buffer.byteLength(part))
                    buf.write(part)
                    return buf
                }))
        }
    }

    _convertMulticastToUnicastRequest (req, rsinfo) {
        const unicastReq = this.request(req.url)
        const unicastAddress = rsinfo.address.split('%')[0]
        const token = req._packet.token.toString('hex')
        if (this._tkToMulticastResAddr[token].includes(unicastAddress)) {
            return null
        }

        unicastReq.url.host = unicastAddress
        unicastReq.sender._host = unicastAddress
        clearTimeout(unicastReq.multicastTimer)
        unicastReq.url.multicast = false
        req.eventNames().forEach(eventName => {
            req.listeners(eventName).forEach(listener => {
                unicastReq.on(eventName, listener)
            })
        })
        this._tkToMulticastResAddr[token].push(unicastAddress)
        unicastReq._packet.token = this._nextToken()
        this._requests++
        return unicastReq
    }
}

module.exports = Agent
<commit_msg>refactor(agent): remove obsolete token statements (#286)<commit_after>'use strict'

/*
 * Copyright (c) 2013-2021 node-coap contributors.
 *
 * node-coap is licensed under an MIT +no-false-attribs license.
 * All rights not explicitly granted in the MIT license are reserved.
 * See the included LICENSE file for more details.
 */

const crypto = require('crypto')
const events = require('events')
const dgram = require('dgram')
const parse = require('coap-packet').parse
const generate = require('coap-packet').generate
const IncomingMessage = require('./incoming_message')
const OutgoingMessage = require('./outgoing_message')
const ObserveStream = require('./observe_read_stream')
const RetrySend = require('./retry_send')
const parseBlock2 = require('./helpers').parseBlock2
const createBlock2 = require('./helpers').createBlock2
const getOption = require('./helpers').getOption
const removeOption = require('./helpers').removeOption
const maxToken = Math.pow(2, 32)
const maxMessageId = Math.pow(2, 16)
const pf = require('./polyfill')
const SegmentedTransmission = require('./segmentation').SegmentedTransmission
const parseBlockOption = require('./block').parseBlockOption

class Agent extends events.EventEmitter {
    constructor (opts) {
        super()

        if (!opts) {
            opts = {}
        }

        if (!opts.type) {
            opts.type = 'udp4'
        }

        if (opts.socket) {
            opts.type = opts.socket.type
            delete opts.port
        }

        this._opts = opts

        this._init(opts.socket)
    }

    _init (socket) {
        this._closing = false

        if (this._sock) {
            return
        }

        this._sock = socket || dgram.createSocket(this._opts.type)
        this._sock.on('message', (msg, rsinfo) => {
            let packet
            try {
                packet = parse(msg)
            } catch (err) {
                return
            }

            if (packet.code[0] === '0' && packet.code !== '0.00') {
                // ignore this packet since it's not a response.
                return
            }

            const outSocket = this._sock.address()
            this._handle(msg, rsinfo, outSocket)
        })

        if (this._opts.port) {
            this._sock.bind(this._opts.port)
        }

        this._sock.on('error', (err) => {
            this.emit('error', err)
        })

        this._msgIdToReq = {}
        this._tkToReq = {}
        this._tkToMulticastResAddr = {}

        this._lastToken = Math.floor(Math.random() * (maxToken - 1))
        this._lastMessageId = Math.floor(Math.random() * (maxMessageId - 1))

        this._msgInFlight = 0
        this._requests = 0
    }

    _cleanUp () {
        if (--this._requests !== 0) {
            return
        }

        if (!this._opts.socket) {
            this._closing = true
        }

        if (this._msgInFlight !== 0) {
            return
        }

        this._doClose()
    }

    _doClose () {
        for (const k in this._msgIdToReq) {
            this._msgIdToReq[k].sender.reset()
        }

        if (this._opts.socket) {
            return
        }

        this._sock.close()
        this._sock = null
    }

    _handle (msg, rsinfo, outSocket) {
        const packet = parse(msg)
        let buf
        let response
        let req = this._msgIdToReq[packet.messageId]
        const ackSent = (err) => {
            if (err && req) {
                req.emit('error', err)
            }

            this._msgInFlight--
            if (this._closing && this._msgInFlight === 0) {
                this._doClose()
            }
        }
        if (!req) {
            if (packet.token.length > 0) {
                req = this._tkToReq[packet.token.toString('hex')]
            }

            if ((packet.ack || packet.reset) && !req) {
                // Nothing to do on unknown or duplicate ACK/RST packet
                return
            }

            if (!req) {
                buf = generate({
                    code: '0.00',
                    reset: true,
                    messageId: packet.messageId
                })

                this._msgInFlight++
                this._sock.send(buf, 0, buf.length, rsinfo.port, rsinfo.address, ackSent)
                return
            }
        }

        if (packet.confirmable) {
            buf = generate({
                code: '0.00',
                ack: true,
                messageId: packet.messageId
            })

            this._msgInFlight++
            this._sock.send(buf, 0, buf.length, rsinfo.port, rsinfo.address, ackSent)
        }

        if (packet.code !== '0.00' && (req._packet.token.length !== packet.token.length || pf.compareBuffers(req._packet.token, packet.token) !== 0)) {
        // The tokens don't match, ignore the message since it is a malformed response
            return
        }

        const block1Buff = getOption(packet.options, 'Block1')
        let block1
        if (block1Buff) {
            block1 = parseBlockOption(block1Buff)
            // check for error
            if (!block1) {
                req.sender.reset()
                return req.emit('error', new Error('Failed to parse block1'))
            }
        }

        req.sender.reset()

        if (block1 && packet.ack) {
        // var initialRequest = this._msgIdToReq[packet.messageId];
        // If the client takes too long to respond then the retry sender will send
        // another packet with the previous messageId, which we've already removed.
            const segmentedSender = req.segmentedSender
            if (segmentedSender) {
                // If there's more to send/receive, then carry on!
                if (segmentedSender.remaining() > 0) {
                    if (segmentedSender.isCorrectACK(packet, block1)) {
                        delete this._msgIdToReq[req._packet.messageId]
                        req._packet.messageId = this._nextMessageId()
                        this._msgIdToReq[req._packet.messageId] = req
                        segmentedSender.receiveACK(packet, block1)
                    } else {
                        segmentedSender.resendPreviousPacket()
                    }
                    return
                } else {
                    // console.log("Packet received done");
                    removeOption(req._packet.options, 'Block1')
                    delete req.segmentedSender
                }
            }
        }

        if (!packet.confirmable && !req.multicast) {
            delete this._msgIdToReq[packet.messageId]
        }

        // Drop empty messages (ACKs), but process RST
        if (packet.code === '0.00' && !packet.reset) {
            return
        }

        const block2Buff = getOption(packet.options, 'Block2')
        let block2
        // if we got blockwise (2) response
        if (block2Buff) {
            block2 = parseBlock2(block2Buff)
            // check for error
            if (!block2) {
                req.sender.reset()
                return req.emit('error', new Error('failed to parse block2'))
            }
        }
        if (block2) {
            if (req.multicast) {
                req = this._convertMulticastToUnicastRequest(req, rsinfo)
                if (!req) {
                    return
                }
            }

            // accumulate payload
            req._totalPayload = Buffer.concat([req._totalPayload, packet.payload])

            if (block2.moreBlock2) {
                // increase message id for next request
                delete this._msgIdToReq[req._packet.messageId]
                req._packet.messageId = this._nextMessageId()
                this._msgIdToReq[req._packet.messageId] = req

                // next block2 request
                const block2Val = createBlock2({
                    moreBlock2: false,
                    num: block2.num + 1,
                    size: block2.size
                })
                if (!block2Val) {
                    req.sender.reset()
                    return req.emit('error', new Error('failed to create block2'))
                }
                req.setOption('Block2', block2Val)
                req._packet.payload = null
                req.sender.send(generate(req._packet))

                return
            } else {
                // get full payload
                packet.payload = req._totalPayload
                // clear the payload incase of block2
                req._totalPayload = Buffer.alloc(0)
            }
        }

        if (req.response) {
            if (req.response.append) {
                // it is an observe request
                // and we are already streaming
                return req.response.append(packet)
            } else {
                // TODO There is a previous response but is not an ObserveStream !
                return
            }
        } else if (block2) {
            delete this._tkToReq[req._packet.token.toString('hex')]
        } else if (!req.url.observe && !req.multicast) {
        // it is not, so delete the token
            delete this._tkToReq[packet.token.toString('hex')]
        }

        if (req.url.observe && packet.code !== '4.04') {
            response = new ObserveStream(packet, rsinfo, outSocket)
            response.on('close', () => {
                delete this._tkToReq[packet.token.toString('hex')]
                this._cleanUp()
            })
            response.on('deregister', () => {
                const deregisterUrl = Object.assign({}, req.url)
                deregisterUrl.observe = 1
                deregisterUrl.token = req._packet.token

                const deregisterReq = this.request(deregisterUrl)
                // If the request fails, we'll deal with it with a RST message anyway.
                deregisterReq.on('error', () => {})
                deregisterReq.end()
            })
        } else {
            response = new IncomingMessage(packet, rsinfo, outSocket)
        }

        if (!req.multicast) {
            req.response = response
        }

        req.emit('response', response)
    }

    _nextToken () {
        const buf = Buffer.alloc(8)

        if (++this._lastToken === maxToken) {
            this._lastToken = 0
        }

        buf.writeUInt32BE(this._lastToken, 0)
        crypto.randomBytes(4).copy(buf, 4)

        return buf
    }

    _nextMessageId () {
        if (++this._lastMessageId === maxMessageId) {
            this._lastMessageId = 0
        }

        return this._lastMessageId
    }

    /**
     * Entry point for a new client-side request.
     * @param {*} url A String representing a CoAP URL, or an object with the appropriate parameters.
     */
    request (url) {
        this._init()

        const options = url.options || url.headers
        let option
        const multicastTimeout = url.multicastTimeout !== undefined ? parseInt(url.multicastTimeout) : 20000

        const req = new OutgoingMessage({}, (req, packet) => {
            let buf

            if (url.confirmable !== false) {
                packet.confirmable = true
            }

            // multicast message should be forced non-confirmable
            if (url.multicast === true) {
                req.multicast = true
                packet.confirmable = false
            }

            if (!(packet.ack || packet.reset)) {
                packet.messageId = this._nextMessageId()
                if ((url.token instanceof Buffer) && (url.token.length > 0)) {
                    if (url.token.length > 8) {
                        return req.emit('error', new Error('Token may be no longer than 8 bytes.'))
                    }
                    packet.token = url.token
                } else {
                    packet.token = this._nextToken()
                }
                const token = packet.token.toString('hex')
                if (req.multicast) {
                    this._tkToMulticastResAddr[token] = []
                }
                if (token) {
                    this._tkToReq[token] = req
                }
            }

            this._msgIdToReq[packet.messageId] = req

            const block1Buff = getOption(packet.options, 'Block1')
            if (block1Buff) {
                // Setup for a segmented transmission
                req.segmentedSender = new SegmentedTransmission(block1Buff[0], req, packet)
                req.segmentedSender.sendNext()
            } else {
                try {
                    buf = generate(packet)
                } catch (err) {
                    req.sender.reset()
                    return req.emit('error', err)
                }
                req.sender.send(buf, !packet.confirmable)
            }
        })

        req.sender = new RetrySend(this._sock, url.port, url.hostname || url.host, url.retrySend)

        req.url = url

        req.statusCode = url.method || 'GET'

        this.urlPropertyToPacketOption(url, req, 'pathname', 'Uri-Path', '/')
        this.urlPropertyToPacketOption(url, req, 'query', 'Uri-Query', '&')

        if (options) {
            for (option in options) {
                if (Object.prototype.hasOwnProperty.call(options, option)) {
                    req.setOption(option, options[option])
                }
            }
        }

        if (url.proxyUri) {
            req.setOption('Proxy-Uri', url.proxyUri)
        }

        req.sender.on('error', req.emit.bind(req, 'error'))

        req.sender.on('sending', () => {
            this._msgInFlight++
        })

        req.sender.on('timeout', (err) => {
            req.emit('timeout', err)
            this.abort(req)
        })

        req.sender.on('sent', () => {
            if (req.multicast) return

            this._msgInFlight--
            if (this._closing && this._msgInFlight === 0) {
                this._doClose()
            }
        })

        // Start multicast monitoring timer in case of multicast request
        if (url.multicast === true) {
            req.multicastTimer = setTimeout(() => {
                if (req._packet.token) {
                    const token = req._packet.token.toString('hex')
                    delete this._tkToReq[token]
                    delete this._tkToMulticastResAddr[token]
                }
                delete this._msgIdToReq[req._packet.messageId]
                this._msgInFlight--
                if (this._msgInFlight === 0 && this._closing) {
                    this._doClose()
                }
            }, multicastTimeout)
        }

        if (typeof (url.observe) === 'number') {
            req.setOption('Observe', url.observe)
        } else if (url.observe) {
            req.setOption('Observe', null)
        } else {
            req.on('response', this._cleanUp.bind(this))
        }

        this._requests++

        req._totalPayload = Buffer.alloc(0)

        return req
    }

    abort (req) {
        req.sender.removeAllListeners()
        req.sender.reset()
        this._cleanUp()
        delete this._msgIdToReq[req._packet.messageId]
        if (req._packet.token) {
            delete this._tkToReq[req._packet.token.toString('hex')]
        }
    }

    urlPropertyToPacketOption (url, req, property, option, separator) {
        if (url[property]) {
            req.setOption(option, url[property].normalize('NFC').split(separator)
                .filter((part) => { return part !== '' })
                .map((part) => {
                    const buf = Buffer.alloc(Buffer.byteLength(part))
                    buf.write(part)
                    return buf
                }))
        }
    }

    _convertMulticastToUnicastRequest (req, rsinfo) {
        const unicastReq = this.request(req.url)
        const unicastAddress = rsinfo.address.split('%')[0]
        const token = req._packet.token.toString('hex')
        if (this._tkToMulticastResAddr[token].includes(unicastAddress)) {
            return null
        }

        unicastReq.url.host = unicastAddress
        unicastReq.sender._host = unicastAddress
        clearTimeout(unicastReq.multicastTimer)
        unicastReq.url.multicast = false
        req.eventNames().forEach(eventName => {
            req.listeners(eventName).forEach(listener => {
                unicastReq.on(eventName, listener)
            })
        })
        this._tkToMulticastResAddr[token].push(unicastAddress)
        unicastReq._packet.token = this._nextToken()
        this._requests++
        return unicastReq
    }
}

module.exports = Agent
<|endoftext|>


<commit_before>(function(module) {

  module.exports = function(str) {
    console.log('!', str, '!');
  }

}(
  (this.Module) ?
    Module('alert') :
    module
));

<commit_msg>update alert to same format as other files<commit_after>(function(module, ns) {

  module.exports = function(str) {
    console.log('!', str, '!');
  }

}.apply(
  this,
  (this.Module)?
    [Module('alert'), Module] :
    [module, require('./ns')]
));
<|endoftext|>


<commit_before>import retry from 'async-retry';
import dns from 'dns';
import Now from '../lib';
import toHost from './to-host';
import chalk from 'chalk';

export default class Alias extends Now {

  async ls (deployment) {
    if (deployment) {
      const target = await this.findDeployment(deployment);
      if (!target) {
        const err = new Error(`Aliases not found by "${deployment}". Run ${chalk.dim('`now alias ls`')} to see your aliases.`);
        err.userError = true;
        throw err;
      }

      return this.retry(async (bail, attempt) => {
        const res = await this._fetch(`/now/deployments/${target.uid}/aliases`);
        const body = await res.json();
        return body.aliases;
      });
    }

    return this.retry(async (bail, attempt) => {
      const res = await this._fetch('/now/aliases');
      const body = await res.json();
      return body.aliases;
    });
  }

  async rm (alias) {
    const _alias = await this.findAlias(alias);
    if (!_alias) {
      const err = new Error(`Alias not found by "${alias}". Run ${chalk.dim('`now alias ls`')} to see your aliases.`);
      err.userError = true;
      throw err;
    }

    return this.retry(async (bail, attempt) => {
      const res = await this._fetch(`/now/aliases/${_alias.uid}`, {
        method: 'DELETE'
      });

      if (403 === res.status) {
        return bail(new Error('Unauthorized'));
      }

      if (res.status !== 200) {
        const err = new Error('Deletion failed. Try again later.');
        throw err;
      }

      console.log(`${chalk.cyan('> Success!')}`);
    });
  }

  async findAlias (alias) {
    const list = await this.ls();

    let key, val;
    if (/\./.test(alias)) {
      val = toHost(alias);
      key = 'alias';
    } else {
      val = alias;
      key = 'uid';
    }

    const _alias = list.find((d) => {
      if (d[key] === val) {
        if (this._debug) console.log(`> [debug] matched alias ${d.uid} by ${key} ${val}`);
        return true;
      }

      // match prefix
      if (`${val}.now.sh` === d.alias) {
        if (this._debug) console.log(`> [debug] matched alias ${d.uid} by url ${d.host}`);
        return true;
      }

      return false;
    });

    return _alias;
  }

  async findDeployment (deployment) {
    const list = await this.list();
    let key, val;
    if (/\./.test(deployment)) {
      val = toHost(deployment);
      key = 'url';
    } else {
      val = deployment;
      key = 'uid';
    }

    const depl = list.find((d) => {
      if (d[key] === val) {
        if (this._debug) console.log(`> [debug] matched deployment ${d.uid} by ${key} ${val}`);
        return true;
      }

      // match prefix
      if (`${val}.now.sh` === d.url) {
        if (this._debug) console.log(`> [debug] matched deployment ${d.uid} by url ${d.url}`);
        return true;
      }

      return false;
    });

    return depl;
  }

  async set (deployment, alias) {
    const depl = await this.findDeployment(deployment);
    if (!depl) {
      const err = new Error(`Deployment not found by "${deployment}". Run ${chalk.dim('`now ls`')} to see your deployments.`);
      err.userError = true;
      throw err;
    }

    // evaluate the alias
    if (!/\./.test(alias)) {
      if (this._debug) console.log(`> [debug] suffixing \`.now.sh\` to alias ${alias}`);
      alias = `${alias}.now.sh`;
    } else {
      alias = toHost(alias);
    }

    await this.createAlias(depl, alias);
    console.log(`${chalk.cyan('> Success!')} Set up alias ${chalk.bold(alias)}`);
  }

  async createAlias (depl, alias) {
    return this.retry(async (bail, attempt) => {
      if (this._debug) console.time(`> [debug] /now/deployments/${depl.uid}/aliases #${attempt}`);
      const res = await this._fetch(`/now/deployments/${depl.uid}/aliases`, {
        method: 'POST',
        body: { alias }
      });

      if (304 === res.status) return;

      const body = await res.json();
      if (this._debug) console.timeEnd(`> [debug] /now/deployments/${depl.uid}/aliases #${attempt}`);

      // no retry on authorization problems
      if (403 === res.status) {
        const code = body.error.code;

        if ('custom_domain_needs_upgrade' === code) {
          const err = new Error(`You are attempting to use a custom domain alias (${chalk.underline(chalk.cyan(alias))}), but this is only enabled for premium accounts. Please upgrade at ${chalk.underline('https://zeit.co/account')}`);
          err.userError = true;
          return bail(err);
        }

        if ('alias_in_use' === code) {
          const err = new Error(`The alias you are trying to configure (${chalk.underline(chalk.cyan(alias))}) is already in use by a different account.`);
          err.userError = true;
          return bail(err);
        }

        return bail(new Error('Authorization error'));
      }

      // all other errors
      if (body.error) {
        const code = body.error.code;

        if ('deployment_not_found' === code) {
          return bail(new Error('Deployment not found'));
        }

        if ('cert_missing' === code) {
          console.log(`> Provisioning certificate for ${chalk.underline(chalk.cyan(alias))}`);

          await this.verifyOwnership();
          await this.createCert();

          // try again, but now having provisioned the certificate
          return this.createAlias(depl, alias);
        }

        return bail(new Error(body.error.message));
      }

      // the two expected succesful cods are 200 and 304
      if (200 !== res.status && 304 !== res.status) {
        throw new Error('Unhandled error');
      }
    });
  }

  async verifyOwnership (domain) {
    return this.retry(async (bail, attempt) => {
      const targets = await resolve4('alias.zeit.co');

      if (!targets.length) {
        return bail(new Error('Unable to resolve alias.zeit.co'));
      }

      const ips = await resolve4(domain);
      if (!ips.length) {
        const err = new Error('The domain ${domain} A record in the DNS configuration is not returning any IPs.');
        err.userError = true;
        return bail(err);
      }

      for (const ip of ips) {
        if (!~targets.indexOf(ip)) {
          const err = new Error(`The domain ${domain} has an A record ${chalk.bold(ip)} that doesn\'t resolve to ${chalk.bold('alias.zeit.co')}. Make sure the appropriate \`ALIAS\` or \`CNAME\` records are configured.`);
          err.userError = true;
          return bail(err);
        }
      }
    });
  }

  async createCert (domain) {
    return this.retry(async (bail, attempt) => {
      if (this._debug) console.time(`> [debug] /certs #${attempt}`);
      const res = await this._fetch('/certs', {
        method: 'POST',
        body: {
          domains: [domain]
        }
      });

      const body = await res.json();
      if (this._debug) console.timeEnd(`> [debug] /certs #${attempt}`);

      if (body.error) {
        const { code } = body.error;

        if ('verification_failed' === code) {
          const err = new Error(`We couldn't verify ownership of the domain ${domain}. Make sure the appropriate \`ALIAS\` or \`CNAME\` records are configured and pointing to ${chalk.bold('alias.zeit.co')}.`);
          err.userError = true;
          return bail(err);
        }

        throw new Error(body.message);
      }

      if (200 !== res.status && 304 !== res.status) {
        throw new Error('Unhandled error');
      }
    });
  }

  retry (fn) {
    return retry(fn, { retries: 5, randomize: true, onRetry: this._onRetry });
  }

}

function resolve4 (host) {
  return new Promise((resolve, reject) => {
    return dns.resolve4(host, (err, answer) => {
      if (err) return reject(err);
      resolve(answer);
    });
  });
}
<commit_msg>alias: improve success output<commit_after>import retry from 'async-retry';
import dns from 'dns';
import Now from '../lib';
import toHost from './to-host';
import chalk from 'chalk';

export default class Alias extends Now {

  async ls (deployment) {
    if (deployment) {
      const target = await this.findDeployment(deployment);
      if (!target) {
        const err = new Error(`Aliases not found by "${deployment}". Run ${chalk.dim('`now alias ls`')} to see your aliases.`);
        err.userError = true;
        throw err;
      }

      return this.retry(async (bail, attempt) => {
        const res = await this._fetch(`/now/deployments/${target.uid}/aliases`);
        const body = await res.json();
        return body.aliases;
      });
    }

    return this.retry(async (bail, attempt) => {
      const res = await this._fetch('/now/aliases');
      const body = await res.json();
      return body.aliases;
    });
  }

  async rm (alias) {
    const _alias = await this.findAlias(alias);
    if (!_alias) {
      const err = new Error(`Alias not found by "${alias}". Run ${chalk.dim('`now alias ls`')} to see your aliases.`);
      err.userError = true;
      throw err;
    }

    return this.retry(async (bail, attempt) => {
      const res = await this._fetch(`/now/aliases/${_alias.uid}`, {
        method: 'DELETE'
      });

      if (403 === res.status) {
        return bail(new Error('Unauthorized'));
      }

      if (res.status !== 200) {
        const err = new Error('Deletion failed. Try again later.');
        throw err;
      }

      console.log(`${chalk.cyan('> Success!')}`);
    });
  }

  async findAlias (alias) {
    const list = await this.ls();

    let key, val;
    if (/\./.test(alias)) {
      val = toHost(alias);
      key = 'alias';
    } else {
      val = alias;
      key = 'uid';
    }

    const _alias = list.find((d) => {
      if (d[key] === val) {
        if (this._debug) console.log(`> [debug] matched alias ${d.uid} by ${key} ${val}`);
        return true;
      }

      // match prefix
      if (`${val}.now.sh` === d.alias) {
        if (this._debug) console.log(`> [debug] matched alias ${d.uid} by url ${d.host}`);
        return true;
      }

      return false;
    });

    return _alias;
  }

  async findDeployment (deployment) {
    const list = await this.list();
    let key, val;
    if (/\./.test(deployment)) {
      val = toHost(deployment);
      key = 'url';
    } else {
      val = deployment;
      key = 'uid';
    }

    const depl = list.find((d) => {
      if (d[key] === val) {
        if (this._debug) console.log(`> [debug] matched deployment ${d.uid} by ${key} ${val}`);
        return true;
      }

      // match prefix
      if (`${val}.now.sh` === d.url) {
        if (this._debug) console.log(`> [debug] matched deployment ${d.uid} by url ${d.url}`);
        return true;
      }

      return false;
    });

    return depl;
  }

  async set (deployment, alias) {
    const depl = await this.findDeployment(deployment);
    if (!depl) {
      const err = new Error(`Deployment not found by "${deployment}". Run ${chalk.dim('`now ls`')} to see your deployments.`);
      err.userError = true;
      throw err;
    }

    // evaluate the alias
    if (!/\./.test(alias)) {
      if (this._debug) console.log(`> [debug] suffixing \`.now.sh\` to alias ${alias}`);
      alias = `${alias}.now.sh`;
    } else {
      alias = toHost(alias);
    }

    await this.createAlias(depl, alias);
    console.log(`${chalk.cyan('> Success!')} Deployment ${chalk.bold(`https://${depl.url}`)} ${chalk.dim(`(${depl.uid})`)} now points to ${chalk.bold(chalk.underline(`https://${alias}`))}`);
  }

  async createAlias (depl, alias) {
    return this.retry(async (bail, attempt) => {
      if (this._debug) console.time(`> [debug] /now/deployments/${depl.uid}/aliases #${attempt}`);
      const res = await this._fetch(`/now/deployments/${depl.uid}/aliases`, {
        method: 'POST',
        body: { alias }
      });

      if (304 === res.status) return;

      const body = await res.json();
      if (this._debug) console.timeEnd(`> [debug] /now/deployments/${depl.uid}/aliases #${attempt}`);

      // no retry on authorization problems
      if (403 === res.status) {
        const code = body.error.code;

        if ('custom_domain_needs_upgrade' === code) {
          const err = new Error(`You are attempting to use a custom domain alias (${chalk.underline(chalk.cyan(alias))}), but this is only enabled for premium accounts. Please upgrade at ${chalk.underline('https://zeit.co/account')}`);
          err.userError = true;
          return bail(err);
        }

        if ('alias_in_use' === code) {
          const err = new Error(`The alias you are trying to configure (${chalk.underline(chalk.cyan(alias))}) is already in use by a different account.`);
          err.userError = true;
          return bail(err);
        }

        return bail(new Error('Authorization error'));
      }

      // all other errors
      if (body.error) {
        const code = body.error.code;

        if ('deployment_not_found' === code) {
          return bail(new Error('Deployment not found'));
        }

        if ('cert_missing' === code) {
          console.log(`> Provisioning certificate for ${chalk.underline(chalk.cyan(alias))}`);

          await this.verifyOwnership();
          await this.createCert();

          // try again, but now having provisioned the certificate
          return this.createAlias(depl, alias);
        }

        return bail(new Error(body.error.message));
      }

      // the two expected succesful cods are 200 and 304
      if (200 !== res.status && 304 !== res.status) {
        throw new Error('Unhandled error');
      }
    });
  }

  async verifyOwnership (domain) {
    return this.retry(async (bail, attempt) => {
      const targets = await resolve4('alias.zeit.co');

      if (!targets.length) {
        return bail(new Error('Unable to resolve alias.zeit.co'));
      }

      const ips = await resolve4(domain);
      if (!ips.length) {
        const err = new Error('The domain ${domain} A record in the DNS configuration is not returning any IPs.');
        err.userError = true;
        return bail(err);
      }

      for (const ip of ips) {
        if (!~targets.indexOf(ip)) {
          const err = new Error(`The domain ${domain} has an A record ${chalk.bold(ip)} that doesn\'t resolve to ${chalk.bold('alias.zeit.co')}. Make sure the appropriate \`ALIAS\` or \`CNAME\` records are configured.`);
          err.userError = true;
          return bail(err);
        }
      }
    });
  }

  async createCert (domain) {
    return this.retry(async (bail, attempt) => {
      if (this._debug) console.time(`> [debug] /certs #${attempt}`);
      const res = await this._fetch('/certs', {
        method: 'POST',
        body: {
          domains: [domain]
        }
      });

      const body = await res.json();
      if (this._debug) console.timeEnd(`> [debug] /certs #${attempt}`);

      if (body.error) {
        const { code } = body.error;

        if ('verification_failed' === code) {
          const err = new Error(`We couldn't verify ownership of the domain ${domain}. Make sure the appropriate \`ALIAS\` or \`CNAME\` records are configured and pointing to ${chalk.bold('alias.zeit.co')}.`);
          err.userError = true;
          return bail(err);
        }

        throw new Error(body.message);
      }

      if (200 !== res.status && 304 !== res.status) {
        throw new Error('Unhandled error');
      }
    });
  }

  retry (fn) {
    return retry(fn, { retries: 5, randomize: true, onRetry: this._onRetry });
  }

}

function resolve4 (host) {
  return new Promise((resolve, reject) => {
    return dns.resolve4(host, (err, answer) => {
      if (err) return reject(err);
      resolve(answer);
    });
  });
}
<|endoftext|>


<commit_before>WX._customUnitInternals = {};

/**
 * @class DualLevelDetector
 * @description program-dependent envelope following for custom compressors
 */
WX._customUnitInternals.DualLevelDetector = function() {
  Object.defineProperties(this, {
    _fs: {
      enumerable: false,
      writable: false,
      value: WX._context.sampleRate
    },
    _attackFast: {
      enumerable: false,
      writable: true,
      value: 1.0 - Math.exp(-1.0 / (0.125 * this._fs))
    },
    _releaseFast: {
      enumerable: false,
      writable: true,
      value: 1.0 - Math.exp(-1.0 / (0.5 * this._fs))
    },
    _levelFast: {
      enumerable: false,
      writable: true,
      value: 0
    },
    _attackSlow: {
      enumerable: false,
      writable: true,
      value: 1.0 - Math.exp(-1.0 / (0.25 * this._fs))
    },
    _releaseSlow: {
      enumerable: false,
      writable: true,
      value: 1.0 - Math.exp(-1.0 / this._fs)
    },
    _levelSlow: {
      enumerable: false,
      writable: true,
      value: 0
    }
  });
};

WX._customUnitInternals.DualLevelDetector.prototype = Object.create(null, {

  /**
   * get/set attack
   * @param {float} value attack in seconds
   */
  attack: {
    enumerable: true,
    get: function() {
      return this._attackFast;
    },
    set: function(value) {
      this._attackFast = 1 - Math.exp(-1.0 / (value * this._fs));
    }
  },

  /**
   * get/set release
   * @param {float} value release in seconds
   */
  release: {
    enumerable: true,
    get: function() {
      return this._releaseFast;
    },
    set: function(value) {
      this._releaseFast = 1 - Math.exp(-1.0 / (value * this._fs));
    }
  },

  /**
   * reset
   * @description resetting previous tracked level
   */
  reset: {
    enumerable: false,
    value: function() {
      this._levelFast = 0.0;
      this._levelSlow = 0.0;
    }
  },

  /**
   * process and return tracked level
   * @type {float} input value
   * @return {float} output value
   */
  processLevel: {
      value: function(input) {
        // slow detector first
        var s = Math.abs(input);
        if (s > this._levelSlow) {
          this._levelSlow += this._attackSlow * (s - this._levelSlow);
        } else {
          this._levelSlow += this._releaseSlow * (s - this._levelSlow);
        }
        // fast detector
        if (s > this._levelFast) {
          this._levelFast += this._attackFast * (s - this._levelFast);
        } else {
          this._levelFast += this._releaseFast * (this._levelSlow - this._levelFast);
        }
        // write level_fast
        return this._levelFast;
      }
    }
});

/**
 * @class C2 (module)
 * @description compressor with scriptProcessorNode + sidechain
 * @param {object} json parameters in JSON notation
 *                      { threshold, ratio, knee, attack, release }
 */
WX.C2 = function(json) {
  // calling super constructor
  WX._Unit.call(this);
  // creating unit-specific properties
  Object.defineProperties(this, {
    _threshold: {
      enumerable: false,
      writable: true,
      value: -12.0
    },
    _ratio: {
      enumerable: false,
      writable: true,
      value: 4.0
    },
    _makeup: {
      enumerable: false,
      writable: true,
      value: 0.0
    },
    _detector: {
      enumerable: false,
      writable: false,
      value: new WX._customUnitInternals.DualLevelDetector()
    },
    _processor: {
      enumerable: false,
      writable: false,
      value: WX._context.createScriptProcessorNode(
          WX._customUnitBufferSize, 2, 2
        )
    },
    _callback: {
      value: function(event) {
        // temp vars
        var level, gaindB, gain;
        // input and output array buffer
        var inputL = event.inputBuffer.getChannelData(0);
        var inputR = event.inputBuffer.getChannelData(1);
        var outputL = event.outputBuffer.getChannelData(0);
        var outputR = event.outputBuffer.getChannelData(1);
        // callback loop
        for (var i = 0, b = WX._customUnitBufferSize; i < b; ++i) {
          // peak detection
          level = this._detector.process(Math.max(Math.abs(inputL[i]), Math.abs(inputR[i])));
          // gain computer: limiting
          gaindB = Math.min(0.0, WX.lin2db(this._threshold / level));
          // get linear gain
          gain = WX.db2lin(gainDB);
          // compute output
          outputL[i] = inputL[i] * gain * this._makeup;
          outputR[i] = inputR[i] * gain * this._makeup;
        }
      }
    }
  });
  var me = this;
  this._processor.onaudioprocess = function(event) {
    me._callback(event);
  };
  // performing unit-specific actions
  this._inlet.connect(this._processor);
  this._processor.connect(this._outlet);
  // assign (default) parameters
  this.params = json;
};

WX.C2.prototype = Object.create(WX._Unit.prototype, {

  /**
   * get/set threshold
   * @param {float} value threshold: default -24, nominal range of -100 to 0.
   */
  threshold: {
    enumerable: true,
    get: function() {
      return this._threshold;
    },
    set: function(value) {
      this._threshold = value;
    }
  },

  /**
   * get/set ratio
   * @param {float} value arbitrary ratio
   */
  ratio: {
    enumerable: true,
    get: function() {
      return this._ratio;
    },
    set: function(value) {
      this._ratio = value;
    }
  },

  /**
   * get/set attack
   * @param {float} value attack in seconds
   */
  attack: {
    enumerable: true,
    get: function() {
      return this._detector.attack;
    },
    set: function(value) {
      this._detector.attack = value;
    }
  },

  /**
   * get/set release
   * @param {float} value release in seconds
   */
  release: {
    enumerable: true,
    get: function() {
      return this._detector.release;
    },
    set: function(value) {
      this._detector.release = value;
    }
  }
});<commit_msg>added custom compressor C2<commit_after>WX._customUnitInternals = {};

/**
 * @class DualLevelDetector
 * @description program-dependent envelope following for custom compressors
 */
WX._customUnitInternals.DualLevelDetector = function() {
  Object.defineProperties(this, {
    _fs: {
      enumerable: false,
      writable: false,
      value: WX._context.sampleRate
    },
    _attackFast: {
      enumerable: false,
      writable: true,
      value: 1.0 - Math.exp(-1.0 / (0.125 * this._fs))
    },
    _releaseFast: {
      enumerable: false,
      writable: true,
      value: 1.0 - Math.exp(-1.0 / (0.5 * this._fs))
    },
    _levelFast: {
      enumerable: false,
      writable: true,
      value: 0
    },
    _attackSlow: {
      enumerable: false,
      writable: true,
      value: 1.0 - Math.exp(-1.0 / (0.25 * this._fs))
    },
    _releaseSlow: {
      enumerable: false,
      writable: true,
      value: 1.0 - Math.exp(-1.0 / this._fs)
    },
    _levelSlow: {
      enumerable: false,
      writable: true,
      value: 0
    }
  });
};

WX._customUnitInternals.DualLevelDetector.prototype = Object.create(null, {

  /**
   * get/set attack
   * @param {float} value attack in seconds
   */
  attack: {
    enumerable: true,
    get: function() {
      return this._attackFast;
    },
    set: function(value) {
      this._attackFast = 1 - Math.exp(-1.0 / (value * this._fs));
    }
  },

  /**
   * get/set release
   * @param {float} value release in seconds
   */
  release: {
    enumerable: true,
    get: function() {
      return this._releaseFast;
    },
    set: function(value) {
      this._releaseFast = 1 - Math.exp(-1.0 / (value * this._fs));
    }
  },

  /**
   * reset
   * @description resetting previous tracked level
   */
  reset: {
    enumerable: false,
    value: function() {
      this._levelFast = 0.0;
      this._levelSlow = 0.0;
    }
  },

  /**
   * process and return tracked level
   * @type {float} input value
   * @return {float} output value
   */
  processLevel: {
      value: function(input) {
        // slow detector first
        var s = Math.abs(input);
        if (s > this._levelSlow) {
          this._levelSlow += this._attackSlow * (s - this._levelSlow);
        } else {
          this._levelSlow += this._releaseSlow * (s - this._levelSlow);
        }
        // fast detector
        if (s > this._levelFast) {
          this._levelFast += this._attackFast * (s - this._levelFast);
        } else {
          this._levelFast += this._releaseFast * (this._levelSlow - this._levelFast);
        }
        // write level_fast
        return this._levelFast;
      }
    }
});

/**
 * @class C2 (module)
 * @description compressor with scriptProcessorNode + sidechain
 * @param {object} json parameters in JSON notation
 *                      { threshold, ratio, knee, attack, release }
 */
WX.C2 = function(json) {
  // calling super constructor
  WX._Unit.call(this);
  // creating unit-specific properties
  Object.defineProperties(this, {
    _threshold: {
      enumerable: false,
      writable: true,
      value: -12.0
    },
    _ratio: {
      enumerable: false,
      writable: true,
      value: 4.0
    },
    _makeup: {
      enumerable: false,
      writable: true,
      value: 0.0
    },
    _detector: {
      enumerable: false,
      writable: false,
      value: new WX._customUnitInternals.DualLevelDetector()
    },
    _processor: {
      enumerable: false,
      writable: false,
      value: WX._context.createScriptProcessor(
          WX._customUnitBufferSize, 2, 2
        )
    },
    _callback: {
      value: function(event) {
        // temp vars
        var level, gaindB, gain;
        // input and output array buffer
        var inputL = event.inputBuffer.getChannelData(0);
        var inputR = event.inputBuffer.getChannelData(1);
        var outputL = event.outputBuffer.getChannelData(0);
        var outputR = event.outputBuffer.getChannelData(1);
        // callback loop
        for (var i = 0, b = WX._customUnitBufferSize; i < b; ++i) {
          // peak detection
          level = this._detector.process(Math.max(Math.abs(inputL[i]), Math.abs(inputR[i])));
          // gain computer: limiting
          gaindB = Math.min(0.0, WX.lin2db(this._threshold / level));
          // get linear gain
          gain = WX.db2lin(gainDB);
          // compute output
          outputL[i] = inputL[i] * gain * this._makeup;
          outputR[i] = inputR[i] * gain * this._makeup;
        }
      }
    }
  });
  var me = this;
  this._processor.onaudioprocess = function(event) {
    me._callback(event);
  };
  // performing unit-specific actions
  this._inlet.connect(this._processor);
  this._processor.connect(this._outlet);
  // assign (default) parameters
  this.params = json;
};

WX.C2.prototype = Object.create(WX._Unit.prototype, {

  /**
   * get/set threshold
   * @param {float} value threshold: default -24, nominal range of -100 to 0.
   */
  threshold: {
    enumerable: true,
    get: function() {
      return this._threshold;
    },
    set: function(value) {
      this._threshold = value;
    }
  },

  /**
   * get/set ratio
   * @param {float} value arbitrary ratio
   */
  ratio: {
    enumerable: true,
    get: function() {
      return this._ratio;
    },
    set: function(value) {
      this._ratio = value;
    }
  },

  /**
   * get/set attack
   * @param {float} value attack in seconds
   */
  attack: {
    enumerable: true,
    get: function() {
      return this._detector.attack;
    },
    set: function(value) {
      this._detector.attack = value;
    }
  },

  /**
   * get/set release
   * @param {float} value release in seconds
   */
  release: {
    enumerable: true,
    get: function() {
      return this._detector.release;
    },
    set: function(value) {
      this._detector.release = value;
    }
  }
});<|endoftext|>


<commit_before>var express = require('express'),
    bodyParser = require('body-parser');

var app = express();

app.use(bodyParser.json());

app.post('/', function(request, response){
  console.log("Request Body: " + request.body);      // Log Req
  //var reqJson = JSON.parse(request.body);

  function compare(a,b) {
	  if (a.reindeerName < b.reindeerName) return -1;
	  if (a.reindeerName > b.reindeerName) return 1;
	  return 0;
  }
  request.body.sort(compare);
   //reqJson.sort(compare);

  response.body = JSON.stringify(request.body);
  response.send(response.body);                       // echo the Req
  console.log("Response Body: " + response.body);    // Log Response
});

app.listen(8080);

<commit_msg>update path<commit_after>var express = require('express'),
    bodyParser = require('body-parser');

var app = express();

app.use(bodyParser.json());

app.post('/sorter', function(request, response){
  console.log("Request Body: " + request.body);      // Log Req

  function compare(a,b) {
	  if (a.reindeerName < b.reindeerName) return -1;
	  if (a.reindeerName > b.reindeerName) return 1;
	  return 0;
  }
  request.body.sort(compare);

  response.body = JSON.stringify(request.body);
  response.send(response.body);                       // echo the Req
  console.log("Response Body: " + response.body);    // Log Response
});

app.listen(8080);

<|endoftext|>


<commit_before>(function (JSUS) {

	function ARRAY(){};

	// ARRAYs
	/////////

	// Add the filter method to ARRAY objects in case the method is not
	// supported natively.
	// See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/ARRAY/filter#Compatibility

    if (!Array.prototype.filter) {
      Array.prototype.filter = function(fun /*, thisp */) {
        "use strict";
        if (this === void 0 || this === null) throw new TypeError();

        var t = Object(this);
        var len = t.length >>> 0;
        if (typeof fun !== "function") throw new TypeError();

        var res = [];
        var thisp = arguments[1];
        for (var i = 0; i < len; i++) {
          if (i in t) {
            var val = t[i]; // in case fun mutates this
            if (fun.call(thisp, val, i, t)) {
              res.push(val);
            }
          }
        }

        return res;
      };
    }

    ARRAY.removeElement = function (needle, haystack) {

//    	console.log('needle');
//    	console.log(needle);
//    	console.log('haystack');
//    	console.log(haystack);

    	if ('object' === typeof needle) {
        	  var func = JSUS.equals;
	      }
	      else {
	    	  var func = function (a,b) {
	    		  return (a === b);
	    	  }
	      }

    	for (var i=0; i < haystack.length; i++) {
      	    if (func(needle, haystack[i])){
//      	    	console.log('hays');
//      	    	console.log(haystack);
      	    	return haystack.splice(i,1);
      	    }
      	}

      	return false;

    };

    ARRAY.in_array = function (needle, haystack){

        if ('object' === typeof needle) {
      	  var func = JSUS.equals;
        }
        else {
      	  var func = function (a,b) {
      		  return (a === b);
      	  }
        }

  	  for(var i=0;i<haystack.length;i++){
  	    if (func.call(this,needle,haystack[i])) return true;
  	  }
  	  return false;
    };

    /**
	 * Returns an array of N array containing the same number of elements
	 * The last group could have less elements.
	 *
	 */
	ARRAY.getNGroups = function (array, N) {
		return ARRAY.getGroupsSizeN(array, Math.floor(array.length / N));
	};

	/**
	 * Returns an array of array containing N elements each
	 * The last group could have less elements.
	 *
	 */
	ARRAY.getGroupsSizeN = function (array, N) {

		var copy = array.slice(0);
		var len = copy.length;
		var originalLen = copy.length;
		var result = [];

		// Init values for the loop algorithm
		var i;
		var idx;
		var group = [];
		var count = 0;
		for (i=0; i < originalLen; i++) {

			// Get a random idx between 0 and array length
			idx = Math.floor(Math.random()*len);

			// Prepare the array container for the elements of a new group
			if (count >= N) {
				result.push(group);
				count = 0;
				group = [];
			}

			// Insert element in the group
			group.push(copy[idx]);

			// Update
			copy.splice(idx,1);
			len = copy.length;
			count++;
		}

		// Add any remaining element
		if (group.length > 0) {
			result.push(group);
		}

		return result;
	};

	/**
	 * Match each element of the array with N random others.
	 * If strict is equal to true, elements cannot be matched multiple times.
	 */
	ARRAY.matchN = function (array, N, strict) {
		var result = []
		var len = array.length;
		var found = [];
		for (var i = 0 ; i < len ; i++) {
			// Recreate the array
			var copy = array.slice(0);
			copy.splice(i,1);
			if (strict) {
				copy = ARRAY.arrayDiff(copy,found);
			}
			var group = ARRAY.getNRandom(copy,N);
			// Add to the set of used elements
			found = found.concat(group);
			// Re-add the current element
			group.splice(0,0,array[i]);
			result.push(group);

			//Update
			group = [];

		}
		return result;
	};

	ARRAY.arraySelfConcat = function(array) {
		var i = 0;
		var len = array.length;
		var result = []
		for (;i<len;i++) {
			result = result.concat(array[i]);
		}
		return result;
	};

	/**
	 * Performs a diff between two arrays.
	 * Returns all the values of the first array which are not present
	 * in the second one.
	 */
	ARRAY.arrayDiff = function(a1, a2) {
		return a1.filter( function(i) {
			return !(a2.indexOf(i) > -1);
		});
	};

	/**
	 * http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
	 *
	 */
	ARRAY.shuffle = function (array, N, callback) {
		var copy = array.slice(0);
		var len = array.length-1; // ! -1
		for (var i = len; i > 0; i--) {
			var j = Math.floor(Math.random()*(i+1));
			var tmp = copy[j];
			copy[j] = copy[i];
			copy[i] = tmp;
			//console.log(copy);
		}
		return copy;
	};

	ARRAY.getNRandom = function (array, N, callback) {
		return ARRAY.shuffle(array).slice(0,N);
	};

	ARRAY.generateCombinations = function (array, r, callback) {
	    function equal(a, b) {
	        for (var i = 0; i < a.length; i++) {
	            if (a[i] != b[i]) return false;
	        }
	        return true;
	    }
	    function values(i, a) {
	        var ret = [];
	        for (var j = 0; j < i.length; j++) ret.push(a[i[j]]);
	        return ret;
	    }
	    var n = array.length;
	    var indices = [];
	    for (var i = 0; i < r; i++) indices.push(i);
	    var final = [];
	    for (var i = n - r; i < n; i++) final.push(i);
	    while (!equal(indices, final)) {
	        callback(values(indices, array));
	        var i = r - 1;
	        while (indices[i] == n - r + i) i -= 1;
	        indices[i] += 1;
	        for (var j = i + 1; j < r; j++) indices[j] = indices[i] + j - i;
	    }
	    callback(values(indices, array));
	};

	//TODO: Improve
	ARRAY.print_r = function (array) {
		for (var i=0,len=array.length;i<len;i++){
			var el = array[i];
			if (typeof(el) === 'ARRAY'){
				ARRAY.print_r(el);
			}
			else {
				if (typeof(el) === 'Object'){
					for (var key in el) {
						if (el.hasOwnProperty(key)){
							console.log(key + ' ->\n');
							ARRAY.print_r(el[key]);
						}
					}
				}
				else {
					console.log(el);
				}
			}
		}
	};

	JSUS.extend(ARRAY);

})('undefined' !== typeof JSUS ? JSUS : module.parent.exports.JSUS);<commit_msg>Changes to test PR and Table<commit_after>(function (JSUS) {

	function ARRAY(){};

	// ARRAYs
	/////////

	// Add the filter method to ARRAY objects in case the method is not
	// supported natively.
	// See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/ARRAY/filter#Compatibility

    if (!Array.prototype.filter) {
      Array.prototype.filter = function(fun /*, thisp */) {
        "use strict";
        if (this === void 0 || this === null) throw new TypeError();

        var t = Object(this);
        var len = t.length >>> 0;
        if (typeof fun !== "function") throw new TypeError();

        var res = [];
        var thisp = arguments[1];
        for (var i = 0; i < len; i++) {
          if (i in t) {
            var val = t[i]; // in case fun mutates this
            if (fun.call(thisp, val, i, t)) {
              res.push(val);
            }
          }
        }

        return res;
      };
    }

    ARRAY.removeElement = function (needle, haystack) {

//    	console.log('needle');
//    	console.log(needle);
//    	console.log('haystack');
//    	console.log(haystack);

    	if ('object' === typeof needle) {
        	  var func = JSUS.equals;
	      }
	      else {
	    	  var func = function (a,b) {
	    		  return (a === b);
	    	  }
	      }

    	for (var i=0; i < haystack.length; i++) {
      	    if (func(needle, haystack[i])){
//      	    	console.log('hays');
//      	    	console.log(haystack);
      	    	return haystack.splice(i,1);
      	    }
      	}

      	return false;

    };

    ARRAY.in_array = function (needle, haystack){

        if ('object' === typeof needle) {
      	  var func = JSUS.equals;
        }
        else {
      	  var func = function (a,b) {
      		  return (a === b);
      	  }
        }

  	  for(var i=0;i<haystack.length;i++){
  	    if (func.call(this,needle,haystack[i])) return true;
  	  }
  	  return false;
    };

    /**
	 * Returns an array of N array containing the same number of elements
	 * The last group could have less elements.
	 *
	 */
	ARRAY.getNGroups = function (array, N) {
		return ARRAY.getGroupsSizeN(array, Math.floor(array.length / N));
	};

	/**
	 * Returns an array of array containing N elements each
	 * The last group could have less elements.
	 *
	 */
	ARRAY.getGroupsSizeN = function (array, N) {

		var copy = array.slice(0);
		var len = copy.length;
		var originalLen = copy.length;
		var result = [];

		// Init values for the loop algorithm
		var i;
		var idx;
		var group = [];
		var count = 0;
		for (i=0; i < originalLen; i++) {

			// Get a random idx between 0 and array length
			idx = Math.floor(Math.random()*len);

			// Prepare the array container for the elements of a new group
			if (count >= N) {
				result.push(group);
				count = 0;
				group = [];
			}

			// Insert element in the group
			group.push(copy[idx]);

			// Update
			copy.splice(idx,1);
			len = copy.length;
			count++;
		}

		// Add any remaining element
		if (group.length > 0) {
			result.push(group);
		}

		return result;
	};

	/**
	 * Match each element of the array with N random others.
	 * If strict is equal to true, elements cannot be matched multiple times.
	 */
	ARRAY.matchN = function (array, N, strict) {
		console.log('TO MATCH');
		console.log(array.length);

		var result = []
		var len = array.length;
		var found = [];
		for (var i = 0 ; i < len ; i++) {
			// Recreate the array
			var copy = array.slice(0);
			copy.splice(i,1);
			if (strict) {
				copy = ARRAY.arrayDiff(copy,found);
			}
			var group = ARRAY.getNRandom(copy,N);
			// Add to the set of used elements
			found = found.concat(group);
			// Re-add the current element
			group.splice(0,0,array[i]);
			result.push(group);

			//Update
			group = [];

		}
		return result;
	};

	ARRAY.arraySelfConcat = function(array) {
		var i = 0;
		var len = array.length;
		var result = []
		for (;i<len;i++) {
			result = result.concat(array[i]);
		}
		return result;
	};

	/**
	 * Performs a diff between two arrays.
	 * Returns all the values of the first array which are not present
	 * in the second one.
	 */
	ARRAY.arrayDiff = function(a1, a2) {
		return a1.filter( function(i) {
			return !(a2.indexOf(i) > -1);
		});
	};

	/**
	 * http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
	 *
	 */
	ARRAY.shuffle = function (array, N, callback) {
		var copy = array.slice(0);
		var len = array.length-1; // ! -1
		for (var i = len; i > 0; i--) {
			var j = Math.floor(Math.random()*(i+1));
			var tmp = copy[j];
			copy[j] = copy[i];
			copy[i] = tmp;
			//console.log(copy);
		}
		return copy;
	};

	ARRAY.getNRandom = function (array, N, callback) {
		return ARRAY.shuffle(array).slice(0,N);
	};

	ARRAY.generateCombinations = function (array, r, callback) {
	    function equal(a, b) {
	        for (var i = 0; i < a.length; i++) {
	            if (a[i] != b[i]) return false;
	        }
	        return true;
	    }
	    function values(i, a) {
	        var ret = [];
	        for (var j = 0; j < i.length; j++) ret.push(a[i[j]]);
	        return ret;
	    }
	    var n = array.length;
	    var indices = [];
	    for (var i = 0; i < r; i++) indices.push(i);
	    var final = [];
	    for (var i = n - r; i < n; i++) final.push(i);
	    while (!equal(indices, final)) {
	        callback(values(indices, array));
	        var i = r - 1;
	        while (indices[i] == n - r + i) i -= 1;
	        indices[i] += 1;
	        for (var j = i + 1; j < r; j++) indices[j] = indices[i] + j - i;
	    }
	    callback(values(indices, array));
	};

	//TODO: Improve
	ARRAY.print_r = function (array) {
		for (var i=0,len=array.length;i<len;i++){
			var el = array[i];
			if (typeof(el) === 'ARRAY'){
				ARRAY.print_r(el);
			}
			else {
				if (typeof(el) === 'Object'){
					for (var key in el) {
						if (el.hasOwnProperty(key)){
							console.log(key + ' ->\n');
							ARRAY.print_r(el[key]);
						}
					}
				}
				else {
					console.log(el);
				}
			}
		}
	};

	JSUS.extend(ARRAY);

})('undefined' !== typeof JSUS ? JSUS : module.parent.exports.JSUS);<|endoftext|>


<commit_before>'use strict';

var defaults = require('./defaults');
var utils = require('./utils');
var dispatchRequest = require('./core/dispatchRequest');
var InterceptorManager = require('./core/InterceptorManager');
var isAbsoluteURL = require('./helpers/isAbsoluteURL');
var combineURLs = require('./helpers/combineURLs');
var bind = require('./helpers/bind');
var transformData = require('./helpers/transformData');

function Axios(defaultConfig) {
  this.defaults = utils.merge({}, defaultConfig);
  this.interceptors = {
    request: new InterceptorManager(),
    response: new InterceptorManager()
  };
}

Axios.prototype.request = function request(config) {
  /*eslint no-param-reassign:0*/
  // Allow for axios('example/url'[, config]) a la fetch API
  if (typeof config === 'string') {
    config = utils.merge({
      url: arguments[0]
    }, arguments[1]);
  }

  config = utils.merge(defaults, this.defaults, { method: 'get' }, config);

  // Support baseURL config
  if (config.baseURL && !isAbsoluteURL(config.url)) {
    config.url = combineURLs(config.baseURL, config.url);
  }

  // Don't allow overriding defaults.withCredentials
  config.withCredentials = config.withCredentials || this.defaults.withCredentials;

  // Transform request data
  config.data = transformData(
    config.data,
    config.headers,
    config.transformRequest
  );

  // Flatten headers
  config.headers = utils.merge(
    config.headers.common || {},
    config.headers[config.method] || {},
    config.headers || {}
  );

  utils.forEach(
    ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
    function cleanHeaderConfig(method) {
      delete config.headers[method];
    }
  );

  // Hook up interceptors middleware
  var chain = [dispatchRequest, undefined];
  var promise = Promise.resolve(config);

  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });

  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });

  while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift());
  }

  return promise;
};

var defaultInstance = new Axios(defaults);
var axios = module.exports = bind(Axios.prototype.request, defaultInstance);
module.exports.Axios = Axios

// Expose properties from defaultInstance
axios.defaults = defaultInstance.defaults;
axios.interceptors = defaultInstance.interceptors;

// Factory for creating new instances
axios.create = function create(defaultConfig) {
  return new Axios(defaultConfig);
};

// Expose all/spread
axios.all = function all(promises) {
  return Promise.all(promises);
};
axios.spread = require('./helpers/spread');

// Provide aliases for supported request methods
utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url
    }));
  };
  axios[method] = bind(Axios.prototype[method], defaultInstance);
});

utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, data, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url,
      data: data
    }));
  };
  axios[method] = bind(Axios.prototype[method], defaultInstance);
});
<commit_msg>added semicolon<commit_after>'use strict';

var defaults = require('./defaults');
var utils = require('./utils');
var dispatchRequest = require('./core/dispatchRequest');
var InterceptorManager = require('./core/InterceptorManager');
var isAbsoluteURL = require('./helpers/isAbsoluteURL');
var combineURLs = require('./helpers/combineURLs');
var bind = require('./helpers/bind');
var transformData = require('./helpers/transformData');

function Axios(defaultConfig) {
  this.defaults = utils.merge({}, defaultConfig);
  this.interceptors = {
    request: new InterceptorManager(),
    response: new InterceptorManager()
  };
}

Axios.prototype.request = function request(config) {
  /*eslint no-param-reassign:0*/
  // Allow for axios('example/url'[, config]) a la fetch API
  if (typeof config === 'string') {
    config = utils.merge({
      url: arguments[0]
    }, arguments[1]);
  }

  config = utils.merge(defaults, this.defaults, { method: 'get' }, config);

  // Support baseURL config
  if (config.baseURL && !isAbsoluteURL(config.url)) {
    config.url = combineURLs(config.baseURL, config.url);
  }

  // Don't allow overriding defaults.withCredentials
  config.withCredentials = config.withCredentials || this.defaults.withCredentials;

  // Transform request data
  config.data = transformData(
    config.data,
    config.headers,
    config.transformRequest
  );

  // Flatten headers
  config.headers = utils.merge(
    config.headers.common || {},
    config.headers[config.method] || {},
    config.headers || {}
  );

  utils.forEach(
    ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
    function cleanHeaderConfig(method) {
      delete config.headers[method];
    }
  );

  // Hook up interceptors middleware
  var chain = [dispatchRequest, undefined];
  var promise = Promise.resolve(config);

  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });

  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });

  while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift());
  }

  return promise;
};

var defaultInstance = new Axios(defaults);
var axios = module.exports = bind(Axios.prototype.request, defaultInstance);
module.exports.Axios = Axios;

// Expose properties from defaultInstance
axios.defaults = defaultInstance.defaults;
axios.interceptors = defaultInstance.interceptors;

// Factory for creating new instances
axios.create = function create(defaultConfig) {
  return new Axios(defaultConfig);
};

// Expose all/spread
axios.all = function all(promises) {
  return Promise.all(promises);
};
axios.spread = require('./helpers/spread');

// Provide aliases for supported request methods
utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url
    }));
  };
  axios[method] = bind(Axios.prototype[method], defaultInstance);
});

utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, data, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url,
      data: data
    }));
  };
  axios[method] = bind(Axios.prototype[method], defaultInstance);
});
<|endoftext|>


<commit_before>var gulpBabel = require('gulp-babel');
var resolve = require('./resolve');
var report = require('./report');

module.exports = function (opts) {
  opts = opts || {};

  var plugins = resolve(
    'babel-plugin-add-module-exports',
    'babel-plugin-syntax-jsx',
    ['babel-plugin-transform-react-jsx', opts.jsx]
  );

  if (opts.umd) {
    plugins.push('babel-plugin-transform-es2015-modules-umd');
  }

  return report(gulpBabel({
    plugins: plugins,
    presets: resolve('babel-preset-es2015')
  }));
};<commit_msg>Respond to PR comments: resolve<commit_after>var gulpBabel = require('gulp-babel');
var resolve = require('./resolve');
var report = require('./report');

module.exports = function (opts) {
  opts = opts || {};

  var plugins = resolve(
    'babel-plugin-add-module-exports',
    'babel-plugin-syntax-jsx',
    ['babel-plugin-transform-react-jsx', opts.jsx]
  );

  if (opts.umd) {
    plugins.push(resolve('babel-plugin-transform-es2015-modules-umd'));
  }

  return report(gulpBabel({
    plugins: plugins,
    presets: resolve('babel-preset-es2015')
  }));
};<|endoftext|>


<commit_before>const Canvas = require('./canvas');

var dx = 0;
var dy = 2;

function setLeftSlope(){
  dx == -2
  dy = -dy
}

function setCenterSlope(){
  dx == 0
  dy = -dy
}

function setRightSlope(){
  dx == 2
  dy = -dy
}

var Ball = function(game, paddle, bricks){
  var canvas = new Canvas().canvas;
  this.game = game;
  this.paddle = paddle;
  this.startAngle = 0;
  this.x = canvas.width/2;
  this.y = canvas.height-30;
  this.canvasHeightOffset = 8;
  this.radius = 10;
  this.gameSize = {x: this.game.size.x, y: this.game.size.y};
  this.bricks = bricks;
}

Ball.prototype = {

  draw: function(canvas) {
    canvas.beginPath();
    canvas.arc(this.x, this.y, this.radius, this.startAngle, Math.PI*2);
    canvas.fillStyle = "#F00000";
    canvas.fill();
    canvas.closePath();
  },

  reset: function(){
    this.startAngle = 0;
    this.x = canvas.width/2;
    this.y = canvas.height-30;
    dy = -dy
  },

  move: function () {
    this.collisionDetectionBricks();

    if(this.x + dx > this.gameSize.x-this.radius || this.x + dx < this.radius) {
      this.game.wallSound.load();
      this.game.wallSound.play();
      dx = -dx;
    }

    if((this.y - this.canvasHeightOffset) + dy < this.radius) {
      this.game.topSound.load();
      this.game.topSound.play();
      dy = -dy;
    }

    //Drops Below Padde
    else if(this.y + dy > this.gameSize.y - (this.radius * 2)) {
      //Left Hit - between -3 and 39 pixels
      if(this.x > this.paddle.position.x - 3 && this.x < this.paddle.position.x - 3 + 39) {
        debugger
        this.game.paddleSound.load();
        this.game.paddleSound.play();

        setLeftSlope();

      // Center Hit - between 40 and 79 pixels
      } else if ((this.x > this.paddle.position.x - 3) && (this.x > this.paddle.position.x + 40) && (this.x < this.paddle.position.x + 79)) {
        debugger
        this.game.paddleSound.load();
        this.game.paddleSound.play();

        setCenterSlope();

      // Right Hit - between 80 and 123 pixels
      } else if ((this.x > this.paddle.position.x - 3) && (this.x > this.paddle.position.x + 80) && (this.x < this.paddle.position.x + 123)) {
        debugger
        this.game.paddleSound.load();
        this.game.paddleSound.play();

        setRightSlope();

      } else {
        this.game.lives -= 1;
        if (this.game.lives > 0){
          this.reset();
        } else {
          alert("You Fell into the Wall - GAME OVER");
          this.game.deathSound.load();
          this.game.deathSound.play();
          document.location.reload();
        }
      }
   }
    this.x += dx;
    this.y += dy;
  },

  collisionDetectionBricks: function() {
    var self = this;
    var brickHeight = self.bricks[0].size.y;
    var brickWidth = self.bricks[0].size.x;

    for (var i = 0; i < self.bricks.length; i++) {
      if((self.x > self.bricks[i].position.x)
        && (self.x < self.bricks[i].position.x + brickWidth)
        && (self.y - self.radius < self.bricks[i].position.y + brickHeight)
        && (self.y + self.radius > self.bricks[i].position.y - brickHeight)) {
        this.game.brickSound.load();
        this.game.brickSound.play();
        dy = -dy;
        self.bricks[i].status = 0;
        self.bricks.splice(i, 1);
        self.game.score += 10;
      }
    }
    return dy;
  }
};

module.exports = Ball;<commit_msg>Adjusted panes to 50 degree intervals<commit_after>const Canvas = require('./canvas');

var Ball = function(game, paddle, bricks){
  var canvas = new Canvas().canvas;
  this.game = game;
  this.paddle = paddle;
  this.startAngle = 0;
  this.x = canvas.width/2;
  this.y = canvas.height-30;
  this.canvasHeightOffset = 8;
  this.radius = 10;
  this.gameSize = {x: this.game.size.x, y: this.game.size.y};
  this.bricks = bricks;
  this.dx = 0
  this.dy = 5
}

Ball.prototype = {

  draw: function(canvas) {
    canvas.beginPath();
    canvas.arc(this.x, this.y, this.radius, this.startAngle, Math.PI*2);
    canvas.fillStyle = "#F00000";
    canvas.fill();
    canvas.closePath();
  },

  reset: function(){
    this.startAngle = 0;
    this.x = canvas.width/2;
    this.y = canvas.height-30;
    this.dy = -this.dy
  },

  setLeftSlope: function(){
  this.dx = -5
  this.dy = -this.dy
  },

  setCenterSlope: function(){
  this.dx = 0
  this.dy = -this.dy
  },

  setRightSlope: function(){
  this.dx = 5
  this.dy = -this.dy
  },

  move: function () {
    this.collisionDetectionBricks();

    if(this.x + this.dx > this.gameSize.x-this.radius || this.x + this.dx < this.radius) {
      this.game.wallSound.load();
      this.game.wallSound.play();
      this.dx = -this.dx;
    }

    if((this.y - this.canvasHeightOffset) + this.dy < this.radius) {
      this.game.topSound.load();
      this.game.topSound.play();
      this.dy = -this.dy;
    }

    //Drops Below Padde
    else if(this.y + this.dy > this.gameSize.y - (this.radius * 2)) {
      //Left Hit - between -3 and 49 pixels
      if(this.x > this.paddle.position.x - 4 && this.x < this.paddle.position.x + 49) {

        this.game.paddleSound.load();
        this.game.paddleSound.play();

        this.setLeftSlope();

      // Center Hit - between 40 and 79 pixels
      } else if ((this.x > this.paddle.position.x - 4) && (this.x > this.paddle.position.x + 50) && (this.x < this.paddle.position.x + 99)) {

        this.game.paddleSound.load();
        this.game.paddleSound.play();

        this.setCenterSlope();

      // Right Hit - between 80 and 123 pixels
      } else if ((this.x > this.paddle.position.x - 4) && (this.x > this.paddle.position.x + 100) && (this.x < this.paddle.position.x + 154)) {

        this.game.paddleSound.load();
        this.game.paddleSound.play();

        this.setRightSlope();

      } else {
        this.game.lives -= 1;
        if (this.game.lives > 0){
          this.reset();
        } else {
          alert("You Fell into the Wall - GAME OVER");
          this.game.deathSound.load();
          this.game.deathSound.play();
          document.location.reload();
        }
      }
   }
    this.x += this.dx;
    this.y += this.dy;
  },

  collisionDetectionBricks: function() {
    var self = this;
    var brickHeight = self.bricks[0].size.y;
    var brickWidth = self.bricks[0].size.x;

    for (var i = 0; i < self.bricks.length; i++) {
      if((self.x > self.bricks[i].position.x)
        && (self.x < self.bricks[i].position.x + brickWidth)
        && (self.y - self.radius < self.bricks[i].position.y + brickHeight)
        && (self.y + self.radius > self.bricks[i].position.y - brickHeight)) {
        this.game.brickSound.load();
        this.game.brickSound.play();
        this.dy = -this.dy;
        self.bricks[i].status = 0;
        self.bricks.splice(i, 1);
        self.game.score += 10;
      }
    }
    return this.dy;
  }
};

module.exports = Ball;<|endoftext|>