@x-oasis/integer-buffer-set 0.1.20 → 0.1.24
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/dist/index.d.ts +12 -18
- package/dist/integer-buffer-set.cjs.development.js +133 -242
- package/dist/integer-buffer-set.cjs.development.js.map +1 -1
- package/dist/integer-buffer-set.cjs.production.min.js +1 -1
- package/dist/integer-buffer-set.cjs.production.min.js.map +1 -1
- package/dist/integer-buffer-set.esm.js +133 -242
- package/dist/integer-buffer-set.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +208 -360
package/src/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
|
|
16
16
|
const defaultMetaExtractor = (value) => value;
|
|
17
17
|
export const defaultBufferSize = 10;
|
|
18
|
+
const thresholdNumber = Number.MAX_SAFE_INTEGER - 100000;
|
|
18
19
|
|
|
19
20
|
// !!!!! should do meta validation...meta should has an index...
|
|
20
21
|
// value: original data `index` value
|
|
@@ -34,10 +35,8 @@ export const defaultBufferSize = 10;
|
|
|
34
35
|
// the set.
|
|
35
36
|
// feature: add / delete / update item will also in consider..
|
|
36
37
|
class IntegerBufferSet<Meta = any> {
|
|
37
|
-
private _size: number;
|
|
38
38
|
private _name: string;
|
|
39
39
|
private _bufferSize: number;
|
|
40
|
-
// private _positionToValueObject: ValueToPositionObject;
|
|
41
40
|
|
|
42
41
|
private _indexToMetaMap: IndexToMetaMap<Meta>;
|
|
43
42
|
private _metaToPositionMap: MetaToPositionMap<Meta>;
|
|
@@ -68,7 +67,6 @@ class IntegerBufferSet<Meta = any> {
|
|
|
68
67
|
this._indexExtractor = indexExtractor;
|
|
69
68
|
|
|
70
69
|
this._name = name;
|
|
71
|
-
// this._positionToValueObject = {};
|
|
72
70
|
|
|
73
71
|
/**
|
|
74
72
|
* this._indexToMetaMap is used to find the prev meta when finding a position for index.
|
|
@@ -79,7 +77,6 @@ class IntegerBufferSet<Meta = any> {
|
|
|
79
77
|
this._metaToIndexMap = new Map();
|
|
80
78
|
this._onTheFlyIndices = [];
|
|
81
79
|
|
|
82
|
-
this._size = 0;
|
|
83
80
|
this._bufferSize = bufferSize;
|
|
84
81
|
|
|
85
82
|
this._smallValues = new Heap([], this._smallerComparator);
|
|
@@ -87,9 +84,6 @@ class IntegerBufferSet<Meta = any> {
|
|
|
87
84
|
|
|
88
85
|
this.getNewPositionForIndex = this.getNewPositionForIndex.bind(this);
|
|
89
86
|
this.getIndexPosition = this.getIndexPosition.bind(this);
|
|
90
|
-
this.getSize = this.getSize.bind(this);
|
|
91
|
-
this.replacePositionInFliedIndices =
|
|
92
|
-
this.replacePositionInFliedIndices.bind(this);
|
|
93
87
|
this.replaceFurthestIndexPosition =
|
|
94
88
|
this.replaceFurthestIndexPosition.bind(this);
|
|
95
89
|
this._isOnTheFlyFullReturnHook = returnHook(
|
|
@@ -100,21 +94,28 @@ class IntegerBufferSet<Meta = any> {
|
|
|
100
94
|
this._lastUpdatedMS = this._loopMS;
|
|
101
95
|
}
|
|
102
96
|
|
|
103
|
-
getSize() {
|
|
104
|
-
return this._size;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
97
|
get bufferSize() {
|
|
108
98
|
return this._bufferSize;
|
|
109
99
|
}
|
|
110
100
|
|
|
101
|
+
isThresholdMeta(meta) {
|
|
102
|
+
if (typeof meta === 'number' && meta > thresholdNumber) return true;
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
111
106
|
setIsOnTheFlyFull(val: any) {
|
|
112
107
|
if (val != null) {
|
|
113
|
-
const data = this._onTheFlyIndices.filter((v) => v);
|
|
108
|
+
const data = this._onTheFlyIndices.filter((v) => v != null);
|
|
114
109
|
this._isOnTheFlyFull = data.length === this._bufferSize;
|
|
110
|
+
// console.log('fly ', this._isOnTheFlyFull, data.length, this._bufferSize);
|
|
115
111
|
}
|
|
116
112
|
}
|
|
117
113
|
|
|
114
|
+
resetOnTheFlies() {
|
|
115
|
+
this._isOnTheFlyFull = false;
|
|
116
|
+
this._onTheFlyIndices = [];
|
|
117
|
+
}
|
|
118
|
+
|
|
118
119
|
get isBufferFull() {
|
|
119
120
|
return this._positionToMetaList.length >= this._bufferSize;
|
|
120
121
|
}
|
|
@@ -123,7 +124,7 @@ class IntegerBufferSet<Meta = any> {
|
|
|
123
124
|
const { startIndex, endIndex } = safeRange;
|
|
124
125
|
for (let idx = 0; idx < this._onTheFlyIndices.length; idx++) {
|
|
125
126
|
const meta = this._onTheFlyIndices[idx];
|
|
126
|
-
const metaIndex = this.
|
|
127
|
+
const metaIndex = this.getMetaIndex(meta);
|
|
127
128
|
if (!isClamped(startIndex, metaIndex, endIndex)) {
|
|
128
129
|
return idx;
|
|
129
130
|
}
|
|
@@ -135,15 +136,17 @@ class IntegerBufferSet<Meta = any> {
|
|
|
135
136
|
return {
|
|
136
137
|
smallValues: new Heap([], this._smallerComparator),
|
|
137
138
|
largeValues: new Heap([], this._greaterComparator),
|
|
138
|
-
valueToPositionObject: {},
|
|
139
139
|
};
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
getIndexMeta(index: number) {
|
|
143
|
+
if (index == null || index < 0) return null;
|
|
143
144
|
return this._metaExtractor(index);
|
|
144
145
|
}
|
|
145
146
|
|
|
146
147
|
getMetaIndex(meta: Meta) {
|
|
148
|
+
if (meta == null) return -1;
|
|
149
|
+
if (this.isThresholdMeta(meta)) return -1;
|
|
147
150
|
if (this._indexExtractor) return this._indexExtractor(meta);
|
|
148
151
|
return this._metaToIndexMap.get(meta);
|
|
149
152
|
}
|
|
@@ -193,140 +196,19 @@ class IntegerBufferSet<Meta = any> {
|
|
|
193
196
|
return this._largeValues.peek()?.value;
|
|
194
197
|
}
|
|
195
198
|
|
|
196
|
-
|
|
197
|
-
* values actually is the position of original data.
|
|
198
|
-
*/
|
|
199
|
-
setValuePosition(value: number, position: number) {}
|
|
200
|
-
|
|
201
|
-
findPositionMeta(position: number) {
|
|
202
|
-
for (const [meta, pos] of this._metaToPositionMap) {
|
|
203
|
-
if (pos === position) return meta;
|
|
204
|
-
}
|
|
205
|
-
return null;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
rebuildHeapsWithMeta(metaToPositionMap: MetaToPositionMap<Meta>) {
|
|
209
|
-
const { smallValues, largeValues } = this.initialize();
|
|
210
|
-
|
|
211
|
-
for (const [meta, position] of metaToPositionMap) {
|
|
212
|
-
const index = this.getMetaIndex(meta);
|
|
213
|
-
const token = { index, position };
|
|
214
|
-
smallValues.push(token);
|
|
215
|
-
largeValues.push(token);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
this._smallValues = smallValues;
|
|
219
|
-
this._largeValues = largeValues;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
*
|
|
224
|
-
* @param position
|
|
225
|
-
* @param value
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*/
|
|
229
|
-
setPositionIndex(position: number, index: number) {
|
|
230
|
-
const meta = this._metaExtractor(index);
|
|
231
|
-
const originalPosition = this._metaToPositionMap.get(meta);
|
|
232
|
-
|
|
233
|
-
// current index has a position
|
|
234
|
-
if (originalPosition !== undefined) {
|
|
235
|
-
if (originalPosition === position) return true;
|
|
236
|
-
this.deleteMetaIndex(meta);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const metaToReplace = this.findPositionMeta(position);
|
|
240
|
-
if (metaToReplace) this._metaToPositionMap.delete(metaToReplace);
|
|
241
|
-
this._metaToPositionMap.set(meta, position);
|
|
242
|
-
|
|
243
|
-
this.rebuildHeapsWithMeta(this._metaToPositionMap);
|
|
244
|
-
return true;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
getMetaPosition(meta: Meta) {
|
|
248
|
-
return this._metaToPositionMap.get(meta);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// performRangeUpdate(
|
|
252
|
-
// startIndex: number,
|
|
253
|
-
// endIndex: number,
|
|
254
|
-
// safeRange: {
|
|
255
|
-
// startIndex: number;
|
|
256
|
-
// endIndex: number;
|
|
257
|
-
// }
|
|
258
|
-
// ) {
|
|
259
|
-
// const _start = Math.max(startIndex, safeRange.startIndex);
|
|
260
|
-
// const _end = Math.min(endIndex, safeRange.endIndex);
|
|
261
|
-
// const primaryMetaList = [];
|
|
262
|
-
// const secondaryMetaList = [];
|
|
263
|
-
// const locationStartIndex = startIndex;
|
|
264
|
-
// const targetIndices = new Array(this._bufferSize);
|
|
265
|
-
|
|
266
|
-
// const _valueToPositionObject = {};
|
|
267
|
-
// const _positionToValueObject = {};
|
|
268
|
-
|
|
269
|
-
// const _valueToMetaObject = {};
|
|
270
|
-
// const _metaToIndexMap = new Map();
|
|
271
|
-
|
|
272
|
-
// for (let value = startIndex; value <= endIndex; value++) {
|
|
273
|
-
// const meta = this._metaExtractor(value);
|
|
274
|
-
// if (meta) {
|
|
275
|
-
// const _i = value - locationStartIndex;
|
|
276
|
-
// if (isClamped(value, safeRange.startIndex, safeRange.endIndex)) {
|
|
277
|
-
// primaryMetaList[_i] = meta;
|
|
278
|
-
// const targetIndex = this.getMetaPosition(meta);
|
|
279
|
-
// if (isNumber(targetIndex)) {
|
|
280
|
-
// targetIndices[targetIndex] = value;
|
|
281
|
-
// _valueToPositionObject[value] = targetIndex;
|
|
282
|
-
// _valueToMetaObject[value] = meta;
|
|
283
|
-
// _metaToIndexMap.set(meta, value);
|
|
284
|
-
// _positionToValueObject[targetIndex] = value;
|
|
285
|
-
// }
|
|
286
|
-
// } else {
|
|
287
|
-
// secondaryMetaList[_i] = meta;
|
|
288
|
-
// }
|
|
289
|
-
// }
|
|
290
|
-
// }
|
|
291
|
-
|
|
292
|
-
// for (let idx = _start; idx <= _end; idx++) {
|
|
293
|
-
// const meta = this._metaExtractor(idx);
|
|
294
|
-
// if (_metaToIndexMap.get(meta) !== undefined) continue;
|
|
295
|
-
// let p;
|
|
296
|
-
// while (
|
|
297
|
-
// (p =
|
|
298
|
-
// targetIndices[
|
|
299
|
-
// this.resolvePosition(safeRange.startIndex, safeRange.endIndex, idx)
|
|
300
|
-
// ]) === undefined
|
|
301
|
-
// ) {
|
|
302
|
-
// targetIndices[p] = idx;
|
|
303
|
-
// }
|
|
304
|
-
// }
|
|
305
|
-
// }
|
|
306
|
-
|
|
307
|
-
replacePositionInFliedIndices(newIndex: number, safeRange: SafeRange) {
|
|
308
|
-
const { startIndex, endIndex } = safeRange;
|
|
309
|
-
|
|
199
|
+
getFliedPosition(newIndex: number, safeRange: SafeRange) {
|
|
310
200
|
if (this._isOnTheFlyFull) {
|
|
311
201
|
// newIndex is not critical index, do nothing
|
|
312
|
-
if (
|
|
313
|
-
|
|
202
|
+
if (
|
|
203
|
+
safeRange &&
|
|
204
|
+
isClamped(safeRange.startIndex, newIndex, safeRange.endIndex)
|
|
205
|
+
) {
|
|
206
|
+
return this.getOnTheFlyUncriticalPosition(safeRange);
|
|
314
207
|
}
|
|
315
208
|
// if `newIndex` is critical index, replace an un-committed
|
|
316
209
|
// index value from _onTheFlyIndices.
|
|
317
|
-
const pos = this.getOnTheFlyUncriticalPosition(safeRange);
|
|
318
|
-
if (pos != null) return pos;
|
|
319
|
-
}
|
|
320
|
-
return null;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
getFliedPosition(newIndex: number, safeRange: SafeRange) {
|
|
324
|
-
const pos = this.replacePositionInFliedIndices(newIndex, safeRange);
|
|
325
|
-
if (pos != null) {
|
|
326
|
-
const meta = this.getIndexMeta(newIndex);
|
|
327
|
-
this._onTheFlyIndices[pos] = meta;
|
|
328
|
-
this._setMetaIndex(meta, newIndex);
|
|
329
|
-
return this._isOnTheFlyFullReturnHook(pos);
|
|
210
|
+
// const pos = this.getOnTheFlyUncriticalPosition(safeRange);
|
|
211
|
+
// if (pos != null) return pos;
|
|
330
212
|
}
|
|
331
213
|
return null;
|
|
332
214
|
}
|
|
@@ -343,74 +225,73 @@ class IntegerBufferSet<Meta = any> {
|
|
|
343
225
|
getPosition(newIndex: number, safeRange?: SafeRange) {
|
|
344
226
|
this.prepare();
|
|
345
227
|
const meta = this.getIndexMeta(newIndex);
|
|
346
|
-
const
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
228
|
+
const metaPosition = this._metaToPositionMap.get(meta);
|
|
229
|
+
let position, indexMeta;
|
|
230
|
+
|
|
231
|
+
// if (this._name === 'normal_goods')
|
|
232
|
+
// console.log(
|
|
233
|
+
// 'getPosition ',
|
|
234
|
+
// newIndex,
|
|
235
|
+
// !this.isBufferFull,
|
|
236
|
+
// this._isOnTheFlyFull,
|
|
237
|
+
// this._onTheFlyIndices.slice(),
|
|
238
|
+
// this._indexToMetaMap.get(newIndex),
|
|
239
|
+
// this._metaToPositionMap.get(this._indexToMetaMap.get(newIndex))
|
|
240
|
+
// );
|
|
241
|
+
|
|
242
|
+
if (metaPosition !== undefined) {
|
|
243
|
+
position = this.commitPosition({
|
|
244
|
+
newIndex,
|
|
245
|
+
meta,
|
|
246
|
+
safeRange,
|
|
247
|
+
position: metaPosition,
|
|
248
|
+
});
|
|
249
|
+
} else if (!this.isBufferFull) {
|
|
250
|
+
/** placed on new buffered position */
|
|
251
|
+
position = this.getNewPositionForIndex(newIndex);
|
|
252
|
+
} else if (this._isOnTheFlyFull) {
|
|
253
|
+
position = this.getFliedPosition(newIndex, safeRange);
|
|
254
|
+
} else if (
|
|
255
|
+
(indexMeta = this._indexToMetaMap.get(newIndex)) &&
|
|
256
|
+
this._metaToPositionMap.get(indexMeta)
|
|
257
|
+
) {
|
|
258
|
+
/**
|
|
259
|
+
Index has already been stored, but we cant use its old position directly...
|
|
260
|
+
1:index -> meta, meta may be reused later
|
|
261
|
+
2: temp use index -> meta -> position, this issue should exist for follows...
|
|
262
|
+
*/
|
|
263
|
+
position = this.commitPosition({
|
|
264
|
+
newIndex,
|
|
265
|
+
meta,
|
|
266
|
+
safeRange,
|
|
267
|
+
position: this._metaToPositionMap.get(indexMeta),
|
|
268
|
+
});
|
|
269
|
+
} else {
|
|
270
|
+
this._cleanHeaps();
|
|
271
|
+
// console.log('commeit ---')
|
|
272
|
+
position = this.commitPosition({
|
|
273
|
+
newIndex,
|
|
274
|
+
meta,
|
|
275
|
+
safeRange,
|
|
276
|
+
position: this._replaceFurthestIndexPosition(newIndex, safeRange),
|
|
277
|
+
});
|
|
378
278
|
}
|
|
379
279
|
|
|
380
|
-
//
|
|
381
|
-
if (!this.isBufferFull)
|
|
382
|
-
return this._isOnTheFlyFullReturnHook(
|
|
383
|
-
this.getNewPositionForIndex(newIndex)
|
|
384
|
-
);
|
|
385
|
-
|
|
386
|
-
// console.log('this. fly ', this._isOnTheFlyFull)
|
|
387
|
-
if (this._isOnTheFlyFull) return this.getFliedPosition(newIndex, safeRange);
|
|
280
|
+
// console.log('position ', position)
|
|
388
281
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
282
|
+
if (position != null) {
|
|
283
|
+
this._onTheFlyIndices[position] = meta;
|
|
284
|
+
this._setMetaIndex(meta, newIndex);
|
|
285
|
+
this._metaToPositionMap.set(meta, position);
|
|
392
286
|
|
|
393
|
-
|
|
394
|
-
|
|
287
|
+
// this._setMetaPosition(meta, position);
|
|
288
|
+
// should not push to heap, pop only
|
|
289
|
+
// this._pushToHeaps(position, newIndex)
|
|
395
290
|
|
|
396
|
-
|
|
397
|
-
if (!prevIndexMeta) {
|
|
398
|
-
this._cleanHeaps();
|
|
399
|
-
positionToReplace = this._replaceFurthestIndexPosition(
|
|
400
|
-
newIndex,
|
|
401
|
-
safeRange
|
|
402
|
-
);
|
|
403
|
-
} else {
|
|
404
|
-
positionToReplace = this._metaToPositionMap.get(prevIndexMeta);
|
|
291
|
+
return this._isOnTheFlyFullReturnHook(position);
|
|
405
292
|
}
|
|
406
293
|
|
|
407
|
-
|
|
408
|
-
this._setMetaIndex(meta, newIndex);
|
|
409
|
-
this._setMetaPosition(meta, positionToReplace);
|
|
410
|
-
// should not push to heap, pop only
|
|
411
|
-
// this._pushToHeaps(positionToReplace, newIndex)
|
|
412
|
-
|
|
413
|
-
return this._isOnTheFlyFullReturnHook(positionToReplace);
|
|
294
|
+
return null;
|
|
414
295
|
}
|
|
415
296
|
|
|
416
297
|
replaceFurthestIndexPosition(
|
|
@@ -442,11 +323,19 @@ class IntegerBufferSet<Meta = any> {
|
|
|
442
323
|
);
|
|
443
324
|
}
|
|
444
325
|
|
|
326
|
+
let indexToReplace;
|
|
327
|
+
|
|
445
328
|
const minValue = this._smallValues.peek()!.value;
|
|
446
329
|
const maxValue = this._largeValues.peek()!.value;
|
|
447
330
|
|
|
448
|
-
// console.log('
|
|
449
|
-
|
|
331
|
+
// console.log('mathc ', maxValue, maxValue > thresholdNumber)
|
|
332
|
+
if (maxValue > thresholdNumber) {
|
|
333
|
+
indexToReplace = maxValue;
|
|
334
|
+
this._largeValues.pop();
|
|
335
|
+
const replacedMeta = this._indexToMetaMap.get(indexToReplace);
|
|
336
|
+
const position = this._metaToPositionMap.get(replacedMeta);
|
|
337
|
+
return position;
|
|
338
|
+
}
|
|
450
339
|
|
|
451
340
|
if (!safeRange) {
|
|
452
341
|
// far from min
|
|
@@ -495,6 +384,8 @@ class IntegerBufferSet<Meta = any> {
|
|
|
495
384
|
const replacedMeta = this._indexToMetaMap.get(indexToReplace);
|
|
496
385
|
const position = this._metaToPositionMap.get(replacedMeta);
|
|
497
386
|
|
|
387
|
+
// console.log('index ', indexToReplace, replacedMeta, position)
|
|
388
|
+
|
|
498
389
|
return position;
|
|
499
390
|
}
|
|
500
391
|
|
|
@@ -502,29 +393,30 @@ class IntegerBufferSet<Meta = any> {
|
|
|
502
393
|
const indices = new Array(this.bufferSize);
|
|
503
394
|
for (let idx = 0; idx < indices.length; idx++) {
|
|
504
395
|
const meta = this._onTheFlyIndices[idx] || this._positionToMetaList[idx];
|
|
396
|
+
// console.log('ix ', idx,this.getMetaIndex(meta) )
|
|
505
397
|
const targetIndex = this.getMetaIndex(meta);
|
|
506
398
|
indices[idx] = targetIndex;
|
|
507
399
|
}
|
|
508
400
|
|
|
509
401
|
// console.log(
|
|
510
|
-
// '
|
|
402
|
+
// 'indices ',
|
|
511
403
|
// this._positionToMetaList,
|
|
512
|
-
// this._onTheFlyIndices
|
|
404
|
+
// this._onTheFlyIndices.slice(),
|
|
405
|
+
// indices
|
|
513
406
|
// );
|
|
514
407
|
|
|
515
408
|
const _arr = new Array(indices.length);
|
|
516
409
|
const _available = [];
|
|
517
410
|
const indexToMetaMap = new Map();
|
|
518
411
|
const metaToIndexMap = new Map();
|
|
519
|
-
|
|
412
|
+
|
|
520
413
|
for (let idx = 0; idx < indices.length; idx++) {
|
|
521
414
|
const currentIndex = indices[idx];
|
|
522
415
|
const currentMeta = this._metaExtractor(currentIndex);
|
|
416
|
+
// console.log("current ", currentIndex, currentMeta)
|
|
523
417
|
if (currentMeta == null) continue;
|
|
524
|
-
|
|
525
418
|
indexToMetaMap.set(currentIndex, currentMeta);
|
|
526
419
|
metaToIndexMap.set(currentMeta, currentIndex);
|
|
527
|
-
|
|
528
420
|
if (currentMeta === this._positionToMetaList[idx]) {
|
|
529
421
|
_arr[idx] = currentMeta;
|
|
530
422
|
continue;
|
|
@@ -538,74 +430,49 @@ class IntegerBufferSet<Meta = any> {
|
|
|
538
430
|
_available.push(currentMeta);
|
|
539
431
|
}
|
|
540
432
|
|
|
541
|
-
const { smallValues, largeValues } = this.initialize();
|
|
542
433
|
const positionToMetaList = [];
|
|
434
|
+
this._indexToMetaMap = indexToMetaMap;
|
|
435
|
+
this.replaceMetaToIndexMap(metaToIndexMap);
|
|
543
436
|
|
|
544
437
|
for (let position = 0; position < indices.length; position++) {
|
|
545
|
-
const value = indices[position];
|
|
546
438
|
if (_arr[position] != null) {
|
|
547
439
|
positionToMetaList[position] = _arr[position];
|
|
548
|
-
metaToPositionMap.set(_arr[position], position);
|
|
549
|
-
const element = { position, value };
|
|
550
|
-
smallValues.push(element);
|
|
551
|
-
largeValues.push(element);
|
|
552
440
|
continue;
|
|
553
441
|
}
|
|
554
442
|
const meta = _available.shift();
|
|
555
443
|
if (meta != null) {
|
|
556
444
|
positionToMetaList[position] = meta;
|
|
557
|
-
metaToPositionMap.set(meta, position);
|
|
558
|
-
|
|
559
|
-
const element = { position, value };
|
|
560
|
-
smallValues.push(element);
|
|
561
|
-
largeValues.push(element);
|
|
562
445
|
}
|
|
563
446
|
}
|
|
564
447
|
|
|
565
|
-
// console.log('position ', positionToMetaList, largeValues.peek().value);
|
|
566
|
-
|
|
567
448
|
this._positionToMetaList = positionToMetaList;
|
|
568
|
-
this._smallValues = smallValues;
|
|
569
|
-
this._largeValues = largeValues;
|
|
570
|
-
this._indexToMetaMap = indexToMetaMap;
|
|
571
|
-
this.replaceMetaToIndexMap(metaToIndexMap);
|
|
572
|
-
this._metaToPositionMap = metaToPositionMap;
|
|
573
|
-
this._onTheFlyIndices = [];
|
|
574
449
|
|
|
575
|
-
|
|
576
|
-
const indices = new Array(this.bufferSize);
|
|
577
|
-
for (let idx = 0; idx < indices.length; idx++) {
|
|
578
|
-
const meta =
|
|
579
|
-
this._onTheFlyIndices[idx] || this._positionToMetaList[idx];
|
|
580
|
-
const targetIndex = this.getMetaIndex(meta);
|
|
581
|
-
if (meta != null) {
|
|
582
|
-
indices[idx] = {
|
|
583
|
-
meta,
|
|
584
|
-
targetIndex,
|
|
585
|
-
recyclerKey: `${this._name}_${idx}`,
|
|
586
|
-
};
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
return indices;
|
|
590
|
-
} catch (err) {
|
|
591
|
-
this.readyToStartNextLoop();
|
|
592
|
-
return this._positionToMetaList;
|
|
593
|
-
}
|
|
450
|
+
return this.getIndices();
|
|
594
451
|
}
|
|
595
452
|
|
|
596
453
|
// key point: `meta` should be preserved..
|
|
597
454
|
getIndices() {
|
|
455
|
+
const { smallValues, largeValues } = this.initialize();
|
|
456
|
+
|
|
598
457
|
try {
|
|
599
|
-
const indices = new Array(this.
|
|
458
|
+
const indices = new Array(this._positionToMetaList.length);
|
|
459
|
+
const metaToPositionMap = new Map();
|
|
600
460
|
for (let idx = 0; idx < indices.length; idx++) {
|
|
601
461
|
const meta =
|
|
602
462
|
this._onTheFlyIndices[idx] || this._positionToMetaList[idx];
|
|
603
463
|
const targetIndex = this.getMetaIndex(meta);
|
|
604
464
|
// which means source data has changed. such as one element has been deleted
|
|
605
|
-
if (
|
|
465
|
+
if (
|
|
466
|
+
!this.isThresholdMeta(meta) &&
|
|
467
|
+
meta != this.getIndexMeta(targetIndex)
|
|
468
|
+
) {
|
|
606
469
|
return this.shuffle();
|
|
607
470
|
}
|
|
608
|
-
if (meta != null) {
|
|
471
|
+
if (meta != null && !this.isThresholdMeta(meta)) {
|
|
472
|
+
const element = { position: idx, value: targetIndex };
|
|
473
|
+
smallValues.push(element);
|
|
474
|
+
largeValues.push(element);
|
|
475
|
+
metaToPositionMap.set(meta, idx);
|
|
609
476
|
indices[idx] = {
|
|
610
477
|
meta,
|
|
611
478
|
targetIndex,
|
|
@@ -613,13 +480,19 @@ class IntegerBufferSet<Meta = any> {
|
|
|
613
480
|
};
|
|
614
481
|
}
|
|
615
482
|
}
|
|
616
|
-
|
|
617
|
-
this.
|
|
483
|
+
this._smallValues = smallValues;
|
|
484
|
+
this._largeValues = largeValues;
|
|
485
|
+
this._metaToPositionMap = metaToPositionMap;
|
|
486
|
+
this._positionToMetaList = indices.map((v) => v?.meta);
|
|
487
|
+
this.resetOnTheFlies();
|
|
618
488
|
|
|
619
489
|
return indices;
|
|
620
490
|
} catch (err) {
|
|
621
|
-
|
|
491
|
+
console.log('err ', err);
|
|
622
492
|
return this._positionToMetaList;
|
|
493
|
+
} finally {
|
|
494
|
+
this.readyToStartNextLoop();
|
|
495
|
+
// clear on the fly indices after return indices.
|
|
623
496
|
}
|
|
624
497
|
}
|
|
625
498
|
|
|
@@ -631,12 +504,45 @@ class IntegerBufferSet<Meta = any> {
|
|
|
631
504
|
}
|
|
632
505
|
|
|
633
506
|
_setMetaPosition(meta: Meta, position: number) {
|
|
634
|
-
|
|
635
|
-
|
|
507
|
+
// do not delete meta2position; because getPosition will get by meta first...
|
|
508
|
+
// const prevMetaOnPosition = this._positionToMetaList[position];
|
|
509
|
+
// if (prevMetaOnPosition) this._metaToPositionMap.delete(prevMetaOnPosition);
|
|
636
510
|
this._positionToMetaList[position] = meta;
|
|
637
511
|
this._metaToPositionMap.set(meta, position);
|
|
638
512
|
}
|
|
639
513
|
|
|
514
|
+
commitPosition(props: {
|
|
515
|
+
newIndex: number;
|
|
516
|
+
position: number;
|
|
517
|
+
meta: Meta;
|
|
518
|
+
safeRange: SafeRange;
|
|
519
|
+
}) {
|
|
520
|
+
const { newIndex, safeRange, position, meta } = props;
|
|
521
|
+
const onTheFlyPositionMeta = this._onTheFlyIndices[position];
|
|
522
|
+
let positionToReplace = position;
|
|
523
|
+
|
|
524
|
+
// console.log('position ', newIndex, position);
|
|
525
|
+
|
|
526
|
+
if (onTheFlyPositionMeta) {
|
|
527
|
+
// such as place item 11 twice...
|
|
528
|
+
if (onTheFlyPositionMeta === meta) return position;
|
|
529
|
+
if (this._isOnTheFlyFull)
|
|
530
|
+
return this.getFliedPosition(newIndex, safeRange);
|
|
531
|
+
positionToReplace = this._replaceFurthestIndexPosition(
|
|
532
|
+
newIndex,
|
|
533
|
+
safeRange
|
|
534
|
+
);
|
|
535
|
+
|
|
536
|
+
while (this._onTheFlyIndices[positionToReplace]) {
|
|
537
|
+
positionToReplace = this._replaceFurthestIndexPosition(
|
|
538
|
+
newIndex,
|
|
539
|
+
safeRange
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return positionToReplace;
|
|
544
|
+
}
|
|
545
|
+
|
|
640
546
|
/**
|
|
641
547
|
*
|
|
642
548
|
* @param meta
|
|
@@ -665,16 +571,21 @@ class IntegerBufferSet<Meta = any> {
|
|
|
665
571
|
|
|
666
572
|
this._onTheFlyIndices = [];
|
|
667
573
|
this._isOnTheFlyFull = false;
|
|
668
|
-
const len = this._positionToMetaList.length;
|
|
669
|
-
|
|
670
|
-
for (let index = 0; index < len; index++) {}
|
|
671
574
|
}
|
|
672
575
|
|
|
673
576
|
_cleanHeaps() {
|
|
674
577
|
// We not usually only remove object from one heap while moving value.
|
|
675
578
|
// Here we make sure that there is no stale data on top of heaps.
|
|
676
|
-
this._cleanHeap(this._smallValues);
|
|
677
|
-
this._cleanHeap(this._largeValues);
|
|
579
|
+
// this._cleanHeap(this._smallValues);
|
|
580
|
+
// this._cleanHeap(this._largeValues);
|
|
581
|
+
|
|
582
|
+
for (let idx = 0; idx < this._positionToMetaList.length; idx++) {
|
|
583
|
+
if (this._positionToMetaList[idx] == null) {
|
|
584
|
+
this._recreateHeaps();
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
678
589
|
const minHeapSize = Math.min(
|
|
679
590
|
this._smallValues.size(),
|
|
680
591
|
this._largeValues.size()
|
|
@@ -689,112 +600,49 @@ class IntegerBufferSet<Meta = any> {
|
|
|
689
600
|
this._recreateHeaps();
|
|
690
601
|
}
|
|
691
602
|
}
|
|
603
|
+
_recreateHeaps() {
|
|
604
|
+
const { smallValues, largeValues } = this.initialize();
|
|
605
|
+
for (
|
|
606
|
+
let position = 0;
|
|
607
|
+
position < this._positionToMetaList.length;
|
|
608
|
+
position++
|
|
609
|
+
) {
|
|
610
|
+
const meta = this._positionToMetaList[position];
|
|
611
|
+
let value = this.getMetaIndex(meta);
|
|
692
612
|
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
position: number;
|
|
696
|
-
value: number;
|
|
697
|
-
}>
|
|
698
|
-
) {
|
|
699
|
-
const valueToPositionObject = {};
|
|
700
|
-
const newSmallValues = new Heap<HeapItem>([], this._smallerComparator);
|
|
701
|
-
const newLargeValues = new Heap<HeapItem>([], this._greaterComparator);
|
|
702
|
-
|
|
703
|
-
arr.forEach((element) => {
|
|
704
|
-
const { position, value } = element;
|
|
705
|
-
if (value !== undefined) {
|
|
706
|
-
const element = {
|
|
707
|
-
position,
|
|
708
|
-
value,
|
|
709
|
-
};
|
|
710
|
-
newSmallValues.push(element);
|
|
711
|
-
newLargeValues.push(element);
|
|
712
|
-
valueToPositionObject[value] = position;
|
|
713
|
-
}
|
|
714
|
-
});
|
|
715
|
-
const _arr = new Array(this._bufferSize).fill(2);
|
|
716
|
-
Object.keys(valueToPositionObject).map(
|
|
717
|
-
(key) => (_arr[valueToPositionObject[key]] = 1)
|
|
718
|
-
);
|
|
719
|
-
_arr.forEach((_i, position) => {
|
|
720
|
-
if (_i === 2) {
|
|
721
|
-
const value = Number.MAX_SAFE_INTEGER - position;
|
|
722
|
-
const element = {
|
|
723
|
-
position,
|
|
724
|
-
value,
|
|
725
|
-
};
|
|
726
|
-
|
|
727
|
-
newSmallValues.push(element);
|
|
728
|
-
newLargeValues.push(element);
|
|
729
|
-
valueToPositionObject[value] = position;
|
|
613
|
+
if (!meta || value === -1 || value == null) {
|
|
614
|
+
value = Number.MAX_SAFE_INTEGER - position;
|
|
730
615
|
}
|
|
731
|
-
});
|
|
732
|
-
this._smallValues = newSmallValues;
|
|
733
|
-
this._largeValues = newLargeValues;
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
// rebuildHeaps() {
|
|
737
|
-
// const valueToPositionObject = {};
|
|
738
|
-
// const newSmallValues = new Heap<HeapItem>([], this._smallerComparator);
|
|
739
|
-
// const newLargeValues = new Heap<HeapItem>([], this._greaterComparator);
|
|
740
|
-
|
|
741
|
-
// const keys = Object.keys(this._positionToValueObject);
|
|
742
|
-
// for (let position = 0; position < keys.length; position++) {
|
|
743
|
-
// const value = this._positionToValueObject[position];
|
|
744
|
-
// if (value !== undefined) {
|
|
745
|
-
// const element = {
|
|
746
|
-
// position,
|
|
747
|
-
// value,
|
|
748
|
-
// };
|
|
749
|
-
// valueToPositionObject[value] = position;
|
|
750
|
-
// newSmallValues.push(element);
|
|
751
|
-
// newLargeValues.push(element);
|
|
752
|
-
// }
|
|
753
|
-
// }
|
|
754
|
-
|
|
755
|
-
// this._smallValues = newSmallValues;
|
|
756
|
-
// this._largeValues = newLargeValues;
|
|
757
|
-
// }
|
|
758
616
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
);
|
|
768
|
-
const newLargeValues = new Heap<HeapItem>(
|
|
769
|
-
[], // Initial datat in the heap
|
|
770
|
-
this._greaterComparator
|
|
771
|
-
);
|
|
772
|
-
while (!sourceHeap.empty()) {
|
|
773
|
-
const element = sourceHeap.pop()!;
|
|
774
|
-
// Push all still valid elements to new heaps
|
|
775
|
-
if (
|
|
776
|
-
this._metaToPositionMap.get(this._indexToMetaMap.get(element.value)) !=
|
|
777
|
-
null
|
|
778
|
-
) {
|
|
779
|
-
newSmallValues.push(element);
|
|
780
|
-
newLargeValues.push(element);
|
|
617
|
+
const element = { position, value };
|
|
618
|
+
smallValues.push(element);
|
|
619
|
+
largeValues.push(element);
|
|
620
|
+
if (value > thresholdNumber) {
|
|
621
|
+
// @ts-ignore
|
|
622
|
+
this._setMetaPosition(value, position);
|
|
623
|
+
// @ts-ignore
|
|
624
|
+
this._setMetaIndex(value, value);
|
|
781
625
|
}
|
|
782
626
|
}
|
|
783
|
-
this._smallValues = newSmallValues;
|
|
784
|
-
this._largeValues = newLargeValues;
|
|
785
|
-
}
|
|
786
627
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
this._indexToMetaMap.get(heap.peek()!.value)
|
|
792
|
-
) == null
|
|
793
|
-
) {
|
|
794
|
-
heap.pop();
|
|
795
|
-
}
|
|
628
|
+
this._largeValues.peek().value;
|
|
629
|
+
|
|
630
|
+
this._smallValues = smallValues;
|
|
631
|
+
this._largeValues = largeValues;
|
|
796
632
|
}
|
|
797
633
|
|
|
634
|
+
// _cleanHeap(heap: Heap<HeapItem>) {
|
|
635
|
+
// while (
|
|
636
|
+
// !heap.empty() &&
|
|
637
|
+
// this._metaToPositionMap.get(
|
|
638
|
+
// this._indexToMetaMap.get(heap.peek()!.value)
|
|
639
|
+
// ) == null
|
|
640
|
+
// ) {
|
|
641
|
+
// console.log('pop ---', heap.peek()!.value);
|
|
642
|
+
// heap.pop();
|
|
643
|
+
// }
|
|
644
|
+
// }
|
|
645
|
+
|
|
798
646
|
_smallerComparator(lhs: HeapItem, rhs: HeapItem) {
|
|
799
647
|
return lhs.value < rhs.value;
|
|
800
648
|
}
|