changing the ParticipantType to an IntFlag, so multiple roles are possible. Adapting every validation rule (0001, 0003, 0004, 0005), which may be affected by this change. Changing the filter for a participant type to properly include the change. Changing the pier_side rule (0006B), which uses the shipcall and times_terminal. New shipcalls should now be evaluated properly, unless no participant is assigned at all. If the ladder case can occur, the validation rules 0001N+0001O will be added (held back for now).
This commit is contained in:
parent
8e9be1eae5
commit
dc79f05b8b
@ -1,6 +1,6 @@
|
||||
from enum import Enum
|
||||
from enum import Enum, IntFlag
|
||||
|
||||
class ParticipantType(Enum):
|
||||
class ParticipantType(IntFlag):
|
||||
"""determines the type of a participant"""
|
||||
NONE = 0
|
||||
BSMD = 1
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import datetime
|
||||
import typing
|
||||
from BreCal.schemas.model import Shipcall, Ship, Participant, Berth, User, Times
|
||||
from BreCal.database.enums import ParticipantType
|
||||
|
||||
@ -110,7 +111,8 @@ class SQLHandler():
|
||||
self.initialize_shipcall_participant_list()
|
||||
|
||||
# update the 'type' in shipcall_participants_map
|
||||
self.add_participant_type_to_map()
|
||||
# fully deprecated
|
||||
# self.add_participant_type_to_map()
|
||||
return
|
||||
|
||||
def build_full_mysql_df_dict(self, all_schemas):
|
||||
@ -143,11 +145,12 @@ class SQLHandler():
|
||||
applies a lambda function, where the 'type'-column in the shipcall_participant_map is updated by reading the
|
||||
respective data from the participants. Updates the shipcall_participant_map inplace.
|
||||
"""
|
||||
spm = self.df_dict["shipcall_participant_map"]
|
||||
participant_df = self.df_dict["participant"]
|
||||
raise Exception("deprecated! Overwriting the shipcall_participant_map may cause harm, as a participant with multi-flag might be wrongfully assigned to multiple roles simultaneously.")
|
||||
#spm = self.df_dict["shipcall_participant_map"]
|
||||
#participant_df = self.df_dict["participant"]
|
||||
|
||||
spm.loc[:,"type"] = spm.loc[:].apply(lambda x: set_participant_type(x, participant_df=participant_df),axis=1)
|
||||
self.df_dict["shipcall_participant_map"] = spm
|
||||
#spm.loc[:,"type"] = spm.loc[:].apply(lambda x: set_participant_type(x, participant_df=participant_df),axis=1)
|
||||
#self.df_dict["shipcall_participant_map"] = spm
|
||||
return
|
||||
|
||||
def get_assigned_participants(self, shipcall)->pd.DataFrame:
|
||||
@ -159,7 +162,11 @@ class SQLHandler():
|
||||
|
||||
def get_assigned_participants_by_type(self, assigned_participants:pd.DataFrame, participant_type:ParticipantType):
|
||||
"""filters a dataframe of assigned_participants by the provided type enumerator"""
|
||||
assigned_participants_of_type = assigned_participants.loc[assigned_participants["type"]==participant_type.value]
|
||||
if isinstance(participant_type,int):
|
||||
participant_type = ParticipantType(participant_type)
|
||||
|
||||
assigned_participants_of_type = assigned_participants.loc[[participant_type in ParticipantType(int(pt_)) for pt_ in list(assigned_participants["type"].values)]]
|
||||
#assigned_participants_of_type = assigned_participants.loc[assigned_participants["type"]==participant_type.value]
|
||||
return assigned_participants_of_type
|
||||
|
||||
def check_if_any_participant_of_type_is_unassigned(self, shipcall, *args:list[ParticipantType])->bool:
|
||||
@ -234,8 +241,25 @@ class SQLHandler():
|
||||
data = data_model(**data)
|
||||
return data
|
||||
|
||||
def filter_df_by_participant_type(self, df, participant_type:typing.Union[int, ParticipantType])->pd.DataFrame:
|
||||
"""
|
||||
As ParticipantTypes are Flag objects, a dataframe's integer might resemble multiple participant types simultaneously.
|
||||
This function allows for more complex filters, as the IntFlag allows more complex queries
|
||||
|
||||
e.g.:
|
||||
ParticipantType(6) is 2,4 (2+4 = 6)
|
||||
|
||||
Participant(2) in Participant(6) = True # 6 is both, 2 and 4
|
||||
Participant(1) in Participant(6) = False # 6 is both, 2 and 4, but not 1
|
||||
"""
|
||||
if isinstance(participant_type,int):
|
||||
participant_type = ParticipantType(participant_type)
|
||||
filtered_df = df.loc[[participant_type in ParticipantType(df_pt) for df_pt in list(df["participant_type"].values)]]
|
||||
return filtered_df
|
||||
|
||||
def get_times_for_participant_type(self, df_times, participant_type:int):
|
||||
filtered_series = df_times.loc[df_times["participant_type"]==participant_type]
|
||||
filtered_series = self.filter_df_by_participant_type(df_times, participant_type)
|
||||
#filtered_series = df_times.loc[df_times["participant_type"]==participant_type]
|
||||
|
||||
if len(filtered_series)==0:
|
||||
return None
|
||||
@ -299,7 +323,8 @@ class SQLHandler():
|
||||
df_times = df_times.loc[~df_times[non_null_column].isnull()] # NOT null filter
|
||||
|
||||
# filter by the agency participant_type
|
||||
times_agency = df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]
|
||||
times_agency = self.filter_df_by_participant_type(df_times, ParticipantType.AGENCY.value)
|
||||
#times_agency = df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]
|
||||
return times_agency
|
||||
|
||||
def filter_df_by_key_value(self, df, key, value)->pd.DataFrame:
|
||||
|
||||
@ -866,18 +866,18 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
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):
|
||||
if (shipcall.pier_side is None) or (times_terminal.pier_side is 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)):
|
||||
if (pd.isnull(shipcall.pier_side)) or (pd.isnull(times_terminal.pier_side)):
|
||||
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 self.get_no_violation_default_output()
|
||||
|
||||
violation_state = bool(times_agency.pier_side)!=bool(times_terminal.pier_side)
|
||||
violation_state = bool(shipcall.pier_side)!=bool(times_terminal.pier_side)
|
||||
|
||||
if violation_state:
|
||||
validation_name = "validation_rule_fct_agency_and_terminal_pier_side_disagreement"
|
||||
|
||||
@ -34,6 +34,10 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
if len(df_times)==0:
|
||||
return (StatusFlags.GREEN.value, [])
|
||||
|
||||
spm = self.sql_handler.df_dict["shipcall_participant_map"]
|
||||
if len(spm.loc[spm["shipcall_id"]==shipcall.id])==0:
|
||||
return (StatusFlags.GREEN.value, [])
|
||||
|
||||
# filter by shipcall id
|
||||
df_times = self.sql_handler.get_times_of_shipcall(shipcall)
|
||||
|
||||
|
||||
@ -1114,7 +1114,8 @@ def test_validation_rule_fct_agency_and_terminal_pier_side_disagreement__agency_
|
||||
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
|
||||
shipcall.pier_side = True
|
||||
# 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"] = True
|
||||
|
||||
(code, msg) = vr.validation_rule_fct_agency_and_terminal_pier_side_disagreement(shipcall=shipcall, df_times=df_times)
|
||||
@ -1126,7 +1127,8 @@ def test_validation_rule_fct_agency_and_terminal_pier_side_disagreement__agency_
|
||||
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
|
||||
shipcall.pier_side = True
|
||||
#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"] = False
|
||||
|
||||
(code, msg) = vr.validation_rule_fct_agency_and_terminal_pier_side_disagreement(shipcall=shipcall, df_times=df_times)
|
||||
@ -1138,7 +1140,8 @@ def test_validation_rule_fct_agency_and_terminal_pier_side_disagreement__agency_
|
||||
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
|
||||
shipcall.pier_side = True
|
||||
# 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)
|
||||
@ -1178,7 +1181,8 @@ def test_validation_rule_fct_agency_and_terminal_pier_side_agreement(build_sql_p
|
||||
t2.participant_type = ParticipantType.TERMINAL.value
|
||||
|
||||
# agreement
|
||||
t1.pier_side = True
|
||||
shipcall.pier_side = True
|
||||
# t1.pier_side = True
|
||||
t2.pier_side = True
|
||||
|
||||
time_objects = [t1, t2]
|
||||
@ -1209,7 +1213,8 @@ def test_validation_rule_fct_agency_and_terminal_pier_side_disagreement(build_sq
|
||||
t2.participant_type = ParticipantType.TERMINAL.value
|
||||
|
||||
# disagreement
|
||||
t1.pier_side = True
|
||||
shipcall.pier_side = True
|
||||
# t1.pier_side = True
|
||||
t2.pier_side = False
|
||||
|
||||
time_objects = [t1, t2]
|
||||
|
||||
Reference in New Issue
Block a user