diff --git a/src/ifc4d/ifc4d/__main__.py b/src/ifc4d/ifc4d/__main__.py new file mode 100644 index 0000000000..cca02078f3 --- /dev/null +++ b/src/ifc4d/ifc4d/__main__.py @@ -0,0 +1,70 @@ +import os +import sys +import argparse + +from p6xer2ifc import P6XER2Ifc +from p62ifc import P62Ifc +from msp2ifc import MSP2Ifc +import ifcopenshell + + +parser = argparse.ArgumentParser() +parser .add_argument('-f','--file', action='store', type=str, + required=True, help="schedule file name to be parsed") +parser .add_argument('-s','--schedule', action='store', required=True, + type=str, help='file format as xer, p6xml, mspxml') +parser .add_argument('-i', '--ifcfile', action='store', required=False, + type=str, help='ifc file name as string e.g. \"file.ifc\"') +parser .add_argument('-o', '--output', action='store', required=True, + type=str, help='ifc file name as string e.g. \"file.ifc\"') +args = parser .parse_args() + +def get_file(): + ifcfile = None + if args.ifcfile: + ifcfile = ifcopenshell.open(args.ifcfile) + elif args.output: + ifc = ifcopenshell.file(schema='IFC4') + ifc.create_entity("IfcWorkPlan") + ifc.create_entity("IfcContext") + ifc.write(args.output) + ifcfile = ifcopenshell.open(args.output) + else: + ifcfile = None + return ifcfile + +if not args.ifcfile: + print("You need to provide an ifc file to add schedule") + print("Examples python ifc4d -i model.ifc -s xer -f schedule.xer -o newifc.ifc") +elif not args.output: + print("an output file is required to save changes") + print("python ifc4d -o newfile.ifc -s xer -f schedule.xer") + +elif args.schedule== "xer": + p6xer = P6XER2Ifc() + p6xer.xer = args.file + p6xer.output = args.output + ifcfile = get_file() + if ifcfile: + p6xer.file = ifcfile + p6xer.execute() + else: raise Exception("No files provided for output") +elif args.schedule == "mspxml": + msp = MSP2Ifc() + msp.xml = args.file() + msp.output = args.output + ifcfile = get_file() + if ifcfile: + msp.file = ifcfile + msp.execute() +elif args.schedule == "p6xml": + p6xml = P62Ifc() + p6xml.output = args.output + p6xml.xml = args.file + ifcfile = get_file() + if ifcfile: + p6xml.file = ifcopenshell.open(args.ifcfile) + p6xml.execute() +else: + print("schedule type you selected is not implemented at the moment") + diff --git a/src/ifc4d/ifc4d/common.py b/src/ifc4d/ifc4d/common.py index e859f01f46..a43284273c 100644 --- a/src/ifc4d/ifc4d/common.py +++ b/src/ifc4d/ifc4d/common.py @@ -7,17 +7,17 @@ from datetime import datetime, timedelta, date class ScheduleIfcGenerator: - def __init__(self, file, work_plan, project, calendars, wbs, - root_activites, activities, relationships, resources): + def __init__(self, file, output, settings): self.file = file - self.work_plan = work_plan - self.project = project - self.calendars = calendars - self.wbs = wbs - self.root_activites = root_activites - self.activities = activities - self.relationships = relationships - self.resources = resources + self.work_plan = settings['work_plan'] + self.project = settings['project'] + self.calendars = settings['calendars'] + self.wbs = settings['wbs'] + self.root_activites = settings['root_activities'] + self.activities = settings['activities'] + self.relationships = settings['relationships'] + self.resources = settings['resources'] + self.output = output self.day_map = { "Monday": 1, "Tuesday": 2, @@ -38,6 +38,8 @@ class ScheduleIfcGenerator: self.create_tasks(work_schedule) self.create_rel_sequences() self.create_resources() + if self.output: + self.file.write(self.output) def create_work_schedule(self): return ifcopenshell.api.run( @@ -50,11 +52,11 @@ class ScheduleIfcGenerator: "sequence.add_work_calendar", self.file, name=calendar["Name"] ) self.process_working_week(calendar["StandardWorkWeek"], calendar["ifc"]) - self.process_exceptions(calendar["HolidayOrExceptions"], calendar["ifc"]) + self.process_exceptions(calendar.get("HolidayOrExceptions"), calendar["ifc"]) def process_working_week(self, week, calendar): for day in week: - if day["ifc"] or not day["WorkTimes"]: + if day["ifc"] or not day.get("WorkTimes"): continue day["ifc"] = ifcopenshell.api.run( @@ -96,12 +98,13 @@ class ScheduleIfcGenerator: ) def process_exceptions(self, exceptions, calendar): - for year, year_data in exceptions.items(): - for month, month_data in year_data.items(): - if month_data["FullDay"]: - self.process_full_day_exceptions(year, month, month_data, calendar) - if month_data["WorkTime"]: - self.process_work_time_exceptions(year, month, month_data, calendar) + if exceptions: + for year, year_data in exceptions.items(): + for month, month_data in year_data.items(): + if month_data["FullDay"]: + self.process_full_day_exceptions(year, month, month_data, calendar) + if month_data["WorkTime"]: + self.process_work_time_exceptions(year, month, month_data, calendar) def process_full_day_exceptions(self, year, month, month_data, calendar): work_time = ifcopenshell.api.run( @@ -288,35 +291,37 @@ class ScheduleIfcGenerator: def create_resources(self): - - for id, resource in self.resources.items(): - - parent = self.resources.get(resource.get("ParentObjectId")) - if parent: - if not parent.get("ifc"): - parent["ifc"] = ifcopenshell.api.run( - "resource.add_resource", - self.file, - **{"ifc_class": "IfcCrewResource", - "name": parent['Name']} - ) - if parent: - resource["ifc"] = ifcopenshell.api.run( - "resource.add_resource", - self.file, - **{"parent_resource": parent["ifc"] if parent else None, - "ifc_class": "IfcCrewResource", - "name": resource['Name'] - } - ) - else: - resource["ifc"] = ifcopenshell.api.run( - "resource.add_resource", - self.file, - **{ "ifc_class": "IfcCrewResource", - "name": resource['Name'] - } - ) + # print("Resources", self.resources) + if self.resources: + for id, resource in self.resources.items(): + + parent = self.resources.get(resource.get("ParentObjectId")) + if parent: + if not parent.get("ifc"): + parent["ifc"] = ifcopenshell.api.run( + "resource.add_resource", + self.file, + **{"ifc_class": "IfcCrewResource", + "name": parent['Name']} + ) + if parent: + resource["ifc"] = ifcopenshell.api.run( + "resource.add_resource", + self.file, + **{"parent_resource": parent["ifc"] if parent else None, + "ifc_class": "IfcCrewResource", + "name": resource['Name'] + } + ) + else: + resource["ifc"] = ifcopenshell.api.run( + "resource.add_resource", + self.file, + **{ "ifc_class": "IfcCrewResource", + "name": resource['Name'] + } + ) + print(self.resources) diff --git a/src/ifc4d/ifc4d/msp2ifc.py b/src/ifc4d/ifc4d/msp2ifc.py index 8b600e375c..8970e24921 100644 --- a/src/ifc4d/ifc4d/msp2ifc.py +++ b/src/ifc4d/ifc4d/msp2ifc.py @@ -36,15 +36,32 @@ class MSP2Ifc: self.calendars = {} self.wbs = {} self.root_activites = [] + self.activities = [] self.tasks = {} self.relationships = {} + self.resources = {} + self.output = None + self.RESOURCE_TYPES_MAPPING = { + '1' : "LABOR", + '0' : "MATERIAL", + '2' : None + } + def execute(self): self.parse_xml() - ifcCreator = ScheduleIfcGenerator(self.file, self.work_plan, self.project, self.calendars, - self.wbs, self.root_activites, self.activities, self.relationships, None) + settings = { + "work_plan":self.work_plan, + "project": self.project, + "calendars": self.calendars, + "wbs": self.wbs, + "root_activities": self.root_activites, + "activities": self.activities, + "relationships": self.relationships, + "resources": self.resources + } + ifcCreator = ScheduleIfcGenerator(self.file, self.output, settings) ifcCreator.create_ifc() - #self.create_ifc() def parse_xml(self): tree = ET.parse(self.xml) @@ -55,6 +72,8 @@ class MSP2Ifc: self.outline_parents = {} self.parse_task_xml(project) self.parse_calendar_xml(project) + self.parse_resources_xml(project) + def parse_relationship_xml(self, task): relationships = {} @@ -123,4 +142,26 @@ class MSP2Ifc: self.calendars[calendar_id] = { "Name": calendar.find("pr:Name", self.ns).text, "StandardWorkWeek": week_days, - } \ No newline at end of file + } + + def parse_resources_xml(self, project): + resources_lst = project.find("pr:Resources", self.ns) + resources = resources_lst.findall("pr:Resource", self.ns) + # print("Resource text", resources[4].find("pr:Name", self.ns).text) + for resource in resources: + name = resource.find("pr:Name", self.ns) + id = resource.find("pr:ID", self.ns).text + if name is not None: + name = name.text + else: + # print("- No Name") + name = None + self.resources[id] = { + "Name": name, + "Code": resource.find("pr:UID", self.ns).text, + "ParentObjectId": None, + "Type": self.RESOURCE_TYPES_MAPPING[resource.find("pr:Type", self.ns).text], + "ifc": None, + "rel": None, + } + print("Resource found", self.resources) diff --git a/src/ifc4d/ifc4d/p62ifc.py b/src/ifc4d/ifc4d/p62ifc.py index a4da0fd627..b5151e6560 100644 --- a/src/ifc4d/ifc4d/p62ifc.py +++ b/src/ifc4d/ifc4d/p62ifc.py @@ -23,7 +23,7 @@ import ifcopenshell import ifcopenshell.api import ifcopenshell.util.date import xml.etree.ElementTree as ET -from common import ScheduleIfcGenerator +from .common import ScheduleIfcGenerator class P62Ifc: def __init__(self): @@ -37,6 +37,7 @@ class P62Ifc: self.activities = {} self.relationships = {} self.resources = {} + self.output = None self.day_map = { "Monday": 1, "Tuesday": 2, @@ -64,8 +65,17 @@ class P62Ifc: start = time.time() print("Started") self.parse_xml() - ifcCreator = ScheduleIfcGenerator(self.file, self.work_plan, self.project, self.calendars, - self.wbs, self.root_activites, self.activities, self.relationships, self.resources) + settings = { + "work_plan":self.work_plan, + "project": self.project, + "calendars": self.calendars, + "wbs": self.wbs, + "root_activities": self.root_activites, + "activities": self.activities, + "relationships": self.relationships, + "resources": self.resources + } + ifcCreator = ScheduleIfcGenerator(self.file, self.output, settings) end = time.time() ifcCreator.create_ifc() diff --git a/src/ifc4d/ifc4d/p6xer2ifc.py b/src/ifc4d/ifc4d/p6xer2ifc.py index 75cf9c1cfd..d99538f2b2 100644 --- a/src/ifc4d/ifc4d/p6xer2ifc.py +++ b/src/ifc4d/ifc4d/p6xer2ifc.py @@ -65,7 +65,7 @@ class P6XER2Ifc(): self.activities = {} self.relationships = {} self.resources = {} - + self.output = None self.day_map2 = { '1': "Monday", @@ -80,10 +80,18 @@ class P6XER2Ifc(): def execute(self): self.parse_xer() - ifcCreator = ScheduleIfcGenerator(self.file, self.work_plan, self.project, self.calendars, - self.wbs, self.root_activites, self.activities, self.relationships, self.resources) + settings = { + "work_plan":self.work_plan, + "project": self.project, + "calendars": self.calendars, + "wbs": self.wbs, + "root_activities": self.root_activites, + "activities": self.activities, + "relationships": self.relationships, + "resources": self.resources + } + ifcCreator = ScheduleIfcGenerator(self.file, self.output, settings) ifcCreator.create_ifc() - # self.create_ifc() def parse_xer(self): @@ -177,7 +185,6 @@ class P6XER2Ifc(): "ifc": None, "rel": None, } - print(dir(self.model.resources._rsrcs[0]), self.model.resources._rsrcs[0].rsrc_title_name)