<commit_before>var Twit = require('twit');
var settings = require('./settings.js');
var TweetFilter = require('./lib/filter');
var path = require('path');
var fs = require('fs');

// Declare your own Twitter app credentials here, if duplicating
var T = new Twit(settings.CREDS);
// Whenever the Twitter stream notifies us of a new Tweet with the term 'vegan', we handle it!
var stream = T.stream('statuses/filter', { track: 'vegan' });
// Load filters from all files in the filters directory
var filter = new TweetFilter('filters', settings.FILTERED_TERMS);
// Run with option '--dry-run' to disable retweeting and instead log matches to console
var isDryRun = process.argv[2] === '--dry-run';
// Use a different log file for dry-run
var logFile = path.join(__dirname, (isDryRun ? 'matches.dry-run' : 'matches') + '.json');
// Check that we can write to disk, so that we can log it upfront and safely ignore errors later
// This allows the bot to function even if it doesn't have write access to the disk
fs.appendFile(logFile, "", function(err) {
    if (err) { console.warn("Unable to write to log file: " + path.relative(__dirname, logFile)); }
})

// log tweets and their matches as json, each tweet/match will be a separate line of json
var logMatches = function(tweet, matches) {
    // flatten match objects a bit
    matches = matches.map(function(match){
        return {match: match[0], index: match.index, filter: match.filter.toString(), filterList: match.filterList };
    })
    // provide an empty callback to swallow errors
    fs.appendFile(logFile, JSON.stringify({ tweet: tweet, matches: matches }) + "\n", function(){});
}

stream.on('connect', function (response) {
    console.log("Connecting to Twitter..." + (isDryRun ? " (dry run, will not retweet matches)" : ""))
})
stream.on('connected', function (response) {
    console.log("Connected")
})
stream.on('reconnect', function (response) {
    console.log("Reconnecting...")
})
stream.on('tweet', function(tweet) {
    var matches = filter.matches(tweet);
    if (matches) {
        logMatches(tweet, matches);
        if (isDryRun) {
            console.log(tweet.id_str + ' : ' + tweet.user.screen_name + ' : ' + tweet.text);
            return;
        }
        // positive match; let's retweet!
        T.post('statuses/retweet/:id', {id: tweet.id_str}, function(err, data, response) {
            if (err) {
                console.log(err);
                return false;
            }
            console.log('Retweeted: ' + tweet.id_str);
        });
    }
});<commit_msg>add some translations of 'vegan' to track<commit_after>var Twit = require('twit');
var settings = require('./settings.js');
var TweetFilter = require('./lib/filter');
var path = require('path');
var fs = require('fs');

// Declare your own Twitter app credentials here, if duplicating
var T = new Twit(settings.CREDS);
// Whenever the Twitter stream notifies us of a new Tweet with the term 'vegan' (or its international equivalents), we handle it!
var stream = T.stream('statuses/filter', { track: ['vegan', 'veganist', 'vegana'] });
// Load filters from all files in the filters directory
var filter = new TweetFilter('filters', settings.FILTERED_TERMS);
// Run with option '--dry-run' to disable retweeting and instead log matches to console
var isDryRun = process.argv[2] === '--dry-run';
// Use a different log file for dry-run
var logFile = path.join(__dirname, (isDryRun ? 'matches.dry-run' : 'matches') + '.json');
// Check that we can write to disk, so that we can log it upfront and safely ignore errors later
// This allows the bot to function even if it doesn't have write access to the disk
fs.appendFile(logFile, "", function(err) {
    if (err) { console.warn("Unable to write to log file: " + path.relative(__dirname, logFile)); }
})

// log tweets and their matches as json, each tweet/match will be a separate line of json
var logMatches = function(tweet, matches) {
    // flatten match objects a bit
    matches = matches.map(function(match){
        return {match: match[0], index: match.index, filter: match.filter.toString(), filterList: match.filterList };
    })
    // provide an empty callback to swallow errors
    fs.appendFile(logFile, JSON.stringify({ tweet: tweet, matches: matches }) + "\n", function(){});
}

stream.on('connect', function (response) {
    console.log("Connecting to Twitter..." + (isDryRun ? " (dry run, will not retweet matches)" : ""))
})
stream.on('connected', function (response) {
    console.log("Connected")
})
stream.on('reconnect', function (response) {
    console.log("Reconnecting...")
})
stream.on('tweet', function(tweet) {
    var matches = filter.matches(tweet);
    if (matches) {
        logMatches(tweet, matches);
        if (isDryRun) {
            console.log(tweet.id_str + ' : ' + tweet.user.screen_name + ' : ' + tweet.text);
            return;
        }
        // positive match; let's retweet!
        T.post('statuses/retweet/:id', {id: tweet.id_str}, function(err, data, response) {
            if (err) {
                console.log(err);
                return false;
            }
            console.log('Retweeted: ' + tweet.id_str);
        });
    }
});
<|endoftext|>


<commit_before>/* eslint-env node */

module.exports = {
    rules: {
        // Enforces getter/setter pairs in objects
        "accessor-pairs": 0,

        // Treat var statements as if they were block scoped
        "block-scoped-var": "error",

        // Specify the maximum cyclomatic complexity allowed in a program
        "complexity": [ 0, 11 ],

        // Require return statements to either always or never specify values
        "consistent-return": "error",

        // Specify curly brace conventions for all control statements
        "curly": [ "error", "multi-line" ],

        // Require default case in switch statements
        "default-case": "error",

        // Enforces consistent newlines before or after dots
        "dot-location": 0,

        // Encourages use of dot notation whenever possible
        "dot-notation": [
            "error", {
                allowKeywords: true,
            },
        ],

        // Require the use of === and !==
        "eqeqeq": "error",

        // Make sure for-in loops have an if statement
        "guard-for-in": "error",

        // Disallow the use of alert, confirm, and prompt
        "no-alert": 1,

        // Disallow use of arguments.caller or arguments.callee
        "no-caller": "error",

        // Disallow lexical declarations in case clauses
        "no-case-declarations": "error",

        /*
         * Disallow division operators explicitly at beginning of regular
         * expression
         */
        "no-div-regex": 0,

        // Disallow else after a return in an if
        "no-else-return": [ "error", {
            allowElseIf: false,
        } ],

        // Disallow use of empty destructuring patterns
        "no-empty-pattern": 0,

        // Disallow comparisons to null without a type-checking operator
        "no-eq-null": 0,

        // Disallow use of eval()
        "no-eval": "error",

        // Disallow adding to native types
        "no-extend-native": "error",

        // Disallow unnecessary function binding
        "no-extra-bind": "error",

        // Disallow fallthrough of case statements
        "no-fallthrough": "error",

        /*
         * Disallow the use of leading or trailing decimal points in numeric
         * Literals
         */
        "no-floating-decimal": "error",

        // Disallow the type conversions with shorter notations
        "no-implicit-coercion": 0,

        // Disallow use of eval()-like methods
        "no-implied-eval": "error",

        // Disallow this keywords outside of classes or class-like objects
        "no-invalid-this": 0,

        // Disallow usage of __iterator__ property
        "no-iterator": "error",

        // Disallow use of labels for anything other then loops and switches
        "no-label": 0,

        // Disallow use of labeled statements
        "no-labels": "error",

        // Disallow unnecessary nested blocks
        "no-lone-blocks": "error",

        // Disallow creation of functions within loops
        "no-loop-func": "error",

        // Disallow the use of magic numbers
        "no-magic-numbers": 0,

        /*
         * This rule aims to disallow multiple whitespace around logical
         * Expressions, conditional expressions, declarations, array elements,
         * Object properties, sequences and function parameters.
         */
        "no-multi-spaces": "warn",

        // Disallow use of multiline strings
        "no-multi-str": "error",

        // Disallow reassignments of native objects
        "no-native-reassign": "error",

        /*
         * Disallow use of new operator when not part of the assignment or
         * Comparison
         */
        "no-new": "error",

        // Disallow use of new operator for Function object
        "no-new-func": "error",

        // Disallows creating new instances of String,Number, and Boolean
        "no-new-wrappers": "error",

        // Disallow use of (old style) octal literals
        "no-octal": "error",

        /*
         * Disallow use of octal escape sequences in string literals, such as
         * Var foo = "Copyright \251";
         */
        "no-octal-escape": "error",

        // Disallow reassignment of function parameters
        "no-param-reassign": [
            "error", {
                props: false,
            },
        ],

        // Disallow use of process.env
        "no-process-env": 0,

        // Disallow usage of __proto__ property
        "no-proto": "error",

        // Disallow declaring the same variable more then once
        "no-redeclare": "error",

        // Disallow use of assignment in return statement
        "no-return-assign": "error",

        // Disallow use of `javascript:` urls.
        "no-script-url": "error",

        // Disallow comparisons where both sides are exactly the same
        "no-self-compare": "error",

        // Disallow use of comma operator
        "no-sequences": "error",

        // Restrict what can be thrown as an exception
        "no-throw-literal": "error",

        // Disallow usage of expressions in statement position
        "no-unused-expressions": "error",

        // Disallow unnecessary .call() and .apply()
        "no-useless-call": 0,

        // Disallow unnecessary concatenation of literals or template literals
        "no-useless-concat": 0,

        // Disallow use of void operator
        "no-void": 0,

        // Disallow usage of configurable warning terms in comments: e.g. todo
        "no-warning-comments": [
            0, {
                location: "start",
                terms   : [ "todo", "fixme", "xxx" ],
            },
        ],

        // Disallow use of the with statement
        "no-with": "error",

        // Require use of the second argument for parseInt()
        "radix": "error",

        // Requires to declare all vars on top of their containing scope
        "vars-on-top": "error",

        // Require immediate function invocation to be wrapped in parentheses
        "wrap-iife": [ "error", "outside" ],

        // Require or disallow Yoda conditions
        "yoda": 0,
    },
}
<commit_msg>Changing `no-unused-expressions`<commit_after>/* eslint-env node */

module.exports = {
    rules: {
        // Enforces getter/setter pairs in objects
        "accessor-pairs": 0,

        // Treat var statements as if they were block scoped
        "block-scoped-var": "error",

        // Specify the maximum cyclomatic complexity allowed in a program
        "complexity": [ 0, 11 ],

        // Require return statements to either always or never specify values
        "consistent-return": "error",

        // Specify curly brace conventions for all control statements
        "curly": [ "error", "multi-line" ],

        // Require default case in switch statements
        "default-case": "error",

        // Enforces consistent newlines before or after dots
        "dot-location": 0,

        // Encourages use of dot notation whenever possible
        "dot-notation": [
            "error", {
                allowKeywords: true,
            },
        ],

        // Require the use of === and !==
        "eqeqeq": "error",

        // Make sure for-in loops have an if statement
        "guard-for-in": "error",

        // Disallow the use of alert, confirm, and prompt
        "no-alert": 1,

        // Disallow use of arguments.caller or arguments.callee
        "no-caller": "error",

        // Disallow lexical declarations in case clauses
        "no-case-declarations": "error",

        /*
         * Disallow division operators explicitly at beginning of regular
         * expression
         */
        "no-div-regex": 0,

        // Disallow else after a return in an if
        "no-else-return": [ "error", {
            allowElseIf: false,
        } ],

        // Disallow use of empty destructuring patterns
        "no-empty-pattern": 0,

        // Disallow comparisons to null without a type-checking operator
        "no-eq-null": 0,

        // Disallow use of eval()
        "no-eval": "error",

        // Disallow adding to native types
        "no-extend-native": "error",

        // Disallow unnecessary function binding
        "no-extra-bind": "error",

        // Disallow fallthrough of case statements
        "no-fallthrough": "error",

        /*
         * Disallow the use of leading or trailing decimal points in numeric
         * Literals
         */
        "no-floating-decimal": "error",

        // Disallow the type conversions with shorter notations
        "no-implicit-coercion": 0,

        // Disallow use of eval()-like methods
        "no-implied-eval": "error",

        // Disallow this keywords outside of classes or class-like objects
        "no-invalid-this": 0,

        // Disallow usage of __iterator__ property
        "no-iterator": "error",

        // Disallow use of labels for anything other then loops and switches
        "no-label": 0,

        // Disallow use of labeled statements
        "no-labels": "error",

        // Disallow unnecessary nested blocks
        "no-lone-blocks": "error",

        // Disallow creation of functions within loops
        "no-loop-func": "error",

        // Disallow the use of magic numbers
        "no-magic-numbers": 0,

        /*
         * This rule aims to disallow multiple whitespace around logical
         * Expressions, conditional expressions, declarations, array elements,
         * Object properties, sequences and function parameters.
         */
        "no-multi-spaces": "warn",

        // Disallow use of multiline strings
        "no-multi-str": "error",

        // Disallow reassignments of native objects
        "no-native-reassign": "error",

        /*
         * Disallow use of new operator when not part of the assignment or
         * Comparison
         */
        "no-new": "error",

        // Disallow use of new operator for Function object
        "no-new-func": "error",

        // Disallows creating new instances of String,Number, and Boolean
        "no-new-wrappers": "error",

        // Disallow use of (old style) octal literals
        "no-octal": "error",

        /*
         * Disallow use of octal escape sequences in string literals, such as
         * Var foo = "Copyright \251";
         */
        "no-octal-escape": "error",

        // Disallow reassignment of function parameters
        "no-param-reassign": [
            "error", {
                props: false,
            },
        ],

        // Disallow use of process.env
        "no-process-env": 0,

        // Disallow usage of __proto__ property
        "no-proto": "error",

        // Disallow declaring the same variable more then once
        "no-redeclare": "error",

        // Disallow use of assignment in return statement
        "no-return-assign": "error",

        // Disallow use of `javascript:` urls.
        "no-script-url": "error",

        // Disallow comparisons where both sides are exactly the same
        "no-self-compare": "error",

        // Disallow use of comma operator
        "no-sequences": "error",

        // Restrict what can be thrown as an exception
        "no-throw-literal": "error",

        // Disallow usage of expressions in statement position
        "no-unused-expressions": [ "error", {
            allowShortCircuit: true,
            allowTernary     : true,
        } ],

        // Disallow unnecessary .call() and .apply()
        "no-useless-call": 0,

        // Disallow unnecessary concatenation of literals or template literals
        "no-useless-concat": 0,

        // Disallow use of void operator
        "no-void": 0,

        // Disallow usage of configurable warning terms in comments: e.g. todo
        "no-warning-comments": [
            0, {
                location: "start",
                terms   : [ "todo", "fixme", "xxx" ],
            },
        ],

        // Disallow use of the with statement
        "no-with": "error",

        // Require use of the second argument for parseInt()
        "radix": "error",

        // Requires to declare all vars on top of their containing scope
        "vars-on-top": "error",

        // Require immediate function invocation to be wrapped in parentheses
        "wrap-iife": [ "error", "outside" ],

        // Require or disallow Yoda conditions
        "yoda": 0,
    },
}
<|endoftext|>


<commit_before>/*!
*   Gerador e Validador de CPF v3.0.0
*   https://github.com/tiagoporto/gerador-validador-cpf
*   Copyright (c) 2014-2016 Tiago Porto (http://www.tiagoporto.com)
*   Released under the MIT license
*/

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };

/**
 * CPF Class
 *
 * generate function
 * @param  {string} param      Formatting option
 * @return {string}            Valid and formatted CPF
 *
 * validate function
 * @param  {string} value      The value for validation
 * @return {boolean}           True = valid || False = invalid
 *
 * format function
 * @param  {string} value      The value for formatting
 * @param  {string} param      Formatting option
 *
 * @return {string}            Formatted CPF || error message
 */

/*eslint-env node*/
(function () {
    'use strict';

    var root = (typeof self === 'undefined' ? 'undefined' : _typeof(self)) === 'object' && self.self === self && self || (typeof global === 'undefined' ? 'undefined' : _typeof(global)) === 'object' && global.global === global && global || this;

    var CPF = function CPF() {};

    if (typeof exports !== 'undefined' && !exports.nodeType) {
        if (typeof module !== 'undefined' && !module.nodeType && module.exports) {
            exports = module.exports = CPF;
        }
        exports.CPF = CPF;
    } else {
        root.CPF = CPF;
    }

    function calcChecker1(firstNineDigits) {
        var sum = null;

        for (var j = 0; j < 9; ++j) {
            sum += firstNineDigits.toString().charAt(j) * (10 - j);
        }

        var lastSumChecker1 = sum % 11;
        var checker1 = lastSumChecker1 < 2 ? 0 : 11 - lastSumChecker1;

        return checker1;
    }

    function calcChecker2(cpfWithChecker1) {
        var sum = null;

        for (var k = 0; k < 10; ++k) {
            sum += cpfWithChecker1.toString().charAt(k) * (11 - k);
        }

        var lastSumChecker2 = sum % 11;
        var checker2 = lastSumChecker2 < 2 ? 0 : 11 - lastSumChecker2;

        return checker2;
    }

    function cleaner(value) {
        var digits = value.replace(/\.|\-|\s/g, '');

        return digits;
    }

    function formatCPF(value, formatter) {
        var digitsSeparator = '.',
            checkersSeparator = '-';

        if (formatter === 'digits') {
            digitsSeparator = '';
            checkersSeparator = '';
        } else if (formatter === 'checker') {
            digitsSeparator = '';
            checkersSeparator = '-';
        }

        if (!/^[0-9]+$/.test(value)) {
            return 'The value contains invalid characters.';
        }

        if (value.length > 11) {
            return 'The value contains error. Has more than 11 digits.';
        } else if (value.length < 11) {
            return 'The value contains error. Has fewer than 11 digits.';
        } else {
            return value.slice(0, 3) + digitsSeparator + value.slice(3, 6) + digitsSeparator + value.slice(6, 9) + checkersSeparator + value.slice(9, 11);
        }
    }

    CPF.generate = function (param) {
        var firstNineDigits = '';

        // Generating the first 9 digits of the CPF
        for (var i = 0; i < 9; ++i) {
            firstNineDigits += Math.floor(Math.random() * 9) + '';
        }

        var checker1 = calcChecker1(firstNineDigits);
        var generatedCPF = firstNineDigits + checker1 + calcChecker2(firstNineDigits + checker1);

        return formatCPF(generatedCPF, param);
    };

    CPF.validate = function (value) {
        var cleanCPF = cleaner(value),
            firstNineDigits = cleanCPF.substring(0, 9),
            checker = cleanCPF.substring(9, 11);

        // Checking if all digits are equal
        for (var i = 0; i < 10; i++) {
            if ('' + firstNineDigits + checker === Array(12).join(i)) {
                return false;
            }
        }

        var checker1 = calcChecker1(firstNineDigits);
        var checker2 = calcChecker2(firstNineDigits + '' + checker1);

        if (checker.toString() === checker1.toString() + checker2.toString()) {
            return true;
        } else {
            return false;
        }
    };

    CPF.format = function (value, param) {
        var getCPF = cleaner(value);

        return formatCPF(getCPF, param);
    };

    return CPF;
})();<commit_msg>cleaner() can clean almost any user input<commit_after>/*!
*   Gerador e Validador de CPF v3.0.0
*   https://github.com/tiagoporto/gerador-validador-cpf
*   Copyright (c) 2014-2016 Tiago Porto (http://www.tiagoporto.com)
*   Released under the MIT license
*/

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };

/**
 * CPF Class
 *
 * generate function
 * @param  {string} param      Formatting option
 * @return {string}            Valid and formatted CPF
 *
 * validate function
 * @param  {string} value      The value for validation
 * @return {boolean}           True = valid || False = invalid
 *
 * format function
 * @param  {string} value      The value for formatting
 * @param  {string} param      Formatting option
 *
 * @return {string}            Formatted CPF || error message
 */

/*eslint-env node*/
(function () {
    'use strict';

    var root = (typeof self === 'undefined' ? 'undefined' : _typeof(self)) === 'object' && self.self === self && self || (typeof global === 'undefined' ? 'undefined' : _typeof(global)) === 'object' && global.global === global && global || this;

    var CPF = function CPF() {};

    if (typeof exports !== 'undefined' && !exports.nodeType) {
        if (typeof module !== 'undefined' && !module.nodeType && module.exports) {
            exports = module.exports = CPF;
        }
        exports.CPF = CPF;
    } else {
        root.CPF = CPF;
    }

    function calcChecker1(firstNineDigits) {
        var sum = null;

        for (var j = 0; j < 9; ++j) {
            sum += firstNineDigits.toString().charAt(j) * (10 - j);
        }

        var lastSumChecker1 = sum % 11;
        var checker1 = lastSumChecker1 < 2 ? 0 : 11 - lastSumChecker1;

        return checker1;
    }

    function calcChecker2(cpfWithChecker1) {
        var sum = null;

        for (var k = 0; k < 10; ++k) {
            sum += cpfWithChecker1.toString().charAt(k) * (11 - k);
        }

        var lastSumChecker2 = sum % 11;
        var checker2 = lastSumChecker2 < 2 ? 0 : 11 - lastSumChecker2;

        return checker2;
    }

    function cleaner(value) {
        var digits = value.replace(/[^\d]/g, '');

        return digits;
    }

    function formatCPF(value, formatter) {
        var digitsSeparator = '.',
            checkersSeparator = '-';

        if (formatter === 'digits') {
            digitsSeparator = '';
            checkersSeparator = '';
        } else if (formatter === 'checker') {
            digitsSeparator = '';
            checkersSeparator = '-';
        }

        if (!/^[0-9]+$/.test(value)) {
            return 'The value contains invalid characters.';
        }

        if (value.length > 11) {
            return 'The value contains error. Has more than 11 digits.';
        } else if (value.length < 11) {
            return 'The value contains error. Has fewer than 11 digits.';
        } else {
            return value.slice(0, 3) + digitsSeparator + value.slice(3, 6) + digitsSeparator + value.slice(6, 9) + checkersSeparator + value.slice(9, 11);
        }
    }

    CPF.generate = function (param) {
        var firstNineDigits = '';

        // Generating the first 9 digits of the CPF
        for (var i = 0; i < 9; ++i) {
            firstNineDigits += Math.floor(Math.random() * 9) + '';
        }

        var checker1 = calcChecker1(firstNineDigits);
        var generatedCPF = firstNineDigits + checker1 + calcChecker2(firstNineDigits + checker1);

        return formatCPF(generatedCPF, param);
    };

    CPF.validate = function (value) {
        var cleanCPF = cleaner(value),
            firstNineDigits = cleanCPF.substring(0, 9),
            checker = cleanCPF.substring(9, 11);

        // Checking if all digits are equal
        for (var i = 0; i < 10; i++) {
            if ('' + firstNineDigits + checker === Array(12).join(i)) {
                return false;
            }
        }

        var checker1 = calcChecker1(firstNineDigits);
        var checker2 = calcChecker2(firstNineDigits + '' + checker1);

        if (checker.toString() === checker1.toString() + checker2.toString()) {
            return true;
        } else {
            return false;
        }
    };

    CPF.format = function (value, param) {
        var getCPF = cleaner(value);

        return formatCPF(getCPF, param);
    };

    return CPF;
})();
<|endoftext|>


<commit_before>// this is the main entry point for the app
// it renders the App component after wrapping it in the Provider from Redux

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import { Router, Route, IndexRoute, browserHistory, Link } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';

import App from './components/App';
import MainRecipe from './components/MainRecipe';
import Profile from './components/Profile';
import Dashboard from './components/Dashboard';
import SearchResults from './components/SearchResults';
import ImageUpload from './components/ImageUpload.js';
import CreateRecipe from './components/CreateRecipe';

import rootReducer from './reducers';

// Grab the state from a global injected into server-generated HTML
const initialState = window.__INITIAL_STATE__;

// Create Redux store with initial state
// the store manages the state of our app
// createStore accepts a single reducer or a collection of reducers
const store = createStore(rootReducer, initialState);

const history = syncHistoryWithStore(browserHistory, store);

const render = function () {
  ReactDOM.render(
    <Provider store={store}>

        <Router history={history}>
          <Route path="/" component={App}>
            <IndexRoute component={Dashboard} />
            <Route path="/profile" component={Profile} />
            <Route path="/recipe" component={MainRecipe} />
            <Route path="/dashboard" component={Dashboard} />
            <Route path="/create" component={CreateRecipe} />
            <Route path="/search" component={SearchResults} />
            <Route path="/*" component={Dashboard} />
          </Route>
        </Router>

    </Provider>,
    document.getElementById('app')
  );
};

render();
store.subscribe(render);
<commit_msg>Add route to individual recipe page<commit_after>// this is the main entry point for the app
// it renders the App component after wrapping it in the Provider from Redux

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import { Router, Route, IndexRoute, browserHistory, Link } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';

import App from './components/App';
import MainRecipe from './components/MainRecipe';
import Profile from './components/Profile';
import Dashboard from './components/Dashboard';
import SearchResults from './components/SearchResults';
import ImageUpload from './components/ImageUpload.js';
import CreateRecipe from './components/CreateRecipe';

import rootReducer from './reducers';

// Grab the state from a global injected into server-generated HTML
const initialState = window.__INITIAL_STATE__;

// Create Redux store with initial state
// the store manages the state of our app
// createStore accepts a single reducer or a collection of reducers
const store = createStore(rootReducer, initialState);

const history = syncHistoryWithStore(browserHistory, store);

const render = function () {
  ReactDOM.render(
    <Provider store={store}>

        <Router history={history}>
          <Route path="/" component={App}>
            <IndexRoute component={Dashboard} />
            <Route path="/profile" component={Profile} />
            <Route path="/recipe" component={MainRecipe} />
            <Route path="/recipe/:id" component={MainRecipe} />
            <Route path="/dashboard" component={Dashboard} />
            <Route path="/create" component={CreateRecipe} />
            <Route path="/search" component={SearchResults} />
            <Route path="/*" component={Dashboard} />
          </Route>
        </Router>

    </Provider>,
    document.getElementById('app')
  );
};

render();
store.subscribe(render);
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 Vanderbilt University, All rights reserved.
 *
 * Authors: Tamas Kecskes, Robert Kereskenyi
 */

var requirejs = require("requirejs");

requirejs.config({
    nodeRequire: require,
    baseUrl: __dirname + "/.."
});

requirejs([ "util/common", "util/assert", "core/tasync", "util/guid", "client/js/RegistryKeys" ], function (COMMON, ASSERT, TASYNC,GUID, REGISTRY_KEYS) {
    "use strict";

    TASYNC.trycatch(main, function (error) {
        console.log(error.trace || error.stack);

        COMMON.setProgress(null);
        COMMON.closeProject();
        COMMON.closeDatabase();
    });
    var _commit = null,
        _startHash = null,
        _branch = null,
        _projectName = null,
        _outFile = null;

    //these registry keys will be saved in the item's registry
    var _protectedRegistryKeys = [REGISTRY_KEYS.PROJECT_REGISTRY,
                                    REGISTRY_KEYS.META_SHEETS,
                                    REGISTRY_KEYS.IS_ABSTRACT,
                                    REGISTRY_KEYS.IS_PORT,
                                    REGISTRY_KEYS.DECORATOR,
                                    REGISTRY_KEYS.DISPLAY_FORMAT,
                                    REGISTRY_KEYS.POSITION,
                                    REGISTRY_KEYS.SVG_ICON
                                ];

    //these registry keys will be saved in the setmembers' registry
    var _protectedSetMemberRegistryKeys = [REGISTRY_KEYS.POSITION];

    function main () {
        var args = COMMON.getParameters(null);

        if (COMMON.getParameters("help") !== null) {
            console.log("Usage: node update_project.js [options]");
            console.log("");
            console.log("Updates the given branch to the latest webgme format. Possible options:");
            console.log("");
            console.log("  -mongo [database [host [port]]]\topens a mongo database");
            console.log("  -proj <project>\t\t\tselects the given project");
            console.log("  -branch <branch>\t\t\tthe branch to serialize");
            console.log("  -help\t\t\t\t\tprints out this help message");
            console.log("");
            return;
        }

        console.log('starting serialization',new Date());
        _outFile = args[0];

        _branch = COMMON.getParameters("branch");
        if (_branch) {
            _branch = _branch[0] || "parsed";
        } else {
            _branch = "master";
        }
        _projectName = COMMON.getParameters("proj");
        if(_projectName){
            _projectName = _projectName[0];
        }

        var done = TASYNC.call(COMMON.openDatabase);
        done = TASYNC.call(COMMON.openProject, done);
        var core = TASYNC.call(COMMON.getCore, done);
        if(!_startHash){
            if(_branch){
                _startHash = TASYNC.call(getRootHashOfBranch,_branch,done);
                TASYNC.call(settingCommitHashOfBranch,_branch,done);
            } else if(_commit){
                _startHash = TASYNC.call(getRootHashOfCommit,_commit,done);
            } else {
                done = TASYNC.call(COMMON.closeProject, done);
                done = TASYNC.call(COMMON.closeDatabase, done);
                return done;
            }
        }
        done = TASYNC.call(updateProject,core,_startHash);
        done = TASYNC.call(function(newhash){
            console.log('the root after serializing and normalizing:',newhash);
            console.log('the commit hash what we modified:',_commit);
            if(_commit){
                //we should make a commit
                var newCommit = makeCommit(newhash,_commit);
                if(_branch){
                    //we also should update the branch
                    return TASYNC.call(writeBranch,newCommit);
                } else {
                    return null;
                }
            } else {
                return null;
            }
        },done);
        done = TASYNC.call(COMMON.closeProject, done);
        done = TASYNC.call(COMMON.closeDatabase, done);
        done = TASYNC.call(function(){
            console.log('finished',new Date());
        },done);
        return done;
    }

    function makeCommit (rootHash, parentCommitHash) {
        var project = COMMON.getProject();
        return project.makeCommit([parentCommitHash], rootHash, "Updating project to be visible with latest webGME.");
    }

    function getRootHashOfBranch (branch){
        var project = COMMON.getProject();
        var commitHash = project.getBranchHash(branch,null);
        var done = TASYNC.call(project.loadObject,commitHash);
        done = TASYNC.call(function(object){
            console.log('getRootHashOfBranch',branch,object.root);
            _branch = branch;
            return object.root;
        },done);
        return done;
    }

    function settingCommitHashOfBranch (branch){
        var project = COMMON.getProject();
        var cHash = project.getBranchHash(branch,null);
        return TASYNC.call(function(hash){
            _commit = hash;
            return hash;
        },cHash);
    }

    function getRootHashOfCommit (commit){
        var project = COMMON.getProject();
        return TASYNC.call(function(object){
            console.log('getRootHashOfCommit',commit,object.root);
            return object.root;
        },TASYNC.call(project.loadObject,commit));
    }

    function writeBranch (hash) {
        var project = COMMON.getProject();
        var done = project.setBranchHash(_branch, _commit, hash);
        return TASYNC.call(function () {
            console.log("Commit " + hash + " written to branch " + _branch);
        }, done);
    }

    function updateNode(core,node){ //TODO this method should be always up-to-date...
        var objID = core.getPath(node,core.getRoot(node)) + ' ('+core.getAttribute(node,"name")+"): ";
        console.log(objID);

        //clear item's global registry values
        var registryKeys = core.getRegistryNames(node) || [];
        var len = registryKeys.length;
        var removedRegKeys = "";
        var rk;
        while (len--) {
            //remove all that's not defined as protected
            rk = registryKeys[len];
            if (_protectedRegistryKeys.indexOf(rk) === -1) {
                core.delRegistry(node, rk);
                removedRegKeys += rk + ", ";
            }
        }
        if (removedRegKeys !== "") {
            console.log('\tRemoved node registry entries: ' + removedRegKeys);
        }

        //check if this node has any sets and remove the not protected set registry entries too
        var sets = core.getSetNames(node) || [];
        len = sets.length;
        var setMemberRegistryKeys;
        var set;
        var setMembers;
        var setMemberIdx;
        var setMemberRegKeysIdx;
        var sm;
        while (len--) {
            //remove all that's not defined as protected
            set = sets[len];
            setMembers = core.getMemberPaths(node, set) || [];
            setMemberIdx = setMembers.length;
            while (setMemberIdx--) {
                sm = setMembers[setMemberIdx];
                setMemberRegistryKeys = core.getMemberRegistryNames(node, set, sm) || [];
                setMemberRegKeysIdx = setMemberRegistryKeys.length;
                removedRegKeys = "";
                while (setMemberRegKeysIdx--) {
                    rk = setMemberRegistryKeys[setMemberRegKeysIdx];
                    if (_protectedSetMemberRegistryKeys.indexOf(rk) === -1) {
                        core.delMemberRegistry(node, set, sm, rk);
                        removedRegKeys += rk + ", ";
                    }
                }
                if (removedRegKeys !== "") {
                    console.log('\tRemoved set member registry entries for SET "' + set + '" and MEMBER "' + sm +  '": ' + removedRegKeys);
                }
            }
        }

        //insert newline
        console.log('\n');
    }
    function traverseNode (core,node){
        updateNode(core,node);
        var children = core.loadChildren(node);
        var traverseChildren = function(core,nodearray){
            var done;
            for(var i=0;i<nodearray.length;i++){
                done = TASYNC.call(traverseNode,core,nodearray[i],done);
            }
            return TASYNC.call(function(){return;},done);
        };
        return TASYNC.call(traverseChildren,core,children);
    }
    function updateProject(core,roothash){
        var root = core.loadRoot(roothash);
        var done = TASYNC.call(traverseNode,core,root);
        return TASYNC.call(saveChanges,core,root,done);
    }
    function saveChanges(core,root){
        console.log("Finalizing the update...");
        var done = core.persist(root);
        var hash = core.getHash(root);
        return TASYNC.join(hash, done);
    }

});

<commit_msg>fix: make sure that the FCO has all the necessary registry keys that we create for a new project<commit_after>/*
 * Copyright (C) 2013 Vanderbilt University, All rights reserved.
 *
 * Authors: Tamas Kecskes, Robert Kereskenyi
 */

var requirejs = require("requirejs");

requirejs.config({
    nodeRequire: require,
    baseUrl: __dirname + "/..",
    paths: {
        "underscore": 'client/lib/underscore/underscore-min'
    }
});

requirejs([ "util/common", "util/assert", "core/tasync", "util/guid", "client/js/RegistryKeys", "client/js/Constants" ], function (COMMON, ASSERT, TASYNC,GUID, REGISTRY_KEYS, CONSTANTS) {
    "use strict";

    TASYNC.trycatch(main, function (error) {
        console.log(error.trace || error.stack);

        COMMON.setProgress(null);
        COMMON.closeProject();
        COMMON.closeDatabase();
    });
    var _commit = null,
        _startHash = null,
        _branch = null,
        _projectName = null,
        _outFile = null;

    var FCO_REGISTRY_KEYS = [REGISTRY_KEYS.DECORATOR,  REGISTRY_KEYS.SVG_ICON, REGISTRY_KEYS.IS_PORT, REGISTRY_KEYS.IS_ABSTRACT];
    var FCO_REGISTRY_VALUES = {};
    FCO_REGISTRY_VALUES[REGISTRY_KEYS.DECORATOR] = "";
    FCO_REGISTRY_VALUES[REGISTRY_KEYS.SVG_ICON] = "";
    FCO_REGISTRY_VALUES[REGISTRY_KEYS.IS_PORT] = false;
    FCO_REGISTRY_VALUES[REGISTRY_KEYS.IS_ABSTRACT] = false;

    //these registry keys will be saved in the item's registry
    var _protectedRegistryKeys = [REGISTRY_KEYS.PROJECT_REGISTRY,
                                    REGISTRY_KEYS.META_SHEETS,
                                    REGISTRY_KEYS.IS_ABSTRACT,
                                    REGISTRY_KEYS.IS_PORT,
                                    REGISTRY_KEYS.DECORATOR,
                                    REGISTRY_KEYS.DISPLAY_FORMAT,
                                    REGISTRY_KEYS.POSITION,
                                    REGISTRY_KEYS.SVG_ICON
                                ];

    //these registry keys will be saved in the setmembers' registry
    var _protectedSetMemberRegistryKeys = [REGISTRY_KEYS.POSITION];

    function main () {
        var args = COMMON.getParameters(null);

        if (COMMON.getParameters("help") !== null) {
            console.log("Usage: node update_project.js [options]");
            console.log("");
            console.log("Updates the given branch to the latest webgme format. Possible options:");
            console.log("");
            console.log("  -mongo [database [host [port]]]\topens a mongo database");
            console.log("  -proj <project>\t\t\tselects the given project");
            console.log("  -branch <branch>\t\t\tthe branch to serialize");
            console.log("  -help\t\t\t\t\tprints out this help message");
            console.log("");
            return;
        }

        console.log('starting serialization',new Date());
        _outFile = args[0];

        _branch = COMMON.getParameters("branch");
        if (_branch) {
            _branch = _branch[0] || "parsed";
        } else {
            _branch = "master";
        }
        _projectName = COMMON.getParameters("proj");
        if(_projectName){
            _projectName = _projectName[0];
        }

        var done = TASYNC.call(COMMON.openDatabase);
        done = TASYNC.call(COMMON.openProject, done);
        var core = TASYNC.call(COMMON.getCore, done);
        if(!_startHash){
            if(_branch){
                _startHash = TASYNC.call(getRootHashOfBranch,_branch,done);
                TASYNC.call(settingCommitHashOfBranch,_branch,done);
            } else if(_commit){
                _startHash = TASYNC.call(getRootHashOfCommit,_commit,done);
            } else {
                done = TASYNC.call(COMMON.closeProject, done);
                done = TASYNC.call(COMMON.closeDatabase, done);
                return done;
            }
        }
        done = TASYNC.call(updateProject,core,_startHash);
        done = TASYNC.call(function(newhash){
            console.log('the root after serializing and normalizing:',newhash);
            console.log('the commit hash what we modified:',_commit);
            if(_commit){
                //we should make a commit
                var newCommit = makeCommit(newhash,_commit);
                if(_branch){
                    //we also should update the branch
                    return TASYNC.call(writeBranch,newCommit);
                } else {
                    return null;
                }
            } else {
                return null;
            }
        },done);
        done = TASYNC.call(COMMON.closeProject, done);
        done = TASYNC.call(COMMON.closeDatabase, done);
        done = TASYNC.call(function(){
            console.log('finished',new Date());
        },done);
        return done;
    }

    function makeCommit (rootHash, parentCommitHash) {
        var project = COMMON.getProject();
        return project.makeCommit([parentCommitHash], rootHash, "Updating project to be visible with latest webGME.");
    }

    function getRootHashOfBranch (branch){
        var project = COMMON.getProject();
        var commitHash = project.getBranchHash(branch,null);
        var done = TASYNC.call(project.loadObject,commitHash);
        done = TASYNC.call(function(object){
            console.log('getRootHashOfBranch',branch,object.root);
            _branch = branch;
            return object.root;
        },done);
        return done;
    }

    function settingCommitHashOfBranch (branch){
        var project = COMMON.getProject();
        var cHash = project.getBranchHash(branch,null);
        return TASYNC.call(function(hash){
            _commit = hash;
            return hash;
        },cHash);
    }

    function getRootHashOfCommit (commit){
        var project = COMMON.getProject();
        return TASYNC.call(function(object){
            console.log('getRootHashOfCommit',commit,object.root);
            return object.root;
        },TASYNC.call(project.loadObject,commit));
    }

    function writeBranch (hash) {
        var project = COMMON.getProject();
        var done = project.setBranchHash(_branch, _commit, hash);
        return TASYNC.call(function () {
            console.log("Commit " + hash + " written to branch " + _branch);
        }, done);
    }

    var __FCOID;
    function updateNode(core,node){ //TODO this method should be always up-to-date...
        if (!__FCOID) {
            __FCOID = core.getRegistry(core.getRoot(node), REGISTRY_KEYS.PROJECT_REGISTRY)[CONSTANTS.PROJECT_FCO_ID];
        }

        var objID = core.getPath(node,core.getRoot(node));
        var objName = objID + ' ('+core.getAttribute(node,"name")+"): ";
        console.log(objName);

        //clear item's global registry values
        var registryKeys = core.getRegistryNames(node) || [];
        var rk;
        var msg;

        //make sure that the FCO has all the necessary REGISTRY fields
        if (objID === __FCOID) {
            console.log("Checking project's FCO's registry:");
            var fcoRegKeyLen = FCO_REGISTRY_KEYS.length;

            while (fcoRegKeyLen--) {
                rk = FCO_REGISTRY_KEYS[fcoRegKeyLen];
                msg = '\t' + rk + ': ';
                if (registryKeys.indexOf(rk) !== -1) {
                    msg += 'OK';
                } else {
                    core.setRegistry(node, rk, FCO_REGISTRY_VALUES[rk]);
                    msg += 'was missing, created with value: "' + FCO_REGISTRY_VALUES[rk] + '"';
                }
                console.log(msg);
            }
        }
        var len = registryKeys.length;
        var removedRegKeys = "";
        while (len--) {
            //remove all that's not defined as protected
            rk = registryKeys[len];
            if (_protectedRegistryKeys.indexOf(rk) === -1) {
                core.delRegistry(node, rk);
                removedRegKeys += rk + ", ";
            }
        }
        if (removedRegKeys !== "") {
            console.log('\tRemoved node registry entries: ' + removedRegKeys);
        }

        //check if this node has any sets and remove the not protected set registry entries too
        var sets = core.getSetNames(node) || [];
        len = sets.length;
        var setMemberRegistryKeys;
        var set;
        var setMembers;
        var setMemberIdx;
        var setMemberRegKeysIdx;
        var sm;
        while (len--) {
            //remove all that's not defined as protected
            set = sets[len];
            setMembers = core.getMemberPaths(node, set) || [];
            setMemberIdx = setMembers.length;
            while (setMemberIdx--) {
                sm = setMembers[setMemberIdx];
                setMemberRegistryKeys = core.getMemberRegistryNames(node, set, sm) || [];
                setMemberRegKeysIdx = setMemberRegistryKeys.length;
                removedRegKeys = "";
                while (setMemberRegKeysIdx--) {
                    rk = setMemberRegistryKeys[setMemberRegKeysIdx];
                    if (_protectedSetMemberRegistryKeys.indexOf(rk) === -1) {
                        core.delMemberRegistry(node, set, sm, rk);
                        removedRegKeys += rk + ", ";
                    }
                }
                if (removedRegKeys !== "") {
                    console.log('\tRemoved set member registry entries for SET "' + set + '" and MEMBER "' + sm +  '": ' + removedRegKeys);
                }
            }
        }

        //insert newline
        console.log('\n');
    }
    function traverseNode (core,node){
        updateNode(core,node);
        var children = core.loadChildren(node);
        var traverseChildren = function(core,nodearray){
            var done;
            for(var i=0;i<nodearray.length;i++){
                done = TASYNC.call(traverseNode,core,nodearray[i],done);
            }
            return TASYNC.call(function(){return;},done);
        };
        return TASYNC.call(traverseChildren,core,children);
    }

    function updateProject(core,roothash){
        var root = core.loadRoot(roothash);
        var done = TASYNC.call(traverseNode,core,root);
        return TASYNC.call(saveChanges,core,root,done);
    }
    function saveChanges(core,root){
        console.log("Finalizing the update...");
        var done = core.persist(root);
        var hash = core.getHash(root);
        return TASYNC.join(hash, done);
    }

});

<|endoftext|>


<commit_before>/*
Copyright (c) 2013 William Malone (www.williammalone.com)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

/*global window */

var BLOCKS;

if (BLOCKS === undefined) {
	BLOCKS = {};
}

BLOCKS.container = function (game) {

	"use strict";

	var container = BLOCKS.eventDispatcher(),

		// Private Properties
		views = [],
		motors = [],

		// Private Methods
		motorDestroyed = function (motor) {

			var i;

			motor.removeEventListener("destroyed", motorDestroyed);

			for (i = 0 ; i < motors.length; i += 1)  {
				motors.splice(i, 1);
				break;
			}
		};

	// Public Properties
	container.visible = true;
	container.dirty = true;
	container.layers = {};

	// Public Methods
	container.assignLayer = function (name) {

		var i, key, found;

		if (container.layers[name]) {
			BLOCKS.error("Layer already assigned to this container: " + name);
		} else {

			for (i = 0; i < game.layers.length; i += 1) {

				found = false;
				for (key in container.layers) {
					if (container.layers.hasOwnProperty(key)) {
						if (game.layers[i] === container.layers[key]) {
							found = true;
							break;
						}
					}
				}
				if (!found) {
					container.layers[name] = game.layers[i];
					return container.layers[name];
				}
			}
		}
	};

	container.addView = function (view) {

		views.push(view);
	};

	container.removeView = function (view) {

		var i;

		for (i = 0; i < views.length; i += 1) {

			if (view === views[i]) {
				views.splice(i, 1);
				break;
			}
		}
	};

	container.clear = function () {

		var key;

		for (key in container.layers) {
			if (container.layers.hasOwnProperty(key)) {
				container.layers[key].clear();
			}
		}
	};

	container.motorize = function (motor) {

		motor.addEventListener("destroyed", motorDestroyed);
		motors.push(motor);
	};

	container.update = function () {

		var i;

		for (i = 0; i < views.length; i += 1) {
			views[i].update();
		}
	};

	container.render = function () {

		var i, key,
			dirtyLayers = {};

		if (container.visible) {

			for (i = 0; i < views.length; i += 1) {
				if (views[i].dirty || container.dirty || views[i].layer.dirty) {
					dirtyLayers[views[i].layer.name] = views[i].layer;
				}
			}

			for (key in dirtyLayers) {
				if (dirtyLayers.hasOwnProperty(key)) {
					dirtyLayers[key].clear();
				}
			}

			for (i = 0; i < views.length; i += 1) {
				if (dirtyLayers[views[i].layer.name]) {
					views[i].dirty = true;
				}
				views[i].render();
			}
		}

		container.dirty = false;
	};

	container.destroy = function () {

		var i;

		for (i = 0; i < views.length; i += 1) {
			views[i].destroy();
			views[i] = null;
		}
		views = null;
	};

	return container;
};<commit_msg>Layers without Views Set Dirty Now Clear<commit_after>/*
Copyright (c) 2013 William Malone (www.williammalone.com)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

/*global window */

var BLOCKS;

if (BLOCKS === undefined) {
	BLOCKS = {};
}

BLOCKS.container = function (game) {

	"use strict";

	var container = BLOCKS.eventDispatcher(),

		// Private Properties
		views = [],
		motors = [],

		// Private Methods
		motorDestroyed = function (motor) {

			var i;

			motor.removeEventListener("destroyed", motorDestroyed);

			for (i = 0 ; i < motors.length; i += 1)  {
				motors.splice(i, 1);
				break;
			}
		};

	// Public Properties
	container.visible = true;
	container.dirty = true;
	container.layers = {};

	// Public Methods
	container.assignLayer = function (name) {

		var i, key, found;

		if (container.layers[name]) {
			BLOCKS.error("Layer already assigned to this container: " + name);
		} else {

			for (i = 0; i < game.layers.length; i += 1) {

				found = false;
				for (key in container.layers) {
					if (container.layers.hasOwnProperty(key)) {
						if (game.layers[i] === container.layers[key]) {
							found = true;
							break;
						}
					}
				}
				if (!found) {
					container.layers[name] = game.layers[i];
					return container.layers[name];
				}
			}
		}
	};

	container.addView = function (view) {

		views.push(view);
	};

	container.removeView = function (view) {

		var i;

		for (i = 0; i < views.length; i += 1) {

			if (view === views[i]) {
				views.splice(i, 1);
				break;
			}
		}
	};

	container.clear = function () {

		var key;

		for (key in container.layers) {
			if (container.layers.hasOwnProperty(key)) {
				container.layers[key].clear();
			}
		}
	};

	container.motorize = function (motor) {

		motor.addEventListener("destroyed", motorDestroyed);
		motors.push(motor);
	};

	container.update = function () {

		var i;

		for (i = 0; i < views.length; i += 1) {
			views[i].update();
		}
	};

	container.render = function () {

		var i, key,
			dirtyLayers = {};

		if (container.visible) {

			// Check if any layers were set to dirty (or the container is dirty)
			for (key in container.layers) {
				if (container.layers.hasOwnProperty(key)) {
					if (container.layers[key].dirty || container.dirty) {
						dirtyLayers[key] = container.layers[key];
					}
				}
			}

			// Check if any views are dirty
			for (i = 0; i < views.length; i += 1) {
				if (views[i].dirty/* || container.dirty || views[i].layer.dirty*/) {
					dirtyLayers[views[i].layer.name] = views[i].layer;
				}
			}

			for (key in dirtyLayers) {
				if (dirtyLayers.hasOwnProperty(key)) {
					dirtyLayers[key].clear();
				}
			}

			for (i = 0; i < views.length; i += 1) {
				if (dirtyLayers[views[i].layer.name]) {
					views[i].dirty = true;
				}
				views[i].render();
			}
		}

		container.dirty = false;
	};

	container.destroy = function () {

		var i;

		for (i = 0; i < views.length; i += 1) {
			views[i].destroy();
			views[i] = null;
		}
		views = null;
	};

	return container;
};<|endoftext|>


<commit_before>(function() {

  // local vars for linting (and performance)
  var vendor = window.vendor;

  var VERSION = "0.5.2";

  // upper bar
  var logos = document.querySelectorAll(".group-logo");
  logos = Array.prototype.slice.call(logos);
  var recentButton = document.querySelector(".group-logo[data-group=recent]");
  var searchInput = document.getElementById("search");

  // group divs
  var groups = document.querySelectorAll(".group[data-emoji=true]");
  groups = Array.prototype.slice.call(groups);
  var recentDiv = document.getElementById("recent");
  var searchContainer = document.getElementById("search-container");

  // detail area
  var detailInput = document.getElementById("detail-input");
  var unicodeInput = document.getElementById("unicode-input");
  var detailLogo = document.getElementById("detail-logo");
  var aboutButton = document.getElementById("about-button");

  // recently used emojis
  var recent = [];

  // maximum number of recents
  var MAX_RECENT = 50;

  // maximum displayed search results for performance
  var MAX_SEARCH_RESULTS = 200;

  // very simple utility http get function
  function getJSON(url, cb) {
    var request = new XMLHttpRequest();
    request.open("GET", url, true);
    request.send();
    request.onreadystatechange = function() {
      if (request.readyState === 4) {
        cb(request.responseText);
      }
    };
  }

  // load emojis from json
  var emojis = [];
  getJSON("./sprite/sprite.json", function(res) {
    // flatten and objectify emojis
    var map = JSON.parse(res);
    Object.keys(map).forEach(function(group) {
      Object.keys(map[group]).forEach(function(k) {
        var emoji = map[group][k];
        emojis.push({
          name: k,
          unicode: emoji.unicode,
          pos: -emoji.x / 2 + "px " + -emoji.y / 2 + "px"
        });
      });
    });
  });

  // show an emoji in the bottom detail screen
  function showDetail(item) {
    detailLogo.style.backgroundPosition = item.pos;
    detailInput.value = ":" + item.name + ":";
    if(unicodeInput){
      unicodeInput.value = item.unicode;
    }
  }

  function addEmojiClickListener(node) {
    node.addEventListener('click', function() {
      var item = {
        name: node.dataset.name,
        unicode : node.dataset.unicode,
        pos: node.style.backgroundPosition
      };

      // save last in local storage
      vendor.setLocal('last', item);

      // set item in recent
      recent = [item].concat(recent.filter(function(el) {
        return el.name !== item.name;
      }));

      // remove last if number too high
      if (recent.length > MAX_RECENT) {
        recent.splice(MAX_RECENT, 1);
      }

      // persist recent
      vendor.setLocal('recent', recent);

      // show selected emoji in detail
      showDetail(item);
      vendor.copyToClipboard(detailInput);
    });
  }

  function appendItem(container, item) {
    var cont = document.createElement("div");
    cont.classList.add("emoji");
    cont.dataset.name = item.name;
    cont.dataset.unicode = item.unicode || "";
    cont.style.backgroundPosition = item.pos;

    addEmojiClickListener(cont);
    container.appendChild(cont);
  }

  function updateRecent() {
    recentDiv.innerHTML = "";

    // intermediate container to render the dom as few times as possible
    var cont = document.createElement("div");
    recent.forEach(appendItem.bind(null, cont));
    recentDiv.appendChild(cont);
  }

  groups.forEach(function(group) {
    var nodes = Array.prototype.slice.call(group.childNodes);
    nodes.forEach(addEmojiClickListener);
  });

  var setActiveGroup = (function() {
    // show first group
    var activeGroup = groups[0];
    activeGroup.style.display = "block";
    var activeLogo = logos[0];
    activeLogo.classList.add("selected");

    return function(logo) {
      if (activeLogo !== logo) {
        logo.classList.add("selected");
        activeLogo.classList.remove("selected");
        activeLogo = logo;
        var newActive = document.getElementById(logo.dataset.group);
        activeGroup.style.display = "none";
        newActive.style.display = "block";
        activeGroup = newActive;
      }
    };
  }());

  aboutButton.addEventListener('click', function() {
    setActiveGroup(aboutButton);
  });

  recentButton.addEventListener('click', updateRecent);

  // add click listener to logo that changes the displayed group
  logos.forEach(function(logo) {
    logo.addEventListener('click', setActiveGroup.bind(null, logo));
  });

  // search functionality
  (function() {
    var lastVal;
    searchInput.addEventListener("keyup", function() {
      setActiveGroup(searchInput);
      var val = searchInput.value;
      // prevent flickering
      setTimeout(function() {
        if (searchInput.value === val && val !== lastVal) {
          lastVal = val;
          searchContainer.innerHTML = "";

          // intermediate container to render the dom as few times as possible
          var cont = document.createElement("div");
          var filtered = emojis.filter(function(emoji) {
            return emoji.name.indexOf(val) !== -1;
          });
          filtered = filtered.slice(0, MAX_SEARCH_RESULTS);
          filtered.forEach(appendItem.bind(null, searchContainer));
          recentDiv.appendChild(cont);
        }
      }, 200);
    });
  }());

  // wait for plugin to be fully loaded before querying data
  window.addEventListener("load", function() {
    // get last used emoji from user locals and display
    vendor.getLocal("last", function(item) {
      if (item) {
        showDetail(item);
      }
    });

    // get recents from user locals
    vendor.getLocal("recent", function(rec) {
      if(rec && rec.length){
        recent = rec;
      }
      updateRecent();
    });

    // show info in blue when updated
    vendor.getLocal("version", function (ver) {
      if(ver !== VERSION){
        aboutButton.classList.add("update");
        aboutButton.addEventListener('click', function() {
          aboutButton.classList.remove("update");
          vendor.setLocal("version", VERSION);
        });
      }
    });

  }, false);

  var alphaNum = /[a-zA-Z0-9]/;
  document.addEventListener("keydown", function (event) {
    if(event.target === searchInput){
      return;
    }
    switch (event.keyCode) {
      case 49:
        // show recent
        updateRecent();
        setActiveGroup(logos[0]);
        break;
      case 50:
        // show people
        setActiveGroup(logos[1]);
        break;
      case 51:
        // show nature
        setActiveGroup(logos[2]);
        break;
      case 52:
        // show objects
        setActiveGroup(logos[3]);
        break;
      case 53:
        // show places
        setActiveGroup(logos[4]);
        break;
      case 54:
        // show symbols
        setActiveGroup(logos[5]);
        break;
      default:
        var str = String.fromCharCode(event.keyCode);
        if(alphaNum.test(str)){
          searchInput.value = "";
          searchInput.focus();
        }
        break;
    }
  });

}());
<commit_msg>more file path<commit_after>(function() {

  // local vars for linting (and performance)
  var vendor = window.vendor;

  var VERSION = "0.5.2";

  // upper bar
  var logos = document.querySelectorAll(".group-logo");
  logos = Array.prototype.slice.call(logos);
  var recentButton = document.querySelector(".group-logo[data-group=recent]");
  var searchInput = document.getElementById("search");

  // group divs
  var groups = document.querySelectorAll(".group[data-emoji=true]");
  groups = Array.prototype.slice.call(groups);
  var recentDiv = document.getElementById("recent");
  var searchContainer = document.getElementById("search-container");

  // detail area
  var detailInput = document.getElementById("detail-input");
  var unicodeInput = document.getElementById("unicode-input");
  var detailLogo = document.getElementById("detail-logo");
  var aboutButton = document.getElementById("about-button");

  // recently used emojis
  var recent = [];

  // maximum number of recents
  var MAX_RECENT = 50;

  // maximum displayed search results for performance
  var MAX_SEARCH_RESULTS = 200;

  // very simple utility http get function
  function getJSON(url, cb) {
    var request = new XMLHttpRequest();
    request.open("GET", url, true);
    request.send();
    request.onreadystatechange = function() {
      if (request.readyState === 4) {
        cb(request.responseText);
      }
    };
  }

  // load emojis from json
  var emojis = [];
  getJSON("./data/sprite.json", function(res) {
    // flatten and objectify emojis
    var map = JSON.parse(res);
    Object.keys(map).forEach(function(group) {
      Object.keys(map[group]).forEach(function(k) {
        var emoji = map[group][k];
        emojis.push({
          name: k,
          unicode: emoji.unicode,
          pos: -emoji.x / 2 + "px " + -emoji.y / 2 + "px"
        });
      });
    });
  });

  // show an emoji in the bottom detail screen
  function showDetail(item) {
    detailLogo.style.backgroundPosition = item.pos;
    detailInput.value = ":" + item.name + ":";
    if(unicodeInput){
      unicodeInput.value = item.unicode;
    }
  }

  function addEmojiClickListener(node) {
    node.addEventListener('click', function() {
      var item = {
        name: node.dataset.name,
        unicode : node.dataset.unicode,
        pos: node.style.backgroundPosition
      };

      // save last in local storage
      vendor.setLocal('last', item);

      // set item in recent
      recent = [item].concat(recent.filter(function(el) {
        return el.name !== item.name;
      }));

      // remove last if number too high
      if (recent.length > MAX_RECENT) {
        recent.splice(MAX_RECENT, 1);
      }

      // persist recent
      vendor.setLocal('recent', recent);

      // show selected emoji in detail
      showDetail(item);
      vendor.copyToClipboard(detailInput);
    });
  }

  function appendItem(container, item) {
    var cont = document.createElement("div");
    cont.classList.add("emoji");
    cont.dataset.name = item.name;
    cont.dataset.unicode = item.unicode || "";
    cont.style.backgroundPosition = item.pos;

    addEmojiClickListener(cont);
    container.appendChild(cont);
  }

  function updateRecent() {
    recentDiv.innerHTML = "";

    // intermediate container to render the dom as few times as possible
    var cont = document.createElement("div");
    recent.forEach(appendItem.bind(null, cont));
    recentDiv.appendChild(cont);
  }

  groups.forEach(function(group) {
    var nodes = Array.prototype.slice.call(group.childNodes);
    nodes.forEach(addEmojiClickListener);
  });

  var setActiveGroup = (function() {
    // show first group
    var activeGroup = groups[0];
    activeGroup.style.display = "block";
    var activeLogo = logos[0];
    activeLogo.classList.add("selected");

    return function(logo) {
      if (activeLogo !== logo) {
        logo.classList.add("selected");
        activeLogo.classList.remove("selected");
        activeLogo = logo;
        var newActive = document.getElementById(logo.dataset.group);
        activeGroup.style.display = "none";
        newActive.style.display = "block";
        activeGroup = newActive;
      }
    };
  }());

  aboutButton.addEventListener('click', function() {
    setActiveGroup(aboutButton);
  });

  recentButton.addEventListener('click', updateRecent);

  // add click listener to logo that changes the displayed group
  logos.forEach(function(logo) {
    logo.addEventListener('click', setActiveGroup.bind(null, logo));
  });

  // search functionality
  (function() {
    var lastVal;
    searchInput.addEventListener("keyup", function() {
      setActiveGroup(searchInput);
      var val = searchInput.value;
      // prevent flickering
      setTimeout(function() {
        if (searchInput.value === val && val !== lastVal) {
          lastVal = val;
          searchContainer.innerHTML = "";

          // intermediate container to render the dom as few times as possible
          var cont = document.createElement("div");
          var filtered = emojis.filter(function(emoji) {
            return emoji.name.indexOf(val) !== -1;
          });
          filtered = filtered.slice(0, MAX_SEARCH_RESULTS);
          filtered.forEach(appendItem.bind(null, searchContainer));
          recentDiv.appendChild(cont);
        }
      }, 200);
    });
  }());

  // wait for plugin to be fully loaded before querying data
  window.addEventListener("load", function() {
    // get last used emoji from user locals and display
    vendor.getLocal("last", function(item) {
      if (item) {
        showDetail(item);
      }
    });

    // get recents from user locals
    vendor.getLocal("recent", function(rec) {
      if(rec && rec.length){
        recent = rec;
      }
      updateRecent();
    });

    // show info in blue when updated
    vendor.getLocal("version", function (ver) {
      if(ver !== VERSION){
        aboutButton.classList.add("update");
        aboutButton.addEventListener('click', function() {
          aboutButton.classList.remove("update");
          vendor.setLocal("version", VERSION);
        });
      }
    });

  }, false);

  var alphaNum = /[a-zA-Z0-9]/;
  document.addEventListener("keydown", function (event) {
    if(event.target === searchInput){
      return;
    }
    switch (event.keyCode) {
      case 49:
        // show recent
        updateRecent();
        setActiveGroup(logos[0]);
        break;
      case 50:
        // show people
        setActiveGroup(logos[1]);
        break;
      case 51:
        // show nature
        setActiveGroup(logos[2]);
        break;
      case 52:
        // show objects
        setActiveGroup(logos[3]);
        break;
      case 53:
        // show places
        setActiveGroup(logos[4]);
        break;
      case 54:
        // show symbols
        setActiveGroup(logos[5]);
        break;
      default:
        var str = String.fromCharCode(event.keyCode);
        if(alphaNum.test(str)){
          searchInput.value = "";
          searchInput.focus();
        }
        break;
    }
  });

}());
<|endoftext|>


<commit_before>function $(id) {
  return document.getElementById(id);
}

function $input(id) {
  return /** @type {HTMLInputElement} */ ($(id));
}

/**
 * Splits text like "Your hand: Copper, Silver, Gold"
 * Into text and colored span elements
 * @param {string} text
 */
function log(text) {
  // Splits text like /
  const parts = /** @type {string[]} */ ([]);
  const regex = new RegExp(colorBreak); // Copy to allow exec iteration
  let match = null;
  let prevIndex = 0;
  while ((match = regex.exec(text)) !== null) {
    parts.push(text.substring(prevIndex, match.index));
    parts.push(match["0"]);
    prevIndex = match.index + match["0"].length;
  }
  parts.push(text.substring(prevIndex, text.length));

  const elems = parts.map(t => {
    const color = colors[t];
    if (!color) {
      return t;
    }
    const span = document.createElement("span");
    span.textContent = t;
    span.style.color = color;
    span.style.fontWeight = "bold";
    return span;
  });

  $("log").append(...elems, document.createElement("br"));
  $("log").scrollTop = $("log").scrollHeight;
}

/**
 * @param {string} cardName
 * @param {HTMLElement} e
 */
function addCardImage(cardName, e) {
  const jpg = document.createElement("img");
  jpg.style.width = "200";
  jpg.style.maxWidth = "50%";
  jpg.style.height = "auto";
  jpg.src = `/cards/${cardName}.jpg`;
  e.appendChild(jpg);
}

/**
 * @param {Object<string, string[]>} data
 * @param {WebSocket} ws
 */
function addManage(data, ws) {
  const CARD_COUNT = 10;

  const manageDiv = $("manage");

  const options = Object.values(data).flatMap(d => d);

  for (const set in data) {
    const setOptions = data[set];
    if (!setOptions.length) {
      continue;
    }

    const setHeader = document.createElement("span");
    setHeader.textContent = set;
    setHeader.style.color = "grey";
    manageDiv.append(setHeader);
    manageDiv.appendChild(document.createElement("br"));

    for (const option of setOptions) {
      const box = document.createElement("input");
      box.setAttribute("type", "checkbox");
      box.setAttribute("id", "optional" + option);

      const label = document.createElement("label");
      label.style.whiteSpace = "nowrap";
      label.append(box, option);
      manageDiv.append(label, " ");
    }

    manageDiv.appendChild(document.createElement("br"));
  }

  const randomButton = document.createElement("button");
  randomButton.innerText = "Randomize";
  randomButton.onclick = () => {
    const randomOptions = options.slice();
    while (randomOptions.length > CARD_COUNT) {
      randomOptions.splice(Math.floor(Math.random() * randomOptions.length), 1);
    }
    options.forEach(n => {
      $input("optional" + n).checked = Boolean(randomOptions.includes(n));
    });
  };
  manageDiv.appendChild(randomButton);

  const clearButton = document.createElement("button");
  clearButton.innerText = "Clear";
  clearButton.onclick = () => {
    options.forEach(n => $input("optional" + n).checked = false);
  };
  manageDiv.appendChild(clearButton);

  const countText = document.createElement("span");
  countText.innerText = "0 Selected";
  manageDiv.onclick = () => {
    const optionsChecked = options.filter(n => $input("optional" + n).checked);
    countText.innerText = `${optionsChecked.length} Selected`;

    if (optionsChecked.length === CARD_COUNT) {
      startButton.style.color = "black";
      startButton.style.fontWeight = "bold";
    } else {
      startButton.style.color = "darkgrey";
      startButton.style.fontWeight = "";
      // Button still works if you want to try on nonstandard game, but looks disabled
    }

    const helpSelected = $("helpSelected");
    if (!helpSelected) {
      return;
    }
    while (helpSelected.firstElementChild) {
      helpSelected.removeChild(helpSelected.firstElementChild);
    }
    optionsChecked.forEach(c => addCardImage(c, helpSelected));
    helpSelected.style.marginBottom = optionsChecked.length ? "20px" : "";
  };
  manageDiv.appendChild(countText);

  const startButton = document.createElement("button");
  startButton.innerHTML = "Start";
  startButton.onclick = e => {
    const included = options.filter(n => $input("optional" + n).checked);
    const debugMode = $input("debugMode").checked;

    while (manageDiv.firstChild) {
      manageDiv.removeChild(manageDiv.firstChild);
    }

    ws.send(JSON.stringify({gameStart: {included, debugMode}}));

    e.stopPropagation();
  };

  manageDiv.appendChild(startButton);

  const debugBox = document.createElement("input");
  debugBox.setAttribute("type", "checkbox");
  debugBox.setAttribute("id", "debugMode");
  manageDiv.appendChild(debugBox);

  const debugLabel = document.createElement("label");
  debugLabel.innerText = "Debug";
  debugLabel.htmlFor = "debugMode";
  manageDiv.appendChild(debugLabel);
}

function updateChoicesDisabled() {
  const disabled = !$input("name").value;
  for (const button of $("choices").children) {
    const input = /** @type {HTMLInputElement} */ (button);
    input.disabled = disabled;
  }
}

let colors = {};
let colorBreak = /(?=a)b/; // null regex which won't match anything
window.onload = () => {
  const address = window.location.href.replace("http", "ws");
  const name = $input("name");
  name.value = localStorage.getItem("name") || "";
  name.addEventListener("input", () => {
    localStorage.setItem("name", name.value);
    ws.send(JSON.stringify({name: name.value}));

    updateChoicesDisabled();
  });

  const helpOverlay = $("helpOverlay");
  helpOverlay.onclick = () => helpOverlay.style.display = "none";
  $("help").onclick = () => helpOverlay.style.display = "";

  let turnAlert;
  const chat = $input("chat");
  const ws = new WebSocket(address);
  ws.addEventListener("open", () => {
    log("Connected to Server");
    chat.disabled = false;
    ws.send(JSON.stringify({name: name.value}));
  });
  ws.addEventListener("close", () => {
    log("Connection to Server lost");
    chat.disabled = true;
  });
  ws.addEventListener("message", e => {
    let data = JSON.parse(e.data);
    const type = Object.keys(data)[0];
    data = data[type];

    switch (type) {
    case "message":
      log(data);
      break;
    case "choices":
      const choicesDiv = $("choices");
      const choiceOnClick = event => {
        ws.send(JSON.stringify({choice: event.target.innerHTML}));
        while (choicesDiv.firstChild) {
          choicesDiv.removeChild(choicesDiv.firstChild);
        }
      };
      for (const choice of data) {
        if (choice === "\n") {
          choicesDiv.appendChild(document.createElement("br"));
        } else {
          const button = document.createElement("button");
          button.innerHTML = choice;
          const color = colors[choice];
          if (color) {
            button.style.color = color;
          }
          button.style.fontWeight = "bold";
          button.onclick = choiceOnClick;
          choicesDiv.appendChild(button);
        }
      }
      updateChoicesDisabled();
      $("log").scrollTop = $("log").scrollHeight;
      if (document.hasFocus && !document.hasFocus()) {
        if (!turnAlert) {
          turnAlert = new Audio("Computer Error Alert from SoundBible.com.mp3");
        }
        // Audio need to reload sound before each play
        // http://stackoverflow.com/a/8959342/771768
        turnAlert.load();
        turnAlert.play().catch(_ => {/* whatever*/});
      }
      break;
    case "isLeader":
      addManage(data, ws);
      break;
    case "colors":
      colors = data;
      // Create a regex like \bCopper|Silver|Gold\b
      colorBreak = new RegExp(`\\b${Object.keys(colors).join("|")}\\b`, "g");
      break;
    case "included":
      while (helpOverlay.firstElementChild) {
        helpOverlay.removeChild(helpOverlay.firstElementChild);
      }

      const helpSelected = document.createElement("div");
      helpSelected.id = "helpSelected";
      helpOverlay.append(helpSelected);

      data.forEach(cardName => addCardImage(cardName, helpOverlay));
      break;
    default:
      throw new Error("Not implemented: " + type);
    }
  });
  chat.addEventListener("keydown", e => {
    if (ws && ws.readyState === 1 && e.keyCode === 13) {
      ws.send(JSON.stringify({chat: chat.value}));
      chat.value = "";
    }
  });
};

// Maybe remove this after winning each game, then restore?
window.onbeforeunload = e => "Don't leave the game hanging!";
<commit_msg>store options in browser storage<commit_after>function $(id) {
  return document.getElementById(id);
}

function $input(id) {
  return /** @type {HTMLInputElement} */ ($(id));
}

/**
 * Splits text like "Your hand: Copper, Silver, Gold"
 * Into text and colored span elements
 * @param {string} text
 */
function log(text) {
  // Splits text like /
  const parts = /** @type {string[]} */ ([]);
  const regex = new RegExp(colorBreak); // Copy to allow exec iteration
  let match = null;
  let prevIndex = 0;
  while ((match = regex.exec(text)) !== null) {
    parts.push(text.substring(prevIndex, match.index));
    parts.push(match["0"]);
    prevIndex = match.index + match["0"].length;
  }
  parts.push(text.substring(prevIndex, text.length));

  const elems = parts.map(t => {
    const color = colors[t];
    if (!color) {
      return t;
    }
    const span = document.createElement("span");
    span.textContent = t;
    span.style.color = color;
    span.style.fontWeight = "bold";
    return span;
  });

  $("log").append(...elems, document.createElement("br"));
  $("log").scrollTop = $("log").scrollHeight;
}

/**
 * @param {string} cardName
 * @param {HTMLElement} e
 */
function addCardImage(cardName, e) {
  const jpg = document.createElement("img");
  jpg.style.width = "200";
  jpg.style.maxWidth = "50%";
  jpg.style.height = "auto";
  jpg.src = `/cards/${cardName}.jpg`;
  e.appendChild(jpg);
}

/**
 * @param {Object<string, string[]>} data
 * @param {WebSocket} ws
 */
function addManage(data, ws) {
  const CARD_COUNT = 10;

  const manageDiv = $("manage");

  const options = Object.values(data).flatMap(d => d);
  let optionsFromStorage = [];
  try {
    optionsFromStorage = JSON.parse(localStorage.getItem("options"));
  } catch (e) {
    // If for some reason this fails, it's not important to warn the user.
  }
  const optionSet = new Set(optionsFromStorage);

  for (const set in data) {
    const setOptions = data[set];
    if (!setOptions.length) {
      continue;
    }

    const setHeader = document.createElement("span");
    setHeader.textContent = set;
    setHeader.style.color = "grey";
    manageDiv.append(setHeader);
    manageDiv.appendChild(document.createElement("br"));

    for (const option of setOptions) {
      const box = document.createElement("input");
      box.setAttribute("type", "checkbox");
      box.setAttribute("id", "optional" + option);
      box.checked = optionSet.has(option);

      const label = document.createElement("label");
      label.style.whiteSpace = "nowrap";
      label.append(box, option);
      manageDiv.append(label, " ");
    }

    manageDiv.appendChild(document.createElement("br"));
  }

  const randomButton = document.createElement("button");
  randomButton.innerText = "Randomize";
  randomButton.onclick = () => {
    const randomOptions = options.slice();
    while (randomOptions.length > CARD_COUNT) {
      randomOptions.splice(Math.floor(Math.random() * randomOptions.length), 1);
    }
    options.forEach(n => {
      $input("optional" + n).checked = Boolean(randomOptions.includes(n));
    });
  };
  manageDiv.appendChild(randomButton);

  const clearButton = document.createElement("button");
  clearButton.innerText = "Clear";
  clearButton.onclick = () => {
    options.forEach(n => $input("optional" + n).checked = false);
  };
  manageDiv.appendChild(clearButton);

  const countText = document.createElement("span");
  countText.innerText = "0 Selected";
  manageDiv.onclick = () => {
    const optionsChecked = options.filter(n => $input("optional" + n).checked);
    countText.innerText = `${optionsChecked.length} Selected`;

    if (optionsChecked.length === CARD_COUNT) {
      startButton.style.color = "black";
      startButton.style.fontWeight = "bold";
    } else {
      startButton.style.color = "darkgrey";
      startButton.style.fontWeight = "";
      // Button still works if you want to try on nonstandard game, but looks disabled
    }

    const helpSelected = $("helpSelected");
    if (!helpSelected) {
      return;
    }
    while (helpSelected.firstElementChild) {
      helpSelected.removeChild(helpSelected.firstElementChild);
    }
    optionsChecked.forEach(c => addCardImage(c, helpSelected));
    helpSelected.style.marginBottom = optionsChecked.length ? "20px" : "";

    localStorage.setItem("options", JSON.stringify(optionsChecked));
  };
  manageDiv.appendChild(countText);

  const startButton = document.createElement("button");
  startButton.innerHTML = "Start";
  startButton.onclick = e => {
    const included = options.filter(n => $input("optional" + n).checked);
    const debugMode = $input("debugMode").checked;

    while (manageDiv.firstChild) {
      manageDiv.removeChild(manageDiv.firstChild);
    }

    ws.send(JSON.stringify({gameStart: {included, debugMode}}));

    e.stopPropagation();
  };

  manageDiv.appendChild(startButton);

  const debugBox = document.createElement("input");
  debugBox.setAttribute("type", "checkbox");
  debugBox.setAttribute("id", "debugMode");
  manageDiv.appendChild(debugBox);

  const debugLabel = document.createElement("label");
  debugLabel.innerText = "Debug";
  debugLabel.htmlFor = "debugMode";
  manageDiv.appendChild(debugLabel);
}

function updateChoicesDisabled() {
  const disabled = !$input("name").value;
  for (const button of $("choices").children) {
    const input = /** @type {HTMLInputElement} */ (button);
    input.disabled = disabled;
  }
}

let colors = {};
let colorBreak = /(?=a)b/; // null regex which won't match anything
window.onload = () => {
  const address = window.location.href.replace("http", "ws");
  const name = $input("name");
  name.value = localStorage.getItem("name") || "";
  name.addEventListener("input", () => {
    localStorage.setItem("name", name.value);
    ws.send(JSON.stringify({name: name.value}));

    updateChoicesDisabled();
  });

  const helpOverlay = $("helpOverlay");
  helpOverlay.onclick = () => helpOverlay.style.display = "none";
  $("help").onclick = () => helpOverlay.style.display = "";

  let turnAlert;
  const chat = $input("chat");
  const ws = new WebSocket(address);
  ws.addEventListener("open", () => {
    log("Connected to Server");
    chat.disabled = false;
    ws.send(JSON.stringify({name: name.value}));
  });
  ws.addEventListener("close", () => {
    log("Connection to Server lost");
    chat.disabled = true;
  });
  ws.addEventListener("message", e => {
    let data = JSON.parse(e.data);
    const type = Object.keys(data)[0];
    data = data[type];

    switch (type) {
    case "message":
      log(data);
      break;
    case "choices":
      const choicesDiv = $("choices");
      const choiceOnClick = event => {
        ws.send(JSON.stringify({choice: event.target.innerHTML}));
        while (choicesDiv.firstChild) {
          choicesDiv.removeChild(choicesDiv.firstChild);
        }
      };
      for (const choice of data) {
        if (choice === "\n") {
          choicesDiv.appendChild(document.createElement("br"));
        } else {
          const button = document.createElement("button");
          button.innerHTML = choice;
          const color = colors[choice];
          if (color) {
            button.style.color = color;
          }
          button.style.fontWeight = "bold";
          button.onclick = choiceOnClick;
          choicesDiv.appendChild(button);
        }
      }
      updateChoicesDisabled();
      $("log").scrollTop = $("log").scrollHeight;
      if (document.hasFocus && !document.hasFocus()) {
        if (!turnAlert) {
          turnAlert = new Audio("Computer Error Alert from SoundBible.com.mp3");
        }
        // Audio need to reload sound before each play
        // http://stackoverflow.com/a/8959342/771768
        turnAlert.load();
        turnAlert.play().catch(_ => {/* whatever*/});
      }
      break;
    case "isLeader":
      addManage(data, ws);
      break;
    case "colors":
      colors = data;
      // Create a regex like \bCopper|Silver|Gold\b
      colorBreak = new RegExp(`\\b${Object.keys(colors).join("|")}\\b`, "g");
      break;
    case "included":
      while (helpOverlay.firstElementChild) {
        helpOverlay.removeChild(helpOverlay.firstElementChild);
      }

      const helpSelected = document.createElement("div");
      helpSelected.id = "helpSelected";
      helpOverlay.append(helpSelected);

      data.forEach(cardName => addCardImage(cardName, helpOverlay));
      break;
    default:
      throw new Error("Not implemented: " + type);
    }
  });
  chat.addEventListener("keydown", e => {
    if (ws && ws.readyState === 1 && e.keyCode === 13) {
      ws.send(JSON.stringify({chat: chat.value}));
      chat.value = "";
    }
  });
};

// Maybe remove this after winning each game, then restore?
window.onbeforeunload = e => "Don't leave the game hanging!";
<|endoftext|>


<commit_before>function type$meta(x,$$targs$$) {
  if (x===null){
    return AppliedClass$jsint($_null(),{Type$AppliedClass:{t:Null},Arguments$AppliedClass:{t:Empty}});
  }
  if ($$targs$$.Type$type.t===Nothing) {
    return nothingType$meta$model();
  }
  if (x===true||x===false) {
    var cls=x?$_true:$_false;
    return AppliedClass$jsint(cls,{Type$AppliedClass:{t:cls},Arguments$AppliedClass:{t:Empty}});
  }
  var mm=getrtmm$$(x);
  var _t=$$targs$$.Type$type.t;
  if (mm===undefined) {
    if (x.getT$name && x.getT$all) {
      var mmm=x.getT$all()[x.getT$name()];
      if (mmm){mm=mmm.$crtmm$;_t=mmm;}
      if (typeof(mm)==='function') {
        mm=mm(); mmm.$crtmm$=mm;
      }
    }
  }
  if (mm===undefined&&x.rt$)mm=$_Array.$crtmm$;
  if (mm===undefined)throw new Error("Cannot retrieve metamodel for " + x);
  var _cntr=mm.$cont ? get_model(getrtmm$$(mm.$cont)) : undefined;
  var _classOrInterfaceMember = _cntr && (_cntr.mt==='c' || _cntr.mt==='i' || _cntr.mt==='o');
  if (mm.$t) { //it's a value
    if (typeof(x)==='function') { //It's a callable
      if (_classOrInterfaceMember) {
        return AppliedMethod$jsint(x,undefined,{Type$AppliedMethod:mm.$t,Arguments$AppliedMethod:{t:Nothing},Container$AppliedMethod:{t:mm.$cont}});
      }
      return AppliedFunction$jsint(x,{Type$Function:mm.$t,Arguments$Function:{t:Nothing}});
    }
    var rv=_classOrInterfaceMember?AppliedMemberClass$jsint(mm.$t.t, {Type$AppliedMemberClass:mm.$t,Arguments$AppliedMemberClass:{t:Nothing},Container$AppliedMemberClass:{t:mm.$cont}})
           : AppliedClass$jsint(mm.$t.t, {Type$AppliedClass:mm.$t,Arguments$AppliedClass:{t:Nothing}});
    rv.src$=x;
    return rv;
  }
  var c;
  if ($$targs$$.Type$type.t==='T') {
    var rt=retpl$($$targs$$.Type$type);
    c=AppliedClass$jsint(Tuple,{Type$AppliedClass:$$targs$$.Type$type, Arguments$AppliedClass:{t:'T',l:[$$targs$$.Type$type.l[0],rt.Rest$Tuple]}});
  } else {
    var _ta={T:{t:x.getT$all()[x.getT$name()]}, A:{t:Sequential,a:{Element$Iterable:{t:Anything}}}};
    if (x.$$targs$$)_ta.T.a=x.$$targs$$;
    if (x.outer$) {
      _ta.C={t:x.outer$.getT$all()[x.outer$.getT$name()]};
      if (x.outer$.$$targs$$)_ta.C.a=x.outer$.$$targs$$;
    }
    if (_classOrInterfaceMember) {
      c=AppliedMemberClass$jsint(_t, {Type$AppliedMemberClass:_ta.T,Arguments$AppliedMemberClass:_ta.A,Container$AppliedMemberClass:_ta.C});
    } else {
      c=AppliedClass$jsint(_t, {Type$AppliedClass:_ta.T,Arguments$AppliedClass:_ta.A});
    }
  }
  if ($$targs$$.Type$type.a)c.$targs=$$targs$$.Type$type.a;
  c.src$=x;
  return c;
}
<commit_msg>pass type arguments to member class<commit_after>function type$meta(x,$$targs$$) {
  if (x===null){
    return AppliedClass$jsint($_null(),{Type$AppliedClass:{t:Null},Arguments$AppliedClass:{t:Empty}});
  }
  if ($$targs$$.Type$type.t===Nothing) {
    return nothingType$meta$model();
  }
  if (x===true||x===false) {
    var cls=x?$_true:$_false;
    return AppliedClass$jsint(cls,{Type$AppliedClass:{t:cls},Arguments$AppliedClass:{t:Empty}});
  }
  var mm=getrtmm$$(x);
  var _t=$$targs$$.Type$type.t;
  if (mm===undefined) {
    if (x.getT$name && x.getT$all) {
      var mmm=x.getT$all()[x.getT$name()];
      if (mmm){mm=mmm.$crtmm$;_t=mmm;}
      if (typeof(mm)==='function') {
        mm=mm(); mmm.$crtmm$=mm;
      }
    }
  }
  if (mm===undefined&&x.rt$)mm=$_Array.$crtmm$;
  if (mm===undefined)throw new Error("Cannot retrieve metamodel for " + x);
  var _cntr=mm.$cont ? get_model(getrtmm$$(mm.$cont)) : undefined;
  var _classOrInterfaceMember = _cntr && (_cntr.mt==='c' || _cntr.mt==='i' || _cntr.mt==='o');
  if (mm.$t) { //it's a value
    if (typeof(x)==='function') { //It's a callable
      if (_classOrInterfaceMember) {
        return AppliedMethod$jsint(x,undefined,{Type$AppliedMethod:mm.$t,Arguments$AppliedMethod:{t:Nothing},Container$AppliedMethod:{t:mm.$cont}});
      }
      return AppliedFunction$jsint(x,{Type$Function:mm.$t,Arguments$Function:{t:Nothing}});
    }
    var rv=_classOrInterfaceMember?AppliedMemberClass$jsint(mm.$t.t, {Type$AppliedMemberClass:mm.$t,Arguments$AppliedMemberClass:{t:Nothing},Container$AppliedMemberClass:{t:mm.$cont}})
           : AppliedClass$jsint(mm.$t.t, {Type$AppliedClass:mm.$t,Arguments$AppliedClass:{t:Nothing}});
    rv.src$=x;
    return rv;
  }
  var c;
  if ($$targs$$.Type$type.t==='T') {
    var rt=retpl$($$targs$$.Type$type);
    c=AppliedClass$jsint(Tuple,{Type$AppliedClass:$$targs$$.Type$type, Arguments$AppliedClass:{t:'T',l:[$$targs$$.Type$type.l[0],rt.Rest$Tuple]}});
  } else {
    var _ta={T:{t:x.getT$all()[x.getT$name()]}, A:{t:Sequential,a:{Element$Iterable:{t:Anything}}}};
    var mytargs;
    if (x.$$targs$$) {
      _ta.T.a=x.$$targs$$;
    }
    if (x.outer$) {
      _ta.C={t:x.outer$.getT$all()[x.outer$.getT$name()]};
      if (x.outer$.$$targs$$)_ta.C.a=x.outer$.$$targs$$;
      mytargs={};
      for (ta in x.$$targs$$)mytargs[ta]=x.$$targs$$[ta];
      var ou=x.outer$;
      while (ou) {
        if (ou.$$targs$$) {
          for (ta in ou.$$targs$$)mytargs[ta]=ou.$$targs$$[ta];
        }
        ou=ou.outer$;
      }
    }
    if (_classOrInterfaceMember) {
      c=AppliedMemberClass$jsint(_t, {Type$AppliedMemberClass:_ta.T,Arguments$AppliedMemberClass:_ta.A,Container$AppliedMemberClass:_ta.C},undefined,mytargs);
    } else {
      c=AppliedClass$jsint(_t, {Type$AppliedClass:_ta.T,Arguments$AppliedClass:_ta.A},undefined,x.$$targs$$);
    }
  }
  if ($$targs$$.Type$type.a)c.$targs=$$targs$$.Type$type.a;
  c.src$=x;
  return c;
}
<|endoftext|>


<commit_before>import Ember from 'ember';
import DS from 'ember-data';
import IdProxy from '../utils/idproxy';

var Model = DS.Model.extend({
  primaryKey: Ember.computed('id', {
    get: function() {
      var id = this.get('id');
      if (id === null) {
        // id isn't setted in newly created records.
        return null;
      }

      if (IdProxy.idIsProxied(id)) {
        return IdProxy.retrieve(id).id;
      } else {
        return id;
      }
    }
  }),

  projection: Ember.computed('id', {
    get: function() {
      var id = this.get('id');
      if (id === null) {
        // id isn't setted in newly created records.
        return null;
      }

      if (IdProxy.idIsProxied(id, this.constructor)) {
        return IdProxy.retrieve(id).projection;
      } else {
        return null;
      }
    }
  })
});

Model.reopenClass({
  /**
   * Define Model Projections here using
   * ModelProjectionsCollection and ModelProjection classes.
   */
  Projections: null
});

export default Model;
<commit_msg>Fix projected-model due to wrong idproxy call<commit_after>import Ember from 'ember';
import DS from 'ember-data';
import IdProxy from '../utils/idproxy';

var Model = DS.Model.extend({
  primaryKey: Ember.computed('id', {
    get: function() {
      var id = this.get('id');
      if (id === null) {
        // id isn't setted in newly created records.
        return null;
      }

      if (IdProxy.idIsProxied(id)) {
        return IdProxy.retrieve(id).id;
      } else {
        return id;
      }
    }
  }),

  projection: Ember.computed('id', {
    get: function() {
      var id = this.get('id');
      if (id === null) {
        // id isn't setted in newly created records.
        return null;
      }

      if (IdProxy.idIsProxied(id)) {
        return IdProxy.retrieve(id, this.constructor).projection;
      } else {
        return null;
      }
    }
  })
});

Model.reopenClass({
  /**
   * Define Model Projections here using
   * ModelProjectionsCollection and ModelProjection classes.
   */
  Projections: null
});

export default Model;
<|endoftext|>


<commit_before>#!/usr/bin/env node

require('./proof')(1, function (step, Strata, tmp, serialize, gather, deepEqual) {
    var strata = new Strata({
        directory: tmp,
        branchSize: 3,
        leafSize: 3,
        readRecordStartLength: 2
    })
    step(function () {
        serialize(__dirname + '/fixtures/read-record.before.json', tmp, step())
    }, function () {
        strata.open(step())
    }, function () {
        gather(step, strata)
    }, function (records) {
        deepEqual(records, [ 'a', 'c', 'd' ], 'records')
    }, function () {
        strata.close(step())
    })
})
<commit_msg>Use `assert` in `read-record-overflow.t.js`.<commit_after>#!/usr/bin/env node

require('./proof')(1, function (step, Strata, tmp, serialize, gather, assert) {
    var strata = new Strata({
        directory: tmp,
        branchSize: 3,
        leafSize: 3,
        readRecordStartLength: 2
    })
    step(function () {
        serialize(__dirname + '/fixtures/read-record.before.json', tmp, step())
    }, function () {
        strata.open(step())
    }, function () {
        gather(step, strata)
    }, function (records) {
        assert(records, [ 'a', 'c', 'd' ], 'records')
    }, function () {
        strata.close(step())
    })
})
<|endoftext|>


<commit_before><commit_msg>forgot exports<commit_after><|endoftext|>