<commit_before>window.model = (function () {

    var STATUS = {
        pass: "PASS",
        fail: "FAIL",
        notRun: "NOT RUN"
    };

    var KEYWORD_TYPE = {
        kw: 'KEYWORD',
        setup:'SETUP',
        teardown:'TEARDOWN'
    };

    function Suite(data) {
        var suite = createModelObject(data);
        suite.source = data.source;
        suite.fullName = data.parent ? data.parent.fullName + "." + data.name : data.name;
        setStats(suite, data.statistics);
        suite.metadata = data.metadata;
        suite.populateKeywords = createIterablePopulator("Keyword");
        suite.populateTests = createIterablePopulator("Test");
        suite.populateSuites = createIterablePopulator("Suite");
        suite.message = data.message;
        suite.children = function () {
            return suite.keywords().concat(suite.tests()).concat(suite.suites());
        };
        suite.hasTeardownFailure = function () {
            return suiteTeardownFailed(suite) || data.parentSuiteTeardownFailed;
        };
        suite.searchTests = function (predicate) {
            var tests = [];
            var subSuites = this.suites();
            for (var i in subSuites)
                tests = tests.concat(subSuites[i].searchTests(predicate));
            return tests.concat(util.filter(this.tests(), predicate));
        };
        suite.searchTestsByTag = function (tag) {
            return suite.searchTests(function (test) {
                if (tag.combined)
                    return containsTagPattern(test.tags, tag.combined);
                return containsTag(test.tags, tag.label);
            });
        };
        suite.findSuiteByName = function (name) {
            return findSuiteByName(suite, name);
        };
        suite.allTests = function () {
            return suite.searchTests(function (test) {
                return true;
            });
        };
        suite.criticalTests = function () {
            return suite.searchTests(function (test) {
                return test.isCritical;
            });
        };
        return suite;
    }

    function containsTag(testTags, tagname) {
        testTags = util.map(testTags, util.normalize);
        return util.contains(testTags, util.normalize(tagname));
    }

    function containsTagPattern(testTags, pattern) {
        testTags = util.map(testTags, util.normalize);
        if (pattern.indexOf('&') != -1) {
            var tagnames = pattern.split('&');
            return util.all(util.map(tagnames, function (name) {
                return containsTagPattern(testTags, name);
            }));
        }
        if (pattern.indexOf('NOT') != -1) {
            var tagnames = pattern.split('NOT');
            var required = tagnames[0];
            var notAllowed = tagnames.slice(1);
            return containsTagPattern(testTags, required) &&
                    util.all(util.map(notAllowed, function (name) {
                        return !containsTagPattern(testTags, name);
                    }));
        }
        var matcher = util.Matcher(pattern);
        return util.any(util.map(testTags, matcher.matches));
    }

    function findSuiteByName(suite, name) {
        if (suite.fullName == name)
            return suite;
        var subSuites = suite.suites();
        for (var i in subSuites) {
            var match = findSuiteByName(subSuites[i], name);
            if (match)
                return match;
        }
        return null;
    }

    function suiteTeardownFailed(suite) {
        var keywords = suite.keywords();
        var maybeTeardown = keywords[keywords.length - 1];
        if (maybeTeardown && maybeTeardown.type == KEYWORD_TYPE.teardown)
            return maybeTeardown.status == STATUS.fail;
        return false;
    }

    function setStats(suite, stats) {
        for (var name in stats) {
            suite[name] = stats[name];
        }
    }

    function createModelObject(data) {
        return {
            name: data.name,
            doc: data.doc,
            status: data.status,
            times: data.times,
            callWhenChildrenReady: function (callable) { callable(); }
        };
    }

    function Test(data) {
        var test = createModelObject(data);
        test.fullName = data.parent.fullName + "." + test.name;
        test.formatParentName = function () { return util.formatParentName(test); };
        test.timeout = data.timeout;
        test.populateKeywords = createIterablePopulator("Keyword");
        test.isChildrenLoaded = data.isChildrenLoaded;
        // TODO: Should callable handling be in loadTestKeywordsFile function?
        var callables = [];
        test.callWhenChildrenReady = function (callable) {
            if (!test.isChildrenLoaded) {
                callables.push(callable);
                if (callables.length == 1) {
                    window.fileLoading.load(test.childFileName, function () {
                        test.isChildrenLoaded = true;
                        for (var i = 0; i < callables.length; i++) {
                            callables[i]();
                        };
                    });
                }
            } else {
                callable();
            }
        };
        test.children = function () {
            if (test.isChildrenLoaded)
                return test.keywords();

        };
        test.isCritical = data.isCritical;
        test.tags = data.tags;
        test.message = data.message;
        return test;
    }

    function Keyword(data) {
        var kw = createModelObject(data);
        kw.type = data.type;
        var parent = data.parent
        var parentPath = (parent.path === undefined) ? parent.fullName : parent.path;
        kw.path = parentPath + "." + data.index;
        kw.arguments = data.args;
        kw.timeout = data.timeout;
        kw.populateKeywords = createIterablePopulator("Keyword");
        kw.populateMessages = createIterablePopulator("Message");
        kw.children = function () {
            return kw.keywords();
        };
        return kw;
    }

    function Message(level, time, text, link) {
        var message = {};
        message.level = level;
        message.levelText = level.toUpperCase();
        message.time = time;
        message.shortTime = function () {
            return timeFromDate(message.time);
        };
        message.date = function () {
            return formatDate(message.time);
        };
        message.text = text;
        message.link = link;
        return message;
    }

    function Times(timedata) {
        var start = timedata[0];
        var end = timedata[1];
        var elapsed = timedata[2];
        return {
            elapsedMillis: elapsed,
            elapsedTime: formatElapsed(elapsed),
            startTime: formatDate(start),
            endTime:  formatDate(end)
        };
    }

    function timeFromDate(date) {
        if (!date)
            return "N/A"
        return shortTime(date.getHours(), date.getMinutes(),
                         date.getSeconds(), date.getMilliseconds());
    }

    function formatDate(date) {
        if (!date)
            return "N/A"
        return padTo(date.getFullYear(), 4) +
               padTo(date.getMonth() + 1, 2) +
               padTo(date.getDate(), 2) + " " +
               shortTime(date.getHours(), date.getMinutes(),
                         date.getSeconds(), date.getMilliseconds());
    }

    function shortTime(hours, minutes, seconds, milliseconds) {
        return padTo(hours, 2) + ":" +
               padTo(minutes, 2) + ":" +
               padTo(seconds, 2) + "." +
               padTo(milliseconds, 3);
    }

    function formatElapsed(elapsed) {
        var millis = elapsed;
        var hours = Math.floor(millis / (60 * 60 * 1000));
        millis -= hours * 60 * 60 * 1000;
        var minutes = Math.floor(millis / (60 * 1000));
        millis -= minutes * 60 * 1000;
        var seconds = Math.floor(millis / 1000);
        millis -= seconds * 1000;
        return shortTime(hours, minutes, seconds, millis);
    }

    function padTo(number, len) {
        var numString = number + "";
        while (numString.length < len) numString = "0" + numString;
        return numString;
    }

    function createIterablePopulator(name) {
        return function (populator) {
            populateIterable(this, name, populator);
        };
    }

    function populateIterable(obj, name, populator) {
        var nameInLowerCase = name.toLowerCase();
        obj[nameInLowerCase + "s"] = createGetAllFunction(populator.numberOfItems, populator.creator);
    }

    function createGetAllFunction(numberOfElements, creator) {
        var cached = undefined;
        return function () {
            if (cached === undefined) {
                cached = [];
                for (var i = 0; i < numberOfElements(); i++) {
                    cached.push(creator(i));
                }
            }
            return cached;
        };
    }

    return {
        Suite: Suite,
        Test: Test,
        Keyword: Keyword,
        Message: Message,
        Times: Times,
        PASS: STATUS.pass,
        FAIL: STATUS.fail,
        NOT_RUN: STATUS.notRun,
        formatElapsed: formatElapsed,
        containsTag: containsTag,  // Exposed for tests
        containsTagPattern: containsTagPattern,  // Exposed for tests
        shortTime: shortTime
    };
}());

window.stats = (function () {

    function Statistics(totalElems, tagElems, suiteElems){
        return {total: util.map(totalElems, statElem),
                tag:   util.map(tagElems, tagStatElem),
                suite: util.map(suiteElems, suiteStatElem)};
    }

    function statElem(stat) {
        stat.total = stat.pass + stat.fail;
        var percents = calculatePercents(stat.total, stat.pass, stat.fail);
        stat.passPercent = percents[0];
        stat.failPercent = percents[1];
        var widths = calculateWidths(stat.passPercent, stat.failPercent);
        stat.passWidth = widths[0];
        stat.failWidth = widths[1];
        return stat;
    }

    function tagStatElem(data) {
        var stat = statElem(data);
        stat.links = parseLinks(stat.links);
        return stat;
    }

    function suiteStatElem(data) {
        var stat = statElem(data);
        stat.fullName = stat.label;
        stat.formatParentName = function () { return util.formatParentName(stat); };
        // compatibility with RF 2.5 outputs
        if (!stat.name)
            stat.name = stat.label.split('.').pop();
        return stat;
    }

    function parseLinks(linksData) {
        if (!linksData)
            return [];
        return util.map(linksData.split(':::'), function (link) {
                var index = link.indexOf(':');
                return {title: link.slice(0, index), url: link.slice(index+1)};
            });
    }

    function calculatePercents(total, passed, failed) {
        if (total == 0)
            return [0.0, 0.0];
        pass = 100.0 * passed / total;
        fail = 100.0 * failed / total;
        if (pass > 0 && pass < 0.1)
            return [0.1, 99.9];
        if (fail > 0 && fail < 0.1)
            return [99.9, 0.1];
        return [Math.round(pass*10)/10, Math.round(fail*10)/10];
    }

    function calculateWidths(num1, num2) {
        if (num1 + num2 == 0)
            return [0.0, 0.0];
        // Make small percentages better visible
        if (num1 > 0 && num1 < 1)
            return [1.0, 99.0];
        if (num2 > 0 && num2 < 1)
            return [99.0, 1.0];
        // Handle situation where both are rounded up
        while (num1 + num2 > 100) {
            if (num1 > num2)
                num1 -= 0.1;
            if (num2 > num1)
                num2 -= 0.1;
        }
        return [num1, num2];
    }

    return {
        Statistics: Statistics
    };

}());
<commit_msg>model.js: Use the same find path finding algorithm in report and log<commit_after>window.model = (function () {

    var STATUS = {
        pass: "PASS",
        fail: "FAIL",
        notRun: "NOT RUN"
    };

    var KEYWORD_TYPE = {
        kw: 'KEYWORD',
        setup:'SETUP',
        teardown:'TEARDOWN'
    };

    function Suite(data) {
        var suite = createModelObject(data);
        suite.source = data.source;
        suite.fullName = data.parent ? data.parent.fullName + "." + data.name : data.name;
        setStats(suite, data.statistics);
        suite.metadata = data.metadata;
        suite.populateKeywords = createIterablePopulator("Keyword");
        suite.populateTests = createIterablePopulator("Test");
        suite.populateSuites = createIterablePopulator("Suite");
        suite.message = data.message;
        suite.children = function () {
            return suite.keywords().concat(suite.tests()).concat(suite.suites());
        };
        suite.hasTeardownFailure = function () {
            return suiteTeardownFailed(suite) || data.parentSuiteTeardownFailed;
        };
        suite.searchTests = function (predicate) {
            var tests = [];
            var subSuites = this.suites();
            for (var i in subSuites)
                tests = tests.concat(subSuites[i].searchTests(predicate));
            return tests.concat(util.filter(this.tests(), predicate));
        };
        suite.searchTestsByTag = function (tag) {
            return suite.searchTests(function (test) {
                if (tag.combined)
                    return containsTagPattern(test.tags, tag.combined);
                return containsTag(test.tags, tag.label);
            });
        };
        suite.findSuiteByName = function (name) {
            var path = window.testdata.pathToSuite(name)
            if(path.length){
                return window.testdata.find(path[path.length-1]);
            }
            return null;
        };
        suite.allTests = function () {
            return suite.searchTests(function (test) {
                return true;
            });
        };
        suite.criticalTests = function () {
            return suite.searchTests(function (test) {
                return test.isCritical;
            });
        };
        return suite;
    }

    function containsTag(testTags, tagname) {
        testTags = util.map(testTags, util.normalize);
        return util.contains(testTags, util.normalize(tagname));
    }

    function containsTagPattern(testTags, pattern) {
        testTags = util.map(testTags, util.normalize);
        if (pattern.indexOf('&') != -1) {
            var tagnames = pattern.split('&');
            return util.all(util.map(tagnames, function (name) {
                return containsTagPattern(testTags, name);
            }));
        }
        if (pattern.indexOf('NOT') != -1) {
            var tagnames = pattern.split('NOT');
            var required = tagnames[0];
            var notAllowed = tagnames.slice(1);
            return containsTagPattern(testTags, required) &&
                    util.all(util.map(notAllowed, function (name) {
                        return !containsTagPattern(testTags, name);
                    }));
        }
        var matcher = util.Matcher(pattern);
        return util.any(util.map(testTags, matcher.matches));
    }

    function suiteTeardownFailed(suite) {
        var keywords = suite.keywords();
        var maybeTeardown = keywords[keywords.length - 1];
        if (maybeTeardown && maybeTeardown.type == KEYWORD_TYPE.teardown)
            return maybeTeardown.status == STATUS.fail;
        return false;
    }

    function setStats(suite, stats) {
        for (var name in stats) {
            suite[name] = stats[name];
        }
    }

    function createModelObject(data) {
        return {
            name: data.name,
            doc: data.doc,
            status: data.status,
            times: data.times,
            callWhenChildrenReady: function (callable) { callable(); }
        };
    }

    function Test(data) {
        var test = createModelObject(data);
        test.fullName = data.parent.fullName + "." + test.name;
        test.formatParentName = function () { return util.formatParentName(test); };
        test.timeout = data.timeout;
        test.populateKeywords = createIterablePopulator("Keyword");
        test.isChildrenLoaded = data.isChildrenLoaded;
        // TODO: Should callable handling be in loadTestKeywordsFile function?
        var callables = [];
        test.callWhenChildrenReady = function (callable) {
            if (!test.isChildrenLoaded) {
                callables.push(callable);
                if (callables.length == 1) {
                    window.fileLoading.load(test.childFileName, function () {
                        test.isChildrenLoaded = true;
                        for (var i = 0; i < callables.length; i++) {
                            callables[i]();
                        };
                    });
                }
            } else {
                callable();
            }
        };
        test.children = function () {
            if (test.isChildrenLoaded)
                return test.keywords();

        };
        test.isCritical = data.isCritical;
        test.tags = data.tags;
        test.message = data.message;
        return test;
    }

    function Keyword(data) {
        var kw = createModelObject(data);
        kw.type = data.type;
        var parent = data.parent
        var parentPath = (parent.path === undefined) ? parent.fullName : parent.path;
        kw.path = parentPath + "." + data.index;
        kw.arguments = data.args;
        kw.timeout = data.timeout;
        kw.populateKeywords = createIterablePopulator("Keyword");
        kw.populateMessages = createIterablePopulator("Message");
        kw.children = function () {
            return kw.keywords();
        };
        return kw;
    }

    function Message(level, time, text, link) {
        var message = {};
        message.level = level;
        message.levelText = level.toUpperCase();
        message.time = time;
        message.shortTime = function () {
            return timeFromDate(message.time);
        };
        message.date = function () {
            return formatDate(message.time);
        };
        message.text = text;
        message.link = link;
        return message;
    }

    function Times(timedata) {
        var start = timedata[0];
        var end = timedata[1];
        var elapsed = timedata[2];
        return {
            elapsedMillis: elapsed,
            elapsedTime: formatElapsed(elapsed),
            startTime: formatDate(start),
            endTime:  formatDate(end)
        };
    }

    function timeFromDate(date) {
        if (!date)
            return "N/A"
        return shortTime(date.getHours(), date.getMinutes(),
                         date.getSeconds(), date.getMilliseconds());
    }

    function formatDate(date) {
        if (!date)
            return "N/A"
        return padTo(date.getFullYear(), 4) +
               padTo(date.getMonth() + 1, 2) +
               padTo(date.getDate(), 2) + " " +
               shortTime(date.getHours(), date.getMinutes(),
                         date.getSeconds(), date.getMilliseconds());
    }

    function shortTime(hours, minutes, seconds, milliseconds) {
        return padTo(hours, 2) + ":" +
               padTo(minutes, 2) + ":" +
               padTo(seconds, 2) + "." +
               padTo(milliseconds, 3);
    }

    function formatElapsed(elapsed) {
        var millis = elapsed;
        var hours = Math.floor(millis / (60 * 60 * 1000));
        millis -= hours * 60 * 60 * 1000;
        var minutes = Math.floor(millis / (60 * 1000));
        millis -= minutes * 60 * 1000;
        var seconds = Math.floor(millis / 1000);
        millis -= seconds * 1000;
        return shortTime(hours, minutes, seconds, millis);
    }

    function padTo(number, len) {
        var numString = number + "";
        while (numString.length < len) numString = "0" + numString;
        return numString;
    }

    function createIterablePopulator(name) {
        return function (populator) {
            populateIterable(this, name, populator);
        };
    }

    function populateIterable(obj, name, populator) {
        var nameInLowerCase = name.toLowerCase();
        obj[nameInLowerCase + "s"] = createGetAllFunction(populator.numberOfItems, populator.creator);
    }

    function createGetAllFunction(numberOfElements, creator) {
        var cached = undefined;
        return function () {
            if (cached === undefined) {
                cached = [];
                for (var i = 0; i < numberOfElements(); i++) {
                    cached.push(creator(i));
                }
            }
            return cached;
        };
    }

    return {
        Suite: Suite,
        Test: Test,
        Keyword: Keyword,
        Message: Message,
        Times: Times,
        PASS: STATUS.pass,
        FAIL: STATUS.fail,
        NOT_RUN: STATUS.notRun,
        formatElapsed: formatElapsed,
        containsTag: containsTag,  // Exposed for tests
        containsTagPattern: containsTagPattern,  // Exposed for tests
        shortTime: shortTime
    };
}());

window.stats = (function () {

    function Statistics(totalElems, tagElems, suiteElems){
        return {total: util.map(totalElems, statElem),
                tag:   util.map(tagElems, tagStatElem),
                suite: util.map(suiteElems, suiteStatElem)};
    }

    function statElem(stat) {
        stat.total = stat.pass + stat.fail;
        var percents = calculatePercents(stat.total, stat.pass, stat.fail);
        stat.passPercent = percents[0];
        stat.failPercent = percents[1];
        var widths = calculateWidths(stat.passPercent, stat.failPercent);
        stat.passWidth = widths[0];
        stat.failWidth = widths[1];
        return stat;
    }

    function tagStatElem(data) {
        var stat = statElem(data);
        stat.links = parseLinks(stat.links);
        return stat;
    }

    function suiteStatElem(data) {
        var stat = statElem(data);
        stat.fullName = stat.label;
        stat.formatParentName = function () { return util.formatParentName(stat); };
        // compatibility with RF 2.5 outputs
        if (!stat.name)
            stat.name = stat.label.split('.').pop();
        return stat;
    }

    function parseLinks(linksData) {
        if (!linksData)
            return [];
        return util.map(linksData.split(':::'), function (link) {
                var index = link.indexOf(':');
                return {title: link.slice(0, index), url: link.slice(index+1)};
            });
    }

    function calculatePercents(total, passed, failed) {
        if (total == 0)
            return [0.0, 0.0];
        pass = 100.0 * passed / total;
        fail = 100.0 * failed / total;
        if (pass > 0 && pass < 0.1)
            return [0.1, 99.9];
        if (fail > 0 && fail < 0.1)
            return [99.9, 0.1];
        return [Math.round(pass*10)/10, Math.round(fail*10)/10];
    }

    function calculateWidths(num1, num2) {
        if (num1 + num2 == 0)
            return [0.0, 0.0];
        // Make small percentages better visible
        if (num1 > 0 && num1 < 1)
            return [1.0, 99.0];
        if (num2 > 0 && num2 < 1)
            return [99.0, 1.0];
        // Handle situation where both are rounded up
        while (num1 + num2 > 100) {
            if (num1 > num2)
                num1 -= 0.1;
            if (num2 > num1)
                num2 -= 0.1;
        }
        return [num1, num2];
    }

    return {
        Statistics: Statistics
    };

}());
<|endoftext|>


<commit_before>/**
    Copyright 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.

    Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at

        http://aws.amazon.com/apache2.0/

    or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/

'use strict';
var textHelper = require('./textHelper'),
    storage = require('./storage');

var registerIntentHandlers = function (intentHandlers, skillContext) {
    intentHandlers.NewRecipeIntent = function (intent, session, response) {
        var AWS = require("aws-sdk");

        AWS.config.update({
            region: "us-east-1",
            endpoint: "https://dynamodb.us-east-1.amazonaws.com"
        });

        var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

        // TASK: reconfigure the "new game" for our own table

        // get the recipe from the intent

        var recipeName = textHelper.getRecipeName(intent.slots.RecipeName.value);

        if (!recipeName) {
            response.ask('OK. What do you want to cook today?', 'What do you want to cook today?');
            return;
        }

        /*

        */

        // query the recipeName from the DynamoDB database
        dynamodb.getItem({
                TableName: 'Recipes',
                Key: {
                    title: {
                        S: recipeName
                    },
                }
        }, function (err, data) {
            if (err || data === undefined) {
                 console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
                 var text = 'I\'m sorry, no existing recipe for ' + recipeName + ' exists.';
                 response.tell(text);
                 return;

            } else {
                    console.log("Query succeeded.");
                    console.log(data);
                    console.log(data.Item.actual_title.S);
                    //data.Items.forEach(function(item) {
                    //console.log("something was found");
                    storage.newGame(session).save(function () {
                    var speechOutput = 'Ok. Let\'s cook ' + recipeName + '. Do you want to hear ingredients, begin cooking, or other?';
                    var repromptText = 'Do you want to hear ingredients, begin cooking, or other?';
                    response.ask(speechOutput, repromptText);
                    });

            }
        });

        dynamodb.getItem({
            TableName: 'RecipeState',
            Key: {
                Name: {
                    S: "test"
                }
            }
        }, function (err, data){
            if (err){
                console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
            }
            if (data === undefined){
                console.log("unable to find the item");
            } else {
                // set the state holder to be the new recipe name
                console.log("found the item");
                console.log(data);

                dynamodb.putItem({
                    TableName: 'RecipeState',
                    Item: {
                        Name: {
                            S: 'test'
                        },
                        Recipe: {
                            S: recipeName
                        },
                        Step: {
                            N: '1'
                        }

                    }
                }, function (err, data) {
                    if (err){
                        console.log(err);
                    }

                });
                console.log(data);
            }
        });
        return;

        //reset scores for all existing players
        storage.loadGame(session, function (currentGame) {
            if (currentGame.data.players.length === 0) {
                response.ask('New game started. Who\'s your first player?',
                    'Please tell me who\'s your first player?');
                return;
            }
            currentGame.data.players.forEach(function (player) {
                currentGame.data.scores[player] = 0;
            });
            currentGame.save(function () {
                var speechOutput = 'New game started with '
                    + currentGame.data.players.length + ' existing player';
                if (currentGame.data.players.length > 1) {
                    speechOutput += 's';
                }
                speechOutput += '.';
                if (skillContext.needMoreHelp) {
                    speechOutput += '. You can give a player points, add another player, reset all players or exit. What would you like?';
                    var repromptText = 'You can give a player points, add another player, reset all players or exit. What would you like?';
                    response.ask(speechOutput, repromptText);
                } else {
                    response.tell(speechOutput);
                }
            });
        });
    }

    // TASK: actually link this to database, pulling
    intentHandlers.ListIngredientsIntent = function (intent, session, response) {

        response.ask('The ingredients are ', 'Do you want to hear ingredients, begin cooking, or other?');
        return;
    }

    intentHandlers.AskCaloriesIntent = function (intent, session, response) {
        var calories = 100;

        response.ask("This recipe is " + calories.toString() + " calories per serving.", "Do you want to hear ingredients, begin cooking, or other?");
    }

    intentHandlers.AskRatingIntent = function (intent, session, response) {
        var rating = 5;

        if (rating === 5) {
            response.ask("Previous people have said this recipe is great!", "Do you want to hear ingredients, begin cooking, or other?");
        }
    }

    intentHandlers.AskNumServingsIntent = function (intent, session, response) {
        var servings = 5;

        response.ask("This recipe is designed for " + servings.toString() + " servings.", "Do you want to hear ingredients, begin cooking, or other?");
    }

    intentHandlers.NextStepIntent = function (intent, session, response) {

        storage.loadGame(session, function (currentGame) {

            currentGame.data.step = currentGame.data.step + 1;
            response.ask('Next step.', 'Next step.');
            currentGame.save();
            return;

        });
    }

    intentHandlers.AddPlayerIntent = function (intent, session, response) {
        //add a player to the current game,
        //terminate or continue the conversation based on whether the intent
        //is from a one shot command or not.
        var recipeName = textHelper.getRecipeName(intent.slots.RecipeName.value);
        if (!recipeName) {
            response.ask('OK. What do you want to cook today?', 'What do you want to cook today?');
            return;
        }
        storage.loadGame(session, function (currentGame) {
            var speechOutput,
                reprompt;
            if (currentGame.data.scores[recipeName] !== undefined) {
                speechOutput = recipeName + ' has already joined the game.';
                if (skillContext.needMoreHelp) {
                    response.ask(speechOutput + ' What else?', 'What else?');
                } else {
                    response.tell(speechOutput);
                }
                return;
            }
            speechOutput = recipeName + ' has joined your game. ';
            currentGame.data.players.push(recipeName);
            currentGame.data.scores[recipeName] = 0;
            if (skillContext.needMoreHelp) {
                if (currentGame.data.players.length == 1) {
                    speechOutput += 'You can say, I am Done Adding Players. Now who\'s your next player?';
                    reprompt = textHelper.nextHelp;
                } else {
                    speechOutput += 'Who is your next player?';
                    reprompt = textHelper.nextHelp;
                }
            }
            currentGame.save(function () {
                if (reprompt) {
                    response.ask(speechOutput, reprompt);
                } else {
                    response.tell(speechOutput);
                }
            });
        });
    };

    intentHandlers.AddScoreIntent = function (intent, session, response) {
        //give a player points, ask additional question if slot values are missing.
        var recipeName = textHelper.getRecipeName(intent.slots.RecipeName.value),
            score = intent.slots.ScoreNumber,
            scoreValue;
        if (!recipeName) {
            response.ask('sorry, I did not hear the player name, please say that again', 'Please say the name again');
            return;
        }
        scoreValue = parseInt(score.value);
        if (isNaN(scoreValue)) {
            console.log('Invalid score value = ' + score.value);
            response.ask('sorry, I did not hear the points, please say that again', 'please say the points again');
            return;
        }
        storage.loadGame(session, function (currentGame) {
            var targetPlayer, speechOutput = '', newScore;
            if (currentGame.data.players.length < 1) {
                response.ask('sorry, no player has joined the game yet, what can I do for you?', 'what can I do for you?');
                return;
            }
            for (var i = 0; i < currentGame.data.players.length; i++) {
                if (currentGame.data.players[i] === recipeName) {
                    targetPlayer = currentGame.data.players[i];
                    break;
                }
            }
            if (!targetPlayer) {
                response.ask('Sorry, ' + recipeName + ' has not joined the game. What else?', recipeName + ' has not joined the game. What else?');
                return;
            }
            newScore = currentGame.data.scores[targetPlayer] + scoreValue;
            currentGame.data.scores[targetPlayer] = newScore;

            speechOutput += scoreValue + ' for ' + targetPlayer + '. ';
            if (currentGame.data.players.length == 1 || currentGame.data.players.length > 3) {
                speechOutput += targetPlayer + ' has ' + newScore + ' in total.';
            } else {
                speechOutput += 'That\'s ';
                currentGame.data.players.forEach(function (player, index) {
                    if (index === currentGame.data.players.length - 1) {
                        speechOutput += 'And ';
                    }
                    speechOutput += player + ', ' + currentGame.data.scores[player];
                    speechOutput += ', ';
                });
            }
            currentGame.save(function () {
                response.tell(speechOutput);
            });
        });
    };

    intentHandlers.TellScoresIntent = function (intent, session, response) {
        //tells the scores in the leaderboard and send the result in card.
        storage.loadGame(session, function (currentGame) {
            var sortedPlayerScores = [],
                continueSession,
                speechOutput = '',
                leaderboard = '';
            if (currentGame.data.players.length === 0) {
                response.tell('Nobody has joined the game.');
                return;
            }
            currentGame.data.players.forEach(function (player) {
                sortedPlayerScores.push({
                    score: currentGame.data.scores[player],
                    player: player
                });
            });
            sortedPlayerScores.sort(function (p1, p2) {
                return p2.score - p1.score;
            });
            sortedPlayerScores.forEach(function (playerScore, index) {
                if (index === 0) {
                    speechOutput += playerScore.player + ' has ' + playerScore.score + 'point';
                    if (playerScore.score > 1) {
                        speechOutput += 's';
                    }
                } else if (index === sortedPlayerScores.length - 1) {
                    speechOutput += 'And ' + playerScore.player + ' has ' + playerScore.score;
                } else {
                    speechOutput += playerScore.player + ', ' + playerScore.score;
                }
                speechOutput += '. ';
                leaderboard += 'No.' + (index + 1) + ' - ' + playerScore.player + ' : ' + playerScore.score + '\n';
            });
            response.tellWithCard(speechOutput, "Leaderboard", leaderboard);
        });
    };

    intentHandlers.ResetPlayersIntent = function (intent, session, response) {
        //remove all players
        storage.newGame(session).save(function () {
            response.ask('New game started without players, who do you want to add first?', 'Who do you want to add first?');
        });
    };

    intentHandlers['AMAZON.HelpIntent'] = function (intent, session, response) {
        var speechOutput = textHelper.completeHelp;
        if (skillContext.needMoreHelp) {
            response.ask(textHelper.completeHelp + ' So, how can I help?', 'How can I help?');
        } else {
            response.tell(textHelper.completeHelp);
        }
    };

    intentHandlers['AMAZON.CancelIntent'] = function (intent, session, response) {
        if (skillContext.needMoreHelp) {
            response.tell('Okay.  Whenever you\'re ready, you can start giving points to the players in your game.');
        } else {
            response.tell('');
        }
    };

    intentHandlers['AMAZON.StopIntent'] = function (intent, session, response) {
        if (skillContext.needMoreHelp) {
            response.tell('Okay.  Whenever you\'re ready, you can start giving points to the players in your game.');
        } else {
            response.tell('');
        }
    };
};
exports.register = registerIntentHandlers;
<commit_msg>finished rating, serving, calories<commit_after>/**
    Copyright 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.

    Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at

        http://aws.amazon.com/apache2.0/

    or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/

'use strict';
var textHelper = require('./textHelper'),
    storage = require('./storage');

var registerIntentHandlers = function (intentHandlers, skillContext) {
    intentHandlers.NewRecipeIntent = function (intent, session, response) {
        var AWS = require("aws-sdk");

        AWS.config.update({
            region: "us-east-1",
            endpoint: "https://dynamodb.us-east-1.amazonaws.com"
        });

        var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

        // TASK: reconfigure the "new game" for our own table

        // get the recipe from the intent

        var recipeName = textHelper.getRecipeName(intent.slots.RecipeName.value);

        if (!recipeName) {
            response.ask('OK. What do you want to cook today?', 'What do you want to cook today?');
            return;
        }

        /*

        */

        // query the recipeName from the DynamoDB database
        dynamodb.getItem({
                TableName: 'Recipes',
                Key: {
                    title: {
                        S: recipeName
                    },
                }
        }, function (err, data) {
            if (err || data === undefined) {
                 console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
                 var text = 'I\'m sorry, no existing recipe for ' + recipeName + ' exists.';
                 response.tell(text);
                 return;

            } else {
                    console.log("Query succeeded.");
                    console.log(data);
                    console.log(data.Item.actual_title.S);
                    //data.Items.forEach(function(item) {
                    //console.log("something was found");
                    storage.newGame(session).save(function () {
                    var speechOutput = 'Ok. Let\'s cook ' + recipeName + '. Do you want to hear ingredients, begin cooking, or other?';
                    var repromptText = 'Do you want to hear ingredients, begin cooking, or other?';
                    response.ask(speechOutput, repromptText);
                    });

            }
        });

        dynamodb.getItem({
            TableName: 'RecipeState',
            Key: {
                Name: {
                    S: "test"
                }
            }
        }, function (err, data){
            if (err){
                console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
            }
            if (data === undefined){
                console.log("unable to find the item");
            } else {
                // set the state holder to be the new recipe name
                console.log("found the item");
                console.log(data);

                dynamodb.putItem({
                    TableName: 'RecipeState',
                    Item: {
                        Name: {
                            S: 'test'
                        },
                        Recipe: {
                            S: recipeName
                        },
                        Step: {
                            N: '1'
                        }

                    }
                }, function (err, data) {
                    if (err){
                        console.log(err);
                    }

                });
                console.log(data);
            }
        });
        return;

        //reset scores for all existing players
        storage.loadGame(session, function (currentGame) {
            if (currentGame.data.players.length === 0) {
                response.ask('New game started. Who\'s your first player?',
                    'Please tell me who\'s your first player?');
                return;
            }
            currentGame.data.players.forEach(function (player) {
                currentGame.data.scores[player] = 0;
            });
            currentGame.save(function () {
                var speechOutput = 'New game started with '
                    + currentGame.data.players.length + ' existing player';
                if (currentGame.data.players.length > 1) {
                    speechOutput += 's';
                }
                speechOutput += '.';
                if (skillContext.needMoreHelp) {
                    speechOutput += '. You can give a player points, add another player, reset all players or exit. What would you like?';
                    var repromptText = 'You can give a player points, add another player, reset all players or exit. What would you like?';
                    response.ask(speechOutput, repromptText);
                } else {
                    response.tell(speechOutput);
                }
            });
        });
    }

    // TASK: actually link this to database, pulling
    intentHandlers.ListIngredientsIntent = function (intent, session, response) {

        response.ask('The ingredients are ', 'Do you want to hear ingredients, begin cooking, or other?');
        return;
    }

    intentHandlers.AskCaloriesIntent = function (intent, session, response) {
        var AWS = require("aws-sdk");
        AWS.config.update({
            region: "us-east-1",
            endpoint: "https://dynamodb.us-east-1.amazonaws.com"
        });
        var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
        var id;
        var calories = 1000;
        console.log(dynamodb);
        dynamodb.getItem({
            TableName: 'RecipeState',
            Key: {
                Name: {
                    S: "test"
                }
            }
        }, function (err, data){
            console.log(data);
            if (err){
                console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
                return;
            }
            if (data === undefined){
                console.log("unable to find the item");
                return;
            } else {
                console.log("found the item");
                id = data.Item.Recipe.S;
                console.log(id);
                dynamodb.getItem({
                    TableName: 'Recipes',
                    Key: {
                        title: {
                            S: id
                        }
                    }
                }, function (err, data){
                    if (err){
                        console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
                    }
                    if (data === undefined){
                        console.log("unable to find the item");

                    }else {
                        calories = data.Item.calories.N;
                        response.ask("This " + id + " recipe is " + calories.toString() + " calories per serving.", "Do you want to hear ingredients, begin cooking, or other?");
                    }
                });

            }
        });

    }

    intentHandlers.AskRatingIntent = function (intent, session, response) {
        var AWS = require("aws-sdk");
        AWS.config.update({
            region: "us-east-1",
            endpoint: "https://dynamodb.us-east-1.amazonaws.com"
        });
        var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
        var id;
        var rating = 0;
        console.log(dynamodb);
        dynamodb.getItem({
            TableName: 'RecipeState',
            Key: {
                Name: {
                    S: "test"
                }
            }
        }, function (err, data){
            console.log(data);
            if (err){
                console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
                return;
            }
            if (data === undefined){
                console.log("unable to find the item");
                return;
            } else {
                console.log("found the item");
                id = data.Item.Recipe.S;
                console.log(id);
                dynamodb.getItem({
                    TableName: 'Recipes',
                    Key: {
                        title: {
                            S: id
                        }
                    }
                }, function (err, data){
                    if (err){
                        console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
                    }
                    if (data === undefined){
                        console.log("unable to find the item");

                    }else {
                        rating = data.Item.ratings.N;
                        var tag = "";
                        if (rating === '5'){
                            tag = "really great.";
                        } else if (rating === '4'){
                            tag = "pretty good.";
                        } else if (rating === '3'){
                            tag = "decent.";
                        } else if (rating === '2'){
                            tag = "average.";
                        } else {
                            tag = "not very good.";
                        }
                        response.ask("Others think this " + id + " recipe is " + tag, "Do you want to hear ingredients, begin cooking, or other?");

                    }
                });

            }
        });
    }

    intentHandlers.AskNumServingsIntent = function (intent, session, response) {
        var AWS = require("aws-sdk");
        AWS.config.update({
            region: "us-east-1",
            endpoint: "https://dynamodb.us-east-1.amazonaws.com"
        });
        var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
        var id;
        var servings = 100;
        console.log(dynamodb);
        dynamodb.getItem({
            TableName: 'RecipeState',
            Key: {
                Name: {
                    S: "test"
                }
            }
        }, function (err, data){
            console.log(data);
            if (err){
                console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
                return;
            }
            if (data === undefined){
                console.log("unable to find the item");
                return;
            } else {
                console.log("found the item");
                id = data.Item.Recipe.S;
                console.log(id);
                dynamodb.getItem({
                    TableName: 'Recipes',
                    Key: {
                        title: {
                            S: id
                        }
                    }
                }, function (err, data){
                    if (err){
                        console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
                    }
                    if (data === undefined){
                        console.log("unable to find the item");

                    }else {
                        servings = data.Item.servings.N;
                        response.ask("This " + id + " recipe is designed for " + servings.toString() + " servings.", "Do you want to hear ingredients, begin cooking, or other?");

                    }
                });

            }
        });

    }

    intentHandlers.NextStepIntent = function (intent, session, response) {

        /*
        storage.loadGame(session, function (currentGame) {

            //currentGame.data.step = currentGame.data.step + 1;
            //response.ask('Next step.', 'Next step.');
            //currentGame.save();

            return;

        });
*/
    }

    intentHandlers.AddPlayerIntent = function (intent, session, response) {
        //add a player to the current game,
        //terminate or continue the conversation based on whether the intent
        //is from a one shot command or not.
        var recipeName = textHelper.getRecipeName(intent.slots.RecipeName.value);
        if (!recipeName) {
            response.ask('OK. What do you want to cook today?', 'What do you want to cook today?');
            return;
        }
        storage.loadGame(session, function (currentGame) {
            var speechOutput,
                reprompt;
            if (currentGame.data.scores[recipeName] !== undefined) {
                speechOutput = recipeName + ' has already joined the game.';
                if (skillContext.needMoreHelp) {
                    response.ask(speechOutput + ' What else?', 'What else?');
                } else {
                    response.tell(speechOutput);
                }
                return;
            }
            speechOutput = recipeName + ' has joined your game. ';
            currentGame.data.players.push(recipeName);
            currentGame.data.scores[recipeName] = 0;
            if (skillContext.needMoreHelp) {
                if (currentGame.data.players.length == 1) {
                    speechOutput += 'You can say, I am Done Adding Players. Now who\'s your next player?';
                    reprompt = textHelper.nextHelp;
                } else {
                    speechOutput += 'Who is your next player?';
                    reprompt = textHelper.nextHelp;
                }
            }
            currentGame.save(function () {
                if (reprompt) {
                    response.ask(speechOutput, reprompt);
                } else {
                    response.tell(speechOutput);
                }
            });
        });
    };

    intentHandlers.AddScoreIntent = function (intent, session, response) {
        //give a player points, ask additional question if slot values are missing.
        var recipeName = textHelper.getRecipeName(intent.slots.RecipeName.value),
            score = intent.slots.ScoreNumber,
            scoreValue;
        if (!recipeName) {
            response.ask('sorry, I did not hear the player name, please say that again', 'Please say the name again');
            return;
        }
        scoreValue = parseInt(score.value);
        if (isNaN(scoreValue)) {
            console.log('Invalid score value = ' + score.value);
            response.ask('sorry, I did not hear the points, please say that again', 'please say the points again');
            return;
        }
        storage.loadGame(session, function (currentGame) {
            var targetPlayer, speechOutput = '', newScore;
            if (currentGame.data.players.length < 1) {
                response.ask('sorry, no player has joined the game yet, what can I do for you?', 'what can I do for you?');
                return;
            }
            for (var i = 0; i < currentGame.data.players.length; i++) {
                if (currentGame.data.players[i] === recipeName) {
                    targetPlayer = currentGame.data.players[i];
                    break;
                }
            }
            if (!targetPlayer) {
                response.ask('Sorry, ' + recipeName + ' has not joined the game. What else?', recipeName + ' has not joined the game. What else?');
                return;
            }
            newScore = currentGame.data.scores[targetPlayer] + scoreValue;
            currentGame.data.scores[targetPlayer] = newScore;

            speechOutput += scoreValue + ' for ' + targetPlayer + '. ';
            if (currentGame.data.players.length == 1 || currentGame.data.players.length > 3) {
                speechOutput += targetPlayer + ' has ' + newScore + ' in total.';
            } else {
                speechOutput += 'That\'s ';
                currentGame.data.players.forEach(function (player, index) {
                    if (index === currentGame.data.players.length - 1) {
                        speechOutput += 'And ';
                    }
                    speechOutput += player + ', ' + currentGame.data.scores[player];
                    speechOutput += ', ';
                });
            }
            currentGame.save(function () {
                response.tell(speechOutput);
            });
        });
    };

    intentHandlers.TellScoresIntent = function (intent, session, response) {
        //tells the scores in the leaderboard and send the result in card.
        storage.loadGame(session, function (currentGame) {
            var sortedPlayerScores = [],
                continueSession,
                speechOutput = '',
                leaderboard = '';
            if (currentGame.data.players.length === 0) {
                response.tell('Nobody has joined the game.');
                return;
            }
            currentGame.data.players.forEach(function (player) {
                sortedPlayerScores.push({
                    score: currentGame.data.scores[player],
                    player: player
                });
            });
            sortedPlayerScores.sort(function (p1, p2) {
                return p2.score - p1.score;
            });
            sortedPlayerScores.forEach(function (playerScore, index) {
                if (index === 0) {
                    speechOutput += playerScore.player + ' has ' + playerScore.score + 'point';
                    if (playerScore.score > 1) {
                        speechOutput += 's';
                    }
                } else if (index === sortedPlayerScores.length - 1) {
                    speechOutput += 'And ' + playerScore.player + ' has ' + playerScore.score;
                } else {
                    speechOutput += playerScore.player + ', ' + playerScore.score;
                }
                speechOutput += '. ';
                leaderboard += 'No.' + (index + 1) + ' - ' + playerScore.player + ' : ' + playerScore.score + '\n';
            });
            response.tellWithCard(speechOutput, "Leaderboard", leaderboard);
        });
    };

    intentHandlers.ResetPlayersIntent = function (intent, session, response) {
        //remove all players
        storage.newGame(session).save(function () {
            response.ask('New game started without players, who do you want to add first?', 'Who do you want to add first?');
        });
    };

    intentHandlers['AMAZON.HelpIntent'] = function (intent, session, response) {
        var speechOutput = textHelper.completeHelp;
        if (skillContext.needMoreHelp) {
            response.ask(textHelper.completeHelp + ' So, how can I help?', 'How can I help?');
        } else {
            response.tell(textHelper.completeHelp);
        }
    };

    intentHandlers['AMAZON.CancelIntent'] = function (intent, session, response) {
        if (skillContext.needMoreHelp) {
            response.tell('Okay.  Whenever you\'re ready, you can start giving points to the players in your game.');
        } else {
            response.tell('');
        }
    };

    intentHandlers['AMAZON.StopIntent'] = function (intent, session, response) {
        if (skillContext.needMoreHelp) {
            response.tell('Okay.  Whenever you\'re ready, you can start giving points to the players in your game.');
        } else {
            response.tell('');
        }
    };
};
exports.register = registerIntentHandlers;
<|endoftext|>


<commit_before>'use strict';

angular.module('sumaAnalysis')
  .factory('processTimeSeriesData', function ($q, $rootScope) {
    var weekdays = {
      Sunday: 0,
      Monday: 1,
      Tuesday: 2,
      Wednesday: 3,
      Thursday: 4,
      Friday: 5,
      Saturday: 6
    };

    function calcCount(obj, coll, prop) {
      var hasChildren;

      hasChildren = _.filter(coll, function (item) {
        if (prop === 'activityGroup') {
          return obj.id === item[prop] && obj.type === 'activityGroup';
        }

        return obj.id === item[prop];
      });

      if (hasChildren.length < 1) {
        return obj.count;
      }

      return _.reduce(_.map(hasChildren, function (o) {
        return calcCount(o, coll, prop);
      }), function (sum, num) {
        return sum + num;
      });
    }

    function buildArray (source, response, total, trunc, pct) {
      return _.filter(_.map(_.cloneDeep(source), function (o) {
        o.name = o.title;

        if (trunc) {
          o.count = response[o.id] ? response[o.id].toFixed(2) : null;
        } else {
          if (o.type === 'activityGroup') {
            o.count = null;
          } else {
            o.count = response[o.id] || null;
          }
        }

        if (o.count !== null) {
          o.percent = (o.count / total * 100).toFixed(2);
        } else {
          o.percent = null;
        }

        if (pct) {
          o.count = o.percent;
        }

        return o;
      }), function (obj) {
        return obj.count !== null;
      });
    }

    function buildTableArray (source, response, total, flag) {
      var counts;

      counts = _.map(_.cloneDeep(source), function (loc) {
        loc.name = loc.title;
        loc.count = response[loc.id] || null;

        return loc;
      });

      // Calculate counts for children
      return _.map(counts, function (loc, index, coll) {
        loc.count = calcCount(loc, coll, flag);
        loc.percent = (loc.count / total * 100).toFixed(2);

        return loc;
      });
    }

    function insertNoActs (source, total, mode) {
      var obj = {},
        noActs;

      noActs = _.find(source, function (item, key) {
        return key === '_No Activity';
      });

      if (noActs) {
        obj.name = 'No Activity';
        obj.depth = 0;

        obj.percent = (noActs / total * 100).toFixed(2);

        if (mode === 'pct') {
          obj.count = (noActs / total * 100).toFixed(2);
        }

        if (mode === 'sum') {
          obj.count = noActs;
        }

        if (mode === 'avg') {
          obj.count = noActs.toFixed(2);
        }

        return obj;
      }

      return false;
    }

    function processData (response, activities, locations) {
      var noActsSum,
        noActsAvgSum,
        noActsAvgAvg,
        counts;

      // Convert response into arrays of objects
      counts = {};

      // CSV
      counts.csv = response.csv;

      // Total Sum
      counts.total = [{
        count : response.total
      }];

      // Locations related data
      counts.locationsTable = buildTableArray(locations, response.locationsSum, response.total, 'parent');
      counts.locationsSum = buildArray(locations, response.locationsSum, response.total);
      counts.locationsAvgSum = buildArray(locations, response.locationsAvgSum, response.total, true);
      counts.locationsAvgAvg = buildArray(locations, response.locationsAvgAvg, response.total, true);
      counts.locationsPct = buildArray(locations, response.locationsSum, response.total, false, true);

      // Activities related data
      counts.activitiesTable = buildTableArray(activities, response.activitiesSum, response.total, 'activityGroup');
      counts.activitiesSum = buildArray(activities, response.activitiesSum, response.total);
      counts.activitiesAvgSum = buildArray(activities, response.activitiesAvgSum, response.total, true);
      counts.activitiesAvgAvg = buildArray(activities, response.activitiesAvgAvg, response.total, true);
      counts.activitiesPct = buildArray(activities, response.activitiesSum, response.total, false, true);

      // Handle insertion of no activity values
      noActsSum = insertNoActs(response.activitiesSum, response.total, 'sum');
      if (noActsSum) {
        counts.activitiesSum.push(noActsSum);
        counts.activitiesTable.push(noActsSum);
        counts.activitiesPct.push(insertNoActs(response.activitiesSum, response.total, 'pct'));
      }

      noActsAvgSum = insertNoActs(response.activitiesAvgSum, response.total, 'avg');
      if (noActsAvgSum) {
        counts.activitiesAvgSum.push(noActsAvgSum);
      }

      noActsAvgAvg = insertNoActs(response.activitiesAvgAvg, response.total, 'avg');
      if (noActsAvgAvg) {
        counts.activitiesAvgAvg.push(noActsAvgAvg);
      }

      // Period Sum
      counts.periodSum = _.sortBy(_.map(response.periodSum, function (element, index) {
        return {
          date: index,
          count: element.count
        };
      }), function (item) {
        return new Date(item.date).getTime();
      });

      // Period Avg
      counts.periodAvg = _.sortBy(_.map(response.periodAvg, function (element, index) {
        return {
          date: index,
          count: element.count
        };
      }), function (item) {
        return new Date(item.date).getTime();
      });

      // Hourly Summary
      counts.hourlySummary = _.map(response.hourSummary, function (element, index) {
        return {
          name: index,
          count: element,
          percent: (element / response.total * 100).toFixed(2)
        };
      });

      // Day of Week Summary
      counts.dayOfWeekSummary = _.sortBy(_.map(response.dayOfWeekSummary, function (element, index) {
        return {
          name: index,
          count: element,
          percent: (element / response.total * 100).toFixed(2)
        };
      }), function (item) {
        return weekdays[item.name];
      });

      // Month Summary
      counts.monthSummary = _.sortBy(_.flatten(_.map(response.monthSummary, function (months, year) {
        return _.map(months, function (count, month) {
          return {
            date: month + ' ' + '1' + ', ' + year,
            name: month + ' ' + year,
            count: count,
            percent: (count / response.total * 100).toFixed(2)
          };
        });
      })), function (item) {
        return new Date(item.date).getTime();
      });

      // Year Summary
      counts.yearSummary = _.sortBy(_.map(response.yearSummary, function (element, index) {
        return {
          name: index,
          count: element,
          percent: (element / response.total * 100).toFixed(2)
        };
      }), function (item) {
        return item.name;
      });

      counts.timeSeriesOptions = [
        {title: 'Daily Avg', val: 'avg', data: counts.periodAvg},
        {title: 'Daily Sum', val: 'sum', data: counts.periodSum}
      ];

      counts.timeSeriesData = counts.timeSeriesOptions[1];

      counts.actsLocsOptions = [
        {title: 'Activities', val: 'activities', items: [
          {title: 'Avg of Sum', data: counts.activitiesAvgSum},
          {title: 'Avg of Avg', data: counts.activitiesAvgAvg},
          {title: 'Sum', data: counts.activitiesSum},
          {title: 'Pct', data: counts.activitiesPct}
        ]},
        {title: 'Locations', val: 'locations', items: [
          {title: 'Avg of Sum', data: counts.locationsAvgSum},
          {title: 'Avg of Avg', data: counts.locationsAvgAvg},
          {title: 'Sum', data: counts.locationsSum},
          {title: 'Pct', data: counts.locationsPct}
        ]}
      ];

      counts.actsLocsData = counts.actsLocsOptions[1];

      counts.barChartData = counts.actsLocsData.items[2];
      return counts;
      // dfd.resolve(counts);

      // return dfd.promise;
    }

    return {
      get: function (response, acts, locs) {
        var data,
            dataTest,
            dfd;

        dfd = $q.defer();

        acts = _.filter(acts, function (act) {
          return act.id !== 'all';
        });

        locs = _.filter(locs, function (loc) {
          return loc.id !== 'all';
        });

        // TODO: Clean-up response checking and expand conditions
        // Reject if no locations
        if (!response.locationsSum) {
          dfd.reject({statusText: 'no data, locationsSum not found'});
        }

        data = processData(response, acts, locs);

        // Check data for display
        dataTest = _.reduce(_.pluck(data.periodSum, 'count'), function (sum, num) {
          return sum + num;
        });

        if (!dataTest) {
          dfd.reject({statusText: 'no data, dataTest failed'});
        }

        dfd.resolve(data);

        return dfd.promise;
      }
    };
  });
<commit_msg>code cleanup<commit_after>'use strict';

angular.module('sumaAnalysis')
  .factory('processTimeSeriesData', function ($q, $rootScope) {
    var weekdays = {
      Sunday: 0,
      Monday: 1,
      Tuesday: 2,
      Wednesday: 3,
      Thursday: 4,
      Friday: 5,
      Saturday: 6
    };

    function calcCount(obj, coll, prop) {
      var hasChildren;

      hasChildren = _.filter(coll, function (item) {
        if (prop === 'activityGroup') {
          return obj.id === item[prop] && obj.type === 'activityGroup';
        }

        return obj.id === item[prop];
      });

      if (hasChildren.length < 1) {
        return obj.count;
      }

      return _.reduce(_.map(hasChildren, function (o) {
        return calcCount(o, coll, prop);
      }), function (sum, num) {
        return sum + num;
      });
    }

    function buildArray (source, response, total, trunc, pct) {
      return _.filter(_.map(_.cloneDeep(source), function (o) {
        o.name = o.title;

        if (trunc) {
          o.count = response[o.id] ? response[o.id].toFixed(2) : null;
        } else {
          if (o.type === 'activityGroup') {
            o.count = null;
          } else {
            o.count = response[o.id] || null;
          }
        }

        if (o.count !== null) {
          o.percent = (o.count / total * 100).toFixed(2);
        } else {
          o.percent = null;
        }

        if (pct) {
          o.count = o.percent;
        }

        return o;
      }), function (obj) {
        return obj.count !== null;
      });
    }

    function buildTableArray (source, response, total, flag) {
      var counts;

      counts = _.map(_.cloneDeep(source), function (loc) {
        loc.name = loc.title;
        loc.count = response[loc.id] || null;

        return loc;
      });

      // Calculate counts for children
      return _.map(counts, function (loc, index, coll) {
        loc.count = calcCount(loc, coll, flag);
        loc.percent = (loc.count / total * 100).toFixed(2);

        return loc;
      });
    }

    function insertNoActs (source, total, mode) {
      var obj = {},
        noActs;

      noActs = _.find(source, function (item, key) {
        return key === '_No Activity';
      });

      if (noActs) {
        obj.name = 'No Activity';
        obj.depth = 0;

        obj.percent = (noActs / total * 100).toFixed(2);

        if (mode === 'pct') {
          obj.count = (noActs / total * 100).toFixed(2);
        }

        if (mode === 'sum') {
          obj.count = noActs;
        }

        if (mode === 'avg') {
          obj.count = noActs.toFixed(2);
        }

        return obj;
      }

      return false;
    }

    function processData (response, activities, locations) {
      var noActsSum,
        noActsAvgSum,
        noActsAvgAvg,
        counts;

      // Convert response into arrays of objects
      counts = {};

      // CSV
      counts.csv = response.csv;

      // Total Sum
      counts.total = [{
        count : response.total
      }];

      // Locations related data
      counts.locationsTable = buildTableArray(locations, response.locationsSum, response.total, 'parent');
      counts.locationsSum = buildArray(locations, response.locationsSum, response.total);
      counts.locationsAvgSum = buildArray(locations, response.locationsAvgSum, response.total, true);
      counts.locationsAvgAvg = buildArray(locations, response.locationsAvgAvg, response.total, true);
      counts.locationsPct = buildArray(locations, response.locationsSum, response.total, false, true);

      // Activities related data
      counts.activitiesTable = buildTableArray(activities, response.activitiesSum, response.total, 'activityGroup');
      counts.activitiesSum = buildArray(activities, response.activitiesSum, response.total);
      counts.activitiesAvgSum = buildArray(activities, response.activitiesAvgSum, response.total, true);
      counts.activitiesAvgAvg = buildArray(activities, response.activitiesAvgAvg, response.total, true);
      counts.activitiesPct = buildArray(activities, response.activitiesSum, response.total, false, true);

      // Handle insertion of no activity values
      noActsSum = insertNoActs(response.activitiesSum, response.total, 'sum');
      if (noActsSum) {
        counts.activitiesSum.push(noActsSum);
        counts.activitiesTable.push(noActsSum);
        counts.activitiesPct.push(insertNoActs(response.activitiesSum, response.total, 'pct'));
      }

      noActsAvgSum = insertNoActs(response.activitiesAvgSum, response.total, 'avg');
      if (noActsAvgSum) {
        counts.activitiesAvgSum.push(noActsAvgSum);
      }

      noActsAvgAvg = insertNoActs(response.activitiesAvgAvg, response.total, 'avg');
      if (noActsAvgAvg) {
        counts.activitiesAvgAvg.push(noActsAvgAvg);
      }

      // Period Sum
      counts.periodSum = _.sortBy(_.map(response.periodSum, function (element, index) {
        return {
          date: index,
          count: element.count
        };
      }), function (item) {
        return new Date(item.date).getTime();
      });

      // Period Avg
      counts.periodAvg = _.sortBy(_.map(response.periodAvg, function (element, index) {
        return {
          date: index,
          count: element.count
        };
      }), function (item) {
        return new Date(item.date).getTime();
      });

      // Hourly Summary
      counts.hourlySummary = _.map(response.hourSummary, function (element, index) {
        return {
          name: index,
          count: element,
          percent: (element / response.total * 100).toFixed(2)
        };
      });

      // Day of Week Summary
      counts.dayOfWeekSummary = _.sortBy(_.map(response.dayOfWeekSummary, function (element, index) {
        return {
          name: index,
          count: element,
          percent: (element / response.total * 100).toFixed(2)
        };
      }), function (item) {
        return weekdays[item.name];
      });

      // Month Summary
      counts.monthSummary = _.sortBy(_.flatten(_.map(response.monthSummary, function (months, year) {
        return _.map(months, function (count, month) {
          return {
            date: month + ' ' + '1' + ', ' + year,
            name: month + ' ' + year,
            count: count,
            percent: (count / response.total * 100).toFixed(2)
          };
        });
      })), function (item) {
        return new Date(item.date).getTime();
      });

      // Year Summary
      counts.yearSummary = _.sortBy(_.map(response.yearSummary, function (element, index) {
        return {
          name: index,
          count: element,
          percent: (element / response.total * 100).toFixed(2)
        };
      }), function (item) {
        return item.name;
      });

      counts.timeSeriesOptions = [
        {title: 'Daily Avg', val: 'avg', data: counts.periodAvg},
        {title: 'Daily Sum', val: 'sum', data: counts.periodSum}
      ];

      counts.timeSeriesData = counts.timeSeriesOptions[1];

      counts.actsLocsOptions = [
        {title: 'Activities', val: 'activities', items: [
          {title: 'Avg of Sum', data: counts.activitiesAvgSum},
          {title: 'Avg of Avg', data: counts.activitiesAvgAvg},
          {title: 'Sum', data: counts.activitiesSum},
          {title: 'Pct', data: counts.activitiesPct}
        ]},
        {title: 'Locations', val: 'locations', items: [
          {title: 'Avg of Sum', data: counts.locationsAvgSum},
          {title: 'Avg of Avg', data: counts.locationsAvgAvg},
          {title: 'Sum', data: counts.locationsSum},
          {title: 'Pct', data: counts.locationsPct}
        ]}
      ];

      counts.actsLocsData = counts.actsLocsOptions[1];

      counts.barChartData = counts.actsLocsData.items[2];

      return counts;
    }

    return {
      get: function (response, acts, locs) {
        var data,
            dataTest,
            dfd;

        dfd = $q.defer();

        acts = _.filter(acts, function (act) {
          return act.id !== 'all';
        });

        locs = _.filter(locs, function (loc) {
          return loc.id !== 'all';
        });

        // TODO: Clean-up response checking and expand conditions
        // Reject if no locations
        if (!response.locationsSum) {
          dfd.reject({statusText: 'no data, locationsSum not found'});
        }

        data = processData(response, acts, locs);

        // Check data for display
        dataTest = _.reduce(_.pluck(data.periodSum, 'count'), function (sum, num) {
          return sum + num;
        });

        if (!dataTest) {
          dfd.reject({statusText: 'no data, dataTest failed'});
        }

        dfd.resolve(data);

        return dfd.promise;
      }
    };
  });
<|endoftext|>


<commit_before>"use strict";

const _ = require("lodash");
const moment = require("moment-timezone");

const config = require("./config");

// https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
// the Fisher-Yates Shuffle
function shuffle(array) {
  let currentIndex = array.length;
  let temporaryValue;
  let randomIndex;
  while (currentIndex !== 0) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }
  return array;
}

function generateThemes(themes, mainTheme, subTheme, excluded) {

  const candidates = _.difference(themes, [mainTheme, subTheme, ...(excluded || [])]);
  const shuffled = shuffle(candidates);
  return [mainTheme, ..._.take(shuffled, 2), subTheme];

}

function getNextSequence(seq, themes) {

  if (!Array.isArray(seq) || seq.length <= 1) {

    const newseq = shuffle(themes);
    if (newseq[0] === seq[0]) {
      newseq.unshift(newseq.pop());
    }
    return newseq;

  }

  return seq.slice(1);

}

function getNextContext(prevctx) {

  const now = moment().tz(config.timezone);

  const prevContext = Object.assign({}, prevctx);
  const context = {};

  if (config.wordThemes) {

    const dateIndex = _.findIndex(
      config.wordThemes.date,
      d => d[0] === now.month() + 1 && d[1] === now.date()
    );

    if (dateIndex >= 0) {

      context.wordTheme = config.wordThemes.date[dateIndex][2];
      context.wordThemes = prevContext.wordThemes;

    } else {

      context.wordThemes = getNextSequence(
        prevContext.wordThemes || [],
        _.flatten(config.wordThemes.words)
      );

      context.wordTheme = context.wordThemes[0];

    }

  }

  if (config.characterFree.indexOf(now.day()) >= 0) {

    context.mainThemes = prevContext.mainThemes;
    context.subThemes = prevContext.subThemes;
    context.themes = prevContext.themes;

  } else {

    context.mainThemes = getNextSequence(
      prevContext.mainThemes || [],
      config.mainThemes
    );

    context.subThemes = getNextSequence(
      prevContext.subThemes || [],
      config.subThemes
    );

    // Decide and save themes

    context.themes = generateThemes(
      config.themes,
      context.mainThemes[0],
      context.subThemes[0],
      config.excludePrevThemes ? prevContext.themes || [] : []
    );

  }

  return context;

}

module.exports = {
  generateThemes,
  getNextSequence,
  getNextContext
};
<commit_msg>Fix word theme generation<commit_after>"use strict";

const _ = require("lodash");
const moment = require("moment-timezone");

const config = require("./config");

// https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
// the Fisher-Yates Shuffle
function shuffle(array) {
  let currentIndex = array.length;
  let temporaryValue;
  let randomIndex;
  while (currentIndex !== 0) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }
  return array;
}

function generateThemes(themes, mainTheme, subTheme, excluded) {

  const candidates = _.difference(themes, [mainTheme, subTheme, ...(excluded || [])]);
  const shuffled = shuffle(candidates);
  return [mainTheme, ..._.take(shuffled, 2), subTheme];

}

function getNextSequence(seq, themes) {

  if (!Array.isArray(seq) || seq.length <= 1) {

    const newseq = shuffle(themes);
    if (newseq[0] === seq[0]) {
      newseq.unshift(newseq.pop());
    }
    return newseq;

  }

  return seq.slice(1);

}

function getNextContext(prevctx) {

  const now = moment().tz(config.timezone);

  const prevContext = Object.assign({}, prevctx);
  const context = {};

  if (config.wordThemes) {

    const dateIndex = _.findIndex(
      config.wordThemes.date,
      d => d[0] === now.month() + 1 && d[1] === now.date()
    );

    if (dateIndex >= 0) {

      context.wordTheme = config.wordThemes.date[dateIndex][2];
      context.wordThemes = prevContext.wordThemes;

    } else if (
      Array.isArray(config.wordThemes.words) &&
      config.wordThemes.words.length > 0
    ) {

      context.wordThemes = getNextSequence(
        prevContext.wordThemes || [],
        _.flatten(config.wordThemes.words)
      );

      context.wordTheme = context.wordThemes[0];

    }

  }

  if (config.characterFree.indexOf(now.day()) >= 0) {

    context.mainThemes = prevContext.mainThemes;
    context.subThemes = prevContext.subThemes;
    context.themes = prevContext.themes;

  } else {

    context.mainThemes = getNextSequence(
      prevContext.mainThemes || [],
      config.mainThemes
    );

    context.subThemes = getNextSequence(
      prevContext.subThemes || [],
      config.subThemes
    );

    // Decide and save themes

    context.themes = generateThemes(
      config.themes,
      context.mainThemes[0],
      context.subThemes[0],
      config.excludePrevThemes ? prevContext.themes || [] : []
    );

  }

  return context;

}

module.exports = {
  generateThemes,
  getNextSequence,
  getNextContext
};
<|endoftext|>


<commit_before>import pad from 'multipad'
import Particle from 'particle-api-js'
import pickRandom from 'pick-random'
import request from 'request-promise'
import { COBOT_SUBDOMAIN } from '../../config/config'

const particle = new Particle()
const Checkin = require('mongoose').model('Checkin')
const Membership = require('mongoose').model('Membership')

function welcomeMessage(member) {
  const { name } = member
  const greetings = [
    [ 'Howdy', name ],
    [ 'Why hello', name ],
    [ 'Ciao', name ],
    [ 'Come on in', name ],
    [ 'I love you', name ],
    [ name, 'looking hot!' ],
    [ 'You rock', name ],
    [ 'Hola', name ],
  ]
  // Pick message and center text.
  const message = pickRandom(greetings).map((msg) => pad.center(msg, 16))
  return message.join('\n')
}

export default async (req, res) => {

  // Immediately return for Particle
  res.sendStatus(200)

  console.log('[checkin] Request body:', req.body)

  // Hack because cards start with 0's but
  // the Arduino app has them stripped off.
  // RFID card numbers are 10 characters long
  const accessToken = pad.left(req.body.data, 10, '0')

  console.log('[checkin] Access token:', accessToken)

  const member = await Membership.findOne({ accessToken })

  console.log('[checkin] Found member:', member)

  const auth = req.currentAccount.particleAccessToken

  if (member) {

    console.log('[checkin] Card accepted:', accessToken)

    await particle.publishEvent({
      name: 'sentry/allow',
      data: welcomeMessage(member),
      auth,
    })

    const checkin = await Checkin.create({
      accessToken,
      cobotId: member.cobotId,
      memberId: member.id,
      memberName: member.name,
      memberPlan: member.plan,
    })

  } else {

    console.error('[checkin] Card denied:', accessToken)

    await particle.publishEvent({
      name: 'sentry/deny',
      data: {},
      auth,
    })
  }

  // TODO: log checkin in cobot
  //{
    //"eventName": "Your event name",
    //"data": "Your event contents",
    //"published_at": "When it was published",
    //"coreid": "Your device ID"
  //}
  //const memberId =
  //const accessToken = req.currentAccount.cobotAccessToken
  //const tokens = await request({
    //headers: { 'Authorization': `Bearer ${accessToken}` },
    //method: 'POST',
    //json: true,
    //uri: `https://${COBOT_SUBDOMAIN}.cobot.me/api/memberships/${memberId}/work_sessions`,
  //})

}
<commit_msg>logshit<commit_after>import pad from 'multipad'
import Particle from 'particle-api-js'
import pickRandom from 'pick-random'
import request from 'request-promise'
import { COBOT_SUBDOMAIN } from '../../config/config'

const particle = new Particle()
const Checkin = require('mongoose').model('Checkin')
const Membership = require('mongoose').model('Membership')

function welcomeMessage(member) {
  const { name } = member
  const greetings = [
    [ 'Howdy', name ],
    [ 'Why hello', name ],
    [ 'Ciao', name ],
    [ 'Come on in', name ],
    [ 'I love you', name ],
    [ name, 'looking hot!' ],
    [ 'You rock', name ],
    [ 'Hola', name ],
  ]
  console.log(name)
  // Pick message and center text.
  let message = pickRandom(greetings)
  console.log(message)
  message = message.map((msg) => pad.center(msg, 16))
  return message.join('\n')
}

export default async (req, res) => {

  // Immediately return for Particle
  res.sendStatus(200)

  console.log('[checkin] Request body:', req.body)

  // Hack because cards start with 0's but
  // the Arduino app has them stripped off.
  // RFID card numbers are 10 characters long
  const accessToken = pad.left(req.body.data, 10, '0')

  console.log('[checkin] Access token:', accessToken)

  const member = await Membership.findOne({ accessToken })

  console.log('[checkin] Found member:', member)

  const auth = req.currentAccount.particleAccessToken

  if (member) {

    console.log('[checkin] Card accepted:', accessToken)

    await particle.publishEvent({
      name: 'sentry/allow',
      data: welcomeMessage(member),
      auth,
    })

    const checkin = await Checkin.create({
      accessToken,
      cobotId: member.cobotId,
      memberId: member.id,
      memberName: member.name,
      memberPlan: member.plan,
    })

  } else {

    console.error('[checkin] Card denied:', accessToken)

    await particle.publishEvent({
      name: 'sentry/deny',
      data: {},
      auth,
    })
  }

  // TODO: log checkin in cobot
  //{
    //"eventName": "Your event name",
    //"data": "Your event contents",
    //"published_at": "When it was published",
    //"coreid": "Your device ID"
  //}
  //const memberId =
  //const accessToken = req.currentAccount.cobotAccessToken
  //const tokens = await request({
    //headers: { 'Authorization': `Bearer ${accessToken}` },
    //method: 'POST',
    //json: true,
    //uri: `https://${COBOT_SUBDOMAIN}.cobot.me/api/memberships/${memberId}/work_sessions`,
  //})

}
<|endoftext|>


<commit_before>var validator = require('validator');
var errors = require('./errors');

function notAllowed(msg, req, res, next) {
    var result = {status: 'failure', message: msg};
    res.send(result);
}

function ping(msg, req, res, next) {
    var result = {status: 'ping', message: msg};
    res.send(result);
}

function preflight(msg, req, res, next) {
    res.send(204);
}

/**
 * Utility method for ensuring the payload is JSON
 *
 * @param req
 * @returns {*}
 */
function getBodyAsJSON(req) {

    if (!req) {
        return;
    }

    var rawData = req.body;

    if (!rawData) {
        return;
    }

    var type = typeof rawData;

    var data = rawData;
    if ("string" === typeof rawData) {
        data = JSON.parse(rawData);
    }
    return data;
}

/**
 * Utility method for extracting the access_token from either
 * a query parameter, body parameter, or header.
 *
 * @param req
 * @returns access_token if available via one of these strategies
 */
function getAccessToken(req) {

    var rawToken;

    if (req.query && req.query.access_token) {
        rawToken = req.query.access_token;
    }

    if (!rawToken && req.params && req.params.access_token) {
        rawToken = req.params.access_token;
    }

    if (!rawToken) {
        var jsonBody = getBodyAsJSON(req);
        if (jsonBody && jsonBody.access_token) {
            rawToken = jsonBody.access_token;
        }
    }

    if (!rawToken && req.headers && req.headers.authorization) {

        var authPieces = req.headers.authorization.split(' ');

        if (authPieces.length === 2) {
            var type = authPieces[0];
            var token = authPieces[1];

            if (type === 'Bearer' && token) {
                rawToken = token;
            }
        }
    }

    if (rawToken) {
        var sanitizedToken = validator.toString(rawToken);
        if (validator.isUUID(sanitizedToken, 4)) {
            return sanitizedToken;
        }
    }

}

/**
 * Utility method for extracting the permissions from either
 * a query parameter or the body.
 *
 * @param req
 * @returns permissions if available via one of these strategies
 */
function getPermissions(req) {

    var rawPermissions;

    if (req.query && req.query.permissions) {
        rawPermissions = req.query.permissions;
    }

    if (!rawPermissions && req.params && req.params.permissions) {
        rawPermissions = req.params.permissions;
    }

    if (!rawPermissions) {
        var jsonBody = getBodyAsJSON(req);
        if (jsonBody && jsonBody.permissions) {
            rawPermissions = jsonBody.permissions;
        }
    }

    if (rawPermissions) {
        var sanitizedPermissions = validator.toString(rawPermissions);
        var permissionsArray = sanitizedPermissions.split(' ');
        var testRegEx = /^[A-Za-z0-9\.]*$/;
        for (var i = 0; i < permissionsArray.length; i++) {
            var perm = permissionsArray[i];
            if (!testRegEx.test(perm)) {
                return null;
            }
        }
        return permissionsArray;
    }

}

/**
 * Fetch the origins field from either a query parameter
 * or the body. This is NOT the origin header field.
 * @param req
 * @returns origin field if available from one of these strategies
 */
function getOrigin(req, callback) {

    var rawOrigin;

    if (req.query && req.query.origin) {
        rawOrigin = req.query.origin;
    }

    if (!rawOrigin && req.params && req.params.origin) {
        rawOrigin = req.params.origin;
    }

    if (!rawOrigin) {
        var jsonBody = getBodyAsJSON(req);
        if (jsonBody && jsonBody.origin) {
            rawOrigin = jsonBody.origin;
        }
    }

    var sanitizedOrigin;
    if (rawOrigin) {
        if (typeof(rawOrigin) !=='string') {
            console.log('Type of origin value is not string: ' + typeof(rawOrigin));
            return callback(new errors.BadRequestError('invalidOriginFormat'), null);
        }
        sanitizedOrigin = validator.toString(rawOrigin);
        var spos = sanitizedOrigin.indexOf(':');
        if (spos != -1) {
            sanitizedOrigin = sanitizedOrigin.substring(0, spos);
        }
        var testRegEx = /^[A-Za-z0-9\.\-\$_]*$/;
        if (!testRegEx.test(sanitizedOrigin)) {
            console.log('Origin regex is failing on: ' + sanitizedOrigin);
            return callback(new errors.BadRequestError('invalidOriginFormat'), null);

        }
    }
    callback(null, sanitizedOrigin);
}

function getLocale(req) {
    return 'en';
};

module.exports.getBodyAsJSON = getBodyAsJSON;
module.exports.getAccessToken = getAccessToken;
module.exports.getPermissions = getPermissions;
module.exports.getOrigin = getOrigin;
module.exports.notAllowed = notAllowed;
module.exports.preflight = preflight;
module.exports.ping = ping;
module.exports.getLocale = getLocale;<commit_msg>NTFY-22 Moved the getHost utility function from database.js<commit_after>var validator = require('validator');
var errors = require('./errors');

function notAllowed(msg, req, res, next) {
    var result = {status: 'failure', message: msg};
    res.send(result);
}

function ping(msg, req, res, next) {
    var result = {status: 'ping', message: msg};
    res.send(result);
}

function preflight(msg, req, res, next) {
    res.send(204);
}

/**
 * Utility method for ensuring the payload is JSON
 *
 * @param req
 * @returns {*}
 */
function getBodyAsJSON(req) {

    if (!req) {
        return;
    }

    var rawData = req.body;

    if (!rawData) {
        return;
    }

    var type = typeof rawData;

    var data = rawData;
    if ("string" === typeof rawData) {
        data = JSON.parse(rawData);
    }
    return data;
}

/**
 * Utility method for extracting the access_token from either
 * a query parameter, body parameter, or header.
 *
 * @param req
 * @returns access_token if available via one of these strategies
 */
function getAccessToken(req) {

    var rawToken;

    if (req.query && req.query.access_token) {
        rawToken = req.query.access_token;
    }

    if (!rawToken && req.params && req.params.access_token) {
        rawToken = req.params.access_token;
    }

    if (!rawToken) {
        var jsonBody = getBodyAsJSON(req);
        if (jsonBody && jsonBody.access_token) {
            rawToken = jsonBody.access_token;
        }
    }

    if (!rawToken && req.headers && req.headers.authorization) {

        var authPieces = req.headers.authorization.split(' ');

        if (authPieces.length === 2) {
            var type = authPieces[0];
            var token = authPieces[1];

            if (type === 'Bearer' && token) {
                rawToken = token;
            }
        }
    }

    if (rawToken) {
        var sanitizedToken = validator.toString(rawToken);
        if (validator.isUUID(sanitizedToken, 4)) {
            return sanitizedToken;
        }
    }

}

/**
 * Utility method for extracting the permissions from either
 * a query parameter or the body.
 *
 * @param req
 * @returns permissions if available via one of these strategies
 */
function getPermissions(req) {

    var rawPermissions;

    if (req.query && req.query.permissions) {
        rawPermissions = req.query.permissions;
    }

    if (!rawPermissions && req.params && req.params.permissions) {
        rawPermissions = req.params.permissions;
    }

    if (!rawPermissions) {
        var jsonBody = getBodyAsJSON(req);
        if (jsonBody && jsonBody.permissions) {
            rawPermissions = jsonBody.permissions;
        }
    }

    if (rawPermissions) {
        var sanitizedPermissions = validator.toString(rawPermissions);
        var permissionsArray = sanitizedPermissions.split(' ');
        var testRegEx = /^[A-Za-z0-9\.]*$/;
        for (var i = 0; i < permissionsArray.length; i++) {
            var perm = permissionsArray[i];
            if (!testRegEx.test(perm)) {
                return null;
            }
        }
        return permissionsArray;
    }

}

/**
 * Fetch the origins field from either a query parameter
 * or the body. This is NOT the origin header field.
 * @param req
 * @returns origin field if available from one of these strategies
 */
function getOrigin(req, callback) {

    var rawOrigin;

    if (req.query && req.query.origin) {
        rawOrigin = req.query.origin;
    }

    if (!rawOrigin && req.params && req.params.origin) {
        rawOrigin = req.params.origin;
    }

    if (!rawOrigin) {
        var jsonBody = getBodyAsJSON(req);
        if (jsonBody && jsonBody.origin) {
            rawOrigin = jsonBody.origin;
        }
    }

    var sanitizedOrigin;
    if (rawOrigin) {
        if (typeof(rawOrigin) !=='string') {
            console.log('Type of origin value is not string: ' + typeof(rawOrigin));
            return callback(new errors.BadRequestError('invalidOriginFormat'), null);
        }
        sanitizedOrigin = validator.toString(rawOrigin);
        var spos = sanitizedOrigin.indexOf(':');
        if (spos != -1) {
            sanitizedOrigin = sanitizedOrigin.substring(0, spos);
        }
        var testRegEx = /^[A-Za-z0-9\.\-\$_]*$/;
        if (!testRegEx.test(sanitizedOrigin)) {
            console.log('Origin regex is failing on: ' + sanitizedOrigin);
            return callback(new errors.BadRequestError('invalidOriginFormat'), null);

        }
    }
    callback(null, sanitizedOrigin);
}

function getLocale(req) {
    return 'en';
};

/**
 * Get the host value from the request. This prefers the forwarded host header (if provided)
 * over the local host
 * @param req
 */
var getHost = function(req) {

    var host = req.headers.host;
    if (req.headers['x-forwarded-host']) {
        host = req.headers['x-forwarded-host'];
    }
    return host;
};

module.exports.getBodyAsJSON = getBodyAsJSON;
module.exports.getAccessToken = getAccessToken;
module.exports.getPermissions = getPermissions;
module.exports.getOrigin = getOrigin;
module.exports.notAllowed = notAllowed;
module.exports.preflight = preflight;
module.exports.ping = ping;
module.exports.getLocale = getLocale;
module.exports.getHost = getHost;<|endoftext|>


<commit_before>var Facade    = require('./facade')
  , component = require('require-component')(require)
  , clone     = component('clone')
  , Identify  = component('./identify')
  , inherit   = component('inherit')
  , isEmail   = component('is-email');

module.exports = Track;

function Track(track) {
  Facade.call(this, track);
}

inherit(Track, Facade);

Track.prototype.action = function () {
  return 'track';
};

/**
 * Property fields
 */

Track.prototype.userId     = Facade.field('userId');
Track.prototype.sessionId  = Facade.field('sessionId');
Track.prototype.event      = Facade.field('event');

/**
 * Return properties or an empty object
 */

Track.prototype.properties = function () {
  return this.field('properties') || {};
};

/**
 * Backwards compat, should probably re-examine where these come from.
 */

Track.prototype.referrer   = Facade.proxy('properties.referrer');
Track.prototype.username   = Facade.proxy('properties.username');

Track.prototype.query      = Facade.proxy('options.query');

/**
 * Parse the revenue from a number or a string matching '$45.00'
 */

Track.prototype.revenue = function () {
  var proxy   = Facade.proxy('properties.revenue')
    , revenue = proxy.call(this);

  if (!revenue) return;
  if (typeof revenue === 'number') return revenue;
  if (typeof revenue !== 'string') return;

  revenue = revenue.replace(/\$/g, '');
  revenue = parseFloat(revenue);

  if (!isNaN(revenue)) return revenue;
};

/**
 * Use the email if the userId matches it
 */

Track.prototype.email = function () {
  var userId = this.userId() || this.sessionId();
  if (isEmail(userId)) return userId;
};

/**
 * Adds the ability to send 'super properties' as part of a track
 * TODO: remove me eventually and just use state on the server
 */

Track.prototype.traits = function () {
  return this.proxy('options.traits') || {};
};

/**
 * A utility to turn the pieces of a track call into an identify. Used for
 * integrations with super properties or rate limits.
 * TODO: remove me.
 */

Track.prototype.identify = function () {
  var json = this.json();
  json.traits = this.traits();
  return new Identify(json);
};<commit_msg>track: updating .email()<commit_after>var Facade    = require('./facade')
  , component = require('require-component')(require)
  , clone     = component('clone')
  , Identify  = component('./identify')
  , inherit   = component('inherit')
  , isEmail   = component('is-email');

module.exports = Track;

function Track(track) {
  Facade.call(this, track);
}

inherit(Track, Facade);

Track.prototype.action = function () {
  return 'track';
};

/**
 * Property fields
 */

Track.prototype.userId     = Facade.field('userId');
Track.prototype.sessionId  = Facade.field('sessionId');
Track.prototype.event      = Facade.field('event');

/**
 * Return properties or an empty object
 */

Track.prototype.properties = function () {
  return this.field('properties') || {};
};

/**
 * Backwards compat, should probably re-examine where these come from.
 */

Track.prototype.referrer   = Facade.proxy('properties.referrer');
Track.prototype.username   = Facade.proxy('properties.username');

Track.prototype.query      = Facade.proxy('options.query');

/**
 * Parse the revenue from a number or a string matching '$45.00'
 */

Track.prototype.revenue = function () {
  var proxy   = Facade.proxy('properties.revenue')
    , revenue = proxy.call(this);

  if (!revenue) return;
  if (typeof revenue === 'number') return revenue;
  if (typeof revenue !== 'string') return;

  revenue = revenue.replace(/\$/g, '');
  revenue = parseFloat(revenue);

  if (!isNaN(revenue)) return revenue;
};

/**
 * Use the email if the userId matches it
 */

Track.prototype.email = function () {
  var userId = this.userId() || this.sessionId();
  if (isEmail(userId)) return userId;

  return this.proxy('traits.email') || this.proxy('properties.email');
};

/**
 * Adds the ability to send 'super properties' as part of a track
 * TODO: remove me eventually and just use state on the server
 */

Track.prototype.traits = function () {
  return this.proxy('options.traits') || {};
};

/**
 * A utility to turn the pieces of a track call into an identify. Used for
 * integrations with super properties or rate limits.
 * TODO: remove me.
 */

Track.prototype.identify = function () {
  var json = this.json();
  json.traits = this.traits();
  return new Identify(json);
};<|endoftext|>