From a7febaa9b09dcaacb14e25ca77b3d26829f78c68 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 11 Nov 2022 11:37:56 +1100 Subject: [PATCH] Fix astapowerproject import to ifc which seemed mostly broken for some reason --- src/ifc4d/ifc4d/pp2ifc.py | 215 +++++++++++++++++------------------- src/ifc4d/ifc4d/wpattern.py | 51 ++++----- 2 files changed, 125 insertions(+), 141 deletions(-) diff --git a/src/ifc4d/ifc4d/pp2ifc.py b/src/ifc4d/ifc4d/pp2ifc.py index c3dd574da5..b0faddc22d 100644 --- a/src/ifc4d/ifc4d/pp2ifc.py +++ b/src/ifc4d/ifc4d/pp2ifc.py @@ -1,6 +1,7 @@ print("In module products __package__, __name__ ==", __package__) print(__name__) -import sys +import sys + print("In module products sys.path[0], __package__ ==", sys.path[0], __package__) sys.path.append(sys.path[0]) @@ -16,20 +17,20 @@ from .common import ScheduleIfcGenerator import time - list_of_tables = [ - 'BAR', - 'EXPANDED_TASK', - 'PERMANENT_RESOURCE', - 'CONSUMABLE_RESOURCE', - 'TASK', - 'PROJECT_SUMMARY', - 'WBS_ENTRY' + "BAR", + "EXPANDED_TASK", + "PERMANENT_RESOURCE", + "CONSUMABLE_RESOURCE", + "TASK", + "PROJECT_SUMMARY", + "WBS_ENTRY", ] + class PP2Ifc: def __init__(self): - + self.pp = None self.file = None self.work_plan = None @@ -41,30 +42,14 @@ class PP2Ifc: self.relationships = {} self.resources = {} self.output = None - self.day_map = { - "Monday": 1, - "Tuesday": 2, - "Wednesday": 3, - "Thursday": 4, - "Friday": 5, - "Saturday": 6, - "Sunday": 7, - } - - 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): - 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()] return r - + def get_json_with_filter(self, table_name, attr_name, 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()] @@ -75,19 +60,19 @@ class PP2Ifc: self.cur = self.con.cursor() self.parse_pp() settings = { - "work_plan":self.work_plan, + "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 + "resources": self.resources, } start = time.time() ifcCreator = ScheduleIfcGenerator(self.file, self.output, settings) end = time.time() - + ifcCreator.create_ifc() end2 = time.time() print("Parsing time is", end - start) @@ -96,34 +81,35 @@ class PP2Ifc: # self.create_ifc() def parse_pp(self): - + project = self.get_json("PROJECT_SUMMARY")[0] self.project["Name"] = project["SHORT_NAME"] self.parse_calendar_pp() - self.parse_wbs_pp() - self.parse_activity_pp() + self.parse_bar() self.parse_relationship_pp(project) def parse_calendar_pp(self): calendars = self.get_json("CALENDAR") wp_data = self.get_json("WORK_PATTERN") work_types = self.get_json("EXCEPTIONN") - work_type_ids = [wt['ID'] for wt in work_types if wt['EXCEPTION_TYPE'] == 0] + work_type_ids = [wt["ID"] for wt in work_types if wt["EXCEPTION_TYPE"] == 0] for calendar in calendars: calendar_id = calendar["ID"] calendar_wp = calendar["DOMINANT_WORK_PATTERN"] wp_data = self.get_json_with_filter("WORK_PATTERN", "ID", calendar_wp) - wp = AstaCalendarWorkPattern(wp_data[0]['SHIFTS'], work_type_ids) + wp = AstaCalendarWorkPattern(wp_data[0]["SHIFTS"], work_type_ids) exceptions = {} timex = [] for times in wp.dict_wp: work_times = timedelta(hours=0) - for daily in times['WorkTimes']: - fin = daily['Finish'] - strt = daily['Start'] - work_times += timedelta(hours=fin.hour, minutes=fin.minute) - timedelta(hours=strt.hour, minutes=strt.minute) - timex.append(work_times.total_seconds() /(60*60)) + for daily in times["WorkTimes"]: + fin = daily["Finish"] + strt = daily["Start"] + work_times += timedelta(hours=fin.hour, minutes=fin.minute) - timedelta( + hours=strt.hour, minutes=strt.minute + ) + timex.append(work_times.total_seconds() / (60 * 60)) self.calendars[calendar_id] = { "Name": calendar["NAME"], @@ -132,87 +118,84 @@ class PP2Ifc: "StandardWorkWeek": wp.dict_wp, "HolidayOrExceptions": exceptions, } - #print(self.calendars[calendar_id]) + # print(self.calendars[calendar_id]) - def parse_wbs_pp(self): + def parse_bar(self): bars = self.get_json("BAR") - extended_tasks = 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")} + milestones = {m["BAR"]: m for m in self.get_json("MILESTONE")} + + schedule_task = None + + bar_tasks = {} + wbs_activities = {} + for bar in bars: - self.wbs[bar["ID"]] = { - "Name": bar["NAME"], - "Code": bar["ID"], - "ParentObjectId": bar["EXPANDED_TASK"] if bar["EXPANDED_TASK"]> 0 else None, - "ifc": None, - "rel": None, - "activities": [], - } - for bar in extended_tasks: - self.wbs[bar["ID"]] = { - "Name": bar["NAME"], - "Code": bar["ID"], - "ParentObjectId": bar["BAR"] if bar["BAR"]> 0 else None, - "ifc": None, - "rel": None, - "activities": [], - } - #print(self.wbs) + extra_type = None + extra_data = None + bar_id = None - def parse_activity_pp(self): - activities = self.get_json("TASK") - milestones = self.get_json("MILESTONE") - for activity in activities: - activity_type = "TASK" - activity_id = activity["ID"] - if 'PLANNED_DURATION' in activity.keys(): - activity_duration = float(activity["PLANNED_DURATION"].split(",")[-2].replace("<","").replace(">","")) - elif 'GIVEN_DURATION' in activity.keys(): - activity_duration = float(activity["GIVEN_DURATION"].split(",")[-2].replace("<","").replace(">","")) + if bar["ID"] in expanded_tasks: + extra_type = "EXPANDED_TASK" + extra_data = expanded_tasks[bar["ID"]] + elif bar["ID"] in tasks: + extra_type = "TASK" + extra_data = tasks[bar["ID"]] + elif bar["ID"] in milestones: + extra_type = "MILESTONE" + extra_data = milestones[bar["ID"]] else: - activity_duration = 0.0 + # Not sure where this might be the case + continue - wbs_id = activity["BAR"] - if wbs_id: - self.wbs[wbs_id]["activities"].append(activity_id) + name = bar["NAME"] + if extra_data["NAME"]: + name += f" - {extra_data['NAME']}" + bar_tasks[extra_data["ID"]] = {"bar": bar, "extra_type": extra_type, "extra_data": extra_data} + + if extra_type == "EXPANDED_TASK": + self.wbs[extra_data["ID"]] = { + "Name": name, + "Code": extra_data["ID"], + "ParentObjectId": bar["EXPANDED_TASK"] if bar["EXPANDED_TASK"] > 0 else None, + "ifc": None, + "rel": None, + "activities": [], + } else: - self.root_activites.append(activity_id) - self.activities[activity_id] = { - "Name": activity["NAME"], - "Identification": activity["ID"], - "StartDate": datetime.datetime.fromisoformat(activity["LINKABLE_START"]), - "FinishDate": datetime.datetime.fromisoformat(activity["LINKABLE_FINISH"]), - "PlannedDuration": activity_duration, - "Status": "PLANNED", - "CalendarObjectId": activity["CALENDAR"], - "ifc": None, - } - - for activity in milestones: - activity_type = "MILESTONE" - activity_id = activity["ID"] - wbs_id = activity["BAR"] - if wbs_id: - self.wbs[wbs_id]["activities"].append(activity_id) - else: - self.root_activites.append(activity_id) - self.activities[activity_id] = { - "Name": activity["NAME"], - "Identification": activity["ID"], - "StartDate": datetime.datetime.fromisoformat(activity["LINKABLE_START"]), - "FinishDate": datetime.datetime.fromisoformat(activity["LINKABLE_FINISH"]), - "PlannedDuration": 0.0, - "Status": "PLANNED", - "CalendarObjectId": activity["CALENDAR"], - "ifc": None, - } - #print("***ACTIVITIES", self.activities[activity_id]) + if "PLANNED_DURATION" in extra_data.keys(): + activity_duration = float( + extra_data["PLANNED_DURATION"].split(",")[-2].replace("<", "").replace(">", "") + ) + elif "GIVEN_DURATION" in extra_data.keys(): + activity_duration = float( + extra_data["GIVEN_DURATION"].split(",")[-2].replace("<", "").replace(">", "") + ) + else: + activity_duration = 0.0 + + self.activities[extra_data["ID"]] = { + "Name": name, + "Identification": extra_data["ID"], + "StartDate": datetime.datetime.fromisoformat(extra_data["LINKABLE_START"]), + "FinishDate": datetime.datetime.fromisoformat(extra_data["LINKABLE_FINISH"]), + "PlannedDuration": activity_duration, + "Status": "PLANNED", + "CalendarObjectId": extra_data["CALENDAR"], + "ifc": None, + } + wbs_activities.setdefault(bar["EXPANDED_TASK"], []).append(extra_data["ID"]) + + for wbs, activities in wbs_activities.items(): + self.wbs[wbs]["activities"] = activities def parse_relationship_pp(self, project): - relations = self.get_json('LINK') - print(relations) + relations = self.get_json("LINK") + # print(relations) for relationship in relations: - predecessor = relationship['START_TASK'] - successor = relationship['END_TASK'] + predecessor = relationship["START_TASK"] + successor = relationship["END_TASK"] if predecessor not in self.activities: print(f"Linked predecessor task {predecessor} cannot be found.") continue @@ -222,6 +205,6 @@ class PP2Ifc: self.relationships[relationship["ID"]] = { "PredecessorActivity": predecessor, "SuccessorActivity": successor, - "Type": self.relationship_map[relationship['LINK_KIND']], - "Lag": float(relationship['END_LAG_TIME'].split(",")[-2].replace("<","").replace(">","")), + "Type": self.relationship_map[relationship["LINK_KIND"]], + "Lag": float(relationship["END_LAG_TIME"].split(",")[-2].replace("<", "").replace(">", "")), } diff --git a/src/ifc4d/ifc4d/wpattern.py b/src/ifc4d/ifc4d/wpattern.py index 51358e425e..db17ce5c70 100644 --- a/src/ifc4d/ifc4d/wpattern.py +++ b/src/ifc4d/ifc4d/wpattern.py @@ -10,28 +10,27 @@ import re from datetime import time, datetime - class AstaCalendarWorkPattern: def get_keys(self, s): regex = r"\<(\".+?\")\>(\w|\d|)+?" - matches=re.finditer(regex, s) + matches = re.finditer(regex, s) matcs = [] for matchNum, match in enumerate(matches, start=1): matcs.append(match.group(1)) - return matcs - + return matcs def get_values(self, s): rx2 = r"<\"[^<>]+\">" - data = re.split('<[^<>]+>', s) + data = re.split("<[^<>]+>", s) return data def __init__(self, string, work_type_ids): self.string = string self.Days = { - 'en': ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], - 'sv': ['Söndag', 'Måndag', 'Tisdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lördag'], + "en": ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], + "sv": ["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag"], + "de": ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"], } self.keys = self.get_keys(string) self.values = self.get_values(string) @@ -40,29 +39,31 @@ class AstaCalendarWorkPattern: for d, m in zip(self.values[1:], self.keys): splt_data = d.strip().split(",") workhours = [] - if len(splt_data)>=7: + if len(splt_data) >= 7: number_of_work_slots = splt_data[1] for i in range(int(number_of_work_slots)): - if int(splt_data[2+i*3]) in work_type_ids: - st1_1 = datetime.strptime(splt_data[2+i*3+1].ljust(5,'0'), "%H%M%S") - st1_2 = datetime.strptime(splt_data[2+i*3+2].ljust(5,'0'), "%H%M%S") - st = {"Start":time(st1_1.hour, st1_1.minute), "Finish": time(st1_2.hour, st1_2.minute), "ifc": None} + if int(splt_data[2 + i * 3]) in work_type_ids: + st1_1 = datetime.strptime(splt_data[2 + i * 3 + 1].ljust(5, "0"), "%H%M%S") + st1_2 = datetime.strptime(splt_data[2 + i * 3 + 2].ljust(5, "0"), "%H%M%S") + st = { + "Start": time(st1_1.hour, st1_1.minute), + "Finish": time(st1_2.hour, st1_2.minute), + "ifc": None, + } workhours.append(st) - - self.dict_wp.append({'DayOfWeek': m.replace("\"",""), - 'WorkTimes': workhours, "ifc": None}) - + + self.dict_wp.append({"DayOfWeek": m.replace('"', ""), "WorkTimes": workhours, "ifc": None}) + # Translate day names to english - for index, day in enumerate(self.Days['en']): - d = self.dict_wp[-1]['DayOfWeek'] + for index, day in enumerate(self.Days["en"]): + d = self.dict_wp[-1]["DayOfWeek"] for lang in self.Days.keys(): - if lang == 'en': + if lang == "en": continue - self.dict_wp[-1]['DayOfWeek'] = d.replace(self.Days[lang][index], self.Days['en'][index]) - - for day in self.Days['en']: - if not len(list(filter(lambda d: d['DayOfWeek']== day , self.dict_wp))) > 0: + self.dict_wp[-1]["DayOfWeek"] = d.replace(self.Days[lang][index], self.Days["en"][index]) + + 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}) + self.dict_wp.append({"DayOfWeek": day, "WorkTimes": [], "ifc": None}) print("final", self.dict_wp)