bugfix of 0004A and B, where the tide window may have deviated by few seconds, so the wrong state would be concluded.

This commit is contained in:
scopesorting 2023-12-07 11:54:37 +01:00
parent c0a9557584
commit 82309a53d6
3 changed files with 60 additions and 2 deletions

View File

@ -2,6 +2,15 @@ import datetime
import numpy as np import numpy as np
import pandas as pd import pandas as pd
def validate_time_exceeds_threshold(value:datetime.datetime, seconds:int=60, minutes:int=60, hours:int=24, days:int=30, months:int=12)->bool:
"""returns a boolean when the input value is very distant in the future. The parameters provide the threshold"""
# time difference in seconds. Positive: in the future, Negative: in the past
current_time = datetime.datetime.now()
time_ = (value-current_time).total_seconds()
threshold = seconds*minutes*hours*days*months
print(time_, threshold)
return time_>=threshold
class TimeLogic(): class TimeLogic():
def __init__(self): def __init__(self):
return return
@ -41,10 +50,11 @@ class TimeLogic():
def time_inbetween(self, query_time:datetime.datetime, start_time:datetime.datetime, end_time:datetime.datetime) -> bool: def time_inbetween(self, query_time:datetime.datetime, start_time:datetime.datetime, end_time:datetime.datetime) -> bool:
""" """
checks, whether the query time is inbetween the start & end time. Returns a bool to indicate that. checks, whether the query time is inbetween the start & end time. Returns a bool to indicate that.
The function internally rounds seconds and microseconds to zero, so they are ignored in the evaluation.
Example: Example:
a = datetime.datetime(2017, 5, 16, 8, 21, 10) a = datetime.datetime(2017, 5, 16, 8, 21, 10)
b = datetime.datetime(2017, 5, 17, 8, 21, 10) b = datetime.datetime(2017, 5, 17, 8, 21, 09)
c = datetime.datetime(2017, 5, 18, 8, 21, 10) c = datetime.datetime(2017, 5, 18, 8, 21, 10)
is b between a and c? -> yes. Returns True is b between a and c? -> yes. Returns True
@ -55,7 +65,12 @@ class TimeLogic():
assert isinstance(query_time, datetime.datetime) assert isinstance(query_time, datetime.datetime)
assert isinstance(start_time, datetime.datetime) assert isinstance(start_time, datetime.datetime)
assert isinstance(end_time, datetime.datetime) assert isinstance(end_time, datetime.datetime)
"""
query_time = query_time.replace(second=0, microsecond=0)
start_time = start_time.replace(second=0, microsecond=0)
end_time = end_time.replace(second=0, microsecond=0)"""
print("time_inbetween function! UNVIOLATED?", start_time <= query_time <= end_time, start_time, query_time, end_time)
return start_time <= query_time <= end_time return start_time <= query_time <= end_time
def time_inbetween_absolute_delta(self, query_time:datetime.datetime, start_time:datetime.datetime, end_time:datetime.datetime) -> tuple: def time_inbetween_absolute_delta(self, query_time:datetime.datetime, start_time:datetime.datetime, end_time:datetime.datetime) -> tuple:

View File

@ -3,6 +3,7 @@ import types
from BreCal.database.enums import ParticipantType, ShipcallType, ParticipantwiseTimeDelta from BreCal.database.enums import ParticipantType, ShipcallType, ParticipantwiseTimeDelta
import numpy as np import numpy as np
import pandas as pd import pandas as pd
import datetime
from BreCal.validators.time_logic import TimeLogic from BreCal.validators.time_logic import TimeLogic
from BreCal.database.enums import StatusFlags from BreCal.database.enums import StatusFlags
#from BreCal.validators.schema_validation import validation_state_and_validation_name #from BreCal.validators.schema_validation import validation_state_and_validation_name
@ -713,7 +714,12 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
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): 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 self.get_no_violation_default_output() return self.get_no_violation_default_output()
# check, whether the start of operations is AFTER the estimated arrival time # check, whether the end of operations is BEFORE the estimated arrival time
if isinstance(times_terminal.operations_start, (pd.Timestamp, datetime.datetime)):
times_terminal.operations_start = times_terminal.operations_start.replace(second=0, microsecond=0)
if isinstance(times_agency.eta_berth, (pd.Timestamp, datetime.datetime)):
times_agency.eta_berth = times_agency.eta_berth.replace(second=0, microsecond=0)
violation_state = times_terminal.operations_start < times_agency.eta_berth violation_state = times_terminal.operations_start < times_agency.eta_berth
if violation_state: if violation_state:
@ -749,6 +755,11 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
return self.get_no_violation_default_output() return self.get_no_violation_default_output()
# check, whether the end of operations is AFTER the estimated departure time # check, whether the end of operations is AFTER the estimated departure time
if isinstance(times_terminal.operations_end, (pd.Timestamp, datetime.datetime)):
times_terminal.operations_end = times_terminal.operations_end.replace(second=0, microsecond=0)
if isinstance(times_agency.etd_berth, (pd.Timestamp, datetime.datetime)):
times_agency.etd_berth = times_agency.etd_berth.replace(second=0, microsecond=0)
violation_state = times_terminal.operations_end > times_agency.etd_berth violation_state = times_terminal.operations_end > times_agency.etd_berth
if violation_state: if violation_state:

View File

@ -1062,6 +1062,38 @@ def test_validation_rule_fct_etd_time_not_in_tidal_window__etd_outside_tidal_win
assert code==StatusFlags.RED, f"state should be 'red', etd_berth takes place after the tidal window" assert code==StatusFlags.RED, f"state should be 'red', etd_berth takes place after the tidal window"
return return
def test_validation_rule_fct_tidal_window_is_precisely_eta_or_etd__is_okay(build_sql_proxy_connection):
"""0004-A & 0004-B eta/etd is exactly tidal window: no violation"""
vr = build_sql_proxy_connection['vr']
shipcall = get_shipcall_simple()
df_times = get_df_times(shipcall)
times_agency = vr.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
# tidal window: [t0 +1min, t0 +1hr)
# etd berth:
t0_time = datetime.datetime.now()
times_agency.eta_berth = t0_time
shipcall.tidal_window_from = t0_time
shipcall.tidal_window_to = t0_time+datetime.timedelta(minutes=3)
violation_state = not vr.time_logic.time_inbetween(
query_time=times_agency.eta_berth, start_time=shipcall.tidal_window_from, end_time=shipcall.tidal_window_to
)
assert violation_state==False
t0_time = datetime.datetime.now()
times_agency.etd_berth = t0_time
shipcall.tidal_window_from = t0_time+datetime.timedelta(minutes=-3)
shipcall.tidal_window_to = t0_time
violation_state = not vr.time_logic.time_inbetween(
query_time=times_agency.etd_berth, start_time=shipcall.tidal_window_from, end_time=shipcall.tidal_window_to
)
assert violation_state==False
return
def test_validation_rule_fct_too_many_identical_eta_times__is_violated_by_too_many_identical_times(build_sql_proxy_connection): def test_validation_rule_fct_too_many_identical_eta_times__is_violated_by_too_many_identical_times(build_sql_proxy_connection):
"""0005-A validation_rule_fct_too_many_identical_eta_times""" """0005-A validation_rule_fct_too_many_identical_eta_times"""
vr = build_sql_proxy_connection['vr'] vr = build_sql_proxy_connection['vr']