<commit_before>/*
	Name: autoComplete
	Authors:
		Andy Matthews: @commadelimited
		Raymond Camden: @cfjedimaster

	Website: http://andyMatthews.net
	Version: 1.5.1
*/(function(e){"use strict";var t={method:"GET",icon:"arrow-r",cancelRequests:!1,target:e(),source:null,callback:null,link:null,minLength:0,transition:"fade",matchFromStart:!0,labelHTML:function(e){return e},onNoResults:function(){return},onLoading:function(){return},onLoadingFinished:function(){return},termParam:"term",loadingHtml:'
Searching...
',interval:0,builder:null},n={},r=function(t,n,r){var s;if(r.builder)s=r.builder.apply(t.eq(0),[n,r]);else{s=[];n&&e.each(n,function(t,n){e.isPlainObject(n)?s.push("
"+r.labelHTML(n.label)+"
"):s.push("
'+r.labelHTML(n)+"
")})}e.isArray(s)&&(s=s.join(""));e(r.target).html(s).listview("refresh");r.callback!==null&&e.isFunction(r.callback)&&i(r);if(s.length>0)t.trigger("targetUpdated.autocomplete");else{t.trigger("targetCleared.autocomplete");r.onNoResults&&r.onNoResults()}},i=function(t){e("li a",e(t.target)).bind("click.autocomplete",function(e){e.stopPropagation();e.preventDefault();t.callback(e)})},s=function(e,t){t.html("").listview("refresh").closest("fieldset").removeClass("ui-search-active");e.trigger("targetCleared.autocomplete")},o=function(t){var i=e(this),u=i.attr("id"),a,f,l=i.jqmData("autocomplete"),c,h;Date.now||(Date.now=function(){return(new Date).valueOf()});t&&(t.keyCode===38?e(".ui-btn-active",e(l.target)).removeClass("ui-btn-active").prevAll("li.ui-btn:eq(0)").addClass("ui-btn-active").length||e(".ui-btn:last",e(l.target)).addClass("ui-btn-active"):t.keyCode===40?e(".ui-btn-active",e(l.target)).removeClass("ui-btn-active").nextAll("li.ui-btn:eq(0)").addClass("ui-btn-active").length||e(".ui-btn:first",e(l.target)).addClass("ui-btn-active"):t.keyCode===13&&(e(".ui-btn-active a",e(l.target)).click().length||e(".ui-btn:first a",e(l.target)).click()));if(l){a=i.val();if(l._lastText===a)return;if(l._retryTimeout){window.clearTimeout(l._retryTimeout);l._retryTimeout=null}if(!(!t||t.keyCode!==13&&t.keyCode!==38&&t.keyCode!==40))return;if(a.length<l.minLength)s(i,e(l.target));else{if(l.interval&&Date.now()-l._lastRequest<l.interval){l._retryTimeout=window.setTimeout(e.proxy(o,this),l.interval-Date.now()+l._lastRequest);return}l._lastRequest=Date.now();l._lastText=a;if(e.isArray(l.source)){f=l.source.sort().filter(function(t){l.matchFromStart?(c,h=new RegExp("^"+a,"i")):(c,h=new RegExp(a,"i"));e.isPlainObject(t)?c=t.label:c=t;return h.test(c)});r(i,f,l)}else if(typeof l.source=="function")l.source(a,function(e){r(i,e,l)});else{var p={type:l.method,data:{},dataType:"json",beforeSend:function(e){if(l.cancelRequests){n[u]&&n[u].abort();n[u]=e}l.onLoading&&l.onLoadingFinished&&l.onLoading();if(l.loadingHtml){l.target.html(l.loadingHtml).listview("refresh");l.target.closest("fieldset").addClass("ui-search-active")}},success:function(e){r(i,e,l)},complete:function(){l.cancelRequests&&(n[u]=null);l.onLoadingFinished&&l.onLoadingFinished()}};if(e.isPlainObject(l.source)){l.source.callback&&l.source.callback(a,p);for(var d in l.source)d!=="callback"&&(p[d]=l.source[d])}else p.url=l.source;l.termParam&&(p.data[l.termParam]=a);e.ajax(p)}}}},u={init:function(n){var r=this;r.jqmData("autocomplete",e.extend({},t,n));var i=r.jqmData("autocomplete");return r.unbind("keyup.autocomplete").bind("keyup.autocomplete",o).next(".ui-input-clear").bind("click",function(){s(r,e(i.target))})},update:function(t){var n=this.jqmData("autocomplete");n&&this.jqmData("autocomplete",e.extend(n,t));return this},clear:function(){var t=this.jqmData("autocomplete");t&&s(this,e(t.target));return this},destroy:function(){var t=this.jqmData("autocomplete");if(t){s(this,e(t.target));this.jqmRemoveData("autocomplete");this.unbind(".autocomplete")}return this}};e.fn.autocomplete=function(e){if(u[e])return u[e].apply(this,Array.prototype.slice.call(arguments,1));if(typeof e=="object"||!e)return u.init.apply(this,arguments)}})(jQuery);<commit_msg>Minor bug fixes, new version number.<commit_after>/*
	Name: autoComplete
	Authors:
		Andy Matthews: @commadelimited
		Raymond Camden: @cfjedimaster

	Website: http://andyMatthews.net
	Version: 1.5.1
*/(function(e){"use strict";var t={method:"GET",icon:"arrow-r",cancelRequests:!1,target:e(),source:null,callback:null,link:null,minLength:0,transition:"fade",matchFromStart:!0,labelHTML:function(e){return e},onNoResults:function(){return},onLoading:function(){return},onLoadingFinished:function(){return},termParam:"term",loadingHtml:'
Searching...
',interval:0,builder:null},n={},r=function(t,n,r){var s;if(r.builder)s=r.builder.apply(t.eq(0),[n,r]);else{s=[];n&&e.each(n,function(t,n){e.isPlainObject(n)?s.push("
"+r.labelHTML(n.label)+"
"):s.push("
'+r.labelHTML(n)+"
")})}e.isArray(s)&&(s=s.join(""));e(r.target).html(s).listview("refresh");r.callback!==null&&e.isFunction(r.callback)&&i(r);if(s.length>0)t.trigger("targetUpdated.autocomplete");else{t.trigger("targetCleared.autocomplete");r.onNoResults&&r.onNoResults()}},i=function(t){e("li a",e(t.target)).bind("click.autocomplete",function(e){e.stopPropagation();e.preventDefault();t.callback(e)})},s=function(e,t){t.html("").listview("refresh").closest("fieldset").removeClass("ui-search-active");e.trigger("targetCleared.autocomplete")},o=function(t){var i=e(this),u=i.attr("id"),a,f,l=i.jqmData("autocomplete"),c,h;Date.now||(Date.now=function(){return(new Date).valueOf()});t&&(t.keyCode===38?e(".ui-btn-active",e(l.target)).removeClass("ui-btn-active").prevAll("li.ui-btn:eq(0)").addClass("ui-btn-active").length||e(".ui-btn:last",e(l.target)).addClass("ui-btn-active"):t.keyCode===40?e(".ui-btn-active",e(l.target)).removeClass("ui-btn-active").nextAll("li.ui-btn:eq(0)").addClass("ui-btn-active").length||e(".ui-btn:first",e(l.target)).addClass("ui-btn-active"):t.keyCode===13&&(e(".ui-btn-active a",e(l.target)).click().length||e(".ui-btn:first a",e(l.target)).click()));if(l){a=i.val();if(l._lastText===a)return;if(l._retryTimeout){window.clearTimeout(l._retryTimeout);l._retryTimeout=null}if(!(!t||t.keyCode!==13&&t.keyCode!==38&&t.keyCode!==40))return;if(a.length<l.minLength)s(i,e(l.target));else{if(l.interval&&Date.now()-l._lastRequest<l.interval){l._retryTimeout=window.setTimeout(e.proxy(o,this),l.interval-Date.now()+l._lastRequest);return}l._lastRequest=Date.now();l._lastText=a;if(e.isArray(l.source)){f=l.source.sort().filter(function(t){l.matchFromStart?(c,h=new RegExp("^"+a,"i")):(c,h=new RegExp(a,"i"));e.isPlainObject(t)?c=t.label:c=t;return h.test(c)});r(i,f,l)}else if(typeof l.source=="function")l.source(a,function(e){r(i,e,l)});else{var p={type:l.method,data:{},dataType:"json",beforeSend:function(t){if(l.cancelRequests){n[u]&&n[u].abort();n[u]=t}l.onLoading&&l.onLoadingFinished&&l.onLoading();if(l.loadingHtml){e(l.target).html(l.loadingHtml).listview("refresh");e(l.target).closest("fieldset").addClass("ui-search-active")}},success:function(e){r(i,e,l)},complete:function(){l.cancelRequests&&(n[u]=null);l.onLoadingFinished&&l.onLoadingFinished()}};if(e.isPlainObject(l.source)){l.source.callback&&l.source.callback(a,p);for(var d in l.source)d!=="callback"&&(p[d]=l.source[d])}else p.url=l.source;l.termParam&&(p.data[l.termParam]=a);e.ajax(p)}}}},u={init:function(n){var r=this;r.jqmData("autocomplete",e.extend({},t,n));var i=r.jqmData("autocomplete");return r.unbind("keyup.autocomplete").bind("keyup.autocomplete",o).next(".ui-input-clear").bind("click",function(){s(r,e(i.target))})},update:function(t){var n=this.jqmData("autocomplete");n&&this.jqmData("autocomplete",e.extend(n,t));return this},clear:function(){var t=this.jqmData("autocomplete");t&&s(this,e(t.target));return this},destroy:function(){var t=this.jqmData("autocomplete");if(t){s(this,e(t.target));this.jqmRemoveData("autocomplete");this.unbind(".autocomplete")}return this}};e.fn.autocomplete=function(e){if(u[e])return u[e].apply(this,Array.prototype.slice.call(arguments,1));if(typeof e=="object"||!e)return u.init.apply(this,arguments)}})(jQuery);<|endoftext|>


<commit_before>var CodeBox = {

  disableJavascript:  null,
  element:            null,
  submitButtons:      null,
  editor:             null,
  editorSession:      null,
  editorElement:      null,
  cont:               true,
  high:               false,
  animationTime:      800,
  waitTimePerItem:    500,
  images:             null,

  initialize: function() {
    this.disableJavascript = $('#disable-javascript-codebox').length > 0;
    this.element = $("#code-box");
    this.submitButtons = $("#run-button, #submission-button");

    if(!this.disableJavascript && this.submitButtons.length > 0) {
      this.setupEditor();
    }

    this.submitButtons.live("click", $.proxy(this.run, this));
  },

  setupEditor: function() {
    this.element.after("

" +
        this.element.val() + "

");

    this.element.hide();
    this.editorElement = $("#editor");

    this.editor = ace.edit("editor");
    this.editor.setTheme("ace/theme/textmate");

    var ClojureMode = require("ace/mode/clojure").Mode;
    this.editorSession = this.editor.getSession();
    this.editorSession.setMode(new ClojureMode());
    this.editorSession.setUseSoftTabs(true);
    this.editorSession.setTabSize(2);
    this.editorElement.css("font-size", "13px");
  },

  getCode: function() {
    if(this.disableJavascript)
      return $("#code-box").val();
    else
      return this.editorSession.getValue();
  },

  run: function(e) {
    e.preventDefault();

    var text = this.getCode(),
      id = $('#id').attr("value");

    this.images = $(".testcases").find("img"),

    $.ajax({
      type: "POST",
      url: "/rest/problem/"+id,
      dataType: "json",
      data: { id: id, code: text, },
      timeout: 20000, // default clojail timeout is 10000
      beforeSend: $.proxy(this.beforeSendCallback, this),
      success: $.proxy(this.successCallback, this),
      error: function(data, str, error) {
        $("#message-text").text("An Error occured: "+error);
      }});
  },

  beforeSendCallback: function() {
    var anim = function() {
      if(this.cont) {
        this.images.animate({
          opacity: this.high ? 1.0 : 0.1,
        }, this.animationTime);
        this.high = !this.high;
        setTimeout(anim,this.animationTime);
      }
    };

    $("#message-text").text("Executing unit tests...");
    $("#error-message-text").text("");
    this.images.each( function(index, element) {
      setIconColor(element, "blue");
    });
    setTimeout(changeToCodeView,0);
    setTimeout($.proxy(anim, this),0);
  },

  successCallback: function(data) {
    var waitTime = this.waitTimePerItem;

    var failingTest = data.failingTest,
      getColorFor = function(index) {
        return index === failingTest ? "red" : "green";
      },
      testWasExecuted = function(index) {
        return index <= failingTest;
      },
      setColor = function(index,element) {
        var color = getColorFor(index);
        waitTime = CodeBox.waitTimePerItem * (index+1);
        setIconColor(element, color, waitTime);
      },
      setMessages = function() {
        alert("setting messages");
        $("#message-text").html(data.message);
        $("#error-message-text").html(data.error);
        $("#golfgraph").html(data.golfChart);
        $("#golfscore").html(data.golfScore);
        configureGolf();
      },
      stopAnimation = function() {
        this.cont = false;
        this.images.stop(true);
        this.images.css({ opacity: 1.0, });
      };

    setTimeout($.proxy(stopAnimation, this), waitTime);
    this.images.filter( testWasExecuted ).each(setColor);
    setTimeout(setMessages, waitTime);
  },
}
<commit_msg>Removed debug line<commit_after>var CodeBox = {

  disableJavascript:  null,
  element:            null,
  submitButtons:      null,
  editor:             null,
  editorSession:      null,
  editorElement:      null,
  cont:               true,
  high:               false,
  animationTime:      800,
  waitTimePerItem:    500,
  images:             null,

  initialize: function() {
    this.disableJavascript = $('#disable-javascript-codebox').length > 0;
    this.element = $("#code-box");
    this.submitButtons = $("#run-button, #submission-button");

    if(!this.disableJavascript && this.submitButtons.length > 0) {
      this.setupEditor();
    }

    this.submitButtons.live("click", $.proxy(this.run, this));
  },

  setupEditor: function() {
    this.element.after("

" +
        this.element.val() + "

");

    this.element.hide();
    this.editorElement = $("#editor");

    this.editor = ace.edit("editor");
    this.editor.setTheme("ace/theme/textmate");

    var ClojureMode = require("ace/mode/clojure").Mode;
    this.editorSession = this.editor.getSession();
    this.editorSession.setMode(new ClojureMode());
    this.editorSession.setUseSoftTabs(true);
    this.editorSession.setTabSize(2);
    this.editorElement.css("font-size", "13px");
  },

  getCode: function() {
    if(this.disableJavascript)
      return $("#code-box").val();
    else
      return this.editorSession.getValue();
  },

  run: function(e) {
    e.preventDefault();

    var text = this.getCode(),
      id = $('#id').attr("value");

    this.images = $(".testcases").find("img"),

    $.ajax({
      type: "POST",
      url: "/rest/problem/"+id,
      dataType: "json",
      data: { id: id, code: text, },
      timeout: 20000, // default clojail timeout is 10000
      beforeSend: $.proxy(this.beforeSendCallback, this),
      success: $.proxy(this.successCallback, this),
      error: function(data, str, error) {
        $("#message-text").text("An Error occured: "+error);
      }});
  },

  beforeSendCallback: function() {
    var anim = function() {
      if(this.cont) {
        this.images.animate({
          opacity: this.high ? 1.0 : 0.1,
        }, this.animationTime);
        this.high = !this.high;
        setTimeout(anim,this.animationTime);
      }
    };

    $("#message-text").text("Executing unit tests...");
    $("#error-message-text").text("");
    this.images.each( function(index, element) {
      setIconColor(element, "blue");
    });
    setTimeout(changeToCodeView,0);
    setTimeout($.proxy(anim, this),0);
  },

  successCallback: function(data) {
    var waitTime = this.waitTimePerItem;

    var failingTest = data.failingTest,
      getColorFor = function(index) {
        return index === failingTest ? "red" : "green";
      },
      testWasExecuted = function(index) {
        return index <= failingTest;
      },
      setColor = function(index,element) {
        var color = getColorFor(index);
        waitTime = CodeBox.waitTimePerItem * (index+1);
        setIconColor(element, color, waitTime);
      },
      setMessages = function() {
        $("#message-text").html(data.message);
        $("#error-message-text").html(data.error);
        $("#golfgraph").html(data.golfChart);
        $("#golfscore").html(data.golfScore);
        configureGolf();
      },
      stopAnimation = function() {
        this.cont = false;
        this.images.stop(true);
        this.images.css({ opacity: 1.0, });
      };

    setTimeout($.proxy(stopAnimation, this), waitTime);
    this.images.filter( testWasExecuted ).each(setColor);
    setTimeout(setMessages, waitTime);
  },
}
<|endoftext|>


<commit_before>/**
 * RDTA alert dialog
 */

class RDTAAlertDialog {

    /**
     * Class constructor.
     *
     * @private Do not access this method directly, it was called from `alert()` method.
     * @param {object} options
     * @returns {RDTAAlertDialog}
     */
    constructor(options) {
        let defaultOptions = {
            'type': 'danger',
            'html': '',
            'text': '',
            'txtCloseButton': 'OK'
        };
        this.options = Object.assign(defaultOptions, options);
        defaultOptions = undefined;
    }// constructor

    /**
     * Display alert dialog.
     *
     * @param {object} options
     * @returns {undefined}
     */
    static alert(options) {
        let thisClass = new this(options);

        // create HTML and put to body
        thisClass.createHtmlDialog();
        // listen on click ok (close) button
        thisClass.listenOnCloseButton();
        // listen on key press (esc) to close.
        thisClass.listenOnKeyPressClose();
    }// alert

    /**
     * Create HTML and put into body.
     *
     * @returns {undefined}
     */
    createHtmlDialog() {
        let dialogMessage = '';
        if (this.options && this.options.text) {
            dialogMessage = '
' + this.options.text + '
';
        } else {
            dialogMessage = this.options.html;
        }

        let dialogIcon = '';
        let alertClass = '';
        if (this.options && this.options.type) {
            switch (this.options.type) {
                case 'info':
                    dialogIcon = '';
                    alertClass = 'alert-info';
                    break;
                case 'warning':
                    dialogIcon = '';
                    alertClass = 'alert-warning';
                    break;
                case 'success':
                    dialogIcon = '';
                    alertClass = 'alert-success';
                    break;
                case 'danger':
                default:
                    dialogIcon = '';
                    alertClass = 'alert-danger';
                    break;
            }
        }

        let dialogHtml = '
' +
            '
' +
                '
' +
                    '
' + dialogIcon + '
' +
                    dialogMessage +
                '
' +
                '
' +
                    '<button class="rd-button primary" type="button" data-dismiss="dialog" aria-label="' + (this.options ? this.options.txtCloseButton : 'OK') + '">' +
                        (this.options ? this.options.txtCloseButton : 'OK') +
                    '</button>' +
                '
' +
            '
' +
        '
';

        document.body.insertAdjacentHTML('beforeend', dialogHtml);
        document.body.classList.add('rd-alertdialog-modal-open');

        if (document.querySelector('.rd-alertdialog [data-dismiss="dialog"]')) {
            document.querySelector('.rd-alertdialog [data-dismiss="dialog"]').focus();
        }
    }// createHtmlDialog

    /**
     * Listen on click OK (close) button to close dialog.
     *
     * @returns {undefined}
     */
    listenOnCloseButton() {
        let thisClass = this;

        document.body.addEventListener('click', function handler(event) {
            for (let target= event.target; target && target != this; target = target.parentNode) {
                // loop parent nodes from the target to the delegation node
                if (target.matches('[data-dismiss="dialog"]')) {
                    if (target.closest('.rd-alertdialog-modal')) {
                        target.closest('.rd-alertdialog-modal').remove();
                        document.body.classList.remove('rd-alertdialog-modal-open');
                        document.body.removeEventListener('click', handler);
                    }
                    break;
                }
            }
        });
    }// listenOnCloseButton

    /**
     * Listen on key press to close if no attribute specified.
     *
     * @private
     */
    listenOnKeyPressClose() {
        document.body.addEventListener('keyup', function handler(event) {
            if (
                (event.key === 'Escape' || event.code === 'NumpadEnter' || event.key === 'Enter') &&
                event.altKey === false &&
                event.ctrlKey === false &&
                event.metaKey === false &&
                event.shiftKey === false
            ) {
                if (document.querySelector('.rd-alertdialog-modal.show')) {
                    if (
                        document.querySelector('.rd-alertdialog-modal.show .rd-alertdialog') &&
                        document.querySelector('.rd-alertdialog-modal.show .rd-alertdialog').dataset &&
                        document.querySelector('.rd-alertdialog-modal.show .rd-alertdialog').dataset.escKeyNotClose !== 'true'
                    ) {
                        if (document.querySelector('.rd-alertdialog-modal.show [data-dismiss="dialog"]')) {
                            document.querySelector('.rd-alertdialog-modal.show [data-dismiss="dialog"]').focus();
                            document.querySelector('.rd-alertdialog-modal.show [data-dismiss="dialog"]').click();
                        }
                    }
                }
            }
        });
    }// listenOnKeyPressClose

}// RDTAAlertDialog<commit_msg>Add events to alert dialog.<commit_after>/**
 * RDTA alert dialog
 */

class RDTAAlertDialog {

    /**
     * Class constructor.
     *
     * @private Do not access this method directly, it was called from `alert()` method.
     * @param {object} options
     * @returns {RDTAAlertDialog}
     */
    constructor(options) {
        let defaultOptions = {
            'type': 'danger',
            'html': '',
            'text': '',
            'txtCloseButton': 'OK'
        };
        this.options = Object.assign(defaultOptions, options);
        defaultOptions = undefined;
    }// constructor

    /**
     * Display alert dialog.
     *
     * @param {object} options
     * @returns {undefined}
     */
    static alert(options) {
        let thisClass = new this(options);

        // create HTML and put to body
        thisClass.createHtmlDialog();
        // listen on click ok (close) button
        thisClass.listenOnCloseButton();
        // listen on key press (esc) to close.
        thisClass.listenOnKeyPressClose();
    }// alert

    /**
     * Create HTML and put into body.
     *
     * @returns {undefined}
     */
    createHtmlDialog() {
        let dialogMessage = '';
        if (this.options && this.options.text) {
            dialogMessage = '
' + this.options.text + '
';
        } else {
            dialogMessage = this.options.html;
        }

        let dialogIcon = '';
        let alertClass = '';
        if (this.options && this.options.type) {
            switch (this.options.type) {
                case 'info':
                    dialogIcon = '';
                    alertClass = 'alert-info';
                    break;
                case 'warning':
                    dialogIcon = '';
                    alertClass = 'alert-warning';
                    break;
                case 'success':
                    dialogIcon = '';
                    alertClass = 'alert-success';
                    break;
                case 'danger':
                default:
                    dialogIcon = '';
                    alertClass = 'alert-danger';
                    break;
            }
        }

        let dialogHtml = '
' +
            '
' +
                '
' +
                    '
' + dialogIcon + '
' +
                    dialogMessage +
                '
' +
                '
' +
                    '<button class="rd-button primary" type="button" data-dismiss="dialog" aria-label="' + (this.options ? this.options.txtCloseButton : 'OK') + '">' +
                        (this.options ? this.options.txtCloseButton : 'OK') +
                    '</button>' +
                '
' +
            '
' +
        '
';

        document.body.insertAdjacentHTML('beforeend', dialogHtml);
        document.body.classList.add('rd-alertdialog-modal-open');

        if (document.querySelector('.rd-alertdialog [data-dismiss="dialog"]')) {
            document.querySelector('.rd-alertdialog [data-dismiss="dialog"]').focus();
        }

        // fire event.
        let event = new Event('rdta.alertdialog.opened');
        document.body.dispatchEvent(event);
    }// createHtmlDialog

    /**
     * Listen on click OK (close) button to close dialog.
     *
     * @returns {undefined}
     */
    listenOnCloseButton() {
        let thisClass = this;

        document.body.addEventListener('click', function handler(event) {
            for (let target= event.target; target && target != this; target = target.parentNode) {
                // loop parent nodes from the target to the delegation node
                if (target.matches('[data-dismiss="dialog"]')) {
                    if (target.closest('.rd-alertdialog-modal')) {
                        target.closest('.rd-alertdialog-modal').remove();
                        document.body.classList.remove('rd-alertdialog-modal-open');
                        document.body.removeEventListener('click', handler);

                        // fire event
                        let event = new Event('rdta.alertdialog.closed');
                        document.body.dispatchEvent(event);
                    }
                    break;
                }
            }
        });
    }// listenOnCloseButton

    /**
     * Listen on key press to close if no attribute specified.
     *
     * @private
     */
    listenOnKeyPressClose() {
        document.body.addEventListener('keyup', function handler(event) {
            if (
                (event.key === 'Escape' || event.code === 'NumpadEnter' || event.key === 'Enter') &&
                event.altKey === false &&
                event.ctrlKey === false &&
                event.metaKey === false &&
                event.shiftKey === false
            ) {
                if (document.querySelector('.rd-alertdialog-modal.show')) {
                    if (
                        document.querySelector('.rd-alertdialog-modal.show .rd-alertdialog') &&
                        document.querySelector('.rd-alertdialog-modal.show .rd-alertdialog').dataset &&
                        document.querySelector('.rd-alertdialog-modal.show .rd-alertdialog').dataset.escKeyNotClose !== 'true'
                    ) {
                        if (document.querySelector('.rd-alertdialog-modal.show [data-dismiss="dialog"]')) {
                            document.querySelector('.rd-alertdialog-modal.show [data-dismiss="dialog"]').focus();
                            document.querySelector('.rd-alertdialog-modal.show [data-dismiss="dialog"]').click();
                        }
                    }
                }
            }
        });
    }// listenOnKeyPressClose

}// RDTAAlertDialog<|endoftext|>


<commit_before>/**
 * `modules/analytics` data store: settings.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import invariant from 'invariant';

/**
 * Internal dependencies
 */
import API from 'googlesitekit-api';
import { CORE_FORMS } from '../../../googlesitekit/datastore/forms/constants';
import { CORE_MODULES } from '../../../googlesitekit/modules/datastore/constants';
import { MODULES_TAGMANAGER } from '../../tagmanager/datastore/constants';
import {
	MODULES_ANALYTICS_4,
	PROPERTY_CREATE as GA4_PROPERTY_CREATE,
	WEBDATASTREAM_CREATE,
} from '../../analytics-4/datastore/constants';
import {
	INVARIANT_DOING_SUBMIT_CHANGES,
	INVARIANT_SETTINGS_NOT_CHANGED,
} from '../../../googlesitekit/data/create-settings-store';
import {
	isValidAccountID,
	isValidInternalWebPropertyID,
	isValidPropertySelection,
	isValidProfileSelection,
	isValidPropertyID,
	isValidProfileName,
	isValidAdsConversionID,
} from '../util';
import {
	MODULES_ANALYTICS,
	PROPERTY_CREATE,
	PROFILE_CREATE,
	FORM_SETUP,
} from './constants';
import { createStrictSelect } from '../../../googlesitekit/data/utils';
import { isFeatureEnabled } from '../../../features';
import { isPermissionScopeError } from '../../../util/errors';

// Invariant error messages.
export const INVARIANT_INVALID_ACCOUNT_ID =
	'a valid accountID is required to submit changes';
export const INVARIANT_INVALID_PROPERTY_SELECTION =
	'a valid propertyID is required to submit changes';
export const INVARIANT_INVALID_PROFILE_SELECTION =
	'a valid profileID is required to submit changes';
export const INVARIANT_INVALID_CONVERSION_ID =
	'a valid adsConversionID is required to submit changes';
export const INVARIANT_INSUFFICIENT_GTM_TAG_PERMISSIONS =
	'cannot submit changes without having permissions for GTM property ID';
export const INVARIANT_INVALID_PROFILE_NAME =
	'a valid profile name is required to submit changes';
export const INVARIANT_INVALID_INTERNAL_PROPERTY_ID =
	'cannot submit changes with incorrect internal webPropertyID';
export const INVARIANT_INSUFFICIENT_TAG_PERMISSIONS =
	'cannot submit without proper permissions';

async function submitGA4Changes( { select, dispatch } ) {
	if ( ! select( MODULES_ANALYTICS_4 ).haveSettingsChanged() ) {
		return {};
	}

	const { error } = await dispatch( MODULES_ANALYTICS_4 ).submitChanges();
	if ( isPermissionScopeError( error ) ) {
		return { error };
	}

	return {};
}

export async function submitChanges( registry ) {
	const { select, dispatch } = registry;

	let propertyID = select( MODULES_ANALYTICS ).getPropertyID();
	if ( propertyID === PROPERTY_CREATE ) {
		const accountID = select( MODULES_ANALYTICS ).getAccountID();
		const { response: property, error } = await dispatch(
			MODULES_ANALYTICS
		).createProperty( accountID );

		if ( error ) {
			return { error };
		}

		propertyID = property.id;
		dispatch( MODULES_ANALYTICS ).setPropertyID( property.id );
		dispatch( MODULES_ANALYTICS ).setInternalWebPropertyID(
			// eslint-disable-next-line sitekit/acronym-case
			property.internalWebPropertyId
		);
	}

	const profileID = select( MODULES_ANALYTICS ).getProfileID();
	if ( profileID === PROFILE_CREATE ) {
		const profileName = select( CORE_FORMS ).getValue(
			FORM_SETUP,
			'profileName'
		);
		const accountID = select( MODULES_ANALYTICS ).getAccountID();
		const { response: profile, error } = await dispatch(
			MODULES_ANALYTICS
		).createProfile( accountID, propertyID, { profileName } );

		if ( error ) {
			return { error };
		}

		dispatch( MODULES_ANALYTICS ).setProfileID( profile.id );
	}

	const ga4PropertyID = select( MODULES_ANALYTICS_4 ).getPropertyID();
	const ga4StreamID = select( MODULES_ANALYTICS_4 ).getWebDataStreamID();

	if (
		ga4PropertyID === GA4_PROPERTY_CREATE ||
		ga4StreamID === WEBDATASTREAM_CREATE
	) {
		const { error } = await submitGA4Changes( registry );
		if ( error ) {
			return { error };
		}
	}

	// This action shouldn't be called if settings haven't changed,
	// but this prevents errors in tests.
	if ( select( MODULES_ANALYTICS ).haveSettingsChanged() ) {
		const { error } = await dispatch( MODULES_ANALYTICS ).saveSettings();

		if ( error ) {
			return { error };
		}
	}

	await API.invalidateCache( 'modules', 'analytics' );

	const { error } = await submitGA4Changes( registry );
	if ( error ) {
		return { error };
	}

	return {};
}

export function rollbackChanges( { select, dispatch } ) {
	dispatch( MODULES_ANALYTICS_4 ).rollbackChanges();

	if ( select( MODULES_ANALYTICS ).haveSettingsChanged() ) {
		dispatch( MODULES_ANALYTICS ).rollbackSettings();
	}
}

export function validateCanSubmitChanges( select ) {
	const isGA4Enabled = isFeatureEnabled( 'ga4setup' );

	const strictSelect = createStrictSelect( select );
	const {
		getAccountID,
		getAdsConversionID,
		getInternalWebPropertyID,
		getProfileID,
		getPropertyID,
		hasExistingTagPermission,
		hasTagPermission,
		haveSettingsChanged,
		isDoingSubmitChanges,
	} = strictSelect( MODULES_ANALYTICS );

	// Note: these error messages are referenced in test assertions.
	invariant( ! isDoingSubmitChanges(), INVARIANT_DOING_SUBMIT_CHANGES );

	const gtmIsActive = strictSelect( CORE_MODULES ).isModuleActive(
		'tagmanager'
	);
	if ( gtmIsActive ) {
		const gtmAnalyticsPropertyID = strictSelect(
			MODULES_TAGMANAGER
		).getSingleAnalyticsPropertyID();
		invariant(
			! isValidPropertyID( gtmAnalyticsPropertyID ) ||
				hasTagPermission( gtmAnalyticsPropertyID ) !== false,
			INVARIANT_INSUFFICIENT_GTM_TAG_PERMISSIONS
		);
	}

	invariant(
		haveSettingsChanged() ||
			( isGA4Enabled &&
				select( MODULES_ANALYTICS_4 ).haveSettingsChanged() ),
		INVARIANT_SETTINGS_NOT_CHANGED
	);

	invariant(
		isValidAccountID( getAccountID() ),
		INVARIANT_INVALID_ACCOUNT_ID
	);
	invariant(
		isValidPropertySelection( getPropertyID() ),
		INVARIANT_INVALID_PROPERTY_SELECTION
	);
	invariant(
		isValidProfileSelection( getProfileID() ),
		INVARIANT_INVALID_PROFILE_SELECTION
	);

	if ( getAdsConversionID() ) {
		invariant(
			isValidAdsConversionID( getAdsConversionID() ),
			INVARIANT_INVALID_CONVERSION_ID
		);
	}

	if ( getProfileID() === PROFILE_CREATE ) {
		const profileName = select( CORE_FORMS ).getValue(
			FORM_SETUP,
			'profileName'
		);
		invariant(
			isValidProfileName( profileName ),
			INVARIANT_INVALID_PROFILE_NAME
		);
	}

	// If the property ID is valid (non-create) the internal ID must be valid as well.
	invariant(
		! isValidPropertyID( getPropertyID() ) ||
			isValidInternalWebPropertyID( getInternalWebPropertyID() ),
		INVARIANT_INVALID_INTERNAL_PROPERTY_ID
	);

	// Do existing tag check last.
	invariant(
		hasExistingTagPermission() !== false,
		INVARIANT_INSUFFICIENT_TAG_PERMISSIONS
	);

	if ( select( MODULES_ANALYTICS ).canUseGA4Controls() ) {
		select( MODULES_ANALYTICS_4 ).__dangerousCanSubmitChanges();
	}
}
<commit_msg>Update settings datastore to keep checking the ga4setup feature flag.<commit_after>/**
 * `modules/analytics` data store: settings.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import invariant from 'invariant';

/**
 * Internal dependencies
 */
import API from 'googlesitekit-api';
import { CORE_FORMS } from '../../../googlesitekit/datastore/forms/constants';
import { CORE_MODULES } from '../../../googlesitekit/modules/datastore/constants';
import { MODULES_TAGMANAGER } from '../../tagmanager/datastore/constants';
import {
	MODULES_ANALYTICS_4,
	PROPERTY_CREATE as GA4_PROPERTY_CREATE,
	WEBDATASTREAM_CREATE,
} from '../../analytics-4/datastore/constants';
import {
	INVARIANT_DOING_SUBMIT_CHANGES,
	INVARIANT_SETTINGS_NOT_CHANGED,
} from '../../../googlesitekit/data/create-settings-store';
import {
	isValidAccountID,
	isValidInternalWebPropertyID,
	isValidPropertySelection,
	isValidProfileSelection,
	isValidPropertyID,
	isValidProfileName,
	isValidAdsConversionID,
} from '../util';
import {
	MODULES_ANALYTICS,
	PROPERTY_CREATE,
	PROFILE_CREATE,
	FORM_SETUP,
} from './constants';
import { createStrictSelect } from '../../../googlesitekit/data/utils';
import { isFeatureEnabled } from '../../../features';
import { isPermissionScopeError } from '../../../util/errors';

// Invariant error messages.
export const INVARIANT_INVALID_ACCOUNT_ID =
	'a valid accountID is required to submit changes';
export const INVARIANT_INVALID_PROPERTY_SELECTION =
	'a valid propertyID is required to submit changes';
export const INVARIANT_INVALID_PROFILE_SELECTION =
	'a valid profileID is required to submit changes';
export const INVARIANT_INVALID_CONVERSION_ID =
	'a valid adsConversionID is required to submit changes';
export const INVARIANT_INSUFFICIENT_GTM_TAG_PERMISSIONS =
	'cannot submit changes without having permissions for GTM property ID';
export const INVARIANT_INVALID_PROFILE_NAME =
	'a valid profile name is required to submit changes';
export const INVARIANT_INVALID_INTERNAL_PROPERTY_ID =
	'cannot submit changes with incorrect internal webPropertyID';
export const INVARIANT_INSUFFICIENT_TAG_PERMISSIONS =
	'cannot submit without proper permissions';

async function submitGA4Changes( { select, dispatch } ) {
	if ( ! select( MODULES_ANALYTICS_4 ).haveSettingsChanged() ) {
		return {};
	}

	const { error } = await dispatch( MODULES_ANALYTICS_4 ).submitChanges();
	if ( isPermissionScopeError( error ) ) {
		return { error };
	}

	return {};
}

export async function submitChanges( registry ) {
	const { select, dispatch } = registry;

	let propertyID = select( MODULES_ANALYTICS ).getPropertyID();
	if ( propertyID === PROPERTY_CREATE ) {
		const accountID = select( MODULES_ANALYTICS ).getAccountID();
		const { response: property, error } = await dispatch(
			MODULES_ANALYTICS
		).createProperty( accountID );

		if ( error ) {
			return { error };
		}

		propertyID = property.id;
		dispatch( MODULES_ANALYTICS ).setPropertyID( property.id );
		dispatch( MODULES_ANALYTICS ).setInternalWebPropertyID(
			// eslint-disable-next-line sitekit/acronym-case
			property.internalWebPropertyId
		);
	}

	const profileID = select( MODULES_ANALYTICS ).getProfileID();
	if ( profileID === PROFILE_CREATE ) {
		const profileName = select( CORE_FORMS ).getValue(
			FORM_SETUP,
			'profileName'
		);
		const accountID = select( MODULES_ANALYTICS ).getAccountID();
		const { response: profile, error } = await dispatch(
			MODULES_ANALYTICS
		).createProfile( accountID, propertyID, { profileName } );

		if ( error ) {
			return { error };
		}

		dispatch( MODULES_ANALYTICS ).setProfileID( profile.id );
	}

	const isGA4Enabled = isFeatureEnabled( 'ga4setup' );
	if ( isGA4Enabled ) {
		const ga4PropertyID = select( MODULES_ANALYTICS_4 ).getPropertyID();
		const ga4StreamID = select( MODULES_ANALYTICS_4 ).getWebDataStreamID();

		if (
			ga4PropertyID === GA4_PROPERTY_CREATE ||
			ga4StreamID === WEBDATASTREAM_CREATE
		) {
			const { error } = await submitGA4Changes( registry );
			if ( error ) {
				return { error };
			}
		}
	}

	// This action shouldn't be called if settings haven't changed,
	// but this prevents errors in tests.
	if ( select( MODULES_ANALYTICS ).haveSettingsChanged() ) {
		const { error } = await dispatch( MODULES_ANALYTICS ).saveSettings();

		if ( error ) {
			return { error };
		}
	}

	await API.invalidateCache( 'modules', 'analytics' );

	if ( isGA4Enabled ) {
		const { error } = await submitGA4Changes( registry );
		if ( error ) {
			return { error };
		}
	}

	return {};
}

export function rollbackChanges( { select, dispatch } ) {
	const isGA4Enabled = isFeatureEnabled( 'ga4setup' );
	if ( isGA4Enabled ) {
		dispatch( MODULES_ANALYTICS_4 ).rollbackChanges();
	}

	if ( select( MODULES_ANALYTICS ).haveSettingsChanged() ) {
		dispatch( MODULES_ANALYTICS ).rollbackSettings();
	}
}

export function validateCanSubmitChanges( select ) {
	const isGA4Enabled = isFeatureEnabled( 'ga4setup' );

	const strictSelect = createStrictSelect( select );
	const {
		getAccountID,
		getAdsConversionID,
		getInternalWebPropertyID,
		getProfileID,
		getPropertyID,
		hasExistingTagPermission,
		hasTagPermission,
		haveSettingsChanged,
		isDoingSubmitChanges,
	} = strictSelect( MODULES_ANALYTICS );

	// Note: these error messages are referenced in test assertions.
	invariant( ! isDoingSubmitChanges(), INVARIANT_DOING_SUBMIT_CHANGES );

	const gtmIsActive = strictSelect( CORE_MODULES ).isModuleActive(
		'tagmanager'
	);
	if ( gtmIsActive ) {
		const gtmAnalyticsPropertyID = strictSelect(
			MODULES_TAGMANAGER
		).getSingleAnalyticsPropertyID();
		invariant(
			! isValidPropertyID( gtmAnalyticsPropertyID ) ||
				hasTagPermission( gtmAnalyticsPropertyID ) !== false,
			INVARIANT_INSUFFICIENT_GTM_TAG_PERMISSIONS
		);
	}

	invariant(
		haveSettingsChanged() ||
			( isGA4Enabled &&
				select( MODULES_ANALYTICS_4 ).haveSettingsChanged() ),
		INVARIANT_SETTINGS_NOT_CHANGED
	);

	invariant(
		isValidAccountID( getAccountID() ),
		INVARIANT_INVALID_ACCOUNT_ID
	);
	invariant(
		isValidPropertySelection( getPropertyID() ),
		INVARIANT_INVALID_PROPERTY_SELECTION
	);
	invariant(
		isValidProfileSelection( getProfileID() ),
		INVARIANT_INVALID_PROFILE_SELECTION
	);

	if ( getAdsConversionID() ) {
		invariant(
			isValidAdsConversionID( getAdsConversionID() ),
			INVARIANT_INVALID_CONVERSION_ID
		);
	}

	if ( getProfileID() === PROFILE_CREATE ) {
		const profileName = select( CORE_FORMS ).getValue(
			FORM_SETUP,
			'profileName'
		);
		invariant(
			isValidProfileName( profileName ),
			INVARIANT_INVALID_PROFILE_NAME
		);
	}

	// If the property ID is valid (non-create) the internal ID must be valid as well.
	invariant(
		! isValidPropertyID( getPropertyID() ) ||
			isValidInternalWebPropertyID( getInternalWebPropertyID() ),
		INVARIANT_INVALID_INTERNAL_PROPERTY_ID
	);

	// Do existing tag check last.
	invariant(
		hasExistingTagPermission() !== false,
		INVARIANT_INSUFFICIENT_TAG_PERMISSIONS
	);

	if ( select( MODULES_ANALYTICS ).canUseGA4Controls() ) {
		select( MODULES_ANALYTICS_4 ).__dangerousCanSubmitChanges();
	}
}
<|endoftext|>


<commit_before>function takeScreenshot() {
  chrome.tabs.captureVisibleTab(null, function(img) {
    var screenshotUrl = img;
    var viewTabUrl = chrome.extension.getURL('screenshot.html');

    chrome.tabs.create({url: viewTabUrl}, function(tab) {
      var targetId = tab.id;

      var addSnapshotImageToTab = function(tabId, changedProps) {
        // We are waiting for the tab we opened to finish loading.
        // Check that the the tab's id matches the tab we opened,
        // and that the tab is done loading.
        if (tabId != targetId || changedProps.status != "complete")
          return;

        // Passing the above test means this is the event we were waiting for.
        // There is nothing we need to do for future onUpdated events, so we
        // use removeListner to stop geting called when onUpdated events fire.
        chrome.tabs.onUpdated.removeListener(addSnapshotImageToTab);

        // Look through all views to find the window which will display
        // the screenshot.
        var views = chrome.extension.getViews();
        for (var i = 0; i < views.length; i++) {
          var view = views[i];
          // If more than one screen shot tab is opened, we need to
          // ensure that we do not change an existing screen shot image.
          // view.imageAlreadySet is set to true when an image is set for
          // the first time.  We never change an image in a window with
          // this flag set.
          if (view.location.href == viewTabUrl && !view.imageAlreadySet) {
            view.setScreenshotUrl(screenshotUrl);
            view.imageAlreadySet = true;
            break;
          }
        }
      };
      chrome.tabs.onUpdated.addListener(addSnapshotImageToTab);

    });
  });
}

// Listen for a click on the camera icon.  On that click, take a screenshot.
chrome.browserAction.onClicked.addListener(function(tab) {
  takeScreenshot();
});
<commit_msg>Make sure we insert the screenshot into the correct tab by making each tab's url different.<commit_after>// To make sure we can uniquely identify each screenshot tab, add an id as a
// query param to the url that displays the screenshot.
var id = 100;

function takeScreenshot() {
  chrome.tabs.captureVisibleTab(null, function(img) {
    var screenshotUrl = img;
    var viewTabUrl = [chrome.extension.getURL('screenshot.html'),
                      '?id=', id++].join('');

    chrome.tabs.create({url: viewTabUrl}, function(tab) {
      var targetId = tab.id;

      var addSnapshotImageToTab = function(tabId, changedProps) {
        // We are waiting for the tab we opened to finish loading.
        // Check that the the tab's id matches the tab we opened,
        // and that the tab is done loading.
        if (tabId != targetId || changedProps.status != "complete")
          return;

        // Passing the above test means this is the event we were waiting for.
        // There is nothing we need to do for future onUpdated events, so we
        // use removeListner to stop geting called when onUpdated events fire.
        chrome.tabs.onUpdated.removeListener(addSnapshotImageToTab);

        // Look through all views to find the window which will display
        // the screenshot.  The url of the tab which will display the
        // screenshot includes a query parameter with a unique id, which
        // ensures that exactly one view will have the matching URL.
        var views = chrome.extension.getViews();
        for (var i = 0; i < views.length; i++) {
          var view = views[i];
          if (view.location.href == viewTabUrl) {
            view.setScreenshotUrl(screenshotUrl);
            break;
          }
        }
      };
      chrome.tabs.onUpdated.addListener(addSnapshotImageToTab);

    });
  });
}

// Listen for a click on the camera icon.  On that click, take a screenshot.
chrome.browserAction.onClicked.addListener(function(tab) {
  takeScreenshot();
});
<|endoftext|>


<commit_before>
//==========================================
//      Complex Numbers
//==========================================
var CSNumber={};
CSNumber.niceprint= function(a){
    if (a.value.imag==0) {
        return ""+a.value.real;
    }

    if(a.value.imag>0){
        return ""+a.value.real+" + i*"+a.value.imag;
    } else {
        return ""+a.value.real+" - i*"+(-a.value.imag);
    }
}

CSNumber.complex=function(r,i){
    return {"ctype":"number" ,  "value":{'real':r,'imag':i}}
}

CSNumber.real=function(r){
    return {"ctype":"number" ,  "value":{'real':r,'imag':0}}
}

CSNumber.clone=function(a){
    return {"ctype":"number" ,
            "value":{'real':a.value.real,'imag':a.value.imag},
            "usage":a.usage}
}

CSNumber.argmax=function(a,b){//Achtung: Gibt referenzen zurück, da
                            //nur für NormalizeMax verwendet

    var n1=a.value.real*a.value.real+a.value.imag*a.value.imag;
    var n2=b.value.real*b.value.real+b.value.imag*b.value.imag;
    return (n1<n2 ? b : a );

}

CSNumber.max=function(a,b){
    return {"ctype":"number" ,  "value":{'real':Math.max(a.value.real,b.value.real),
        'imag':Math.max(a.value.imag,b.value.imag)}}
}

CSNumber.min=function(a,b){
    return {"ctype":"number" ,  "value":{'real':Math.min(a.value.real,b.value.real),
        'imag':Math.min(a.value.imag,b.value.imag)}}
}

CSNumber.add=function(a,b){
    return {"ctype":"number" ,  "value":{'real':a.value.real+b.value.real,
        'imag':a.value.imag+b.value.imag}}
}

CSNumber.sub=function(a,b){
    return {"ctype":"number" ,  "value":{'real':a.value.real-b.value.real,
        'imag':a.value.imag-b.value.imag}}
}

CSNumber.neg=function(a){
    return {"ctype":"number" ,
        "value":{'real':-a.value.real, 'imag':-a.value.imag}}
}

CSNumber.re=function(a){
    return {"ctype":"number" ,
        "value":{'real':a.value.real, 'imag':0}}
}

// BUG?
// do we intentinally give back the imag value as the real value?
CSNumber.im=function(a){
    return {"ctype":"number" ,
        "value":{'real':a.value.imag, 'imag':0}}
}

CSNumber.conjugate=function(a){
    return {"ctype":"number" ,
        "value":{'real':a.value.real, 'imag':-a.value.imag}}
}

CSNumber.round=function(a){
    return {"ctype":"number" ,
        "value":{'real':Math.round(a.value.real), 'imag':Math.round(a.value.imag)}}
}

CSNumber.ceil=function(a){
    return {"ctype":"number" ,
        "value":{'real':Math.ceil(a.value.real), 'imag':Math.ceil(a.value.imag)}}
}

CSNumber.floor=function(a){
    return {"ctype":"number" ,
        "value":{'real':Math.floor(a.value.real), 'imag':Math.floor(a.value.imag)}}
}

CSNumber.mult=function(a,b){
    return {"ctype":"number" ,
        "value":{'real':a.value.real*b.value.real-a.value.imag*b.value.imag,
            'imag':a.value.real*b.value.imag+a.value.imag*b.value.real}};
}

// BUG?
// why do we have two argument but throw away the second argument?
CSNumber.abs2=function(a,b){
    return {"ctype":"number" ,
        "value":{'real':a.value.real*a.value.real+a.value.imag*a.value.imag,
            'imag':0}};
}

CSNumber.abs=function(a1){
    return CSNumber.sqrt(CSNumber.abs2(a1))
}

CSNumber.inv=function(a){
    var s=a.value.real*a.value.real+a.value.imag*a.value.imag;
    // BUG?
    // perhaps we should not only check for 0
    // if(Math.abs(s) < 1e32) {
    if(s==0) {
        console.log("DIVISION BY ZERO");
//        halt=immediately;

    }
    return {"ctype":"number" ,
        "value":{'real':a.value.real/s,
            'imag':-a.value.imag/s}}
}

CSNumber.div=function(a,b){
    return CSNumber.mult(a,CSNumber.inv(b));
}

CSNumber.eps=0.0000001;

CSNumber.snap=function(a){
    var r=a.value.real;
    var i=a.value.imag;
    if(Math.floor(r+CSNumber.eps)!=Math.floor(r-CSNumber.eps)){
        r=Math.round(r);
    }
    if(Math.floor(i+CSNumber.eps)!=Math.floor(i-CSNumber.eps)){
        i=Math.round(i);
    }
    return {"ctype":"number" ,"value":{'real':r,'imag':i}};

}

CSNumber.exp=function(a){
    var n = Math.exp(a.value.real);
    var r = n * Math.cos(a.value.imag);
    var i = n * Math.sin(a.value.imag);
    return {"ctype":"number" ,"value":{'real':r,'imag':i}};
}

CSNumber.cos=function(a) {
    var rr=a.value.real;
    var ii=a.value.imag;
    var n = Math.exp(ii);
    var imag1 = n * Math.sin(-rr);
    var real1 = n * Math.cos(-rr);
    n = Math.exp(-ii);
    var imag2 = n * Math.sin(rr);
    var real2 = n * Math.cos(rr);
    var i = (imag1 + imag2) / 2.0;
    var r = (real1 + real2) / 2.0;
  //  if (i * i < 1E-30) i = 0;
  //  if (r * r < 1E-30) r = 0;
    return {"ctype":"number" ,"value":{'real':r,'imag':i}};
}

CSNumber.sin=function(a) {
    var rr=a.value.real;
    var ii=a.value.imag;
    var n = Math.exp(ii);
    var imag1 = n * Math.sin(-rr);
    var real1 = n * Math.cos(-rr);
    n = Math.exp(-ii);
    var imag2 = n * Math.sin(rr);
    var real2 = n * Math.cos(rr);
    var r = -(imag1 - imag2) / 2.0;
    var i = (real1 - real2) / 2.0;
  //  if (i * i < 1E-30) i = 0;
  //  if (r * r < 1E-30) r = 0;
    return {"ctype":"number" ,"value":{'real':r,'imag':i}};
}

CSNumber.tan=function(a) {
    var s=CSNumber.sin(a);
    var c=CSNumber.cos(a);
    return CSNumber.div(s,c);
}

CSNumber.arccos=function(a) {  //OK hässlich aber tuts.
    var t2=CSNumber.mult(a,CSNumber.neg(a));
    var tmp=CSNumber.sqrt(CSNumber.add(CSNumber.real(1),t2));
    var tmp1=CSNumber.add(CSNumber.mult(a,CSNumber.complex(0,1)),tmp);
    var erg=CSNumber.add(CSNumber.mult(CSNumber.log(tmp1),CSNumber.complex(0,1)),CSNumber.real(Math.PI*0.5));
    erg.usage = 'angle';
    return erg;
}

CSNumber.arcsin=function(a) {  //OK hässlich aber tuts.
    var t2=CSNumber.mult(a,CSNumber.neg(a));
    var tmp=CSNumber.sqrt(CSNumber.add(CSNumber.real(1),t2));
    var tmp1=CSNumber.add(CSNumber.mult(a,CSNumber.complex(0,1)),tmp);
    var erg=CSNumber.mult(CSNumber.log(tmp1),CSNumber.complex(0,-1));
    erg.usage = 'angle';
    return erg;
}

CSNumber.arctan=function(a) {  //OK hässlich aber tuts.
    var t1=CSNumber.log(CSNumber.add(CSNumber.mult(a,CSNumber.complex(0,-1)),CSNumber.real(1)));
    var t2=CSNumber.log(CSNumber.add(CSNumber.mult(a,CSNumber.complex(0,1)),CSNumber.real(1)));
    var erg=CSNumber.mult(CSNumber.sub(t1,t2),CSNumber.complex(0,0.5));
    erg.usage = 'angle';
    return erg;
}

//Das ist jetzt genau so wie in Cindy.
//Da wurde das aber niemals voll auf complexe Zahlen umgestellt
//Bei Beiden Baustellen machen!!!
CSNumber.arctan2=function(a,b) {  //OK
    var erg= CSNumber.real(Math.atan2(b.value.real,a.value.real));
    erg.usage = 'angle';
    return erg;
}

CSNumber.sqrt=function(a)  {
    var rr=a.value.real;
    var ii=a.value.imag;
    var n = Math.sqrt(Math.sqrt(rr * rr + ii * ii));
    var w = Math.atan2(ii, rr);
    var i = n * Math.sin(w / 2);
    var r = n * Math.cos(w / 2);
    return {"ctype":"number" ,"value":{'real':r,'imag':i}};
}

CSNumber.log=function(a){
    var re=a.value.real;
    var im=a.value.imag;
    var s = Math.sqrt(re*re+im*im);
    var i = im;

    var imag = Math.atan2(im, re);
    if (i < 0) {
        imag += (2 * Math.PI);
    }
    if (i == 0 && re < 0) {
        imag = Math.PI;
    }
    if (imag > Math.PI) {
        imag -= (2 * Math.PI)
    };
    var real = Math.log(s);

    return CSNumber.snap({"ctype":"number" ,"value":{'real':real,'imag':imag}});
}

CSNumber.pow=function(a,b){

    if(b.value.real==Math.round(b.value.real)&& b.value.imag==0){//TODO später mal effizienter machen
        var erg={"ctype":"number" ,"value":{'real':1,'imag':0}};
        for(var i=0;i<Math.abs(b.value.real);i++){
            erg=CSNumber.mult(erg,a);
        }
        if (b.value.real<0){
            return CSNumber.inv(erg);
        }
        return(erg);

    }
    var res=CSNumber.exp(CSNumber.mult(CSNumber.log(a),b));
    return res;
}

// BUG?
// interesting what your are doing :)
CSNumber.mod=function(a,b){
    var a1=a.value.real;
    var a2=b.value.real;
    var b1=a.value.imag;
    var b2=b.value.imag;

    var r = a1 - Math.floor(a1 / a2) * a2;
    var i = b1 - Math.floor(b1 / b2) * b2;
    if(a2==0) {r=0};
    if(b2==0) {i=0};

    return CSNumber.snap({"ctype":"number" ,"value":{'real':r,'imag':i}});
}

CSNumber._helper={};

CSNumber._helper.seed='NO';
CSNumber.eps=0.0000000001;
CSNumber.epsbig=0.000001;

CSNumber._helper.seedrandom=function(a){
    a=a-Math.floor(a);
    a=a*.8+.1;
    CSNumber._helper.seed=a;
}

CSNumber._helper.rand=function(){
    if(CSNumber._helper.seed=='NO'){
        return Math.random();
    }
    var a=CSNumber._helper.seed;
    a=Math.sin(1000*a)*1000;
    a=a-Math.floor(a);
    CSNumber._helper.seed=a;
    return a;
}

CSNumber._helper.randnormal=function(){
    var a=CSNumber._helper.rand();
    var b=CSNumber._helper.rand();
    return Math.sqrt(-2*Math.log(a))*Math.cos(2*Math.PI*b);
}

CSNumber._helper.isEqual=function(a,b) {
    return (a.value.real == b.value.real) && (a.value.imag == b.value.imag);
}

CSNumber._helper.isLessThan=function(a,b) {

    return(a.value.real < b.value.real
           || a.value.real == b.value.real && a.value.imag < b.value.imag)
}

CSNumber._helper.compare=function(a,b) {
    if(CSNumber._helper.isLessThan(a,b)){return -1}
    if(CSNumber._helper.isEqual(a,b)){return 0}
    return 1;
}

CSNumber._helper.isAlmostEqual=function(a,b,preci) {
    if(preci !== 'undefined'){
	    var eps = preci;
    }
    var r=a.value.real-b.value.real;
    var i=a.value.imag-b.value.imag;
    return (r<CSNumber.eps) && (r>-CSNumber.eps)&&(i<CSNumber.eps) && (i>-CSNumber.eps);
}

CSNumber._helper.isZero=function(a) {
    return (a.value.real == 0) && (a.value.imag == 0);
}

CSNumber._helper.isAlmostZero=function(a) {
    var r=a.value.real;
    var i=a.value.imag;
    return (r<CSNumber.eps) && (r>-CSNumber.eps)&&(i<CSNumber.eps) && (i>-CSNumber.eps);
}

CSNumber._helper.isReal=function(a) {
    return (a.value.imag == 0) ;
}

CSNumber._helper.isAlmostReal=function(a) {
    var i=a.value.imag;
    return (i<CSNumber.epsbig) && (i>-CSNumber.epsbig);//So gemacht wie in Cindy
}

CSNumber._helper.isNaN=function(a) {
    return (isNaN(a.value.real)) || (isNaN(a.value.imag));
}

CSNumber._helper.isAlmostImag=function(a) {
    var r=a.value.real;
    return (r<CSNumber.epsbig) && (r>-CSNumber.epsbig);//So gemacht wie in Cindy
}

<commit_msg>changed to typeof in isAlmostEqual<commit_after>
//==========================================
//      Complex Numbers
//==========================================
var CSNumber={};
CSNumber.niceprint= function(a){
    if (a.value.imag==0) {
        return ""+a.value.real;
    }

    if(a.value.imag>0){
        return ""+a.value.real+" + i*"+a.value.imag;
    } else {
        return ""+a.value.real+" - i*"+(-a.value.imag);
    }
}

CSNumber.complex=function(r,i){
    return {"ctype":"number" ,  "value":{'real':r,'imag':i}}
}

CSNumber.real=function(r){
    return {"ctype":"number" ,  "value":{'real':r,'imag':0}}
}

CSNumber.clone=function(a){
    return {"ctype":"number" ,
            "value":{'real':a.value.real,'imag':a.value.imag},
            "usage":a.usage}
}

CSNumber.argmax=function(a,b){//Achtung: Gibt referenzen zurück, da
                            //nur für NormalizeMax verwendet

    var n1=a.value.real*a.value.real+a.value.imag*a.value.imag;
    var n2=b.value.real*b.value.real+b.value.imag*b.value.imag;
    return (n1<n2 ? b : a );

}

CSNumber.max=function(a,b){
    return {"ctype":"number" ,  "value":{'real':Math.max(a.value.real,b.value.real),
        'imag':Math.max(a.value.imag,b.value.imag)}}
}

CSNumber.min=function(a,b){
    return {"ctype":"number" ,  "value":{'real':Math.min(a.value.real,b.value.real),
        'imag':Math.min(a.value.imag,b.value.imag)}}
}

CSNumber.add=function(a,b){
    return {"ctype":"number" ,  "value":{'real':a.value.real+b.value.real,
        'imag':a.value.imag+b.value.imag}}
}

CSNumber.sub=function(a,b){
    return {"ctype":"number" ,  "value":{'real':a.value.real-b.value.real,
        'imag':a.value.imag-b.value.imag}}
}

CSNumber.neg=function(a){
    return {"ctype":"number" ,
        "value":{'real':-a.value.real, 'imag':-a.value.imag}}
}

CSNumber.re=function(a){
    return {"ctype":"number" ,
        "value":{'real':a.value.real, 'imag':0}}
}

// BUG?
// do we intentinally give back the imag value as the real value?
CSNumber.im=function(a){
    return {"ctype":"number" ,
        "value":{'real':a.value.imag, 'imag':0}}
}

CSNumber.conjugate=function(a){
    return {"ctype":"number" ,
        "value":{'real':a.value.real, 'imag':-a.value.imag}}
}

CSNumber.round=function(a){
    return {"ctype":"number" ,
        "value":{'real':Math.round(a.value.real), 'imag':Math.round(a.value.imag)}}
}

CSNumber.ceil=function(a){
    return {"ctype":"number" ,
        "value":{'real':Math.ceil(a.value.real), 'imag':Math.ceil(a.value.imag)}}
}

CSNumber.floor=function(a){
    return {"ctype":"number" ,
        "value":{'real':Math.floor(a.value.real), 'imag':Math.floor(a.value.imag)}}
}

CSNumber.mult=function(a,b){
    return {"ctype":"number" ,
        "value":{'real':a.value.real*b.value.real-a.value.imag*b.value.imag,
            'imag':a.value.real*b.value.imag+a.value.imag*b.value.real}};
}

// BUG?
// why do we have two argument but throw away the second argument?
CSNumber.abs2=function(a,b){
    return {"ctype":"number" ,
        "value":{'real':a.value.real*a.value.real+a.value.imag*a.value.imag,
            'imag':0}};
}

CSNumber.abs=function(a1){
    return CSNumber.sqrt(CSNumber.abs2(a1))
}

CSNumber.inv=function(a){
    var s=a.value.real*a.value.real+a.value.imag*a.value.imag;
    // BUG?
    // perhaps we should not only check for 0
    // if(Math.abs(s) < 1e32) {
    if(s==0) {
        console.log("DIVISION BY ZERO");
//        halt=immediately;

    }
    return {"ctype":"number" ,
        "value":{'real':a.value.real/s,
            'imag':-a.value.imag/s}}
}

CSNumber.div=function(a,b){
    return CSNumber.mult(a,CSNumber.inv(b));
}

CSNumber.eps=0.0000001;

CSNumber.snap=function(a){
    var r=a.value.real;
    var i=a.value.imag;
    if(Math.floor(r+CSNumber.eps)!=Math.floor(r-CSNumber.eps)){
        r=Math.round(r);
    }
    if(Math.floor(i+CSNumber.eps)!=Math.floor(i-CSNumber.eps)){
        i=Math.round(i);
    }
    return {"ctype":"number" ,"value":{'real':r,'imag':i}};

}

CSNumber.exp=function(a){
    var n = Math.exp(a.value.real);
    var r = n * Math.cos(a.value.imag);
    var i = n * Math.sin(a.value.imag);
    return {"ctype":"number" ,"value":{'real':r,'imag':i}};
}

CSNumber.cos=function(a) {
    var rr=a.value.real;
    var ii=a.value.imag;
    var n = Math.exp(ii);
    var imag1 = n * Math.sin(-rr);
    var real1 = n * Math.cos(-rr);
    n = Math.exp(-ii);
    var imag2 = n * Math.sin(rr);
    var real2 = n * Math.cos(rr);
    var i = (imag1 + imag2) / 2.0;
    var r = (real1 + real2) / 2.0;
  //  if (i * i < 1E-30) i = 0;
  //  if (r * r < 1E-30) r = 0;
    return {"ctype":"number" ,"value":{'real':r,'imag':i}};
}

CSNumber.sin=function(a) {
    var rr=a.value.real;
    var ii=a.value.imag;
    var n = Math.exp(ii);
    var imag1 = n * Math.sin(-rr);
    var real1 = n * Math.cos(-rr);
    n = Math.exp(-ii);
    var imag2 = n * Math.sin(rr);
    var real2 = n * Math.cos(rr);
    var r = -(imag1 - imag2) / 2.0;
    var i = (real1 - real2) / 2.0;
  //  if (i * i < 1E-30) i = 0;
  //  if (r * r < 1E-30) r = 0;
    return {"ctype":"number" ,"value":{'real':r,'imag':i}};
}

CSNumber.tan=function(a) {
    var s=CSNumber.sin(a);
    var c=CSNumber.cos(a);
    return CSNumber.div(s,c);
}

CSNumber.arccos=function(a) {  //OK hässlich aber tuts.
    var t2=CSNumber.mult(a,CSNumber.neg(a));
    var tmp=CSNumber.sqrt(CSNumber.add(CSNumber.real(1),t2));
    var tmp1=CSNumber.add(CSNumber.mult(a,CSNumber.complex(0,1)),tmp);
    var erg=CSNumber.add(CSNumber.mult(CSNumber.log(tmp1),CSNumber.complex(0,1)),CSNumber.real(Math.PI*0.5));
    erg.usage = 'angle';
    return erg;
}

CSNumber.arcsin=function(a) {  //OK hässlich aber tuts.
    var t2=CSNumber.mult(a,CSNumber.neg(a));
    var tmp=CSNumber.sqrt(CSNumber.add(CSNumber.real(1),t2));
    var tmp1=CSNumber.add(CSNumber.mult(a,CSNumber.complex(0,1)),tmp);
    var erg=CSNumber.mult(CSNumber.log(tmp1),CSNumber.complex(0,-1));
    erg.usage = 'angle';
    return erg;
}

CSNumber.arctan=function(a) {  //OK hässlich aber tuts.
    var t1=CSNumber.log(CSNumber.add(CSNumber.mult(a,CSNumber.complex(0,-1)),CSNumber.real(1)));
    var t2=CSNumber.log(CSNumber.add(CSNumber.mult(a,CSNumber.complex(0,1)),CSNumber.real(1)));
    var erg=CSNumber.mult(CSNumber.sub(t1,t2),CSNumber.complex(0,0.5));
    erg.usage = 'angle';
    return erg;
}

//Das ist jetzt genau so wie in Cindy.
//Da wurde das aber niemals voll auf complexe Zahlen umgestellt
//Bei Beiden Baustellen machen!!!
CSNumber.arctan2=function(a,b) {  //OK
    var erg= CSNumber.real(Math.atan2(b.value.real,a.value.real));
    erg.usage = 'angle';
    return erg;
}

CSNumber.sqrt=function(a)  {
    var rr=a.value.real;
    var ii=a.value.imag;
    var n = Math.sqrt(Math.sqrt(rr * rr + ii * ii));
    var w = Math.atan2(ii, rr);
    var i = n * Math.sin(w / 2);
    var r = n * Math.cos(w / 2);
    return {"ctype":"number" ,"value":{'real':r,'imag':i}};
}

CSNumber.log=function(a){
    var re=a.value.real;
    var im=a.value.imag;
    var s = Math.sqrt(re*re+im*im);
    var i = im;

    var imag = Math.atan2(im, re);
    if (i < 0) {
        imag += (2 * Math.PI);
    }
    if (i == 0 && re < 0) {
        imag = Math.PI;
    }
    if (imag > Math.PI) {
        imag -= (2 * Math.PI)
    };
    var real = Math.log(s);

    return CSNumber.snap({"ctype":"number" ,"value":{'real':real,'imag':imag}});
}

CSNumber.pow=function(a,b){

    if(b.value.real==Math.round(b.value.real)&& b.value.imag==0){//TODO später mal effizienter machen
        var erg={"ctype":"number" ,"value":{'real':1,'imag':0}};
        for(var i=0;i<Math.abs(b.value.real);i++){
            erg=CSNumber.mult(erg,a);
        }
        if (b.value.real<0){
            return CSNumber.inv(erg);
        }
        return(erg);

    }
    var res=CSNumber.exp(CSNumber.mult(CSNumber.log(a),b));
    return res;
}

// BUG?
// interesting what your are doing :)
CSNumber.mod=function(a,b){
    var a1=a.value.real;
    var a2=b.value.real;
    var b1=a.value.imag;
    var b2=b.value.imag;

    var r = a1 - Math.floor(a1 / a2) * a2;
    var i = b1 - Math.floor(b1 / b2) * b2;
    if(a2==0) {r=0};
    if(b2==0) {i=0};

    return CSNumber.snap({"ctype":"number" ,"value":{'real':r,'imag':i}});
}

CSNumber._helper={};

CSNumber._helper.seed='NO';
CSNumber.eps=0.0000000001;
CSNumber.epsbig=0.000001;

CSNumber._helper.seedrandom=function(a){
    a=a-Math.floor(a);
    a=a*.8+.1;
    CSNumber._helper.seed=a;
}

CSNumber._helper.rand=function(){
    if(CSNumber._helper.seed=='NO'){
        return Math.random();
    }
    var a=CSNumber._helper.seed;
    a=Math.sin(1000*a)*1000;
    a=a-Math.floor(a);
    CSNumber._helper.seed=a;
    return a;
}

CSNumber._helper.randnormal=function(){
    var a=CSNumber._helper.rand();
    var b=CSNumber._helper.rand();
    return Math.sqrt(-2*Math.log(a))*Math.cos(2*Math.PI*b);
}

CSNumber._helper.isEqual=function(a,b) {
    return (a.value.real == b.value.real) && (a.value.imag == b.value.imag);
}

CSNumber._helper.isLessThan=function(a,b) {

    return(a.value.real < b.value.real
           || a.value.real == b.value.real && a.value.imag < b.value.imag)
}

CSNumber._helper.compare=function(a,b) {
    if(CSNumber._helper.isLessThan(a,b)){return -1}
    if(CSNumber._helper.isEqual(a,b)){return 0}
    return 1;
}

CSNumber._helper.isAlmostEqual=function(a,b,preci) {
    var eps = CSNumber.eps;
    if(typeof(preci) !== 'undefined'){
	    eps = preci;
    }
    var r=a.value.real-b.value.real;
    var i=a.value.imag-b.value.imag;
    return (r<eps) && (r>-eps)&&(i<eps) && (i>-eps);
}

CSNumber._helper.isZero=function(a) {
    return (a.value.real == 0) && (a.value.imag == 0);
}

CSNumber._helper.isAlmostZero=function(a) {
    var r=a.value.real;
    var i=a.value.imag;
    return (r<CSNumber.eps) && (r>-CSNumber.eps)&&(i<CSNumber.eps) && (i>-CSNumber.eps);
}

CSNumber._helper.isReal=function(a) {
    return (a.value.imag == 0) ;
}

CSNumber._helper.isAlmostReal=function(a) {
    var i=a.value.imag;
    return (i<CSNumber.epsbig) && (i>-CSNumber.epsbig);//So gemacht wie in Cindy
}

CSNumber._helper.isNaN=function(a) {
    return (isNaN(a.value.real)) || (isNaN(a.value.imag));
}

CSNumber._helper.isAlmostImag=function(a) {
    var r=a.value.real;
    return (r<CSNumber.epsbig) && (r>-CSNumber.epsbig);//So gemacht wie in Cindy
}

<|endoftext|>


<commit_before>// Copyright 2017, University of Colorado Boulder

/* eslint-env node */
'use strict';

const fs = require( 'fs.extra' ); // eslint-disable-line
const winston = require( 'winston' );

const addToRosetta = require( './addToRosetta' );
const addTranslator = require( './addTranslator' );
const constants = require( './constants' );
const createTranslationsXML = require( './createTranslationsXML' );
const devDeploy = require( './devDeploy' );
const getLocales = require( './getLocales' );
const mkVersionDir = require( './mkVersionDir' );
const notifyServer = require( './notifyServer' );
const pullMaster = require( './pullMaster' );
const writePhetHtaccess = require( './writePhetHtaccess' );
const writePhetioHtaccess = require( './writePhetioHtaccess' );

const execute = require( '../common/execute' );

/**
 * taskQueue ensures that only one build/deploy process will be happening at the same time.  The main build/deploy logic is here.
 *
 * @param {Object} task
 * @property {JSON} task.repos
 * @property {String} task.api
 * @property {String} task.locales - comma separated list of locale codes
 * @property {String} task.simName - lower case simulation name used for creating files/directories
 * @property {String} task.version - sim version identifier string
 * @property {String} task.servers - deployment targets, subset of [ 'dev', 'production' ]
 * @property {String} task.brands - deployment brands
 * @property {String} task.email - used for sending notifications about success/failure
 * @property {String} task.translatorId - rosetta user id for adding translators to the website
 * @property {String} task.res - express response object
 * @property {winston} task.winston - logger
 *
 * @param {Function} taskCallback - called when build is finished or aborted
 */
module.exports = async function( task, taskCallback ) {

  //-------------------------------------------------------------------------------------
  // Parse and validate parameters
  //-------------------------------------------------------------------------------------

  // TODO: change to ES6 destructuring
  const api = task.api;
  const repos = task.repos;
  const locales = task.locales;
  const simName = task.simName;
  let version = task.version;
  const res = task.res;
  const email = task.email;
  const brands = task.brands;
  const servers = task.servers;

  const userId = task.translatorId;
  if ( userId ) {
    winston.log( 'info', 'setting userId = ' + userId );
  }

  //-----------------------------------------------------------------------------------------
  // Define helper functions for use in this function
  //-----------------------------------------------------------------------------------------

  /**
   * Execute a step of the build process. The build aborts if any step fails.
   *
   * @param {String} command - the command to be executed
   * @param {Array.<String>} args - ordered list of args to append
   * @param {String} dir - the directory to execute the command from
   */
  const execWithAbort = async function( command, args, dir ) {
    winston.log( 'info', 'running command: ' + command );
    try {
      await execute( command, args, dir );
    }
    catch( err ) {
      if ( command === 'grunt checkout-master-all' ) {
        taskCallback( 'error running command ' + command + ': ' + err.stdout );
        Promise.reject( 'Build aborted' );
      }
      else {
        return abortBuild( err );
      }
    }
  };

  /**
   * checkout master everywhere and abort build with err
   * @param {String|Error} err - error logged and sent via email
   */
  const abortBuild = async function( err ) {
    winston.log( 'error', 'BUILD ABORTED! ' + err );
    winston.log( 'info', 'build aborted: checking out master for every repo in case build shas are still checked out' );
    await execute( 'grunt', [ 'checkout-master-all' ], constants.PERENNIAL );
    taskCallback( err );
  };

  const simNameRegex = /^[a-z-]+$/;

  // make sure the repos passed in validates
  for ( let key in repos ) {
    if ( repos.hasOwnProperty( key ) ) {
      winston.log( 'info', 'Validating repo: ' + key );

      // make sure all keys in repos object are valid sim names
      if ( !simNameRegex.test( key ) ) {
        return abortBuild( 'invalid simName in repos: ' + simName );
      }

      const value = repos[ key ];
      if ( key === 'comment' ) {
        if ( typeof value !== 'string' ) {
          return abortBuild( 'invalid comment in repos: should be a string' );
        }
      }
      else if ( value instanceof Object && value.hasOwnProperty( 'sha' ) ) {
        if ( !/^[a-f0-9]{40}$/.test( value.sha ) ) {
          return abortBuild( 'invalid sha in repos. key: ' + key + ' value: ' + value + ' sha: ' + value.sha );
        }
      }
      else {
        return abortBuild( 'invalid item in repos. key: ' + key + ' value: ' + value );
      }
    }
  }

  // validate simName
  if ( !simNameRegex.test( simName ) ) {
    return abortBuild( 'invalid simName ' + simName );
  }

  // Infer brand from version string and keep unstripped version for phet-io
  const originalVersion = version;
  if ( api === '1.0' ) {
    // validate version and strip suffixes since just the numbers are used in the directory name on dev and production servers
    const versionMatch = version.match( /^(\d+\.\d+\.\d+)(?:-.*)?$/ );
    if ( versionMatch && versionMatch.length === 2 ) {

      if ( servers.includes( 'dev' ) ) {
        // if deploying an rc version use the -rc.[number] suffix
        version = versionMatch[ 0 ];
      }
      else {
        // otherwise strip any suffix
        version = versionMatch[ 1 ];
      }
      winston.log( 'info', 'detecting version number: ' + version );
    }
    else {
      return abortBuild( 'invalid version number: ' + version );
    }
  }
  else {
    // TODO: handle version validation for https://github.com/phetsims/chipper/issues/560
  }

  // define vars for build dir and sim dir
  const buildDir = './js/build-server/tmp';
  const simDir = '../' + simName;

  winston.log( 'info', 'building sim ' + simName );

  //-------------------------------------------------------------------------------------
  // Define other helper functions used in build process
  //-------------------------------------------------------------------------------------

  /**
   * Clean up after deploy. Checkout master for every repo and remove tmp dir.
   */
  const afterDeploy = async function() {
    await execWithAbort( 'grunt', [ 'checkout-master-all' ], constants.PERENNIAL );
    await execWithAbort( 'rm', [ '-rf ', buildDir ], '.' );
    taskCallback();
  };

  try {
    fs.mkdirSync( buildDir );
  }
  catch( err ) {
    try {
      await execute( 'rm', [ '-rf', buildDir ], '.' );
      fs.mkdirSync( buildDir );
    }
    catch( err ) {
      return abortBuild( err );
    }
  }

  try {
    fs.writeFileSync( buildDir + '/dependencies.json', JSON.stringify( repos ) );
  }
  catch( err ) {
    return abortBuild( err );
  }
  winston.log( 'info', 'wrote file ' + buildDir + '/dependencies.json' );

  await execWithAbort( 'git', [ 'pull' ], constants.PERENNIAL );
  await execWithAbort( 'npm', [ 'prune' ], constants.PERENNIAL );
  await execWithAbort( 'npm', [ 'update' ], constants.PERENNIAL );
  await execWithAbort( './chipper/bin/clone-missing-repos.sh', [], '..' );
  try {
    await pullMaster( repos );
  }
  catch( e ) {
    return abortBuild( e );
  }
  await execWithAbort( 'grunt', [ 'checkout-shas', '--buildServer=true', '--repo=', simName ], constants.PERENNIAL );
  await execWithAbort( 'git', [ 'checkout', repos[ simName ].sha ], simDir );
  await execWithAbort( 'npm', [ 'prune' ], '../chipper' );
  await execWithAbort( 'npm', [ 'update' ], '../chipper' );
  await execWithAbort( 'npm', [ 'prune' ], simDir );
  await execWithAbort( 'npm', [ 'update' ], simDir );
  try {
    await getLocales( locales, simName );
  }
  catch( e ) {
    return abortBuild( e );
  }

  const brandLocales = ( brands.indexOf( constants.PHET_BRAND ) >= 0 ) ? locales : 'en';
  winston.log( 'info', 'building for brands: ' + brands + ' version: ' + version );

  await execWithAbort( 'grunt', [ 'build-for-server', '--allHTML', '--brands=', brands.join( ',' ), '--locales=', brandLocales ], simDir );

  if ( servers.indexOf( constants.DEV_SERVER ) >= 0 ) {
    if ( brands.indexOf( constants.PHET_BRAND ) >= 0 ) {
      await devDeploy( simDir, simName, version, brands );
    }
    else if ( brands.indexOf( constants.PHET_IO_BRAND ) >= 0 ) {
      await writePhetioHtaccess( simDir + '/build/.htaccess', '/htdocs/physics/phet-io/config/.htpasswd' );
      await devDeploy( simDir, simName, version, brands );
    }
  }

  if ( servers.indexOf( constants.PRODUCTION_SERVER ) >= 0 ) {
    let targetDir;
    // TODO: loop over brands
    if ( brands.indexOf( constants.PHET_BRAND ) >= 0 ) {
      targetDir = constants.HTML_SIMS_DIRECTORY + simName + '/' + version + '/';
    }
    else if ( brands.indexOf( constants.PHET_IO_BRAND ) >= 0 ) {
      targetDir = constants.PHETIO_SIMS_DIRECTORY + simName + '/' + originalVersion + '/';
    }
    await mkVersionDir( targetDir );
    // TODO: rewrite names if phet brand
    await execWithAbort( 'cp', [ '-r', 'build/*', targetDir ], simDir );
    if ( brands.indexOf( constants.PHET_BRAND ) >= 0 ) {
      await writePhetHtaccess( simName, version );
      let simTitle = await createTranslationsXML( simName, winston );
      await notifyServer( simName, email );
      await addToRosetta( simTitle, simName, email );

      // if this build request comes from rosetta it will have a userId field and only one locale
      const localesArray = locales.split( ',' );
      if ( userId && localesArray.length === 1 && localesArray[ 0 ] !== '*' ) {
        await addTranslator( localesArray[ 0 ], afterDeploy );
      }
    }
    else {
      await writePhetioHtaccess( constants.PHETIO_SIMS_DIRECTORY + simName + '/' + originalVersion + '/wrappers/.htaccess', '/etc/httpd/conf/phet-io_pw' );
    }
  }

  res.send( 'build process initiated, check logs for details' );
  return afterDeploy();
};<commit_msg>updated execute calls<commit_after>// Copyright 2017, University of Colorado Boulder

/* eslint-env node */
'use strict';

const fs = require( 'fs.extra' ); // eslint-disable-line
const winston = require( 'winston' );

const addToRosetta = require( './addToRosetta' );
const addTranslator = require( './addTranslator' );
const constants = require( './constants' );
const createTranslationsXML = require( './createTranslationsXML' );
const devDeploy = require( './devDeploy' );
const getLocales = require( './getLocales' );
const mkVersionDir = require( './mkVersionDir' );
const notifyServer = require( './notifyServer' );
const pullMaster = require( './pullMaster' );
const writePhetHtaccess = require( './writePhetHtaccess' );
const writePhetioHtaccess = require( './writePhetioHtaccess' );

const execute = require( '../common/execute' );

/**
 * taskQueue ensures that only one build/deploy process will be happening at the same time.  The main build/deploy logic is here.
 *
 * @param {Object} task
 * @property {JSON} task.repos
 * @property {String} task.api
 * @property {String} task.locales - comma separated list of locale codes
 * @property {String} task.simName - lower case simulation name used for creating files/directories
 * @property {String} task.version - sim version identifier string
 * @property {String} task.servers - deployment targets, subset of [ 'dev', 'production' ]
 * @property {String} task.brands - deployment brands
 * @property {String} task.email - used for sending notifications about success/failure
 * @property {String} task.translatorId - rosetta user id for adding translators to the website
 * @property {String} task.res - express response object
 * @property {winston} task.winston - logger
 *
 * @param {Function} taskCallback - called when build is finished or aborted
 */
module.exports = async function( task, taskCallback ) {

  //-------------------------------------------------------------------------------------
  // Parse and validate parameters
  //-------------------------------------------------------------------------------------

  // TODO: change to ES6 destructuring
  const api = task.api;
  const repos = task.repos;
  const locales = task.locales;
  const simName = task.simName;
  let version = task.version;
  const res = task.res;
  const email = task.email;
  const brands = task.brands;
  const servers = task.servers;

  const userId = task.translatorId;
  if ( userId ) {
    winston.log( 'info', 'setting userId = ' + userId );
  }

  //-----------------------------------------------------------------------------------------
  // Define helper functions for use in this function
  //-----------------------------------------------------------------------------------------

  /**
   * Execute a step of the build process. The build aborts if any step fails.
   *
   * @param {String} command - the command to be executed
   * @param {Array.<String>} args - ordered list of args to append
   * @param {String} dir - the directory to execute the command from
   */
  const execWithAbort = async function( command, args, dir ) {
    winston.log( 'info', 'running command: ' + command );
    try {
      await execute( command, args, dir );
    }
    catch( err ) {
      if ( command === 'grunt checkout-master-all' ) {
        taskCallback( 'error running command ' + command + ': ' + err.stdout );
        Promise.reject( 'Build aborted' );
      }
      else {
        return abortBuild( err );
      }
    }
  };

  /**
   * checkout master everywhere and abort build with err
   * @param {String|Error} err - error logged and sent via email
   */
  const abortBuild = async function( err ) {
    winston.log( 'error', 'BUILD ABORTED! ' + err );
    winston.log( 'info', 'build aborted: checking out master for every repo in case build shas are still checked out' );
    await execute( 'grunt', [ 'checkout-master-all' ], constants.PERENNIAL );
    taskCallback( err );
  };

  const simNameRegex = /^[a-z-]+$/;

  // make sure the repos passed in validates
  for ( let key in repos ) {
    if ( repos.hasOwnProperty( key ) ) {
      winston.log( 'info', 'Validating repo: ' + key );

      // make sure all keys in repos object are valid sim names
      if ( !simNameRegex.test( key ) ) {
        return abortBuild( 'invalid simName in repos: ' + simName );
      }

      const value = repos[ key ];
      if ( key === 'comment' ) {
        if ( typeof value !== 'string' ) {
          return abortBuild( 'invalid comment in repos: should be a string' );
        }
      }
      else if ( value instanceof Object && value.hasOwnProperty( 'sha' ) ) {
        if ( !/^[a-f0-9]{40}$/.test( value.sha ) ) {
          return abortBuild( 'invalid sha in repos. key: ' + key + ' value: ' + value + ' sha: ' + value.sha );
        }
      }
      else {
        return abortBuild( 'invalid item in repos. key: ' + key + ' value: ' + value );
      }
    }
  }

  // validate simName
  if ( !simNameRegex.test( simName ) ) {
    return abortBuild( 'invalid simName ' + simName );
  }

  // Infer brand from version string and keep unstripped version for phet-io
  const originalVersion = version;
  if ( api === '1.0' ) {
    // validate version and strip suffixes since just the numbers are used in the directory name on dev and production servers
    const versionMatch = version.match( /^(\d+\.\d+\.\d+)(?:-.*)?$/ );
    if ( versionMatch && versionMatch.length === 2 ) {

      if ( servers.includes( 'dev' ) ) {
        // if deploying an rc version use the -rc.[number] suffix
        version = versionMatch[ 0 ];
      }
      else {
        // otherwise strip any suffix
        version = versionMatch[ 1 ];
      }
      winston.log( 'info', 'detecting version number: ' + version );
    }
    else {
      return abortBuild( 'invalid version number: ' + version );
    }
  }
  else {
    // TODO: handle version validation for https://github.com/phetsims/chipper/issues/560
  }

  // define vars for build dir and sim dir
  const buildDir = './js/build-server/tmp';
  const simDir = '../' + simName;

  winston.log( 'info', 'building sim ' + simName );

  //-------------------------------------------------------------------------------------
  // Define other helper functions used in build process
  //-------------------------------------------------------------------------------------

  /**
   * Clean up after deploy. Checkout master for every repo and remove tmp dir.
   */
  const afterDeploy = async function() {
    await execWithAbort( 'grunt', [ 'checkout-master-all' ], constants.PERENNIAL );
    await execWithAbort( 'rm', [ '-rf ', buildDir ], '.' );
    taskCallback();
  };

  try {
    fs.mkdirSync( buildDir );
  }
  catch( err ) {
    try {
      await execute( 'rm', [ '-rf', buildDir ], '.' );
      fs.mkdirSync( buildDir );
    }
    catch( err ) {
      return abortBuild( err );
    }
  }

  try {
    fs.writeFileSync( buildDir + '/dependencies.json', JSON.stringify( repos ) );
  }
  catch( err ) {
    return abortBuild( err );
  }
  winston.log( 'info', 'wrote file ' + buildDir + '/dependencies.json' );

  await execWithAbort( 'git', [ 'pull' ], constants.PERENNIAL );
  await execWithAbort( 'npm', [ 'prune' ], constants.PERENNIAL );
  await execWithAbort( 'npm', [ 'update' ], constants.PERENNIAL );
  await execWithAbort( './chipper/bin/clone-missing-repos.sh', [], '..' );
  try {
    await pullMaster( repos );
  }
  catch( e ) {
    return abortBuild( e );
  }
  await execWithAbort( 'grunt', [ 'checkout-shas', '--buildServer=true', '--repo=' + simName ], constants.PERENNIAL );
  await execWithAbort( 'git', [ 'checkout', repos[ simName ].sha ], simDir );
  await execWithAbort( 'npm', [ 'prune' ], '../chipper' );
  await execWithAbort( 'npm', [ 'update' ], '../chipper' );
  await execWithAbort( 'npm', [ 'prune' ], simDir );
  await execWithAbort( 'npm', [ 'update' ], simDir );
  try {
    await getLocales( locales, simName );
  }
  catch( e ) {
    return abortBuild( e );
  }

  const brandLocales = ( brands.indexOf( constants.PHET_BRAND ) >= 0 ) ? locales : 'en';
  winston.log( 'info', 'building for brands: ' + brands + ' version: ' + version );

  await execWithAbort( 'grunt', [ 'build-for-server', '--allHTML', '--brands=', brands.join( ',' ), '--locales=', brandLocales ], simDir );

  if ( servers.indexOf( constants.DEV_SERVER ) >= 0 ) {
    if ( brands.indexOf( constants.PHET_BRAND ) >= 0 ) {
      await devDeploy( simDir, simName, version, brands );
    }
    else if ( brands.indexOf( constants.PHET_IO_BRAND ) >= 0 ) {
      await writePhetioHtaccess( simDir + '/build/.htaccess', '/htdocs/physics/phet-io/config/.htpasswd' );
      await devDeploy( simDir, simName, version, brands );
    }
  }

  if ( servers.indexOf( constants.PRODUCTION_SERVER ) >= 0 ) {
    let targetDir;
    // TODO: loop over brands
    if ( brands.indexOf( constants.PHET_BRAND ) >= 0 ) {
      targetDir = constants.HTML_SIMS_DIRECTORY + simName + '/' + version + '/';
    }
    else if ( brands.indexOf( constants.PHET_IO_BRAND ) >= 0 ) {
      targetDir = constants.PHETIO_SIMS_DIRECTORY + simName + '/' + originalVersion + '/';
    }
    await mkVersionDir( targetDir );
    // TODO: rewrite names if phet brand
    await execWithAbort( 'cp', [ '-r', 'build/*', targetDir ], simDir );
    if ( brands.indexOf( constants.PHET_BRAND ) >= 0 ) {
      await writePhetHtaccess( simName, version );
      let simTitle = await createTranslationsXML( simName, winston );
      await notifyServer( simName, email );
      await addToRosetta( simTitle, simName, email );

      // if this build request comes from rosetta it will have a userId field and only one locale
      const localesArray = locales.split( ',' );
      if ( userId && localesArray.length === 1 && localesArray[ 0 ] !== '*' ) {
        await addTranslator( localesArray[ 0 ], afterDeploy );
      }
    }
    else {
      await writePhetioHtaccess( constants.PHETIO_SIMS_DIRECTORY + simName + '/' + originalVersion + '/wrappers/.htaccess', '/etc/httpd/conf/phet-io_pw' );
    }
  }

  res.send( 'build process initiated, check logs for details' );
  return afterDeploy();
};<|endoftext|>


<commit_before>// Settings
PPU = 3;      // Pixels per base unit.
xMax = 100;   // Maximum size of a bar in base units.
trialIndex = 0;
stimulusYSize = 0;

// Create the agent.
create_agent = function() {
    reqwest({
        url: "/node/" + participant_id,
        method: 'post',
        type: 'json',
        success: function (resp) {
            my_node_id = resp.node.id;
            get_info();
        },
        error: function (err) {
            console.log(err);
            err_response = JSON.parse(err.response);
            if (err_response.hasOwnProperty('html')) {
                $('body').html(err_response.html);
            } else {
                allow_exit();
                go_to_page('postquestionnaire');
            }
        }
    });
};

get_info = function() {
    setTimeout(get_received_info, 1000);
};

get_received_info = function() {
    reqwest({
        url: "/node/" + my_node_id + "/received_infos",
        method: 'get',
        type: 'json',
        success: function (resp) {
            if (resp.infos.length === 0) {
                get_info();
            } else {
                r = resp.infos[0].contents;
                int_list = JSON.parse(r);
                $("#title").text("Partner connected");
            }

            // // Get training values
            // xTrain = data.x;
            // yTrain = data.y;

            // N = xTrain.length * 2;
            // $("#total-trials").html(N);
            // yTrainReported = [];

            // // Get test values.
            // // half are from training; the rest are new
            // allX = range(1, xMax);
            // xTestFromTraining = randomSubset(xTrain, N/4);
            // xTestNew = randomSubset(allX.diff(xTrain), N/4);
            // xTest = shuffle(xTestFromTraining.concat(xTestNew));
            // yTest = [];
            // drawUserInterface();
            // proceedToNextTrial();
        },
        error: function (err) {
            console.log(err);
            err_response = JSON.parse(err.response);
            $('body').html(err_response.html);
        }
    });
};

//
// Draw the user interface.
//
drawUserInterface = function () {

    paper = Raphael(0, 50, 600, 400);

    inset = 1;

    // Draw the X bar background.
    backgroundX = paper.rect(50, 50, 300, 25-2*inset);
    backgroundX.attr("stroke", "#CCCCCC");
    backgroundX.attr("stroke-dasharray", "--");

    // Draw the X bar.
    stimulusX = paper.rect(50, 50-inset, 0, 25);
    stimulusX.attr("fill", "#0B486B");
    stimulusX.attr("stroke", "none");

    // Draw the Y bar background.
    backgroundY = paper.rect(450, 400-300, 25-2*inset, 300);
    backgroundY.attr("stroke", "#CCCCCC");
    backgroundY.attr("stroke-dasharray", "--");

    // Draw the Y bar.
    stimulusY = paper.rect(450-inset, 400, 25, 0);
    stimulusY.attr("fill", "#C02942");
    stimulusY.attr("stroke", "none");

    // Draw the feedback bar.
    feedback = paper.rect(500, 400, 25, 0);
    feedback.attr("fill", "#CCCCCC");
    feedback.attr("stroke", "none");
    feedback.hide();

    if (trialIndex === 0) {

        // Track the mouse.
        $(document).mousemove( function(e) {
            y = e.pageY-50;
            stimulusYSize = bounds(400 - y, 1*PPU, xMax*PPU);
            stimulusY.attr({ y: 400 - stimulusYSize, height: stimulusYSize });
        });

        Mousetrap.bind("space", proceedToNextTrial, "keydown");
        document.addEventListener('click', mousedownEventListener);
    }
};

proceedToNextTrial = function () {
    // Prevent repeat keypresses.
    Mousetrap.pause();

    // Increment the trial counter.
    trialIndex = trialIndex + 1;
    $("#trial-number").html(trialIndex);

    // Set up the stimuli.
    if (trialIndex < N/2)
        stimulusXSize = xTrain[trialIndex - 1] * PPU;
    else
        stimulusXSize = xTest[trialIndex - N/2 - 1] * PPU;
    stimulusX.attr({ width: stimulusXSize });
    stimulusX.show();
    stimulusY.show();

    // If this was the last trial, finish up.
    if (trialIndex == N+1) {
        document.removeEventListener('click', mousedownEventListener);
        paper.remove();

        // Send data back to the server.
        response = JSON.stringify({"x": xTest, "y": yTest});

        reqwest({
            url: "/info/" + my_node_id,
            method: 'post',
            data: {
                contents: response,
                info_type: "Info"
            }, success: function(resp) {
                create_agent();
            }
        });
    } else {
        clicked = false;
    }
};

//
// Listen for clicks and act accordingly.
//
function mousedownEventListener(event) {
    if (clicked === false) {

        yNow = Math.round(stimulusYSize/PPU);

        // Training phase
        if (trialIndex < N/2) {
            yTrue = yTrain[trialIndex-1];

            // if they are wrong show feedback
            yTrainReported.push(yNow);
            feedback.attr({ y: 400 - yTrue * PPU, height: yTrue * PPU });
            feedback.show();
            feedback.animate({fill: "#666"}, 100, "<", function () {
                this.animate({fill: "#CCC"}, 100, ">");
            });

            // Move on to next trial if response is correct.
            if(Math.abs(yNow - yTrue) < 4) {
                clicked = true;
                feedback.hide();
                stimulusX.hide();
                stimulusY.hide();
                Mousetrap.resume();
            }
        // Testing phase
        } else if (trialIndex <= N) {
            clicked = true;
            $("#training-or-testing").html("Testing");
            yTest.push(yNow);
            feedback.hide();
            stimulusX.hide();
            stimulusY.hide();
            Mousetrap.resume();
        }
    }
}
<commit_msg>draw a box<commit_after>// Settings
PPU = 3;      // Pixels per base unit.
xMax = 100;   // Maximum size of a bar in base units.
trialIndex = 0;
stimulusYSize = 0;

// Create the agent.
create_agent = function() {
    reqwest({
        url: "/node/" + participant_id,
        method: 'post',
        type: 'json',
        success: function (resp) {
            my_node_id = resp.node.id;
            get_info();
        },
        error: function (err) {
            console.log(err);
            err_response = JSON.parse(err.response);
            if (err_response.hasOwnProperty('html')) {
                $('body').html(err_response.html);
            } else {
                allow_exit();
                go_to_page('postquestionnaire');
            }
        }
    });
};

get_info = function() {
    setTimeout(get_received_info, 1000);
};

get_received_info = function() {
    reqwest({
        url: "/node/" + my_node_id + "/received_infos",
        method: 'get',
        type: 'json',
        success: function (resp) {
            if (resp.infos.length === 0) {
                get_info();
            } else {
                r = resp.infos[0].contents;
                int_list = JSON.parse(r);
                $("#title").text("Partner connected");
                drawUserInterface();
                proceedToNextTrial();
            }

            // // Get training values
            // xTrain = data.x;
            // yTrain = data.y;

            // N = xTrain.length * 2;
            // $("#total-trials").html(N);
            // yTrainReported = [];

            // // Get test values.
            // // half are from training; the rest are new
            // allX = range(1, xMax);
            // xTestFromTraining = randomSubset(xTrain, N/4);
            // xTestNew = randomSubset(allX.diff(xTrain), N/4);
            // xTest = shuffle(xTestFromTraining.concat(xTestNew));
            // yTest = [];
        },
        error: function (err) {
            console.log(err);
            err_response = JSON.parse(err.response);
            $('body').html(err_response.html);
        }
    });
};

//
// Draw the user interface.
//
drawUserInterface = function () {

    paper = Raphael(0, 50, 600, 400);

    inset = 1;

    // Draw the X bar background.
    backgroundX = paper.rect(50, 50, 300, 25-2*inset);
    backgroundX.attr("stroke", "#CCCCCC");
    backgroundX.attr("stroke-dasharray", "--");

    // Draw the X bar.
    stimulusX = paper.rect(50, 50-inset, 0, 25);
    stimulusX.attr("fill", "#0B486B");
    stimulusX.attr("stroke", "none");

    // // Draw the Y bar background.
    // backgroundY = paper.rect(450, 400-300, 25-2*inset, 300);
    // backgroundY.attr("stroke", "#CCCCCC");
    // backgroundY.attr("stroke-dasharray", "--");

    // // Draw the Y bar.
    // stimulusY = paper.rect(450-inset, 400, 25, 0);
    // stimulusY.attr("fill", "#C02942");
    // stimulusY.attr("stroke", "none");

    // // Draw the feedback bar.
    // feedback = paper.rect(500, 400, 25, 0);
    // feedback.attr("fill", "#CCCCCC");
    // feedback.attr("stroke", "none");
    // feedback.hide();

    // if (trialIndex === 0) {

    //     // Track the mouse.
    //     $(document).mousemove( function(e) {
    //         y = e.pageY-50;
    //         stimulusYSize = bounds(400 - y, 1*PPU, xMax*PPU);
    //         stimulusY.attr({ y: 400 - stimulusYSize, height: stimulusYSize });
    //     });

    //     Mousetrap.bind("space", proceedToNextTrial, "keydown");
    //     document.addEventListener('click', mousedownEventListener);
    // }
};

proceedToNextTrial = function () {
    // Prevent repeat keypresses.
    // Mousetrap.pause();

    // Increment the trial counter.
    trialIndex = trialIndex + 1;
    $("#trial-number").html(trialIndex);

    // Set up the stimuli.
    // if (trialIndex < N/2)
    //     stimulusXSize = xTrain[trialIndex - 1] * PPU;
    // else
    //     stimulusXSize = xTest[trialIndex - N/2 - 1] * PPU;
    stimulusX.attr({ width: int_list[0] });
    stimulusX.show();
    // stimulusY.show();

    // If this was the last trial, finish up.
    // if (trialIndex == N+1) {
    //     document.removeEventListener('click', mousedownEventListener);
    //     paper.remove();

    //     // Send data back to the server.
    //     response = JSON.stringify({"x": xTest, "y": yTest});

    //     reqwest({
    //         url: "/info/" + my_node_id,
    //         method: 'post',
    //         data: {
    //             contents: response,
    //             info_type: "Info"
    //         }, success: function(resp) {
    //             create_agent();
    //         }
    //     });
    // } else {
    //     clicked = false;
    // }
};

//
// Listen for clicks and act accordingly.
//
function mousedownEventListener(event) {
    if (clicked === false) {

        yNow = Math.round(stimulusYSize/PPU);

        // Training phase
        if (trialIndex < N/2) {
            yTrue = yTrain[trialIndex-1];

            // if they are wrong show feedback
            yTrainReported.push(yNow);
            feedback.attr({ y: 400 - yTrue * PPU, height: yTrue * PPU });
            feedback.show();
            feedback.animate({fill: "#666"}, 100, "<", function () {
                this.animate({fill: "#CCC"}, 100, ">");
            });

            // Move on to next trial if response is correct.
            if(Math.abs(yNow - yTrue) < 4) {
                clicked = true;
                feedback.hide();
                stimulusX.hide();
                stimulusY.hide();
                Mousetrap.resume();
            }
        // Testing phase
        } else if (trialIndex <= N) {
            clicked = true;
            $("#training-or-testing").html("Testing");
            yTest.push(yNow);
            feedback.hide();
            stimulusX.hide();
            stimulusY.hide();
            Mousetrap.resume();
        }
    }
}
<|endoftext|>