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*)(.*)/;