From eae6983ca53e81e2150019117faa915b378007d5 Mon Sep 17 00:00:00 2001 From: "Sigma Dimensions (Yass)" <79010126+myoualid@users.noreply.github.com> Date: Tue, 22 Aug 2023 19:54:37 +0100 Subject: [PATCH] Fix calculating resource work based from parent's productivity and improve UI to show this --- .../blenderbim/bim/module/resource/data.py | 23 ++++ .../bim/module/resource/operator.py | 7 ++ .../blenderbim/bim/module/resource/prop.py | 10 +- .../blenderbim/bim/module/resource/ui.py | 101 ++++++++++-------- .../ifcopenshell/util/resource.py | 16 +-- 5 files changed, 107 insertions(+), 50 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/resource/data.py b/src/blenderbim/blenderbim/bim/module/resource/data.py index f9abe1729f..21f4250027 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/data.py +++ b/src/blenderbim/blenderbim/bim/module/resource/data.py @@ -58,6 +58,7 @@ class ResourceData: } if resource.is_a() in ["IfcLaborResource", "IfcConstructionEquipmentResource"]: results[resource.id()]["Productivity"] = {} + results[resource.id()]["InheritedProductivity"] = {} productivity = cls.get_productivity(resource) if productivity: results[resource.id()]["Productivity"] = { @@ -65,12 +66,34 @@ class ResourceData: "TimeConsumed": ifcopenshell.util.resource.get_unit_consumed(productivity), "QuantityProducedName": ifcopenshell.util.resource.get_quantity_produced_name(productivity), } + inherited_productivity = cls.get_parent_productivity(resource) + if inherited_productivity: + results[resource.id()]["InheritedProductivity"] = { + "QuantityProduced": ifcopenshell.util.resource.get_quantity_produced(inherited_productivity), + "TimeConsumed": ifcopenshell.util.resource.get_unit_consumed(inherited_productivity), + "QuantityProducedName": ifcopenshell.util.resource.get_quantity_produced_name( + inherited_productivity + ), + } + if resource.Usage: + results[resource.id()]["ScheduleWork"] = ( + ifcopenshell.util.date.readable_ifc_duration(resource.Usage.ScheduleWork) + if resource.Usage.ScheduleWork + else "Calculate", + ) + results[resource.id()]["ScheduleUsage"] = ( + resource.Usage.ScheduleUsage if resource.Usage.ScheduleUsage else "" + ) return results @classmethod def get_productivity(cls, resource): return ifcopenshell.util.resource.get_productivity(resource, should_inherit=False) + @classmethod + def get_parent_productivity(cls, resource): + return ifcopenshell.util.resource.get_parent_productivity(resource) + @classmethod def cost_values(cls): results = [] diff --git a/src/blenderbim/blenderbim/bim/module/resource/operator.py b/src/blenderbim/blenderbim/bim/module/resource/operator.py index 9d9d0aeb07..22fc5a0f07 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/operator.py +++ b/src/blenderbim/blenderbim/bim/module/resource/operator.py @@ -198,6 +198,13 @@ class CalculateResourceWork(bpy.types.Operator, tool.Ifc.Operator): bl_options = {"REGISTER", "UNDO"} resource: bpy.props.IntProperty() + @classmethod + def poll(cls, context): + active_resource = tool.Resource.get_highlighted_resource() + if active_resource: + if tool.Resource.get_productivity(active_resource, should_inherit=True): + return True + def _execute(self, context): core.calculate_resource_work(tool.Ifc, tool.Resource, resource=tool.Ifc.get().by_id(self.resource)) diff --git a/src/blenderbim/blenderbim/bim/module/resource/prop.py b/src/blenderbim/blenderbim/bim/module/resource/prop.py index 951ea9286c..67b486d0dc 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/prop.py +++ b/src/blenderbim/blenderbim/bim/module/resource/prop.py @@ -22,6 +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 from blenderbim.bim.prop import StrProperty, Attribute from bpy.types import PropertyGroup from bpy.props import ( @@ -56,6 +58,8 @@ 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() + tool.Sequence.refresh_task_resources() def get_quantity_types(self, context): @@ -72,7 +76,7 @@ def get_quantity_types(self, context): def update_active_resource_index(self, context): blenderbim.bim.module.pset.data.refresh() - if self.should_show_productivity: + if self.should_show_resource_tools: tool.Resource.load_productivity_data() @@ -91,7 +95,9 @@ def updateResourceUsage(self, context): ) resource.Usage.ScheduleUsage = self.schedule_usage blenderbim.bim.module.pset.data.refresh() + refresh() tool.Resource.load_resource_properties() + tool.Sequence.refresh_task_resources() class ISODuration(PropertyGroup): @@ -144,7 +150,7 @@ class BIMResourceProperties(PropertyGroup): quantity_types: EnumProperty(items=get_quantity_types, name="Quantity Types") is_editing_quantity: BoolProperty(name="Is Editing Quantity") quantity_attributes: CollectionProperty(name="Quantity Attributes", type=Attribute) - should_show_productivity: BoolProperty(name="Edit Productivity", update=update_active_resource_index) + should_show_resource_tools: BoolProperty(name="Edit Productivity", update=update_active_resource_index) class BIMResourceProductivity(PropertyGroup): diff --git a/src/blenderbim/blenderbim/bim/module/resource/ui.py b/src/blenderbim/blenderbim/bim/module/resource/ui.py index 090aa0f8c4..10a22625c3 100644 --- a/src/blenderbim/blenderbim/bim/module/resource/ui.py +++ b/src/blenderbim/blenderbim/bim/module/resource/ui.py @@ -64,11 +64,8 @@ class BIM_PT_resources(Panel): self.props, "active_resource_index", ) - row = self.layout.row(align=True) - row.alignment = "RIGHT" - row.prop(self.props, "should_show_productivity", icon="RECOVER_LAST") - if self.props.should_show_productivity: - self.draw_productivity_ui(context) + self.draw_productivity_ui(context) + if self.props.active_resource_id and self.props.editing_resource_type == "ATTRIBUTES": self.draw_editable_resource_attributes_ui() elif self.props.active_resource_id and self.props.editing_resource_type == "QUANTITY": @@ -79,43 +76,66 @@ class BIM_PT_resources(Panel): self.draw_editable_resource_time_attributes_ui() def draw_productivity_ui(self, context): - total_resources = len(self.tprops.resources) - if not total_resources or self.props.active_resource_index >= total_resources: - return - - ifc_definition_id = self.tprops.resources[self.props.active_resource_index].ifc_definition_id - resource = ResourceData.data["resources"][ifc_definition_id] - - if not resource["type"] in ["IfcConstructionEquipmentResource", "IfcLaborResource"]: - row = self.layout.row(align=True) - row.label(text="Resource type cannot have productivity data", icon="ERROR") - return - - self.productivity_props = context.scene.BIMResourceProductivity - - if resource["Productivity"]: - produtivitiy_rate_message = "Current Rate: {}/{}".format( - resource["Productivity"]["QuantityProduced"], resource["Productivity"]["TimeConsumed"] - ) - row = self.layout.row() - row.alignment = "LEFT" - row.label(text=produtivitiy_rate_message, icon="ARMATURE_DATA") - else: - row = self.layout.row(align=True) - row.alignment = "LEFT" - produtivitiy_rate_message = "No productivity data found" - row.label(text=produtivitiy_rate_message, icon="ARMATURE_DATA") row = self.layout.row(align=True) row.alignment = "RIGHT" - row.prop(self.productivity_props, "quantity_produced", text="Quantity Produced") - row.prop(self.productivity_props, "quantity_produced_name", text="Quantity Name") - row = self.layout.row() - row.alignment = "RIGHT" - self.draw_duration_property(self.productivity_props.quantity_consumed, row) - row = self.layout.row() - row.alignment = "RIGHT" - row.operator("bim.edit_productivity_data", text="Apply", icon="CHECKMARK") + row.prop(self.props, "should_show_resource_tools", icon="RECOVER_LAST") + if self.props.should_show_resource_tools: + total_resources = len(self.tprops.resources) + if not total_resources or self.props.active_resource_index >= total_resources: + return + + ifc_definition_id = self.tprops.resources[self.props.active_resource_index].ifc_definition_id + resource = ResourceData.data["resources"][ifc_definition_id] + + if not resource["type"] in ["IfcConstructionEquipmentResource", "IfcLaborResource"]: + row = self.layout.row(align=True) + row.label(text="Resource type cannot have productivity data", icon="ERROR") + else: + productivity = resource["Productivity"] + parent_productivity = resource["InheritedProductivity"] + + row = self.layout.row() + row.operator( + "bim.calculate_resource_work", text="Calculate Work", icon="TEMP" + ).resource = ifc_definition_id + + row = self.layout.row() + row.label(text="Productivity") + row = self.layout.row() + if productivity: + produtivitiy_rate_message = "Current Productivity Rate: {} {} / {}".format( + productivity["QuantityProduced"], + productivity["QuantityProducedName"], + productivity["TimeConsumed"], + ) + row.alignment = "LEFT" + row.label(text=produtivitiy_rate_message, icon="ARMATURE_DATA") + elif parent_productivity: + produtivitiy_rate_message = "Inherited Productivity Rate: {} {} / {}*".format( + parent_productivity["QuantityProduced"], + parent_productivity["QuantityProducedName"], + parent_productivity["TimeConsumed"], + ) + row.alignment = "LEFT" + row.label(text=produtivitiy_rate_message, icon="ARMATURE_DATA") + else: + row = self.layout.row(align=True) + row.alignment = "LEFT" + produtivitiy_rate_message = "No productivity data found" + row.label(text=produtivitiy_rate_message, icon="ARMATURE_DATA") + + productivity_props = context.scene.BIMResourceProductivity + row = self.layout.row(align=True) + row.alignment = "RIGHT" + row.prop(productivity_props, "quantity_produced", text="Quantity Produced") + row.prop(productivity_props, "quantity_produced_name", text="Quantity Name") + row = self.layout.row() + row.alignment = "RIGHT" + self.draw_duration_property(productivity_props.quantity_consumed, row) + row = self.layout.row() + row.alignment = "RIGHT" + row.operator("bim.edit_productivity_data", text="Apply", icon="CHECKMARK") def draw_resource_operators(self): row = self.layout.row(align=True) @@ -153,9 +173,6 @@ class BIM_PT_resources(Panel): if not self.props.active_resource_id: if resource["type"] in ["IfcLaborResource", "IfcConstructionEquipmentResource"]: - if resource["Productivity"]: - op = row.operator("bim.calculate_resource_work", text="", icon="TEMP") - op.resource = ifc_definition_id row.operator("bim.enable_editing_resource_time", text="", icon="TIME").resource = ifc_definition_id op = row.operator("bim.enable_editing_resource_base_quantity", text="", icon="PROPERTIES") op.resource = ifc_definition_id diff --git a/src/ifcopenshell-python/ifcopenshell/util/resource.py b/src/ifcopenshell-python/ifcopenshell/util/resource.py index 016a653209..477a4e2af6 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/resource.py +++ b/src/ifcopenshell-python/ifcopenshell/util/resource.py @@ -23,14 +23,18 @@ import ifcopenshell.util.date def get_productivity(resource, should_inherit=True): productivity = ifcopenshell.util.element.get_psets(resource).get("EPset_Productivity", None) if should_inherit and not productivity: - # Proposal for Schema - If instance doesn't have any productivity, inherit it's parent's productivity - if not resource.Nests: - return None - else: - parent_resource = resource.Nests[0].RelatingObject - productivity = ifcopenshell.util.element.get_psets(parent_resource).get("EPset_Productivity", None) + #Note: This is not part of the Schema - but it makes sense to inherit from parent + productivity = get_parent_productivity(resource) return productivity +def get_parent_productivity(resource): + if not resource.Nests: + return + else: + parent_resource = resource.Nests[0].RelatingObject + productivity = ifcopenshell.util.element.get_psets(parent_resource).get("EPset_Productivity", None) + return productivity + def get_unit_consumed(productivity): duration = productivity.get("BaseQuantityConsumed", None)