mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 10:11:46 +00:00
pp2ifc refactor and add support for more languages #5417
This commit is contained in:
+75
-18
@@ -1,12 +1,61 @@
|
|||||||
from xerparser.reader import Reader
|
from __future__ import annotations
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
import ifcopenshell.util.date
|
import ifcopenshell.util.date
|
||||||
from datetime import datetime, timedelta, date
|
from datetime import datetime, timedelta, date
|
||||||
|
from typing import Union, Any, TypedDict, NotRequired
|
||||||
|
|
||||||
|
|
||||||
|
class WorkSlot(TypedDict):
|
||||||
|
DayOfWeek: str
|
||||||
|
WorkTimes: list[dict[str, Any]]
|
||||||
|
ifc: Union[ifcopenshell.entity_instance, None]
|
||||||
|
|
||||||
|
|
||||||
|
class ExceptionDict(TypedDict):
|
||||||
|
WorkTime: list[int]
|
||||||
|
FullDay: list[int]
|
||||||
|
|
||||||
|
|
||||||
|
ExceptionsDict = dict[int, dict[int, ExceptionDict]]
|
||||||
|
|
||||||
|
|
||||||
|
class Calendar(TypedDict):
|
||||||
|
Name: str
|
||||||
|
Type: str
|
||||||
|
HoursPerDay: int
|
||||||
|
StandardWorkWeek: list[WorkSlot]
|
||||||
|
HolidayOrExceptions: NotRequired[ExceptionsDict]
|
||||||
|
ifc: NotRequired[ifcopenshell.entity_instance]
|
||||||
|
|
||||||
|
|
||||||
|
class Activity(TypedDict):
|
||||||
|
Name: str
|
||||||
|
Identification: int
|
||||||
|
StartDate: datetime
|
||||||
|
FinishDate: datetime
|
||||||
|
PlannedDuration: float
|
||||||
|
Status: str
|
||||||
|
CalendarObjectId: str
|
||||||
|
ifc: Union[ifcopenshell.entity_instance, None]
|
||||||
|
|
||||||
|
|
||||||
|
class WBSEntry(TypedDict):
|
||||||
|
"""Work Breakdown Strcture Entry"""
|
||||||
|
|
||||||
|
Name: str
|
||||||
|
Code: int
|
||||||
|
ParentObjectId: Union[int, None]
|
||||||
|
ifc: Union[ifcopenshell.entity_instance, None]
|
||||||
|
rel: Union[ifcopenshell.entity_instance, None]
|
||||||
|
activities: list[int]
|
||||||
|
|
||||||
|
|
||||||
class ScheduleIfcGenerator:
|
class ScheduleIfcGenerator:
|
||||||
def __init__(self, file, output, settings):
|
file: Union[ifcopenshell.file, None]
|
||||||
|
calendars: dict[int, Calendar]
|
||||||
|
|
||||||
|
def __init__(self, file: Union[ifcopenshell.file, None], output, settings):
|
||||||
self.file = file
|
self.file = file
|
||||||
self.work_plan = settings["work_plan"]
|
self.work_plan = settings["work_plan"]
|
||||||
self.project = settings["project"]
|
self.project = settings["project"]
|
||||||
@@ -27,7 +76,7 @@ class ScheduleIfcGenerator:
|
|||||||
"Sunday": 7,
|
"Sunday": 7,
|
||||||
}
|
}
|
||||||
|
|
||||||
def create_ifc(self):
|
def create_ifc(self) -> None:
|
||||||
if not self.file:
|
if not self.file:
|
||||||
self.file = self.create_boilerplate_ifc()
|
self.file = self.create_boilerplate_ifc()
|
||||||
if not self.work_plan:
|
if not self.work_plan:
|
||||||
@@ -40,18 +89,18 @@ class ScheduleIfcGenerator:
|
|||||||
if self.output:
|
if self.output:
|
||||||
self.file.write(self.output)
|
self.file.write(self.output)
|
||||||
|
|
||||||
def create_work_schedule(self):
|
def create_work_schedule(self) -> ifcopenshell.entity_instance:
|
||||||
return ifcopenshell.api.run(
|
return ifcopenshell.api.run(
|
||||||
"sequence.add_work_schedule", self.file, name=self.project["Name"], work_plan=self.work_plan
|
"sequence.add_work_schedule", self.file, name=self.project["Name"], work_plan=self.work_plan
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_calendars(self):
|
def create_calendars(self) -> None:
|
||||||
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.get("HolidayOrExceptions"), calendar["ifc"])
|
self.process_exceptions(calendar.get("HolidayOrExceptions"), calendar["ifc"])
|
||||||
|
|
||||||
def process_working_week(self, week, calendar):
|
def process_working_week(self, week: list[WorkSlot], calendar: ifcopenshell.entity_instance) -> None:
|
||||||
for day in week:
|
for day in week:
|
||||||
if day["ifc"] or not day.get("WorkTimes"):
|
if day["ifc"] or not day.get("WorkTimes"):
|
||||||
continue
|
continue
|
||||||
@@ -94,7 +143,9 @@ class ScheduleIfcGenerator:
|
|||||||
end_time=work_time["Finish"],
|
end_time=work_time["Finish"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def process_exceptions(self, exceptions, calendar):
|
def process_exceptions(
|
||||||
|
self, exceptions: Union[ExceptionsDict, None], calendar: ifcopenshell.entity_instance
|
||||||
|
) -> None:
|
||||||
if exceptions:
|
if exceptions:
|
||||||
for year, year_data in exceptions.items():
|
for year, year_data in exceptions.items():
|
||||||
for month, month_data in year_data.items():
|
for month, month_data in year_data.items():
|
||||||
@@ -103,7 +154,9 @@ class ScheduleIfcGenerator:
|
|||||||
if month_data["WorkTime"]:
|
if month_data["WorkTime"]:
|
||||||
self.process_work_time_exceptions(year, month, month_data, calendar)
|
self.process_work_time_exceptions(year, month, month_data, calendar)
|
||||||
|
|
||||||
def process_full_day_exceptions(self, year, month, month_data, calendar):
|
def process_full_day_exceptions(
|
||||||
|
self, year: int, month: int, month_data: dict[str, Any], calendar: ifcopenshell.entity_instance
|
||||||
|
):
|
||||||
work_time = ifcopenshell.api.run(
|
work_time = ifcopenshell.api.run(
|
||||||
"sequence.add_work_time", self.file, work_calendar=calendar, time_type="ExceptionTimes"
|
"sequence.add_work_time", self.file, work_calendar=calendar, time_type="ExceptionTimes"
|
||||||
)
|
)
|
||||||
@@ -130,7 +183,9 @@ class ScheduleIfcGenerator:
|
|||||||
attributes={"DayComponent": month_data["FullDay"], "MonthComponent": [month]},
|
attributes={"DayComponent": month_data["FullDay"], "MonthComponent": [month]},
|
||||||
)
|
)
|
||||||
|
|
||||||
def process_work_time_exceptions(self, year, month, month_data, calendar):
|
def process_work_time_exceptions(
|
||||||
|
self, year: int, month: int, month_data: dict[str, Any], calendar: ifcopenshell.entity_instance
|
||||||
|
) -> None:
|
||||||
for day in month_data["WorkTime"]:
|
for day in month_data["WorkTime"]:
|
||||||
if day["ifc"]:
|
if day["ifc"]:
|
||||||
continue
|
continue
|
||||||
@@ -179,13 +234,13 @@ class ScheduleIfcGenerator:
|
|||||||
end_time=work_time["Finish"],
|
end_time=work_time["Finish"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_tasks(self, work_schedule):
|
def create_tasks(self, work_schedule: ifcopenshell.entity_instance) -> None:
|
||||||
for wbs in self.wbs.values():
|
for wbs in self.wbs.values():
|
||||||
self.create_task_from_wbs(wbs, work_schedule)
|
self.create_task_from_wbs(wbs, work_schedule)
|
||||||
for activity_id in self.root_activites:
|
for activity_id in self.root_activites:
|
||||||
self.create_task_from_activity(self.activities[activity_id], None, work_schedule)
|
self.create_task_from_activity(self.activities[activity_id], None, work_schedule)
|
||||||
|
|
||||||
def create_task_from_wbs(self, wbs, work_schedule):
|
def create_task_from_wbs(self, wbs: WBSEntry, work_schedule: ifcopenshell.entity_instance) -> None:
|
||||||
if not self.wbs.get(wbs["ParentObjectId"]):
|
if not self.wbs.get(wbs["ParentObjectId"]):
|
||||||
wbs["ParentObjectId"] = None
|
wbs["ParentObjectId"] = None
|
||||||
wbs["ifc"] = ifcopenshell.api.run(
|
wbs["ifc"] = ifcopenshell.api.run(
|
||||||
@@ -207,7 +262,12 @@ class ScheduleIfcGenerator:
|
|||||||
for activity_id in wbs["activities"]:
|
for activity_id in wbs["activities"]:
|
||||||
self.create_task_from_activity(self.activities[activity_id], wbs, None)
|
self.create_task_from_activity(self.activities[activity_id], wbs, None)
|
||||||
|
|
||||||
def create_task_from_activity(self, activity, wbs, work_schedule):
|
def create_task_from_activity(
|
||||||
|
self,
|
||||||
|
activity: Activity,
|
||||||
|
wbs: Union[WBSEntry, None],
|
||||||
|
work_schedule: Union[ifcopenshell.entity_instance, None],
|
||||||
|
) -> None:
|
||||||
activity["ifc"] = ifcopenshell.api.run(
|
activity["ifc"] = ifcopenshell.api.run(
|
||||||
"sequence.add_task",
|
"sequence.add_task",
|
||||||
self.file,
|
self.file,
|
||||||
@@ -228,7 +288,6 @@ class ScheduleIfcGenerator:
|
|||||||
)
|
)
|
||||||
task_time = ifcopenshell.api.run("sequence.add_task_time", self.file, task=activity["ifc"])
|
task_time = ifcopenshell.api.run("sequence.add_task_time", self.file, task=activity["ifc"])
|
||||||
calendar = self.calendars[activity["CalendarObjectId"]]
|
calendar = self.calendars[activity["CalendarObjectId"]]
|
||||||
# print(calendar, self.calendars)
|
|
||||||
# Seems intermittently crashy - can we investigate for larger files?
|
# Seems intermittently crashy - can we investigate for larger files?
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run(
|
||||||
"control.assign_control",
|
"control.assign_control",
|
||||||
@@ -254,7 +313,7 @@ class ScheduleIfcGenerator:
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_rel_sequences(self):
|
def create_rel_sequences(self) -> None:
|
||||||
self.sequence_type_map = {
|
self.sequence_type_map = {
|
||||||
"Start to Start": "START_START",
|
"Start to Start": "START_START",
|
||||||
"Start to Finish": "START_FINISH",
|
"Start to Finish": "START_FINISH",
|
||||||
@@ -285,8 +344,7 @@ class ScheduleIfcGenerator:
|
|||||||
duration_type="WORKTIME",
|
duration_type="WORKTIME",
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_resources(self):
|
def create_resources(self) -> None:
|
||||||
# print("Resources", self.resources)
|
|
||||||
if self.resources:
|
if self.resources:
|
||||||
for id, resource in self.resources.items():
|
for id, resource in self.resources.items():
|
||||||
|
|
||||||
@@ -312,8 +370,7 @@ class ScheduleIfcGenerator:
|
|||||||
resource["ifc"] = ifcopenshell.api.run(
|
resource["ifc"] = ifcopenshell.api.run(
|
||||||
"resource.add_resource", self.file, **{"ifc_class": "IfcCrewResource", "name": resource["Name"]}
|
"resource.add_resource", self.file, **{"ifc_class": "IfcCrewResource", "name": resource["Name"]}
|
||||||
)
|
)
|
||||||
print(self.resources)
|
|
||||||
|
|
||||||
def create_boilerplate_ifc(self):
|
def create_boilerplate_ifc(self) -> None:
|
||||||
self.file = ifcopenshell.file(schema="IFC4")
|
self.file = ifcopenshell.file(schema="IFC4")
|
||||||
self.work_plan = self.file.create_entity("IfcWorkPlan")
|
self.work_plan = self.file.create_entity("IfcWorkPlan")
|
||||||
|
|||||||
+31
-34
@@ -6,15 +6,13 @@ print("In module products sys.path[0], __package__ ==", sys.path[0], __package__
|
|||||||
sys.path.append(sys.path[0])
|
sys.path.append(sys.path[0])
|
||||||
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import math
|
|
||||||
import datetime
|
import datetime
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import ifcopenshell
|
|
||||||
import ifcopenshell.api
|
|
||||||
import ifcopenshell.util.date
|
import ifcopenshell.util.date
|
||||||
from .wpattern import AstaCalendarWorkPattern
|
from .wpattern import AstaCalendarWorkPattern
|
||||||
from .common import ScheduleIfcGenerator
|
from .common import ScheduleIfcGenerator, Calendar, WBSEntry, Activity
|
||||||
import time
|
import time
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
list_of_tables = [
|
list_of_tables = [
|
||||||
@@ -29,6 +27,9 @@ list_of_tables = [
|
|||||||
|
|
||||||
|
|
||||||
class PP2Ifc:
|
class PP2Ifc:
|
||||||
|
wbs: dict[int, WBSEntry]
|
||||||
|
activities: dict[int, Activity]
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.pp = None
|
self.pp = None
|
||||||
@@ -45,17 +46,17 @@ class PP2Ifc:
|
|||||||
|
|
||||||
self.relationship_map = {0: "FINISH_START", 1: "FINISH_FINISH", 2: "START_START", 3: "START_FINISH"}
|
self.relationship_map = {0: "FINISH_START", 1: "FINISH_FINISH", 2: "START_START", 3: "START_FINISH"}
|
||||||
|
|
||||||
def get_json(self, table_name):
|
def get_json(self, table_name: str) -> list[dict[str, Any]]:
|
||||||
self.cur.execute("select * from " + table_name)
|
self.cur.execute("select * from " + table_name)
|
||||||
r = [dict((self.cur.description[i][0], value) for i, value in enumerate(row)) for row in self.cur.fetchall()]
|
r = [dict((self.cur.description[i][0], value) for i, value in enumerate(row)) for row in self.cur.fetchall()]
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def get_json_with_filter(self, table_name, attr_name, attr_value):
|
def get_json_with_filter(self, table_name: str, attr_name: str, attr_value: Any) -> list[dict[str, Any]]:
|
||||||
self.cur.execute("select * from " + table_name + " where " + attr_name + " = " + str(attr_value))
|
self.cur.execute("select * from " + table_name + " where " + attr_name + " = " + str(attr_value))
|
||||||
r = [dict((self.cur.description[i][0], value) for i, value in enumerate(row)) for row in self.cur.fetchall()]
|
r = [dict((self.cur.description[i][0], value) for i, value in enumerate(row)) for row in self.cur.fetchall()]
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def execute(self):
|
def execute(self) -> None:
|
||||||
self.con = sqlite3.connect(self.pp)
|
self.con = sqlite3.connect(self.pp)
|
||||||
self.cur = self.con.cursor()
|
self.cur = self.con.cursor()
|
||||||
self.parse_pp()
|
self.parse_pp()
|
||||||
@@ -78,17 +79,15 @@ class PP2Ifc:
|
|||||||
print("Parsing time is", end - start)
|
print("Parsing time is", end - start)
|
||||||
print("IFC Creation took", end2 - end)
|
print("IFC Creation took", end2 - end)
|
||||||
print("Overall Time", end2 - start)
|
print("Overall Time", end2 - start)
|
||||||
# self.create_ifc()
|
|
||||||
|
|
||||||
def parse_pp(self):
|
|
||||||
|
|
||||||
|
def parse_pp(self) -> None:
|
||||||
project = self.get_json("PROJECT_SUMMARY")[0]
|
project = self.get_json("PROJECT_SUMMARY")[0]
|
||||||
self.project["Name"] = project["SHORT_NAME"]
|
self.project["Name"] = project["SHORT_NAME"]
|
||||||
self.parse_calendar_pp()
|
self.parse_calendar_pp()
|
||||||
self.parse_bar()
|
self.parse_bar()
|
||||||
self.parse_relationship_pp(project)
|
self.parse_relationship_pp()
|
||||||
|
|
||||||
def parse_calendar_pp(self):
|
def parse_calendar_pp(self) -> None:
|
||||||
calendars = self.get_json("CALENDAR")
|
calendars = self.get_json("CALENDAR")
|
||||||
wp_data = self.get_json("WORK_PATTERN")
|
wp_data = self.get_json("WORK_PATTERN")
|
||||||
work_types = self.get_json("EXCEPTIONN")
|
work_types = self.get_json("EXCEPTIONN")
|
||||||
@@ -111,16 +110,15 @@ class PP2Ifc:
|
|||||||
)
|
)
|
||||||
timex.append(work_times.total_seconds() / (60 * 60))
|
timex.append(work_times.total_seconds() / (60 * 60))
|
||||||
|
|
||||||
self.calendars[calendar_id] = {
|
self.calendars[calendar_id] = Calendar(
|
||||||
"Name": calendar["NAME"],
|
Name=calendar["NAME"],
|
||||||
"Type": "NOTDEFINED",
|
Type="NOTDEFINED",
|
||||||
"HoursPerDay": max(timex),
|
HoursPerDay=max(timex),
|
||||||
"StandardWorkWeek": wp.dict_wp,
|
StandardWorkWeek=wp.dict_wp,
|
||||||
"HolidayOrExceptions": exceptions,
|
HolidayOrExceptions=exceptions,
|
||||||
}
|
)
|
||||||
# print(self.calendars[calendar_id])
|
|
||||||
|
|
||||||
def parse_bar(self):
|
def parse_bar(self) -> None:
|
||||||
bars = self.get_json("BAR")
|
bars = self.get_json("BAR")
|
||||||
expanded_tasks = {t["BAR"]: t for t in self.get_json("EXPANDED_TASK")}
|
expanded_tasks = {t["BAR"]: t for t in self.get_json("EXPANDED_TASK")}
|
||||||
tasks = {t["BAR"]: t for t in self.get_json("TASK")}
|
tasks = {t["BAR"]: t for t in self.get_json("TASK")}
|
||||||
@@ -129,7 +127,7 @@ class PP2Ifc:
|
|||||||
schedule_task = None
|
schedule_task = None
|
||||||
|
|
||||||
bar_tasks = {}
|
bar_tasks = {}
|
||||||
wbs_activities = {}
|
wbs_activities: dict[int, list[int]] = {}
|
||||||
|
|
||||||
for bar in bars:
|
for bar in bars:
|
||||||
extra_type = None
|
extra_type = None
|
||||||
@@ -175,24 +173,23 @@ class PP2Ifc:
|
|||||||
else:
|
else:
|
||||||
activity_duration = 0.0
|
activity_duration = 0.0
|
||||||
|
|
||||||
self.activities[extra_data["ID"]] = {
|
self.activities[extra_data["ID"]] = Activity(
|
||||||
"Name": name,
|
Name=name,
|
||||||
"Identification": extra_data["ID"],
|
Identification=bar["ID"],
|
||||||
"StartDate": datetime.datetime.fromisoformat(extra_data["LINKABLE_START"]),
|
StartDate=datetime.datetime.fromisoformat(extra_data["LINKABLE_START"]),
|
||||||
"FinishDate": datetime.datetime.fromisoformat(extra_data["LINKABLE_FINISH"]),
|
FinishDate=datetime.datetime.fromisoformat(extra_data["LINKABLE_FINISH"]),
|
||||||
"PlannedDuration": activity_duration,
|
PlannedDuration=activity_duration,
|
||||||
"Status": "PLANNED",
|
Status="PLANNED",
|
||||||
"CalendarObjectId": extra_data["CALENDAR"],
|
CalendarObjectId=extra_data["CALENDAR"],
|
||||||
"ifc": None,
|
ifc=None,
|
||||||
}
|
)
|
||||||
wbs_activities.setdefault(bar["EXPANDED_TASK"], []).append(extra_data["ID"])
|
wbs_activities.setdefault(bar["EXPANDED_TASK"], []).append(extra_data["ID"])
|
||||||
|
|
||||||
for wbs, activities in wbs_activities.items():
|
for wbs, activities in wbs_activities.items():
|
||||||
self.wbs[wbs]["activities"] = activities
|
self.wbs[wbs]["activities"] = activities
|
||||||
|
|
||||||
def parse_relationship_pp(self, project):
|
def parse_relationship_pp(self) -> None:
|
||||||
relations = self.get_json("LINK")
|
relations = self.get_json("LINK")
|
||||||
# print(relations)
|
|
||||||
for relationship in relations:
|
for relationship in relations:
|
||||||
predecessor = relationship["START_TASK"]
|
predecessor = relationship["START_TASK"]
|
||||||
successor = relationship["END_TASK"]
|
successor = relationship["END_TASK"]
|
||||||
|
|||||||
+110
-35
@@ -8,10 +8,12 @@ for each day as a key there is a list of working times with the format
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
from datetime import time, datetime
|
from datetime import time, datetime
|
||||||
|
from typing import Any
|
||||||
|
from ifc4d.common import WorkSlot
|
||||||
|
|
||||||
|
|
||||||
class AstaCalendarWorkPattern:
|
class AstaCalendarWorkPattern:
|
||||||
def get_keys(self, s):
|
def get_keys(self, s: str) -> list[str]:
|
||||||
regex = r"\<(\".+?\")\>(\w|\d|)+?"
|
regex = r"\<(\".+?\")\>(\w|\d|)+?"
|
||||||
|
|
||||||
matches = re.finditer(regex, s)
|
matches = re.finditer(regex, s)
|
||||||
@@ -20,30 +22,115 @@ class AstaCalendarWorkPattern:
|
|||||||
matcs.append(match.group(1))
|
matcs.append(match.group(1))
|
||||||
return matcs
|
return matcs
|
||||||
|
|
||||||
def get_values(self, s):
|
def get_values(self, s: str) -> list[str]:
|
||||||
rx2 = r"<\"[^<>]+\">"
|
rx2 = r"<\"[^<>]+\">" # TODO: unused?
|
||||||
data = re.split("<[^<>]+>", s)
|
data = re.split("<[^<>]+>", s)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def __init__(self, string, work_type_ids):
|
# Used the list of Blender supported languages as a reference.
|
||||||
self.string = string
|
# Method to generate names for other language:
|
||||||
self.Days = {
|
# def get_day_names(lang):
|
||||||
"en": ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
|
# from babel.dates import get_day_names
|
||||||
"sv": ["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag"],
|
# from babel import Locale
|
||||||
"de": ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
|
# locale = Locale(lang)
|
||||||
}
|
# return [i.capitalize() for i in get_day_names(locale=locale, width="wide").values()]
|
||||||
self.keys = self.get_keys(string)
|
Days = {
|
||||||
|
"am": ("እሑድ", "ሰኞ", "ማክሰኞ", "ረቡዕ", "ሐሙስ", "ዓርብ", "ቅዳሜ"),
|
||||||
|
"ar": ("الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت"),
|
||||||
|
"be": ("Нядзеля", "Панядзелак", "Аўторак", "Серада", "Чацвер", "Пятніца", "Субота"),
|
||||||
|
"bg": ("Неделя", "Понеделник", "Вторник", "Сряда", "Четвъртък", "Петък", "Събота"),
|
||||||
|
"ca": ("Diumenge", "Dilluns", "Dimarts", "Dimecres", "Dijous", "Divendres", "Dissabte"),
|
||||||
|
"cs": ("Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota"),
|
||||||
|
"da": ("Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag"),
|
||||||
|
"de": ("Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"),
|
||||||
|
"el": ("Κυριακή", "Δευτέρα", "Τρίτη", "Τετάρτη", "Πέμπτη", "Παρασκευή", "Σάββατο"),
|
||||||
|
"en": ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"),
|
||||||
|
"eo": ("Dimanĉo", "Lundo", "Mardo", "Merkredo", "Ĵaŭdo", "Vendredo", "Sabato"),
|
||||||
|
"es": ("Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"),
|
||||||
|
"et": ("Pühapäev", "Esmaspäev", "Teisipäev", "Kolmapäev", "Neljapäev", "Reede", "Laupäev"),
|
||||||
|
"eu": ("Igandea", "Astelehena", "Asteartea", "Asteazkena", "Osteguna", "Ostirala", "Larunbata"),
|
||||||
|
"fa": ("یکشنبه", "دوشنبه", "سه\u200cشنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه"),
|
||||||
|
"fi": ("Sunnuntaina", "Maanantaina", "Tiistaina", "Keskiviikkona", "Torstaina", "Perjantaina", "Lauantaina"),
|
||||||
|
"fr": ("Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"),
|
||||||
|
"ha": ("Lahadi", "Litinin", "Talata", "Laraba", "Alhamis", "Jummaʼa", "Asabar"),
|
||||||
|
"he": ("יום ראשון", "יום שני", "יום שלישי", "יום רביעי", "יום חמישי", "יום שישי", "יום שבת"),
|
||||||
|
"hi": ("रविवार", "सोमवार", "मंगलवार", "बुधवार", "गुरुवार", "शुक्रवार", "शनिवार"),
|
||||||
|
"hr": ("Nedjelja", "Ponedjeljak", "Utorak", "Srijeda", "Četvrtak", "Petak", "Subota"),
|
||||||
|
"hu": ("Vasárnap", "Hétfő", "Kedd", "Szerda", "Csütörtök", "Péntek", "Szombat"),
|
||||||
|
"id": ("Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"),
|
||||||
|
"it": ("Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"),
|
||||||
|
"ja": ("日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"),
|
||||||
|
"ka": ("კვირა", "ორშაბათი", "სამშაბათი", "ოთხშაბათი", "ხუთშაბათი", "პარასკევი", "შაბათი"),
|
||||||
|
"kk": ("Жексенбі", "Дүйсенбі", "Сейсенбі", "Сәрсенбі", "Бейсенбі", "Жұма", "Сенбі"),
|
||||||
|
"km": ("អាទិត្យ", "ច័ន្ទ", "អង្គារ", "ពុធ", "ព្រហស្បតិ៍", "សុក្រ", "សៅរ៍"),
|
||||||
|
"ko": ("일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"),
|
||||||
|
"ky": ("Жекшемби", "Дүйшөмбү", "Шейшемби", "Шаршемби", "Бейшемби", "Жума", "Ишемби"),
|
||||||
|
"ne": ("आइतबार", "सोमबार", "मङ्गलबार", "बुधबार", "बिहिबार", "शुक्रबार", "शनिबार"),
|
||||||
|
"nl": ("Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag"),
|
||||||
|
"pl": ("Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota"),
|
||||||
|
"pt": ("Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sábado"),
|
||||||
|
"ro": ("Duminică", "Luni", "Marți", "Miercuri", "Joi", "Vineri", "Sâmbătă"),
|
||||||
|
"ru": ("Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"),
|
||||||
|
"sk": ("Nedeľa", "Pondelok", "Utorok", "Streda", "Štvrtok", "Piatok", "Sobota"),
|
||||||
|
"sl": ("Nedelja", "Ponedeljek", "Torek", "Sreda", "Četrtek", "Petek", "Sobota"),
|
||||||
|
"sr": ("Недеља", "Понедељак", "Уторак", "Среда", "Четвртак", "Петак", "Субота"),
|
||||||
|
"sv": ("Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag"),
|
||||||
|
"sw": ("Jumapili", "Jumatatu", "Jumanne", "Jumatano", "Alhamisi", "Ijumaa", "Jumamosi"),
|
||||||
|
"ta": ("ஞாயிறு", "திங்கள்", "செவ்வாய்", "புதன்", "வியாழன்", "வெள்ளி", "சனி"),
|
||||||
|
"th": ("วันอาทิตย์", "วันจันทร์", "วันอังคาร", "วันพุธ", "วันพฤหัสบดี", "วันศุกร์", "วันเสาร์"),
|
||||||
|
"tr": ("Pazar", "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma", "Cumartesi"),
|
||||||
|
"uk": ("Неділя", "Понеділок", "Вівторок", "Середа", "Четвер", "Пʼятниця", "Субота"),
|
||||||
|
"ur": ("اتوار", "پیر", "منگل", "بدھ", "جمعرات", "جمعہ", "ہفتہ"),
|
||||||
|
"vi": ("Chủ nhật", "Thứ hai", "Thứ ba", "Thứ tư", "Thứ năm", "Thứ sáu", "Thứ bảy"),
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_day_names(self, string: str) -> None:
|
||||||
|
"""Parse day names from string and translate them to English.
|
||||||
|
|
||||||
|
:raises Exception: If language is not yet supported.
|
||||||
|
"""
|
||||||
|
# Parse day names.
|
||||||
|
day_names = [day_name.strip('"') for day_name in self.get_keys(string)]
|
||||||
|
# Identify language.
|
||||||
|
day_names_set = set(day_names)
|
||||||
|
for lang in self.Days:
|
||||||
|
lang_day_names = self.Days[lang]
|
||||||
|
if day_names_set.issubset(lang_day_names):
|
||||||
|
en_day_names = self.Days["en"]
|
||||||
|
self.lang = lang
|
||||||
|
# Translate day names to English.
|
||||||
|
self.day_names = [en_day_names[lang_day_names.index(d)] for d in day_names]
|
||||||
|
return
|
||||||
|
|
||||||
|
msg = (
|
||||||
|
"Could not identify language for work patterns, need to update Days dictionary."
|
||||||
|
"Please report it to IfcOpenShell Github issues"
|
||||||
|
f"\nDay names provided: {day_names}."
|
||||||
|
"\nAvailable languages:"
|
||||||
|
)
|
||||||
|
for lang in self.Days:
|
||||||
|
msg += f"\n - {lang}: {self.Days[lang]}"
|
||||||
|
raise Exception(msg)
|
||||||
|
|
||||||
|
lang: str
|
||||||
|
day_names: list[str]
|
||||||
|
|
||||||
|
def __init__(self, string: str, work_type_ids: list[int]):
|
||||||
|
self.get_day_names(string)
|
||||||
self.values = self.get_values(string)
|
self.values = self.get_values(string)
|
||||||
self.dict_wp = []
|
self.dict_wp: list[WorkSlot] = []
|
||||||
for d, m in zip(self.values[1:], self.keys):
|
|
||||||
splt_data = d.strip().split(",")
|
for value, day_name in zip(self.values[1:], self.day_names, strict=True):
|
||||||
workhours = []
|
splt_data = value.strip().split(",")
|
||||||
|
workhours: list[dict[str, Any]] = []
|
||||||
if len(splt_data) >= 7:
|
if len(splt_data) >= 7:
|
||||||
number_of_work_slots = splt_data[1]
|
number_of_work_slots = splt_data[1]
|
||||||
for i in range(int(number_of_work_slots)):
|
for i in range(int(number_of_work_slots)):
|
||||||
if int(splt_data[2 + i * 3]) in work_type_ids:
|
work_slot_data = splt_data[2 + i * 3 :][:3]
|
||||||
st1_1 = datetime.strptime(splt_data[2 + i * 3 + 1].ljust(5, "0"), "%H%M%S")
|
work_type_id, start_time, end_time = work_slot_data
|
||||||
st1_2 = datetime.strptime(splt_data[2 + i * 3 + 2].ljust(5, "0"), "%H%M%S")
|
if int(work_type_id) in work_type_ids:
|
||||||
|
st1_1 = datetime.strptime(start_time.ljust(5, "0"), "%H%M%S")
|
||||||
|
st1_2 = datetime.strptime(end_time.ljust(5, "0"), "%H%M%S")
|
||||||
st = {
|
st = {
|
||||||
"Start": time(st1_1.hour, st1_1.minute),
|
"Start": time(st1_1.hour, st1_1.minute),
|
||||||
"Finish": time(st1_2.hour, st1_2.minute),
|
"Finish": time(st1_2.hour, st1_2.minute),
|
||||||
@@ -51,21 +138,9 @@ class AstaCalendarWorkPattern:
|
|||||||
}
|
}
|
||||||
workhours.append(st)
|
workhours.append(st)
|
||||||
|
|
||||||
self.dict_wp.append({"DayOfWeek": m.replace('"', ""), "WorkTimes": workhours, "ifc": None})
|
self.dict_wp.append(WorkSlot(DayOfWeek=day_name, WorkTimes=workhours, ifc=None))
|
||||||
|
|
||||||
# Translate day names to english
|
# Add empty work times for missing week days.
|
||||||
def translate_days(days, wp):
|
missing_week_days = set(self.Days[self.lang]) - set(self.day_names)
|
||||||
for index, day in enumerate(days["en"]):
|
for day_name in missing_week_days:
|
||||||
for lang in days.keys():
|
self.dict_wp.append(WorkSlot(DayOfWeek=day_name, WorkTimes=[], ifc=None))
|
||||||
if lang == "en":
|
|
||||||
continue
|
|
||||||
if wp["DayOfWeek"] == days[lang][index]:
|
|
||||||
wp["DayOfWeek"] = days["en"][index]
|
|
||||||
return
|
|
||||||
|
|
||||||
translate_days(self.Days, self.dict_wp[-1])
|
|
||||||
|
|
||||||
for day in self.Days["en"]:
|
|
||||||
if not len(list(filter(lambda d: d["DayOfWeek"] == day, self.dict_wp))) > 0:
|
|
||||||
print("MISSING", day)
|
|
||||||
self.dict_wp.append({"DayOfWeek": day, "WorkTimes": [], "ifc": None})
|
|
||||||
|
|||||||
Reference in New Issue
Block a user