diff --git a/pkg/ui/src/views/cluster/containers/dataDistribution/replicaMatrix.tsx b/pkg/ui/src/views/cluster/containers/dataDistribution/replicaMatrix.tsx index 4fcb7bcd5bbc..3ba96783ff70 100644 --- a/pkg/ui/src/views/cluster/containers/dataDistribution/replicaMatrix.tsx +++ b/pkg/ui/src/views/cluster/containers/dataDistribution/replicaMatrix.tsx @@ -9,7 +9,6 @@ import { TreePath, layoutTreeHorizontal, flatten, - sumValuesUnderPaths, LayoutCell, FlattenedNode, visitNodes, @@ -447,39 +446,7 @@ const selectColsWithSize = createSelector( ); // TODO(vilterp): make this depend on the master grid - -const selectFlattenedRows = createSelector( - selectRowsWithSize, - selectColsWithSize, - (propsAndState: PropsAndState) => propsAndState.state.collapsedRows, - (propsAndState: PropsAndState) => propsAndState.state.paginationStates, - selectGetValueFun, - ( - rows: TreeWithSize, - cols: TreeWithSize, - collapsedRows: TreePath[], - paginationStates: AssocList, - getValue: (rowPath: TreePath, colPath: TreePath) => number, - ) => { - console.log("flattening rows"); - const sortBy = (path: TreePath) => { - // TODO(vilterp): get this from the master grid - return sumValuesUnderPaths(rows.node, cols.node, path, [], getValue); - }; - return flatten(rows, collapsedRows, true /* includeNodes */, paginationStates, PAGE_SIZE, sortBy); - }, -); - -const selectFlattenedCols = createSelector( - selectColsWithSize, - (propsAndState: PropsAndState) => propsAndState.state.collapsedCols, - (cols: TreeWithSize, collapseCols: TreePath[]) => { - console.log("flattening cols"); - return flatten(cols, collapseCols, false /* includeNodes */); - }, -); - -interface SumAndIncreate { +interface SumAndIncrease { sum: number; increase: number; } @@ -504,10 +471,10 @@ const selectMasterGrid = createSelector( outputRows.push(row); } - function visitRows(rowPath: TreePath, rowIdx: number, row: TreeWithSize): SumAndIncreate { + function visitRows(rowPath: TreePath, rowIdx: number, row: TreeWithSize): SumAndIncrease { // console.log("visitRows", rowPath, rowIdx); - function visitCols(colPath: TreePath, colIdx: number, col: TreeWithSize): SumAndIncreate { + function visitCols(colPath: TreePath, colIdx: number, col: TreeWithSize): SumAndIncrease { // console.log("visitCols", colPath, rowIdx); if (isLeaf(col.node)) { @@ -566,6 +533,34 @@ const selectMasterGrid = createSelector( }, ); +const selectFlattenedRows = createSelector( + selectMasterGrid, + selectRowsWithSize, + (propsAndState: PropsAndState) => propsAndState.state.collapsedRows, + (propsAndState: PropsAndState) => propsAndState.state.paginationStates, + ( + masterGrid: number[][], + rows: TreeWithSize, + collapsedRows: TreePath[], + paginationStates: AssocList, + ) => { + console.log("flattening rows"); + const sortBy = (masterRowIdx: number) => { + return masterGrid[masterRowIdx][0]; + }; + return flatten(rows, collapsedRows, true /* includeNodes */, paginationStates, PAGE_SIZE, sortBy); + }, +); + +const selectFlattenedCols = createSelector( + selectColsWithSize, + (propsAndState: PropsAndState) => propsAndState.state.collapsedCols, + (cols: TreeWithSize, collapseCols: TreePath[]) => { + console.log("flattening cols"); + return flatten(cols, collapseCols, false /* includeNodes */); + }, +); + const selectAllVals = createSelector( selectMasterGrid, selectFlattenedRows, @@ -585,7 +580,6 @@ const selectAllVals = createSelector( return; } const value = masterGrid[row.masterIdx][col.masterIdx]; - // console.log("get val from master grid:", row.path, row.masterIdx, col.path, col.masterIdx, "=>", value); rowVals.push(value); inSingleArray.push(value); }); diff --git a/pkg/ui/src/views/cluster/containers/dataDistribution/tree.spec.ts b/pkg/ui/src/views/cluster/containers/dataDistribution/tree.spec.ts index b0d522be2d75..0e122072347b 100644 --- a/pkg/ui/src/views/cluster/containers/dataDistribution/tree.spec.ts +++ b/pkg/ui/src/views/cluster/containers/dataDistribution/tree.spec.ts @@ -1,7 +1,7 @@ import { assert } from "chai"; import { - flatten, layoutTreeHorizontal, sumValuesUnderPaths, TreePath, LayoutCell, + flatten, layoutTreeHorizontal, LayoutCell, } from "./tree"; describe("tree", () => { @@ -224,56 +224,4 @@ describe("tree", () => { }); - describe("sumValuesUnderPaths", () => { - - // | | C_1 | - // | | C_2 | C_3 | - // |-------|-----|-----| - // | R_a | | | - // | R_b | 1 | 2 | - // | R_c | 3 | 4 | - - const rowTree = { - name: "a", - children: [ - { name: "b" }, - { name: "c" }, - ], - }; - const colTree = { - name: "1", - children: [ - { name: "2" }, - { name: "3" }, - ], - }; - // by row, then col. - const values: {[name: string]: {[name: string]: number}} = { - "b": {"2": 1, "3": 2}, - "c": {"2": 3, "3": 4}, - }; - function getValue(rowPath: TreePath, colPath: TreePath): number { - return values[rowPath[0]][colPath[0]]; - } - - it("computes a sum for the roots of both trees", () => { - const actualSum = sumValuesUnderPaths(rowTree, colTree, [], [], getValue); - const expectedSum = 1 + 2 + 3 + 4; - assert.equal(actualSum, expectedSum); - }); - - it("computes a sum for the root of one tree and the leaf of another", () => { - const actualSum = sumValuesUnderPaths(rowTree, colTree, ["b"], [], getValue); - const expectedSum = 1 + 2; - assert.equal(actualSum, expectedSum); - }); - - it("computes a sum for a single cell (two leaves)", () => { - const actualSum = sumValuesUnderPaths(rowTree, colTree, ["b"], ["3"], getValue); - const expectedSum = 2; - assert.equal(actualSum, expectedSum); - }); - - }); - }); diff --git a/pkg/ui/src/views/cluster/containers/dataDistribution/tree.ts b/pkg/ui/src/views/cluster/containers/dataDistribution/tree.ts index 6e41a08db90b..8ad092ce889e 100644 --- a/pkg/ui/src/views/cluster/containers/dataDistribution/tree.ts +++ b/pkg/ui/src/views/cluster/containers/dataDistribution/tree.ts @@ -306,7 +306,7 @@ export function flatten( includeInternalNodes: boolean, paginationStates: AssocList = [], pageSize: number = Number.MAX_VALUE, - sortBy?: (path: TreePath) => number, + sortBy?: (masterIndex: number) => number, ): FlattenedNode[] { const output: FlattenedNode[] = []; recur(tree, [], 0); @@ -355,7 +355,7 @@ export function flatten( const offset = page * pageSize; const sortState = paginationState ? paginationState.sortState : SortState.NONE; - const sortedChildren = sortChildren(node.children, pathSoFar, sortState, sortBy); + const sortedChildren = sortChildren(node.children, sortState, sortBy); for (let i = 0; i < offset; i++) { const child = sortedChildren[i]; @@ -379,9 +379,8 @@ export function flatten( function sortChildren( children: TreeWithSize[], - pathSoFar: TreePath, sortState: SortState, - sortBy?: (path: TreePath) => number, + sortBy?: (masterIndex: number) => number, ): TreeWithSize[] { if (sortState === SortState.NONE) { return children; @@ -390,8 +389,7 @@ function sortChildren( throw Error(`sortState ${sortState} but no sortBy provided`); } const sortedChildren = _.sortBy(children, (child) => { - const childPath = [...pathSoFar, child.node.name]; - return sortBy(childPath); + return sortBy(child.masterIdx); }); if (sortState === SortState.DESC) { sortedChildren.reverse(); @@ -399,22 +397,6 @@ function sortChildren( return sortedChildren; } -/** - * nodeAtPath returns the node found under `root` at `path`, throwing - * an error if nothing is found. - */ -function nodeAtPath(root: TreeNode, path: TreePath): TreeNode { - if (path.length === 0) { - return root; - } - const pathSegment = path[0]; - const child = root.children.find((c) => (c.name === pathSegment)); - if (child === undefined) { - throw new Error(`not found: ${path}`); - } - return nodeAtPath(child, path.slice(1)); -} - /** * visitNodes invokes `f` on each node in the tree in pre-order * (`f` is invoked on a node before being invoked on its children). @@ -458,104 +440,6 @@ function expandedHeight(root: TreeNode, collapsedPaths: TreePath[]): numbe return maxHeight; } -/** - * getLeafPathsUnderPath returns paths to all leaf nodes under the given - * `path` in `root`. - * - * E.g. for the tree T = - * - * a/ - * b/ - * c - * d - * e/ - * f - * g - * - * getLeafPaths(T, ['a', 'b']) yields: - * - * [ ['a', 'b', 'c'], - * ['a', 'b', 'd'] ] - * - */ -function getLeafPathsUnderPath(root: TreeNode, path: TreePath): TreePath[] { - const atPath = nodeAtPath(root, path); - const output: TreePath[] = []; - visitNodes(atPath, (node, subPath) => { - if (isLeaf(node)) { - output.push([...path, ...subPath]); - } - return true; - }); - return output; -} - -/** - * cartProd returns all combinations of elements in `as` and `bs`. - * - * e.g. cartProd([1, 2], ['a', 'b']) - * yields: - * [ - * {a: 1, b: 'a'}, - * {a: 1, b: 'b'}, - * {a: 2, b: 'a'}, - * {a: 2, b: 'b'}, - * ] - */ -function cartProd(as: A[], bs: B[]): {a: A, b: B}[] { - const output: {a: A, b: B}[] = []; - as.forEach((a) => { - bs.forEach((b) => { - output.push({ a, b }); - }); - }); - return output; -} - -/** - * sumValuesUnderPaths returns the sum of `getValue(R, C)` - * for all leaf paths R under `rowPath` in `rowTree`, - * and all leaf paths C under `colPath` in `rowTree`. - * - * E.g. in the matrix - * - * | | C_1 | - * | | C_2 | C_3 | - * |-------|-----|-----| - * | R_a | | | - * | R_b | 1 | 2 | - * | R_c | 3 | 4 | - * - * represented by - * - * rowTree = (R_a [R_b R_c]) - * colTree = (C_1 [C_2 C_3]) - * - * calling sumValuesUnderPath(rowTree, colTree, ['R_a'], ['C_1'], getValue) - * sums up all the cells in the matrix, yielding 1 + 2 + 3 + 4 = 10. - * - * Calling sumValuesUnderPath(rowTree, colTree, ['R_a', 'R_b'], ['C_1'], getValue) - * sums up only the cells under R_b, - * yielding 1 + 2 = 3. - * - */ -export function sumValuesUnderPaths( - rowTree: TreeNode, - colTree: TreeNode, - rowPath: TreePath, - colPath: TreePath, - getValue: (row: TreePath, col: TreePath) => number, -): number { - const rowPaths = getLeafPathsUnderPath(rowTree, rowPath); - const colPaths = getLeafPathsUnderPath(colTree, colPath); - const prod = cartProd(rowPaths, colPaths); - let sum = 0; - prod.forEach((coords) => { - sum += getValue(coords.a, coords.b); - }); - return sum; -} - /** * deepIncludes returns true if `array` contains `val`, doing * a deep equality comparison. @@ -578,30 +462,37 @@ export function repeat(times: number, item: T): T[] { export interface TreeWithSize { size: number; + masterIdx: number; node: TreeNode; children?: TreeWithSize[]; } // TODO(vilterp): not store the child arrays twice... // maybe actually just add teh size to teh same struct -export function augmentWithSize(node: TreeNode): TreeWithSize { - if (isLeaf(node)) { +export function augmentWithSize(root: TreeNode): TreeWithSize { + function recur(node: TreeNode, masterIdx: number): TreeWithSize { + if (isLeaf(node)) { + return { + size: 1, + masterIdx, + node, + }; + } + + let size = 0; + const children: TreeWithSize[] = []; + node.children.forEach((child) => { + const augmentedChild = recur(child, masterIdx + size); + size += augmentedChild.size; + children.push(augmentedChild); + }); return { - size: 1, + size: size + 1, // add 1 for the node itself + children, node, + masterIdx, }; } - let size = 1; // node itself - const children: TreeWithSize[] = []; - node.children.forEach((child) => { - const augmentedChild = augmentWithSize(child); - size += augmentedChild.size; - children.push(augmentedChild); - }); - return { - size, - children, - node, - }; + return recur(root, 0); }