<commit_before>/*
 * The MIT License
 *
 * Copyright 2017 OnCore Consulting LLC, 2017
 *
 * 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.
 */
/*
 * Your dashboard ViewModel code goes here
 */
define(['ojs/ojcore', 'knockout', 'jquery', 'common/SecurityUtils'],
        function (oj, ko, $) {

            function DashboardViewModel() {
                var self = this;

                self.router = oj.Router.rootInstance;

                /* toggle button variables */

                self.ordersByQuarterCollection = null;
                self.stackValue = ko.observable('on');
                self.stackLabelValue = ko.observable('on');
                self.orientationValue = ko.observable('vertical');
                self.labelPosition = ko.observable('auto');

                self.barSeriesValue = ko.observableArray();
                self.barGroupsValue = ko.observableArray();

                /* toggle buttons*/
                self.stackOptions = [
                    {id: 'unstacked', label: 'unstacked', value: 'off', icon: 'oj-icon demo-bar-unstack'},
                    {id: 'stacked', label: 'stacked', value: 'on', icon: 'oj-icon demo-bar-stack'}
                ];
                self.stackLabelOptions = [
                    {id: 'labelOff', label: 'off', value: 'off'},
                    {id: 'labelOn', label: 'on', value: 'on'}
                ];
                self.orientationOptions = [
                    {id: 'vertical', label: 'vertical', value: 'vertical', icon: 'oj-icon demo-bar-vert'},
                    {id: 'horizontal', label: 'horizontal', value: 'horizontal', icon: 'oj-icon demo-bar-horiz'}
                ];
                self.labelPositionOptions = ko.observableArray([
                    {id: 'auto', label: 'auto', value: 'auto'},
                    {id: 'center', label: 'center', value: 'center'},
                    {id: 'insideBarEdge', label: 'insideBarEdge', value: 'insideBarEdge'},
                    {id: 'none', label: 'none', value: 'none'}
                ]);

                /* Active orders data */
                self.threeDValue = ko.observable('off');
                self.dataLabelPositionValue = ko.observable('auto');

                /* chart data */

                self.pieSeriesValue = ko.observableArray();
                self.pieSeriesCollection = null;

//                /* Total Sold By Month */
//                var expenseSeries = [{name: "Desktops", items: [400, 0, 56.32, 32.33, 0]},
//                    {name: "Laptops", items: [100.43, 800.32, 0, 0, 323.32]},
//                    {name: "Monitors", items: [80, 80, 80, 80, 80]}];
//
//                var expenseGroups = ["1/2016", "2/2016", "3/2016", "4/2016", "5/2016"];
//
//
//                this.expenseSeriesValue = ko.observableArray(expenseSeries);
//                this.expenseGroupsValue = ko.observableArray(expenseGroups);
//
//
//
//
//                /* Orders by Agency */
//                var ptoSeries = [{name: "DOJ", items: [16, 0, 8, 12, 0]},
//                    {name: "FTB", items: [0, 0, 0, 0, 8]},
//                    {name: "DTS", items: [0, 8, 0, 0, 0]},
//                    {name: "BOE", items: [16, 0, 8, 8, 8]}];
//
//                var ptoGroups = ["1/2016", "2/2016", "3/2016", "4/2016", "5/2016"];
//
//
//                this.ptoSeriesValue = ko.observableArray(ptoSeries);
//                this.ptoGroupsValue = ko.observableArray(ptoGroups);
//
//
//
//                var profileArray = [{Key: 'Name', Value: 'Ricky Bobby'},
//                    {Key: 'Phone', Value: '916.392.3233'},
//                    {Key: 'Address', Value: '3923 Racecar Ct Folsom, CA 95630'},
//                    {Key: 'Hire Date', Value: '04/01/2016'},
//                    {Key: 'Title', Value: 'Driver'}];
//                self.datasource = new oj.ArrayTableDataSource(profileArray, {idAttribute: 'Key'});

                // Below are a subset of the ViewModel methods invoked by the ojModule binding
                // Please reference the ojModule jsDoc for additionaly available methods.

                /**
                 * Optional ViewModel method invoked when this ViewModel is about to be
                 * used for the View transition.  The application can put data fetch logic
                 * here that can return a Promise which will delay the handleAttached function
                 * call below until the Promise is resolved.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 * @return {Promise|undefined} - If the callback returns a Promise, the next phase (attaching DOM) will be delayed until
                 * the promise is resolved
                 */
                self.handleActivated = function (info) {

                    if (!SecurityUtils.isAuthenticated()) {
                        return self.router.go('welcome');
                    }

                    var serviceEndPoints = new ServiceEndPoints();
                    var serviceURL = serviceEndPoints.getEndPoint('fetchOrdersByQuarter');

                    self.ordersByQuarterCollection = new oj.Collection();

                    var dashModel = oj.Model.extend({
                        urlRoot: serviceURL,
                        parse: parseOrderByQuarter
                    });

                    var dash = new dashModel();

                    self.DashCollection = oj.Collection.extend({
                        url: serviceURL,
                        model: dash
                    });

                    dash.fetch({
                        success: function () {

                            // load data for Total Orders by Quarter Chart

                            var barGroups = ["2014", "2015", "2016", "2017"];

                            self.barSeriesValue(self.ordersByQuarterCollection.models[0].attributes.ordersByQuarterDataList);
                            self.barGroupsValue(barGroups);

                        },
                        error: function (jqXHR, textStatus, errorThrown) {
                            console.log("Error occurred when populating the dashboard" + errorThrown);

                            return false;
                        }
                    });

                    //fetchOrderStatusSummary

                    /* chart data */

                    serviceEndPoints = new ServiceEndPoints();
                    serviceURL = serviceEndPoints.getEndPoint('fetchOrderStatusSummary');

                    self.pieSeriesCollection = new oj.Collection();

                    var pieModel = oj.Model.extend({
                        urlRoot: serviceURL,
                        parse: parsePieData
                    });

                    var pie = new pieModel();

                    self.PieCollection = oj.Collection.extend({
                        url: serviceURL,
                        model: pie
                    });

                    pie.fetch({
                        success: function () {
                            self.pieSeriesValue(self.pieSeriesCollection.models[0].attributes.items);

//                            var pieSeries = [{name: "Submitted", items: [42]},
//                    {name: "Processing", items: [55]},
//                    {name: "Shipped", items: [36]},
//                    {name: "Cancelled", items: [10]}];

              //  self.pieSeriesValue(pieSeries);
                        },
                        error: function (jqXHR, textStatus, errorThrown) {
                            console.log("Error occurred when populating the dashboard" + errorThrown);

                            return false;
                        }
                    });

                };

                /**
                 * Optional ViewModel method invoked after the View is inserted into the
                 * document DOM.  The application can put logic that requires the DOM being
                 * attached here.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 * @param {boolean} info.fromCache - A boolean indicating whether the module was retrieved from cache.
                 */
                self.handleAttached = function (info) {
                    // Implement if needed
                };

                /**
                 * Optional ViewModel method invoked after the bindings are applied on this View.
                 * If the current View is retrieved from cache, the bindings will not be re-applied
                 * and this callback will not be invoked.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 */
                self.handleBindingsApplied = function (info) {
                    // Implement if needed
                };

                /*
                 * Optional ViewModel method invoked after the View is removed from the
                 * document DOM.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 * @param {Array} info.cachedNodes - An Array containing cached nodes for the View if the cache is enabled.
                 */
                self.handleDetached = function (info) {
                    // Implement if needed
                };

                /* Active orders by month data */

                var parseOrderByQuarter = function (response)
                {
                    self.ordersByQuarterCollection.push(response);
                };

                var parsePieData = function (response)
                {
                    self.pieSeriesCollection.push(response);
                };

                self.labelPositionChange = function (event, ui) {
                    var seriesInfo = ko.toJS(self.barSeriesValue);
                    for (var i = 0; i < seriesInfo.length; i++) {
                        for (var j = 0; j < seriesInfo[i].items.length; j++) {
                            seriesInfo[i].items[j].labelPosition = ui.value;
                        }
                    }
                    self.barSeriesValue(seriesInfo);
                    return true;
                };
                self.stackLValueChange = function (event, ui) {
                    var isOn = true;
                    if (ui.value == "on") {
                        isOn = false;
                        self.labelPositionOptions([
                            {id: 'auto', label: 'auto', value: 'auto'},
                            {id: 'center', label: 'center', value: 'center'},
                            {id: 'insideBarEdge', label: 'insideBarEdge', value: 'insideBarEdge'},
                            {id: 'none', label: 'none', value: 'none'}
                        ]);
                    } else {
                        self.labelPositionOptions([
                            {id: 'auto', label: 'auto', value: 'auto'},
                            {id: 'center', label: 'center', value: 'center'},
                            {id: 'insideBarEdge', label: 'insideBarEdge', value: 'insideBarEdge'},
                            {id: 'outsideBarEdge', label: 'outsideBarEdge', value: 'outsideBarEdge'},
                            {id: 'none', label: 'none', value: 'none'}
                        ]);
                    }
                    $("#radioButtonset4").ojButtonset({disabled: isOn});
                };

                /* toggle buttons*/
                self.threeDOptions = [
                    {id: '2D', label: '2D', value: 'off', icon: 'oj-icon demo-2d'},
                    {id: '3D', label: '3D', value: 'on', icon: 'oj-icon demo-3d'}
                ];
                self.threeDOptions = [
                    {id: '2D', label: '2D', value: 'off', icon: 'oj-icon demo-2d'},
                    {id: '3D', label: '3D', value: 'on', icon: 'oj-icon demo-3d'}
                ];
                self.threeDValueChange = function (event, data) {
                    self.threeDValue(data.value);
                    return true;
                };

            }

            return new DashboardViewModel();
        }
);

<commit_msg>[#140095601] cleaned up code, moved initialization of variables into the proper method<commit_after>/*
 * The MIT License
 *
 * Copyright 2017 OnCore Consulting LLC, 2017
 *
 * 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.
 */
/*
 * Your dashboard ViewModel code goes here
 */
define(['ojs/ojcore', 'knockout', 'jquery', 'common/SecurityUtils'],
        function (oj, ko, $) {

            function DashboardViewModel() {
                var self = this;

                self.router = oj.Router.rootInstance;

                /* toggle button variables */

                self.ordersByQuarterCollection = null;
                self.stackValue = ko.observable();
                self.stackLabelValue = ko.observable();
                self.orientationValue = ko.observable();
                self.labelPosition = ko.observable();
                self.barSeriesValue = ko.observableArray();
                self.barGroupsValue = ko.observableArray();
                /* pie series data */
                self.threeDValue = ko.observable();
                self.dataLabelPositionValue = ko.observable();
                self.pieSeriesValue = ko.observableArray();
                self.pieSeriesCollection = null;

                self.stackOptions = [
                    {id: 'unstacked', label: 'unstacked', value: 'off', icon: 'oj-icon demo-bar-unstack'},
                    {id: 'stacked', label: 'stacked', value: 'on', icon: 'oj-icon demo-bar-stack'}
                ];

                self.stackLabelOptions = [
                    {id: 'labelOff', label: 'off', value: 'off'},
                    {id: 'labelOn', label: 'on', value: 'on'}
                ];

                self.orientationOptions = [
                    {id: 'vertical', label: 'vertical', value: 'vertical', icon: 'oj-icon demo-bar-vert'},
                    {id: 'horizontal', label: 'horizontal', value: 'horizontal', icon: 'oj-icon demo-bar-horiz'}
                ];

                self.labelPositionOptions = ko.observableArray([
                    {id: 'auto', label: 'auto', value: 'auto'},
                    {id: 'center', label: 'center', value: 'center'},
                    {id: 'insideBarEdge', label: 'insideBarEdge', value: 'insideBarEdge'},
                    {id: 'none', label: 'none', value: 'none'}
                ]);

                self.threeDOptions = [
                    {id: '2D', label: '2D', value: 'off', icon: 'oj-icon demo-2d'},
                    {id: '3D', label: '3D', value: 'on', icon: 'oj-icon demo-3d'}
                ];

                self.threeDOptions = [
                    {id: '2D', label: '2D', value: 'off', icon: 'oj-icon demo-2d'},
                    {id: '3D', label: '3D', value: 'on', icon: 'oj-icon demo-3d'}
                ];

                /**
                 * Optional ViewModel method invoked when this ViewModel is about to be
                 * used for the View transition.  The application can put data fetch logic
                 * here that can return a Promise which will delay the handleAttached function
                 * call below until the Promise is resolved.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 * @return {Promise|undefined} - If the callback returns a Promise, the next phase (attaching DOM) will be delayed until
                 * the promise is resolved
                 */
                self.handleActivated = function (info) {

                    if (!SecurityUtils.isAuthenticated()) {
                        return self.router.go('welcome');
                    }

                    self.ordersByQuarterCollection = null;
                    self.stackValue('on');
                    self.stackLabelValue('on');
                    self.orientationValue('vertical');
                    self.labelPosition('auto');
                    self.barSeriesValue = ko.observableArray();
                    self.barGroupsValue = ko.observableArray();
                    self.threeDValue('off');
                    self.dataLabelPositionValue('auto');
                    self.pieSeriesValue = ko.observableArray();
                    self.pieSeriesCollection = null;

                    var serviceEndPoints = new ServiceEndPoints();
                    var serviceURL = serviceEndPoints.getEndPoint('fetchOrdersByQuarter');

                    self.ordersByQuarterCollection = new oj.Collection();

                    var dashModel = oj.Model.extend({
                        urlRoot: serviceURL,
                        parse: parseOrderByQuarter
                    });

                    var dash = new dashModel();

                    self.DashCollection = oj.Collection.extend({
                        url: serviceURL,
                        model: dash
                    });

                    dash.fetch({
                        success: function () {

                            // load data for Total Orders by Quarter Chart

                            var barGroups = ["2014", "2015", "2016", "2017"];

                            self.barSeriesValue(self.ordersByQuarterCollection.models[0].attributes.ordersByQuarterDataList);
                            self.barGroupsValue(barGroups);

                        },
                        error: function (jqXHR, textStatus, errorThrown) {
                            console.log("Error occurred when populating the dashboard" + errorThrown);

                            return false;
                        }
                    });

                    serviceEndPoints = new ServiceEndPoints();
                    serviceURL = serviceEndPoints.getEndPoint('fetchOrderStatusSummary');

                    self.pieSeriesCollection = new oj.Collection();

                    var pieModel = oj.Model.extend({
                        urlRoot: serviceURL,
                        parse: parsePieData
                    });

                    var pie = new pieModel();

                    self.PieCollection = oj.Collection.extend({
                        url: serviceURL,
                        model: pie
                    });

                    pie.fetch({
                        success: function () {
                            self.pieSeriesValue(self.pieSeriesCollection.models[0].attributes.items);
                        },
                        error: function (jqXHR, textStatus, errorThrown) {
                            console.log("Error occurred when populating the dashboard" + errorThrown);

                            return false;
                        }
                    });

                };

                /**
                 * Optional ViewModel method invoked after the View is inserted into the
                 * document DOM.  The application can put logic that requires the DOM being
                 * attached here.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 * @param {boolean} info.fromCache - A boolean indicating whether the module was retrieved from cache.
                 */
                self.handleAttached = function (info) {
                    // Implement if needed
                };

                /**
                 * Optional ViewModel method invoked after the bindings are applied on this View.
                 * If the current View is retrieved from cache, the bindings will not be re-applied
                 * and this callback will not be invoked.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 */
                self.handleBindingsApplied = function (info) {
                    // Implement if needed
                };

                /*
                 * Optional ViewModel method invoked after the View is removed from the
                 * document DOM.
                 * @param {Object} info - An object with the following key-value pairs:
                 * @param {Node} info.element - DOM element or where the binding is attached. This may be a 'virtual' element (comment node).
                 * @param {Function} info.valueAccessor - The binding's value accessor.
                 * @param {Array} info.cachedNodes - An Array containing cached nodes for the View if the cache is enabled.
                 */
                self.handleDetached = function (info) {
                    // Implement if needed
                };

                /**
                 * Parse data returned from REST call
                 *
                 * @param {type} response
                 * @returns {undefined}
                 */
                var parseOrderByQuarter = function (response)
                {
                    self.ordersByQuarterCollection.push(response);
                };

                /**
                 * Parse data returned from REST call
                 *
                 * @param {type} response
                 * @returns {undefined}
                 */
                var parsePieData = function (response)
                {
                    self.pieSeriesCollection.push(response);
                };

                /**
                 * Adjusts position of labels on bar chart when
                 * the chart alignment and format changes.
                 *
                 * @param {type} event
                 * @param {type} ui
                 * @returns {Boolean}
                 */
                self.labelPositionChange = function (event, ui) {
                    var seriesInfo = ko.toJS(self.barSeriesValue);
                    for (var i = 0; i < seriesInfo.length; i++) {
                        for (var j = 0; j < seriesInfo[i].items.length; j++) {
                            seriesInfo[i].items[j].labelPosition = ui.value;
                        }
                    }
                    self.barSeriesValue(seriesInfo);
                    return true;
                };

                /**
                 * Adjusts the icon, text, value, labels etc. for the
                 * for the bar chart when in stacked view
                 *
                 * @param {type} event
                 * @param {type} ui
                 * @returns {undefined}
                 */
                self.stackLValueChange = function (event, ui) {
                    var isOn = true;
                    if (ui.value == "on") {
                        isOn = false;
                        self.labelPositionOptions([
                            {id: 'auto', label: 'auto', value: 'auto'},
                            {id: 'center', label: 'center', value: 'center'},
                            {id: 'insideBarEdge', label: 'insideBarEdge', value: 'insideBarEdge'},
                            {id: 'none', label: 'none', value: 'none'}
                        ]);
                    } else {
                        self.labelPositionOptions([
                            {id: 'auto', label: 'auto', value: 'auto'},
                            {id: 'center', label: 'center', value: 'center'},
                            {id: 'insideBarEdge', label: 'insideBarEdge', value: 'insideBarEdge'},
                            {id: 'outsideBarEdge', label: 'outsideBarEdge', value: 'outsideBarEdge'},
                            {id: 'none', label: 'none', value: 'none'}
                        ]);
                    }
                    $("#radioButtonset4").ojButtonset({disabled: isOn});
                };

                /**
                 * Adjusts the pie chart format from 2D to 3D and
                 * vice versa
                 *
                 * @param {type} event
                 * @param {type} data
                 * @returns {Boolean}
                 */
                self.threeDValueChange = function (event, data) {
                    self.threeDValue(data.value);
                    return true;
                };

            }

            return new DashboardViewModel();
        }
);

<|endoftext|>


<commit_before>let floatQueue = [];
let floatData = {};
let floatTimer;
let steamListingInfo = {};

// retrieve g_rgListingInfo from page script
window.addEventListener('message', (e) => {
    if (e.data.type == 'listingInfo') {
        steamListingInfo = e.data.listingInfo;
    }
});

const retrieveListingInfoFromPage = function(listingId) {
    if (listingId != null && (listingId in steamListingInfo)) {
        return Promise.resolve(steamListingInfo[listingId]);
    }

    // Reset, since this is a new page
    steamListingInfo = {};

    window.postMessage({
        type: 'requestListingInfo'
    }, '*');

    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (Object.keys(steamListingInfo).length === 0) reject();
            else resolve((listingId != null) ? steamListingInfo[listingId] : steamListingInfo);
        }, 10);
    });
};

const getFloatData = function(listingId, inspectLink) {
    if (listingId in floatData) {
        return Promise.resolve({ iteminfo: floatData[listingId] });
    }

    return fetch(`https://api.csgofloat.com:1738/?url=${inspectLink}`)
    .then((response) => {
        if (response.ok) return response.json();
        return response.json().then((err) => { throw err; });
    });
};

const showFloat = function(listingId) {
    let itemInfo = floatData[listingId];

    if (itemInfo) setFloatText(listingId, `Float: ${itemInfo.floatvalue}<br>Paint Seed: ${itemInfo.paintseed}`, true);
};

const setFloatText = function(listingId, text, removeButton) {
    let floatDiv = document.querySelector(`#item_${listingId}_floatdiv`);

    if (floatDiv) {
        if (removeButton) {
            // Remove the "get float" button
            let floatButton = floatDiv.querySelector('.floatbutton');
            if (floatButton) { floatDiv.removeChild(floatButton); }
        }

        // Show the text to the user
        let msgdiv = floatDiv.querySelector('.floatmessage');
        msgdiv.innerHTML = text;
    }
};

const processFloatQueue = function() {
    if (floatQueue.length === 0) { return setTimeout(processFloatQueue, 100); }

    let lastItem = floatQueue.shift();

    let floatDiv = document.querySelector(`#item_${lastItem.listingId}_floatdiv`);

    if (!floatDiv) {
        // they have switched pages since initiating the request, so continue
        processFloatQueue();
        return;
    }

    let buttonText = floatDiv.querySelector('span');

    if (buttonText) { buttonText.innerText = 'Fetching'; }

    getFloatData(lastItem.listingId, lastItem.inspectLink)
    .then((data) => {
        floatData[lastItem.listingId] = data.iteminfo;

        showFloat(lastItem.listingId);

        processFloatQueue();
    })
    .catch((err) => {
        // Reset the button text for this itemid
        if (buttonText) { buttonText.innerText = 'Get Float'; }

        // Change the message div for this item to the error
        if (floatDiv) {
            floatDiv.querySelector('.floatmessage').innerHTML = err.error || 'Unknown Error';
        }

        processFloatQueue();
    });
};

// Puts all of the available items on the page into the queue for float retrieval
const getAllFloats = function() {
    retrieveListingInfoFromPage()
    .then((steamListingData) => {
        // Get all current items on the page (in proper order)
        let listingRows = document.querySelectorAll('.market_listing_row.market_recent_listing_row');

        for (let row of listingRows) {
            let id = row.id.replace('listing_', '');

            let listingData = steamListingData[id];

            let inspectLink = listingData.asset.market_actions[0].link
            .replace('%listingid%', id)
            .replace('%assetid%', listingData.asset.id);

            floatQueue.push({ listingId: id, inspectLink: inspectLink });
        }
    },
    () => {
        // Try again
        getAllFloats();
    });
};

// Adds the "Get all floats" button
const addAllFloatButton = function() {
    let parentDiv = document.createElement('div');
    parentDiv.style.padding = '10px';
    parentDiv.style.marginTop = '10px';
    parentDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.2)';

    let allFloatButton = document.createElement('a');
    allFloatButton.id = 'allfloatbutton';
    allFloatButton.classList.add('btn_green_white_innerfade');
    allFloatButton.classList.add('btn_small');
    allFloatButton.addEventListener('click', getAllFloats);
    parentDiv.appendChild(allFloatButton);

    let allFloatSpan = document.createElement('span');
    allFloatSpan.innerText = 'Get All Floats';
    allFloatButton.appendChild(allFloatSpan);

    let githubLink = document.createElement('a');
    githubLink.style.marginLeft = '10px';
    githubLink.style.textDecoration = 'underline';
    githubLink.style.fontFamily = `'Motiva Sans', sans-serif`;
    githubLink.href = 'https://github.com/Step7750/CSGOFloat';
    githubLink.innerText = 'Powered by CSGOFloat';
    parentDiv.appendChild(githubLink);

    document.querySelector('#searchResultsTable').insertBefore(parentDiv, document.querySelector('#searchResultsRows'));
};

const getFloatButtonClicked = function(e) {
    let row = e.currentTarget.parentElement.parentElement.parentElement;
    let id = row.id.replace('listing_', '');

    retrieveListingInfoFromPage(id)
    .then((listingData) => {
        let inspectLink = listingData.asset.market_actions[0].link
        .replace('%listingid%', id)
        .replace('%assetid%', listingData.asset.id);

        floatQueue.push({ listingId: id, inspectLink: inspectLink });
    },
    () => {
        setFloatText(id, "Failed to obtain listing info, please try again");
    });
};

// If an item on the current page doesn't have the float div/buttons, this function adds it
const addButtons = function() {
    // Iterate through each item on the page
    let listingRows = document.querySelectorAll('.market_listing_row.market_recent_listing_row');

    for (let row of listingRows) {
        let id = row.id.replace('listing_', '');

        if (row.querySelector(`#item_${id}_floatdiv`)) { continue; }

        let listingNameElement = row.querySelector(`#listing_${id}_name`);

        let buttonDiv = document.createElement('div');
        buttonDiv.style.display = 'inline';
        buttonDiv.style.textAlign = 'left';
        buttonDiv.id = `item_${id}_floatdiv`;
        listingNameElement.parentElement.appendChild(buttonDiv);

        let getFloatButton = document.createElement('a');
        getFloatButton.classList.add('btn_green_white_innerfade');
        getFloatButton.classList.add('btn_small');
        getFloatButton.classList.add('floatbutton');
        getFloatButton.addEventListener('click', getFloatButtonClicked);
        buttonDiv.appendChild(getFloatButton);

        let buttonText = document.createElement('span');
        buttonText.innerText = 'Get Float';
        getFloatButton.appendChild(buttonText);

        let messageDiv = document.createElement('div');
        messageDiv.classList.add('floatmessage');
        buttonDiv.appendChild(messageDiv);

        // check if we already have the float for this item
        if (id in floatData) {
            showFloat(id);
        }
    }

    // Add show all button if it doesn't exist and we have valid items
    if (!document.querySelector('#allfloatbutton') && listingRows.length > 0) {
        addAllFloatButton();
    }
};

// register the message listener in the page scope
let script = document.createElement('script');
script.innerText = `
    window.addEventListener('message', (e) => {
        if (e.data.type == 'requestListingInfo') {
            window.postMessage({
                type: 'listingInfo',
                listingInfo: g_rgListingInfo
            }, '*');
        }
    });
`;
document.head.appendChild(script);

floatTimer = setInterval(() => { addButtons(); }, 500);

// start the queue processing loop
processFloatQueue();

const logStyle = 'background: #222; color: #fff;';
console.log('%c CSGOFloat Market Checker (v1.1.1) by Step7750 ', logStyle);
console.log('%c Changelog can be found here: https://github.com/Step7750/CSGOFloat-Extension ', logStyle);
<commit_msg>Double Quotes -> Single Quotes Styling<commit_after>let floatQueue = [];
let floatData = {};
let floatTimer;
let steamListingInfo = {};

// retrieve g_rgListingInfo from page script
window.addEventListener('message', (e) => {
    if (e.data.type == 'listingInfo') {
        steamListingInfo = e.data.listingInfo;
    }
});

const retrieveListingInfoFromPage = function(listingId) {
    if (listingId != null && (listingId in steamListingInfo)) {
        return Promise.resolve(steamListingInfo[listingId]);
    }

    // Reset, since this is a new page
    steamListingInfo = {};

    window.postMessage({
        type: 'requestListingInfo'
    }, '*');

    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (Object.keys(steamListingInfo).length === 0) reject();
            else resolve((listingId != null) ? steamListingInfo[listingId] : steamListingInfo);
        }, 10);
    });
};

const getFloatData = function(listingId, inspectLink) {
    if (listingId in floatData) {
        return Promise.resolve({ iteminfo: floatData[listingId] });
    }

    return fetch(`https://api.csgofloat.com:1738/?url=${inspectLink}`)
    .then((response) => {
        if (response.ok) return response.json();
        return response.json().then((err) => { throw err; });
    });
};

const showFloat = function(listingId) {
    let itemInfo = floatData[listingId];

    if (itemInfo) setFloatText(listingId, `Float: ${itemInfo.floatvalue}<br>Paint Seed: ${itemInfo.paintseed}`, true);
};

const setFloatText = function(listingId, text, removeButton) {
    let floatDiv = document.querySelector(`#item_${listingId}_floatdiv`);

    if (floatDiv) {
        if (removeButton) {
            // Remove the "get float" button
            let floatButton = floatDiv.querySelector('.floatbutton');
            if (floatButton) { floatDiv.removeChild(floatButton); }
        }

        // Show the text to the user
        let msgdiv = floatDiv.querySelector('.floatmessage');
        msgdiv.innerHTML = text;
    }
};

const processFloatQueue = function() {
    if (floatQueue.length === 0) { return setTimeout(processFloatQueue, 100); }

    let lastItem = floatQueue.shift();

    let floatDiv = document.querySelector(`#item_${lastItem.listingId}_floatdiv`);

    if (!floatDiv) {
        // they have switched pages since initiating the request, so continue
        processFloatQueue();
        return;
    }

    let buttonText = floatDiv.querySelector('span');

    if (buttonText) { buttonText.innerText = 'Fetching'; }

    getFloatData(lastItem.listingId, lastItem.inspectLink)
    .then((data) => {
        floatData[lastItem.listingId] = data.iteminfo;

        showFloat(lastItem.listingId);

        processFloatQueue();
    })
    .catch((err) => {
        // Reset the button text for this itemid
        if (buttonText) { buttonText.innerText = 'Get Float'; }

        // Change the message div for this item to the error
        if (floatDiv) {
            floatDiv.querySelector('.floatmessage').innerHTML = err.error || 'Unknown Error';
        }

        processFloatQueue();
    });
};

// Puts all of the available items on the page into the queue for float retrieval
const getAllFloats = function() {
    retrieveListingInfoFromPage()
    .then((steamListingData) => {
        // Get all current items on the page (in proper order)
        let listingRows = document.querySelectorAll('.market_listing_row.market_recent_listing_row');

        for (let row of listingRows) {
            let id = row.id.replace('listing_', '');

            let listingData = steamListingData[id];

            let inspectLink = listingData.asset.market_actions[0].link
            .replace('%listingid%', id)
            .replace('%assetid%', listingData.asset.id);

            floatQueue.push({ listingId: id, inspectLink: inspectLink });
        }
    },
    () => {
        // Try again
        getAllFloats();
    });
};

// Adds the "Get all floats" button
const addAllFloatButton = function() {
    let parentDiv = document.createElement('div');
    parentDiv.style.padding = '10px';
    parentDiv.style.marginTop = '10px';
    parentDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.2)';

    let allFloatButton = document.createElement('a');
    allFloatButton.id = 'allfloatbutton';
    allFloatButton.classList.add('btn_green_white_innerfade');
    allFloatButton.classList.add('btn_small');
    allFloatButton.addEventListener('click', getAllFloats);
    parentDiv.appendChild(allFloatButton);

    let allFloatSpan = document.createElement('span');
    allFloatSpan.innerText = 'Get All Floats';
    allFloatButton.appendChild(allFloatSpan);

    let githubLink = document.createElement('a');
    githubLink.style.marginLeft = '10px';
    githubLink.style.textDecoration = 'underline';
    githubLink.style.fontFamily = `'Motiva Sans', sans-serif`;
    githubLink.href = 'https://github.com/Step7750/CSGOFloat';
    githubLink.innerText = 'Powered by CSGOFloat';
    parentDiv.appendChild(githubLink);

    document.querySelector('#searchResultsTable').insertBefore(parentDiv, document.querySelector('#searchResultsRows'));
};

const getFloatButtonClicked = function(e) {
    let row = e.currentTarget.parentElement.parentElement.parentElement;
    let id = row.id.replace('listing_', '');

    retrieveListingInfoFromPage(id)
    .then((listingData) => {
        let inspectLink = listingData.asset.market_actions[0].link
        .replace('%listingid%', id)
        .replace('%assetid%', listingData.asset.id);

        floatQueue.push({ listingId: id, inspectLink: inspectLink });
    },
    () => {
        setFloatText(id, 'Failed to obtain listing info, please try again');
    });
};

// If an item on the current page doesn't have the float div/buttons, this function adds it
const addButtons = function() {
    // Iterate through each item on the page
    let listingRows = document.querySelectorAll('.market_listing_row.market_recent_listing_row');

    for (let row of listingRows) {
        let id = row.id.replace('listing_', '');

        if (row.querySelector(`#item_${id}_floatdiv`)) { continue; }

        let listingNameElement = row.querySelector(`#listing_${id}_name`);

        let buttonDiv = document.createElement('div');
        buttonDiv.style.display = 'inline';
        buttonDiv.style.textAlign = 'left';
        buttonDiv.id = `item_${id}_floatdiv`;
        listingNameElement.parentElement.appendChild(buttonDiv);

        let getFloatButton = document.createElement('a');
        getFloatButton.classList.add('btn_green_white_innerfade');
        getFloatButton.classList.add('btn_small');
        getFloatButton.classList.add('floatbutton');
        getFloatButton.addEventListener('click', getFloatButtonClicked);
        buttonDiv.appendChild(getFloatButton);

        let buttonText = document.createElement('span');
        buttonText.innerText = 'Get Float';
        getFloatButton.appendChild(buttonText);

        let messageDiv = document.createElement('div');
        messageDiv.classList.add('floatmessage');
        buttonDiv.appendChild(messageDiv);

        // check if we already have the float for this item
        if (id in floatData) {
            showFloat(id);
        }
    }

    // Add show all button if it doesn't exist and we have valid items
    if (!document.querySelector('#allfloatbutton') && listingRows.length > 0) {
        addAllFloatButton();
    }
};

// register the message listener in the page scope
let script = document.createElement('script');
script.innerText = `
    window.addEventListener('message', (e) => {
        if (e.data.type == 'requestListingInfo') {
            window.postMessage({
                type: 'listingInfo',
                listingInfo: g_rgListingInfo
            }, '*');
        }
    });
`;
document.head.appendChild(script);

floatTimer = setInterval(() => { addButtons(); }, 500);

// start the queue processing loop
processFloatQueue();

const logStyle = 'background: #222; color: #fff;';
console.log('%c CSGOFloat Market Checker (v1.1.1) by Step7750 ', logStyle);
console.log('%c Changelog can be found here: https://github.com/Step7750/CSGOFloat-Extension ', logStyle);
<|endoftext|>


<commit_before>// Window.prototype.devicePixelRatio
(function () {
	var element = document.createElement('x-zoom');
	element.style.cssText = 'clip:rect(0 0 0 0);display:block;font-size:1000px;position:absolute;width:1em';

	function updateDevicePixelRatio() {
		var
		hasBody = document.body,
		body = hasBody || document.documentElement.appendChild(document.createElement('body'));

		body.appendChild(element);

		var rect = element.getBoundingClientRect();

		window.devicePixelRatio = Math.round((rect.right - rect.left) / element.clientWidth * 1000) / 1000;

		body.removeChild(element);

		if (!hasBody) {
			document.documentElement.removeChild(body);
		}
	}

	window.attachEvent('onresize', updateDevicePixelRatio);

	document.attachEvent('onkeyup', updateDevicePixelRatio);

	updateDevicePixelRatio();
})();<commit_msg>Window.devicePixelRatio<commit_after>// Window.prototype.devicePixelRatio
(function () {
	var element = document.createElement('x-zoom');
	element.style.cssText = 'clip:rect(0 0 0 0);display:block;font-size:1000px;position:absolute;width:1em';

	function updateDevicePixelRatio() {
		var
		hasBody = document.body,
		body = hasBody || document.documentElement.appendChild(document.createElement('body'));

		body.appendChild(element);

		var rect = element.getBoundingClientRect();

		window.devicePixelRatio = Math.round((rect.right - rect.left) / element.clientWidth * 1000) / 1000;

		element.parentNode.removeChild(element)

		if (!hasBody) {
			document.documentElement.removeChild(body);
		}
	}

	window.attachEvent('onresize', updateDevicePixelRatio);

	document.attachEvent('onkeyup', updateDevicePixelRatio);

	updateDevicePixelRatio();
})();<|endoftext|>


<commit_before>'use strict';

angular.module('users').controller('AuthenticationController', ['$scope', '$http', '$location', 'Authentication',
	function($scope, $http, $location, Authentication) {
		$scope.authentication = Authentication;

		//If user is signed in then redirect back home
		if ($scope.authentication.user) $location.path('/');

		$scope.signup = function() {
			$http.post('/auth/signup', $scope.credentials).success(function(response) {
				//If successful we assign the response to the global user model
				$scope.authentication.user = response;

				//And redirect to the index page
				$location.path('/');
			}).error(function(response) {
				$scope.error = response.message;
			});
		};

		$scope.signin = function() {
			$http.post('/auth/signin', $scope.credentials).success(function(response) {
				//If successful we assign the response to the global user model
				$scope.authentication.user = response;

				//And redirect to the index page
				$location.path('/');
			}).error(function(response) {
				$scope.error = response.message;
			});
		};
	}
]);<commit_msg>Client-side Validation updates<commit_after>'use strict';

angular.module('users').controller('AuthenticationController', ['$scope', '$http', '$location', 'Authentication',
	function($scope, $http, $location, Authentication) {
		$scope.authentication = Authentication;

		//If user is signed in then redirect back home
		if ($scope.authentication.user) $location.path('/');

		$scope.signup = function(isValid) {
			if (isValid){
				$http.post('/auth/signup', $scope.credentials).success(function(response) {
					//If successful we assign the response to the global user model
					$scope.authentication.user = response;

					//And redirect to the index page
					$location.path('/');
				}).error(function(response) {
					$scope.error = response.message;
				});
			} else {
				$scope.submitted = true;
			}
		};

		$scope.signin = function() {
			$http.post('/auth/signin', $scope.credentials).success(function(response) {
				//If successful we assign the response to the global user model
				$scope.authentication.user = response;

				//And redirect to the index page
				$location.path('/');
			}).error(function(response) {
				$scope.error = response.message;
			});
		};
	}
]);
<|endoftext|>


<commit_before>var Browser = {
  get backButton() {
    delete this.backButton;
    return this.backButton =
      document.getElementById('browser-back-button');
  },

  get goButton() {
    delete this.goButton;
    return this.goButton =
      document.getElementById('browser-go-button');
  },

  get content() {
    delete this.content;
    return this.content = document.getElementById('browser-iframe');
  },

  get urlBar() {
    delete this.urlBar;
    return this.urlBar =
      document.getElementById('browser-url');
  },

  get iframe() {
    delete this.iframe;
    return document.getElementById('browser-iframe');
  },

  init: function() {
    this.goButton.addEventListener('click', (function goHandler(evt) {
      this.navigate(this.urlBar.value);
      evt.preventDefault();
    }).bind(this));

    this.iframe.addEventListener('load', (function loadedHandler(evt) {
      this.urlBar.classList.remove('loading');
    }).bind(this));

    this.backButton.addEventListener('click', (function backHandler(evt) {
      this.back();
    }).bind(this));

    this.navigate(this.urlBar.value);
  },

  navigate: function(url) {
    this.urlBar.value = url;
    this.content.setAttribute('src', url);
    this.urlBar.classList.add('loading');
  },

  back: function() {
    this.content.contentWindow.history.back();
  }
};

window.addEventListener('load', function browserOnLoad(evt) {
  window.removeEventListener('load', browserOnLoad);
  Browser.init();
});
<commit_msg>Browser mock history implementation while cross-origin restrictions still in place. Closes #115.<commit_after>var Browser = {

  get backButton() {
    delete this.backButton;
    return this.backButton =
      document.getElementById('browser-back-button');
  },

  get goButton() {
    delete this.goButton;
    return this.goButton =
      document.getElementById('browser-go-button');
  },

  get content() {
    delete this.content;
    return this.content = document.getElementById('browser-iframe');
  },

  get urlBar() {
    delete this.urlBar;
    return this.urlBar =
      document.getElementById('browser-url');
  },

  get iframe() {
    delete this.iframe;
    return document.getElementById('browser-iframe');
  },

  init: function() {
    this.goButton.addEventListener('click', (function goHandler(evt) {
      var url = this.urlBar.value;
      MockHistory.pushState(null, '', url);
      this.navigate(url);
      evt.preventDefault();
    }).bind(this));

    this.iframe.addEventListener('load', (function loadedHandler(evt) {
      this.urlBar.classList.remove('loading');
    }).bind(this));

    this.backButton.addEventListener('click', (function backHandler(evt) {
      MockHistory.back();
    }).bind(this));

    var url = this.urlBar.value;
    MockHistory.pushState(null, '', url);
    this.navigate(url);
  },

  navigate: function(url) {
    this.urlBar.value = url;
    this.content.setAttribute('src', url);
    this.urlBar.classList.add('loading');
  }
};

window.addEventListener('load', function browserOnLoad(evt) {
  window.removeEventListener('load', browserOnLoad);
  Browser.init();
});

var MockHistory = {
  history: [],
  historyIndex: -1,

  back: function() {
    if(this.backLength() < 1) {;
      return null;
    }
    Browser.navigate(this.history[--this.historyIndex]);
  },

  historyLength: function() {
    return this.history.length;
  },

  backLength: function() {
   if(this.history.length < 2)
     return 0;
   return this.historyIndex;
  },

  pushState: function(stateObj, title, url) {
    this.historyIndex = this.history.push(url) -1;
  }
}

<|endoftext|>


<commit_before>/* jshint node: true */
/* jshint esversion: 6 */

//************************************************************
//  lectureController.js                                    //
//  Active Learning 2110                                    //
//                                                          //
//  Created by Odell Mizrahi on 03/04/2017.                 //
//  Copyright © 2017 Odell Mizrahi. All rights reserved.    //
//                                                          //
//  Date        Name        Description                     //
//  -------     ---------   --------------                  //
//  03/02/05    O. Miz      Initial Design                  //
//                                                          //
//************************************************************
"use strict";

var Course = require('./../models/courseModel'),
    Lecture = require('./../models/lectureModel'),
    Question = require('./../models/questionModel'),
    QuestionSet = require('./../models/questionSetModel'),
    Result = require('./../models/resultModel'),
    winston = require('winston');

var checkForNull = function(data) {
    var promise = new Promise(function(resolve, reject) {
        if (!data) {
            var error_message = new Error('Does Not Exist');
            reject(error_message);
        } else {
            resolve(data);
        }
    });
    return promise;
};

var addQuestionSet = function(req, res) {
    winston.info('lectureController: add question set');
    QuestionSet.findById(req.params.QUESTIONSETID)
        .exec()
        .then(function(questionSet) {
            return Lecture.findOneAndUpdate({
                _id: req.params.LECTUREID
            }, {
                $addToSet: {
                    questions: {
                        $each: questionSet.questions
                    }
                }
            }, {
                new: true
            });
        })
        .then(function(lecture) {
            var updatedLecture = lecture.toObject();
            delete updatedLecture._id;
            updatedLecture.lecture_id = lecture._id.toString();
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Question Set Added To Lecture',
                lecture: updatedLecture
            });
        })
        .catch(function(err) {
            console.log("test");
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var addQuestionToLecture = function(req, res) {
    winston.info('lectureController: add question to lecture');

    Question.findById(req.params.QUESTIONID)
        .exec()
        .then(checkForNull)
        .then(function(question) {
            if (question.instructor_id !== req.decodedToken.sub) {
                var newQuestion = new Question({
                    title: question.title,
                    tags: question.tags,
                    instructor_id: req.decodedToken.sub,
                    html_title: question.html_title,
                    html_body: question.html_body,
                    answer_choices: question.answer_choices,
                    copied: true
                });
                return newQuestion.save();
            } else return question;
        })
        .then(function(question) {
            req.question = question;
            return Lecture.findById(req.params.LECTUREID);
        })
        .then(function(lecture) {
            var question = {
                title: req.question.title,
                question_id: req.question._id.toString(),
                tags: req.question.tags,
                copied: req.question.copied
            };
            lecture.questions.push(question);
            return lecture.save();
        })
        .then(function(lecture) {
            var updatedLecture = lecture.toObject();
            delete updatedLecture._id;
            updatedLecture.lecture_id = lecture._id.toString();
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Question Added to Lecture',
                lecture: updatedLecture
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var deleteLecture = function(req, res) {
    winston.info('lectureController: delete lecture');

    Course.findByIdAndUpdate(req.params.COURSEID, {
            $pull: {
                "lectures": {
                    "lecture_id": req.params.LECTUREID
                }
            }
        }, {
            new: true
        })
        .exec()
        .then(function(course) {
            req.course = course;
            return Lecture.remove({
                _id: req.params.LECTUREID
            });
        })
        .then(function(data) {
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Lecture Deleted',
                lectures: req.course.lectures
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var editLecture = function(req, res) {
    winston.info('lectureController: edit lecture');

    Lecture.findByIdAndUpdate(req.params.LECTUREID, {
            $set: {
                title: req.body.title,
                schedule: req.body.schedule
            }
        }, {
            new: true
        })
        .exec()
        .then(function(lecture) {
            return Course.findOneAndUpdate({
                "_id": lecture.course_id,
                "lectures.lecture_id": req.params.LECTUREID
            }, {
                $set: {
                    "lectures.$.title": req.body.title,
                    "lectures.$.schedule": req.body.schedule
                }
            }, {
                new: true
            });
        })
        .then(function(course) {
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Lecture Edited',
                lectures: course.lectures
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var getLecture = function(req, res) {
    winston.info('lectureController: get lecture');

    Lecture.findById(req.params.LECTUREID, {
            "__v": 0
        })
        .exec()
        .then(checkForNull)
        .then(function(lecture) {
            var updatedLecture = lecture.toObject();
            delete updatedLecture._id;
            updatedLecture.lecture_id = lecture._id.toString();
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Request Success',
                lecture: updatedLecture
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var getCourseLectures = function(req, res) {
    winston.info('lectureController: get course lectures');

    Course.findById(req.params.COURSEID)
        .exec()
        .then(checkForNull)
        .then(function(course) {
            return res.status(201).json({
                success: true,
                jwt_token: req.token,
                message: 'Request Success',
                lectures: course.lectures
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var getAllQuestionSets = function(req, res) {
    winston.info('lectureController: get all question sets');

    QuestionSet.find({
            "instructor_id": req.params.USERID
        })
        .exec()
        .then(function(questionsets) {
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                questionsets: questionsets,
                message: "Success on getAllQuestionSets"
            });
        })
        .catch(function(err) {
            return res.status(500).json({
                success: false,
                message: 'Internal Error'
            });
        });
};

var getStudentResults = function(req, res) {
    winston.info('lectureController: get student results');

    /*
    Result.find({student_id: req.params.STUDENTID, lecture_id: req.params.LECTUREID})
    .exec()
    .then(function(results) {
        return res.status(200).json({
            success: true,
            jwt_token: req.token,
            results: results,
            message: "Success on getStudentResults"
        });
    });
    */
    Result.aggregate([
        {$match: {"student_id": req.params.STUDENTID, "lecture_id": req.params.LECTUREID}},
        {$lookup: {from: "questions",localField: "question_oid",foreignField: "_id",as: "question_details"}}
    ])
    .exec()
    .then(function(results) {
        return res.status(200).json({
            success: true,
            jwt_token: req.token,
            results: results,
            message: "Success on getStudentResults"
        });
    })
    .catch(function(err) {
        return res.status(500).json({
            success: false,
            message: 'Internal Error'
        });
    });
    /*
    Result.aggregate([
        {$match: {student_id: req.params.STUDENTID, lecture_id: req.params.LECTUREID}},
        {$lookup: {from: "questions", localField: "question_id", foreignField: "_id", as: "questions"}}
        ])
    */

    /*
    QuestionSet.find({
            "instructor_id": req.params.USERID
        })
        .exec()
        .then(function(questionsets) {
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                questionsets: questionsets,
                message: "Success on getAllQuestionSets"
            });
        })
        .catch(function(err) {
            return res.status(500).json({
                success: false,
                message: 'Internal Error'
            });
        });
        */
};

var getInstructorResults = function(req, res) {
    winston.info('lectureController: get instructor results');
    console.log(req.params.LECTUREID);

    Result.aggregate( [
      {$match: {"lecture_id" : req.params.LECTUREID}},
     { $group : { "_id" : "$question_id", student_results: { $push: "$correct" }, student_answers: { $push: "$answer" } } }
     ] )
    .exec()
    .then(function(results) {
        return res.status(200).json({
            success: true,
            jwt_token: req.token,
            results: results,
            message: "Success on getInstructorResults"
        });
    })
    .catch(function(err) {
        console.log(err);
        return res.status(500).json({
            success: false,
            message: 'Internal Error'
        });
    });
};

var removeQuestion = function(req, res) {
    winston.info('lectureController: remove question');

    Lecture.findByIdAndUpdate(req.params.LECTUREID, {
            $pull: {
                "questions": {
                    "question_id": req.params.QUESTIONID
                }
            }
        }, {
            new: true
        })
        .exec()
        .then(function(lecture) {
            var updatedLecture = lecture.toObject();
            delete updatedLecture._id;
            updatedLecture.lecture_id = lecture._id.toString();
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Question Removed',
                lecture: updatedLecture
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var reorderQuestion = function(req, res) {
    winston.info('lectureController: re-order question');

    Question.findById(req.params.QUESTIONID)
        .exec()
        .then(checkForNull)
        .then(function(question) {
            req.question = question;
            return Lecture.findByIdAndUpdate(req.params.LECTUREID, {
                $pull: {
                    "questions": {
                        "question_id": req.params.QUESTIONID
                    }
                }
            }, {
                new: true
            });
        })
        .then(function(lecture) {
            var question = {
                title: req.question.title,
                question_id: req.question._id.toString(),
                tags: req.question.tags,
                copied: req.question.copied
            };
            lecture.questions.splice(req.body.index, 0, question);
            return lecture.save();
        })
        .then(function(lecture) {
            var updatedLecture = lecture.toObject();
            delete updatedLecture._id;
            updatedLecture.lecture_id = lecture._id.toString();
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Reorder Complete',
                lecture: updatedLecture
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var savedLectureToDB = function(req, res) {
    winston.info('lectureController: save question to database');

    Course.findById(req.params.COURSEID)
        .exec()
        .then(checkForNull)
        .then(function(course) {
            req.course = course;
            var newLecture = new Lecture({
                title: req.body.lecture_title,
                instructor_id: req.decodedToken.sub,
                course_id: req.params.COURSEID,
                schedule: req.body.lecture_schedule
            });
            return newLecture.save();
        })
        .then(function(lecture) {
            var new_lecture_snapshot = {
                lecture_id: lecture._id.toString(),
                title: lecture.title,
                schedule: lecture.schedule
            };
            req.course.lectures.push(new_lecture_snapshot);
            return req.course.save();
        })
        .then(function(course) {
            return res.status(201).json({
                success: true,
                jwt_token: req.token,
                message: 'Lecture Creation Successsful',
                lectures: course.lectures
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var saveQuestionSet = function(req, res) {
    winston.info('lectureController: save question set');

    Lecture.findById(req.params.LECTUREID)
        .exec()
        .then(function(lecture) {
            var questions = [];
            for (var i = 0; i < lecture.questions.length; i++) {
                questions.push(lecture.questions[i]);
            }
            return questions;
        })
        .then(function(questions) {
            var newQuestionSet = new QuestionSet({
                title: req.body.title,
                instructor_id: req.decodedToken.sub,
                questions: questions
            });
            return newQuestionSet.save();
        })
        .then(function(questionSet) {
            return QuestionSet.find({
                "instructor_id": req.decodedToken.sub
            });
        })
        .then(function(questionSets) {
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Question Set Saved',
                questionSets: questionSets
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

module.exports = {
    addQuestionSet: addQuestionSet,
    addQuestionToLecture: addQuestionToLecture,
    deleteLecture: deleteLecture,
    editLecture: editLecture,
    getLecture: getLecture,
    getCourseLectures: getCourseLectures,
    getAllQuestionSets: getAllQuestionSets,
    getInstructorResults: getInstructorResults,
    getStudentResults: getStudentResults,
    removeQuestion: removeQuestion,
    reorderQuestion: reorderQuestion,
    savedLectureToDB: savedLectureToDB,
    saveQuestionSet: saveQuestionSet
};
<commit_msg>update results<commit_after>/* jshint node: true */
/* jshint esversion: 6 */

//************************************************************
//  lectureController.js                                    //
//  Active Learning 2110                                    //
//                                                          //
//  Created by Odell Mizrahi on 03/04/2017.                 //
//  Copyright © 2017 Odell Mizrahi. All rights reserved.    //
//                                                          //
//  Date        Name        Description                     //
//  -------     ---------   --------------                  //
//  03/02/05    O. Miz      Initial Design                  //
//                                                          //
//************************************************************
"use strict";

var Course = require('./../models/courseModel'),
    Lecture = require('./../models/lectureModel'),
    Question = require('./../models/questionModel'),
    QuestionSet = require('./../models/questionSetModel'),
    Result = require('./../models/resultModel'),
    winston = require('winston');

Array.prototype.getLectureAvg = function() {
   var counter = 0;
   for(var i = 0; i < this.length; i++) {
     if(this[i]) {
       counter++;
     }
   }
   return Math.round((counter / this.length) * 100);
 };

var checkForNull = function(data) {
    var promise = new Promise(function(resolve, reject) {
        if (!data) {
            var error_message = new Error('Does Not Exist');
            reject(error_message);
        } else {
            resolve(data);
        }
    });
    return promise;
};

var addQuestionSet = function(req, res) {
    winston.info('lectureController: add question set');
    QuestionSet.findById(req.params.QUESTIONSETID)
        .exec()
        .then(function(questionSet) {
            return Lecture.findOneAndUpdate({
                _id: req.params.LECTUREID
            }, {
                $addToSet: {
                    questions: {
                        $each: questionSet.questions
                    }
                }
            }, {
                new: true
            });
        })
        .then(function(lecture) {
            var updatedLecture = lecture.toObject();
            delete updatedLecture._id;
            updatedLecture.lecture_id = lecture._id.toString();
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Question Set Added To Lecture',
                lecture: updatedLecture
            });
        })
        .catch(function(err) {
            console.log("test");
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var addQuestionToLecture = function(req, res) {
    winston.info('lectureController: add question to lecture');

    Question.findById(req.params.QUESTIONID)
        .exec()
        .then(checkForNull)
        .then(function(question) {
            if (question.instructor_id !== req.decodedToken.sub) {
                var newQuestion = new Question({
                    title: question.title,
                    tags: question.tags,
                    instructor_id: req.decodedToken.sub,
                    html_title: question.html_title,
                    html_body: question.html_body,
                    answer_choices: question.answer_choices,
                    copied: true
                });
                return newQuestion.save();
            } else return question;
        })
        .then(function(question) {
            req.question = question;
            return Lecture.findById(req.params.LECTUREID);
        })
        .then(function(lecture) {
            var question = {
                title: req.question.title,
                question_id: req.question._id.toString(),
                tags: req.question.tags,
                copied: req.question.copied
            };
            lecture.questions.push(question);
            return lecture.save();
        })
        .then(function(lecture) {
            var updatedLecture = lecture.toObject();
            delete updatedLecture._id;
            updatedLecture.lecture_id = lecture._id.toString();
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Question Added to Lecture',
                lecture: updatedLecture
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var deleteLecture = function(req, res) {
    winston.info('lectureController: delete lecture');

    Course.findByIdAndUpdate(req.params.COURSEID, {
            $pull: {
                "lectures": {
                    "lecture_id": req.params.LECTUREID
                }
            }
        }, {
            new: true
        })
        .exec()
        .then(function(course) {
            req.course = course;
            return Lecture.remove({
                _id: req.params.LECTUREID
            });
        })
        .then(function(data) {
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Lecture Deleted',
                lectures: req.course.lectures
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var editLecture = function(req, res) {
    winston.info('lectureController: edit lecture');

    Lecture.findByIdAndUpdate(req.params.LECTUREID, {
            $set: {
                title: req.body.title,
                schedule: req.body.schedule
            }
        }, {
            new: true
        })
        .exec()
        .then(function(lecture) {
            return Course.findOneAndUpdate({
                "_id": lecture.course_id,
                "lectures.lecture_id": req.params.LECTUREID
            }, {
                $set: {
                    "lectures.$.title": req.body.title,
                    "lectures.$.schedule": req.body.schedule
                }
            }, {
                new: true
            });
        })
        .then(function(course) {
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Lecture Edited',
                lectures: course.lectures
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var getLecture = function(req, res) {
    winston.info('lectureController: get lecture');

    Lecture.findById(req.params.LECTUREID, {
            "__v": 0
        })
        .exec()
        .then(checkForNull)
        .then(function(lecture) {
            var updatedLecture = lecture.toObject();
            delete updatedLecture._id;
            updatedLecture.lecture_id = lecture._id.toString();
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Request Success',
                lecture: updatedLecture
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var getCourseLectures = function(req, res) {
    winston.info('lectureController: get course lectures');

    Course.findById(req.params.COURSEID)
        .exec()
        .then(checkForNull)
        .then(function(course) {
            return res.status(201).json({
                success: true,
                jwt_token: req.token,
                message: 'Request Success',
                lectures: course.lectures
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var getAllQuestionSets = function(req, res) {
    winston.info('lectureController: get all question sets');

    QuestionSet.find({
            "instructor_id": req.params.USERID
        })
        .exec()
        .then(function(questionsets) {
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                questionsets: questionsets,
                message: "Success on getAllQuestionSets"
            });
        })
        .catch(function(err) {
            return res.status(500).json({
                success: false,
                message: 'Internal Error'
            });
        });
};

var getStudentResults = function(req, res) {
    winston.info('lectureController: get student results');

    /*
    Result.find({student_id: req.params.STUDENTID, lecture_id: req.params.LECTUREID})
    .exec()
    .then(function(results) {
        return res.status(200).json({
            success: true,
            jwt_token: req.token,
            results: results,
            message: "Success on getStudentResults"
        });
    });
    */
    Result.aggregate([
        {$match: {"student_id": req.params.STUDENTID, "lecture_id": req.params.LECTUREID}},
        {$lookup: {from: "questions",localField: "question_oid",foreignField: "_id",as: "question_details"}}
    ])
    .exec()
    .then(function(results) {
        return res.status(200).json({
            success: true,
            jwt_token: req.token,
            results: results,
            message: "Success on getStudentResults"
        });
    })
    .catch(function(err) {
        return res.status(500).json({
            success: false,
            message: 'Internal Error'
        });
    });
    /*
    Result.aggregate([
        {$match: {student_id: req.params.STUDENTID, lecture_id: req.params.LECTUREID}},
        {$lookup: {from: "questions", localField: "question_id", foreignField: "_id", as: "questions"}}
        ])
    */

    /*
    QuestionSet.find({
            "instructor_id": req.params.USERID
        })
        .exec()
        .then(function(questionsets) {
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                questionsets: questionsets,
                message: "Success on getAllQuestionSets"
            });
        })
        .catch(function(err) {
            return res.status(500).json({
                success: false,
                message: 'Internal Error'
            });
        });
        */
};

var getInstructorResults = function(req, res) {
    winston.info('lectureController: get instructor results');
    console.log(req.params.LECTUREID);

    Result.aggregate( [
      {$match: {"lecture_id" : req.params.LECTUREID}},
     { $group : { "_id" : "$question_id", student_results: { $push: "$correct" }, student_answers: { $push: "$answer" } } }
     ] )
    .exec()
    .then(function(results) {
      results.forEach(function(result) {
          console.log(result.student_results.getLectureAvg());
          result.class_average = result.student_results.getLectureAvg();
      });
        return res.status(200).json({
            success: true,
            jwt_token: req.token,
            results: results,
            message: "Success on getInstructorResults"
        });
    })
    .catch(function(err) {
        console.log(err);
        return res.status(500).json({
            success: false,
            message: 'Internal Error'
        });
    });
};

var removeQuestion = function(req, res) {
    winston.info('lectureController: remove question');

    Lecture.findByIdAndUpdate(req.params.LECTUREID, {
            $pull: {
                "questions": {
                    "question_id": req.params.QUESTIONID
                }
            }
        }, {
            new: true
        })
        .exec()
        .then(function(lecture) {
            var updatedLecture = lecture.toObject();
            delete updatedLecture._id;
            updatedLecture.lecture_id = lecture._id.toString();
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Question Removed',
                lecture: updatedLecture
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var reorderQuestion = function(req, res) {
    winston.info('lectureController: re-order question');

    Question.findById(req.params.QUESTIONID)
        .exec()
        .then(checkForNull)
        .then(function(question) {
            req.question = question;
            return Lecture.findByIdAndUpdate(req.params.LECTUREID, {
                $pull: {
                    "questions": {
                        "question_id": req.params.QUESTIONID
                    }
                }
            }, {
                new: true
            });
        })
        .then(function(lecture) {
            var question = {
                title: req.question.title,
                question_id: req.question._id.toString(),
                tags: req.question.tags,
                copied: req.question.copied
            };
            lecture.questions.splice(req.body.index, 0, question);
            return lecture.save();
        })
        .then(function(lecture) {
            var updatedLecture = lecture.toObject();
            delete updatedLecture._id;
            updatedLecture.lecture_id = lecture._id.toString();
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Reorder Complete',
                lecture: updatedLecture
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var savedLectureToDB = function(req, res) {
    winston.info('lectureController: save question to database');

    Course.findById(req.params.COURSEID)
        .exec()
        .then(checkForNull)
        .then(function(course) {
            req.course = course;
            var newLecture = new Lecture({
                title: req.body.lecture_title,
                instructor_id: req.decodedToken.sub,
                course_id: req.params.COURSEID,
                schedule: req.body.lecture_schedule
            });
            return newLecture.save();
        })
        .then(function(lecture) {
            var new_lecture_snapshot = {
                lecture_id: lecture._id.toString(),
                title: lecture.title,
                schedule: lecture.schedule
            };
            req.course.lectures.push(new_lecture_snapshot);
            return req.course.save();
        })
        .then(function(course) {
            return res.status(201).json({
                success: true,
                jwt_token: req.token,
                message: 'Lecture Creation Successsful',
                lectures: course.lectures
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

var saveQuestionSet = function(req, res) {
    winston.info('lectureController: save question set');

    Lecture.findById(req.params.LECTUREID)
        .exec()
        .then(function(lecture) {
            var questions = [];
            for (var i = 0; i < lecture.questions.length; i++) {
                questions.push(lecture.questions[i]);
            }
            return questions;
        })
        .then(function(questions) {
            var newQuestionSet = new QuestionSet({
                title: req.body.title,
                instructor_id: req.decodedToken.sub,
                questions: questions
            });
            return newQuestionSet.save();
        })
        .then(function(questionSet) {
            return QuestionSet.find({
                "instructor_id": req.decodedToken.sub
            });
        })
        .then(function(questionSets) {
            return res.status(200).json({
                success: true,
                jwt_token: req.token,
                message: 'Question Set Saved',
                questionSets: questionSets
            });
        })
        .catch(function(err) {
            return res.status(404).json({
                success: false,
                message: err.message
            });
        });
};

module.exports = {
    addQuestionSet: addQuestionSet,
    addQuestionToLecture: addQuestionToLecture,
    deleteLecture: deleteLecture,
    editLecture: editLecture,
    getLecture: getLecture,
    getCourseLectures: getCourseLectures,
    getAllQuestionSets: getAllQuestionSets,
    getInstructorResults: getInstructorResults,
    getStudentResults: getStudentResults,
    removeQuestion: removeQuestion,
    reorderQuestion: reorderQuestion,
    savedLectureToDB: savedLectureToDB,
    saveQuestionSet: saveQuestionSet
};
<|endoftext|>


<commit_before>
// Binary tree node structure
var Node = function(value) {
	this.value = value;
	this.left = null;
	this.right = null;
};

function reverseTree(node) {
	// Checks for the next node/s down the tree, then recursively
	// call reverseTree()

	if(node.left || node.right) {

		if(node.left){
			reverseTree(node.left);
		}
		if(node.right) {
			reverseTree(node.right);
		}

        // Swaps child nodes around
		var temp;
		temp = node.left;
		node.left = node.right;
		node.right = temp;
	}
}

// Builds a string containing the values from an 'inorder' traversal of the tree
function printInOrder(tree) {
    var p = '';
    getOrder(tree);

    function getOrder(root) {

	    if(root){
			getOrder(root.left);
			p += p ?  ", " + root.value : root.value;
			getOrder(root.right);
		}
    }

    return p;

}

// Declare and builds a tree
var test = new Node(1);
test.left = new Node(2);
test.left.left = new Node(3);
test.left.right = new Node(4);
test.right = new Node(5);
test.right.left = new Node(6);
test.right.right = new Node(7);
test.right.right.right = new Node(8);
test.right.right.right.right = new Node(9);

console.log("Tree before reversal:")
console.log(printInOrder(test));
reverseTree(test);
console.log("After reversal:");
console.log(printInOrder(test));<commit_msg>Fixed spacing<commit_after>
// Binary tree node structure
var Node = function(value) {
	this.value = value;
	this.left = null;
	this.right = null;
};

function reverseTree(node) {
	// Checks for the next node/s down the tree, then recursively
	// call reverseTree()

	if(node.left || node.right) {

		if(node.left){
			reverseTree(node.left);
		}
		if(node.right) {
			reverseTree(node.right);
		}
                // Swaps child nodes around only
		// on nodes that have at least
	 	// one !null child
		var temp;
		temp = node.left;
		node.left = node.right;
		node.right = temp;
	}
}

// Builds a string containing the values from an 'inorder' traversal of the tree
function printInOrder(tree) {
    var p = '';
    getOrder(tree);

    function getOrder(root) {
	    if(root){
			getOrder(root.left);
			p += p ?  ", " + root.value : root.value;
			getOrder(root.right);
	    }
    }

    return p;

}
// Declare and builds a tree
var test = new Node(1);
test.left = new Node(2);
test.left.left = new Node(3);
test.left.right = new Node(4);
test.right = new Node(5);
test.right.left = new Node(6);
test.right.right = new Node(7);
test.right.right.right = new Node(8);
test.right.right.right.right = new Node(9);

console.log("Tree before reversal:")
console.log(printInOrder(test));
reverseTree(test);
console.log("After reversal:");
console.log(printInOrder(test));
<|endoftext|>