<commit_before>Ui.Element.extend('Ui.Video',
/**@lends Ui.Video#*/
{
	src: undefined,
	oggSrc: undefined,
	mp3Src: undefined,
	webmSrc: undefined,
	loaddone: false,
	videoDrawing: undefined,
	playing: false,
	paused: false,
	naturalWidth: undefined,
	naturalHeight: undefined,

	/**
	 * @constructs
	 * @class
	 * @extends Ui.Element
	 */
	constructor: function(config) {
		this.addEvents('ready', 'ended', 'timeupdate');
		if((config.oggSrc != undefined) || (config.mp4Src != undefined) || (config.webmSrc != undefined)) {
			if((config.oggSrc != undefined) && (Ui.Video.supportOgg))
				this.setSrc(config.oggSrc);
			else if((config.mp4Src != undefined) && (Ui.Video.supportMp4))
				this.setSrc(config.mp4Src);
			else if((config.webmSrc != undefined) && (Ui.Video.supportWebm))
				this.setSrc(config.webmSrc);
			delete(config.oggSrc);
			delete(config.mp4Src);
			delete(config.webmSrc);
		}

	},

	/**
	 * Set the file URL for the current video element
	 */
	setSrc: function(src) {
		this.loaddone = false;
		this.src = src;

		if(Ui.Video.htmlVideo)
			this.videoDrawing.setAttribute('src', src);
	},

	/**
	 * Play the video element. If the element is already playing
	 * stop it and restart from the begining.
	 */
	play: function() {
		if(Ui.Video.htmlVideo) {
//			console.log('HTML5 video play '+this.videoDrawing.getAttribute('src'));
			try {
				this.videoDrawing.pause();
				this.videoDrawing.currentTime = 0;
				this.videoDrawing.load();
			} catch(e) {}
			this.videoDrawing.play();
		}
		this.playing = true;
		this.paused = false;
	},

	/**
	 * Pause the video element. If the element is not
	 * currently playing, do nothing.
	 */
	pause: function() {
		if(!this.playing || this.paused)
			return;
		this.paused = true;
		if(Ui.Video.htmlVideo)
			this.videoDrawing.pause();
	},

	/**
	 * Stop the video if playing.
	 */
	stop: function() {
		if(!this.playing)
			return;
		if(!this.paused) {
			if(Ui.Video.htmlVideo) {
				this.videoDrawing.pause();
				this.videoDrawing.currentTime = 0;
			}
		}
		this.onEnded();
	},

	/**
	 * Resume the videl element if in paused else
	 * do nothing.
	 */
	resume: function() {
		if(!this.playing || !this.paused)
			return;
		this.paused = false;
		if(Ui.Video.htmlVideo)
			this.videoDrawing.play();
	},

	/**
	 * Set the audio volume between 0 and 1
	 */
	setVolume: function(volume) {
		if(Ui.Video.htmlVideo)
			this.videoDrawing.volume = volume;
	},

	/**
	 * Get the audio volume between 0 and 1
	 */
	getVolume: function() {
		if(Ui.Video.htmlVideo)
			return this.videoDrawing.volume;
		return 1;
	},

	/**
	 * Return the duration in seconds of the video file
	 * or undefined if unknown. This value is only known
	 * after the ready event.
	 */
	getDuration: function() {
		return this.videoDrawing.duration;
	},

	/**
	 * Return the natural width of the image as defined
	 * in the image file. Return undefined if the image is
	 * not ready
	 */
	getNaturalWidth: function() {
		return this.naturalWidth;
	},

	/**
	 * Return the natural height of the image as defined
	 * in the image file. Return undefined if the image is
	 * not ready
	 */
	getNaturalHeight: function() {
		return this.naturalHeight;
	},

	//
	// Private
	//

	onReady: function() {
//		console.log('Video.onReady');
		this.naturalWidth = this.videoDrawing.videoWidth;
		this.naturalHeight = this.videoDrawing.videoHeight;
		this.fireEvent('ready');
	},

	onTimeupdate: function() {
//		console.log('Video.onTimeupdate');
		this.fireEvent('timeupdate', this.videoDrawing.currentTime);
	},

	onEnded: function() {
//		console.log('Video.onEnded');
		this.playing = false;
		this.fireEvent('ended');
	}
},
/**@lends Ui.Video#*/
{
	render: function() {
		var drawing;
		if(Ui.Video.htmlVideo) {
			this.videoDrawing = document.createElement('video');
			this.connect(this.videoDrawing, 'canplaythrough', this.onReady);
			this.connect(this.videoDrawing, 'ended', this.onEnded);
			this.connect(this.videoDrawing, 'timeupdate', this.onTimeupdate);
			this.videoDrawing.setAttribute('preload', 'auto');
			this.videoDrawing.load();
			this.videoDrawing.style.position = 'absolute';
			this.videoDrawing.style.left = '0px';
			this.videoDrawing.style.top = '0px';
			drawing = this.videoDrawing;
		}
		return drawing;
	},

	arrangeCore: function(width, height) {
		if(Ui.Video.htmlVideo) {
			this.videoDrawing.setAttribute('width', width);
			this.videoDrawing.setAttribute('height', height);
			// correct webkit bug
//			if(navigator.isWebkit) {
//				var matrix = this.foreignObject.getScreenCTM();
//				this.videoDrawing.style.webkitTransform = 'matrix('+matrix.a.toFixed(4)+','+matrix.b.toFixed(4)+','+matrix.c.toFixed(4)+','+matrix.d.toFixed(4)+','+matrix.e.toFixed(4)+','+matrix.f.toFixed(4)+')';
//				this.videoDrawing.style.webkitTransformOrigin = '0px 0px';
//			}
			// correct IE that handle nothing
//			if(navigator.isIE) {
//				var matrix = this.foreignObject.getScreenCTM();
//				this.videoDrawing.style.left = matrix.e+'px';
//				this.videoDrawing.style.top = matrix.f+'px';
//			}
		}
	}
});

// detect what video system is supported
Ui.Video.htmlVideo = false;
Ui.Video.flashVideo = false;
Ui.Video.supportOgg = false;
Ui.Video.supportMp4 = false;
Ui.Video.supportWebm = false;

// check for HTMLVideoElement
Ui.Video.videoTest = document.createElement('video');
if(Ui.Video.videoTest.play != undefined) {
	Ui.Video.htmlVideo = true;
	Ui.Video.supportMp4 = !!Ui.Video.videoTest.canPlayType && "" != Ui.Video.videoTest.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');
	Ui.Video.supportOgg = !!Ui.Video.videoTest.canPlayType && "" != Ui.Video.videoTest.canPlayType('video/ogg; codecs="theora, vorbis"');
	Ui.Video.supportWebm = !!Ui.Video.videoTest.canPlayType && "" != Ui.Video.videoTest.canPlayType('video/webm; codecs="vp8, vorbis"');
}
// TODO: flash support
//		Ui.Video.flashVideo = true;
Ui.Video.videoTest = undefined;

//console.log('Video rendering HTML: '+Ui.Video.htmlVideo+', Flash: '+Ui.Video.flashVideo);
//console.log('Video format OGG: '+Ui.Video.supportOgg+', MP4: '+Ui.Video.supportMp4+', WebM: '+Ui.Video.supportWebm);
<commit_msg>improve Ui.Video to start handling buffering problem<commit_after>Ui.Element.extend('Ui.Video',
/**@lends Ui.Video#*/
{
	src: undefined,
	oggSrc: undefined,
	mp3Src: undefined,
	webmSrc: undefined,
	loaddone: false,
	videoDrawing: undefined,
	playing: false,
	paused: false,
	naturalWidth: undefined,
	naturalHeight: undefined,
	canplaythrough: false,

	/**
	 * @constructs
	 * @class
	 * @extends Ui.Element
	 */
	constructor: function(config) {
		this.addEvents('ready', 'ended', 'timeupdate');
		this.connect(this, 'unload', this.onVideoUnload);
		if((config.oggSrc != undefined) || (config.mp4Src != undefined) || (config.webmSrc != undefined)) {
			if((config.oggSrc != undefined) && (Ui.Video.supportOgg))
				this.setSrc(config.oggSrc);
			else if((config.mp4Src != undefined) && (Ui.Video.supportMp4))
				this.setSrc(config.mp4Src);
			else if((config.webmSrc != undefined) && (Ui.Video.supportWebm))
				this.setSrc(config.webmSrc);
			delete(config.oggSrc);
			delete(config.mp4Src);
			delete(config.webmSrc);
		}
	},

	/**
	 * Set the file URL for the current video element
	 */
	setSrc: function(src) {
		this.loaddone = false;
		this.src = src;
		if(Ui.Video.htmlVideo)
			this.videoDrawing.setAttribute('src', src);
	},

	/**
	 * Play the video element. If the element is already playing
	 * stop it and restart from the begining.
	 */
	play: function() {
		if(Ui.Video.htmlVideo) {
			console.log('HTML5 video play '+this.videoDrawing.getAttribute('src'));
			if(!this.canplaythrough) {
				try {
					this.videoDrawing.load();
				} catch(e) {}
			}
			else {
				try {
					this.videoDrawing.play();

//					this.videoDrawing.pause();
//					this.videoDrawing.currentTime = 0;
	//				this.videoDrawing.load();
				} catch(e) {}
//			this.videoDrawing.play();
			}
		}
		this.playing = true;
		this.paused = false;
	},

	/**
	 * Pause the video element. If the element is not
	 * currently playing, do nothing.
	 */
	pause: function() {
		if(!this.playing || this.paused)
			return;
		this.paused = true;
		if(Ui.Video.htmlVideo)
			this.videoDrawing.pause();
	},

	/**
	 * Stop the video if playing.
	 */
	stop: function() {
		if(!this.playing)
			return;
		if(!this.paused) {
			if(Ui.Video.htmlVideo) {
				this.videoDrawing.pause();
				this.videoDrawing.currentTime = 0;
			}
		}
		this.onEnded();
	},

	/**
	 * Resume the videl element if in paused else
	 * do nothing.
	 */
	resume: function() {
		if(!this.playing || !this.paused)
			return;
		this.paused = false;
		if(Ui.Video.htmlVideo)
			this.videoDrawing.play();
	},

	/**
	 * Set the audio volume between 0 and 1
	 */
	setVolume: function(volume) {
		if(Ui.Video.htmlVideo)
			this.videoDrawing.volume = volume;
	},

	/**
	 * Get the audio volume between 0 and 1
	 */
	getVolume: function() {
		if(Ui.Video.htmlVideo)
			return this.videoDrawing.volume;
		return 1;
	},

	/**
	 * Return the duration in seconds of the video file
	 * or undefined if unknown. This value is only known
	 * after the ready event.
	 */
	getDuration: function() {
		return this.videoDrawing.duration;
	},

	/**
	 * Return the natural width of the image as defined
	 * in the image file. Return undefined if the image is
	 * not ready
	 */
	getNaturalWidth: function() {
		return this.naturalWidth;
	},

	/**
	 * Return the natural height of the image as defined
	 * in the image file. Return undefined if the image is
	 * not ready
	 */
	getNaturalHeight: function() {
		return this.naturalHeight;
	},

	//
	// Private
	//

	onReady: function() {
		this.naturalWidth = this.videoDrawing.videoWidth;
		this.naturalHeight = this.videoDrawing.videoHeight;
		this.fireEvent('ready');
		this.canplaythrough = true;
		if(this.playing)
			this.videoDrawing.play();
	},

	onTimeupdate: function() {
		this.checkBuffering();
		this.fireEvent('timeupdate', this.videoDrawing.currentTime);
	},

	onEnded: function() {
		this.playing = false;
		this.fireEvent('ended');
	},

	onWaiting: function() {
		if(this.playing)
			this.videoDrawing.pause();
	},

	getCurrentBufferSize: function() {
		var buffered = this.videoDrawing.buffered;
		var timebuffer = 0;
		var time = this.videoDrawing.currentTime;
		for(var i = 0; i < buffered.length; i++) {
			var start = buffered.start(i);
			var end = buffered.end(i);
			if((start <= time) && (end >= time)) {
				timebuffer = end - time;
				break;
			}
		}
		return timebuffer;
	},

	checkBuffering: function() {
		if(this.playing) {
			var timebuffer = this.getCurrentBufferSize();
			var time = this.videoDrawing.currentTime;
			var duration = this.videoDrawing.duration;
			if(time >= duration)
				return;
			if(this.videoDrawing.paused) {
				if((timebuffer > 5) || (time + timebuffer >= duration))
					this.videoDrawing.play();
			}
			else {
				if((timebuffer < 1) && (time + timebuffer < duration))
					this.videoDrawing.pause();
			}
		}
	},

	onVideoUnload: function() {
		this.playing = false;
		this.videoDrawing.pause();
	}
},
/**@lends Ui.Video#*/
{
	render: function() {
		var drawing;
		if(Ui.Video.htmlVideo) {
			this.videoDrawing = document.createElement('video');
			this.connect(this.videoDrawing, 'canplaythrough', this.onReady);
			this.connect(this.videoDrawing, 'ended', this.onEnded);
			this.connect(this.videoDrawing, 'timeupdate', this.onTimeupdate);
			this.connect(this.videoDrawing, 'progress', this.checkBuffering);
			this.connect(this.videoDrawing, 'waiting', this.onWaiting);
			this.videoDrawing.setAttribute('preload', 'auto');
			this.videoDrawing.load();
			this.videoDrawing.style.position = 'absolute';
			this.videoDrawing.style.left = '0px';
			this.videoDrawing.style.top = '0px';
			drawing = this.videoDrawing;
		}
		return drawing;
	},

	arrangeCore: function(width, height) {
		if(Ui.Video.htmlVideo) {
			this.videoDrawing.setAttribute('width', width);
			this.videoDrawing.setAttribute('height', height);
			// correct webkit bug
//			if(navigator.isWebkit) {
//				var matrix = this.foreignObject.getScreenCTM();
//				this.videoDrawing.style.webkitTransform = 'matrix('+matrix.a.toFixed(4)+','+matrix.b.toFixed(4)+','+matrix.c.toFixed(4)+','+matrix.d.toFixed(4)+','+matrix.e.toFixed(4)+','+matrix.f.toFixed(4)+')';
//				this.videoDrawing.style.webkitTransformOrigin = '0px 0px';
//			}
			// correct IE that handle nothing
//			if(navigator.isIE) {
//				var matrix = this.foreignObject.getScreenCTM();
//				this.videoDrawing.style.left = matrix.e+'px';
//				this.videoDrawing.style.top = matrix.f+'px';
//			}
		}
	}
});

// detect what video system is supported
Ui.Video.htmlVideo = false;
Ui.Video.flashVideo = false;
Ui.Video.supportOgg = false;
Ui.Video.supportMp4 = false;
Ui.Video.supportWebm = false;

// check for HTMLVideoElement
Ui.Video.videoTest = document.createElement('video');
if(Ui.Video.videoTest.play != undefined) {
	Ui.Video.htmlVideo = true;
	Ui.Video.supportMp4 = !!Ui.Video.videoTest.canPlayType && "" != Ui.Video.videoTest.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');
	Ui.Video.supportOgg = !!Ui.Video.videoTest.canPlayType && "" != Ui.Video.videoTest.canPlayType('video/ogg; codecs="theora, vorbis"');
	Ui.Video.supportWebm = !!Ui.Video.videoTest.canPlayType && "" != Ui.Video.videoTest.canPlayType('video/webm; codecs="vp8, vorbis"');
}
// TODO: flash support
//		Ui.Video.flashVideo = true;
Ui.Video.videoTest = undefined;

//console.log('Video rendering HTML: '+Ui.Video.htmlVideo+', Flash: '+Ui.Video.flashVideo);
//console.log('Video format OGG: '+Ui.Video.supportOgg+', MP4: '+Ui.Video.supportMp4+', WebM: '+Ui.Video.supportWebm);
<|endoftext|>


<commit_before>/**
 * FormAjaxValidate.js
 *
 * @category   BaseZF_JS_Helper
 * @package    BaseZF
 * @copyright  Copyright (c) 2008 BaseZF
 * @author     Harold Thétiot (hthetiot)
 */

if (typeof BaseZF == "undefined") var BaseZF = {};
if (typeof BaseZF.Helper == "undefined") BaseZF.Helper = {};

BaseZF.Helper.FormAjaxValidate = new Class({

    Extends: BaseZF.Helper.Abstract,
    Implements: BaseZF.Helper.AjaxAbstract,

    elements: {
        form: null,
        containers: []
    },

    focusField: null,
    lastField: null,

    options: {
        scroll: true
    },

    initializeSelector: function(root, options) {

        if (!$type(root)) {
            var root = document;
        }

        root.getElements('form.formAjaxValidate').each(function(element) {
            new BaseZF.Helper.FormAjaxValidate('element', element, options);
        }, this);
    },

    initializeElement: function(element, options) {

        // check semaphore
        if (0) {
        }

        // init datas
        this.elements.form = element;
        this.options = $merge(this.options, options);

        // init fields validators
        this.initFields();
    },

    initFields: function() {

        this.elements.containers = [];

        // get fields container required
        this.elements.form.getElements('div.required, div.optional').each( function(container) {

            // save container
            this.elements.containers.push(container);

            // get field of container
            this.getFields(container).each(function(field) {

                // save container to field
                field.store('formContainer', container);

                // add validation events
                this.initFieldEvents(field);

                // set current state
                if(this.hasError(field)) {
                    container.store('lastErrorValue', this.toQueryString(container));
                }

            }, this);

        }, this);
    },

    initFieldEvents: function(field) {

        var eventNames = new Array();

        switch (field.type) {
            case 'radio':
            case 'checkbox':
            case 'select-one':
            case 'select-multiple':
               eventNames.push('change');
               break;

           case 'password':
           case 'text':
               eventNames.push('onEnter');
               eventNames.push('blur');
               break;

           case 'file':
           case 'reset':
           case 'submit':
               // field with no validators
               break;

            default:
               eventNames.push('blur');
               break;
        }

        // add event validation
        eventNames.each(function(eventName) {

            if (eventName == 'onEnter') {

                field.addEvent('keydown', function(e) {
                    if(new Event(e).code == Event.Keys.esc || new Event(e).code == Event.Keys.enter) {
                        $clear(this.validationTimer);
                        this.validationTimer = this.processFieldValidation.delay(250, this, field);
                        return false;
                    }
                }.bind(this));

            } else {

                field.addEvent(eventName, function(e) {

                    var isEmpty = (field.value.length == 0);

                    if (field.retrieve('formContainer').hasClass('optional') && isEmpty) {
                        return;
                    } else if (eventName != 'blur') {
                        this.processFieldValidation(field);
                        return;
                    }

                    // direct process to validation asap have value
                    if (!isEmpty) {
                        this.processFieldValidation(field);

                    // delay validation cause is empty and can from a tab usage
                    } else {
                        $clear(this.validationTimer);
                        this.validationTimer = this.processFieldValidation.delay(250, this, field);
                    }

                }.bind(this));
            }

        }, this);

        field.addEvent('focus', function(e) {
            this.focusField = field;
        }.bind(this));
    },

    /**
     * Html builder/Fx
     */

    scrollToField: function(field) {

        if ($type(this.options.scroll)) {

            var scroll = new Fx.Scroll(document, {
                wait: false,
                duration: 1500,
                offset: {'x': -100, 'y': -50},
                transition: Fx.Transitions.Quad.easeInOut
            });

            scroll.toElement(field);
        }

        try {
            field.fireEvent('focus').focus();
        } catch(e){
            //IE barfs if you call focus on hidden elements
        }
    },

    addFieldErrors: function(field, errorsMsg, clear) {

        var container = field.retrieve('formContainer');
        var fieldValue = this.toQueryString(container);

        if ($type(clear)) {
            container.getElement('.error').destroy();
        }

        // update lastErrorValue
        container.store('lastErrorValue', fieldValue);

        // build errorsMsg
        container.addClass('error');
        container.removeClass('validate');

        var errorList = new Element('ul', {'class': 'errors'});
        $H(errorsMsg).each(function(error, errorType) {
            var errorEntry = new Element('li').appendText(error);
            errorEntry.inject(errorList);
        });

        errorList.injectTop(container);
    },

    clearFieldErrors: function(field) {

        // get container
        var container = field.retrieve('formContainer');

        if (container.hasClass('error')) {
            container.getElement('.errors').destroy();
            container.store('lastErrorValue', null);
            container.removeClass('error');
        }
    },

    clearErrors: function() {

        this.elements.containers.each( function(container) {
            container.getElement('.error').destroy();
            container.store('lastErrorValue', null);
            container.removeClass('error');
        });
    },

    hasError: function(field)
    {
        return field.retrieve('formContainer').hasClass('error');
    },

    /**
     * Ajax Validation
     */
    beginTransaction: function(nb)
    {
        // disable submit
        this.toggleFormSubmit(true);
    },

    commitTransaction: function()
    {
        // enable submit
        this.toggleFormSubmit(false);
    },

    roolBackTransaction: function()
    {
        // enable submit
        this.toggleFormSubmit(false);
    },

    updateFieldCache: function(field, errorsMsg) {

        // get container
        var container = field.retrieve('formContainer');

        // update cache
        var fieldValue = this.toQueryString(container);
        var validationCache = container.retrieve('validationCache', $H());
        if (!validationCache.has(fieldValue)) {
            validationCache.set(fieldValue, errorsMsg);
        }
    },

    processFieldValidation: function(field)
    {
        // is a field for check previous value ?
        var parentField = this.getParentField(field);
        if ($type(parentField) == 'element') {

            // validate parent field if has value and no error
            if(this.hasError(parentField)) {
                this.scrollToField(parentField);
            } else if (parentField.value.length > 0) {
                field = parentField;
            }
        }

        var container = field.retrieve('formContainer');

        // do not valid same error value
        if (
            this.hasError(field) &&
            container.retrieve('lastErrorValue') == this.toQueryString(container)
        ) {
            return;
        }

        // do not valid field on back jump
        if (
              $type(this.focusField) &&
              this.focusField != field &&
              this.hasError(this.focusField)
        ) {
            return;
        }

        // disable form submit
        this.beginTransaction();

        // clear field errors
        this.clearFieldErrors(field);

        // has values to validate
        var fieldValue = this.toQueryString(container);
        var validationCache = container.retrieve('validationCache', $H());

        if (validationCache.has(fieldValue)) {

            var errorMsg = validationCache.get(fieldValue);
            if (errorMsg !== null) {
                this.addFieldErrors(field, errorMsg);
                this.scrollToField(field);
            }

        } else {

            // set field has loading
            container.removeClass('validate');
            container.addClass('loading');

            var myRequest = this.getRequest({
                method: this.elements.form.get('method'),
                url: this.elements.form.get('action'),
                data: fieldValue,
                link: 'chain'
            }, 'JSON');

            myRequest.send();
        }
    },

    requestCallback: function(json, b)
    {
        try {

            var fieldErrors = $H(json);

            // add error on field
            fieldErrors.each(function(errorsMsg, field) {

                var field = this.elements.form.getElement('[name^=' + field + ']');

                // ignore missing fields
                if($type(field) == false) {
                    return;
                }

                var container = field.retrieve('formContainer');

                // add error is needed
                if (errorsMsg != null) {
                    this.addFieldErrors(field, errorsMsg);
                // add validate
                } else {
                    container.addClass('validate');
                }

                // update cache
                this.updateFieldCache(field, errorsMsg);

                // hide loading
                container.removeClass('loading');

                this.lastField = field;

            }, this);

            this.scrollToField(this.lastField);

        } catch (e) {

            console.info(e);

            throw e;
        }
    },

    /**
     * Tools
     */

    getParentField: function(field) {

        if (field.name.contains('_check')) {
            return this.elements.form.getElement('[name=' + field.name.replace('_check','') + ']')
        }
    },

    getFieldCheck: function(field) {
        return this.elements.form.getElement('[name=' + field.name + '_check]')
    },

    getFields: function(root) {

        // get by name
        fieldElements = root.getElements('input, select, textarea');

        return fieldElements;
    },

    getFieldContainer: function(field) {
        return field.retrieve('formContainer');
    },

    toggleFormSubmit: function(state)
    {
        this.elements.form.getElement('input[type=submit]').disabled = (state) ? false : true ;
    },

    toQueryString: function(root){

        if (!$type(root)) {
            var root = this.elements.form;
        }

        var elementsValues = $H();
        var elements = root.getElements('input, select, textarea');

        elements.each(function(el) {

            if (!el.name || el.disabled) return;

            var value = '';
            var type = el.type;
            var tagName = el.tagName.toLowerCase();
            var name = el.name;
            var values = $splat(elementsValues.get(name));

            if (tagName == 'select') {

            Element.getSelected(el).each(function(opt){
                values.push(opt.value);
            });

            } else if (type == 'radio' && el.checked) {
                values.push(el.value);
            } else if (type == 'checkbox' && el.checked) {
                values.push(el.value);
            } else if (type == 'password' || type == 'text' || type == 'textarea') {

                // is a field for check previous value ?
                var parentField = this.getParentField(el);
                if ($type(parentField)) {
                    elementsValues.set(parentField.name, [parentField.value]);
                }

                values.push(el.value);
            }

            elementsValues.set(name, values);

        }, this);

        var queryString = [];
        elementsValues.each(function(values, name) {

            if (values.length == 0) {
                queryString.push(name + '=');
            } else {
                values.each(function(value) {
                    queryString.push(name + '=' + encodeURIComponent(value));
                });
            }
        });

        return queryString.join('&');
    },
});

<commit_msg>fix scroll on formAjaxValidation<commit_after>/**
 * FormAjaxValidate.js
 *
 * @category   BaseZF_JS_Helper
 * @package    BaseZF
 * @copyright  Copyright (c) 2008 BaseZF
 * @author     Harold Thétiot (hthetiot)
 */

if (typeof BaseZF == "undefined") var BaseZF = {};
if (typeof BaseZF.Helper == "undefined") BaseZF.Helper = {};

BaseZF.Helper.FormAjaxValidate = new Class({

    Extends: BaseZF.Helper.Abstract,
    Implements: BaseZF.Helper.AjaxAbstract,

    elements: {
        form: null,
        containers: []
    },

    focusField: null,
    lastField: null,

    options: {
        scroll: true
    },

    initializeSelector: function(root, options) {

        if (!$type(root)) {
            var root = document;
        }

        root.getElements('form.formAjaxValidate').each(function(element) {
            new BaseZF.Helper.FormAjaxValidate('element', element, options);
        }, this);
    },

    initializeElement: function(element, options) {

        // check semaphore
        if (0) {
        }

        // init datas
        this.elements.form = element;
        this.options = $merge(this.options, options);

        // init fields validators
        this.initFields();
    },

    initFields: function() {

        this.elements.containers = [];

        // get fields container required
        this.elements.form.getElements('div.required, div.optional').each( function(container) {

            // save container
            this.elements.containers.push(container);

            // get field of container
            this.getFields(container).each(function(field) {

                // save container to field
                field.store('formContainer', container);

                // add validation events
                this.initFieldEvents(field);

                // set current state
                if(this.hasError(field)) {
                    container.store('lastErrorValue', this.toQueryString(container));
                }

            }, this);

        }, this);
    },

    initFieldEvents: function(field) {

        var eventNames = new Array();

        switch (field.type) {
            case 'radio':
            case 'checkbox':
            case 'select-one':
            case 'select-multiple':
               eventNames.push('change');
               break;

           case 'password':
           case 'text':
               eventNames.push('onEnter');
               eventNames.push('blur');
               break;

           case 'file':
           case 'reset':
           case 'submit':
               // field with no validators
               break;

            default:
               eventNames.push('blur');
               break;
        }

        // add event validation
        eventNames.each(function(eventName) {

            if (eventName == 'onEnter') {

                field.addEvent('keydown', function(e) {
                    if(new Event(e).code == Event.Keys.esc || new Event(e).code == Event.Keys.enter) {
                        $clear(this.validationTimer);
                        this.validationTimer = this.processFieldValidation.delay(250, this, field);
                        return false;
                    }
                }.bind(this));

            } else {

                field.addEvent(eventName, function(e) {

                    var isEmpty = (field.value.length == 0);

                    if (field.retrieve('formContainer').hasClass('optional') && isEmpty) {
                        return;
                    } else if (eventName != 'blur') {
                        this.processFieldValidation(field);
                        return;
                    }

                    // direct process to validation asap have value
                    if (!isEmpty) {
                        this.processFieldValidation(field);

                    // delay validation cause is empty and can from a tab usage
                    } else {
                        $clear(this.validationTimer);
                        this.validationTimer = this.processFieldValidation.delay(250, this, field);
                    }

                }.bind(this));
            }

        }, this);

        field.addEvent('focus', function(e) {
            this.focusField = field;
        }.bind(this));
    },

    /**
     * Html builder/Fx
     */

    scrollToField: function(field) {

        if ($type(this.options.scroll)) {

            var scroll = new Fx.Scroll(document, {
                wait: false,
                duration: 1500,
                offset: {'x': -100, 'y': -50},
                transition: Fx.Transitions.Quad.easeInOut
            });

            scroll.toElement(field);
        }

        try {
            field.fireEvent('focus').focus();
        } catch(e){
            //IE barfs if you call focus on hidden elements
        }
    },

    addFieldErrors: function(field, errorsMsg, clear) {

        var container = field.retrieve('formContainer');
        var fieldValue = this.toQueryString(container);

        if ($type(clear)) {
            container.getElement('.error').destroy();
        }

        // update lastErrorValue
        container.store('lastErrorValue', fieldValue);

        // build errorsMsg
        container.addClass('error');
        container.removeClass('validate');

        var errorList = new Element('ul', {'class': 'errors'});
        $H(errorsMsg).each(function(error, errorType) {
            var errorEntry = new Element('li').appendText(error);
            errorEntry.inject(errorList);
        });

        errorList.injectTop(container);
    },

    clearFieldErrors: function(field) {

        // get container
        var container = field.retrieve('formContainer');

        if (container.hasClass('error')) {
            container.getElement('.errors').destroy();
            container.store('lastErrorValue', null);
            container.removeClass('error');
        }
    },

    clearErrors: function() {

        this.elements.containers.each( function(container) {
            container.getElement('.error').destroy();
            container.store('lastErrorValue', null);
            container.removeClass('error');
        });
    },

    hasError: function(field)
    {
        return field.retrieve('formContainer').hasClass('error');
    },

    /**
     * Ajax Validation
     */
    beginTransaction: function(nb)
    {
        // disable submit
        this.toggleFormSubmit(true);
    },

    commitTransaction: function()
    {
        // enable submit
        this.toggleFormSubmit(false);
    },

    roolBackTransaction: function()
    {
        // enable submit
        this.toggleFormSubmit(false);
    },

    updateFieldCache: function(field, errorsMsg) {

        // get container
        var container = field.retrieve('formContainer');

        // update cache
        var fieldValue = this.toQueryString(container);
        var validationCache = container.retrieve('validationCache', $H());
        if (!validationCache.has(fieldValue)) {
            validationCache.set(fieldValue, errorsMsg);
        }
    },

    processFieldValidation: function(field)
    {
        // is a field for check previous value ?
        var parentField = this.getParentField(field);
        if ($type(parentField) == 'element') {

            // validate parent field if has value and no error
            if(this.hasError(parentField)) {
                this.scrollToField(parentField);
            } else if (parentField.value.length > 0) {
                field = parentField;
            }
        }

        var container = field.retrieve('formContainer');

        // do not valid same error value
        if (
            this.hasError(field) &&
            container.retrieve('lastErrorValue') == this.toQueryString(container)
        ) {
            return;
        }

        // do not valid field on back jump
        if (
              $type(this.focusField) &&
              this.focusField != field &&
              this.hasError(this.focusField)
        ) {
            return;
        }

        // disable form submit
        this.beginTransaction();

        // clear field errors
        this.clearFieldErrors(field);

        // has values to validate
        var fieldValue = this.toQueryString(container);
        var validationCache = container.retrieve('validationCache', $H());

        if (validationCache.has(fieldValue)) {

            var errorMsg = validationCache.get(fieldValue);
            if (errorMsg !== null) {
                this.addFieldErrors(field, errorMsg);
                this.scrollToField(field);
            }

        } else {

            // set field has loading
            container.removeClass('validate');
            container.addClass('loading');

            var myRequest = this.getRequest({
                method: this.elements.form.get('method'),
                url: this.elements.form.get('action'),
                data: fieldValue,
                link: 'chain'
            }, 'JSON');

            myRequest.send();
        }
    },

    requestCallback: function(json, b)
    {
        // reset last field
        this.lastField = null;

        try {

            var fieldErrors = $H(json);

            // add error on field
            fieldErrors.each(function(errorsMsg, field) {

                var field = this.elements.form.getElement('[name^=' + field + ']');

                // ignore missing fields
                if($type(field) == false) {
                    return;
                }

                var container = field.retrieve('formContainer');

                // add error is needed
                if (errorsMsg != null) {
                    this.addFieldErrors(field, errorsMsg);
                    this.lastField = field;
                // add validate
                } else {
                    container.addClass('validate');
                }

                // update cache
                this.updateFieldCache(field, errorsMsg);

                // hide loading
                container.removeClass('loading');

            }, this);

            if ($type(this.lastField) == 'element') {
                this.scrollToField(this.lastField);
            }

        } catch (e) {

            throw e;
        }
    },

    /**
     * Tools
     */

    getParentField: function(field) {

        if (field.name.contains('_check')) {
            return this.elements.form.getElement('[name=' + field.name.replace('_check','') + ']')
        }
    },

    getFieldCheck: function(field) {
        return this.elements.form.getElement('[name=' + field.name + '_check]')
    },

    getFields: function(root) {

        // get by name
        fieldElements = root.getElements('input, select, textarea');

        return fieldElements;
    },

    getFieldContainer: function(field) {
        return field.retrieve('formContainer');
    },

    toggleFormSubmit: function(state)
    {
        this.elements.form.getElement('input[type=submit]').disabled = (state) ? false : true ;
    },

    toQueryString: function(root){

        if (!$type(root)) {
            var root = this.elements.form;
        }

        var elementsValues = $H();
        var elements = root.getElements('input, select, textarea');

        elements.each(function(el) {

            if (!el.name || el.disabled) return;

            var value = '';
            var type = el.type;
            var tagName = el.tagName.toLowerCase();
            var name = el.name;
            var values = $splat(elementsValues.get(name));

            if (tagName == 'select') {

            Element.getSelected(el).each(function(opt){
                values.push(opt.value);
            });

            } else if (type == 'radio' && el.checked) {
                values.push(el.value);
            } else if (type == 'checkbox' && el.checked) {
                values.push(el.value);
            } else if (type == 'password' || type == 'text' || type == 'textarea') {

                // is a field for check previous value ?
                var parentField = this.getParentField(el);
                if ($type(parentField)) {
                    elementsValues.set(parentField.name, [parentField.value]);
                }

                values.push(el.value);
            }

            elementsValues.set(name, values);

        }, this);

        var queryString = [];
        elementsValues.each(function(values, name) {

            if (values.length == 0) {
                queryString.push(name + '=');
            } else {
                values.each(function(value) {
                    queryString.push(name + '=' + encodeURIComponent(value));
                });
            }
        });

        return queryString.join('&');
    },
});

<|endoftext|>


<commit_before>
JET.World = function(scene) {
	var v = new THREE.Vector3();

	// Lights
	var ambient = new THREE.AmbientLight(0x444444);
	scene.add(ambient);
	var sun = new THREE.DirectionalLight(0xffffff, 0.6);
	sun.position.set(1.0, 1.0, 2.0);
	scene.add(sun);

	// Sea
	var w = 10000, h = 5000;
	var seaTex = THREE.ImageUtils.loadTexture("assets/water.jpg");
	seaTex.wrapS = seaTex.wrapT = THREE.RepeatWrapping;
	seaTex.repeat.set(4, 2);
	var seaMat = new THREE.MeshBasicMaterial({ map: seaTex });
	var seaGeo = new THREE.PlaneGeometry(w, h);
	var sea = new THREE.Mesh(seaGeo, seaMat);
	scene.add(sea);

	// Clouds
	var cloudsInCluster = 4;
	var numClouds = 250 * cloudsInCluster;
	var cloudDist = 1500;
	var cloudTex = THREE.ImageUtils.loadTexture("assets/cloud1.png");
	var cloudMat = new THREE.ParticleBasicMaterial({
		size: 256,
		map: cloudTex,
		depthTest: true,
		depthWrite: false,
		transparent: true,
		opacity: 0.9
	});
	var cloudGeo = new THREE.BufferGeometry();
	cloudGeo.dynamic = true;
	cloudGeo.attributes = {
		position: {
			itemSize: 3,
			array: new Float32Array(numClouds * 3),
			numItems: numClouds * 3
		}
	};
	var vertex = new THREE.Vector3();
	var cloudPositions = cloudGeo.attributes.position.array;
	for (var i = 0, l = numClouds * 3; i < l; i += 3 * cloudsInCluster) {
		vertex.x = Math.random() * 2 * cloudDist - cloudDist;
		vertex.y = Math.random() * 2 * cloudDist - cloudDist;
		vertex.z = 500 + i/l * 1000;
		for (var j = 0; j < cloudsInCluster; ++j) {
			vertex.add(v.set(THREE.Math.randFloatSpread(100), THREE.Math.randFloatSpread(100), 0));
			cloudPositions[3*j+i  ] = vertex.x;
			cloudPositions[3*j+i+1] = vertex.y;
			cloudPositions[3*j+i+2] = vertex.z;
		}
	}
	var clouds = new THREE.ParticleSystem(cloudGeo, cloudMat);
	clouds.renderDepth = 1000;
	scene.add(clouds);

	this.update = function(position) {
		// Infinite ocean
		sea.position.x = position.x;
		sea.position.y = position.y;
		seaTex.offset.set(position.x / w * seaTex.repeat.x, position.y / h * seaTex.repeat.y);

		// Infinite clouds
		for (var i = 0, l = numClouds * 3; i < l; i += 3) {
			v.set(cloudPositions[i] - position.x, cloudPositions[i+1] - position.y, 0);
			if (Math.abs(v.x) > cloudDist) {
				cloudPositions[i] -= THREE.Math.sign(v.x) * cloudDist * 2;
				cloudGeo.verticesNeedUpdate = true;
			}
			if (Math.abs(v.y) > cloudDist) {
				cloudPositions[i+1] -= THREE.Math.sign(v.y) * cloudDist * 2;
				cloudGeo.verticesNeedUpdate = true;
			}
		}
	};
};
<commit_msg>More complex water material. Still not very good.<commit_after>
JET.World = function(scene) {
	var v = new THREE.Vector3();

	// Lights
	var ambient = new THREE.AmbientLight(0x444444);
	scene.add(ambient);
	var sun = new THREE.DirectionalLight(0xffffff, 0.6);
	sun.position.set(1.0, 1.0, 2.0);
	scene.add(sun);

	// Sea
	var w = 10000, h = 5000;
	var seaTex = THREE.ImageUtils.loadTexture("assets/water.jpg");
	seaTex.wrapS = seaTex.wrapT = THREE.RepeatWrapping;
	seaTex.repeat.set(4, 2);
	var seaMat = new THREE.MeshPhongMaterial({
		specular: 0xffffff,
		shininess: 100,
		map: seaTex,
		bumpMap: seaTex,
		bumpScale: 5.0,
	});
	var seaGeo = new THREE.PlaneGeometry(w, h);
	var sea = new THREE.Mesh(seaGeo, seaMat);
	scene.add(sea);

	// Clouds
	var cloudsInCluster = 4;
	var numClouds = 250 * cloudsInCluster;
	var cloudDist = 1500;
	var cloudTex = THREE.ImageUtils.loadTexture("assets/cloud1.png");
	var cloudMat = new THREE.ParticleBasicMaterial({
		size: 256,
		map: cloudTex,
		depthTest: true,
		depthWrite: false,
		transparent: true,
		opacity: 0.9
	});
	var cloudGeo = new THREE.BufferGeometry();
	cloudGeo.dynamic = true;
	cloudGeo.attributes = {
		position: {
			itemSize: 3,
			array: new Float32Array(numClouds * 3),
			numItems: numClouds * 3
		}
	};
	var vertex = new THREE.Vector3();
	var cloudPositions = cloudGeo.attributes.position.array;
	for (var i = 0, l = numClouds * 3; i < l; i += 3 * cloudsInCluster) {
		vertex.x = Math.random() * 2 * cloudDist - cloudDist;
		vertex.y = Math.random() * 2 * cloudDist - cloudDist;
		vertex.z = 500 + i/l * 1000;
		for (var j = 0; j < cloudsInCluster; ++j) {
			vertex.add(v.set(THREE.Math.randFloatSpread(100), THREE.Math.randFloatSpread(100), 0));
			cloudPositions[3*j+i  ] = vertex.x;
			cloudPositions[3*j+i+1] = vertex.y;
			cloudPositions[3*j+i+2] = vertex.z;
		}
	}
	var clouds = new THREE.ParticleSystem(cloudGeo, cloudMat);
	clouds.renderDepth = 1000;
	scene.add(clouds);

	this.update = function(position) {
		// Infinite ocean
		sea.position.x = position.x;
		sea.position.y = position.y;
		seaTex.offset.set(position.x / w * seaTex.repeat.x, position.y / h * seaTex.repeat.y);

		// Infinite clouds
		for (var i = 0, l = numClouds * 3; i < l; i += 3) {
			v.set(cloudPositions[i] - position.x, cloudPositions[i+1] - position.y, 0);
			if (Math.abs(v.x) > cloudDist) {
				cloudPositions[i] -= THREE.Math.sign(v.x) * cloudDist * 2;
				cloudGeo.verticesNeedUpdate = true;
			}
			if (Math.abs(v.y) > cloudDist) {
				cloudPositions[i+1] -= THREE.Math.sign(v.y) * cloudDist * 2;
				cloudGeo.verticesNeedUpdate = true;
			}
		}
	};
};
<|endoftext|>


<commit_before>function templ(strings, value) {
  const str0 = strings[0];
  const str1 = strings[1];
  if (Array.isArray(value)) {
    const o = value.map(x => x.value);
    const r = [];
    if (!value.length) {
      return '';
    }
    o.forEach((s) => {
      r.push(`${str0}${s}${str1}`);
    });
    return `AND (${r.join(' OR ')})`;
  }
  return `AND ${str0}${value.value !== undefined ? value.value : value}${str1}`;
}

function validate(p) {
  return p !== null && p !== undefined && p.length > 0 && p[0] !== null && p[0] !== undefined;
}

const queryTemplate = (props) => {
  const {
    select,
    group,
    minPatch,
    maxPatch,
    hero,
    player,
    league,
    playerPurchased,
    minDuration,
    maxDuration,
    side,
    result,
    team,
    organization,
    laneRole,
    region,
    minDate,
    maxDate,
    order,
    tier,
    having,
    limit,
    isTi7Team,
  } = props;
  // array inputs
  // group
  // hero
  // player
  // league
  // team
  // organization
  let query;
  let groupArray = [];
  let selectArray = [];
  if (!(Array.isArray(group))) {
    groupArray.push(group);
  } else {
    groupArray = group;
  }
  if (!(Array.isArray(select))) {
    selectArray.push(select);
  } else {
    selectArray = select;
  }
  selectArray = selectArray.filter(x => x !== undefined);
  groupArray = groupArray.filter(x => x !== undefined);
  groupArray.forEach((x) => {
    if (x.json_each) {
      selectArray.push(x);
    }
  });
  groupArray = groupArray.filter(x => !x.json_each);
  selectArray.forEach((x, index) => {
    if (x && x.groupValue) {
      const a = {
        value: x.groupKey, groupKeySelect: x.groupKeySelect, alias: x.alias, key: `key${index.toString()}`,
      };
      if (x.groupKey === 'key') {
        const p = x;
        a.value = `key${index.toString()}.key`;
        p.value = `key${index.toString()}.key`;
        p.join = `${x.join} key${index.toString()}`;
        p.groupValue = `key${index.toString()}.${x.groupValue}`;
      }
      groupArray.push(a);
    }
  });
  if (selectArray && selectArray.template === 'picks_bans') {
    query = `SELECT
hero_id,
count(1) total,
sum(is_pick::int) picks,
sum((NOT is_pick)::int) bans,
sum((is_pick IS TRUE AND ord < 8)::int) first_pick,
sum((is_pick IS FALSE AND ord < 8)::int) first_ban,
sum((is_pick IS TRUE AND ord >= 8 AND ord < 16)::int) second_pick,
sum((is_pick IS FALSE AND ord >= 8 AND ord < 16)::int) second_ban,
sum((is_pick IS TRUE AND ord >= 16)::int) third_pick,
sum((is_pick IS FALSE AND ord >= 16)::int) third_ban,
sum((radiant = radiant_win)::int)::float/count(1) winrate,
sum((radiant = radiant_win AND is_pick IS TRUE)::int)::float/NULLIF(sum(is_pick::int), 0) pick_winrate,
sum((radiant = radiant_win AND is_pick IS FALSE)::int)::float/NULLIF(sum((NOT is_pick)::int), 0) ban_winrate
FROM picks_bans
JOIN matches using(match_id)
JOIN match_patch using(match_id)
JOIN leagues using(leagueid)
JOIN team_match using(match_id)
JOIN teams using(team_id)
WHERE TRUE
${validate(selectArray) && selectArray.where ? selectArray.where : ''}
${organization ? `AND team_id = ${organization.value}` : ''}
${minPatch ? `AND match_patch.patch >= '${minPatch.value}'` : ''}
${maxPatch ? `AND match_patch.patch <= '${maxPatch.value}'` : ''}
${league ? `AND matches.leagueid = ${league.value}` : ''}
${minDuration ? `AND matches.duration >= ${minDuration.value}` : ''}
${maxDuration ? `AND matches.duration <= ${maxDuration.value}` : ''}
${side ? `AND team_match.radiant = ${side.value}` : ''}
${result ? `AND (team_match.radiant = matches.radiant_win) = ${result.value}` : ''}
${region ? `AND matches.cluster IN (${region.value.join(',')})` : ''}
${minDate ? `AND matches.start_time >= extract(epoch from timestamp '${new Date(minDate.value).toISOString()}')` : ''}
${maxDate ? `AND matches.start_time <= extract(epoch from timestamp '${new Date(maxDate.value).toISOString()}')` : ''}
${tier ? `AND leagues.tier = '${tier.value}'` : ''}
${isTi7Team ? 'AND teams.team_id IN (5, 15, 39, 46, 2163, 350190, 1375614, 1838315, 1883502, 2108395, 2512249, 2581813, 2586976, 2640025, 2672298, 1333179, 3331948, 1846548)' : ''}
GROUP BY hero_id
ORDER BY total ${(order && order.value) || 'DESC'}`;
  } else {
    const selectVal = {};
    const groupVal = {};
    if (validate(groupArray)) {
      groupArray.forEach((x) => { groupVal[x.key] = `${x.value}${x.bucket ? ` / ${x.bucket} * ${x.bucket}` : ''}`; });
    }
    if (validate(selectArray)) {
      selectArray.forEach((x) => { selectVal[x.key] = x.groupValue || (x && x.value) || 1; });
    }
    query = `SELECT
    ${validate(selectArray) ? selectArray.map(x => (x.distinct && !validate(groupArray) ? `DISTINCT ON (${x.value})` : '')).join('') : ''}\
    ${(validate(groupArray)) ?
    groupArray.map(x =>
      [`${x.groupKeySelect || groupVal[x.key]} ${x.alias || ''},`].filter(Boolean).join(',\n')).join('') : ''}
${(validate(groupArray)) ?
    (validate(selectArray) && selectArray.map(x =>
      [
        (x && x.countValue) || '',
        (x && x.avgPerMatch) ? `sum(${selectVal[x.key]})::numeric/count(distinct matches.match_id) "AVG ${x.text}"` : `${x && x.avg ? x.avg : `avg(${selectVal[x.key]})`} "AVG ${x.text}"`,
        'count(distinct matches.match_id) count',
        'sum(case when (player_matches.player_slot < 128) = radiant_win then 1 else 0 end)::float/count(1) winrate',
        `((sum(case when (player_matches.player_slot < 128) = radiant_win then 1 else 0 end)::float/count(1))
+ 1.96 * 1.96 / (2 * count(1))
- 1.96 * sqrt((((sum(case when (player_matches.player_slot < 128) = radiant_win then 1 else 0 end)::float/count(1)) * (1 - (sum(case when (player_matches.player_slot < 128) = radiant_win then 1 else 0 end)::float/count(1))) + 1.96 * 1.96 / (4 * count(1))) / count(1))))
/ (1 + 1.96 * 1.96 / count(1)) winrate_wilson`,
        `sum(${selectVal[x.key]}) sum`,
        `min(${selectVal[x.key]}) min`,
        `max(${selectVal[x.key]}) max`,
        `stddev(${selectVal[x.key]}::numeric) stddev
  `,
      ].filter(Boolean).join(',\n'))) || '' : ''}
${!validate(groupArray) ?
    [validate(selectArray) ? selectArray.map(x => `${x.value} ${x.alias || ''}`) : '',
      'matches.match_id',
      'matches.start_time',
      '((player_matches.player_slot < 128) = matches.radiant_win) win',
      'player_matches.hero_id',
      'player_matches.account_id',
      'leagues.name leaguename',
    ].filter(Boolean).join(',\n') : ''}
FROM matches
JOIN match_patch using(match_id)
JOIN leagues using(leagueid)
JOIN player_matches using(match_id)
JOIN heroes on heroes.id = player_matches.hero_id
LEFT JOIN notable_players ON notable_players.account_id = player_matches.account_id AND notable_players.locked_until = (SELECT MAX(locked_until) FROM notable_players)
LEFT JOIN teams using(team_id)
${organization || (groupArray !== null && groupArray.length > 0 && groupArray[0] && groupArray.some(x => x.key === 'organization')) ?
    'JOIN team_match ON matches.match_id = team_match.match_id AND (player_matches.player_slot < 128) = team_match.radiant JOIN teams teams2 ON team_match.team_id = teams2.team_id' : ''}
${validate(selectArray) ? selectArray.map(x => (x.joinFn ? x.joinFn(props) : '')).join('') : ''}
${validate(selectArray) ? selectArray.map(x => (x.join ? x.join : '')).join('') : ''}
WHERE TRUE
${validate(selectArray) ? selectArray.map(x => `AND ${x.value} IS NOT NULL `).join('') : ''}
${minPatch ? templ`match_patch.patch >= '${minPatch}'` : ''}
${maxPatch ? templ`match_patch.patch <= '${maxPatch}'` : ''}
${hero ? templ`player_matches.hero_id = ${hero}` : ''}
${player ? templ`player_matches.account_id = ${player}` : ''}
${league ? templ`matches.leagueid = ${league}` : ''}
${playerPurchased ? templ`(player_matches.purchase->>'${playerPurchased}')::int > 0` : ''}
${minDuration ? templ`matches.duration >= ${minDuration}` : ''}
${maxDuration ? templ`matches.duration <= ${maxDuration}` : ''}
${side ? templ`(player_matches.player_slot < 128) = ${side}` : ''}
${result ? templ`((player_matches.player_slot < 128) = matches.radiant_win) = ${result}` : ''}
${team ? templ`notable_players.team_id = ${team}` : ''}
${organization ? templ`team_match.team_id = ${organization} AND (player_matches.player_slot < 128) = team_match.radiant` : ''}
${laneRole ? templ`player_matches.lane_role = ${laneRole}` : ''}
${region ? templ`matches.cluster IN (${region})` : ''}
${minDate ? templ`matches.start_time >= extract(epoch from timestamp '${new Date(minDate.value).toISOString()}')` : ''}
${maxDate ? templ`matches.start_time <= extract(epoch from timestamp '${new Date(maxDate.value).toISOString()}')` : ''}
${tier ? templ`leagues.tier = '${tier}'` : ''}
${isTi7Team ? 'AND teams.team_id IN (5, 15, 39, 46, 2163, 350190, 1375614, 1838315, 1883502, 2108395, 2512249, 2581813, 2586976, 2640025, 2672298, 1333179, 3331948, 1846548)' : ''}
${validate(groupArray) ? 'GROUP BY' : ''}${(validate(groupArray) && groupArray.map(x => ` ${groupVal[x.key]}`)) || ''}
${validate(groupArray) ? `HAVING count(distinct matches.match_id) >= ${(having && having.value) || '1'}` : ''}
ORDER BY ${
  [`${(validate(groupArray) && validate(selectArray) && selectArray.map(x => `"AVG ${x.text}" ${validate(order) ? (Array.isArray(order) && order.length > 0 && order[0].value) || order.value : 'DESC'}`)) ||
    (validate(selectArray) && selectArray.map(x => `${x.value} ${validate(order) ? (Array.isArray(order) && order.length > 0 && order[0].value) || order.value : 'DESC'}`).join(',')) || 'matches.match_id'}`,
  validate(groupArray) ? 'count DESC' : '',
  ].filter(Boolean).join(',')} NULLS LAST
LIMIT ${validate(limit) ? limit[0].value : 200}`;
  }
  return query
  // Remove extra newlines
    .replace(/\n{2,}/g, '\n');
};

export default queryTemplate;
<commit_msg>fixed Picks/Bans<commit_after>function templ(strings, value) {
  const str0 = strings[0];
  const str1 = strings[1];
  if (Array.isArray(value)) {
    const o = value.map(x => x.value);
    const r = [];
    if (!value.length) {
      return '';
    }
    o.forEach((s) => {
      r.push(`${str0}${s}${str1}`);
    });
    return `AND (${r.join(' OR ')})`;
  }
  return `AND ${str0}${value.value !== undefined ? value.value : value}${str1}`;
}

function validate(p) {
  return p !== null && p !== undefined && p.length > 0 && p[0] !== null && p[0] !== undefined;
}

const queryTemplate = (props) => {
  const {
    select,
    group,
    minPatch,
    maxPatch,
    hero,
    player,
    league,
    playerPurchased,
    minDuration,
    maxDuration,
    side,
    result,
    team,
    organization,
    laneRole,
    region,
    minDate,
    maxDate,
    order,
    tier,
    having,
    limit,
    isTi7Team,
  } = props;
  // array inputs
  // group
  // hero
  // player
  // league
  // team
  // organization
  let query;
  let groupArray = [];
  let selectArray = [];
  if (!(Array.isArray(group))) {
    groupArray.push(group);
  } else {
    groupArray = group;
  }
  if (!(Array.isArray(select))) {
    selectArray.push(select);
  } else {
    selectArray = select;
  }
  selectArray = selectArray.filter(x => x !== undefined);
  groupArray = groupArray.filter(x => x !== undefined);
  groupArray.forEach((x) => {
    if (x.json_each) {
      selectArray.push(x);
    }
  });
  groupArray = groupArray.filter(x => !x.json_each);
  selectArray.forEach((x, index) => {
    if (x && x.groupValue) {
      const a = {
        value: x.groupKey, groupKeySelect: x.groupKeySelect, alias: x.alias, key: `key${index.toString()}`,
      };
      if (x.groupKey === 'key') {
        const p = x;
        a.value = `key${index.toString()}.key`;
        p.value = `key${index.toString()}.key`;
        p.join = `${x.join} key${index.toString()}`;
        p.groupValue = `key${index.toString()}.${x.groupValue}`;
      }
      groupArray.push(a);
    }
  });
  if (validate(selectArray) && selectArray.some(p => p.template === 'picks_bans')) {
    query = `SELECT
hero_id,
count(1) total,
sum(is_pick::int) picks,
sum((NOT is_pick)::int) bans,
sum((is_pick IS TRUE AND ord < 8)::int) first_pick,
sum((is_pick IS FALSE AND ord < 8)::int) first_ban,
sum((is_pick IS TRUE AND ord >= 8 AND ord < 16)::int) second_pick,
sum((is_pick IS FALSE AND ord >= 8 AND ord < 16)::int) second_ban,
sum((is_pick IS TRUE AND ord >= 16)::int) third_pick,
sum((is_pick IS FALSE AND ord >= 16)::int) third_ban,
sum((radiant = radiant_win)::int)::float/count(1) winrate,
sum((radiant = radiant_win AND is_pick IS TRUE)::int)::float/NULLIF(sum(is_pick::int), 0) pick_winrate,
sum((radiant = radiant_win AND is_pick IS FALSE)::int)::float/NULLIF(sum((NOT is_pick)::int), 0) ban_winrate
FROM picks_bans
JOIN matches using(match_id)
JOIN match_patch using(match_id)
JOIN leagues using(leagueid)
JOIN team_match using(match_id)
JOIN teams using(team_id)
WHERE TRUE
${validate(selectArray) && selectArray.find(x => x.where) !== undefined ? selectArray.find(x => x.where).where : ''}
${organization ? templ`team_id = ${organization}` : ''}
${minPatch ? templ`match_patch.patch >= '${minPatch}'` : ''}
${maxPatch ? templ`match_patch.patch <= '${maxPatch}'` : ''}
${league ? templ`matches.leagueid = ${league}` : ''}
${minDuration ? templ`matches.duration >= ${minDuration}` : ''}
${maxDuration ? templ`matches.duration <= ${maxDuration}` : ''}
${side ? templ`team_match.radiant = ${side}` : ''}
${result ? templ`(team_match.radiant = matches.radiant_win) = ${result.value}` : ''}
${region ? templ`matches.cluster IN (${region.value.join(',')})` : ''}
${minDate ? templ`matches.start_time >= extract(epoch from timestamp '${new Date(minDate.value).toISOString()}')` : ''}
${maxDate ? templ`matches.start_time <= extract(epoch from timestamp '${new Date(maxDate.value).toISOString()}')` : ''}
${tier ? templ`leagues.tier = '${tier}'` : ''}
${isTi7Team ? 'AND teams.team_id IN (5, 15, 39, 46, 2163, 350190, 1375614, 1838315, 1883502, 2108395, 2512249, 2581813, 2586976, 2640025, 2672298, 1333179, 3331948, 1846548)' : ''}
GROUP BY hero_id
ORDER BY total ${(order && order.value) || 'DESC'}`;
  } else {
    const selectVal = {};
    const groupVal = {};
    if (validate(groupArray)) {
      groupArray.forEach((x) => { groupVal[x.key] = `${x.value}${x.bucket ? ` / ${x.bucket} * ${x.bucket}` : ''}`; });
    }
    if (validate(selectArray)) {
      selectArray.forEach((x) => { selectVal[x.key] = x.groupValue || (x && x.value) || 1; });
    }
    query = `SELECT
    ${validate(selectArray) ? selectArray.map(x => (x.distinct && !validate(groupArray) ? `DISTINCT ON (${x.value})` : '')).join('') : ''}\
    ${(validate(groupArray)) ?
    groupArray.map(x =>
      [`${x.groupKeySelect || groupVal[x.key]} ${x.alias || ''},`].filter(Boolean).join(',\n')).join('') : ''}
${(validate(groupArray)) ?
    (validate(selectArray) && selectArray.map(x =>
      [
        (x && x.countValue) || '',
        (x && x.avgPerMatch) ? `sum(${selectVal[x.key]})::numeric/count(distinct matches.match_id) "AVG ${x.text}"` : `${x && x.avg ? x.avg : `avg(${selectVal[x.key]})`} "AVG ${x.text}"`,
        'count(distinct matches.match_id) count',
        'sum(case when (player_matches.player_slot < 128) = radiant_win then 1 else 0 end)::float/count(1) winrate',
        `((sum(case when (player_matches.player_slot < 128) = radiant_win then 1 else 0 end)::float/count(1))
+ 1.96 * 1.96 / (2 * count(1))
- 1.96 * sqrt((((sum(case when (player_matches.player_slot < 128) = radiant_win then 1 else 0 end)::float/count(1)) * (1 - (sum(case when (player_matches.player_slot < 128) = radiant_win then 1 else 0 end)::float/count(1))) + 1.96 * 1.96 / (4 * count(1))) / count(1))))
/ (1 + 1.96 * 1.96 / count(1)) winrate_wilson`,
        `sum(${selectVal[x.key]}) sum`,
        `min(${selectVal[x.key]}) min`,
        `max(${selectVal[x.key]}) max`,
        `stddev(${selectVal[x.key]}::numeric) stddev
  `,
      ].filter(Boolean).join(',\n'))) || '' : ''}
${!validate(groupArray) ?
    [validate(selectArray) ? selectArray.map(x => `${x.value} ${x.alias || ''}`) : '',
      'matches.match_id',
      'matches.start_time',
      '((player_matches.player_slot < 128) = matches.radiant_win) win',
      'player_matches.hero_id',
      'player_matches.account_id',
      'leagues.name leaguename',
    ].filter(Boolean).join(',\n') : ''}
FROM matches
JOIN match_patch using(match_id)
JOIN leagues using(leagueid)
JOIN player_matches using(match_id)
JOIN heroes on heroes.id = player_matches.hero_id
LEFT JOIN notable_players ON notable_players.account_id = player_matches.account_id AND notable_players.locked_until = (SELECT MAX(locked_until) FROM notable_players)
LEFT JOIN teams using(team_id)
${organization || (groupArray !== null && groupArray.length > 0 && groupArray[0] && groupArray.some(x => x.key === 'organization')) ?
    'JOIN team_match ON matches.match_id = team_match.match_id AND (player_matches.player_slot < 128) = team_match.radiant JOIN teams teams2 ON team_match.team_id = teams2.team_id' : ''}
${validate(selectArray) ? selectArray.map(x => (x.joinFn ? x.joinFn(props) : '')).join('') : ''}
${validate(selectArray) ? selectArray.map(x => (x.join ? x.join : '')).join('') : ''}
WHERE TRUE
${validate(selectArray) ? selectArray.map(x => `AND ${x.value} IS NOT NULL `).join('') : ''}
${minPatch ? templ`match_patch.patch >= '${minPatch}'` : ''}
${maxPatch ? templ`match_patch.patch <= '${maxPatch}'` : ''}
${hero ? templ`player_matches.hero_id = ${hero}` : ''}
${player ? templ`player_matches.account_id = ${player}` : ''}
${league ? templ`matches.leagueid = ${league}` : ''}
${playerPurchased ? templ`(player_matches.purchase->>'${playerPurchased}')::int > 0` : ''}
${minDuration ? templ`matches.duration >= ${minDuration}` : ''}
${maxDuration ? templ`matches.duration <= ${maxDuration}` : ''}
${side ? templ`(player_matches.player_slot < 128) = ${side}` : ''}
${result ? templ`((player_matches.player_slot < 128) = matches.radiant_win) = ${result}` : ''}
${team ? templ`notable_players.team_id = ${team}` : ''}
${organization ? templ`team_match.team_id = ${organization} AND (player_matches.player_slot < 128) = team_match.radiant` : ''}
${laneRole ? templ`player_matches.lane_role = ${laneRole}` : ''}
${region ? templ`matches.cluster IN (${region})` : ''}
${minDate ? templ`matches.start_time >= extract(epoch from timestamp '${new Date(minDate.value).toISOString()}')` : ''}
${maxDate ? templ`matches.start_time <= extract(epoch from timestamp '${new Date(maxDate.value).toISOString()}')` : ''}
${tier ? templ`leagues.tier = '${tier}'` : ''}
${isTi7Team ? 'AND teams.team_id IN (5, 15, 39, 46, 2163, 350190, 1375614, 1838315, 1883502, 2108395, 2512249, 2581813, 2586976, 2640025, 2672298, 1333179, 3331948, 1846548)' : ''}
${validate(groupArray) ? 'GROUP BY' : ''}${(validate(groupArray) && groupArray.map(x => ` ${groupVal[x.key]}`)) || ''}
${validate(groupArray) ? `HAVING count(distinct matches.match_id) >= ${(having && having.value) || '1'}` : ''}
ORDER BY ${
  [`${(validate(groupArray) && validate(selectArray) && selectArray.map(x => `"AVG ${x.text}" ${validate(order) ? (Array.isArray(order) && order.length > 0 && order[0].value) || order.value : 'DESC'}`)) ||
    (validate(selectArray) && selectArray.map(x => `${x.value} ${validate(order) ? (Array.isArray(order) && order.length > 0 && order[0].value) || order.value : 'DESC'}`).join(',')) || 'matches.match_id'}`,
  validate(groupArray) ? 'count DESC' : '',
  ].filter(Boolean).join(',')} NULLS LAST
LIMIT ${validate(limit) ? limit[0].value : 200}`;
  }
  return query
  // Remove extra newlines
    .replace(/\n{2,}/g, '\n');
};

export default queryTemplate;
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var log4js = require('log4js');
var utils = require('./lib/utils');
var fs = require('fs-extra');

var logRootDir = global.pathToApp || __dirname;

var config =  {
    prepareLogPath: 'log',
    log4js: {
        "appenders": [
            {
                "type": "logLevelFilter",
                "level": global.commander.log || (global.MODE === 'production' ? global.opts.core.common.defaultProdLogLevel : global.opts.core.common.defaultLogLevel),
                "appender": {
                    "type": "console",
                    "layout": {
                        "type": "pattern",
                        "pattern": "%[[%d{yyyy-MM-dd hh:mm:ss}] [%p] -%] %m"
                    }
                }
            },
            {
                "type": "clustered",
                "appenders": [
                    {
                        "type": "file",
                        "filename": path.join(logRootDir, 'log/app.log'),
                        "maxLogSize": 10485760,
                        "numBackups": 3
                    },
                    {
                        "type": "logLevelFilter",
                        "level": "ERROR",
                        "appender": {
                            "type": "file",
                            "filename": path.join(logRootDir, 'log/errors.log')
                        }
                    },
                    {
                        "type": "logLevelFilter",
                        "level": "WARN",
                        "appender": {
                            "type": "file",
                            "filename": path.join(logRootDir, 'log/warnings.log')
                        }
                    }
                ],
                category: 'app'
            }
        ]
    }
};

if (global.opts.core.logger) utils.extendOptions(config, global.opts.core.logger);

var reloadConf = function(currentConf){
    log4js.configure(currentConf);
    log4js.replaceConsole(log4js.getLogger('app'));
};

var addAppenders = function(appendersArr){

    appendersArr.forEach(function(item){
        config.log4js.appenders.push(item);
    });

    reloadConf(config.log4js);
};

var prepareLogDir = function(dir){
    // Preparing log dir
    try {
        fs.mkdirpSync(path.join(logRootDir, dir));
    } catch (e) {
        if (e.code !== 'EEXIST') {
            console.error("Could not set up log directory, error: ", e);
        }
    }
};

// Prepare dafault log path
prepareLogDir(config.prepareLogPath);

// Configuring log4js
reloadConf(config.log4js);

var logger = log4js.getLogger('app');

// Example
// logger.trace('trace');
// logger.debug('debug');
// logger.info('info');
// console.log('console log');
// logger.warn('warn');
// logger.error('error');
// logger.fatal('fatal');

if (global.logQueue) global.logQueue.forEach(function(item){
    logger[item.level](item.msg);
});

module.exports = {
    addAppenders: addAppenders,
    prepareLogDir: prepareLogDir,

    // Default logger
    log: logger,

    // Configured log4js
    log4js: log4js
};<commit_msg>check for arguments existing in logger set-up<commit_after>'use strict';

var path = require('path');
var log4js = require('log4js');
var utils = require('./lib/utils');
var fs = require('fs-extra');

var logRootDir = global.pathToApp || __dirname;
var customLogLevel = global.commander && global.commander.log ? global.commander.log : undefined;
var defaultLogLevel = global.MODE === 'production' ? global.opts.core.common.defaultProdLogLevel : global.opts.core.common.defaultLogLevel;
var logLevel = customLogLevel || defaultLogLevel;

var config =  {
    prepareLogPath: 'log',
    log4js: {
        "appenders": [
            {
                "type": "logLevelFilter",
                "level": logLevel,
                "appender": {
                    "type": "console",
                    "layout": {
                        "type": "pattern",
                        "pattern": "%[[%d{yyyy-MM-dd hh:mm:ss}] [%p] -%] %m"
                    }
                }
            },
            {
                "type": "clustered",
                "appenders": [
                    {
                        "type": "file",
                        "filename": path.join(logRootDir, 'log/app.log'),
                        "maxLogSize": 10485760,
                        "numBackups": 3
                    },
                    {
                        "type": "logLevelFilter",
                        "level": "ERROR",
                        "appender": {
                            "type": "file",
                            "filename": path.join(logRootDir, 'log/errors.log')
                        }
                    },
                    {
                        "type": "logLevelFilter",
                        "level": "WARN",
                        "appender": {
                            "type": "file",
                            "filename": path.join(logRootDir, 'log/warnings.log')
                        }
                    }
                ],
                category: 'app'
            }
        ]
    }
};

if (global.opts.core.logger) utils.extendOptions(config, global.opts.core.logger);

var reloadConf = function(currentConf){
    log4js.configure(currentConf);
    log4js.replaceConsole(log4js.getLogger('app'));
};

var addAppenders = function(appendersArr){

    appendersArr.forEach(function(item){
        config.log4js.appenders.push(item);
    });

    reloadConf(config.log4js);
};

var prepareLogDir = function(dir){
    // Preparing log dir
    try {
        fs.mkdirpSync(path.join(logRootDir, dir));
    } catch (e) {
        if (e.code !== 'EEXIST') {
            console.error("Could not set up log directory, error: ", e);
        }
    }
};

// Prepare dafault log path
prepareLogDir(config.prepareLogPath);

// Configuring log4js
reloadConf(config.log4js);

var logger = log4js.getLogger('app');

// Example
// logger.trace('trace');
// logger.debug('debug');
// logger.info('info');
// console.log('console log');
// logger.warn('warn');
// logger.error('error');
// logger.fatal('fatal');

if (global.logQueue) global.logQueue.forEach(function(item){
    logger[item.level](item.msg);
});

module.exports = {
    addAppenders: addAppenders,
    prepareLogDir: prepareLogDir,

    // Default logger
    log: logger,

    // Configured log4js
    log4js: log4js
};<|endoftext|>


<commit_before>ProLicenceUsersTable = {};
ProLicenceUsersTable = {
    "ProLicenceUsers": {
        "1ad344c0-40c4-4ffe-b1b0-142f6918d437": {
            "reason": "LMauthor",
            "notes": "Jimboy3100"
        },
        "b4c70ce6-602a-4fb6-9196-01d890c66d0e": {
            "reason": "Moderator",
            "notes": "ddevilOWO"
        },
        "32254495-c62d-4d0c-b66e-3d81010d401d": {
            "reason": "℄🌀idris",
            "notes": "℄🌀"
        },
        "7bea1cb9-7e14-4e14-824c-c2682036b0a6": {
            "reason": "℄🌀βurNouT",
            "notes": "℄🌀"
        },
        "204c1426-c4c9-46af-b29d-5fa9d4d8704a": {
            "reason": "℄🌀ilyes",
            "Chosenbyddevilowo": "℄🌀"
        },
        "c8c0f123-2758-410b-a952-e4c4898319e5": {
            "reason": "℄🌀ahmad",
            "Chosenbyddevilowo": "℄🌀"
        },
        "e18af28b-d1de-4645-967f-9b95736e8817": {
            "reason": "Hendrik Schönfelder",
            "notes": "Youtuber"
        },
        "a3742f28-059a-4ea1-abf7-566e69ec97f4": {
            "reason": "Moderator",
            "notes": "Snez"
        },
        "5b26499a-ccd0-4cdb-9c0e-9375b9d7cd4c": {
            "reason": "Shiro",
            "notes": "Advertiser-Japan-Fb"
        },
        "81831afa-0a11-4fce-82b3-81067f6cc9bc": {
            "reason": "Shiro",
            "notes": "Advertiser-Japan-Google"
        },
        "4220bddd-7bd6-4f93-89cf-579903eff2bc": {
            "reason": "Donate",
            "notes": "Cla"
        },
        "17914d3b-6b8f-468a-bb6b-4d91d3c3f670": {
            "reason": "GoodWillForSon",
            "notes": "jebak"
        },
        "bbf24317-be3f-4dac-a4d8-f1770434ace5": {
            "reason": "Donate",
            "notes": "Meelis"
        },
        "84222701-39e7-454e-9e41-bc8fd4f468d2": {
            "reason": "Donate",
            "notes": "Siah"
        },
        "87b8a4f8-0cb4-448d-bedc-358a3010c7e6": {
            "reason": "Donate",
            "notes": "Fiku"
        },
        "83df7615-1c6a-4a9d-9d86-1eba11d9589c": {
            "reason": "BeggerJapan",
            "notes": "padelsendpie"
        },
        "7aa2d964-ac82-497c-aa34-25cc342299bd": {
            "reason": "Donate",
            "notes": "CentralAsia"
        },
        "84cfb97a-03ef-4625-a6cb-913b23d9dc69": {
            "reason": "Give@20200521",
            "notes": "testJimboy"
        },
        "3361c3f4-3d94-49d2-b19c-c1b8241d4574": {
            "reason": "Give@20200612",
            "notes": "AngelDeltaServer"
        },
        "e8a49e32-7f71-4449-b1ae-1bf2fe4dc3b": {
            "reason": "Give@20200612",
            "notes": "MaximumDeltaServer"
        },
        "d7385406-7a71-498d-a613-3faf090f6ccb": {
            "reason": "Give@20200612",
            "notes": "VictoriaAiroFbGoogleaccount"
        },
        "40252edd-4ec4-41a0-865f-aa9d967a3706": {
            "reason": "Give@20200612",
            "notes": "VictoriaAiroFbFacebookaccount"
        },
        "cfff71aa-efa6-45c2-bcaa-4e68ce796a58": {
            "reason": "Give@20200612",
            "notes": "MuhAdits"
        },
        "3361c3f4-3d94-49d2-b19c-c1b8241d4574": {
            "reason": "Give@20200612",
            "notes": "GioBartolo"
        },
        "3caec878-4009-4349-9bb8-9ce16cebbe98": {
            "reason": "Give@20200612",
            "notes": "ZainMohammed"
        },
        "ba288e41-27b2-4da6-b97c-56409e073894": {
            "reason": "Give@20200612",
            "notes": "RavagerCanos"
        },
        "693edb8d-427c-4453-a92d-2d8bd6254750": {
            "reason": "Give@20200612",
            "notes": "イイヅカマユミ"
        },
        "b4dc260f-f14d-479b-a373-63beb131a122": {
            "reason": "Give@20200612",
            "notes": "LamPhạm"
        },
        "5dc487ab-f8bb-4834-a311-fff3fc924948": {
            "reason": "Give@20200612",
            "Chosenbyddevil": "抹茶"
        },
        "a9d42b13-df83-4a4d-b175-ec9dedaaaf33": {
            "reason": "Give@20200612",
            "Chosenbyddevilowo": "wenlong"
        },
        "7f350142-5c90-473f-8eff-9352680ba8e6": {
            "reason": "Give@20200612",
            "Chosenbyddevilowo": "kaizen"
        },
        "8ba00967-ef20-4314-b451-d802e4817eb7": {
            "reason": "Give@20200612",
            "Chosenbyddevilowo": "綾辻芙月渚"
        },
          "e0c362ab-c4f8-4ba3-8deb-fb7651fdb818": {
            "reason": "Give@20200926",
            "Chosenbyddevilowo": "Judah"
        },
        "f27c8c1a-77d4-4641-9160-cf0d6f7281da": {
            "reason": "Give@20200620",
            "Chosenbyddevilowo": "ALI cicineLC"
        },
        "84fda50e-63c4-41d7-9ba3-e6750cb0d94e": {
            "reason": "Give@20200720",
            "Chosenbyddevilowo": "tawis"
        },
        "3a13f17c-0c9b-4c1c-92a5-a66854621986": {
            "reason": "Give@20200720",
            "Chosenbyddevilowo": "maco420"
        },
        "a21f4130-3474-4331-add1-bd02155e607c": {
            "reason": "Donate",
            "Chosenbyddevilowo": "sondick"
        },
        "8edf92ef-1fed-4022-948c-a1308cfa3adf": {
            "reason": "Give@20200720",
            "Chosenbyddevilowo": "haine"
        },
        "e0c362ab-c4f8-4ba3-8deb-fb7651fdb818": {
            "reason": "Give@20200726",
            "Chosenbyddevilowo": "friendofJudah"
        },
        "4e50ef3d-626e-4bf6-a376-2a0fc0629864": {
            "reason": "Donate",
            "notes": "Lizzie"
        }
    },
    "versionsInfo": ["v-0.3", "LM-v2.5"]
};
<commit_msg>Update ProLicenceUsersTableJS.js<commit_after>ProLicenceUsersTable = {};
ProLicenceUsersTable = {
    "ProLicenceUsers": {
        "1ad344c0-40c4-4ffe-b1b0-142f6918d437": {
            "reason": "LMauthor",
            "notes": "Jimboy3100"
        },
        "b4c70ce6-602a-4fb6-9196-01d890c66d0e": {
            "reason": "Moderator",
            "notes": "ddevilOWO"
        },
        "32254495-c62d-4d0c-b66e-3d81010d401d": {
            "reason": "℄🌀idris",
            "notes": "℄🌀"
        },
        "7bea1cb9-7e14-4e14-824c-c2682036b0a6": {
            "reason": "℄🌀βurNouT",
            "notes": "℄🌀"
        },
        "204c1426-c4c9-46af-b29d-5fa9d4d8704a": {
            "reason": "℄🌀ilyes",
            "Chosenbyddevilowo": "℄🌀"
        },
        "c8c0f123-2758-410b-a952-e4c4898319e5": {
            "reason": "℄🌀ahmad",
            "Chosenbyddevilowo": "℄🌀"
        },
        "e18af28b-d1de-4645-967f-9b95736e8817": {
            "reason": "Hendrik Schönfelder",
            "notes": "Youtuber"
        },
        "a3742f28-059a-4ea1-abf7-566e69ec97f4": {
            "reason": "Moderator",
            "notes": "Snez"
        },
        "5b26499a-ccd0-4cdb-9c0e-9375b9d7cd4c": {
            "reason": "Shiro",
            "notes": "Advertiser-Japan-Fb"
        },
        "81831afa-0a11-4fce-82b3-81067f6cc9bc": {
            "reason": "Shiro",
            "notes": "Advertiser-Japan-Google"
        },
        "4220bddd-7bd6-4f93-89cf-579903eff2bc": {
            "reason": "Donate",
            "notes": "Cla"
        },
        "17914d3b-6b8f-468a-bb6b-4d91d3c3f670": {
            "reason": "GoodWillForSon",
            "notes": "jebak"
        },
        "bbf24317-be3f-4dac-a4d8-f1770434ace5": {
            "reason": "Donate",
            "notes": "Meelis"
        },
        "84222701-39e7-454e-9e41-bc8fd4f468d2": {
            "reason": "Donate",
            "notes": "Siah"
        },
        "87b8a4f8-0cb4-448d-bedc-358a3010c7e6": {
            "reason": "Donate",
            "notes": "Fiku"
        },
        "83df7615-1c6a-4a9d-9d86-1eba11d9589c": {
            "reason": "BeggerJapan",
            "notes": "padelsendpie"
        },
        "7aa2d964-ac82-497c-aa34-25cc342299bd": {
            "reason": "Donate",
            "notes": "CentralAsia"
        },
        "84cfb97a-03ef-4625-a6cb-913b23d9dc69": {
            "reason": "Give@20200521",
            "notes": "testJimboy"
        },
        "3361c3f4-3d94-49d2-b19c-c1b8241d4574": {
            "reason": "Give@20200612",
            "notes": "AngelDeltaServer"
        },
        "e8a49e32-7f71-4449-b1ae-1bf2fe4dc3b": {
            "reason": "Give@20200612",
            "notes": "MaximumDeltaServer"
        },
        "d7385406-7a71-498d-a613-3faf090f6ccb": {
            "reason": "Give@20200612",
            "notes": "VictoriaAiroFbGoogleaccount"
        },
        "40252edd-4ec4-41a0-865f-aa9d967a3706": {
            "reason": "Give@20200612",
            "notes": "VictoriaAiroFbFacebookaccount"
        },
        "cfff71aa-efa6-45c2-bcaa-4e68ce796a58": {
            "reason": "Give@20200612",
            "notes": "MuhAdits"
        },
        "3361c3f4-3d94-49d2-b19c-c1b8241d4574": {
            "reason": "Give@20200612",
            "notes": "GioBartolo"
        },
        "3caec878-4009-4349-9bb8-9ce16cebbe98": {
            "reason": "Give@20200612",
            "notes": "ZainMohammed"
        },
        "ba288e41-27b2-4da6-b97c-56409e073894": {
            "reason": "Give@20200612",
            "notes": "RavagerCanos"
        },
        "693edb8d-427c-4453-a92d-2d8bd6254750": {
            "reason": "Give@20200612",
            "notes": "イイヅカマユミ"
        },
        "b4dc260f-f14d-479b-a373-63beb131a122": {
            "reason": "Give@20200612",
            "notes": "LamPhạm"
        },
        "5dc487ab-f8bb-4834-a311-fff3fc924948": {
            "reason": "Give@20200612",
            "Chosenbyddevil": "抹茶"
        },
        "a9d42b13-df83-4a4d-b175-ec9dedaaaf33": {
            "reason": "Give@20200612",
            "Chosenbyddevilowo": "wenlong"
        },
        "7f350142-5c90-473f-8eff-9352680ba8e6": {
            "reason": "Give@20200612",
            "Chosenbyddevilowo": "kaizen"
        },
        "8ba00967-ef20-4314-b451-d802e4817eb7": {
            "reason": "Give@20200612",
            "Chosenbyddevilowo": "綾辻芙月渚"
        },
          "8edf92ef-1fed-4022-948c-a1308cfa3adf": {
            "reason": "Give@20200926",
            "Chosenbyddevilowo": "Judah"
        },
        "f27c8c1a-77d4-4641-9160-cf0d6f7281da": {
            "reason": "Give@20200620",
            "Chosenbyddevilowo": "ALI cicineLC"
        },
        "84fda50e-63c4-41d7-9ba3-e6750cb0d94e": {
            "reason": "Give@20200720",
            "Chosenbyddevilowo": "tawis"
        },
        "3a13f17c-0c9b-4c1c-92a5-a66854621986": {
            "reason": "Give@20200720",
            "Chosenbyddevilowo": "maco420"
        },
        "a21f4130-3474-4331-add1-bd02155e607c": {
            "reason": "Donate",
            "Chosenbyddevilowo": "sondick"
        },
        "8edf92ef-1fed-4022-948c-a1308cfa3adf": {
            "reason": "Give@20200720",
            "Chosenbyddevilowo": "haine"
        },
        "e0c362ab-c4f8-4ba3-8deb-fb7651fdb818": {
            "reason": "Give@20200726",
            "Chosenbyddevilowo": "friendofJudah"
        },
        "4e50ef3d-626e-4bf6-a376-2a0fc0629864": {
            "reason": "Donate",
            "notes": "Lizzie"
        }
    },
    "versionsInfo": ["v-0.3", "LM-v2.5"]
};
<|endoftext|>


<commit_before>describe('When Interceptor sends a captured request to Postman', function() {

	beforeEach(function() {
		this.chromeEventOrder = function(args) {
			onBeforeRequest(args);
			onBeforeSendHeaders(args);
			onSendHeaders(args);
		}
		sinon.stub(chrome.runtime ,'sendMessage');
	});

	it("No request should be captured to Postman by default", function() {
        var request = getNewRequest(1);
		this.chromeEventOrder(request);
		expect(chrome.runtime.sendMessage.called).toBe(false);
	});

	it("Should capture a request when Toggle is ON.", function() {
		appOptions.isCaptureStateEnabled = true;
        var request = getNewRequest(1);
		this.chromeEventOrder(request);

		expect(chrome.runtime.sendMessage.args[0][0]).toBe('POSTMAN');
		expect(chrome.runtime.sendMessage.args[0][1].postmanMessage.reqId).toBe(1);
		expect(chrome.runtime.sendMessage.args[0][1].postmanMessage.request).toBe(request);

		appOptions.isCaptureStateEnabled = false;
	});

    it("Filter should allow all domains by default", function() {
        appOptions.isCaptureStateEnabled = true;
        expect(appOptions.filterRequestUrl).toBe(".*");
        var request = getNewRequest(1);
        this.chromeEventOrder(request);

        expect(chrome.runtime.sendMessage.called).toBe(true);
        expect(chrome.runtime.sendMessage.args[0][1].postmanMessage.reqId).toBe(1);
    });

    it("Filter should block incorrect domains when enabled", function() {
        appOptions.isCaptureStateEnabled = true;
        appOptions.filterRequestUrl = "google";
        var request = getNewRequest(1);
        this.chromeEventOrder(request);

        expect(chrome.runtime.sendMessage.called).toBe(false);

        appOptions.filterRequestUrl = ".*";
    });

    it("Filter should allow correct domains when enabled", function() {
        appOptions.isCaptureStateEnabled = true;
        appOptions.filterRequestUrl = "google";
        var request = getNewRequest(2);
        request.url = "www.google.com/someXHR";
        this.chromeEventOrder(request);

        expect(chrome.runtime.sendMessage.called).toBe(true);
        expect(chrome.runtime.sendMessage.args[0][1].postmanMessage.reqId).toBe(2);
    });

	afterEach(function() {
		this.chromeEventOrder = null;
		chrome.runtime.sendMessage.restore();
	});

});

describe("When Postman sends a message to Interceptor", function() {

    it("Toggle should send correct message to interceptor", function() {
        var postmanMessage = getPostmanMessage("detectExtension");
        var sender = { id: 1 };
        var sendResponse = sinon.stub();
        onExternalMessage(postmanMessage, sender, sendResponse);

        expect(sendResponse.called).toBe(true);
        expect(sendResponse.callCount).toBe(2);
        expect(sendResponse.args[0][0].result).toBe("Ok, got your message");
    });

    it("Interceptor should recieve XHR request from Postman", function() {
        var postmanMessage = getPostmanMessage("xhrRequest");
        var sender = { id: 1 };
        var sendResponse = sinon.stub();
        sinon.stub(window, 'sendXhrRequest');
        onExternalMessage(postmanMessage, sender, sendResponse);

        expect(sendResponse.called).toBe(true);
        expect(sendResponse.calledOnce).toBe(true);
        expect(sendResponse.args[0][0].result).toBe("Ok, got your message");
        expect(sendXhrRequest.called).toBe(true);
        expect(sendXhrRequest.args[0][0].headers[0]["key"]).toBe("Postman-Token");
    });

});
<commit_msg>Added tests for postman request capturing<commit_after>describe('When Interceptor sends a captured request to Postman', function() {

	beforeEach(function() {
		this.chromeEventOrder = function(args) {
			onBeforeRequest(args);
			onBeforeSendHeaders(args);
			onSendHeaders(args);
		}
		sinon.stub(chrome.runtime ,'sendMessage');
	});

	it("No request should be captured to Postman by default", function() {
        var request = getNewRequest(1);
		this.chromeEventOrder(request);
		expect(chrome.runtime.sendMessage.called).toBe(false);
	});

	it("Should capture a request when Toggle is ON.", function() {
		appOptions.isCaptureStateEnabled = true;
        var request = getNewRequest(1);
		this.chromeEventOrder(request);

		expect(chrome.runtime.sendMessage.args[0][0]).toBe('POSTMAN');
		expect(chrome.runtime.sendMessage.args[0][1].postmanMessage.reqId).toBe(1);
		expect(chrome.runtime.sendMessage.args[0][1].postmanMessage.request).toBe(request);

		appOptions.isCaptureStateEnabled = false;
	});

    it("Filter should allow all domains by default", function() {
        appOptions.isCaptureStateEnabled = true;
        expect(appOptions.filterRequestUrl).toBe(".*");
        var request = getNewRequest(1);
        this.chromeEventOrder(request);

        expect(chrome.runtime.sendMessage.called).toBe(true);
        expect(chrome.runtime.sendMessage.args[0][1].postmanMessage.reqId).toBe(1);
    });

    it("Filter should block incorrect domains when enabled", function() {
        appOptions.isCaptureStateEnabled = true;
        appOptions.filterRequestUrl = "google";
        var request = getNewRequest(1);
        this.chromeEventOrder(request);

        expect(chrome.runtime.sendMessage.called).toBe(false);

        appOptions.filterRequestUrl = ".*";
    });

    it("Filter should allow correct domains when enabled", function() {
        appOptions.isCaptureStateEnabled = true;
        appOptions.filterRequestUrl = "google";
        var request = getNewRequest(2);
        request.url = "www.google.com/someXHR";
        this.chromeEventOrder(request);

        expect(chrome.runtime.sendMessage.called).toBe(true);
        expect(chrome.runtime.sendMessage.args[0][1].postmanMessage.reqId).toBe(2);

        appOptions.filterRequestUrl = ".*";
    });

    it("Postman requests should not be captured", function(){
        appOptions.isCaptureStateEnabled = true;
        var request = getNewRequest(3);
        // set a postman header to mock a postman request
        request.requestHeaders = [ { name: "Postman-Token", value: "1" } ];
        this.chromeEventOrder(request);

        expect(chrome.runtime.sendMessage.called).toBe(false);
    });

    it("clears cache on each request", function() {
    });

	afterEach(function() {
		this.chromeEventOrder = null;
        appOptions.isCaptureStateEnabled = false;
		chrome.runtime.sendMessage.restore();
	});

});

describe("When Postman sends a message to Interceptor", function() {

    it("Toggle should send correct message to interceptor", function() {
        var postmanMessage = getPostmanMessage("detectExtension");
        var sender = { id: 1 };
        var sendResponse = sinon.stub();
        onExternalMessage(postmanMessage, sender, sendResponse);

        expect(sendResponse.called).toBe(true);
        expect(sendResponse.callCount).toBe(2);
        expect(sendResponse.args[0][0].result).toBe("Ok, got your message");
    });

    it("Interceptor should recieve XHR request from Postman", function() {
        var postmanMessage = getPostmanMessage("xhrRequest");
        var sender = { id: 1 };
        var sendResponse = sinon.stub();
        sinon.stub(window, 'sendXhrRequest');
        onExternalMessage(postmanMessage, sender, sendResponse);

        expect(sendResponse.called).toBe(true);
        expect(sendResponse.calledOnce).toBe(true);
        expect(sendResponse.args[0][0].result).toBe("Ok, got your message");
        expect(sendXhrRequest.called).toBe(true);
        expect(sendXhrRequest.args[0][0].headers[0]["key"]).toBe("Postman-Token");
    });

});
<|endoftext|>


<commit_before>var stringifyError = require('./stringify-error');

module.exports = function (app, bundle) {
  //
  // Singular bundles
  //
  app.get('/bundle/:module', singular(bundle));
  app.get('/debug-bundle/:module', singular(bundle, { debug: true }));
  app.get('/standalone/:module', singular(bundle, { standalone: true }));
  app.get('/debug-standalone/:module', singular(bundle, { standalone: true, debug: true }));
};

function singular(bundle, opts) {
  opts = opts || {};

  return function (req, res) {
    var t = req.params.module.split('@'),
        module = t.shift(),
        version;

    if (t.length) {
      version = t.shift();
    }
    else {
      version = 'latest';
    }

    opts.module = module;
    opts.version = version;

    bundle(opts, serveBundle(res));
  };
}

function serveBundle(res) {
  return function (err, bundle) {
    if (err) {
      res.setHeader('content-type', 'text/plain');
      res.statusCode = 500;
      res.write(stringifyError.hello);
      res.write(stringifyError(err));
      res.end(stringifyError.goodbye);
    }
    res.setHeader('content-type', 'text/javascript');
    res.end(bundle);
  };
}
<commit_msg>[fix] On bundle errors, only end the response once<commit_after>var stringifyError = require('./stringify-error');

module.exports = function (app, bundle) {
  //
  // Singular bundles
  //
  app.get('/bundle/:module', singular(bundle));
  app.get('/debug-bundle/:module', singular(bundle, { debug: true }));
  app.get('/standalone/:module', singular(bundle, { standalone: true }));
  app.get('/debug-standalone/:module', singular(bundle, { standalone: true, debug: true }));
};

function singular(bundle, opts) {
  opts = opts || {};

  return function (req, res) {
    var t = req.params.module.split('@'),
        module = t.shift(),
        version;

    if (t.length) {
      version = t.shift();
    }
    else {
      version = 'latest';
    }

    opts.module = module;
    opts.version = version;

    bundle(opts, serveBundle(res));
  };
}

function serveBundle(res) {
  return function (err, bundle) {
    if (err) {
      res.setHeader('content-type', 'text/plain');
      res.statusCode = 500;
      res.write(stringifyError.hello);
      res.write(stringifyError(err));
      return res.end(stringifyError.goodbye);
    }
    res.setHeader('content-type', 'text/javascript');
    res.end(bundle);
  };
}
<|endoftext|>