Spaces:
Sleeping
Sleeping
File size: 2,341 Bytes
90cbf22 |
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 |
import { FieldConfig, History, unpackSampleRecord } from '../../convex/engine/historicalObject';
import { useMemo, useRef } from 'react';
export function useHistoricalValue<T extends Record<string, number>>(
fields: FieldConfig,
historicalTime: number | undefined,
value: T | undefined,
history: ArrayBuffer | undefined,
): T | undefined {
const manager = useRef(new HistoryManager());
const sampleRecord: Record<string, History> | undefined = useMemo(() => {
if (!value || !history) {
return undefined;
}
if (!(history instanceof ArrayBuffer)) {
throw new Error(`Expected ArrayBuffer, found ${typeof history}`);
}
return unpackSampleRecord(fields, history);
}, [value && history]);
if (sampleRecord) {
manager.current.receive(sampleRecord);
}
if (value === undefined) {
return undefined;
}
if (!historicalTime) {
return value;
}
const historicalFields = manager.current.query(historicalTime);
return { ...value, ...historicalFields };
}
class HistoryManager {
histories: Record<string, History[]> = {};
receive(sampleRecord: Record<string, History>) {
for (const [fieldName, history] of Object.entries(sampleRecord)) {
let histories = this.histories[fieldName];
if (!histories) {
histories = [];
this.histories[fieldName] = histories;
}
if (histories[histories.length - 1] == history) {
continue;
}
histories.push(history);
}
}
query(historicalTime: number): Record<string, number> {
const result: Record<string, number> = {};
for (const [fieldName, histories] of Object.entries(this.histories)) {
if (histories.length == 0) {
continue;
}
let foundIndex = null;
let currentValue = histories[0].initialValue;
for (let i = 0; i < histories.length; i++) {
const history = histories[i];
for (const sample of history.samples) {
if (sample.time > historicalTime) {
foundIndex = i;
break;
}
currentValue = sample.value;
}
if (foundIndex !== null) {
break;
}
}
if (foundIndex !== null) {
this.histories[fieldName] = histories.slice(foundIndex);
}
result[fieldName] = currentValue;
}
return result;
}
}
|