Engine.Utils = class
{
/// <summary>
/// Current Time in MS as LONG
/// </summary>
/// <returns></returns>
static getTimer()
{
var date = new Date();
return date.getTime();
}
static initializeServerTime(serverTimeInSeconds)
{
UtilsStatics.serverTimeOffset = serverTimeInSeconds - Engine.Utils.nowTime();
}
static nowTimeServer()
{
return Engine.Utils.nowTime() + UtilsStatics.serverTimeOffset;
}
static getValueOrDefault(nullable, defaultValue)
{
if (nullable === undefined || nullable == null) return defaultValue;
return nullable;
}
/// <summary>
/// Current Time in Seconds as int
/// </summary>
/// <returns></returns>
static nowTime()
{
var date = new Date();
return date.getTime() / 1000;
}
static parseBigNumberString(number)
{
var match = UtilsStatics.bigNumberRegex.exec(number);
var magnitude = 0;
var thousands = 0;
var hundreds = 0;
if (number.indexOf('e') != -1 || number.indexOf('E') != -1)
{
return parseFloat(number);
}
if (match)
{
var mag = match[3];
magnitude = UtilsStatics.symbols.indexOf(mag);
if (match[1])
{
thousands = parseInt(match[1]);
if (match[2] && match[2] != "")
{ // if numbers are split by comma, multiply by 1000
thousands *= 1000;
}
}
else
{
thousands = 0;
}
hundreds = match[2] && match[2] != "" ? parseInt(match[2]) : 0;
}
return (thousands + hundreds) * Math.pow(1000, magnitude + 1);
}
static formatCountdown(timeRemaining, padHours)
{
if (padHours === undefined) padHours = true;
var cooldownRemaining = Math.floor(timeRemaining);
var hours = Math.floor(cooldownRemaining) / (60 * 60);
cooldownRemaining -= hours * 60 * 60;
var mins = Math.floor(cooldownRemaining) / 60;
cooldownRemaining -= mins * 60;
var seconds = Math.floor(cooldownRemaining);
var hoursStr = hours > 0 ? hours + ":" : "";
if (padHours && hours > 0 && hours < 10) hoursStr = "0" + hoursStr;
var minStr = "";
if (hours > 0 || mins > 0)
{
minStr = mins + ":";
if (mins < 10) minStr = "0" + minStr;
}
var secondsStr = seconds + "";
if (seconds < 10) secondsStr = "0" + secondsStr;
var countdown = hoursStr + minStr + secondsStr;
return countdown;
}
static formatFixedSizeCountdown(timeRemaining)
{
var cooldownRemaining = Math.floor(timeRemaining);
var hours = Math.floor(cooldownRemaining / (60 * 60));
cooldownRemaining -= hours * 60 * 60;
var mins = Math.floor(cooldownRemaining / 60);
cooldownRemaining -= mins * 60;
var seconds = Math.floor(cooldownRemaining);
var countdown = (hours < 10 ?"0":"") + hours + ":" + (mins < 10 ? "0" : "") + mins + ":" + (seconds < 10 ? "0" : "") + seconds;
return countdown;
}
static formatTime(seconds, show_seconds, abrv)
{
if (show_seconds === undefined) show_seconds = true;
if (abrv === undefined) abrv = false;
if (seconds < 60) show_seconds = true;
return Engine.Utils.formatTime2(Math.floor(seconds), show_seconds ? UtilsStatics.TimeResolution.Seconds : UtilsStatics.TimeResolution.Minutes, abrv);
}
static SetTimeStrings(dayParam, hourParam, minuteParam, secondParam, dayPlurParam, hourPlurParam, minutePlurParam, secondPlurParam,
dayAbrParam, hourAbrParam, minuteAbrParam, secondAbrParam)
{
UtilsStatics.day = dayParam;
UtilsStatics.hour = hourParam;
UtilsStatics.minute = minuteParam;
UtilsStatics.second = secondParam;
UtilsStatics.dayPlur = dayPlurParam;
UtilsStatics.hourPlur = hourPlurParam;
UtilsStatics.minutePlur = minutePlurParam;
UtilsStatics.secondPlur = secondPlurParam;
UtilsStatics.dayAbr = dayAbrParam;
UtilsStatics.hourAbr = hourAbrParam;
UtilsStatics.minuteAbr = minuteAbrParam;
UtilsStatics.secondAbr = secondAbrParam;
}
static formatTime2(timeInSeconds, maxRes, useAbbreviations, maxDivisions)
{
if (maxRes === undefined) maxRes = UtilsStatics.TimeResolution.Seconds;
if (useAbbreviations === undefined) useAbbreviations = false;
if (maxDivisions === undefined) maxDivisions = null;
var days = Math.floor(timeInSeconds / (60 * 60 * 24));
var timeRemaining = timeInSeconds - (days * 60 * 60 * 24);
var hours = Math.floor(timeRemaining / (60 * 60));
timeRemaining -= (hours * 60 * 60);
var minutes = Math.floor(timeRemaining / 60);
timeRemaining -= (minutes * 60);
var seconds = timeRemaining;
var dayNames = useAbbreviations ? { "First":UtilsStatics.dayAbr, "Second":UtilsStatics.dayAbr } : {"First":" "+ UtilsStatics.day + " ", "Second":" " + UtilsStatics.dayPlur + " "};
var hourNames = useAbbreviations ? { "First":UtilsStatics.hourAbr, "Second":UtilsStatics.hourAbr } : {"First":" " + UtilsStatics.hour + " ", "Second":" " + UtilsStatics.hourPlur + " "};
var minuteNames = useAbbreviations ? { "First":UtilsStatics.minuteAbr, "Second":UtilsStatics.minuteAbr } : {"First":" " + UtilsStatics.minute + " ", "Second":" " + UtilsStatics.minutePlur + " "};
var secondNames = useAbbreviations ? { "First":UtilsStatics.secondAbr, "Second":UtilsStatics.secondAbr } : {"First":" " + UtilsStatics.second + " ", "Second":" " + UtilsStatics.secondPlur + " "};
var divisionsUsed = 0;
var output = "";
if (days > 0 && maxRes >= UtilsStatics.TimeResolution.Days && (maxDivisions == null || divisionsUsed < maxDivisions))
{
output += days + (days == 1 ? dayNames.First : dayNames.Second);
divisionsUsed++;
}
if (hours > 0 && maxRes >= UtilsStatics.TimeResolution.Hours && (maxDivisions == null || divisionsUsed < maxDivisions))
{
output += hours + (hours == 1 ? hourNames.First : hourNames.Second);
divisionsUsed++;
}
if (minutes > 0 && maxRes >= UtilsStatics.TimeResolution.Minutes && (maxDivisions == null || divisionsUsed < maxDivisions))
{
output += minutes + (minutes == 1 ? minuteNames.First : minuteNames.Second);
divisionsUsed++;
}
if (seconds > 0 && maxRes >= UtilsStatics.TimeResolution.Seconds && (maxDivisions == null || divisionsUsed < maxDivisions))
{
output += seconds + (seconds == 1 ? secondNames.First : secondNames.Second);
divisionsUsed++;
}
return output.trim();
}
static formatBigNumber(number, round)
{
if (round === undefined) round = false;
if (!isFinite(number)) return "INF";
// If it's a small number with decimals, just return the number back
if (!round && number < 100 && (number - Math.floor(number) != 0))
{
var rounded = number < 0 ? Math.round(number * -1000) * -1 : Math.round(number * 1000); //Javascript rounds towards positive infinity, but we want to round away from zero
return "" + (rounded / 1000.0).toFixed(Engine.Utils.getFixed(number));
}
if (round && number < 100)
{
return number < 0 ? Math.round(number * -1) * -1 : Math.round(number) + ""; //Javascript rounds towards positive infinity, but we want to round away from zero
}
if (number < 100 && number == Math.floor(number)) return number + "";
if (!round && number < 1000 && number != Math.floor(number)) return number.toFixed(Engine.Utils.getFixed(number));
if (UtilsStatics.ForceScientific && number < 10000)
{
var out = number.toFixed(0);
if (out.length == 4) out = out.substr(0, 1) + "," + out.substr(1);
return out;
}
if (UtilsStatics.divisors.length == 0)
{
for (var i = 0; i < UtilsStatics.symbols.length; i++) UtilsStatics.divisors.push(Math.pow(1000, i + 1));
}
// Determine what the number is and which symbol we're going to use
var amount = number;
var symbol = "";
for (var i = UtilsStatics.divisors.length - 1; i >= 0; i--)
{
if (number >= UtilsStatics.divisors[i])
{
amount = (number / UtilsStatics.divisors[i]);
symbol = UtilsStatics.symbols[i];
break;
}
}
if (UtilsStatics.ForceScientific || amount >= 1000)
{
//return number.toString("#.00e00");
var amount_str = Number.parseFloat(number).toExponential(2).replace("+", "");
if (amount_str.charAt(amount_str.length - 2) == "e") amount_str = amount_str.slice(0, amount_str.length - 1) + "0" + amount_str.slice(amount_str.length - 1);
return amount_str;
}
else
{
// determine number of whole digits (will dictat how many decimals we show)
var whole = Math.floor(amount);
var amount_str = "" + whole;
var decimalDivider = 100 / Math.pow(10, amount_str.length - 1);
// round to nearest decimal place
amount = (Math.floor(amount * decimalDivider)) / decimalDivider;
var amountString = "" + amount;
var noDecimal = amountString.replace(".", "");
if (noDecimal.length == 2)
{
if (amountString.indexOf(".") != -1) amountString += "0";
else amountString += ".0";
}
else if (noDecimal.length == 1) amountString += ".00";
return amountString + symbol; // concat symbol
}
}
static getFixed(n)
{
if (n * 10 - Math.floor(n * 10) == 0)
{
return 1;
}
return 2;
}
static isNumberInvalid(n)
{
if (!isFinite(n)) return true;
return false;
}
static sanitizeNumber(n)
{
if (isFinite(n)) return Number(n);
return 0;
}
static md5(str)
{
return md5b(str);
//TODO IMPLEMENT THIS...
/*
MD5 md5Hash = MD5.Create();
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(str));
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
*/
}
static formatNumber(cost)
{
return cost;
//return String.Format("{0:#,##0}", cost);
}
// normal random variate generator; mean m, standard deviation s
static boxMullerRandomNormal(m, s)
{
var x1, x2, w, y1;
var y2;
do {
x1 = 2.0 * Math.random() - 1.0;
x2 = 2.0 * Math.random() - 1.0;
w = x1* x1 + x2* x2;
} while ( w >= 1.0 );
w = Math.sqrt( (-2.0 * Math.log(w ) ) / w );
y1 = x1* w;
y2 = x2* w;
return( m + y1* s );
}
/// <summary>
/// Get a double between 0.0 <= x < 1.0
/// </summary>
/// <returns></returns>
static randomDouble()
{
return Math.random();
}
/// <summary>
/// Get an integer between min and max
/// </summary>
/// <param name="min">min inclusive</param>
/// <param name="max">max exclusive</param>
/// <returns></returns>
static getRandom(min, max)
{
return Math.floor(Math.random() * Math.floor(max - min)) + min;
}
/// <summary>
/// Fisher-Yates shuffle rearraange the items in the list
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
static shuffle(list)
{
for (var i = 0; i < list.length; i++)
{
var r = i + Math.floor(Math.random() * (list.length - i));
var t = list[r];
list[r] = list[i];
list[i] = t;
}
}
/// <summary>
/// Get the time in timer format ( hh:mm:ss ). Hours not displayed if 0.
/// </summary>
/// <param name="timeSeconds"></param>
/// <returns></returns>
static formatTimeAsTimer(timeSeconds)
{
var hours = 0;// (int)cooldownRemaining / (60 * 60);
var mins = Math.floor(timeSeconds) / 60;
var seconds = Math.floor(timeSeconds) - (hours * 60 * 60) - (mins * 60);
var hoursStr = hours > 0 ? hours + ":" : "";
if (hours > 0 && hours < 10) hoursStr = "0" + hoursStr;
var minStr = mins > 0 ? mins + ": " : "00: ";
if (mins > 0 && mins < 10) minStr = "0" + minStr;
var secondsStr = seconds + "";
if (seconds < 10) secondsStr = "0" + secondsStr;
return hoursStr + minStr + secondsStr;
}
/// <summary>
/// Rotates the given point around (0,0) by radians.
/// </summary>
/// <param name="point"></param>
/// <param name="radians"></param>
/// <returns></returns>
static rotatePoint(point, radians)
{
var cos = Math.cos(radians);
var sin = Math.sin(radians);
var x = point.x * cos - point.y * sin;
var y = point.x * sin + point.y * cos;
return new PIXI.Point(x, y);
}
/// <summary>
/// Gets whether or not an email is valid
/// </summary>
/// <param name="email">Email to be checkd</param>
/// <returns>whether or not the emial is valid</returns>
static isValidEmail(email)
{
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(String(email).toLowerCase());
}
static copyObject(obj)
{
var newObj = {};
for (var key in obj)
{
newObj[key] = obj[key];
}
return newObj;
}
static deepCopy(obj)
{
if (Array.isArray(obj))
{
var newArr = [];
for (var i in obj)
{
newArr[i] = this.deepCopy(obj[i]);
}
return newArr;
}
if (typeof obj == "object")
{
var newObj = {};
for (var key in obj)
{
newObj[key] = this.deepCopy(obj[key]);
}
return newObj;
}
return obj;
}
static concatObject(a, b)
{
var newObj = {};
if (a != null)
{
for (var key in a) newObj[key] = a[key];
}
if (b != null)
{
for (var key in b) newObj[key] = b[key];
}
return newObj;
}
static toCamelCase(input, firstUpper)
{
if (firstUpper === undefined) firstUpper = true;
var result = input.replace(/(?:^\w|[A-Z]|\b\w)/g, function(letter, index) { return index == 0 && !firstUpper ? letter.toLowerCase() : letter.toUpperCase(); }).replace(/\s+/g, '');
return result;
}
static toUnderlineCase(input)
{
var toUnderlineCaseReg = /[^A-Z0-9][A-Z0-9]/g;
return input.replace(toUnderlineCaseReg, match => [match.slice(0, 1), "_", match.slice(1)].join('')).toLowerCase();
}
static openInNewTab(url)
{
var win = window.open(url, '_blank');
win.focus();
}
static readRange(data, )
{
}
static scaleAngleRadians(radians, scaleX, scaleY)
{
return Math.atan2(Math.sin(radians) * scaleY, Math.cos(radians) * scaleX);
}
static scaleAngle(degrees, scaleX, scaleY)
{
return Engine.Utils.scaleAngleRadians(degrees * Math.PI / 180.0, scaleX, scaleY) * 180.0 / Math.PI;
}
static formatDate(date)
{
var month = this.monthPrefix(date.getMonth() + 1);
var day = date.getDate()
var year = date.getFullYear();
var hour = date.getHours();
var ampm = "am";
if (hour >= 12)
{
hour -= 12;
ampm = "pm";
}
if (hour == 0) hour += 12;
var min = date.getMinutes();
if (min < 10) min = "0" + min;
return "" + month + " " + day + ", " + year + " " + hour + ":" + min + " " + ampm;
}
static monthPrefix(month)
{
switch (month)
{
case 1:
return "Jan";
case 2:
return "Feb";
case 3:
return "Mar";
case 4:
return "Apr";
case 5:
return "May";
case 6:
return "June";
case 7:
return "July";
case 8:
return "Aug";
case 9:
return "Sept";
case 10:
return "Oct";
case 11:
return "Nov";
case 12:
return "Dec";
default:
return "Mon";
}
}
static getComparisonOp(comparison)
{
switch (comparison.toLowerCase())
{
case "less_than":
case "lt":
case "<":
return UtilsStatics.ComparisonOp.LT;
case "less_than_or_equal":
case "less_than_equal":
case "lte":
case "<=":
return UtilsStatics.ComparisonOp.LTE;
case "greater_than":
case "gt":
case ">":
return UtilsStatics.ComparisonOp.GT;
case "greater_than_or_equal":
case "greater_than_equal":
case "gte":
case ">=":
return UtilsStatics.ComparisonOp.GTE;
case "eq":
case "equal":
case "equal_to":
case "equals":
case "=":
case "==":
return UtilsStatics.ComparisonOp.EQ;
case "ne":
case "neq":
case "not_equal":
case "not_equal_to":
case "!equal":
case "!=":
case "<>":
return UtilsStatics.ComparisonOp.NEQ;
}
return null;
}
static makeComparison(valueLeft, comparison, valueRight)
{
if (typeof comparison == "string")
{
comparison = Engine.Utils.getComparisonOp(comparison);
}
if (comparison != null)
{
switch (comparison)
{
case UtilsStatics.ComparisonOp.LT:
return valueLeft < valueRight;
case UtilsStatics.ComparisonOp.LTE:
return valueLeft <= valueRight;
case UtilsStatics.ComparisonOp.GT:
return valueLeft > valueRight;
case UtilsStatics.ComparisonOp.GTE:
return valueLeft >= valueRight;
case UtilsStatics.ComparisonOp.EQ:
return valueLeft == valueRight;
case UtilsStatics.ComparisonOp.NEQ:
return valueLeft != valueRight;
}
}
return false;
}
static reportError(error, message)
{
if (message === undefined) message = error;
Debug.LogError(error)
Engine.DialogManagerInstance.showMessageBox(message, "ok");
}
// stack 105034 thankyou!
static uuidv4()
{
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
}
var UtilsStatics = {};
UtilsStatics.ComparisonOp = { LT:0, LTE:1, GT:2, GTE:3, EQ:4, NEQ:5 };
UtilsStatics.day = "day";
UtilsStatics.hour = "hour";
UtilsStatics.minute = "minute";
UtilsStatics.second = "second";
UtilsStatics.dayPlur = "days";
UtilsStatics.hourPlur = "hours";
UtilsStatics.minutePlur = "minutes";
UtilsStatics.secondPlur = "seconds";
UtilsStatics.dayAbr = "d";
UtilsStatics.hourAbr = "h";
UtilsStatics.minuteAbr = "m";
UtilsStatics.secondAbr = "s";
UtilsStatics.serverTimeOffset = 0;
UtilsStatics.TimeResolution = { "Days":1, "Hours":2, "Minutes":3, "Seconds":4 }
UtilsStatics.ForceScientific = false;
UtilsStatics.symbols = ["K", "M", "B", "t", "q", "Q", "s", "S", "o", "n", "d", "U", "D", "T", "Qt", "Qd", "Sd", "St", "O", "N", "v", "c"];
UtilsStatics.divisors = [];
UtilsStatics.bigNumberRegex = /(\d*),?(\d*)(.*)/;