Skip to content

Commit

Permalink
Enhance Hierarchy Population to Support Nodes with Multiple Parents
Browse files Browse the repository at this point in the history
This commit refines the `populateSelectedNodeHierarchy` method in the `SkillTreeViewModel` to accurately represent nodes that possess multiple parent nodes, ensuring a comprehensive and non-redundant representation of the entire hierarchy leading back to the root nodes.

Modifications and Features:
- The method now employs recursion to traverse all possible paths back to the root nodes from a selected node, capturing every unique node in the hierarchies.
- A `Set` is utilized to monitor and ensure that each node is only added once to the `_selectedNodeHierarchy` list, eliminating the possibility of duplicates.
- The finalized `_selectedNodeHierarchy` list is constructed such that the root of the tree is the last item in the list, providing a more logical representation of the hierarchy.

These enhancements ensure a more accurate and efficient representation of the skill tree structure, particularly in scenarios where nodes have multiple parents, facilitating better navigation and interaction within the skill tree.
  • Loading branch information
hunteraraujo committed Sep 23, 2023
1 parent 0785591 commit ecc8d94
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 35 deletions.
62 changes: 32 additions & 30 deletions frontend/lib/viewmodels/skill_tree_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -97,36 +97,40 @@ class SkillTreeViewModel extends ChangeNotifier {
notifyListeners();
}

// TODO: Do we want to continue testing other branches of tree if one branch side fails benchmarking?
void populateSelectedNodeHierarchy(String startNodeId) {
// Initialize an empty list to hold the nodes in the hierarchy.
_selectedNodeHierarchy = [];
// Initialize an empty list to hold the nodes in all hierarchies.
_selectedNodeHierarchy = <SkillTreeNode>[];

// Find the starting node (the selected node) in the skill tree nodes list.
SkillTreeNode? currentNode =
_skillTreeNodes.firstWhere((node) => node.id == startNodeId);
// Initialize a set to keep track of nodes that have been added.
final addedNodes = <String>{};

// Loop through the tree to populate the hierarchy list.
// The loop will continue as long as there's a valid current node.
while (currentNode != null) {
// Add the current node to the hierarchy list.
_selectedNodeHierarchy!.add(currentNode);
// Start the recursive population of the hierarchy from the startNodeId.
recursivePopulateHierarchy(startNodeId, addedNodes);

// Notify listeners about the change in the selectedNodeHierarchy state.
notifyListeners();
}

// Find the parent node by looking through the skill tree edges.
// We find the edge where the 'to' field matches the ID of the current node.
SkillTreeEdge? parentEdge = _skillTreeEdges
.firstWhereOrNull((edge) => edge.to == currentNode?.id);

// If a parent edge is found, find the corresponding parent node.
if (parentEdge != null) {
// The 'from' field of the edge gives us the ID of the parent node.
// We find that node in the skill tree nodes list.
currentNode = _skillTreeNodes
.firstWhereOrNull((node) => node.id == parentEdge.from);
} else {
// If no parent edge is found, it means we've reached the root node.
// We set currentNode to null to exit the loop.
currentNode = null;
void recursivePopulateHierarchy(String nodeId, Set<String> addedNodes) {
// Find the current node in the skill tree nodes list.
final currentNode =
_skillTreeNodes.firstWhereOrNull((node) => node.id == nodeId);

// If the node is found and it hasn't been added yet, proceed with the population.
if (currentNode != null && addedNodes.add(currentNode.id)) {
// Find all parent edges for the current node.
final parentEdges =
_skillTreeEdges.where((edge) => edge.to == currentNode.id);

// For each parent edge found, recurse to the parent node.
for (final parentEdge in parentEdges) {
// Recurse to the parent node identified by the 'from' field of the edge.
recursivePopulateHierarchy(parentEdge.from, addedNodes);
}

// After processing all parent nodes, add the current node to the list.
_selectedNodeHierarchy!.add(currentNode);
}
}

Expand Down Expand Up @@ -156,16 +160,14 @@ class SkillTreeViewModel extends ChangeNotifier {
// Notify listeners
notifyListeners();

// Populate benchmarkStatusList with reversed node hierarchy
final reversedSelectedNodeHierarchy =
List.from(_selectedNodeHierarchy!.reversed);
for (var node in reversedSelectedNodeHierarchy) {
// Populate benchmarkStatusList with node hierarchy
for (var node in _selectedNodeHierarchy!) {
benchmarkStatusMap[node] = BenchmarkTaskStatus.notStarted;
}

try {
// Loop through the nodes in the hierarchy
for (var node in reversedSelectedNodeHierarchy) {
for (var node in _selectedNodeHierarchy!) {
benchmarkStatusMap[node] = BenchmarkTaskStatus.inProgress;
notifyListeners();

Expand Down
9 changes: 4 additions & 5 deletions frontend/lib/views/task_queue/task_queue_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,18 @@ class TaskQueueView extends StatelessWidget {
Widget build(BuildContext context) {
final viewModel = Provider.of<SkillTreeViewModel>(context);

// Reverse the node hierarchy
final reversedHierarchy =
viewModel.selectedNodeHierarchy?.reversed.toList() ?? [];
// Node hierarchy
final nodeHierarchy = viewModel.selectedNodeHierarchy ?? [];

return Material(
color: Colors.white,
child: Stack(
children: [
// The list of tasks (tiles)
ListView.builder(
itemCount: reversedHierarchy.length,
itemCount: nodeHierarchy.length,
itemBuilder: (context, index) {
final node = reversedHierarchy[index];
final node = nodeHierarchy[index];

// Choose the appropriate leading widget based on the task status
Widget leadingWidget;
Expand Down

0 comments on commit ecc8d94

Please sign in to comment.