From d1f470310241ad1a29ed0aa331302dbdef576edb Mon Sep 17 00:00:00 2001 From: scopesorting Date: Wed, 25 Oct 2023 14:20:24 +0200 Subject: [PATCH] updating rules 0002 A-C (check_participants_agree_on_estimated_time) and 0004 B (typo in function) --- .../validators/validation_rule_functions.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/server/BreCal/validators/validation_rule_functions.py b/src/server/BreCal/validators/validation_rule_functions.py index 4cb9a5e..81f53f3 100644 --- a/src/server/BreCal/validators/validation_rule_functions.py +++ b/src/server/BreCal/validators/validation_rule_functions.py @@ -62,6 +62,8 @@ class ValidationRuleBaseFunctions(): Instead of comparing each individual result, this function counts the amount of unique instances. When there is not only one unique value, there are deviating time estimates, and a violation occurs + To reduce the potential of false violations, the agreement is rounded (e.g., by minute). + returns: violation_state (bool) """ # shipcall type filter: consider only shipcalls, where the type matches @@ -73,19 +75,23 @@ class ValidationRuleBaseFunctions(): participant_types = [ParticipantType.AGENCY.value, ParticipantType.MOORING.value, ParticipantType.PORT_ADMINISTRATION.value, ParticipantType.PILOT.value, ParticipantType.TUG.value] df_times = df_times.loc[df_times["participant_type"].isin(participant_types),:] - # exclude missing entries - df_times.loc[~df_times[query].isnull(),:] + # exclude missing entries and consider only pd.Timestamp entries (which ignores pd.NaT/null entries) + estimated_times = [type(time_) for time_ in df_times.loc[:,query].tolist() if isinstance(time_, pd.Timestamp)] # df_times = df_times.loc[~df_times[query].isnull(),:] + + # apply rounding. For example, the agreement of different participants may be required to match minute-wise + # '15min' rounds to 'every 15 minutes'. E.g., '2023-09-22 08:18:49' becomes '2023-09-22 08:15:00' + estimated_times = [time_.round("15min") for time_ in estimated_times] # when there are no entries left (no entries are provided), skip - if len(df_times)==0: + if len(estimated_times)==0: violation_state = False return violation_state # there should only be one eta_berth, when all participants have provided the same time # this equates to the same criteria as checking, whether # times_agency.eta_berth==times_mooring.eta_berth==times_portadministration.eta_berth==times_pilot.eta_berth==times_tug.eta_berth - unique_times = len(pd.unique(df_times.loc[:,query])) - violation_state = unique_times!=1 + n_unique_times = len(np.unique(estimated_times)) + violation_state = n_unique_times!=1 return violation_state def check_unique_shipcall_counts(self, query:str, rounding="min", maximum_threshold=3)->bool: @@ -673,7 +679,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions): 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 (shipcall.tidal_window_from is pd.NaT) or (shipcall.tidal_window_to is pd.NaT) or (df_times.eta_berth is pd.NaT): + if (shipcall.tidal_window_from is pd.NaT) or (shipcall.tidal_window_to is pd.NaT) or (df_times.etd_berth is pd.NaT): return (StatusFlags.GREEN, None) # check, whether the query time is between start & end time