-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaquavhtree.ts
executable file
·184 lines (173 loc) · 5.25 KB
/
aquavhtree.ts
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
import { AquaTree, RevisionTree } from "./types"
import { reorderAquaTreeRevisionsProperties } from "./utils"
/**
* Recursively searches for a node in the revision tree by its hash
*
* @param tree - The revision tree to search
* @param hash - Hash to search for
* @returns Matching RevisionTree node or null if not found
*
* This function traverses the tree structure to find a specific revision
* by matching its hash value.
*/
function findNode(tree: RevisionTree, hash: string): RevisionTree | null {
if (tree.hash === hash) {
return tree
}
for (let i = 0; i < tree.children.length; i++) {
const child = tree.children[i]
const result = findNode(child, hash)
if (result) {
return result
}
}
return null
}
/**
* Finds all paths from root to each leaf node in the revision tree
*
* @param tree - The revision tree to analyze
* @param path - Current path being built (used in recursion)
* @returns Object mapping each leaf hash to its complete path from root
*
* This function:
* - Builds paths from root to each leaf
* - Tracks the complete revision history for each branch
* - Returns a map of leaf hashes to their full paths
*/
function findPaths(
tree: RevisionTree,
path: string[],
): { [key: string]: string[] } {
let paths: { [key: string]: string[] } = {}
path.push(tree.hash)
if (tree.children.length === 0) {
paths[tree.hash] = path
} else {
for (let i = 0; i < tree.children.length; i++) {
const child = tree.children[i]
const childPaths = findPaths(child, [...path])
paths = { ...paths, ...childPaths }
}
}
return paths
}
/**
* Finds the leaf hash with the longest path from root
*
* @param tree - The revision tree to analyze
* @returns Object containing all paths and the hash with longest path
*
* This function:
* - Identifies the longest revision chain
* - Returns both the complete path mapping and the latest hash
* - Used to find the most current revision in the tree
*/
export function findHashWithLongestPath(tree: RevisionTree) {
let paths = findPaths(tree, [])
let hash = ""
let longestPathLength = 0
for (let key in paths) {
if (paths[key].length > longestPathLength) {
hash = key
longestPathLength = paths[key].length
}
}
return {
paths,
latestHash: hash,
}
}
/**
* Creates a tree structure from Aqua Tree revision data
*
* @param aquaTree - The Aqua Tree data containing revisions
* @returns RevisionTree structure representing the revision hierarchy
*
* This function:
* - Converts flat revision data into a tree structure
* - Links revisions based on previous_verification_hash
* - Creates parent-child relationships between revisions
*/
export function createAquaTreeTree(aquaTree: any) {
let obj = aquaTree
// Create a tree given such revision data
let revisionTree: RevisionTree = {} as RevisionTree
for (let revisionHash in obj.revisions) {
const revision = obj.revisions[revisionHash]
const parentHash = revision.previous_verification_hash
if (parentHash === "") {
// This is the root node
revisionTree.hash = revisionHash
revisionTree.children = []
} else {
// Find the parent node
const parentNode = findNode(revisionTree, parentHash)
if (parentNode) {
// Add the current node as a child of the parent node
parentNode.children.push({
hash: revisionHash,
children: [],
})
}
}
}
return revisionTree
}
/**
* Creates a complete Aqua Tree with tree structure and mappings
*
* @param aquaTree - The raw Aqua Tree data
* @returns Enhanced AquaTree with tree structure and path mappings, or null if invalid
*
* This function:
* - Validates the input Aqua Tree
* - Creates the revision tree structure
* - Generates path mappings for revisions
* - Combines original data with tree structure
*/
export function createAquaTree(aquaTree: any): AquaTree | null {
if (
!aquaTree.revisions ||
aquaTree.revisions === null ||
Object.keys(aquaTree.revisions).length === 0
) {
return null
}
let aquaTreeWithReorderdRevisionPrperties =
reorderAquaTreeRevisionsProperties(aquaTree)
let tree = createAquaTreeTree(aquaTreeWithReorderdRevisionPrperties)
let pathResult = findHashWithLongestPath(tree)
return {
...aquaTreeWithReorderdRevisionPrperties,
tree,
treeMapping: pathResult,
}
}
/**
* Prints a visual representation of the Aqua Tree structure
*
* @param node - The revision tree node to display
* @param prefix - String prefix for current line (used in recursion)
* @param isLast - Whether the current node is the last child
*
* This function:
* - Creates a tree-like visual output
* - Shows parent-child relationships between revisions
* - Uses ASCII characters to draw tree structure
*/
export function logAquaTree(
node: RevisionTree,
prefix: string = "",
isLast: boolean = true,
): void {
// Log the current node's hash
console.log(prefix + (isLast ? "└── " : "├── ") + node.hash)
// Update the prefix for children
const newPrefix = prefix + (isLast ? " " : "│ ")
// Recursively log each child
node.children.forEach((child, index) => {
const isChildLast = index === node.children.length - 1
logAquaTree(child, newPrefix, isChildLast)
})
}