Passed
Push — master ( cc7abf...63524c )
by Night
01:13
created

UB.latLonDistance   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 1
Metric Value
cc 1
eloc 11
c 1
b 1
f 1
nc 1
nop 4
dl 0
loc 16
rs 9.85
1
/** global: UB */
2
3
UB.intMaxValue = 2147483647;
4
UB.intMinValue = -2147483648;
5
UB.floatMaxValue = 3.40282e+038; /// 038 or 056? .. it was originally 038F
6
UB.floatMinValue = -3.40282e+038;
7
UB.doubleMaxValue =  9223372036854775807;
8
UB.doubleMinValue = -9223372036854775808;
9
10
UB.roman1s = ["", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix"];
11
UB.roman10s = ["", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc"];
12
UB.roman100s = ["", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm"];
13
UB.roman1000s = ["", "m", "mm", "mmm", "mmmm", "", "", "", "", ""];
14
UB.roman = [UB.roman1s, UB.roman10s, UB.roman100s, UB.roman1000s];
15
UB.letterLegal = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "BB", "CC", "DD", "EE", "FF", "GG", "HH", "II", "JJ", "KK", "LL", "MM", "NN", "OO", "PP", "QQ", "RR", "SS", "TT", "UU", "VV", "WW", "XX", "YY", "ZZ", "AAA", "BBB", "CCC", "DDD", "EEE", "FFF", "GGG", "HHH", "III", "JJJ", "KKK", "LLL", "MMM", "NNN", "OOO", "PPP", "QQQ", "RRR", "SSS", "TTT", "UUU", "VVV", "WWW", "XXX", "YYY", "ZZZ", "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLL", "MMMM", "NNNN", "OOOO", "PPPP", "QQQQ", "RRRR", "SSSS", "TTTT", "UUUU", "VVVV", "WWWW", "XXXX", "YYYY", "ZZZZ", "AAAAA", "BBBBB", "CCCCC", "DDDDD", "EEEEE", "FFFFF", "GGGGG", "HHHHH", "IIIII", "JJJJJ", "KKKKK", "LLLLL", "MMMMM", "NNNNN", "OOOOO", "PPPPP", "QQQQQ", "RRRRR", "SSSSS", "TTTTT", "UUUUU", "VVVVV", "WWWWW", "XXXXX", "YYYYY", "ZZZZZ"];
16
UB.letterExcel = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AJ", "AK", "AL", "AM", "AN", "AO", "AP", "AQ", "AR", "AS", "AT", "AU", "AV", "AW", "AX", "AY", "AZ", "BA", "BB", "BC", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BK", "BL", "BM", "BN", "BO", "BP", "BQ", "BR", "BS", "BT", "BU", "BV", "BW", "BX", "BY", "BZ", "CA", "CB", "CC", "CD", "CE", "CF", "CG", "CH", "CI", "CJ", "CK", "CL", "CM", "CN", "CO", "CP", "CQ", "CR", "CS", "CT", "CU", "CV", "CW", "CX", "CY", "CZ", "DA", "DB", "DC", "DD", "DE", "DF", "DG", "DH", "DI", "DJ", "DK", "DL", "DM", "DN", "DO", "DP", "DQ", "DR", "DS", "DT", "DU", "DV", "DW", "DX", "DY", "DZ"];
17
UB.decZeros = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
18
UB.hexChars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"];
19
UB.toDegrees = (180 / Math.PI);
20
UB.toRadians = (Math.PI / 180);
21
22
UB.minOf3 = function(num1, num2, num3){
23
	if (num1 < num2) {
24
		if (num1 < num3) {
25
			return num1;
26
		}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
27
			return num3;
28
		}
29
	}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
30
		if (num2 < num3) {
31
			return num2;
32
		}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
33
			return num3;
34
		}
35
	}
36
};
37
UB.maxOf3 = function(num1, num2, num3){
38
	if (num1 > num2) {
39
		if (num1 > num3) {
40
			return num1;
41
		}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
42
			return num3;
43
		}
44
	}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
45
		if (num2 > num3) {
46
			return num2;
47
		}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
48
			return num3;
49
		}
50
	}
51
};
52
53
UB.minOf4 = function(num1, num2, num3, num4){
54
	if (num1 < num2) {
55
		
56
		// 1, 3, 4
57
		if (num1 < num3) {
58
			
59
			// 1, 4
60
			if (num1 < num4) {
61
				return num1;
62
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
63
				return num4;
64
			}
65
		}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
66
			
67
			// 3, 4
68
			if (num3 < num4) {
69
				return num3;
70
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
71
				return num4;
72
			}
73
		}
74
		
75
	}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
76
		
77
		// 2, 3, 4
78
		if (num2 < num3) {
79
			
80
			// 2, 4
81
			if (num2 < num4) {
82
				return num2;
83
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
84
				return num4;
85
			}
86
		}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
87
			
88
			// 3, 4
89
			if (num3 < num4) {
90
				return num3;
91
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
92
				return num4;
93
			}
94
		}
95
	}
96
};
97
UB.maxOf4 = function(num1, num2, num3, num4){
98
	if (num1 > num2) {
99
		
100
		// 1, 3, 4
101
		if (num1 > num3) {
102
			
103
			// 1, 4
104
			if (num1 > num4) {
105
				return num1;
106
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
107
				return num4;
108
			}
109
		}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
110
			
111
			// 3, 4
112
			if (num3 > num4) {
113
				return num3;
114
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
115
				return num4;
116
			}
117
		}
118
		
119
	}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
120
		
121
		// 2, 3, 4
122
		if (num2 > num3) {
123
			
124
			// 2, 4
125
			if (num2 > num4) {
126
				return num2;
127
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
128
				return num4;
129
			}
130
		}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
131
			
132
			// 3, 4
133
			if (num3 > num4) {
134
				return num3;
135
			}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
136
				return num4;
137
			}
138
		}
139
	}
140
};
141
142
/** calc overlap of 2 numeric ranges */
143
UB.overlap = function(value1Start, value1End, value2Start, value2End){
144
	
145
	// swap if reversed
146
	if (value1Start > value1End) {
147
		var temp = value1Start;
148
		value1Start = value1End;
149
		value1End = temp;
150
	}
151
	if (value2Start > value2End) {
152
		temp = value2Start;
153
		value2Start = value2End;
154
		value2End = temp;
155
	}
156
	
157
	// exit if no overlap
158
	if (value1End < value2Start || value2End < value1Start) {
159
		return 0;
160
	}
161
	
162
	// return overlap of 2 ranges
163
	if (value1Start >= value2Start && value1End <= value2End) {
164
		return (value1End - value1Start);
165
	} else if (value2Start >= value1Start && value2End <= value1End) {
166
		return (value2End - value2Start);
167
	} else if (value1Start < value2Start && value1End <= value2End) {
168
		return (value1End - value2Start);
169
	} else if (value2Start < value1Start && value2End <= value1End) {
170
		return (value2End - value1Start);
171
	}
172
	return 0;
173
};
174
175
// distance between 2 lat/lon coords
176
UB.latLonDistance = function(latitude1, longitude1, latitude2, longitude2){
177
	
178
	// all lat/lons are floating point numbers in degrees
179
	
180
	var theta = longitude1 - longitude2;
181
	var miles = (Math.sin(latitude1*UB.toRadians)*Math.sin(latitude2*UB.toRadians)) + (Math.cos(latitude1*UB.toRadians)*Math.cos(latitude2*UB.toRadians)*Math.cos(theta*UB.toRadians));
182
	miles = Math.acos(miles);
183
	miles = (miles * UB.toDegrees);
184
	
185
	miles = miles * 60 * 1.1515;
186
	var feet = miles*5280;
187
	var yards = feet / 3;
188
	var kilometers = miles*1.609344;
189
	var meters = kilometers*1000;
190
	return [miles, feet, yards, kilometers, meters];
191
};
192
	
193
194
var stringFuncs = {
195
	
196
	/** CONVERT LEGAL LETTER TO NUMBER .. A = 1, B = 2, C = 3  */
197
	legalNumeralToNumber: function(zeroBased){
198
		var s = this.toString();
199
		return UB.letterLegal.indexOf(s.toUpperCase()) + (zeroBased ? 0 : 1);
200
	},
201
	/** CONVERT EXCEL COLUMN ID TO NUMBER .. A = 1, B = 2, C = 3  */
202
	excelColumnToNumber: function(zeroBased = false){
203
		var s = this.toString();
204
		return UB.letterExcel.indexOf(s.toUpperCase()) + (zeroBased ? 0 : 1);
205
	},
206
	
207
	hexToDecimal: function(onlyDigits = 0){
208
		var hex = this.toString();
209
		hex = hex.toUpperCase();
210
		
211
		// remove prefix
212
		if (hex.indexOf("0X") == 0){
1 ignored issue
show
Best Practice introduced by
Comparing hex.indexOf("0X") to 0 using the == operator is not safe. Consider using === instead.
Loading history...
213
			hex = hex.substr(2);
214
		}else if (hex.charAt(0) == "#"){
215
			hex = hex.substr(1);
216
		}
217
		
218
		if (onlyDigits) {
219
			hex = hex.substr(0, onlyDigits);
220
		}
221
		return int("0x" + hex);
222
	},
223
	
224
	binaryToDecimal: function(){
225
		var num = bin.toString();
0 ignored issues
show
Unused Code introduced by
The variable num seems to be never used. Consider removing it.
Loading history...
Bug introduced by
The variable bin seems to be never declared. If this is a global, consider adding a /** global: bin */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
226
		bin = bin.toUpperCase();
0 ignored issues
show
Bug introduced by
The variable bin seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.bin.
Loading history...
227
		
228
		// remove prefix
229
		if (bin.indexOf("0B") == 0){
1 ignored issue
show
Best Practice introduced by
Comparing bin.indexOf("0B") to 0 using the == operator is not safe. Consider using === instead.
Loading history...
230
			bin = bin.substr(2);
231
		}
232
		
233
		var byte = 0;
234
		for (var i = 0, il = bin.length, il2 = bin.length - 1;i<il;i++){
235
			byte += uint(bin.charAt(il2 - i)) * Math.pow(2,i);
236
		}
237
		return byte;
238
	},
239
	
240
	none:null
241
};
242
243
// register funcs
244
UB.registerFuncs(String.prototype, stringFuncs);
245
246
247
248
var numberFuncs = {
249
	
250
	isOdd: function(){
251
		var val = this;
252
		return (val % 2) != 0;
1 ignored issue
show
Best Practice introduced by
Comparing val % 2 to 0 using the != operator is not safe. Consider using !== instead.
Loading history...
253
	},
254
	isEven: function(){
255
		var val = this;
256
		return (val % 2) == 0;
1 ignored issue
show
Best Practice introduced by
Comparing val % 2 to 0 using the == operator is not safe. Consider using === instead.
Loading history...
257
	},
258
	isPositive: function(){
259
		var val = this;
260
		return (val > 0);
261
	},
262
	isNegative: function(){
263
		var val = this;
264
		return (val < 0);
265
	},
266 View Code Duplication
	relativeTo: function(v2, type){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
267
		var v1 = this;
268
		// type .. 0=any, 1=pos, 2=neg
269
		var v = v2 - v1;
270
		if (type == 1) {
1 ignored issue
show
Best Practice introduced by
Comparing type to 1 using the == operator is not safe. Consider using === instead.
Loading history...
271
			return v > 0 ? v : -v;
272
		}else if (type == 2) {
273
			return v > 0 ? -v : v;
274
		}
275
		return v;
276
	},
277
	abs: function(negative = false){
278
		var v = this;
279
		if (negative){
280
			return v > 0 ? -v : v;
281
		}
282
		return v > 0 ? v : -v;
283
	},
284
	acos: function(degrees = false){
285
		var v = this;
286
		if (degrees) {
287
			return Math.acos(v) * UB.toDegrees;
288
		}
289
		return Math.acos(v);
290
	},
291
	asin: function(degrees = false){
292
		var v = this;
293
		if (degrees) {
294
			return Math.asin(v) * UB.toDegrees;
295
		}
296
		return Math.asin(v);
297
	},
298
	atan: function(degrees = false){
299
		var v = this;
300
		if (degrees) {
301
			return Math.atan(v) * UB.toDegrees;
302
		}
303
		return Math.atan(v);
304
	},
305
	atan2: function(x, degrees = false){
306
		var y = this;
307
		if (degrees) {
308
			return Math.atan2(y, x) * UB.toDegrees;
309
		}
310
		return Math.atan2(y, x);
311
	},
312
	exp: function(){
313
		var v = this;
314
		return Math.exp(v);
315
	},
316
	log: function(){
317
		var v = this;
318
		return Math.log(v);
319
	},
320
	pow: function(power){
321
		var base = this;
322
		return Math.pow(base, power)
323
	},
324
	sin: function(degrees = false){
325
		var angle = this;
326
		if (degrees) {
327
			return Math.sin(angle * UB.toRadians);
328
		}
329
		return Math.sin(angle);
330
	},
331
	cos: function(degrees = false){
332
		var angle = this;
333
		if (degrees) {
334
			return Math.cos(angle * UB.toRadians);
335
		}
336
		return Math.cos(angle);
337
	},
338
	tan: function(degrees = false){
339
		var angle = this;
340
		if (degrees) {
341
			return Math.tan(angle * UB.toRadians);
342
		}
343
		return Math.tan(angle);
344
	},
345
	sqrt: function(){
346
		var v = this;
347
		return Math.sqrt(v);
348
	},
349
	compare: function(v2){
350
		var v1 = this;
351
		if (v1 < v2) {
352
			return -1;
353
		}
354
		if (v1 > v2) {
355
			return 1;
356
		}
357
		return 0;
358
	},
359
	positive: function(){
360
		var val = this;
361
		return val > 0 ? val : -val;
362
	},
363
	negative: function(){
364
		var val = this;
365
		return val > 0 ? -val : val;
366
	},
367
	
368
	exists: function(zeroOK = false){
369
		var v = this;
370
		if (zeroOK) {
371
			return (v != null && v == v);
1 ignored issue
show
Best Practice introduced by
Comparing v to null using the != operator is not safe. Consider using !== instead.
Loading history...
372
		}
373
		return v != null && v == v && v != 0;
374
	},
375
	
376
	
377
	min: function(num2){
378
		var num1 = this;
379
		if (num1 < num2) {
380
			return num1;
381
		}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
382
			return num2;
383
		}
384
	},
385
	max: function(num2){
386
		var num1 = this;
387
		if (num1 > num2) {
388
			return num1;
389
		}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
390
			return num2;
391
		}
392
	},
393
	atMost: function(limit){
394
		var num = this;
395
		return num > limit ? limit : num;
396
	},
397
	atLeast: function(limit){
398
		var num = this;
399
		return num < limit ? limit : num;
400
	},
401
	
402
	
403
	isNear: function(target, near = 1){
404
		var val = this;
405
		return val >= (target - near) && val <= (target + near);
406
	},
407
	
408
409
	/** Render a percentage (25%) using 2 values */
410
	percentageToString: function(current, decimals = 0){
411
		var total = this;
412
		return ((current / total) * 100).roundToString(decimals) + "%";
413
	},
414
	
415
416
	// CONVERT TO ABBREVIATION .. 1.5K
417
	toAbbreviation: function(decimals = 1){
418
		var num = this;
419
		if (num < 0) {
420
			return "-" + (-num).toAbbreviation; // -5.2K, -5.2M ..
421
		}
422
		if (num < 1000) {
423
			return String(num); // 520
424
		}
425
		if (num < 1000000) {
426
			return (num / 1000).roundToDigits(decimals) + 'K'; // 5.2K
427
		}
428
		if (num < 1000000000) {
429
			return (num / 1000000).roundToDigits(decimals) + 'M'; // 5.2M
430
		}
431
		return (num / 1000000000).roundToDigits(decimals) + 'G'; // 5.2B
432
	},
433
	
434
	
435
	// CONVERT TO ROMAN
436
	toRomanNumeral: function(){
437
		var n = this;
438
		if (n < 1) {
439
			n = 1;
440
		}
441
		
442
		// exit quickly if single digit
443
		if (n <= 9) {
444
			return UB.roman1s[n];
445
		}
446
		
447
		// create roman number if longer
448
		var str = n.toString();
449
		var output = [];
450
		for (var n = 0, nl = str.length;n<nl;n++){
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable n already seems to be declared on line 437. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
451
			var series = ((nl - 1) - n);
452
			var charIndex = int(str.charAt(n));
453
			output.push(UB.roman[series][charIndex]);
454
		}
455
		return output.join("");
456
	},
457
	
458
	/** CONVERT TO LEGAL LETTER .. 1 = A, 2 = B, 3 = C .. AA, BB, CC */
459
	toLegalNumeral: function(){
460
		var n = this;
461
		if (n < 1) {
462
			n = 1;
463
		}
464
		return UB.letterLegal[n];
465
	},
466
	// CONVERT TO NORMAL LETTER .. A, B, C .. AB, AB, AC .. BA, BB, BC
467
	toLetterNumeral: function(){
468
		var n = this;
469
		if (n <= 26) {
470
			return UB.letterLegal[n];
471
		}
472
		return "?";
473
	},
474
	/** CONVERT TO EXCEL COLUMN ID .. 1 = A, 2 = B, 3 = C .. AA, AB, AC */
475
	toExcelColumn: function(zeroBased = false){
476
		var n = this;
477
		var min = zeroBased?0:1;
478
		if (n < min) {
479
			n = min;
480
		}
481
		return UB.letterExcel[zeroBased ? n : n-1];
482
	},
483
	
484
	// CONVERT TO ORDINAL FORMAT .. 1st, 2nd, 3rd
485
	toOrdinal: function(){
486
		var i = this;
487
		var j = i % 10;
488
		var k = i % 100;
489
		if (j == 1 && k != 11) {
1 ignored issue
show
Best Practice introduced by
Comparing j to 1 using the == operator is not safe. Consider using === instead.
Loading history...
490
			return i + "st";
491
		}
492
		if (j == 2 && k != 12) {
493
			return i + "nd";
494
		}
495
		if (j == 3 && k != 13) {
496
			return i + "rd";
497
		}
498
		return i + "th";
499
	},
500
	
501
	
502
	// OR
503
	or: function(returnVal, ifNull = 0){
504
		var n = this;
505
		if (n == ifNull) {
506
			return returnVal;
507
		}
508
		return n;
509
	},
510
	
511
	
512
	/** Calc padding for a given length */
513
	padding: function(multipleOf){
514
		var length = this;
515
		return (multipleOf - (length % multipleOf));
516
	},
517
	
518
	multipleOf: function(multipleOf){
519
		var value = this;
520
		return value + (multipleOf - (value % multipleOf));
521
	},
522
	
523
	
524
	// FROM C#
525
	
526
	distance: function(n2){
527
		var n1 = this;
528
		return Math.abs(n1 - n2);
529
	},
530
	
531
	/** Calc x % of the given value */
532
	percentage: function(percentWanted){
533
		var val100Percent = this;
534
		if (percentWanted == 100) {
535
			return val100Percent;
536
		}
537
		return val100Percent * (percentWanted / 100.0);
538
	},
539
	
540
	/** Calc the % of otherVal in relation to val100Percent */
541
	percentOf: function(otherVal){
542
		var val100Percent = this;
543
		return (otherVal / val100Percent) * 100.0;
544
	},
545
	
546
	/** Calc the difference between 2 numbers in %
547
	//  ... 100, 50 shows -50% difference
548
	//  ... 100, 150 shows 50% difference */
549
	percentDifference: function(otherVal){
550
		var val100Percent = this;
551
		return ((otherVal - val100Percent) / val100Percent) * 100.0;
552
	},
553
	
554
	isConsequetive: function(value, value2){
555
		return value2 == (value - 1) || value2 == (value + 1);
556
	},
557
	
558
	/** Returns the number halfway between the 2 given numbers
559
		Value1 can be greater than Value2. */
560
	between: function(value2){
561
		var value1 = this;
562
		if (value1 > value2) {
563
			return value2 + ((value1 - value2) / 2);
564
		}
565
		return value1 + ((value2 - value1) / 2);
566
	},
567
	
568
	/** Returns the number halfway between the 2 given numbers
569
		Value1 can be greater than Value2. */
570
	middle: function(value2){
571
		var value1 = this;
572
		if (value1 > value2) {
573
			return value2 + ((value1 - value2) / 2);
574
		}
575
		return value1 + ((value2 - value1) / 2);
576
	},
577
	
578
	calcScale: function(targetValue){
579
		var value = this;
580
		if (targetValue == 0 && value == 0) {
2 ignored issues
show
Best Practice introduced by
Comparing targetValue to 0 using the == operator is not safe. Consider using === instead.
Loading history...
Best Practice introduced by
Comparing value to 0 using the == operator is not safe. Consider using === instead.
Loading history...
581
			return 0;
582
		}
583
		return (value / targetValue);
584
	},
585
	
586
	ensure: function(defaultVal){
587
		var value = this;
588
		if (value == 0) {
1 ignored issue
show
Best Practice introduced by
Comparing value to 0 using the == operator is not safe. Consider using === instead.
Loading history...
589
			return defaultVal;
590
		}
591
		return value;
592
	},
593
	
594
	snapToHigher: function(snapBy){
595
		var val = this;
596
		return Math.ceil(val / snapBy) * snapBy;
597
	},
598
	snapToLower: function(snapBy){
599
		var val = this;
600
		return Math.floor(val / snapBy) * snapBy;
601
	},
602
	snapToNearest: function(snapBy){
603
		var val = this;
604
		return Math.round(val / snapBy) * snapBy;
605
	},
606
	
607
	toInt: function(round){
608
		var num = this;
609
		if (!round || round == "truncate") {
610
			return parseInt(num);
611
		}
612
		if (round == "round") {
613
			return Math.round(num);
614
		}
615
		if (round == "floor") {
616
			return Math.floor(num);
617
		}
618
		if (round == "ceiling") {
619
			return Math.ceil(num);
620
		}
621
		return 0;
622
	},
623
	
624
	/**
625
	 * Formats a Number adding commas and the specified decimal digits.
626
	 * Supports the million/billion and lakh/crore system.
627
	 * 
628
	 * @param	system					"million" or "lakh"
629
	 * @param	decimals				-1 = keep exact decimals as number, 0 = no decimals, 1+ = specific decimals
630
	 * @param	alwaysShowDecimal		add decimal even if decimal part is 0
631
	 */
632
	formatNumber: function(system, decimals = -1, alwaysShowDecimal = false){
633
		var num = this;
634
		
635
		var commas = system == "lakh" ? 2 : 3;
636
637
		// test if number is negative
638
		var neg = false;
639
		if (num < 0) {
640
			neg = true;
641
			num = -num;
642
		}
643
		// get the left number
644
		var numStr = String(num);
645
		var hasDot = numStr.indexOf(".")>-1;
646
		if (hasDot) {
647
			var parts = numStr.split(".");
648
			var whole = parts[0];
649
			var decimal = parts[1];
650
		}else{
651
			whole = numStr;
652
			decimal = null;
653
		}
654
		
655
		// if at least 4 digits
656
		if (whole.length > 3) {
657
			
658
			// extract 3 digits first 
659
			var wholeRight3 = whole.substr(whole.length - 3, 3);
660
			whole = whole.substr(0, whole.length - 3);			
661
			
662
			// add million / crore seperators
663
			if (whole.length < commas) {
664
				whole = whole + "," + wholeRight3;
665
			}else {
666
				var thou = "";
667
				var rem = whole.substr(0, int(whole.length % commas));
668
				var l = ((int(whole.length / commas)*commas) - commas) + (whole.length % commas);
669
				for (var c = 0;l >= 0;l -= commas, c++){
0 ignored issues
show
Unused Code introduced by
The loop variable c is initialized by the loop but not used in the test. Consider using another type of loop if this is the intended behavior.
Loading history...
670
					thou = whole.substr(l, commas) + (c == 0 ? "" : ",") + thou;
1 ignored issue
show
Best Practice introduced by
Comparing c to 0 using the == operator is not safe. Consider using === instead.
Loading history...
671
				}
672
				whole = (rem == "" ? "" : rem + ",") + thou + "," + wholeRight3;
673
			}
674
		}
675
		
676
		// return with or without dot
677
		var result = whole;
678
		if (hasDot) {
679
			if (decimals > 0) {
680
				//  4.200
681
				result = whole + "." + decimal.substr(0, decimals).padRight("0", decimals);
682
			}else if (decimals == 0) {
1 ignored issue
show
Best Practice introduced by
Comparing decimals to 0 using the == operator is not safe. Consider using === instead.
Loading history...
683
				//  4
684
				result = whole;
685
			}else if (decimals == -1) {
686
				//  4.2
687
				result = whole + "." + decimal;
688
			}
689
			
690
		}else if (alwaysShowDecimal && decimals > 0) {
691
			
692
			//  4.0000
693
			result = whole + "." + decimals.repeat("0");
694
		}else {
695
			
696
			//  4
697
			result = whole;
698
		}
699
		return (neg ? "-" + result : result);
700
	},
701
	
702
	ensureNotNaN: function(instead = 0){
703
		var val = this;
704
		if (val != val) { /// fast isNaN check
705
			return instead;
706
		}else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
707
			return val;
708
		}
709
	},
710
	
711
	isNaN: function(){
712
		var val = this;
713
		return val != val || isNaN(val);
714
	},
715
	
716
	isAny: function(haystacks, asInt = false, fractionalDigits = -1){
717
		var needle = this;
718
		
719
		// return true if any haystack equals the needle
720
		for (var s = 0, sl = haystacks.length;s<sl;s++){
721
			var num = haystacks[s];
722
			
723
			// simplify value for comparison
724
			if (asInt) {
725
				num = int(num);
726
			}else if(fractionalDigits != -1) {
727
				num = num.roundToDigits(fractionalDigits);
728
			}
729
			
730
			if (needle == num) {
731
				return true;
732
			}
733
		}
734
		return false;
735
	},
736
	
737
	scale: function(inputMin, inputMax, outputMin, outputMax, outputLimit = true, outputFlip = false){
738
		var input = this;
739
		
740
		// ensure input within limits
741
		if (input < inputMin) {
742
			input = inputMin;
743
		}
744
		if (input > inputMax) {
745
			input = inputMax;
746
		}
747
		
748
		// convert input to %
749
		var percent = ((1*(input - inputMin)) / (inputMax - inputMin));
750
		
751
		// convert % to output
752
		var output = (percent*(outputMax - outputMin)) + outputMin;
753
		
754
		// ensure output within limits
755
		if (outputLimit){
756
			if (output < outputMin) {
757
				output = outputMin;
758
			}
759
			if (output > outputMax) {
760
				output = outputMax;
761
			}
762
		}
763
		
764
		// flip output
765
		if (outputFlip) {
766
			output = ((outputMax - outputMin) - (output - outputMin)) + outputMin;
767
		}
768
		
769
		// return scaled, limit-checked output
770
		return output;
771
	},
772
	smartScale: function(inputMin, inputMax, outputMin, outputMax){
773
		var input = this;
774
		if (inputMin > inputMax) {
775
			if (outputMin > outputMax) {
776
				return input.flipWithin(inputMin, inputMax).scale(inputMax, inputMin, outputMax, outputMin, true, true);
777
			} else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
778
				return input.flipWithin(inputMin, inputMax).scale(inputMax, inputMin, outputMin, outputMax);
779
			}
780
		} else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
781
			if (outputMin > outputMax) {
782
				return input.scale(inputMin, inputMax, outputMax, outputMin, true, true);
783
			} else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
784
				return input.scale(inputMin, inputMax, outputMin, outputMax);
785
			}
786
		}
787
	},
788
	
789
	flipWithin: function(min, max){
790
		var input = this;
791
		if (max < min) {
792
			return ((min - max) - (input - max)) + min;
793
		}
794
		return ((max - min) - (input - min)) + min;
795
	},
796
	
797
	limitToDigits: function(digits){
798
		var input = this;
799
		return parseFloat(input.toString().substr(0, digits));
800
	},
801 View Code Duplication
	limit: function(min, max){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
802
		var input = this;
803
		
804
		// ensure ok
805
		if (input != input) { /// fast isNaN check
806
			return min;
807
		}
808
		
809
		// flip limits if in reverse order
810
		if (min > max) {
811
			var temp = max;
812
			max = min;
813
			min = temp;
814
		}
815
		
816
		// ensure within limits
817
		if (input < min) {
818
			return min;
819
		}
820
		if (input > max) {
821
			return max;
822
		}
823
		return input;
824
	},
825
	limitToArray: function(array, extraMax = 0, extraMin = 0){
826
		var pointer = this;
827
		if (pointer <= -extraMin) {
828
			return -extraMin;
829
		}
830
		var last = (array.length + extraMax) - 1;
831
		if (last == -1) {
832
			return -extraMin;
833
		}
834
		if (pointer > last) {
835
			return last;
836
		}
837
		return pointer
838
	},
839
	
840
	wrap: function(min, max){
841
		var value = this;
842
		value -= min;
843
		var diff = (max - min) + 1;
844
		while (value < 0) {
845
			value += diff;
846
		}
847
		return min + (value % diff);
848
	},
849 View Code Duplication
	wrap2: function(min, max){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
850
		var input = this;
851
		
852
		// flip limits if in reverse order
853
		if (min > max) {
854
			var temp = max;
855
			max = min;
856
			min = temp;
857
		}
858
		
859
		// ensure wrapped to limits
860
		var diff = (max - min) + 1;
861
		while (input < min) {
862
			input += diff;
863
		}
864
		while (input > max) {
865
			input -= diff;
866
		}
867
		return input;
868
	},
869
	wrapToMax: function(max){
870
		var value = this;
871
		var diff = max + 1;
872
		while (value < 0) {
873
			value += diff;
874
		}
875
		return value % diff;
876
	},
877
	
878
	/** Identical to modulo operator, except negative values are also supported, and brought into positive range.
879
		Value will never reach limit, just like the modulo operator.
880
		Simpler than `wrap` which takes `min` and `max`. */
881
	modulo: function(limit){
882
		var input = this;
883
		
884
		// ensure wrapped to limits
885
		while (input < 0) {
886
			input += limit;
887
		}
888
		while (input >= limit) {
889
			input -= limit;
890
		}
891
		return input;
892
	},
893
	
894
	roundToDigits: function(decimals = 4){
895
		var input = this;
896
		
897
		if (decimals <= 0) {
898
			return Math.round(input);
899
		}
900
		
901
		// Returns a number rounded to specified number of decimals
902
		var multiplier = Math.pow(10, decimals);
903
		return Math.round(input*multiplier)/multiplier;
904
	},
905
	roundToString: function(decimals){
906
		var input = this;
907
		
908
		// Returns a number rounded to specified number of decimals
909
		// Add zeros to always return those many decimals
910
		var num = RoundTo(input, decimals).toString();
911
		if (decimals <= 0) {
912
			return num;
913
		}
914
		var add0 = 0;
915
		if (num.lastIndexOf(".") == -1){
916
			num = num+".";
917
			add0 = decimals;
918
		}else{
919
			add0 = decimals - ((num.length - num.lastIndexOf(".")) - 1);
920
		}
921
		while(add0 > 0){
922
			num = num+"0";
923
			add0 --;
924
		}
925
		return num;
926
	},
927
	
928
	
929
	// CHECKS
930
	/** Checks if the value is within min and max (supporting inclusive/exclusive modes) */
931
	isWithin: function(min, max, inclusive = true){
932
		var num = this;
933
		if (inclusive) {
934
			if (min > max) {
935
				return (num >= max && num <= min);
936
			}
937
			return (num >= min && num <= max);
938
		} else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
939
			if (min > max) {
940
				return (num > max && num < min);
941
			}
942
			return (num > min && num < max);
943
		}
944
	},
945
	isWithinArray: function(arr){
946
		var slot = this;
947
		
948
		// no, if array empty / index negative / index more than last slot
949
		var len = arr.length;
950
		if (len == 0 || slot < 0 || slot >= len) {
1 ignored issue
show
Best Practice introduced by
Comparing len to 0 using the == operator is not safe. Consider using === instead.
Loading history...
951
			return false;
952
		}
953
		
954
		// else yes
955
		return true;
956
	},
957
	/** Checks if the value is > min and < max */
958
	isBetween: function(min, max){
959
		var num = this;
960
		return (num > min && num < max);
961
	},
962
	isOutside: function(min, max, inclusive = true){
963
		var num = this;
964
		if (inclusive) {
965
			return num <= min || num >= max;
966
		}
967
		return num < min || num > max;
968
	},
969
	isFractional: function(){
970
		var num = this;
971
		return int(num) != num;
972
	},
973
	isInteger: function(){
974
		var num = this;
975
		return int(num) == num;
976
	},
977
	
978
	
979
	// HEX
980
	/** DO NOT USE THIS FOR `uint`s! */
981
	toHex: function(digits = 6, withHash = true){
982
		var num = this;
983
		var zeros = ("0000000000000000000000000000000000").substr(0, digits - 1);
984
		return ((withHash ? "#" : "") + (zeros + num.toString(16).toUpperCase()).substr( -digits));
985
	},
986
	/** USE THIS FOR `uint`s! */
987
	toHexUInt: function(digits = 8, withHash = true){
988
		var num = this;
989
		var zeros = ("0000000000000000000000000000000000").substr(0, digits - 1);
990
		return ((withHash ? "#" : "") + (zeros + num.toString(16).toUpperCase()).substr( -digits));
991
	},
992
	
993
	incrementWithin: function(min, max){
994
		var num = this;
995
		num++;
996
		if (num > max) {
997
			return min;
998
		}
999
		return num;
1000
	},
1001
	decrementWithin: function(min, max){
1002
		var num = this;
1003
		num--;
1004
		if (num < min) {
1005
			return max;
1006
		}
1007
		return num;
1008
	},
1009
	
1010
	
1011
	decimalToBinary: function(num, digits = 8){
1012
		var zeros = UB.decZeros.substr(0, digits - 1);
1013
		return (zeros + num.toString(2)).substr( -digits);
1014
	}, 
1015
	decimalToBinary2: function(byte, digits = 8){
1016
		var bin = '';
1017
		for (var i = 0;i<digits;i++){
1018
			bin += String((byte & (0x80 >> i)) >> (7 - i));
1019
		}
1020
		return bin;
1021
	},
1022
	
1023
	
1024
	
1025
	// MISC MATH
1026
	pad: function(number, length, addToEnd = false, padChar = '0'){
1027
		
1028
		// num to text
1029
		var result = String(number);
1030
		
1031
		// exit quickly if already reached target len
1032
		if (result.length >= length) {
1033
			return result;
1034
		}
1035
		
1036
		
1037
		// pad
1038
		if (addToEnd) {
1039
			while (result.length < length){
1040
				result = result + padChar;
1041
			}
1042
		}else {
1043
			while (result.length < length){
1044
				result = padChar + result;
1045
			}
1046
		}
1047
		
1048
		
1049
		return result;
1050
	},
1051
	interpolate: function(min, max){
1052
		var progress = this;
1053
		// progress = (0 to 1)
1054
		/*return( (1 - progress) * min + progress * max ); <---- WHAT IS THIS??? */ 
1055
		return min + ((max - min) * progress);
1056
	},
1057
	hypot: function(b){
1058
		var a = this;
1059
		// sqrt(a^2 + b^2) without under/overflow.
1060
		
1061
		var r;
1062
		var aAbs = (a > 0 ? a : -a);
1063
		var bAbs = (b > 0 ? b : -b);
1064
		if (aAbs > bAbs) {
1065
			r = b/a;
1066
			r = aAbs*Math.sqrt(1+r*r);
1067
		} else if (b != 0) {
1 ignored issue
show
Best Practice introduced by
Comparing b to 0 using the != operator is not safe. Consider using !== instead.
Loading history...
1068
			r = a/b;
1069
			r = bAbs*Math.sqrt(1+r*r);
1070
		} else {
1071
			r = 0.0;
1072
		}
1073
		return r;
1074
	},
1075
	apow: function(value){
1076
		var pow = this;
1077
		// input:	1,2,4,8,16,32,64
1078
		// output:	1,2,3,4,5,6,7
1079
		if (value == 1 || value == -1) return value;
1 ignored issue
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
Best Practice introduced by
Comparing value to 1 using the == operator is not safe. Consider using === instead.
Loading history...
1080
		var count = 0;
1081
		while (value != 0) {
1082
			//remainder = value % pow;
1083
			value = value / pow;
1084
			count++;
1085
		}
1086
		return count;
1087
	},
1088
	invert: function(){
1089
		var value = this;
1090
		// input:	0.1		0.5		1 	2 		8
1091
		// output:	10		2		1	0.5		0.2
1092
		return 1 / value;
1093
	},
1094
	powAbs: function(exponent){
1095
		var x = this;
1096
		// This function always returns a positive value that conforms to the expected Exponent curve.
1097
		// Math.pow: If x is negative, and exponent is not an integer, returns NaN.
1098
		if( x >= 0 ) {
1099
			return Math.pow( x, exponent );
1100
		} else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
1101
			return Math.pow(-x, 1/exponent);
1102
		}
1103
	},
1104
	
1105
	// count digits in number
1106
	getWhole: function(){
1107
		var val = this;
1108
		
1109
		// -10.235 has 2 whole digits
1110
		return int(val);
1111
	},
1112
	setWhole: function(newval){
1113
		var val = this;
1114
		return newval + GetFractional(val);
1115
	},
1116
	getFractional: function(){
1117
		var val = this;
1118
		
1119
		// -10.235 has 3 fractional digits
1120
		var s = (val < 0 ? -val : val).toString();
1121
		var i = s.indexOf(".");
1122
		return (i == -1) ? int(val) : int(s.substr(i + 1));
1123
	},
1124
	setFractional: function(fraction){
1125
		var val = this;
1126
		return Number((parseInt(val).toString()) + "." + fraction.toString());
1127
	},
1128
	
1129
	
1130
	
1131
	// SLOT INDEX
1132
	minIndex: function(index2){
1133
		var index1 = this;
1134
		if (index1 <= -1) {
1135
			return index2;
1136
		}
1137
		if (index2 <= -1) {
1138
			return index1;
1139
		}
1140
		if (index1 < index2) {
1141
			return index1;
1142
		} else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
1143
			return index2;
1144
		}
1145
	},
1146
	maxIndex: function(index2){
1147
		var index1 = this;
1148
		if (index1 <= -1) {
1149
			return index2;
1150
		}
1151
		if (index2 <= -1) {
1152
			return index1;
1153
		}
1154
		if (index1 > index2) {
1155
			return index1;
1156
		} else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
1157
			return index2;
1158
		}
1159
	},
1160
	
1161
	
1162
	
1163
	none:null
1164
};
1165
1166
// register funcs
1167
UB.registerFuncs(Number.prototype, numberFuncs);
1168
1169