-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathutility.js
executable file
·135 lines (132 loc) · 3.47 KB
/
utility.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
Array.prototype.binarySearch = function(v) {
var min = 0, max = this.length - 1;
var mid, el;
while(min <= max) {
el = this[mid = (min + ((max - min) >> 1)) | 0];
if(el < v) {
min = mid + 1;
} else if(el > v) {
max = mid - 1;
} else {
return mid;
}
}
return ~min;
};
Array.prototype.clear = function() { this.splice(0, this.length) };
RegExp.compile = function(pattern, args) {
try {
return new RegExp(pattern, args);
} catch(error) {
console.error(pattern + ' is not valid RegExp. Escaping...');
// https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions
return RegExp.compile(pattern.replace(/([.*+?^${}()|\[\]\/\\])/g, "\\$1"), args);
}
}
// You may be wondering why I didn't use something like lodash.
// It's because my implementations are faster, and I don't need all of the functionality in lodash.
// That is, I wouldn't save 15k of space by using lodash. The js is only 75k anyways. :P
// TODO: maybe not populate in the global namespace
function isString(s) { // NOTE: only tests string or array
// see http://jsperf.com/testing-string-vs-array
return !s.sort;
}
// log n time LIKE A BOSS
function prefixBinarySearch(a, v) {
if(!a.length) { return -1 }
var start = 0, end = a.length - 1, mid = -1, el = null;
while(start <= end) {
mid = (start + (end - start) / 2) | 0;
el = a[mid];
if(el.length >= v.length && el.lastIndexOf(v, 0) == 0) {
while(mid > 0 && a[mid - 1].length >= v.length && a[mid - 1].lastIndexOf(v, 0) == 0) {
mid--;
}
return mid;
} else if(el < v) {
start = mid + 1;
} else if(el > v) {
end = mid - 1;
} else {
// y'know a shouldn't happen...
return mid;
}
}
return -1;
};
function getTime() {
return !!window.performance ? window.performance.now() : new Date().getTime();
}
const grades = ['D', 'D+', 'C-', 'C', 'C+', 'B-', 'B', 'B+', 'A-', 'A'];
function toGradeArray(grade_object) {
return fetch(grade_object, grades);
}
function getGPA(grade_array) {
return apply([1.0, 1.3, 1.7, 2.0, 2.3, 2.7, 3.0, 3.3, 3.7, 4.0], grade_array, product).reduce(sum) / grade_array.reduce(sum);
}
function strcmp(a, b) {
if(a < b) { return -1 }
else if(a > b) { return 1 }
else { return 0 }
}
function toTermOrdinal(term) {
var year = 4 * parseInt(term.substring(term.length - 4));
if(term[0] == 'W') {
return year;
}
if(term[0] == 'A') {
return year + 3;
}
if(term[1] == 'p') {
return year + 1;
}
return year + 2;
}
function fetch(a, keys) {
var out = [];
for(var i = 0; i < keys.length; i++) {
out.push(a[keys[i]]);
}
return out;
}
function apply(a, b, operator) {
var out = [];
for(var i = 0; i < a.length; i++) {
out.push(operator(a[i], b[i]));
}
return out;
}
function normalize(a) {
var total = a.reduce(sum, 0);
for(var i = 0; i < a.length; i++) {
a[i] /= total;
}
return a;
}
function pick(o, keys) {
var out = {};
for(var i = 0; i < keys.length; i++) {
out[keys[i]] = o[keys[i]];
}
return out;
}
function sum(a, b) { return a + b }
function product(a, b) { return a * b }
function addDataColumns(table) {
for(var i = 0; i < grades.length; i++) {
table.addColumn('number', grades[i]);
}
}
// convenient string functions
if(!String.prototype.startsWith) {
String.prototype.startsWith = function(pattern) {
// this is faster on chrome, firefox's startsWith implementation is fastest
// ie and safari can suck it.
for(var i = 0, length = pattern.length; i < length; i++) {
if(pattern.charAt(i) !== this.charAt(i)) {
return false;
}
}
return true;
};
}