<commit_before>/*
 * TradingEvents object contains all the event handler function required for
 * websocket trading page
 *
 * We need it as object so that we can call TradingEvent.init() only on trading
 * page for pjax to work else it will fire on all pages
 *
 */
var TradingEvents = (function () {
    'use strict';

    var initiate = function () {
        /*
         * attach event to market list, so when client change market we need to update undelryings
         * and request for new Contract details to populate the form and request price accordingly
         */
        var marketNavElement = document.getElementById('contract_markets');
        var onMarketChange = function(market){
            sessionStorage.setItem('market', market);

            // as different markets have different forms so remove from sessionStorage
            // it will default to proper one
            sessionStorage.removeItem('formname');
            sessionStorage.removeItem('underlying');
            processMarket(1);
        };

        if (marketNavElement) {
            marketNavElement.addEventListener('change', function(e) {
                var clickedMarket = e.target;
                onMarketChange(clickedMarket.value);
            });
        }

        /*
         * attach event to form list, so when client click on different form we need to update form
         * and request for new Contract details to populate the form and request price accordingly
         */
        var contractFormEventChange = function () {
            processContractForm();
            requestTradeAnalysis();
        };

        var formNavElement = document.getElementById('contract_form_name_nav');
        if (formNavElement) {
            formNavElement.addEventListener('click', function(e) {
                if (e.target && e.target.getAttribute('menuitem')) {
                    var clickedForm = e.target;
                    var isFormActive = clickedForm.classList.contains('active');
                    sessionStorage.setItem('formname', clickedForm.getAttribute('menuitem'));

                    setFormPlaceholderContent();
                    // if form is already active then no need to send same request again
                    toggleActiveCatMenuElement(formNavElement, e.target.getAttribute('menuitem'));

                    if (!isFormActive) {
                        contractFormEventChange();
                    }
                    var contractFormCheckbox = document.getElementById('contract_form_show_menu');
                    if (contractFormCheckbox) {
                        contractFormCheckbox.checked = false;
                    }
                }
            });
        }

        /*
         * attach event to underlying change, event need to request new contract details and price
         */
        var underlyingElement = document.getElementById('underlying');
        if (underlyingElement) {
            underlyingElement.addEventListener('change', function(e) {
                if (e.target) {
                    var underlying = e.target.value;
                    sessionStorage.setItem('underlying', underlying);
                    requestTradeAnalysis();

                    Contract.getContracts(underlying);

                    // forget the old tick id i.e. close the old tick stream
                    processForgetTickId();
                    // get ticks for current underlying
                    TradeSocket.send({ ticks : underlying });
                }
            });
        }

        /*
         * bind event to change in duration amount, request new price
         */
        var durationAmountElement = document.getElementById('duration_amount');
        if (durationAmountElement) {
            durationAmountElement.addEventListener('input', debounce (function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach event to expiry time change, event need to populate duration
         * and request new price
         */
        var expiryTypeElement = document.getElementById('expiry_type');
        if (expiryTypeElement) {
            expiryTypeElement.addEventListener('change', function(e) {
                durationPopulate();
                if(e.target && e.target.value === 'endtime') {
                    var current_moment = moment().add(5, 'minutes').utc();
                    document.getElementById('expiry_date').value = current_moment.format('YYYY-MM-DD');
                    document.getElementById('expiry_time').value = current_moment.format('HH:mm');
                }
                processPriceRequest();
            });
        }

        /*
         * bind event to change in duration units, populate duration and request price
         */
        var durationUnitElement = document.getElementById('duration_units');
        if (durationUnitElement) {
            durationUnitElement.addEventListener('change', function () {
                durationPopulate();
                processPriceRequest();
            });
        }

        /*
         * bind event to change in endtime date and time
         */
        var endDateElement = document.getElementById('expiry_date');
        if (endDateElement) {
            endDateElement.addEventListener('change', function () {
                var input = this.value;
                var match = input.match(/^(\d{4})-(\d{2})-(\d{2})$/);
                if(match){
                    var date1 = new Date();
                    date1.setUTCFullYear(match[1]);
                    date1.setUTCMonth(match[2]-1);
                    date1.setUTCDate(match[3]);

                    var date2 = new Date();
                    var diff = date1.getTime() - date2.getTime();
                    var expiry_time = document.getElementById('expiry_time');
                    if(diff > 24*60*60*1000){
                        expiry_time.hide();
                    }
                    else{
                        expiry_time.show();
                    }
                    processPriceRequest();
                }
            });
        }

        var endTimeElement = document.getElementById('expiry_time');
        if (endTimeElement) {
            endTimeElement.addEventListener('change', function () {
                processPriceRequest();
            });
        }

        /*
         * attach event to change in amount, request new price only
         */
        var amountElement = document.getElementById('amount');
        if (amountElement) {
            amountElement.addEventListener('input', debounce( function(e) {
                sessionStorage.setItem('amount', e.target.value);
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach event to start time, display duration based on
         * whether start time is forward starting or not and request
         * new price
         */
        var dateStartElement = document.getElementById('date_start');
        if (dateStartElement) {
            dateStartElement.addEventListener('change', function (e) {
                if (e.target && e.target.value === 'now') {
                    displayDurations('spot');
                } else {
                    displayDurations('forward');
                }
                processPriceRequest();
            });
        }

        /*
         * attach event to change in amount type that is whether its
         * payout or stake and request new price
         */
        var amountTypeElement = document.getElementById('amount_type');
        if (amountTypeElement) {
            amountTypeElement.addEventListener('change', function (e) {
                sessionStorage.setItem('amount_type', e.target.value);
                processPriceRequest();
            });
        }

        /*
         * attach event to change in submarkets. We need to disable
         * underlyings that are not in selected seubmarkets
         */
        var submarketElement = document.getElementById('submarket');
        if (submarketElement) {
            submarketElement.addEventListener('change', function (e) {
                if (e.target) {
                    var elem = document.getElementById('underlying');
                    var underlyings = elem.children;

                    for (var i = 0, len = underlyings.length; i < len; i++ ) {
                        if (e.target.value !== 'all' && e.target.value !== underlyings[i].className) {
                            underlyings[i].disabled = true;
                        } else {
                            underlyings[i].disabled = false;
                        }
                    }

                    // as submarket change has modified the underlying list so we need to manually
                    // fire change event for underlying
                    document.querySelectorAll('#underlying option:enabled')[0].selected = 'selected';
                    var event = new Event('change');
                    elem.dispatchEvent(event);
                }
            });
        }

        /*
         * attach an event to change in currency
         */
        var currencyElement = document.getElementById('currency');
        if (currencyElement) {
            currencyElement.addEventListener('change', function (e) {
                sessionStorage.setItem('currency', e.target.value);
                var stopTypeDollarLabel = document.getElementById('stop_type_dollar_label');
                if (stopTypeDollarLabel && isVisible(stopTypeDollarLabel)) {
                    stopTypeDollarLabel.textContent = e.target.value;
                }
                processPriceRequest();
            });
        }

        /*
         * attach event to purchase buttons to buy the current contract
         */
        // using function expression form here as it used inside for loop
        var purchaseContractEvent = function () {
            var id = this.getAttribute('data-purchase-id'),
                askPrice = this.getAttribute('data-ask-price');

            var params = {buy: id, price: askPrice, passthrough:{}};
            var ids = Price.bufferedIds();
            if(ids[id]){
                for(var attr in this.attributes){
                    if(attr && this.attributes[attr] && this.attributes[attr].name){
                        var m = this.attributes[attr].name.match(/data\-(.+)/);

                        if(m && m[1] && m[1]!=="purchase-id"){
                            params.passthrough[m[1]] = this.attributes[attr].value;
                        }
                    }
                }
                if (id && askPrice) {
                    TradeSocket.send(params);
                    processForgetPriceIds();
                }
            }
        };

        var purchaseButtonElements = document.getElementsByClassName('purchase_button');
        if (purchaseButtonElements) {
            for (var j = 0, l = purchaseButtonElements.length; j < l; j++) {
                purchaseButtonElements[j].addEventListener('click', purchaseContractEvent);
            }
        }

        /*
         * attach event to close icon for purchase container
         */
        var closeContainerElement = document.getElementById('close_confirmation_container');
        if (closeContainerElement) {
            closeContainerElement.addEventListener('click', function (e) {
                if (e.target) {
                    e.preventDefault();
                    document.getElementById('contract_confirmation_container').style.display = 'none';
                    document.getElementById('contracts_list').style.display = 'flex';
                    processPriceRequest();
                }
            });
        }

        /*
         * attach an event to change in barrier
         */
        var barrierElement = document.getElementById('barrier');
        if (barrierElement) {
            barrierElement.addEventListener('input', debounce( function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach an event to change in low barrier
         */
        var lowBarrierElement = document.getElementById('barrier_low');
        if (lowBarrierElement) {
            lowBarrierElement.addEventListener('input', debounce( function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach an event to change in high barrier
         */
        var highBarrierElement = document.getElementById('barrier_high');
        if (highBarrierElement) {
            highBarrierElement.addEventListener('input', debounce( function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach an event to change in digit prediction input
         */
        var predictionElement = document.getElementById('prediction');
        if (predictionElement) {
            predictionElement.addEventListener('input', debounce( function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach an event to change in amount per point for spreads
         */
        var amountPerPointElement = document.getElementById('amount_per_point');
        if (amountPerPointElement) {
            amountPerPointElement.addEventListener('input', debounce( function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach an event to change in stop type for spreads
         */
        var stopTypeEvent = function () {
            processPriceRequest();
        };

        var stopTypeElement = document.querySelectorAll('input[name="stop_type"]');
        if (stopTypeElement) {
            for (var i = 0, len = stopTypeElement.length; i < len; i++) {
                stopTypeElement[i].addEventListener('click', stopTypeEvent);
            }
        }

        /*
         * attach an event to change in stop loss input value
         */
        var stopLossElement = document.getElementById('stop_loss');
        if (stopLossElement) {
            stopLossElement.addEventListener('input', debounce( function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach an event to change in stop profit input value
         */
        var stopProfitElement = document.getElementById('stop_profit');
        if (stopProfitElement) {
            stopProfitElement.addEventListener('input', debounce( function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }
    };

    return {
        init: initiate
    };
})();

<commit_msg>purchase_fix<commit_after>/*
 * TradingEvents object contains all the event handler function required for
 * websocket trading page
 *
 * We need it as object so that we can call TradingEvent.init() only on trading
 * page for pjax to work else it will fire on all pages
 *
 */
var TradingEvents = (function () {
    'use strict';

    var initiate = function () {
        /*
         * attach event to market list, so when client change market we need to update undelryings
         * and request for new Contract details to populate the form and request price accordingly
         */
        var marketNavElement = document.getElementById('contract_markets');
        var onMarketChange = function(market){
            sessionStorage.setItem('market', market);

            // as different markets have different forms so remove from sessionStorage
            // it will default to proper one
            sessionStorage.removeItem('formname');
            sessionStorage.removeItem('underlying');
            processMarket(1);
        };

        if (marketNavElement) {
            marketNavElement.addEventListener('change', function(e) {
                var clickedMarket = e.target;
                onMarketChange(clickedMarket.value);
            });
        }

        /*
         * attach event to form list, so when client click on different form we need to update form
         * and request for new Contract details to populate the form and request price accordingly
         */
        var contractFormEventChange = function () {
            processContractForm();
            requestTradeAnalysis();
        };

        var formNavElement = document.getElementById('contract_form_name_nav');
        if (formNavElement) {
            formNavElement.addEventListener('click', function(e) {
                if (e.target && e.target.getAttribute('menuitem')) {
                    var clickedForm = e.target;
                    var isFormActive = clickedForm.classList.contains('active');
                    sessionStorage.setItem('formname', clickedForm.getAttribute('menuitem'));

                    setFormPlaceholderContent();
                    // if form is already active then no need to send same request again
                    toggleActiveCatMenuElement(formNavElement, e.target.getAttribute('menuitem'));

                    if (!isFormActive) {
                        contractFormEventChange();
                    }
                    var contractFormCheckbox = document.getElementById('contract_form_show_menu');
                    if (contractFormCheckbox) {
                        contractFormCheckbox.checked = false;
                    }
                }
            });
        }

        /*
         * attach event to underlying change, event need to request new contract details and price
         */
        var underlyingElement = document.getElementById('underlying');
        if (underlyingElement) {
            underlyingElement.addEventListener('change', function(e) {
                if (e.target) {
                    var underlying = e.target.value;
                    sessionStorage.setItem('underlying', underlying);
                    requestTradeAnalysis();

                    Contract.getContracts(underlying);

                    // forget the old tick id i.e. close the old tick stream
                    processForgetTickId();
                    // get ticks for current underlying
                    TradeSocket.send({ ticks : underlying });
                }
            });
        }

        /*
         * bind event to change in duration amount, request new price
         */
        var durationAmountElement = document.getElementById('duration_amount');
        if (durationAmountElement) {
            durationAmountElement.addEventListener('input', debounce (function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach event to expiry time change, event need to populate duration
         * and request new price
         */
        var expiryTypeElement = document.getElementById('expiry_type');
        if (expiryTypeElement) {
            expiryTypeElement.addEventListener('change', function(e) {
                durationPopulate();
                if(e.target && e.target.value === 'endtime') {
                    var current_moment = moment().add(5, 'minutes').utc();
                    document.getElementById('expiry_date').value = current_moment.format('YYYY-MM-DD');
                    document.getElementById('expiry_time').value = current_moment.format('HH:mm');
                }
                processPriceRequest();
            });
        }

        /*
         * bind event to change in duration units, populate duration and request price
         */
        var durationUnitElement = document.getElementById('duration_units');
        if (durationUnitElement) {
            durationUnitElement.addEventListener('change', function () {
                durationPopulate();
                processPriceRequest();
            });
        }

        /*
         * bind event to change in endtime date and time
         */
        var endDateElement = document.getElementById('expiry_date');
        if (endDateElement) {
            endDateElement.addEventListener('change', function () {
                var input = this.value;
                var match = input.match(/^(\d{4})-(\d{2})-(\d{2})$/);
                if(match){
                    var date1 = new Date();
                    date1.setUTCFullYear(match[1]);
                    date1.setUTCMonth(match[2]-1);
                    date1.setUTCDate(match[3]);

                    var date2 = new Date();
                    var diff = date1.getTime() - date2.getTime();
                    var expiry_time = document.getElementById('expiry_time');
                    if(diff > 24*60*60*1000){
                        expiry_time.hide();
                    }
                    else{
                        expiry_time.show();
                    }
                    processPriceRequest();
                }
            });
        }

        var endTimeElement = document.getElementById('expiry_time');
        if (endTimeElement) {
            endTimeElement.addEventListener('change', function () {
                processPriceRequest();
            });
        }

        /*
         * attach event to change in amount, request new price only
         */
        var amountElement = document.getElementById('amount');
        if (amountElement) {
            amountElement.addEventListener('input', debounce( function(e) {
                sessionStorage.setItem('amount', e.target.value);
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach event to start time, display duration based on
         * whether start time is forward starting or not and request
         * new price
         */
        var dateStartElement = document.getElementById('date_start');
        if (dateStartElement) {
            dateStartElement.addEventListener('change', function (e) {
                if (e.target && e.target.value === 'now') {
                    displayDurations('spot');
                } else {
                    displayDurations('forward');
                }
                processPriceRequest();
            });
        }

        /*
         * attach event to change in amount type that is whether its
         * payout or stake and request new price
         */
        var amountTypeElement = document.getElementById('amount_type');
        if (amountTypeElement) {
            amountTypeElement.addEventListener('change', function (e) {
                sessionStorage.setItem('amount_type', e.target.value);
                processPriceRequest();
            });
        }

        /*
         * attach event to change in submarkets. We need to disable
         * underlyings that are not in selected seubmarkets
         */
        var submarketElement = document.getElementById('submarket');
        if (submarketElement) {
            submarketElement.addEventListener('change', function (e) {
                if (e.target) {
                    var elem = document.getElementById('underlying');
                    var underlyings = elem.children;

                    for (var i = 0, len = underlyings.length; i < len; i++ ) {
                        if (e.target.value !== 'all' && e.target.value !== underlyings[i].className) {
                            underlyings[i].disabled = true;
                        } else {
                            underlyings[i].disabled = false;
                        }
                    }

                    // as submarket change has modified the underlying list so we need to manually
                    // fire change event for underlying
                    document.querySelectorAll('#underlying option:enabled')[0].selected = 'selected';
                    var event = new Event('change');
                    elem.dispatchEvent(event);
                }
            });
        }

        /*
         * attach an event to change in currency
         */
        var currencyElement = document.getElementById('currency');
        if (currencyElement) {
            currencyElement.addEventListener('change', function (e) {
                sessionStorage.setItem('currency', e.target.value);
                var stopTypeDollarLabel = document.getElementById('stop_type_dollar_label');
                if (stopTypeDollarLabel && isVisible(stopTypeDollarLabel)) {
                    stopTypeDollarLabel.textContent = e.target.value;
                }
                processPriceRequest();
            });
        }

        /*
         * attach event to purchase buttons to buy the current contract
         */
        // using function expression form here as it used inside for loop
        var purchaseContractEvent = function () {
            var id = this.getAttribute('data-purchase-id'),
                askPrice = this.getAttribute('data-ask-price');

            var params = {buy: id, price: askPrice, passthrough:{}};
            var ids = Price.bufferedIds();
            if(ids[id]){
                for(var attr in this.attributes){
                    if(attr && this.attributes[attr] && this.attributes[attr].name){
                        var m = this.attributes[attr].name.match(/data\-(.+)/);

                        if(m && m[1] && m[1]!=="purchase-id" && m[1]!=="passthrough"){
                            params.passthrough[m[1]] = this.attributes[attr].value;
                        }
                    }
                }
                if (id && askPrice) {
                    TradeSocket.send(params);
                    processForgetPriceIds();
                }
            }
        };

        var purchaseButtonElements = document.getElementsByClassName('purchase_button');
        if (purchaseButtonElements) {
            for (var j = 0, l = purchaseButtonElements.length; j < l; j++) {
                purchaseButtonElements[j].addEventListener('click', purchaseContractEvent);
            }
        }

        /*
         * attach event to close icon for purchase container
         */
        var closeContainerElement = document.getElementById('close_confirmation_container');
        if (closeContainerElement) {
            closeContainerElement.addEventListener('click', function (e) {
                if (e.target) {
                    e.preventDefault();
                    document.getElementById('contract_confirmation_container').style.display = 'none';
                    document.getElementById('contracts_list').style.display = 'flex';
                    processPriceRequest();
                }
            });
        }

        /*
         * attach an event to change in barrier
         */
        var barrierElement = document.getElementById('barrier');
        if (barrierElement) {
            barrierElement.addEventListener('input', debounce( function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach an event to change in low barrier
         */
        var lowBarrierElement = document.getElementById('barrier_low');
        if (lowBarrierElement) {
            lowBarrierElement.addEventListener('input', debounce( function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach an event to change in high barrier
         */
        var highBarrierElement = document.getElementById('barrier_high');
        if (highBarrierElement) {
            highBarrierElement.addEventListener('input', debounce( function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach an event to change in digit prediction input
         */
        var predictionElement = document.getElementById('prediction');
        if (predictionElement) {
            predictionElement.addEventListener('input', debounce( function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach an event to change in amount per point for spreads
         */
        var amountPerPointElement = document.getElementById('amount_per_point');
        if (amountPerPointElement) {
            amountPerPointElement.addEventListener('input', debounce( function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach an event to change in stop type for spreads
         */
        var stopTypeEvent = function () {
            processPriceRequest();
        };

        var stopTypeElement = document.querySelectorAll('input[name="stop_type"]');
        if (stopTypeElement) {
            for (var i = 0, len = stopTypeElement.length; i < len; i++) {
                stopTypeElement[i].addEventListener('click', stopTypeEvent);
            }
        }

        /*
         * attach an event to change in stop loss input value
         */
        var stopLossElement = document.getElementById('stop_loss');
        if (stopLossElement) {
            stopLossElement.addEventListener('input', debounce( function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }

        /*
         * attach an event to change in stop profit input value
         */
        var stopProfitElement = document.getElementById('stop_profit');
        if (stopProfitElement) {
            stopProfitElement.addEventListener('input', debounce( function (e) {
                processPriceRequest();
                submitForm(document.getElementById('websocket_form'));
            }));
        }
    };

    return {
        init: initiate
    };
})();

<|endoftext|>


<commit_before>/*global $:true */

// Build User: ${build.user}
// Version: ${build.version}
// Build Date: ${build.date}

// TODO: Allow escape (this will have to be figured out in the regular expression)
// TODO: jsdoc
// TODO: .add() should take in an optional third argument (resolver map)

// TODO: Add getNames()
// TODO: Add empty()
// TODO: remove jquery

(function(root, factory) {
    'use strict';

    // Try to define a console object
    (function(){
        try {
            if (!console && (window)) {
                // Union of Chrome, FF, IE, and Safari console methods
                var consoleFunctions = [
                    'log', 'info', 'warn', 'error', 'debug', 'trace', 'dir', 'group',
                    'groupCollapsed', 'groupEnd', 'time', 'timeEnd', 'profile', 'profileEnd',
                    'dirxml', 'assert', 'count', 'markTimeline', 'timeStamp', 'clear'
                ];
                // Define undefined methods as no-ops to prevent errors
                for (var i = 0; i < consoleFunctions.length; i++) {
                    if (!window.console[consoleFunctions[i]]) {
                        window.console[consoleFunctions[i]] = function() {};
                    }
                }
            }
        } catch(error) {
            // Not much to do if there is no console
        }

    })();

    // Determine the module system (if any)
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(factory);
    } else {
        // Node
        if (typeof exports !== 'undefined') {
            module.exports = factory();
        } else {
            // None
            root.TemplateManager = factory();
        }
    }

})(this, function() {
    'use strict';

    // This is a regex cache for all of the instances of TemplateManager (like a private static member)
    var _getRegex = function(regex) {
        // Memoize the cache
        if (!_getRegex.cache) {
            _getRegex.cache = {};
        }

        if (!_getRegex.cache[regex]) {
            _getRegex.cache[regex] = new RegExp(regex, 'gi');
        }

        return _getRegex.cache[regex];
    };

    var TemplateManager = function(defaultResolverMap, options) {

        if (!(this instanceof TemplateManager)) {
            return new TemplateManager(defaultResolverMap, options);
        }

        var _options = $.extend({
            scriptType: 'text/x-template-manager'
        }, options);

        // The template cache
        var _templateCache = [];

        // Flag to determine if the templates have been loaded from the HTML page
        var _hasLoaded = false;

        var _find = function(name) {
            return _templateCache[name];
        };

        var _addToCache = function(name, template) {
            if (name) {
                _templateCache[name] = template;
            }
        };

        var _add = function(name, template) {
            _addToCache(name, template);
            return _get(name);
        };

        var _load = function() {
            // Get all the scripts
            var $scripts = jQuery('script');

            // Add each template into the cache
            $scripts.each(function(index, script) {
                var $script;
                var name;
                var content;

                // Check to see if the script type matches the type desired
                if (_options.scriptType === script.type) {
                    $script = jQuery(script);
                    name = $script.data('name').trim();
                    content = script.innerHTML.trim();

                    if (name.length) {
                        // Add to the cache
                        _addToCache(name, content);
                    } else {
                        // Output warning (no name)
                        console.warn('Template has no name');
                    }
                }
            });

            _hasLoaded = true;
        };

        var _remove = function(name) {
            delete _templateCache[name];
        };

        var _raw = function(templateName, template) {
            return template || '';
        };

        var _processLoop = function(template, resolverMap) {
            var processedTemplateString = template;

            jQuery.each(resolverMap, function(index, resolver) {
                var regex = _getRegex('\\${' + resolver.regex + '}');
                var replacement;

                // We allow functions for the replacement!
                if (jQuery.isFunction(resolver.replacement)) {
                    try {
                        replacement = resolver.replacement(resolver.regex, template, processedTemplateString);
                    } catch(error) {
                        console.error('Error while calculating replacement for', resolver.regex, error);
                    }
                } else {
                    replacement = resolver.replacement;
                }

                // Only replace if the replacement is defined
                if (replacement) {
                    processedTemplateString = processedTemplateString.replace(regex, replacement);
                }
            });

            return processedTemplateString;
        };

        var _process = function(templateName, template, resolverMap) {
            var processedTemplateString = template;
            var processedLoopResult;

            var _resolverMap = [];

            // Return the empty string if the template is not defined
            if (!template) {
                return '';
            }

            // Populate the default resolvers
            if (defaultResolverMap && defaultResolverMap[templateName]) {
                jQuery.each(defaultResolverMap[templateName], function(index, resolver) {
                    _resolverMap.push(resolver);
                });
            }

            // Populate the resolver map
            if (resolverMap) {
                jQuery.each(resolverMap, function(index, resolver) {
                    _resolverMap.push(resolver);
                });
            }

            // Only process if there are resolvers!
            if (_resolverMap.length) {
                // Loop through until no more resolutions take place
                while (processedTemplateString !== (processedLoopResult = _processLoop(processedTemplateString, _resolverMap))) {
                    processedTemplateString = processedLoopResult;
                }
            }

            return processedTemplateString;
        };

        var _get = function(name) {
            var rawTemplate;

            if (!_hasLoaded) {
                _load();
            }

            // Get the template from the cache
            rawTemplate = _find(name);

            // If the template is not found in the cache, return null
            if (!rawTemplate) {
                console.error('Template \'%s\' does not exist', name);
            }
            return {
                process: function(resolverMap) {
                    return _process(name, rawTemplate, resolverMap);
                },
                raw: function() {
                    return _raw(name, rawTemplate);
                }
            };

        };

        return {
            load: _load,
            get: _get,
            add: _add,
            remove: _remove
        };

    };

    // Place the version as a member in the function
    TemplateManager.version = '${build.version}';

    return TemplateManager;
});
<commit_msg>-Added TODO<commit_after>/*global $:true */

// Build User: ${build.user}
// Version: ${build.version}
// Build Date: ${build.date}

// TODO: Allow escape (this will have to be figured out in the regular expression)
// TODO: jsdoc
// TODO: .add() should take in an optional third argument (resolver map)

// TODO: Add getNames()
// TODO: Add empty()
// TODO: remove jquery & allow for use in node

(function(root, factory) {
    'use strict';

    // Try to define a console object
    (function(){
        try {
            if (!console && (window)) {
                // Union of Chrome, FF, IE, and Safari console methods
                var consoleFunctions = [
                    'log', 'info', 'warn', 'error', 'debug', 'trace', 'dir', 'group',
                    'groupCollapsed', 'groupEnd', 'time', 'timeEnd', 'profile', 'profileEnd',
                    'dirxml', 'assert', 'count', 'markTimeline', 'timeStamp', 'clear'
                ];
                // Define undefined methods as no-ops to prevent errors
                for (var i = 0; i < consoleFunctions.length; i++) {
                    if (!window.console[consoleFunctions[i]]) {
                        window.console[consoleFunctions[i]] = function() {};
                    }
                }
            }
        } catch(error) {
            // Not much to do if there is no console
        }

    })();

    // Determine the module system (if any)
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(factory);
    } else {
        // Node
        if (typeof exports !== 'undefined') {
            module.exports = factory();
        } else {
            // None
            root.TemplateManager = factory();
        }
    }

})(this, function() {
    'use strict';

    // This is a regex cache for all of the instances of TemplateManager (like a private static member)
    var _getRegex = function(regex) {
        // Memoize the cache
        if (!_getRegex.cache) {
            _getRegex.cache = {};
        }

        if (!_getRegex.cache[regex]) {
            _getRegex.cache[regex] = new RegExp(regex, 'gi');
        }

        return _getRegex.cache[regex];
    };

    var TemplateManager = function(defaultResolverMap, options) {

        if (!(this instanceof TemplateManager)) {
            return new TemplateManager(defaultResolverMap, options);
        }

        var _options = $.extend({
            scriptType: 'text/x-template-manager'
        }, options);

        // The template cache
        var _templateCache = [];

        // Flag to determine if the templates have been loaded from the HTML page
        var _hasLoaded = false;

        var _find = function(name) {
            return _templateCache[name];
        };

        var _addToCache = function(name, template) {
            if (name) {
                _templateCache[name] = template;
            }
        };

        var _add = function(name, template) {
            _addToCache(name, template);
            return _get(name);
        };

        var _load = function() {
            // Get all the scripts
            var $scripts = jQuery('script');

            // Add each template into the cache
            $scripts.each(function(index, script) {
                var $script;
                var name;
                var content;

                // Check to see if the script type matches the type desired
                if (_options.scriptType === script.type) {
                    $script = jQuery(script);
                    name = $script.data('name').trim();
                    content = script.innerHTML.trim();

                    if (name.length) {
                        // Add to the cache
                        _addToCache(name, content);
                    } else {
                        // Output warning (no name)
                        console.warn('Template has no name');
                    }
                }
            });

            _hasLoaded = true;
        };

        var _remove = function(name) {
            delete _templateCache[name];
        };

        var _raw = function(templateName, template) {
            return template || '';
        };

        var _processLoop = function(template, resolverMap) {
            var processedTemplateString = template;

            jQuery.each(resolverMap, function(index, resolver) {
                var regex = _getRegex('\\${' + resolver.regex + '}');
                var replacement;

                // We allow functions for the replacement!
                if (jQuery.isFunction(resolver.replacement)) {
                    try {
                        replacement = resolver.replacement(resolver.regex, template, processedTemplateString);
                    } catch(error) {
                        console.error('Error while calculating replacement for', resolver.regex, error);
                    }
                } else {
                    replacement = resolver.replacement;
                }

                // Only replace if the replacement is defined
                if (replacement) {
                    processedTemplateString = processedTemplateString.replace(regex, replacement);
                }
            });

            return processedTemplateString;
        };

        var _process = function(templateName, template, resolverMap) {
            var processedTemplateString = template;
            var processedLoopResult;

            var _resolverMap = [];

            // Return the empty string if the template is not defined
            if (!template) {
                return '';
            }

            // Populate the default resolvers
            if (defaultResolverMap && defaultResolverMap[templateName]) {
                jQuery.each(defaultResolverMap[templateName], function(index, resolver) {
                    _resolverMap.push(resolver);
                });
            }

            // Populate the resolver map
            if (resolverMap) {
                jQuery.each(resolverMap, function(index, resolver) {
                    _resolverMap.push(resolver);
                });
            }

            // Only process if there are resolvers!
            if (_resolverMap.length) {
                // Loop through until no more resolutions take place
                while (processedTemplateString !== (processedLoopResult = _processLoop(processedTemplateString, _resolverMap))) {
                    processedTemplateString = processedLoopResult;
                }
            }

            return processedTemplateString;
        };

        var _get = function(name) {
            var rawTemplate;

            if (!_hasLoaded) {
                _load();
            }

            // Get the template from the cache
            rawTemplate = _find(name);

            // If the template is not found in the cache, return null
            if (!rawTemplate) {
                console.error('Template \'%s\' does not exist', name);
            }
            return {
                process: function(resolverMap) {
                    return _process(name, rawTemplate, resolverMap);
                },
                raw: function() {
                    return _raw(name, rawTemplate);
                }
            };

        };

        return {
            load: _load,
            get: _get,
            add: _add,
            remove: _remove
        };

    };

    // Place the version as a member in the function
    TemplateManager.version = '${build.version}';

    return TemplateManager;
});
<|endoftext|>


<commit_before>angular.module('ngBoilerplate.player', [])

.service('playerService', function() {
  console.log("GDR: count factory invoked");
  var num = 0;
  this.count = function() {
    console.log("GDR: count invoked");
    num++;
    return num;
  };

  this.setState = function( newstate ) {
    console.log( 'state: ' + state + ' -> ' + newstate);
    state = newstate;
  };

  var state = 'uninitialised';
  var audiocontext;
  var destnode; // the final output node
  var gainnode;
  var osc;

  try {
    audiocontext = new AudioContext();
    destnode = audiocontext.destination;
    gainnode = audiocontext.createGain();
    gainnode.gain.value = 0.2;
    gainnode.connect( destnode);
    this.setState('available');
  } catch  (e) {
    console.log("Exception whilst getting audio: " + e.message);
    audiocontext = undefined;
    this.setState('failed');
  }

  /* unavailable, available, playing */
  this.getStatus = function() {
    return state;
  };

  this.startPow = function() {
    if( state === 'available' ) {
      this.setState('playing');
      osc = audiocontext.createOscillator();
      osc.frequency.value = 220;
      osc.start(0);
      osc.connect(gainnode);
    }
  };

  this.stopPow = function() {
    if( state === 'playing' ) {
      osc.disconnect(gainnode);
      this.setState('available');
    }
  };
});

<commit_msg>Changed gain<commit_after>angular.module('ngBoilerplate.player', [])

.service('playerService', function() {
  console.log("GDR: count factory invoked");
  var num = 0;
  this.count = function() {
    console.log("GDR: count invoked");
    num++;
    return num;
  };

  this.setState = function( newstate ) {
    console.log( 'state: ' + state + ' -> ' + newstate);
    state = newstate;
  };

  var state = 'uninitialised';
  var audiocontext;
  var destnode; // the final output node
  var gainnode;
  var osc;

  try {
    audiocontext = new AudioContext();
    destnode = audiocontext.destination;
    gainnode = audiocontext.createGain();
    gainnode.gain.value = 0.3;
    gainnode.connect( destnode);
    this.setState('available');
  } catch  (e) {
    console.log("Exception whilst getting audio: " + e.message);
    audiocontext = undefined;
    this.setState('failed');
  }

  /* unavailable, available, playing */
  this.getStatus = function() {
    return state;
  };

  this.startPow = function() {
    if( state === 'available' ) {
      this.setState('playing');
      osc = audiocontext.createOscillator();
      osc.frequency.value = 220;
      osc.start(0);
      osc.connect(gainnode);
    }
  };

  this.stopPow = function() {
    if( state === 'playing' ) {
      osc.disconnect(gainnode);
      this.setState('available');
    }
  };
});

<|endoftext|>


<commit_before>// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue';
import App from './App';
import router from './router';

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: { App },
});
<commit_msg>Initialise the database and file manager every time app load<commit_after>// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import storage from 'src/database/storage';
import fileManager from 'src/logic/filemanager';
import Vue from 'vue';
import App from './App';
import router from './router';

// Initialise the application
storage
.initializeDatabase()
.then(fileManager.start)
.then(() => {
  /* eslint-disable no-new */
  new Vue({
    el: '#app',
    router,
    template: '<App/>',
    components: { App },
  });
});
<|endoftext|>


<commit_before>
/**
 * UI Layout Resize
 * @class UI.Layout.Resize
 * @implement UI.Layout
 * @author Jerome D. Vial
 */
UI.Layout.implement({
	options: {
		resizer: {
			modifier: {
				row: {
					size: 'width',
					from: 'left',
					mode: {
						y: false
					}
				},
				column: {
					size: 'height',
					from: 'top',
					mode: {
						x: false
					}
				}
			}
		}
	},

	/**
	 * [_initResizeBorder description]
	 * @param  {[type]} component [description]
	 * @param  {[type]} border    [description]
	 * @return {[type]}           [description]
	 */
	_initResizer: function(component) {
		//_log('_initResizer', component.options.name);

		var self = this,
			name = component.options.name,
			element = component.element,
			container = component.container,
			last = component.options.last;

		this._initMaximize(component);

		if (!container) return;

		var direction = container.getStyle('flex-direction');

		if (!direction)	return;

		var modifier = this.options.resizer.modifier[direction];

		if (!modifier) return;

		//console.log('direction', direction, modifier);

		//_log(element, coord);
		var resizer = this.resizer[name] = new Element('div', {
			'class': 'ui-resizer',
			'data-name': component.options.name
		}).addEvents({
			click: function(e){
				e.stop();
			},
			mousedown: function(e) {
				e.stop();
			}
		}).inject(container);

		if (modifier.size) {
			resizer.addClass('resizer-'+ modifier.size);
		}

		if (last) {
			//_log('------last' );
			//resizer.addClass('resizer-last');
		}

		this._initResizerDrag(resizer, modifier, component);
		this._initResizerEvent(component, resizer, modifier);

		this.fireEvent('drag');
	},

	/**
	 * [_initDrag description]
	 * @param  {[type]} resizer  [description]
	 * @param  {[type]} modifier [description]
	 * @return {[type]}          [description]
	 */
	_initResizerDrag: function(resizer, modifier, component) {
		var self = this;
		//_log('initResizerDrag', resizer, modifier);

		var element = component.element,
			container = component.container,
			last = component.options.last;

		var drag = new Drag.Move(resizer, {
			modifiers: modifier.mode,
		    onStart: function(el){
				//_log('onStart', el);
				//self.fireEvent('resizeStart', el);
			},
			onDrag: function(el, ev){
				//_log('onDrag', el);
				var coord = element.getCoordinates(container);
				var coordc = container.getCoordinates();
				var c = resizer.getCoordinates(container);
				//element.setStyle('flex','none');
				//element.setStyle(modifier.size, c[modifier.from] - coord[modifier.from]);
				if (last){
					//_log(modifier.size, coordc[modifier.size], c[modifier.from]);
					element.setStyle(modifier.size, coordc[modifier.size] - c[modifier.from]);
				}
				else {
					element.setStyle(modifier.size, c[modifier.from] - coord[modifier.from]);
				}

				self.fireEvent('drag');
			},
			onComplete: function(el){
				//_log('onComplete', component.main, modifier.size, size);
				//_log('onComplete', modifier.size, element.getCoordinates(container)[modifier.size]);
				var coord = element.getCoordinates(container);
				var size = element.getCoordinates(container)[modifier.size];
				self.fireEvent('resizer', [component.main, modifier.size, size]);
				component.fireEvent('resizeComplete', [modifier.size, size]);

				//_log('size', modifier, size);

				component[modifier.size] = size;
			}
		});

		return drag;
	},

	/**
	 * [_initResizerEvent description]
	 * @param  {[type]} component [description]
	 * @param  {[type]} resizer   [description]
	 * @param  {[type]} modifier  [description]
	 * @return {[type]}           [description]
	 */
	// will definitly use a controller for that
	_initResizerEvent: function(component, resizer, modifier) {
		//_log('_initResizerEvent', component.options.name, component.options.last);
		var self = this;

		this.addEvents({
			drag: function(e) {
				//_log('drag', e);
				self._updateSize(component, resizer, modifier);
			},
			maximize: function() {
				//_log(direction);
				self._updateSize(component, resizer, modifier);
			},
			normalize: function() {
				//_log(direction);
				self._updateSize(component, resizer, modifier);
			},
			resize: function() {
				//_log('resize', component.element, resizer);

				self._updateSize(component, resizer, modifier);
			}
		});
	},

	_updateSize: function(component, resizer, modifier) {
		//_log('_updazeSize');
		var container = component.container,
			element = component.element;

		var coord = element.getCoordinates(container);
		//_log('coord',  coord[modifier.from]);
		//
		// the last container doesnt need resizedr
		if (component.options.last) {
			resizer.setStyle(modifier.from, coord[modifier.from] -3);
		} else {
			resizer.setStyle(modifier.from, coord[modifier.from] + coord[modifier.size] -3);
		}
	},

	/**
	 * Init maximisation. dblclick trigger the toggle
	 * @param  {[type]} component [description]
	 * @return {[type]}           [description]
	 */
	_initMaximize: function(component) {
		//_log('_initMaximize', component);
		var self = this;
		var element = component.element;
		var container = component.container;

		if (!container) return;

		component.addEvent('max', function() {
			var name = component.options.name;

			_log('max', component);
			if (element.hasClass('container-max')) {
				element.removeClass('container-max');
				container.getChildren('.ui-container').each(function(c) {
					c.setStyle('display', c.retrieve('display'));
				});

				element.setStyle('width', element.retrieve('width'));
				element.setStyle('height', element.retrieve('height'));

				self.fireEvent('normalize', component);
			} else{
				element.addClass('container-max');
				element.store('width', element.getStyle('width'));
				element.store('height', element.getStyle('height'));
				element.setStyle('width', 'initial');
				element.setStyle('height', 'initial');
				container.getChildren('.ui-container').each(function(c) {
					if (!c.hasClass('container-'+name)) {
						c.store('display', c.getStyle('display'));
						c.hide();
					}
				});

				self.fireEvent('resize', component);
			}
		});
	},

	/**
	 * [_initResize description]
	 * @return {[type]} [description]
	 */
	_initResizers: function(components) {
		//_log('_initResizers');
		var len = components.length;

		// add resize Border on the right or on the bottom
		// execpt for the last one
		for (var i = 0; i < len; i++) {
			var component = components[i];

			if (component.options.noResizer) {
				//console.log('--', component.main);
				continue;
			}

			this._initResizer(component);

		}
	},

});
<commit_msg>fix mask when layout size + reveal apply button when click on mask<commit_after>
/**
 * UI Layout Resize
 * @class UI.Layout.Resize
 * @implement UI.Layout
 * @author Jerome D. Vial
 */
UI.Layout.implement({
	options: {
		resizer: {
			modifier: {
				row: {
					size: 'width',
					from: 'left',
					mode: {
						y: false
					}
				},
				column: {
					size: 'height',
					from: 'top',
					mode: {
						x: false
					}
				}
			}
		}
	},

	/**
	 * [_initResizeBorder description]
	 * @param  {[type]} component [description]
	 * @param  {[type]} border    [description]
	 * @return {[type]}           [description]
	 */
	_initResizer: function(component) {
		//_log('_initResizer', component.options.name);

		var self = this,
			name = component.options.name,
			element = component.element,
			container = component.container,
			last = component.options.last;

		this._initMaximize(component);

		if (!container) return;

		var direction = container.getStyle('flex-direction');

		if (!direction)	return;

		var modifier = this.options.resizer.modifier[direction];

		if (!modifier) return;

		//console.log('direction', direction, modifier);

		//_log(element, coord);
		var resizer = this.resizer[name] = new Element('div', {
			'class': 'ui-resizer',
			'data-name': component.options.name
		}).addEvents({
			click: function(e){
				e.stop();
			},
			mousedown: function(e) {
				e.stop();
			}
		}).inject(container);

		if (modifier.size) {
			resizer.addClass('resizer-'+ modifier.size);
		}

		if (last) {
			//_log('------last' );
			//resizer.addClass('resizer-last');
		}

		this._initResizerDrag(resizer, modifier, component);
		this._initResizerEvent(component, resizer, modifier);

		this.fireEvent('drag');
	},

	/**
	 * [_initDrag description]
	 * @param  {[type]} resizer  [description]
	 * @param  {[type]} modifier [description]
	 * @return {[type]}          [description]
	 */
	_initResizerDrag: function(resizer, modifier, component) {
		var self = this;
		//_log('initResizerDrag', resizer, modifier);

		var element = component.element,
			container = component.container,
			last = component.options.last;

		var drag = new Drag.Move(resizer, {
			modifiers: modifier.mode,
		    onStart: function(el){
				//_log('onStart', el);
				//self.fireEvent('resizeStart', el);
			},
			onDrag: function(el, ev){
				//_log('onDrag', el);
				var coord = element.getCoordinates(container);
				var coordc = container.getCoordinates();
				var c = resizer.getCoordinates(container);
				//element.setStyle('flex','none');
				//element.setStyle(modifier.size, c[modifier.from] - coord[modifier.from]);
				if (last){
					//_log(modifier.size, coordc[modifier.size], c[modifier.from]);
					element.setStyle(modifier.size, coordc[modifier.size] - c[modifier.from]);
				}
				else {
					element.setStyle(modifier.size, c[modifier.from] - coord[modifier.from]);
				}

				self.fireEvent('drag');
			},
			onComplete: function(el){
				//_log('onComplete', component.main, modifier.size, size);
				//_log('onComplete', modifier.size, element.getCoordinates(container)[modifier.size]);
				var coord = element.getCoordinates(container);
				var size = element.getCoordinates(container)[modifier.size];
				self.fireEvent('resizer', [component.main, modifier.size, size]);
				component.fireEvent('resizeComplete', [modifier.size, size]);

				//_log('size', modifier, size);

				component[modifier.size] = size;
			}
		});

		return drag;
	},

	/**
	 * [_initResizerEvent description]
	 * @param  {[type]} component [description]
	 * @param  {[type]} resizer   [description]
	 * @param  {[type]} modifier  [description]
	 * @return {[type]}           [description]
	 */
	// will definitly use a controller for that
	_initResizerEvent: function(component, resizer, modifier) {
		//_log('_initResizerEvent', component.options.name, component.options.last);
		var self = this;

		this.addEvents({
			drag: function(e) {
				//_log('drag', e);
				self._updateSize(component, resizer, modifier);
			},
			maximize: function() {
				//_log(direction);
				self._updateSize(component, resizer, modifier);
			},
			normalize: function() {
				//_log(direction);
				self._updateSize(component, resizer, modifier);
			},
			resize: function() {
				//_log('resize', component.element, resizer);

				self._updateSize(component, resizer, modifier);
			}
		});
	},

	_updateSize: function(component, resizer, modifier) {
		_log('_updazeSize');
		var container = component.container,
			element = component.element;

		var coord = element.getCoordinates(container);
		//_log('coord',  coord[modifier.from]);
		//
		// the last container doesnt need resizedr
		if (component.options.last) {
			resizer.setStyle(modifier.from, coord[modifier.from] -3);
		} else {
			resizer.setStyle(modifier.from, coord[modifier.from] + coord[modifier.size] -3);
		}

		this.fireEvent('size');
	},

	/**
	 * Init maximisation. dblclick trigger the toggle
	 * @param  {[type]} component [description]
	 * @return {[type]}           [description]
	 */
	_initMaximize: function(component) {
		//_log('_initMaximize', component);
		var self = this;
		var element = component.element;
		var container = component.container;

		if (!container) return;

		component.addEvent('max', function() {
			var name = component.options.name;

			_log('max', component);
			if (element.hasClass('container-max')) {
				element.removeClass('container-max');
				container.getChildren('.ui-container').each(function(c) {
					c.setStyle('display', c.retrieve('display'));
				});

				element.setStyle('width', element.retrieve('width'));
				element.setStyle('height', element.retrieve('height'));

				self.fireEvent('normalize', component);
			} else{
				element.addClass('container-max');
				element.store('width', element.getStyle('width'));
				element.store('height', element.getStyle('height'));
				element.setStyle('width', 'initial');
				element.setStyle('height', 'initial');
				container.getChildren('.ui-container').each(function(c) {
					if (!c.hasClass('container-'+name)) {
						c.store('display', c.getStyle('display'));
						c.hide();
					}
				});

				self.fireEvent('resize', component);
			}
		});
	},

	/**
	 * [_initResize description]
	 * @return {[type]} [description]
	 */
	_initResizers: function(components) {
		//_log('_initResizers');
		var len = components.length;

		// add resize Border on the right or on the bottom
		// execpt for the last one
		for (var i = 0; i < len; i++) {
			var component = components[i];

			if (component.options.noResizer) {
				//console.log('--', component.main);
				continue;
			}

			this._initResizer(component);

		}
	},

});
<|endoftext|>


<commit_before>'use strict';

/**
 * Test suite for CheckSchema module.
 *
 * @author Carlos Lozano Sánchez
 * @license MIT
 * @copyright 2015-2016 Carlos Lozano Sánchez
 *
 * @testsuite
 */

const should = require('should');
const mockery = require('mockery');

const microrestModules = require('../../../env/MicrorestModules');

describe('Functionality: CheckSchema.check()', function checkTest() {
    let checkSchemaModule;

    beforeEach(function beforeEach() {
        mockery.enable({
            warnOnReplace: false,
            warnOnUnregistered: false,
            useCleanCache: true
        });

        checkSchemaModule = require(microrestModules.checkSchema);
    });

    afterEach(function afterEach() {
        mockery.deregisterAll();
        mockery.disable();
    });

    it('Case 1: The schema parameter is null', function case1() {
        (function () {
            checkSchemaModule.check(null, {});
        }).should.throw();
    });

    it('Case 2: The schema parameter is undefined', function case2() {
        (function () {
            checkSchemaModule.check(undefined, {});
        }).should.throw();
    });

    it('Case 3: The schema parameter is not an object', function case3() {
        (function () {
            checkSchemaModule.check(1, {});
        }).should.throw();
    });

    it('Case 4: The object parameter is null', function case4() {
        (function () {
            checkSchemaModule.check({}, null);
        }).should.throw();
    });

    it('Case 5: The object parameter is undefined', function case5() {
        (function () {
            checkSchemaModule.check({}, undefined);
        }).should.throw();
    });

    it('Case 6: The object parameter is not an object', function case6() {
        (function () {
            checkSchemaModule.check({}, 1);
        }).should.throw();
    });

    it('Case 7: The schema and object parameter are empty objects', function case7() {
        (function () {
            checkSchemaModule.check({}, {});
        }).should.not.throw();
    });
});
<commit_msg>Fix test case<commit_after>'use strict';

/**
 * Test suite for CheckSchema module.
 *
 * @author Carlos Lozano Sánchez
 * @license MIT
 * @copyright 2015-2016 Carlos Lozano Sánchez
 *
 * @testsuite
 */

const should = require('should');
const mockery = require('mockery');

const microrestModules = require('../../../env/MicrorestModules');

describe('Functionality: CheckSchema.check()', function checkTest() {
    let checkSchemaModule;

    beforeEach(function beforeEach() {
        mockery.enable({
            warnOnReplace: false,
            warnOnUnregistered: false,
            useCleanCache: true
        });

        checkSchemaModule = require(microrestModules.checkSchema);
    });

    afterEach(function afterEach() {
        mockery.deregisterAll();
        mockery.disable();
    });

    it('Case 1: The schema parameter is null', function case1() {
        (function () {
            checkSchemaModule.check(null, {});
        }).should.throw();
    });

    it('Case 2: The schema parameter is undefined', function case2() {
        (function () {
            checkSchemaModule.check(undefined, {});
        }).should.throw();
    });

    it('Case 3: The schema parameter is not an object', function case3() {
        (function () {
            checkSchemaModule.check(1, {});
        }).should.throw();
    });

    it('Case 4: The object parameter is null', function case4() {
        (function () {
            checkSchemaModule.check({}, null);
        }).should.throw();
    });

    it('Case 5: The object parameter is undefined', function case5() {
        (function () {
            checkSchemaModule.check({}, undefined);
        }).should.throw();
    });

    it('Case 6: The object parameter is not an object', function case6() {
        (function () {
            checkSchemaModule.check({}, 1);
        }).should.throw();
    });

    it('Case 7: The schema and object parameter are empty objects', function case7() {
        (function () {
            checkSchemaModule.check({}, {});
        }).should.throw();
    });
});
<|endoftext|>


<commit_before>var THREE_COLORS = {
    OCEAN: new THREE.Color('#82caff'),
    BEACH: new THREE.Color('#ffe98d'),
    LAKE: new THREE.Color('#2f9ceb'),
    RIVER: new THREE.Color('#369eea'),
    SOURCE: new THREE.Color('#00f'),
    MARSH: new THREE.Color('#2ac6d3'),
    ICE: new THREE.Color('#b3deff'),
    ROCK: new THREE.Color('#535353'),
    LAVA: new THREE.Color('#e22222'),

    SNOW: new THREE.Color('#f8f8f8'),
    TUNDRA: new THREE.Color('#ddddbb'),
    BARE: new THREE.Color('#bbbbbb'),
    SCORCHED: new THREE.Color('#999999'),
    TAIGA: new THREE.Color('#ccd4bb'),
    SHRUBLAND: new THREE.Color('#c4ccbb'),
    TEMPERATE_DESERT: new THREE.Color('#e4e8ca'),
    TEMPERATE_RAIN_FOREST: new THREE.Color('#a4c4a8'),
    TEMPERATE_DECIDUOUS_FOREST: new THREE.Color('#b4c9a9'),
    GRASSLAND: new THREE.Color('#c4d4aa'),
    TROPICAL_RAIN_FOREST: new THREE.Color('#9cbba9'),
    TROPICAL_SEASONAL_FOREST: new THREE.Color('#a9cca4'),
    SUBTROPICAL_DESERT: new THREE.Color('#e9ddc7')
};

var ThreeJsRenderer = {
    canvas: null,
    diagram: null,
    sites: null,
    config: null,

    scene: null,
    camera: null,
    light: null,
    renderer: null,

    render: function (canvas, diagram, sites, config) {
        if (!diagram || !sites || !config) {
            console.error("ThreeJsRenderer.render method requires a not null diagram, sites and config parameters");
            return;
        }
        this.canvas = canvas;
        this.diagram = diagram;
        this.sites = sites;
        this.config = config;

        // Scene
        this.scene = new THREE.Scene();
        //this.scene.background = new THREE.Color(0xcce0ff);
        //this.scene.fog = new THREE.Fog(0xcce0ff, 500, 10000);
        //this.scene.add(new THREE.AmbientLight(0x666666));

        // Camera
        this.camera = new THREE.PerspectiveCamera(75, 1, 1, 10000);
        this.camera.position.x = 0;
        this.camera.position.y = 0;
        this.camera.position.z = 200;
        this.scene.add(this.camera);

        // Light
        this.light = this.renderLight();
        this.scene.add(this.light);

        // Ground
        //var groundMaterial = new THREE.MeshPhongMaterial({ color: THREE_COLORS.OCEAN.clone(), side: THREE.DoubleSide })
        //var groundMesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(this.config.width, this.config.height), groundMaterial);
        //this.scene.add(groundMesh);

        // Renderer
        this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas});
        this.renderer.setSize(this.config.width*2, this.config.height*2);
        //this.renderer.physicallyCorrectLights = true;
        //this.renderer.gammaInput = true;
        //this.renderer.gammaOutput = true;
        //this.renderer.shadowMap.enabled = true;
        //this.renderer.toneMapping = THREE.ReinhardToneMapping;

        // Cells
        //var group = new THREE.Group();
        //this.renderCells(group);
        //this.scene.add(group);

        //var plane = this.renderHeightMap();
        var plane = this.renderMap();
        this.scene.add(plane);

        // Controls
        var controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
        //controls.maxPolarAngle = Math.PI * 0.5;
        controls.minDistance = 1;
        controls.maxDistance = 7500;

        animate();

        console.info("Three render completed");
    },

    renderLight: function () {
        var bulbGeometry = new THREE.SphereGeometry(5, 16, 8);
        bulbLight = new THREE.PointLight(0xffee88, 1, 1000, 2);
        bulbMat = new THREE.MeshStandardMaterial({
            emissive: 0xffffee,
            emissiveIntensity: 1,
            color: 0x000000
        });
        bulbLight.add(new THREE.Mesh(bulbGeometry, bulbMat));
        bulbLight.position.x = 0;
        bulbLight.position.y = 0;
        bulbLight.position.z = 300;
        bulbLight.castShadow = true;

        return bulbLight;
    },

    renderHeightMap: function () {
        // The idea is to create an height map from the voronoi data we have
        // http://blog.mastermaps.com/2013/10/terrain-building-with-threejs.html
        // https://codepen.io/Fusty/pen/GJvdWe

        // Create polygons Paths
        var polygonsX = [];
        var polygonsY = [];
        var cells = [];
        this.populatePolygonsAndCells(polygonsX, polygonsY, cells);

        // Create the texture
        // https://codepen.io/SereznoKot/pen/vNjJWd
        // https://github.com/mrdoob/three.js/issues/486
        /*
        var side = this.config.width * this.config.height; // power of two textures are better cause powers of two are required by some algorithms. Like ones that decide what color will pixel have if amount of pixels is less than amount of textels (see three.js console error when given non-power-of-two texture)
        var amount = Math.pow(side, 2); // you need 4 values for every pixel in side*side plane
        var data = new Uint8Array(amount);
        for (var i = 0; i < amount; i++) {
            data[i] = Math.random() * 256; // generates random r,g,b,a values from 0 to 1
        }
        */

        // Create geometry
        var geometry = new THREE.PlaneBufferGeometry(this.config.width, this.config.height, this.config.width - 1, this.config.height - 1);
        var vertices = geometry.attributes.position.array;

        // Set altitudes
        var halfWith = this.config.width / 2;
        var halfHeight = this.config.height / 2;
        for (var i = 0, j = 0, numVertices = vertices.length; i < numVertices; i += 3, j += 4) {
            vertices[i+2] = 0; // by default is 0
            var point = [vertices[i] + halfWith, vertices[i + 1] + halfHeight];
            console.log("Evaluating point (" + point[0] + "," + point[1] + ")");

            for (var cll = 0, numCells = cells.length; cll < numCells; cll++) {
                if (this.isPointInPolygon(point[0], point[1], polygonsX[cll], polygonsY[cll])) {
                    vertices[i+2] = cells[cll].realElevation * 100;
                    // geometry.vertices[i].z = data[i] / 65535 * 10;
                    break;
                }
            }
        }
        /*
        var texture = new THREE.DataTexture(data, side, side, THREE.LuminanceFormat, THREE.UnsignedByteType);
        texture.needsUpdate = true;
        var material = new THREE.MeshBasicMaterial({ color: THREE_COLORS["OCEAN"], alphaMap: texture, transparent: false });
        */
        var material = new THREE.MeshPhongMaterial({
            color: THREE_COLORS["GRASSLAND"],
            wireframe: true
        });
        return new THREE.Mesh(geometry, material);
    },

    renderCells: function (group) {
        // Add a layer?
        for (var cellid in this.diagram.cells) {
            var cell = this.diagram.cells[cellid];
            var color = THREE_COLORS[cell.biome].clone();

            var cellPoints = [];
            var start = cell.halfedges[0].getStartpoint();
            cellPoints.push(new THREE.Vector2(start.x, start.y));
            for (var iHalfedge = 0; iHalfedge < cell.halfedges.length; iHalfedge++) {
                var halfEdge = cell.halfedges[iHalfedge];
                var end = halfEdge.getEndpoint();
                cellPoints.push(new THREE.Vector2(end.x, end.y));
            }
            var cellShape = new THREE.Shape(cellPoints);
            cellShape.autoClose = true; //just in case
            var cellGeometry = new THREE.ShapeBufferGeometry(cellShape);
            var cellMesh = new THREE.Mesh(cellGeometry, new THREE.MeshPhongMaterial({ color: color, side: THREE.DoubleSide }));
            //cellMesh.position.set(cell.site.x, cell.site.y, 0);
            //mesh.rotation.set(rx, ry, rz);
            //mesh.scale.set(s, s, s);
            group.add(cellMesh);
        }
    },

    renderMap: function () {
        var data = this.generateHeight();

        // var geometry = new THREE.PlaneBufferGeometry( 7500, 7500, worldWidth - 1, worldDepth - 1 ); ????
        var geometry = new THREE.PlaneBufferGeometry(this.config.width, this.config.height, this.config.width - 1, this.config.height - 1);
        //geometry.rotateX(- Math.PI / 2);

        // Set altitudes
        var vertices = geometry.attributes.position.array;
        for (var i = 0, j = 0, numVertices = vertices.length; i < numVertices; i += 3 , j ++) {
            vertices[i + 2] = data.elevations[j] * 10;
        }

        texture = new THREE.CanvasTexture(this.generateTexture(data, this.config.width, this.config.height));
        texture.wrapS = THREE.ClampToEdgeWrapping;
        texture.wrapT = THREE.ClampToEdgeWrapping;

        return new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ map: texture }));
    },

    populatePolygonsAndCells(polygonsX, polygonsY, cells) {
        for (var cellid in this.diagram.cells) {
            var polygonX = [];
            var polygonY = [];
            var cell = this.diagram.cells[cellid];

            // No need to process the ocean cells, the elevation there can be set to a fix number
            if (cell.ocean) {
                continue;
            }
            var start = cell.halfedges[0].getStartpoint();
            polygonX.push(start.x);
            polygonY.push(start.y);
            for (var iHalfedge = 0; iHalfedge < cell.halfedges.length - 1; iHalfedge++) {
                var halfEdge = cell.halfedges[iHalfedge];
                var end = halfEdge.getEndpoint();
                polygonX.push(end.x);
                polygonY.push(end.y);
            }
            cells.push(cell);
            polygonsX.push(polygonX);
            polygonsY.push(polygonY);
        }
    },

    generateHeight: function () {
        // Create polygons Paths
        var polygonsX = [];
        var polygonsY = [];
        var cells = [];
        this.populatePolygonsAndCells(polygonsX, polygonsY, cells);

        var halfWith = this.config.width / 2;
        var halfHeight = this.config.height / 2;

        var size = this.config.width * this.config.height;
        var data = new Object();
        data.elevations = new Uint8Array(size);
        data.biomes = new Array(size);

        for (var i = 0; i < size; i++) {
            data.elevations[i] = 0; // by default is 0
            data.biomes[i] = "OCEAN"; // by default is OCEAN
            var point = [i % this.config.width, Math.floor(i / this.config.height)];

            for (var cll = 0, numCells = cells.length; cll < numCells; cll++) {
                if (this.isPointInPolygon(point[0], point[1], polygonsX[cll], polygonsY[cll])) {
                    data.elevations[i] = cells[cll].realElevation * 10;
                    data.biomes[i] = cells[cll].biome;
                    break;
                }
            }
        }

        return data;
    },

    generateTexture: function(data, width, height) {
        var canvas, canvasScaled, context, image, imageData,
        level, diff, vector3, sun, shade;

        vector3 = new THREE.Vector3(0, 0, 0);

        sun = new THREE.Vector3(1, 1, 1);
        sun.normalize();

        canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;

        context = canvas.getContext('2d');
        context.fillStyle = '#000';
        context.fillRect(0, 0, width, height);

        image = context.getImageData(0, 0, canvas.width, canvas.height);
        imageData = image.data;

        for (var i = 0, j = 0, l = imageData.length; i < l; i += 4, j++) {

            vector3.x = data.elevations[j - 2] - data.elevations[j + 2];
            vector3.y = 2;
            vector3.z = data.elevations[j - width * 2] - data.elevations[j + width * 2];
            vector3.normalize();

            shade = vector3.dot(sun);

            imageData[i] = THREE_COLORS[data.biomes[j]].r * 255 * shade;  //(96 + shade * 128) * (0.5 + data.elevations[j] * 0.007);
            imageData[i + 1] = THREE_COLORS[data.biomes[j]].g * 255 * shade; //(32 + shade * 96) * (0.5 + data.elevations[j] * 0.007);
            imageData[i + 2] = THREE_COLORS[data.biomes[j]].b * 255 * shade; //(shade * 96) * (0.5 + data.elevations[j] * 0.007);
        }

        context.putImageData(image, 0, 0);

        // Scaled 4x

        canvasScaled = document.createElement('canvas');
        canvasScaled.width = width * 4;
        canvasScaled.height = height * 4;

        context = canvasScaled.getContext('2d');
        context.scale(4, 4);
        context.drawImage(canvas, 0, 0);

        image = context.getImageData(0, 0, canvasScaled.width, canvasScaled.height);
        imageData = image.data;

        for (var i = 0, l = imageData.length; i < l; i += 4) {

            var v = ~~(Math.random() * 5);

            imageData[i] += v;
            imageData[i + 1] += v;
            imageData[i + 2] += v;

        }

        context.putImageData(image, 0, 0);

        return canvasScaled;
    },

    isPointInPolygon: function (x, y, cornersX, cornersY) {
        var i, j = cornersX.length - 1;
        var oddNodes = false;

        var polyX = cornersX;
        var polyY = cornersY;

        for (i = 0; i < cornersX.length; i++) {
            if ((polyY[i] < y && polyY[j] >= y || polyY[j] < y && polyY[i] >= y) && (polyX[i] <= x || polyX[j] <= x)) {
                oddNodes ^= (polyX[i] + (y - polyY[i]) / (polyY[j] - polyY[i]) * (polyX[j] - polyX[i]) < x);
            }
            j = i;
        }

        return oddNodes;
    }
}

function animate() {
    requestAnimationFrame(animate);

    ThreeJsRenderer.renderer.render(ThreeJsRenderer.scene, ThreeJsRenderer.camera);
}<commit_msg>3d Render looking nice<commit_after>var THREE_COLORS = {
    OCEAN: new THREE.Color('#82caff'),
    BEACH: new THREE.Color('#ffe98d'),
    LAKE: new THREE.Color('#2f9ceb'),
    RIVER: new THREE.Color('#369eea'),
    SOURCE: new THREE.Color('#00f'),
    MARSH: new THREE.Color('#2ac6d3'),
    ICE: new THREE.Color('#b3deff'),
    ROCK: new THREE.Color('#535353'),
    LAVA: new THREE.Color('#e22222'),

    SNOW: new THREE.Color('#f8f8f8'),
    TUNDRA: new THREE.Color('#ddddbb'),
    BARE: new THREE.Color('#bbbbbb'),
    SCORCHED: new THREE.Color('#999999'),
    TAIGA: new THREE.Color('#ccd4bb'),
    SHRUBLAND: new THREE.Color('#c4ccbb'),
    TEMPERATE_DESERT: new THREE.Color('#e4e8ca'),
    TEMPERATE_RAIN_FOREST: new THREE.Color('#a4c4a8'),
    TEMPERATE_DECIDUOUS_FOREST: new THREE.Color('#b4c9a9'),
    GRASSLAND: new THREE.Color('#c4d4aa'),
    TROPICAL_RAIN_FOREST: new THREE.Color('#9cbba9'),
    TROPICAL_SEASONAL_FOREST: new THREE.Color('#a9cca4'),
    SUBTROPICAL_DESERT: new THREE.Color('#e9ddc7')
};

var ThreeJsRenderer = {
    canvas: null,
    diagram: null,
    sites: null,
    config: null,

    scene: null,
    camera: null,
    light: null,
    renderer: null,

    render: function (canvas, diagram, sites, config) {
        if (!diagram || !sites || !config) {
            console.error("ThreeJsRenderer.render method requires a not null diagram, sites and config parameters");
            return;
        }
        this.canvas = canvas;
        this.diagram = diagram;
        this.sites = sites;
        this.config = config;

        // Scene
        this.scene = new THREE.Scene();
        //this.scene.background = new THREE.Color(0xcce0ff);
        //this.scene.fog = new THREE.Fog(0xcce0ff, 500, 10000);
        //this.scene.add(new THREE.AmbientLight(0x666666));

        // Camera
        this.camera = new THREE.PerspectiveCamera(75, 1, 1, 10000);
        this.camera.position.x = 0;
        this.camera.position.y = 0;
        this.camera.position.z = this.config.width * 4;
        this.scene.add(this.camera);

        // Light
        this.light = this.renderLight();
        this.scene.add(this.light);

        // Ground
        //var groundMaterial = new THREE.MeshPhongMaterial({ color: THREE_COLORS.OCEAN.clone(), side: THREE.DoubleSide })
        //var groundMesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(this.config.width, this.config.height), groundMaterial);
        //this.scene.add(groundMesh);

        // Renderer
        this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas});
        this.renderer.setSize(this.config.width*4, this.config.height*4);
        //this.renderer.physicallyCorrectLights = true;
        //this.renderer.gammaInput = true;
        //this.renderer.gammaOutput = true;
        //this.renderer.shadowMap.enabled = true;
        //this.renderer.toneMapping = THREE.ReinhardToneMapping;

        var plane = this.renderMap();
        this.scene.add(plane);

        // Controls
        var controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
        //controls.maxPolarAngle = Math.PI * 0.5;
        controls.minDistance = 1;
        controls.maxDistance = 7500;

        animate();

        console.info("Three render completed");
    },

    renderLight: function () {
        var bulbGeometry = new THREE.SphereGeometry(5, 16, 8);
        bulbLight = new THREE.PointLight(0xffee88, 1, 1000, 2);
        bulbMat = new THREE.MeshStandardMaterial({
            emissive: 0xffffee,
            emissiveIntensity: 1,
            color: 0x000000
        });
        bulbLight.add(new THREE.Mesh(bulbGeometry, bulbMat));
        bulbLight.position.x = 0;
        bulbLight.position.y = 0;
        bulbLight.position.z = this.config.width * 4;
        bulbLight.castShadow = true;

        return bulbLight;
    },

    renderMap: function () {
        var data = this.generateHeight();

        // var geometry = new THREE.PlaneBufferGeometry( 7500, 7500, worldWidth - 1, worldDepth - 1 ); ????
        var geometry = new THREE.PlaneBufferGeometry(this.config.width*4, this.config.height*4, this.config.width - 1, this.config.height - 1);
        //geometry.rotateX(- Math.PI / 2);

        // Set altitudes
        var vertices = geometry.attributes.position.array;
        for (var i = 0, j = 0, numVertices = vertices.length; i < numVertices; i += 3 , j ++) {
            vertices[i + 2] = data.elevations[j] * 100;
        }

        texture = new THREE.CanvasTexture(this.generateTexture(data, this.config.width, this.config.height));
        texture.wrapS = THREE.ClampToEdgeWrapping;
        texture.wrapT = THREE.ClampToEdgeWrapping;

        return new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ map: texture }));
    },

    populatePolygonsAndCells(polygonsX, polygonsY, cells) {
        for (var cellid in this.diagram.cells) {
            var polygonX = [];
            var polygonY = [];
            var cell = this.diagram.cells[cellid];

            // No need to process the ocean cells, the elevation there can be set to a fix number
            if (cell.ocean) {
                continue;
            }
            var start = cell.halfedges[0].getStartpoint();
            polygonX.push(start.x);
            polygonY.push(start.y);
            for (var iHalfedge = 0; iHalfedge < cell.halfedges.length - 1; iHalfedge++) {
                var halfEdge = cell.halfedges[iHalfedge];
                var end = halfEdge.getEndpoint();
                polygonX.push(end.x);
                polygonY.push(end.y);
            }
            cells.push(cell);
            polygonsX.push(polygonX);
            polygonsY.push(polygonY);
        }
    },

    generateHeight: function () {
        // Create polygons Paths
        var polygonsX = [];
        var polygonsY = [];
        var cells = [];
        this.populatePolygonsAndCells(polygonsX, polygonsY, cells);

        var halfWith = this.config.width / 2;
        var halfHeight = this.config.height / 2;

        var size = this.config.width * this.config.height;
        var data = new Object();
        data.elevations = new Array(size);
        data.biomes = new Array(size);

        for (var i = 0; i < size; i++) {
            data.elevations[i] = 0; // by default is 0
            data.biomes[i] = "OCEAN"; // by default is OCEAN
            var point = [i % this.config.width, Math.floor(i / this.config.height)];

            for (var cll = 0, numCells = cells.length; cll < numCells; cll++) {
                if (this.isPointInPolygon(point[0], point[1], polygonsX[cll], polygonsY[cll])) {
                    //data.elevations[i] = cells[cll].realElevation;
                    data.elevations[i] = this.calculatePointRealElevation(point, cells[cll]);
                    data.biomes[i] = cells[cll].biome;
                    break;
                }
            }
        }

        return data;
    },

    generateTexture: function(data, width, height) {
        var canvas, canvasScaled, context, image, imageData,
        level, diff, vector3, sun, shade;

        vector3 = new THREE.Vector3(0, 0, 0);

        sun = new THREE.Vector3(1, 1, 1);
        sun.normalize();

        canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;

        context = canvas.getContext('2d');
        context.fillStyle = '#000';
        context.fillRect(0, 0, width, height);

        image = context.getImageData(0, 0, canvas.width, canvas.height);
        imageData = image.data;

        for (var i = 0, j = 0, l = imageData.length; i < l; i += 4, j++) {

            vector3.x = data.elevations[j - 2] - data.elevations[j + 2];
            vector3.y = 2;
            vector3.z = data.elevations[j - width * 2] - data.elevations[j + width * 2];
            vector3.normalize();

            shade = vector3.dot(sun);

            imageData[i] = THREE_COLORS[data.biomes[j]].r * 255 * shade;  //(96 + shade * 128) * (0.5 + data.elevations[j] * 0.007);
            imageData[i + 1] = THREE_COLORS[data.biomes[j]].g * 255 * shade; //(32 + shade * 96) * (0.5 + data.elevations[j] * 0.007);
            imageData[i + 2] = THREE_COLORS[data.biomes[j]].b * 255 * shade; //(shade * 96) * (0.5 + data.elevations[j] * 0.007);
        }

        context.putImageData(image, 0, 0);

        // Scaled 4x

        canvasScaled = document.createElement('canvas');
        canvasScaled.width = width * 4;
        canvasScaled.height = height * 4;

        context = canvasScaled.getContext('2d');
        context.scale(4, 4);
        context.drawImage(canvas, 0, 0);

        image = context.getImageData(0, 0, canvasScaled.width, canvasScaled.height);
        imageData = image.data;

        for (var i = 0, l = imageData.length; i < l; i += 4) {

            var v = ~~(Math.random() * 5);

            imageData[i] += v;
            imageData[i + 1] += v;
            imageData[i + 2] += v;

        }

        context.putImageData(image, 0, 0);

        return canvasScaled;
    },

    calculatePointRealElevation: function (point, cell) {
        var distanceToOwnSite = this.calculate2dDistance(point, [cell.site.x, cell.site.y]);
        var ownSiteRealElevation = cell.realElevation;

        var distanceToClosestSites = 999999;
        var closestSiteRealElevation = 0;

        var neighbors = cell.getNeighborIds();
        for (var j = 0; j < neighbors.length; j++) {
            var neighborCell = this.diagram.cells[neighbors[j]];

            var distanceToNeighborSite = this.calculate2dDistance(point, [neighborCell.site.x, neighborCell.site.y]);
            if (distanceToNeighborSite < distanceToClosestSites) {
                distanceToClosestSites = distanceToNeighborSite;
                closestSiteRealElevation = neighborCell.realElevation;
            }
        }

        return ((1-(distanceToOwnSite / (distanceToOwnSite + distanceToClosestSites))) * ownSiteRealElevation) +
            ((1-(distanceToClosestSites / (distanceToOwnSite + distanceToClosestSites))) * closestSiteRealElevation);
    },

    calculate2dDistance: function (point1, point2) {
        var a = point1[0] - point2[0];
        var b = point1[1] - point2[1];
        return Math.sqrt(a * a + b * b);
    },

    isPointInPolygon: function (x, y, cornersX, cornersY) {
        var i, j = cornersX.length - 1;
        var oddNodes = false;

        var polyX = cornersX;
        var polyY = cornersY;

        for (i = 0; i < cornersX.length; i++) {
            if ((polyY[i] < y && polyY[j] >= y || polyY[j] < y && polyY[i] >= y) && (polyX[i] <= x || polyX[j] <= x)) {
                oddNodes ^= (polyX[i] + (y - polyY[i]) / (polyY[j] - polyY[i]) * (polyX[j] - polyX[i]) < x);
            }
            j = i;
        }

        return oddNodes;
    }
}

function animate() {
    requestAnimationFrame(animate);

    ThreeJsRenderer.renderer.render(ThreeJsRenderer.scene, ThreeJsRenderer.camera);
}<|endoftext|>