UNPKG

vscroll

Version:
129 lines 4.27 kB
import { SizeStrategy } from '../../inputs/index'; export class SizesRecalculation { constructor() { this.reset(); } reset() { this.newItems = []; this.oldItems = []; this.removed = []; } } export class DefaultSize { constructor(itemSize, sizeStrategy) { this.itemSize = itemSize; this.sizeStrategy = sizeStrategy; this.sizeMap = new Map(); this.recalculation = new SizesRecalculation(); } reset(force) { if (force) { this.constantSize = this.itemSize; this.frequentSize = this.itemSize; this.averageSize = this.itemSize; this.averageSizeFloat = this.itemSize; this.sizeMap.clear(); } this.recalculation.reset(); } get() { switch (this.sizeStrategy) { case SizeStrategy.Average: return this.averageSize; case SizeStrategy.Frequent: return this.frequentSize; default: return this.constantSize; } } recalculateAverageSize(cacheSize) { const { oldItems, newItems, removed } = this.recalculation; if (oldItems.length) { const oldSize = oldItems.reduce((acc, item) => acc + item.size, 0); const newSize = oldItems.reduce((acc, item) => acc + item.newSize, 0); const averageSize = this.averageSizeFloat || 0; this.averageSizeFloat = averageSize - (oldSize - newSize) / (cacheSize - newItems.length); } if (newItems.length) { const newSize = newItems.reduce((acc, item) => acc + item.size, 0); const averageSize = this.averageSizeFloat || 0; this.averageSizeFloat = ((cacheSize - newItems.length) * averageSize + newSize) / cacheSize; } if (removed.length) { const removedSize = removed.reduce((acc, item) => acc + item.size, 0); const averageSize = this.averageSizeFloat || 0; this.averageSizeFloat = ((cacheSize + removed.length) * averageSize - removedSize) / cacheSize; } this.averageSize = Math.round(this.averageSizeFloat); } recalculateFrequentSize() { const { oldItems, newItems, removed } = this.recalculation; const oldFrequentSizeCount = this.sizeMap.get(this.frequentSize); if (newItems.length) { newItems.forEach(({ size }) => this.sizeMap.set(size, (this.sizeMap.get(size) || 0) + 1)); } if (oldItems.length) { oldItems.forEach(({ size }) => this.sizeMap.set(size, Math.max((this.sizeMap.get(size) || 0) - 1, 0))); oldItems.forEach(({ newSize: s }) => this.sizeMap.set(s, (this.sizeMap.get(s) || 0) + 1)); } if (removed.length) { removed.forEach(({ size }) => this.sizeMap.set(size, Math.max((this.sizeMap.get(size) || 0) - 1, 0))); } const sorted = [...this.sizeMap.entries()].sort((a, b) => b[1] - a[1]); const mostFrequentCount = sorted[0][1]; const listEqual = sorted.filter(i => i[1] === mostFrequentCount); if (listEqual.length > 1 && listEqual.find(i => i[0] === oldFrequentSizeCount)) { // if there are more than 1 most frequent sizes, but the old one is present return; } this.frequentSize = sorted[0][0]; } recalculate(cacheSize) { if (this.sizeStrategy === SizeStrategy.Constant) { return false; } const { oldItems, newItems, removed } = this.recalculation; if (!oldItems.length && !newItems.length && !removed.length) { return false; } const oldValue = this.get(); if (!cacheSize) { this.reset(true); } else { if (this.sizeStrategy === SizeStrategy.Average) { this.recalculateAverageSize(cacheSize); } else { this.recalculateFrequentSize(); } this.recalculation.reset(); } return this.get() !== oldValue; } setExisted(oldSize, newSize) { if (this.sizeStrategy !== SizeStrategy.Constant) { this.recalculation.oldItems.push({ size: oldSize, newSize }); } } setNew(size) { if (this.sizeStrategy !== SizeStrategy.Constant) { this.recalculation.newItems.push({ size }); } else { if (!this.constantSize) { this.constantSize = size; } } } setRemoved(size) { if (this.sizeStrategy !== SizeStrategy.Constant) { this.recalculation.removed.push({ size }); } } } //# sourceMappingURL=defaultSize.js.map