<commit_before>/*#ifndef(UMD)*/
(function () { /* Begin of privacy scope */
    "use strict";
/*#endif*/

    var
        gpfI = gpf.interfaces,
        _BUFREADSTREAM_READ_SIZE        = 256,
        _BUFREADSTREAM_ISTATE_INIT        = 0,
        _BUFREADSTREAM_ISTATE_INPROGRESS  = 1,
        _BUFREADSTREAM_ISTATE_WAITING     = 2,
        _BUFREADSTREAM_ISTATE_EOS         = 3;

    /**
     * The Readable stream interface is the abstraction for a source of data
     * that you are reading from. In other words, data comes out of a Readable
     * stream.
     *
     * @class gpf.interfaces.IReadableStream
     * @extends gpf.interfaces.Interface
     */
    gpf._defIntrf("IReadableStream", {

        /**
         * Triggers the reading of data.
         * The expected behavior is:
         * - The callback is asynchronous
         * - One of the following callback must be called after a read
         *   - EVENT_ERROR: an error occurred.
         *     the stream can't be used after this.
         *   - EVENT_END_OF_STREAM: stream ended.
         *     the stream can't be used after this.
         *   - EVENT_DATA: a buffer is provided, it can't be empty.
         *
         * @param {Number} [size=0] size Number of bytes to read. Read
         * as much as possible if 0
         * @param {gpf.events.Handler} eventsHandler
         *
         * @event data Some data is ready to be used
         * @eventParam {gpf.IReadOnlyArray} buffer Bytes buffer
         *
         * @event eos No more data can be read from the stream
         *
         */
        read: function (size, eventsHandler) {
            gpf.interfaces.ignoreParameter(size);
            gpf.interfaces.ignoreParameter(eventsHandler);
        },

        static: {
            EVENT_ERROR: "error",
            EVENT_DATA: "data",
            EVENT_END_OF_STREAM: "eos",

            EXCEPTION_READ_IN_PROGRESS: {
                message: "Read in progress"
            }
        }

    });

    /**
     * The Writable stream interface is an abstraction for a destination that
     * you are writing data to.
     * The expected behavior is:
     * - The callback is asynchronous
     * - One of the following callback must be called after a read
     *   - EVENT_ERROR: an error occurred.
     *     the stream can't be used after this.
     *   - EVENT_READY: the write operation succeeded, the provided buffer has
     *     been fully written (otherwise an error is thrown)
     *
     * @class gpf.interfaces.IReadableStream
     * @extends gpf.interfaces.Interface
     */
    gpf._defIntrf("IWritableStream", {

        /**
         * Triggers the writing of data
         *
         * @param {IReadOnlyArray} int8buffer Buffer to write
         * @param {gpf.events.Handler} eventsHandler
         *
         * @event ready it is appropriate to begin writing more data to the
         * stream
         *
         */
        write: function (int8buffer, eventsHandler) {
            gpf.interfaces.ignoreParameter(int8buffer);
            gpf.interfaces.ignoreParameter(eventsHandler);
        },

        static: {
            EVENT_ERROR: "error",
            EVENT_READY: "ready",

            EXCEPTION_WRITE_IN_PROGRESS: {
                message: "Read in progress"
            }
        }

    });

    /**
     * The stream combines both IReadableStream and IWritableStream
     */
    gpf._defIntrf("IStream", {

        /**
         * @inheritDoc gpf.interfaces.IReadableStream:read
         */
        read: function (size, eventsHandler) {
            gpf.interfaces.ignoreParameter(size);
            gpf.interfaces.ignoreParameter(eventsHandler);
        },

        /**
         * @inheritDoc gpf.interfaces.IWritableStream:write
         */
        write: function (int8buffer, eventsHandler) {
            gpf.interfaces.ignoreParameter(int8buffer);
            gpf.interfaces.ignoreParameter(eventsHandler);
        }

    });

    /**
     * Text stream: instead of an int8 buffer, the interface handles strings
     *
     * @class gpf.interfaces.ITextStream
     * @extends gpf.interfaces.IStream
     *
     * @event data Some data is ready to be ready
     * @eventParam {String} buffer
     */
    gpf._defIntrf("ITextStream", gpfI.IStream, {
    });

    /**
     * Internal helper to implement the expected write behavior in all streams
     * @inheritDoc gpf.interfaces.ITextStream:write
     */
    gpfI.ITextStream._write = function () {
        var argIdx, arg;
        for (argIdx = 0; argIdx < arguments.length; ++argIdx) {
            arg = arguments[argIdx];
            if (null !== arg && "string" !== typeof arg) {
                arg = arg.toString();
            }
            this.write_(arg);
        }
        if (0 === argIdx) { // No parameter at all
            this.write_(null);
        }
    };

    //region Stream helpers

    gpf.stream = {};

    /**
     * Handles a buffered stream that depends on a read stream.
     * The way the underlying buffer is read and converted can be overridden
     * through the following protected APIs:
     * - _readSize
     * - _addToBuffer
     *
     * @class gpf.stream.BufferedOnRead
     * @abstract
     * @implements gpf.interfaces.IReadableStream
     */
    gpf.define("gpf.stream.BufferedOnRead", {

        "[Class]": [gpf.$InterfaceImplement(gpfI.IReadableStream)],

        //region Configurable part

        protected: {

            /**
             * Output buffer containing content to be read
             *
             * @type {*[]}
             * @protected
             */
            _buffer: [],

            /**
             * Length of the buffer (compared with read size)
             *
             * @type {Number}
             * @protected
             */
            _bufferLength: 0,

            /**
             * Underlying stream default read size
             *
             * @type {Number}
             * @protected
             */
            _readSize: _BUFREADSTREAM_READ_SIZE,

            /**
             * Process underlying stream buffer (this should grow the output
             * buffer)
             *
             * @param {Array} buffer
             * @abstract
             * @protected
             */
            _addToBuffer: function (buffer) {
                gpf.interfaces.ignoreParameter(buffer);
                gpf.Error.Abstract();
            },

            /**
             * Underlying stream reached its end (this may grow the output
             * buffer)
             *
             * @protected
             */
            _endOfInputStream: function () {
            },

            /**
             * Read buffer.
             * This default implementation checks the buffer type to switch
             * between string and byte array.
             *
             * @param {Number} size
             * @returns {String|Array}
             * @protected
             */
            _readFromBuffer: function (size) {
                gpf.ASSERT(0 !== this._buffer.length, "Buffer is not empty");
                if ("string" === this._buffer[0]) {
                    return this._readFromStringBuffer(size);
                } else {
                    return this._readFromByteBuffer(size);
                }
            },

            /**
             * Read string buffer.
             *
             * @param {Number} size
             * @returns {String}
             * @protected
             */
            _readFromStringBuffer: function (size) {
                var
                    result = gpf.stringExtractFromStringArray(this._buffer,
                        size);
                this._bufferLength -= result.length;
                return result;
            },

            /**
             * Read byte buffer.
             *
             * @param {Number} size
             * @returns {Array}
             * @protected
             */
            _readFromByteBuffer: function (size) {
                var
                    buffer = this._buffer,
                    len = buffer.length;
                if (size > len) {
                    size = len;
                }
                this._bufferLength -= size;
                return buffer.splice(0, size);
            }

        },

        //endregion

        //region Implementation

        public: {

            /**
             * @param {gpf.interfaces.IReadableStream} input
             * @constructor
             */
            constructor: function (input) {
                this._iStream = gpfI.query(input, gpfI.IReadableStream, true);
                this._buffer = [];
            },

            //region gpf.interfaces.IReadableStream

            /**
             * @implements gpf.interfaces.IReadableStream:read
             */
            read: function (size, eventsHandler) {
                var
                    iState = this._iState,
                    length = this._bufferLength;
                if (_BUFREADSTREAM_ISTATE_INPROGRESS === iState) {
                    // A read call is already in progress
                    throw gpfI.IReadableStream.EXCEPTION_READ_IN_PROGRESS;

                } else if (size < length
                    || length && _BUFREADSTREAM_ISTATE_EOS === iState) {
                    // Enough chars in the output buffer to do the read
                    // OR there won't be any more chars. Can output something.
                    gpf.events.fire.apply(this, [
                        gpfI.IReadableStream.EVENT_DATA,
                        {
                            buffer: this._readFromBuffer(size)
                        },
                        eventsHandler
                    ]);

                } else if (_BUFREADSTREAM_ISTATE_EOS === iState) {
                    // No more input and output buffer is empty
                    gpf.events.fire.apply(this, [
                        gpfI.IReadableStream.EVENT_END_OF_STREAM,
                        eventsHandler
                    ]);

                } else {
                    // Read input
                    if (_BUFREADSTREAM_ISTATE_INIT === this._iState) {
                        // Very first call, create callback for input reads
                        this._cbRead = new gpf.Callback(this._onRead, this);
                    }
                    this._iState = _BUFREADSTREAM_ISTATE_INPROGRESS;
                    // Backup parameters
                    this._size = size;
                    this._eventsHandler = eventsHandler;
                    this._iStream.read(this._readSize, this._cbRead);
                }
            }

            //endregion
        },

        private: {

            /**
             * Input stream
             * @type {gpf.interfaces.IReadableStream}
             */
            _iStream: null,

            /**
             * Input stream read callback (pointing to this:_onRead)
             * @type {gpf.Callback}
             */
            _cbRead: null,

            /**
             * Input state
             * @type {Number} see _BUFREADSTREAM_ISTATE_xxx
             */
            _iState: _BUFREADSTREAM_ISTATE_INIT,

            /**
             * Pending read call size
             * @type {Number}
             */
            _size: 0,

            /**
             * Pending read call event handlers
             * @type {gpf.events.Handler}
             */
            _eventsHandler: null,

            /**
             * Handles input stream read event
             *
             * @param {gpf.events.Event} event
             * @private
             */
            _onRead: function (event) {
                var
                    type = event.type();
                if (type === gpfI.IReadableStream.EVENT_END_OF_STREAM) {
                    this._iState = _BUFREADSTREAM_ISTATE_EOS;
                    this._endOfInputStream();
                    // Redirect to read with backed parameters
                    return this.read(this._size, this._eventsHandler);

                } else if (type === gpfI.IReadableStream.EVENT_ERROR) {
                    // Forward the event
                    gpf.events.fire.apply(this, [
                        event,
                        this._eventsHandler
                    ]);

                } else {
                    this._iState = _BUFREADSTREAM_ISTATE_WAITING;
                    this._addToBuffer(event.get("buffer"));
                    if (0 < this._bufferLength) {
                        // Redirect to read with backed parameters
                        return this.read(this._size, this._eventsHandler);
                    } else {
                        // Try to read source again
                        this._iStream.read(_BUFREADSTREAM_READ_SIZE,
                            this._cbRead);
                    }
                }
            }

        }

        //endregion
    });

    /**
     *
     * @param {gpf.interfaces.ITextStream} stream
     * @param {gpf.events.Handler} eventsHandler
     * @param {Function} concatMethod
     *
     * @forwardThis
     *
     * @event data finished reading the stream, the buffer is provided
     * @eventParam {Array|String} buffer
     */
    gpf.stream.readAll = function (stream, concatMethod, eventsHandler) {
        stream = gpf.interfaces.query(stream, gpfI.IReadableStream,  true);
        (new StreamReader(this, eventsHandler, concatMethod)).read(stream);
    };

    function StreamReader(scope, eventsHandler, concatMethod) {
        this._scope = gpf.Callback.resolveScope(scope);
        this._eventsHandler = eventsHandler;
        this._concatMethod = concatMethod;
    }
    gpf.extend(StreamReader.prototype, {

        _scope: null,
        _eventsHandler: null,
        _concatMethod: null,
        _buffer: undefined,

        read: function (stream) {
            stream.read(0, gpf.Callback.bind(this, "callback"));
        },

        callback: function (event) {
            var
                type = event.type(),
                stream = event.scope();
            if (type === gpfI.IReadableStream.EVENT_END_OF_STREAM) {
                gpf.events.fire.apply(this._scope, [
                    gpfI.IReadableStream.EVENT_DATA,
                    {
                        buffer: this._concatMethod(this._buffer)
                    },
                    this._eventsHandler
                ]);

            } else if (type === gpfI.IReadableStream.EVENT_ERROR) {
                // Forward the event
                gpf.events.fire.apply(this._scope, [
                    event,
                    this._eventsHandler
                ]);

            } else {
                this._buffer = this._concatMethod(this._buffer,
                    event.get("buffer"));
                this.read(stream);
            }
        }

    });

    //endregion

/*#ifndef(UMD)*/
}()); /* End of privacy scope */
/*#endif*/<commit_msg>Initialize size if not set<commit_after>/*#ifndef(UMD)*/
(function () { /* Begin of privacy scope */
    "use strict";
/*#endif*/

    var
        gpfI = gpf.interfaces,
        _BUFREADSTREAM_READ_SIZE        = 256,
        _BUFREADSTREAM_ISTATE_INIT        = 0,
        _BUFREADSTREAM_ISTATE_INPROGRESS  = 1,
        _BUFREADSTREAM_ISTATE_WAITING     = 2,
        _BUFREADSTREAM_ISTATE_EOS         = 3;

    /**
     * The Readable stream interface is the abstraction for a source of data
     * that you are reading from. In other words, data comes out of a Readable
     * stream.
     *
     * @class gpf.interfaces.IReadableStream
     * @extends gpf.interfaces.Interface
     */
    gpf._defIntrf("IReadableStream", {

        /**
         * Triggers the reading of data.
         * The expected behavior is:
         * - The callback is asynchronous
         * - One of the following callback must be called after a read
         *   - EVENT_ERROR: an error occurred.
         *     the stream can't be used after this.
         *   - EVENT_END_OF_STREAM: stream ended.
         *     the stream can't be used after this.
         *   - EVENT_DATA: a buffer is provided, it can't be empty.
         *
         * @param {Number} [size=0] size Number of bytes to read. Read
         * as much as possible if 0
         * @param {gpf.events.Handler} eventsHandler
         *
         * @event data Some data is ready to be used
         * @eventParam {gpf.IReadOnlyArray} buffer Bytes buffer
         *
         * @event eos No more data can be read from the stream
         *
         */
        read: function (size, eventsHandler) {
            gpf.interfaces.ignoreParameter(size);
            gpf.interfaces.ignoreParameter(eventsHandler);
        },

        static: {
            EVENT_ERROR: "error",
            EVENT_DATA: "data",
            EVENT_END_OF_STREAM: "eos",

            EXCEPTION_READ_IN_PROGRESS: {
                message: "Read in progress"
            }
        }

    });

    /**
     * The Writable stream interface is an abstraction for a destination that
     * you are writing data to.
     * The expected behavior is:
     * - The callback is asynchronous
     * - One of the following callback must be called after a read
     *   - EVENT_ERROR: an error occurred.
     *     the stream can't be used after this.
     *   - EVENT_READY: the write operation succeeded, the provided buffer has
     *     been fully written (otherwise an error is thrown)
     *
     * @class gpf.interfaces.IReadableStream
     * @extends gpf.interfaces.Interface
     */
    gpf._defIntrf("IWritableStream", {

        /**
         * Triggers the writing of data
         *
         * @param {IReadOnlyArray} int8buffer Buffer to write
         * @param {gpf.events.Handler} eventsHandler
         *
         * @event ready it is appropriate to begin writing more data to the
         * stream
         *
         */
        write: function (int8buffer, eventsHandler) {
            gpf.interfaces.ignoreParameter(int8buffer);
            gpf.interfaces.ignoreParameter(eventsHandler);
        },

        static: {
            EVENT_ERROR: "error",
            EVENT_READY: "ready",

            EXCEPTION_WRITE_IN_PROGRESS: {
                message: "Read in progress"
            }
        }

    });

    /**
     * The stream combines both IReadableStream and IWritableStream
     */
    gpf._defIntrf("IStream", {

        /**
         * @inheritDoc gpf.interfaces.IReadableStream:read
         */
        read: function (size, eventsHandler) {
            gpf.interfaces.ignoreParameter(size);
            gpf.interfaces.ignoreParameter(eventsHandler);
        },

        /**
         * @inheritDoc gpf.interfaces.IWritableStream:write
         */
        write: function (int8buffer, eventsHandler) {
            gpf.interfaces.ignoreParameter(int8buffer);
            gpf.interfaces.ignoreParameter(eventsHandler);
        }

    });

    /**
     * Text stream: instead of an int8 buffer, the interface handles strings
     *
     * @class gpf.interfaces.ITextStream
     * @extends gpf.interfaces.IStream
     *
     * @event data Some data is ready to be ready
     * @eventParam {String} buffer
     */
    gpf._defIntrf("ITextStream", gpfI.IStream, {
    });

    /**
     * Internal helper to implement the expected write behavior in all streams
     * @inheritDoc gpf.interfaces.ITextStream:write
     */
    gpfI.ITextStream._write = function () {
        var argIdx, arg;
        for (argIdx = 0; argIdx < arguments.length; ++argIdx) {
            arg = arguments[argIdx];
            if (null !== arg && "string" !== typeof arg) {
                arg = arg.toString();
            }
            this.write_(arg);
        }
        if (0 === argIdx) { // No parameter at all
            this.write_(null);
        }
    };

    //region Stream helpers

    gpf.stream = {};

    /**
     * Handles a buffered stream that depends on a read stream.
     * The way the underlying buffer is read and converted can be overridden
     * through the following protected APIs:
     * - _readSize
     * - _addToBuffer
     *
     * @class gpf.stream.BufferedOnRead
     * @abstract
     * @implements gpf.interfaces.IReadableStream
     */
    gpf.define("gpf.stream.BufferedOnRead", {

        "[Class]": [gpf.$InterfaceImplement(gpfI.IReadableStream)],

        //region Configurable part

        protected: {

            /**
             * Output buffer containing content to be read
             *
             * @type {*[]}
             * @protected
             */
            _buffer: [],

            /**
             * Length of the buffer (compared with read size)
             *
             * @type {Number}
             * @protected
             */
            _bufferLength: 0,

            /**
             * Underlying stream default read size
             *
             * @type {Number}
             * @protected
             */
            _readSize: _BUFREADSTREAM_READ_SIZE,

            /**
             * Process underlying stream buffer (this should grow the output
             * buffer)
             *
             * @param {Array} buffer
             * @abstract
             * @protected
             */
            _addToBuffer: function (buffer) {
                gpf.interfaces.ignoreParameter(buffer);
                gpf.Error.Abstract();
            },

            /**
             * Underlying stream reached its end (this may grow the output
             * buffer)
             *
             * @protected
             */
            _endOfInputStream: function () {
            },

            /**
             * Read buffer.
             * This default implementation checks the buffer type to switch
             * between string and byte array.
             *
             * @param {Number} size
             * @returns {String|Array}
             * @protected
             */
            _readFromBuffer: function (size) {
                gpf.ASSERT(0 !== this._buffer.length, "Buffer is not empty");
                if ("string" === this._buffer[0]) {
                    return this._readFromStringBuffer(size);
                } else {
                    return this._readFromByteBuffer(size);
                }
            },

            /**
             * Read string buffer.
             *
             * @param {Number} size
             * @returns {String}
             * @protected
             */
            _readFromStringBuffer: function (size) {
                var
                    result = gpf.stringExtractFromStringArray(this._buffer,
                        size);
                this._bufferLength -= result.length;
                return result;
            },

            /**
             * Read byte buffer.
             *
             * @param {Number} size
             * @returns {Array}
             * @protected
             */
            _readFromByteBuffer: function (size) {
                var
                    buffer = this._buffer,
                    len = buffer.length;
                if (size > len) {
                    size = len;
                }
                this._bufferLength -= size;
                return buffer.splice(0, size);
            }

        },

        //endregion

        //region Implementation

        public: {

            /**
             * @param {gpf.interfaces.IReadableStream} input
             * @constructor
             */
            constructor: function (input) {
                this._iStream = gpfI.query(input, gpfI.IReadableStream, true);
                this._buffer = [];
            },

            //region gpf.interfaces.IReadableStream

            /**
             * @implements gpf.interfaces.IReadableStream:read
             */
            read: function (size, eventsHandler) {
                var
                    iState = this._iState,
                    length = this._bufferLength;
                if (_BUFREADSTREAM_ISTATE_INPROGRESS === iState) {
                    // A read call is already in progress
                    throw gpfI.IReadableStream.EXCEPTION_READ_IN_PROGRESS;

                } else if (size < length
                    || length && _BUFREADSTREAM_ISTATE_EOS === iState) {
                    // Enough chars in the output buffer to do the read
                    // OR there won't be any more chars. Can output something.
                    if (0 === size) {
                        size = length;
                    }
                    gpf.events.fire.apply(this, [
                        gpfI.IReadableStream.EVENT_DATA,
                        {
                            buffer: this._readFromBuffer(size)
                        },
                        eventsHandler
                    ]);

                } else if (_BUFREADSTREAM_ISTATE_EOS === iState) {
                    // No more input and output buffer is empty
                    gpf.events.fire.apply(this, [
                        gpfI.IReadableStream.EVENT_END_OF_STREAM,
                        eventsHandler
                    ]);

                } else {
                    // Read input
                    if (_BUFREADSTREAM_ISTATE_INIT === this._iState) {
                        // Very first call, create callback for input reads
                        this._cbRead = new gpf.Callback(this._onRead, this);
                    }
                    this._iState = _BUFREADSTREAM_ISTATE_INPROGRESS;
                    // Backup parameters
                    this._size = size;
                    this._eventsHandler = eventsHandler;
                    this._iStream.read(this._readSize, this._cbRead);
                }
            }

            //endregion
        },

        private: {

            /**
             * Input stream
             * @type {gpf.interfaces.IReadableStream}
             */
            _iStream: null,

            /**
             * Input stream read callback (pointing to this:_onRead)
             * @type {gpf.Callback}
             */
            _cbRead: null,

            /**
             * Input state
             * @type {Number} see _BUFREADSTREAM_ISTATE_xxx
             */
            _iState: _BUFREADSTREAM_ISTATE_INIT,

            /**
             * Pending read call size
             * @type {Number}
             */
            _size: 0,

            /**
             * Pending read call event handlers
             * @type {gpf.events.Handler}
             */
            _eventsHandler: null,

            /**
             * Handles input stream read event
             *
             * @param {gpf.events.Event} event
             * @private
             */
            _onRead: function (event) {
                var
                    type = event.type();
                if (type === gpfI.IReadableStream.EVENT_END_OF_STREAM) {
                    this._iState = _BUFREADSTREAM_ISTATE_EOS;
                    this._endOfInputStream();
                    // Redirect to read with backed parameters
                    return this.read(this._size, this._eventsHandler);

                } else if (type === gpfI.IReadableStream.EVENT_ERROR) {
                    // Forward the event
                    gpf.events.fire.apply(this, [
                        event,
                        this._eventsHandler
                    ]);

                } else {
                    this._iState = _BUFREADSTREAM_ISTATE_WAITING;
                    this._addToBuffer(event.get("buffer"));
                    if (0 < this._bufferLength) {
                        // Redirect to read with backed parameters
                        return this.read(this._size, this._eventsHandler);
                    } else {
                        // Try to read source again
                        this._iStream.read(_BUFREADSTREAM_READ_SIZE,
                            this._cbRead);
                    }
                }
            }

        }

        //endregion
    });

    /**
     *
     * @param {gpf.interfaces.ITextStream} stream
     * @param {gpf.events.Handler} eventsHandler
     * @param {Function} concatMethod
     *
     * @forwardThis
     *
     * @event data finished reading the stream, the buffer is provided
     * @eventParam {Array|String} buffer
     */
    gpf.stream.readAll = function (stream, concatMethod, eventsHandler) {
        stream = gpf.interfaces.query(stream, gpfI.IReadableStream,  true);
        (new StreamReader(this, eventsHandler, concatMethod)).read(stream);
    };

    function StreamReader(scope, eventsHandler, concatMethod) {
        this._scope = gpf.Callback.resolveScope(scope);
        this._eventsHandler = eventsHandler;
        this._concatMethod = concatMethod;
    }
    gpf.extend(StreamReader.prototype, {

        _scope: null,
        _eventsHandler: null,
        _concatMethod: null,
        _buffer: undefined,

        read: function (stream) {
            stream.read(0, gpf.Callback.bind(this, "callback"));
        },

        callback: function (event) {
            var
                type = event.type(),
                stream = event.scope();
            if (type === gpfI.IReadableStream.EVENT_END_OF_STREAM) {
                gpf.events.fire.apply(this._scope, [
                    gpfI.IReadableStream.EVENT_DATA,
                    {
                        buffer: this._concatMethod(this._buffer)
                    },
                    this._eventsHandler
                ]);

            } else if (type === gpfI.IReadableStream.EVENT_ERROR) {
                // Forward the event
                gpf.events.fire.apply(this._scope, [
                    event,
                    this._eventsHandler
                ]);

            } else {
                this._buffer = this._concatMethod(this._buffer,
                    event.get("buffer"));
                this.read(stream);
            }
        }

    });

    //endregion

/*#ifndef(UMD)*/
}()); /* End of privacy scope */
/*#endif*/<|endoftext|>


<commit_before>var expect = require('chai').expect;

function toEnglish(word){
  if ( word === "zero" ){
      return 0;
  }

  if ( word === "one" ){
      return 1;
  }
  if ( word === "two" ){
      return 2;
  }
  if ( word === "three" ){
      return 3;
  }
  if ( word === "four" ){
      return 4;
  }
  if ( word === "five"){
      return 5;
  }
  if ( word === "six"){
      return 6;
  }
  if ( word === "seven"){
    return 7;
  }
  if ( word === "eight"){
    return 8;
  }
  if ( word === "nine" ){
    return 9;
  }
  if ( word === "ten" ){
    return 10;
  }
}

expect(toEnglish("zero")).to.equal(0);
expect(toEnglish("one")).to.equal(1);
expect(toEnglish("two")).to.equal(2);
expect(toEnglish("three")).to.equal(3);
expect(toEnglish("four")).to.equal(4);
expect(toEnglish("five")).to.equal(5);
expect(toEnglish("six")).to.equal(6);
expect(toEnglish("seven")).to.equal(7);
expect(toEnglish("eight")).to.equal(8);
expect(toEnglish("nine")).to.equal(9);
expect(toEnglish("ten")).to.equal(10);

/*function plus(A, B){
  return toEnglish(A) + toEnglish(B);
} NIGHTMARE
*/
function plus(a,b){
    var a = toEnglish(a);
    var b = toEnglish(b);

if (a === "zero" && b === "zero"){
  var a = 0;
  var b = 0;
}
if (a === "zero" && b === "one"){
  var a = 0;
  var b = 1;
}
if (a === "zero" && b === "two"){
  var a = 0;
  var b = 2;
}
if (a === "zero" && b === "three"){
  var a = 0;
  var b = 3;
}
if (a === "zero" && b === "four"){
  var a = 0;
  var b = 4;
}
if (a === "zero" && b === "five"){
  var a = 0;
  var b = 5;
}
if (a === "zero" && b === "six"){
  var a = 0;
  var b = 6;
}
if (a === "zero" && b === "seven"){
  var a = 0;
  var b = 7;
}
if (a === "zero" && b === "eight"){
  var a = 0;
  var b = 8;
}
if (a === "zero" && b === "nine"){
  var a = 0;
  var b = 9;
}
  return a + b;
}

/*function divide(A, B){
  return toEnglish(A) / toEnglish(B);
}*/

expect(plus).to.exist;
expect(plus("zero", "zero")).to.equal(0);
expect(plus("zero", "one")).to.equal(1);
expect(plus("zero", "two")).to.equal(2);
expect(plus("zero", "three")).to.equal(3);
expect(plus("zero", "four")).to.equal(4);
expect(plus("zero", "five")).to.equal(5);
expect(plus("zero", "six")).to.equal(6);
expect(plus("zero", "seven")).to.equal(7);
expect(plus("zero", "eight")).to.equal(8);
expect(plus("zero", "nine")).to.equal(9);

/* console.log(plus("zero", "zero"));
 console.log(plus("zero", "one"));
 console.log(plus("zero", "two"));

expect(plus("one", "one")).to.equal(2);
expect(plus("one", "two")).to.equal(3);
expect(plus("one", "three")).to.equal(4);
expect(plus("one", "four")).to.equal(5);
expect(plus("one", "five")).to.equal(6);
expect(plus("one", "six")).to.equal(7);
expect(plus("one", "seven")).to.equal(8);
expect(plus("one", "eight")).to.equal(9);
expect(plus("one", "nine")).to.equal(10);

expect(plus("two", "zero")).to.equal(2);
expect(plus("two", "one")).to.equal(3);
expect(plus("two", "two")).to.equal(4);
expect(plus("two", "three")).to.equal(5);
expect(plus("two", "four")).to.equal(6);
expect(plus("two", "five")).to.equal(7);
expect(plus("two", "six")).to.equal(8);
expect(plus("two", "seven")).to.equal(9);
expect(plus("two", "eight")).to.equal(10);
expect(plus("two", "nine")).to.equal(11);

expect(plus("three", "zero")).to.equal(3);
expect(plus("three", "one")).to.equal(4);
expect(plus("three", "two")).to.equal(5);
expect(plus("three", "three")).to.equal(6);
expect(plus("three", "four")).to.equal(7);
expect(plus("three", "five")).to.equal(8);
expect(plus("three", "six")).to.equal(9);
expect(plus("three", "seven")).to.equal(10);
expect(plus("three", "eight")).to.equal(11);
expect(plus("three", "nine")).to.equal(12);

expect(plus("four", "zero")).to.equal(4);
expect(plus("four", "one")).to.equal(5);
expect(plus("four", "two")).to.equal(6);
expect(plus("four", "three")).to.equal(7);
expect(plus("four", "four")).to.equal(8);
expect(plus("four", "five")).to.equal(9);
expect(plus("four", "six")).to.equal(10);
expect(plus("four", "seven")).to.equal(11);
expect(plus("four", "eight")).to.equal(12);
expect(plus("four", "nine")).to.equal(13);

expect(plus("five", "zero")).to.equal(5);
expect(plus("five", "one")).to.equal(6);
expect(plus("five", "two")).to.equal(7);
expect(plus("five", "three")).to.equal(8);
expect(plus("five", "four")).to.equal(9);
expect(plus("five", "five")).to.equal(10);
expect(plus("five", "six")).to.equal(11);
expect(plus("five", "seven")).to.equal(12);
expect(plus("five", "eight")).to.equal(13);
expect(plus("five", "nine")).to.equal(14);

expect(plus("six", "zero")).to.equal(6);
expect(plus("six", "one")).to.equal(7);
expect(plus("six", "two")).to.equal(8);
expect(plus("six", "three")).to.equal(9);
expect(plus("six", "four")).to.equal(10);
expect(plus("six", "five")).to.equal(11);
expect(plus("six", "six")).to.equal(12);
expect(plus("six", "seven")).to.equal(13);
expect(plus("six", "eight")).to.equal(14);
expect(plus("six", "nine")).to.equal(15);

expect(plus("seven", "zero")).to.equal(7);
expect(plus("seven", "one")).to.equal(8);
expect(plus("seven", "two")).to.equal(9);
expect(plus("seven", "three")).to.equal(10);
expect(plus("seven", "four")).to.equal(11);
expect(plus("seven", "five")).to.equal(12);
expect(plus("seven", "six")).to.equal(13);
expect(plus("seven", "seven")).to.equal(14);
expect(plus("seven", "eight")).to.equal(15);
expect(plus("seven", "nine")).to.equal(16);

/*expect(divide).to.exist;
expect(divide("zero", "NaN")).to.equal(0);
expect(divide("zero", "one")).to.equal(0);*/
<commit_msg>@pcreglow & &mstaehling<commit_after>var expect = require('chai').expect;

function toEnglish(word){
  if ( word === "zero" ){
      return 0;
  }

  if ( word === "one" ){
      return 1;
  }
  if ( word === "two" ){
      return 2;
  }
  if ( word === "three" ){
      return 3;
  }
  if ( word === "four" ){
      return 4;
  }
  if ( word === "five"){
      return 5;
  }
  if ( word === "six"){
      return 6;
  }
  if ( word === "seven"){
    return 7;
  }
  if ( word === "eight"){
    return 8;
  }
  if ( word === "nine" ){
    return 9;
  }
  if ( word === "ten" ){
    return 10;
  }
}

expect(toEnglish("zero")).to.equal(0);
expect(toEnglish("one")).to.equal(1);
expect(toEnglish("two")).to.equal(2);
expect(toEnglish("three")).to.equal(3);
expect(toEnglish("four")).to.equal(4);
expect(toEnglish("five")).to.equal(5);
expect(toEnglish("six")).to.equal(6);
expect(toEnglish("seven")).to.equal(7);
expect(toEnglish("eight")).to.equal(8);
expect(toEnglish("nine")).to.equal(9);
expect(toEnglish("ten")).to.equal(10);

function plus(a,b){
    var a = toEnglish(a);
    var b = toEnglish(b);

  if (a === "zero" && b === "zero"){
    var a = 0;
    var b = 0;
  }
  if (a === "zero" && b === "one"){
    var a = 0;
    var b = 1;
  }
  if (a === "zero" && b === "two"){
    var a = 0;
    var b = 2;
  }
  if (a === "zero" && b === "three"){
    var a = 0;
    var b = 3;
  }
  if (a === "zero" && b === "four"){
    var a = 0;
    var b = 4;
  }
  if (a === "zero" && b === "five"){
    var a = 0;
    var b = 5;
  }
  if (a === "zero" && b === "six"){
    var a = 0;
    var b = 6;
  }
  if (a === "zero" && b === "seven"){
    var a = 0;
    var b = 7;
  }
  if (a === "zero" && b === "eight"){
    var a = 0;
    var b = 8;
  }
  if (a === "zero" && b === "nine"){
    var a = 0;
    var b = 9;
  }
  if (a === "one" && b === "zero"){
    var a = 1;
    var b = 0;
  }
  if (a === "one" && b === "one"){
    var a = 1;
    var b = 1;
  }
  if (a === "one" && b === "two"){
    var a = 1;
    var b = 2;
  }
  if (a === "one" && b === "three"){
    var a = 1;
    var b = 3;
  }
  if (a === "one" && b === "four"){
    var a = 1;
    var b = 4;
  }
  if (a === "one" && b === "five"){
    var a = 1;
    var b = 5;
  }
  if (a === "one" && b === "six"){
    var a = 1;
    var b = 6;
  }
  if (a === "one" && b === "seven"){
    var a = 1;
    var b = 7;
  }
  if (a === "one" && b === "eight"){
    var a = 1;
    var b = 8;
  }
  if (a === "one" && b === "nine"){
    var a = 1;
    var b = 9;
  }

  return a + b;
}

/*function plus(A, B){
  return toEnglish(A) + toEnglish(B);
} NIGHTMARE
*/

expect(plus).to.exist;
expect(plus("zero", "zero")).to.equal(0);
expect(plus("zero", "one")).to.equal(1);
expect(plus("zero", "two")).to.equal(2);
expect(plus("zero", "three")).to.equal(3);
expect(plus("zero", "four")).to.equal(4);
expect(plus("zero", "five")).to.equal(5);
expect(plus("zero", "six")).to.equal(6);
expect(plus("zero", "seven")).to.equal(7);
expect(plus("zero", "eight")).to.equal(8);
expect(plus("zero", "nine")).to.equal(9);

expect(plus("one", "zero")).to.equal(1);
expect(plus("one", "one")).to.equal(2);
expect(plus("one", "two")).to.equal(3);
expect(plus("one", "three")).to.equal(4);
expect(plus("one", "four")).to.equal(5);
expect(plus("one", "five")).to.equal(6);
expect(plus("one", "six")).to.equal(7);
expect(plus("one", "seven")).to.equal(8);
expect(plus("one", "eight")).to.equal(9);
expect(plus("one", "nine")).to.equal(10);

/*expect(plus("two", "zero")).to.equal(2);
expect(plus("two", "one")).to.equal(3);
expect(plus("two", "two")).to.equal(4);
expect(plus("two", "three")).to.equal(5);
expect(plus("two", "four")).to.equal(6);
expect(plus("two", "five")).to.equal(7);
expect(plus("two", "six")).to.equal(8);
expect(plus("two", "seven")).to.equal(9);
expect(plus("two", "eight")).to.equal(10);
expect(plus("two", "nine")).to.equal(11);

expect(plus("three", "zero")).to.equal(3);
expect(plus("three", "one")).to.equal(4);
expect(plus("three", "two")).to.equal(5);
expect(plus("three", "three")).to.equal(6);
expect(plus("three", "four")).to.equal(7);
expect(plus("three", "five")).to.equal(8);
expect(plus("three", "six")).to.equal(9);
expect(plus("three", "seven")).to.equal(10);
expect(plus("three", "eight")).to.equal(11);
expect(plus("three", "nine")).to.equal(12);

expect(plus("four", "zero")).to.equal(4);
expect(plus("four", "one")).to.equal(5);
expect(plus("four", "two")).to.equal(6);
expect(plus("four", "three")).to.equal(7);
expect(plus("four", "four")).to.equal(8);
expect(plus("four", "five")).to.equal(9);
expect(plus("four", "six")).to.equal(10);
expect(plus("four", "seven")).to.equal(11);
expect(plus("four", "eight")).to.equal(12);
expect(plus("four", "nine")).to.equal(13);

expect(plus("five", "zero")).to.equal(5);
expect(plus("five", "one")).to.equal(6);
expect(plus("five", "two")).to.equal(7);
expect(plus("five", "three")).to.equal(8);
expect(plus("five", "four")).to.equal(9);
expect(plus("five", "five")).to.equal(10);
expect(plus("five", "six")).to.equal(11);
expect(plus("five", "seven")).to.equal(12);
expect(plus("five", "eight")).to.equal(13);
expect(plus("five", "nine")).to.equal(14);

expect(plus("six", "zero")).to.equal(6);
expect(plus("six", "one")).to.equal(7);
expect(plus("six", "two")).to.equal(8);
expect(plus("six", "three")).to.equal(9);
expect(plus("six", "four")).to.equal(10);
expect(plus("six", "five")).to.equal(11);
expect(plus("six", "six")).to.equal(12);
expect(plus("six", "seven")).to.equal(13);
expect(plus("six", "eight")).to.equal(14);
expect(plus("six", "nine")).to.equal(15);

expect(plus("seven", "zero")).to.equal(7);
expect(plus("seven", "one")).to.equal(8);
expect(plus("seven", "two")).to.equal(9);
expect(plus("seven", "three")).to.equal(10);
expect(plus("seven", "four")).to.equal(11);
expect(plus("seven", "five")).to.equal(12);
expect(plus("seven", "six")).to.equal(13);
expect(plus("seven", "seven")).to.equal(14);
expect(plus("seven", "eight")).to.equal(15);
expect(plus("seven", "nine")).to.equal(16);

/* console.log(plus("zero", "zero"));
 console.log(plus("zero", "one"));
 console.log(plus("zero", "two"));

/*function div(a, b){
    if (toNumber(a) === 0 && toNumber(b) === 0);
    return NaN;
  } else if (toNumber(b) === 0);{
    return infinity;
} else {
  return toNumber(a) / toNumber(b);
}*/

/*expect(divide).to.exist;
expect(divide("zero", "NaN")).to.equal(0);
expect(divide("zero", "one")).to.equal(0);*/
<|endoftext|>


<commit_before>'use strict';

var cache = require('cache-file');
var filesize = require('filesize');
var fs = require('fs');
var gifsicle = require('gifsicle').path;
var jpegtran = require('jpegtran-bin').path;
var mkdir = require('mkdirp');
var mout = require('mout');
var optipng = require('optipng-bin').path;
var path = require('path');
var spawn = require('child_process').spawn;

/**
 * Initialize `Imagemin` with options
 *
 * @param {String} src
 * @param {String} dest
 * @param {Object} opts
 * @api private
 */

function Imagemin(src, dest, opts) {
    opts = opts || {};
    this.opts = opts;
    this.src = src;
    this.dest = dest;
    this.optimizers = {
        '.gif': this._optimizeGif,
        '.jpg': this._optimizeJpeg,
        '.jpeg': this._optimizeJpeg,
        '.png': this._optimizePng
    };
    this.optimizerTypes = Object.keys(this.optimizers);
    this.optimizer = this._getOptimizer(this.src);
}

/**
 * Optimize GIF, JPEG, and PNG images
 *
 * @param {Function} cb
 * @api public
 */

Imagemin.prototype.optimize = function (cb) {
    if (!cb || !mout.lang.isFunction(cb)) {
        cb = function () {};
    }

    if (!fs.existsSync(path.dirname(this.dest))) {
        mkdir.sync(path.dirname(this.dest));
    }

    if (this.opts.cache && cache.check(this.src, { name: 'imagemin' })) {
        cache.get(this.src, this.dest, { name: 'imagemin' });
        return cb(this._process());
    }

    var self = this;
    var optimizer = this.optimizer(this.src, this.dest, cb);

    optimizer.once('close', function () {
        cb(self._process());
    });
};

/**
 * Get the optimizer for a desired file
 *
 * @param {String} src
 * @api private
 */

Imagemin.prototype._getOptimizer = function (src) {
    src = src.toLowerCase();

    var ext = mout.array.find(this.optimizerTypes, function (ext) {
        return mout.string.endsWith(src, ext);
    });

    return ext ? this.optimizers[ext] : null;
};

/**
 * Optimize a GIF image
 *
 * @param {String} src
 * @param {String} dest
 * @api private
 */

Imagemin.prototype._optimizeGif = function (src, dest) {
    var args = ['-w'];

    if (this.opts.interlaced) {
        args.push('--interlace');
    }

    return spawn(gifsicle, args.concat(['-o', dest, src]));
};

/**
 * Optimize a JPEG image
 *
 * @param {String} src
 * @param {String} dest
 * @api private
 */

Imagemin.prototype._optimizeJpeg = function (src, dest) {
    var args = ['-copy', 'none', '-optimize'];

    if (this.opts.progressive) {
        args.push('-progressive');
    }

    return spawn(jpegtran, args.concat(['-outfile', dest, src]));
};

/**
 * Optimize a PNG image
 *
 * @param {String} src
 * @param {String} dest
 * @api private
 */

Imagemin.prototype._optimizePng = function (src, dest) {
    var args = ['-strip', 'all'];

    if (typeof this.opts.optimizationLevel === 'number') {
        args.push('-o', this.opts.optimizationLevel);
    }

    return spawn(optipng, args.concat(['-out', dest, src]));
};

/**
 * Process optimized images
 *
 * @api private
 */

Imagemin.prototype._process = function () {
    var size = fs.statSync(this.src).size;
    var saved = size - fs.statSync(this.dest).size;

    if (this.opts.cache && !cache.check(this.src, { name: 'imagemin' })) {
        cache.store(this.dest, this.src, { name: 'imagemin' });
    }

    var data = {
        size: filesize(saved),
        sizeRaw: saved
    };

    return data;
};

/**
 * Module exports
 */

module.exports = function (src, dest, opts, cb) {
    if (!cb && mout.lang.isFunction(opts)) {
        cb = opts;
        opts = {};
    }

    var imagemin = new Imagemin(src, dest, opts);
    return imagemin.optimize(cb);
};
<commit_msg>Optimization<commit_after>'use strict';

var cache = require('cache-file');
var endsWith = require('mout/string/endsWith');
var filesize = require('filesize');
var find = require('mout/array/find');
var fs = require('fs');
var isFunction = require('mout/lang/isFunction');
var mkdir = require('mkdirp');
var path = require('path');
var spawn = require('child_process').spawn;

/**
 * Initialize `Imagemin` with options
 *
 * @param {String} src
 * @param {String} dest
 * @param {Object} opts
 * @api private
 */

function Imagemin(src, dest, opts) {
    opts = opts || {};
    this.opts = opts;
    this.src = src;
    this.dest = dest;
    this.optimizers = {
        '.gif': this._optimizeGif,
        '.jpg': this._optimizeJpeg,
        '.jpeg': this._optimizeJpeg,
        '.png': this._optimizePng
    };
    this.optimizerTypes = Object.keys(this.optimizers);
    this.optimizer = this._getOptimizer(this.src);
}

/**
 * Optimize GIF, JPEG, and PNG images
 *
 * @param {Function} cb
 * @api public
 */

Imagemin.prototype.optimize = function (cb) {
    if (!cb || !isFunction(cb)) {
        cb = function () {};
    }

    if (!fs.existsSync(path.dirname(this.dest))) {
        mkdir.sync(path.dirname(this.dest));
    }

    if (this.opts.cache && cache.check(this.src, { name: 'imagemin' })) {
        cache.get(this.src, this.dest, { name: 'imagemin' });
        return cb(this._process());
    }

    var self = this;
    var optimizer = this.optimizer(this.src, this.dest, cb);

    optimizer.once('close', function () {
        cb(self._process());
    });
};

/**
 * Get the optimizer for a desired file
 *
 * @param {String} src
 * @api private
 */

Imagemin.prototype._getOptimizer = function (src) {
    src = src.toLowerCase();

    var ext = find(this.optimizerTypes, function (ext) {
        return endsWith(src, ext);
    });

    return ext ? this.optimizers[ext] : null;
};

/**
 * Optimize a GIF image
 *
 * @param {String} src
 * @param {String} dest
 * @api private
 */

Imagemin.prototype._optimizeGif = function (src, dest) {
    var args = ['-w'];
    var gifsicle = require('gifsicle').path;

    if (this.opts.interlaced) {
        args.push('--interlace');
    }

    return spawn(gifsicle, args.concat(['-o', dest, src]));
};

/**
 * Optimize a JPEG image
 *
 * @param {String} src
 * @param {String} dest
 * @api private
 */

Imagemin.prototype._optimizeJpeg = function (src, dest) {
    var args = ['-copy', 'none', '-optimize'];
    var jpegtran = require('jpegtran-bin').path;

    if (this.opts.progressive) {
        args.push('-progressive');
    }

    return spawn(jpegtran, args.concat(['-outfile', dest, src]));
};

/**
 * Optimize a PNG image
 *
 * @param {String} src
 * @param {String} dest
 * @api private
 */

Imagemin.prototype._optimizePng = function (src, dest) {
    var args = ['-strip', 'all'];
    var optipng = require('optipng-bin').path;

    if (typeof this.opts.optimizationLevel === 'number') {
        args.push('-o', this.opts.optimizationLevel);
    }

    return spawn(optipng, args.concat(['-out', dest, src]));
};

/**
 * Process optimized images
 *
 * @api private
 */

Imagemin.prototype._process = function () {
    var size = fs.statSync(this.src).size;
    var saved = size - fs.statSync(this.dest).size;

    if (this.opts.cache && !cache.check(this.src, { name: 'imagemin' })) {
        cache.store(this.dest, this.src, { name: 'imagemin' });
    }

    var data = {
        size: filesize(saved),
        sizeRaw: saved
    };

    return data;
};

/**
 * Module exports
 */

module.exports = function (src, dest, opts, cb) {
    if (!cb && isFunction(opts)) {
        cb = opts;
        opts = {};
    }

    var imagemin = new Imagemin(src, dest, opts);
    return imagemin.optimize(cb);
};
<|endoftext|>


<commit_before>'use strict';

var cache = require('cache-file');
var endsWith = require('mout/string/endsWith');
var filesize = require('filesize');
var find = require('mout/array/find');
var fs = require('fs');
var isFunction = require('mout/lang/isFunction');
var mkdir = require('mkdirp');
var path = require('path');
var spawn = require('child_process').spawn;

/**
 * Initialize `Imagemin` with options
 *
 * @param {String} src
 * @param {String} dest
 * @param {Object} opts
 * @api private
 */

function Imagemin(src, dest, opts) {
    opts = opts || {};
    this.opts = opts;
    this.src = src;
    this.dest = dest;
    this.optimizers = {
        '.gif': this._optimizeGif,
        '.jpg': this._optimizeJpeg,
        '.jpeg': this._optimizeJpeg,
        '.png': this._optimizePng
    };
    this.optimizerTypes = Object.keys(this.optimizers);
    this.optimizer = this._getOptimizer(this.src);
}

/**
 * Optimize GIF, JPEG, and PNG images
 *
 * @param {Function} cb
 * @api public
 */

Imagemin.prototype.optimize = function (cb) {
    if (!cb || !isFunction(cb)) {
        cb = function () {};
    }

    if (!fs.existsSync(path.dirname(this.dest))) {
        mkdir.sync(path.dirname(this.dest));
    }

    if (this.opts.cache && cache.check(this.src, { name: 'imagemin' })) {
        cache.get(this.src, this.dest, { name: 'imagemin' });
        return cb(this._process());
    }

    if (!isFunction(this.optimizer)) {
        return cb();
    }

    var self = this;
    var optimizer = this.optimizer(this.src, this.dest, cb);

    optimizer.once('close', function () {
        cb(self._process());
    });
};

/**
 * Get the optimizer for a desired file
 *
 * @param {String} src
 * @api private
 */

Imagemin.prototype._getOptimizer = function (src) {
    src = src.toLowerCase();

    var ext = find(this.optimizerTypes, function (ext) {
        return endsWith(src, ext);
    });

    return ext ? this.optimizers[ext] : null;
};

/**
 * Optimize a GIF image
 *
 * @param {String} src
 * @param {String} dest
 * @api private
 */

Imagemin.prototype._optimizeGif = function (src, dest) {
    var args = ['-w'];
    var gifsicle = require('gifsicle').path;

    if (this.opts.interlaced) {
        args.push('--interlace');
    }

    return spawn(gifsicle, args.concat(['-o', dest, src]));
};

/**
 * Optimize a JPEG image
 *
 * @param {String} src
 * @param {String} dest
 * @api private
 */

Imagemin.prototype._optimizeJpeg = function (src, dest) {
    var args = ['-copy', 'none', '-optimize'];
    var jpegtran = require('jpegtran-bin').path;

    if (this.opts.progressive) {
        args.push('-progressive');
    }

    return spawn(jpegtran, args.concat(['-outfile', dest, src]));
};

/**
 * Optimize a PNG image
 *
 * @param {String} src
 * @param {String} dest
 * @api private
 */

Imagemin.prototype._optimizePng = function (src, dest) {
    var args = ['-strip', 'all'];
    var optipng = require('optipng-bin').path;

    if (typeof this.opts.optimizationLevel === 'number') {
        args.push('-o', this.opts.optimizationLevel);
    }

    return spawn(optipng, args.concat(['-out', dest, src]));
};

/**
 * Process optimized images
 *
 * @api private
 */

Imagemin.prototype._process = function () {
    var size = fs.statSync(this.src).size;
    var saved = size - fs.statSync(this.dest).size;

    if (this.opts.cache && !cache.check(this.src, { name: 'imagemin' })) {
        cache.store(this.dest, this.src, { name: 'imagemin' });
    }

    var data = {
        size: filesize(saved),
        sizeRaw: saved
    };

    return data;
};

/**
 * Module exports
 */

module.exports = function (src, dest, opts, cb) {
    if (!cb && isFunction(opts)) {
        cb = opts;
        opts = {};
    }

    var imagemin = new Imagemin(src, dest, opts);
    return imagemin.optimize(cb);
};
<commit_msg>Include more useful info in the `data` object<commit_after>'use strict';

var cache = require('cache-file');
var endsWith = require('mout/string/endsWith');
var filesize = require('filesize');
var find = require('mout/array/find');
var fs = require('fs');
var isFunction = require('mout/lang/isFunction');
var mkdir = require('mkdirp');
var path = require('path');
var spawn = require('child_process').spawn;

/**
 * Initialize `Imagemin` with options
 *
 * @param {String} src
 * @param {String} dest
 * @param {Object} opts
 * @api private
 */

function Imagemin(src, dest, opts) {
    opts = opts || {};
    this.opts = opts;
    this.src = src;
    this.dest = dest;
    this.optimizers = {
        '.gif': this._optimizeGif,
        '.jpg': this._optimizeJpeg,
        '.jpeg': this._optimizeJpeg,
        '.png': this._optimizePng
    };
    this.optimizerTypes = Object.keys(this.optimizers);
    this.optimizer = this._getOptimizer(this.src);
}

/**
 * Optimize GIF, JPEG, and PNG images
 *
 * @param {Function} cb
 * @api public
 */

Imagemin.prototype.optimize = function (cb) {
    if (!cb || !isFunction(cb)) {
        cb = function () {};
    }

    if (!fs.existsSync(path.dirname(this.dest))) {
        mkdir.sync(path.dirname(this.dest));
    }

    if (this.opts.cache && cache.check(this.src, { name: 'imagemin' })) {
        cache.get(this.src, this.dest, { name: 'imagemin' });
        return cb(this._process());
    }

    if (!isFunction(this.optimizer)) {
        return cb();
    }

    var self = this;
    var optimizer = this.optimizer(this.src, this.dest, cb);

    optimizer.once('close', function () {
        cb(self._process());
    });
};

/**
 * Get the optimizer for a desired file
 *
 * @param {String} src
 * @api private
 */

Imagemin.prototype._getOptimizer = function (src) {
    src = src.toLowerCase();

    var ext = find(this.optimizerTypes, function (ext) {
        return endsWith(src, ext);
    });

    return ext ? this.optimizers[ext] : null;
};

/**
 * Optimize a GIF image
 *
 * @param {String} src
 * @param {String} dest
 * @api private
 */

Imagemin.prototype._optimizeGif = function (src, dest) {
    var args = ['-w'];
    var gifsicle = require('gifsicle').path;

    if (this.opts.interlaced) {
        args.push('--interlace');
    }

    return spawn(gifsicle, args.concat(['-o', dest, src]));
};

/**
 * Optimize a JPEG image
 *
 * @param {String} src
 * @param {String} dest
 * @api private
 */

Imagemin.prototype._optimizeJpeg = function (src, dest) {
    var args = ['-copy', 'none', '-optimize'];
    var jpegtran = require('jpegtran-bin').path;

    if (this.opts.progressive) {
        args.push('-progressive');
    }

    return spawn(jpegtran, args.concat(['-outfile', dest, src]));
};

/**
 * Optimize a PNG image
 *
 * @param {String} src
 * @param {String} dest
 * @api private
 */

Imagemin.prototype._optimizePng = function (src, dest) {
    var args = ['-strip', 'all'];
    var optipng = require('optipng-bin').path;

    if (typeof this.opts.optimizationLevel === 'number') {
        args.push('-o', this.opts.optimizationLevel);
    }

    return spawn(optipng, args.concat(['-out', dest, src]));
};

/**
 * Process optimized images
 *
 * @api private
 */

Imagemin.prototype._process = function () {
    var size = fs.statSync(this.src).size;
    var saved = size - fs.statSync(this.dest).size;

    if (this.opts.cache && !cache.check(this.src, { name: 'imagemin' })) {
        cache.store(this.dest, this.src, { name: 'imagemin' });
    }

    var data = {
        origSize: filesize(size),
        origSizeRaw: size,
        diffSize: filesize(saved),
        diffSizeRaw: saved
    };

    return data;
};

/**
 * Module exports
 */

module.exports = function (src, dest, opts, cb) {
    if (!cb && isFunction(opts)) {
        cb = opts;
        opts = {};
    }

    var imagemin = new Imagemin(src, dest, opts);
    return imagemin.optimize(cb);
};
<|endoftext|>


<commit_before>(function(exports) {
    function rgb_avg(a, b) {
        return {
            r: (a.r + b.r) / 2,
            g: (a.g + b.g) / 2,
            b: (a.b + b.b) / 2
        };
    }

    function rgb_equal(a, b, tol) {
        tol = tol || 2;

        if (Math.abs(a.r - b.r) > tol) {
            return false;
        }
        if (Math.abs(a.g - b.g) > tol) {
            return false;
        }
        if (Math.abs(a.b - b.b) > tol) {
            return false;
        }

        return true;
    }

    function arrayToRgb(arr) {
        if (!arr) {
            //return;
        }

        var ret = {
            r: arr[0],
            g: arr[1],
            b: arr[2]
        };

        if (arr.length == 4) {
            ret.a = arr[3];
        }

        return ret;
    };

    function getPixel(arr, x, y) {
        return arrayToRgb(arr[y][x]);
    }

    function calculateGradient(arr) {
        var ret = [];
        var height = arr.length;
        var width = arr[0].length;
        var tl = getPixel(arr, 0, 0);
        var tr = getPixel(arr, width - 1, 0);
        var bl = getPixel(arr, 0, height - 1);
        var br = getPixel(arr, width - 1, height - 1);

        var grad_len;
        var grad;
        var mid;
        var grad_start;

        // vertical gradient -- row[0][0] == row[0][height]
        if (rgb_equal(tl, tr)) {
            grad_start = "top";
            grad_len = height;
            if (grad_len % 2 === 0) {
                mid = getPixel(arr, 0, grad_len / 2);
            }
            else {
                mid = rgb_avg(getPixel(arr, 0, grad_len / 2), getPixel(image, 0, (grad_len / 2) - 1));
            }
        }
        // horizontal gradient
        else if (rgb_equal(tl, bl)) {
            grad_start = "left";
            grad_len = width;
            if (grad_len % 2 === 0) {
                mid = getPixel(arr, grad_len / 2, 0);
            }
            else {
                mid = rgb_avg(getPixel(arr, Math.floor(grad_len / 2), 0), getPixel(arr, Math.ceil(grad_len / 2), 0));
            }
        }
        // ltr diag
        else if(rgb_equal(tr, bl) && !rgb_equal(tl, br)) {
            grad_start = "top_left";
            grad_len = height;
        }
        // rtl diag
        else if(rgb_equal(tl, br) && !rgb_equal(tr, bl)) {
            grad_start = "top_right";
            grad_len = height;
            tl = tr;
            br = bl;
        }

        log(grad_len, grad, mid, grad_start);

        //g->colors = (rgb *)calloc(2, sizeof(rgb));
        //g->colors[0] = tl;
        //g->colors[1] = br;
        //g->ncolors = 2;

        // If it's a diagonal, we only support 2 colours
        // If it's horizontal or vertical and the middle colour is the avg of the ends, then
        // we only need two colours
        //Also, if the image is less than 3 pixels in the direction of the gradient, then you
        //  really cannot have more than 2 colours

        //if(g->start == top_left || g->start == top_right || l < 3
            //|| rgb_equal(mid, rgb_avg(tl, br))) {
            //return;
        //}

        //Now we come to the complicated part where there are more than 2 colours
        //The good thing though is that it's either horizontal or vertical at this point
        //and that it is at least 3 pixels long in the direction of the gradient
        // So this is what we'll do.
        // - take a slice of the image from the top (or left) and see if the mid pixel matches
        // - the average of the two ends.  we start at 3 pixels.
        // - if it does, then double the size of the slice and retry (until you reach the end of the image)
        // - if it does not match, then reduce until it does match this is the first stop

        // min = base = 0;
        // xy[0][g->start] = base;
        // max = i = 2;
        // while(i+base<l) {
            // xy[1][g->start] = i+base;
            // avg = rgb_avg(getpixel(image, xy[0][0], xy[0][1]), getpixel(image, xy[1][0], xy[1][1]));
            // if((i+base) % 2 == 0) {
                // mid = getpixel(image, (xy[1][0]+xy[0][0])/2, (xy[1][1]+xy[0][1])/2);
            // }
            // else {
                // mid = rgb_avg(
                    // getpixel(image, (xy[1][0]+xy[0][0])/2, (xy[1][1]+xy[0][1])/2),
                    // getpixel(image, (xy[1][0]+xy[0][0])/2+1, (xy[1][1]+xy[0][1])/2+1)
                // );
            // }

        // if(!rgb_equal(avg, mid)) {
            // if(min == max) {
                // min++;
                // max=i=min+2;
            // }
            // else {
                // max = i;
                // i = (i+min)/2;
            // }
        // }
        // else if(max-i<=1 && i-min<=1) {
            // We've converged
            // if(base+i >= l-1) {
                // This is the same as the end point, so skip
                // i++;
            // }
            // else {
                // g->ncolors++;
                // g->colors = (rgb *)realloc(g->colors, sizeof(rgb)*g->ncolors);
                // g->colors[g->ncolors-2] = getpixel(image, xy[1][0], xy[1][1]);
                // g->colors[g->ncolors-2].pos = (i+base)*100/l;

                // base += i;
                // min = 0;
                // max = i = l-base-1;
                // xy[0][g->start] = base;
            // }
        // }
        // else {
            // min = i;
            // if(i == max) {
                // i*=2;
                // if(i+base >= l)
                    // i = l-base-1;
                // max = i;
            // }
            // else {
                // i = (i+max)/2;
            // }
        // }
    // }
    // g->colors[g->ncolors-1] = br;
        return [];
    }

    function getColorArray(ctx) {
        var imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
        var width = imageData.width;
        var height = imageData.height;
        var data = imageData.data;

        var colors = [];
        for (var y = 0; y < height; y++) {
            var row = [];
            for (var x = 0; x < width; x++) {
                var idx = ((width * y) + x) * 4;
                var r = data[idx];
                var g = data[idx + 1];
                var b = data[idx + 2];
                var a = data[idx + 3];
                row.push([r, g, b, a]);
            }

            colors[y] = row;
        }

        return colors;
    }

    function getCssGrad(stops, len) {
        var grad = "-webkit-linear-gradient(left," + _.map(stops, function (s) {
            var pct = Math.ceil((s.idx / len) * 100);
            var color = s.color.toRgbString();
            return color + " " + pct + "%";
        }).join(",") + ")";
    }

    function findGrad(dataurl) {
        var image = new Image();
        image.src = dataurl;
        image.onload = function () {
            var img = this;
            var canvas = $("<canvas>")[0];
            var ctx = canvas.getContext("2d");
            canvas.width = img.width;
            canvas.height = img.height;

            ctx.drawImage(img, 0, 0);
            var colors = getColorArray(ctx);
            var stops = calculateGradient(colors);
            return "";
            //var len = img.width - 1;
            //return getCssGrad(stops, len);
        };
    }
    exports.findGrad = findGrad;
})(window);<commit_msg>rename variables and remove dead-end code.<commit_after>(function(exports) {
    function Gradient(stops, start) {
        this.stops = stops;
        this.start = start;
    }

    function rgb_avg(a, b) {
        return {
            r: (a.r + b.r) / 2,
            g: (a.g + b.g) / 2,
            b: (a.b + b.b) / 2
        };
    }

    function rgb_equal(a, b, tol) {
        tol = tol || 2;

        if (Math.abs(a.r - b.r) > tol) {
            return false;
        }
        if (Math.abs(a.g - b.g) > tol) {
            return false;
        }
        if (Math.abs(a.b - b.b) > tol) {
            return false;
        }

        return true;
    }

    function arrayToRgb(arr) {
        var ret = {
            r: arr[0],
            g: arr[1],
            b: arr[2]
        };

        if (arr.length == 4) {
            ret.a = arr[3];
        }

        return ret;
    };

    function getPixel(arr, x, y) {
        return arrayToRgb(arr[y][x]);
    }

    function calculateGradient(arr) {
        var ret = [];
        var height = arr.length;
        var width = arr[0].length;
        var top_left = getPixel(arr, 0, 0);
        var top_right = getPixel(arr, width - 1, 0);
        var bottom_left = getPixel(arr, 0, height - 1);
        var bottom_right = getPixel(arr, width - 1, height - 1);

        var grad_len;
        var grad;
        var mid;
        var grad_start;

        // vertical gradient -- row[0][0] == row[0][height]
        if (rgb_equal(top_left, top_right)) {
            grad_start = "top";
            grad_len = height;
            if (grad_len % 2 === 0) {
                mid = getPixel(arr, 0, grad_len / 2);
            }
            else {
                mid = rgb_avg(getPixel(arr, 0, grad_len / 2), getPixel(image, 0, (grad_len / 2) - 1));
            }
        }
        // horizontal gradient
        else if (rgb_equal(top_left, bottom_left)) {
            grad_start = "left";
            grad_len = width;
            if (grad_len % 2 === 0) {
                mid = getPixel(arr, grad_len / 2, 0);
            }
            else {
                mid = rgb_avg(getPixel(arr, Math.floor(grad_len / 2), 0), getPixel(arr, Math.ceil(grad_len / 2), 0));
            }
        }
        // ltr diag
        else if(rgb_equal(top_right, bottom_left) && !rgb_equal(top_left, bottom_right)) {
            grad_start = "top_left";
            grad_len = height;
        }
        // rtl diag
        else if(rgb_equal(top_left, bottom_right) && !rgb_equal(top_right, bottom_left)) {
            grad_start = "top_right";
            grad_len = height;
            top_left = top_right;
            bottom_right = bottom_left;
        }

        var stops = {};
        stops[0] = top_left;
        stops[grad_len] = bottom_right;

        // If it's a diagonal, we only support 2 colours
        // If it's horizontal or vertical and the middle colour is the avg of the ends, then
        // we only need two colours
        //Also, if the image is less than 3 pixels in the direction of the gradient, then you
        //  really cannot have more than 2 colours
        if (grad_len < 3 || rgb_equal(mid, rgb_avg(top_left, bottom_right))) {
            return new Gradient(stops, grad_start);
        }

        return [];

        //if(g->start == top_left || g->start == top_right || l < 3
            //|| rgb_equal(mid, rgb_avg(tl, br))) {
            //return;
        //}

        //Now we come to the complicated part where there are more than 2 colours
        //The good thing though is that it's either horizontal or vertical at this point
        //and that it is at least 3 pixels long in the direction of the gradient
        // So this is what we'll do.
        // - take a slice of the image from the top (or left) and see if the mid pixel matches
        // - the average of the two ends.  we start at 3 pixels.
        // - if it does, then double the size of the slice and retry (until you reach the end of the image)
        // - if it does not match, then reduce until it does match this is the first stop

        // min = base = 0;
        // xy[0][g->start] = base;
        // max = i = 2;
        // while(i+base<l) {
            // xy[1][g->start] = i+base;
            // avg = rgb_avg(getpixel(image, xy[0][0], xy[0][1]), getpixel(image, xy[1][0], xy[1][1]));
            // if((i+base) % 2 == 0) {
                // mid = getpixel(image, (xy[1][0]+xy[0][0])/2, (xy[1][1]+xy[0][1])/2);
            // }
            // else {
                // mid = rgb_avg(
                    // getpixel(image, (xy[1][0]+xy[0][0])/2, (xy[1][1]+xy[0][1])/2),
                    // getpixel(image, (xy[1][0]+xy[0][0])/2+1, (xy[1][1]+xy[0][1])/2+1)
                // );
            // }

        // if(!rgb_equal(avg, mid)) {
            // if(min == max) {
                // min++;
                // max=i=min+2;
            // }
            // else {
                // max = i;
                // i = (i+min)/2;
            // }
        // }
        // else if(max-i<=1 && i-min<=1) {
            // We've converged
            // if(base+i >= l-1) {
                // This is the same as the end point, so skip
                // i++;
            // }
            // else {
                // g->ncolors++;
                // g->colors = (rgb *)realloc(g->colors, sizeof(rgb)*g->ncolors);
                // g->colors[g->ncolors-2] = getpixel(image, xy[1][0], xy[1][1]);
                // g->colors[g->ncolors-2].pos = (i+base)*100/l;

                // base += i;
                // min = 0;
                // max = i = l-base-1;
                // xy[0][g->start] = base;
            // }
        // }
        // else {
            // min = i;
            // if(i == max) {
                // i*=2;
                // if(i+base >= l)
                    // i = l-base-1;
                // max = i;
            // }
            // else {
                // i = (i+max)/2;
            // }
        // }
    // }
    // g->colors[g->ncolors-1] = br;
        return [];
    }

    function getColorArray(ctx) {
        var imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
        var width = imageData.width;
        var height = imageData.height;
        var data = imageData.data;

        var colors = [];
        for (var y = 0; y < height; y++) {
            var row = [];
            for (var x = 0; x < width; x++) {
                var idx = ((width * y) + x) * 4;
                var r = data[idx];
                var g = data[idx + 1];
                var b = data[idx + 2];
                var a = data[idx + 3];
                row.push([r, g, b, a]);
            }

            colors[y] = row;
        }

        return colors;
    }

    function getCssGrad(stops, len) {
        var grad = "-webkit-linear-gradient(left," + _.map(stops, function (s) {
            var pct = Math.ceil((s.idx / len) * 100);
            var color = s.color.toRgbString();
            return color + " " + pct + "%";
        }).join(",") + ")";
    }

    function findGrad(dataurl) {
        var image = new Image();
        image.src = dataurl;
        image.onload = function () {
            var img = this;
            var canvas = $("<canvas>")[0];
            var ctx = canvas.getContext("2d");
            canvas.width = img.width;
            canvas.height = img.height;

            ctx.drawImage(img, 0, 0);
            var colors = getColorArray(ctx);
            var stops = calculateGradient(colors);
            log(stops);
            //var len = img.width - 1;
            //return getCssGrad(stops, len);
        };
    }
    exports.findGrad = findGrad;
})(window);<|endoftext|>


<commit_before>'use strict'

// initialize Hoodie
var hoodie  = new Hoodie();

// on ready calls all binds
$(function () {
  $('#sign-up').bind('submit', submitSignUp)
  $('#go-on-vacation').bind('click', result)
})

// sign-in on main page
var submitSignUp = function submitSignUp(){
  var usr = $('#email').val();
  var pwd = $('#pwd').val();

  hoodie.account.signIn(usr, pwd).done(function(){
    if(hoodie.account.username) {
      location.href = 'dashboard.html'
    }
  })
  return false;
}

// return results
var result = function result(event) {
  var e = event.target;
  var urlReq = e.getAttribute('data-url');

  $.ajax({
    url: urlReq
  })
  .done(function( data ) {
    var dom = $("#output");
    var res = data.results;

    res.forEach(function (obj) {
      var li = '
' + obj.price + ' € / p. n. & p.
 Book now!
' + obj.name + '
' + obj.city + '

'
      $("#output").append(li);
    })
//    var html = ich.result_list(data);
 //   $("#output").append(html);
  });
}
<commit_msg>dance<commit_after>'use strict'

// initialize Hoodie
var hoodie  = new Hoodie();

// on ready calls all binds
$(function () {
  $('#sign-up').bind('submit', submitSignUp)
  $('#go-on-vacation').bind('click', result)
})

// sign-in on main page
var submitSignUp = function submitSignUp(){
  var usr = $('#email').val();
  var pwd = $('#pwd').val();

  hoodie.account.signIn(usr, pwd).done(function(){
    if(hoodie.account.username) {
      location.href = 'dashboard.html'
    }
  })
  return false;
}

// return results
var result = function result(event) {
  var e = event.target;
  var urlReq = e.getAttribute('data-url');

  $.ajax({
    url: urlReq
  })
  .done(function( data ) {
    var dom = $("#output");
    var res = data.results;

    res.forEach(function (obj) {
      var li = '
' + obj.price + ' € / p. n. & p.
 Book now!
' + obj.name + '
' + obj.city + '

'
      $("#output").append(li);
    })
  });
}
<|endoftext|>


<commit_before>'use strict'

// initialize Hoodie
var hoodie  = new Hoodie();

// on ready calls all binds
$(function () {
  if(hoodie.account.username) {
    hoodie.store.find('settings', 'user-settings')
    .done(function(settings) {
      $('#username').append(settings.name || hoodie.account.username)
      $('h2.welcoming').append(settings.name || hoodie.account.username )
    })
    .fail(function() {
      $('#username').append(hoodie.account.username)
      $('h2.welcoming').append(hoodie.account.username)
      // console.log((!$('#main') && hoodie.account.username == undefined))
    // location.href = 'index.html';
    })
  }
  $('#logout').bind('click', signOutUsr);
  $('#sign-up').bind('submit', submitSignUp);
  $('#go-on-vacation').bind('click', result);
  $('.day-ani').bind('live', animateDays)
})

// animation of work/vac days in dashboard
var animateDays = function animateDays() {
  alert('jo')
}

// sign-in on main page
var submitSignUp = function submitSignUp() {
  var usr = $('#email').val();
  var pwd = $('#pwd').val();

  hoodie.account.signIn(usr, pwd).done(function() {
    if(hoodie.account.username) {
      location.href = 'dashboard.html';
    }
  }).fail(function () {
    hoodie.account.signUp(usr, pwd, pwd)
      .done(function(){
      if(hoodie.account.username) {
        location.href = 'settings-init.html';
      }
    })
    .fail(function () {
      alert('Your credentials are wrong!');
    })
  })
  return false;
}

var signOutUsr = function signOutUsr () {
  hoodie.account.signOut().done(function () {
    location.href = 'index.html';
  })
}

// return results
var result = function result(event) {
  var e = event.target;
  var urlReq = e.getAttribute('data-url');

  var base = "http://justrelax.rrbone.io/booking/holiday?"

  var scores = window.engine.scores()
  var recommends = window.engine.blocks(scores);

  for (var i=1; i<=3; i++) {
    (function(i) {
      var from = recommends[i-1].start.date;
      var to = recommends[i-1].end.date;
      var location = "Deutschland";
      var urlReq = base +
        "from=" + from +
        "&to=" + to +
        "&location=" + location;
      $.ajax({
        url: urlReq
      })
      .done(function( data ) {
        var dom = $(".output");
        var res = data.results;

        var f = moment(from).format("DD.MM.YYYY");
        var t = moment(to).format("DD.MM.YYYY");
        $(".output-option-"+i).text(
          "Option " + i + ": " + f + " - " + t
        )

        res.slice(0,3).forEach(function (obj) {
          var li = '
' + obj.price + ' € / p. n. & p.
 Book now!
' + obj.name + '
' + obj.city + '

'
          $(".output-"+i).append(li).fadeIn().removeClass('hide');;
        })
      });
    })(i);
  }
  $(".output").fadeIn().removeClass('hide');
  $('#dashboard').fadeOut().addClass('hide');
}

if (window.recommender) {
  window.engine = recommender({
    dates: dates,
    lastVacation: moment(),
    blockedWork: [
      {
        from: '2015-06-28',
        to: '2015-06-30',
        days: 3
      }
    ],
    blockedVac: [
      {
        from: '2015-07-03',
        to: '2015-07-13',
        days: 2
      }
    ]
  })
}
<commit_msg>Build URL async<commit_after>'use strict'

// initialize Hoodie
var hoodie  = new Hoodie();

// on ready calls all binds
$(function () {
  if(hoodie.account.username) {
    hoodie.store.find('settings', 'user-settings')
    .done(function(settings) {
      $('#username').append(settings.name || hoodie.account.username)
      $('h2.welcoming').append(settings.name || hoodie.account.username )
    })
    .fail(function() {
      $('#username').append(hoodie.account.username)
      $('h2.welcoming').append(hoodie.account.username)
      // console.log((!$('#main') && hoodie.account.username == undefined))
    // location.href = 'index.html';
    })
  }
  $('#logout').bind('click', signOutUsr);
  $('#sign-up').bind('submit', submitSignUp);
  $('#go-on-vacation').bind('click', result);
  $('.day-ani').bind('live', animateDays)
})

// animation of work/vac days in dashboard
var animateDays = function animateDays() {
  alert('jo')
}

// sign-in on main page
var submitSignUp = function submitSignUp() {
  var usr = $('#email').val();
  var pwd = $('#pwd').val();

  hoodie.account.signIn(usr, pwd).done(function() {
    if(hoodie.account.username) {
      location.href = 'dashboard.html';
    }
  }).fail(function () {
    hoodie.account.signUp(usr, pwd, pwd)
      .done(function(){
      if(hoodie.account.username) {
        location.href = 'settings-init.html';
      }
    })
    .fail(function () {
      alert('Your credentials are wrong!');
    })
  })
  return false;
}

var signOutUsr = function signOutUsr () {
  hoodie.account.signOut().done(function () {
    location.href = 'index.html';
  })
}

var buildUrl = function buildUrl(from, to) {
  var base = "http://justrelax.rrbone.io/booking/holiday?"

  var urlReq = base + "from=" + from + "&to=" + to;

  return hoodie.store.find("settings", "user-settings")
  .then(function(s) {
    urlReq += "&location=" + s.favDestination;

    var adults = parseInt(s.adults, 10);
    var kids = parseInt(s.kids, 10);
    var budget = parseInt(s.budget, 10);

    if (adults > 0) urlReq += "&adults=" + adults;
    if (kids > 0) urlReq += "&kids=" + kids;
    if (budget > 0) urlReq += "&budget=" + budget;

    return urlReq;
  })
}

// return results
var result = function result(event) {
  var e = event.target;
  var urlReq = e.getAttribute('data-url');

  var scores = window.engine.scores()
  var recommends = window.engine.blocks(scores);

  for (var i=1; i<=3; i++) {
    (function(i) {
      var from = recommends[i-1].start.date;
      var to   = recommends[i-1].end.date;
      buildUrl(from, to).then(function(urlReq) {
        $.ajax({
          url: urlReq
        })
        .done(function( data ) {
          var dom = $(".output");
          var res = data.results;

          var f = moment(from).format("DD.MM.YYYY");
          var t = moment(to).format("DD.MM.YYYY");
          $(".output-option-"+i).text(
            "Option " + i + ": " + f + " - " + t
          )

          res.slice(0,3).forEach(function (obj) {
            var li = '
' + obj.price + ' € / p. n. & p.
 Book now!
' + obj.name + '
' + obj.city + '

'
            $(".output-"+i).append(li).fadeIn().removeClass('hide');;
          })
        });
      });
    })(i);
  }
  $(".output").fadeIn().removeClass('hide');
  $('#dashboard').fadeOut().addClass('hide');
}

if (window.recommender) {
  window.engine = recommender({
    dates: dates,
    lastVacation: moment(),
    blockedWork: [
      {
        from: '2015-06-28',
        to: '2015-06-30',
        days: 3
      }
    ],
    blockedVac: [
      {
        from: '2015-07-03',
        to: '2015-07-13',
        days: 2
      }
    ]
  })
}
<|endoftext|>


<commit_before>"use strict";
// initialize Hoodie
var hoodie  = new Hoodie();

// Chats Collection/View
function Chats($element) {
  var collection = [];
  var $el = $element;

  // Handle marking chat as "done"
  $el.on('click', 'input[type=checkbox]', function() {
    hoodie.store.remove('chat', $(this).parent().data('id'));
    return false;
  });

  // Handle "inline editing" of a chat.
  $el.on('click', 'label', function() {
    $(this).parent().parent().find('.editing').removeClass('editing');
    $(this).parent().addClass('editing');
    return false;
  });

  // Handle updating of an "inline edited" chat.
  $el.on('keypress', 'input[type=text]', function(event) {
    if (event.keyCode === 13) {
      hoodie.store.update('chat', $(this).parent().data('id'), {title: event.target.value});
    }
  });

  // Find index/position of a chat in collection.
  function getChatItemIndexById(id) {
    for (var i = 0, len = collection.length; i < len; i++) {
      if (collection[i].id === id) {
        return i;
      }
    }
    return null;
  }

  function paint() {
    $el.html('');
    collection.sort(function(a, b) {
      return ( a.createdAt > b.createdAt ) ? 1 : -1;
    });
    for (var i = 0, len = collection.length; i<len; i++) {
      $el.append(
        '
' +
          '<input type="checkbox"> ' + collection[i].title + '' +
          '<input type="text" value="' + collection[i].title + '"/>' +
        '
'
      );
    }
  }

  this.add = function(chat) {
    collection.push(chat);
    paint();
  };

  this.update = function(chat) {
    collection[getChatItemIndexById(chat.id)] = chat;
    paint();
  };

  this.remove = function(chat) {
    collection.splice(getChatItemIndexById(chat.id), 1);
    paint();
  };

  this.clear = function() {
    collection = [];
    paint();
  };
}

// Instantiate Chats collection & view.
var chats = new Chats($('#chatlist'));

// initial load of all chat items from the store
hoodie.store.findAll('chat').then(function(allChats) {
  allChats.forEach(chats.add);
});

// when a chat changes, update the UI.
hoodie.store.on('chat:add', chats.add);
hoodie.store.on('chat:update', chats.update);
hoodie.store.on('chat:remove', chats.remove);
// clear chats when user logs out,
hoodie.account.on('signout', chats.clear);

// handle creating a new task
$('#chatinput').on('keypress', function(event) {
  // ENTER & non-empty.
  if (event.keyCode === 13 && event.target.value.length) {
    hoodie.store.add('chat', {title: event.target.value});
    event.target.value = '';
  }
});
<commit_msg>Add a basic storage model for messages<commit_after>"use strict";
// initialize Hoodie
var hoodie  = new Hoodie();
var messageStore = hoodie.store('chatMessages');

// create a message model for re-use later

// Chats Collection/View
function Chats($element) {
  var collection = [];
  var $el = $element;

  // Handle marking chat as "done"
  $el.on('click', 'input[type=checkbox]', function() {
    messageStore.remove($(this).parent().data('id'));
    return false;
  });

  // Handle "inline editing" of a chat.
  $el.on('click', 'label', function() {
    $(this).parent().parent().find('.editing').removeClass('editing');
    $(this).parent().addClass('editing');
    return false;
  });

  // Handle updating of an "inline edited" chat.
  $el.on('keypress', 'input[type=text]', function(event) {
    if (event.keyCode === 13) {
      messageStore.update($(this).parent().data('id'), {title: event.target.value});
    }
  });

  // Find index/position of a chat in collection.
  function getChatItemIndexById(id) {
    for (var i = 0, len = collection.length; i < len; i++) {
      if (collection[i].id === id) {
        return i;
      }
    }
    return null;
  }

  function paint() {
    $el.html('');
    collection.sort(function(a, b) {
      return ( a.createdAt > b.createdAt ) ? 1 : -1;
    });
    for (var i = 0, len = collection.length; i<len; i++) {
      $el.append(
        '
' +
          '<input type="checkbox"> ' + collection[i].title + '' +
          '<input type="text" value="' + collection[i].title + '"/>' +
        '
'
      );
    }
  }

  this.add = function(chat) {
    collection.push(chat);
    paint();
  };

  this.update = function(chat) {
    collection[getChatItemIndexById(chat.id)] = chat;
    paint();
  };

  this.remove = function(chat) {
    collection.splice(getChatItemIndexById(chat.id), 1);
    paint();
  };

  this.clear = function() {
    collection = [];
    paint();
  };
}

// Instantiate Chats collection & view.
var chats = new Chats($('#chatlist'));

// initial load of all chat items from the store
messageStore.findAll('chat').then(function(allChats) {
  allChats.forEach(chats.add);
});

// when a chat changes, update the UI.
messageStore.on('chat:add', chats.add);
messageStore.on('chat:update', chats.update);
messageStore.on('chat:remove', chats.remove);
// clear chats when user logs out,
hoodie.account.on('signout', chats.clear);

// handle creating a new task
$('#chatinput').on('keypress', function(event) {
  // ENTER & non-empty.
  if (event.keyCode === 13 && event.target.value.length) {
    var text = event.target.value.trim(),
        msg = new messageModel(text);
    messageStore.add(msg);
    hoodie.remote.push();
    event.target.value = '';
  }
});
<|endoftext|>