<commit_before>/*
 * Copyright (c) 2012 Glenn Ruehle
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true,  regexp: true, indent: 4, maxerr: 50 */
/*global define, brackets, $, window, marked, _hideSettings */

define(function (require, exports, module) {
    "use strict";

    // Brackets modules
    var AppInit             = brackets.getModule("utils/AppInit"),
        NativeApp           = brackets.getModule("utils/NativeApp"),
        DocumentManager     = brackets.getModule("document/DocumentManager"),
        EditorManager       = brackets.getModule("editor/EditorManager"),
        ExtensionUtils      = brackets.getModule("utils/ExtensionUtils"),
        FileUtils           = brackets.getModule("file/FileUtils"),
        PanelManager        = brackets.getModule("view/PanelManager"),
        PopUpManager        = brackets.getModule("widgets/PopUpManager"),
        PreferencesManager  = brackets.getModule("preferences/PreferencesManager"),
        Resizer             = brackets.getModule("utils/Resizer"),
        StringUtils         = brackets.getModule("utils/StringUtils"),
        _                   = brackets.getModule("thirdparty/lodash");

    // Templates
    var panelHTML       = require("text!templates/panel.html"),
        previewHTML     = require("text!templates/preview.html"),
        settingsHTML    = require("text!templates/settings.html");

    // Local modules
    var marked          = require("lib/marked");

    // jQuery objects
    var $icon,
        $iframe,
        $panel,
        $settingsToggle,
        $settings;

    // Other vars
    var currentDoc,
        currentEditor,
        panel,
        visible = false,
        realVisibility = false;

    // Prefs
    var _prefs = PreferencesManager.getExtensionPrefs("markdown-preview");
    _prefs.definePreference("useGFM", "boolean", false);
    _prefs.definePreference("theme", "string", "clean");
    _prefs.definePreference("syncScroll", "boolean", true);

    // Convert any old-style prefs
    PreferencesManager.convertPreferences(module, {
        "useGFM": "user markdown-preview.useGFM",
        "theme": "user markdown-preview.theme"
    });

    // (based on code in brackets.js)
    function _handleLinkClick(e) {
        // Check parents too, in case link has inline formatting tags
        var node = e.target, url;
        while (node) {
            if (node.tagName === "A") {
                url = node.getAttribute("href");
                if (url && !url.match(/^#/)) {
                    NativeApp.openURLInDefaultBrowser(url);
                }
                e.preventDefault();
                break;
            }
            node = node.parentElement;
        }

        // Close settings dropdown, if open
        _hideSettings();
    }

    function _calcScrollPos() {
        var scrollInfo = currentEditor._codeMirror.getScrollInfo();
        var scrollPercentage = scrollInfo.top / (scrollInfo.height - scrollInfo.clientHeight);
        var scrollTop = ($iframe[0].contentDocument.height - $iframe[0].height) * scrollPercentage;

        return Math.round(scrollTop);
    }

    function _editorScroll() {
        if (_prefs.get("syncScroll") && $iframe) {
            var scrollTop = _calcScrollPos();

            $iframe[0].contentDocument.body.scrollTop = scrollTop;
        }
    }

    function _loadDoc(doc, preserveScrollPos) {
        if (doc && visible && $iframe) {
            var docText     = doc.getText(),
                scrollPos   = 0,
                bodyText    = "",
                yamlRegEx   = /^-{3}([\w\W]+?)(-{3})/,
                yamlMatch   = yamlRegEx.exec(docText);

            // If there's yaml front matter, remove it.
            if (yamlMatch) {
                docText = docText.substr(yamlMatch[0].length);
            }

            if (preserveScrollPos) {
                scrollPos = $iframe.contents()[0].body.scrollTop;
            } else if (_prefs.get("syncScroll")) {
                scrollPos = _calcScrollPos();
            }

            // Parse markdown into HTML
            bodyText = marked(docText);

            // Show URL in link tooltip
            bodyText = bodyText.replace(/(href=\"([^\"]*)\")/g, "$1 title=\"$2\"");

            // Make <base> tag for relative URLS
            var baseUrl = window.location.protocol + "//" + FileUtils.getDirectoryPath(doc.file.fullPath);

            // Assemble the HTML source
            var htmlSource = _.template(previewHTML, {
                baseUrl    : baseUrl,
                themeUrl   : require.toUrl("./themes/" + _prefs.get("theme") + ".css"),
                scrollTop  : scrollPos,
                bodyText   : bodyText
            });
            $iframe.attr("srcdoc", htmlSource);

            $iframe.load(function () {
                // Open external browser when links are clicked
                // (similar to what brackets.js does - but attached to the iframe's document)
                $iframe[0].contentDocument.body.addEventListener("click", _handleLinkClick, true);

                // Sync scroll position (if needed)
                _editorScroll();

                // Make sure iframe is showing
                $iframe.show();
            });
        }
    }

    function _documentChange(e) {
        _loadDoc(e.target, true);
    }

    function _resizeIframe() {
        if (visible && $iframe) {
            var iframeWidth = panel.$panel.innerWidth();
            $iframe.attr("width", iframeWidth + "px");
        }
    }

    function _updateSettings() {
        // Format
        var useGFM = _prefs.get("useGFM");
        marked.setOptions({
            breaks: useGFM,
            gfm: useGFM
        });

        // Re-render
        _loadDoc(currentDoc, true);
    }

    function _documentClicked(e) {
        if (!$settings.is(e.target) &&
                !$settingsToggle.is(e.target) &&
                $settings.has(e.target).length === 0) {
            _hideSettings();
        }
    }

    function _hideSettings() {
        if ($settings) {
            $settings.remove();
            $settings = null;
            $(window.document).off("mousedown", _documentClicked);
        }
    }

    function _showSettings(e) {
        _hideSettings();

        $settings = $(settingsHTML)
            .css({
                right: 12,
                top: $settingsToggle.position().top + $settingsToggle.outerHeight() + 12
            })
            .appendTo($panel);

        $settings.find("#markdown-preview-format")
            .prop("selectedIndex", _prefs.get("useGFM") ? 1 : 0)
            .change(function (e) {
                _prefs.set("useGFM", e.target.selectedIndex === 1);
                _updateSettings();
            });

        $settings.find("#markdown-preview-theme")
            .val(_prefs.get("theme"))
            .change(function (e) {
                _prefs.set("theme", e.target.value);
                _updateSettings();
            });

        var $syncScroll = $settings.find("#markdown-preview-sync-scroll");

        $syncScroll.change(function (e) {
            _prefs.set("syncScroll", e.target.checked);
            _editorScroll();
        });

        if (_prefs.get("syncScroll")) {
            $syncScroll.attr("checked", true);
        }

        PopUpManager.addPopUp($settings, _hideSettings, true);
        $(window.document).on("mousedown", _documentClicked);
    }

    function _setPanelVisibility(isVisible) {
        if (isVisible === realVisibility) {
            return;
        }

        realVisibility = isVisible;
        if (isVisible) {
            if (!panel) {
                $panel = $(panelHTML);
                $iframe = $panel.find("#panel-markdown-preview-frame");

                panel = PanelManager.createBottomPanel("markdown-preview-panel", $panel);
                $panel.on("panelResizeUpdate", function (e, newSize) {
                    $iframe.attr("height", newSize);
                });
                $iframe.attr("height", $panel.height());

                window.setTimeout(_resizeIframe);

                $settingsToggle = $("#markdown-settings-toggle")
                    .click(function (e) {
                        if ($settings) {
                            _hideSettings();
                        } else {
                            _showSettings(e);
                        }
                    });

                $iframe.hide();
            }
            _loadDoc(DocumentManager.getCurrentDocument());
            $icon.toggleClass("active");
            panel.show();
        } else {
            $icon.toggleClass("active");
            panel.hide();
            $iframe.hide();
        }
    }

    function _currentDocChangedHandler() {
        var doc = DocumentManager.getCurrentDocument(),
            ext = doc ? FileUtils.getFileExtension(doc.file.fullPath).toLowerCase() : "";

        if (currentDoc) {
            $(currentDoc).off("change", _documentChange);
            currentDoc = null;
        }

        if (currentEditor) {
            $(currentEditor).off("scroll", _editorScroll);
            currentEditor = null;
        }

        if (doc && /md|markdown|litcoffee|txt/.test(ext)) {
            currentDoc = doc;
            $(currentDoc).on("change", _documentChange);
            currentEditor = EditorManager.getCurrentFullEditor();
            $(currentEditor).on("scroll", _editorScroll);
            $icon.css({display: "block"});
            _setPanelVisibility(visible);
            _loadDoc(doc);
        } else {
            $icon.css({display: "none"});
            _setPanelVisibility(false);
        }
    }

    function _toggleVisibility() {
        visible = !visible;
        _setPanelVisibility(visible);
    }

    // Debounce event callback to avoid excess overhead
    // Update preview 300 ms ofter document change
    // Sync scroll 1ms after document scroll (just enough to ensure
    // the document scroll isn't blocked).
    _documentChange = _.debounce(_documentChange, 300);
    _editorScroll = _.debounce(_editorScroll, 1);

    // Insert CSS for this extension
    ExtensionUtils.loadStyleSheet(module, "styles/MarkdownPreview.css");

    // Add toolbar icon
    $icon = $("<a>")
        .attr({
            id: "markdown-preview-icon",
            href: "#"
        })
        .css({
            display: "none"
        })
        .click(_toggleVisibility)
        .appendTo($("#main-toolbar .buttons"));

    // Add a document change handler
    $(DocumentManager).on("currentDocumentChange", _currentDocChangedHandler);

    // currentDocumentChange is *not* called for the initial document. Use
    // appReady() to set initial state.
    AppInit.appReady(function () {
        _currentDocChangedHandler();
    });

    // Listen for resize events
    $(PanelManager).on("editorAreaResize", _resizeIframe);
    $("#sidebar").on("panelCollapsed panelExpanded panelResizeUpdate", _resizeIframe);
});
<commit_msg>Fix Deprecation Warnings in upcoming 0.44 release<commit_after>/*
 * Copyright (c) 2012 Glenn Ruehle
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true,  regexp: true, indent: 4, maxerr: 50 */
/*global define, brackets, $, window, marked, _hideSettings */

define(function (require, exports, module) {
    "use strict";

    // Brackets modules
    var AppInit             = brackets.getModule("utils/AppInit"),
        NativeApp           = brackets.getModule("utils/NativeApp"),
        DocumentManager     = brackets.getModule("document/DocumentManager"),
        EditorManager       = brackets.getModule("editor/EditorManager"),
        ExtensionUtils      = brackets.getModule("utils/ExtensionUtils"),
        FileUtils           = brackets.getModule("file/FileUtils"),
        WorkspaceManager    = brackets.getModule("view/WorkspaceManager"),
        PopUpManager        = brackets.getModule("widgets/PopUpManager"),
        PreferencesManager  = brackets.getModule("preferences/PreferencesManager"),
        Resizer             = brackets.getModule("utils/Resizer"),
        StringUtils         = brackets.getModule("utils/StringUtils"),
        MainViewManager     = brackets.getModule("view/MainViewManager"),
        _                   = brackets.getModule("thirdparty/lodash");

    // Templates
    var panelHTML       = require("text!templates/panel.html"),
        previewHTML     = require("text!templates/preview.html"),
        settingsHTML    = require("text!templates/settings.html");

    // Local modules
    var marked          = require("lib/marked");

    // jQuery objects
    var $icon,
        $iframe,
        $panel,
        $settingsToggle,
        $settings;

    // Other vars
    var currentDoc,
        currentEditor,
        panel,
        visible = false,
        realVisibility = false;

    // Prefs
    var _prefs = PreferencesManager.getExtensionPrefs("markdown-preview");
    _prefs.definePreference("useGFM", "boolean", false);
    _prefs.definePreference("theme", "string", "clean");
    _prefs.definePreference("syncScroll", "boolean", true);

    // Convert any old-style prefs
    PreferencesManager.convertPreferences(module, {
        "useGFM": "user markdown-preview.useGFM",
        "theme": "user markdown-preview.theme"
    });

    // (based on code in brackets.js)
    function _handleLinkClick(e) {
        // Check parents too, in case link has inline formatting tags
        var node = e.target, url;
        while (node) {
            if (node.tagName === "A") {
                url = node.getAttribute("href");
                if (url && !url.match(/^#/)) {
                    NativeApp.openURLInDefaultBrowser(url);
                }
                e.preventDefault();
                break;
            }
            node = node.parentElement;
        }

        // Close settings dropdown, if open
        _hideSettings();
    }

    function _calcScrollPos() {
        var scrollInfo = currentEditor._codeMirror.getScrollInfo();
        var scrollPercentage = scrollInfo.top / (scrollInfo.height - scrollInfo.clientHeight);
        var scrollTop = ($iframe[0].contentDocument.height - $iframe[0].height) * scrollPercentage;

        return Math.round(scrollTop);
    }

    function _editorScroll() {
        if (_prefs.get("syncScroll") && $iframe) {
            var scrollTop = _calcScrollPos();

            $iframe[0].contentDocument.body.scrollTop = scrollTop;
        }
    }

    function _loadDoc(doc, preserveScrollPos) {
        if (doc && visible && $iframe) {
            var docText     = doc.getText(),
                scrollPos   = 0,
                bodyText    = "",
                yamlRegEx   = /^-{3}([\w\W]+?)(-{3})/,
                yamlMatch   = yamlRegEx.exec(docText);

            // If there's yaml front matter, remove it.
            if (yamlMatch) {
                docText = docText.substr(yamlMatch[0].length);
            }

            if (preserveScrollPos) {
                scrollPos = $iframe.contents()[0].body.scrollTop;
            } else if (_prefs.get("syncScroll")) {
                scrollPos = _calcScrollPos();
            }

            // Parse markdown into HTML
            bodyText = marked(docText);

            // Show URL in link tooltip
            bodyText = bodyText.replace(/(href=\"([^\"]*)\")/g, "$1 title=\"$2\"");

            // Make <base> tag for relative URLS
            var baseUrl = window.location.protocol + "//" + FileUtils.getDirectoryPath(doc.file.fullPath);

            // Assemble the HTML source
            var htmlSource = _.template(previewHTML, {
                baseUrl    : baseUrl,
                themeUrl   : require.toUrl("./themes/" + _prefs.get("theme") + ".css"),
                scrollTop  : scrollPos,
                bodyText   : bodyText
            });
            $iframe.attr("srcdoc", htmlSource);

            $iframe.load(function () {
                // Open external browser when links are clicked
                // (similar to what brackets.js does - but attached to the iframe's document)
                $iframe[0].contentDocument.body.addEventListener("click", _handleLinkClick, true);

                // Sync scroll position (if needed)
                _editorScroll();

                // Make sure iframe is showing
                $iframe.show();
            });
        }
    }

    function _documentChange(e) {
        _loadDoc(e.target, true);
    }

    function _resizeIframe() {
        if (visible && $iframe) {
            var iframeWidth = panel.$panel.innerWidth();
            $iframe.attr("width", iframeWidth + "px");
        }
    }

    function _updateSettings() {
        // Format
        var useGFM = _prefs.get("useGFM");
        marked.setOptions({
            breaks: useGFM,
            gfm: useGFM
        });

        // Re-render
        _loadDoc(currentDoc, true);
    }

    function _documentClicked(e) {
        if (!$settings.is(e.target) &&
                !$settingsToggle.is(e.target) &&
                $settings.has(e.target).length === 0) {
            _hideSettings();
        }
    }

    function _hideSettings() {
        if ($settings) {
            $settings.remove();
            $settings = null;
            $(window.document).off("mousedown", _documentClicked);
        }
    }

    function _showSettings(e) {
        _hideSettings();

        $settings = $(settingsHTML)
            .css({
                right: 12,
                top: $settingsToggle.position().top + $settingsToggle.outerHeight() + 12
            })
            .appendTo($panel);

        $settings.find("#markdown-preview-format")
            .prop("selectedIndex", _prefs.get("useGFM") ? 1 : 0)
            .change(function (e) {
                _prefs.set("useGFM", e.target.selectedIndex === 1);
                _updateSettings();
            });

        $settings.find("#markdown-preview-theme")
            .val(_prefs.get("theme"))
            .change(function (e) {
                _prefs.set("theme", e.target.value);
                _updateSettings();
            });

        var $syncScroll = $settings.find("#markdown-preview-sync-scroll");

        $syncScroll.change(function (e) {
            _prefs.set("syncScroll", e.target.checked);
            _editorScroll();
        });

        if (_prefs.get("syncScroll")) {
            $syncScroll.attr("checked", true);
        }

        PopUpManager.addPopUp($settings, _hideSettings, true);
        $(window.document).on("mousedown", _documentClicked);
    }

    function _setPanelVisibility(isVisible) {
        if (isVisible === realVisibility) {
            return;
        }

        realVisibility = isVisible;
        if (isVisible) {
            if (!panel) {
                $panel = $(panelHTML);
                $iframe = $panel.find("#panel-markdown-preview-frame");

                panel = WorkspaceManager.createBottomPanel("markdown-preview-panel", $panel);
                $panel.on("panelResizeUpdate", function (e, newSize) {
                    $iframe.attr("height", newSize);
                });
                $iframe.attr("height", $panel.height());

                window.setTimeout(_resizeIframe);

                $settingsToggle = $("#markdown-settings-toggle")
                    .click(function (e) {
                        if ($settings) {
                            _hideSettings();
                        } else {
                            _showSettings(e);
                        }
                    });

                $iframe.hide();
            }
            _loadDoc(DocumentManager.getCurrentDocument());
            $icon.toggleClass("active");
            panel.show();
        } else {
            $icon.toggleClass("active");
            panel.hide();
            $iframe.hide();
        }
    }

    function _currentDocChangedHandler() {
        var doc = DocumentManager.getCurrentDocument(),
            ext = doc ? FileUtils.getFileExtension(doc.file.fullPath).toLowerCase() : "";

        if (currentDoc) {
            $(currentDoc).off("change", _documentChange);
            currentDoc = null;
        }

        if (currentEditor) {
            $(currentEditor).off("scroll", _editorScroll);
            currentEditor = null;
        }

        if (doc && /md|markdown|litcoffee|txt/.test(ext)) {
            currentDoc = doc;
            $(currentDoc).on("change", _documentChange);
            currentEditor = EditorManager.getCurrentFullEditor();
            $(currentEditor).on("scroll", _editorScroll);
            $icon.css({display: "block"});
            _setPanelVisibility(visible);
            _loadDoc(doc);
        } else {
            $icon.css({display: "none"});
            _setPanelVisibility(false);
        }
    }

    function _toggleVisibility() {
        visible = !visible;
        _setPanelVisibility(visible);
    }

    // Debounce event callback to avoid excess overhead
    // Update preview 300 ms ofter document change
    // Sync scroll 1ms after document scroll (just enough to ensure
    // the document scroll isn't blocked).
    _documentChange = _.debounce(_documentChange, 300);
    _editorScroll = _.debounce(_editorScroll, 1);

    // Insert CSS for this extension
    ExtensionUtils.loadStyleSheet(module, "styles/MarkdownPreview.css");

    // Add toolbar icon
    $icon = $("<a>")
        .attr({
            id: "markdown-preview-icon",
            href: "#"
        })
        .css({
            display: "none"
        })
        .click(_toggleVisibility)
        .appendTo($("#main-toolbar .buttons"));

    // Add a document change handler
    $(MainViewManager).on("currentFileChange", _currentDocChangedHandler);

    // currentDocumentChange is *not* called for the initial document. Use
    // appReady() to set initial state.
    AppInit.appReady(function () {
        _currentDocChangedHandler();
    });

    // Listen for resize events
    $(MainViewManager).on("workspaceUpdateLayout", _resizeIframe);
    $("#sidebar").on("panelCollapsed panelExpanded panelResizeUpdate", _resizeIframe);
});
<|endoftext|>


<commit_before>var v = new Vue({
    el: '#app',
    data:{
        debug: true,
        static: null,
        user_data: [],
        active_page: "bundles",
        active_room: 0,
        active_bundle: 0,
        active_season: "spring",
        active_skill: "farming",
        save_mode: false,
        load_mode: false,
        hideCompleted: false,
        hideSpoilers: false
    },
    ready: function(){
        this.fetchData();
        new Clipboard('.copy');
        storedUserData = localStorage.getItem('user_data');
        if(storedUserData !== null && storedUserData !== ""){
            this.loadData(storedUserData);
        }
    },
    computed: {
       user_data_serialized: function(){
           return btoa(JSON.stringify(this.user_data));
       }
    },
    methods: {
        fetchData: function(){
            this.$http.get('bundles.json', function(data, status, response){
                if(status == 200){
                    this.static = data;
                    if(this.user_data.length <= 0){
                        for(i=0; i<this.static.bundles.length;i++){
                            this.user_data.push([]);
                        }
                    }
                }
            });
        },
        enterLoadMode: function(){
            this.load_mode = true;
        },
        exitLoadMode: function(){
            this.load_mode = false;
        },
        loadData: function(data){
            this.user_data = JSON.parse(atob(data));
            this.exitLoadMode();
        },
        enterSaveMode: function(){
            this.save_mode = true;
            localStorage.setItem('user_data', this.user_data_serialized);
        },
        exitSaveMode: function(){
            this.save_mode = false;
        },
        change_page: function(new_page){
          this.active_page = new_page;
        },
        change_bundle: function(new_bundle){
            this.active_bundle = new_bundle;
        },
        change_room: function(new_room){
            this.active_room = new_room;
        },
        change_season: function(new_season){
            this.active_season = new_season;
        },
        change_skill: function(new_skill){
            this.active_skill = new_skill;
        },
        addItemToBundle: function(bundleId, itemId, itemPosition){
            this.user_data[bundleId].push({item: itemId, position: itemPosition});
        },
        removeItemFromBundle: function(bundleId, itemId, itemPosition){
            console.log("Removing item from bundle" + bundleId + " | " + itemId + " | " + itemPosition);
            for(i = 0; i < this.user_data[bundleId].length; i++){
                if(this.user_data[bundleId][i].item === itemId && this.user_data[bundleId][i].position === itemPosition){
                    console.log("Found a match with: ");
                    console.log(this.user_data[bundleId][i]);
                    this.user_data[bundleId].splice(i, 1);
                }
            }
        },
        toggleItemInBundle: function(bundleId, itemId, itemPosition){
            if(this.isItemInBundle(bundleId, itemId, itemPosition)){
                this.removeItemFromBundle(bundleId, itemId, itemPosition);
            }
            else{
                this.addItemToBundle(bundleId, itemId, itemPosition);
            }
        },
        isItemInBundle: function(bundleId, itemId, itemPosition){
            if(this.user_data[bundleId].filter(function(element){
                    return element.item === itemId && element.position === itemPosition;
                }).length > 0){
                return true;
            }
            else{
                return false;
            }
        },
        getSeasonName: function(seasonId){
            for(i = 0; i < this.static.seasons.length; i++){
                if(this.static.seasons[i].id === seasonId){
                    return this.static.seasons[i].name;
                }
            }
            return "";
        },
        getSkillName: function(skillId){
            for(i = 0; i < this.static.skills.length; i++){
                if(this.static.skills[i].id === skillId){
                    return this.static.skills[i].name;
                }
            }
            return "";
        },
        getRoomItemsRequired: function(roomId) {
            return this.static.bundles.reduce(function(previousValue, nextValue){
                if(nextValue.room === roomId){
                    return previousValue + nextValue.items_required;
                }
                else{
                    return previousValue;
                }
            }, 0)
        },
        getRoomItemsChecked: function(roomId){
            return this.static.bundles
                .filter(function(b){ return b.room === roomId; })
                .reduce(function(p, c){ return p + Math.min(v.user_data[c.id].length, c.items_required); }, 0);
        }
    }
});

Vue.filter('inBundle', function(value, id){
    return value.filter(function(element){
        if(element.bundles.indexOf(id) > -1){
            return true;
        }
        else{
            return false;
        }
    });
});

Vue.filter('filterByArray', function(array1, array2){
    return array1.filter(function(element){
        if(array2.indexOf(element.id) > -1){
            return true;
        }
        else{
            return false;
        }
    });
});
<commit_msg>Added a function to determine if an item is complete.<commit_after>var v = new Vue({
    el: '#app',
    data:{
        debug: true,
        static: null,
        user_data: [],
        active_page: "bundles",
        active_room: 0,
        active_bundle: 0,
        active_season: "spring",
        active_skill: "farming",
        save_mode: false,
        load_mode: false,
        hideCompleted: false,
        hideSpoilers: false
    },
    ready: function(){
        this.fetchData();
        new Clipboard('.copy');
        storedUserData = localStorage.getItem('user_data');
        if(storedUserData !== null && storedUserData !== ""){
            this.loadData(storedUserData);
        }
    },
    computed: {
       user_data_serialized: function(){
           return btoa(JSON.stringify(this.user_data));
       }
    },
    methods: {
        fetchData: function(){
            this.$http.get('bundles.json', function(data, status, response){
                if(status == 200){
                    this.static = data;
                    if(this.user_data.length <= 0){
                        for(i=0; i<this.static.bundles.length;i++){
                            this.user_data.push([]);
                        }
                    }
                }
            });
        },
        enterLoadMode: function(){
            this.load_mode = true;
        },
        exitLoadMode: function(){
            this.load_mode = false;
        },
        loadData: function(data){
            this.user_data = JSON.parse(atob(data));
            this.exitLoadMode();
        },
        enterSaveMode: function(){
            this.save_mode = true;
            localStorage.setItem('user_data', this.user_data_serialized);
        },
        exitSaveMode: function(){
            this.save_mode = false;
        },
        change_page: function(new_page){
          this.active_page = new_page;
        },
        change_bundle: function(new_bundle){
            this.active_bundle = new_bundle;
        },
        change_room: function(new_room){
            this.active_room = new_room;
        },
        change_season: function(new_season){
            this.active_season = new_season;
        },
        change_skill: function(new_skill){
            this.active_skill = new_skill;
        },
        addItemToBundle: function(bundleId, itemId, itemPosition){
            this.user_data[bundleId].push({item: itemId, position: itemPosition});
        },
        removeItemFromBundle: function(bundleId, itemId, itemPosition){
            console.log("Removing item from bundle" + bundleId + " | " + itemId + " | " + itemPosition);
            for(i = 0; i < this.user_data[bundleId].length; i++){
                if(this.user_data[bundleId][i].item === itemId && this.user_data[bundleId][i].position === itemPosition){
                    console.log("Found a match with: ");
                    console.log(this.user_data[bundleId][i]);
                    this.user_data[bundleId].splice(i, 1);
                }
            }
        },
        toggleItemInBundle: function(bundleId, itemId, itemPosition){
            if(this.isItemInBundle(bundleId, itemId, itemPosition)){
                this.removeItemFromBundle(bundleId, itemId, itemPosition);
            }
            else{
                this.addItemToBundle(bundleId, itemId, itemPosition);
            }
        },
        isItemInBundle: function(bundleId, itemId, itemPosition){
            if(this.user_data[bundleId].filter(function(element){
                    return element.item === itemId && element.position === itemPosition;
                }).length > 0){
                return true;
            }
            else{
                return false;
            }
        },
        getSeasonName: function(seasonId){
            for(i = 0; i < this.static.seasons.length; i++){
                if(this.static.seasons[i].id === seasonId){
                    return this.static.seasons[i].name;
                }
            }
            return "";
        },
        getSkillName: function(skillId){
            for(i = 0; i < this.static.skills.length; i++){
                if(this.static.skills[i].id === skillId){
                    return this.static.skills[i].name;
                }
            }
            return "";
        },
        getRoomItemsRequired: function(roomId) {
            return this.static.bundles.reduce(function(previousValue, nextValue){
                if(nextValue.room === roomId){
                    return previousValue + nextValue.items_required;
                }
                else{
                    return previousValue;
                }
            }, 0)
        },
        getRoomItemsChecked: function(roomId){
            return this.static.bundles
                .filter(function(b){ return b.room === roomId; })
                .reduce(function(p, c){ return p + Math.min(v.user_data[c.id].length, c.items_required); }, 0);
        },
        isCompleted: function (item) {
            for(i=0; i < item.bundles.length; i++){
                if(!this.isItemInBundle(item.bundles[i], item.id, i)){
                    return false;
                }
            }

            return true;
        }
    }
});

Vue.filter('inBundle', function(value, id){
    return value.filter(function(element){
        if(element.bundles.indexOf(id) > -1){
            return true;
        }
        else{
            return false;
        }
    });
});

Vue.filter('filterByArray', function(array1, array2){
    return array1.filter(function(element){
        if(array2.indexOf(element.id) > -1){
            return true;
        }
        else{
            return false;
        }
    });
});
<|endoftext|>


<commit_before>const {app, BrowserWindow, globalShortcut} = require('electron')
var   mainWindow     = null;

app.on('window-all-closed', function () {
	if (process.platform != 'darwin') {
		app.quit();
	}
});

app.on('ready', function () {
	mainWindow = new BrowserWindow({
		width             : 1280,
		height            : 720,
		'title'           : 'Brain.fm',
		webSecurity       : false,
		'node-integration': false
	});

	mainWindow.setMenu(null);
	mainWindow.loadURL('http://brain.fm');
	//mainWindow.webContents.openDevTools();

	mainWindow.on('app-command', function (e, cmd) {
		if (cmd === 'browser-backward' && mainWindow.webContents.canGoBack()) {
			mainWindow.webContents.goBack();
		}
		else if (cmd === 'browser-forward' && mainWindow.webContents.canGoForward()) {
			mainWindow.webContents.goForward();
		}
	});

	// Global shortcuts..
	globalShortcut.register('MediaNextTrack', function () {skip();});
	globalShortcut.register('MediaPlayPause', function () {playPause();});
	//globalShortcut.register('MediaPreviousTrack', function() {});

	mainWindow.on('closed', function () {
		mainWindow = null;
	});
});

function skip() {
	if (mainWindow == null) {
		return;
	}
	// todo
}

function playPause() {
	if (mainWindow == null) {
		return;
	}

	mainWindow.webContents.executeJavaScript('$("#play_button").click()');
}<commit_msg>feat: goes to the app instead of the homepage<commit_after>const {app, BrowserWindow, globalShortcut} = require('electron')
var   mainWindow     = null;

app.on('window-all-closed', function () {
	if (process.platform != 'darwin') {
		app.quit();
	}
});

app.on('ready', function () {
	mainWindow = new BrowserWindow({
		width             : 1280,
		height            : 720,
		'title'           : 'Brain.fm',
		webSecurity       : false,
		'node-integration': false
	});

	mainWindow.setMenu(null);
	mainWindow.loadURL('http://brain.fm/app');
	//mainWindow.webContents.openDevTools();

	mainWindow.on('app-command', function (e, cmd) {
		if (cmd === 'browser-backward' && mainWindow.webContents.canGoBack()) {
			mainWindow.webContents.goBack();
		}
		else if (cmd === 'browser-forward' && mainWindow.webContents.canGoForward()) {
			mainWindow.webContents.goForward();
		}
	});

	// Global shortcuts..
	globalShortcut.register('MediaNextTrack', function () {skip();});
	globalShortcut.register('MediaPlayPause', function () {playPause();});
	//globalShortcut.register('MediaPreviousTrack', function() {});

	mainWindow.on('closed', function () {
		mainWindow = null;
	});
});

function skip() {
	if (mainWindow == null) {
		return;
	}
	// todo
}

function playPause() {
	if (mainWindow == null) {
		return;
	}

	mainWindow.webContents.executeJavaScript('$("#play_button").click()');
}
<|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var mylcd = new (require("jsupm_i2clcd").Jhd1313m1)(6, 0x3E, 0x62);

// parse application/json
app.use(bodyParser.json());

app.use(function (req, res, next) {
  console.log(req.body); // populated!
  next();
});

var backlight = {
    r:0,
    g:0,
    b:0
};
mylcd.setColor(backlight.r,backlight.g,backlight.b);

var lcdtext = "";

app.get('/lcd/backlight/', function (req, res) {
  res.status(200).json(backlight);
});

app.post('/lcd/backlight/', function (req, res) {
   backlight = {
      r:parseInt(req.query.r),
      g:parseInt(req.query.g),
      b:parseInt(req.query.b)
  };
  mylcd.setColor(backlight.r,backlight.g,backlight.b);
  res.status(201).send("Success");
});

app.delete('/lcd/backlight/', function (req, res) {
  backlight = {r:0,g:0,b:0};
  mylcd.setColor(backlight.r,backlight.g,backlight.b);
  res.status(204).send("Deleted");
});

app.get('/lcd/text/', function (req, res) {
  res.status(200).json(lcdtext);
});

app.post('/lcd/text/', function (req, res) {
  lcdtext = req.query.lcdtext;
  mylcd.clear();
  mylcd.write(lcdtext);
  res.status(201).send("Success");
});

app.delete('/lcd/text/', function (req, res) {
  mylcd.clear();
  res.status(204).send("Deleted");
});

var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);
});
<commit_msg>Fix lcd issue<commit_after>// The express library provides a quick and easy way to create on HTTP server
var express = require('express');

// The body-parser library allows us to declare the server will use JSON format
var bodyParser = require('body-parser');

// Declare the HTTP server as a variable named "app"
var app = express();

// Declare the LCD variable
var LCD = require("jsupm_jhd1313m1");
var OFFSET = 512;
var mylcd = new LCD.Jhd1313m1(0+OFFSET, 0x3E, 0x62);

// parse application/json
app.use(bodyParser.json());

// This function will print the route for each incoming HTTP request
app.use(function (req, res, next) {
  console.log(req.body); // populated!
  next();
});

var backlight = {
    r:0,
    g:0,
    b:0
};

var lcdtext = "";
mylcd.setColor(backlight.r,backlight.g,backlight.b);

app.get('/lcd/backlight/', function (req, res) {
  res.status(200).json(backlight);
});
app.get('/lcd/text/', function (req, res) {
  res.status(200).json(lcdtext);
});

app.post('/lcd/backlight/', function (req, res) {
   backlight = {
      r:parseInt(req.query.r),
      g:parseInt(req.query.g),
      b:parseInt(req.query.b)
  };
  mylcd.setColor(backlight.r,backlight.g,backlight.b);
  res.status(201).send("Success");
});

app.post('/lcd/text/', function (req, res) {
  lcdtext = req.query.lcdtext;
  mylcd.clear();
  mylcd.write(lcdtext);
  res.status(201).send("Success");
});

app.delete('/lcd/backlight/', function (req, res) {
  backlight = {r:0,g:0,b:0};
  mylcd.setColor(backlight.r,backlight.g,backlight.b);
  res.status(204).send("Deleted");
});

app.delete('/lcd/text/', function (req, res) {
  mylcd.clear();
  res.status(204).send("Deleted");
});

var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;

console.log('Example app listening at http://%s:%s', host, port);
});
<|endoftext|>


<commit_before>/**
 * TimeSlice by Nicholas L. Goodman
 * Allows basic "timebox" time management for increased productivity.
 * It is provided under a GPL license.
 * https://gnu.org/licenses/gpl-3.0.txt
 * Cuckoo Sound Effect by MorgantJ under a Creative Commons License
 * http://creativecommons.org/licenses/by/3.0/legalcode
 * http://freesound.org/people/morgantj/sounds/58628/
 * Tock provided by Mr Chimp under the MIT License
 */

window.onload = function() {
	var boxes = 0;
	var breaks = 0;
	var completed = false;
	var box_duration = $('#box_duration').val();
	var count = 0;
	var iter = 4;
	var short_break_duration = $('#break_short').val();
	var long_break_duration = $('#break_long').val();
	var on_short_break = false;
	var on_long_break = false;

	var isRunning = false;
	var cuckoo = new Audio('cuckoo.mp3');

	function proceed () {

		if (boxes >= iter){
			on_long_break = true;
			on_short_break = false;
		}

		if (on_short_break){
			breaks++;
			//$('#time_left').val($('#break_short').val());
			timebox.start($('#break_short').val());
			on_short_break = false;
		}
		else if (on_long_break){
			cuckoo.play();
			breaks = 0;
			boxes = 0;
			//$('#time_left').val($('#break_long').val());
			timebox.start($('#break_long').val());
			on_long_break = false;
			iter = iter_original;
		}
		else {
			boxes++;
			//$('#time_left').val($('#box_duration').val());
			timebox.start($('#box_duration').val());
			on_short_break = true;

		};

         $('#timeBoxes').text(boxes);
         $('#breaks').text(breaks);
	   };

    var timebox = Tock({
    	countdown: true,
        interval: 250,
        callback: function () {
            console.log(timebox.lap() / 1000);
            $('#time_left').val(timebox.msToTime(timebox.lap()));
        },
        complete: function () {
            console.log('end');
            cuckoo.play();
			proceed();
           }
    });

  $('#start_box').on('click', function () {
  		cuckoo.pause();
  		if (isRunning) {
  			isRunning = false;
  			timebox.stop($('#time_left').val());
        }
        else {
        	isRunning = true;
			proceed();
        }
    });

    $('#reset_box').on('click', function () {
    	isRunning = false;
        timebox.stop();
        $('#time_left').val($('#box_duration').val());
        boxes = 0;
        breaks = 0;
        $('#timeBoxes').text(boxes);
        $('#breaks').text(breaks);

    });

};
<commit_msg>Delete main.js<commit_after><|endoftext|>


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

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

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

var bt = require("../utilities/bt");
var sql = require("../utilities/sql");

var EXT = require("../utilities/ext.json");

function Repo(path) {
	var repo = this;
	repo.PATH = path;
	repo.DATA = pathModule.resolve(repo.PATH, "./data");
	repo.CACHE = pathModule.resolve(repo.PATH, "./cache");
	repo.LOG = pathModule.resolve(repo.DATA, "./hashes.log"); // TODO: Move to top level, rename.
	repo.CONFIG = pathModule.resolve(repo.PATH, "./secret.json"); // TODO: Move to EarthFS.json.
	repo.KEY = pathModule.resolve(repo.PATH, "./server.key");
	repo.CERT = pathModule.resolve(repo.PATH, "./server.crt");
	repo.log = fs.createWriteStream(repo.LOG, {flags: "a", encoding: "utf8"});
	repo.config = JSON.parse(fs.readFileSync(repo.CONFIG, "utf8")); // TODO: Async?
	repo.db = new pg.Client(repo.config.db); // TODO: Use client pool.
	repo.db.connect();
}
Repo.prototype.pathForEntry = function(dir, hash, type) {
	var t = type.split(";")[0];
	if(!bt.has(EXT, t)) throw new Error("Invalid MIME type "+type);
	return dir+"/"+hash.slice(0, 2)+"/"+hash+"."+EXT[t];
};
Repo.prototype.addEntry = function(source, type, h, p, callback/* (err, entryID) */) {
	var repo = this;

	repo.log.write(JSON.stringify({
		"date": new Date().toISOString(),
		"internalHash": h.internalHash,
		"type": type,
		"source": source,
	})+"\n");

	sql.debug(repo.db,
		'INSERT INTO "entries" ("hash", "type", "fulltext")'+
		' VALUES ($1, $2, to_tsvector(\'english\', $3)) RETURNING "entryID"',
		[h.internalHash, type, p.fullText],
		function(err, results) {
			if(err) return callback(err, null);
			var entryID = results.rows[0].entryID;
			var allLinks = h.URNs.concat(p.links, p.metaEntries, p.metaLinks).unique();
			sql.debug(repo.db,
				'INSERT INTO "URIs" ("URI")'+
				' VALUES '+sql.list2D(allLinks, 1)+'', allLinks,
				function(err, results) {
					if(err) return callback(err, null);
					sql.debug(repo.db,
						'UPDATE "URIs" SET "entryID" = $1'+
						' WHERE "URI" IN ('+sql.list1D(h.URNs, 2)+')',
						[entryID].concat(h.URNs),
						function(err, results) {
							if(err) return callback(err, null);
							if(!p.links.length) return callback(null, entryID);
							sql.debug(repo.db,
								'INSERT INTO "links"'+
								' ("fromEntryID", "toUriID", "direct", "indirect")'+
								' SELECT $1, "uriID", true, 1'+
								' FROM "URIs" WHERE "URI" IN ('+sql.list1D(p.links, 2)+')',
								[entryID].concat(p.links),
								function(err, results) {
									if(err) return callback(err, null);
									// TODO
									// 1. Add meta-links to the meta-entries
									// 2. Recurse over links and add indirect rows
									callback(err, entryID);
								}
							);
						}
					);
				}
			);
		}
	);

};

module.exports = Repo;
<commit_msg>Rename repo files.<commit_after>/* Copyright Ben Trask and other contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

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

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

var bt = require("../utilities/bt");
var sql = require("../utilities/sql");

var EXT = require("../utilities/ext.json");

function Repo(path) {
	var repo = this;
	repo.PATH = path;
	repo.DATA = pathModule.resolve(repo.PATH, "./data");
	repo.CACHE = pathModule.resolve(repo.PATH, "./cache");
	repo.LOG = pathModule.resolve(repo.PATH, "./entries.log");
	repo.CONFIG = pathModule.resolve(repo.PATH, "./EarthFS.json");
	repo.KEY = pathModule.resolve(repo.PATH, "./server.key");
	repo.CERT = pathModule.resolve(repo.PATH, "./server.crt");
	repo.log = fs.createWriteStream(repo.LOG, {flags: "a", encoding: "utf8"});
	repo.config = JSON.parse(fs.readFileSync(repo.CONFIG, "utf8")); // TODO: Async?
	repo.db = new pg.Client(repo.config.db); // TODO: Use client pool.
	repo.db.connect();
}
Repo.prototype.pathForEntry = function(dir, hash, type) {
	var t = type.split(";")[0];
	if(!bt.has(EXT, t)) throw new Error("Invalid MIME type "+type);
	return dir+"/"+hash.slice(0, 2)+"/"+hash+"."+EXT[t];
};
Repo.prototype.addEntry = function(source, type, h, p, callback/* (err, entryID) */) {
	var repo = this;

	repo.log.write(JSON.stringify({
		"date": new Date().toISOString(),
		"internalHash": h.internalHash,
		"type": type,
		"source": source,
	})+"\n");

	sql.debug(repo.db,
		'INSERT INTO "entries" ("hash", "type", "fulltext")'+
		' VALUES ($1, $2, to_tsvector(\'english\', $3)) RETURNING "entryID"',
		[h.internalHash, type, p.fullText],
		function(err, results) {
			if(err) return callback(err, null);
			var entryID = results.rows[0].entryID;
			var allLinks = h.URNs.concat(p.links, p.metaEntries, p.metaLinks).unique();
			sql.debug(repo.db,
				'INSERT INTO "URIs" ("URI")'+
				' VALUES '+sql.list2D(allLinks, 1)+'', allLinks,
				function(err, results) {
					if(err) return callback(err, null);
					sql.debug(repo.db,
						'UPDATE "URIs" SET "entryID" = $1'+
						' WHERE "URI" IN ('+sql.list1D(h.URNs, 2)+')',
						[entryID].concat(h.URNs),
						function(err, results) {
							if(err) return callback(err, null);
							if(!p.links.length) return callback(null, entryID);
							sql.debug(repo.db,
								'INSERT INTO "links"'+
								' ("fromEntryID", "toUriID", "direct", "indirect")'+
								' SELECT $1, "uriID", true, 1'+
								' FROM "URIs" WHERE "URI" IN ('+sql.list1D(p.links, 2)+')',
								[entryID].concat(p.links),
								function(err, results) {
									if(err) return callback(err, null);
									// TODO
									// 1. Add meta-links to the meta-entries
									// 2. Recurse over links and add indirect rows
									callback(err, entryID);
								}
							);
						}
					);
				}
			);
		}
	);

};

module.exports = Repo;
<|endoftext|>


<commit_before>
var _ = require("lodash");
var moment = require("moment");
var Immutable = require('immutable');

var BaseStore = require("./basestore");
var Commands = require("ui/core/atomconstants").commands;
var AtomState = require("ui/core/atomstate");
var LayoutEngine = require("ui/core/layout/layoutengine");

var commandHandlers = {
    /**
     * [updateTicker description]
     * @param  {[type]} payload {ticker: 'MSFT'}
     * @return {[type]}         [description]
     */
    updateTicker: function (payload) {
        this.atom.transact(function (state) {
            var activeChartIndex = this.getActiveChartIndex();
            return state.updateIn(['chartStore', 'charts', activeChartIndex, 'keys', 'ticker'], function (value) {
                return payload.ticker;
            });
        }.bind(this));
    },

    /**
     * [updateTimeFrame description]
     * @param  {[type]} payload {from: <Date>, to: <Date>}
     * @return {[type]}         [description]
     */
    updateTimeFrame: function (payload) {
        this.atom.transact(function (state) {
            var activeChartIndex = this.getActiveChartIndex();
            return state.updateIn(['chartStore', 'charts', activeChartIndex, 'keys', 'timeframe'], function (value) {
                return Immutable.fromJS(payload.timeframe); //remove fromJS() ??
            });
        }.bind(this));
    },

    /**
     * [updateRange description]
     * @param  {[type]} payload {duration: 'daily'}
     * @return {[type]}         [description]
     */
    updateDuration: function (payload) {
        this.atom.transact(function (state) {
            var activeChartIndex = this.getActiveChartIndex();
            return state.updateIn(['chartStore', 'charts', activeChartIndex, 'keys', 'duration'], function (value) {
                return payload.duration;
            });
        }.bind(this));
    },

     /**
     * [updateActiveChart description]
     * @param  {[type]} payload {chartId: '23523525'}
     * @return {[type]}         [description]
     */
    updateActiveChart: function (payload) {
        this.atom.transact(function (state) {
            var activeChartIndex = this.getActiveChartIndex();
            return state.updateIn(['chartStore', 'activeChartId'], function (value) {
                return payload.chartId;
            });
        }.bind(this));
    },

    /**
     * [updatePriceData description]
     * @param  {[type]} payload {
     *   data: {
              status: "loaded",
              series: [{
                    date: Date.parse(record[0]),
                    open: +parseFloat(record[1]).toFixed(2),
                    high: +parseFloat(record[2]).toFixed(2),
                    low: +parseFloat(record[3]).toFixed(2),
                    close: +parseFloat(record[4]).toFixed(2),
                    volume: +parseFloat(record[5]).toFixed(2),
                    adjClose: +parseFloat(record[6]).toFixed(2),
              }, ...],
              min: 0,
              max: 0,
              minVolume: 0,
              maxVolume: 0
            }
     * }
     * @return {[type]}         [description]
     */
    updatePriceData: function (payload) {
        this.atom.transact(function (state) {
            var activeChartIndex = this.getActiveChartIndex();
            return state.updateIn(['chartStore', 'charts', activeChartIndex, 'data'], function (value) {
                return payload.data; //set raw json (immutable map not needed, also speeeds up the lookup)
            });
        }.bind(this));
    },

    /**
     * [updatePriceData description]
     * @param  {[type]} payload  {
     *   data: {
              status: "loading",
              series: [{
                    date: Date.parse(record[0]),
                    open: +parseFloat(record[1]).toFixed(2),
                    high: +parseFloat(record[2]).toFixed(2),
                    low: +parseFloat(record[3]).toFixed(2),
                    close: +parseFloat(record[4]).toFixed(2),
                    volume: +parseFloat(record[5]).toFixed(2),
                    adjClose: +parseFloat(record[6]).toFixed(2),
              }, ...],
              min: 0,
              max: 0,
              minVolume: 0,
              maxVolume: 0
            }
     * }
     * @return {[type]} [description]
     */
    setDataToLoading: function (/*payload*/) {
        this.atom.transact(function (state) {
            var activeChartIndex = this.getActiveChartIndex();
            return state.updateIn(['chartStore', 'charts', activeChartIndex, 'data'], function (value) {
                return {
                          status: "loading",
                          series: [],
                          min: 0,
                          max: 0,
                          minVolume: 0,
                          maxVolume: 0
                        };
                });
        }.bind(this));
    },

    /**
     * [updateChartLayout description]
     * @param  {[type]} layoutId [description]
     * @return {[type]}          [description]
     */
    updateChartLayout: function (payload) {
        var _this = this;
        // TODO: CLEANUP
        this.atom.transact(function (state) {
            // debugger;
            var totalChartsToRender = parseInt(payload.layoutId.replace("chartslayout", ""));

            var atomState = _this.atom.getState();
            var currentCharts = atomState.getIn(['chartStore', 'charts']);
            var currentChartCount = currentCharts.size;

            if (totalChartsToRender > currentChartCount) {
              // Clone the additional charts from the getDefaultChartState
              // update layoutids, chartid
              // set ticker, keys, data from active charts
              var chartsToAdd = totalChartsToRender - currentChartCount;
              _.times(chartsToAdd, function (index) {
                  var chart = _this.getActiveChart();
                  chart.id = new Date().getTime() + Math.floor(Math.random() * (1000 - 50)) + 50;
                  chart.data = null;

                  // immutable obj
                  chart = Immutable.fromJS(chart);
                  chart = chart.updateIn(['data'], function () {
                      return _this.getPriceData();
                  });
                  currentCharts = currentCharts.push(chart);
              });
            } else if (totalChartsToRender < currentChartCount)  {
                var chartsToRemove = currentChartCount - totalChartsToRender;
                currentCharts = currentCharts.splice(-chartsToRemove);
            }

            // update layout id for all the remaining charts
            currentCharts = currentCharts.map(function (chart, index) {
                  return chart.updateIn(['keys', 'layoutId'], function (value) {
                      return payload.layoutId + "_" + (index + 1)
                  });
                  //console.log(chart.toJS());
              });

            return atomState.updateIn(['chartStore', 'charts'], function () {
                  return currentCharts;
              });

        }.bind(this));

    },
};

function ChartsStore(atom) {
    BaseStore.call(this, atom);
    this.registerCommandHandlers([
        { key: Commands.CHART_UPDATE_TICKER,         value: commandHandlers.updateTicker.bind(this) },
        { key: Commands.CHART_UPDATE_DURATION,       value: commandHandlers.updateDuration.bind(this) },
        { key: Commands.CHART_UPDATE_TIMEFRAME,      value: commandHandlers.updateTimeFrame.bind(this) },
        { key: Commands.CHART_DATA_LOADING,          value: commandHandlers.setDataToLoading.bind(this) },
        { key: Commands.CHART_DATA_FETCHED,          value: commandHandlers.updatePriceData.bind(this) },
        { key: Commands.CHART_UPDATE_LAYOUT,         value: commandHandlers.updateChartLayout.bind(this)},
        { key: Commands.CHART_UPDATE_ACTIVECHART,    value: commandHandlers.updateActiveChart.bind(this)}
    ]);
    this.priceChartModel = null;
}

ChartsStore.prototype = _.create(BaseStore.prototype, {

    'constructor': ChartsStore,

    _getActiveChart: function (id) {
        var atomState = this.atom.getState();
        var activeChartId = id || this.getActiveChartId();
        return atomState
                .getIn(['chartStore', 'charts'])
                  .find(function(item) {
                    return (item.getIn(['id']) === activeChartId);
                  });
    },

    _getChartKeys: function (id) {
        return this._getActiveChart(id).getIn(['keys']);
    },

    getActiveChartId: function (id) {
        var atomState = this.atom.getState();
        return atomState.getIn(['chartStore', 'activeChartId']);
    },

    getActiveChartIndex: function (id) {
        var atomState = this.atom.getState();
        var activeChartId = id || this.getActiveChartId();
        return atomState
                .getIn(['chartStore', 'charts'])
                  .findIndex(function(item) {
                    return (item.getIn(['id']) === activeChartId);
                  });
    },

    getAllChartIds: function () {
        var atomState = this.atom.getState();
        return atomState
                .getIn(['chartStore', 'charts'])
                .map(function(item) {
                  return (item.getIn(['id']));
                }).toJS();
    },

    getActiveChart: function (id) {
        return this._getActiveChart(id).toJS();
    },

    getChartKeys: function (id) {
        return this._getChartKeys(id).toJS();
    },

    getTicker: function (id) {
        return this._getChartKeys(id).getIn(['ticker']);
    },

    getTimeframe: function (id) {
        return this._getChartKeys(id).getIn(['timeframe']).toJS();
    },

    getTimeframeInMonths: function (id) {
        var timeframe = this.getTimeframe(id);
        return Math.ceil(moment(timeframe.to).diff(moment(timeframe.from), 'months', true));
    },

    getDuration: function (id) {
        return this._getChartKeys(id).getIn(['duration']);
    },

    getChartLayoutId: function (id) {
       return this._getChartKeys(id).getIn(['layoutId']);
    },

    getPositionRect: function (id) {
      var chartRect = LayoutEngine.getLayoutRect(this.getChartLayoutId(id));
      return {
        width: chartRect.width - 16,
        height: chartRect.height - 16,
        top: chartRect.top + 8,
        left: chartRect.left + 8
      };
    },

    getPriceData: function (id) {
      var data = this._getActiveChart(id).getIn(['data']);
      return data.toJS ? data.toJS() : data;
    }
});

module.exports = ChartsStore;

<commit_msg>fix activechartid consistency when charts are removed<commit_after>
var _ = require("lodash");
var moment = require("moment");
var Immutable = require('immutable');

var BaseStore = require("./basestore");
var Commands = require("ui/core/atomconstants").commands;
var AtomState = require("ui/core/atomstate");
var LayoutEngine = require("ui/core/layout/layoutengine");

var commandHandlers = {
    /**
     * [updateTicker description]
     * @param  {[type]} payload {ticker: 'MSFT'}
     * @return {[type]}         [description]
     */
    updateTicker: function (payload) {
        this.atom.transact(function (state) {
            var activeChartIndex = this.getActiveChartIndex();
            return state.updateIn(['chartStore', 'charts', activeChartIndex, 'keys', 'ticker'], function (value) {
                return payload.ticker;
            });
        }.bind(this));
    },

    /**
     * [updateTimeFrame description]
     * @param  {[type]} payload {from: <Date>, to: <Date>}
     * @return {[type]}         [description]
     */
    updateTimeFrame: function (payload) {
        this.atom.transact(function (state) {
            var activeChartIndex = this.getActiveChartIndex();
            return state.updateIn(['chartStore', 'charts', activeChartIndex, 'keys', 'timeframe'], function (value) {
                return Immutable.fromJS(payload.timeframe); //remove fromJS() ??
            });
        }.bind(this));
    },

    /**
     * [updateRange description]
     * @param  {[type]} payload {duration: 'daily'}
     * @return {[type]}         [description]
     */
    updateDuration: function (payload) {
        this.atom.transact(function (state) {
            var activeChartIndex = this.getActiveChartIndex();
            return state.updateIn(['chartStore', 'charts', activeChartIndex, 'keys', 'duration'], function (value) {
                return payload.duration;
            });
        }.bind(this));
    },

     /**
     * [updateActiveChart description]
     * @param  {[type]} payload {chartId: '23523525'}
     * @return {[type]}         [description]
     */
    updateActiveChart: function (payload) {
        this.atom.transact(function (state) {
            var activeChartIndex = this.getActiveChartIndex();
            return state.updateIn(['chartStore', 'activeChartId'], function (value) {
                return payload.chartId;
            });
        }.bind(this));
    },

    /**
     * [updatePriceData description]
     * @param  {[type]} payload {
     *   data: {
              status: "loaded",
              series: [{
                    date: Date.parse(record[0]),
                    open: +parseFloat(record[1]).toFixed(2),
                    high: +parseFloat(record[2]).toFixed(2),
                    low: +parseFloat(record[3]).toFixed(2),
                    close: +parseFloat(record[4]).toFixed(2),
                    volume: +parseFloat(record[5]).toFixed(2),
                    adjClose: +parseFloat(record[6]).toFixed(2),
              }, ...],
              min: 0,
              max: 0,
              minVolume: 0,
              maxVolume: 0
            }
     * }
     * @return {[type]}         [description]
     */
    updatePriceData: function (payload) {
        this.atom.transact(function (state) {
            var activeChartIndex = this.getActiveChartIndex();
            return state.updateIn(['chartStore', 'charts', activeChartIndex, 'data'], function (value) {
                return payload.data; //set raw json (immutable map not needed, also speeeds up the lookup)
            });
        }.bind(this));
    },

    /**
     * [updatePriceData description]
     * @param  {[type]} payload  {
     *   data: {
              status: "loading",
              series: [{
                    date: Date.parse(record[0]),
                    open: +parseFloat(record[1]).toFixed(2),
                    high: +parseFloat(record[2]).toFixed(2),
                    low: +parseFloat(record[3]).toFixed(2),
                    close: +parseFloat(record[4]).toFixed(2),
                    volume: +parseFloat(record[5]).toFixed(2),
                    adjClose: +parseFloat(record[6]).toFixed(2),
              }, ...],
              min: 0,
              max: 0,
              minVolume: 0,
              maxVolume: 0
            }
     * }
     * @return {[type]} [description]
     */
    setDataToLoading: function (/*payload*/) {
        this.atom.transact(function (state) {
            var activeChartIndex = this.getActiveChartIndex();
            return state.updateIn(['chartStore', 'charts', activeChartIndex, 'data'], function (value) {
                return {
                          status: "loading",
                          series: [],
                          min: 0,
                          max: 0,
                          minVolume: 0,
                          maxVolume: 0
                        };
                });
        }.bind(this));
    },

    /**
     * [updateChartLayout description]
     * @param  {[type]} layoutId [description]
     * @return {[type]}          [description]
     */
    updateChartLayout: function (payload) {
        var _this = this;
        // TODO: CLEANUP
        this.atom.transact(function (state) {
            // debugger;
            var totalChartsToRender = parseInt(payload.layoutId.replace("chartslayout", ""));

            var atomState = _this.atom.getState();
            var currentCharts = atomState.getIn(['chartStore', 'charts']);
            var activeChartId = atomState.getIn(['chartStore', 'activeChartId']);
            var currentChartCount = currentCharts.size;

            if (totalChartsToRender > currentChartCount) {
              // Clone the additional charts from the getDefaultChartState
              // update layoutids, chartid
              // set ticker, keys, data from active charts
              var chartsToAdd = totalChartsToRender - currentChartCount;
              _.times(chartsToAdd, function (index) {
                  var chart = _this.getActiveChart();
                  chart.id = new Date().getTime() + Math.floor(Math.random() * (1000 - 50)) + 50;
                  chart.data = null;

                  // immutable obj
                  chart = Immutable.fromJS(chart);
                  chart = chart.updateIn(['data'], function () {
                      return _this.getPriceData();
                  });
                  currentCharts = currentCharts.push(chart);
              });
            } else if (totalChartsToRender < currentChartCount)  {
                var chartsToRemove = currentChartCount - totalChartsToRender;
                currentCharts = currentCharts.splice(-chartsToRemove);
            }

            var validActiveChartId = false, newActiveChartId;

            // update layout id for all the remaining charts and find if activeChartId needs an update
            currentCharts = currentCharts.map(function (chart, index) {
                  if (!validActiveChartId && chart.getIn(['id']) === activeChartId) {
                    validActiveChartId = true;
                  }

                  return chart.updateIn(['keys', 'layoutId'], function (value) {
                      return payload.layoutId + "_" + (index + 1)
                  });
              });

            //reset active chartId (if needed due to removed charts);
            newActiveChartId = (!validActiveChartId) ? currentCharts.getIn([0, 'id']) : activeChartId;

            return atomState.updateIn(['chartStore', 'charts'], function () {
                  return currentCharts;
              }).updateIn(['chartStore', 'activeChartId'], function (value) {
                return newActiveChartId;
              });

        }.bind(this));

    },
};

function ChartsStore(atom) {
    BaseStore.call(this, atom);
    this.registerCommandHandlers([
        { key: Commands.CHART_UPDATE_TICKER,         value: commandHandlers.updateTicker.bind(this) },
        { key: Commands.CHART_UPDATE_DURATION,       value: commandHandlers.updateDuration.bind(this) },
        { key: Commands.CHART_UPDATE_TIMEFRAME,      value: commandHandlers.updateTimeFrame.bind(this) },
        { key: Commands.CHART_DATA_LOADING,          value: commandHandlers.setDataToLoading.bind(this) },
        { key: Commands.CHART_DATA_FETCHED,          value: commandHandlers.updatePriceData.bind(this) },
        { key: Commands.CHART_UPDATE_LAYOUT,         value: commandHandlers.updateChartLayout.bind(this)},
        { key: Commands.CHART_UPDATE_ACTIVECHART,    value: commandHandlers.updateActiveChart.bind(this)}
    ]);
    this.priceChartModel = null;
}

ChartsStore.prototype = _.create(BaseStore.prototype, {

    'constructor': ChartsStore,

    _getActiveChart: function (id) {
        var atomState = this.atom.getState();
        var activeChartId = id || this.getActiveChartId();
        return atomState
                .getIn(['chartStore', 'charts'])
                  .find(function(item) {
                    return (item.getIn(['id']) === activeChartId);
                  });
    },

    _getChartKeys: function (id) {
        return this._getActiveChart(id).getIn(['keys']);
    },

    getActiveChartId: function (id) {
        var atomState = this.atom.getState();
        return atomState.getIn(['chartStore', 'activeChartId']);
    },

    getActiveChartIndex: function (id) {
        var atomState = this.atom.getState();
        var activeChartId = id || this.getActiveChartId();
        return atomState
                .getIn(['chartStore', 'charts'])
                  .findIndex(function(item) {
                    return (item.getIn(['id']) === activeChartId);
                  });
    },

    getAllChartIds: function () {
        var atomState = this.atom.getState();
        return atomState
                .getIn(['chartStore', 'charts'])
                .map(function(item) {
                  return (item.getIn(['id']));
                }).toJS();
    },

    getActiveChart: function (id) {
        return this._getActiveChart(id).toJS();
    },

    getChartKeys: function (id) {
        return this._getChartKeys(id).toJS();
    },

    getTicker: function (id) {
        return this._getChartKeys(id).getIn(['ticker']);
    },

    getTimeframe: function (id) {
        return this._getChartKeys(id).getIn(['timeframe']).toJS();
    },

    getTimeframeInMonths: function (id) {
        var timeframe = this.getTimeframe(id);
        return Math.ceil(moment(timeframe.to).diff(moment(timeframe.from), 'months', true));
    },

    getDuration: function (id) {
        return this._getChartKeys(id).getIn(['duration']);
    },

    getChartLayoutId: function (id) {
       return this._getChartKeys(id).getIn(['layoutId']);
    },

    getPositionRect: function (id) {
      var chartRect = LayoutEngine.getLayoutRect(this.getChartLayoutId(id));
      return {
        width: chartRect.width - 16,
        height: chartRect.height - 16,
        top: chartRect.top + 8,
        left: chartRect.left + 8
      };
    },

    getPriceData: function (id) {
      var data = this._getActiveChart(id).getIn(['data']);
      return data.toJS ? data.toJS() : data;
    }
});

module.exports = ChartsStore;

<|endoftext|>


<commit_before>var subarg = require('subarg');

function Prorogram(opts) {

    Object.defineProperty(this, 'opts', {
        enumerable: false,
        value: opts || {}
    });

    this.options = {};
    this.commands = {};

    this.raw_arguments = {};
    this.parsed = {};

    this.selected = {};
}

// Prototype Setter/Getter Properties

Object.defineProperty(Prorogram.prototype, "command_name", {
    enumerable: true,
    get: function() {
        return this.opts.command_name;
    }
});

Object.defineProperty(Prorogram.prototype, "parent_command", {
    enumerable: true,
    get: function() {
        return this.opts.parent_command;
    }
});

Object.defineProperty(Prorogram.prototype, "action", {
    enumerable: true,
    get: function() {
        return this.opts.action;
    },
    set: function(fn) {
        this.opts.action = fn;
    }
});

Object.defineProperty(Prorogram.prototype, "error", {
    enumerable: true,
    get: function() {
        return this.opts.error;
    },
    set: function(fn) {
        this.opts.error = fn;
    }
});

Object.defineProperty(Prorogram.prototype, "required", {
    enumerable: true,
    get: function() {
        return this.opts.required;
    },
    set: function(reqd) {
        this.opts.required = reqd;
    }
});

Object.defineProperty(Prorogram.prototype, "description", {
    enumerable: true,
    get: function() {
        return this.opts.description;
    },
    set: function(desc) {
        this.opts.description = desc;
    }
});

// Main API Methods

Prorogram.prototype.create = function create(opts) {
    return new Prorogram(opts);
};

Prorogram.prototype.option = function(flag_name, opts, fn) {

    opts = mergeOpts(opts, fn);

    if (typeof flag_name !== 'string') {
        throw new Error("Missing Option Flag Name");
    }

    opts.flag_name = flag_name = clearLeadingDashes(flag_name);
    opts.shortcut = createShortcut(opts.shortcut, flag_name, this.options);
    opts.parent_command = this;

    this.options[flag_name] = opts;

    if (typeof opts.added === 'function') {
        opts.added(this, this.options[flag_name]);
    }

    return this;
};

Prorogram.prototype.command = function(command_name, opts, fn) {

    opts = mergeOpts(opts, fn);

    if (typeof command_name !== 'string') {
        throw new Error("Missing Command Name");
    }

    opts.command_name = command_name;
    opts.parent_command = this;

    this.commands[command_name] = new Prorogram(opts);

    return this.commands[command_name];
};

Prorogram.prototype.parse = function(argv) {

    if (!Array.isArray(argv) && typeof argv === 'object') {
        argv = this.rebuildArgArray(argv);
    }

    this.parsed = subarg(argv);
    this.raw_arguments = {
        _: argv
    };

    if (!evaluateCommand(this, this.parsed, argv, this.commands)) {
        evaluateFlags(this, this.parsed, this.options);
    }
};

// Core Functional Evaluation Methods

function evaluateFlags(program, args, options) {

    var value = null,
        err = null,
        flag = null;

    for (var flag_name in options) {

        flag = options[flag_name];
        value = args[flag_name] || args[flag.shortcut];

        if (value) {
            if (flag.required && value === true) {
                err = new Error('Required argument <' + flag.required + '> missing for flag: \'--' + flag_name + '\'');
            } else {
                err = null;
            }

            program.selected[flag_name] = value;

            if (err !== null && typeof flag.error === 'function') {
                flag.error(err, remaining_args, program);
            } else if (typeof flag.action === 'function') {
                flag.action(err, value, program);
            }
        }
    }
}

function processUniversalCommand(global_command, program) {

    var recursive = global_command.opts.recursive,
        global_options = global_command.options,
        global_commands = global_command.commands,
        has_action = (global_command.action),
        has_error = (global_command.error);

    for (var command_name in program.commands) {
        addToCommand(program.commands[command_name],
            global_command,
            global_options,
            global_commands,
            has_action,
            has_error,
            recursive);
    }

    if (global_command.opts.includeRoot) {
        addToCommand(program,
            global_command,
            global_options,
            global_commands,
            has_action,
            has_error,
            false);
    }
}

function addToCommand(command, global_command, global_options, global_commands, recursive) {

    for (var global_flag_name in global_options) {
        if (command.options[global_flag_name] === undefined) {
            command.options[global_flag_name] = global_options[global_flag_name];
        }
    }

    for (var global_command_name in global_commands) {

        if (recursive) {
            addToCommand(command.commands[global_command_name],
                global_command,
                global_options,
                global_commands,
                has_action,
                has_error,
                recursive);
        }

        if (!command.action && global_command.action) {
            command.action = global_command.action;
        }

        if (!command.error && global_command.error) {
            command.error = global_command.error;
        }

        if (command.commands[global_command_name] === undefined) {
            command.commands[global_command_name] = global_commands[global_command_name];
        }
    }
}

function evaluateCommand(program, parse_args, argv, commands) {

    var possible_commands = parse_args._,
        command,
        possible,
        remaining_args,
        err;

    if (program.commands['*']) {
        processUniversalCommand(program.commands['*'], program);
    }

    for (var i = 0; i < possible_commands.length; i++) {

        possible = possible_commands[i];

        for (var command_name in commands) {

            if (possible === command_name || possible === commands[command_name].alias) {

                command = commands[command_name];

                if (command.required && possible_commands[i + 1] === undefined) {
                    err = new Error('Required argument <' + command.required + '> missing for command: \'' + command_name + '\'');
                } else {
                    err = null;
                }

                remaining_args = argv.slice(i);
                command.parse(remaining_args);

                if (err !== null && typeof command.error === 'function') {
                    command.error(err, remaining_args, command);
                } else if (typeof command.action === 'function') {
                    command.action(err, remaining_args, command);
                }

                return true;
            }
        }
    }
    return false;
}

// Extra Sauce API Methods

Prorogram.prototype.rebuildArgString = function(parsed_args) {
    return unparse(parsed_args).command_string;
};

Prorogram.prototype.rebuildArgArray = function(parsed_args) {
    return unparse(parsed_args);
};

function createShortcut(shortcut, flag_name, options) {

    var exists;

    if (!shortcut) {
        for (var i = 0; i < flag_name.length; i++) {
            exists = false;
            shortcut = flag_name[i];
            for (var flag in options) {
                if (options[flag].shortcut === shortcut) {
                    exists = true;
                    break;
                }
            }
            if (!exists) {
                break;
            }
        }
    } else {
        shortcut = clearLeadingDashes(shortcut);
    }
    return shortcut;
}

function clearLeadingDashes(str) {
    for (var i = 0; i < str.length; i++) {
        if (str[i] !== '-')
            break;
    }
    return str.slice(i);
}

function mergeOpts(opts, fn) {
    opts = opts || {};

    if (typeof opts === 'function' && fn === undefined) {
        fn = opts;
        opts = {};
    }
    if (typeof fn === 'function' && typeof opts.action !== 'function') {
        opts.action = fn;
    }

    return opts;
}

module.exports = exports = new Prorogram({
    root: true
});
<commit_msg>logging global command<commit_after>var subarg = require('subarg');

function Prorogram(opts) {

    Object.defineProperty(this, 'opts', {
        enumerable: false,
        value: opts || {}
    });

    this.options = {};
    this.commands = {};

    this.raw_arguments = {};
    this.parsed = {};

    this.selected = {};
}

// Prototype Setter/Getter Properties

Object.defineProperty(Prorogram.prototype, "command_name", {
    enumerable: true,
    get: function() {
        return this.opts.command_name;
    }
});

Object.defineProperty(Prorogram.prototype, "parent_command", {
    enumerable: true,
    get: function() {
        return this.opts.parent_command;
    }
});

Object.defineProperty(Prorogram.prototype, "action", {
    enumerable: true,
    get: function() {
        return this.opts.action;
    },
    set: function(fn) {
        this.opts.action = fn;
    }
});

Object.defineProperty(Prorogram.prototype, "error", {
    enumerable: true,
    get: function() {
        return this.opts.error;
    },
    set: function(fn) {
        this.opts.error = fn;
    }
});

Object.defineProperty(Prorogram.prototype, "required", {
    enumerable: true,
    get: function() {
        return this.opts.required;
    },
    set: function(reqd) {
        this.opts.required = reqd;
    }
});

Object.defineProperty(Prorogram.prototype, "description", {
    enumerable: true,
    get: function() {
        return this.opts.description;
    },
    set: function(desc) {
        this.opts.description = desc;
    }
});

// Main API Methods

Prorogram.prototype.create = function create(opts) {
    return new Prorogram(opts);
};

Prorogram.prototype.option = function(flag_name, opts, fn) {

    opts = mergeOpts(opts, fn);

    if (typeof flag_name !== 'string') {
        throw new Error("Missing Option Flag Name");
    }

    opts.flag_name = flag_name = clearLeadingDashes(flag_name);
    opts.shortcut = createShortcut(opts.shortcut, flag_name, this.options);
    opts.parent_command = this;

    this.options[flag_name] = opts;

    if (typeof opts.added === 'function') {
        opts.added(this, this.options[flag_name]);
    }

    return this;
};

Prorogram.prototype.command = function(command_name, opts, fn) {

    opts = mergeOpts(opts, fn);

    if (typeof command_name !== 'string') {
        throw new Error("Missing Command Name");
    }

    opts.command_name = command_name;
    opts.parent_command = this;

    this.commands[command_name] = new Prorogram(opts);

    return this.commands[command_name];
};

Prorogram.prototype.parse = function(argv) {

    if (!Array.isArray(argv) && typeof argv === 'object') {
        argv = this.rebuildArgArray(argv);
    }

    this.parsed = subarg(argv);
    this.raw_arguments = {
        _: argv
    };

    if (!evaluateCommand(this, this.parsed, argv, this.commands)) {
        evaluateFlags(this, this.parsed, this.options);
    }
};

// Core Functional Evaluation Methods

function evaluateFlags(program, args, options) {

    var value = null,
        err = null,
        flag = null;

    for (var flag_name in options) {

        flag = options[flag_name];
        value = args[flag_name] || args[flag.shortcut];

        if (value) {
            if (flag.required && value === true) {
                err = new Error('Required argument <' + flag.required + '> missing for flag: \'--' + flag_name + '\'');
            } else {
                err = null;
            }

            program.selected[flag_name] = value;

            if (err !== null && typeof flag.error === 'function') {
                flag.error(err, remaining_args, program);
            } else if (typeof flag.action === 'function') {
                flag.action(err, value, program);
            }
        }
    }
}

function processUniversalCommand(global_command, program) {

    var recursive = global_command.opts.recursive,
        global_options = global_command.options,
        global_commands = global_command.commands,
        has_action = (global_command.action),
        has_error = (global_command.error);

    console.log("GLOBAL COMMAND", global_command);

    for (var command_name in program.commands) {
        addToCommand(program.commands[command_name],
            global_command,
            global_options,
            global_commands,
            has_action,
            has_error,
            recursive);
    }

    if (global_command.opts.includeRoot) {
        addToCommand(program,
            global_command,
            global_options,
            global_commands,
            has_action,
            has_error,
            false);
    }
}

function addToCommand(command, global_command, global_options, global_commands, recursive) {

    for (var global_flag_name in global_options) {
        if (command.options[global_flag_name] === undefined) {
            command.options[global_flag_name] = global_options[global_flag_name];
        }
    }

    for (var global_command_name in global_commands) {

        if (recursive) {
            addToCommand(command.commands[global_command_name],
                global_command,
                global_options,
                global_commands,
                has_action,
                has_error,
                recursive);
        }

        if (!command.action && global_command.action) {
            command.action = global_command.action;
        }

        if (!command.error && global_command.error) {
            command.error = global_command.error;
        }

        if (command.commands[global_command_name] === undefined) {
            command.commands[global_command_name] = global_commands[global_command_name];
        }
    }
}

function evaluateCommand(program, parse_args, argv, commands) {

    var possible_commands = parse_args._,
        command,
        possible,
        remaining_args,
        err;

    if (program.commands['*']) {
        processUniversalCommand(program.commands['*'], program);
    }

    for (var i = 0; i < possible_commands.length; i++) {

        possible = possible_commands[i];

        for (var command_name in commands) {

            if (possible === command_name || possible === commands[command_name].alias) {

                command = commands[command_name];

                if (command.required && possible_commands[i + 1] === undefined) {
                    err = new Error('Required argument <' + command.required + '> missing for command: \'' + command_name + '\'');
                } else {
                    err = null;
                }

                remaining_args = argv.slice(i);
                command.parse(remaining_args);

                if (err !== null && typeof command.error === 'function') {
                    command.error(err, remaining_args, command);
                } else if (typeof command.action === 'function') {
                    command.action(err, remaining_args, command);
                }

                return true;
            }
        }
    }
    return false;
}

// Extra Sauce API Methods

Prorogram.prototype.rebuildArgString = function(parsed_args) {
    return unparse(parsed_args).command_string;
};

Prorogram.prototype.rebuildArgArray = function(parsed_args) {
    return unparse(parsed_args);
};

function createShortcut(shortcut, flag_name, options) {

    var exists;

    if (!shortcut) {
        for (var i = 0; i < flag_name.length; i++) {
            exists = false;
            shortcut = flag_name[i];
            for (var flag in options) {
                if (options[flag].shortcut === shortcut) {
                    exists = true;
                    break;
                }
            }
            if (!exists) {
                break;
            }
        }
    } else {
        shortcut = clearLeadingDashes(shortcut);
    }
    return shortcut;
}

function clearLeadingDashes(str) {
    for (var i = 0; i < str.length; i++) {
        if (str[i] !== '-')
            break;
    }
    return str.slice(i);
}

function mergeOpts(opts, fn) {
    opts = opts || {};

    if (typeof opts === 'function' && fn === undefined) {
        fn = opts;
        opts = {};
    }
    if (typeof fn === 'function' && typeof opts.action !== 'function') {
        opts.action = fn;
    }

    return opts;
}

module.exports = exports = new Prorogram({
    root: true
});
<|endoftext|>