mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-25 09:32:37 +00:00
fix msp .xml import: exception days for a standard working week #3766
This commit is contained in:
+123
-26
@@ -17,7 +17,7 @@
|
|||||||
# along with Ifc4D. If not, see <http://www.gnu.org/licenses/>.
|
# along with Ifc4D. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from datetime import timedelta
|
from datetime import timedelta, date
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
import ifcopenshell.util.date
|
import ifcopenshell.util.date
|
||||||
@@ -110,31 +110,73 @@ class MSP2Ifc:
|
|||||||
for calendar in project.find("pr:Calendars", self.ns).findall("pr:Calendar", self.ns):
|
for calendar in project.find("pr:Calendars", self.ns).findall("pr:Calendar", self.ns):
|
||||||
calendar_id = calendar.find("pr:UID", self.ns).text
|
calendar_id = calendar.find("pr:UID", self.ns).text
|
||||||
week_days = []
|
week_days = []
|
||||||
|
exceptions = {}
|
||||||
week_days_element = calendar.find("pr:WeekDays", self.ns)
|
week_days_element = calendar.find("pr:WeekDays", self.ns)
|
||||||
week_day_elements = week_days_element.findall("pr:WeekDay", self.ns) if week_days_element else []
|
week_day_elements = week_days_element.findall("pr:WeekDay", self.ns) if week_days_element else []
|
||||||
for week_day in week_day_elements:
|
for week_day in week_day_elements:
|
||||||
working_times = []
|
|
||||||
if week_day.find("pr:WorkingTimes", self.ns):
|
if week_day.find("pr:WorkingTimes", self.ns):
|
||||||
for working_time in week_day.find("pr:WorkingTimes", self.ns).findall("pr:WorkingTime", self.ns):
|
working_times = []
|
||||||
if working_time.find("pr:FromTime", self.ns) is None:
|
if week_day.find("pr:DayType", self.ns).text == "0":
|
||||||
continue
|
d = datetime.datetime.fromisoformat(
|
||||||
working_times.append(
|
week_day.find("pr:TimePeriod", self.ns).find("pr:FromDate", self.ns).text
|
||||||
|
).date()
|
||||||
|
month = exceptions.setdefault(d.year, {}).setdefault(d.month, {})
|
||||||
|
month.setdefault("FullDay", [])
|
||||||
|
month.setdefault("WorkTime", [])
|
||||||
|
for working_time in week_day.find("pr:WorkingTimes", self.ns).findall(
|
||||||
|
"pr:WorkingTime", self.ns
|
||||||
|
):
|
||||||
|
if working_time.find("pr:FromTime", self.ns) is None:
|
||||||
|
continue
|
||||||
|
working_times.append(
|
||||||
|
{
|
||||||
|
"Start": datetime.time.fromisoformat(
|
||||||
|
working_time.find("pr:FromTime", self.ns).text
|
||||||
|
),
|
||||||
|
"Finish": datetime.time.fromisoformat(working_time.find("pr:ToTime", self.ns).text),
|
||||||
|
"ifc": None,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if working_times:
|
||||||
|
exceptions[d.year][d.month]["WorkTime"].append(
|
||||||
|
{
|
||||||
|
"Day": d.day,
|
||||||
|
"FromDate": datetime.datetime.fromisoformat(
|
||||||
|
week_day.find("pr:TimePeriod", self.ns).find("pr:FromDate", self.ns).text
|
||||||
|
),
|
||||||
|
"ToDate": datetime.datetime.fromisoformat(
|
||||||
|
week_day.find("pr:TimePeriod", self.ns).find("pr:ToDate", self.ns).text
|
||||||
|
),
|
||||||
|
"WorkingTimes": working_times,
|
||||||
|
"ifc": None,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
for working_time in week_day.find("pr:WorkingTimes", self.ns).findall(
|
||||||
|
"pr:WorkingTime", self.ns
|
||||||
|
):
|
||||||
|
if working_time.find("pr:FromTime", self.ns) is None:
|
||||||
|
continue
|
||||||
|
working_times.append(
|
||||||
|
{
|
||||||
|
"Start": datetime.time.fromisoformat(
|
||||||
|
working_time.find("pr:FromTime", self.ns).text
|
||||||
|
),
|
||||||
|
"Finish": datetime.time.fromisoformat(working_time.find("pr:ToTime", self.ns).text),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
week_days.append(
|
||||||
{
|
{
|
||||||
"Start": datetime.time.fromisoformat(working_time.find("pr:FromTime", self.ns).text),
|
"DayType": week_day.find("pr:DayType", self.ns).text,
|
||||||
"Finish": datetime.time.fromisoformat(working_time.find("pr:ToTime", self.ns).text),
|
"WorkingTimes": working_times,
|
||||||
|
"ifc": None,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
week_days.append(
|
|
||||||
{
|
|
||||||
"DayType": week_day.find("pr:DayType", self.ns).text,
|
|
||||||
"WorkingTimes": working_times,
|
|
||||||
"ifc": None,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
exceptions = {}
|
|
||||||
self.calendars[calendar_id] = {
|
self.calendars[calendar_id] = {
|
||||||
"Name": calendar.find("pr:Name", self.ns).text,
|
"Name": calendar.find("pr:Name", self.ns).text,
|
||||||
"StandardWorkWeek": week_days,
|
"StandardWorkWeek": week_days,
|
||||||
|
"HolidayOrExceptions": exceptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
def create_ifc(self):
|
def create_ifc(self):
|
||||||
@@ -166,6 +208,7 @@ class MSP2Ifc:
|
|||||||
for calendar in self.calendars.values():
|
for calendar in self.calendars.values():
|
||||||
calendar["ifc"] = ifcopenshell.api.run("sequence.add_work_calendar", self.file, name=calendar["Name"])
|
calendar["ifc"] = ifcopenshell.api.run("sequence.add_work_calendar", self.file, name=calendar["Name"])
|
||||||
self.process_working_week(calendar["StandardWorkWeek"], calendar["ifc"])
|
self.process_working_week(calendar["StandardWorkWeek"], calendar["ifc"])
|
||||||
|
self.process_exceptions(calendar["HolidayOrExceptions"], calendar["ifc"])
|
||||||
|
|
||||||
def create_task(self, task, work_schedule=None, parent_task=None):
|
def create_task(self, task, work_schedule=None, parent_task=None):
|
||||||
task["ifc"] = ifcopenshell.api.run(
|
task["ifc"] = ifcopenshell.api.run(
|
||||||
@@ -218,13 +261,14 @@ class MSP2Ifc:
|
|||||||
|
|
||||||
def process_working_week(self, week, calendar):
|
def process_working_week(self, week, calendar):
|
||||||
day_map = {
|
day_map = {
|
||||||
"1": 7, # Sunday
|
"1": 7, # Sunday
|
||||||
"2": 1, # Monday
|
"2": 1, # Monday
|
||||||
"3": 2, # Tuesday
|
"3": 2, # Tuesday
|
||||||
"4": 3, # Wednesday
|
"4": 3, # Wednesday
|
||||||
"5": 4, # Thursday
|
"5": 4, # Thursday
|
||||||
"6": 5, # Friday
|
"6": 5, # Friday
|
||||||
"7": 6, # Saturday
|
"7": 6, # Saturday
|
||||||
|
"0": 0, # Exception
|
||||||
}
|
}
|
||||||
for day in week:
|
for day in week:
|
||||||
if day["ifc"]:
|
if day["ifc"]:
|
||||||
@@ -297,14 +341,12 @@ class MSP2Ifc:
|
|||||||
def parse_resources_xml(self, project):
|
def parse_resources_xml(self, project):
|
||||||
resources_lst = project.find("pr:Resources", self.ns)
|
resources_lst = project.find("pr:Resources", self.ns)
|
||||||
resources = resources_lst.findall("pr:Resource", 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:
|
for resource in resources:
|
||||||
name = resource.find("pr:Name", self.ns)
|
name = resource.find("pr:Name", self.ns)
|
||||||
id = resource.find("pr:ID", self.ns).text
|
id = resource.find("pr:ID", self.ns).text
|
||||||
if name is not None:
|
if name is not None:
|
||||||
name = name.text
|
name = name.text
|
||||||
else:
|
else:
|
||||||
# print("- No Name")
|
|
||||||
name = None
|
name = None
|
||||||
self.resources[id] = {
|
self.resources[id] = {
|
||||||
"Name": name,
|
"Name": name,
|
||||||
@@ -314,4 +356,59 @@ class MSP2Ifc:
|
|||||||
"ifc": None,
|
"ifc": None,
|
||||||
"rel": None,
|
"rel": None,
|
||||||
}
|
}
|
||||||
print("Resource found", self.resources)
|
|
||||||
|
def process_exceptions(self, exceptions, calendar):
|
||||||
|
if exceptions:
|
||||||
|
for year, year_data in exceptions.items():
|
||||||
|
for month, month_data in year_data.items():
|
||||||
|
if month_data["WorkTime"]:
|
||||||
|
self.process_work_time_exceptions(year, month, month_data, calendar)
|
||||||
|
|
||||||
|
def process_work_time_exceptions(self, year, month, month_data, calendar):
|
||||||
|
for day in month_data["WorkTime"]:
|
||||||
|
if day["ifc"]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
day["ifc"] = ifcopenshell.api.run(
|
||||||
|
"sequence.add_work_time", self.file, work_calendar=calendar, time_type="ExceptionTimes"
|
||||||
|
)
|
||||||
|
|
||||||
|
day_component = [day["Day"]]
|
||||||
|
for day2 in month_data["WorkTime"]:
|
||||||
|
if day["Day"] == day2["Day"]:
|
||||||
|
continue
|
||||||
|
if day["WorkingTimes"] == day2["WorkingTimes"]:
|
||||||
|
day_component.append(day2["Day"])
|
||||||
|
# Don't process the next day, as we can group it
|
||||||
|
day2["ifc"] = day["ifc"]
|
||||||
|
|
||||||
|
ifcopenshell.api.run(
|
||||||
|
"sequence.edit_work_time",
|
||||||
|
self.file,
|
||||||
|
work_time=day["ifc"],
|
||||||
|
attributes={
|
||||||
|
"Name": "{}-{}-{}".format(year, month, ", ".join([str(d) for d in day_component])),
|
||||||
|
"Start": ifcopenshell.util.date.datetime2ifc(day["FromDate"], "IfcDate"),
|
||||||
|
"Finish": ifcopenshell.util.date.datetime2ifc(day["ToDate"], "IfcDate"),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
recurrence = ifcopenshell.api.run(
|
||||||
|
"sequence.assign_recurrence_pattern",
|
||||||
|
self.file,
|
||||||
|
parent=day["ifc"],
|
||||||
|
recurrence_type="YEARLY_BY_DAY_OF_MONTH",
|
||||||
|
)
|
||||||
|
ifcopenshell.api.run(
|
||||||
|
"sequence.edit_recurrence_pattern",
|
||||||
|
self.file,
|
||||||
|
recurrence_pattern=recurrence,
|
||||||
|
attributes={"DayComponent": day_component, "MonthComponent": [month]},
|
||||||
|
)
|
||||||
|
for work_time in day["WorkingTimes"]:
|
||||||
|
ifcopenshell.api.run(
|
||||||
|
"sequence.add_time_period",
|
||||||
|
self.file,
|
||||||
|
recurrence_pattern=recurrence,
|
||||||
|
start_time=work_time["Start"],
|
||||||
|
end_time=work_time["Finish"],
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user