build static method
Builds a Merkle Tree from a map of HLC strings to content hashes.
Implementation
static MerkleTree build(List<MapEntry<String, String>> items) {
// 1. Group items by Hour prefix (length 13: YYYY-MM-DDTHH)
final Map<String, List<String>> hourBuckets = {};
for (final entry in items) {
final hlcStr = entry.key;
final contentHash = entry.value;
// Extract ISO prefix "YYYY-MM-DDTHH:mm" (16 chars)
// If invalid or too short, bucket into a default "0000-00-00T00:00"
String minutePrefix = '0000-00-00T00:00';
if (hlcStr.length >= 16 && hlcStr.contains('T') && hlcStr.contains(':')) {
minutePrefix = hlcStr.substring(0, 16);
}
hourBuckets.putIfAbsent(minutePrefix, () => []).add(contentHash);
}
// 2. Build Hour Nodes (Leaves of the bucket tree)
final Map<String, MerkleNode> hourNodes = {};
for (final entry in hourBuckets.entries) {
final prefix = entry.key;
final hashes = entry.value;
hourNodes[prefix] = MerkleNode(
hash: combineHashes(hashes),
prefix: prefix,
count: hashes.length,
);
}
// 3. Group Hour Nodes by Day prefix (length 10: YYYY-MM-DD)
final Map<String, Map<String, MerkleNode>> dayBuckets = {};
for (final entry in hourNodes.entries) {
final hourPrefix = entry.key;
final node = entry.value;
String dayPrefix = '0000-00-00';
if (hourPrefix.length >= 10) {
dayPrefix = hourPrefix.substring(0, 10);
}
dayBuckets.putIfAbsent(dayPrefix, () => {})[hourPrefix] = node;
}
// 4. Build Day Nodes
final Map<String, MerkleNode> dayNodes = {};
for (final entry in dayBuckets.entries) {
final prefix = entry.key;
final children = entry.value;
final childHashes = children.values.map((n) => n.hash).toList();
final count = children.values.fold(0, (sum, n) => sum + n.count);
dayNodes[prefix] = MerkleNode(
hash: combineHashes(childHashes),
prefix: prefix,
children: children,
count: count,
);
}
// 5. Build Root Node
final rootChildHashes = dayNodes.values.map((n) => n.hash).toList();
final totalCount = dayNodes.values.fold(0, (sum, n) => sum + n.count);
final rootNode = MerkleNode(
hash: combineHashes(rootChildHashes),
prefix: '',
children: dayNodes,
count: totalCount,
);
return MerkleTree(rootNode);
}