diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/calculate_task_duration.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/calculate_task_duration.py index e46915332a..4a3f5b1413 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/calculate_task_duration.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/calculate_task_duration.py @@ -12,7 +12,7 @@ class Usecase: self.settings[key] = value def execute(self): - self.seconds_per_day = self.calculate_seconds_per_day() + self.seconds_per_workday = self.calculate_seconds_per_workday() duration = self.calculate_max_resource_usage_duration() if duration: self.set_task_duration(duration) @@ -32,18 +32,18 @@ class Usecase: ifcopenshell.api.run("sequence.add_task_time", self.file, task=self.settings["task"]) self.settings["task"].TaskTime.ScheduleDuration = f"P{duration}D" - def calculate_seconds_per_day(self): - default_seconds_per_day = 8 * 60 * 60 - work_schedule = self.get_work_schedule() + def calculate_seconds_per_workday(self): + default_seconds_per_workday = 8 * 60 * 60 + work_schedule = self.get_work_schedule(self.settings["task"]) if not work_schedule: - return default_seconds_per_day + return default_seconds_per_workday psets = ifcopenshell.util.element.get_psets(work_schedule) if ( not psets or "Pset_WorkControlCommon" not in psets or "WorkDayDuration" not in psets["Pset_WorkControlCommon"] ): - return default_seconds_per_day + return default_seconds_per_workday work_day_duration = ifcopenshell.util.date.ifc2datetime(psets["Pset_WorkControlCommon"]["WorkDayDuration"]) return work_day_duration.seconds @@ -59,8 +59,12 @@ class Usecase: return schedule_usage = resource.Usage.ScheduleUsage or 1 schedule_duration = ifcopenshell.util.date.ifc2datetime(resource.Usage.ScheduleWork) - schedule_seconds = 0 - if schedule_duration.days: - schedule_seconds += schedule_duration.days * self.seconds_per_day - schedule_seconds += schedule_duration.seconds - return math.ceil((schedule_seconds / self.seconds_per_day) / schedule_usage) + if self.is_hourly_work(resource.Usage.ScheduleWork): + schedule_seconds = (schedule_duration.days * 24 * 60 * 60) + schedule_duration.seconds + else: + partial_days = schedule_duration.seconds / (24 * 60 * 60) + schedule_seconds = (schedule_duration.days + partial_days) * self.seconds_per_workday + return math.ceil((schedule_seconds / self.seconds_per_workday) / schedule_usage) + + def is_hourly_work(self, schedule_work): + return "T" in schedule_work diff --git a/src/ifcopenshell-python/test/api/sequence/__init__.py b/src/ifcopenshell-python/test/api/sequence/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ifcopenshell-python/test/api/sequence/test_calculate_task_duration.py b/src/ifcopenshell-python/test/api/sequence/test_calculate_task_duration.py new file mode 100644 index 0000000000..7fe64f7fe1 --- /dev/null +++ b/src/ifcopenshell-python/test/api/sequence/test_calculate_task_duration.py @@ -0,0 +1,26 @@ +import test.bootstrap +import ifcopenshell.api + + +class TestCalculateTaskDuration(test.bootstrap.IFC4): + def test_calculating_the_duration_based_on_a_labour_resource_with_work_hours(self): + ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcProject") + schedule = ifcopenshell.api.run("sequence.add_work_schedule", self.file) + task = ifcopenshell.api.run("sequence.add_task", self.file, work_schedule=schedule) + resource = ifcopenshell.api.run("resource.add_resource", self.file, ifc_class="IfcLaborResource") + resource_time = ifcopenshell.api.run("resource.add_resource_time", self.file, resource=resource) + resource_time.ScheduleWork = "PT48H" + ifcopenshell.api.run("sequence.assign_process", self.file, relating_process=task, related_object=resource) + ifcopenshell.api.run("sequence.calculate_task_duration", self.file, task=task) + assert task.TaskTime.ScheduleDuration == "P6D" + + def test_calculating_the_duration_based_on_a_labour_resource_with_work_days(self): + ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcProject") + schedule = ifcopenshell.api.run("sequence.add_work_schedule", self.file) + task = ifcopenshell.api.run("sequence.add_task", self.file, work_schedule=schedule) + resource = ifcopenshell.api.run("resource.add_resource", self.file, ifc_class="IfcLaborResource") + resource_time = ifcopenshell.api.run("resource.add_resource_time", self.file, resource=resource) + resource_time.ScheduleWork = "P3.5D" + ifcopenshell.api.run("sequence.assign_process", self.file, relating_process=task, related_object=resource) + ifcopenshell.api.run("sequence.calculate_task_duration", self.file, task=task) + assert task.TaskTime.ScheduleDuration == "P4D"