@ejfdelgado/ejflab-common 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +2 -0
- package/package.json +29 -0
- package/src/CollisionsEngine.js +252 -0
- package/src/CsvFormatter.js +54 -0
- package/src/CsvFormatter.test.js +119 -0
- package/src/CsvFormatterFilters.js +79 -0
- package/src/CsvParser.js +51 -0
- package/src/CsvParser.test.js +41 -0
- package/src/CsvWithFilters.js +114 -0
- package/src/FaceEncoder.js +64 -0
- package/src/FlowChartDiagram.js +503 -0
- package/src/IdGen.js +211 -0
- package/src/ModuloDatoSeguro.js +142 -0
- package/src/ModuloDatoSeguro.test.js +29 -0
- package/src/ModuloDatoSeguro.test.mjs +45 -0
- package/src/ModuloDatoSeguroBack.mjs +55 -0
- package/src/ModuloDatoSeguroFront.js +73 -0
- package/src/ModuloSonido.js +83 -0
- package/src/ModuloVideos.js +51 -0
- package/src/MyColor.js +136 -0
- package/src/MyColor.test.js +37 -0
- package/src/MyConstants.js +147 -0
- package/src/MyCookies.js +34 -0
- package/src/MyDates.js +412 -0
- package/src/MyDates.test.js +26 -0
- package/src/MyDatesBack.mjs +21 -0
- package/src/MyDatesFront.js +41 -0
- package/src/MyJsPdf.js +52 -0
- package/src/MyRoutes.js +29 -0
- package/src/MyTemplate.js +272 -0
- package/src/MyTemplate.test.js +90 -0
- package/src/MyTensorflow.js +248 -0
- package/src/MyTensorflow.test.js +19 -0
- package/src/MyTensorflowBack.mjs +33 -0
- package/src/MyThrottle.js +80 -0
- package/src/MyTuples.js +445 -0
- package/src/MyTuples.test.js +330 -0
- package/src/MyUtilities.js +137 -0
- package/src/SimpleObj.js +153 -0
- package/src/SimpleObj.test.js +58 -0
- package/src/TriangulacionGeometric.js +335 -0
- package/src/changePath.js +38 -0
- package/src/data/case0.csv +3 -0
- package/src/data/case0.json +24 -0
- package/src/data/case1.csv +2 -0
- package/src/data/case1.json +24 -0
- package/src/data/case2.csv +3 -0
- package/src/data/case2.json +24 -0
- package/src/data/case3.csv +3 -0
- package/src/data/case3.json +24 -0
- package/src/data/format0.json +0 -0
- package/src/data/format0.txt +1 -0
- package/src/data/tensordata.csv +10 -0
- package/src/data/tensordata.json +37 -0
- package/src/data/tensordata.test.csv +10 -0
- package/src/data/tensormodel.json +113 -0
- package/src/fft.js +224 -0
- package/src/flowchart/FlowChartExec.js +763 -0
- package/src/flowchart/steps/CommandBasic.js +32 -0
- package/src/flowchart/steps/CommandInc.js +19 -0
- package/src/flowchart/steps/CommandMilvus.js +47 -0
- package/src/flowchart/steps/CommandMinio.js +28 -0
- package/src/flowchart/steps/CommandMongo.js +59 -0
- package/src/flowchart/steps/CommandPrint.js +12 -0
- package/src/flowchart/steps/CommandSet.js +14 -0
- package/src/flowchart/steps/CommandTimeline.js +21 -0
- package/src/flowchart/steps/CommandTimelineNext.js +28 -0
- package/src/flowchart/steps/StepBasic.js +184 -0
- package/src/flowchart/steps/StepCheckProcessor.js +26 -0
- package/src/flowchart/steps/StepCheckSrc.js +42 -0
- package/src/flowchart/steps/StepIsTrue.js +12 -0
- package/src/flowchart/steps/StepOneTime.js +21 -0
- package/src/flowchart/steps/StepProcess.js +163 -0
- package/src/flowchart/steps/StepReadSrc.js +66 -0
- package/src/flowchart/steps/StepSleep.js +22 -0
- package/src/flowchart/steps/StepTimeLineEnds.js +21 -0
- package/src/flowchart/steps/StepTimeLineHasMore.js +16 -0
- package/src/gif/index.d.ts +20 -0
- package/src/gif/index.mjs +85 -0
- package/src/gif/utils/checkTypes.d.ts +2 -0
- package/src/gif/utils/checkTypes.mjs +11 -0
- package/src/js-colormaps.js +19484 -0
- package/src/sortify.js +75 -0
- package/src/sqlmodelparser/SqlModelParser.js +22 -0
- package/src/test/csv/test_1000_20230429204538700.csv +1001 -0
- package/src/test/csv/test_5_20230429204525930.csv +6 -0
- package/src/test/svg/test.html +5 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
|
|
2
|
+
function debounce(fn, delay) {
|
|
3
|
+
let timer = null;
|
|
4
|
+
|
|
5
|
+
return (...args) => {
|
|
6
|
+
if (timer) {
|
|
7
|
+
clearTimeout(timer);
|
|
8
|
+
}
|
|
9
|
+
timer = setTimeout(() => fn(...args), delay)
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
const GAP_ms = 500;
|
|
15
|
+
Si quieres tener en cuenta solo la primera invocación e ignorar las repetidas invocaciones con intervalos de menos de gap:
|
|
16
|
+
new MyThrottle(GAP_ms, true);
|
|
17
|
+
|
|
18
|
+
Si quieres tener en cuenta solo la última invocación entre repetidas invocaciones con intervalos de menos de gap:
|
|
19
|
+
new MyThrottle(GAP_ms, false);
|
|
20
|
+
*/
|
|
21
|
+
class MyThrottle {
|
|
22
|
+
constructor(timeGap, useFirst = true) {
|
|
23
|
+
this.timeGap = timeGap;
|
|
24
|
+
this.useFirst = useFirst;
|
|
25
|
+
this.lastCalledTime = 0;
|
|
26
|
+
this.isCalling = false;
|
|
27
|
+
this.isIgnoring = false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
throttle(promisedFunction) {
|
|
31
|
+
const afterGap = () => {
|
|
32
|
+
if (this.useFirst) {
|
|
33
|
+
if (calledTime == this.lastCalledTime) {
|
|
34
|
+
// Listen again
|
|
35
|
+
this.isIgnoring = false;
|
|
36
|
+
} else {
|
|
37
|
+
console.log("Ignoring...");
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
this.isIgnoring = false;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const calledTime = new Date().getTime();
|
|
44
|
+
this.lastCalledTime = calledTime;
|
|
45
|
+
if (this.useFirst && this.isIgnoring) {
|
|
46
|
+
setTimeout(afterGap, this.timeGap);
|
|
47
|
+
}
|
|
48
|
+
if (this.isCalling || this.isIgnoring) {
|
|
49
|
+
// Ignore
|
|
50
|
+
console.log("Ignoring...");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const afterCall = () => {
|
|
54
|
+
this.isCalling = false;
|
|
55
|
+
};
|
|
56
|
+
if (this.useFirst) {
|
|
57
|
+
// Use first
|
|
58
|
+
this.isCalling = true;
|
|
59
|
+
this.isIgnoring = true;
|
|
60
|
+
promisedFunction().finally(afterCall);
|
|
61
|
+
setTimeout(afterGap, this.timeGap);
|
|
62
|
+
} else {
|
|
63
|
+
// Use last
|
|
64
|
+
setTimeout(() => {
|
|
65
|
+
if (calledTime == this.lastCalledTime) {
|
|
66
|
+
// Call!
|
|
67
|
+
this.isCalling = true;
|
|
68
|
+
promisedFunction().finally(afterCall);
|
|
69
|
+
} else {
|
|
70
|
+
console.log("Ignoring...");
|
|
71
|
+
}
|
|
72
|
+
}, this.timeGap);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = {
|
|
78
|
+
MyThrottle,
|
|
79
|
+
debounce
|
|
80
|
+
};
|
package/src/MyTuples.js
ADDED
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
const { IdGen } = require("./IdGen");
|
|
2
|
+
const { SimpleObj } = require("./SimpleObj");
|
|
3
|
+
|
|
4
|
+
const TAMANIO_ALEATORIO = 10;
|
|
5
|
+
const MAX_BUFFER_CHANGES = 50;
|
|
6
|
+
|
|
7
|
+
const fakeProcessor = ({ min = 500, max = 1000 }) => {
|
|
8
|
+
return new Promise((resolve) => {
|
|
9
|
+
const tiempo = min + Math.random() * (max - min);
|
|
10
|
+
setTimeout(() => {
|
|
11
|
+
resolve();
|
|
12
|
+
}, tiempo);
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
class MyTuples {
|
|
17
|
+
static TIPOS_BASICOS = ["string", "number", "boolean"];
|
|
18
|
+
static arrayCompress({ someArray, maxLength = 65535 }) {
|
|
19
|
+
const response = [];
|
|
20
|
+
let actualString = "[";
|
|
21
|
+
let actualCount = 0;
|
|
22
|
+
for (let i = 0; i < someArray.length; i++) {
|
|
23
|
+
const actual = JSON.stringify(someArray[i]);
|
|
24
|
+
if (actual.length > maxLength - 2) {
|
|
25
|
+
throw new Error(`Can't compress with size ${maxLength} one item has size ${actual.length}`);
|
|
26
|
+
}
|
|
27
|
+
let caracteresExtra = 1;
|
|
28
|
+
if (actualCount > 0) {
|
|
29
|
+
caracteresExtra++;
|
|
30
|
+
}
|
|
31
|
+
if (actualString.length + actual.length > maxLength - caracteresExtra) {
|
|
32
|
+
// Se hace push y se crea un nuevo string
|
|
33
|
+
actualString += "]";
|
|
34
|
+
response.push(actualString);
|
|
35
|
+
actualString = "[";
|
|
36
|
+
actualString += actual;
|
|
37
|
+
actualCount = 1;
|
|
38
|
+
} else {
|
|
39
|
+
if (actualCount > 0) {
|
|
40
|
+
actualString += ",";
|
|
41
|
+
}
|
|
42
|
+
actualString += actual;
|
|
43
|
+
actualCount += 1;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Se agrega el último
|
|
47
|
+
if (actualString.length > 0) {
|
|
48
|
+
actualString += "]";
|
|
49
|
+
response.push(actualString);
|
|
50
|
+
}
|
|
51
|
+
return response;
|
|
52
|
+
};
|
|
53
|
+
static arrayUnCompress(someArray) {
|
|
54
|
+
const response = [];
|
|
55
|
+
for (let i = 0; i < someArray.length; i++) {
|
|
56
|
+
const actual = JSON.parse(someArray[i]);
|
|
57
|
+
for (let j = 0; j < actual.length; j++) {
|
|
58
|
+
response.push(actual[j]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return response;
|
|
62
|
+
}
|
|
63
|
+
static convertFromBD(model) {
|
|
64
|
+
const response = {};
|
|
65
|
+
model.forEach((value) => {
|
|
66
|
+
response[value.k] = value.v;
|
|
67
|
+
});
|
|
68
|
+
return response;
|
|
69
|
+
}
|
|
70
|
+
static getTuples(o, blackKeyPatterns = [], filterRoutes = []) {
|
|
71
|
+
const response = {};
|
|
72
|
+
let cache = [];
|
|
73
|
+
function isInBlackList(ruta) {
|
|
74
|
+
for (let i = 0; i < blackKeyPatterns.length; i++) {
|
|
75
|
+
const pattern = blackKeyPatterns[i];
|
|
76
|
+
if (pattern.test(ruta)) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
function startsWithInArray(ruta, filterRoutes) {
|
|
83
|
+
for (let i = 0; i < filterRoutes.length; i++) {
|
|
84
|
+
const prefix = filterRoutes[i];
|
|
85
|
+
if (ruta.startsWith(prefix)) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
function visitor(mo, path = []) {
|
|
92
|
+
if (typeof mo == "object") {
|
|
93
|
+
if (mo != null) {
|
|
94
|
+
if (cache.includes(mo)) return;
|
|
95
|
+
cache.push(mo);
|
|
96
|
+
}
|
|
97
|
+
for (const [key, value] of Object.entries(mo)) {
|
|
98
|
+
const rutaLocal = path.concat([key]);
|
|
99
|
+
const ruta = rutaLocal.join(".");
|
|
100
|
+
if (isInBlackList(ruta) || (filterRoutes.length > 0 && !startsWithInArray(ruta, filterRoutes))) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (MyTuples.TIPOS_BASICOS.indexOf(typeof value) >= 0 || value === null) {
|
|
104
|
+
response[ruta] = value;
|
|
105
|
+
} else {
|
|
106
|
+
if (typeof value == "object" && value !== null && !cache.includes(value)) {
|
|
107
|
+
if (value instanceof Array) {
|
|
108
|
+
response[ruta] = [];
|
|
109
|
+
} else {
|
|
110
|
+
response[ruta] = {};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
visitor(value, rutaLocal);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
visitor(o);
|
|
119
|
+
cache = null;
|
|
120
|
+
return response;
|
|
121
|
+
}
|
|
122
|
+
static getObject(t1, response = {}) {
|
|
123
|
+
const llaves = Object.keys(t1);
|
|
124
|
+
for (let i = 0; i < llaves.length; i++) {
|
|
125
|
+
const llave = llaves[i];
|
|
126
|
+
const valor = t1[llave];
|
|
127
|
+
SimpleObj.recreate(response, "t." + llave, valor);
|
|
128
|
+
}
|
|
129
|
+
return response;
|
|
130
|
+
}
|
|
131
|
+
static restarArreglo(a, b) {
|
|
132
|
+
return a.filter((value) => {
|
|
133
|
+
return b.indexOf(value) < 0;
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
static intersecionArreglo(a, b) {
|
|
137
|
+
return a.filter((value) => {
|
|
138
|
+
return b.indexOf(value) >= 0;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
static getBuilder(config = {}) {
|
|
142
|
+
const START_BACKOFF = typeof config.START_BACKOFF == "number" ? config.START_BACKOFF : 0;
|
|
143
|
+
const BACK_OFF_MULTIPLIER = typeof config.BACK_OFF_MULTIPLIER == "number" ? config.BACK_OFF_MULTIPLIER : 500;
|
|
144
|
+
// Cuántas tuplas se pueden afectar en un llamado
|
|
145
|
+
const MAX_SEND_SIZE = typeof config.MAX_SEND_SIZE == "number" ? config.MAX_SEND_SIZE : 20;
|
|
146
|
+
const LOW_PRESSURE_MS = typeof config.LOW_PRESSURE_MS == "number" ? config.LOW_PRESSURE_MS : 1000;
|
|
147
|
+
|
|
148
|
+
let blackKeyPatterns = [];
|
|
149
|
+
let resultado = {};
|
|
150
|
+
let myFreeze = null;
|
|
151
|
+
let pending = [];
|
|
152
|
+
let procesor = null;
|
|
153
|
+
let listeners = [];
|
|
154
|
+
let ultimaFechaInicio = null;
|
|
155
|
+
let isProcessing = false;
|
|
156
|
+
const ownTrackedChanges = [];
|
|
157
|
+
|
|
158
|
+
const setBlackKeyPatterns = (myBlack) => {
|
|
159
|
+
blackKeyPatterns = myBlack;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const addActivityListener = (a) => {
|
|
163
|
+
if (!(a in listeners)) {
|
|
164
|
+
listeners.push(a);
|
|
165
|
+
}
|
|
166
|
+
return () => {
|
|
167
|
+
const indice = listeners.indexOf(a);
|
|
168
|
+
listeners.splice(indice, 1);
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
const setActivityStatus = (value) => {
|
|
172
|
+
for (let i = 0; i < listeners.length; i++) {
|
|
173
|
+
const listener = listeners[i];
|
|
174
|
+
if (typeof listener == "function") {
|
|
175
|
+
listener(value);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const startProcess = () => {
|
|
181
|
+
// Single execution
|
|
182
|
+
if (isProcessing) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (typeof procesor != "function") {
|
|
186
|
+
setActivityStatus(false);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
// Low pressure
|
|
190
|
+
const ahora = new Date().getTime();
|
|
191
|
+
ultimaFechaInicio = ahora;
|
|
192
|
+
const internalFun = async () => {
|
|
193
|
+
if (ultimaFechaInicio == ahora) {
|
|
194
|
+
isProcessing = true;
|
|
195
|
+
// Notify
|
|
196
|
+
setActivityStatus(isProcessing);
|
|
197
|
+
// Then try process
|
|
198
|
+
const processAll = async () => {
|
|
199
|
+
if (pending.length > 0) {
|
|
200
|
+
const ultimo = JSON.parse(JSON.stringify(pending.splice(0, 1)[0]));
|
|
201
|
+
//Se deben partir los cambios en grupos de MAX_SEND_SIZE
|
|
202
|
+
const crearBatch = () => {
|
|
203
|
+
const batch = {
|
|
204
|
+
"r": createTrackId(),
|
|
205
|
+
"t": createTimestamp(),
|
|
206
|
+
"+": [],
|
|
207
|
+
"-": [],
|
|
208
|
+
"*": [],
|
|
209
|
+
total: 0,
|
|
210
|
+
};
|
|
211
|
+
trackChangeId(batch);
|
|
212
|
+
const pasarElemento = (simbolo) => {
|
|
213
|
+
const lista = ultimo[simbolo];
|
|
214
|
+
if (lista.length > 0) {
|
|
215
|
+
batch[simbolo].push(lista.splice(lista.length - 1, 1)[0]);
|
|
216
|
+
batch.total += 1;
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
return false;
|
|
220
|
+
};
|
|
221
|
+
const pasarAlgunElemento = () => {
|
|
222
|
+
return pasarElemento("-") || pasarElemento("+") || pasarElemento("*");
|
|
223
|
+
};
|
|
224
|
+
const pasarElementos = () => {
|
|
225
|
+
let pasoAlgo = false;
|
|
226
|
+
do {
|
|
227
|
+
pasoAlgo = pasarAlgunElemento();
|
|
228
|
+
} while (pasoAlgo && batch.total < MAX_SEND_SIZE);
|
|
229
|
+
};
|
|
230
|
+
pasarElementos();
|
|
231
|
+
return batch;
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
let unBatch;
|
|
235
|
+
do {
|
|
236
|
+
unBatch = crearBatch();
|
|
237
|
+
const reintentos = () => {
|
|
238
|
+
let backOffCount = START_BACKOFF;
|
|
239
|
+
return new Promise((resolve, reject) => {
|
|
240
|
+
const unIntento = () => {
|
|
241
|
+
// Retry infinitelly with linear backoff
|
|
242
|
+
const delay = backOffCount * BACK_OFF_MULTIPLIER;
|
|
243
|
+
//console.log(`unIntento delay ${delay}`);
|
|
244
|
+
setTimeout(async () => {
|
|
245
|
+
try {
|
|
246
|
+
const theResponse = await procesor(unBatch);
|
|
247
|
+
//const theResponse = await fakeProcessor();
|
|
248
|
+
resolve(theResponse);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
if ([403].indexOf(error.status) < 0) {
|
|
251
|
+
backOffCount += 1;
|
|
252
|
+
unIntento();
|
|
253
|
+
} else {
|
|
254
|
+
reject(error);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}, delay);
|
|
258
|
+
};
|
|
259
|
+
unIntento();
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
if (unBatch.total > 0) {
|
|
263
|
+
await reintentos();
|
|
264
|
+
}
|
|
265
|
+
} while (unBatch.total > 0);
|
|
266
|
+
}
|
|
267
|
+
return pending.length;
|
|
268
|
+
};//processAll
|
|
269
|
+
try {
|
|
270
|
+
let procesados = 0;
|
|
271
|
+
do {
|
|
272
|
+
// Se evacúa todo lo que está pendiente!
|
|
273
|
+
procesados = await processAll();
|
|
274
|
+
} while (procesados > 0);
|
|
275
|
+
} catch (err) {
|
|
276
|
+
// do nothing
|
|
277
|
+
}
|
|
278
|
+
isProcessing = false;
|
|
279
|
+
setActivityStatus(isProcessing);
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
if (LOW_PRESSURE_MS == 0) {
|
|
283
|
+
internalFun();
|
|
284
|
+
} else {
|
|
285
|
+
setTimeout(internalFun, LOW_PRESSURE_MS);//setTimeout
|
|
286
|
+
}
|
|
287
|
+
};//startProcess
|
|
288
|
+
|
|
289
|
+
const isOwnChange = (cambio) => {
|
|
290
|
+
const randomId = cambio["r"];
|
|
291
|
+
if (ownTrackedChanges.indexOf(randomId) >= 0) {
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
return false;
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const trackChangeId = (batch) => {
|
|
298
|
+
ownTrackedChanges.push(batch.r);
|
|
299
|
+
const tamanioActual = ownTrackedChanges.length;
|
|
300
|
+
const sobrantes = tamanioActual - MAX_BUFFER_CHANGES;
|
|
301
|
+
if (sobrantes > 0) {
|
|
302
|
+
ownTrackedChanges.splice(0, sobrantes);
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const createTimestamp = () => {
|
|
307
|
+
return IdGen.num2ord(new Date().getTime());
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const createTrackId = () => {
|
|
311
|
+
return Math.floor(Math.random() * Math.pow(10, TAMANIO_ALEATORIO)).toString(36);
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
return {
|
|
315
|
+
setBlackKeyPatterns,
|
|
316
|
+
isOwnChange,
|
|
317
|
+
addActivityListener,
|
|
318
|
+
build: (buffer) => {
|
|
319
|
+
resultado = MyTuples.getObject(buffer, resultado);
|
|
320
|
+
},
|
|
321
|
+
end: () => {
|
|
322
|
+
if (!resultado.t) {
|
|
323
|
+
resultado.t = {};
|
|
324
|
+
}
|
|
325
|
+
myFreeze = JSON.stringify(resultado.t);
|
|
326
|
+
return JSON.parse(myFreeze);
|
|
327
|
+
},
|
|
328
|
+
affect: (batch, listenerKeys = [], callback = null) => {
|
|
329
|
+
const tuplas1 = MyTuples.getTuples(JSON.parse(myFreeze));
|
|
330
|
+
const llavesBorrar = batch["-"];
|
|
331
|
+
const llavesNuevasModificadas = batch["*"].concat(batch["+"]);
|
|
332
|
+
|
|
333
|
+
//Borro las tuplas
|
|
334
|
+
for (let i = 0; i < llavesBorrar.length; i++) {
|
|
335
|
+
const llaveBorrar = llavesBorrar[i].k;
|
|
336
|
+
if (callback !== null && listenerKeys.indexOf(llaveBorrar) >= 0) {
|
|
337
|
+
callback(llaveBorrar, undefined);
|
|
338
|
+
}
|
|
339
|
+
delete tuplas1[llaveBorrar];
|
|
340
|
+
}
|
|
341
|
+
//Reemplazo las tuplas
|
|
342
|
+
for (let i = 0; i < llavesNuevasModificadas.length; i++) {
|
|
343
|
+
const nuevaModificar = llavesNuevasModificadas[i];
|
|
344
|
+
if (callback !== null && listenerKeys.indexOf(nuevaModificar.k) >= 0) {
|
|
345
|
+
callback(nuevaModificar.k, nuevaModificar.v);
|
|
346
|
+
}
|
|
347
|
+
tuplas1[nuevaModificar.k] = nuevaModificar.v;
|
|
348
|
+
}
|
|
349
|
+
const resultado = MyTuples.getObject(tuplas1, {});
|
|
350
|
+
if (!resultado.t) {
|
|
351
|
+
resultado.t = {};
|
|
352
|
+
}
|
|
353
|
+
myFreeze = JSON.stringify(resultado.t);
|
|
354
|
+
return JSON.parse(myFreeze);
|
|
355
|
+
},
|
|
356
|
+
setProcesor: (p) => {
|
|
357
|
+
procesor = p;
|
|
358
|
+
},
|
|
359
|
+
trackDifferences: (nuevo, listenerKeys = [], callback = null, filterRoutes = []) => {
|
|
360
|
+
const tuplas2 = MyTuples.getTuples(nuevo, blackKeyPatterns, filterRoutes);
|
|
361
|
+
const tuplas1 = MyTuples.getTuples(JSON.parse(myFreeze), blackKeyPatterns, filterRoutes);
|
|
362
|
+
|
|
363
|
+
const tuplas2Keys = Object.keys(tuplas2);
|
|
364
|
+
const tuplas1Keys = Object.keys(tuplas1);
|
|
365
|
+
|
|
366
|
+
// Calculas las nuevas (llaves de 2 menos las llaves de 1)
|
|
367
|
+
const nuevas = MyTuples.restarArreglo(tuplas2Keys, tuplas1Keys);
|
|
368
|
+
// Calcular las borradas (llaves de 1 menos las llaves de 2)
|
|
369
|
+
const borradas = MyTuples.restarArreglo(tuplas1Keys, tuplas2Keys);
|
|
370
|
+
// Calcular las modificadas (ver intersección de llaves)
|
|
371
|
+
const modificadas = MyTuples.intersecionArreglo(tuplas1Keys, tuplas2Keys);
|
|
372
|
+
|
|
373
|
+
const batch = {
|
|
374
|
+
"r": createTrackId(),
|
|
375
|
+
"t": createTimestamp(),
|
|
376
|
+
"+": [],
|
|
377
|
+
"-": [],
|
|
378
|
+
"*": [],
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
trackChangeId(batch);
|
|
382
|
+
|
|
383
|
+
for (let i = 0; i < nuevas.length; i++) {
|
|
384
|
+
const llave = nuevas[i];
|
|
385
|
+
if (callback != null && listenerKeys.indexOf(llave) >= 0) {
|
|
386
|
+
callback(llave, tuplas2[llave]);
|
|
387
|
+
}
|
|
388
|
+
batch["+"].push({
|
|
389
|
+
k: llave,
|
|
390
|
+
v: tuplas2[llave],
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
for (let i = 0; i < borradas.length; i++) {
|
|
394
|
+
const llave = borradas[i];
|
|
395
|
+
if (callback != null && listenerKeys.indexOf(llave) >= 0) {
|
|
396
|
+
callback(llave, undefined);
|
|
397
|
+
}
|
|
398
|
+
batch["-"].push({
|
|
399
|
+
k: llave,
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
for (let i = 0; i < modificadas.length; i++) {
|
|
403
|
+
const llave = modificadas[i];
|
|
404
|
+
let valor1 = tuplas1[llave];
|
|
405
|
+
let valor2 = tuplas2[llave];
|
|
406
|
+
if (typeof valor1 == "object" && valor1 != null) {
|
|
407
|
+
valor1 = JSON.stringify(valor1);
|
|
408
|
+
}
|
|
409
|
+
if (typeof valor2 == "object" && valor2 != null) {
|
|
410
|
+
valor2 = JSON.stringify(valor2);
|
|
411
|
+
}
|
|
412
|
+
if (valor1 !== valor2) {
|
|
413
|
+
if (callback != null && listenerKeys.indexOf(llave) >= 0) {
|
|
414
|
+
callback(llave, tuplas2[llave]);
|
|
415
|
+
}
|
|
416
|
+
batch["*"].push({
|
|
417
|
+
k: llave,
|
|
418
|
+
v: tuplas2[llave],
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const compFun = (a, b) => {
|
|
424
|
+
return b.k.length - a.k.length;
|
|
425
|
+
};
|
|
426
|
+
batch['*'].sort(compFun);
|
|
427
|
+
batch['-'].sort(compFun);
|
|
428
|
+
batch['+'].sort(compFun);
|
|
429
|
+
|
|
430
|
+
batch.total = batch['*'].length + batch['-'].length + batch['+'].length;
|
|
431
|
+
if (batch.total > 0) {
|
|
432
|
+
myFreeze = JSON.stringify(nuevo);
|
|
433
|
+
pending.push(batch);
|
|
434
|
+
startProcess();
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
return batch;
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
module.exports = {
|
|
444
|
+
MyTuples
|
|
445
|
+
};
|