|
| 1 | +import { closestIdx } from '@grafana/data'; |
| 2 | + |
| 3 | +export type Table = [times: number[], ...values: any[][]]; |
| 4 | + |
| 5 | +// prevTable and nextTable are assumed sorted ASC on reference [0] arrays |
| 6 | +// nextTable is assumed to be contiguous, only edges are checked for overlap |
| 7 | +// ...so prev: [1,2,5] + next: [3,4,6] -> [1,2,3,4,6] |
| 8 | +export function amendTable(prevTable: Table, nextTable: Table): Table { |
| 9 | + let [prevTimes] = prevTable; |
| 10 | + let [nextTimes] = nextTable; |
| 11 | + |
| 12 | + let pLen = prevTimes.length; |
| 13 | + let pStart = prevTimes[0]; |
| 14 | + let pEnd = prevTimes[pLen - 1]; |
| 15 | + |
| 16 | + let nLen = nextTimes.length; |
| 17 | + let nStart = nextTimes[0]; |
| 18 | + let nEnd = nextTimes[nLen - 1]; |
| 19 | + |
| 20 | + let outTable: Table; |
| 21 | + |
| 22 | + if (pLen) { |
| 23 | + if (nLen) { |
| 24 | + // append, no overlap |
| 25 | + if (nStart > pEnd) { |
| 26 | + outTable = prevTable.map((_, i) => prevTable[i].concat(nextTable[i])) as Table; |
| 27 | + } |
| 28 | + // prepend, no overlap |
| 29 | + else if (nEnd < pStart) { |
| 30 | + outTable = nextTable.map((_, i) => nextTable[i].concat(prevTable[i])) as Table; |
| 31 | + } |
| 32 | + // full replace |
| 33 | + else if (nStart <= pStart && nEnd >= pEnd) { |
| 34 | + outTable = nextTable; |
| 35 | + } |
| 36 | + // partial replace |
| 37 | + else if (nStart > pStart && nEnd < pEnd) { |
| 38 | + } |
| 39 | + // append, with overlap |
| 40 | + else if (nStart >= pStart) { |
| 41 | + let idx = closestIdx(nStart, prevTimes); |
| 42 | + idx = prevTimes[idx] < nStart ? idx - 1 : idx; |
| 43 | + outTable = prevTable.map((_, i) => prevTable[i].slice(0, idx).concat(nextTable[i])) as Table; |
| 44 | + } |
| 45 | + // prepend, with overlap |
| 46 | + else if (nEnd >= pStart) { |
| 47 | + let idx = closestIdx(nEnd, prevTimes); |
| 48 | + idx = prevTimes[idx] < nEnd ? idx : idx + 1; |
| 49 | + outTable = nextTable.map((_, i) => nextTable[i].concat(prevTable[i].slice(idx))) as Table; |
| 50 | + } |
| 51 | + } else { |
| 52 | + outTable = prevTable; |
| 53 | + } |
| 54 | + } else { |
| 55 | + if (nLen) { |
| 56 | + outTable = nextTable; |
| 57 | + } else { |
| 58 | + outTable = [[]]; |
| 59 | + } |
| 60 | + } |
| 61 | + |
| 62 | + return outTable!; |
| 63 | +} |
| 64 | + |
| 65 | +export function trimTable(table: Table, fromTime: number, toTime: number): Table { |
| 66 | + let [times, ...vals] = table; |
| 67 | + let fromIdx: number | undefined; |
| 68 | + let toIdx: number | undefined; |
| 69 | + |
| 70 | + // trim to bounds |
| 71 | + if (times[0] < fromTime) { |
| 72 | + fromIdx = closestIdx(fromTime, times); |
| 73 | + |
| 74 | + if (times[fromIdx] < fromTime) { |
| 75 | + fromIdx++; |
| 76 | + } |
| 77 | + } |
| 78 | + |
| 79 | + if (times[times.length - 1] > toTime) { |
| 80 | + toIdx = closestIdx(toTime, times); |
| 81 | + |
| 82 | + if (times[toIdx] > toTime) { |
| 83 | + toIdx--; |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + if (fromIdx != null || toIdx != null) { |
| 88 | + times = times.slice(fromIdx ?? 0, toIdx); |
| 89 | + vals = vals.map(vals2 => vals2.slice(fromIdx ?? 0, toIdx)); |
| 90 | + } |
| 91 | + |
| 92 | + return [times, ...vals]; |
| 93 | +} |
0 commit comments