<commit_before>/*
Stephen Wetzel
smw347@drexel.edu
CS338:GUI, Project
*/

var hourly = 60 * 60;
var daily = 60 * 60 * 24;
var twiceDaily = 60 * 60 * 12;
var weekly = 60 * 60 * 24 * 7;
var monthly = 60 * 60 * 24 * 30;

testUserData = [
{"type":"Blood Pressure (diastolic)","data":[{"date":1457297331940,"value":78},{"date":1457297330949,"value":83},{"date":1457486304867,"value":88}]},
{"type":"Blood Pressure (systolic)","data":[{"date":1457297231840,"value":119},{"date":1457297230849,"value":108},{"date":1457486304867,"value":138}]},
{"type":"Heart Rate","data":[{"date":1457177231912,"value":72},{"date":1457187131929,"value":66}]}]

userData = []

datatypes = [
	{type: "Fasting Blood Sugar", max: 100, min: 70, logFreq: daily, unit: "mg/dL"},
	{type: "Heart Rate", max: 100, min: 60, logFreq: daily, unit: "BPM"},
	{type: "Cholesterol (Total)", max: 200, min: 70, logFreq: daily, unit: "mg/dL"},
	{type: "Cholesterol (LDL)", max: 130, min: 70, logFreq: daily, unit: "mg/dL"},
	{type: "Cholesterol (HDL)", max: 200, min: 50, logFreq: daily, unit: "mg/dL"},
	{type: "Triglycerides", max: 150, min: 10, logFreq: daily, unit: "mg/dL"},
	{type: "Blood Pressure (diastolic)", max: 90, min: 60, logFreq: daily, unit: "mm Hg"},
	{type: "Blood Pressure (systolic)", max: 120, min: 80, logFreq: daily, unit: "mm Hg"}]

function StoreData(obj)
{//take a js obj and store it a string in localStorage
	localStorage.setItem("userData", JSON.stringify(obj));
}

function ReadData()
{//retrieve string from localStorage, and parse it as obj
	var data = localStorage.userData;
	if (data === undefined) { return testUserData; }
	else { return JSON.parse(data); }
	//return JSON.parse(localStorage.userData);
}

function roundTo(num, digits)
{//rounds num to #digits past decimal
	digits = typeof digits !== 'undefined' ? digits : 2; //default to 2 digits
	var offset = Math.pow(10,digits);
	var num = Math.round(offset*num)/offset
	return num;
}

function zeroPad(num)
{//pad to 2 digits with zeros (eg, 7 -> 07)
	if (num <= 9) { (num = '0' + num).slice(-2); }
	return num;
}

//get a date object and return a formatted string, the format is hardcoded
function formatDate(date)
{//Output: 2/13/2001, 12:01:02 AM
	output = "";
	output += (date.getMonth() + 1) + "/";
	output += date.getDate() + "/";
	output += date.getFullYear() + ", ";
	if (date.getHours() > 12) {
		output += date.getHours() - 12 + ":";
		amPm = "PM";
	} else if (date.getHours() == 12) {
		output += "12:";
		amPm = "PM";
	} else if (date.getHours() == 0) {
		output += "12:";
		amPm = "AM";
	} else {
		output += date.getHours() + ":";
		amPm = "AM";
	}
	output += zeroPad(date.getMinutes()) + ":";
	output += zeroPad(date.getSeconds()) + " ";
	output += amPm;
	return output;
}

function getNewestPoint(data)
{
	var newestDate = 0;
	var newestValue = 0;
	data.data.forEach(function(item, ii) {
		if (item.date > newestDate) {
			newestDate = item.date;
			newestValue = item.value;
		}
	});
	return {date: newestDate, value: newestValue}
}

function convertSecsToDays(secs) {

	output = '';
	if (secs > monthly) {
		output = roundTo(secs / monthly) + " months ago";
	} else if (secs > weekly) {
		output = roundTo(secs / weekly) + " weeks ago";
	} else if (secs > daily) {
		output = roundTo(secs / daily) + " days ago";
	} else if (secs > hourly) {
		output = roundTo(secs / hourly) + " hours ago";
	} else if (secs > 60) {
		output = roundTo(secs / 60) + " minutes ago";
	} else {
		output = roundTo(secs) + " seconds ago";
	}

	return output;
}

function isCurrTracked(type)
{
	var bool = false;
	userData.forEach(function(item, ii) {
		if (item.type == type) {
			bool = true;
		}
	});
	return bool;
}

function getDataAge(data)
{
	var output = '';
	var freq = 0;
	datatypes.forEach(function(item, ii) {
		if (item.type == data.type)
		{
			freq = item.logFreq;
		}
	});
	var newestPoint = getNewestPoint(data);

	var now = Date.now();
	var age = (now - newestPoint.date) / 1000;
	if (age > freq) {
		output = "" + convertSecsToDays(age) + "";
	} else {
		output = "" + convertSecsToDays(age) + "";
	}
	return output;
}

function AddDataType(type)
{
	var newType = document.getElementById("DataTypeSelect").value
	//{"type":"Blood Pressure (diastolic)","data":[]}
	if ( !isCurrTracked(newType) ) {
		userData.push({type: newType, data: []});
		PromptForData(newType);
	} else {

	}
	StoreData(userData);
	BuildHomePage();
}

function AddData(type, data)
{
	userData.forEach(function(item, ii) {
		if (item.type == type)
		{
			item.data.push({date: Date.now(), value: data});
		}
	});
	StoreData(userData);
}

function checkDataPoint(type, data)
{
	datatypes.forEach(function(item, ii) {
		if (item.type == type)
		{
			max = item.max;
			min = item.min;
		}
	});

	if (data > max) {
		return 1;
	} else if (data < min) {
		return -1;
	}
	return 0;
}

function PromptForData(type)
{
	var input = '';
	while (!isNumeric(input)) {
		input = prompt("Enter New " + type, '');
	}
	AddData(type, input);
	var ok = checkDataPoint(type, input);
	if (ok == 1) { alert ("Warning! Too high!"); }
	else if (ok == -1) { alert ("Warning! Too low!"); }
	else { /*ok value*/ }
	BuildHomePage();
}

function DeleteData(type)
{
	userData.forEach(function(item, ii) {
		if (item.type == type)
		{
			userData.pop(ii);
		}
	});
	StoreData(userData);
	BuildHomePage();
}

function isNumeric(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

function getUnit(data) {
	var unit = '';
	datatypes.forEach(function(item, ii) {
		if (item.type == data.type)
		{
			unit = item.unit;
		}
	});
	return unit;
}

function BuildHomePage()
{
	var output = '';
	var style = "oddLine";

	userData = ReadData();

	userData.forEach(function(item, ii) {
		var age = getDataAge(item);
		var unit = getUnit(item);
		var newestPoint = getNewestPoint(item);
		var condClass = '';
		var ok = checkDataPoint(item.type, newestPoint.value)
		if (ok == 0) { condClass = "okValue"; }
		else { condClass = "badValue"; }
		output += "
";
		output += "";
		output += item.type + "";
		output += "Current Value: "+newestPoint.value+" "+unit+"";
		output += "<input type='submit' value='Add Data' onclick='PromptForData(\""+item.type+"\")'>"
		output += "Last updated: " + age + "";
		output += "<input type='submit' value='Delete Data' onclick='DeleteData(\""+item.type+"\")'>"

		output += "
";
		if (style == "oddLine") { style = "evenLine"; }
		else {style = "oddLine"; }

	});

	output += "
Track a new type of data: <select id='DataTypeSelect'>"
	datatypes.forEach(function(item, ii) {
		output += "<option value='"+item.type+"'>"+item.type+"</option>";
	});
	output += "</select>  <input type='submit' value='Track a New Type' onclick='AddDataType()'>
";

	//confirm delete
	//view report at bottom of page
	//something with bmi
	//ask user for unchanging stats: height, sex, name
	//clear all button
	//result to default data button

	document.getElementById('container').innerHTML = output;
}

function ResetDefaultData()
{
	console.log("Reset Data");
	userData = testUserData;
	StoreData(userData);
	BuildHomePage();
}

function ClearAllData()
{
	console.log("Clear Data");
	userData = [];
	StoreData(userData);
	BuildHomePage();
}

function addUserInfo()
{
	console.log("User Data");
}
<commit_msg>Add code for getting user info, change localStorage method to allow any variable to be stored<commit_after>/*
Stephen Wetzel
smw347@drexel.edu
CS338:GUI, Project
*/

var hourly = 60 * 60;
var daily = 60 * 60 * 24;
var twiceDaily = 60 * 60 * 12;
var weekly = 60 * 60 * 24 * 7;
var monthly = 60 * 60 * 24 * 30;

testUserData = [
{"type":"Blood Pressure (diastolic)","data":[{"date":1457297331940,"value":78},{"date":1457297330949,"value":83},{"date":1457486304867,"value":88}]},
{"type":"Blood Pressure (systolic)","data":[{"date":1457297231840,"value":119},{"date":1457297230849,"value":108},{"date":1457486304867,"value":138}]},
{"type":"Heart Rate","data":[{"date":1457177231912,"value":72},{"date":1457187131929,"value":66}]}];

userData = [];

userInfo = {name: '', height: 0, sex: ''};

datatypes = [
	{type: "Fasting Blood Sugar", max: 100, min: 70, logFreq: daily, unit: "mg/dL"},
	{type: "Heart Rate", max: 100, min: 60, logFreq: daily, unit: "BPM"},
	{type: "Cholesterol (Total)", max: 200, min: 70, logFreq: daily, unit: "mg/dL"},
	{type: "Cholesterol (LDL)", max: 130, min: 70, logFreq: daily, unit: "mg/dL"},
	{type: "Cholesterol (HDL)", max: 200, min: 50, logFreq: daily, unit: "mg/dL"},
	{type: "Triglycerides", max: 150, min: 10, logFreq: daily, unit: "mg/dL"},
	{type: "Blood Pressure (diastolic)", max: 90, min: 60, logFreq: daily, unit: "mm Hg"},
	{type: "Blood Pressure (systolic)", max: 120, min: 80, logFreq: daily, unit: "mm Hg"}];

function StoreData(obj, name)
{//take a js obj and store it as a string in localStorage
	localStorage.setItem(name, JSON.stringify(obj));
}

function ReadData(name)
{//retrieve string from localStorage, and parse it as obj
	var data = localStorage[name];
	if (data === undefined) { return testUserData; }
	else { return JSON.parse(data); }
	//return JSON.parse(localStorage.userData);
}

function roundTo(num, digits)
{//rounds num to #digits past decimal
	digits = typeof digits !== 'undefined' ? digits : 2; //default to 2 digits
	var offset = Math.pow(10,digits);
	var num = Math.round(offset*num)/offset
	return num;
}

function zeroPad(num)
{//pad to 2 digits with zeros (eg, 7 -> 07)
	if (num <= 9) { (num = '0' + num).slice(-2); }
	return num;
}

//get a date object and return a formatted string, the format is hardcoded
function formatDate(date)
{//Output: 2/13/2001, 12:01:02 AM
	output = "";
	output += (date.getMonth() + 1) + "/";
	output += date.getDate() + "/";
	output += date.getFullYear() + ", ";
	if (date.getHours() > 12) {
		output += date.getHours() - 12 + ":";
		amPm = "PM";
	} else if (date.getHours() == 12) {
		output += "12:";
		amPm = "PM";
	} else if (date.getHours() == 0) {
		output += "12:";
		amPm = "AM";
	} else {
		output += date.getHours() + ":";
		amPm = "AM";
	}
	output += zeroPad(date.getMinutes()) + ":";
	output += zeroPad(date.getSeconds()) + " ";
	output += amPm;
	return output;
}

function getNewestPoint(data)
{
	var newestDate = 0;
	var newestValue = 0;
	data.data.forEach(function(item, ii) {
		if (item.date > newestDate) {
			newestDate = item.date;
			newestValue = item.value;
		}
	});
	return {date: newestDate, value: newestValue}
}

function convertSecsToDays(secs) {

	output = '';
	if (secs > monthly) {
		output = roundTo(secs / monthly) + " months ago";
	} else if (secs > weekly) {
		output = roundTo(secs / weekly) + " weeks ago";
	} else if (secs > daily) {
		output = roundTo(secs / daily) + " days ago";
	} else if (secs > hourly) {
		output = roundTo(secs / hourly) + " hours ago";
	} else if (secs > 60) {
		output = roundTo(secs / 60) + " minutes ago";
	} else {
		output = roundTo(secs) + " seconds ago";
	}

	return output;
}

function isCurrTracked(type)
{
	var bool = false;
	userData.forEach(function(item, ii) {
		if (item.type == type) {
			bool = true;
		}
	});
	return bool;
}

function getDataAge(data)
{
	var output = '';
	var freq = 0;
	datatypes.forEach(function(item, ii) {
		if (item.type == data.type)
		{
			freq = item.logFreq;
		}
	});
	var newestPoint = getNewestPoint(data);

	var now = Date.now();
	var age = (now - newestPoint.date) / 1000;
	if (age > freq) {
		output = "" + convertSecsToDays(age) + "";
	} else {
		output = "" + convertSecsToDays(age) + "";
	}
	return output;
}

function AddDataType(type)
{
	var newType = document.getElementById("DataTypeSelect").value
	//{"type":"Blood Pressure (diastolic)","data":[]}
	if ( !isCurrTracked(newType) ) {
		userData.push({type: newType, data: []});
		PromptForData(newType);
	} else {

	}
	StoreData(userData, "userData");
	BuildHomePage();
}

function AddData(type, data)
{
	userData.forEach(function(item, ii) {
		if (item.type == type)
		{
			item.data.push({date: Date.now(), value: data});
		}
	});
	StoreData(userData, "userData");
}

function checkDataPoint(type, data)
{
	datatypes.forEach(function(item, ii) {
		if (item.type == type)
		{
			max = item.max;
			min = item.min;
		}
	});

	if (data > max) {
		return 1;
	} else if (data < min) {
		return -1;
	}
	return 0;
}

function PromptForData(type)
{
	var input = '';
	while (!isNumeric(input)) {
		input = prompt("Enter New " + type, '');
	}
	AddData(type, input);
	var ok = checkDataPoint(type, input);
	if (ok == 1) { alert ("Warning! Too high!"); }
	else if (ok == -1) { alert ("Warning! Too low!"); }
	else { /*ok value*/ }
	BuildHomePage();
}

function DeleteData(type)
{
	userData.forEach(function(item, ii) {
		if (item.type == type)
		{
			userData.pop(ii);
		}
	});
	StoreData(userData, "userData");
	BuildHomePage();
}

function isNumeric(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

function getUnit(data) {
	var unit = '';
	datatypes.forEach(function(item, ii) {
		if (item.type == data.type)
		{
			unit = item.unit;
		}
	});
	return unit;
}

function BuildHomePage()
{
	var output = '';
	var style = "oddLine";

	userInfo = ReadData("userInfo");
	userData = ReadData("userData");

	userData.forEach(function(item, ii) {
		var age = getDataAge(item);
		var unit = getUnit(item);
		var newestPoint = getNewestPoint(item);
		var condClass = '';
		var ok = checkDataPoint(item.type, newestPoint.value)
		if (ok == 0) { condClass = "okValue"; }
		else { condClass = "badValue"; }
		output += "
";
		output += "";
		output += item.type + "";
		output += "Current Value: "+newestPoint.value+" "+unit+"";
		output += "<input type='submit' value='Add Data' onclick='PromptForData(\""+item.type+"\")'>"
		output += "Last updated: " + age + "";
		output += "<input type='submit' value='Delete Data' onclick='DeleteData(\""+item.type+"\")'>"

		output += "
";
		if (style == "oddLine") { style = "evenLine"; }
		else {style = "oddLine"; }
	});

	output += "
Track a new type of data: <select id='DataTypeSelect'>"
	datatypes.forEach(function(item, ii) {
		output += "<option value='"+item.type+"'>"+item.type+"</option>";
	});
	output += "</select>  <input type='submit' value='Track a New Type' onclick='AddDataType()'>
";

	//confirm delete
	//view report at bottom of page
	//something with bmi

	document.getElementById('container').innerHTML = output;
}

function ResetDefaultData()
{
	userData = testUserData;
	userInfo = {name: '', height: 0, sex: ''};
	StoreData(userData, "userData");
	StoreData(userInfo, "userInfo");
	BuildHomePage();
}

function ClearAllData()
{
	userData = [];
	userInfo = {name: '', height: 0, sex: ''};
	StoreData(userData, "userData");
	StoreData(userInfo, "userInfo");
	BuildHomePage();
}

function addUserInfo()
{
	var input = '';
	input = prompt("Enter Your Name ", '');
	userInfo.name = input;

	input = '';
	while (!isNumeric(input)) {
		input = prompt("Enter Your Height (inches) ", '');
	}
	userInfo.height = input;

	//input = '';
	//while (!isNumeric(input)) {
	//	input = prompt("Enter Your Height (inches) ", '');
	//}
	//userInfo.height = input;
	StoreData(userInfo, "userInfo");
}
<|endoftext|>


<commit_before>(function ($) {
    "use strict";

    try {
        Object.defineProperties($, {

            // greatest common divisor
            GCD: {
                value: function () {
                    var
                        remains,
                        primeFactor = 2,
                        product = 1,
                        i = 0,
                        numbers = [],
                        count = 0,

                        euclidesAlgorithm = function(a, b) {
                            var
                                rest = b;

                            while(rest !== 0) {
                               rest = a % b;
                               a = b;
                               b = rest;
                            }

                            return a;
                        },

                        everyoneAreMultipleOf = function(remains, primeFactor) {
                            var
                                i = 0;

                            while(i < remains.length) {
                                if (!remains[i++].multipleOf(primeFactor)) {
                                    return false;
                                }
                            }

                            return true;
                        },

                        hasSomeMultipleOf = function(remains, primeFactor) {
                            var
                                i = 0;

                            while(i < remains.length) {
                                if (remains[i++].multipleOf(primeFactor)) {
                                    return true;
                                }
                            }

                            return false;
                        };

                    numbers = Array.from(arguments);
                    numbers = numbers.uniq();
                    if(numbers.length == 1) {
                        return numbers[0];
                    }

                    // properties

                    // se todos os números forem múltiplos entre si, o MDC será menor deles
                    if(numbers.areMultiples()) {return numbers.min();}

                    // o algorítmo de Euclides é mais eficiente para calcular o MDC entre apenas dois números
                    if(numbers.length == 2) {
                        return euclidesAlgorithm(numbers[0], numbers[1]);
                    }

                    // dois números primos não são múltiplos entre si
                    i = 0;
                    while(true) {
                        if((numbers[i]).isPrime()) {count++;}
                        if(count >= 2) {return 1;}
                        if(i == numbers.length -1) {break;}
                        i++;
                    }

                    remains = numbers.clone();

                    while(remains.count(1) != remains.length) {
                        if(everyoneAreMultipleOf(remains, primeFactor)) {
                            product *= primeFactor;
                        }

                        i = 0;
                        while(i < remains.length) {
                            if (remains[i].multipleOf(primeFactor)) {
                                remains[i] /= primeFactor;
                            }
                            i++;
                        }

                        if(!hasSomeMultipleOf(remains, primeFactor)) {
                            primeFactor = primeFactor.nextPrimeFactor();
                        }
                    }

                    return product;
                }
            },

            // least common multiple
            LCM: {
                value: function () {
                    var
                        numbers = [],
                        primeFactors = [],
                        commonFactors = [],
                        nonCommonfactors = [],
                        biggerFactorsHash = {},
                        i = 0,
                        biggerCommonProduct = 1,
                        noCommonFactors = 1,

                        for2Factors = function(numbers) {
                            var
                                product = 1;

                            numbers.forEach(function (v) {
                                product *= v;
                            });

                            return product/Math.GCD.apply(null, numbers);
                        };

                    numbers = Array.from(arguments);
                    numbers = numbers.uniq();
                    if(numbers.length == 1) {
                        return numbers[0];
                    }

                    if(numbers.areMultiples()) {return numbers.max();}

                    if(numbers.length == 2) {return for2Factors(numbers);}

                    numbers.forEach(function (v) {
                        primeFactors.push(v.primeFactors());
                    });

                    commonFactors = primeFactors.intersection();

                    primeFactors.forEach(function (a) {
                        commonFactors.forEach(function (v) {
                            if(!biggerFactorsHash[v]) {
                                biggerFactorsHash[v] = a.count(v);
                            } else {
                                if(a.count(v) > biggerFactorsHash[v]) {
                                    biggerFactorsHash[v] = a.count(v);
                                }
                            }
                        });
                    });

                    for(i in biggerFactorsHash) {
                        if (biggerFactorsHash.hasOwnProperty(i)) {
                                biggerCommonProduct *= Math
                                    .pow(i, biggerFactorsHash[i]);
                        }
                    }

                    nonCommonfactors = primeFactors.flatten().uniq()
                        .differences(commonFactors);

                    nonCommonfactors.forEach(function (v) {
                        noCommonFactors *= v;
                    });

                    return biggerCommonProduct * noCommonFactors;
                }
            }

        });

    } catch(e) {}

})(Math);

// Simone 2002
// Sem Limite (com Robert De Niro)
<commit_msg>comment<commit_after>(function ($) {
    "use strict";

    try {
        Object.defineProperties($, {

            // greatest common divisor
            GCD: {
                value: function () {
                    var
                        remains,
                        primeFactor = 2,
                        product = 1,
                        i = 0,
                        numbers = [],
                        count = 0,

                        euclidesAlgorithm = function(a, b) {
                            var
                                rest = b;

                            while(rest !== 0) {
                               rest = a % b;
                               a = b;
                               b = rest;
                            }

                            return a;
                        },

                        everyoneAreMultipleOf = function(remains, primeFactor) {
                            var
                                i = 0;

                            while(i < remains.length) {
                                if (!remains[i++].multipleOf(primeFactor)) {
                                    return false;
                                }
                            }

                            return true;
                        },

                        hasSomeMultipleOf = function(remains, primeFactor) {
                            var
                                i = 0;

                            while(i < remains.length) {
                                if (remains[i++].multipleOf(primeFactor)) {
                                    return true;
                                }
                            }

                            return false;
                        };

                    numbers = Array.from(arguments);
                    numbers = numbers.uniq();
                    if(numbers.length == 1) {
                        return numbers[0];
                    }

                    // properties

                    // se todos os números forem múltiplos entre si, o MDC será menor deles
                    if(numbers.areMultiples()) {return numbers.min();}

                    // o algorítmo de Euclides é mais eficiente para calcular o MDC entre apenas dois números
                    if(numbers.length == 2) {
                        return euclidesAlgorithm(numbers[0], numbers[1]);
                    }

                    // dois números primos não são múltiplos entre si
                    i = 0;
                    while(true) {
                        if((numbers[i]).isPrime()) {count++;}
                        if(count >= 2) {return 1;}
                        if(i == numbers.length -1) {break;}
                        i++;
                    }

                    remains = numbers.clone();

                    while(remains.count(1) != remains.length) {
                        if(everyoneAreMultipleOf(remains, primeFactor)) {
                            product *= primeFactor;
                        }

                        i = 0;
                        while(i < remains.length) {
                            if (remains[i].multipleOf(primeFactor)) {
                                remains[i] /= primeFactor;
                            }
                            i++;
                        }

                        if(!hasSomeMultipleOf(remains, primeFactor)) {
                            primeFactor = primeFactor.nextPrimeFactor();
                        }
                    }

                    return product;
                }
            },

            // TODO: revisar
            // least common multiple
            LCM: {
                value: function () {
                    var
                        numbers = [],
                        primeFactors = [],
                        commonFactors = [],
                        nonCommonfactors = [],
                        biggerFactorsHash = {},
                        i = 0,
                        biggerCommonProduct = 1,
                        noCommonFactors = 1,

                        for2Factors = function(numbers) {
                            var
                                product = 1;

                            numbers.forEach(function (v) {
                                product *= v;
                            });

                            return product/Math.GCD.apply(null, numbers);
                        };

                    numbers = Array.from(arguments);
                    numbers = numbers.uniq();
                    if(numbers.length == 1) {
                        return numbers[0];
                    }

                    if(numbers.areMultiples()) {return numbers.max();}

                    if(numbers.length == 2) {return for2Factors(numbers);}

                    numbers.forEach(function (v) {
                        primeFactors.push(v.primeFactors());
                    });

                    commonFactors = primeFactors.intersection();

                    primeFactors.forEach(function (a) {
                        commonFactors.forEach(function (v) {
                            if(!biggerFactorsHash[v]) {
                                biggerFactorsHash[v] = a.count(v);
                            } else {
                                if(a.count(v) > biggerFactorsHash[v]) {
                                    biggerFactorsHash[v] = a.count(v);
                                }
                            }
                        });
                    });

                    for(i in biggerFactorsHash) {
                        if (biggerFactorsHash.hasOwnProperty(i)) {
                                biggerCommonProduct *= Math
                                    .pow(i, biggerFactorsHash[i]);
                        }
                    }

                    nonCommonfactors = primeFactors.flatten().uniq()
                        .differences(commonFactors);

                    nonCommonfactors.forEach(function (v) {
                        noCommonFactors *= v;
                    });

                    return biggerCommonProduct * noCommonFactors;
                }
            }

        });

    } catch(e) {}

})(Math);

// Simone 2002
// Sem Limite (com Robert De Niro)
<|endoftext|>


<commit_before>
'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;

const scriptRules = require('./script.json');

var myDate = new Date();
var groet = '';

/* hour is before noon */
if ( myDate.getHours() < 12 )
{
groet = "Goeiemorgen";
}
else  /* Hour is from noon to 5pm (actually to 5:59 pm) */
if ( myDate.getHours() >= 12 && myDate.getHours() <= 17 )
{
groet = "Goedendag";
}
else  /* the hour is after 5pm, so it is between 6pm and midnight */
if ( myDate.getHours() > 17 && myDate.getHours() <= 24 )
{
groet = "Goedenavond";
}
else  /* the hour is not between 0 and 24, so something is wrong */
{
groet = "Welkom";
}

function wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

module.exports = new Script({

 processing: {
//prompt: (bot) => bot.say('...'),
 receive: () => 'processing'
 },

start: {
    receive: (bot,message) => {
        const opening = message.text.trim().toUpperCase();
        return bot.say(`${groet}, wat voor soort hypotheek zoek je? `)
        .then(() => bot.say(`%[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`))
        .then(() => 'selecteerHypotheek');
    }
},

selecteerHypotheek: {
    receive: (bot, message) => {
      switch(message.text) {
      case 'Hoi':
            return bot.say(`${groet} waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
            .then(() => 'askName')
          break;
      case 'Starters hypotheek':
      //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
          return bot.say(`Wat voor type woning zoek je? `)
          .then(() => bot.say(`%[Appartement](postback:hypotheekkeuze_appartement) %[Huis](postback:hypotheekkeuze_huis) %[Vakantiewoning](postback:hypotheekkeuze_vakantiewoning)`))
          .then(() => 'hypotheek_starter')
              break;
        case 'Nieuwe hypotheek':
          return bot.say(`Helaas biedt Independer momenteel alleen Starters een hypotheek aan.`)
          .then(() => bot.say(`Via onderstaande link kun je de beste hypotheekadviseur voor jou vinden. %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)`))
            .then(() => 'finish')
          break;
        case 'Hypotheek oversluiten':
          return bot.say(`Het spijt me maar op dit moment biedt Independer alleen  Starters een hypotheek.`)
          .then(()=> bot.say('Als het allemaal wel zo ver is, wil je dan een update ontvangen? %[Ja - graag](postback:update_ja) %[Nee, bedankt](postback:update_nee)'))
            .then(() => 'updateOntvangen')
          break;
        default:
          return bot.say(`...`)
            .then(() => 'processing')
          break;
      }
    }
},

updateOntvangen: {
    receive: (bot, message) => {
      switch(message.text) {
        case 'Ja - graag':
            return bot.say(`Leuk, dan houd ik  je op de hoogte zodra er weer nieuws is.' `)
            .then(() => 'update_ja');
          break;
          case 'Nee, bedankt':
              receive: () => 'bye'
              break;
          default:
            return bot.say(`...`)
              .then(() => 'processing')
            break;
}
}
},

update_ja: {
  prompt: (bot) => bot.say('Wat is je email adres?'),
      receive: (bot, message) => {
        return bot.say('...')
          .then(() => 'processing')
  //          const emailVisitor = message.text;
  //          //return bot.setProp('emailVisitor', emailVisitor)
  //           .then(()  => bot.say('Ok - dan hou ik je via ${emailVisitor} op de hoogte.'))
  //           .then(()  =>'processing')
    }
},

hypotheekkeuze_appartement: {
receive: (bot,message)  => {
    //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
}
},
hypotheekkeuze_huis: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
  receive: () => 'askName'
},
hypotheekkeuze_vakantiewoning: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
},
hypotheektype_starter: {
    prompt: (bot) => bot.say('Pleasure meeting you - starter'),
    receive: () => 'processing'
},
hypotheektype_nieuw: {
    prompt: (bot) => bot.say(`Independer biedt momenteel alleen voor Starters een hypotheek. Onderstaande link bied je meer informatie %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)`),
    receive: () => 'processing'
},

askName: {
  receive: (bot, message) => {
    switch(message.text) {
        case 'Appartement':
          return bot.say(`Nice!`)
          .then(() => 'vervolgVragen')
          break;
      case 'Huis':
          return bot.say(`Leuk :)`)
          .then(() => 'vervolgVragen')
          break;
      default:
        return bot.say(`...`)
          .then(() => 'processing')
        break;
    }
    }
},

vervolgVragen: {
  prompt: (bot) => bot.say('Hoe heet je eigelijk? Dat maakt het praten een stuk makkelijker...'),
  receive: (bot, message) => {
      const name = message.text;
      return bot.setProp('name', name)
          .then(() => bot.say(`Hoi ${name}. Ik heb nog wat vragen voor je om verder te kunnen.`))
          .then(() => 'lastCheck');
    }
},

lastCheck: {
    // prompt: (bot) => bot.say('Is er nog iets waar ik  je bij kan helpen? %[JA](postback:nogietsanders) %[NEE](postback:bye) '),
    // .then(()  => 'processing');
},

bye: {
    prompt: (bot) => bot.say('Fijn je gesproken te hebben. Bedankt voor je tijd'),
    receive: ()  => 'finish'
},

// error: {
// prompt: (bot) => bot.say('Sorry - kun je dat nog eens zeggen?  Er ging iets mis...'),
// receive: () => ''
// },

finish: {
receive: () => 'finish'
},

  speak: {
          receive: (bot, message) => {

              let upperText = message.text.trim().toUpperCase();

              function updateSilent() {
                  switch (upperText) {
                      case "CONNECT ME":
                          return bot.setProp("silent", true);
                      case "DISCONNECT":
                          return bot.setProp("silent", false);
                      default:
                          return Promise.resolve();
                  }
              }

              function getSilent() {
                  return bot.getProp("silent");
              }

              function processMessage(isSilent) {
                  if (isSilent) {
                      return Promise.resolve("speak");
                  }

                  if (!_.has(scriptRules, upperText)) {
                      return bot.say(`So, I'm good at structured conversations but stickers, emoji and sentences still confuse me. Say 'more' to chat about something else.`).then(() => 'speak');
                  }

                  var response = scriptRules[upperText];
                  var lines = response.split('\n');

                  var p = Promise.resolve();
                  _.each(lines, function(line) {
                      line = line.trim();
                      p = p.then(function() {
                          console.log(line);
                          return wait(50).then(function() {
                              return bot.say(line);
                          });
                      });
                  });

                  return p.then(() => 'speak');
              }

              return updateSilent()
                  .then(getSilent)
                  .then(processMessage);
          }
      }
});
<commit_msg>wd<commit_after>
'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;

const scriptRules = require('./script.json');

var myDate = new Date();
var groet = '';

/* hour is before noon */
if ( myDate.getHours() < 12 )
{
groet = "Goeiemorgen";
}
else  /* Hour is from noon to 5pm (actually to 5:59 pm) */
if ( myDate.getHours() >= 12 && myDate.getHours() <= 17 )
{
groet = "Goedendag";
}
else  /* the hour is after 5pm, so it is between 6pm and midnight */
if ( myDate.getHours() > 17 && myDate.getHours() <= 24 )
{
groet = "Goedenavond";
}
else  /* the hour is not between 0 and 24, so something is wrong */
{
groet = "Welkom";
}

function wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

module.exports = new Script({

 processing: {
//prompt: (bot) => bot.say('...'),
 receive: () => 'processing'
 },

start: {
    receive: (bot,message) => {
        const opening = message.text.trim().toUpperCase();
        return bot.say(`${groet}, wat voor soort hypotheek zoek je? `)
        .then(() => bot.say(`%[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`))
        .then(() => 'selecteerHypotheek');
    }
},

selecteerHypotheek: {
    receive: (bot, message) => {
      switch(message.text) {
      case 'Hoi':
            return bot.say(`${groet} waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
            .then(() => 'askName')
          break;
      case 'Starters hypotheek':
      //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
          return bot.say(`Wat voor type woning zoek je? `)
          .then(() => bot.say(`%[Appartement](postback:hypotheekkeuze_appartement) %[Huis](postback:hypotheekkeuze_huis) %[Vakantiewoning](postback:hypotheekkeuze_vakantiewoning)`))
          .then(() => 'hypotheek_starter')
              break;
        case 'Nieuwe hypotheek':
          return bot.say(`Helaas biedt Independer momenteel alleen Starters een hypotheek aan.`)
          .then(() => bot.say(`Via onderstaande link kun je de beste hypotheekadviseur voor jou vinden. %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)`))
            .then(() => 'finish')
          break;
        case 'Hypotheek oversluiten':
          return bot.say(`Het spijt me maar op dit moment biedt Independer alleen  Starters een hypotheek.`)
          .then(()=> bot.say('Als het allemaal wel zo ver is, wil je dan een update ontvangen? %[Ja - graag](postback:update_ja) %[Nee, bedankt](postback:update_nee)'))
            .then(() => 'updateOntvangen')
          break;
        default:
          return bot.say(`...`)
            .then(() => 'processing')
          break;
      }
    }
},

updateOntvangen: {
    receive: (bot, message) => {
      switch(message.text) {
        case 'Ja - graag':
            return bot.say(`Leuk, dan houd ik  je op de hoogte zodra er weer nieuws is.' `)
            .then(() => 'update_ja');
          break;
          case 'Nee, bedankt':
              receive: () => 'bye'
              break;
          default:
            return bot.say(`...`)
              .then(() => 'processing')
            break;
}
}
},

update_ja: {
  prompt: (bot) => bot.say('Wat is je email adres?'),
      receive: (bot, message) => {
        const emailVisitor = message.text;
        return bot.say('...')
          .then(() => 'processing')
  //          const emailVisitor = message.text;
  //          //return bot.setProp('emailVisitor', emailVisitor)
  //           .then(()  => bot.say('Ok - dan hou ik je via ${emailVisitor} op de hoogte.'))
  //           .then(()  =>'processing')
    }
},

hypotheekkeuze_appartement: {
receive: (bot,message)  => {
    //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
}
},
hypotheekkeuze_huis: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
  receive: () => 'askName'
},
hypotheekkeuze_vakantiewoning: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
},
hypotheektype_starter: {
    prompt: (bot) => bot.say('Pleasure meeting you - starter'),
    receive: () => 'processing'
},
hypotheektype_nieuw: {
    prompt: (bot) => bot.say(`Independer biedt momenteel alleen voor Starters een hypotheek. Onderstaande link bied je meer informatie %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)`),
    receive: () => 'processing'
},

askName: {
  receive: (bot, message) => {
    switch(message.text) {
        case 'Appartement':
          return bot.say(`Nice!`)
          .then(() => 'vervolgVragen')
          break;
      case 'Huis':
          return bot.say(`Leuk :)`)
          .then(() => 'vervolgVragen')
          break;
      default:
        return bot.say(`...`)
          .then(() => 'processing')
        break;
    }
    }
},

vervolgVragen: {
  prompt: (bot) => bot.say('Hoe heet je eigelijk? Dat maakt het praten een stuk makkelijker...'),
  receive: (bot, message) => {
      const name = message.text;
      return bot.setProp('name', name)
          .then(() => bot.say(`Hoi ${name}. Ik heb nog wat vragen voor je om verder te kunnen.`))
          .then(() => 'lastCheck');
    }
},

lastCheck: {
    // prompt: (bot) => bot.say('Is er nog iets waar ik  je bij kan helpen? %[JA](postback:nogietsanders) %[NEE](postback:bye) '),
    // .then(()  => 'processing');
},

bye: {
    prompt: (bot) => bot.say('Fijn je gesproken te hebben. Bedankt voor je tijd'),
    receive: ()  => 'finish'
},

// error: {
// prompt: (bot) => bot.say('Sorry - kun je dat nog eens zeggen?  Er ging iets mis...'),
// receive: () => ''
// },

finish: {
receive: () => 'finish'
},

  speak: {
          receive: (bot, message) => {

              let upperText = message.text.trim().toUpperCase();

              function updateSilent() {
                  switch (upperText) {
                      case "CONNECT ME":
                          return bot.setProp("silent", true);
                      case "DISCONNECT":
                          return bot.setProp("silent", false);
                      default:
                          return Promise.resolve();
                  }
              }

              function getSilent() {
                  return bot.getProp("silent");
              }

              function processMessage(isSilent) {
                  if (isSilent) {
                      return Promise.resolve("speak");
                  }

                  if (!_.has(scriptRules, upperText)) {
                      return bot.say(`So, I'm good at structured conversations but stickers, emoji and sentences still confuse me. Say 'more' to chat about something else.`).then(() => 'speak');
                  }

                  var response = scriptRules[upperText];
                  var lines = response.split('\n');

                  var p = Promise.resolve();
                  _.each(lines, function(line) {
                      line = line.trim();
                      p = p.then(function() {
                          console.log(line);
                          return wait(50).then(function() {
                              return bot.say(line);
                          });
                      });
                  });

                  return p.then(() => 'speak');
              }

              return updateSilent()
                  .then(getSilent)
                  .then(processMessage);
          }
      }
});
<|endoftext|>


<commit_before>/*
 * Websensor video stabilization project
 * https://github.com/jessenie-intel/websensor-video
 *
 * Copyright (c) 2017 Jesse Nieminen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

'use strict';

var constraints = {audio: true,video: {  width: { min: 640, ideal: 640, max: 640 },  height: { min: 480, ideal: 480, max: 480 }}};
var mediaRecorder = null;
var chunks = [];
var videoData = null;
var interval = null;

var accel_sensor = null;
var orientation_sensor = null;
var sensorfreq = 60;

//var roll = null;
//var pitch = null;
//var yaw = null;
var accel = {"x": null, "y": null, "z": null};
var velGyro = {"x": null, "y": null, "z": null};
var ori = {"roll": null, "pitch": null, "yaw": null, "time": null};
var oriInitial = {"roll": null, "pitch": null, "yaw": null, "time": null};
var initialoriobtained = false;
var orientationData = [];       //array to store all the orientation data
var frameData = {"data": null, "time": null, "ori": null};
var dataArray = [];     //array to store all the combined data
var dataArray2 = [];     //array to store all the combined data

var time = null;
var timestamps = [];
var nFrame = 0; //frame number with which we can combine timestamp and frame data

//canvas
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');

//video element
var videoElement = document.querySelector('video');
videoElement.controls = false;

var ref = null;
var extraFrames = 0;

class AbsOriSensor {
        constructor() {
        const sensor = new AbsoluteOrientationSensor({ frequency: sensorfreq });
        const mat4 = new Float32Array(16);
        const euler = new Float32Array(3);
        sensor.onreading = () => {
                sensor.populateMatrix(mat4);
                toEulerianAngle(sensor.quaternion, euler);      //From quaternion to Eulerian angles
                this.roll = euler[0];
                this.pitch = euler[1];
                this.yaw = euler[2];
                this.timestamp = sensor.timestamp;
                if (this.onreading) this.onreading();
        };
        sensor.onactivate = () => {
                if (this.onactivate) this.onactivate();
        };
        const start = () => sensor.start();
        Object.assign(this, { start });
        }
}

function update_debug()
{
                        document.getElementById("ori").textContent = `${ori.roll} ${ori.pitch} ${ori.yaw}`;
                        document.getElementById("accel").textContent = `${accel.x} ${accel.y} ${accel.z}`;
                        document.getElementById("rrate").textContent = `${velGyro.x} ${velGyro.y} ${velGyro.z}`;
}

//WINDOWS 10 HAS DIFFERENT CONVENTION: Yaw z, pitch x, roll y
function toEulerianAngle(quat, out)
{
        const ysqr = quat[1] ** 2;

        // Roll (x-axis rotation).
        const t0 = 2 * (quat[3] * quat[0] + quat[1] * quat[2]);
        const t1 = 1 - 2 * (ysqr + quat[0] ** 2);
        out[0] = Math.atan2(t0, t1);
        // Pitch (y-axis rotation).
        let t2 = 2 * (quat[3] * quat[1] - quat[2] * quat[0]);
        t2 = t2 > 1 ? 1 : t2;
        t2 = t2 < -1 ? -1 : t2;
        out[1] = Math.asin(t2);
        // Yaw (z-axis rotation).
        const t3 = 2 * (quat[3] * quat[2] + quat[0] * quat[1]);
        const t4 = 1 - 2 * (ysqr + quat[2] ** 2);
        out[2] = Math.atan2(t3, t4);
        return out;
}

function errorCallback(error){
	console.log("error: ", error);
}

function startDemo () {
		navigator.getUserMedia(constraints, startRecording, errorCallback);
}

function startRecording(stream) {

                try {
                //Initialize sensors
                accel_sensor = new Accelerometer();
                accel_sensor.onreading = () => {
                        accel = {"x": accel_sensor.x, "y": accel_sensor.y, "z": accel_sensor.z};
                };
                accel_sensor.onactivate = () => {
                };
                accel_sensor.start();
                gyroscope = new Gyroscope();
                gyroscope.onreading = () => {
                        velGyro = {x:gyroscope.x, y:gyroscope.y, z:gyroscope.z};
                };
                gyroscope.onactivate = () => {
                };
                gyroscope.start();
                orientation_sensor = new AbsOriSensor();
                orientation_sensor.onreading = () => {
                        let roll = orientation_sensor.roll;
                        let pitch = orientation_sensor.pitch;
                        let yaw = orientation_sensor.yaw;
                        time = orientation_sensor.timestamp;
                        if(!initialoriobtained) //obtain initial orientation
                        {
                                oriInitial = {"roll": orientation_sensor.roll, "pitch": orientation_sensor.pitch, "yaw": orientation_sensor.yaw, "time": orientation_sensor.timestamp};
                                initialoriobtained = true;
                        }
                        ori = {"roll": orientation_sensor.roll, "pitch": orientation_sensor.pitch, "yaw": orientation_sensor.yaw, "time": orientation_sensor.timestamp};
                };
                orientation_sensor.onactivate = () => {
                };
                orientation_sensor.start();
                }
                catch(err) {
                        console.log(err.message);
                        console.log("Your browser doesn't seem to support generic sensors. If you are running Chrome, please enable it in about:flags.");
                        //this.innerHTML = "Your browser doesn't seem to support generic sensors. If you are running Chrome, please enable it in about:flags";
                }
	        //var options = {mimeType: 'video/webm;codecs=vp9'};
		//mediaRecorder = new MediaRecorder(stream, options);
		mediaRecorder = new MediaRecorder(stream);

	        mediaRecorder.start(10);

	        var url = window.URL;
	        videoElement.src = url ? url.createObjectURL(stream) : stream;
                //videoElement.play();

	        mediaRecorder.ondataavailable = function(e) {
                        //console.log("Data available", e);
                        //console.log(time);
                        timestamps.push(time);
                        frameData.time = time;
		        chunks.push(e.data);
                        frameData.data = e.data;
                        orientationData.push(ori);
                        frameData.ori = ori;
                        var b = new Object;     //need to push by value
                        Object.assign(b, frameData);
                        dataArray.push(b);
	        };

	        mediaRecorder.onerror = function(e){
		        console.log('Error: ', e);
	        };

	        mediaRecorder.onstart = function(){
                        console.log("Recording started", mediaRecorder.state);
	        };

	        mediaRecorder.onstop = function(){
		        var blob = new Blob(chunks, {type: "video/webm"});
		        chunks = [];

		        var videoURL = window.URL.createObjectURL(blob);

		        videoElement.src = videoURL;
                        //videoElement.load();

                        //resize canvas
videoElement.addEventListener('loadedmetadata', function() {
  canvas.width = videoElement.videoWidth;
  canvas.height = videoElement.videoHeight;
});

                        /*//Read blob data so we can stabilize the video
                        var reader = new FileReader();
                         reader.onload = function(event){
                                let text = reader.result;
                                console.log(text);
                          };
                        reader.readAsText(blob, "video/webm");*/
                        //console.log(orientationData);
                        //console.log(timestamps);
                        //console.log(dataArray);
/*
var blobUrl = URL.createObjectURL(blob);
var x = new XMLHttpRequest();
// set x.responseType = 'blob' if you want to get a Blob object:
// x.responseType = 'blob';
x.onload = function() {
    alert(x.responseText);
};
console.log(x.open('get', blobUrl));*/
                        readFrameData(blob, orientationData);    //reads the video into dataArray2
                        /*videoElement.onended = function() {
                                alert("The video has ended");
                                cancelAnimationFrame(ref);
                        };*/
                        //ctx.clearRect(0, 0, canvas.width, canvas.height);
                        //stabilize(dataArray2);        //now we can operate on it
                        interval=window.setInterval(update_debug,100);
	        };

	        mediaRecorder.onpause = function(){
	        }

	        mediaRecorder.onresume = function(){
	        }

	        mediaRecorder.onwarning = function(e){
	        };
}

function stopRecording(){
	mediaRecorder.stop();
        //Now stabilize
	videoElement.controls = true;
}
//Idea: copy video to canvas, operate on the video, and then use the canvas with the stabilized video as source for the video element
function readFrameData(blob, oriArray) {     //Read video data from blob to object form with pixel data we can operate on
        //console.log("frame");

        nFrame = videoElement.webkitDecodedFrameCount - extraFrames;
        //console.log(videoElement.webkitDecodedFrameCount);      //only works in webkit browsers
        //console.log(timestamps[nFrame] - timestamps[0], videoElement.currentTime);
        //while(!videoElement.ended)
        //{
        let dx = 0;
        let dy = 0;
        let oriDiff = null;
                //videoElement.playbackRate = 0.5;        //fix playback being too fast
                let ori = orientationData[nFrame];
                if(ori !== undefined)
                {
                        oriDiff = {"roll": ori.roll-oriInitial.roll, "pitch": ori.pitch-oriInitial.pitch, "yaw": ori.yaw-oriInitial.yaw};
                        dx = videoElement.videoWidth*(oriDiff.yaw/(2*Math.PI));
                        //x = 100*oriDiff.yaw;
                        dy = -videoElement.videoHeight*(oriDiff.roll/(2*Math.PI));     //each 2pi means 1 video height
                        //y = 100*oriDiff.roll;
                }
                else
                {
                        dx = 0;
                        dy = 0;
                }
                //console.log(x, y);
                let widthR = 0.8*canvas.width;
                let heightR = 0.8*canvas.height;
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                ctx.drawImage(videoElement,0,0, videoElement.videoWidth, videoElement.videoHeight);
                ctx.beginPath();
                ctx.rect(dx+0.1*canvas.width,dy+0.1*canvas.height,widthR,heightR);
                ctx.stroke();

                //ctx.drawImage(videoElement, 0, 0);
                //let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                /*let pixeldataArray = [];
                //loop through every pixel
                for(let i=0; i<imageData.data.length; i = i+4)
                {
                        let pixeldata = {"red": imageData.data[i], "green":imageData.data[i+1], "blue": imageData.data[i+2], "alpha":imageData.data[i+3]};
                        //pixeldataArray.push(pixeldata);
                }
                //pixeldataArray.push(imageData);*/
                if(ori !== undefined) {
                        //let timestamp = dataArray[nFrame].time;
                        //let frameData2 = {"imagedata": imageData, "time": timestamp, "oridiff": oriDiff};
                        //dataArray2.push(frameData2);
                        //console.log(pixeldataArray);
                        //newImageData.data = data;
                    // Draw the pixels onto the visible canvas
                    //ctx.putImageData(newImageData,0,0);
                        //ctx.putImageData(imageData, 0, 0)
                        //xD
                }
        //}
                //nFrame = nFrame + 1;
                ref = requestAnimationFrame(readFrameData);
        /*
        if(dataArray2.length === timestamps.length)     //now we have read the whole blob - should use callback here instead of if condition
        {
                console.log("ended");
                cancelAnimationFrame(ref);
                console.log(dataArray2);
                stabilize(dataArray2);
        } */
        if(videoElement.ended)
        {
                console.log("ended");
        }
        if(nFrame >= orientationData.length-1)
        {
                extraFrames = extraFrames + nFrame;
                nFrame = 0;
                //cancelAnimationFrame(ref);
        }
}

function stabilize(dataArrayArg) { //Create a stabilized video from the pixel data given as input
        let frame = dataArrayArg[0];      //first frame
        console.log(frame);
        //ctx.drawImage(frame.imagedata,0,0, videoElement.videoWidth, videoElement.videoHeight);
        //ctx.putImageData(frame.imagedata, 0, 0);
}
<commit_msg>Gyro fix<commit_after>/*
 * Websensor video stabilization project
 * https://github.com/jessenie-intel/websensor-video
 *
 * Copyright (c) 2017 Jesse Nieminen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

'use strict';

var constraints = {audio: true,video: {  width: { min: 640, ideal: 640, max: 640 },  height: { min: 480, ideal: 480, max: 480 }}};
var mediaRecorder = null;
var chunks = [];
var videoData = null;
var interval = null;

var accel_sensor = null;
var orientation_sensor = null;
var gyroscope = null;
var sensorfreq = 60;

//var roll = null;
//var pitch = null;
//var yaw = null;
var accel = {"x": null, "y": null, "z": null};
var velGyro = {"x": null, "y": null, "z": null};
var ori = {"roll": null, "pitch": null, "yaw": null, "time": null};
var oriInitial = {"roll": null, "pitch": null, "yaw": null, "time": null};
var initialoriobtained = false;
var orientationData = [];       //array to store all the orientation data
var frameData = {"data": null, "time": null, "ori": null};
var dataArray = [];     //array to store all the combined data
var dataArray2 = [];     //array to store all the combined data

var time = null;
var timestamps = [];
var nFrame = 0; //frame number with which we can combine timestamp and frame data

//canvas
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');

//video element
var videoElement = document.querySelector('video');
videoElement.controls = false;

var ref = null;
var extraFrames = 0;

class AbsOriSensor {
        constructor() {
        const sensor = new AbsoluteOrientationSensor({ frequency: sensorfreq });
        const mat4 = new Float32Array(16);
        const euler = new Float32Array(3);
        sensor.onreading = () => {
                sensor.populateMatrix(mat4);
                toEulerianAngle(sensor.quaternion, euler);      //From quaternion to Eulerian angles
                this.roll = euler[0];
                this.pitch = euler[1];
                this.yaw = euler[2];
                this.timestamp = sensor.timestamp;
                if (this.onreading) this.onreading();
        };
        sensor.onactivate = () => {
                if (this.onactivate) this.onactivate();
        };
        const start = () => sensor.start();
        Object.assign(this, { start });
        }
}

function update_debug()
{
                        document.getElementById("ori").textContent = `${ori.roll} ${ori.pitch} ${ori.yaw}`;
                        document.getElementById("accel").textContent = `${accel.x} ${accel.y} ${accel.z}`;
                        document.getElementById("rrate").textContent = `${velGyro.x} ${velGyro.y} ${velGyro.z}`;
}

//WINDOWS 10 HAS DIFFERENT CONVENTION: Yaw z, pitch x, roll y
function toEulerianAngle(quat, out)
{
        const ysqr = quat[1] ** 2;

        // Roll (x-axis rotation).
        const t0 = 2 * (quat[3] * quat[0] + quat[1] * quat[2]);
        const t1 = 1 - 2 * (ysqr + quat[0] ** 2);
        out[0] = Math.atan2(t0, t1);
        // Pitch (y-axis rotation).
        let t2 = 2 * (quat[3] * quat[1] - quat[2] * quat[0]);
        t2 = t2 > 1 ? 1 : t2;
        t2 = t2 < -1 ? -1 : t2;
        out[1] = Math.asin(t2);
        // Yaw (z-axis rotation).
        const t3 = 2 * (quat[3] * quat[2] + quat[0] * quat[1]);
        const t4 = 1 - 2 * (ysqr + quat[2] ** 2);
        out[2] = Math.atan2(t3, t4);
        return out;
}

function errorCallback(error){
	console.log("error: ", error);
}

function startDemo () {
		navigator.getUserMedia(constraints, startRecording, errorCallback);
}

function startRecording(stream) {

                try {
                //Initialize sensors
                accel_sensor = new Accelerometer();
                accel_sensor.onreading = () => {
                        accel = {"x": accel_sensor.x, "y": accel_sensor.y, "z": accel_sensor.z};
                };
                accel_sensor.onactivate = () => {
                };
                accel_sensor.start();
                gyroscope = new Gyroscope();
                gyroscope.onreading = () => {
                        velGyro = {x:gyroscope.x, y:gyroscope.y, z:gyroscope.z};
                };
                gyroscope.onactivate = () => {
                };
                gyroscope.start();
                orientation_sensor = new AbsOriSensor();
                orientation_sensor.onreading = () => {
                        let roll = orientation_sensor.roll;
                        let pitch = orientation_sensor.pitch;
                        let yaw = orientation_sensor.yaw;
                        time = orientation_sensor.timestamp;
                        if(!initialoriobtained) //obtain initial orientation
                        {
                                oriInitial = {"roll": orientation_sensor.roll, "pitch": orientation_sensor.pitch, "yaw": orientation_sensor.yaw, "time": orientation_sensor.timestamp};
                                initialoriobtained = true;
                        }
                        ori = {"roll": orientation_sensor.roll, "pitch": orientation_sensor.pitch, "yaw": orientation_sensor.yaw, "time": orientation_sensor.timestamp};
                };
                orientation_sensor.onactivate = () => {
                };
                orientation_sensor.start();
                }
                catch(err) {
                        console.log(err.message);
                        console.log("Your browser doesn't seem to support generic sensors. If you are running Chrome, please enable it in about:flags.");
                        //this.innerHTML = "Your browser doesn't seem to support generic sensors. If you are running Chrome, please enable it in about:flags";
                }
	        //var options = {mimeType: 'video/webm;codecs=vp9'};
		//mediaRecorder = new MediaRecorder(stream, options);
		mediaRecorder = new MediaRecorder(stream);

	        mediaRecorder.start(10);

	        var url = window.URL;
	        videoElement.src = url ? url.createObjectURL(stream) : stream;
                //videoElement.play();

	        mediaRecorder.ondataavailable = function(e) {
                        //console.log("Data available", e);
                        //console.log(time);
                        timestamps.push(time);
                        frameData.time = time;
		        chunks.push(e.data);
                        frameData.data = e.data;
                        orientationData.push(ori);
                        frameData.ori = ori;
                        var b = new Object;     //need to push by value
                        Object.assign(b, frameData);
                        dataArray.push(b);
	        };

	        mediaRecorder.onerror = function(e){
		        console.log('Error: ', e);
	        };

	        mediaRecorder.onstart = function(){
                        console.log("Recording started", mediaRecorder.state);
	        };

	        mediaRecorder.onstop = function(){
		        var blob = new Blob(chunks, {type: "video/webm"});
		        chunks = [];

		        var videoURL = window.URL.createObjectURL(blob);

		        videoElement.src = videoURL;
                        //videoElement.load();

                        //resize canvas
videoElement.addEventListener('loadedmetadata', function() {
  canvas.width = videoElement.videoWidth;
  canvas.height = videoElement.videoHeight;
});

                        /*//Read blob data so we can stabilize the video
                        var reader = new FileReader();
                         reader.onload = function(event){
                                let text = reader.result;
                                console.log(text);
                          };
                        reader.readAsText(blob, "video/webm");*/
                        //console.log(orientationData);
                        //console.log(timestamps);
                        //console.log(dataArray);
/*
var blobUrl = URL.createObjectURL(blob);
var x = new XMLHttpRequest();
// set x.responseType = 'blob' if you want to get a Blob object:
// x.responseType = 'blob';
x.onload = function() {
    alert(x.responseText);
};
console.log(x.open('get', blobUrl));*/
                        readFrameData(blob, orientationData);    //reads the video into dataArray2
                        /*videoElement.onended = function() {
                                alert("The video has ended");
                                cancelAnimationFrame(ref);
                        };*/
                        //ctx.clearRect(0, 0, canvas.width, canvas.height);
                        //stabilize(dataArray2);        //now we can operate on it
                        interval=window.setInterval(update_debug,100);
	        };

	        mediaRecorder.onpause = function(){
	        }

	        mediaRecorder.onresume = function(){
	        }

	        mediaRecorder.onwarning = function(e){
	        };
}

function stopRecording(){
	mediaRecorder.stop();
        //Now stabilize
	videoElement.controls = true;
}
//Idea: copy video to canvas, operate on the video, and then use the canvas with the stabilized video as source for the video element
function readFrameData(blob, oriArray) {     //Read video data from blob to object form with pixel data we can operate on
        //console.log("frame");

        nFrame = videoElement.webkitDecodedFrameCount - extraFrames;
        //console.log(videoElement.webkitDecodedFrameCount);      //only works in webkit browsers
        //console.log(timestamps[nFrame] - timestamps[0], videoElement.currentTime);
        //while(!videoElement.ended)
        //{
        let dx = 0;
        let dy = 0;
        let oriDiff = null;
                //videoElement.playbackRate = 0.5;        //fix playback being too fast
                let ori = orientationData[nFrame];
                if(ori !== undefined)
                {
                        oriDiff = {"roll": ori.roll-oriInitial.roll, "pitch": ori.pitch-oriInitial.pitch, "yaw": ori.yaw-oriInitial.yaw};
                        dx = videoElement.videoWidth*(oriDiff.yaw/(2*Math.PI));
                        //x = 100*oriDiff.yaw;
                        dy = -videoElement.videoHeight*(oriDiff.roll/(2*Math.PI));     //each 2pi means 1 video height
                        //y = 100*oriDiff.roll;
                }
                else
                {
                        dx = 0;
                        dy = 0;
                }
                //console.log(x, y);
                let widthR = 0.8*canvas.width;
                let heightR = 0.8*canvas.height;
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                ctx.drawImage(videoElement,0,0, videoElement.videoWidth, videoElement.videoHeight);
                ctx.beginPath();
                ctx.rect(dx+0.1*canvas.width,dy+0.1*canvas.height,widthR,heightR);
                ctx.stroke();

                //ctx.drawImage(videoElement, 0, 0);
                //let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                /*let pixeldataArray = [];
                //loop through every pixel
                for(let i=0; i<imageData.data.length; i = i+4)
                {
                        let pixeldata = {"red": imageData.data[i], "green":imageData.data[i+1], "blue": imageData.data[i+2], "alpha":imageData.data[i+3]};
                        //pixeldataArray.push(pixeldata);
                }
                //pixeldataArray.push(imageData);*/
                if(ori !== undefined) {
                        //let timestamp = dataArray[nFrame].time;
                        //let frameData2 = {"imagedata": imageData, "time": timestamp, "oridiff": oriDiff};
                        //dataArray2.push(frameData2);
                        //console.log(pixeldataArray);
                        //newImageData.data = data;
                    // Draw the pixels onto the visible canvas
                    //ctx.putImageData(newImageData,0,0);
                        //ctx.putImageData(imageData, 0, 0)
                        //xD
                }
        //}
                //nFrame = nFrame + 1;
                ref = requestAnimationFrame(readFrameData);
        /*
        if(dataArray2.length === timestamps.length)     //now we have read the whole blob - should use callback here instead of if condition
        {
                console.log("ended");
                cancelAnimationFrame(ref);
                console.log(dataArray2);
                stabilize(dataArray2);
        } */
        if(videoElement.ended)
        {
                console.log("ended");
        }
        if(nFrame >= orientationData.length-1)
        {
                extraFrames = extraFrames + nFrame;
                nFrame = 0;
                //cancelAnimationFrame(ref);
        }
}

function stabilize(dataArrayArg) { //Create a stabilized video from the pixel data given as input
        let frame = dataArrayArg[0];      //first frame
        console.log(frame);
        //ctx.drawImage(frame.imagedata,0,0, videoElement.videoWidth, videoElement.videoHeight);
        //ctx.putImageData(frame.imagedata, 0, 0);
}
<|endoftext|>


<commit_before>function solve(args) {
	var a = +args[0],
		b = +args[1];

}
<commit_msg>Delete script.js<commit_after><|endoftext|>


<commit_before>'use strict';

nyplViewer.controller('SettingsDialogCtrl',
  function ($mdDialog, lodash, DatabaseConnection, $q, NyplApiCalls, $mdToast, FirebaseStorageModel) {
    var ctrl = this;
    ctrl.readonly = false;
    ctrl.selectedItem = null;
    ctrl.searchText = '';
    ctrl.autocompleteDemoRequireMatch = true;
    ctrl.themes = [];
    ctrl.isResultsForNewThemeItem = false;
    ctrl.isSearchRun = false;
    ctrl.newThemeItemName = '';
    ctrl.newThemeItemResultCount = 0;
    ctrl.isLoadingDone = true;
    ctrl.isEditingTheme = false;
    ctrl.isNew = false;

    ctrl.theme = undefined;

    ctrl.newTheme = {
      isDefault: false,
      name: '',
      items: [
      ]
    };

    ctrl.newThemeItem = {
      search: '',
      page: 1,
      totalPages: 0,
      isPageInfoRetrieved: false,
    };

    ctrl.addTheme = function () {
      ctrl.isNew = true;
    }

    ctrl.filter = function (searchStr) {
      var results = lodash.filter(ctrl.themes, function (theme) { return theme.name.indexOf(searchStr) > -1; });
      return results;
    }

    ctrl.getThemes = function () {
      ctrl.themes = [];
      DatabaseConnection.getThemes().then(function (results) { // first get user's themes
        lodash.forEach(results, function (value, key) {
          value['id'] = key
          value['isDefault'] = false;
          ctrl.themes.push(value);
        });
      })
      FirebaseStorageModel.getDefaultThemes().then(function (results) { // then get default themes
        lodash.forEach(results, function (value, key) {
          value['id'] = key
          value['isDefault'] = true;
          ctrl.themes.push(value);
        });
      })
    }

    ctrl.showToast = function (text) {
      $mdToast.show(
        $mdToast.simple()
          .textContent(text)
          .position('top right')
          .hideDelay(1500)
      );
    };

    ctrl.isDuplicateObject = function (collectionToCheck, key, value) {
      return (lodash.find(collectionToCheck, function (obj) { return obj[key] == value; }));
    }

    ctrl.isDuplicateArrayElement = function (array, value) {
      return (lodash.find(array, function (ele) { return ele == value; }) != undefined);
    }

    ctrl.addThemeItem = function () {
      if (!ctrl.isDuplicateObject(ctrl.newTheme.items, 'search', ctrl.newThemeItem.search)) {
        ctrl.newTheme.items.push(ctrl.newThemeItem);
        ctrl.newThemeItem = {
          search: '',
          page: 1,
          totalPages: 0,
          isPageInfoRetrieved: false,
        };
        ctrl.isSearchRun = false;
        ctrl.isResultsForNewThemeItem = false;
      }
      else {
        ctrl.showToast('Theme item already in your theme!');
      }
    }

    ctrl.saveTheme = function () {
      if (ctrl.newTheme.name === '') {
        ctrl.showToast('Theme name not entered. Save failed!');
        return;
      }
      if (ctrl.newTheme.items.length < 1) {
        ctrl.showToast('No new theme items present. Save failed!');
        return;
      }
      if (ctrl.newTheme.items.length < 2) {
        ctrl.showToast('A new theme must have at lease 2 theme items. Save failed!');
        return;
      }
      if (!ctrl.isDuplicateObject(ctrl.themes, 'name', ctrl.newTheme.name) || ctrl.isEditing) {
        var themeStr = angular.toJson(ctrl.newTheme);
        var themeJson = JSON.parse(themeStr); // Workaround to strip $$hash key from the properties
        if (ctrl.isEditing) {
          if (themeJson.isDefault) {
            FirebaseStorageModel.editDefaultTheme(themeJson);
          } else {
            DatabaseConnection.editTheme(themeJson);
          }
          ctrl.isEditing = false;
        } else {
          DatabaseConnection.createTheme(themeJson);
          ctrl.isNew = false;
        }
        ctrl.newTheme = {
          isDefault: false,
          name: '',
          items: [
          ]
        };

        ctrl.newThemeItem = {
          search: '',
          page: 1,
          totalPages: 0,
          isPageInfoRetrieved: false,
        };
        ctrl.getThemes();
        ctrl.showToast('Theme sucessfully saved to favorites.');
      }
      else {
        ctrl.showToast('A theme with that name already exists in your favorites!');
      }

    }

    ctrl.newThemeItemSearchChange = function () {
      ctrl.isSearchRun = false;
      ctrl.isResultsForNewThemeItem = false;
      if (ctrl.newThemeItem.search != '') {
        ctrl.isSearchRun = false;
        ctrl.isLoadingDone = false;
        NyplApiCalls.nyplSearch(ctrl.newThemeItem.search, 1).then(function (results) {
          var numResults = results.data.nyplAPI.response.numResults;
          if (numResults > 0) {
            ctrl.newThemeItemResultCount = numResults;
            ctrl.isResultsForNewThemeItem = true;
          }
          ctrl.isLoadingDone = true;
          ctrl.isSearchRun = true;
        })
      }
    }

    ctrl.loadSelectedTheme = function () {
      deferred = $q.defer();
      if (ctrl.theme != undefined) {
        deferred.resolve();
      } else {
        DatabaseConnection.getUserInfo().then(function (user) {
          if (user.selectedTheme == null) {
            console.log('No selected theme for this user!');
          } else {
            ctrl.theme = user.selectedTheme;
            ctrl.searchText = ctrl.theme.name;
          }
          deferred.resolve();
        })
      }
      return deferred.promise;
    }

    ctrl.editTheme = function () {
      if (ctrl.theme != undefined) {
        ctrl.newTheme = ctrl.theme;
        ctrl.isEditing = true;
      }
    }

    ctrl.deleteTheme = function () {
      if (ctrl.theme != undefined) {
        DatabaseConnection.deleteSelectedTheme(ctrl.theme);
        ctrl.showToast('Theme deleted.');
      }
    }

    ctrl.selectedItemChange = function (value) {
      ctrl.theme = value;
    }

    ctrl.searchTextChange = function (searchText) {

    }

    ctrl.hide = function () {
      $mdDialog.hide();
    };

    ctrl.cancel = function () {
      $mdDialog.hide();
    };

    ctrl.save = function () {
      if (ctrl.theme != undefined) {
        DatabaseConnection.saveSelectedTheme(ctrl.theme);
        $mdDialog.hide();
      } else {
        ctrl.showToast('No theme selected. Save failed!');
      }

    };

    ctrl.loadSelectedTheme();
    ctrl.getThemes();

  });<commit_msg>fixed issue where selected theme wasn't saving<commit_after>'use strict';

nyplViewer.controller('SettingsDialogCtrl',
  function ($mdDialog, lodash, DatabaseConnection, $q, NyplApiCalls, $mdToast, FirebaseStorageModel) {
    var ctrl = this;
    ctrl.readonly = false;
    ctrl.selectedItem = null;
    ctrl.searchText = '';
    ctrl.autocompleteDemoRequireMatch = true;
    ctrl.themes = [];
    ctrl.isResultsForNewThemeItem = false;
    ctrl.isSearchRun = false;
    ctrl.newThemeItemName = '';
    ctrl.newThemeItemResultCount = 0;
    ctrl.isLoadingDone = true;
    ctrl.isEditingTheme = false;
    ctrl.isNew = false;

    ctrl.theme = undefined;

    ctrl.newTheme = {
      isDefault: false,
      name: '',
      items: [
      ]
    };

    ctrl.newThemeItem = {
      search: '',
      page: 1,
      totalPages: 0,
      isPageInfoRetrieved: false,
    };

    ctrl.addTheme = function () {
      ctrl.isNew = true;
    }

    ctrl.filter = function (searchStr) {
      var results = lodash.filter(ctrl.themes, function (theme) { return theme.name.indexOf(searchStr) > -1; });
      return results;
    }

    ctrl.getThemes = function () {
      ctrl.themes = [];
      DatabaseConnection.getThemes().then(function (results) { // first get user's themes
        lodash.forEach(results, function (value, key) {
          value['id'] = key
          value['isDefault'] = false;
          ctrl.themes.push(value);
        });
      })
      FirebaseStorageModel.getDefaultThemes().then(function (results) { // then get default themes
        lodash.forEach(results, function (value, key) {
          value['id'] = key
          value['isDefault'] = true;
          ctrl.themes.push(value);
        });
      })
    }

    ctrl.showToast = function (text) {
      $mdToast.show(
        $mdToast.simple()
          .textContent(text)
          .position('top right')
          .hideDelay(1500)
      );
    };

    ctrl.isDuplicateObject = function (collectionToCheck, key, value) {
      return (lodash.find(collectionToCheck, function (obj) { return obj[key] == value; }));
    }

    ctrl.isDuplicateArrayElement = function (array, value) {
      return (lodash.find(array, function (ele) { return ele == value; }) != undefined);
    }

    ctrl.addThemeItem = function () {
      if (!ctrl.isDuplicateObject(ctrl.newTheme.items, 'search', ctrl.newThemeItem.search)) {
        ctrl.newTheme.items.push(ctrl.newThemeItem);
        ctrl.newThemeItem = {
          search: '',
          page: 1,
          totalPages: 0,
          isPageInfoRetrieved: false,
        };
        ctrl.isSearchRun = false;
        ctrl.isResultsForNewThemeItem = false;
      }
      else {
        ctrl.showToast('Theme item already in your theme!');
      }
    }

    ctrl.saveTheme = function () {
      if (ctrl.newTheme.name === '') {
        ctrl.showToast('Theme name not entered. Save failed!');
        return;
      }
      if (ctrl.newTheme.items.length < 1) {
        ctrl.showToast('No new theme items present. Save failed!');
        return;
      }
      if (ctrl.newTheme.items.length < 2) {
        ctrl.showToast('A new theme must have at lease 2 theme items. Save failed!');
        return;
      }
      if (!ctrl.isDuplicateObject(ctrl.themes, 'name', ctrl.newTheme.name) || ctrl.isEditing) {
        var themeStr = angular.toJson(ctrl.newTheme);
        var themeJson = JSON.parse(themeStr); // Workaround to strip $$hash key from the properties
        if (ctrl.isEditing) {
          if (themeJson.isDefault) {
            FirebaseStorageModel.editDefaultTheme(themeJson);
          } else {
            DatabaseConnection.editTheme(themeJson);
          }
          ctrl.isEditing = false;
        } else {
          DatabaseConnection.createTheme(themeJson);
          ctrl.isNew = false;
        }
        ctrl.newTheme = {
          isDefault: false,
          name: '',
          items: [
          ]
        };

        ctrl.newThemeItem = {
          search: '',
          page: 1,
          totalPages: 0,
          isPageInfoRetrieved: false,
        };
        ctrl.getThemes();
        ctrl.showToast('Theme sucessfully saved to favorites.');
      }
      else {
        ctrl.showToast('A theme with that name already exists in your favorites!');
      }

    }

    ctrl.newThemeItemSearchChange = function () {
      ctrl.isSearchRun = false;
      ctrl.isResultsForNewThemeItem = false;
      if (ctrl.newThemeItem.search != '') {
        ctrl.isSearchRun = false;
        ctrl.isLoadingDone = false;
        NyplApiCalls.nyplSearch(ctrl.newThemeItem.search, 1).then(function (results) {
          var numResults = results.data.nyplAPI.response.numResults;
          if (numResults > 0) {
            ctrl.newThemeItemResultCount = numResults;
            ctrl.isResultsForNewThemeItem = true;
          }
          ctrl.isLoadingDone = true;
          ctrl.isSearchRun = true;
        })
      }
    }

    ctrl.loadSelectedTheme = function () {
      deferred = $q.defer();
      if (ctrl.theme != undefined) {
        deferred.resolve();
      } else {
        DatabaseConnection.getUserInfo().then(function (user) {
          if (user.selectedTheme == null) {
            console.log('No selected theme for this user!');
          } else {
            ctrl.theme = user.selectedTheme;
            ctrl.searchText = ctrl.theme.name;
          }
          deferred.resolve();
        })
      }
      return deferred.promise;
    }

    ctrl.editTheme = function () {
      if (ctrl.theme != undefined) {
        ctrl.newTheme = ctrl.theme;
        ctrl.isEditing = true;
      }
    }

    ctrl.deleteTheme = function () {
      if (ctrl.theme != undefined) {
        DatabaseConnection.deleteSelectedTheme(ctrl.theme);
        ctrl.showToast('Theme deleted.');
      }
    }

    ctrl.selectedItemChange = function (value) {
      ctrl.theme = value;
    }

    ctrl.searchTextChange = function (searchText) {

    }

    ctrl.hide = function () {
      $mdDialog.hide();
    };

    ctrl.cancel = function () {
      $mdDialog.hide();
    };

    ctrl.save = function () {
      if (ctrl.theme != undefined) {
        var themeStr = angular.toJson(ctrl.theme);
        var themeJson = JSON.parse(themeStr); // Workaround to strip $$hash key from the properties
        DatabaseConnection.saveSelectedTheme(themeJson);
        $mdDialog.hide();
      } else {
        ctrl.showToast('No theme selected. Save failed!');
      }

    };

    ctrl.loadSelectedTheme();
    ctrl.getThemes();

  });<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

/*
* When adding names to the namespace, ensure that they are added in alphabetical order according to alias (namespace key).
*/

var ns = [];

ns.push({
	'alias': 'GAMMA_LANCZOS_G',
	'path': '@stdlib/constants/math/float64-gamma-lanczos-g',
	'value': require( '@stdlib/constants/math/float64-gamma-lanczos-g' ),
	'type': 'number',
	'related': []
});

ns.push({
	'alias': 'getegid',
	'path': '@stdlib/process/getegid',
	'value': require( '@stdlib/process/getegid' ),
	'type': 'Function',
	'related': [
		'@stdlib/process/geteuid',
		'@stdlib/process/getgid',
		'@stdlib/process/getuid',
		'@stdlib/process/setegid',
		'@stdlib/process/seteuid',
		'@stdlib/process/setuid'
	]
});

ns.push({
	'alias': 'geteuid',
	'path': '@stdlib/process/geteuid',
	'value': require( '@stdlib/process/geteuid' ),
	'type': 'Function',
	'related': [
		'@stdlib/process/getegid',
		'@stdlib/process/getgid',
		'@stdlib/process/getuid',
		'@stdlib/process/setegid',
		'@stdlib/process/seteuid',
		'@stdlib/process/setuid'
	]
});

ns.push({
	'alias': 'getgid',
	'path': '@stdlib/process/getgid',
	'value': require( '@stdlib/process/getgid' ),
	'type': 'Function',
	'related': [
		'@stdlib/process/getegid',
		'@stdlib/process/geteuid',
		'@stdlib/process/getuid',
		'@stdlib/process/setegid',
		'@stdlib/process/seteuid',
		'@stdlib/process/setuid'
	]
});

ns.push({
	'alias': 'getGlobal',
	'path': '@stdlib/utils/global',
	'value': require( '@stdlib/utils/global' ),
	'type': 'Function',
	'related': []
});

ns.push({
	'alias': 'getPrototypeOf',
	'path': '@stdlib/utils/get-prototype-of',
	'value': require( '@stdlib/utils/get-prototype-of' ),
	'type': 'Function',
	'related': [
		'@stdlib/assert/has-prototype'
	]
});

ns.push({
	'alias': 'getuid',
	'path': '@stdlib/process/getuid',
	'value': require( '@stdlib/process/getuid' ),
	'type': 'Function',
	'related': [
		'@stdlib/process/getegid',
		'@stdlib/process/geteuid',
		'@stdlib/process/getgid',
		'@stdlib/process/setegid',
		'@stdlib/process/seteuid',
		'@stdlib/process/setuid'
	]
});

ns.push({
	'alias': 'GLAISHER',
	'path': '@stdlib/constants/math/float64-glaisher-kinkelin',
	'value': require( '@stdlib/constants/math/float64-glaisher-kinkelin' ),
	'type': 'number',
	'related': []
});

ns.push({
	'alias': 'group',
	'path': '@stdlib/utils/group',
	'value': require( '@stdlib/utils/group' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/bifurcate',
		'@stdlib/utils/count-by',
		'@stdlib/utils/group-by'
	]
});

ns.push({
	'alias': 'groupBy',
	'path': '@stdlib/utils/group-by',
	'value': require( '@stdlib/utils/group-by' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/bifurcate-by',
		'@stdlib/utils/count-by',
		'@stdlib/utils/group'
	]
});

ns.push({
	'alias': 'groupByAsync',
	'path': '@stdlib/utils/group-by-async',
	'value': require( '@stdlib/utils/group-by-async' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/bifurcate-by-async',
		'@stdlib/utils/count-by-async',
		'@stdlib/utils/group-by'
	]
});

ns.push({
	'alias': 'groupIn',
	'path': '@stdlib/utils/group-in',
	'value': require( '@stdlib/utils/group-in' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/bifurcate-in',
		'@stdlib/utils/count-in',
		'@stdlib/utils/group-by',
		'@stdlib/utils/group-own'
	]
});

ns.push({
	'alias': 'groupOwn',
	'path': '@stdlib/utils/group-own',
	'value': require( '@stdlib/utils/group-own' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/bifurcate-own',
		'@stdlib/utils/count-own',
		'@stdlib/utils/group',
		'@stdlib/utils/group-by'
	]
});

// EXPORTS //

module.exports = ns;
<commit_msg>Add function to REPL namespace<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

/*
* When adding names to the namespace, ensure that they are added in alphabetical order according to alias (namespace key).
*/

var ns = [];

ns.push({
	'alias': 'GAMMA_LANCZOS_G',
	'path': '@stdlib/constants/math/float64-gamma-lanczos-g',
	'value': require( '@stdlib/constants/math/float64-gamma-lanczos-g' ),
	'type': 'number',
	'related': []
});

ns.push({
	'alias': 'getegid',
	'path': '@stdlib/process/getegid',
	'value': require( '@stdlib/process/getegid' ),
	'type': 'Function',
	'related': [
		'@stdlib/process/geteuid',
		'@stdlib/process/getgid',
		'@stdlib/process/getuid',
		'@stdlib/process/setegid',
		'@stdlib/process/seteuid',
		'@stdlib/process/setuid'
	]
});

ns.push({
	'alias': 'geteuid',
	'path': '@stdlib/process/geteuid',
	'value': require( '@stdlib/process/geteuid' ),
	'type': 'Function',
	'related': [
		'@stdlib/process/getegid',
		'@stdlib/process/getgid',
		'@stdlib/process/getuid',
		'@stdlib/process/setegid',
		'@stdlib/process/seteuid',
		'@stdlib/process/setuid'
	]
});

ns.push({
	'alias': 'getgid',
	'path': '@stdlib/process/getgid',
	'value': require( '@stdlib/process/getgid' ),
	'type': 'Function',
	'related': [
		'@stdlib/process/getegid',
		'@stdlib/process/geteuid',
		'@stdlib/process/getuid',
		'@stdlib/process/setegid',
		'@stdlib/process/seteuid',
		'@stdlib/process/setuid'
	]
});

ns.push({
	'alias': 'getGlobal',
	'path': '@stdlib/utils/global',
	'value': require( '@stdlib/utils/global' ),
	'type': 'Function',
	'related': []
});

ns.push({
	'alias': 'getOwnPropertyNames',
	'path': '@stdlib/utils/own-property-names',
	'value': require( '@stdlib/utils/own-property-names' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/keys'
	]
});

ns.push({
	'alias': 'getPrototypeOf',
	'path': '@stdlib/utils/get-prototype-of',
	'value': require( '@stdlib/utils/get-prototype-of' ),
	'type': 'Function',
	'related': [
		'@stdlib/assert/has-prototype'
	]
});

ns.push({
	'alias': 'getuid',
	'path': '@stdlib/process/getuid',
	'value': require( '@stdlib/process/getuid' ),
	'type': 'Function',
	'related': [
		'@stdlib/process/getegid',
		'@stdlib/process/geteuid',
		'@stdlib/process/getgid',
		'@stdlib/process/setegid',
		'@stdlib/process/seteuid',
		'@stdlib/process/setuid'
	]
});

ns.push({
	'alias': 'GLAISHER',
	'path': '@stdlib/constants/math/float64-glaisher-kinkelin',
	'value': require( '@stdlib/constants/math/float64-glaisher-kinkelin' ),
	'type': 'number',
	'related': []
});

ns.push({
	'alias': 'group',
	'path': '@stdlib/utils/group',
	'value': require( '@stdlib/utils/group' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/bifurcate',
		'@stdlib/utils/count-by',
		'@stdlib/utils/group-by'
	]
});

ns.push({
	'alias': 'groupBy',
	'path': '@stdlib/utils/group-by',
	'value': require( '@stdlib/utils/group-by' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/bifurcate-by',
		'@stdlib/utils/count-by',
		'@stdlib/utils/group'
	]
});

ns.push({
	'alias': 'groupByAsync',
	'path': '@stdlib/utils/group-by-async',
	'value': require( '@stdlib/utils/group-by-async' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/bifurcate-by-async',
		'@stdlib/utils/count-by-async',
		'@stdlib/utils/group-by'
	]
});

ns.push({
	'alias': 'groupIn',
	'path': '@stdlib/utils/group-in',
	'value': require( '@stdlib/utils/group-in' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/bifurcate-in',
		'@stdlib/utils/count-in',
		'@stdlib/utils/group-by',
		'@stdlib/utils/group-own'
	]
});

ns.push({
	'alias': 'groupOwn',
	'path': '@stdlib/utils/group-own',
	'value': require( '@stdlib/utils/group-own' ),
	'type': 'Function',
	'related': [
		'@stdlib/utils/bifurcate-own',
		'@stdlib/utils/count-own',
		'@stdlib/utils/group',
		'@stdlib/utils/group-by'
	]
});

// EXPORTS //

module.exports = ns;
<|endoftext|>