From c6d1bf30a68285856938bfe4bb81deab917b8511 Mon Sep 17 00:00:00 2001 From: scopesorting Date: Tue, 14 Nov 2023 12:06:39 +0100 Subject: [PATCH 1/7] adapting rules 0001-L & 0001-M (times terminal) and 0006-B. However, for 0006-B the provided solution is not verified, as the errors could not be reproduced locally. --- .../validators/validation_rule_functions.py | 10 +++---- .../test_validation_rule_functions.py | 28 +++++++++++++++++-- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/server/BreCal/validators/validation_rule_functions.py b/src/server/BreCal/validators/validation_rule_functions.py index 591dfb8..80bb15d 100644 --- a/src/server/BreCal/validators/validation_rule_functions.py +++ b/src/server/BreCal/validators/validation_rule_functions.py @@ -500,7 +500,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): a certain threshold (e.g., 20 hours), a violation occurs 0001-L: - - Checks, if times_terminal.eta_berth is filled in. + - Checks, if times_terminal.operations_start is filled in. - Measures the difference between 'now' and 'times_agency.eta_berth'. """ # check, if the header is filled in (agency & terminal) @@ -512,7 +512,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value) query_time = times_agency.eta_berth - key_time = times_terminal.eta_berth + key_time = times_terminal.operations_start # eta_berth does not exist in times_terminal! Instead, it is called operations_start threshold = ParticipantwiseTimeDelta.TERMINAL violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold) @@ -530,7 +530,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): a certain threshold (e.g., 20 hours), a violation occurs 0001-M: - - Checks, if times_terminal.etd_berth is filled in. + - Checks, if times_terminal.operations_end is filled in. - Measures the difference between 'now' and 'times_agency.etd_berth'. """ # check, if the header is filled in (agency & terminal) @@ -542,7 +542,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value) query_time = times_agency.etd_berth - key_time = times_terminal.etd_berth + key_time = times_terminal.operations_end # etd_berth does not exist in times_terminal! Instead, it is called operations_end threshold = ParticipantwiseTimeDelta.TERMINAL violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold) @@ -850,7 +850,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): if shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]: return (StatusFlags.GREEN, None) - violation_state = times_agency.pier_side!=times_terminal.pier_side + violation_state = bool(times_agency.pier_side)!=bool(times_terminal.pier_side) if violation_state: validation_name = inspect.currentframe().f_code.co_name diff --git a/src/server/tests/validators/test_validation_rule_functions.py b/src/server/tests/validators/test_validation_rule_functions.py index 3fccac5..cdb0183 100644 --- a/src/server/tests/validators/test_validation_rule_functions.py +++ b/src/server/tests/validators/test_validation_rule_functions.py @@ -367,7 +367,7 @@ def test_validation_rule_fct_missing_time_terminal_berth_eta__shipcall_soon_but_ df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value, "eta_berth"] = datetime.datetime.now() + datetime.timedelta(minutes=ParticipantwiseTimeDelta.TERMINAL-10) # set times agency to be undetermined - df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value, "eta_berth"] = None + df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value, "operations_start"] = None # previously: eta_berth, which does not exist in times_terminal # apply the validation rule (state, msg) = vr.validation_rule_fct_missing_time_terminal_berth_eta(shipcall=shipcall, df_times=df_times) @@ -389,7 +389,7 @@ def test_validation_rule_fct_missing_time_terminal_berth_etd__shipcall_soon_but_ df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value, "etd_berth"] = datetime.datetime.now() + datetime.timedelta(minutes=ParticipantwiseTimeDelta.TERMINAL-10) # set times agency to be undetermined - df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value, "etd_berth"] = None + df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value, "operations_end"] = None # previously: etd_berth, which does not exist in times_terminal # apply the validation rule (state, msg) = vr.validation_rule_fct_missing_time_terminal_berth_etd(shipcall=shipcall, df_times=df_times) @@ -820,6 +820,30 @@ def test_validation_rule_fct_agency_and_terminal_pier_side_disagreement__agency_ assert code==StatusFlags.YELLOW, f"status should be 'yellow', because agency and terminal do not agree on the selected pier side" return +def test_validation_rule_fct_agency_and_terminal_pier_side_disagreement__agency_and_terminal_disagree_terminal_is_none(build_sql_proxy_connection): + """0006-B validation_rule_fct_agency_and_terminal_pier_side_disagreement""" + vr = build_sql_proxy_connection['vr'] + shipcall = get_shipcall_simple() + df_times = get_df_times(shipcall) + df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value, "pier_side"] = True + df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value, "pier_side"] = None + + (code, msg) = vr.validation_rule_fct_agency_and_terminal_pier_side_disagreement(shipcall=shipcall, df_times=df_times) + assert code==StatusFlags.GREEN, f"status should be 'green', because the terminal's pier_side is not provided" + return + +def test_validation_rule_fct_agency_and_terminal_pier_side_disagreement__agency_and_terminal_disagree_terminal_is_nan(build_sql_proxy_connection): + """0006-B validation_rule_fct_agency_and_terminal_pier_side_disagreement""" + vr = build_sql_proxy_connection['vr'] + shipcall = get_shipcall_simple() + df_times = get_df_times(shipcall) + df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value, "pier_side"] = True + df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value, "pier_side"] = float("nan") + + (code, msg) = vr.validation_rule_fct_agency_and_terminal_pier_side_disagreement(shipcall=shipcall, df_times=df_times) + assert code==StatusFlags.GREEN, f"status should be 'yellow', because the terminal's pier_side is not provided" + return + def test_validation_rule_fct_agency_and_terminal_pier_side_agreement(build_sql_proxy_connection): From 21e9c7578196b72331f8207a032dfc82f38221b0 Mon Sep 17 00:00:00 2001 From: scopesorting Date: Tue, 14 Nov 2023 12:07:59 +0100 Subject: [PATCH 2/7] typo. --- src/server/tests/validators/test_validation_rule_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/tests/validators/test_validation_rule_functions.py b/src/server/tests/validators/test_validation_rule_functions.py index cdb0183..1847973 100644 --- a/src/server/tests/validators/test_validation_rule_functions.py +++ b/src/server/tests/validators/test_validation_rule_functions.py @@ -841,7 +841,7 @@ def test_validation_rule_fct_agency_and_terminal_pier_side_disagreement__agency_ df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value, "pier_side"] = float("nan") (code, msg) = vr.validation_rule_fct_agency_and_terminal_pier_side_disagreement(shipcall=shipcall, df_times=df_times) - assert code==StatusFlags.GREEN, f"status should be 'yellow', because the terminal's pier_side is not provided" + assert code==StatusFlags.GREEN, f"status should be 'green', because the terminal's pier_side is not provided" return From 40dc022b258766f87fdf76db9eb5810c4da7607b Mon Sep 17 00:00:00 2001 From: scopesorting Date: Mon, 20 Nov 2023 16:22:58 +0100 Subject: [PATCH 3/7] fixing np to_list error, which may have caused the evaluation function to stop altogether. --- src/server/BreCal/database/sql_handler.py | 7 +- .../validators/validation_rule_functions.py | 141 ++++++++++-------- 2 files changed, 86 insertions(+), 62 deletions(-) diff --git a/src/server/BreCal/database/sql_handler.py b/src/server/BreCal/database/sql_handler.py index 6c1acd2..3ecd895 100644 --- a/src/server/BreCal/database/sql_handler.py +++ b/src/server/BreCal/database/sql_handler.py @@ -176,7 +176,8 @@ class SQLHandler(): def get_times_for_participant_type(self, df_times, participant_type:int): filtered_series = df_times.loc[df_times["participant_type"]==participant_type] - assert len(filtered_series)<=1, f"found multiple results" + + assert len(filtered_series)<=1, f"found multiple results in function SQLHandler.get_times_for_participant_type" times = self.df_loc_to_data_model(filtered_series, id=0, model_str='times', loc_type="iloc") # use iloc! to retrieve the first result return times @@ -201,7 +202,9 @@ class SQLHandler(): df = df.set_index('shipcall_id', inplace=False) # the 'if' call is needed to ensure, that no Exception is raised, when the shipcall_id is not present in the df - participant_id_list = df.loc[shipcall_id, "participant_id"].to_list() if shipcall_id in list(df.index) else [] + participant_id_list = df.loc[shipcall_id, "participant_id"].tolist() if shipcall_id in list(df.index) else [] + if not isinstance(participant_id_list,list): + participant_id_list = [participant_id_list] return participant_id_list def get_times_of_shipcall(self, shipcall)->pd.DataFrame: diff --git a/src/server/BreCal/validators/validation_rule_functions.py b/src/server/BreCal/validators/validation_rule_functions.py index 80bb15d..a8138ab 100644 --- a/src/server/BreCal/validators/validation_rule_functions.py +++ b/src/server/BreCal/validators/validation_rule_functions.py @@ -63,6 +63,10 @@ class ValidationRuleBaseFunctions(): returns: string """ return self.error_message_dict.get(key,key) + + def get_no_violation_default_output(self): + """return the default output of a validation function with no validation: a tuple of (GREEN state, None)""" + return (StatusFlags.GREEN, None) def check_time_delta_violation_query_time_to_now(self, query_time:pd.Timestamp, key_time:pd.Timestamp, threshold:float)->bool: """ @@ -209,7 +213,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): """ # check, if the header is filled in (agency) if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value])]) != 1: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) @@ -222,7 +226,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_missing_time_agency_berth_etd(self, shipcall, df_times, *args, **kwargs): """ @@ -237,7 +241,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): """ # check, if the header is filled in (agency) if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value])]) != 1: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) @@ -250,7 +254,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_missing_time_mooring_berth_eta(self, shipcall, df_times, *args, **kwargs): """ @@ -265,7 +269,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): """ # check, if the header is filled in (agency & MOORING) if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.MOORING.value])]) != 2: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) @@ -280,7 +284,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_missing_time_mooring_berth_etd(self, shipcall, df_times, *args, **kwargs): """ @@ -295,7 +299,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): """ # check, if the header is filled in (agency & MOORING) if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.MOORING.value])]) != 2: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) @@ -310,7 +314,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_missing_time_portadministration_berth_eta(self, shipcall, df_times, *args, **kwargs): """ @@ -325,7 +329,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): """ # check, if the header is filled in (agency & PORT_ADMINISTRATION) if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.PORT_ADMINISTRATION.value])]) != 2: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) @@ -340,7 +344,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_missing_time_portadministration_berth_etd(self, shipcall, df_times, *args, **kwargs): """ @@ -355,7 +359,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): """ # check, if the header is filled in (agency & PORT_ADMINISTRATION) if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.PORT_ADMINISTRATION.value])]) != 2: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) @@ -370,7 +374,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_missing_time_pilot_berth_eta(self, shipcall, df_times, *args, **kwargs): """ @@ -385,7 +389,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): """ # check, if the header is filled in (agency & PILOT) if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.PILOT.value])]) != 2: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) @@ -400,7 +404,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_missing_time_pilot_berth_etd(self, shipcall, df_times, *args, **kwargs): """ @@ -415,7 +419,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): """ # check, if the header is filled in (agency & PILOT) if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.PILOT.value])]) != 2: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) @@ -430,7 +434,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_missing_time_tug_berth_eta(self, shipcall, df_times, *args, **kwargs): """ @@ -445,7 +449,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): """ # check, if the header is filled in (agency & TUG) if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TUG.value])]) != 2: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) @@ -460,7 +464,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_missing_time_tug_berth_etd(self, shipcall, df_times, *args, **kwargs): """ @@ -475,7 +479,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): """ # check, if the header is filled in (agency & TUG) if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TUG.value])]) != 2: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) @@ -490,7 +494,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_missing_time_terminal_berth_eta(self, shipcall, df_times, *args, **kwargs): """ @@ -504,8 +508,11 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): - Measures the difference between 'now' and 'times_agency.eta_berth'. """ # check, if the header is filled in (agency & terminal) - if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TERMINAL.value])]) != 2: - return (StatusFlags.GREEN, None) + if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1: + return self.get_no_violation_default_output() # rule not applicable + + if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1: + return self.get_no_violation_default_output() # rule not applicable # preparation: obtain the correct times of the participant, define the query time and the key time times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) @@ -520,7 +527,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_missing_time_terminal_berth_etd(self, shipcall, df_times, *args, **kwargs): """ @@ -534,8 +541,11 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): - Measures the difference between 'now' and 'times_agency.etd_berth'. """ # check, if the header is filled in (agency & terminal) - if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TERMINAL.value])]) != 2: - return (StatusFlags.GREEN, None) + if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1: + return self.get_no_violation_default_output() # rule not applicable + + if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1: + return self.get_no_violation_default_output() # rule not applicable # preparation: obtain the correct times of the participant, define the query time and the key time times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) @@ -550,8 +560,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) - + return self.get_no_violation_default_output() def validation_rule_fct_shipcall_incoming_participants_disagree_on_eta(self, shipcall, df_times, *args, **kwargs): """ @@ -574,7 +583,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.RED, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_shipcall_outgoing_participants_disagree_on_etd(self, shipcall, df_times, *args, **kwargs): """ @@ -597,7 +606,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.RED, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_shipcall_shifting_participants_disagree_on_eta_or_etd(self, shipcall, df_times, *args, **kwargs): """ @@ -634,7 +643,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.RED, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_eta_time_not_in_operation_window(self, shipcall, df_times, *args, **kwargs): """ @@ -646,15 +655,18 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): start_time & end_time: operations_start & operations_end (times_terminal) """ # check, if the header is filled in (agency & terminal) - if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TERMINAL.value])]) != 2: - return (StatusFlags.GREEN, None) + if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1: + return self.get_no_violation_default_output() # rule not applicable + + if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1: + return self.get_no_violation_default_output() # rule not applicable # get agency & terminal times times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value) if self.check_is_not_a_time_or_is_none(times_terminal.operations_start) or self.check_is_not_a_time_or_is_none(times_agency.eta_berth): - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # check, whether the start of operations is AFTER the estimated arrival time violation_state = times_terminal.operations_start < times_agency.eta_berth @@ -663,7 +675,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.RED, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_etd_time_not_in_operation_window(self, shipcall, df_times, *args, **kwargs): """ @@ -675,15 +687,18 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): start_time & end_time: operations_start & operations_end (times_terminal) """ # check, if the header is filled in (agency & terminal) - if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TERMINAL.value])]) != 2: - return (StatusFlags.GREEN, None) + if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1: + return self.get_no_violation_default_output() # rule not applicable + + if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1: + return self.get_no_violation_default_output() # rule not applicable # get agency & terminal times times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value) if self.check_is_not_a_time_or_is_none(times_terminal.operations_end) or self.check_is_not_a_time_or_is_none(times_agency.etd_berth): - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # check, whether the end of operations is AFTER the estimated departure time violation_state = times_terminal.operations_end > times_agency.etd_berth @@ -692,7 +707,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.RED, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_eta_time_not_in_tidal_window(self, shipcall, df_times, *args, **kwargs): """ @@ -705,12 +720,12 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): """ # check, if the header is filled in (agency) if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value])]) != 1: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) # requirements: tidal window (from & to) is filled in if self.check_is_not_a_time_or_is_none(shipcall.tidal_window_from) or self.check_is_not_a_time_or_is_none(shipcall.tidal_window_to) or self.check_is_not_a_time_or_is_none(times_agency.eta_berth): # 202310310: note: this should check times_agency, shouldn't it? - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # check, whether the query time is between start & end time # a violation is observed, when the time is NOT between start & end @@ -720,7 +735,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.RED, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_etd_time_not_in_tidal_window(self, shipcall, df_times, *args, **kwargs): """ @@ -733,12 +748,12 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): """ # check, if the header is filled in (agency) if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value])]) != 1: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) # requirements: tidal window (from & to) is filled in if self.check_is_not_a_time_or_is_none(shipcall.tidal_window_from) or self.check_is_not_a_time_or_is_none(shipcall.tidal_window_to) or self.check_is_not_a_time_or_is_none(times_agency.etd_berth): # 202310310: note: this should check times_agency, shouldn't it? - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # check, whether the query time is between start & end time # a violation is observed, when the time is NOT between start & end @@ -748,7 +763,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.RED, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_too_many_identical_eta_times(self, shipcall, df_times, rounding = "min", maximum_threshold = 3, all_times_agency=None, *args, **kwargs): """ @@ -759,7 +774,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): times_agency = df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value] # check, if the header is filled in (agency) if len(times_agency) != 1: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # when ANY of the unique values exceeds the threshold, a violation is observed query = "eta_berth" @@ -769,7 +784,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_too_many_identical_etd_times(self, shipcall, df_times, rounding = "min", maximum_threshold = 3, all_times_agency=None, *args, **kwargs): """ @@ -780,7 +795,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): times_agency = df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value] # check, if the header is filled in (agency) if len(times_agency) != 1: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # when ANY of the unique values exceeds the threshold, a violation is observed query = "etd_berth" @@ -790,7 +805,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_agency_and_terminal_berth_id_disagreement(self, shipcall, df_times, *args, **kwargs): """ @@ -799,22 +814,25 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): Description: This validation rule checks, whether agency and terminal agree with their designated berth place by checking berth_id. """ # check, if the header is filled in (agency & terminal) - if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TERMINAL.value])]) != 2: - return (StatusFlags.GREEN, None) + if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1: + return self.get_no_violation_default_output() # rule not applicable + + if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1: + return self.get_no_violation_default_output() # rule not applicable times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value) # when one of the two values is null, the state is GREEN if (times_agency.berth_id is None) or (times_terminal.berth_id is None): - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # when one of the two values is null, the state is GREEN if (pd.isnull(times_agency.berth_id)) or (pd.isnull(times_terminal.berth_id)): - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() if shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # only incoming shipcalls matter. The other ones are not relevant for the berth selection violation_state = times_agency.berth_id!=times_terminal.berth_id @@ -823,7 +841,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() def validation_rule_fct_agency_and_terminal_pier_side_disagreement(self, shipcall, df_times, *args, **kwargs): """ @@ -832,23 +850,26 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): Description: This validation rule checks, whether agency and terminal agree with their designated pier side by checking pier_side. """ # check, if the header is filled in (agency & terminal) - if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TERMINAL.value])]) != 2: - return (StatusFlags.GREEN, None) + if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1: + return self.get_no_violation_default_output() # rule not applicable + + if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1: + return self.get_no_violation_default_output() # rule not applicable times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value) # when one of the two values is null, the state is GREEN if (times_agency.pier_side is None) or (times_terminal.pier_side is None): - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # when one of the two values is null, the state is GREEN if (pd.isnull(times_agency.pier_side)) or (pd.isnull(times_terminal.pier_side)): - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() # only incoming shipcalls matter. The other ones are not relevant for the pier_side selection if shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() violation_state = bool(times_agency.pier_side)!=bool(times_terminal.pier_side) @@ -856,6 +877,6 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): validation_name = inspect.currentframe().f_code.co_name return (StatusFlags.YELLOW, validation_name) else: - return (StatusFlags.GREEN, None) + return self.get_no_violation_default_output() From 49bbb7762483c5dd53273890f1da86c061d6f6a7 Mon Sep 17 00:00:00 2001 From: scopesorting Date: Mon, 20 Nov 2023 16:35:31 +0100 Subject: [PATCH 4/7] refactoring a few methods --- .../validators/validation_rule_functions.py | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/server/BreCal/validators/validation_rule_functions.py b/src/server/BreCal/validators/validation_rule_functions.py index a8138ab..478a7cf 100644 --- a/src/server/BreCal/validators/validation_rule_functions.py +++ b/src/server/BreCal/validators/validation_rule_functions.py @@ -268,7 +268,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): - Measures the difference between 'now' and 'times_agency.eta_berth'. """ # check, if the header is filled in (agency & MOORING) - if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.MOORING.value])]) != 2: + if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.MOORING.value]) != 1): return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time @@ -298,7 +298,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): - Measures the difference between 'now' and 'times_agency.etd_berth'. """ # check, if the header is filled in (agency & MOORING) - if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.MOORING.value])]) != 2: + if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.MOORING.value]) != 1): return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time @@ -328,7 +328,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): - Measures the difference between 'now' and 'times_agency.eta_berth'. """ # check, if the header is filled in (agency & PORT_ADMINISTRATION) - if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.PORT_ADMINISTRATION.value])]) != 2: + if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.PORT_ADMINISTRATION.value]) != 1): return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time @@ -358,7 +358,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): - Measures the difference between 'now' and 'times_agency.etd_berth'. """ # check, if the header is filled in (agency & PORT_ADMINISTRATION) - if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.PORT_ADMINISTRATION.value])]) != 2: + if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.PORT_ADMINISTRATION.value]) != 1): return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time @@ -388,7 +388,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): - Measures the difference between 'now' and 'times_agency.eta_berth'. """ # check, if the header is filled in (agency & PILOT) - if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.PILOT.value])]) != 2: + if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.PILOT.value]) != 1): return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time @@ -418,7 +418,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): - Measures the difference between 'now' and 'times_agency.etd_berth'. """ # check, if the header is filled in (agency & PILOT) - if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.PILOT.value])]) != 2: + if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.PILOT.value]) != 1): return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time @@ -448,7 +448,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): - Measures the difference between 'now' and 'times_agency.eta_berth'. """ # check, if the header is filled in (agency & TUG) - if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TUG.value])]) != 2: + if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.TUG.value]) != 1): return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time @@ -478,7 +478,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): - Measures the difference between 'now' and 'times_agency.etd_berth'. """ # check, if the header is filled in (agency & TUG) - if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TUG.value])]) != 2: + if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.TUG.value]) != 1): return self.get_no_violation_default_output() # preparation: obtain the correct times of the participant, define the query time and the key time @@ -508,10 +508,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): - Measures the difference between 'now' and 'times_agency.eta_berth'. """ # check, if the header is filled in (agency & terminal) - if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1: - return self.get_no_violation_default_output() # rule not applicable - - if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1: + if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1): return self.get_no_violation_default_output() # rule not applicable # preparation: obtain the correct times of the participant, define the query time and the key time From a5220fd6f257a5018adfb6299d3ea84c3d23665e Mon Sep 17 00:00:00 2001 From: scopesorting Date: Mon, 20 Nov 2023 16:43:27 +0100 Subject: [PATCH 5/7] refactoring: simplification of error messages. These now stem from a string, which is the function name. Previously, the inspect module was used with a rather complex function call to obtain the method's name. The simplification makes code more readable for future work. --- .../validators/validation_rule_functions.py | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/server/BreCal/validators/validation_rule_functions.py b/src/server/BreCal/validators/validation_rule_functions.py index 478a7cf..9bb2e94 100644 --- a/src/server/BreCal/validators/validation_rule_functions.py +++ b/src/server/BreCal/validators/validation_rule_functions.py @@ -223,7 +223,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_missing_time_agency_berth_eta" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -251,7 +251,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_missing_time_agency_berth_etd" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -281,7 +281,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_missing_time_mooring_berth_eta" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -311,7 +311,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_missing_time_mooring_berth_etd" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -341,7 +341,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_missing_time_portadministration_berth_eta" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -371,7 +371,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_missing_time_portadministration_berth_etd" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -401,7 +401,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_missing_time_pilot_berth_eta" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -431,7 +431,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_missing_time_pilot_berth_etd" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -461,7 +461,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_missing_time_tug_berth_eta" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -491,7 +491,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_missing_time_tug_berth_etd" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -521,7 +521,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_missing_time_terminal_berth_eta" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -554,7 +554,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_missing_time_terminal_berth_etd" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -577,7 +577,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): ) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_shipcall_incoming_participants_disagree_on_eta" return (StatusFlags.RED, validation_name) else: return self.get_no_violation_default_output() @@ -600,7 +600,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): ) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_shipcall_outgoing_participants_disagree_on_etd" return (StatusFlags.RED, validation_name) else: return self.get_no_violation_default_output() @@ -637,7 +637,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = (violation_state_eta) or (violation_state_etd) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_shipcall_shifting_participants_disagree_on_eta_or_etd" return (StatusFlags.RED, validation_name) else: return self.get_no_violation_default_output() @@ -669,7 +669,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = times_terminal.operations_start < times_agency.eta_berth if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_eta_time_not_in_operation_window" return (StatusFlags.RED, validation_name) else: return self.get_no_violation_default_output() @@ -701,7 +701,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = times_terminal.operations_end > times_agency.etd_berth if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_etd_time_not_in_operation_window" return (StatusFlags.RED, validation_name) else: return self.get_no_violation_default_output() @@ -729,7 +729,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = not self.time_logic.time_inbetween(query_time=times_agency.eta_berth, start_time=shipcall.tidal_window_from, end_time=shipcall.tidal_window_to) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_eta_time_not_in_tidal_window" return (StatusFlags.RED, validation_name) else: return self.get_no_violation_default_output() @@ -757,7 +757,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = not self.time_logic.time_inbetween(query_time=times_agency.etd_berth, start_time=shipcall.tidal_window_from, end_time=shipcall.tidal_window_to) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_etd_time_not_in_tidal_window" return (StatusFlags.RED, validation_name) else: return self.get_no_violation_default_output() @@ -778,7 +778,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = self.check_unique_shipcall_counts(query, times_agency=times_agency, rounding=rounding, maximum_threshold=maximum_threshold, all_times_agency=all_times_agency) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_too_many_identical_eta_times" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -799,7 +799,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = self.check_unique_shipcall_counts(query, times_agency=times_agency, rounding=rounding, maximum_threshold=maximum_threshold, all_times_agency=all_times_agency) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_too_many_identical_etd_times" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -835,7 +835,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = times_agency.berth_id!=times_terminal.berth_id if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_agency_and_terminal_berth_id_disagreement" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() @@ -871,7 +871,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): violation_state = bool(times_agency.pier_side)!=bool(times_terminal.pier_side) if violation_state: - validation_name = inspect.currentframe().f_code.co_name + validation_name = "validation_rule_fct_agency_and_terminal_pier_side_disagreement" return (StatusFlags.YELLOW, validation_name) else: return self.get_no_violation_default_output() From 3cc1591aba108e539988d184b55faaeee35bfc43 Mon Sep 17 00:00:00 2001 From: scopesorting Date: Tue, 21 Nov 2023 11:41:56 +0100 Subject: [PATCH 6/7] potentially correcting 0006A/0006B --- src/server/BreCal/database/sql_handler.py | 16 ++++++++++++---- .../validators/validation_rule_functions.py | 8 ++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/server/BreCal/database/sql_handler.py b/src/server/BreCal/database/sql_handler.py index 3ecd895..f715b4b 100644 --- a/src/server/BreCal/database/sql_handler.py +++ b/src/server/BreCal/database/sql_handler.py @@ -159,7 +159,10 @@ class SQLHandler(): return all_data def df_loc_to_data_model(self, df, id, model_str, loc_type:str="loc"): - assert len(df)>0, f"empty dataframe" + if not len(df)>0: + import warnings + warnings.warn(f"empty dataframe in SQLHandler.df_loc_to_data_model for model type: {model_str}\n") + return df # get a pandas series from the dataframe series = df.loc[id] if loc_type=="loc" else df.iloc[id] @@ -177,7 +180,12 @@ class SQLHandler(): def get_times_for_participant_type(self, df_times, participant_type:int): filtered_series = df_times.loc[df_times["participant_type"]==participant_type] - assert len(filtered_series)<=1, f"found multiple results in function SQLHandler.get_times_for_participant_type" + if not len(filtered_series)<=1: + # correcting the error: ERROR:root:found multiple results + # however, a warning will still be issued + import warnings + warnings.warn(f"found multiple results in function SQLHandler.get_times_for_participant_type\nConsidering only the first match!\nAffected Times Indexes: {filtered_series.index}") + times = self.df_loc_to_data_model(filtered_series, id=0, model_str='times', loc_type="iloc") # use iloc! to retrieve the first result return times @@ -240,8 +248,8 @@ class SQLHandler(): """given a dataframe of all agency times, get all unique ship counts, their values (datetime) and the string tags. returns a tuple (values,unique,counts)""" # optional: rounding if rounding is not None: - all_df_times.loc[:, query] = all_df_times.loc[:, query].dt.round(rounding) # e.g., 'min' - query_time_agency = times_agency[query].iloc[0].round(rounding)# e.g., 'min' + all_df_times.loc[:, query] = pd.to_datetime(all_df_times.loc[:, query]).dt.round(rounding) # e.g., 'min' --- # correcting the error: 'AttributeError: Can only use .dt accessor with datetimelike values' + query_time_agency = pd.to_datetime(times_agency[query]).iloc[0].round(rounding)# e.g., 'min' # after rounding, filter {all_df_times}, so only those, which match the current query are of interest # takes 'times_agency' to sample, which value should match diff --git a/src/server/BreCal/validators/validation_rule_functions.py b/src/server/BreCal/validators/validation_rule_functions.py index 9bb2e94..e1c59ff 100644 --- a/src/server/BreCal/validators/validation_rule_functions.py +++ b/src/server/BreCal/validators/validation_rule_functions.py @@ -811,10 +811,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): Description: This validation rule checks, whether agency and terminal agree with their designated berth place by checking berth_id. """ # check, if the header is filled in (agency & terminal) - if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1: + if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) == 0: return self.get_no_violation_default_output() # rule not applicable - if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1: + if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) == 0: return self.get_no_violation_default_output() # rule not applicable times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) @@ -847,10 +847,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): Description: This validation rule checks, whether agency and terminal agree with their designated pier side by checking pier_side. """ # check, if the header is filled in (agency & terminal) - if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1: + if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) == 0: return self.get_no_violation_default_output() # rule not applicable - if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1: + if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) == 0: return self.get_no_violation_default_output() # rule not applicable times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value) From 9346920a97a9954c0893e015c751fec87900f8b6 Mon Sep 17 00:00:00 2001 From: scopesorting Date: Tue, 21 Nov 2023 11:51:49 +0100 Subject: [PATCH 7/7] potentially solving the 'shipcall_id' error log --- src/server/BreCal/database/sql_handler.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/server/BreCal/database/sql_handler.py b/src/server/BreCal/database/sql_handler.py index f715b4b..f34f345 100644 --- a/src/server/BreCal/database/sql_handler.py +++ b/src/server/BreCal/database/sql_handler.py @@ -207,7 +207,8 @@ class SQLHandler(): returns: participant_id_list, where every element is an int """ df = self.df_dict.get("shipcall_participant_map") - df = df.set_index('shipcall_id', inplace=False) + if 'shipcall_id' in list(df.columns): + df = df.set_index('shipcall_id', inplace=False) # the 'if' call is needed to ensure, that no Exception is raised, when the shipcall_id is not present in the df participant_id_list = df.loc[shipcall_id, "participant_id"].tolist() if shipcall_id in list(df.index) else []