diff --git a/src/blenderbim/blenderbim/bim/module/resource/prop.py b/src/blenderbim/blenderbim/bim/module/resource/prop.py index 67b486d0dc..1d3491a3c2 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/prop.py +++ b/src/blenderbim/blenderbim/bim/module/resource/prop.py @@ -1,5 +1,5 @@ # BlenderBIM Add-on - OpenBIM Blender Add-on -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2021, 2022, 2023 Dion Moult, Yassine Oualid # # This file is part of BlenderBIM Add-on. # @@ -22,8 +22,8 @@ import ifcopenshell.util.resource from blenderbim.bim.ifc import IfcStore import blenderbim.tool as tool import blenderbim.bim.module.pset.data -from blenderbim.bim.module.resource.data import refresh -from blenderbim.bim.module.sequence.data import refresh as refresh_sequence +import blenderbim.bim.module.resource.data +import blenderbim.bim.module.sequence.data from blenderbim.bim.prop import StrProperty, Attribute from bpy.types import PropertyGroup from bpy.props import ( @@ -58,7 +58,7 @@ def updateResourceName(self, context): if props.active_resource_id == self.ifc_definition_id: attribute = props.resource_attributes.get("Name") attribute.string_value = self.name - refresh() + blenderbim.bim.module.resource.data.refresh() tool.Sequence.refresh_task_resources() @@ -88,17 +88,15 @@ def updateResourceUsage(self, context): if self.schedule_usage == "": return resource = tool.Ifc.get().by_id(self.ifc_definition_id) - if not resource.Usage: - tool.Ifc.run( - "resource.add_resource_time", - resource=resource, - ) - resource.Usage.ScheduleUsage = self.schedule_usage - blenderbim.bim.module.pset.data.refresh() - refresh() + tool.Resource.run_edit_resource_time(resource, attributes={ + "ScheduleUsage": self.schedule_usage + }) tool.Resource.load_resource_properties() + tool.Sequence.load_task_properties() + blenderbim.bim.module.resource.data.refresh() + blenderbim.bim.module.sequence.data.refresh() tool.Sequence.refresh_task_resources() - + blenderbim.bim.module.pset.data.refresh() class ISODuration(PropertyGroup): name: StringProperty(name="Name") diff --git a/src/blenderbim/blenderbim/bim/module/resource/ui.py b/src/blenderbim/blenderbim/bim/module/resource/ui.py index f4b325571a..963b807ae6 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/ui.py +++ b/src/blenderbim/blenderbim/bim/module/resource/ui.py @@ -110,11 +110,11 @@ class BIM_PT_resources(Panel): is_work_locked = True row = self.layout.row() row.label(text="Resource Work") - schedule_usage = "Schedule Usage: {}".format(resource.get("ScheduleUsage")) schedule_work = "Schedule Work: {}".format(resource.get("ScheduleWork")) row = self.layout.row() row.alignment = "LEFT" - row.label(text=schedule_usage, icon="ARMATURE_DATA") + row.label(text="Schedule Usage:") + row.prop(self.tprops.resources[self.props.active_resource_index], "schedule_usage", text="") row2 = self.layout.row() row2.alignment = "LEFT" row2.label(text=schedule_work, icon="ARMATURE_DATA") diff --git a/src/blenderbim/blenderbim/tool/resource.py b/src/blenderbim/blenderbim/tool/resource.py index f8b92074f1..a130d01d7a 100644 --- a/src/blenderbim/blenderbim/tool/resource.py +++ b/src/blenderbim/blenderbim/tool/resource.py @@ -32,7 +32,7 @@ import ifcopenshell.util.date as ifcdateutils import ifcopenshell.util.cost import ifcopenshell.util.resource import blenderbim.bim.schema - +import ifcopenshell.util.constraint class Resource(blenderbim.core.tool.Resource): @classmethod @@ -384,68 +384,30 @@ class Resource(blenderbim.core.tool.Resource): @classmethod def get_constraints(cls, resource): - constraints = [] - for rel in resource.HasAssociations or []: - if rel.is_a("IfcRelAssociatesConstraint"): - constraints.append(rel.RelatingConstraint) - return constraints + return ifcopenshell.util.constraint.get_constraints(product=resource) @classmethod def get_metrics(cls, constraint): - metrics = [] - for metric in constraint.BenchmarkValues or []: - metrics.append(metric) - return metrics + return ifcopenshell.util.constraint.get_metrics(constraint) @classmethod def get_metric_reference(cls, metric, is_deep=True): - def get_reference_Attribute(ref, path): - if ref: - if is_deep: - if not path: - path = ref.AttributeIdentifier - else: - path += ".{}".format(ref.AttributeIdentifier) if ref.AttributeIdentifier else "" - return get_reference_Attribute(ref.InnerReference, path) - else: - return ref.AttributeIdentifier - return path - - reference = metric.ReferencePath - return get_reference_Attribute(reference, "") - - @classmethod - def get_resource_benchmarks(cls, resource): - constraints = [] - for constraint in cls.get_constraints(resource) or []: - metrics = [] - for metric in cls.get_metrics(constraint) or []: - metrics.append( - { - "reference": cls.get_metric_reference(metric), - "Benchmark": metric.Benchmark, - "ConstraintGrade": metric.ConstraintGrade, - } - ) - constraints.append({"ObjectiveQualifier": constraint.ObjectiveQualifier, "metrics": metrics}) - return constraints + return ifcopenshell.util.constraint.get_metric_reference(metric, is_deep=is_deep) @classmethod def has_metric_constraint(cls, resource, attribute): - constraints = tool.Resource.get_constraints(resource) - metrics = [] - for constraint in constraints: - for metric in tool.Resource.get_metrics(constraint) or []: - is_same_reference = bool( - tool.Resource.get_metric_reference(metric, is_deep=False) == attribute - or tool.Resource.get_metric_reference(metric, is_deep=True) == attribute - ) - if is_same_reference: - metrics.append(metric) - if metrics: - return metrics[0] - return None + metrics = ifcopenshell.util.constraint.has_metric_constraints(resource, attribute) + return metrics[0] if metrics else None @classmethod def has_usage_metric(cls, resource): return cls.has_metric_constraint(resource, "Usage") + + @classmethod + def run_edit_resource_time(cls, resource, attributes): + if not resource.Usage: + tool.Ifc.run( + "resource.add_resource_time", + resource=resource, + ) + tool.Ifc.run("resource.edit_resource_time", resource_time=resource.Usage, attributes=attributes) \ No newline at end of file diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/calculate_resource_work.py b/src/ifcopenshell-python/ifcopenshell/api/resource/calculate_resource_work.py index c1d09b3ea0..cc6717fd5f 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/resource/calculate_resource_work.py +++ b/src/ifcopenshell-python/ifcopenshell/api/resource/calculate_resource_work.py @@ -60,6 +60,9 @@ class Usecase: self.settings = {"resource": resource} def execute(self): + metrics= ifcopenshell.util.constraint.has_metric_constraints(self.settings["resource"], "Usage.ScheduleWork") + if metrics and metrics[0].ConstraintGrade == "HARD" and metrics[0].Benchmark == "EQUALTO": + return amount_worked = ifcopenshell.util.resource.get_resource_required_work( self.settings["resource"] ) diff --git a/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource_time.py b/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource_time.py index 451fb62658..29317007fb 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource_time.py +++ b/src/ifcopenshell-python/ifcopenshell/api/resource/edit_resource_time.py @@ -17,8 +17,7 @@ # along with IfcOpenShell. If not, see . import datetime -import ifcopenshell.util.date - +import ifcopenshell class Usecase: def __init__(self, file, resource_time=None, attributes=None): @@ -77,6 +76,9 @@ class Usecase: del self.settings["attributes"]["ActualFinish"] for name, value in self.settings["attributes"].items(): + metrics = ifcopenshell.util.constraint.has_metric_constraints(self.resource, "Usage." + name) + if metrics and self.is_hard_constraint(metrics[0]): + continue if value: if "Start" in name or "Finish" in name or name == "StatusTime": value = ifcopenshell.util.date.datetime2ifc(value, "IfcDateTime") @@ -87,6 +89,15 @@ class Usecase: ): value = ifcopenshell.util.date.datetime2ifc(value, "IfcDuration") setattr(self.settings["resource_time"], name, value) + if name == "ScheduleUsage" and ifcopenshell.util.constraint.has_metric_constraints(self.resource, "Usage.ScheduleWork"): + for rel in self.resource.HasAssignments or []: + if not rel.is_a("IfcRelAssignsToProcess"): + continue + task = rel.RelatingProcess + ifcopenshell.api.run("sequence.calculate_task_duration", self.file, task=task) + + def is_hard_constraint(self, metric): + return bool(metric.ConstraintGrade == "HARD" and metric.Benchmark == "EQUALTO") def get_resource(self): return [