File size: 10,125 Bytes
6369972 |
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 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
import os
import json
import logging
from src.wbs.wbs_task import WBSTask, WBSProject
from src.uuid_util.is_valid_uuid import is_valid_uuid
logger = logging.getLogger(__name__)
class WBSPopulate:
@staticmethod
def project_from_level1_json(path_level1_json: str) -> WBSProject:
"""
Create a WBSProject from a level 1 JSON file.
"""
if not isinstance(path_level1_json, str):
raise ValueError("Invalid path_level1_json.")
with open(path_level1_json) as f:
d = json.load(f)
if not isinstance(d, dict):
raise ValueError("Expected a dictionary in the JSON file.")
root_task_id = d.get('id', None)
project_title = d.get('project_title', None)
final_deliverable = d.get('final_deliverable', None)
if not is_valid_uuid(root_task_id):
logger.error(f"Expected valid UUID, but got root_task_id: {root_task_id}")
root_task = WBSTask(
id = root_task_id,
description=project_title,
)
root_task.set_field('final_deliverable', final_deliverable)
return WBSProject(root_task)
@staticmethod
def extend_project_with_level2_json(wbs_project: WBSProject, path_level2_json: str):
"""
Grow the tree hierarchy with tasks from a WBS Level 2 JSON file.
"""
if not isinstance(wbs_project, WBSProject):
raise ValueError("Expected a WBSProject object.")
if not isinstance(path_level2_json, str):
raise ValueError("Invalid path_level2_json.")
with open(path_level2_json) as f:
task_item_list = json.load(f)
if not isinstance(task_item_list, list):
raise ValueError("Expected a list of tasks in the JSON file.")
for task_index, task_json in enumerate(task_item_list):
task_id = task_json.get('id', None)
if not is_valid_uuid(task_id):
logger.error(f"Expected valid UUID, but got task_id: {task_id} for task_index: {task_index}")
task_id = "MISSING_TASK_ID"
major_phase_title = task_json.get('major_phase_title', None)
if not major_phase_title:
logger.error(f"Missing 'major_phase_title' for task with id: {task_id} for task_index: {task_index}")
major_phase_title = "MISSING_MAJOR_PHASE_TITLE"
task = WBSTask(
id=task_id,
description=major_phase_title
)
wbs_project.root_task.task_children.append(task)
subtask_list = task_json.get('subtasks', None)
if not subtask_list:
logger.error(f"Missing 'subtasks' for task with id: {task_id}")
subtask_list = []
for subtask_json in subtask_list:
subtask_id = subtask_json.get('id', None)
if not is_valid_uuid(subtask_id):
logger.error(f"Expected valid UUID, but got subtask_id: {subtask_id} for task with id: {task_id}")
subtask_description = subtask_json.get('description', None)
if not subtask_description:
logger.error(f"Missing 'description' for subtask with id: {subtask_id}")
subtask_description = "MISSING_SUBTASK_DESCRIPTION"
subtask = WBSTask(
id=subtask_id,
description=subtask_description
)
task.task_children.append(subtask)
@staticmethod
def extend_project_with_dependencies_json(wbs_project: WBSProject, path_dependencies_json: str):
"""
Enrich the tree hierarchy with tasks from a dependencies JSON file.
Establish dependencies between tasks, with explanations why these dependencies exists.
"""
if not isinstance(wbs_project, WBSProject):
raise ValueError("Expected a WBSProject object.")
if not isinstance(path_dependencies_json, str):
raise ValueError("Invalid path_dependencies_json.")
with open(path_dependencies_json) as f:
d = json.load(f)
if not isinstance(d, dict):
raise ValueError("Expected a dictionary in the JSON file.")
task_item_list = d.get('task_dependency_details', [])
for task_json in task_item_list:
dependent_task_id = task_json['dependent_task_id']
dependent_task = wbs_project.root_task.find_task_by_id(dependent_task_id)
if not dependent_task:
logger.debug(f"ERROR: Task with id {dependent_task_id} not found. Cannot set dependencies.")
continue
depends_on_task_id_list = task_json['depends_on_task_id_list']
# Check if all uuid's in the depends_on_task_id_list are valid
for depends_on_task_id in depends_on_task_id_list:
depends_on_task = wbs_project.root_task.find_task_by_id(depends_on_task_id)
if not depends_on_task:
logger.debug(f"ERROR: Task with id {depends_on_task_id} not found. Cannot set dependency for task {dependent_task_id}.")
continue
dependent_task.set_field('depends_on_task_ids', depends_on_task_id_list)
depends_on_task_explanation_list = task_json['depends_on_task_explanation_list']
dependent_task.set_field('depends_on_task_explanations', depends_on_task_explanation_list)
@staticmethod
def extend_project_with_durations_json(wbs_project: WBSProject, path_durations_json: str):
"""
Enrich the task hierarchy with time estimates from a task_durations JSON file.
"""
if not isinstance(wbs_project, WBSProject):
raise ValueError("Expected a WBSProject object.")
if not isinstance(path_durations_json, str):
raise ValueError("Invalid path_dependencies_json.")
with open(path_durations_json) as f:
task_duration_list = json.load(f)
if not isinstance(task_duration_list, list):
raise ValueError("Expected a list in the JSON file.")
# logger.debug(f"task_duration_list length: {len(task_duration_list)}")
for task_duration_index, task_duration_json in enumerate(task_duration_list):
task_id = task_duration_json.get('task_id', None)
if not is_valid_uuid(task_id):
logger.error(f"Expected valid UUID, but got task_id: {task_id} for task_duration_index: {task_duration_index}")
continue
task = wbs_project.root_task.find_task_by_id(task_id)
if not task:
logger.error(f"Task with id {task_id} not found in WBSProject. Cannot set duration fields.")
continue
delay_risks = task_duration_json.get('delay_risks', None)
if delay_risks:
task.set_field('delay_risks', delay_risks)
mitigation_strategy = task_duration_json.get('mitigation_strategy', None)
if mitigation_strategy:
task.set_field('mitigation_strategy', mitigation_strategy)
days_min = task_duration_json.get('days_min', None)
if days_min:
task.set_field('days_min', days_min)
days_max = task_duration_json.get('days_max', None)
if days_max:
task.set_field('days_max', days_max)
days_realistic = task_duration_json.get('days_realistic', None)
if days_realistic:
task.set_field('days_realistic', days_realistic)
@staticmethod
def extend_project_with_decomposed_tasks_json(wbs_project: WBSProject, path_decomposed_tasks_json: str):
"""
Enrich the task hierarchy with more subtasks from a decomposed_tasks JSON file.
"""
if not isinstance(wbs_project, WBSProject):
raise ValueError("Expected a WBSProject object.")
if not isinstance(path_decomposed_tasks_json, str):
raise ValueError("Invalid path_decomposed_tasks_json.")
with open(path_decomposed_tasks_json) as f:
task_list = json.load(f)
if not isinstance(task_list, list):
raise ValueError("Expected a list in the JSON file.")
# logger.debug(f"Number of subtasks to be added. count: {len(task_list)}")
for task_index, task_json in enumerate(task_list):
task_id = task_json.get('id', None)
if not is_valid_uuid(task_id):
logger.error(f"Expected valid UUID, but got task_id: {task_id} for task_index: {task_index}. Cannot create subtask.")
continue
task_parent_id = task_json.get('parent_id', None)
if not is_valid_uuid(task_parent_id):
logger.error(f"Expected valid UUID, but got task_parent_id: {task_parent_id} for task_index: {task_index}. Cannot create subtask.")
continue
subtask_name = task_json.get('name', None)
if not subtask_name:
logger.error(f"Missing 'name' for task with id: {task_id}.")
subtask_name = "MISSING_SUBTASK_NAME"
parent_task = wbs_project.root_task.find_task_by_id(task_parent_id)
if not parent_task:
logger.error(f"Task with id {task_parent_id} not found. Cannot create subtask for child task {task_id}.")
continue
task = WBSTask(
id=task_id,
description=subtask_name
)
subtask_detailed_description = task_json.get('description', None)
if subtask_detailed_description:
task.set_field('detailed_description', subtask_detailed_description)
subtask_resources_needed = task_json.get('resources_needed', None)
if subtask_resources_needed:
task.set_field('resources_needed', subtask_resources_needed)
parent_task.task_children.append(task)
# logger.debug(f"Added task {task_id} to parent task {task_parent_id}")
|