<commit_before>#!/usr/bin/env node
"use strict";

var path = require("path"),
    request = require("request"),
    async = require("async"),
    _ = require("underscore"),
    assert = require("assert"),
    fs = require("fs"),
    pth = require("path");

var apiDriver = require("api-driver"),
    reporter_ = require("./lib/reporter");

var topics = [];
var openTopic;
var beforeFn = function() {};
var afterFn = function() {};

var Topic = function(description) {
    this.description = description || "";
    this._orderedStories = [];
    this._stories = {};
    this._orderedSteps = [];
    this._steps = {};
    this._stepDescriptions = {};
    this._beforeFn = function() {};
    this._afterFn = function() {};
};

var depthFirst = function(step) {
    var paths = [];

    var _depthFirst = function(step, path) {
        path.push(step);
        if (! step || ! step.nextSteps || step.nextSteps.length === 0) {
            //leaf -- this is the end of a path
            paths.push(path);
            return;
        }
        _.each(step.nextSteps, function(c) {
                var newPath = _.clone(path);
                _depthFirst(c, newPath);
            });
    };

    _depthFirst(step, []);
    return paths;
};

Topic.prototype.setBefore = function(fn) {
    assert(_.isFunction(fn));
    this._beforeFn = fn;
};

Topic.prototype.setAfter = function(fn) {
    assert(_.isFunction(fn));
    this._afterFn = fn;
};

Topic.prototype.matchingStories = function(patterns) {
    var stories = this._orderedStories;
    return _.filter(stories, function(story) {
        return _.any( patterns, function(pat) {
            return pat.test(story.description);
        });
    });
};

var pathDesc = function(path) {
    var pathDesc = "";
    if (path[0].description !== "$body$") {
        var steps = _.filter(path, _.identity);
        pathDesc = _.pluck(steps, "description").join(" > ");
    }

    return pathDesc;
};

Topic.prototype.run = function(pathPatterns, before, after, stories, reporter, pathReporter, done) {
    var that = this;

    async.forEachSeries(stories, function(story, storyCb) {

        if (! story.root ) {
            console.log(story.description);
            console.log("  #### deferred ####");
            return storyCb();
        }

        reporter.story(story.description);
        console.log(story.description);

        var paths = depthFirst(story.root);
        if (pathPatterns) {
            paths = _.filter(paths, function(path) {
                var desc = pathDesc(path);
                return _.any(pathPatterns, function(pat) {
                    return pat.test(desc);
                });
            });
        }
        async.forEachSeries(paths, function(path, cb) {
            try {
                var driver = apiDriver.driver();

                reporter.beforeAll();
                before(driver);
                reporter.endBeforeAll();

                reporter.before();
                driver.wait();
                that._beforeFn(driver);
                reporter.endBefore();

                reporter.path();

                var stepDeferred = false;
                _.each(path, function(step) {

                    if ( ! step ) {
                        stepDeferred = true;
                        return;
                    }

                    reporter.step(step.description, step.isFork);

                    driver.wait();

                    driver.scribingOn( reporter.getScribe() );
                    step.fn(driver);
                    driver.scribingOff();

                    reporter.endStep();

                });

                reporter.endPath();

                driver.results( function(err, expectationResults) {
                    var desc = pathDesc(path) + (stepDeferred ? " > ### deferred ###" : "");
                    pathReporter(err, desc, expectationResults);
                    cb();
                });

            } catch (e) {
                pathReporter(e, "");
                cb();
            }
        }, function() {

            that._afterFn();

            reporter.endStory();

            storyCb();

        });

    }, done);
};

Topic.prototype.addStory = function(story) {
    this._orderedStories.push(story);
};

var runTopics = function(opts, pathReporter, transcriptReporter, done) {

    // Only run stories that have a match in the supplied patterns
    var topics_ = _.filter(topics, function(t) {
        return ! opts.topics ||
               _.any( opts.topics, function(pat) { return pat.test(t.description); });
    });

    async.forEachSeries(topics_, function(topic, cb) {
        var stories = topic.matchingStories(opts.stories || [RegExp(".*")] );
        if (stories.length > 0) {
            var length = topic.description.length;
            var titlePad = 80 - length;
            console.log();
            console.log();
            console.log(Array(titlePad+1).join(" ") + topic.description);
            console.log(Array(80+1).join("-"));

            var reporter = reporter_.makeReporter(topic.description + " (stories)");
            topic.run(opts.paths, beforeFn, afterFn, stories, reporter, pathReporter, function() {
                transcriptReporter(reporter.transcript);
                cb();
            });
            return;
        }
        cb();
    }, done);
};

var linkSteps = function(steps) {
    assert(   steps.what === "step"
           || _.isArray(steps));
    if (steps.what === "step") return steps;
    var curStep = steps[0];
    _.any(_.rest(steps), function(step) {
        if (curStep === null) return true;
        if (_.isArray(step)) {
            curStep.nextSteps = step;
        } else {
            curStep.nextSteps = [step];
            curStep = step;
        }
    });

    return steps[0];
};

var config = {};

module.exports = {
    config : function(opts) {
        apiDriver.config(opts);
        if (opts.endpoint) config.endpoint = opts.endpoint;
    },

    beforeEachPath : function(fn) {
        // console.log(fn.toString());
        assert(_.isFunction(fn));
        beforeFn = fn;
    },

    afterEachPath: function(fn) {
        // console.log(fn.toString());
        assert(_.isFunction(fn));
        afterFn = fn;
    },

    topic : function(description, fn) {
        openTopic = new Topic(description);
        fn();
        topics.push(openTopic);
        openTopic = null;
    },

    before : function(fn) {
        assert(_.isFunction(fn));
        openTopic.setBefore(fn);
    },

    after : function(fn) {
        assert(_.isFunction(fn));
        openTopic.setAfter(fn);
    },

    story : function(description, body) {
        assert( _.isFunction(body)
                || body === null
                || body.what === "step",
                "Story must be a function or a step");
        var step;
        if (_.isFunction(body)) {
            step = {
                what: "step",
                description: "$body$",
                fn: body,
                nextSteps: []
            };
        } else {
            step = body;
        }

        var story = {
            description: description,
            root: step
        };

        openTopic.addStory(story);
    },

    test : function(description /*, splat...*/) {
        var splat = _.rest(_.toArray(arguments));
        assert( _.isFunction(splat[0])
                || splat[0] === null
                || splat[0].what === "step",
                "Test takes a function or a step");
        var rootStep;
        if (_.isFunction(splat[0])) {
            rootStep = {
                what: "step",
                description: "$body$",
                fn: splat[0],
                nextSteps: []
            };
        } else {
            rootStep = linkSteps(splat);
        }

        var story = {
            description: description,
            root: rootStep
        };

        openTopic.addStory(story);

    },

    step : function(description, fn) {
        assert(_.isFunction(fn) || fn === null);

        var steps = [];
        if (fn !== null) {
            steps = _.toArray(arguments).slice(2);
            assert( _.all(steps, function(s) { return s === null || s.what === "step"; } ),
                    "Optional args to a step must be additional steps or null" );
            if (steps.length > 1) {
                _.map(steps, function(step) {
                    if (step) step.isFork = true;
                    return step;
                });
            }

            // other steps are deferred
            var last = steps.indexOf(null);
            if (last !== -1) {
                steps = steps.slice(0, last+1);
            }
        }

        return {
            what: "step",
            description: description,
            fn: fn,
            nextSteps: steps
        };
    },

    branch : function(/* branches... */) {
        var nextSteps = [];
        _.each(_.toArray(arguments), function(steps) {
            nextSteps.push(_.extend(linkSteps(steps), {isFork: true}));
        });
        return nextSteps;
    }

};

module.exports.suite = module.exports.topic;
module.exports.beforeEach = module.exports.beforeEachPath;
module.exports.afterEach = module.exports.afterEachPath;
module.exports.expectations = require("api-driver/expectations");
module.exports.driverApi = require("api-driver").api;

if (! module.parent) {
    var program = require("commander"),
        minimatch = require("minimatch");

    var list = function(val) {
        return val.split(',');
    };

    var patterns = function(fnpat) {
        return _.map(list(fnpat), minimatch.makeRe );
    };

    var invertTest = function(pat) {
        return {
            test: function(val) {
                return (! pat.test(val));
            }
        };
    };

    var inversePatterns = function(fnpat) {
        return _.map(list(fnpat), function(fnpat) {
            return invertTest( minimatch.makeRe(fnpat) );
        });
    };

    program
        .version("0.0.1")
        .usage("[options] <configfile> <storyfiles...>")
        .option("-s, --suites <patterns,...>",
                "only run suites that match the fnmatch pattern",
                patterns)
        .option("-S, --not-suites <patterns,...>",
                "only run suites that do not match the fnmatch pattern",
                inversePatterns)
        .option("-t, --test <patterns,...>",
                "only run tests that match the fnmatch pattern",
                patterns)
        .option("-T, --not-tests <patterns,...>",
                "only run tests that do not match the fnmatch pattern",
                inversePatterns)
        .option("-p, --paths <patterns,...>",
                "only run paths that match the fnmatch pattern",
                patterns)
        .option("-P, --not-paths <patterns,...>",
                "only run paths that do not match the fnmatch pattern",
                inversePatterns)
        .option("-o, --transcripts <dir>",
                "output directory for transcripts")
        .option("-e, --endpoint <dir>",
                "Url for the base path of the api.  If path portion is " +
                "included, e.g. /api/v1/, it will be appended to " +
                "all requests.")
        .option("-c, --setup <dir>",
                "Location of the setup file.  By default, stories from the " +
                "the first test file and checks each folder " +
                "up to the root for 'stories_setup.js')")
        .parse(process.argv);

    var outDir = program.transcripts;
    var testFiles = program.args;

    if (testFiles.length < 1) {
        program.outputHelp();
        process.exit(1);
    }

    program.topics = program.suites || program.notSuites;
    program.stories = program.tests || program.notTests;
    program.paths = program.paths || program.notPaths;

    var logRight = function(msg) {
        var colWidth = 80;
        var pad = colWidth - msg.length;
        var spaces = Array(pad+1).join(" ");
        console.log(spaces + msg);
    };

    var load = function(path) {
        if (path.slice(0,2) !== "." + pth.sep && path.slice(0,1) !== pth.sep) {
            path = "." + pth.sep + path;
        }
        require(pth.resolve(path));
    };

    var setupFile = program.setup;
    if (! setupFile) {
        var dirs = pth.resolve(testFiles[0]).split(path.sep).slice(0,-1);
        _.each(
            _.range(dirs.length)
            , function(i) {
                var f = _.first(dirs, dirs.length-i)
                        .concat(["stories_setup.js"])
                        .join(pth.sep);
                if (fs.existsSync(f)) {
                    setupFile = f;
                }
            }
        );
    }
    if (! setupFile) {
        console.log("warning: setup file not specified and not found");
    } else {
        load(setupFile);
    }

    // load(testFiles[0]); // first file is the config file
    // testFiles = _.rest(testFiles);

    // command line overrides config
    if (program.endpoint) config.endpoint = program.endpoint;

    if (! config.endpoint) {
        console.log("error: api endpoint not provided");
        process.exit(1);
    }

    request(config.endpoint+"/version", function(err, resp, body) {

        var failed = false;
        if (err) {
            throw err;
        }
        var commitSHA;
        try {
            commitSHA = JSON.parse(body).commit;
            assert(commitSHA);
        } catch(e) {
            console.error("warning: api version string not found");
        }
        var transcripts = [];
        var apiIndex = {
            commit: commitSHA,
            transcripts: transcripts
        };
        var expectationsPassed = 0;
        var expectationsFailed = 0;
        async.forEachSeries(testFiles, function(testFile, callback) {

            // give filename relative path for use with requires
            load(testFile);
            callback();

        }, function() {
            runTopics(

                program,

                // called for each path
                function(err, path, expectationResults) {
                    if (err || expectationResults.expectationsFailed) {
                        //it's an error
                        console.log("  XX: " + path);
                        console.log();
                        console.log(err ? err.stack : expectationResults.err.stack);
                        console.log();
                        failed = true;
                    } else {
                        var msg = path === "" ? "  ok" : "  ok: " + path;
                        console.log(msg);
                    }
                    if (expectationResults) {
                        expectationsPassed += expectationResults.expectationsPassed;
                        expectationsFailed += expectationResults.expectationsFailed;
                    }
                },
                function(transcript) {
                    if (! outDir) { return; }

                    var outFile = path.basename(transcript.description.replace(/ /g, '_'), ".js") + ".json";
                    fs.writeFileSync(outDir + "/" + outFile, JSON.stringify(transcript, null, 4));
                    transcripts.push({desc: transcript.description, file: outFile});
                },
                // called when all done
                function() {
                    if (outDir) {
                        fs.writeFileSync(outDir + "/index2.json", JSON.stringify(apiIndex, null, 4));
                    }
                    if (!failed) {
                        logRight("Expectations Passed: " + expectationsPassed);
                        logRight("ALL OK!");
                    } else {
                        logRight("Expectations Failed: " + expectationsFailed);
                        logRight("FAILED!");
                        process.exit(1);
                    }
                }
            );
        });
    });
}
<commit_msg>driver module nolonger has config<commit_after>#!/usr/bin/env node
"use strict";

var path = require("path"),
    request = require("request"),
    async = require("async"),
    _ = require("underscore"),
    assert = require("assert"),
    fs = require("fs"),
    pth = require("path");

var apiDriver = require("api-driver"),
    reporter_ = require("./lib/reporter");

var topics = [];
var openTopic;
var beforeFn = function() {};
var afterFn = function() {};

var Topic = function(description) {
    this.description = description || "";
    this._orderedStories = [];
    this._stories = {};
    this._orderedSteps = [];
    this._steps = {};
    this._stepDescriptions = {};
    this._beforeFn = function() {};
    this._afterFn = function() {};
};

var depthFirst = function(step) {
    var paths = [];

    var _depthFirst = function(step, path) {
        path.push(step);
        if (! step || ! step.nextSteps || step.nextSteps.length === 0) {
            //leaf -- this is the end of a path
            paths.push(path);
            return;
        }
        _.each(step.nextSteps, function(c) {
                var newPath = _.clone(path);
                _depthFirst(c, newPath);
            });
    };

    _depthFirst(step, []);
    return paths;
};

Topic.prototype.setBefore = function(fn) {
    assert(_.isFunction(fn));
    this._beforeFn = fn;
};

Topic.prototype.setAfter = function(fn) {
    assert(_.isFunction(fn));
    this._afterFn = fn;
};

Topic.prototype.matchingStories = function(patterns) {
    var stories = this._orderedStories;
    return _.filter(stories, function(story) {
        return _.any( patterns, function(pat) {
            return pat.test(story.description);
        });
    });
};

var pathDesc = function(path) {
    var pathDesc = "";
    if (path[0].description !== "$body$") {
        var steps = _.filter(path, _.identity);
        pathDesc = _.pluck(steps, "description").join(" > ");
    }

    return pathDesc;
};

Topic.prototype.run = function(pathPatterns, before, after, stories, reporter, pathReporter, done) {
    var that = this;

    async.forEachSeries(stories, function(story, storyCb) {

        if (! story.root ) {
            console.log(story.description);
            console.log("  #### deferred ####");
            return storyCb();
        }

        reporter.story(story.description);
        console.log(story.description);

        var paths = depthFirst(story.root);
        if (pathPatterns) {
            paths = _.filter(paths, function(path) {
                var desc = pathDesc(path);
                return _.any(pathPatterns, function(pat) {
                    return pat.test(desc);
                });
            });
        }
        async.forEachSeries(paths, function(path, cb) {
            try {
                var driver = apiDriver.driver();

                reporter.beforeAll();
                before(driver);
                reporter.endBeforeAll();

                reporter.before();
                driver.wait();
                that._beforeFn(driver);
                reporter.endBefore();

                reporter.path();

                var stepDeferred = false;
                _.each(path, function(step) {

                    if ( ! step ) {
                        stepDeferred = true;
                        return;
                    }

                    reporter.step(step.description, step.isFork);

                    driver.wait();

                    driver.scribingOn( reporter.getScribe() );
                    step.fn(driver);
                    driver.scribingOff();

                    reporter.endStep();

                });

                reporter.endPath();

                driver.results( function(err, expectationResults) {
                    var desc = pathDesc(path) + (stepDeferred ? " > ### deferred ###" : "");
                    pathReporter(err, desc, expectationResults);
                    cb();
                });

            } catch (e) {
                pathReporter(e, "");
                cb();
            }
        }, function() {

            that._afterFn();

            reporter.endStory();

            storyCb();

        });

    }, done);
};

Topic.prototype.addStory = function(story) {
    this._orderedStories.push(story);
};

var runTopics = function(opts, pathReporter, transcriptReporter, done) {

    // Only run stories that have a match in the supplied patterns
    var topics_ = _.filter(topics, function(t) {
        return ! opts.topics ||
               _.any( opts.topics, function(pat) { return pat.test(t.description); });
    });

    async.forEachSeries(topics_, function(topic, cb) {
        var stories = topic.matchingStories(opts.stories || [RegExp(".*")] );
        if (stories.length > 0) {
            var length = topic.description.length;
            var titlePad = 80 - length;
            console.log();
            console.log();
            console.log(Array(titlePad+1).join(" ") + topic.description);
            console.log(Array(80+1).join("-"));

            var reporter = reporter_.makeReporter(topic.description + " (stories)");
            topic.run(opts.paths, beforeFn, afterFn, stories, reporter, pathReporter, function() {
                transcriptReporter(reporter.transcript);
                cb();
            });
            return;
        }
        cb();
    }, done);
};

var linkSteps = function(steps) {
    assert(   steps.what === "step"
           || _.isArray(steps));
    if (steps.what === "step") return steps;
    var curStep = steps[0];
    _.any(_.rest(steps), function(step) {
        if (curStep === null) return true;
        if (_.isArray(step)) {
            curStep.nextSteps = step;
        } else {
            curStep.nextSteps = [step];
            curStep = step;
        }
    });

    return steps[0];
};

var config = {};

module.exports = {
    config : function(opts) {
        if (opts.endpoint) config.endpoint = opts.endpoint;
    },

    beforeEachPath : function(fn) {
        // console.log(fn.toString());
        assert(_.isFunction(fn));
        beforeFn = fn;
    },

    afterEachPath: function(fn) {
        // console.log(fn.toString());
        assert(_.isFunction(fn));
        afterFn = fn;
    },

    topic : function(description, fn) {
        openTopic = new Topic(description);
        fn();
        topics.push(openTopic);
        openTopic = null;
    },

    before : function(fn) {
        assert(_.isFunction(fn));
        openTopic.setBefore(fn);
    },

    after : function(fn) {
        assert(_.isFunction(fn));
        openTopic.setAfter(fn);
    },

    story : function(description, body) {
        assert( _.isFunction(body)
                || body === null
                || body.what === "step",
                "Story must be a function or a step");
        var step;
        if (_.isFunction(body)) {
            step = {
                what: "step",
                description: "$body$",
                fn: body,
                nextSteps: []
            };
        } else {
            step = body;
        }

        var story = {
            description: description,
            root: step
        };

        openTopic.addStory(story);
    },

    test : function(description /*, splat...*/) {
        var splat = _.rest(_.toArray(arguments));
        assert( _.isFunction(splat[0])
                || splat[0] === null
                || splat[0].what === "step",
                "Test takes a function or a step");
        var rootStep;
        if (_.isFunction(splat[0])) {
            rootStep = {
                what: "step",
                description: "$body$",
                fn: splat[0],
                nextSteps: []
            };
        } else {
            rootStep = linkSteps(splat);
        }

        var story = {
            description: description,
            root: rootStep
        };

        openTopic.addStory(story);

    },

    step : function(description, fn) {
        assert(_.isFunction(fn) || fn === null);

        var steps = [];
        if (fn !== null) {
            steps = _.toArray(arguments).slice(2);
            assert( _.all(steps, function(s) { return s === null || s.what === "step"; } ),
                    "Optional args to a step must be additional steps or null" );
            if (steps.length > 1) {
                _.map(steps, function(step) {
                    if (step) step.isFork = true;
                    return step;
                });
            }

            // other steps are deferred
            var last = steps.indexOf(null);
            if (last !== -1) {
                steps = steps.slice(0, last+1);
            }
        }

        return {
            what: "step",
            description: description,
            fn: fn,
            nextSteps: steps
        };
    },

    branch : function(/* branches... */) {
        var nextSteps = [];
        _.each(_.toArray(arguments), function(steps) {
            nextSteps.push(_.extend(linkSteps(steps), {isFork: true}));
        });
        return nextSteps;
    }

};

module.exports.suite = module.exports.topic;
module.exports.beforeEach = module.exports.beforeEachPath;
module.exports.afterEach = module.exports.afterEachPath;
module.exports.expectations = require("api-driver/expectations");
module.exports.driverApi = require("api-driver").api;

if (! module.parent) {
    var program = require("commander"),
        minimatch = require("minimatch");

    var list = function(val) {
        return val.split(',');
    };

    var patterns = function(fnpat) {
        return _.map(list(fnpat), minimatch.makeRe );
    };

    var invertTest = function(pat) {
        return {
            test: function(val) {
                return (! pat.test(val));
            }
        };
    };

    var inversePatterns = function(fnpat) {
        return _.map(list(fnpat), function(fnpat) {
            return invertTest( minimatch.makeRe(fnpat) );
        });
    };

    program
        .version("0.0.1")
        .usage("[options] <configfile> <storyfiles...>")
        .option("-s, --suites <patterns,...>",
                "only run suites that match the fnmatch pattern",
                patterns)
        .option("-S, --not-suites <patterns,...>",
                "only run suites that do not match the fnmatch pattern",
                inversePatterns)
        .option("-t, --test <patterns,...>",
                "only run tests that match the fnmatch pattern",
                patterns)
        .option("-T, --not-tests <patterns,...>",
                "only run tests that do not match the fnmatch pattern",
                inversePatterns)
        .option("-p, --paths <patterns,...>",
                "only run paths that match the fnmatch pattern",
                patterns)
        .option("-P, --not-paths <patterns,...>",
                "only run paths that do not match the fnmatch pattern",
                inversePatterns)
        .option("-o, --transcripts <dir>",
                "output directory for transcripts")
        .option("-e, --endpoint <dir>",
                "Url for the base path of the api.  If path portion is " +
                "included, e.g. /api/v1/, it will be appended to " +
                "all requests.")
        .option("-c, --setup <dir>",
                "Location of the setup file.  By default, stories from the " +
                "the first test file and checks each folder " +
                "up to the root for 'stories_setup.js')")
        .parse(process.argv);

    var outDir = program.transcripts;
    var testFiles = program.args;

    if (testFiles.length < 1) {
        program.outputHelp();
        process.exit(1);
    }

    program.topics = program.suites || program.notSuites;
    program.stories = program.tests || program.notTests;
    program.paths = program.paths || program.notPaths;

    var logRight = function(msg) {
        var colWidth = 80;
        var pad = colWidth - msg.length;
        var spaces = Array(pad+1).join(" ");
        console.log(spaces + msg);
    };

    var load = function(path) {
        if (path.slice(0,2) !== "." + pth.sep && path.slice(0,1) !== pth.sep) {
            path = "." + pth.sep + path;
        }
        require(pth.resolve(path));
    };

    var setupFile = program.setup;
    if (! setupFile) {
        var dirs = pth.resolve(testFiles[0]).split(path.sep).slice(0,-1);
        _.each(
            _.range(dirs.length)
            , function(i) {
                var f = _.first(dirs, dirs.length-i)
                        .concat(["stories_setup.js"])
                        .join(pth.sep);
                if (fs.existsSync(f)) {
                    setupFile = f;
                }
            }
        );
    }
    if (! setupFile) {
        console.log("warning: setup file not specified and not found");
    } else {
        load(setupFile);
    }

    // load(testFiles[0]); // first file is the config file
    // testFiles = _.rest(testFiles);

    // command line overrides config
    if (program.endpoint) config.endpoint = program.endpoint;

    if (! config.endpoint) {
        console.log("error: api endpoint not provided");
        process.exit(1);
    }

    request(config.endpoint+"/version", function(err, resp, body) {

        var failed = false;
        if (err) {
            throw err;
        }
        var commitSHA;
        try {
            commitSHA = JSON.parse(body).commit;
            assert(commitSHA);
        } catch(e) {
            console.error("warning: api version string not found");
        }
        var transcripts = [];
        var apiIndex = {
            commit: commitSHA,
            transcripts: transcripts
        };
        var expectationsPassed = 0;
        var expectationsFailed = 0;
        async.forEachSeries(testFiles, function(testFile, callback) {

            // give filename relative path for use with requires
            load(testFile);
            callback();

        }, function() {
            runTopics(

                program,

                // called for each path
                function(err, path, expectationResults) {
                    if (err || expectationResults.expectationsFailed) {
                        //it's an error
                        console.log("  XX: " + path);
                        console.log();
                        console.log(err ? err.stack : expectationResults.err.stack);
                        console.log();
                        failed = true;
                    } else {
                        var msg = path === "" ? "  ok" : "  ok: " + path;
                        console.log(msg);
                    }
                    if (expectationResults) {
                        expectationsPassed += expectationResults.expectationsPassed;
                        expectationsFailed += expectationResults.expectationsFailed;
                    }
                },
                function(transcript) {
                    if (! outDir) { return; }

                    var outFile = path.basename(transcript.description.replace(/ /g, '_'), ".js") + ".json";
                    fs.writeFileSync(outDir + "/" + outFile, JSON.stringify(transcript, null, 4));
                    transcripts.push({desc: transcript.description, file: outFile});
                },
                // called when all done
                function() {
                    if (outDir) {
                        fs.writeFileSync(outDir + "/index2.json", JSON.stringify(apiIndex, null, 4));
                    }
                    if (!failed) {
                        logRight("Expectations Passed: " + expectationsPassed);
                        logRight("ALL OK!");
                    } else {
                        logRight("Expectations Failed: " + expectationsFailed);
                        logRight("FAILED!");
                        process.exit(1);
                    }
                }
            );
        });
    });
}
<|endoftext|>


<commit_before>/*
* @Author: ChalrieHwang
* @Date:   2015-06-01 17:45:29
* @Last Modified by:   ChalrieHwang
* @Last Modified time: 2015-06-01 20:35:51
*/

'use strict';
(function(angular){

  var GraphConfig = function($stateProvider){
    $stateProvider.state('graph',{
      url: '/graph',
      templateUrl: 'graph/graph.tpl.html',
      controller: GraphCtrl
    });
  };

  var GraphCtrl = function($scope){

    // $scope.init = function(){
    //   $scope.
    // };

    /**
     * Define function for creating the graph canvas object
     * @return {d3} d3 graph object
     */
    $scope.createCanvas = function(){
      var g = new dagreD3.graphlib.Graph()
        .setGraph({})
        .setDefaultEdgeLabel(function() { return {}; });
      return g;
    };

    /**
     * Define function for rendering nodes on the graph
     * @param  {d3} canvas d3 graph object
     * @return {[type]}        [description]
     */
    $scope.renderGraph = function(canvas){
      var render = new dagreD3.render();
      var svg = d3.select('svg');
      render(d3.select('svg g'), canvas);
      var initialScale = 0.5;
      var width = canvas.graph().width * initialScale;
      $scope.onZoom()
        .translate([(svg.attr('width') - width) / 40 + 30, 20])
        .scale(initialScale)
        .event(svg);
      svg.attr('height', canvas.graph().height * initialScale + 40);
    };

    /**
     * Define event listeners to handle zooming
     * @return {d3} [description]
     */
    $scope.onZoom = function(){
      var svg = d3.select('svg');
      var inner = svg.select('g');
      var zoom = d3.behavior.zoom().on('zoom', function() {
            inner.attr('transform', 'translate(' + d3.event.translate + ')'+'scale(' + d3.event.scale + ')');
          });
      svg.call(zoom);
      return zoom;
    };

    /**
     * Define function to create node in graph object
     * @param  {d3} canvas  d3 graph object to collect nodes
     * @param  {json} jsonObj node data from server
     * @return {[type]}         [description]
     */
    $scope.createNode = function(canvas, jsonObj){
      var id = jsonObj.nodeID;
      var label = jsonObj.abbrev;
      var nodeType = jsonObj.nodeType;

      canvas.setNode(id, {
        label: label,
        class: nodeType,
        shape: 'circle'
      });
      canvas.node(id).name = jsonObj.name;
      canvas.node(id).description = jsonObj.description;
      canvas.node(id).asignee = jsonObj.asignee;
      canvas.node(id).user = jsonObj.user;
      canvas.node(id).parentCluster = jsonObj.parentCluster;
      canvas.node(id).upstreams = jsonObj.upstreams;
      canvas.node(id).downstreams = jsonObj.downstreams;
      canvas.node(id).status = jsonObj.status;
      canvas.node(id).issueType = jsonObj.labels;
    };
    /**
     * Define function to setup all edges of the node
     * @param  {d3} canvas d3 graph object
     * @param  {number} id     The id of node
     * @return {[type]}        [description]
     */
    $scope.createEdge = function(canvas, id){
      canvas.node(id).downstreams.forEach(function(downstreamID){
        canvas.setEdge(id, downstreamID, {lineInterpolate: 'basis'});
      });
    };

    $scope.addEdge = function(upstreamID, downstreamID, canvas){
      var entryID = canvas.nodes()[0];
      var exitID = canvas.nodes()[1];
      var downstreamNode = canvas.node(downstreamID);
      var upstreamNode = canvas.node(upstreamID);
      var foundNode;
      var resultUp = false;
      var resultDown = false;
      var traverseUp = function(nodeID, targetID){

        if(nodeID === entryID){
          return;
        }
        var list = canvas.node(nodeID).upstreams;
        if(list.hasOwnProperty(targetID)){
          resultUp = true;
          foundNode = targetID;
          return;
        }
        for(var key in list){
          if(!resultUp){
            traverseUp(key, targetID);
          }
        }
      };
      var traverseDown = function(nodeID, targetID){

        if(nodeID === exitID){
          return;
        }
        var list = canvas.node(nodeID).downstreams;
        if(list.hasOwnProperty(targetID)){
          resultDown = true;
          foundNode = targetID;
          return;
        }
        for(var key in list){
          if(!resultDown){
            traverseUp(key, targetID);
          }
        }
      };
      var deleteDownStreams = function(upstreamID, downstreamID, canvas){
        var downList = canvas.node(downstreamID).downstreams;
        var updownList = canvas.node(upstreamID).downstreams;
        for(var key in downList){
          if(updownList.hasOwnProperty(key)){
            delete canvas.node(upstreamID).downstreams[key];
            canvas.removeEdge(upstreamID, key);
          }
        }
      };
      //check if dwn's upstream has entry
      if(downstreamNode.upstreams.hasOwnProperty(entryID)){
        delete downstreamNode.upstreams[entryID];
        downstreamNode.upstreams[upstreamID] = true;
      } else {
      //traverse the tree
        for(var nodeID in downstreamNode.upstreams){
          traverseUp(upstreamID, nodeID);
        }
        if(!resultUp){
          for(var nodeID in downstreamNode.downstreams){
            traverseDown(downstreamID, nodeID);
          }
        };
        if(!resultUp && !resultDown){
          canvas.setEdge(upstreamID, downstreamID, {lineInterpolate: 'basis'});
          deleteDownStreams(upstreamID, downstreamID,canvas);
          renderGraph(g);
        } else if (resultUp && !resultDown) {
          canvas.setEdge(upstreamID, downstreamID, {lineInterpolate: 'basis'});
          canvas.removeEdge(foundNode, downstreamID);
          canvas.node(downstreamID).upstreams[upstreamID];
          canvas.node(upstreamID).downstreams[downstreamID];
          delete canvas.node(downstreamID).upstreams[foundNode];
          delete canvas.node(foundNode).downstreams[downstreamID];
          deleteDownStreams(upstreamID, downstreamID,canvas);
          renderGraph(g);
        }
      }
    };
    $scope.createCanvas();
  };

// ---------------------------------------------------------
// Module Entry Point
// ---------------------------------------------------------
  angular.module('cd-app.graph', [
  	'ngAnimate',
  	'ui.router'
  ])
  .config(GraphConfig)
  .controller('graphCtrl', GraphCtrl);
})(angular);

<commit_msg>(feat) Add listener for zooming on graph<commit_after>/*
* @Author: ChalrieHwang
* @Date:   2015-06-01 17:45:29
* @Last Modified by:   ChalrieHwang
* @Last Modified time: 2015-06-02 15:43:40
*/

'use strict';
(function(angular){

  var GraphConfig = function($stateProvider){
    $stateProvider.state('graph',{
      url: '/graph',
      templateUrl: 'graph/graph.tpl.html',
      controller: GraphCtrl
    });
  };

  var GraphCtrl = function($scope){

    /**
     * Define function for creating the graph canvas object
     * @return {d3} d3 graph object
     */
    $scope.createCanvas = function(){
      var g = new dagreD3.graphlib.Graph()
        .setGraph({})
        .setDefaultEdgeLabel(function() {
          return {};
        });
      return g;
    };

    /**
     * Define function for rendering nodes on the graph
     * @param  {d3} canvas d3 graph object
     * @return {[type]}        [description]
     */
    $scope.renderGraph = function(canvas){
      var render = new dagreD3.render();
      var svg = d3.select('svg');
      render(d3.select('svg g'), canvas);
      var initialScale = 1.5;
      var width = canvas.graph().width * initialScale;
      $scope.onZoom()
        .translate([(svg.attr('width') - width) / 40 + 70, 20])
        .scale(initialScale)
        .event(svg);
      svg.attr('height', canvas.graph().height * initialScale + 40);
    };

    /**
     * Define event listeners to handle zooming
     * @return {d3} [description]
     */
    $scope.onZoom = function(){
      var svg = d3.select('svg');
      var inner = svg.select('g');
      var zoom = d3.behavior.zoom().on('zoom', function() {
            inner.attr('transform', 'translate(' + d3.event.translate + ')'+'scale(' + d3.event.scale + ')');
          });
      svg.call(zoom);
      return zoom;
    };

    /**
     * Define function to create node in graph object
     * @param  {d3} canvas  d3 graph object to collect nodes
     * @param  {json} jsonObj node data from server
     * @return {[type]}         [description]
     */
    $scope.createNode = function(jsonObj){
      var id = jsonObj.nodeID;
      var label = jsonObj.abbrev;
      var nodeType = jsonObj.nodeType;
      $scope.g.setNode(id, {
        label: label,
        class: nodeType,
        shape: 'circle'
      });
      $scope.g.node(id).name = jsonObj.name;
      $scope.g.node(id).description = jsonObj.description;
      $scope.g.node(id).asignee = jsonObj.asignee;
      $scope.g.node(id).user = jsonObj.user;
      $scope.g.node(id).parentCluster = jsonObj.parentCluster;
      $scope.g.node(id).upstreams = jsonObj.upstreams;
      $scope.g.node(id).downstreams = jsonObj.downstreams;
      $scope.g.node(id).status = jsonObj.status;
      $scope.g.node(id).issueType = jsonObj.labels;
    };

    /**
     * Define function to setup all edges of the node
     * @param  {d3} canvas d3 graph object
     * @param  {number} id     The id of node
     * @return {[type]}        [description]
     */
    $scope.createEdge = function(id){
      $scope.g.node(id).downstreams.forEach(function(downstreamID){
        $scope.g.setEdge(id, downstreamID, {lineInterpolate: 'basis'});
      });
    };

    //Testing Data
    $scope.data = [
      {
        nodeID : 0,
        abbrev : "Entry",
        nodeType : "Entry",
        name : "Cunstruct Database",
        description : "Build database with monggose",
        asignee: ["Tony","Tom"],
        user : "Tony",
        parentCluster : null,
        upstreams : [],
        downstreams : [5,6,8],
        status : "open",
        labels : "bug"
      },
      {
        nodeID : 1,
        abbrev : "Exit",
        nodeType : "Exit",
        name : "Cunstruct Database",
        description : "Build database with monggose",
        asignee: ["Tony","Tom"],
        user : "Tony",
        parentCluster : null,
        upstreams : [3,4],
        downstreams : [],
        status : "open",
        labels : "bug"
      },
      {
        nodeID : 2,
        abbrev : "2",
        nodeType : "Issue",
        name : "Cunstruct Database",
        description : "Build database with monggose",
        asignee: ["Tony","Tom"],
        user : "Tony",
        parentCluster : null,
        upstreams : [6,8],
        downstreams : [3],
        status : "open",
        labels : "bug"
      },
      {
        nodeID : 3,
        abbrev : "3",
        nodeType : "Issue",
        name : "Build Server API",
        description : "Build server with Express",
        asignee: ["Tom"],
        user : "Tony",
        parentCluster : null,
        upstreams : [2,7],
        downstreams : [1],
        status : "open",
        labels : "bug"
      },
      {
        nodeID : 4,
        abbrev : "4",
        nodeType : "Issue",
        name : "Build Client API",
        description : "Build client app with Angular",
        asignee: ["Brad"],
        user : "Tony",
        parentCluster : null,
        upstreams : [5,8],
        downstreams : [1],
        status : "open",
        labels : "bug"
      },
      {
        nodeID : 5,
        abbrev : "5",
        nodeType : "Issue",
        name : "Build Client API",
        description : "Build client app with Angular",
        asignee: ["Brad"],
        user : "Tony",
        parentCluster : null,
        upstreams : [0],
        downstreams : [4],
        status : "open",
        labels : "bug"
      },
      {
        nodeID : 6,
        abbrev : "6",
        nodeType : "Issue",
        name : "Build Client API",
        description : "Build client app with Angular",
        asignee: ["Brad"],
        user : "Tony",
        parentCluster : null,
        upstreams : [0],
        downstreams : [2,7],
        status : "open",
        labels : "bug"
      },
      {
        nodeID : 7,
        abbrev : "7",
        nodeType : "Issue",
        name : "Build Client API",
        description : "Build client app with Angular",
        asignee: ["Brad"],
        user : "Tony",
        parentCluster : null,
        upstreams : [6],
        downstreams : [3],
        status : "open",
        labels : "bug"
      },
      {
        nodeID : 8,
        abbrev : "8",
        nodeType : "Issue",
        name : "Build Client API",
        description : "Build client app with Angular",
        asignee: ["Brad"],
        user : "Tony",
        parentCluster : null,
        upstreams : [0],
        downstreams : [2,4],
        status : "open",
        labels : "bug"
      }
    ];

    $scope.g = $scope.createCanvas();
    $scope.data.forEach(function(ele){
      $scope.createNode(ele);
    });
    $scope.data.forEach(function(ele){
      $scope.createEdge(ele.nodeID);
    });
    $scope.renderGraph($scope.g);
  };

// ---------------------------------------------------------
// Module Entry Point
// ---------------------------------------------------------
  angular.module('cd-app.graph', [
  	'ngAnimate',
  	'ui.router'
  ])
  .config(GraphConfig)
  .controller('graphCtrl', GraphCtrl);
})(angular);
<|endoftext|>


<commit_before>'use strict';

angular.
  module('admin').
  component('admin', {
    templateUrl: 'admin/admin.template.html',
    controller: /*['$http',*/
      function AdminController(/*$http*/) {
        var self = this;

        self.defaultList = [
          'Milk',
          'Bread',
          'Water',
          'Ketchup',
          'Almonds'
        ];

        /* methods */
        //add a new item to the shopping list
        self.addItem = function(item){
          /* TODO: add to the shopping list */
          //remove from the current list
          var i = self.defaultList.indexOf(item);
          if (i !=-1 ) {
            self.defaultList.splice(i, 1);
          }
        };
      }
    //]
  });
<commit_msg>Starred items are added to the list when clicked<commit_after>'use strict';

angular.
  module('admin').
  component('admin', {
    templateUrl: 'admin/admin.template.html',
    controller: ['$http',
      function AdminController($http) {
        var self = this;

        self.defaultList = [
          'Milk',
          'Bread',
          'Water',
          'Ketchup',
          'Almonds'
        ];

        /* methods */
        //add a new item to the shopping list
        self.addItem = function(item){
          $http.post('/api/shoplist', {'text':item})
                .success(function(data) {
                    //self.list = data;
                    console.log(data);
                })
                .error(function(data) {
                    console.log('Error:' + data);
                });
          //remove from the current default list
          var i = self.defaultList.indexOf(item);
          if (i !=-1 ) {
            self.defaultList.splice(i, 1);
          }
        };
      }
    ]
  });
<|endoftext|>


<commit_before>var React = require('react');
var MenuItems = require('./menu-items');<commit_msg>use strict;<commit_after>'use strict';

var React = require('react');
var MenuItems = require('./menu-items');<|endoftext|>


<commit_before>var VERBOSE = "VERBOSE" in process.env;
var TESTS = "TESTS" in process.env ? process.env["TESTS"].split(/,/) : null;

var ShExParser = require('../lib/ShExParser').Parser;
var ShExUtil = require('../lib/ShExUtil');
var ShExWriter = require('../lib/ShExWriter');

var fs = require('fs');
var expect = require('chai').expect;

var schemasPath = __dirname + '/../schemas/';
var partitionedSchemasPath = __dirname + '/../test/partitionedSchemas/';
var manifestFile = __dirname + '/../test/partitionedSchemas/Manifest.json';

describe('Partitioning', function () {
  var parser = new ShExParser();

  // Ensure the same blank node identifiers are used in every test
  beforeEach(function () { parser._resetBlanks(); });
  var manifest = parseJSON(fs.readFileSync(manifestFile, 'utf8'));
  if (TESTS)
    schemas.tests = schemas.tests.filter(function (t) {
      return TESTS.indexOf(s.from) !== -1 || TESTS.indexOf(s.expect) !== -1;
    });

  manifest.tests.forEach(function (test) {

    var schemaFile = schemasPath + test.from + ".shex";
    var expectedFile = partitionedSchemasPath + test.expect + ".shex";
    var schema = parser.parse(fs.readFileSync(schemaFile, 'utf8')); parser._resetBlanks();
    var partition = ShExUtil.partition(schema, test.include);
    var expected = parser.parse(fs.readFileSync(expectedFile, 'utf8')); parser._resetBlanks();

    it((VERBOSE ? schemaFile : test.from) +
       ' for ' + test.include.join(', ') + ' should match ' +
       (VERBOSE ? expectedFile : test.expect), function () {
      if (VERBOSE) console.log("schema: ", JSON.stringify(schema));
      if (VERBOSE) console.log("include: ", JSON.stringify(test.include));
      if (VERBOSE) console.log("partition: ", JSON.stringify(partition));
      if (VERBOSE) console.log("expect: ", JSON.stringify(expected));
      expect(partition).to.deep.equal(expected);
    });
  });
});

// Parses a JSON object, restoring `undefined` values
function parseJSON(string) {
  var object = JSON.parse(string);
  return /"\{undefined\}"/.test(string) ? restoreUndefined(object) : object;
}

<commit_msg>~ fix TESTS filter<commit_after>var VERBOSE = "VERBOSE" in process.env;
var TESTS = "TESTS" in process.env ? process.env["TESTS"].split(/,/) : null;

var ShExParser = require('../lib/ShExParser').Parser;
var ShExUtil = require('../lib/ShExUtil');
var ShExWriter = require('../lib/ShExWriter');

var fs = require('fs');
var expect = require('chai').expect;

var schemasPath = __dirname + '/../schemas/';
var partitionedSchemasPath = __dirname + '/../test/partitionedSchemas/';
var manifestFile = __dirname + '/../test/partitionedSchemas/Manifest.json';

describe('Partitioning', function () {
  var parser = new ShExParser();

  // Ensure the same blank node identifiers are used in every test
  beforeEach(function () { parser._resetBlanks(); });
  var manifest = parseJSON(fs.readFileSync(manifestFile, 'utf8'));
  if (TESTS)
    manifest.tests = manifest.tests.filter(function (t) {
      return TESTS.indexOf(t.from) !== -1 || TESTS.indexOf(t.expect) !== -1;
    });

  manifest.tests.forEach(function (test) {

    var schemaFile = schemasPath + test.from + ".shex";
    var expectedFile = partitionedSchemasPath + test.expect + ".shex";
    var schema = parser.parse(fs.readFileSync(schemaFile, 'utf8')); parser._resetBlanks();
    var partition = ShExUtil.partition(schema, test.include);
    var expected = parser.parse(fs.readFileSync(expectedFile, 'utf8')); parser._resetBlanks();

    it((VERBOSE ? schemaFile : test.from) +
       ' for ' + test.include.join(', ') + ' should match ' +
       (VERBOSE ? expectedFile : test.expect), function () {
      if (VERBOSE) console.log("schema: ", JSON.stringify(schema));
      if (VERBOSE) console.log("include: ", JSON.stringify(test.include));
      if (VERBOSE) console.log("partition: ", JSON.stringify(partition));
      if (VERBOSE) console.log("expect: ", JSON.stringify(expected));
      expect(partition).to.deep.equal(expected);
    });
  });
});

// Parses a JSON object, restoring `undefined` values
function parseJSON(string) {
  var object = JSON.parse(string);
  return /"\{undefined\}"/.test(string) ? restoreUndefined(object) : object;
}

<|endoftext|>


<commit_before>'use strict';

module.exports = function (grunt) {
  grunt.registerMultiTask('consolidate', function () {
    var options = this.options();

    var path = require('path');
    var _ = require('lodash');

    var basePath = path.join(options.srcFolder, options.academicYear.replace('/', '-'), options.semester);
    var bulletinModulesPath = path.join(basePath, grunt.config('bulletinModules').options.destFileName);
    var corsPath = path.join(basePath, grunt.config('cors').options.destFileName);
    var corsBiddingStatsOptions = grunt.config('corsBiddingStats').options;
    var corsBiddingStatsPath = path.join(corsBiddingStatsOptions.destFolder, corsBiddingStatsOptions.destFileName);
    var examTimetablePath = path.join(basePath, grunt.config('examTimetable').options.destFileName);
    var ivlePath = path.join(basePath, grunt.config('ivle').options.destFileName);
    var moduleTimetableDeltaPath = path.join(basePath, grunt.config('moduleTimetableDelta').options.destFileName);

    var modules = {};

    if (grunt.file.exists(bulletinModulesPath)) {
      var bulletinModules = grunt.file.readJSON(bulletinModulesPath);
      bulletinModules.forEach(function (mod) {
        modules[mod.ModuleCode] = modules[mod.ModuleCode] || {};
        modules[mod.ModuleCode].Bulletin = mod;
      });
    }

    if (grunt.file.exists(corsPath)) {
      var cors = grunt.file.readJSON(corsPath);

      var corsMods = {};
      cors.forEach(function (mod) {
        var codes = mod.ModuleCode.split(' / ');
        codes.forEach(function (code) {
          corsMods[code] = corsMods[code] || _.omit(mod, 'Type');
          corsMods[code].Types = corsMods[code].Types || {};
          if (/^GE[KM]\d/.test(code)) {
            corsMods[code].Types.GEM = true;
          } else if (/^SS[A-Z]\d/.test(code)) {
            corsMods[code].Types.SSM = true;
          } else if (mod.Type !== 'GEM' && mod.Type !== 'SSM') {
            corsMods[code].Types[mod.Type] = true;
          }
        });
      });
      _.each(corsMods, function (mod, code) {
        mod.Types = Object.keys(mod.Types).sort();
        modules[code] = modules[code] || {};
        modules[code].CORS = mod;
      });
    }

    if (grunt.file.exists(corsBiddingStatsPath)) {
      var corsBiddingStats = grunt.file.readJSON(corsBiddingStatsPath);
      corsBiddingStats.forEach(function (stat) {
        modules[stat.ModuleCode] = modules[stat.ModuleCode] || {};
        modules[stat.ModuleCode].CorsBiddingStats = modules[stat.ModuleCode].CorsBiddingStats || [];
        modules[stat.ModuleCode].CorsBiddingStats.push(stat);
      });
    }

    if (grunt.file.exists(examTimetablePath)) {
      var examTimetable = grunt.file.readJSON(examTimetablePath);
      examTimetable.forEach(function (exam) {
        modules[exam.Code] = modules[exam.Code] || {};
        modules[exam.Code].Exam = exam;
      });
    }

    if (grunt.file.exists(ivlePath)) {
      var ivle = grunt.file.readJSON(ivlePath);
      ivle.forEach(function (results) {
        var code = results[0].CourseCode;
        modules[code] = modules[code] || {};
        modules[code].IVLE = results;
      });
    }

    if (grunt.file.exists(moduleTimetableDeltaPath)) {
      var moduleTimetableDelta = grunt.file.readJSON(moduleTimetableDeltaPath);
      moduleTimetableDelta.forEach(function (delta) {
        modules[delta.ModuleCode] = modules[delta.ModuleCode] || {};
        modules[delta.ModuleCode].TimetableDelta = modules[delta.ModuleCode].TimetableDelta || [];
        modules[delta.ModuleCode].TimetableDelta.push(delta);
      });
    }

    _.each(modules, function (mod, code) {
      mod.ModuleCode = code;
    });
    modules = _.sortBy(_.values(modules), 'ModuleCode');
    grunt.file.write(
      path.join(basePath, options.destFileName),
      JSON.stringify(modules, null, options.jsonSpace)
    );
  });
};
<commit_msg>Do not consolidate cors bidding stats for modules not offered in semester<commit_after>'use strict';

module.exports = function (grunt) {
  grunt.registerMultiTask('consolidate', function () {
    var options = this.options();

    var path = require('path');
    var _ = require('lodash');

    var basePath = path.join(options.srcFolder, options.academicYear.replace('/', '-'), options.semester);
    var bulletinModulesPath = path.join(basePath, grunt.config('bulletinModules').options.destFileName);
    var corsPath = path.join(basePath, grunt.config('cors').options.destFileName);
    var corsBiddingStatsOptions = grunt.config('corsBiddingStats').options;
    var corsBiddingStatsPath = path.join(corsBiddingStatsOptions.destFolder, corsBiddingStatsOptions.destFileName);
    var examTimetablePath = path.join(basePath, grunt.config('examTimetable').options.destFileName);
    var ivlePath = path.join(basePath, grunt.config('ivle').options.destFileName);
    var moduleTimetableDeltaPath = path.join(basePath, grunt.config('moduleTimetableDelta').options.destFileName);

    var modules = {};

    if (grunt.file.exists(bulletinModulesPath)) {
      var bulletinModules = grunt.file.readJSON(bulletinModulesPath);
      bulletinModules.forEach(function (mod) {
        modules[mod.ModuleCode] = modules[mod.ModuleCode] || {};
        modules[mod.ModuleCode].Bulletin = mod;
      });
    }

    if (grunt.file.exists(corsPath)) {
      var cors = grunt.file.readJSON(corsPath);

      var corsMods = {};
      cors.forEach(function (mod) {
        var codes = mod.ModuleCode.split(' / ');
        codes.forEach(function (code) {
          corsMods[code] = corsMods[code] || _.omit(mod, 'Type');
          corsMods[code].Types = corsMods[code].Types || {};
          if (/^GE[KM]\d/.test(code)) {
            corsMods[code].Types.GEM = true;
          } else if (/^SS[A-Z]\d/.test(code)) {
            corsMods[code].Types.SSM = true;
          } else if (mod.Type !== 'GEM' && mod.Type !== 'SSM') {
            corsMods[code].Types[mod.Type] = true;
          }
        });
      });
      _.each(corsMods, function (mod, code) {
        mod.Types = Object.keys(mod.Types).sort();
        modules[code] = modules[code] || {};
        modules[code].CORS = mod;
      });
    }

    if (grunt.file.exists(examTimetablePath)) {
      var examTimetable = grunt.file.readJSON(examTimetablePath);
      examTimetable.forEach(function (exam) {
        modules[exam.Code] = modules[exam.Code] || {};
        modules[exam.Code].Exam = exam;
      });
    }

    if (grunt.file.exists(ivlePath)) {
      var ivle = grunt.file.readJSON(ivlePath);
      ivle.forEach(function (results) {
        var code = results[0].CourseCode;
        modules[code] = modules[code] || {};
        modules[code].IVLE = results;
      });
    }

    if (grunt.file.exists(moduleTimetableDeltaPath)) {
      var moduleTimetableDelta = grunt.file.readJSON(moduleTimetableDeltaPath);
      moduleTimetableDelta.forEach(function (delta) {
        modules[delta.ModuleCode] = modules[delta.ModuleCode] || {};
        modules[delta.ModuleCode].TimetableDelta = modules[delta.ModuleCode].TimetableDelta || [];
        modules[delta.ModuleCode].TimetableDelta.push(delta);
      });
    }

    if (grunt.file.exists(corsBiddingStatsPath)) {
      var corsBiddingStats = grunt.file.readJSON(corsBiddingStatsPath);
      corsBiddingStats.forEach(function (stat) {
        if (modules[stat.ModuleCode]) {
          modules[stat.ModuleCode].CorsBiddingStats = modules[stat.ModuleCode].CorsBiddingStats || [];
          modules[stat.ModuleCode].CorsBiddingStats.push(stat);
        }
      });
    }

    _.each(modules, function (mod, code) {
      mod.ModuleCode = code;
    });
    modules = _.sortBy(_.values(modules), 'ModuleCode');
    grunt.file.write(
      path.join(basePath, options.destFileName),
      JSON.stringify(modules, null, options.jsonSpace)
    );
  });
};
<|endoftext|>


<commit_before>$(function () {

    var modal = $('.modal');
    var remote = $('.modal.remote');

    // Clear remote modals when closed.
    remote.on('hidden.bs.modal', function () {

        $(this).removeData('bs.modal');

        $(this).find('.modal-content').html('

');
    });

    // Show loader for remote modals.
    remote.on('show.bs.modal', function () {
        $(this).find('.modal-content').html('

');
    });

    // Handle ajax links in modals.
    modal.on('click', 'a.ajax, .pagination a', function (e) {

        e.preventDefault();

        var wrapper = $(this).closest('.modal-content');

        wrapper.append('

');

        $.get($(this).attr('href'), function (html) {
            wrapper.html(html);
        });
    });

    // Handle ajax forms in modals.
    modal.on('submit', 'form.ajax', function (e) {

        e.preventDefault();

        var wrapper = $(this).closest('.modal-content');

        wrapper.append('

');

        if ($(this).attr('method') == 'GET') {
            $.get($(this).attr('action'), $(this).serializeArray(), function (html) {
                wrapper.html(html);
            });
        } else {
            $.post($(this).attr('action'), $(this).serializeArray(), function (html) {
                wrapper.html(html);
            });
        }
    });
});
<commit_msg>Fix modal<commit_after>var initModal = function () {

    var modal = $('.modal');
    var remote = $('.modal.remote');

    // Clear remote modals when closed.
    remote.on('hidden.bs.modal', function () {

        $(this).removeData('bs.modal');

        $(this).find('.modal-content').html('

');
    });

    // Show loader for remote modals.
    remote.on('show.bs.modal', function () {
        $(this).find('.modal-content').html('

');
    });

    // Handle ajax links in modals.
    modal.on('click', 'a.ajax, .pagination a', function (e) {

        e.preventDefault();

        var wrapper = $(this).closest('.modal-content');

        wrapper.append('

');

        $.get($(this).attr('href'), function (html) {
            wrapper.html(html);
        });
    });

    // Handle ajax forms in modals.
    modal.on('submit', 'form.ajax', function (e) {

        e.preventDefault();

        var wrapper = $(this).closest('.modal-content');

        wrapper.append('

');

        if ($(this).attr('method') == 'GET') {
            $.get($(this).attr('action'), $(this).serializeArray(), function (html) {
                wrapper.html(html);
            });
        } else {
            $.post($(this).attr('action'), $(this).serializeArray(), function (html) {
                wrapper.html(html);
            });
        }
    });
};

$(document).ready(function () {
    initModal();
});

$(document).ajaxComplete(function () {
    initModal();
});
<|endoftext|>


<commit_before>'use strict';

var sportsArray = [['Basketball', 'Football', 'Soccer'],
                   ['College', 'Semi-Pro', 'Pro'],       // used for all 3 main categories
                   ['Beavers', 'Vikings', 'Ducks'],      // used for all college sports
                   ['Energy', 'Rainmakers', 'Chinooks'], // semi-pro basketball
                   ['Blazers', 'Fire', 'Storm'],         // pro basketball
                   ['Raiders', 'Stallions', 'Boltz'],    // semi-pro football
                   ['Seahawks', 'Steel', 'Shockwave'],   // pro football
                   ['Victory', 'Stars'],                 // semi-pro soccer
                   ['Timbers', 'Thorns', 'Sounders']];   // pro soccer

// used for local storage
var storedArray = [];

var main = document.getElementById('main');
var oneOne = document.getElementById('1_1');
var oneTwo = document.getElementById('1_2');
var oneThree = document.getElementById('1_3');

// names refer to the tier and item in that tier
oneOne.addEventListener('click', oneOneClickHandler);
oneTwo.addEventListener('click', oneTwoClickHandler);
oneThree.addEventListener('click', oneThreeClickHandler);

// used to short circuit click handlers once clicked
var tierOneClicked = false;
// var tierTwoClicked = false;
// var tierThreeClicked = false;

// Baskbetball
// click handler
function oneOneClickHandler() {
  if (tierOneClicked === true) {
    return;
  } else {
  // creates containing div
    var tierTwo = document.createElement('div');
    tierTwo.id = 'tier_2-1';
    main.appendChild(tierTwo);

  // creates individual divs/categories
    for (var i = 0; i < sportsArray[1].length; i++) {
      var subCategory = document.createElement('div');
      subCategory.textContent = sportsArray[1][i];
      tierTwo.classList.add('tier_2');
      tierTwo.appendChild(subCategory);

      // adds on click functions to the subcategories
      // Basketball --> College --- Index [2]
      if (i === 0) {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-1';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[2].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[2][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][2]);
              };
            }
          }
        };

      // Basketball --> Semi-Pro --- Index [3]
      } else if (i === 1) {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-2';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[3].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[3][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[3][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[3][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[3][2]);
              };
            }
          }
        };

      // Basketball --> Pro --- Index [4]
      } else {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-3';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[4].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[4][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[4][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[4][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[4][2]);
              };
            }
          }
        };
      }
    }
    tierOneClicked = true;
  }
}

// Football
// click handler
function oneTwoClickHandler() {
  if (tierOneClicked === true) {
    return;
  } else {
  // creates containing div
    var tierTwo = document.createElement('div');
    tierTwo.id = 'tier_2-2';
    main.appendChild(tierTwo);

  // creates individual divs
    for (var i = 0; i < 3; i++) {
      var subCategory = document.createElement('div');
      subCategory.textContent = sportsArray[1][i];
      tierTwo.classList.add('tier_2');
      tierTwo.appendChild(subCategory);

      // Football --> College --- Index [2]
      if (i === 0) {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-2';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[2].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[2][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][2]);
              };
            }
          }
        };

      // Football --> Semi-pro --- Index [5]
      } else if (i === 1) {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-3';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[5].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[5][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[5][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[5][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[5][2]);
              };
            }
          }
        };

      // Football --> Pro --- Index [6]
      } else {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-4';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[6].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[6][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[6][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[6][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[6][2]);
              };
            }
          }
        };
      }
    }
    tierOneClicked = true;
  }
}

// Soccer
// click handler
function oneThreeClickHandler() {
  if (tierOneClicked === true) {
    return;
  } else {
  // creates containing div
    var tierTwo = document.createElement('div');
    tierTwo.id = 'tier_2-3';
    main.appendChild(tierTwo);

  // creates individual divs
    for (var i = 0; i < 3; i++) {
      var subCategory = document.createElement('div');
      subCategory.textContent = sportsArray[1][i];
      tierTwo.classList.add('tier_2');
      tierTwo.appendChild(subCategory);

      // Soccer --> College --- Index [2]
      if (i === 0) {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-3';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[2].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[2][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][2]);
              };
            }
          }
        };

      // Soccer --> Semi-pro --- Index [7]
      } else if (i === 1) {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-4';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[7].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[7][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[7][0]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[7][1]);
              };
            }
          }
        };

      // Soccer --> Pro --- Index [8]
      } else {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-5';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[8].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[8][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[8][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[8][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[8][2]);
              };
            }
          }
        };
      }
    }
    tierOneClicked = true;
  }
}

var results = document.getElementById('results');
results.addEventListener('click', resultsHandler);
function resultsHandler() {
  var storeArray = JSON.stringify(storedArray);
  localStorage.setItem('storedArray', storeArray);
};

var newTree = document.getElementById('refresh');
newTree.addEventListener('click', newTreeHandler);

function newTreeHandler() {
  var storeArray = JSON.stringify(storedArray);
  localStorage.setItem('storedArray', storeArray);
  location.reload();
  JSON.parse(localStorage.getItem('storedArray'));
};
<commit_msg>refresh button functioning properly<commit_after>'use strict';

var sportsArray = [['Basketball', 'Football', 'Soccer'],
                   ['College', 'Semi-Pro', 'Pro'],       // used for all 3 main categories
                   ['Beavers', 'Vikings', 'Ducks'],      // used for all college sports
                   ['Energy', 'Rainmakers', 'Chinooks'], // semi-pro basketball
                   ['Blazers', 'Fire', 'Storm'],         // pro basketball
                   ['Raiders', 'Stallions', 'Boltz'],    // semi-pro football
                   ['Seahawks', 'Steel', 'Shockwave'],   // pro football
                   ['Victory', 'Stars'],                 // semi-pro soccer
                   ['Timbers', 'Thorns', 'Sounders']];   // pro soccer

// sets the stored array to what is in local storage
var storedArray = JSON.parse(localStorage.getItem('storedArray'));;

// checks if something is in local storage
// if null, sets storedArray equal to an empty array
if (!storedArray) {
  storedArray = [];
}

var main = document.getElementById('main');
var oneOne = document.getElementById('1_1');
var oneTwo = document.getElementById('1_2');
var oneThree = document.getElementById('1_3');

// names refer to the tier and item in that tier
oneOne.addEventListener('click', oneOneClickHandler);
oneTwo.addEventListener('click', oneTwoClickHandler);
oneThree.addEventListener('click', oneThreeClickHandler);

// used to short circuit click handlers once clicked
var tierOneClicked = false;
// var tierTwoClicked = false;
// var tierThreeClicked = false;

// Baskbetball
// click handler
function oneOneClickHandler() {
  if (tierOneClicked === true) {
    return;
  } else {
  // creates containing div
    var tierTwo = document.createElement('div');
    tierTwo.id = 'tier_2-1';
    main.appendChild(tierTwo);

  // creates individual divs/categories
    for (var i = 0; i < sportsArray[1].length; i++) {
      var subCategory = document.createElement('div');
      subCategory.textContent = sportsArray[1][i];
      tierTwo.classList.add('tier_2');
      tierTwo.appendChild(subCategory);

      // adds on click functions to the subcategories
      // Basketball --> College --- Index [2]
      if (i === 0) {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-1';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[2].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[2][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][2]);
              };
            }
          }
        };

      // Basketball --> Semi-Pro --- Index [3]
      } else if (i === 1) {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-2';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[3].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[3][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[3][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[3][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[3][2]);
              };
            }
          }
        };

      // Basketball --> Pro --- Index [4]
      } else {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-3';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[4].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[4][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[4][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[4][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[4][2]);
              };
            }
          }
        };
      }
    }
    tierOneClicked = true;
  }
}

// Football
// click handler
function oneTwoClickHandler() {
  if (tierOneClicked === true) {
    return;
  } else {
  // creates containing div
    var tierTwo = document.createElement('div');
    tierTwo.id = 'tier_2-2';
    main.appendChild(tierTwo);

  // creates individual divs
    for (var i = 0; i < 3; i++) {
      var subCategory = document.createElement('div');
      subCategory.textContent = sportsArray[1][i];
      tierTwo.classList.add('tier_2');
      tierTwo.appendChild(subCategory);

      // Football --> College --- Index [2]
      if (i === 0) {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-2';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[2].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[2][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][2]);
              };
            }
          }
        };

      // Football --> Semi-pro --- Index [5]
      } else if (i === 1) {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-3';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[5].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[5][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[5][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[5][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[5][2]);
              };
            }
          }
        };

      // Football --> Pro --- Index [6]
      } else {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-4';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[6].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[6][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[6][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[6][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[6][2]);
              };
            }
          }
        };
      }
    }
    tierOneClicked = true;
  }
}

// Soccer
// click handler
function oneThreeClickHandler() {
  if (tierOneClicked === true) {
    return;
  } else {
  // creates containing div
    var tierTwo = document.createElement('div');
    tierTwo.id = 'tier_2-3';
    main.appendChild(tierTwo);

  // creates individual divs
    for (var i = 0; i < 3; i++) {
      var subCategory = document.createElement('div');
      subCategory.textContent = sportsArray[1][i];
      tierTwo.classList.add('tier_2');
      tierTwo.appendChild(subCategory);

      // Soccer --> College --- Index [2]
      if (i === 0) {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-3';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[2].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[2][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[2][2]);
              };
            }
          }
        };

      // Soccer --> Semi-pro --- Index [7]
      } else if (i === 1) {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-4';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[7].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[7][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[7][0]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[7][1]);
              };
            }
          }
        };

      // Soccer --> Pro --- Index [8]
      } else {
        subCategory.onclick = function() {
          var tierThree = document.createElement('div');
          tierThree.id = 'tier_3-5';
          main.appendChild(tierThree);

          for (var j = 0; j < sportsArray[8].length; j++) {
            var subCategory = document.createElement('div');
            subCategory.textContent = sportsArray[8][j];
            tierThree.classList.add('tier_3');
            tierThree.appendChild(subCategory);

            if (j === 0) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[8][0]);
              };
            } else if (j === 1) {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[8][1]);
              };
            } else {
              subCategory.onclick = function() {
                storedArray.push(sportsArray[8][2]);
              };
            }
          }
        };
      }
    }
    tierOneClicked = true;
  }
}

var results = document.getElementById('results');
results.addEventListener('click', resultsHandler);
function resultsHandler() {

  var storeArray = JSON.stringify(storedArray);
  localStorage.setItem('storedArray', storeArray);
  // location.reload();

}

var newTree = document.getElementById('refresh');
newTree.addEventListener('click', newTreeHandler);

function newTreeHandler() {
  var storeArray = JSON.stringify(storedArray);
  localStorage.setItem('storedArray', storeArray);
  location.reload();
};
<|endoftext|>