<commit_before>/**
 * Created by raulbeniteznetto on 9/26/16.
 */
// window.onerror = function(msg, url, line)
// {
//   var req = new XMLHttpRequest();
//   var params = "msg=" + encodeURIComponent(msg) + '&url=' + encodeURIComponent(url) + "&line=" + line;
//   // req.open("POST", "/scripts/logerror.php");
//   // req.send(params);
//     console.log(params);
// };

function throw_error_logging(msg){
    console.log(msg);
    throw msg;
}

var time = moment();
var DATETIME_FORMAT = "YYYY-MM-DD HH:mm:ss.SSSSSSZZ";
function getTimeNow(){
    return time.format(DATETIME_FORMAT);
}

function EventReg(params){
    var key;
    var paramenters = params;
    var init = function () {
        var unique_d = new Date().valueOf();
        key = "EVENT_"+ unique_d.toString();
        if(paramenters == null || paramenters == undefined){
            paramenters = {};
        }
        paramenters['created_at'] = getTimeNow();
    };
    init();

    this.getKey = function (){
        return key;
    };
    this.getParameters = function(){
        return paramenters;
    };
}
function Metrics(active){
    var active = active;
    var thiz = this;
    this.blobURL = null;

    function init() {
        var blob = new Blob([ "onmessage = function(e) { " +
                "var rows_affected = e.data[0];"+
                "var rows_affected_new = [rows_affected.length];"+
                "var origin = e.data[1];"+
                "self.importScripts(origin+'/static/manati_ui/js/libs/underscore-min.js');"+
                "self.importScripts(origin+'/static/manati_ui/js/libs/cryptico.min.js');"+
                "self.importScripts(origin+'/static/js/utils.js');"+
                "for(var i = 0; i< rows_affected.length; i++) {" +
                    "var row = rows_affected[i];"+
                    "var r = {};"+
                    "for(var key in row){"+
                        "var d = findDomainOfURL(row[key]);"+
                        "if(d!=null)r[key] = SHA256(d);"+
                    "};"+
                    "r['dt_id']=row['dt_id'];"+
                    "rows_affected_new[i] = r;"+
                "};"+
                "self.postMessage(rows_affected_new);" +
            "}"]);

            // Obtain a blob URL reference to our worker 'file'.
        thiz.blobURL = window.URL.createObjectURL(blob);

    }
    init();

    function addValue(obj){
        if(obj instanceof EventReg){
            localStorage.setItem(obj.getKey(), JSON.stringify(obj.getParameters()));
        }
    }
    function removeValue(obj){
        if(obj instanceof EventReg){
            localStorage.removeItem(obj.getKey());
        }
    }
    function removeValueByKey(key){
        localStorage.removeItem(key);
    }
    function bulkRemoveValueByKey(keys){
        $.each(keys,function(index, v){
            removeValueByKey(v);
        })

    }
    this.listValues = function(){
        for (var i = 0; i < localStorage.length; i++)   {
            console.log(localStorage.key(i) + "=[" + localStorage.getItem(localStorage.key(i)) + "]");
        }
    };

    this.getAllValues = function () {
        var values = {"keys":[], "data":[]};
        for (var i = 0; i < localStorage.length; i++)   {
            var key = localStorage.key(i);
            if(key.indexOf('EVENT_') >= 0) {
                values["keys"].add(key);
                values["data"].add(localStorage.getItem(key));
            }
        }
        return values;
    };

    // save single labeling and if they/it were/was by Buttons or menucontext or hotkeys
    var EventMultipleLabelings = function(rows_affected, verdict, produced_by){
        if(!active) return false;
        if(rows_affected instanceof Array){
            if(rows_affected.length <= 0) return;
            var worker = new Worker(thiz.blobURL);
            worker.addEventListener('message', function(e) {
                var event_name;
                var data_wb = e.data;
                if(data_wb.length > 1){
                    event_name = "multiple_labelings";
                }else{
                    event_name = "single_labeling";
                }
                var event_reg = new EventReg({  'event_name': event_name,
                                            'weblogs_affected':data_wb,
                                            'amount_wbls': data_wb.length,
                                            'new_verdict': verdict,
                                            'event_produced_by': produced_by});
                addValue(event_reg);
            });
            worker.postMessage([rows_affected,document.location.origin]);
            return true;
        }else{
            throw_error_logging("the 'weblogs_old' must be an array");
            return false;
        }

    };
    this.EventMultipleLabelingsByButtons = function(rows_affected, verdict){
        EventMultipleLabelings(rows_affected,verdict, "buttons")

    };
    this.EventMultipleLabelingsByMenuContext = function(rows_affected, verdict){
        EventMultipleLabelings(rows_affected,verdict, "menucontext")

    };
    this.EventMultipleLabelingsByHotKeys = function(rows_affected, verdict){
        EventMultipleLabelings(rows_affected,verdict, "hotkeys")
    };

    var EventBulkLabeling = function (rows_affected, verdict, labeled_by, filter_by){
        if(!active)return false;
        if(rows_affected instanceof Array){
            if(rows_affected.length <= 0) return;
            var worker = new Worker(thiz.blobURL);
            worker.addEventListener('message', function(e) {
                var event_name = "bulk_labeling";
                var data_wb = e.data;
                var event_reg = new EventReg({  'event_name': event_name,
                                        'weblogs_affected':data_wb,
                                        'filter_by': SHA256(filter_by),
                                        'amount_wbls': data_wb.length,
                                        'new_verdict': verdict,
                                        'labeled_by': labeled_by});
                addValue(event_reg);
            });
            worker.postMessage([rows_affected,document.location.origin]);
            return true;
        }else{
            throw_error_logging("the 'weblogs_old' must be an array");
            return false
        }

    };
    this.EventBulkLabelingByDomains = function(weblogs_old, verdict,domain){
        EventBulkLabeling(weblogs_old,verdict, "domains", domain)

    };
    this.EventBulkLabelingByEndServerIP = function(weblogs_old, verdict, ip){
        EventBulkLabeling(weblogs_old,verdict, "ip", ip)
    };

    this.EventSearching = function(amount_wbls_affected){
        if(!active)return false;
        var event_name = "searching";
        var event_reg = new EventReg({event_name: event_name,
                                    amount_wbls: amount_wbls_affected});
        addValue(event_reg);
        return true;
    };

    var fileUploadingStarted = false;
    this.EventFileUploadingStart = function(file_name_raw, size, type){
        if(!active) return false;
        var event_name = "file_uploading_start";
        if(!fileUploadingStarted){
            fileUploadingStarted = true;
            var event_reg = new EventReg({ event_name: event_name,
                                        file_name_raw: SHA256(file_name_raw),
                                        file_type: type,
                                        file_size: size});
            addValue(event_reg);
            return true;
        }else{
            throw_error_logging("you must throw EventFileUploadingStart and then EventFileUploadingFinished, to close the circuit ");
        }

    };
    this.EventFileUploadingFinished = function(file_name_raw, number_rows){
        if(!active)return false;
        var event_name = "file_uploading_finished";
        if(fileUploadingStarted){
            var event_reg = new EventReg({ event_name: event_name,
                                        file_name_raw: SHA256(file_name_raw),
                                        number_rows: number_rows});
            addValue(event_reg);
            fileUploadingStarted = false;
            return true;
        }else{
            throw_error_logging("you cannot throw EventFileUploadingFinished before of EventFileUploadingStart");
            return false;
        }

    };
    this.EventFileUploadingError = function(file_name_raw){
        if(!active) return false;
        var event_name = "file_uploading_error";
        if(fileUploadingStarted){
            var event_reg = new EventReg({  event_name: event_name,
                                        file_name_raw: SHA256(file_name_raw)});
            addValue(event_reg);
            fileUploadingStarted = false;
            return true;
        }else{
            throw_error_logging("you cannot throw EventFileUploadingFinished before of EventFileUploadingStart");
            return false;
        }

    };
    var AnalysisSessionSavingStarted = false;
    this.EventAnalysisSessionSavingStart = function(number_rows, analysis_session_name){
        if(!active) return false;
        var event_name = "analysis_session_saving_start";
        if(!AnalysisSessionSavingStarted){
            AnalysisSessionSavingStarted = true;
            var event_reg = new EventReg({  event_name: event_name,
                                        analysis_session_name: SHA256(analysis_session_name),
                                        number_rows: number_rows});
            addValue(event_reg);
            return true;
        }else{
            throw_error_logging("you must throw EventAnalysisSessionSavingStart and then EventAnalysisSessionSavingFinished, to close the circuit ");
        }
    };
    this.EventAnalysisSessionSavingFinished = function(analysis_session_name, analysis_session_id){
        if(!active)return false;
        var event_name = "analysis_session_saving_finished";
        if(AnalysisSessionSavingStarted){
            var event_reg = new EventReg({  event_name: event_name,
                                        analysis_session_name: SHA256(analysis_session_name),
                                        analysis_session_id: analysis_session_id});
            addValue(event_reg);
            AnalysisSessionSavingStarted = false;
            return true;
        }else{
            throw_error_logging("you cannot throw EventAnalysisSessionSavingFinished before of EventAnalysisSessionSavingStart");
            return false;
        }
    };
    this.EventAnalysisSessionSavingError = function (analysis_session_name, analysis_session_id) {
        if(!active)return false;
        var event_name = "analysis_session_saving_error";
        if(AnalysisSessionSavingStarted){
            var event_reg = new EventReg({ event_name: event_name,
                                        analysis_session_name: SHA256(analysis_session_name)});
            addValue(event_reg);
            AnalysisSessionSavingStarted = false;
            return true;
        }else{
            throw_error_logging("you cannot throw EventAnalysisSessionSavingFinished before of EventAnalysisSessionSavingStart");
            return false;
        }
    };
    var AS_loading_edit_started = false;
    this.EventLoadingEditingStart = function(analysis_session_id){
        if(!active) return false;
        var event_name = "anal_ses_loading_edit_start";
        if(!AS_loading_edit_started){
            AS_loading_edit_started = true;
            var event_reg = new EventReg({  event_name: event_name,
                                        analysis_session_id: analysis_session_id});
            addValue(event_reg);
            return true;
        }else{
            throw_error_logging("you must throw EventLoadingEditingStart and then EventLoadingEditingFinished, to close the circuit ");
        }

    };
    this.EventLoadingEditingFinished = function(analysis_session_id,number_rows){
        if(!active)return false;
        var event_name = "anal_ses_loading_edit_finished";
        if(AS_loading_edit_started){
            var event_reg = new EventReg({  event_name: event_name,
                                        analysis_session_id: analysis_session_id,
                                        number_rows: number_rows});
            addValue(event_reg);
            AS_loading_edit_started = false;
            return true;
        }else{
            throw_error_logging("you cannot throw EventLoadingEditingFinished before of EventLoadingEditingStart");
            return false;
        }
    };
    this.EventLoadingEditingError = function (analysis_session_id) {
        if(!active) return false;
        var event_name = "anal_ses_loading_edit_error";
        if(AS_loading_edit_started){
            var event_reg = new EventReg({  event_name: event_name,
                                        analysis_session_id: analysis_session_id});
            addValue(event_reg);
            AS_loading_edit_started = false;
            return true;
        }else{
            throw_error_logging("you cannot throw EventAnalysisSessionSavingFinished before of EventAnalysisSessionSavingStart");
            return false;
        }
    };
    this.EventExportingTable = function(number_rows, exporting_type){
        if(!active)return false;
        var event_name = "exporting";
        var event_reg = new EventReg({  event_name: event_name,
                                    number_rows: number_rows,
                                    exporting_type: exporting_type});
        addValue(event_reg);
        return true;
    };
    this.EventMerging = function(rows_affected, verdict_merged){
        if(!active)return false;
        var event_name = "merging_detected";
        var event_reg = new EventReg({  event_name: event_name,
                                    rows_affected: rows_affected,
                                    verdict_merged: verdict_merged});
        addValue(event_reg);
        return true;
    };
    var EventMakeComments = function (type_comments, object_id){
        //yet no implemented, add Worker to 'hash' it
        if(!active)return false;
        var event_name = "merging_detected";
        var event_reg = new EventReg({  event_name: event_name,
                                    rows_affected: rows_affected,
                                    verdict_merged: verdict_merged});
        addValue(event_reg);
        return true;
    };
    this.EventMakeCommentsWeblog = function(weblog_id){
        return EventMakeComments("weblog",weblog_id)
    }
    this.EventMakeCommentsAnalysisSession = function(analysis_session_id){
        return EventMakeComments("analysis_session",analysis_session_id)
    }

    var syncWithDB = function(){
        var measurements = thiz.getAllValues();
        if(measurements['data'].length > 0){
            var data = {'measurements[]': JSON.stringify(measurements['data']), "keys[]": JSON.stringify(measurements['keys']) };
            $.ajax({
                    type:"POST",
                    data: data,
                    dataType: "json",
                    url: "/manati_ui/analysis_session/sync_metrics",
                    success : function(json) {// handle a successful response
                        var keys = json.keys;
                        // console.log("Sync Metrics DONE, " + json.measurements_length + " registers were saved");
                        // console.log(keys);
                        bulkRemoveValueByKey(keys);

                    },
                    error : function(xhr,errmsg,err) { // handle a non-successful response
                        $.notify(xhr.status + ": " + xhr.responseText, "error");
                        console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
                    }
                });
        }

    };
    setInterval(syncWithDB, 1000 * 60 ); //each minute start synchronization
}<commit_msg>minor change in metrics<commit_after>/**
 * Created by raulbeniteznetto on 9/26/16.
 */
// window.onerror = function(msg, url, line)
// {
//   var req = new XMLHttpRequest();
//   var params = "msg=" + encodeURIComponent(msg) + '&url=' + encodeURIComponent(url) + "&line=" + line;
//   // req.open("POST", "/scripts/logerror.php");
//   // req.send(params);
//     console.log(params);
// };

function throw_error_logging(msg){
    console.log(msg);
    throw msg;
}

var time = moment();
var DATETIME_FORMAT = "YYYY-MM-DD HH:mm:ss.SSSSSSZZ";
function getTimeNow(){
    return time.format(DATETIME_FORMAT);
}

function EventReg(params){
    var key;
    var paramenters = params;
    var init = function () {
        var unique_d = new Date().valueOf();
        key = "EVENT_"+ unique_d.toString();
        if(paramenters == null || paramenters == undefined){
            paramenters = {};
        }
        paramenters['created_at'] = getTimeNow();
    };
    init();

    this.getKey = function (){
        return key;
    };
    this.getParameters = function(){
        return paramenters;
    };
}
function Metrics(active){
    var active = active;
    var thiz = this;
    this.blobURL = null;

    function init() {
        var blob = new Blob([ "onmessage = function(e) { " +
                "var rows_affected = e.data[0];"+
                "var rows_affected_new = [rows_affected.length];"+
                "var origin = e.data[1];"+
                "self.importScripts(origin+'/static/manati_ui/js/libs/underscore-min.js');"+
                "self.importScripts(origin+'/static/manati_ui/js/libs/cryptico.min.js');"+
                "self.importScripts(origin+'/static/js/utils.js');"+
                "for(var i = 0; i< rows_affected.length; i++) {" +
                    "var row = rows_affected[i];"+
                    "var r = {};"+
                    "for(var key in row){"+
                        "var d = findDomainOfURL(row[key]);"+
                        "if(d!=null)r[key] = SHA256(d);"+
                    "};"+
                    "r['dt_id']=row['dt_id'];"+
                    "rows_affected_new[i] = r;"+
                "};"+
                "self.postMessage(rows_affected_new);" +
            "}"]);

            // Obtain a blob URL reference to our worker 'file'.
        thiz.blobURL = window.URL.createObjectURL(blob);

    }
    init();

    function addValue(obj){
        if(obj instanceof EventReg){
            localStorage.setItem(obj.getKey(), JSON.stringify(obj.getParameters()));
        }
    }
    function removeValue(obj){
        if(obj instanceof EventReg){
            localStorage.removeItem(obj.getKey());
        }
    }
    function removeValueByKey(key){
        localStorage.removeItem(key);
    }
    function bulkRemoveValueByKey(keys){
        $.each(keys,function(index, v){
            removeValueByKey(v);
        })

    }
    this.listValues = function(){
        for (var i = 0; i < localStorage.length; i++)   {
            console.log(localStorage.key(i) + "=[" + localStorage.getItem(localStorage.key(i)) + "]");
        }
    };

    this.getAllValues = function () {
        var values = {"keys":[], "data":[]};
        for (var i = 0; i < localStorage.length; i++)   {
            var key = localStorage.key(i);
            if(key.indexOf('EVENT_') >= 0) {
                values["keys"].add(key);
                values["data"].add(localStorage.getItem(key));
            }
        }
        return values;
    };

    // save single labeling and if they/it were/was by Buttons or menucontext or hotkeys
    var EventMultipleLabelings = function(rows_affected, verdict, produced_by){
        if(!active) return false;
        if(rows_affected instanceof Array){
            if(rows_affected.length <= 0) return;
            var worker = new Worker(thiz.blobURL);
            worker.addEventListener('message', function(e) {
                var event_name;
                var data_wb = e.data;
                if(data_wb.length > 1){
                    event_name = "multiple_labelings";
                }else{
                    event_name = "single_labeling";
                }
                var event_reg = new EventReg({  'event_name': event_name,
                                            'weblogs_affected':data_wb,
                                            'amount_wbls': data_wb.length,
                                            'new_verdict': verdict,
                                            'event_produced_by': produced_by});
                addValue(event_reg);
            });
            worker.postMessage([rows_affected,document.location.origin]);
            return true;
        }else{
            throw_error_logging("the 'weblogs_old' must be an array");
            return false;
        }

    };
    this.EventMultipleLabelingsByButtons = function(rows_affected, verdict){
        EventMultipleLabelings(rows_affected,verdict, "buttons")

    };
    this.EventMultipleLabelingsByMenuContext = function(rows_affected, verdict){
        EventMultipleLabelings(rows_affected,verdict, "menucontext")

    };
    this.EventMultipleLabelingsByHotKeys = function(rows_affected, verdict){
        EventMultipleLabelings(rows_affected,verdict, "hotkeys")
    };

    var EventBulkLabeling = function (rows_affected, verdict, labeled_by, filter_by){
        if(!active)return false;
        if(rows_affected instanceof Array){
            if(rows_affected.length <= 0) return;
            var worker = new Worker(thiz.blobURL);
            worker.addEventListener('message', function(e) {
                var event_name = "bulk_labeling";
                var data_wb = e.data;
                var event_reg = new EventReg({  'event_name': event_name,
                                        'weblogs_affected':data_wb,
                                        'filter_by': SHA256(filter_by),
                                        'amount_wbls': data_wb.length,
                                        'new_verdict': verdict,
                                        'labeled_by': labeled_by});
                addValue(event_reg);
            });
            worker.postMessage([rows_affected,document.location.origin]);
            return true;
        }else{
            throw_error_logging("the 'weblogs_old' must be an array");
            return false
        }

    };
    this.EventBulkLabelingByDomains = function(weblogs_old, verdict,domain){
        EventBulkLabeling(weblogs_old,verdict, "domains", domain)

    };
    this.EventBulkLabelingByEndServerIP = function(weblogs_old, verdict, ip){
        EventBulkLabeling(weblogs_old,verdict, "ip", ip)
    };

    this.EventSearching = function(amount_wbls_affected){
        if(!active)return false;
        var event_name = "searching";
        var event_reg = new EventReg({event_name: event_name,
                                    amount_wbls: amount_wbls_affected});
        addValue(event_reg);
        return true;
    };

    var fileUploadingStarted = false;
    this.EventFileUploadingStart = function(file_name_raw, size, type){
        if(!active) return false;
        var event_name = "file_uploading_start";
        if(!fileUploadingStarted){
            fileUploadingStarted = true;
            var event_reg = new EventReg({ event_name: event_name,
                                        file_name_raw: SHA256(file_name_raw),
                                        file_type: type,
                                        file_size: size});
            addValue(event_reg);
            return true;
        }else{
            throw_error_logging("you must throw EventFileUploadingStart and then EventFileUploadingFinished, to close the circuit ");
        }

    };
    this.EventFileUploadingFinished = function(file_name_raw, number_rows){
        if(!active)return false;
        var event_name = "file_uploading_finished";
        if(fileUploadingStarted){
            var event_reg = new EventReg({ event_name: event_name,
                                        file_name_raw: SHA256(file_name_raw),
                                        number_rows: number_rows});
            addValue(event_reg);
            fileUploadingStarted = false;
            return true;
        }else{
            throw_error_logging("you cannot throw EventFileUploadingFinished before of EventFileUploadingStart");
            return false;
        }

    };
    this.EventFileUploadingError = function(file_name_raw){
        if(!active) return false;
        var event_name = "file_uploading_error";
        if(fileUploadingStarted){
            var event_reg = new EventReg({  event_name: event_name,
                                        file_name_raw: SHA256(file_name_raw)});
            addValue(event_reg);
            fileUploadingStarted = false;
            return true;
        }else{
            throw_error_logging("you cannot throw EventFileUploadingFinished before of EventFileUploadingStart");
            return false;
        }

    };
    var AnalysisSessionSavingStarted = false;
    this.EventAnalysisSessionSavingStart = function(number_rows, analysis_session_name){
        if(!active) return false;
        var event_name = "analysis_session_saving_start";
        if(!AnalysisSessionSavingStarted){
            AnalysisSessionSavingStarted = true;
            var event_reg = new EventReg({  event_name: event_name,
                                        analysis_session_name: SHA256(analysis_session_name),
                                        number_rows: number_rows});
            addValue(event_reg);
            return true;
        }else{
            throw_error_logging("you must throw EventAnalysisSessionSavingStart and then EventAnalysisSessionSavingFinished, to close the circuit ");
        }
    };
    this.EventAnalysisSessionSavingFinished = function(analysis_session_name, analysis_session_id){
        if(!active)return false;
        var event_name = "analysis_session_saving_finished";
        if(AnalysisSessionSavingStarted){
            var event_reg = new EventReg({  event_name: event_name,
                                        analysis_session_name: SHA256(analysis_session_name),
                                        analysis_session_id: analysis_session_id});
            addValue(event_reg);
            AnalysisSessionSavingStarted = false;
            return true;
        }else{
            throw_error_logging("you cannot throw EventAnalysisSessionSavingFinished before of EventAnalysisSessionSavingStart");
            return false;
        }
    };
    this.EventAnalysisSessionSavingError = function (analysis_session_name) {
        if(!active)return false;
        var event_name = "analysis_session_saving_error";
        if(AnalysisSessionSavingStarted){
            var event_reg = new EventReg({ event_name: event_name,
                                        analysis_session_name: SHA256(analysis_session_name)});
            addValue(event_reg);
            AnalysisSessionSavingStarted = false;
            return true;
        }else{
            throw_error_logging("you cannot throw EventAnalysisSessionSavingFinished before of EventAnalysisSessionSavingStart");
            return false;
        }
    };
    var AS_loading_edit_started = false;
    this.EventLoadingEditingStart = function(analysis_session_id){
        if(!active) return false;
        var event_name = "anal_ses_loading_edit_start";
        if(!AS_loading_edit_started){
            AS_loading_edit_started = true;
            var event_reg = new EventReg({  event_name: event_name,
                                        analysis_session_id: analysis_session_id});
            addValue(event_reg);
            return true;
        }else{
            throw_error_logging("you must throw EventLoadingEditingStart and then EventLoadingEditingFinished, to close the circuit ");
        }

    };
    this.EventLoadingEditingFinished = function(analysis_session_id,number_rows){
        if(!active)return false;
        var event_name = "anal_ses_loading_edit_finished";
        if(AS_loading_edit_started){
            var event_reg = new EventReg({  event_name: event_name,
                                        analysis_session_id: analysis_session_id,
                                        number_rows: number_rows});
            addValue(event_reg);
            AS_loading_edit_started = false;
            return true;
        }else{
            throw_error_logging("you cannot throw EventLoadingEditingFinished before of EventLoadingEditingStart");
            return false;
        }
    };
    this.EventLoadingEditingError = function (analysis_session_id) {
        if(!active) return false;
        var event_name = "anal_ses_loading_edit_error";
        if(AS_loading_edit_started){
            var event_reg = new EventReg({  event_name: event_name,
                                        analysis_session_id: analysis_session_id});
            addValue(event_reg);
            AS_loading_edit_started = false;
            return true;
        }else{
            throw_error_logging("you cannot throw EventAnalysisSessionSavingFinished before of EventAnalysisSessionSavingStart");
            return false;
        }
    };
    this.EventExportingTable = function(number_rows, exporting_type){
        if(!active)return false;
        var event_name = "exporting";
        var event_reg = new EventReg({  event_name: event_name,
                                    number_rows: number_rows,
                                    exporting_type: exporting_type});
        addValue(event_reg);
        return true;
    };
    this.EventMerging = function(rows_affected, verdict_merged){
        if(!active)return false;
        var event_name = "merging_detected";
        var event_reg = new EventReg({  event_name: event_name,
                                    rows_affected: rows_affected,
                                    verdict_merged: verdict_merged});
        addValue(event_reg);
        return true;
    };
    var EventMakeComments = function (type_comments, object_id){
        //yet no implemented, add Worker to 'hash' it
        if(!active)return false;
        var event_name = "merging_detected";
        var event_reg = new EventReg({  event_name: event_name,
                                    rows_affected: rows_affected,
                                    verdict_merged: verdict_merged});
        addValue(event_reg);
        return true;
    };
    this.EventMakeCommentsWeblog = function(weblog_id){
        return EventMakeComments("weblog",weblog_id)
    }
    this.EventMakeCommentsAnalysisSession = function(analysis_session_id){
        return EventMakeComments("analysis_session",analysis_session_id)
    }

    var syncWithDB = function(){
        var measurements = thiz.getAllValues();
        if(measurements['data'].length > 0){
            var data = {'measurements[]': JSON.stringify(measurements['data']), "keys[]": JSON.stringify(measurements['keys']) };
            $.ajax({
                    type:"POST",
                    data: data,
                    dataType: "json",
                    url: "/manati_ui/analysis_session/sync_metrics",
                    success : function(json) {// handle a successful response
                        var keys = json.keys;
                        // console.log("Sync Metrics DONE, " + json.measurements_length + " registers were saved");
                        // console.log(keys);
                        bulkRemoveValueByKey(keys);

                    },
                    error : function(xhr,errmsg,err) { // handle a non-successful response
                        $.notify(xhr.status + ": " + xhr.responseText, "error");
                        console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
                    }
                });
        }

    };
    setInterval(syncWithDB, 1000 * 60 ); //each minute start synchronization
}<|endoftext|>


<commit_before>function loadStaticData(input) {
    $.get('/files/' + input, function(csv) {
        visualize(csv);
    });
}

function visualize(csv) {
    renderable = d3.csv.parse(csv)
    console.log(renderable)
    var chart = createLineViewForData(renderable);
    chart.draw(renderable);
}

function createTableViewForData(data) {
  var chart = new aplos.chart.LineChartView();
  return chart;
}

function createLineViewForData(data) {
  var chart = new aplos.chart.LineChartView();
  chart.configureSeries().x('week_start_date');
  chart.configureSeries().y('queries');
  return chart
}
<commit_msg>Updateds.<commit_after>function loadStaticData(input) {
//    $.get('/files/' + input, function(csv) {
    $.get('/static/result.csv', function(csv) {
        visualize(csv);
    });
}

function visualize(csv) {
    renderable = d3.csv.parse(csv)
    var chart = createLineViewForData(renderable);
    chart.draw(renderable);
}

function createTableViewForData(data) {
  var chart = new aplos.chart.LineChartView();
  return chart;
}

function createLineViewForData(data) {
  if (data == null || data.length === 0) { // null input, return empty chart
    return new aplos.chart.LineChartView();
  } else if (Object.keys(data[0]).length === 2) { // single series line view
    var chart = new aplos.chart.LineChartView().frameSize({width: 800, height: 300});
    var keys = Object.keys(data[0]);
    chart.configureSeries().x(keys[0]);
    chart.configureSeries().y(keys[1]);
    return chart;
  } else {
    var chart = new aplos.chart.LineChartView().frameSize({width: 800, height: 300});
    var keys = Object.keys(data[0]);
    var x_axis = keys[0];
    return new aplos.chart.LineChartView();
  }
}
<|endoftext|>


<commit_before>$(function(){
  var tour = {
    id: "raspied-tour",
    steps: [
      {
        title: "Welcome to the RASPIED website!",
        content: "This tour will walk you through how to use the website to interact with the RASPIED robot. Let's get started! :)",
        target: document.querySelector("#logo-container.brand-logo"),
        placement: "bottom"
      },
      {
        title: "This is your home page",
        content: "This is where you can write code for the robot, upload code to the robot, and view a live video stream of the robot as it runs your code.",
        target: document.querySelector("#nav-home"),
        placement: "bottom"
      },
      {
        title: "This is the code editor tab",
        content: "All the tools for writing and uploading code are in this tab.",
        target: document.querySelector("#editor-tab-link"),
        xOffset: "center",
        placement: "bottom"
      },
      {
        title: "Code editor",
        content: "Your python code goes here. You can type the code in yourself, paste in some code, or even upload a file that you have saved on your computer.",
        target: document.querySelector("#editor"),
        placement: "top"
      },
      {
        title: "View the docs",
        content: "This will open the docs for the RASPIED robot in a new tab. The docs contain tutorials, FAQ's, and comprehensive documentation of the RASPIED robot library.",
        target: document.querySelector("#view-wiki-btn"),
        placement: "bottom"
      },
      {
        title: "Open an existing script",
        content: "This button will allow you to load any python script that you have saved on your computer. Once you have selected and uploaded the script, it will appear in the code editor below and you will then be able to edit it and/or run it on the robot.",
        target: document.querySelector("#open-script-btn"),
        placement: "bottom"
      },
      {
        title: "Save your script",
        content: "This button will download the the script currently in the code editor. This is useful if you want to save your work.",
        target: document.querySelector("#download-script-btn"),
        placement: "bottom"
      },
      {
        title: "Run your script!",
        content: "Clicking this button will upload the script in the code editor to the robot and run it. Note that this button will only be enabled if you have the current booking to use the robot.",
        target: document.querySelector("#run-script-btn"),
        placement: "bottom",
        onNext: function(){
          $("ul.tabs").tabs("select_tab", "output-tab");
        }
      },
      {
        title: "This is the output tab",
        content: "Here you can see a live video stream of the robot and view the output of the code that you run on the robot.",
        target: document.querySelector("#output-tab-link"),
        placement: "bottom"
      },
      {
        title: "Say hello to the RASPIED robot!",
        content: "This is a live video stream of the RASPIED robot.",
        target: document.querySelector("#video-help"),
        xOffset: "center",
        placement: "bottom"
      },
      {
        title: "Code output",
        content: "Any output from code that you run on the robot will be shown here.",
        target: document.querySelector("#terminal-output"),
        placement: "top"
      },
      {
        title: "Before you jump right in...",
        content: "You need to make a booking in order to upload code to the robot. You are allowed to make up to 5 bookings per month and each booking lasts for 1 hour.",
        target: document.querySelector("#nav-booking"),
        placement: "bottom",
        multipage: true,
        onNext: function(){
          window.location = window.location.href.replace("home", "booking");
        }
      },
      {
        title: "These are your upcoming bookings",
        content: "Any upcoming bookings that you have made are shown here.",
        target: document.querySelector("#user-bookings-card"),
        placement: "bottom"
      },
      {
        title: "Make a new booking",
        content: "To make a new booking, simply select the date and time that you wish to book and click the 'Make Booking' button. Your new booking should then appear in your list of upcomming bookings.",
        target: document.querySelector("#submit-new-booking"),
        placement: "bottom"
      },
      {
        title: "One more thing",
        content: "Remember to logout when you're done ;)",
        target: document.querySelector("#nav-logout"),
        placement: "bottom"
      },
      {
        title: "Now you're ready to go",
        content: "You can start by making a booking and then try writing and uploading some code to the robot. Have fun! :D",
        target: document.querySelector("#submit-new-booking"),
        placement: "bottom"
      }
    ]
  };

  if(window.location.href.includes("home")){
    $("#take-tour-btn").click(function(){
      hopscotch.startTour(tour);
    });

    if(is_first_login === true){
      hopscotch.startTour(tour);
    }
  }else if(window.location.href.includes("booking")){
    if (hopscotch.getState() === "raspied-tour:12") {
      hopscotch.startTour(tour);
    }
  }
});
<commit_msg>Add the 'new script button' to the tour and remove the terminal output from the tour (user's don't yet have a booking so this is useless).<commit_after>$(function(){
  var tour = {
    id: "raspied-tour",
    steps: [
      {
        title: "Welcome to the RASPIED website!",
        content: "This tour will walk you through how to use the website to interact with the RASPIED robot. Let's get started! :)",
        target: document.querySelector("#logo-container.brand-logo"),
        placement: "bottom"
      },
      {
        title: "This is your home page",
        content: "This is where you can write code for the robot, upload code to the robot, and view a live video stream of the robot as it runs your code.",
        target: document.querySelector("#nav-home"),
        placement: "bottom"
      },
      {
        title: "This is the code editor tab",
        content: "All the tools for writing and uploading code are in this tab.",
        target: document.querySelector("#editor-tab-link"),
        xOffset: "center",
        placement: "bottom"
      },
      {
        title: "Code editor",
        content: "Your python code goes here. You can type the code in yourself, paste in some code, or even upload a file that you have saved on your computer.",
        target: document.querySelector("#editor"),
        placement: "top"
      },
      {
        title: "Start a new script",
        content: "This will reset the code editor to it's original state and clear any changes you have made. Be sure to save your changes before starting a new script!",
        target: document.querySelector("#new-script-btn"),
        placement: "bottom"
      },
      {
        title: "View the docs",
        content: "This will open the docs for the RASPIED robot in a new tab. The docs contain tutorials, FAQ's, and comprehensive documentation of the RASPIED robot library.",
        target: document.querySelector("#view-wiki-btn"),
        placement: "bottom"
      },
      {
        title: "Open an existing script",
        content: "This button will allow you to load any python script that you have saved on your computer. Once you have selected and uploaded the script, it will appear in the code editor below and you will then be able to edit it and/or run it on the robot.",
        target: document.querySelector("#open-script-btn"),
        placement: "bottom"
      },
      {
        title: "Save your script",
        content: "This button will download the the script currently in the code editor. This is useful if you want to save your work.",
        target: document.querySelector("#download-script-btn"),
        placement: "bottom"
      },
      {
        title: "Run your script!",
        content: "Clicking this button will upload the script in the code editor to the robot and run it. Note that this button will only be enabled if you have the current booking to use the robot.",
        target: document.querySelector("#run-script-btn1"),
        placement: "bottom",
        onNext: function(){
          $("ul.tabs").tabs("select_tab", "output-tab");
        }
      },
      {
        title: "This is the output tab",
        content: "Here you can see a live video stream of the robot and view the output of the code that you run on the robot.",
        target: document.querySelector("#output-tab-link"),
        placement: "bottom"
      },
      {
        title: "Say hello to the RASPIED robot!",
        content: "This is a live video stream of the RASPIED robot.",
        target: document.querySelector("#video-help"),
        xOffset: "center",
        placement: "bottom"
      },
      // {
      //   title: "Code output",
      //   content: "Any output from code that you run on the robot will be shown here.",
      //   target: document.querySelector("#terminal-output"),
      //   placement: "top"
      // },
      {
        title: "Before you jump right in...",
        content: "You need to make a booking in order to upload code to the robot. You are allowed to make up to 5 bookings per month and each booking lasts for 1 hour.",
        target: document.querySelector("#nav-booking"),
        placement: "bottom",
        multipage: true,
        onNext: function(){
          window.location = window.location.href.replace("home", "booking");
        }
      },
      {
        title: "These are your upcoming bookings",
        content: "Any upcoming bookings that you have made are shown here.",
        target: document.querySelector("#user-bookings-card"),
        placement: "bottom"
      },
      {
        title: "Make a new booking",
        content: "To make a new booking, simply select the date and time that you wish to book and click the 'Make Booking' button. Your new booking should then appear in your list of upcomming bookings.",
        target: document.querySelector("#submit-new-booking"),
        placement: "bottom"
      },
      {
        title: "One more thing",
        content: "Remember to logout when you're done ;)",
        target: document.querySelector("#nav-logout"),
        placement: "bottom"
      },
      {
        title: "Now you're ready to go",
        content: "You can start by making a booking and then try writing and uploading some code to the robot. Have fun! :D",
        target: document.querySelector("#submit-new-booking"),
        placement: "bottom"
      }
    ]
  };

  if(window.location.href.includes("home")){
    $("#take-tour-btn").click(function(){
      hopscotch.startTour(tour);
    });

    if(is_first_login === true){
      hopscotch.startTour(tour);
    }
  }else if(window.location.href.includes("booking")){
    if (hopscotch.getState() === "raspied-tour:12") {
      hopscotch.startTour(tour);
    }
  }
});
<|endoftext|>


<commit_before>/**
 *
 */
var page = require('webpage').create();
var sites = require('./sites.json');

page.onError=function(msg, trace){

	console.log('error: '+ msg);
	console.log(trace);
	phantom.exit(1);

};
page.onConsoleMessage = function(msg, lineNum, sourceId) {
	console.log('CONSOLE: ' + msg );
};

sites.forEach(function(site){

	var url=site.url;
	var test=site.test;

	console.log('testing: '+url+' with: '+test);

	page.open(url), function(status) {
		console.log("Status: " + status);
		if(status === "success") {

			setTimeout(function(){

				try{

					var status=page.evaluate(function(){

						console.log("Parsing Qunit output");
						var result={
								failed:parseInt($$('span.failed')[0].innerHTML),
								passed:parseInt($$('span.passed')[0].innerHTML),
								total:parseInt($$('span.total')[0].innerHTML),
								errors:[],
								configs:Object.keys(UIFormManager._forms)
						};

						$$('li li.fail').forEach(function(l){ result.errors.push(l.textContent); });

						return result;
					});
					console.log(JSON.stringify(status));
				}catch(e){
					console.log('Exception parsing qunit results');
				}
				phantom.exit(status.failed);
			}, 10000);
			console.log('waiting for 10s - to ensure qunit completes');

		}else{
			phantom.exit(1);
		}

	});

});<commit_msg>broken?<commit_after>/**
 *
 */
var page = require('webpage').create();
var sites = require('./sites.json');

phantom.onError=function(msg, trace){
	console.error( msg);
	console.error(trace);

});

page.onError=function(msg, trace){

	console.log('error: '+ msg);
	console.log(trace);
	phantom.exit(1);

};
page.onConsoleMessage = function(msg, lineNum, sourceId) {
	console.log('CONSOLE: ' + msg );
};

sites.forEach(function(site){

	var url=site.url;
	var test=site.test;

	console.log('testing: '+url+' with: '+test);

	page.open(url), function(status) {
		console.log("Status: " + status);
		if(status === "success") {

			setTimeout(function(){

				try{

					var status=page.evaluate(function(){

						console.log("Parsing Qunit output");
						var result={
								failed:parseInt($$('span.failed')[0].innerHTML),
								passed:parseInt($$('span.passed')[0].innerHTML),
								total:parseInt($$('span.total')[0].innerHTML),
								errors:[],
								configs:Object.keys(UIFormManager._forms)
						};

						$$('li li.fail').forEach(function(l){ result.errors.push(l.textContent); });

						return result;
					});
					console.log(JSON.stringify(status));
				}catch(e){
					console.log('Exception parsing qunit results');
				}
				phantom.exit(status.failed);
			}, 10000);
			console.log('waiting for 10s - to ensure qunit completes');

		}else{
			phantom.exit(1);
		}

	});

});<|endoftext|>


<commit_before>var chai = require("chai");
var expect = chai.expect;
var inspect = require("util").inspect;

var SuperTask = require('../supertask');
var Optimizer = require('../lib/Optimizations');
var TaskManager;
var exec = 0;
var averager = { prev: 0, current: 0 };

var ftasks = {
    t1: "var exec = 0; module.exports = function(a1, callback){ setTimeout(function(){callback(null, a1, ++exec);}, 10) };",
    t2: "module.exports = function(callback) { callback(); console.log('hey'); };",
    t3: "module.exports = function(callback) { callback(null, process.hrtime()); };"
};

var samples = {
    o_basic: [{
        name: "e1",
        averageExecutionTime: 5300
    }, {
        name: "e2",
        averageExecutionTime: 1200
    }, {
        name: "e3",
        averageExecutionTime: 2000
    }],
    o_mixed: [{
        name: "e1",
        averageExecutionTime: 3000
    }, {
        name: "e2",
        averageExecutionTime: 5300
    }, {
        name: "e3",
        averageExecutionTime: 2000
    }],
    o_mixed_2: [{
        name: "e1",
        averageExecutionTime: 1900
    }, {
        name: "e2",
        averageExecutionTime: 3200
    }, {
        name: "e3",
        averageExecutionTime: 1000
    }],
    o_advanced: [{
        name: "e1",
        averageExecutionTime: 1900,
        executionRounds: 10
    }, {
        name: "e2",
        averageExecutionTime: 1900,
        executionRounds: 100
    }, {
        name: "e3",
        averageExecutionTime: 8000,
        executionRounds: 0
    }]
};

function noop () { return null; }

describe('Basic Test Suite', function(){
    it('should create a new instance', function() {
        TaskManager = new SuperTask();
    });
    it('should add a local task', function(done) {
        TaskManager.addLocal('test', function(callback) {
            exec++;
            callback(null, 'hey');
        }, function(error, task) {
            if(error) throw error;
            expect(task).to.have.property('local');
            done();
        });
    });
    it('should run a task', function(done) {
        TaskManager.do('test', {}, [], function(error, result) {
            if(error) throw error;
            expect(result).to.equal('hey');
            expect(exec).to.be.gte(1);
            averager.prev = this.lastDiff;
            done();
        });
    });
    it('should calculate average execution time', function(done) {
        TaskManager.do('test', {}, [], function(error, result) {
            if(error) throw error;
            expect(result).to.equal('hey');
            expect(exec).to.be.gte(1);
            averager.current = (averager.prev + this.lastDiff)/2;
            expect(this.averageExecutionTime).to.be.equal(averager.current);
            // Sanity Check
            expect(this.averageExecutionTime).to.be.lt(1000000000);
            done();
        });
    });
    it('should deny duplicate task names', function(done) {
        TaskManager.addLocal('test', function(callback) {
            exec++;
            callback(null, 'hey');
        }, function(error) {
            expect(error.message).to.be.equal('Enable to create new task. A Task with the given name already exists.');
            done();
        });
    });
    it('should check if task exists on has call', function(done) {
       TaskManager.has('test', function(error, has) {
           if(error) throw error;
           expect(has).to.be.equal(true);
           done();
       });
    });
    it('should remove given task', function(done) {
        TaskManager.remove('test', function(error) {
            if(error) throw error;
            TaskManager.has('test', function(error, has) {
                if(error) throw error;
                expect(has).to.be.equal(false);
                done();
            });
        });
    });
    it('should contain optimization flags', function (){
        expect(SuperTask).to.have.property('ST_O0');
        expect(SuperTask).to.have.property('ST_O_PRIORITY_ASC');
    });
});

describe('Foreign Task Suite', function(){
    it('should add a foreign task', function(done) {
        TaskManager.addForeignWithContext('foreign', ftasks.t1, {}, SuperTask.ST_MINIMAL, function(error, task) {
            if(error) throw error;
            expect(task).to.have.property('sandboxed');
            done();
        });
    });
    it('should run a foreign task', function(done) {
        TaskManager.do('foreign', {}, ['HelloWorld'], function(error, a1, count) {
            if(error) throw error;
            expect(a1).to.equal('HelloWorld');
            expect(count).to.equal(1);

            done();
        });
    });
    it('should compile and cache a foreign task', function(done) {
        TaskManager.do('foreign', {}, ['HelloWorld'], function(error, a1, count) {
            if(error) throw error;
            expect(a1).to.equal('HelloWorld');
            expect(count).to.equal(2);
            expect(this.isCompiled).to.equal(true);
            done();
        });
    });
    it('should run a foreign task with unique context', function(done) {
        TaskManager.addForeign('foreignUnique', ftasks.t2, function(error, task) {
            if(error) throw error;
            TaskManager.do('foreignUnique', { console: { log: function(m){
                expect(m).to.equal("hey");
                done();
            }}});
        });
    });
    it('should allow foreign tasks as JS functions', function(done) {
        TaskManager.addForeign('foreignFunc', function(callback) {
            console.log('hey');
            callback();
        }, function(error, task) {
            if(error) throw error;
            TaskManager.do('foreignFunc', { console: { log: function(m){
                expect(m).to.equal("hey");
                done();
            }}});
        });
    });
});

describe('Queue & Cargo Suite', function(){
    it('should queue tasks', function() {
        TaskManager.do('foreign', {}, ['HelloWorld']);
        expect(TaskManager.cargo.length()).to.be.gte(1);
    });
    it('should queue tasks in parallel', function() {
        // Queue 5 times
        var i = 0;
        for(i=0; i<5; i++) {
            TaskManager.do('foreign', {}, ['HelloWorld']);
        }
        expect(TaskManager.cargo.length()).to.be.gte(5);
    });
    it('should handle large parallel tasks', function(done) {
        this.timeout(10000);
        // Set max parallel to 5000
        TaskManager.cargo.payload = 5000;
        // Queue 5000 times
        var i = 0;
        for(i=0; i<5000; i++) {
            TaskManager.do('foreign', {}, ['HelloWorld']);
        }
        expect(TaskManager.cargo.length()).to.be.gte(5000);
        TaskManager.cargo.drain = function(){
            done();
            // Reset
            TaskManager.cargo.drain = noop;
        };
    });
    it('should respect maximum parallel execution limit', function(done) {
        TaskManager.cargo.payload = 10;
        var saturated = false;
        TaskManager.cargo.saturated = function(){
            saturated = true;
        };
        // Queue 30 times
        var i = 0;
        for(i=0; i<30; i++) {
            TaskManager.do('foreign', {}, ['HelloWorld']);
        }
        expect(saturated).to.be.equal(true);
        var c = 0;
        TaskManager.cargo.drain = function(){
            done();
            // Reset
            TaskManager.cargo.drain = noop;
        };
    });
});

describe('Permission & Context Suite', function(){
    /* Add More Tests */
    it('should contain the context with respect to permissions', function(done) {
        TaskManager.addForeignWithContext('foreignT3', ftasks.t3, {}, SuperTask.ST_UNRESTRICTED, function(error, task) {
            if(error) throw error;
            expect(task).to.have.property('sandboxed');
            TaskManager.do('foreignT3', {}, [], function(error, time) {
                expect(time).to.be.an('array');
                expect(time).to.have.length(2);
                done();
            });
        });
    });
    it('should restrict the context', function(done) {
        TaskManager.addForeignWithContext('foreignT3C', ftasks.t3, {}, SuperTask.ST_RESTRICTED, function(error, task) {
            if(error) throw error;
            expect(task).to.have.property('sandboxed');
            TaskManager.do('foreignT3C', {}, [], function(error, time) {
                expect(error.message).to.have.string('process is not defined');
                done();
            });
        });
    });
});

describe('Optimizer Test Suite', function() {
    it('should oprimize based on AET', function() {
        var OptimizedArray = Optimizer.optimize(samples.o_basic);
        expect(OptimizedArray[0]).to.deep.equal({ name: 'e2', averageExecutionTime: 1200, value: 0 });
    });
    it('should retain original content of objects within array', function() {
        var OptimizedArray = Optimizer.optimize(samples.o_basic);
        expect(OptimizedArray[0]).to.have.property('averageExecutionTime', 1200);
        expect(OptimizedArray[0]).to.have.property('name', 'e2');
    });
    it('should allow ascending/descending order', function() {
        var OptimizedArray = Optimizer.optimize(samples.o_mixed, Optimizer.levels.ST_O2, Optimizer.flags.ST_O_AET_DSC);
        expect(OptimizedArray[0]).to.have.property('averageExecutionTime', 5300);
        expect(OptimizedArray[0]).to.have.property('name', 'e2');
    });
    it('should respect sorting algorithm selection & offer same results', function() {
        var OptimizedArray = Optimizer.optimize(samples.o_mixed, Optimizer.levels.ST_O2, Optimizer.flags.ST_O_AET_DSC | Optimizer.flags.ST_O_SORT_QUICKONLY);
        expect(OptimizedArray[0]).to.have.property('averageExecutionTime', 5300);
        expect(OptimizedArray[0]).to.have.property('name', 'e2');
    });
    it('should not optimize with level O0', function() {
        var Array = Optimizer.optimize(samples.o_mixed_2, Optimizer.levels.ST_O0);
        expect(Array[0]).to.have.property('name', 'e1');
        expect(Array[0]).to.not.have.property('value');
    });
    it('should optimize at optimization level', function() {
        var Array = Optimizer.optimize(samples.o_mixed_2, Optimizer.levels.ST_O1, Optimizer.flags.ST_O_ER_ASC);
        expect(Array[0]).to.have.property('name', 'e1');
    });
    it('should respect ER optimization', function() {
        var first = Optimizer.optimize(samples.o_advanced, Optimizer.levels.ST_O2, Optimizer.flags.ST_O_ER_DSC);
        expect(first[0]).to.have.property('name', 'e2');
        var second = Optimizer.optimize(samples.o_advanced, Optimizer.levels.ST_O2, Optimizer.flags.ST_O_ER_ASC);
        expect(second[0]).to.have.property('name', 'e1');
    });
});<commit_msg>Added more test units for coverage<commit_after>var chai = require("chai");
var expect = chai.expect;
var inspect = require("util").inspect;

var SuperTask = require('../supertask');
var Optimizer = require('../lib/Optimizations');
var TaskManager;
var exec = 0;
var averager = { prev: 0, current: 0 };

var ftasks = {
    t1: "var exec = 0; module.exports = function(a1, callback){ setTimeout(function(){callback(null, a1, ++exec);}, 10) };",
    t2: "module.exports = function(callback) { callback(); console.log('hey'); };",
    t3: "module.exports = function(callback) { callback(null, process.hrtime()); };"
};

var samples = {
    o_basic: [{
        name: "e1",
        averageExecutionTime: 5300
    }, {
        name: "e2",
        averageExecutionTime: 1200
    }, {
        name: "e3",
        averageExecutionTime: 2000
    }],
    o_mixed: [{
        name: "e1",
        averageExecutionTime: 3000
    }, {
        name: "e2",
        averageExecutionTime: 5300
    }, {
        name: "e3",
        averageExecutionTime: 2000
    }],
    o_mixed_2: [{
        name: "e1",
        averageExecutionTime: 1900
    }, {
        name: "e2",
        averageExecutionTime: 3200
    }, {
        name: "e3",
        averageExecutionTime: 1000
    }],
    o_advanced: [{
        name: "e1",
        averageExecutionTime: 1900,
        executionRounds: 10
    }, {
        name: "e2",
        averageExecutionTime: 1900,
        executionRounds: 100
    }, {
        name: "e3",
        averageExecutionTime: 8000,
        executionRounds: 0
    }]
};

function noop () { return null; }

describe('Basic Test Suite', function(){
    it('should create a new instance', function() {
        TaskManager = new SuperTask();
    });
    it('should add a local task', function(done) {
        TaskManager.addLocal('test', function(callback) {
            exec++;
            callback(null, 'hey');
        }, function(error, task) {
            if(error) throw error;
            expect(task).to.have.property('local');
            done();
        });
    });
    it('should run a task', function(done) {
        TaskManager.do('test', {}, [], function(error, result) {
            if(error) throw error;
            expect(result).to.equal('hey');
            expect(exec).to.be.gte(1);
            averager.prev = this.lastDiff;
            done();
        });
    });
    it('should calculate average execution time', function(done) {
        TaskManager.do('test', {}, [], function(error, result) {
            if(error) throw error;
            expect(result).to.equal('hey');
            expect(exec).to.be.gte(1);
            averager.current = (averager.prev + this.lastDiff)/2;
            expect(this.averageExecutionTime).to.be.equal(averager.current);
            // Sanity Check
            expect(this.averageExecutionTime).to.be.lt(1000000000);
            done();
        });
    });
    it('should deny duplicate task names', function(done) {
        TaskManager.addLocal('test', function(callback) {
            exec++;
            callback(null, 'hey');
        }, function(error) {
            expect(error.message).to.be.equal('Enable to create new task. A Task with the given name already exists.');
            done();
        });
    });
    it('should call with an error if do name is invalid', function(done) {
        TaskManager.do('unknown', {}, [], function(error) {
            expect(error).to.be.an('error');
            expect(error).to.have.property('message', 'Task not found!');
            done();
        });
    });
    it('should check if task exists on has call', function(done) {
       TaskManager.has('test', function(error, has) {
           if(error) throw error;
           expect(has).to.be.equal(true);
           done();
       });
    });
    it('should remove given task', function(done) {
        TaskManager.remove('test', function(error) {
            if(error) throw error;
            TaskManager.has('test', function(error, has) {
                if(error) throw error;
                expect(has).to.be.equal(false);
                done();
            });
        });
    });
    it('should contain optimization flags', function (){
        expect(SuperTask).to.have.property('ST_O0');
        expect(SuperTask).to.have.property('ST_O_PRIORITY_ASC');
    });
});

describe('Foreign Task Suite', function(){
    it('should add a foreign task', function(done) {
        TaskManager.addForeignWithContext('foreign', ftasks.t1, {}, SuperTask.ST_MINIMAL, function(error, task) {
            if(error) throw error;
            expect(task).to.have.property('sandboxed');
            done();
        });
    });
    it('should run a foreign task', function(done) {
        TaskManager.do('foreign', {}, ['HelloWorld'], function(error, a1, count) {
            if(error) throw error;
            expect(a1).to.equal('HelloWorld');
            expect(count).to.equal(1);

            done();
        });
    });
    it('should compile and cache a foreign task', function(done) {
        TaskManager.do('foreign', {}, ['HelloWorld'], function(error, a1, count) {
            if(error) throw error;
            expect(a1).to.equal('HelloWorld');
            expect(count).to.equal(2);
            expect(this.isCompiled).to.equal(true);
            done();
        });
    });
    it('should run a foreign task with unique context', function(done) {
        TaskManager.addForeign('foreignUnique', ftasks.t2, function(error, task) {
            if(error) throw error;
            TaskManager.do('foreignUnique', { console: { log: function(m){
                expect(m).to.equal("hey");
                done();
            }}});
        });
    });
    it('should allow foreign tasks as JS functions', function(done) {
        TaskManager.addForeign('foreignFunc', function(callback) {
            console.log('hey');
            callback();
        }, function(error, task) {
            if(error) throw error;
            TaskManager.do('foreignFunc', { console: { log: function(m){
                expect(m).to.equal("hey");
                done();
            }}});
        });
    });
    it('should allow foreign tasks with context as JS functions', function(done) {
        TaskManager.addForeignWithContext('foreignFunc2', function(callback) {
            console.log('hey');
            callback();
        }, { console: {
                log: function(m){
                    expect(m).to.equal("hey");
                    done();
                }
            }
        }, SuperTask.ST_UNRESTRICTED, function(error, task) {
            if(error) throw error;
            TaskManager.do('foreignFunc2');
        });
    });
});

describe('Queue & Cargo Suite', function(){
    it('should queue tasks', function() {
        TaskManager.do('foreign', {}, ['HelloWorld']);
        expect(TaskManager.cargo.length()).to.be.gte(1);
    });
    it('should queue tasks in parallel', function() {
        // Queue 5 times
        var i = 0;
        for(i=0; i<5; i++) {
            TaskManager.do('foreign', {}, ['HelloWorld']);
        }
        expect(TaskManager.cargo.length()).to.be.gte(5);
    });
    it('should handle large parallel tasks', function(done) {
        this.timeout(10000);
        // Set max parallel to 5000
        TaskManager.cargo.payload = 5000;
        // Queue 5000 times
        var i = 0;
        for(i=0; i<5000; i++) {
            TaskManager.do('foreign', {}, ['HelloWorld']);
        }
        expect(TaskManager.cargo.length()).to.be.gte(5000);
        TaskManager.cargo.drain = function(){
            done();
            // Reset
            TaskManager.cargo.drain = noop;
        };
    });
    it('should respect maximum parallel execution limit', function(done) {
        TaskManager.cargo.payload = 10;
        var saturated = false;
        TaskManager.cargo.saturated = function(){
            saturated = true;
        };
        // Queue 30 times
        var i = 0;
        for(i=0; i<30; i++) {
            TaskManager.do('foreign', {}, ['HelloWorld']);
        }
        expect(saturated).to.be.equal(true);
        var c = 0;
        TaskManager.cargo.drain = function(){
            done();
            // Reset
            TaskManager.cargo.drain = noop;
        };
    });
});

describe('Permission & Context Suite', function(){
    /* Add More Tests */
    it('should contain the context with respect to permissions', function(done) {
        TaskManager.addForeignWithContext('foreignT3', ftasks.t3, {}, SuperTask.ST_UNRESTRICTED, function(error, task) {
            if(error) throw error;
            expect(task).to.have.property('sandboxed');
            TaskManager.do('foreignT3', {}, [], function(error, time) {
                expect(time).to.be.an('array');
                expect(time).to.have.length(2);
                done();
            });
        });
    });
    it('should restrict the context', function(done) {
        TaskManager.addForeignWithContext('foreignT3C', ftasks.t3, {}, SuperTask.ST_RESTRICTED, function(error, task) {
            if(error) throw error;
            expect(task).to.have.property('sandboxed');
            TaskManager.do('foreignT3C', {}, [], function(error, time) {
                expect(error.message).to.have.string('process is not defined');
                done();
            });
        });
    });
});

describe('Optimizer Test Suite', function() {
    it('should oprimize based on AET', function() {
        var OptimizedArray = Optimizer.optimize(samples.o_basic);
        expect(OptimizedArray[0]).to.deep.equal({ name: 'e2', averageExecutionTime: 1200, value: 0 });
    });
    it('should retain original content of objects within array', function() {
        var OptimizedArray = Optimizer.optimize(samples.o_basic);
        expect(OptimizedArray[0]).to.have.property('averageExecutionTime', 1200);
        expect(OptimizedArray[0]).to.have.property('name', 'e2');
    });
    it('should allow ascending/descending order', function() {
        var OptimizedArray = Optimizer.optimize(samples.o_mixed, Optimizer.levels.ST_O2, Optimizer.flags.ST_O_AET_DSC);
        expect(OptimizedArray[0]).to.have.property('averageExecutionTime', 5300);
        expect(OptimizedArray[0]).to.have.property('name', 'e2');
    });
    it('should respect sorting algorithm selection & offer same results', function() {
        var OptimizedArray = Optimizer.optimize(samples.o_mixed, Optimizer.levels.ST_O2, Optimizer.flags.ST_O_AET_DSC | Optimizer.flags.ST_O_SORT_QUICKONLY);
        expect(OptimizedArray[0]).to.have.property('averageExecutionTime', 5300);
        expect(OptimizedArray[0]).to.have.property('name', 'e2');
    });
    it('should not optimize with level O0', function() {
        var Array = Optimizer.optimize(samples.o_mixed_2, Optimizer.levels.ST_O0);
        expect(Array[0]).to.have.property('name', 'e1');
        expect(Array[0]).to.not.have.property('value');
    });
    it('should optimize at optimization level', function() {
        var Array = Optimizer.optimize(samples.o_mixed_2, Optimizer.levels.ST_O1, Optimizer.flags.ST_O_ER_ASC);
        expect(Array[0]).to.have.property('name', 'e1');
    });
    it('should respect ER optimization', function() {
        var first = Optimizer.optimize(samples.o_advanced, Optimizer.levels.ST_O2, Optimizer.flags.ST_O_ER_DSC);
        expect(first[0]).to.have.property('name', 'e2');
        var second = Optimizer.optimize(samples.o_advanced, Optimizer.levels.ST_O2, Optimizer.flags.ST_O_ER_ASC);
        expect(second[0]).to.have.property('name', 'e1');
    });
});<|endoftext|>


<commit_before>var Converter = require('../src/converter'),
hex2bin = new Converter('0123456789abcdef', '01'),
bin2hex = new Converter('01', '0123456789abcdef'),
dec2hex = new Converter('0123456789', '0123456789abcdef'),
hex2dec = new Converter('0123456789abcdef', '0123456789'),
oct2dec = new Converter('01234567', '0123456789'),
dec2otc = new Converter('0123456789', '01234567'),
shorter = new Converter('0123456789', '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-.,'),
unshorter = new Converter('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-.,', '0123456789');

function test (a, b, desc) {
    if (a === b) {
        console.log('\033[32mOK: ' + desc + '\033[0m');
    } else {
        console.error('\033[31mFAIL: ' + desc + '\033[0m');
        console.error('\t\033[31m"' + a + '" doesn\'t match "' + b + '"');
    }
}

// Standard numeric string tests
test(hex2bin.convert('2d5e'), '10110101011110', 'hex2bin(2d5e) === 10110101011110');
test(bin2hex.convert('10110101011110'), '2d5e', 'hex2bin(10110101011110) === 2d5e');
test(dec2hex.convert('11614'), '2d5e', 'hex2bin(11614) === 2d5e');
test(hex2dec.convert('2d5e'), '11614', 'hex2bin(2d5e) === 11614');
test(oct2dec.convert('26536'), '11614', 'hex2bin(26536) === 11614');
test(dec2otc.convert('11614'), '26536', 'hex2bin(11614) === 26536');

var short = shorter.convert('123456789123456789');
test(unshorter.convert(short), '123456789123456789', 'unshorter(shorter(123456789123456789)) === 123456789123456789');

// UTF-8 codepoint compatibility tests
var ucs2 = require('punycode').ucs2;
var dec2moji = new Converter(
  ucs2.decode('0123456789'),
  ucs2.decode(
    '😀😃😄😁😆😅😂🤣☺😊😇🙂🙃😉😌😍😘😗😙😚😋😜😝😛🤑🤗🤓😎😏😒😞😔😟😕🙁☹😣😖😫😩😤😠😡😶😐😑😯😦😧😮😲😵😳😱😨😰😢😥😴🤤😭😓😪🙄'
  )
);
var hex2moji = new Converter(
  ucs2.decode('0123456789abcdef'),
  ucs2.decode(
    '😀😃😄😁😆😅😂🤣☺😊😇🙂🙃😉😌😍😘😗😙😚😋😜😝😛🤑🤗🤓😎😏😒😞😔😟😕🙁☹😣😖😫😩😤😠😡😶😐😑😯😦😧😮😲😵😳😱😨😰😢😥😴🤤😭😓😪🙄'
  )
);
var moji2hex = new Converter(
  ucs2.decode(
    '😀😃😄😁😆😅😂🤣☺😊😇🙂🙃😉😌😍😘😗😙😚😋😜😝😛🤑🤗🤓😎😏😒😞😔😟😕🙁☹😣😖😫😩😤😠😡😶😐😑😯😦😧😮😲😵😳😱😨😰😢😥😴🤤😭😓😪🙄'
  ),
  ucs2.decode('0123456789abcdef')
);

test(
  ucs2.encode(dec2moji.convert(ucs2.decode('11614'))),
  '😄😱😞',
  'ucs2.encode(dec2moji.convert(ucs2.decode(11614))) === 😄😱😞'
);
test(
  ucs2.encode(hex2moji.convert(ucs2.decode('2d5e'))),
  '😄😱😞',
  'ucs2.encode(hex2moji.convert(ucs2.decode(2d5e))) === 😄😱😞'
);
test(
  ucs2.encode(moji2hex.convert(ucs2.decode('😄😱😞'))),
  '2d5e',
  'ucs2.encode(moji2hex.convert(ucs2.decode(😄😱😞))) === 2d5e'
);<commit_msg>Make test difference output nicer<commit_after>var Converter = require('../src/converter'),
hex2bin = new Converter('0123456789abcdef', '01'),
bin2hex = new Converter('01', '0123456789abcdef'),
dec2hex = new Converter('0123456789', '0123456789abcdef'),
hex2dec = new Converter('0123456789abcdef', '0123456789'),
oct2dec = new Converter('01234567', '0123456789'),
dec2otc = new Converter('0123456789', '01234567'),
shorter = new Converter('0123456789', '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-.,'),
unshorter = new Converter('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-.,', '0123456789');

function test (a, b, desc) {
    if (a === b) {
        console.log('\033[32mOK: ' + desc + '\033[0m');
    } else {
        console.error('\033[31mFAIL: ' + desc + '\033[0m');
        console.error('\t\033[31m"\033[0m' + a + '\033[31m" doesn\'t match "\033[0m' + b + '\033[31m"\033[0m');
    }
}

// Standard numeric string tests
test(hex2bin.convert('2d5e'), '10110101011110', 'hex2bin(2d5e) === 10110101011110');
test(bin2hex.convert('10110101011110'), '2d5e', 'hex2bin(10110101011110) === 2d5e');
test(dec2hex.convert('11614'), '2d5e', 'hex2bin(11614) === 2d5e');
test(hex2dec.convert('2d5e'), '11614', 'hex2bin(2d5e) === 11614');
test(oct2dec.convert('26536'), '11614', 'hex2bin(26536) === 11614');
test(dec2otc.convert('11614'), '26536', 'hex2bin(11614) === 26536');

var short = shorter.convert('123456789123456789');
test(unshorter.convert(short), '123456789123456789', 'unshorter(shorter(123456789123456789)) === 123456789123456789');

// UTF-8 codepoint compatibility tests
var ucs2 = require('punycode').ucs2;
var dec2moji = new Converter(
  ucs2.decode('0123456789'),
  ucs2.decode(
    '😀😃😄😁😆😅😂🤣☺😊😇🙂🙃😉😌😍😘😗😙😚😋😜😝😛🤑🤗🤓😎😏😒😞😔😟😕🙁☹😣😖😫😩😤😠😡😶😐😑😯😦😧😮😲😵😳😱😨😰😢😥😴🤤😭😓😪🙄'
  )
);
var hex2moji = new Converter(
  ucs2.decode('0123456789abcdef'),
  ucs2.decode(
    '😀😃😄😁😆😅😂🤣☺😊😇🙂🙃😉😌😍😘😗😙😚😋😜😝😛🤑🤗🤓😎😏😒😞😔😟😕🙁☹😣😖😫😩😤😠😡😶😐😑😯😦😧😮😲😵😳😱😨😰😢😥😴🤤😭😓😪🙄'
  )
);
var moji2hex = new Converter(
  ucs2.decode(
    '😀😃😄😁😆😅😂🤣☺😊😇🙂🙃😉😌😍😘😗😙😚😋😜😝😛🤑🤗🤓😎😏😒😞😔😟😕🙁☹😣😖😫😩😤😠😡😶😐😑😯😦😧😮😲😵😳😱😨😰😢😥😴🤤😭😓😪🙄'
  ),
  ucs2.decode('0123456789abcdef')
);

test(
  ucs2.encode(dec2moji.convert(ucs2.decode('11614'))),
  '😄😱😞',
  'ucs2.encode(dec2moji.convert(ucs2.decode(11614))) === 😄😱😞'
);
test(
  ucs2.encode(hex2moji.convert(ucs2.decode('2d5e'))),
  '😄😱😞',
  'ucs2.encode(hex2moji.convert(ucs2.decode(2d5e))) === 😄😱😞'
);
test(
  ucs2.encode(moji2hex.convert(ucs2.decode('😄😱😞'))),
  '2d5e',
  'ucs2.encode(moji2hex.convert(ucs2.decode(😄😱😞))) === 2d5e'
);<|endoftext|>


<commit_before>/**
 *
 */
var assert=require('assert');
assert.equal(true, true);
var EchoTest=require('./echo.js');

var ws=require('ws');

var series=require("async").series(
		[
function(callback){
	//test direct load
	EchoTest(require('node-rproxy').AutoConnect, require('node-rproxy').Bridge, {echo:9001, bridge:9002, count:20, eachClient:function(client, i){
		client.on('message',function(m){
			console.log('test 0, client '+i+' success');
		});
	}}, function(err, message){

		if(err){
			assert.fail(err);
		}

		callback(null);

	});
},
function(callback){
	console.log('');
	var http=require('http');
	var server = http.createServer(function(request, response){
		 response.end('Http Server: ' + request.url);
	});

	var Bridge= require('node-rproxy').Bridge;
	new Bridge({server:server},function(){
		console.log('hello world server: http+ws');
		server.close();
		callback(null);
	}, function(){

		assert.fail('should not have connected');

	});
	server.listen(9003);

}

],
function(err, results) {
			if(err){
				assert.fail(err.message||err);
			}
			console.log('tests completed successfully');
			process.exit(0);
		});

<commit_msg>rmove line<commit_after>/**
 *
 */
var assert=require('assert');
assert.equal(true, true);
var EchoTest=require('./echo.js');

var series=require("async").series(
		[
function(callback){
	//test direct load
	EchoTest(require('node-rproxy').AutoConnect, require('node-rproxy').Bridge, {echo:9001, bridge:9002, count:20, eachClient:function(client, i){
		client.on('message',function(m){
			console.log('test 0, client '+i+' success');
		});
	}}, function(err, message){

		if(err){
			assert.fail(err);
		}

		callback(null);

	});
},
function(callback){
	console.log('');
	var http=require('http');
	var server = http.createServer(function(request, response){
		 response.end('Http Server: ' + request.url);
	});

	var Bridge= require('node-rproxy').Bridge;
	new Bridge({server:server},function(){
		console.log('hello world server: http+ws');
		server.close();
		callback(null);
	}, function(){

		assert.fail('should not have connected');

	});
	server.listen(9003);

}

],
function(err, results) {
			if(err){
				assert.fail(err.message||err);
			}
			console.log('tests completed successfully');
			process.exit(0);
		});

<|endoftext|>


<commit_before>// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// Occur
// A mechanism for filtering lines of text, repeatedly of necessary. You can use
// it when the search widget (Cmd-F) is active, press Ctrl-O or the occur button
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

import { arr } from "lively.lang";
import { TextSearcher } from "./search.js";
import Document from "./document.js";
import KeyHandler from "../events/KeyHandler.js"

const occurKeyHandler = Object.assign(
  KeyHandler.withBindings([
    {keys: 'Escape|Ctrl-G', command: "occur exit"},
    {keys: 'Enter', command: "occur accept"}
  ]),
  {isOccurHandler: true});

export var occurStartCommand = {
  name: "occur",
  exec: (textMorph, opts = {}) => {
    if (opts.needle)
      textMorph.addPlugin(new Occur(opts));
    return !!opts.needle;
  }
}

function findOccurPlugin(textMorph) {
  return textMorph.plugins.slice().reverse().find(ea => ea.isOccurPlugin);
}

var occurCommands = [{
    name: "occur exit",
    exec: function(textMorph) {
      var occur = findOccurPlugin(textMorph);
      if (!occur) return false;
      occur.options.translatePosition = true;
      textMorph.removePlugin(occur);
      // multiple occurs active, activate the previous one
      var otherOccur = findOccurPlugin(textMorph)
      if (otherOccur) otherOccur.highlight();
      return true;
    },
    readOnly: true
}, {
    name: "occur accept",
    bindKey: 'Enter',
    exec: (textMorph) => {
      var occur = findOccurPlugin(textMorph)
      if (!occur) return false;
      occur.options.translatePosition = true;
      textMorph.removePlugin(occur);
      // multiple occurs active, activate the previous one
      var otherOccur = findOccurPlugin(textMorph)
      if (otherOccur) otherOccur.highlight();
      return true;
    },
    readOnly: true
}];

export class Occur {

  constructor(options = {}) {
    this.options = options;
    if (options.textMorph)
      this.textMorph = options.textMorph;
  }

  get isOccurPlugin() { return true; }

  attach(textMorph) {
    this.textMorph = textMorph;

    // Enables occur mode. expects that `options.needle` is a search term.
    // This search term is used to filter out all the lines that include it
    // and these then replacethe original content. The current cursor position of
    // editor will be translated so that the cursor is on the matching
    // row/column as it was before.
    var pos = this.textMorph.cursorPosition;
    var notEmpty = this.displayOccurContent(this.options);

    if(notEmpty) {
        var translatedPos = this.originalToOccurPosition(pos);
        this.textMorph.cursorPosition = translatedPos;
    }
    return this;
  }

  detach(textMorph) {
    this.removeHighlight();
    var pos = this.options.translatePosition && this.textMorph.cursorPosition,
        translatedPos = pos && this.occurToOriginalPosition(pos);
    this.displayOriginalContent();
    if (translatedPos)
      this.textMorph.cursorPosition = translatedPos;
    this.textMorph = null;
    return this;
  }

  getKeyHandlers(morphKeyHandlers) { return morphKeyHandlers.concat(occurKeyHandler); }
  getCommands(morphCommands) { return occurCommands.concat(morphCommands); }

  matchingLines(options = {needle: ""}) {
    if (!options.needle) return [];
    var lines = this.textMorph.document.lines,
        search = new TextSearcher(this.textMorph),
        found = search.searchForAll({...options, start: {column: 0, row: 0}});

    return arr.groupBy(found, ({range: {start: {row}}}) => row)
        .mapGroups((_, foundInRow) => {
          var row = foundInRow[0].range.start.row;
          return {
            row, ranges: foundInRow.map(({range}) => range),
            line: lines[row]
          }
        }).toArray();
  }

  displayOccurContent(options) {
    this._originalDocument = this.textMorph.document;
    var found = this.matchingLines(options),
        lines = found.map(({line}) => line),
        occurDocument = this._document = new Document(lines);
    occurDocument._occurMatchingLines = found;
    if (found.length > 0) {
       this.textMorph.changeDocument(occurDocument, true);
       this.highlight(options.needle);
       return true;
    } else {
       return false;
    }
  }

  displayOriginalContent() {
    this.textMorph.changeDocument(this._originalDocument);
  }

  occurToOriginalPosition(pos) {
    // Translates the position from the occur document to the original document
    // or `pos` if not found.
    var lines = this._document._occurMatchingLines;
    if (!lines || !lines[pos.row]) return pos;
    return {row: lines[pos.row].row, column: pos.column};
  }

  originalToOccurPosition(pos) {
    var lines = this._document._occurMatchingLines,
        nullPos = {row: 0, column: 0};
    if (!lines) return nullPos;
    for (var i = 0; i < lines.length; i++)
      if (lines[i].row === pos.row)
        return {row: i, column: pos.column};
    return nullPos;
  }

  highlight(needle) {
    this.removeHighlight();
    var style = {
        borderRadius: "4px",
        backgroundColor: "rgba(87, 255, 8, 0.25)",
        position: "absolute",
        "-moz-box-sizing": "border-box",
        "-webkit-box-sizing": "border-box",
        "box-sizing": "border-box",
        "box-shadow": "0 0 4px rgb(91, 255, 50)"
    }
    var ranges = arr.flatmap(this._document._occurMatchingLines, ({ranges}, row) =>
                  ranges.map(({start: {column}, end: {column: endColumn}}) =>
                    ({start: {column, row}, end: {column: endColumn, row}})))

    ranges.map((range, i) => ({id: "occur-"+i, range, style}))
          .forEach(m => this.textMorph.addMarker(m));
  }

  removeHighlight() {
    (this.textMorph.markers || [])
      .filter(({id}) => id.indexOf("occur-") === 0)
      .forEach(m => this.textMorph.removeMarker(m));
  }
}
<commit_msg>text2: fixing occur<commit_after>// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// Occur
// A mechanism for filtering lines of text, repeatedly of necessary. You can use
// it when the search widget (Cmd-F) is active, press Ctrl-O or the occur button
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

import { arr } from "lively.lang";
import { TextSearcher } from "./search.js";
import KeyHandler from "../events/KeyHandler.js"

const occurKeyHandler = Object.assign(
  KeyHandler.withBindings([
    {keys: 'Escape|Ctrl-G', command: "occur exit"},
    {keys: 'Enter', command: "occur accept"}
  ]),
  {isOccurHandler: true});

export var occurStartCommand = {
  name: "occur",
  exec: (textMorph, opts = {}) => {
    if (opts.needle)
      textMorph.addPlugin(new Occur(opts));
    return !!opts.needle;
  }
}

function findOccurPlugin(textMorph) {
  return textMorph.plugins.slice().reverse().find(ea => ea.isOccurPlugin);
}

var occurCommands = [{
    name: "occur exit",
    exec: function(textMorph) {
      var occur = findOccurPlugin(textMorph);
      if (!occur) return false;
      occur.options.translatePosition = true;
      textMorph.removePlugin(occur);
      // multiple occurs active, activate the previous one
      var otherOccur = findOccurPlugin(textMorph)
      if (otherOccur) otherOccur.highlight();
      return true;
    },
    readOnly: true
}, {
    name: "occur accept",
    bindKey: 'Enter',
    exec: (textMorph) => {
      var occur = findOccurPlugin(textMorph)
      if (!occur) return false;
      occur.options.translatePosition = true;
      textMorph.removePlugin(occur);
      // multiple occurs active, activate the previous one
      var otherOccur = findOccurPlugin(textMorph)
      if (otherOccur) otherOccur.highlight();
      return true;
    },
    readOnly: true
}];

export class Occur {

  constructor(options = {}) {
    this.options = options;
    if (options.textMorph)
      this.textMorph = options.textMorph;
  }

  get isOccurPlugin() { return true; }

  attach(textMorph) {
    this.textMorph = textMorph;

    // Enables occur mode. expects that `options.needle` is a search term.
    // This search term is used to filter out all the lines that include it
    // and these then replacethe original content. The current cursor position of
    // editor will be translated so that the cursor is on the matching
    // row/column as it was before.
    var pos = this.textMorph.cursorPosition;
    var notEmpty = this.displayOccurContent(this.options);

    if(notEmpty) {
        var translatedPos = this.originalToOccurPosition(pos);
        this.textMorph.cursorPosition = translatedPos;
    }
    return this;
  }

  detach(textMorph) {
    this.removeHighlight();
    var pos = this.options.translatePosition && this.textMorph.cursorPosition,
        translatedPos = pos && this.occurToOriginalPosition(pos);
    this.displayOriginalContent();
    if (translatedPos)
      this.textMorph.cursorPosition = translatedPos;
    this.textMorph = null;
    return this;
  }

  getKeyHandlers(morphKeyHandlers) { return morphKeyHandlers.concat(occurKeyHandler); }
  getCommands(morphCommands) { return occurCommands.concat(morphCommands); }

  matchingLines(options = {needle: ""}) {
    if (!options.needle) return [];
    var lines = this.textMorph.document.lineStrings,
        search = new TextSearcher(this.textMorph),
        found = search.searchForAll({...options, start: {column: 0, row: 0}});

    return arr.groupBy(found, ({range: {start: {row}}}) => row)
        .mapGroups((_, foundInRow) => {
          var row = foundInRow[0].range.start.row;
          return {
            row, ranges: foundInRow.map(({range}) => range),
            line: lines[row]
          }
        }).toArray();
  }

  displayOccurContent(options) {
    this._originalDocument = this.textMorph.document;
    var Document = this._originalDocument.constructor,
        found = this.matchingLines(options),
        lines = found.map(({line}) => line),
        occurDocument = this._document = new Document(lines);
    occurDocument._occurMatchingLines = found;
    if (found.length > 0) {
       this.textMorph.changeDocument(occurDocument, true);
       this.highlight(options.needle);
       return true;
    } else {
       return false;
    }
  }

  displayOriginalContent() {
    this.textMorph.changeDocument(this._originalDocument);
  }

  occurToOriginalPosition(pos) {
    // Translates the position from the occur document to the original document
    // or `pos` if not found.
    var lines = this._document._occurMatchingLines;
    if (!lines || !lines[pos.row]) return pos;
    return {row: lines[pos.row].row, column: pos.column};
  }

  originalToOccurPosition(pos) {
    var lines = this._document._occurMatchingLines,
        nullPos = {row: 0, column: 0};
    if (!lines) return nullPos;
    for (var i = 0; i < lines.length; i++)
      if (lines[i].row === pos.row)
        return {row: i, column: pos.column};
    return nullPos;
  }

  highlight(needle) {
    this.removeHighlight();
    var style = {
        borderRadius: "4px",
        backgroundColor: "rgba(87, 255, 8, 0.25)",
        position: "absolute",
        "-moz-box-sizing": "border-box",
        "-webkit-box-sizing": "border-box",
        "box-sizing": "border-box",
        "box-shadow": "0 0 4px rgb(91, 255, 50)"
    }
    var ranges = arr.flatmap(this._document._occurMatchingLines, ({ranges}, row) =>
                  ranges.map(({start: {column}, end: {column: endColumn}}) =>
                    ({start: {column, row}, end: {column: endColumn, row}})))

    ranges.map((range, i) => ({id: "occur-"+i, range, style}))
          .forEach(m => this.textMorph.addMarker(m));
  }

  removeHighlight() {
    (this.textMorph.markers || [])
      .filter(({id}) => id.indexOf("occur-") === 0)
      .forEach(m => this.textMorph.removeMarker(m));
  }
}
<|endoftext|>