<commit_before>// Node.js API.
var assert = require('assert')
var events = require('events')

var Procession = require('procession')

// An evented semaphore.
var Signal = require('signal')

// Return the first not null-like value.
var coalesce = require('extant')

// Asynchronous control flow.
var cadence = require('cadence')

// Do nothing.
var noop = require('nop')

// Generate a unique, canonical string key from a JSON object.
var Keyify = require('keyify')

// Controlled demolition of asynchronous operations.
var Destructible = require('destructible')

var Cubbyhole = require('cubbyhole')

var Interrupt = require('interrupt').createInterrupter('olio')

var Sender = require('./sender')

var http = require('http')
var Downgrader = require('downgrader')

var delta = require('delta')

var Conduit = require('conduit')

var Staccato = require('staccato')

var Socket = require('procession/socket')(require('./hangup'))

var Turnstile = require('turnstile')
var restrictor = require('restrictor')

var Keyify = require('keyify')

var events = require('events')
var util = require('util')

function Olio (destructible, dispatcher, message) {
    this.destroyed = false

    this._destructible = destructible
    this._destructible.destruct.wait(this, function () { this.destroyed = true })

    this._ready = dispatcher.ready
    this._registered = dispatcher.registered

    this.name = message.name
    this.index = message.index
    this.address = message.address
    this.socket = message.socket
    this.counts = message.counts

    this._transmitter = dispatcher.transmitter

    this.turnstile = new Turnstile
    this.turnstile.listen(destructible.monitor('turnstile'))
    destructible.destruct.wait(this.turnstile, 'destroy')

    events.EventEmitter.call(this)
}
util.inherits(Olio, events.EventEmitter)

Olio.prototype.send = restrictor.push(cadence(function (async, envelope) {
    var to = {
        name: envelope.body.shift(),
        index: envelope.body.shift()
    }
    var name = envelope.body.shift()
    var message = envelope.body.shift()
    var handle = coalesce(envelope.body.shift())
    if (envelope.canceled) {
        if (handle != null) {
            handle.destroy()
        }
    } else {
        async(function () {
            this._registered.wait(Keyify.stringify([ to.name, to.index ]), async())
        }, function (registered) {
            this._transmitter.kibitz(registered.address, {
                name: name,
                body: message
            }, coalesce(handle))
        })
    }
}))

Olio.prototype.broadcast = restrictor.push(cadence(function (async, envelope) {
    if (!envelope.canceled) {
        var to = { name: envelope.body.shift() }
        var name = envelope.body.shift()
        var message = envelope.body.shift()
        async.loop([ 0 ], function (index) {
            if (index == this.counts[to.name]) {
                return [ async.break ]
            }
            async(function () {
                this._registered.wait(Keyify.stringify([ to.name, index ]), async())
            }, function (registered) {
                this._transmitter.kibitz(registered.address, {
                    name: name,
                    body: message
                }, null)
                return index + 1
            })
        })
    }
}))

Olio.prototype.ready = cadence(function (async, name) {
    this._ready.wait(name, async())
})

Olio.prototype._createSender = cadence(function (async, destructible, Receiver, message, index) {
    async(function () {
        var request = http.request({
            socketPath: this.socket,
            url: 'http://olio/',
            headers: Downgrader.headers({
                'x-olio-to-name': message.name,
                'x-olio-to-index': index,
                'x-olio-from-name': this.name,
                'x-olio-from-index': this.index
            })
        })
        delta(async()).ee(request).on('upgrade')
        request.end()
    }, function (request, socket, head) {
        async(function () {
            var readable = new Staccato.Readable(socket)
            var writable = new Staccato.Writable(socket)
            destructible.monitor('socket', Socket, {
                label: 'sender',
                from: { name: this.name, index: this.index },
                to: { name: message.name, index: index }
            }, readable, writable, head, async())
        }, function (inbox, outbox) {
            var shifter = inbox.shifter()
            async(function () {
                destructible.monitor('receiver', Receiver, inbox, outbox, async())
            }, function (conduit) {
                async(function () {
                    shifter.dequeue(async())
                }, function (header) {
                    Interrupt.assert(header.module == 'olio' && header.method == 'connect', 'failed to start middleware')
                    Interrupt.assert(shifter.shift() == null, 'unexpected traffic on connect')
                    // Do we do this or do we register an end to pumping instead? It
                    // would depend on how we feal about ending a Conduit. I do
                    // believe it pushed out a `null` to indicate that the stream
                    // has closed. A Window would look for this and wait for
                    // restart. The Window needs to be closed explicity.
                    return [ conduit ]
                })
            })
        })
    })
})

Olio.prototype.sender = cadence(function (async, name) {
    var vargs = Array.prototype.slice.call(arguments, 2)
    async(function () {
        this.ready(name, async())
    }, function (sibling) {
        var i = 0, receivers = []
        async(function () {
            async.loop([], function () {
                if (i == sibling.count) {
                    return [ async.break ]
                }
                // TODO `message.name` instead.
                this._destructible.monitor([ 'created', sibling.name, i ], this, '_createSender', vargs, sibling, i, async())
            }, function (receiver) {
                receivers[i++] = receiver
            })
        }, function () {
            return new Sender(receivers, sibling.addresses, sibling.count)
        })
    })
})

// TODO You're working through this right now.
//
// If one of our sender creators raises an error, we are ready with the error.
// Our destructible will gather up any other waiting initialzers, so that we
// will still get a full bouquet of errors through the destructible. We're
// turnign the corner here, you see, with an initialization stack that is
// waiting on the Olio constructor and multiple senders. Ready is not waiting on
// receivers, it waiting for all senders to be ready. Thus, we go forward when
// we have all our senders. We can still error building a receiver, though.
// (Let's put this in our unit tests.)
//
// Ordered thoughts.
//
// * We are waiting for all our senders to be ready because we cannot use the
// Olio until all the senders are ready.
// * Waiting on receivers is probably a function of having a countdow latch
// elsewhere that is waiting for incoming signals. Not a use case I've
// encountered yet though.
// * An error initializing a sender will cause us to be ready, but we report
// ready by passing the error.

//

module.exports = cadence(function (async, destructible, dispatcher, message) {
    return new Olio(destructible, dispatcher, message)
})
<commit_msg>Destroy the ready and registered Cubbyholes.<commit_after>// Node.js API.
var assert = require('assert')
var events = require('events')

var Procession = require('procession')

// An evented semaphore.
var Signal = require('signal')

// Return the first not null-like value.
var coalesce = require('extant')

// Asynchronous control flow.
var cadence = require('cadence')

// Do nothing.
var noop = require('nop')

// Generate a unique, canonical string key from a JSON object.
var Keyify = require('keyify')

// Controlled demolition of asynchronous operations.
var Destructible = require('destructible')

var Cubbyhole = require('cubbyhole')

var Interrupt = require('interrupt').createInterrupter('olio')

var Sender = require('./sender')

var http = require('http')
var Downgrader = require('downgrader')

var delta = require('delta')

var Conduit = require('conduit')

var Staccato = require('staccato')

var Socket = require('procession/socket')(require('./hangup'))

var Turnstile = require('turnstile')
var restrictor = require('restrictor')

var Keyify = require('keyify')

var events = require('events')
var util = require('util')

function Olio (destructible, dispatcher, message) {
    this.destroyed = false

    this._destructible = destructible
    this._destructible.destruct.wait(this, function () { this.destroyed = true })

    this._ready = dispatcher.ready
    this._registered = dispatcher.registered

    this.name = message.name
    this.index = message.index
    this.address = message.address
    this.socket = message.socket
    this.counts = message.counts

    this._transmitter = dispatcher.transmitter

    this.turnstile = new Turnstile
    this.turnstile.listen(destructible.monitor('turnstile'))
    destructible.destruct.wait(this.turnstile, 'destroy')

    destructible.destruct.wait(this, function () {
        this._ready.destroy(new Error('canceled'))
        this._registered.destroy(new Error('canceled'))
    })

    events.EventEmitter.call(this)
}
util.inherits(Olio, events.EventEmitter)

Olio.prototype.send = restrictor.push(cadence(function (async, envelope) {
    var to = {
        name: envelope.body.shift(),
        index: envelope.body.shift()
    }
    var name = envelope.body.shift()
    var message = envelope.body.shift()
    var handle = coalesce(envelope.body.shift())
    if (envelope.canceled) {
        if (handle != null) {
            handle.destroy()
        }
    } else {
        async(function () {
            this._registered.wait(Keyify.stringify([ to.name, to.index ]), async())
        }, function (registered) {
            this._transmitter.kibitz(registered.address, {
                name: name,
                body: message
            }, coalesce(handle))
        })
    }
}))

Olio.prototype.broadcast = restrictor.push(cadence(function (async, envelope) {
    if (!envelope.canceled) {
        var to = { name: envelope.body.shift() }
        var name = envelope.body.shift()
        var message = envelope.body.shift()
        async.loop([ 0 ], function (index) {
            if (index == this.counts[to.name]) {
                return [ async.break ]
            }
            async(function () {
                this._registered.wait(Keyify.stringify([ to.name, index ]), async())
            }, function (registered) {
                this._transmitter.kibitz(registered.address, {
                    name: name,
                    body: message
                }, null)
                return index + 1
            })
        })
    }
}))

Olio.prototype.ready = cadence(function (async, name) {
    this._ready.wait(name, async())
})

Olio.prototype._createSender = cadence(function (async, destructible, Receiver, message, index) {
    async(function () {
        var request = http.request({
            socketPath: this.socket,
            url: 'http://olio/',
            headers: Downgrader.headers({
                'x-olio-to-name': message.name,
                'x-olio-to-index': index,
                'x-olio-from-name': this.name,
                'x-olio-from-index': this.index
            })
        })
        delta(async()).ee(request).on('upgrade')
        request.end()
    }, function (request, socket, head) {
        async(function () {
            var readable = new Staccato.Readable(socket)
            var writable = new Staccato.Writable(socket)
            destructible.monitor('socket', Socket, {
                label: 'sender',
                from: { name: this.name, index: this.index },
                to: { name: message.name, index: index }
            }, readable, writable, head, async())
        }, function (inbox, outbox) {
            var shifter = inbox.shifter()
            async(function () {
                destructible.monitor('receiver', Receiver, inbox, outbox, async())
            }, function (conduit) {
                async(function () {
                    shifter.dequeue(async())
                }, function (header) {
                    Interrupt.assert(header.module == 'olio' && header.method == 'connect', 'failed to start middleware')
                    Interrupt.assert(shifter.shift() == null, 'unexpected traffic on connect')
                    // Do we do this or do we register an end to pumping instead? It
                    // would depend on how we feal about ending a Conduit. I do
                    // believe it pushed out a `null` to indicate that the stream
                    // has closed. A Window would look for this and wait for
                    // restart. The Window needs to be closed explicity.
                    return [ conduit ]
                })
            })
        })
    })
})

Olio.prototype.sender = cadence(function (async, name) {
    var vargs = Array.prototype.slice.call(arguments, 2)
    async(function () {
        this.ready(name, async())
    }, function (sibling) {
        var i = 0, receivers = []
        async(function () {
            async.loop([], function () {
                if (i == sibling.count) {
                    return [ async.break ]
                }
                // TODO `message.name` instead.
                this._destructible.monitor([ 'created', sibling.name, i ], this, '_createSender', vargs, sibling, i, async())
            }, function (receiver) {
                receivers[i++] = receiver
            })
        }, function () {
            return new Sender(receivers, sibling.addresses, sibling.count)
        })
    })
})

// TODO You're working through this right now.
//
// If one of our sender creators raises an error, we are ready with the error.
// Our destructible will gather up any other waiting initialzers, so that we
// will still get a full bouquet of errors through the destructible. We're
// turnign the corner here, you see, with an initialization stack that is
// waiting on the Olio constructor and multiple senders. Ready is not waiting on
// receivers, it waiting for all senders to be ready. Thus, we go forward when
// we have all our senders. We can still error building a receiver, though.
// (Let's put this in our unit tests.)
//
// Ordered thoughts.
//
// * We are waiting for all our senders to be ready because we cannot use the
// Olio until all the senders are ready.
// * Waiting on receivers is probably a function of having a countdow latch
// elsewhere that is waiting for incoming signals. Not a use case I've
// encountered yet though.
// * An error initializing a sender will cause us to be ready, but we report
// ready by passing the error.

//

module.exports = cadence(function (async, destructible, dispatcher, message) {
    return new Olio(destructible, dispatcher, message)
})
<|endoftext|>


<commit_before>(function()
{
    "use strict";

    var math = require('mathjs');

    var R = require('ramda');
    var Rp = require('./plus-fp/plus-fp');

    // modifying the final result
    // return -1..1

    exports.reducers = [
    {
        name: 'min',
        fn: math.min,
        weight: 1
    },
    {
        name: 'max',
        fn: math.max,
        weight: 1
    }
    // {
    //     name: 'last',
    //     fn: R.last,
    //     weight: 1
    // },
    // {
    //     name: 'mean',
    //     fn: math.mean,
    //     weight: 1
    // }
    ];

    var adjx = function(x, adj)
    {
        x += adj;

        if (x < -1)
        {
            x = 2 + x;
        }
        else if (x > 1)
        {
            x = -2 + x;
        }

        return x;
    };

    exports.modifiers = [
        {
            fn: function()
            {
                var fn = R.curry(function(phase, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var x = adjx(math.atan2(z.re, z.im) / math.pi, phase);

                        return x;
                    }, result.zs);

                    return vals;
                });

                var phase = math.random(-1, 1);

                return {
                    fn: fn(phase),
                    params:
                    {
                        name: 'angle',
                        phase: phase
                    }
                };
            },
            weight: 1,
        },
        {
            fn: function()
            {
                var fn = R.curry(function(phase, functal, result)
                {
                    var vals = R.mapIndexed(function(z, i, zs)
                    {
                        var x = 0;

                        if (i > 0)
                        {
                            var z1 = zs[i - 1];
                            var z2 = math.subtract(zs[i], z1);

                            x = math.atan2(z2.re, z2.im) / math.pi;
                        }

                        x = adjx(x, phase);

                        return x;

                    }, result.zs);

                    return vals;
                });

                var phase = math.random(-1, 1);

                return {
                    fn: fn(phase),
                    params:
                    {
                        name: 'angleChange',
                        phase: phase
                    }
                };
            },
            weight: 1,
        },
        {
            fn: function()
            {
                return {
                    fn: function real(functal, result)
                    {
                        // normalized z.re

                        var max = math.max(R.map(function(z)
                        {
                            return math.abs(z.re);
                        }, result.zs));

                        var vals = R.map(function(z)
                        {
                            return max ? z.re / max : 1;
                        }, result.zs);

                        return vals;
                    },
                    params:
                    {
                        name: 'real'
                    }
                };
            },
            weight: 1,
        },

        {
            fn: function()
            {
                var fn = R.curry(function(phase, functal, result)
                {
                    // normalized z.re

                    var max = math.max(R.map(function(z)
                    {
                        return math.abs(z.re);
                    }, result.zs));

                    var vals = R.map(function(z)
                    {
                        return adjx(max ? z.re / max : 1, offset);
                    }, result.zs);

                    return vals;
                });

                var offset = math.random(-1, 1);

                return {
                    fn: fn(offset),
                    params:
                    {
                        name: 'real',
                        offset: offset
                    }
                };
            },
            weight: 1,
        },

        {
            fn: function()
            {
                var fn = R.curry(function(phase, functal, result)
                {

                    var vals = R.map(function(z)
                    {
                        var x = functal.finite(math.norm(z)) / functal.limit;

                        return adjx(x, offset);
                    }, result.zs);

                    return vals;
                });

                var offset = math.random(-1, 1);

                return {
                    fn: fn(offset),
                    params:
                    {
                        name: 'norm',
                        offset: offset
                    }
                };
            },
            weight: 1,
        },

        {
            // point trap

            fn: function()
            {
                var fn = R.curry(function pointTrap(point, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var z1 = math.subtract(z, point);

                        var distance = math.sqrt(functal.finite(math.norm(z1)));

                        return distance;
                    }, result.zs);

                    return vals;
                });

                var point = math.complex(Rp.bandom(1, 2) * Rp.randomSign() - 1, Rp.bandom(1, 2) * Rp.randomSign());

                // return curried function with constant params
                return {
                    fn: fn(point),
                    params:
                    {
                        name: 'pointTrap',
                        point: point
                    }
                };
            },
            weight: 1,
        },

        {
            // circle trap

            fn: function()
            {
                var fn = R.curry(function circleTrap(diameter, band, centre, functal, result)
                {
                    var x;

                    var vals = R.map(function(z)
                    {
                        var z1 = math.subtract(z, centre);

                        var distance = math.sqrt(functal.finite(math.norm(z1)));

                        if (math.abs(distance - diameter) < band)
                        {
                            x = math.max(-1, math.min(1, distance - diameter));
                        }
                        else
                        {
                            x = 0;
                        }

                        return x;
                    }, result.zs);

                    return vals;
                });

                var diameter = Rp.bandom(1, -2);
                var band = Rp.bandom(1, -3);
                var centre = math.complex(Rp.bandom(1, 2) * Rp.randomSign() - 1, Rp.bandom(1, 2) * Rp.randomSign());

                // return curried function with constant params
                return {
                    fn: fn(diameter, band, centre),
                    params:
                    {
                        name: 'circleTrap',
                        diameter: diameter,
                        band: band,
                        centre: centre
                    }
                };
            },
            weight: 1,
        },
        {
            // real circle trap

            fn: function()
            {
                var fn = R.curry(function realCircleTrap(centre, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var x = math.mod(z.re - centre, 1);

                        return math.sqrt(math.max(0, 1.0 - x * x));

                    }, result.zs);

                    return vals;
                });

                var centre = math.complex(Rp.bandom(1, 2) * Rp.randomSign() - 1, Rp.bandom(1, 2) * Rp.randomSign());

                return {
                    fn: fn(centre),
                    params:
                    {
                        name: 'realCircleTrap',
                        centre: centre
                    }

                };

            },
            weight: 1,
        },
        {
            // box trap

            fn: function()
            {
                var fn = R.curry(function boxTrap(diameter, centre, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var z1 = math.subtract(z, centre);

                        var x = math.abs(z1.re);
                        var y = math.abs(z1.im);

                        var dist = math.max(x, y);

                        return math.mod(dist - diameter, 1);

                    }, result.zs);

                    var max = math.max(R.map(math.abs, vals));

                    return math.divide(vals, max);
                });

                var diameter = Rp.bandom(1, -2);
                var centre = math.complex(Rp.bandom(1, 2) * Rp.randomSign() - 1, Rp.bandom(1, 2) * Rp.randomSign());

                return {
                    fn: fn(diameter, centre),
                    params:
                    {
                        name: 'boxTrap',
                        diameter: diameter,
                        centre: centre
                    }

                };
            },
            weight: 2,
        },
        {
            // sin trap

            fn: function()
            {
                var fn = R.curry(function sinTrap(diameter, centre, ampl, freq, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var z1 = math.subtract(z, centre);

                        return z1.im + ampl * math.sin(freq * z1.re) - diameter;

                    }, result.zs);

                    var max = math.max(R.map(math.abs, vals));

                    return math.divide(vals, max);
                });

                var diameter = Rp.bandom(1, -2);
                var centre = math.complex(Rp.bandom(1, 2) * Rp.randomSign() - 1, Rp.bandom(1, 2) * Rp.randomSign());
                var freq = Rp.bandom(2, 4);
                var ampl = math.random(0.5);

                return {
                    fn: fn(diameter, centre, freq, ampl),
                    params:
                    {
                        name: 'sinTrap',
                        diameter: diameter,
                        centre: centre,
                        freq: freq,
                        ampl: ampl
                    }

                };
            },
            weight: 1,
        },
        {
            // real imag trap

            name: 'reimTrap',
            fn: function()
            {
                var fn = R.curry(function reimTrap(diameter, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var y = functal.finite(z.im * z.re) - diameter;

                        return y;

                    }, result.zs);

                    var max = math.max(R.map(math.abs, vals));

                    return math.divide(vals, max);

                });

                var diameter = Rp.bandom(1, -2);

                return {
                    fn: fn(diameter),
                    params:
                    {
                        name: 'reimTrap',
                        diameter: diameter
                    }

                };
            },
            weight: 1,
        },
        {
            // spiral trap

            name: 'spiralTrap',
            fn: function()
            {
                var fn = R.curry(function spiralTrap(freq, diameter, centre, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var z1 = math.subtract(z, centre);

                        var theta = math.atan2(z1.re, z1.im); // -pi .. pi

                        var ctheta = math.cos(theta);
                        var stheta = math.sin(theta);

                        theta = theta + math.pi; // 0..2pi

                        var minDist = 1e6;

                        var pi2 = 2.0 * math.pi;
                        var f = 1.0 / (math.pi * freq) * diameter; // factor to convert theta to a radius from 0..diam

                        // find the closest point in the spiral

                        for (var j = 0; j < freq; j++)
                        {
                            var theta2 = theta + j * pi2;

                            var r = theta2 * f;

                            var x = r  * ctheta;
                            var y = r  * stheta;

                            var dist = math.sqrt(math.square(x - z1.re) + math.square(y - z1.im));

                            minDist = math.min(dist, minDist);
                        }

                        return minDist;

                    }, result.zs);

                    var max = math.max(R.map(math.abs, vals));

                    return math.divide(vals, max);
                });

                var freq = math.randomInt(1, 11);
                var diameter = Rp.bandom(1, -2);
                var centre = math.complex(Rp.bandom(1, 2) * Rp.randomSign() - 1, Rp.bandom(1, 2) * Rp.randomSign());

                return {
                    fn: fn(freq, diameter, centre),
                    params:
                    {
                        name: 'spiralTrap',
                        freq: freq,
                        diameter: diameter,
                        centre: centre
                    }

                };
            },
            weight: 1,
        },
    ];
}());
<commit_msg>line traps<commit_after>(function()
{
    "use strict";

    var math = require('mathjs');

    var R = require('ramda');
    var Rp = require('./plus-fp/plus-fp');

    // modifying the final result
    // return -1..1

    exports.reducers = [
    {
        name: 'min',
        fn: math.min,
        weight: 1
    },
    {
        name: 'max',
        fn: math.max,
        weight: 1
    }
    // {
    //     name: 'last',
    //     fn: R.last,
    //     weight: 1
    // },
    // {
    //     name: 'mean',
    //     fn: math.mean,
    //     weight: 1
    // }
    ];

    var adjx = function(x, adj)
    {
        x += adj;

        if (x < -1)
        {
            x = 2 + x;
        }
        else if (x > 1)
        {
            x = -2 + x;
        }

        return x;
    };

    exports.modifiers = [
        {
            fn: function()
            {
                var fn = R.curry(function(phase, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var x = adjx(math.atan2(z.re, z.im) / math.pi, phase);

                        return x;
                    }, result.zs);

                    return vals;
                });

                var phase = math.random(-1, 1);

                return {
                    fn: fn(phase),
                    params:
                    {
                        name: 'angle',
                        phase: phase
                    }
                };
            },
            weight: 1,
        },
        {
            fn: function()
            {
                var fn = R.curry(function(phase, functal, result)
                {
                    var vals = R.mapIndexed(function(z, i, zs)
                    {
                        var x = 0;

                        if (i > 0)
                        {
                            var z1 = zs[i - 1];
                            var z2 = math.subtract(zs[i], z1);

                            x = math.atan2(z2.re, z2.im) / math.pi;
                        }

                        x = adjx(x, phase);

                        return x;

                    }, result.zs);

                    return vals;
                });

                var phase = math.random(-1, 1);

                return {
                    fn: fn(phase),
                    params:
                    {
                        name: 'angleChange',
                        phase: phase
                    }
                };
            },
            weight: 1,
        },
        {
            fn: function()
            {
                return {
                    fn: function real(functal, result)
                    {
                        // normalized z.re

                        var max = math.max(R.map(function(z)
                        {
                            return math.abs(z.re);
                        }, result.zs));

                        var vals = R.map(function(z)
                        {
                            return max ? z.re / max : 1;
                        }, result.zs);

                        return vals;
                    },
                    params:
                    {
                        name: 'real'
                    }
                };
            },
            weight: 1,
        },

        {
            fn: function()
            {
                var fn = R.curry(function(phase, functal, result)
                {
                    // normalized z.re

                    var max = math.max(R.map(function(z)
                    {
                        return math.abs(z.re);
                    }, result.zs));

                    var vals = R.map(function(z)
                    {
                        return adjx(max ? z.re / max : 1, offset);
                    }, result.zs);

                    return vals;
                });

                var offset = math.random(-1, 1);

                return {
                    fn: fn(offset),
                    params:
                    {
                        name: 'real',
                        offset: offset
                    }
                };
            },
            weight: 1,
        },

        {
            fn: function()
            {
                var fn = R.curry(function(phase, functal, result)
                {

                    var vals = R.map(function(z)
                    {
                        var x = functal.finite(math.norm(z)) / functal.limit;

                        return adjx(x, offset);
                    }, result.zs);

                    return vals;
                });

                var offset = math.random(-1, 1);

                return {
                    fn: fn(offset),
                    params:
                    {
                        name: 'norm',
                        offset: offset
                    }
                };
            },
            weight: 1,
        },

        {
            // point trap

            fn: function()
            {
                var fn = R.curry(function pointTrap(point, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var z1 = math.subtract(z, point);

                        var distance = math.sqrt(functal.finite(math.norm(z1)));

                        return distance;
                    }, result.zs);

                    return vals;
                });

                var point = math.complex(Rp.bandom(1, 2) * Rp.randomSign() - 1, Rp.bandom(1, 2) * Rp.randomSign());

                // return curried function with constant params
                return {
                    fn: fn(point),
                    params:
                    {
                        name: 'pointTrap',
                        point: point
                    }
                };
            },
            weight: 1,
        },

        {
            // vertical line trap

            fn: function()
            {
                var fn = R.curry(function pointTrap(x, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var distance = math.abs(z.re - x);

                        return distance;
                    }, result.zs);

                    return vals;
                });

                var x = math.random(-1, 1);

                return {
                    fn: fn(x),
                    params:
                    {
                        name: 'vertical line trap',
                        x: x
                    }
                };
            },
            weight: 1,
        },

        {
            // horizontal line trap

            fn: function()
            {
                var fn = R.curry(function pointTrap(y, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var distance = math.abs(z.im - y);

                        return distance;
                    }, result.zs);

                    return vals;
                });

                var y = math.random(-1, 1);

                return {
                    fn: fn(y),
                    params:
                    {
                        name: 'horizontal line trap',
                        y: y
                    }
                };
            },
            weight: 1,
        },

        {
            // circle trap

            fn: function()
            {
                var fn = R.curry(function circleTrap(diameter, band, centre, functal, result)
                {
                    var x;

                    var vals = R.map(function(z)
                    {
                        var z1 = math.subtract(z, centre);

                        var distance = math.sqrt(functal.finite(math.norm(z1)));

                        if (math.abs(distance - diameter) < band)
                        {
                            x = math.max(-1, math.min(1, distance - diameter));
                        }
                        else
                        {
                            x = 0;
                        }

                        return x;
                    }, result.zs);

                    return vals;
                });

                var diameter = Rp.bandom(1, -2);
                var band = Rp.bandom(1, -3);
                var centre = math.complex(Rp.bandom(1, 2) * Rp.randomSign() - 1, Rp.bandom(1, 2) * Rp.randomSign());

                // return curried function with constant params
                return {
                    fn: fn(diameter, band, centre),
                    params:
                    {
                        name: 'circleTrap',
                        diameter: diameter,
                        band: band,
                        centre: centre
                    }
                };
            },
            weight: 1,
        },
        {
            // real circle trap

            fn: function()
            {
                var fn = R.curry(function realCircleTrap(centre, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var x = math.mod(z.re - centre, 1);

                        return math.sqrt(math.max(0, 1.0 - x * x));

                    }, result.zs);

                    return vals;
                });

                var centre = math.complex(Rp.bandom(1, 2) * Rp.randomSign() - 1, Rp.bandom(1, 2) * Rp.randomSign());

                return {
                    fn: fn(centre),
                    params:
                    {
                        name: 'realCircleTrap',
                        centre: centre
                    }

                };

            },
            weight: 1,
        },
        {
            // box trap

            fn: function()
            {
                var fn = R.curry(function boxTrap(diameter, centre, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var z1 = math.subtract(z, centre);

                        var x = math.abs(z1.re);
                        var y = math.abs(z1.im);

                        var dist = math.max(x, y);

                        return math.mod(dist - diameter, 1);

                    }, result.zs);

                    var max = math.max(R.map(math.abs, vals));

                    return math.divide(vals, max);
                });

                var diameter = Rp.bandom(1, -2);
                var centre = math.complex(Rp.bandom(1, 2) * Rp.randomSign() - 1, Rp.bandom(1, 2) * Rp.randomSign());

                return {
                    fn: fn(diameter, centre),
                    params:
                    {
                        name: 'boxTrap',
                        diameter: diameter,
                        centre: centre
                    }

                };
            },
            weight: 2,
        },
        {
            // sin trap

            fn: function()
            {
                var fn = R.curry(function sinTrap(diameter, centre, ampl, freq, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var z1 = math.subtract(z, centre);

                        return z1.im + ampl * math.sin(freq * z1.re) - diameter;

                    }, result.zs);

                    var max = math.max(R.map(math.abs, vals));

                    return math.divide(vals, max);
                });

                var diameter = Rp.bandom(1, -2);
                var centre = math.complex(Rp.bandom(1, 2) * Rp.randomSign() - 1, Rp.bandom(1, 2) * Rp.randomSign());
                var freq = Rp.bandom(2, 4);
                var ampl = math.random(0.5);

                return {
                    fn: fn(diameter, centre, freq, ampl),
                    params:
                    {
                        name: 'sinTrap',
                        diameter: diameter,
                        centre: centre,
                        freq: freq,
                        ampl: ampl
                    }

                };
            },
            weight: 1,
        },
        {
            // real imag trap

            name: 'reimTrap',
            fn: function()
            {
                var fn = R.curry(function reimTrap(diameter, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var y = functal.finite(z.im * z.re) - diameter;

                        return y;

                    }, result.zs);

                    var max = math.max(R.map(math.abs, vals));

                    return math.divide(vals, max);

                });

                var diameter = Rp.bandom(1, -2);

                return {
                    fn: fn(diameter),
                    params:
                    {
                        name: 'reimTrap',
                        diameter: diameter
                    }

                };
            },
            weight: 1,
        },
        {
            // spiral trap

            name: 'spiralTrap',
            fn: function()
            {
                var fn = R.curry(function spiralTrap(freq, diameter, centre, functal, result)
                {
                    var vals = R.map(function(z)
                    {
                        var z1 = math.subtract(z, centre);

                        var theta = math.atan2(z1.re, z1.im); // -pi .. pi

                        var ctheta = math.cos(theta);
                        var stheta = math.sin(theta);

                        theta = theta + math.pi; // 0..2pi

                        var minDist = 1e6;

                        var pi2 = 2.0 * math.pi;
                        var f = 1.0 / (math.pi * freq) * diameter; // factor to convert theta to a radius from 0..diam

                        // find the closest point in the spiral

                        for (var j = 0; j < freq; j++)
                        {
                            var theta2 = theta + j * pi2;

                            var r = theta2 * f;

                            var x = r  * ctheta;
                            var y = r  * stheta;

                            var dist = math.sqrt(math.square(x - z1.re) + math.square(y - z1.im));

                            minDist = math.min(dist, minDist);
                        }

                        return minDist;

                    }, result.zs);

                    var max = math.max(R.map(math.abs, vals));

                    return math.divide(vals, max);
                });

                var freq = math.randomInt(1, 11);
                var diameter = Rp.bandom(1, -2);
                var centre = math.complex(Rp.bandom(1, 2) * Rp.randomSign() - 1, Rp.bandom(1, 2) * Rp.randomSign());

                return {
                    fn: fn(freq, diameter, centre),
                    params:
                    {
                        name: 'spiralTrap',
                        freq: freq,
                        diameter: diameter,
                        centre: centre
                    }

                };
            },
            weight: 1,
        },
    ];
}());
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2019 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview The class representing a cursor.
 * Used primarily for keyboard navigation.
 * @author aschmiedt@google.com (Abby Schmiedt)
 */
'use strict';

goog.provide('Blockly.Cursor');

goog.require('Blockly.ASTNode');
goog.require('Blockly.Marker');
goog.require('Blockly.registry');
goog.require('Blockly.utils.object');

/**
 * Class for a cursor.
 * A cursor controls how a user navigates the Blockly AST.
 * @constructor
 * @extends {Blockly.Marker}
 */
Blockly.Cursor = function() {
  Blockly.Cursor.superClass_.constructor.call(this);

  /**
   * @override
   */
  this.type = 'cursor';
};
Blockly.utils.object.inherits(Blockly.Cursor, Blockly.Marker);

/**
 * Find the next connection, field, or block.
 * @return {Blockly.ASTNode} The next element, or null if the current node is
 *     not set or there is no next value.
 * @public
 */
Blockly.Cursor.prototype.next = function() {
  var curNode = this.getCurNode();
  if (!curNode) {
    return null;
  }

  var newNode = curNode.next();
  while (newNode && newNode.next() &&
         (newNode.getType() == Blockly.ASTNode.types.NEXT ||
          newNode.getType() == Blockly.ASTNode.types.BLOCK)) {
    newNode = newNode.next();
  }

  if (newNode) {
    this.setCurNode(newNode);
  }
  return newNode;
};

/**
 * Find the in connection or field.
 * @return {Blockly.ASTNode} The in element, or null if the current node is
 *     not set or there is no in value.
 * @public
 */
Blockly.Cursor.prototype.in = function() {
  var curNode = this.getCurNode();
  if (!curNode) {
    return null;
  }
  // If we are on a previous or output connection, go to the block level before
  // performing next operation.
  if (curNode.getType() == Blockly.ASTNode.types.PREVIOUS ||
      curNode.getType() == Blockly.ASTNode.types.OUTPUT) {
    curNode = curNode.next();
  }
  var newNode = curNode.in();

  if (newNode) {
    this.setCurNode(newNode);
  }
  return newNode;
};

/**
 * Find the previous connection, field, or block.
 * @return {Blockly.ASTNode} The previous element, or null if the current node
 *     is not set or there is no previous value.
 * @public
 */
Blockly.Cursor.prototype.prev = function() {
  var curNode = this.getCurNode();
  if (!curNode) {
    return null;
  }
  var newNode = curNode.prev();

  while (newNode && newNode.prev() &&
         (newNode.getType() == Blockly.ASTNode.types.NEXT ||
          newNode.getType() == Blockly.ASTNode.types.BLOCK)) {
    newNode = newNode.prev();
  }

  if (newNode) {
    this.setCurNode(newNode);
  }
  return newNode;
};

/**
 * Find the out connection, field, or block.
 * @return {Blockly.ASTNode} The out element, or null if the current node is
 *     not set or there is no out value.
 * @public
 */
Blockly.Cursor.prototype.out = function() {
  var curNode = this.getCurNode();
  if (!curNode) {
    return null;
  }
  var newNode = curNode.out();

  if (newNode && newNode.getType() == Blockly.ASTNode.types.BLOCK) {
    newNode = newNode.prev() || newNode;
  }

  if (newNode) {
    this.setCurNode(newNode);
  }
  return newNode;
};

Blockly.registry.register(
    Blockly.registry.Type.CURSOR, Blockly.registry.DEFAULT, Blockly.Cursor);
<commit_msg>Migrate core/keyboard_nav/cursor.js to ES6 const/let<commit_after>/**
 * @license
 * Copyright 2019 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview The class representing a cursor.
 * Used primarily for keyboard navigation.
 * @author aschmiedt@google.com (Abby Schmiedt)
 */
'use strict';

goog.provide('Blockly.Cursor');

goog.require('Blockly.ASTNode');
goog.require('Blockly.Marker');
goog.require('Blockly.registry');
goog.require('Blockly.utils.object');

/**
 * Class for a cursor.
 * A cursor controls how a user navigates the Blockly AST.
 * @constructor
 * @extends {Blockly.Marker}
 */
Blockly.Cursor = function() {
  Blockly.Cursor.superClass_.constructor.call(this);

  /**
   * @override
   */
  this.type = 'cursor';
};
Blockly.utils.object.inherits(Blockly.Cursor, Blockly.Marker);

/**
 * Find the next connection, field, or block.
 * @return {Blockly.ASTNode} The next element, or null if the current node is
 *     not set or there is no next value.
 * @public
 */
Blockly.Cursor.prototype.next = function() {
  const curNode = this.getCurNode();
  if (!curNode) {
    return null;
  }

  let newNode = curNode.next();
  while (newNode && newNode.next() &&
         (newNode.getType() == Blockly.ASTNode.types.NEXT ||
          newNode.getType() == Blockly.ASTNode.types.BLOCK)) {
    newNode = newNode.next();
  }

  if (newNode) {
    this.setCurNode(newNode);
  }
  return newNode;
};

/**
 * Find the in connection or field.
 * @return {Blockly.ASTNode} The in element, or null if the current node is
 *     not set or there is no in value.
 * @public
 */
Blockly.Cursor.prototype.in = function() {
  let curNode = this.getCurNode();
  if (!curNode) {
    return null;
  }
  // If we are on a previous or output connection, go to the block level before
  // performing next operation.
  if (curNode.getType() == Blockly.ASTNode.types.PREVIOUS ||
      curNode.getType() == Blockly.ASTNode.types.OUTPUT) {
    curNode = curNode.next();
  }
  const newNode = curNode.in();

  if (newNode) {
    this.setCurNode(newNode);
  }
  return newNode;
};

/**
 * Find the previous connection, field, or block.
 * @return {Blockly.ASTNode} The previous element, or null if the current node
 *     is not set or there is no previous value.
 * @public
 */
Blockly.Cursor.prototype.prev = function() {
  const curNode = this.getCurNode();
  if (!curNode) {
    return null;
  }
  let newNode = curNode.prev();

  while (newNode && newNode.prev() &&
         (newNode.getType() == Blockly.ASTNode.types.NEXT ||
          newNode.getType() == Blockly.ASTNode.types.BLOCK)) {
    newNode = newNode.prev();
  }

  if (newNode) {
    this.setCurNode(newNode);
  }
  return newNode;
};

/**
 * Find the out connection, field, or block.
 * @return {Blockly.ASTNode} The out element, or null if the current node is
 *     not set or there is no out value.
 * @public
 */
Blockly.Cursor.prototype.out = function() {
  const curNode = this.getCurNode();
  if (!curNode) {
    return null;
  }
  let newNode = curNode.out();

  if (newNode && newNode.getType() == Blockly.ASTNode.types.BLOCK) {
    newNode = newNode.prev() || newNode;
  }

  if (newNode) {
    this.setCurNode(newNode);
  }
  return newNode;
};

Blockly.registry.register(
    Blockly.registry.Type.CURSOR, Blockly.registry.DEFAULT, Blockly.Cursor);
<|endoftext|>


<commit_before>const debug = require('ghost-ignition').debug('web:site:app');
const path = require('path');
const express = require('express');
const cors = require('cors');
const {URL} = require('url');

// App requires
const config = require('../../config');
const common = require('../../lib/common');
const apps = require('../../services/apps');
const constants = require('../../lib/constants');
const storage = require('../../adapters/storage');
const urlService = require('../../../frontend/services/url');
const labsService = require('../../services/labs');
const urlUtils = require('../../lib/url-utils');
const sitemapHandler = require('../../../frontend/services/sitemap/handler');
const themeMiddleware = require('../../../frontend/services/themes').middleware;
const membersService = require('../../services/members');
const siteRoutes = require('./routes');
const shared = require('../shared');

const STATIC_IMAGE_URL_PREFIX = `/${urlUtils.STATIC_IMAGE_URL_PREFIX}`;

let router;

const corsOptionsDelegate = function corsOptionsDelegate(req, callback) {
    const origin = req.header('Origin');
    const corsOptions = {
        origin: false, // disallow cross-origin requests by default
        credentials: true // required to allow admin-client to login to private sites
    };

    if (origin) {
        const originUrl = new URL(origin);

        // allow all localhost and 127.0.0.1 requests no matter the port
        if (originUrl.hostname === 'localhost' || originUrl.hostname === '127.0.0.1') {
            corsOptions.origin = true;
        }

        // allow the configured host through on any protocol
        const siteUrl = new URL(config.get('url'));
        if (originUrl.host === siteUrl.host) {
            corsOptions.origin = true;
        }

        // allow the configured admin:url host through on any protocol
        if (config.get('admin:url')) {
            const adminUrl = new URL(config.get('admin:url'));
            if (originUrl.host === adminUrl.host) {
                corsOptions.origin = true;
            }
        }
    }

    callback(null, corsOptions);
};

function SiteRouter(req, res, next) {
    router(req, res, next);
}

module.exports = function setupSiteApp(options = {}) {
    debug('Site setup start');

    const siteApp = express();

    // Make sure 'req.secure' is valid for proxied requests
    // (X-Forwarded-Proto header will be checked, if present)
    // NB: required here because it's not passed down via vhost
    siteApp.enable('trust proxy');

    // ## App - specific code
    // set the view engine
    siteApp.set('view engine', 'hbs');

    // enable CORS headers (allows admin client to hit front-end when configured on separate URLs)
    siteApp.use(cors(corsOptionsDelegate));

    // you can extend Ghost with a custom redirects file
    // see https://github.com/TryGhost/Ghost/issues/7707
    shared.middlewares.customRedirects.use(siteApp);

    // More redirects
    siteApp.use(shared.middlewares.adminRedirects());

    // force SSL if blog url is set to https. The redirects handling must happen before asset and page routing,
    // otherwise we serve assets/pages with http. This can cause mixed content warnings in the admin client.
    siteApp.use(shared.middlewares.urlRedirects);

    // Static content/assets
    // @TODO make sure all of these have a local 404 error handler
    // Favicon
    siteApp.use(shared.middlewares.serveFavicon());

    // /public/members.js
    siteApp.get('/public/members-theme-bindings.js',
        shared.middlewares.labs('members'),
        shared.middlewares.servePublicFile.createPublicFileMiddleware(
            'public/members-theme-bindings.js',
            'application/javascript',
            constants.ONE_HOUR_S
        )
    );
    siteApp.get('/public/members.js',
        shared.middlewares.labs('members'),
        shared.middlewares.servePublicFile.createPublicFileMiddleware(
            'public/members.js',
            'application/javascript',
            constants.ONE_HOUR_S
        )
    );

    // Serve sitemap.xsl file
    siteApp.use(shared.middlewares.servePublicFile('sitemap.xsl', 'text/xsl', constants.ONE_DAY_S));

    // Serve stylesheets for default templates
    siteApp.use(shared.middlewares.servePublicFile('public/ghost.css', 'text/css', constants.ONE_HOUR_S));
    siteApp.use(shared.middlewares.servePublicFile('public/ghost.min.css', 'text/css', constants.ONE_YEAR_S));

    // Serve images for default templates
    siteApp.use(shared.middlewares.servePublicFile('public/404-ghost@2x.png', 'png', constants.ONE_HOUR_S));
    siteApp.use(shared.middlewares.servePublicFile('public/404-ghost.png', 'png', constants.ONE_HOUR_S));

    // Serve blog images using the storage adapter
    siteApp.use(STATIC_IMAGE_URL_PREFIX, shared.middlewares.image.handleImageSizes, storage.getStorage().serve());

    // @TODO find this a better home
    // We do this here, at the top level, because helpers require so much stuff.
    // Moving this to being inside themes, where it probably should be requires the proxy to be refactored
    // Else we end up with circular dependencies
    require('../../../frontend/helpers').loadCoreHelpers();
    debug('Helpers done');

    // @TODO only loads this stuff if members is enabled
    // Set req.member & res.locals.member if a cookie is set
    siteApp.get('/members/ssr', shared.middlewares.labs.members, async function (req, res) {
        try {
            const token = await membersService.ssr.getIdentityTokenForMemberFromSession(req, res);
            res.writeHead(200);
            res.end(token);
        } catch (err) {
            common.logging.warn(err.message);
            res.writeHead(err.statusCode);
            res.end(err.message);
        }
    });

    siteApp.delete('/members/ssr', shared.middlewares.labs.members, async function (req, res) {
        try {
            await membersService.ssr.deleteSession(req, res);
            res.writeHead(204);
            res.end();
        } catch (err) {
            common.logging.warn(err.message);
            res.writeHead(err.statusCode);
            res.end(err.message);
        }
    });
    siteApp.post('/members/webhooks/stripe', (req, res, next) => membersService.api.middleware.handleStripeWebhook(req, res, next));
    siteApp.use(async function (req, res, next) {
        if (!labsService.isSet('members')) {
            req.member = null;
            return next();
        }
        try {
            const member = await membersService.ssr.getMemberDataFromSession(req, res);
            Object.assign(req, {member});
            next();
        } catch (err) {
            common.logging.warn(err.message);
            Object.assign(req, {member: null});
            next();
        }
    });
    siteApp.use(async function (req, res, next) {
        if (!labsService.isSet('members')) {
            return next();
        }
        if (!req.url.includes('token=')) {
            return next();
        }
        try {
            const member = await membersService.ssr.exchangeTokenForSession(req, res);
            Object.assign(req, {member});
            next();
        } catch (err) {
            common.logging.warn(err.message);
            return next();
        }
    });
    siteApp.use(function (req, res, next) {
        res.locals.member = req.member;
        next();
    });

    // Theme middleware
    // This should happen AFTER any shared assets are served, as it only changes things to do with templates
    // At this point the active theme object is already updated, so we have the right path, so it can probably
    // go after staticTheme() as well, however I would really like to simplify this and be certain
    siteApp.use(themeMiddleware);
    debug('Themes done');

    // Theme static assets/files
    siteApp.use(shared.middlewares.staticTheme());
    debug('Static content done');

    // Serve robots.txt if not found in theme
    siteApp.use(shared.middlewares.servePublicFile('robots.txt', 'text/plain', constants.ONE_HOUR_S));

    // setup middleware for internal apps
    // @TODO: refactor this to be a proper app middleware hook for internal & external apps
    config.get('apps:internal').forEach((appName) => {
        const app = require(path.join(config.get('paths').internalAppPath, appName));

        if (Object.prototype.hasOwnProperty.call(app, 'setupMiddleware')) {
            app.setupMiddleware(siteApp);
        }
    });

    // site map - this should probably be refactored to be an internal app
    sitemapHandler(siteApp);
    debug('Internal apps done');

    // send 503 error page in case of maintenance
    siteApp.use(shared.middlewares.maintenance);

    // Add in all trailing slashes & remove uppercase
    // must happen AFTER asset loading and BEFORE routing
    siteApp.use(shared.middlewares.prettyUrls);

    // ### Caching
    // Site frontend is cacheable UNLESS request made by a member
    const publicCacheControl = shared.middlewares.cacheControl('public');
    const privateCacheControl = shared.middlewares.cacheControl('private');
    siteApp.use(function (req, res, next) {
        if (req.member) {
            return privateCacheControl(req, res, next);
        } else {
            return publicCacheControl(req, res, next);
        }
    });

    debug('General middleware done');

    router = siteRoutes(options);
    Object.setPrototypeOf(SiteRouter, router);

    // Set up Frontend routes (including private blogging routes)
    siteApp.use(SiteRouter);

    // ### Error handlers
    siteApp.use(shared.middlewares.errorHandler.pageNotFound);
    siteApp.use(shared.middlewares.errorHandler.handleThemeResponse);

    debug('Site setup end');

    return siteApp;
};

module.exports.reload = () => {
    // https://github.com/expressjs/express/issues/2596
    router = siteRoutes({start: true});
    Object.setPrototypeOf(SiteRouter, router);

    // re-initialse apps (register app routers, because we have re-initialised the site routers)
    apps.init();

    // connect routers and resources again
    urlService.queue.start({
        event: 'init',
        tolerance: 100,
        requiredSubscriberCount: 1
    });
};
<commit_msg>Wired up middleware to handle unsubscribing<commit_after>const debug = require('ghost-ignition').debug('web:site:app');
const path = require('path');
const express = require('express');
const cors = require('cors');
const {URL} = require('url');

// App requires
const config = require('../../config');
const common = require('../../lib/common');
const apps = require('../../services/apps');
const constants = require('../../lib/constants');
const storage = require('../../adapters/storage');
const urlService = require('../../../frontend/services/url');
const labsService = require('../../services/labs');
const urlUtils = require('../../lib/url-utils');
const sitemapHandler = require('../../../frontend/services/sitemap/handler');
const themeMiddleware = require('../../../frontend/services/themes').middleware;
const megaService = require('../../services/mega');
const membersService = require('../../services/members');
const siteRoutes = require('./routes');
const shared = require('../shared');

const STATIC_IMAGE_URL_PREFIX = `/${urlUtils.STATIC_IMAGE_URL_PREFIX}`;

let router;

const corsOptionsDelegate = function corsOptionsDelegate(req, callback) {
    const origin = req.header('Origin');
    const corsOptions = {
        origin: false, // disallow cross-origin requests by default
        credentials: true // required to allow admin-client to login to private sites
    };

    if (origin) {
        const originUrl = new URL(origin);

        // allow all localhost and 127.0.0.1 requests no matter the port
        if (originUrl.hostname === 'localhost' || originUrl.hostname === '127.0.0.1') {
            corsOptions.origin = true;
        }

        // allow the configured host through on any protocol
        const siteUrl = new URL(config.get('url'));
        if (originUrl.host === siteUrl.host) {
            corsOptions.origin = true;
        }

        // allow the configured admin:url host through on any protocol
        if (config.get('admin:url')) {
            const adminUrl = new URL(config.get('admin:url'));
            if (originUrl.host === adminUrl.host) {
                corsOptions.origin = true;
            }
        }
    }

    callback(null, corsOptions);
};

function SiteRouter(req, res, next) {
    router(req, res, next);
}

module.exports = function setupSiteApp(options = {}) {
    debug('Site setup start');

    const siteApp = express();

    // Make sure 'req.secure' is valid for proxied requests
    // (X-Forwarded-Proto header will be checked, if present)
    // NB: required here because it's not passed down via vhost
    siteApp.enable('trust proxy');

    // ## App - specific code
    // set the view engine
    siteApp.set('view engine', 'hbs');

    // enable CORS headers (allows admin client to hit front-end when configured on separate URLs)
    siteApp.use(cors(corsOptionsDelegate));

    // you can extend Ghost with a custom redirects file
    // see https://github.com/TryGhost/Ghost/issues/7707
    shared.middlewares.customRedirects.use(siteApp);

    // More redirects
    siteApp.use(shared.middlewares.adminRedirects());

    // force SSL if blog url is set to https. The redirects handling must happen before asset and page routing,
    // otherwise we serve assets/pages with http. This can cause mixed content warnings in the admin client.
    siteApp.use(shared.middlewares.urlRedirects);

    // Static content/assets
    // @TODO make sure all of these have a local 404 error handler
    // Favicon
    siteApp.use(shared.middlewares.serveFavicon());

    // /public/members.js
    siteApp.get('/public/members-theme-bindings.js',
        shared.middlewares.labs('members'),
        shared.middlewares.servePublicFile.createPublicFileMiddleware(
            'public/members-theme-bindings.js',
            'application/javascript',
            constants.ONE_HOUR_S
        )
    );
    siteApp.get('/public/members.js',
        shared.middlewares.labs('members'),
        shared.middlewares.servePublicFile.createPublicFileMiddleware(
            'public/members.js',
            'application/javascript',
            constants.ONE_HOUR_S
        )
    );

    // Serve sitemap.xsl file
    siteApp.use(shared.middlewares.servePublicFile('sitemap.xsl', 'text/xsl', constants.ONE_DAY_S));

    // Serve stylesheets for default templates
    siteApp.use(shared.middlewares.servePublicFile('public/ghost.css', 'text/css', constants.ONE_HOUR_S));
    siteApp.use(shared.middlewares.servePublicFile('public/ghost.min.css', 'text/css', constants.ONE_YEAR_S));

    // Serve images for default templates
    siteApp.use(shared.middlewares.servePublicFile('public/404-ghost@2x.png', 'png', constants.ONE_HOUR_S));
    siteApp.use(shared.middlewares.servePublicFile('public/404-ghost.png', 'png', constants.ONE_HOUR_S));

    // Serve blog images using the storage adapter
    siteApp.use(STATIC_IMAGE_URL_PREFIX, shared.middlewares.image.handleImageSizes, storage.getStorage().serve());

    // @TODO find this a better home
    // We do this here, at the top level, because helpers require so much stuff.
    // Moving this to being inside themes, where it probably should be requires the proxy to be refactored
    // Else we end up with circular dependencies
    require('../../../frontend/helpers').loadCoreHelpers();
    debug('Helpers done');

    // @TODO only loads this stuff if members is enabled
    // Set req.member & res.locals.member if a cookie is set
    siteApp.get('/members/ssr', shared.middlewares.labs.members, async function (req, res) {
        try {
            const token = await membersService.ssr.getIdentityTokenForMemberFromSession(req, res);
            res.writeHead(200);
            res.end(token);
        } catch (err) {
            common.logging.warn(err.message);
            res.writeHead(err.statusCode);
            res.end(err.message);
        }
    });

    siteApp.delete('/members/ssr', shared.middlewares.labs.members, async function (req, res) {
        try {
            await membersService.ssr.deleteSession(req, res);
            res.writeHead(204);
            res.end();
        } catch (err) {
            common.logging.warn(err.message);
            res.writeHead(err.statusCode);
            res.end(err.message);
        }
    });
    siteApp.post('/members/webhooks/stripe', (req, res, next) => membersService.api.middleware.handleStripeWebhook(req, res, next));
    siteApp.use(async function (req, res, next) {
        if (!labsService.isSet('members')) {
            req.member = null;
            return next();
        }
        try {
            const member = await membersService.ssr.getMemberDataFromSession(req, res);
            Object.assign(req, {member});
            next();
        } catch (err) {
            common.logging.warn(err.message);
            Object.assign(req, {member: null});
            next();
        }
    });
    siteApp.use(async function (req, res, next) {
        if (!labsService.isSet('members')) {
            return next();
        }
        if (!req.url.includes('token=')) {
            return next();
        }
        try {
            const member = await membersService.ssr.exchangeTokenForSession(req, res);
            Object.assign(req, {member});
            next();
        } catch (err) {
            common.logging.warn(err.message);
            return next();
        }
    });
    siteApp.use(async function (req, res, next) {
        if (!labsService.isSet('members')) {
            return next();
        }
        if (!req.url.includes('unsubscribe=')) {
            return next();
        }
        try {
            await megaService.mega.handleUnsubscribeRequest(req);
            next();
        } catch (err) {
            common.logging.warn(err.message);
            return next();
        }
    });
    siteApp.use(function (req, res, next) {
        res.locals.member = req.member;
        next();
    });

    // Theme middleware
    // This should happen AFTER any shared assets are served, as it only changes things to do with templates
    // At this point the active theme object is already updated, so we have the right path, so it can probably
    // go after staticTheme() as well, however I would really like to simplify this and be certain
    siteApp.use(themeMiddleware);
    debug('Themes done');

    // Theme static assets/files
    siteApp.use(shared.middlewares.staticTheme());
    debug('Static content done');

    // Serve robots.txt if not found in theme
    siteApp.use(shared.middlewares.servePublicFile('robots.txt', 'text/plain', constants.ONE_HOUR_S));

    // setup middleware for internal apps
    // @TODO: refactor this to be a proper app middleware hook for internal & external apps
    config.get('apps:internal').forEach((appName) => {
        const app = require(path.join(config.get('paths').internalAppPath, appName));

        if (Object.prototype.hasOwnProperty.call(app, 'setupMiddleware')) {
            app.setupMiddleware(siteApp);
        }
    });

    // site map - this should probably be refactored to be an internal app
    sitemapHandler(siteApp);
    debug('Internal apps done');

    // send 503 error page in case of maintenance
    siteApp.use(shared.middlewares.maintenance);

    // Add in all trailing slashes & remove uppercase
    // must happen AFTER asset loading and BEFORE routing
    siteApp.use(shared.middlewares.prettyUrls);

    // ### Caching
    // Site frontend is cacheable UNLESS request made by a member
    const publicCacheControl = shared.middlewares.cacheControl('public');
    const privateCacheControl = shared.middlewares.cacheControl('private');
    siteApp.use(function (req, res, next) {
        if (req.member) {
            return privateCacheControl(req, res, next);
        } else {
            return publicCacheControl(req, res, next);
        }
    });

    debug('General middleware done');

    router = siteRoutes(options);
    Object.setPrototypeOf(SiteRouter, router);

    // Set up Frontend routes (including private blogging routes)
    siteApp.use(SiteRouter);

    // ### Error handlers
    siteApp.use(shared.middlewares.errorHandler.pageNotFound);
    siteApp.use(shared.middlewares.errorHandler.handleThemeResponse);

    debug('Site setup end');

    return siteApp;
};

module.exports.reload = () => {
    // https://github.com/expressjs/express/issues/2596
    router = siteRoutes({start: true});
    Object.setPrototypeOf(SiteRouter, router);

    // re-initialse apps (register app routers, because we have re-initialised the site routers)
    apps.init();

    // connect routers and resources again
    urlService.queue.start({
        event: 'init',
        tolerance: 100,
        requiredSubscriberCount: 1
    });
};
<|endoftext|>


<commit_before>////////////////////////////////
// Controller for admin panel //
////////////////////////////////

'use strict';

pay.controller('Admin', [
    '$scope',
    '$http',
    '$timeout',
    'PayAuth',
    'Event',
    'FormValidator',
    'Error',
    function ($scope, $http, $timeout, PayAuth, Event, FormValidator, Error) {
        if (!PayAuth.needUser()) { return; }

        $scope.isAdmin = PayAuth.etu.isAdmin === true;
        $scope.fundation = PayAuth.etu.fundation;

        /**
         * Show events list
         */
        function getEventsListsWithAccounts () {
            Event.query(function (events) {
                var keptEvents = [];
                var keptEventsSeller = [];
                $http.get('/api/accounts/' + PayAuth.etu.id).then(function (data) {
                    data.data.forEach(function (account) {
                        events.forEach(function (event) {
                            if (event.id === account.event) {
                                if (PayAuth.etu.isAdmin) {
                                    keptEvents.push(event);
                                    keptEventsSeller.push(event);
                                } else if (account.admin) {
                                    keptEvents.push(event);
                                } else {
                                    keptEventsSeller.push(event);
                                }
                            }
                        });
                    });
                }, function () {
                    Error('Erreur', 0);
                });

                $scope.events = keptEvents;
                $scope.eventsSeller = keptEventsSeller;
            });
        }

        getEventsListsWithAccounts();

        // Model for the new event
        $scope.newEvent = {};
        $scope.fileInfo = null;
        $scope.datePattern = /^\d{1,2}\/\d{1,2}\/\d{4} [0-2][0-9]?:[0-5]?[0-9]$/;

        /**
         * Called when the ng-if has been evaluted
         */
        this.activateDate = function () {
            // Activate the datepicker, and ng-validate when the date changes
            $('.date').datetimepicker().on('dp.change', function () {
                var $self = $(this).children().first();
                $timeout(function () {
                    $self.data().$ngModelController.$setViewValue($self.val());
                }, 0);
            });
        };

        /**
         * Called when the ng-if has been evaluated
         */
        this.activateFile = function () {
            // Updates the input text with the input file name
            $('input[type=file]').on('change', function (e) {
                if (this.files.length === 1) {
                    $(this).parent().parent().next().val(this.files[0].name);
                }
            });
        };

        /**
         * Creates a event
         */
        this.createEvent = function () {
            if (!FormValidator(newEventForm, 'file')) {
                return;
            }

            var file = newEventForm.file.files[0];

            // Image -> string
            var reader = new FileReader();
            reader.onload = function (e) {
                var result = e.currentTarget.result;
                // Duplicate event to preserve from changes made by the resource
                var newEventData = jQuery.extend(true, {}, $scope.newEvent);

                newEventData.image = result;
                newEventData.date = moment(newEventData.date, 'DD/MM/YYYY HH:mm').toDate();
                newEventData.fundationId = $scope.fundation.id;
                var newEvent = new Event(newEventData);
                newEvent.$save(function () {
                    getEventsListsWithAccounts();
                }, function (res) {
                    // Request entity too large => file size too large
                    if (res.status === 413) {
                        Error('Erreur', 16);
                    }
                    Error('Erreur', res.data.error);
                });
            };
            reader.readAsDataURL(file);
        };
    }
]);
<commit_msg>Wait for user account to be done to reload<commit_after>////////////////////////////////
// Controller for admin panel //
////////////////////////////////

'use strict';

pay.controller('Admin', [
    '$scope',
    '$http',
    '$timeout',
    'PayAuth',
    'Event',
    'FormValidator',
    'Error',
    function ($scope, $http, $timeout, PayAuth, Event, FormValidator, Error) {
        if (!PayAuth.needUser()) { return; }

        $scope.isAdmin = PayAuth.etu.isAdmin === true;
        $scope.fundation = PayAuth.etu.fundation;

        /**
         * Show events list
         */
        function getEventsListsWithAccounts () {
            Event.query(function (events) {
                var keptEvents = [];
                var keptEventsSeller = [];
                $http.get('/api/accounts/' + PayAuth.etu.id).then(function (data) {
                    data.data.forEach(function (account) {
                        events.forEach(function (event) {
                            if (event.id === account.event) {
                                if (PayAuth.etu.isAdmin) {
                                    keptEvents.push(event);
                                    keptEventsSeller.push(event);
                                } else if (account.admin) {
                                    keptEvents.push(event);
                                } else {
                                    keptEventsSeller.push(event);
                                }
                            }
                        });
                    });
                }, function () {
                    Error('Erreur', 0);
                });

                $scope.events = keptEvents;
                $scope.eventsSeller = keptEventsSeller;
            });
        }

        getEventsListsWithAccounts();

        // Model for the new event
        $scope.newEvent = {};
        $scope.fileInfo = null;
        $scope.datePattern = /^\d{1,2}\/\d{1,2}\/\d{4} [0-2][0-9]?:[0-5]?[0-9]$/;

        /**
         * Called when the ng-if has been evaluted
         */
        this.activateDate = function () {
            // Activate the datepicker, and ng-validate when the date changes
            $('.date').datetimepicker().on('dp.change', function () {
                var $self = $(this).children().first();
                $timeout(function () {
                    $self.data().$ngModelController.$setViewValue($self.val());
                }, 0);
            });
        };

        /**
         * Called when the ng-if has been evaluated
         */
        this.activateFile = function () {
            // Updates the input text with the input file name
            $('input[type=file]').on('change', function (e) {
                if (this.files.length === 1) {
                    $(this).parent().parent().next().val(this.files[0].name);
                }
            });
        };

        /**
         * Creates a event
         */
        this.createEvent = function () {
            if (!FormValidator(newEventForm, 'file')) {
                return;
            }

            var file = newEventForm.file.files[0];

            // Image -> string
            var reader = new FileReader();
            reader.onload = function (e) {
                var result = e.currentTarget.result;
                // Duplicate event to preserve from changes made by the resource
                var newEventData = jQuery.extend(true, {}, $scope.newEvent);

                newEventData.image = result;
                newEventData.date = moment(newEventData.date, 'DD/MM/YYYY HH:mm').toDate();
                newEventData.fundationId = $scope.fundation.id;
                var newEvent = new Event(newEventData);
                newEvent.$save(function () {
                    getEventsListsWithAccounts();
                    $timeout(function () {
                        $scope.$emit('$locationChangeSuccess', '');
                    }, 1000);
                }, function (res) {
                    // Request entity too large => file size too large
                    if (res.status === 413) {
                        Error('Erreur', 16);
                    }
                    Error('Erreur', res.data.error);
                });
            };
            reader.readAsDataURL(file);
        };
    }
]);
<|endoftext|>


<commit_before>//latest

//adding this override to address the callback when limit is one.
cracked.array_next = function(arr,offset,limit,callback) {
    offset = offset || 0;
    limit = limit || arr.length;
    var adjusted_limit = Math.min(limit,arr.length);
    var adjusted_offset = Math.min(offset,adjusted_limit-1);
    var old_index = arr.current_index = __.ifUndef(arr.current_index,-1);
    arr.current_index = (arr.current_index+1+adjusted_offset) >= adjusted_limit ? 0 : arr.current_index+1;
    if((old_index >= arr.current_index) && (typeof callback === "function")) {
        callback();
    }
    return arr[arr.current_index + adjusted_offset];
};

/*
  v1_length
  v2_length
  v3_length
  v4_length

  v1_throttle
  v2_throttle
  v3_throttle
  v4_throttle
*/

/////////////////////////////

var v1_length_staging = 0;
var v2_length_staging = 0
var v3_length_staging = 0;
var v4_length_staging = 0;

var v1_length = 0;
var v2_length = 0
var v3_length = 0;
var v4_length = 0;

var throttle_64  = function(d){return d >=64;};
var throttle_32  = function(d){return d >=32;};
var throttle_16  = function(d){return d >=16;};
var throttle_8   = function(d){return d >=8};
var throttle_4   = function(d){return d >=4};
var throttle_2   = function(d){return d >=2};
var throttle_1   = function(d){return d >=1};

var v1_throttle_staging = throttle_4;
var v2_throttle_staging = throttle_2;
var v3_throttle_staging = throttle_16;
var v4_throttle_staging = throttle_1;
var v5_throttle_staging = throttle_4;

var v1_throttle = throttle_4;
var v2_throttle = throttle_2;
var v3_throttle = throttle_16;
var v4_throttle = throttle_1;
var v5_throttle = throttle_4;

var throttle_lookup = [
    throttle_1,
    throttle_2,
    throttle_4,
    throttle_8,
    throttle_16,
    throttle_32,
    throttle_64
];

/////////////////////////////

__().gain({id:"main"}).overdrive().overdrive().overdrive().dac(1);

for(var z=0;z<20;z++) {

  var v = Math.floor(z/5)+1;
  var p = {v1:-1,v2:1,v3:-1/2,v4:1/2};
  __().sine({id:"s"+z}).gain({class:"v"+v}).gain({class:"level_"+v}).panner(p["v"+v]).connect("#main");

}
__().sine(120).lowpass({q:200,frequency:60}).adsr(1/16).gain({id:"kick"}).gain({class:"kick_level"}).connect("#main");

/////////////////////////////

var chord = [0,4,7,10,12];
var chord2 = [0,4,7,10,12];
var chord3 = [0,4,7,10,12];
var chord4 = [0,4,7,10,12];
var step = 0;

var ok_to_run = [
    true,
    true,
    true,
    true,
    true
];

__("gain").volume(0);
__("#main,#kick").volume(1);
__(".level_1,.level_2,.level_3,.level_4,.kick_level").volume(1);
__(".v1,.v2,.v3,.v4").volume(1/20);

__.loop({interval:75,steps:64},function(idx,data) {

///////////////////////////// V1

  if(v1_throttle(data) && ok_to_run[0]) {

    var p = __.array_next(chord,0,v1_length,function(){
        v1_length = v1_length_staging;
        v1_throttle = v1_throttle_staging;
    });

    for(var i=0;i<chord.length;i++) {
      __("#s"+i).frequency(__.pitch2freq(p+i*12+48+step));
    }

  }

///////////////////////////// V2

  if(v2_throttle(data) && ok_to_run[1]) {

    var p2 = __.array_next(chord2,0,v2_length,function(){
        v2_length = v2_length_staging;
        v2_throttle = v2_throttle_staging;
    });

    for(var j=0;j<chord2.length;j++) {
      __("#s"+(j+5)).frequency(__.pitch2freq(p2+j*12+36+step));
    }

  }

///////////////////////////// V3

    if(v3_throttle(data) && ok_to_run[2]) {

        var p3 = __.array_next(chord3,0,v3_length,function(){
            v3_length = v3_length_staging;
            v3_throttle = v3_throttle_staging;
        });

        for(var k=0;k<chord3.length;k++) {
            __("#s"+(k+10)).frequency(__.pitch2freq(p3+k*12+24+step));
        }

    }

///////////////////////////// V4

    if(v4_throttle(data) && ok_to_run[3]) {

        var p4 = __.array_next(chord4,0,v4_length,function(){
            v4_length = v4_length_staging;
            v4_throttle = v4_throttle_staging;
        });

        for(var l=0;l<chord2.length;l++) {
            __("#s"+(l+15)).frequency(__.pitch2freq(p4+l*12+72+step));
        }

    }

///////////////////////////// V5

  if(v5_throttle(data) && ok_to_run[4]) {

    v5_throttle = v5_throttle_staging;

    __("adsr").adsr("trigger");

  }

},[
        64,1,2,1,4,1,2,1,8,1,2,1,4,1,2,1,
        16,1,2,1,4,1,2,1,8,1,2,1,4,1,2,1,
        32,1,2,1,4,1,2,1,8,1,2,1,4,1,2,1,
        16,1,2,1,4,1,2,1,8,1,2,1,4,1,2,1
]);

/* monome code below **************************************/
//the model
var monome_model = {};
//copy the old one
var previous_monome_model = {};

//dispatch events to the right functions
function dispatch_event(item) {
    if(item.x === 15) {
        switch(item.y) {
            case 7:
                item.led_state = item.led_state ? 0 : 1;
                break;
            case 0:
                item.led_state = item.led_state ? 0 : 1;
                break;
            default:
                item.led_state = 1;
                break;
        }
        dispatch_control(item);
    } else {
        item.led_state = 1;
        switch(item.x) {
            case 0:
                //endpoint v1
                dispatch_endpoint(item);
                break;
            case 1:
                //endpoint v2
                dispatch_endpoint(item);
                break;
            case 2:
                //endpoint v3
                dispatch_endpoint(item);
                break;
            case 3:
                //endpoint v4
                dispatch_endpoint(item);
                break;
            case 4:
                //throttle v1
                dispatch_throttle(item);
                break;
            case 5:
                //throttle v2
                dispatch_throttle(item);
                break;
            case 6:
                //throttle v3
                dispatch_throttle(item);
                break;
            case 7:
                //throttle v4
                dispatch_throttle(item);
                break;
            case 8:
                //throttle kick
                dispatch_throttle(item);
                break;
            case 9:
                //level v1
                dispatch_level(item);
                break;
            case 10:
                //level v2
                dispatch_level(item);
                break;
            case 11:
                //level v3
                dispatch_level(item);
                break;
            case 12:
                //level v4
                dispatch_level(item);
                break;
            case 13:
                //level kick
                dispatch_level(item);
                break;
            case 14:
                break;
            default:
                break;
        }
    }
}

//clear the column
function clear_column(x) {
    Object.keys(monome_model).map(function(el,idx,arr){
        if(!(x === 15 && monome_model[el].y===7) && !(x === 15 && monome_model[el].y===0)) {
            var regexp = new RegExp('mn_col_'+x+"_");
            if(regexp.test(el)) {
                delete monome_model[el];
            }
        }
    });
}

//handle press events
function handle_press(x,y) {

    var item;

    if(!(x===15 && y === 7)&&!(x===15 && y === 0)) {
        clear_column(x);
    }

    if(monome_model['mn_col_'+x+'_row_'+y]) {
        item = monome_model['mn_col_'+x+'_row_'+y];
    } else {
        item = {
            "led_state":0,
            "x":x,
            "y":y
        };
        monome_model['mn_col_'+x+'_row_'+y] = item;
    }

    dispatch_event(monome_model['mn_col_'+x+'_row_'+y]);
    update_monome();
}

//update the monome view - sync leds w model
function update_monome() {

    //if a key is missing from the current model, then it
    //has been deleted and we want to turn the led off
    Object.keys(previous_monome_model).map(function(el,idx,arr){

        if(!monome_model[el]) {
            __.monome_led_off(previous_monome_model[el].x,previous_monome_model[el].y);
        }

    });

    //update the monome from the current model
    Object.keys(monome_model).map(function(el,idx,arr) {
        var item = monome_model[el];
        if(item.led_state) {
            __.monome_led_on(item.x, item.y);
        } else {
            __.monome_led_off(item.x, item.y);
        }
    });

    //save a copy of the model for later reference
    previous_monome_model = Object.assign({},monome_model);

}

function dispatch_control(item) {
    switch(item.y) {
        case 7:
            if(item.led_state) {
                __.loop("start");
                __("dac").volume(1).play();
            } else {
                __.loop("stop");
                __("dac").volume(0).stop();
            }
            break;
         case 0:
            if(item.led_state) {
                __.loop("stop");
            } else {
                __.loop("start");
            }
        default:
            break;
    }
}

function dispatch_endpoint(item) {
    switch(item.x) {
        case 0:
            v1_length_staging = Math.max(chord.length-item.y,1);
            break;
        case 1:
            v2_length_staging = Math.max(chord.length-item.y,1);
            break;
        case 2:
            v3_length_staging = Math.max(chord.length-item.y,1);
            break;
        case 3:
            v4_length_staging = Math.max(chord.length-item.y,1);
            break;
    }
}

function dispatch_throttle(item) {
    if(item.y === 7) {
        ok_to_run[item.x-4]=false;
    } else {
        ok_to_run[item.x-4]=true;
        switch(item.x) {
            case 4:
                v1_throttle_staging = throttle_lookup[item.y] ? throttle_lookup[item.y] : v1_throttle_staging;
                break;
            case 5:
                v2_throttle_staging = throttle_lookup[item.y] ? throttle_lookup[item.y] : v2_throttle_staging;
                break;
            case 6:
                v3_throttle_staging = throttle_lookup[item.y] ? throttle_lookup[item.y] : v3_throttle_staging;
                break;
            case 7:
                v4_throttle_staging = throttle_lookup[item.y] ? throttle_lookup[item.y] : v4_throttle_staging;
                break;
            case 8:
                v5_throttle_staging = throttle_lookup[item.y] ? throttle_lookup[item.y] : v5_throttle_staging;
                break;
        }
    }
}

function dispatch_level(item) {
    switch(item.x) {
        case 9:
            __(".level_1").volume((7-item.y)/7);
            break;
        case 10:
            __(".level_2").volume((7-item.y)/7);
            break;
        case 11:
            __(".level_3").volume((7-item.y)/7);
            break;
        case 12:
            __(".level_4").volume((7-item.y)/7);
            break;
        case 13:
            __(".kick_level").volume((7-item.y)/7);
            break;
    }
}

//general purpose button handler
__.monome_press(function(x,y,s) {
    if(s) {
        handle_press(x,y);
    }
});

function set_individual_values(x,y) {
    monome_model['mn_col_'+x+'_row_'+y] = {
        "led_state":1,
        "x":x,
        "y":y
    };
}

function clear_monome() {
    for(var i=0;i<16;i++) {
        for(var j=0;j<8;j++) {
            __.monome_led_off(i, j);
        }
    }
}

//reset the sucker
clear_monome();

//v1_length
set_individual_values(0,v1_length);
//v2_length
set_individual_values(1,v2_length);
//v3_length
set_individual_values(2,v3_length);
//v4_length
set_individual_values(3,v4_length);

//v1_throttle
set_individual_values(4,throttle_lookup.indexOf(v1_throttle));
//v2_throttle
set_individual_values(5,throttle_lookup.indexOf(v2_throttle));
//v3_throttle
set_individual_values(6,throttle_lookup.indexOf(v3_throttle));
//v4_throttle
set_individual_values(7,throttle_lookup.indexOf(v4_throttle));
//v5_throttle
set_individual_values(8,throttle_lookup.indexOf(v5_throttle));

//v1 level
set_individual_values(9,0);
//v2 level
set_individual_values(10,0);
//v3 level
set_individual_values(11,0);
//v4 level
set_individual_values(12,0);
//kick level
set_individual_values(13,0);

//update the leds
update_monome();
<commit_msg>Delete latest.js<commit_after><|endoftext|>