<commit_before>/**
 * _scripts/widgets/pantheon/terminal.js
 * Creates a realistic terminal designed to mimic pantheon-terminal
 *
 * @exports {Class} default - Creates a realistic terminal
 */

/**
 * Here lies some basic commands that are included by default
 *
 * @param {String} cmd - command ran
 * @param {Object} term - terminal object
 * @returns {Number} exit code for command
 */
const commands = {}

commands[/^clear/] = function (cmd, term) {
    return new Promise((resolve, reject) => {
        term.history = []
        term.$i.text('')
        return resolve(0)
    })
}

commands[/^exit/] = function (cmd, term) {
    return new Promise((resolve, reject) => {
        window.history.back()
        return resolve(0)
    })
}

commands[/^whoami$/] = function (cmd, term) {
    if (term.user === 'groot') {
        return term.append('i am groot')
        .then(() => 0)
    } else {
        return term.append(term.user)
        .then(() => 0)
    }
}

commands[/^USER=/] = function (cmd, term) {
    return new Promise((resolve, reject) => {
        const userCMD = cmd.split('=')[1]
        if (userCMD == null || userCMD === '') return resolve(0)

        const user = userCMD.split(' ')[0]
        if (user == null || userCMD === '') return resolve(0)

        term.user = user
        return resolve(0)
    })
}

commands[/^rm -rf \/$/] = function (cmd, term) {
    return term.append('no.')
    .then(() => 0)
}

commands[/^cd/] = function (cmd, term) {
    return new Promise((resolve, reject) => {
        const split = cmd.split(' ')

        if (split[1] == null) return resolve(0)
        if (split[1] === '.' || split[1] === '~' || split[1] === './') return resolve(0)

        return resolve(term.append(`I'm sorry, ${term.user}. I'm afraid I can't do that.`))
        .then(() => 1)
    })
}

commands[/^echo/] = function (cmd, term) {
    return new Promise((resolve, reject) => {
        const text = cmd.match(/(["'])[^]*?\1/)[0]

        return resolve(term.append(text.substring(1, text.length - 1)))
        .then(() => 0)
    })
}

commands[/^mkdir .\/website$/] = function (cmd, term) {
    return 0
}

commands[/^rm -rf .\/website$/] = function (cmd, term) {
    return 0
}

commands[/^git clone https:\/\/github.com\/elementary\/website.git$/] = function (cmd, term) {
    return term.append(`Cloning into '/home/${term.user}/website'...`, 300)
    .then(() => term.append('remote: Counting objects: 20257, done.', 100))
    .then(() => {
        return term.append('remote: Compressing objects: 0% (0/29)')
        .then(($l) => {
            return new Promise((resolve, reject) => {
                let t = 0

                for (let i = 0; i <= 29; i++) {
                    setTimeout(() => {
                        $l.text(`remote: Compressing objects: ${Math.floor(i / 29 * 100)}% (${i}/29)${(i === 29) ? ', done.' : ''}`)
                    }, t)

                    t += Math.floor(Math.random() * 75)
                }

                setTimeout(() => {
                    return resolve()
                }, t)
            })
        })
    })
    .then(() => {
        return term.append('Receiving objects: 0% (0/20257), 0MiB | 0 MiB/s')
        .then(($l) => {
            return new Promise((resolve, reject) => {
                let t = 0

                for (let i = 0; i <= 20257; i++) {
                    setTimeout(() => {
                        $l.text(`Receiving objects: ${Math.floor(i / 20257 * 100)}% (${i}/20257), ${Math.floor(i / t * 4)}MiB | 1.21 GW/s${(i === 20257) ? ', done.' : ''}`)
                    }, t)

                    i += Math.floor(Math.random() * 50)
                    t += Math.random() * 10
                }

                setTimeout(() => {
                    $l.text('Receiving objects: 100% (20257/20257), 21MiB | 1.21 GW/s, done.')
                    return resolve()
                }, t)
            })
        })
    })
    .then(() => term.append('Receiving deltas: 100% (13052/13052), done.', Math.random() * 800))
    .then(() => term.append('Checking connectivity... done', Math.random() * 600))
    .then(() => 0)
}

// A rather special command that runs other commands
commands[/^\.\/demo$/] = function (cmd, term) {
    term.prompt()

    return term.type('rm -rf ./website')
    .then(() => term.type('git clone https://github.com/elementary/website.git'))
    .then(() => term.type('./demo'))
}

/**
 * default
 * A showcase slider for elementary homepage.
 *
 * @param {String} w - jQuery selector the terminal window
 */
export default class Terminal {

    /**
     * constructor
     * Creates a new Showcase
     *
     * @param {String} w - jQuery selector the terminal window
     */
    constructor (w = '.window[type="terminal"]') {
        this.w = w
        this.title = 'Home'
        this.user = 'ellie'
        this.host = 'elementary'
        this.folder = `/home/${this.user}`

        this.history = []

        // terminal colors by index
        this.colors = [
            '#073642',
            '#dc322f',
            '#859900',
            '#b58900',
            '#268bd2',
            '#ec0048',
            '#2aa198',
            '#94a3a5'
        ]

        // avalible commands to this terminal
        this.commands = commands

        this.$w = $(w)
        this.$i = $('.input', this.$w)
    }

    /**
     * start
     * Starts JS logic for the terminal
     */
    start () {
        this.handle()
        this.prompt()
        this.type('./demo')
    }

    /**
     * handle
     * Sets up handles for events
     */
    handle () {
        $(window).on('scroll', () => {
            this.activeCheck()
        })

        $(window).on('resize', (e) => {
            this.activeCheck()
            this.$i.trigger('move')
        })

        $(window).on('keydown', (e) => {
            if (!this.$w.hasClass('active')) return

            var key = e.which

            // TODO: we need to detect if active better before
            // preventing critical key defaults
            if (key === 8 || key === 32) {
                // e.preventDefault()
                this.keyper(key)
            } else if (key === 13) {
                // e.preventDefault()
                this.process()
            }
        })

        $(window).on('keypress', (e) => {
            if (!this.$w.hasClass('active')) return

            this.keyper(e.which)
            this.$i.trigger('move')
        })

        this.$i.on('move', () => {
            this.$i.scrollTop(this.$i[0].scrollHeight)
        })
    }

    /**
     * activeCheck
     * Checks if the current terminal window should be active
     */
    activeCheck () {
        const debounce = () => {
            var pT = this.$w.offset().top
            var pL = this.$w.offset().left
            var scroll = $(window).scrollTop()
            var wH = $(window).height()
            var wW = $(window).width()

            if (scroll + wH > pT && scroll < pT + wH && pL < wW) {
                this.$w.addClass('active')
            } else {
                this.$w.removeClass('active')
            }
        }

        var diff = new Date().getTime() - this.activeChecked

        if (this.activeChecked == null || diff >= 500) {
            this.activeChecked = new Date().getTime()
            debounce()
        } else {
            clearTimeout(this.activeTimer)
            this.activeTimer = setTimeout(debounce, 500)
        }
    }

    /**
     * keyper
     * Simple handler for all input to terminal
     *
     * @param {Number} key - key charactor
     */
    keyper (key) {
        const letter = String.fromCharCode(key)
        const $line = $('> span:last-child', this.$i)
        let $sec = $('> span:last-child', $line)

        if (!$sec.hasClass('input')) {
            $line.append('')
            $sec = $('> span:last-child', $line)
        }

        if (key === 8) {
            $sec.text($sec.text().slice(0, -1))
        } else {
            $sec.text($sec.text() + letter)
        }

        this.$i.trigger('move')
    }

    /**
    * append
    * Writes a new line to terminal
    *
    * @param {String} str - string to write to terminal (it can honestly be anything)
    * @param {Number} time - time in miliseconds to wait before appending
    * @returns {Object} - jQuery object of newly appended line
    */
    append (str, time = 0) {
        if (str.substr(0, 4) !== '<span') str = '' + str + ''
        const data = $(str)

        return new Promise((resolve, reject) => {
            setTimeout(() => {
                this.$i.append(data)
                this.$i.trigger('move')
                return resolve($('> span:last-child', this.$i))
            }, time)
        })
    }

    /**
     * format
     * Returns span ready for DOM appendage
     *
     * @param {String} str - string to write
     * @param {Number} c - terminal color code
     * @param {String} s - text style properties (bold)
     * @param {String} i - additional classes to write
     * @returns {String} - span wrapped text with color
     */
    format (str, c, s, i) {
        if (this.colors[c] != null) c = this.colors[c]

        var out = ' 0) {
            out += ' style="'

            styles.forEach((o) => {
                out += `${o[0]}: ${o[1]};`
            })

            out += '"'
        }

        if (i != null) out += ` class="${i}"`

        out += `>${str}</span>`

        return out
    }

    /**
     * prompt
     * Prints a prompt
     */
    prompt () {
        const folder = this.folder.replace(`/home/${this.user}`, '~')
        const prompt = this.format(`${this.user}@${this.host}`, 2, 'b') + this.format(':') + this.format(folder, 4, 'b') + this.format('$')

        let title = this.folder
        if (this.folder === `/home/${this.user}`) {
            title = 'Home'
        }
        if (this.history.length > 0) {
            const last = this.history[this.history.length - 1]

            if (last.length > 30) {
                title += `: ${last.split(' ')[0]}`
            } else {
                title += `: ${last}`
            }
        }

        $('.titlebar .title', this.$w).text(title)
        $('.tabbar .tab.active .title', this.$w).text(title)
        this.append(`<span class="prompt">${prompt} </span><span class="input"></span>`)
        this.$i.trigger('move')
    }

    /**
     * process
     * Takes user input from line and processes it
     *
     * @param {String} cmd - command to process
     * @returns {Number} exit code of the ran command
     */
    process (cmd = $('> span:last-child > span.input:last-of-type', this.$i).text()) {
        cmd = cmd.replace(/</g, '<').replace(/>/g, '>').replace(/"|'/g, '"')

        if (!this.$w.hasClass('active') || this.onHold) {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    this.process(cmd)
                }, 50)
            })
        }

        const time = new Date()

        return new Promise((resolve, reject) => {
            if (cmd == null || cmd === '') return resolve(0)

            const cmds = Object.keys(this.commands).filter((reg) => {
                const regex = new RegExp(reg.substr(1, reg.lastIndexOf('/') - 1), reg.substr(reg.lastIndexOf('/') + 1))
                return regex.test(cmd)
            })

            if (cmds.length < 1) return reject(-1)

            this.history.push(cmd)

            $('.titlebar .title', this.$w).text(cmd)
            $('.tabbar .tab.active .title', this.$w).text(cmd)

            return resolve(this.commands[cmds[0]](cmd, this))
        })
        .catch((code) => {
            if (code !== -1) return

            return this.append(`${cmd.split(' ')[0]}: command not found`, Math.random() * 30)
            .then(() => 1)
        })
        .then((code) => {
            const current = new Date()

            if (current - time > 300) this.notify(this.history[this.history.length - 1])

            this.prompt()
            return code
        })
    }

    /**
     * notify
     * Creates a notification
     *
     * @param {String} cmd - command to put on notification
     */
    notify (cmd) {
        if (!this.$w.hasClass('active')) return

        const $c = $('#notification-container')
        const $p = $c.parent('.pantheon')

        var $n = $('[type="notification"]', $c)
        $('p', $n).text(cmd)
        $n.addClass('active')

        $p.show()
        $c.append($n)
        $n.one('animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd', (e) => {
            $p.hide()
        })
    }

    /**
     * type
     * Types a command out in the terminal then runs it
     *
     * @param {String} cmd - command to type
     * @returns {Number} exit code of the ran command
     */
    type (cmd) {
        return new Promise((resolve, reject) => {
            let time = 0

            for (let i = 0; i < cmd.length; i++) {
                setTimeout(() => {
                    this.keyper(cmd.charCodeAt(i))
                }, time)

                time += 50
            }

            setTimeout(() => {
                this.process()
                .then((c) => resolve(c))
                .catch((e) => reject(e))
            }, time + 200)
        })
    }
}
<commit_msg>Killall terminal (#1708)<commit_after>/**
 * _scripts/widgets/pantheon/terminal.js
 * Creates a realistic terminal designed to mimic pantheon-terminal
 *
 * @exports {Class} default - Creates a realistic terminal
 */

/**
 * Here lies some basic commands that are included by default
 *
 * @param {String} cmd - command ran
 * @param {Object} term - terminal object
 * @returns {Number} exit code for command
 */
const commands = {}

commands[/^clear/] = function (cmd, term) {
    return new Promise((resolve, reject) => {
        term.history = []
        term.$i.text('')
        return resolve(0)
    })
}

commands[/^mkdir .\/website$/] = function (cmd, term) {
    return 0
}

commands[/^rm -rf .\/website$/] = function (cmd, term) {
    return 0
}

commands[/^git clone https:\/\/github.com\/elementary\/website.git$/] = function (cmd, term) {
    return term.append(`Cloning into '/home/${term.user}/website'...`, 300)
    .then(() => term.append('remote: Counting objects: 20257, done.', 100))
    .then(() => {
        return term.append('remote: Compressing objects: 0% (0/29)')
        .then(($l) => {
            return new Promise((resolve, reject) => {
                let t = 0

                for (let i = 0; i <= 29; i++) {
                    setTimeout(() => {
                        $l.text(`remote: Compressing objects: ${Math.floor(i / 29 * 100)}% (${i}/29)${(i === 29) ? ', done.' : ''}`)
                    }, t)

                    t += Math.floor(Math.random() * 75)
                }

                setTimeout(() => {
                    return resolve()
                }, t)
            })
        })
    })
    .then(() => {
        return term.append('Receiving objects: 0% (0/20257), 0MiB | 0 MiB/s')
        .then(($l) => {
            return new Promise((resolve, reject) => {
                let t = 0

                for (let i = 0; i <= 20257; i++) {
                    setTimeout(() => {
                        $l.text(`Receiving objects: ${Math.floor(i / 20257 * 100)}% (${i}/20257), ${Math.floor(i / t * 4)}MiB | 1.21 GW/s${(i === 20257) ? ', done.' : ''}`)
                    }, t)

                    i += Math.floor(Math.random() * 50)
                    t += Math.random() * 10
                }

                setTimeout(() => {
                    $l.text('Receiving objects: 100% (20257/20257), 21MiB | 1.21 GW/s, done.')
                    return resolve()
                }, t)
            })
        })
    })
    .then(() => term.append('Receiving deltas: 100% (13052/13052), done.', Math.random() * 800))
    .then(() => term.append('Checking connectivity... done', Math.random() * 600))
    .then(() => 0)
}

// A rather special command that runs other commands
commands[/^\.\/demo$/] = function (cmd, term) {
    term.prompt()

    return term.type('rm -rf ./website')
    .then(() => term.type('git clone https://github.com/elementary/website.git'))
    .then(() => term.type('./demo'))
}

/**
 * default
 * A showcase slider for elementary homepage.
 *
 * @param {String} w - jQuery selector the terminal window
 */
export default class Terminal {

    /**
     * constructor
     * Creates a new Showcase
     *
     * @param {String} w - jQuery selector the terminal window
     */
    constructor (w = '.window[type="terminal"]') {
        this.w = w
        this.title = 'Home'
        this.user = 'ellie'
        this.host = 'elementary'
        this.folder = `/home/${this.user}`

        this.history = []

        // terminal colors by index
        this.colors = [
            '#073642',
            '#dc322f',
            '#859900',
            '#b58900',
            '#268bd2',
            '#ec0048',
            '#2aa198',
            '#94a3a5'
        ]

        // avalible commands to this terminal
        this.commands = commands

        this.$w = $(w)
        this.$i = $('.input', this.$w)
    }

    /**
     * start
     * Starts JS logic for the terminal
     */
    start () {
        this.handle()
        this.prompt()
        this.type('./demo')
    }

    /**
     * handle
     * Sets up handles for events
     */
    handle () {
        $(window).on('scroll', () => {
            this.activeCheck()
        })

        $(window).on('resize', (e) => {
            this.activeCheck()
            this.$i.trigger('move')
        })

        this.$i.on('move', () => {
            this.$i.scrollTop(this.$i[0].scrollHeight)
        })
    }

    /**
     * activeCheck
     * Checks if the current terminal window should be active
     */
    activeCheck () {
        const debounce = () => {
            var pT = this.$w.offset().top
            var pL = this.$w.offset().left
            var scroll = $(window).scrollTop()
            var wH = $(window).height()
            var wW = $(window).width()

            if (scroll + wH > pT && scroll < pT + wH && pL < wW) {
                this.$w.addClass('active')
            } else {
                this.$w.removeClass('active')
            }
        }

        var diff = new Date().getTime() - this.activeChecked

        if (this.activeChecked == null || diff >= 500) {
            this.activeChecked = new Date().getTime()
            debounce()
        } else {
            clearTimeout(this.activeTimer)
            this.activeTimer = setTimeout(debounce, 500)
        }
    }

    /**
     * keyper
     * Simple handler for all input to terminal
     *
     * @param {Number} key - key charactor
     */
    keyper (key) {
        const letter = String.fromCharCode(key)
        const $line = $('> span:last-child', this.$i)
        let $sec = $('> span:last-child', $line)

        if (!$sec.hasClass('input')) {
            $line.append('')
            $sec = $('> span:last-child', $line)
        }

        if (key === 8) {
            $sec.text($sec.text().slice(0, -1))
        } else {
            $sec.text($sec.text() + letter)
        }

        this.$i.trigger('move')
    }

    /**
    * append
    * Writes a new line to terminal
    *
    * @param {String} str - string to write to terminal (it can honestly be anything)
    * @param {Number} time - time in miliseconds to wait before appending
    * @returns {Object} - jQuery object of newly appended line
    */
    append (str, time = 0) {
        if (str.substr(0, 4) !== '<span') str = '' + str + ''
        const data = $(str)

        return new Promise((resolve, reject) => {
            setTimeout(() => {
                this.$i.append(data)
                this.$i.trigger('move')
                return resolve($('> span:last-child', this.$i))
            }, time)
        })
    }

    /**
     * format
     * Returns span ready for DOM appendage
     *
     * @param {String} str - string to write
     * @param {Number} c - terminal color code
     * @param {String} s - text style properties (bold)
     * @param {String} i - additional classes to write
     * @returns {String} - span wrapped text with color
     */
    format (str, c, s, i) {
        if (this.colors[c] != null) c = this.colors[c]

        var out = ' 0) {
            out += ' style="'

            styles.forEach((o) => {
                out += `${o[0]}: ${o[1]};`
            })

            out += '"'
        }

        if (i != null) out += ` class="${i}"`

        out += `>${str}</span>`

        return out
    }

    /**
     * prompt
     * Prints a prompt
     */
    prompt () {
        const folder = this.folder.replace(`/home/${this.user}`, '~')
        const prompt = this.format(`${this.user}@${this.host}`, 2, 'b') + this.format(':') + this.format(folder, 4, 'b') + this.format('$')

        let title = this.folder
        if (this.folder === `/home/${this.user}`) {
            title = 'Home'
        }
        if (this.history.length > 0) {
            const last = this.history[this.history.length - 1]

            if (last.length > 30) {
                title += `: ${last.split(' ')[0]}`
            } else {
                title += `: ${last}`
            }
        }

        $('.titlebar .title', this.$w).text(title)
        $('.tabbar .tab.active .title', this.$w).text(title)
        this.append(`<span class="prompt">${prompt} </span><span class="input"></span>`)
        this.$i.trigger('move')
    }

    /**
     * process
     * Takes user input from line and processes it
     *
     * @param {String} cmd - command to process
     * @returns {Number} exit code of the ran command
     */
    process (cmd = $('> span:last-child > span.input:last-of-type', this.$i).text()) {
        cmd = cmd.replace(/</g, '<').replace(/>/g, '>').replace(/"|'/g, '"')

        if (!this.$w.hasClass('active') || this.onHold) {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    this.process(cmd)
                }, 50)
            })
        }

        const time = new Date()

        return new Promise((resolve, reject) => {
            if (cmd == null || cmd === '') return resolve(0)

            const cmds = Object.keys(this.commands).filter((reg) => {
                const regex = new RegExp(reg.substr(1, reg.lastIndexOf('/') - 1), reg.substr(reg.lastIndexOf('/') + 1))
                return regex.test(cmd)
            })

            if (cmds.length < 1) return reject(-1)

            this.history.push(cmd)

            $('.titlebar .title', this.$w).text(cmd)
            $('.tabbar .tab.active .title', this.$w).text(cmd)

            return resolve(this.commands[cmds[0]](cmd, this))
        })
        .catch((code) => {
            if (code !== -1) return

            return this.append(`${cmd.split(' ')[0]}: command not found`, Math.random() * 30)
            .then(() => 1)
        })
        .then((code) => {
            const current = new Date()

            if (current - time > 300) this.notify(this.history[this.history.length - 1])

            this.prompt()
            return code
        })
    }

    /**
     * notify
     * Creates a notification
     *
     * @param {String} cmd - command to put on notification
     */
    notify (cmd) {
        if (!this.$w.hasClass('active')) return

        const $c = $('#notification-container')
        const $p = $c.parent('.pantheon')

        var $n = $('[type="notification"]', $c)
        $('p', $n).text(cmd)
        $n.addClass('active')

        $p.show()
        $c.append($n)
        $n.one('animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd', (e) => {
            $p.hide()
        })
    }

    /**
     * type
     * Types a command out in the terminal then runs it
     *
     * @param {String} cmd - command to type
     * @returns {Number} exit code of the ran command
     */
    type (cmd) {
        return new Promise((resolve, reject) => {
            let time = 0

            for (let i = 0; i < cmd.length; i++) {
                setTimeout(() => {
                    this.keyper(cmd.charCodeAt(i))
                }, time)

                time += 50
            }

            setTimeout(() => {
                this.process()
                .then((c) => resolve(c))
                .catch((e) => reject(e))
            }, time + 200)
        })
    }
}
<|endoftext|>


<commit_before>// Script created by Max1Truc
// Source available on GitHub at https://GitHub.com/Max1Truc/crypt
// It's under the MIT License

function modulo(a, b) {
    return a - b * Math.floor(a / b);
}

function crypt(message, password) {
    // ALPHABET, changing it changes characters which are encrypted
    const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 =";
    // initialize the crypted message var
    var crypted = "";
    // crypt each letter
    for (var i = 0; i < message.length; i++) {
        var indexLetterInText, indexLetterInPass, cryptedLetter;
        indexLetterInText = modulo(ALPHABET.indexOf(message[i]), ALPHABET.length);
        indexLetterInPass = modulo(
            ALPHABET.indexOf(password[modulo(i, password.length)]),
            ALPHABET.length
        );
        cryptedLetter =
            ALPHABET[modulo(indexLetterInText + indexLetterInPass, ALPHABET.length)];
        crypted = crypted.concat(cryptedLetter);
    }
    // return
    return crypted;
}

function decrypt(cryptedMessage, password) {
    // ALPHABET, changing it changes characters which are encrypted
    const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 =";
    // initialize the decrypted message var
    var decrypted = "";
    // decrypt each letter
    for (var i = 0; i < cryptedMessage.length; i++) {
        var indexLetterInText, indexLetterInPass, decryptedLetter;
        indexLetterInText = modulo(ALPHABET.indexOf(cryptedMessage[i]), ALPHABET.length);
        indexLetterInPass = modulo(
            ALPHABET.indexOf(password[modulo(i, password.length)]),
            ALPHABET.length
        );
        decryptedLetter =
            ALPHABET[modulo(indexLetterInText - indexLetterInPass, ALPHABET.length)];
        decrypted = decrypted.concat(decryptedLetter);
    }
    // return
    return decrypted;
}

// Tests functions, else log it into the console
var message = "Hello World";
var pass = "MyPassword";
if (decrypt(crypt(message, pass), pass) !== message) {
    console.error("Error in Max1Truc's Crypt library !");
}
<commit_msg>Fix #18<commit_after>// Script created by Max1Truc
// Source available on GitHub at https://GitHub.com/Max1Truc/crypt
// It's under the MIT License

function modulo(a, b) {
  return a - (b * Math.floor(a / b))
}

function crypt(message, password) {
  // ALPHABET, changing it changes characters which are encrypted
  const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ";
  // initialize the crypted message var
  var crypted = '';
  // crypt each letter
  for (var i = 0; i < message.length; i++) {
    var indexLetterInText, indexLetterInPass, cryptedLetter;
    indexLetterInText = modulo(ALPHABET.indexOf(message[i]), ALPHABET.length);
    indexLetterInPass = modulo(ALPHABET.indexOf(password[modulo(i, password.length)]), ALPHABET.length);
    cryptedLetter = ALPHABET[modulo(indexLetterInText + indexLetterInPass, ALPHABET.length)];
    crypted = crypted.concat(cryptedLetter);
  }
  // return
  return crypted;
}

function decrypt(cryptedMessage, password) {
  // ALPHABET, changing it changes characters which are encrypted
  const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ";
  // initialize the decrypted message var
  var decrypted = '';
  // decrypt each letter
  for (var i = 0; i < cryptedMessage.length; i++) {
    var indexLetterInText, indexLetterInPass, decryptedLetter;
    indexLetterInText = modulo(ALPHABET.indexOf(cryptedMessage[i]), ALPHABET.length);
    indexLetterInPass = modulo(ALPHABET.indexOf(password[modulo(i, password.length)]), ALPHABET.length);
    decryptedLetter = ALPHABET[modulo(indexLetterInText - indexLetterInPass, ALPHABET.length)];
    decrypted = decrypted.concat(decryptedLetter);
  }
  // return
  return decrypted;
}

// Tests functions, else log it into the console
var message = 'Hello World, this letter does not work with "2" as a password : I';
var pass = 'Password 2';
if (decrypt(crypt(message, pass), pass) !== message) {
  console.error('Error in Max1Truc\'s Crypt library !');
}
<|endoftext|>


<commit_before>/**
  @module ember-flexberry-gis
*/

import Ember from 'ember';
import layout from '../../templates/components/map-commands/edit';
import {
  translationMacro as t
} from 'ember-i18n';

/**
  Component's CSS-classes names.
  JSON-object containing string constants with CSS-classes names related to component's .hbs markup elements.

  @property {Object} flexberryClassNames
  @property {String} flexberryClassNames.prefix Component's CSS-class names prefix ('flexberry-drag-map-tool').
  @property {String} flexberryClassNames.wrapper Component's wrapping
 CSS-class name ('flexberry-drag-map-tool').
  @readonly
  @static

  @for EditMapCommandComponent
*/
const flexberryClassNamesPrefix = 'flexberry-edit-map-command';
const flexberryClassNames = {
  prefix: flexberryClassNamesPrefix,
  wrapper: flexberryClassNamesPrefix,
  editdialog: 'flexberry-edit-dialog-map-command',
};

/**
  Flexberry edit map-command component.
  Component must be used in combination with {{#crossLink "FlexberryMaptoolbarComponent"}}flexberry-maptoolbar component{{/crossLink}}
  as a wrapper.

  Usage:
  templates/my-map-form.hbs
  ```handlebars
  {{#flexberry-maptoolbar leafletMap=leafletMap as |maptoolbar|}}
    {{map-commands/edit execute=(action "onMapCommandExecute" target=maptoolbar)}}
  {{/flexberry-maptoolbar}}
  ```

  @class EditMapCommandComponent
  @extends Ember.Component
  @uses SlotsMixin
*/
let EditMapCommandComponent = Ember.Component.extend({
  /**
    Flag: indicates whether edit dialog has been already requested by user or not.

    @property _editDialogHasBeenRequested
    @type boolean
    @default false
    @private
  */
  _editDialogHasBeenRequested: false,

  /**
    Flag: indicates whether edit dialog is visible or not.

    @property _editDialogIsVisible
    @type boolean
    @default false
    @private
  */
  _editDialogIsVisible: false,

  /**
    Reference to component's template.
  */
  layout,

  /**
    Reference to component's CSS-classes names.
    Must be also a component's instance property to be available from component's .hbs template.
  */
  flexberryClassNames,

  /**
    Overridden ['tagName'](http://emberjs.com/api/classes/Ember.Component.html#property_tagName)
    to disable a component's wrapping element.

    @property tagName
    @type String
    @default ''
  */
  tagName: '',

  /**
    Map command's additional CSS-class.

    @property class
    @type String
    @default null
  */
  class: null,

  /**
    Map command's caption.

    @property caption
    @type String
    @default t('components.map-commands.edit.caption')
  */
  caption: t('components.map-commands.edit.caption'),

  /**
    Map command's tooltip text.
    Will be added as wrapper's element 'title' attribute.

    @property tooltip
    @default t('components.map-commands.edit.tooltip')
  */
  tooltip: t('components.map-commands.edit.tooltip'),

  /**
    Map command's icon CSS-class names.

    @property iconClass
    @type String
    @default 'edit icon'
  */
  iconClass: 'edit icon',

  /**
    Map model

    @property mapModel
    @type Object
    @default null
  */
  mapModel: null,

  actions: {
    /**
      Handles {{#crossLink "BaseMapCommandComponent/sendingActions.execute:method"}}base map-command's 'execute' action{{/crossLink}}.

      @method actions.onEditMapCommandExecute
      @param {Object} e Base map-command's 'execute' action event-object.
    */
    onEditMapCommandExecute(e) {
      this._showEditDialog({ executeActionEventObject: e });
    },

    /**
      Handles edit dialog's 'approve' action.
      Invokes own {{#crossLink "EditMapCommandComponent/sendingActions.execute:method"}}'execute' action{{/crossLink}}.

      @method actions.onEditDialogApprove
      @param {Object} e Action's event object.
    */
    onEditDialogApprove(e) {
      //Set properties from new map model to current map model.

      //this.sendAction('execute', e);
    },
  },

  /**
    Shows edit dialog.

    @method _showEditDialog
    @param {Object} [options] Method options.
    @private
  */
  _showEditDialog(options) {
    options = options || {};

    // Delay execution, but send action to initialize map-command.
    let executeActionEventObject = Ember.get(options, 'executeActionEventObject');
    Ember.set(executeActionEventObject, 'execute', false);
    this.sendAction('execute', executeActionEventObject);

    // Remember event-object to execute command later (when dialog will be approved).
    this.set('_executeActionEventObject', executeActionEventObject);

    // Include dialog to markup.
    this.set('_editDialogHasBeenRequested', true);

    // Show dialog.
    this.set('_editDialogIsVisible', true);
  },

  /**
    Hides edit dialog.

    @method _hideEditDialog
    @private
  */
  _hideEditDialog() {
    // Hide dialog.
    this.set('_editDialogIsVisible', false);
  },

  /**
    Destroys DOM-related component's properties & logic.
  */
  willDestroyElement() {
    this._super(...arguments);

    this._hideEditDialog();
  },

  /**
    Destroys component.
  */
  willDestroy() {
    this._super(...arguments);

    this.set('_executeActionEventObject', null);
  }

  /**
    Component's action invoking when map-command must be executed.

    @method sendingActions.execute
    @param {Object} e Action's event object from
    {{#crossLink "BaseMapCommandComponent/sendingActions.execute:method"}}base map-command's 'execute' action{{/crossLink}}.
  */
});

// Add component's CSS-class names as component's class static constants
// to make them available outside of the component instance.
EditMapCommandComponent.reopenClass({
  flexberryClassNames
});

export default EditMapCommandComponent;
<commit_msg>Map save logic<commit_after>/**
  @module ember-flexberry-gis
*/

import Ember from 'ember';
import layout from '../../templates/components/map-commands/edit';
import {
  translationMacro as t
} from 'ember-i18n';

/**
  Component's CSS-classes names.
  JSON-object containing string constants with CSS-classes names related to component's .hbs markup elements.

  @property {Object} flexberryClassNames
  @property {String} flexberryClassNames.prefix Component's CSS-class names prefix ('flexberry-drag-map-tool').
  @property {String} flexberryClassNames.wrapper Component's wrapping
 CSS-class name ('flexberry-drag-map-tool').
  @readonly
  @static

  @for EditMapCommandComponent
*/
const flexberryClassNamesPrefix = 'flexberry-edit-map-command';
const flexberryClassNames = {
  prefix: flexberryClassNamesPrefix,
  wrapper: flexberryClassNamesPrefix,
  editdialog: 'flexberry-edit-dialog-map-command',
};

/**
  Flexberry edit map-command component.
  Component must be used in combination with {{#crossLink "FlexberryMaptoolbarComponent"}}flexberry-maptoolbar component{{/crossLink}}
  as a wrapper.

  Usage:
  templates/my-map-form.hbs
  ```handlebars
  {{#flexberry-maptoolbar leafletMap=leafletMap as |maptoolbar|}}
    {{map-commands/edit execute=(action "onMapCommandExecute" target=maptoolbar)}}
  {{/flexberry-maptoolbar}}
  ```

  @class EditMapCommandComponent
  @extends Ember.Component
  @uses SlotsMixin
*/
let EditMapCommandComponent = Ember.Component.extend({
  /**
    Flag: indicates whether edit dialog has been already requested by user or not.

    @property _editDialogHasBeenRequested
    @type boolean
    @default false
    @private
  */
  _editDialogHasBeenRequested: false,

  /**
    Flag: indicates whether edit dialog is visible or not.

    @property _editDialogIsVisible
    @type boolean
    @default false
    @private
  */
  _editDialogIsVisible: false,

  /**
    Reference to component's template.
  */
  layout,

  /**
    Reference to component's CSS-classes names.
    Must be also a component's instance property to be available from component's .hbs template.
  */
  flexberryClassNames,

  /**
    Overridden ['tagName'](http://emberjs.com/api/classes/Ember.Component.html#property_tagName)
    to disable a component's wrapping element.

    @property tagName
    @type String
    @default ''
  */
  tagName: '',

  /**
    Map command's additional CSS-class.

    @property class
    @type String
    @default null
  */
  class: null,

  /**
    Map command's caption.

    @property caption
    @type String
    @default t('components.map-commands.edit.caption')
  */
  caption: t('components.map-commands.edit.caption'),

  /**
    Map command's tooltip text.
    Will be added as wrapper's element 'title' attribute.

    @property tooltip
    @default t('components.map-commands.edit.tooltip')
  */
  tooltip: t('components.map-commands.edit.tooltip'),

  /**
    Map command's icon CSS-class names.

    @property iconClass
    @type String
    @default 'edit icon'
  */
  iconClass: 'edit icon',

  /**
    Map model

    @property mapModel
    @type Object
    @default null
  */
  mapModel: null,

  actions: {
    /**
      Handles {{#crossLink "BaseMapCommandComponent/sendingActions.execute:method"}}base map-command's 'execute' action{{/crossLink}}.

      @method actions.onEditMapCommandExecute
      @param {Object} e Base map-command's 'execute' action event-object.
    */
    onEditMapCommandExecute(e) {
      this._showEditDialog({ executeActionEventObject: e });
    },

    /**
      Handles edit dialog's 'approve' action.
      Invokes own {{#crossLink "EditMapCommandComponent/sendingActions.execute:method"}}'execute' action{{/crossLink}}.

      @method actions.onEditDialogApprove
      @param {Object} e Action's event object.
    */
    onEditDialogApprove(e) {
      //Set properties from new map model to current map model.
      let mapModel = e.mapProperties;
      let model = this.get('mapModel');

      model.set('name', mapModel.name);
      model.set('lat', mapModel.lat);
      model.set('lng', mapModel.lng);
      model.set('zoom', mapModel.zoom);
      model.set('public', mapModel.public);
      model.set('description', mapModel.description);
      model.save();
      //this.sendAction('execute', e);
    },
  },

  /**
    Shows edit dialog.

    @method _showEditDialog
    @param {Object} [options] Method options.
    @private
  */
  _showEditDialog(options) {
    options = options || {};

    // Delay execution, but send action to initialize map-command.
    let executeActionEventObject = Ember.get(options, 'executeActionEventObject');
    Ember.set(executeActionEventObject, 'execute', false);
    this.sendAction('execute', executeActionEventObject);

    // Remember event-object to execute command later (when dialog will be approved).
    this.set('_executeActionEventObject', executeActionEventObject);

    // Include dialog to markup.
    this.set('_editDialogHasBeenRequested', true);

    // Show dialog.
    this.set('_editDialogIsVisible', true);
  },

  /**
    Hides edit dialog.

    @method _hideEditDialog
    @private
  */
  _hideEditDialog() {
    // Hide dialog.
    this.set('_editDialogIsVisible', false);
  },

  /**
    Destroys DOM-related component's properties & logic.
  */
  willDestroyElement() {
    this._super(...arguments);

    this._hideEditDialog();
  },

  /**
    Destroys component.
  */
  willDestroy() {
    this._super(...arguments);

    this.set('_executeActionEventObject', null);
  }

  /**
    Component's action invoking when map-command must be executed.

    @method sendingActions.execute
    @param {Object} e Action's event object from
    {{#crossLink "BaseMapCommandComponent/sendingActions.execute:method"}}base map-command's 'execute' action{{/crossLink}}.
  */
});

// Add component's CSS-class names as component's class static constants
// to make them available outside of the component instance.
EditMapCommandComponent.reopenClass({
  flexberryClassNames
});

export default EditMapCommandComponent;
<|endoftext|>


<commit_before>import Ember from 'ember';
import layout from '../templates/components/tooltip-on-parent';

const { computed, warn, run } = Ember;

export default Ember.Component.extend({
  attributeBindings: ['style'],
  layout,

  style: computed(function() {
    return Ember.String.htmlSafe('display:none;');
  }),

  init(...args) {
    this._super(args);

    run.schedule('afterRender', () => {
      const parentView = this.get('parentView');

      if (parentView.renderTooltip) {
        parentView.renderTooltip(this);
      } else {
        warn('No renderTooltip method found on the parent view of the {{tooltip-on-parent}} component');
      }

      this.remove();
    });
  },

});
<commit_msg>explicit option for rendering<commit_after>import Ember from 'ember';
import layout from '../templates/components/tooltip-on-parent';

const { computed, warn, run, get } = Ember;

export default Ember.Component.extend({
  attributeBindings: ['style'],
  layout,

  style: computed(function() {
    return Ember.String.htmlSafe('display:none;');
  }),

  init(...args) {
    this._super(args);

    run.schedule('afterRender', () => {
      const parentView = this.get('parentView');

      if (parentView.renderTooltip) {
        const target = get(this, 'tooltipTarget') ? get(this, 'tooltipTarget') : this;
        parentView.renderTooltip(target);
      } else {
        warn('No renderTooltip method found on the parent view of the {{tooltip-on-parent}} component');
      }

      this.remove();
    });
  },

});
<|endoftext|>


<commit_before>import Ember from 'ember';

var DO_NOT_SET = Object.create(null);

/**
 * Handles updating a property given the name of the source property using a delayed method from
 * `Ember.run` (`throttle`, `debounce`, `later`).
 *
 * @mixin WithDelayedPropertyMixin
 */
var WithDelayedPropertyMixin = Ember.Mixin.create({
  /**
   * The name of the property to use as source value
   * @property delayedPropertyName
   * @type String
   */
  delayedPropertyName:        Ember.required(),
  /**
   * The name of the property to use as destination (computed value from source using the
   * `delayedPropertyFunction` will be set to this property)
   * @property delayedPropertyDestination
   * @type String
   */
  delayedPropertyDestination: Ember.required(),
  /**
   * The delay to use with the `Ember.run.*` method
   * @property delayedPropertyDelay
   * @type Number
   */
  delayedPropertyDelay:       500,
  /**
   * The method to delay the computed value of destination (`throttle`, `debounce`, `later`)
   * @property delayedPropertyMethod
   * @type String
   */
  delayedPropertyMethod:      'throttle',
  /**
   * The value to be used when computing the value of the destination fails.
   * Using `WithDelayedPropertyMixin.DO_NOT_SET` will result in not setting the destination property
   * @property delayedPropertyErrorValue
   * @type *
   */
  delayedPropertyErrorValue:  DO_NOT_SET,
  /**
   * The function used to computed the value of the destination. It can directly return the computed
   * value, or return a promise which would resolve in that computed value
   * @property delayedPropertyFunction
   * @type Function
   */
  delayedPropertyFunction:    function (value) {
    return value;
  },

  /**
   * The main function, used to update the destination property using the source property
   *
   * @method updateDelayedPropertyValue
   */
  updateDelayedPropertyValue: function () {
    var value, self = this;
    var sourceValue = this.get(this.get('delayedPropertyName'));
    if (this.isDestroyed || this.isDestroying) {
      return;
    }
    if (this._delayedPropertyPromise) {
      this._scheduleDelayedPropertyUpdate();
    }
    else {
      try {
        value = this.delayedPropertyFunction(sourceValue);
      }
      catch (error) {
        Ember.warn('[ember-marked] ' + error);
        this._setDelayedPropertyValue(this.get('delayedPropertyErrorValue'));
        return;
      }
      if (value && typeof value.then === 'function') {
        this._delayedPropertyPromise = value;
        value
          .then(function updateValueSuccess(value) {
            self._delayedPropertyPromise = null;
            self._setDelayedPropertyValue(value);
          })
          /* jshint -W024 */
          .catch(function updateValueError(error) {
            Ember.warn('[ember-marked] ' + error);
            self._delayedPropertyPromise = null;
            self._setDelayedPropertyValue(self.get('delayedPropertyErrorValue'));
          });
      }
      else {
        this._setDelayedPropertyValue(value);
      }
    }
  },

  /**
   * Setup our mixin, listening for the source property changes
   *
   * @method _setupWithDelayedPropertyMixin
   * @private
   */
  _setupWithDelayedPropertyMixin: Ember.on('init', Ember.observer('delayedPropertyName',
    function () {
      var prop = this.get('delayedPropertyName');
      if (prop) {
        this.addObserver(prop, this, '_scheduleDelayedPropertyUpdate');
      }
    }
  )),

  /**
   * Teardown our mixin, removing the listeners for the source property changes
   *
   * @method _teardownWithDelayedPropertyMixin
   * @private
   */
  _teardownWithDelayedPropertyMixin: Ember.on('destroy', Ember.beforeObserver('delayedPropertyName',
    function () {
      var prop = this.get('delayedPropertyName');
      if (prop) {
        this.removeObserver(prop, this, '_scheduleDelayedPropertyUpdate');
      }
    }
  )),

  /**
   * Save the promise used to resolve the property value, so that we don't run it many times
   * @property _delayedPropertyPromise
   * @type Ember.RSVP.Promise
   * @private
   */
  _delayedPropertyPromise: null,

  /**
   * Sets the value of the destination
   *
   * @method _setDelayedPropertyValue
   * @param {*} value
   * @private
   */
  _setDelayedPropertyValue: function (value) {
    var name, srcName;
    if (this.isDestroyed || this.isDestroying) {
      return;
    }
    name = this.get('delayedPropertyDestination');
    srcName = this.get('delayedPropertyName');
    if (!name) {
      return;
    }
    if (name === srcName) {
      // if the destination is the same as the source, stop listening while updating
      this._teardownWithDelayedPropertyMixin();
      this.set(name, value);
      this._setupWithDelayedPropertyMixin();
    }
    else {
      this.set(name, value);
    }
  },

  /**
   * Schedule the update of our destination property
   *
   * @method _scheduleDelayedPropertyUpdate
   * @private
   */
  _scheduleDelayedPropertyUpdate: Ember.on('init', function () {
    var value = this.get(this.get('delayedPropertyName'));
    Ember.run[this.get('delayedPropertyMethod')](
      this, 'updateDelayedPropertyValue', value, this.get('delayedPropertyDelay')
    );
  })
});

/**
 * Value to use when you do not want to update the destination value if there was an error
 * @property DO_NOT_SET
 * @type Object
 */
WithDelayedPropertyMixin.DO_NOT_SET = DO_NOT_SET;

export default WithDelayedPropertyMixin;
<commit_msg>Fix an issue when the delayed property name isnt set yet<commit_after>import Ember from 'ember';

var DO_NOT_SET = Object.create(null);

/**
 * Handles updating a property given the name of the source property using a delayed method from
 * `Ember.run` (`throttle`, `debounce`, `later`).
 *
 * @mixin WithDelayedPropertyMixin
 */
var WithDelayedPropertyMixin = Ember.Mixin.create({
  /**
   * The name of the property to use as source value
   * @property delayedPropertyName
   * @type String
   */
  delayedPropertyName:        Ember.required(),
  /**
   * The name of the property to use as destination (computed value from source using the
   * `delayedPropertyFunction` will be set to this property)
   * @property delayedPropertyDestination
   * @type String
   */
  delayedPropertyDestination: Ember.required(),
  /**
   * The delay to use with the `Ember.run.*` method
   * @property delayedPropertyDelay
   * @type Number
   */
  delayedPropertyDelay:       500,
  /**
   * The method to delay the computed value of destination (`throttle`, `debounce`, `later`)
   * @property delayedPropertyMethod
   * @type String
   */
  delayedPropertyMethod:      'throttle',
  /**
   * The value to be used when computing the value of the destination fails.
   * Using `WithDelayedPropertyMixin.DO_NOT_SET` will result in not setting the destination property
   * @property delayedPropertyErrorValue
   * @type *
   */
  delayedPropertyErrorValue:  DO_NOT_SET,
  /**
   * The function used to computed the value of the destination. It can directly return the computed
   * value, or return a promise which would resolve in that computed value
   * @property delayedPropertyFunction
   * @type Function
   */
  delayedPropertyFunction:    function (value) {
    return value;
  },

  /**
   * The main function, used to update the destination property using the source property
   *
   * @method updateDelayedPropertyValue
   */
  updateDelayedPropertyValue: function () {
    var value, self = this, sourceValue;
    if (this.isDestroyed || this.isDestroying) {
      return;
    }
    // added `__dummy__` in case there is no delayed property set, to avoid errors
    sourceValue = this.get(this.get('delayedPropertyName') || '__dummy__');
    if (this._delayedPropertyPromise) {
      this._scheduleDelayedPropertyUpdate();
    }
    else {
      try {
        value = this.delayedPropertyFunction(sourceValue);
      }
      catch (error) {
        Ember.warn('[ember-marked] ' + error);
        this._setDelayedPropertyValue(this.get('delayedPropertyErrorValue'));
        return;
      }
      if (value && typeof value.then === 'function') {
        this._delayedPropertyPromise = value;
        value
          .then(function updateValueSuccess(value) {
            self._delayedPropertyPromise = null;
            self._setDelayedPropertyValue(value);
          })
          /* jshint -W024 */
          .catch(function updateValueError(error) {
            Ember.warn('[ember-marked] ' + error);
            self._delayedPropertyPromise = null;
            self._setDelayedPropertyValue(self.get('delayedPropertyErrorValue'));
          });
      }
      else {
        this._setDelayedPropertyValue(value);
      }
    }
  },

  /**
   * Setup our mixin, listening for the source property changes
   *
   * @method _setupWithDelayedPropertyMixin
   * @private
   */
  _setupWithDelayedPropertyMixin: Ember.on('init', Ember.observer('delayedPropertyName',
    function () {
      var prop = this.get('delayedPropertyName');
      if (prop) {
        this.addObserver(prop, this, '_scheduleDelayedPropertyUpdate');
      }
    }
  )),

  /**
   * Teardown our mixin, removing the listeners for the source property changes
   *
   * @method _teardownWithDelayedPropertyMixin
   * @private
   */
  _teardownWithDelayedPropertyMixin: Ember.on('destroy', Ember.beforeObserver('delayedPropertyName',
    function () {
      var prop = this.get('delayedPropertyName');
      if (prop) {
        this.removeObserver(prop, this, '_scheduleDelayedPropertyUpdate');
      }
    }
  )),

  /**
   * Save the promise used to resolve the property value, so that we don't run it many times
   * @property _delayedPropertyPromise
   * @type Ember.RSVP.Promise
   * @private
   */
  _delayedPropertyPromise: null,

  /**
   * Sets the value of the destination
   *
   * @method _setDelayedPropertyValue
   * @param {*} value
   * @private
   */
  _setDelayedPropertyValue: function (value) {
    var name, srcName;
    if (this.isDestroyed || this.isDestroying) {
      return;
    }
    name = this.get('delayedPropertyDestination');
    srcName = this.get('delayedPropertyName');
    if (!name) {
      return;
    }
    if (name === srcName) {
      // if the destination is the same as the source, stop listening while updating
      this._teardownWithDelayedPropertyMixin();
      this.set(name, value);
      this._setupWithDelayedPropertyMixin();
    }
    else {
      this.set(name, value);
    }
  },

  /**
   * Schedule the update of our destination property
   *
   * @method _scheduleDelayedPropertyUpdate
   * @private
   */
  _scheduleDelayedPropertyUpdate: Ember.on('init', function () {
    var value = this.get(this.get('delayedPropertyName') || '__dummy__');
    Ember.run[this.get('delayedPropertyMethod')](
      this, 'updateDelayedPropertyValue', value, this.get('delayedPropertyDelay')
    );
  })
});

/**
 * Value to use when you do not want to update the destination value if there was an error
 * @property DO_NOT_SET
 * @type Object
 */
WithDelayedPropertyMixin.DO_NOT_SET = DO_NOT_SET;

export default WithDelayedPropertyMixin;
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule renderApplication
 */

'use strict';

var Inspector = require('Inspector');
var Portal = require('Portal');
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
var React = require('React');
var StyleSheet = require('StyleSheet');
var Subscribable = require('Subscribable');
var View = require('View');

var invariant = require('invariant');

var YellowBox = __DEV__ ? require('YellowBox') : null;

// require BackAndroid so it sets the default handler that exits the app if no listeners respond
require('BackAndroid');

var AppContainer = React.createClass({
  mixins: [Subscribable.Mixin],

  getInitialState: function() {
    return {
      enabled: __DEV__,
      inspectorVisible: false,
      rootNodeHandle: null,
      rootImportanceForAccessibility: 'auto',
    };
  },

  toggleElementInspector: function() {
    this.setState({
      inspectorVisible: !this.state.inspectorVisible,
      rootNodeHandle: React.findNodeHandle(this.refs.main),
    });
  },

  componentDidMount: function() {
    this.addListenerOn(
      RCTDeviceEventEmitter,
      'toggleElementInspector',
      this.toggleElementInspector
    );

    this._unmounted = false;
  },

  renderInspector: function() {
    return this.state.inspectorVisible ?
      <Inspector
        rootTag={this.props.rootTag}
        inspectedViewTag={this.state.rootNodeHandle}
      /> :
      null;
  },

  componentWillUnmount: function() {
    this._unmounted = true;
  },

  setRootAccessibility: function(modalVisible) {
    if (this._unmounted) {
      return;
    }

    this.refs.accessibilityWrapper.setNativeProps({
      importantForAccessibility: modalVisible ? 'no-hide-descendants' : 'auto',
    });
  },

  render: function() {
    var RootComponent = this.props.rootComponent;
    var appView =
      <View
        ref="main"
        collapsable={!this.state.inspectorVisible}
        style={styles.appContainer}>
        <View
          ref="accessibilityWrapper"
          collapsable={true}
          style={styles.appContainer}>
          <RootComponent
            {...this.props.initialProps}
            rootTag={this.props.rootTag}/>
        </View>
        <Portal
          onModalVisibilityChanged={this.setRootAccessibility}/>
      </View>;
    let yellowBox = null;
    if (__DEV__) {
      yellowBox = <YellowBox />;
    }
    return this.state.enabled ?
      <View style={styles.appContainer}>
        {appView}
        {yellowBox}
        {this.renderInspector()}
      </View> :
      appView;
  }
});

function renderApplication<D, P, S>(
  RootComponent: ReactClass<D, P, S>,
  initialProps: P,
  rootTag: any
) {
  invariant(
    rootTag,
    'Expect to have a valid rootTag, instead got ', rootTag
  );
  React.render(
    <AppContainer
      rootComponent={RootComponent}
      initialProps={initialProps}
      rootTag={rootTag} />,
    rootTag
  );
}

var styles = StyleSheet.create({
  // This is needed so the application covers the whole screen
  // and therefore the contents of the Portal are not clipped.
  appContainer: {
    position: 'absolute',
    left: 0,
    top: 0,
    right: 0,
    bottom: 0,
  },
});

module.exports = renderApplication;
<commit_msg>revert D2928371 to unbreak drawer.<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule renderApplication
 */

'use strict';

var Inspector = require('Inspector');
var Portal = require('Portal');
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
var React = require('React');
var StyleSheet = require('StyleSheet');
var Subscribable = require('Subscribable');
var View = require('View');

var invariant = require('invariant');

var YellowBox = __DEV__ ? require('YellowBox') : null;

// require BackAndroid so it sets the default handler that exits the app if no listeners respond
require('BackAndroid');

var AppContainer = React.createClass({
  mixins: [Subscribable.Mixin],

  getInitialState: function() {
    return {
      enabled: __DEV__,
      inspectorVisible: false,
      rootNodeHandle: null,
      rootImportanceForAccessibility: 'auto',
    };
  },

  toggleElementInspector: function() {
    this.setState({
      inspectorVisible: !this.state.inspectorVisible,
      rootNodeHandle: React.findNodeHandle(this.refs.main),
    });
  },

  componentDidMount: function() {
    this.addListenerOn(
      RCTDeviceEventEmitter,
      'toggleElementInspector',
      this.toggleElementInspector
    );

    this._unmounted = false;
  },

  renderInspector: function() {
    return this.state.inspectorVisible ?
      <Inspector
        rootTag={this.props.rootTag}
        inspectedViewTag={this.state.rootNodeHandle}
      /> :
      null;
  },

  componentWillUnmount: function() {
    this._unmounted = true;
  },

  setRootAccessibility: function(modalVisible) {
    if (this._unmounted) {
      return;
    }

    this.setState({
      rootImportanceForAccessibility: modalVisible ? 'no-hide-descendants' : 'auto',
    });
  },

  render: function() {
    var RootComponent = this.props.rootComponent;
    var appView =
      <View
        ref="main"
        collapsable={!this.state.inspectorVisible}
        style={styles.appContainer}>
        <RootComponent
          {...this.props.initialProps}
          rootTag={this.props.rootTag}
          importantForAccessibility={this.state.rootImportanceForAccessibility}/>
        <Portal
          onModalVisibilityChanged={this.setRootAccessibility}/>
      </View>;
    let yellowBox = null;
    if (__DEV__) {
      yellowBox = <YellowBox />;
    }
    return this.state.enabled ?
      <View style={styles.appContainer}>
        {appView}
        {yellowBox}
        {this.renderInspector()}
      </View> :
      appView;
  }
});

function renderApplication<D, P, S>(
  RootComponent: ReactClass<D, P, S>,
  initialProps: P,
  rootTag: any
) {
  invariant(
    rootTag,
    'Expect to have a valid rootTag, instead got ', rootTag
  );
  React.render(
    <AppContainer
      rootComponent={RootComponent}
      initialProps={initialProps}
      rootTag={rootTag} />,
    rootTag
  );
}

var styles = StyleSheet.create({
  // This is needed so the application covers the whole screen
  // and therefore the contents of the Portal are not clipped.
  appContainer: {
    position: 'absolute',
    left: 0,
    top: 0,
    right: 0,
    bottom: 0,
  },
});

module.exports = renderApplication;
<|endoftext|>


<commit_before>var distribution = {};
// Each distribution needs a pdf, cdf and icdf

/*
Usage:
    var foo = new distribution.Normal(0,1);
    var bar = foo.sample();
*/
// Uniform Distribution
distribution.Uniform = function(a,b){
  this.pdf = function(x){
    var pd = (x>=a && x<=b) ? 1/(b-a) : 0;
    return pd;
  };
  this.cdf = function(x){
    if(x<a){
      return 0;
    }
    else if(x>b){
      return 1;
    }
    else{
      return (x-a) / (b-a);
    }
  };
  this.icdf = function(p){
    var id= (p>=0 && p<=1) ? a+(p*(b-a)) : NaN;
    return id;
  };
};

// Normal Distribution
distribution.Normal = function(mu,sigma){
  this.mu = !mu ? 0 : mu;
  this.sigma = !sigma ? 1 : sigma;
  this.pdf = function(x){
    var exponential = Math.exp(-1 * Math.pow(x-this.mu,2) / (2 * Math.pow(this.sigma,2) ) );
    return (1/ (this.sigma * Math.sqrt(2*Math.PI)) ) * exponential;
  };
  this.cdf = function(x){
  // Approximation from West (2009) Better Approximations to Cumulative Normal Functions
    var cd,
        z = (x - this.mu) / this.sigma,
        Z = Math.abs(z);
    if(Z>37){
      cd = 0;
    }
    else{
      var sum,
          exponential = Math.exp( -1*(Z*Z) / 2);
      if(Z<7.07106781186547){
        sum = 3.52624965998911e-02*Z + 0.700383064443688;
        sum = sum*Z + 6.37396220353165;
        sum = sum*Z + 33.912866078383;
        sum = sum*Z + 112.079291497871;
        sum = sum*Z + 221.213596169931;
        sum = sum*Z + 220.206867912376;
        cd = exponential * sum;
        sum = 8.83883476483184e-02*Z + 1.75566716318264;
        sum = sum*Z + 16.064177579207;
        sum = sum*Z + 86.7807322029461;
        sum = sum*Z + 296.564248779674;
        sum = sum*Z + 637.333633378831;
        sum = sum*Z + 793.826512519948;
        sum = sum*Z + 440.413735824752;
        cd = cd / sum;
      }
      else{
        sum = Z + 0.65;
        sum = Z + 4 / sum;
        sum = Z + 3 / sum;
        sum = Z + 2 / sum;
        sum = Z + 1 / sum;
        cd = exponential / sum / 2.506628274631;
      }
    }
    if(z>0)
      return 1-cd;
    else
      return cd;
  };
  this.icdf = function(p){
  // Approximation of Probit function using inverse error function.
    if(p<=0 || p>=1){
      return NaN;
    }
    else{
      var ierf = function(x){
        var a = (8*(Math.PI - 3))/(3 * Math.PI * (4-Math.PI)),
            parta = ( 2 / (Math.PI*a) ) + (Math.log(1-Math.pow(x,2))/2),
            partb = Math.log(1 - (x*x))/a;
        return Math.sign(x)*Math.sqrt( Math.sqrt( (parta*parta) - partb) - parta);
      };
      return this.mu + this.sigma*Math.sqrt(2)*ierf(2*p - 1);
    }
  };
};

module.exports = distribution;
<commit_msg>Remove reliance on new spec<commit_after>var distribution = {};
// Each distribution needs a pdf, cdf and icdf

/*
Usage:
    var foo = new distribution.Normal(0,1);
    var bar = foo.sample();
*/
// Uniform Distribution
distribution.Uniform = function(a,b){
  this.pdf = function(x){
    var pd = (x>=a && x<=b) ? 1/(b-a) : 0;
    return pd;
  };
  this.cdf = function(x){
    if(x<a){
      return 0;
    }
    else if(x>b){
      return 1;
    }
    else{
      return (x-a) / (b-a);
    }
  };
  this.icdf = function(p){
    var id= (p>=0 && p<=1) ? a+(p*(b-a)) : NaN;
    return id;
  };
};

// Normal Distribution
distribution.Normal = function(mu,sigma){
  this.mu = !mu ? 0 : mu;
  this.sigma = !sigma ? 1 : sigma;
  this.pdf = function(x){
    var exponential = Math.exp(-1 * Math.pow(x-this.mu,2) / (2 * Math.pow(this.sigma,2) ) );
    return (1/ (this.sigma * Math.sqrt(2*Math.PI)) ) * exponential;
  };
  this.cdf = function(x){
  // Approximation from West (2009) Better Approximations to Cumulative Normal Functions
    var cd,
        z = (x - this.mu) / this.sigma,
        Z = Math.abs(z);
    if(Z>37){
      cd = 0;
    }
    else{
      var sum,
          exponential = Math.exp( -1*(Z*Z) / 2);
      if(Z<7.07106781186547){
        sum = 3.52624965998911e-02*Z + 0.700383064443688;
        sum = sum*Z + 6.37396220353165;
        sum = sum*Z + 33.912866078383;
        sum = sum*Z + 112.079291497871;
        sum = sum*Z + 221.213596169931;
        sum = sum*Z + 220.206867912376;
        cd = exponential * sum;
        sum = 8.83883476483184e-02*Z + 1.75566716318264;
        sum = sum*Z + 16.064177579207;
        sum = sum*Z + 86.7807322029461;
        sum = sum*Z + 296.564248779674;
        sum = sum*Z + 637.333633378831;
        sum = sum*Z + 793.826512519948;
        sum = sum*Z + 440.413735824752;
        cd = cd / sum;
      }
      else{
        sum = Z + 0.65;
        sum = Z + 4 / sum;
        sum = Z + 3 / sum;
        sum = Z + 2 / sum;
        sum = Z + 1 / sum;
        cd = exponential / sum / 2.506628274631;
      }
    }
    if(z>0)
      return 1-cd;
    else
      return cd;
  };
  this.icdf = function(p){
  // Approximation of Probit function using inverse error function.
    if(p<=0 || p>=1){
      return NaN;
    }
    else{
      var ierf = function(x){
        var a = (8*(Math.PI - 3))/(3 * Math.PI * (4-Math.PI)),
            parta = ( 2 / (Math.PI*a) ) + (Math.log(1-Math.pow(x,2))/2),
            partb = Math.log(1 - (x*x))/a,
            signx = (x>0) ? 1 : -1;
        return signx*Math.sqrt( Math.sqrt( (parta*parta) - partb) - parta);
      };
      return this.mu + this.sigma*Math.sqrt(2)*ierf(2*p - 1);
    }
  };
};

module.exports = distribution;
<|endoftext|>


<commit_before>import url from 'url';

// assets.preview will be:
// - undefined
// - string e.g. 'static/preview.9adbb5ef965106be1cc3.bundle.js'
// - array of strings e.g.
// [ 'static/preview.9adbb5ef965106be1cc3.bundle.js',
//   'preview.0d2d3d845f78399fd6d5e859daa152a9.css',
//   'static/preview.9adbb5ef965106be1cc3.bundle.js.map',
//   'preview.0d2d3d845f78399fd6d5e859daa152a9.css.map' ]
const previewUrlsFromAssets = assets => {
  if (!assets) {
    return {
      js: 'static/preview.bundle.js',
    };
  }

  if (typeof assets.preview === 'string') {
    return {
      js: assets.preview,
    };
  }

  return {
    js: assets.preview.find(filename => filename.match(/\.js$/)),
    css: assets.preview.find(filename => filename.match(/\.css$/)),
  };
};

export default function(data) {
  const { assets, headHtml, publicPath } = data;

  const previewUrls = previewUrlsFromAssets(assets);

  let previewCssTag = '';
  if (previewUrls.css) {
    previewCssTag = `<link rel='stylesheet' type='text/css' href='${url.resolve(publicPath, previewUrls.css)}'>`;
  }

  return `
    <!DOCTYPE html>

        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Storybook</title>
        ${headHtml}
        ${previewCssTag}

  `;
}
<commit_msg>Add support for multiple webpack chunks in iframe<commit_after>import url from 'url';

// assets.preview will be:
// - undefined
// - string e.g. 'static/preview.9adbb5ef965106be1cc3.bundle.js'
// - array of strings e.g.
// [ 'static/preview.9adbb5ef965106be1cc3.bundle.js',
//   'preview.0d2d3d845f78399fd6d5e859daa152a9.css',
//   'static/preview.9adbb5ef965106be1cc3.bundle.js.map',
//   'preview.0d2d3d845f78399fd6d5e859daa152a9.css.map' ]
const previewUrlsFromAssets = assets => {
  if (!assets) {
    return {
      js: ['static/preview.bundle.js'],
      css: [],
    };
  }

  const urls = {
    js: [],
    css: [],
  };

  const re = /.+\.(\w+)$/;
  Object.keys(assets)
    // Don't load the manager script in the iframe
    .filter(key => key !== 'manager')
    .forEach(key => {
      const asset = assets[key];
      if (typeof asset === 'string') {
        urls[re.exec(asset)[1]].push(asset);
      } else {
        const assetUrl = asset.find(u => re.exec(u)[1] !== 'map');
        urls[re.exec(assetUrl)[1]].push(assetUrl);
      }
    });

  return urls;
};

export default function(data) {
  const { assets, headHtml, publicPath } = data;

  const urls = urlsFromAssets(assets);

  const cssTags = urls.css
    .map(u => `<link rel='stylesheet' type='text/css' href='${url.resolve(publicPath, u)}'>`)
    .join('\n');
  const scriptTags = urls.js
    .map(u => `<script src="${url.resolve(publicPath, u)}"></script>`)
    .join('\n');

  return `
    <!DOCTYPE html>

        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Storybook</title>
        ${headHtml}
        ${cssTags}

        ${scriptTags}

  `;
}
<|endoftext|>


<commit_before>const handleOutbreak = require('./handleOutbreak')
const shuffle = require('./shuffle')
const increaseInfectionRate = require('./increaseInfectionRate')

module.exports = function(refs) {
  const { player, playerRef, roomRef } = refs

  return playerRef.child('hand').once('value').then(snapshot => {
    const hand = snapshot.val()

    for (const card in hand) {
      if (hand[card].hasOwnProperty('Epidemic')) {
        console.log('coping with an epidemic!')
        const fetchCities = roomRef.child('cities').once('value').then(snapshot => snapshot.val())
        const fetchInfectionDeck = roomRef.child('infectionDeck').once('value').then(snapshot => snapshot.val())
        const fetchInfectionDiscard = roomRef.child('infectionDiscard').once('value').then(snapshot => snapshot.val())
        const completeIncrease = increaseInfectionRate(roomRef)

        return Promise.all([fetchCities, fetchInfectionDeck, fetchInfectionDiscard, completeIncrease])
        .then(data => {
          const cities = data[0]
          const infectionDeck = data[1]
          let infectionDiscard = data[2]
          const updatedDecks = {}

          // step 2: infect -- draw the bottom card from the infection deck & add to discard
          // TO-DO: UNLESS IT'S BEEN ERADICATED
          const outbreakCard = infectionDeck.shift()
          if (!infectionDiscard) {
            infectionDiscard = [outbreakCard]
          } else {
            infectionDiscard.push(outbreakCard)
          }

          // step 2.5: check infection rate & handle the outbreak there (if necessary)
          const outbreakSite = outbreakCard.split(' ').join('-')
          const { updatedData, nOutbreaks } = handleOutbreak(outbreakSite, cities)
          console.log('the epidemic affected')
          console.log(updatedData)

          // step 3: intensify -- reshuffle infection discard and add it to pile
          const newInfectionDeck = infectionDeck.concat(shuffle(infectionDiscard))
          updatedDecks['/infectionDeck'] = newInfectionDeck
          updatedDecks['/infectionDiscard'] = []
          updatedDecks['/epidemicMessage'] = 'There was an epidemic in ' + outbreakCard
          console.log('epidemicMessage: There was an epidemic in ' + outbreakCard)
          const all = Object.assign({}, updatedDecks, updatedData)
          console.log('data to update...')
          console.log(all)
          return roomRef.update(all)
        })
      }
    }
    // necessary for Firebase speed
    return undefined
  })
}
<commit_msg>fix: epidemic cards not staying in hand<commit_after>const handleOutbreak = require('./handleOutbreak')
const shuffle = require('./shuffle')
const increaseInfectionRate = require('./increaseInfectionRate')

module.exports = function(refs) {
  const { player, playerRef, roomRef } = refs

  return playerRef.child('hand').once('value').then(snapshot => {
    const hand = snapshot.val()

    for (const card in hand) {
      if (hand[card].hasOwnProperty('Epidemic')) {
        console.log('coping with an epidemic!')
        console.log('deleting the card')
        delete hand[card]
        const fetchCities = roomRef.child('cities').once('value').then(snapshot => snapshot.val())
        const fetchInfectionDeck = roomRef.child('infectionDeck').once('value').then(snapshot => snapshot.val())
        const fetchInfectionDiscard = roomRef.child('infectionDiscard').once('value').then(snapshot => snapshot.val())
        const completeIncrease = increaseInfectionRate(roomRef)

        return Promise.all([fetchCities, fetchInfectionDeck, fetchInfectionDiscard, completeIncrease])
        .then(data => {
          const cities = data[0]
          const infectionDeck = data[1]
          let infectionDiscard = data[2]
          const updatedDecks = {}

          // step 2: infect -- draw the bottom card from the infection deck & add to discard
          // TO-DO: UNLESS IT'S BEEN ERADICATED
          const outbreakCard = infectionDeck.shift()
          if (!infectionDiscard) {
            infectionDiscard = [outbreakCard]
          } else {
            infectionDiscard.push(outbreakCard)
          }

          // step 2.5: check infection rate & handle the outbreak there (if necessary)
          const outbreakSite = outbreakCard.split(' ').join('-')
          const { updatedData, nOutbreaks } = handleOutbreak(outbreakSite, cities)
          console.log('the epidemic affected')
          console.log(updatedData)

          // step 3: intensify -- reshuffle infection discard and add it to pile
          const newInfectionDeck = infectionDeck.concat(shuffle(infectionDiscard))
          updatedDecks[`/players/${player}/hand`] = hand
          updatedDecks['/infectionDeck'] = newInfectionDeck
          updatedDecks['/infectionDiscard'] = []
          updatedDecks['/epidemicMessage'] = 'There was an epidemic in ' + outbreakCard
          console.log('epidemicMessage: There was an epidemic in ' + outbreakCard)
          const all = Object.assign({}, updatedDecks, updatedData)
          console.log('data to update...')
          console.log(all)
          return roomRef.update(all)
        })
      }
    }
    // necessary for Firebase speed
    return undefined
  })
}
<|endoftext|>


<commit_before>(function() {

  var MENU_TIMEOUT = 10000;

  // Hijack score.
  var oldCInterface = window.CInterface;
  window.CInterface = function() {
    oldCInterface.call(this);

    var oldRefScore = this.refreshScore;
    this.refreshScore = function(x) {
      oldRefScore.call(this, x);
      window.muniverse.score = function() {
        return Promise.resolve(x);
      };
    }
  }

  // Needed to skip the help pane that appears
  // when you first hit play.
  var oldCHelpPanel = window.CHelpPanel;
  var globalCHelpPanel = null;
  window.CHelpPanel = function() {
    oldCHelpPanel.call(this);
    globalCHelpPanel = this;
  };

  // Create a Promise that waits for a condition.
  function pollAndWait(timeout, check) {
    var INTERVAL = 100;
    return new Promise(function(resolve, reject) {
      var ival;
      ival = setInterval(function() {
        if (check()) {
          clearInterval(ival);
          resolve();
        }
        timeout -= INTERVAL;
        if (timeout < 0) {
          clearInterval(ival);
          reject('timeout surpassed');
        }
      }, INTERVAL);
    });
  }

  var gameOver = false;
  window.muniverse = {
    init: function() {
      return pollAndWait(MENU_TIMEOUT, function() {
        // Wait for the main menu.
        return 'undefined' !== typeof s_oMenu;
      }).then(function() {
        s_oMenu._onButPlayRelease();
        return pollAndWait(MENU_TIMEOUT, function() {
          // Wait for the help panel to popup.
          return globalCHelpPanel !== null &&
            'undefined' !== typeof s_oGame;
        });
      }).then(function() {
        // Hijack "game over" logic so step() works.
        var gameOverBackup = s_oGame.gameOver;
        s_oGame.gameOver = function() {
          gameOver = true;
          gameOverBackup.call(this);
        };

        // Close help panel, exposing the game.
        globalCHelpPanel._onExit();

        // From now on, time only passes due to step().
        window.faketime.pause();
      });
    },

    score: function() {
      return Promise.resolve(0);
    },

    step: function(millis) {
      return new Promise(function(resolve) {
        window.faketime.advance(millis);
        resolve(gameOver);
      });
    }
  };

})();
<commit_msg>environments are responsible for event safety<commit_after>(function() {

  var MENU_TIMEOUT = 10000;

  // Hijack score.
  var oldCInterface = window.CInterface;
  window.CInterface = function() {
    oldCInterface.call(this);

    var oldRefScore = this.refreshScore;
    this.refreshScore = function(x) {
      oldRefScore.call(this, x);
      window.muniverse.score = function() {
        return Promise.resolve(x);
      };
    }
  }

  // Needed to skip the help pane that appears
  // when you first hit play.
  var oldCHelpPanel = window.CHelpPanel;
  var globalCHelpPanel = null;
  window.CHelpPanel = function() {
    oldCHelpPanel.call(this);
    globalCHelpPanel = this;
  };

  // Create a Promise that waits for a condition.
  function pollAndWait(timeout, check) {
    var INTERVAL = 100;
    return new Promise(function(resolve, reject) {
      var ival;
      ival = setInterval(function() {
        if (check()) {
          clearInterval(ival);
          resolve();
        }
        timeout -= INTERVAL;
        if (timeout < 0) {
          clearInterval(ival);
          reject('timeout surpassed');
        }
      }, INTERVAL);
    });
  }

  var gameOver = false;
  window.muniverse = {
    init: function() {
      return pollAndWait(MENU_TIMEOUT, function() {
        // Wait for the main menu.
        return 'undefined' !== typeof s_oMenu;
      }).then(function() {
        s_oMenu._onButPlayRelease();
        return pollAndWait(MENU_TIMEOUT, function() {
          // Wait for the help panel to popup.
          return globalCHelpPanel !== null &&
            'undefined' !== typeof s_oGame;
        });
      }).then(function() {
        // Hijack "game over" logic so step() works.
        var gameOverBackup = s_oGame.gameOver;
        s_oGame.gameOver = function() {
          gameOver = true;
          gameOverBackup.call(this);
        };

        // Block the exit button.
        s_oGame.onExit = function() {};

        // Close help panel, exposing the game.
        globalCHelpPanel._onExit();

        // From now on, time only passes due to step().
        window.faketime.pause();
      });
    },

    score: function() {
      return Promise.resolve(0);
    },

    step: function(millis) {
      return new Promise(function(resolve) {
        window.faketime.advance(millis);
        resolve(gameOver);
      });
    }
  };

})();
<|endoftext|>


<commit_before>/* global exports */

var multiModule = require('../../multi/server');
var ScreenArranger = multiModule.screens.HorizontalArranger;
var Snake = require('./snake');

exports.Game = function (session) {

	var snakes = null;
	var interval = null;
	var arranger = new ScreenArranger(session);

	session.on('playerJoined', onPlayerJoined);
	session.on('startGame', onStartGame);
	session.on('destroyed', onSessionDestroyed);

	function move() {
		var dead = [];
		snakes.forEach(function (snake) {
			snake.update();
			if (snake.isDead(snakes)) {
				dead.push(snake);
				snake.owner.message('died');
			}
		});
		dead.forEach(function (snake) {
			snakes.splice(snakes.indexOf(snake), 1);
		});
		if (snakes.length === 0) {
			onEndGame();
		}
	}

	function onPlayerJoined(event) {
		event.player.attributes.color = multiModule.color.random();
	}

	function onSessionDestroyed() {
		onEndGame();
	}

	function onPlayerLeft() {
		onEndGame();
	}

	function onEndGame() {
		clearInterval(interval);
		session.message('finished');
		session.removeListener('playerLeft', onPlayerLeft);
	}

	function onStartGame() {
		snakes = [];

		for (var i in session.players) {
			snakes.push(new Snake(session.players[i], arranger));
		}

		session.on('playerLeft', onPlayerLeft);

		// very, very simple gameloop for the start
		interval = setInterval(function () {
			move();
			console.log('tick');
		}, 100);
		// session.message('finished');
	}

};<commit_msg>simplified game loop<commit_after>/* global exports */

var multiModule = require('../../multi/server');
var ScreenArranger = multiModule.screens.HorizontalArranger;
var Snake = require('./snake');

exports.Game = function (session) {

	var snakes = null;
	var interval = null;
	var arranger = new ScreenArranger(session);

	session.on('playerJoined', onPlayerJoined);
	session.on('startGame', onStartGame);
	session.on('destroyed', onSessionDestroyed);

	function move() {
		var dead = [];
		snakes.forEach(function (snake) {
			snake.update();
			if (snake.isDead(snakes)) {
				dead.push(snake);
				snake.owner.message('died');
			}
		});
		dead.forEach(function (snake) {
			snakes.splice(snakes.indexOf(snake), 1);
		});
		if (snakes.length === 0) {
			onEndGame();
		}
	}

	function onPlayerJoined(event) {
		event.player.attributes.color = multiModule.color.random();
	}

	function onSessionDestroyed() {
		onEndGame();
	}

	function onPlayerLeft() {
		onEndGame();
	}

	function onEndGame() {
		clearInterval(interval);
		session.message('finished');
		session.removeListener('playerLeft', onPlayerLeft);
	}

	function onStartGame() {
		snakes = [];

		for (var i in session.players) {
			snakes.push(new Snake(session.players[i], arranger));
		}

		session.on('playerLeft', onPlayerLeft);

		// very, very simple gameloop for the start
		interval = setInterval(move, 100);
	}

};<|endoftext|>


<commit_before>'use strict';

angular.module('lbClientApp')
.controller('AddFoodCtrl', function ($scope, $controller, AddFoodService) {
  angular.extend(this, $controller('BaseCtrl', {$scope: $scope}));

  $scope.item = {
    type: 'food'
  };

  $scope.isFood = function () {
    return $scope.item.type === 'food';
  };

  $scope.isBeverage = function () {
    return $scope.item.type === 'beverage';
  };

  $scope.selectFood = function () {
    $scope.item.type = 'food';
  };

  $scope.selectBeverage = function () {
    $scope.item.type = 'beverage';
  };

  $scope.quantityLabel = function () {
    return $scope.item.type === 'food' ? 'grams' : 'milliliters';
  };

  $scope.isInputValid = function () {
    var item = $scope.item;
    return item.name &&
             $.isNumeric(item.calories) &&
             $.isNumeric(item.fats) &&
             $.isNumeric(item.carbohydrates) &&
             $.isNumeric(item.proteins);
  };

  $scope.sendItem = function() {
    var item = $scope.item;

    function clearItem() {
      $scope.item = {
        type: item.type
      }
    }

    if ($scope.isFood()) {
      AddFoodService.addFood(item.name, item.calories,
        item.carbohydrates, item.fats, item.proteins, clearItem);
    } else {
      AddFoodService.addBeverage(item.name, item.calories,
        item.carbohydrates, item.fats, item.proteins, clearItem);
    }
  };
});
<commit_msg>Minor: Fixed a syntax error.<commit_after>'use strict';

angular.module('lbClientApp')
.controller('AddFoodCtrl', function ($scope, $controller, AddFoodService) {
  angular.extend(this, $controller('BaseCtrl', {$scope: $scope}));

  $scope.item = {
    type: 'food'
  };

  $scope.isFood = function () {
    return $scope.item.type === 'food';
  };

  $scope.isBeverage = function () {
    return $scope.item.type === 'beverage';
  };

  $scope.selectFood = function () {
    $scope.item.type = 'food';
  };

  $scope.selectBeverage = function () {
    $scope.item.type = 'beverage';
  };

  $scope.quantityLabel = function () {
    return $scope.item.type === 'food' ? 'grams' : 'milliliters';
  };

  $scope.isInputValid = function () {
    var item = $scope.item;
    return item.name &&
             $.isNumeric(item.calories) &&
             $.isNumeric(item.fats) &&
             $.isNumeric(item.carbohydrates) &&
             $.isNumeric(item.proteins);
  };

  $scope.sendItem = function() {
    var item = $scope.item;

    function clearItem() {
      $scope.item = {
        type: item.type
      };
    }

    if ($scope.isFood()) {
      AddFoodService.addFood(item.name, item.calories,
        item.carbohydrates, item.fats, item.proteins, clearItem);
    } else {
      AddFoodService.addBeverage(item.name, item.calories,
        item.carbohydrates, item.fats, item.proteins, clearItem);
    }
  };
});
<|endoftext|>