export class Sum { ColumnIndex: number; Table: Table; Original: number; Adjustment: number; FromParents: number; FromChildren: number; FromOutside: number; constructor(inIndex: number, inTable: Table) { this.ColumnIndex = inIndex; this.Table = inTable; this.Original = 0; this.Adjustment = 1; this.FromParents = 1; } } export class Table { Name: string; Rows: Array>; Columns: Array; Parent?: Table; Children: Array; constructor(inName: string, inRows: Array>, inColumns: Array) { this.Name = inName; this.Rows = inRows; this.Parent = null; this.Children = []; this.Columns = inColumns.map( (inIndex: number) => new Sum(inIndex, this) ); } Pivot(inColumnPivot: number) { var cell: string; var child: Table; this.Rows.forEach((inRow: Array)=> { cell = inRow[inColumnPivot]; child = this.Children.find( (inChild: Table) => inChild.Name == cell ); if(!child) { child = new Table(cell, [], this.Columns.map( (inColumn: Sum) => inColumn.ColumnIndex )); child.Parent = this; this.Children.push(child); } child.Rows.push(inRow); }); this.Rows = []; } PivotTree(inColumnsPivot: Array) { var pivotsRemaining: Array; if(inColumnsPivot.length == 0) { return; } pivotsRemaining = [...inColumnsPivot]; this.Pivot(pivotsRemaining.shift()); this.Children.forEach( (inChild: Table) => inChild.PivotTree(pivotsRemaining) ); } ItrParents(inFunction: Function) { if(this.Parent) { inFunction(this.Parent, this); this.Parent.ItrParents(inFunction); } } ItrChildren(inFunction: Function) { this.Children.forEach( (inChild: Table) => { inFunction(inChild, this); inChild.ItrChildren(inFunction); }); } ItrLeaves(inFunction:Function) { if(this.Children.length == 0) { inFunction(this); } else { this.Children.forEach( (inChild: Table) => inChild.ItrLeaves(inFunction) ); } } }