mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Command Line Interface and MS Project Resource Parsing (#1845)
* implemented initial cli and support for resource parsing for ms project * Added command line interface and resource support for MS Project XML files * Removed the test code * Check for output exists before writting the file to avoid failure
This commit is contained in:
@@ -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")
|
||||
|
||||
+52
-47
@@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user