<commit_before>/**
 * @license Copyright (c) CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.html or http://ckeditor.com/license
 */

(function() {
    if (!supportsLocalStorage()) {
        CKEDITOR.plugins.add("autosave", {}); //register a dummy plugin to pass CKEditor plugin initialization process
        return;
    }

    CKEDITOR.plugins.add("autosave", {
        lang: 'ca,de,en,es,ja,pl,pt-br,sv,zh,zh-cn', // %REMOVE_LINE_CORE%
        version: 0.10,
        init: function(editor) {
            CKEDITOR.document.appendStyleSheet(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'css/autosave.min.css'));

            if (typeof (jQuery) === 'undefined') {
                CKEDITOR.scriptLoader.load('//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js', function() {
                    jQuery.noConflict();

                    loadPlugin(editor);
                });

            } else {
                CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'js/extensions.min.js'), function() {
                    loadPlugin(editor);
                });
            }
        }
    });

    function loadPlugin(editorInstance) {
        var autoSaveKey = editorInstance.config.autosave_SaveKey != null ? editorInstance.config.autosave_SaveKey : 'autosave_' + window.location + "_" + editorInstance.id;
        var notOlderThan = editorInstance.config.autosave_NotOlderThan != null ? editorInstance.config.autosave_NotOlderThan : 1440;
        var saveOnDestroy = editorInstance.config.autosave_saveOnDestroy != null ? editorInstance.config.autosave_saveOnDestroy : false;
        var saveDetectionSelectors =
            editorInstance.config.autosave_saveDetectionSelectors != null ? editorInstance.config.autosave_saveDetectionSelectors : "a[href^='javascript:__doPostBack'][id*='Save'],a[id*='Cancel']";

        CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'js/extensions.min.js'), function() {
            GenerateAutoSaveDialog(editorInstance, autoSaveKey);

            CheckForAutoSavedContent(editorInstance, autoSaveKey, notOlderThan);
        });

        jQuery(saveDetectionSelectors).click(function() {
            RemoveStorage(autoSaveKey);
        });

        editorInstance.on('change', startTimer);

        editorInstance.on('destroy', function() {
            if (saveOnDestroy) {
                SaveData(autoSaveKey, editorInstance);
            }
        });

        editorInstance.on('uiSpace', function(event) {
            if (event.data.space == 'bottom') {
                event.data.html += '

'
                    + event.editor.lang.autosave.autoSaveMessage
                    + '

';
            }
        }, editorInstance, null, 100);
    }

    function autoSaveMessageId(editorInstance) {
        return 'cke_autoSaveMessage_' + editorInstance.name;
    }

    var timeOutId = 0,
        savingActive = false;

    var startTimer = function(event) {
        if (timeOutId) {
            clearTimeout(timeOutId);
        }
        var delay = CKEDITOR.config.autosave_delay != null ? CKEDITOR.config.autosave_delay : 10;
        timeOutId = setTimeout(onTimer, delay * 1000, event);
    };
    var onTimer = function(event) {
        if (savingActive) {
            startTimer(event);
        } else if (event.editor.checkDirty() || event.editor.plugins.bbcode) {
            savingActive = true;
            var editor = event.editor,
                autoSaveKey = editor.config.autosave_SaveKey != null ? editor.config.autosave_SaveKey : 'autosave_' + window.location + "_" + editor.id;

            SaveData(autoSaveKey, editor);

            savingActive = false;
        }
    };

    // localStorage detection
    function supportsLocalStorage() {
        if (typeof (Storage) === 'undefined') {
            return false;
        }

        try {
            localStorage.getItem("___test_key");
            return true;
        } catch (e) {
            return false;
        }
    }

    function GenerateAutoSaveDialog(editorInstance, autoSaveKey) {
        CKEDITOR.dialog.add('autosaveDialog', function() {
            return {
                title: editorInstance.lang.autosave.title,
                minHeight: 155,
                height: 300,
                width: 750,
                onShow: function() {
                    RenderDiff(this, editorInstance, autoSaveKey);
                },
                onOk: function() {
                    var jsonSavedContent = LoadData(autoSaveKey);

                    editorInstance.setData(jsonSavedContent.data);

                    RemoveStorage(autoSaveKey);
                },
                onCancel: function() {
                    RemoveStorage(autoSaveKey);
                },
                contents: [
                    {
                        label: '',
                        id: 'general',
                        elements: [
                            {
                                type: 'radio',
                                id: 'diffType',
                                label: editorInstance.lang.autosave.diffType,
                                items: [[editorInstance.lang.autosave.sideBySide, 'sideBySide'], [editorInstance.lang.autosave.inline, 'inline']],
                                'default': 'sideBySide',
                                onClick: function() {
                                    RenderDiff(this._.dialog, editorInstance, autoSaveKey);
                                }
                            }, {
                                type: 'html',
                                id: 'diffContent',
                                html: ''
                            }
                        ]
                    }
                ],
                buttons: [
                    {
                        id: 'ok',
                        type: 'button',
                        label: editorInstance.lang.autosave.ok,
                        'class': 'cke_dialog_ui_button_ok cke_dialog_autosave_ok',
                        onClick: function(evt) {
                            var dialog = evt.data.dialog;
                            if (dialog.fire('ok', { hide: true }).hide !== false)
                                dialog.hide();
                        }
                    },
                    {
                        id: 'cancel',
                        type: 'button',
                        label: editorInstance.lang.autosave.no,
                        'class': 'cke_dialog_ui_button_cancel',
                        onClick: function(evt) {
                            var dialog = evt.data.dialog;
                            if (dialog.fire('cancel', { hide: true }).hide !== false)
                                dialog.hide();
                        }
                    }
                ]
            };
        });
    }

    function CheckForAutoSavedContent(editorInstance, autoSaveKey, notOlderThan) {
        // Checks If there is data available and load it
        if (localStorage.getItem(autoSaveKey)) {
            var jsonSavedContent = LoadData(autoSaveKey);

            var autoSavedContent = jsonSavedContent.data;
            var autoSavedContentDate = jsonSavedContent.saveTime;

            var editorLoadedContent = editorInstance.getData();

            // check if the loaded editor content is the same as the autosaved content
            if (editorLoadedContent == autoSavedContent) {
                localStorage.removeItem(autoSaveKey);
                return;
            }

            // Ignore if autosaved content is older then x minutes
            if (moment(new Date()).diff(autoSavedContentDate, 'minutes') > notOlderThan) {
                RemoveStorage(autoSaveKey);

                return;
            }

            var confirmMessage = editorInstance.lang.autosave.loadSavedContent.replace("{0}", moment(autoSavedContentDate).lang(editorInstance.config.language).format(editorInstance.lang.autosave.dateFormat));
            if (confirm(confirmMessage)) {
                // Open DIFF Dialog
                editorInstance.openDialog('autosaveDialog');
            } else {
                RemoveStorage(autoSaveKey);
            }
        }
    }

    function LoadData(autoSaveKey) {
        var compressedJSON = LZString.decompressFromUTF16(localStorage.getItem(autoSaveKey));
        return JSON.parse(compressedJSON);
    }

    function SaveData(autoSaveKey, editorInstance) {
        var compressedJSON = LZString.compressToUTF16(JSON.stringify({ data: editorInstance.getData(), saveTime: new Date() }));
        localStorage.setItem(autoSaveKey, compressedJSON);

        var autoSaveMessage = document.getElementById(autoSaveMessageId(editorInstance));

        if (autoSaveMessage) {
            autoSaveMessage.className = "show";

            setTimeout(function() {
                autoSaveMessage.className = "hidden";
            }, 2000);
        }
    }

    function RemoveStorage(autoSaveKey) {
        if (timeOutId) {
            clearTimeout(timeOutId);
        }

        localStorage.removeItem(autoSaveKey);
    }

    function RenderDiff(dialog, editorInstance, autoSaveKey) {
        var jsonSavedContent = LoadData(autoSaveKey);

        var base = difflib.stringAsLines(editorInstance.getData());
        var newtxt = difflib.stringAsLines(jsonSavedContent.data);
        var sm = new difflib.SequenceMatcher(base, newtxt);
        var opcodes = sm.get_opcodes();

        dialog.getContentElement('general', 'diffContent').getElement().setHtml('
' + diffview.buildView({
            baseTextLines: base,
            newTextLines: newtxt,
            opcodes: opcodes,
            baseTextName: editorInstance.lang.autosave.loadedContent,
            newTextName: editorInstance.lang.autosave.autoSavedContent + (moment(jsonSavedContent.saveTime).lang(editorInstance.config.language).format(editorInstance.lang.autosave.dateFormat)) + '\'',
            contextSize: 3,
            viewType: dialog.getContentElement('general', 'diffType').getValue() == "inline" ? 1 : 0
        }).outerHTML + '
');
    }
})();
<commit_msg>fixed display of the save message<commit_after>/**
 * @license Copyright (c) CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.html or http://ckeditor.com/license
 */

(function() {
    if (!supportsLocalStorage()) {
        CKEDITOR.plugins.add("autosave", {}); //register a dummy plugin to pass CKEditor plugin initialization process
        return;
    }

    CKEDITOR.plugins.add("autosave", {
        lang: 'ca,de,en,es,ja,pl,pt-br,sv,zh,zh-cn', // %REMOVE_LINE_CORE%
        version: 0.10,
        init: function(editor) {
            CKEDITOR.document.appendStyleSheet(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'css/autosave.min.css'));

            editor.on('uiSpace', function (event) {
                if (event.data.space == 'bottom') {

                    event.data.html += '

'
                        + event.editor.lang.autosave.autoSaveMessage
                        + '

';
                }
            }, editor, null, 100);

            if (typeof (jQuery) === 'undefined') {
                CKEDITOR.scriptLoader.load('//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js', function() {
                    jQuery.noConflict();

                    loadPlugin(editor);
                });

            } else {
                CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'js/extensions.min.js'), function() {
                    loadPlugin(editor);
                });
            }
        }
    });

    function loadPlugin(editorInstance) {
        var autoSaveKey = editorInstance.config.autosave_SaveKey != null ? editorInstance.config.autosave_SaveKey : 'autosave_' + window.location + "_" + editorInstance.id;
        var notOlderThan = editorInstance.config.autosave_NotOlderThan != null ? editorInstance.config.autosave_NotOlderThan : 1440;
        var saveOnDestroy = editorInstance.config.autosave_saveOnDestroy != null ? editorInstance.config.autosave_saveOnDestroy : false;
        var saveDetectionSelectors =
            editorInstance.config.autosave_saveDetectionSelectors != null ? editorInstance.config.autosave_saveDetectionSelectors : "a[href^='javascript:__doPostBack'][id*='Save'],a[id*='Cancel']";

        CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'js/extensions.min.js'), function() {
            GenerateAutoSaveDialog(editorInstance, autoSaveKey);

            CheckForAutoSavedContent(editorInstance, autoSaveKey, notOlderThan);
        });

        jQuery(saveDetectionSelectors).click(function() {
            RemoveStorage(autoSaveKey);
        });

        editorInstance.on('change', startTimer);

        editorInstance.on('destroy', function() {
            if (saveOnDestroy) {
                SaveData(autoSaveKey, editorInstance);
            }
        });
    }

    function autoSaveMessageId(editorInstance) {
        return 'cke_autoSaveMessage_' + editorInstance.name;
    }

    var timeOutId = 0,
        savingActive = false;

    var startTimer = function(event) {
        if (timeOutId) {
            clearTimeout(timeOutId);
        }
        var delay = CKEDITOR.config.autosave_delay != null ? CKEDITOR.config.autosave_delay : 10;
        timeOutId = setTimeout(onTimer, delay * 1000, event);
    };
    var onTimer = function(event) {
        if (savingActive) {
            startTimer(event);
        } else if (event.editor.checkDirty() || event.editor.plugins.bbcode) {
            savingActive = true;
            var editor = event.editor,
                autoSaveKey = editor.config.autosave_SaveKey != null ? editor.config.autosave_SaveKey : 'autosave_' + window.location + "_" + editor.id;

            SaveData(autoSaveKey, editor);

            savingActive = false;
        }
    };

    // localStorage detection
    function supportsLocalStorage() {
        if (typeof (Storage) === 'undefined') {
            return false;
        }

        try {
            localStorage.getItem("___test_key");
            return true;
        } catch (e) {
            return false;
        }
    }

    function GenerateAutoSaveDialog(editorInstance, autoSaveKey) {
        CKEDITOR.dialog.add('autosaveDialog', function() {
            return {
                title: editorInstance.lang.autosave.title,
                minHeight: 155,
                height: 300,
                width: 750,
                onShow: function() {
                    RenderDiff(this, editorInstance, autoSaveKey);
                },
                onOk: function() {
                    var jsonSavedContent = LoadData(autoSaveKey);

                    editorInstance.setData(jsonSavedContent.data);

                    RemoveStorage(autoSaveKey);
                },
                onCancel: function() {
                    RemoveStorage(autoSaveKey);
                },
                contents: [
                    {
                        label: '',
                        id: 'general',
                        elements: [
                            {
                                type: 'radio',
                                id: 'diffType',
                                label: editorInstance.lang.autosave.diffType,
                                items: [[editorInstance.lang.autosave.sideBySide, 'sideBySide'], [editorInstance.lang.autosave.inline, 'inline']],
                                'default': 'sideBySide',
                                onClick: function() {
                                    RenderDiff(this._.dialog, editorInstance, autoSaveKey);
                                }
                            }, {
                                type: 'html',
                                id: 'diffContent',
                                html: ''
                            }
                        ]
                    }
                ],
                buttons: [
                    {
                        id: 'ok',
                        type: 'button',
                        label: editorInstance.lang.autosave.ok,
                        'class': 'cke_dialog_ui_button_ok cke_dialog_autosave_ok',
                        onClick: function(evt) {
                            var dialog = evt.data.dialog;
                            if (dialog.fire('ok', { hide: true }).hide !== false)
                                dialog.hide();
                        }
                    },
                    {
                        id: 'cancel',
                        type: 'button',
                        label: editorInstance.lang.autosave.no,
                        'class': 'cke_dialog_ui_button_cancel',
                        onClick: function(evt) {
                            var dialog = evt.data.dialog;
                            if (dialog.fire('cancel', { hide: true }).hide !== false)
                                dialog.hide();
                        }
                    }
                ]
            };
        });
    }

    function CheckForAutoSavedContent(editorInstance, autoSaveKey, notOlderThan) {
        // Checks If there is data available and load it
        if (localStorage.getItem(autoSaveKey)) {
            var jsonSavedContent = LoadData(autoSaveKey);

            var autoSavedContent = jsonSavedContent.data;
            var autoSavedContentDate = jsonSavedContent.saveTime;

            var editorLoadedContent = editorInstance.getData();

            // check if the loaded editor content is the same as the autosaved content
            if (editorLoadedContent == autoSavedContent) {
                localStorage.removeItem(autoSaveKey);
                return;
            }

            // Ignore if autosaved content is older then x minutes
            if (moment(new Date()).diff(autoSavedContentDate, 'minutes') > notOlderThan) {
                RemoveStorage(autoSaveKey);

                return;
            }

            var confirmMessage = editorInstance.lang.autosave.loadSavedContent.replace("{0}", moment(autoSavedContentDate).lang(editorInstance.config.language).format(editorInstance.lang.autosave.dateFormat));
            if (confirm(confirmMessage)) {
                // Open DIFF Dialog
                editorInstance.openDialog('autosaveDialog');
            } else {
                RemoveStorage(autoSaveKey);
            }
        }
    }

    function LoadData(autoSaveKey) {
        var compressedJSON = LZString.decompressFromUTF16(localStorage.getItem(autoSaveKey));
        return JSON.parse(compressedJSON);
    }

    function SaveData(autoSaveKey, editorInstance) {
        var compressedJSON = LZString.compressToUTF16(JSON.stringify({ data: editorInstance.getData(), saveTime: new Date() }));
        localStorage.setItem(autoSaveKey, compressedJSON);

        var autoSaveMessage = document.getElementById(autoSaveMessageId(editorInstance));

        if (autoSaveMessage) {
            autoSaveMessage.className = "show";

            setTimeout(function() {
                autoSaveMessage.className = "hidden";
            }, 2000);
        }
    }

    function RemoveStorage(autoSaveKey) {
        if (timeOutId) {
            clearTimeout(timeOutId);
        }

        localStorage.removeItem(autoSaveKey);
    }

    function RenderDiff(dialog, editorInstance, autoSaveKey) {
        var jsonSavedContent = LoadData(autoSaveKey);

        var base = difflib.stringAsLines(editorInstance.getData());
        var newtxt = difflib.stringAsLines(jsonSavedContent.data);
        var sm = new difflib.SequenceMatcher(base, newtxt);
        var opcodes = sm.get_opcodes();

        dialog.getContentElement('general', 'diffContent').getElement().setHtml('
' + diffview.buildView({
            baseTextLines: base,
            newTextLines: newtxt,
            opcodes: opcodes,
            baseTextName: editorInstance.lang.autosave.loadedContent,
            newTextName: editorInstance.lang.autosave.autoSavedContent + (moment(jsonSavedContent.saveTime).lang(editorInstance.config.language).format(editorInstance.lang.autosave.dateFormat)) + '\'',
            contextSize: 3,
            viewType: dialog.getContentElement('general', 'diffType').getValue() == "inline" ? 1 : 0
        }).outerHTML + '
');
    }
})();
<|endoftext|>


<commit_before>
function flattenObject(object) {
	let out = {};
	flattenObject2(object, false, out);
	return out;
}

function flattenObject2(object, key, out) {
	if ( ! _.isObject(object)) {
		if ( ! key) key = 'no-key';
		out[key] = object;
		return;
	}
	// Hack for prettier output: avoid extra nesting in key if we can do so without potential clashes
	let prevKey = key+' ';
	if (true || ! key || Object.keys(object).length === 1 || _.isArray(object)) {
		prevKey = '';
	}
	_.forIn(object, function(value, key2) {
		flattenObject2(value, prevKey+key2, out);
	});
}

$(function(){

	$.get('http://localhost:8765/project/assist?action=get')
	.then(function(results){
		console.log("results",results);
		let scores = pivot(results, "'cargo' -> i -> '_source' -> 'results' -> scores", 'scores');
		scores = flattenObject(scores);
		let scoreNames = Object.keys(scores);
		console.log("scoreNames", scoreNames);
		let expIds = pivot(results, "'cargo' -> i -> '_id' -> id", 'id');
		console.log("expIds", expIds);
		// Build a table of results
		const $tbl = $('

');
		{	// header
			let $tr = $('

');
			$tr.append('Experiment Name	'); // exp name
			$tr.append('	'); // exp controls
			for(let i=0; i<scoreNames.length; i++) {
				$tr.append(''+scoreNames[i].replace(/[_\-]/g, ' ')+'	');
			}
			const $thead = $("

");
			$thead.append($tr);
			$tbl.append($thead);
		}
		let experiments = results.cargo;
		const $tbody = $("

");
		for(let ri=0; ri<experiments.length; ri++) {
			const e = experiments[ri];
			const scores = e._source.results;
			let flatScores = flattenObject(scores);
			const spec = e._source.spec;
			let $tr = $('

');
			let ename = e._source.name;
			if ( ! ename && spec) {
				ename = spec.planname;
			}
			if ( ! ename) {
				ename = e._id;
			} //data_source
			$tr.append(''+ename.substr(0,60)+'	');
			let $td = $('	');
			let $delBtn = $('<button></button>');
			$delBtn.click(function() {
				let ok = confirm("Trash this experiment?");
				if ( ! ok) return;
				$.get('http://localhost:8765/project/assist?action=delete&id='+escape(e._id))
				.then(function(){
					$tr.fadeOut();
				});
			});
			$td.append($delBtn);
			$tr.append($td);
			for(let si=0; si<scoreNames.length; si++) {
				let score = flatScores[scoreNames[si]];
				console.log('flatScores', flatScores, scoreNames[si]);
				let klass = judge(scoreNames[si], score);
				$tr.append(''+(_.isNumber(score)? printer.prettyNumber(score) : printer.str(score))+'	');
			}
			$tbody.append($tr);
		}
		$tbl.append($tbody);
		$('#results').append($tbl);
		setTimeout(function(){$tbl.DataTable();},50);
	});

});

function judge(scoreName, score) {
	const GOOD = 'success', WARNING='warning', BAD='danger';
	if (scoreName.indexOf('R2') !== -1) {
		if (score>0.8) return GOOD;
		if (score<0.5) return BAD;
		if (score<0.65) return WARNING;
	}
	if (scoreName==='kfold_overfitting_indicator') {
		if (score<0.02) return GOOD;
		if (score>0.15) return BAD;
		if (score<0.05) return WARNING;
	}
	if (scoreName==='durbin_watson') {
		// 1 to 2 is the good range
		if (score < 0.75) return BAD; // successive error terms are positively correlated
		if (score > 2.25) return BAD; // successive error terms are negatively correlated
		if (score>=1 && score <= 2) return GOOD;
	}
	return '';
}1<commit_msg>why has it gone slow<commit_after>
function flattenObject(object) {
	let out = {};
	flattenObject2(object, false, out);
	return out;
}

function flattenObject2(object, key, out) {
	if ( ! _.isObject(object)) {
		if ( ! key) key = 'no-key';
		out[key] = object;
		return;
	}
	// Hack for prettier output: avoid extra nesting in key if we can do so without potential clashes
	let prevKey = key+' ';
	if (true || ! key || Object.keys(object).length === 1 || _.isArray(object)) {
		prevKey = '';
	}
	_.forIn(object, function(value, key2) {
		flattenObject2(value, prevKey+key2, out);
	});
}

$(function(){

	$.get('http://localhost:8765/project/assist?action=get')
	.then(function(results){
		console.log("results",results);
		let scores = pivot(results, "'cargo' -> i -> '_source' -> 'results' -> scores", 'scores');
		scores = flattenObject(scores);
		let scoreNames = Object.keys(scores);
		console.log("scoreNames", scoreNames);
		let expIds = pivot(results, "'cargo' -> i -> '_id' -> id", 'id');
		console.log("expIds", expIds);
		// Build a table of results
		const $tbl = $('

');
		{	// header
			let $tr = $('

');
			$tr.append('Experiment Name	'); // exp name
			$tr.append('	'); // exp controls
			for(let i=0; i<scoreNames.length; i++) {
				$tr.append(''+scoreNames[i].replace(/[_\-]/g, ' ')+'	');
			}
			const $thead = $("

");
			$thead.append($tr);
			$tbl.append($thead);
		}
		let experiments = results.cargo;
		const $tbody = $("

");
		for(let ri=0; ri<experiments.length; ri++) {
			const e = experiments[ri];
			const scores = e._source.results;
			let flatScores = flattenObject(scores);
			const spec = e._source.spec;
			let $tr = $('

');
			let ename = e._source.name;
			if ( ! ename && spec) {
				ename = spec.planname;
			}
			if ( ! ename) {
				ename = e._id;
			} //data_source
			let link = 'http://localhost:8766/assist/experiment/'+e._id;
			$tr.append(''+ename.substr(0,60)+'	');
			let $td = $('	');
			let $delBtn = $('<button></button>');
			$delBtn.click(function() {
				let ok = confirm("Trash this experiment?");
				if ( ! ok) return;
				$.get('http://localhost:8765/project/assist?action=delete&id='+escape(e._id))
				.then(function(){
					$tr.fadeOut();
				});
			});
			$td.append($delBtn);
			$tr.append($td);
			for(let si=0; si<scoreNames.length; si++) {
				let score = flatScores[scoreNames[si]];
				console.log('flatScores', flatScores, scoreNames[si]);
				let klass = judge(scoreNames[si], score);
				$tr.append(''+(_.isNumber(score)? printer.prettyNumber(score) : _.isUndefined(score)? -1 : printer.str(score))+'	');
			}
			$tbody.append($tr);
		}
		$tbl.append($tbody);
		$('#results').append($tbl);
		setTimeout(function(){$tbl.DataTable();},50);
	});

});

function judge(scoreName, score) {
	const GOOD = 'success', WARNING='warning', BAD='danger';
	if (scoreName.indexOf('R2') !== -1) {
		if (score>0.8) return GOOD;
		if (score<0.5) return BAD;
		if (score<0.65) return WARNING;
	}
	if (scoreName==='kfold_overfitting_indicator') {
		if (score<0.02) return GOOD;
		if (score>0.15) return BAD;
		if (score<0.05) return WARNING;
	}
	if (scoreName==='durbin_watson') {
		// 1 to 2 is the good range
		if (score < 0.75) return BAD; // successive error terms are positively correlated
		if (score > 2.25) return BAD; // successive error terms are negatively correlated
		if (score>=1 && score <= 2) return GOOD;
	}
	if (scoreName==='stopwatch') {
		// NB: kfold will slow stuff down
		if (score<60) return GOOD;
		if (score>200) return BAD;
		if (score>120) return WARNING;
	}
	if (scoreName.indexOf('uplift ratio mean') != -1) {
		if (score<0 || score >20) return BAD;
		if (score < 0.5 || score>10) return WARNING;
		if (score > 2 && score <10) return GOOD;
	}
	if (scoreName.indexOf('caused by')!=-1) {
		if (score<0 || score >0.8) return BAD;
		if (score<0.1 || score>0.7) return WARNING;
	}
	if (scoreName.indexOf('correlation')!=-1) {
		let as = Math.abs(score);
		if (as < 0.4 || as>1.1) return BAD;
		if (as < 0.6) return WARNING;
	}
	if (scoreName==='NRMSE') {
		if (score<0.1) return GOOD;
		if (score>0.6) return BAD;
		if (score>0.4) return WARNING;
	}
	return '';
}<|endoftext|>


<commit_before>// https://gist.github.com/mojodna/1251812
var async = require("async");
var models = require("../../models");
var log = require('../utils/logger');
var queue = require('./queue');
var i18n = require('../utils/i18n');
var toJson = require('../utils/to_json');

var GenerateNewsFeedFromNotifications = require('../engine/news_feeds/generate_from_notifications.js');
var NotificationNewsFeedWorker = function () {};

NotificationNewsFeedWorker.prototype.process = function (notificationJson, callback) {
  try {
    var user;
    var notification;
    var domain;
    var community;

    async.series([
      function(callback){
        models.AcNotification.find({
          where: { id: notificationJson.id },
          order: [
            [ { model: models.AcActivity, as: 'AcActivities' } ,'updated_at', 'asc' ]
          ],
          include: [
            {
              model: models.User,
              attributes: ['id','notifications_settings','email','name','created_at'],
              required: false
            },
            {
              model: models.AcActivity,
              as: 'AcActivities',
              required: true,
              include: [
                {
                  model: models.User,
                  attributes: ['id','notifications_settings','email','name','created_at'],
                  required: false
                },
                {
                  model: models.Domain,
                  required: false
                },
                {
                  model: models.Community,
                  required: false
                },
                {
                  model: models.Group,
                  required: false
                },
                {
                  model: models.Post,
                  required: false
                },
                {
                  model: models.Point,
                  required: false
                }
              ]
            }
          ]
        }).then(function(results) {
          if (results) {
            notification = results;
            domain = notification.AcActivities[0].Domain;
            community = notification.AcActivities[0].Community;
            callback();
          } else {
            callback('Notification not found');
          }
        }).catch(function(error) {
          callback(error);
        });
      },
      function(callback){
        models.User.find({
          where: { id: notification.user_id },
          attributes: ['id','notifications_settings','email','name','created_at']
        }).then(function(userResults) {
          if (userResults) {
            user = userResults;
            callback();
          } else {
            callback();
          }
        }).catch(function(error) {
          callback(error);
        });
      },
      function(callback){
        if (user) {
          user.setLocale(i18n, domain, community, function () {
            callback();
          });
        } else {
          callback();
        }
      }
    ],
    function(error) {
      if (error) {
        log.error("NotificationNewsFeedWorker Error", {err: error});
        callback();
      } else {
        log.info('Processing NotificationNewsFeedWorker Started', { type: notification.type, user: user ? user.simple() : null });
        switch(notification.type) {
          case "notification.post.new":
          case "notification.post.endorsement":
          case "notification.point.new":
          case "notification.point.quality":
            GenerateNewsFeedFromNotifications(notification, user, function () {
              log.info('Processing GenerateNewsFeedFromNotifications Completed', { type: notification.type, user: user.simple() });
              callback();
            });
            break;
          default:
            callback();
        }
      }
    });
  } catch (error) {
    log.error("Processing NotificationNewsFeedWorker Error", {err: error});
    callback();
  }
};

module.exports = new NotificationNewsFeedWorker();
<commit_msg>Fixes for callback name<commit_after>// https://gist.github.com/mojodna/1251812
var async = require("async");
var models = require("../../models");
var log = require('../utils/logger');
var queue = require('./queue');
var i18n = require('../utils/i18n');
var toJson = require('../utils/to_json');

var GenerateNewsFeedFromNotifications = require('../engine/news_feeds/generate_from_notifications.js');
var NotificationNewsFeedWorker = function () {};

NotificationNewsFeedWorker.prototype.process = function (notificationJson, callback) {
  try {
    var user;
    var notification;
    var domain;
    var community;

    async.series([
      function(seriesCallback){
        models.AcNotification.find({
          where: { id: notificationJson.id },
          order: [
            [ { model: models.AcActivity, as: 'AcActivities' } ,'updated_at', 'asc' ]
          ],
          include: [
            {
              model: models.User,
              attributes: ['id','notifications_settings','email','name','created_at'],
              required: false
            },
            {
              model: models.AcActivity,
              as: 'AcActivities',
              required: true,
              include: [
                {
                  model: models.User,
                  attributes: ['id','notifications_settings','email','name','created_at'],
                  required: false
                },
                {
                  model: models.Domain,
                  required: false
                },
                {
                  model: models.Community,
                  required: false
                },
                {
                  model: models.Group,
                  required: false
                },
                {
                  model: models.Post,
                  required: false
                },
                {
                  model: models.Point,
                  required: false
                }
              ]
            }
          ]
        }).then(function(results) {
          if (results) {
            notification = results;
            domain = notification.AcActivities[0].Domain;
            community = notification.AcActivities[0].Community;
            seriesCallback();
          } else {
            seriesCallback('Notification not found');
          }
        }).catch(function(error) {
          seriesCallback(error);
        });
      },
      function(seriesCallback){
        models.User.find({
          where: { id: notification.user_id },
          attributes: ['id','notifications_settings','email','name','created_at']
        }).then(function(userResults) {
          if (userResults) {
            user = userResults;
            seriesCallback();
          } else {
            seriesCallback();
          }
        }).catch(function(error) {
          seriesCallback(error);
        });
      },
      function(seriesCallback){
        if (user) {
          user.setLocale(i18n, domain, community, function () {
            seriesCallback();
          });
        } else {
          seriesCallback();
        }
      }
    ],
    function(error) {
      if (error) {
        log.error("NotificationNewsFeedWorker Error", {err: error});
        callback();
      } else {
        log.info('Processing NotificationNewsFeedWorker Started', { type: notification.type, user: user ? user.simple() : null });
        switch(notification.type) {
          case "notification.post.new":
          case "notification.post.endorsement":
          case "notification.point.new":
          case "notification.point.quality":
            GenerateNewsFeedFromNotifications(notification, user, function () {
              log.info('Processing GenerateNewsFeedFromNotifications Completed', { type: notification.type, user: user.simple() });
              callback();
            });
            break;
          default:
            callback();
        }
      }
    });
  } catch (error) {
    log.error("Processing NotificationNewsFeedWorker Error", {err: error});
    callback();
  }
};

module.exports = new NotificationNewsFeedWorker();
<|endoftext|>


<commit_before>/*
  Merge sort algorithm sorts an array in O(n*log(n)) time.

  @author Evgeniy Kuznetsov
  @date 30.1.2015 1:47
 */

// @param {Array.<Integer>} a
// @return {Array.<Integer>} Sorted version of a given array
function mergeSort(a){

  // Get split point for a given length of an array
  // @param {Integer} n Length of an array
  // @return {Integer}
  var getSplitPoint = function(n){
    return Math.floor(n/2);
  };

  // Merge two sorted arrays into one
  // @param {Array.<Integer>} a
  // @return {Array.<Integer>}
  var merge = function(f,s){
    var i=0,
        j=0,
        tlength = f.length + s.length,
        result = [];

    var chooseF = function(){
      result.push(f[i]);
      i++;
    };

    var chooseS = function(){
      result.push(s[j]);
      j++;
    }

    for(var k=0;k<tlength;k++){

      if(f[i] && s[j]){
        f[i]<s[j] ? chooseF() : chooseS();
      }else if(f[i]){
        chooseF();
      }else{
        chooseS();
      }

    }

    return result;
  }

  // Main recursion loop
  // @param {Array.<Integer>} a
  // @return {Integer}
  var sort = function(a){
    if(a.length<2){
      return a;

    }else{

      var splitPoint = getSplitPoint(a.length);
      var fpart = sort(a.slice(0, splitPoint));
      var spart = sort(a.slice(splitPoint, a.length));

      return merge(fpart, spart);
    }
  }

  return sort(a);
}

var test = [];

test = [];
console.log("Case 1:", mergeSort(test).toString()==[].toString());

test = [1,2];
console.log("Case 2:", mergeSort(test).toString()==[1,2].toString(), mergeSort(test));

test = [2,1];
console.log("Case 3:", mergeSort(test).toString()==[1,2].toString(), mergeSort(test));

test = [1,2,3];
console.log("Case 4:", mergeSort(test).toString()==[1,2,3].toString(), mergeSort(test));

test = [3,2,1];
console.log("Case 5:", mergeSort(test).toString()==[1,2,3].toString(), mergeSort(test));

test = [3,1,2];
console.log("Case 6:", mergeSort(test).toString()==[1,2,3].toString(), mergeSort(test));<commit_msg>isNaN check<commit_after>/*
  Merge sort algorithm sorts an array for O(n*log(n)) time.

  @author Evgeniy Kuznetsov
  @date 30.1.2015 1:47
 */

// @param {Array.<Integer>} a
// @return {Array.<Integer>} Sorted version of a given array
function mergeSort(a){

  // Get split point for a given length of an array
  // @param {Integer} n Length of an array
  // @return {Integer}
  var getSplitPoint = function(n){
    return Math.floor(n/2);
  };

  // Merge two sorted arrays into one
  // @param {Array.<Integer>} a
  // @return {Array.<Integer>}
  var merge = function(f,s){
    var i=0,
        j=0,
        tlength = f.length + s.length,
        result = [];

    var chooseF = function(){
      result.push(f[i]);
      i++;
    };

    var chooseS = function(){
      result.push(s[j]);
      j++;
    }

    for(var k=0;k<tlength;k++){

      if(!isNaN(f[i]) && !isNaN(s[j])){
        f[i]<s[j] ? chooseF() : chooseS();
      }else if(f[i]){
        chooseF();
      }else{
        chooseS();
      }

    }

    return result;
  }

  // Main recursion loop
  // @param {Array.<Integer>} a
  // @return {Integer}
  var sort = function(a){
    if(a.length<2){
      return a;

    }else{

      var splitPoint = getSplitPoint(a.length);
      var fpart = sort(a.slice(0, splitPoint));
      var spart = sort(a.slice(splitPoint, a.length));

      return merge(fpart, spart);
    }
  }

  return sort(a);
}

var test = [];

test = [];
console.log("Case 1:", mergeSort(test).toString()==[].toString());

test = [1,2];
console.log("Case 2:", mergeSort(test).toString()==[1,2].toString(), mergeSort(test));

test = [2,1];
console.log("Case 3:", mergeSort(test).toString()==[1,2].toString(), mergeSort(test));

test = [1,2,3];
console.log("Case 4:", mergeSort(test).toString()==[1,2,3].toString(), mergeSort(test));

test = [3,2,1];
console.log("Case 5:", mergeSort(test).toString()==[1,2,3].toString(), mergeSort(test));

test = [3,1,2];
console.log("Case 6:", mergeSort(test).toString()==[1,2,3].toString(), mergeSort(test));

test = [5,8,9,0,-1,3,2,4];
console.log("Case 7:", mergeSort(test).toString()==[-1,0,2,3,4,5,8,9].toString(), mergeSort(test));<|endoftext|>


<commit_before>/*
---
name: ART.Popup
description: Base class for windows and other popups.
requires: [ART.Widget, Core/Fx.Tween, More/IframeShim, More/Element.Position, Stacker, Touch/Touch, More/Mask, More/Element.Delegation, ART.Keyboard]
provides: [ART.Popup, ART.WindowManager]
...
*/

ART.WindowManager = new Class({

	Extends: Stacker,

	initialize: function(widget, options){
		this.parent(options);
		this.keyboard = new Keyboard({
			active: true,
			manager: widget ? widget.keyboard : null
		});
		this.keyboard.widget = widget || 'window manager';
	},

	register: function(instance){
		this.parent.apply(this, arguments);
		this.keyboard.manage(instance.keyboard);
		self = this;
		instance._stackerEvents = events = {
			hide: function(){
				var layer = self.getLayerForInstance(instance);
				self.cycle('back', (layer && layer.name) || 'default');
			}
		};
		instance.addEvents(instance._stackerEvents);

	},

	unregister: function(instance) {
		var cycle = (this.enabled == instance);
		var layer = this.getLayerForInstance(instance);
		this.parent.apply(this, arguments);
		this.keyboard.drop(instance.keyboard);
		this.enableTop(layer);
		if (instance._stackerEvents) instance.removeEvents(instance._stackerEvents);
	}

});

ART.Popup = new Class({

	Extends: ART.Widget,

	name: 'popup',

	options: {
		/*
		inject: {
			target: document.body,
			where: 'bottom'
		},
		content: null,
		timeout: 0,
		width: null,
		height: null,
		iframeShimSelector: '',
		closeOnClickOut: false,
		closeOnEsc: false,
		windowManager: instanceOfStacker,
		destroyOnClose: false,
		windowManagerLayer: 'default',
		keyboardOptions: {},
		//events:
		'drag:start': $empty,
		'drag:move': $empty(x,y),
		'drag:end': $empty,
		'shade': $empty
		'unshade': $empty,

		//these are the defaults for Element.position anyway
		************************************************
		edge: false, //see Element.position
		position: 'center', //center, corner == upperLeft, upperRight, bottomLeft, bottomRight
		offset: {x:0,y:0},
		relativeTo: document.body,
		allowNegative: false,
		posMin: {x: , y:}, //passed as 'minimum' to element.position
		posMax: {x: , y: },//passed as 'maximum' to element.position
		************************************************

		mask: false,
		maskTarget: document.body,
		*/
		maskOptions: {},
		hideOnMaskClick: true,
		closeClass: 'closeWin',
		close: true,
		draggable: false,
		dragHandle: false,
		showNow: true,
		useIframeShim: true,
		cascaded: false,
		constrainToContainer: false
	},

	initialize: function(options) {
		//by default, inject instances into the document.body
		if (!this.options.inject) {
			this.options.inject = {
				target: document.body,
				where: 'bottom'
			};
		}
		options = options || {};
		//delete any Class instance references from the options to avoid recurssion errors
		this.windowManager = options.windowManager || this.options.windowManager || ART.Popup.DefaultManager;
		delete this.options.windowManager;
		delete options.windowManager;

		//the window manager enables the windows; so we must start with disabled = true
		this.disabled = true;

		this.parent(options);

		//store a reference to this instance on the element
		this.element.store('Popup', this);

		//configure this instance's element
		this._build();

		new ART.Keyboard(this, this.options.keyboardOptions);

		//register this instance
		this.windowManager.register(this, this.options.windowManagerLayer);

		if (this.options.draggable) this.makeDraggable();

		if (this.options.timeout) {
			//hide this instance after the specified timeout
			this.addEvent('show', function(){
				this.hide.delay(this.options.timeout, this);
			}.bind(this));
		}

		this.attach();

		if (this.options.destroyOnClose) this.addEvent('hide', this.destroy.bind(this));
		this.element.setStyle('display', 'none');

		if (this.options.useIframeShim) this.hideIframeShim();
		this.setState('hidden', true);

		if (this.options.content) this.setContent(this.options.content);

		if (this.options.showNow) this.show();
		//add event to hide the instance whenever an element with the closeClass is clicked

		this.element.addEvent('click:relay(.' + this.options.closeClass + ')', function(){
			this.hide();
		}.bind(this));

	},

	attach: function(attach){
		if (!this.options.closeOnClickOut && !this.options.closeOnEsc) return;
		//add events for closing on escape and closing on clicking outside of the window
		var method = $pick(attach, true) ? 'addEvents' : 'removeEvents';
		var events = {};
		this._boundEsc = this._boundEsc || this.esc.bind(this);
		if (this.options.closeOnClickOut) events.click = this._boundEsc;
		if (this.options.closeOnEsc) events.keyup = this._boundEsc;
		document[method](events);
		return this;
	},

	detach: function(){
		return this.attach(false);
	},

	//check if the user hit the escape key and, if so, close the window
	esc: function(e) {
		if ((e.type == "click" && this.element != e.target && !this.element.hasChild(e.target)) || e.key == "esc") this.hide();
	},

	//set up the element
	_build: function(){
		//hide it and inject it into the document.
		this.element.setStyles({
			display: 'none',
			position: 'absolute'
		});
		this.inject(this.options.inject.target, this.options.inject.target, this.options.inject.where);
	},

	//hides the instance
	hide: function(){
		if (!this.getState('hidden')){
			this.element.setStyle('display', 'none');
			if (this.options.useIframeShim) this.hideIframeShim();
			this.fireEvent('hide');
			this.windowManager.enableTop(this.options.windowManagerLayer);
			this.deferDraw();
		}
		return this;
	},

	//masks a target beneath the window (such as the document body)
	maskTarget: function(){
		var target = document.id(this.options.maskTarget);
		if (!target && this.options.maskOptions.inject && this.options.maskOptions.inject.target)
			target = document.id(this.options.maskOptions.inject.target) || document.id(document.body);
		else target = document.id(document.body);

		var mask = target.retrieve('Popup:mask');
		if (!mask) {
			//compute the zindex of the mask to be just above the target
			//unless it's the document body, in which case put it just below this instance
			var zIndex = this.options.maskOptions.zIndex;
			if (zIndex == null) {
				if (target != document.body && target.getStyle('zIndex') != "auto") zIndex = document.id(target).getStyle('zIndex').toInt() + 1;
				if (target == document.body || zIndex > document.id(this).getStyle('zIndex').toInt() || zIndex == null)
					zIndex = document.id(this).getStyle('zIndex').toInt() - 1;
				if (zIndex < 0 || isNaN(NaN)) zIndex = 0;
			}
			if (zIndex >= document.id(this).getStyle('zIndex').toInt()) document.id(this).setStyle('z-index', zIndex + 1);
			mask = new Mask(target, $merge({
					style: {
						zIndex: zIndex
					},
					destroyOnHide: true,
					hideOnClick: this.options.hideOnMaskClick
				}, this.options.maskOptions)
			).addEvent('hide', function(){
				if (!this.getState('hidden')) this.hide();
			}.bind(this));
			this.addEvent('hide', function(){
				if (!mask.hidden) mask.hide();
			});
			target.store('Popup:mask', mask);
		}
		mask.show();
	},

	//show this instance
	show: function(){
		if (this.getState('hidden')){
			this.setState('hidden', false);
			this.windowManager.enable(this);
			this.fireEvent('display');
			if (!this.positioned) {
				this.position();
			}
			this.showIframeShim();
			if (this.options.mask) this.maskTarget();
		}
		return this;
	},

	//bring this instance to the front
	bringToFront: function(){
		this.windowManager.bringToFront(this);
		return this;
	},

	//positions this instance to the position specified in the options
	//pass in new options (same as those passed in on init) to override
	position: function(options, callback){
		this.positioned = true;
		this.setOptions(options);
		//if cascading is enabled and the window manager doesn't want to do this positioning for us
		if (true && this.options.cascaded && !this.windowManager.positionNew(this, this.options)) {
			//if top/left options defined in options, put the window there
			if ($defined(this.options.top) && $defined(this.options.left)) {
				this.element.setStyles({
					top: this.options.top,
					left: this.options.left
				});
			} else {
				if (!this._drawn) {
					this.position.delay(1, this, arguments);
					return this;
				}
				//else position it using the other options specified
				this.element.position({
					allowNegative: $pick(this.options.allowNegative, this.options.relativeTo != document.body),
					relativeTo: document.id(this.options.relativeTo) || document.id(document.body),
					position: this.options.position,
					offset: this.options.offset,
					edge: this.options.edge,
					minimum: this.options.posMin,
					maximum: this.options.posMax
				});
			}
		}
		if (callback) callback();
		if (this.shim) this.shim.position();
		return this;
	},

	draw: function(){
		this._drawn = true;
		this.element.setStyle('display', this.getState('hidden') ? 'none' : 'block');
		return this.parent.apply(this, arguments);
	},

	//pins an instance to a specific fixed location using Element.Pin
	pin: function(pin) {
		if (this.element.pin) {
			this.pinned = $pick(pin, true);
			this.element.pin(pin);
		}
		return this;
	},

	unpin: function(){
		return this.pin(false);
	},

	togglepin: function(){
		return this.pin(!this.pinned);
	},

	//makes the instance draggable using MooTools Touch
	makeDraggable: function(handle){
		handle = handle || this.options.dragHandle || this.element;
		this.touchDrag = new Touch(handle);
		handle.setStyle('cursor', 'move');
		var size, containerSize;
		this.touchDrag.addEvent('start', function(){
			this.fireEvent('drag:start');
			this.startTop = this.element.offsetTop;
			this.startLeft = this.element.offsetLeft;
			if (this.options.constrainToContainer) {
				size = this.element.getSize();
				var container = document.id(this.options.constrainToContainer) || this.element.getParent();
				containerSize = container.getSize();
			}
		}.bind(this));
		this.touchDrag.addEvent('move', function(dx, dy){
			this._displayForDrag(true);
			var top = this.startTop + dy;
			var left = this.startLeft + dx;
			if (top < 0) top = 0;
			if (left < 0) left = 0;
			if (this.options.constrainToContainer) {
				if (top + size.y > containerSize.y) top = containerSize.y - size.y;
				if (left + size.x > containerSize.x) left = containerSize.x - size.x;
			}
			this.element.setStyles({
				'top': top,
				'left': left
			});
			this.fireEvent('drag:move', [top, left]);
		}.bind(this));
		var end = function(){
			this._displayForDrag(false);
			this.fireEvent('drag:end');
		}.bind(this);
		this.touchDrag.addEvent('end', end);
		this.touchDrag.addEvent('cancel', end);
	},

	//add pseudo for dragging and fire the shade event when dragging starts/stops
	_displayForDrag: function(dragging, render) {
		if (this.getState('dragging') == dragging) return;
		render = $pick(render, true);
		this.setState('dragging', dragging);
		if (render) this.deferDraw();
		this.fireEvent(dragging ? 'shade' : 'unshade');
	},

	disableDrag: function(){
		this.touchDrag.detach();
		return this;
	},

	enableDrag: function(){
		this.touchDrag.attach();
		return this;
	},

	//set the content of this window
	//argument can be an element, an array of elements, or a string of html
	setContent: function(){
		if (document.id(content) || $type(content) == "array") this.element.adopt(content);
		else if ($type(content) == "string") this.element.set('html', content);
		return this;
	},

	//resize this instance to a given size
	resize: function(width, height){
		if (this.isDestroyed()) return;

		this.draw({'height': height, 'width': width});
		if (this.shim) this.shim.position();
		return this;
	},

	enable: function(callParent){
		if (callParent) this.parent();
		else this.windowManager.enable(this);
		return this;
	},

	destroy: function(){
		this.windowManager.unregister(this);
		if (this.options.useIframeShim && this.shim) this.shim.destroy();
		this.eject();
		this.element.destroy();
		this.fireEvent('destroy');
		return this;
	},

	//creates an IframeShim for this instance if one is required.
	makeIframeShim: function(target){
		if (!this.shim){
			var el = this.element || target;
			if(this.options.iframeShimSelector) el = this.element.getElement(this.options.iframeShimSelector);
			this.shim = new IframeShim(el, {
				display: false,
				name: this.prefix + '_Shim'
			});
		}
	},

	showIframeShim: function(){
		if (this.options.useIframeShim) {
			this.makeIframeShim();
			this.shim.show();
		}
	},

	hideIframeShim: function(){
		if (this.shim) this.shim.hide();
	},

	//moves the instance to be on the screen
	getOnScreen: function(){
		var pos = this.element.getPosition();
		var size = this.element.getSize();
		var bottom = pos.y + size.y;
		var right = pos.x + size.x;
		var containerSize = document.id(window.getDocument()).getSize();
		if (bottom > containerSize.y) this.element.setStyle('top', containerSize.y - size.y);
		if (right > containerSize.x) this.element.setStyle('left', containerSize.x - size.x);
		return true;
	}

});

ART.Popup.DefaultManager = new ART.WindowManager();
<commit_msg>allowing an offset to be specified in art.popup's getOnScreen method<commit_after>/*
---
name: ART.Popup
description: Base class for windows and other popups.
requires: [ART.Widget, Core/Fx.Tween, More/IframeShim, More/Element.Position, Stacker, Touch/Touch, More/Mask, More/Element.Delegation, ART.Keyboard]
provides: [ART.Popup, ART.WindowManager]
...
*/

ART.WindowManager = new Class({

	Extends: Stacker,

	initialize: function(widget, options){
		this.parent(options);
		this.keyboard = new Keyboard({
			active: true,
			manager: widget ? widget.keyboard : null
		});
		this.keyboard.widget = widget || 'window manager';
	},

	register: function(instance){
		this.parent.apply(this, arguments);
		this.keyboard.manage(instance.keyboard);
		self = this;
		instance._stackerEvents = events = {
			hide: function(){
				var layer = self.getLayerForInstance(instance);
				self.cycle('back', (layer && layer.name) || 'default');
			}
		};
		instance.addEvents(instance._stackerEvents);

	},

	unregister: function(instance) {
		var cycle = (this.enabled == instance);
		var layer = this.getLayerForInstance(instance);
		this.parent.apply(this, arguments);
		this.keyboard.drop(instance.keyboard);
		this.enableTop(layer);
		if (instance._stackerEvents) instance.removeEvents(instance._stackerEvents);
	}

});

ART.Popup = new Class({

	Extends: ART.Widget,

	name: 'popup',

	options: {
		/*
		inject: {
			target: document.body,
			where: 'bottom'
		},
		content: null,
		timeout: 0,
		width: null,
		height: null,
		iframeShimSelector: '',
		closeOnClickOut: false,
		closeOnEsc: false,
		windowManager: instanceOfStacker,
		destroyOnClose: false,
		windowManagerLayer: 'default',
		keyboardOptions: {},
		//events:
		'drag:start': $empty,
		'drag:move': $empty(x,y),
		'drag:end': $empty,
		'shade': $empty
		'unshade': $empty,

		//these are the defaults for Element.position anyway
		************************************************
		edge: false, //see Element.position
		position: 'center', //center, corner == upperLeft, upperRight, bottomLeft, bottomRight
		offset: {x:0,y:0},
		relativeTo: document.body,
		allowNegative: false,
		posMin: {x: , y:}, //passed as 'minimum' to element.position
		posMax: {x: , y: },//passed as 'maximum' to element.position
		************************************************

		mask: false,
		maskTarget: document.body,
		*/
		maskOptions: {},
		hideOnMaskClick: true,
		closeClass: 'closeWin',
		close: true,
		draggable: false,
		dragHandle: false,
		showNow: true,
		useIframeShim: true,
		cascaded: false,
		constrainToContainer: false
	},

	initialize: function(options) {
		//by default, inject instances into the document.body
		if (!this.options.inject) {
			this.options.inject = {
				target: document.body,
				where: 'bottom'
			};
		}
		options = options || {};
		//delete any Class instance references from the options to avoid recurssion errors
		this.windowManager = options.windowManager || this.options.windowManager || ART.Popup.DefaultManager;
		delete this.options.windowManager;
		delete options.windowManager;

		//the window manager enables the windows; so we must start with disabled = true
		this.disabled = true;

		this.parent(options);

		//store a reference to this instance on the element
		this.element.store('Popup', this);

		//configure this instance's element
		this._build();

		new ART.Keyboard(this, this.options.keyboardOptions);

		//register this instance
		this.windowManager.register(this, this.options.windowManagerLayer);

		if (this.options.draggable) this.makeDraggable();

		if (this.options.timeout) {
			//hide this instance after the specified timeout
			this.addEvent('show', function(){
				this.hide.delay(this.options.timeout, this);
			}.bind(this));
		}

		this.attach();

		if (this.options.destroyOnClose) this.addEvent('hide', this.destroy.bind(this));
		this.element.setStyle('display', 'none');

		if (this.options.useIframeShim) this.hideIframeShim();
		this.setState('hidden', true);

		if (this.options.content) this.setContent(this.options.content);

		if (this.options.showNow) this.show();
		//add event to hide the instance whenever an element with the closeClass is clicked

		this.element.addEvent('click:relay(.' + this.options.closeClass + ')', function(){
			this.hide();
		}.bind(this));

	},

	attach: function(attach){
		if (!this.options.closeOnClickOut && !this.options.closeOnEsc) return;
		//add events for closing on escape and closing on clicking outside of the window
		var method = $pick(attach, true) ? 'addEvents' : 'removeEvents';
		var events = {};
		this._boundEsc = this._boundEsc || this.esc.bind(this);
		if (this.options.closeOnClickOut) events.click = this._boundEsc;
		if (this.options.closeOnEsc) events.keyup = this._boundEsc;
		document[method](events);
		return this;
	},

	detach: function(){
		return this.attach(false);
	},

	//check if the user hit the escape key and, if so, close the window
	esc: function(e) {
		if ((e.type == "click" && this.element != e.target && !this.element.hasChild(e.target)) || e.key == "esc") this.hide();
	},

	//set up the element
	_build: function(){
		//hide it and inject it into the document.
		this.element.setStyles({
			display: 'none',
			position: 'absolute'
		});
		this.inject(this.options.inject.target, this.options.inject.target, this.options.inject.where);
	},

	//hides the instance
	hide: function(){
		if (!this.getState('hidden')){
			this.element.setStyle('display', 'none');
			if (this.options.useIframeShim) this.hideIframeShim();
			this.fireEvent('hide');
			this.windowManager.enableTop(this.options.windowManagerLayer);
			this.deferDraw();
			this.setState('hidden', true);
		}
		return this;
	},

	//masks a target beneath the window (such as the document body)
	maskTarget: function(){
		var target = document.id(this.options.maskTarget);
		if (!target && this.options.maskOptions.inject && this.options.maskOptions.inject.target)
			target = document.id(this.options.maskOptions.inject.target) || document.id(document.body);
		else target = document.id(document.body);

		var mask = target.retrieve('Popup:mask');
		if (!mask) {
			//compute the zindex of the mask to be just above the target
			//unless it's the document body, in which case put it just below this instance
			var zIndex = this.options.maskOptions.zIndex;
			if (zIndex == null) {
				if (target != document.body && target.getStyle('zIndex') != "auto") zIndex = document.id(target).getStyle('zIndex').toInt() + 1;
				if (target == document.body || zIndex > document.id(this).getStyle('zIndex').toInt() || zIndex == null)
					zIndex = document.id(this).getStyle('zIndex').toInt() - 1;
				if (zIndex < 0 || isNaN(NaN)) zIndex = 0;
			}
			if (zIndex >= document.id(this).getStyle('zIndex').toInt()) document.id(this).setStyle('z-index', zIndex + 1);
			mask = new Mask(target, $merge({
					style: {
						zIndex: zIndex
					},
					destroyOnHide: true,
					hideOnClick: this.options.hideOnMaskClick
				}, this.options.maskOptions)
			).addEvent('hide', function(){
				if (!this.getState('hidden')) this.hide();
			}.bind(this));
			this.addEvent('hide', function(){
				if (!mask.hidden) mask.hide();
			});
			target.store('Popup:mask', mask);
		}
		mask.show();
	},

	//show this instance
	show: function(){
		if (this.getState('hidden')){
			this.setState('hidden', false);
			this.windowManager.enable(this);
			this.fireEvent('display');
			if (!this.positioned) {
				this.position();
			}
			this.showIframeShim();
			if (this.options.mask) this.maskTarget();
		}
		return this;
	},

	//bring this instance to the front
	bringToFront: function(){
		this.windowManager.bringToFront(this);
		return this;
	},

	//positions this instance to the position specified in the options
	//pass in new options (same as those passed in on init) to override
	position: function(options, callback){
		this.positioned = true;
		this.setOptions(options);
		//if cascading is enabled and the window manager doesn't want to do this positioning for us
		if (true && this.options.cascaded && !this.windowManager.positionNew(this, this.options)) {
			//if top/left options defined in options, put the window there
			if ($defined(this.options.top) && $defined(this.options.left)) {
				this.element.setStyles({
					top: this.options.top,
					left: this.options.left
				});
			} else {
				if (!this._drawn) {
					this.position.delay(1, this, arguments);
					return this;
				}
				//else position it using the other options specified
				this.element.position({
					allowNegative: $pick(this.options.allowNegative, this.options.relativeTo != document.body),
					relativeTo: document.id(this.options.relativeTo) || document.id(document.body),
					position: this.options.position,
					offset: this.options.offset,
					edge: this.options.edge,
					minimum: this.options.posMin,
					maximum: this.options.posMax
				});
			}
		}
		if (callback) callback();
		if (this.shim) this.shim.position();
		return this;
	},

	draw: function(){
		this._drawn = true;
		this.element.setStyle('display', this.getState('hidden') ? 'none' : 'block');
		return this.parent.apply(this, arguments);
	},

	//pins an instance to a specific fixed location using Element.Pin
	pin: function(pin) {
		if (this.element.pin) {
			this.pinned = $pick(pin, true);
			this.element.pin(pin);
		}
		return this;
	},

	unpin: function(){
		return this.pin(false);
	},

	togglepin: function(){
		return this.pin(!this.pinned);
	},

	//makes the instance draggable using MooTools Touch
	makeDraggable: function(handle){
		handle = handle || this.options.dragHandle || this.element;
		this.touchDrag = new Touch(handle);
		handle.setStyle('cursor', 'move');
		var size, containerSize;
		this.touchDrag.addEvent('start', function(){
			this.fireEvent('drag:start');
			this.startTop = this.element.offsetTop;
			this.startLeft = this.element.offsetLeft;
			if (this.options.constrainToContainer) {
				size = this.element.getSize();
				var container = document.id(this.options.constrainToContainer) || this.element.getParent();
				containerSize = container.getSize();
			}
		}.bind(this));
		this.touchDrag.addEvent('move', function(dx, dy){
			this._displayForDrag(true);
			var top = this.startTop + dy;
			var left = this.startLeft + dx;
			if (top < 0) top = 0;
			if (left < 0) left = 0;
			if (this.options.constrainToContainer) {
				if (top + size.y > containerSize.y) top = containerSize.y - size.y;
				if (left + size.x > containerSize.x) left = containerSize.x - size.x;
			}
			this.element.setStyles({
				'top': top,
				'left': left
			});
			this.fireEvent('drag:move', [top, left]);
		}.bind(this));
		var end = function(){
			this._displayForDrag(false);
			this.fireEvent('drag:end');
		}.bind(this);
		this.touchDrag.addEvent('end', end);
		this.touchDrag.addEvent('cancel', end);
	},

	//add pseudo for dragging and fire the shade event when dragging starts/stops
	_displayForDrag: function(dragging, render) {
		if (this.getState('dragging') == dragging) return;
		render = $pick(render, true);
		this.setState('dragging', dragging);
		if (render) this.deferDraw();
		this.fireEvent(dragging ? 'shade' : 'unshade');
	},

	disableDrag: function(){
		this.touchDrag.detach();
		return this;
	},

	enableDrag: function(){
		this.touchDrag.attach();
		return this;
	},

	//set the content of this window
	//argument can be an element, an array of elements, or a string of html
	setContent: function(){
		if (document.id(content) || $type(content) == "array") this.element.adopt(content);
		else if ($type(content) == "string") this.element.set('html', content);
		return this;
	},

	//resize this instance to a given size
	resize: function(width, height){
		if (this.isDestroyed()) return;

		this.draw({'height': height, 'width': width});
		if (this.shim) this.shim.position();
		return this;
	},

	enable: function(callParent){
		if (callParent) this.parent();
		else this.windowManager.enable(this);
		return this;
	},

	destroy: function(){
		this.windowManager.unregister(this);
		if (this.options.useIframeShim && this.shim) this.shim.destroy();
		this.eject();
		this.element.destroy();
		this.fireEvent('destroy');
		return this;
	},

	//creates an IframeShim for this instance if one is required.
	makeIframeShim: function(target){
		if (!this.shim){
			var el = this.element || target;
			if(this.options.iframeShimSelector) el = this.element.getElement(this.options.iframeShimSelector);
			this.shim = new IframeShim(el, {
				display: false,
				name: this.prefix + '_Shim'
			});
		}
	},

	showIframeShim: function(){
		if (this.options.useIframeShim) {
			this.makeIframeShim();
			this.shim.show();
		}
	},

	hideIframeShim: function(){
		if (this.shim) this.shim.hide();
	},

	//moves the instance to be on the screen
	getOnScreen: function(offset){
		if (!offset) offset = {};
		var pos = this.element.getPosition();
		var size = this.element.getSize();
		var bottom = pos.y + size.y;
		var right = pos.x + size.x;
		var containerSize = document.id(window.getDocument()).getSize();
		if (bottom > containerSize.y) this.element.setStyle('top', containerSize.y - size.y + (offset.y || 0));
		if (right > containerSize.x) this.element.setStyle('left', containerSize.x - size.x + (offset.x || 0));
		return true;
	}

});

ART.Popup.DefaultManager = new ART.WindowManager();
<|endoftext|>


<commit_before>module.exports = function(app) {
  app.controller('ChatController', [
    '$scope',
    '$q',
    '$http',
    '$ionicPlatform',
    '$ionicScrollDelegate',
    // '$ionicView',
    '$cordovaHealthKit',
    ChatController
  ]);
}

function ChatController(
    $scope,
    $q,
    $http,
    $ionicPlatform,
    $ionicScrollDelegate,
    // $ionicView,
    $cordovaHealthKit
  ) {

  var vm = this;

  vm.currentInputMessage = "";
  vm.currentInputID = "";

  vm.chatMessages = [];

  // TODO: Change this to correspond to what the server returns.
  vm.inputOptions = [];

  vm.doRefresh = doRefresh;
  vm.sendClientContext = sendClientContext;

  vm.enterClientInput = enterClientInput;
  vm.requestNextComm = requestNextComm;

  vm.handleSuccessComm = handleSuccessComm;
  vm.handleErrorComm = handleErrorComm;

  vm.getSteps = getSteps;

  // TODO: Test this when Healthkit entitlement becomes possible.
  $ionicPlatform.ready(function() {
    console.log("Platform is ready here.");
    $cordovaHealthKit.isAvailable().then(
      function(yes) {

        var readPermissions = [
          'HKQuantityTypeIdentifierDistanceWalkingRunning',
          'HKQuantityTypeIdentifierDistanceCycling',
          'HKQuantityTypeIdentifierStepCount',
        ];

        var writePermissions = [];
        console.log(readPermissions);

        $cordovaHealthKit.requestAuthorization(
          readPermissions,
          writePermissions
        ).then(function(success){
          console.log("Requested permissions to read and write health information.");
         });
      },
      function(no) {});
  });

  // FIXME: Can this be 'vm'. If so, or if not, why?
  $scope.$on('$ionicView.enter', function() {
    console.log("I have entered the app.");
    // TODO: This is where you can send the context of the walking steps.
  });

  function doRefresh() {
    console.log("Refreshing the conversation!");
    // vm.sendClientContext();
    vm.chatMessages = [];
    vm.requestNextComm("root");
    $scope.$broadcast('scroll.refreshComplete');
  }

  function getSteps(startDate, endDate) {
    console.log("Getting step count.");

    return $q(function (resolve, reject) {
      window.plugins.healthkit.sumQuantityType({
        'startDate': startDate,
        'endDate': endDate,
        'distanceUnit': 'mileUnit',
        'sampleType': 'HKQuantityTypeIdentifierStepCount'
      }, function(steps) {
        console.log("HealthKit Step Count Success: " + steps + " steps.");
        resolve(steps);
      }, function () {
        console.log("HealthKit Step Count Query unsuccessful.");
        reject();
      });
    });
  }

  function sendClientContext() {
    console.log("I am now going to send client context.");

    var m = moment().startOf('day');
    var startDate = m.toDate();
    var endDate = moment(m).add(1, 'd').toDate();

    console.log(startDate);
    console.log(endDate);

    vm.getSteps(startDate, endDate)
      .then(function(steps) {
        // TODO: Change this to the correct route.
        var route = CURRENT_HOST + "/api/v1/documents/1";
        var clientContext = {
          // TODO: Change user_id.
          userID: 1,
          steps: steps
        }

        $http.patch(route, clientContext).
          success(function(data, status, headers, config) {
            console.log(data.message);

            // TODO: Populate messages with the next message.
            // Call method to populate messages and commands.

          }).
          error(function(data, status, headers, config) {
            alert("An error happened sending the message.");
          });
      }, function() {
        console.log("Error in getSteps promise.");
      });
  }

  function enterClientInput($index) {
    console.log("Entering the client input.");
    console.log("Input option index: " + $index);
    console.log("Input option: " + vm.inputOptions[$index]);

    vm.currentInputMessage = vm.inputOptions[$index].inputMessage;
    vm.currentInputID = vm.inputOptions[$index].inputCommID;
    console.log(vm.currentInputMessage);

    // Now push client message into the history.
    // TODO: This is not DRY. Package and make DRY.
    vm.chatMessages.push({
      speaker: "client",
      message: vm.currentInputMessage,
    });

    // Clear input options.
    vm.currentInputMessage = "";
    vm.inputOptions = [];
    console.log("Input options are cleared?");
    console.log(vm.inputOptions);

    vm.requestNextComm(vm.currentInputID);
  }

  function requestNextComm(nextCommID) {
    var route = "/api/v1/communications"
    console.log(route);
    var commRequest = {
      commID: nextCommID
    };

    $http.post(route, commRequest).
      success(vm.handleSuccessComm).
      error(vm.handleErrorComm);
  }

  function handleSuccessComm(data, status, headers, config) {
    // this callback will be called asynchronously
    // when the response is available
    console.log("Conversation started!");
    console.log(data);

    // When we reach the last message, terminate the conversation.
    if (data === null) {
      console.log("Data is null.");
      return;
    }

    var currentCommID = data.commID;
    var currentSpeaker = data.speaker;
    var currentMessage = data.message;

    var nextCommID = data.childrenCards[0].cardId;
    var nextSpeaker = data.childrenCards[0].speaker;

    console.log("Returned commID: " + nextCommID);
    console.log("Returned speaker: " + nextSpeaker);

    // Push the mssage of the card.
    if (currentSpeaker === "ai") {
      vm.chatMessages.push({
        speaker: currentSpeaker,
        message: currentMessage,
      });
    }

    // Do another request if the next speaker is also an AI.
    if (nextSpeaker === "ai") {
      vm.requestNextComm(nextCommID);
    }

    // Populate choices if next speaker is a client.
    if (nextSpeaker === "client") {
      console.log("Next speaker is a client.");

      vm.inputOptions = [];

      // Push over the options.
      for (i in data.childrenCards) {
        vm.inputOptions.push({
          inputMessage: data.childrenCards[i].message,
          inputCommID: data.childrenCards[i].cardId
        });
      }
    }
  }

  function handleErrorComm(data, status, headers, config) {
    console.log(data);
    alert("Conversation start unsuccessful.");
  }
}
<commit_msg>Refixed a big. Why did it disappear?<commit_after>module.exports = function(app) {
  app.controller('ChatController', [
    '$scope',
    '$q',
    '$http',
    '$ionicPlatform',
    '$ionicScrollDelegate',
    // '$ionicView',
    '$cordovaHealthKit',
    ChatController
  ]);
}

function ChatController(
    $scope,
    $q,
    $http,
    $ionicPlatform,
    $ionicScrollDelegate,
    // $ionicView,
    $cordovaHealthKit
  ) {

  var vm = this;

  vm.currentInputMessage = "";
  vm.currentInputID = "";

  vm.chatMessages = [];

  // TODO: Change this to correspond to what the server returns.
  vm.inputOptions = [];

  vm.enterClientInput = enterClientInput;
  vm.requestNextComm = requestNextComm;

  vm.handleSuccessComm = handleSuccessComm;
  vm.handleErrorComm = handleErrorComm;

  vm.getSteps = getSteps;

  // TODO: Test this when Healthkit entitlement becomes possible.
  $ionicPlatform.ready(function() {
    console.log("Platform is ready here.");
    $cordovaHealthKit.isAvailable().then(
      function(yes) {

        vm.sendClientContext = sendClientContext;
        vm.doRefresh = doRefresh;

        var readPermissions = [
          'HKQuantityTypeIdentifierDistanceWalkingRunning',
          'HKQuantityTypeIdentifierDistanceCycling',
          'HKQuantityTypeIdentifierStepCount',
        ];

        var writePermissions = [];
        console.log(readPermissions);

        $cordovaHealthKit.requestAuthorization(
          readPermissions,
          writePermissions
        ).then(function(success){
          console.log("Requested permissions to read and write health information.");
         });
      },
      function(no) {});
  });

  // FIXME: Can this be 'vm'. If so, or if not, why?
  $scope.$on('$ionicView.enter', function() {
    console.log("I have entered the app.");
    // TODO: This is where you can send the context of the walking steps.
    vm.doRefresh();
  });

  function doRefresh() {
    console.log("Refreshing the conversation!");
    vm.sendClientContext();
    vm.chatMessages = [];
    vm.requestNextComm("root");
    $scope.$broadcast('scroll.refreshComplete');
  }

  function getSteps(startDate, endDate) {
    console.log("Getting step count.");

    return $q(function (resolve, reject) {
      window.plugins.healthkit.sumQuantityType({
        'startDate': startDate,
        'endDate': endDate,
        'distanceUnit': 'mileUnit',
        'sampleType': 'HKQuantityTypeIdentifierStepCount'
      }, function(steps) {
        console.log("HealthKit Step Count Success: " + steps + " steps.");
        resolve(steps);
      }, function () {
        console.log("HealthKit Step Count Query unsuccessful.");
        reject();
      });
    });
  }

  function sendClientContext() {
    console.log("I am now going to send client context.");

    var m = moment().startOf('day');
    var startDate = m.toDate();
    var endDate = moment(m).add(1, 'd').toDate();

    console.log(startDate);
    console.log(endDate);

    vm.getSteps(startDate, endDate)
      .then(function(steps) {
        // TODO: Change this to the correct route.
        var route = CURRENT_HOST + "/api/v1/documents/2";
        var clientContext = {
          "document": {
            // TODO: Change user_id.
            userID: 1,
            steps: steps
          }
        }

        $http.patch(route, clientContext).
          success(function(data, status, headers, config) {
            console.log(data.message);

            // TODO: Populate messages with the next message.
            // Call method to populate messages and commands.

          }).
          error(function(data, status, headers, config) {
            alert("An error happened sending the message.");
          });
      }, function() {
        console.log("Error in getSteps promise.");
      });
  }

  function enterClientInput($index) {
    console.log("Entering the client input.");
    console.log("Input option index: " + $index);
    console.log("Input option: " + vm.inputOptions[$index]);

    vm.currentInputMessage = vm.inputOptions[$index].inputMessage;
    vm.currentInputID = vm.inputOptions[$index].inputCommID;
    console.log(vm.currentInputMessage);

    // Now push client message into the history.
    // TODO: This is not DRY. Package and make DRY.
    vm.chatMessages.push({
      speaker: "client",
      message: vm.currentInputMessage,
    });

    // Clear input options.
    vm.currentInputMessage = "";
    vm.inputOptions = [];
    console.log("Input options are cleared?");
    console.log(vm.inputOptions);

    vm.requestNextComm(vm.currentInputID);
  }

  function requestNextComm(nextCommID) {
    var route = "/api/v1/communications"
    console.log(route);
    var commRequest = {
      commID: nextCommID
    };

    $http.post(route, commRequest).
      success(vm.handleSuccessComm).
      error(vm.handleErrorComm);
  }

  function handleSuccessComm(data, status, headers, config) {
    // this callback will be called asynchronously
    // when the response is available
    console.log("Conversation started!");
    console.log(data);

    // When we reach the last message, terminate the conversation.
    if (data === null) {
      console.log("Data is null.");
      return;
    }

    var currentCommID = data.commID;
    var currentSpeaker = data.speaker;
    var currentMessage = data.message;

    var nextCommID = data.childrenCards[0].cardId;
    var nextSpeaker = data.childrenCards[0].speaker;

    console.log("Returned commID: " + nextCommID);
    console.log("Returned speaker: " + nextSpeaker);

    // Push the mssage of the card.
    if (currentSpeaker === "ai") {
      vm.chatMessages.push({
        speaker: currentSpeaker,
        message: currentMessage,
      });
    }

    // Do another request if the next speaker is also an AI.
    if (nextSpeaker === "ai") {
      vm.requestNextComm(nextCommID);
    }

    // Populate choices if next speaker is a client.
    if (nextSpeaker === "client") {
      console.log("Next speaker is a client.");

      vm.inputOptions = [];

      // Push over the options.
      for (i in data.childrenCards) {
        vm.inputOptions.push({
          inputMessage: data.childrenCards[i].message,
          inputCommID: data.childrenCards[i].cardId
        });
      }
    }
  }

  function handleErrorComm(data, status, headers, config) {
    console.log(data);
    alert("Conversation start unsuccessful.");
  }
}
<|endoftext|>