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 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():
def __init__(self):
return
@ -41,10 +50,11 @@ class TimeLogic():
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.
The function internally rounds seconds and microseconds to zero, so they are ignored in the evaluation.
Example:
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)
is b between a and c? -> yes. Returns True
@ -55,7 +65,12 @@ class TimeLogic():
assert isinstance(query_time, datetime.datetime)
assert isinstance(start_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
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
import numpy as np
import pandas as pd
import datetime
from BreCal.validators.time_logic import TimeLogic
from BreCal.database.enums import StatusFlags
#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):
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
if violation_state:
@ -749,6 +755,11 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
return self.get_no_violation_default_output()
# 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
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"
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):
"""0005-A validation_rule_fct_too_many_identical_eta_times"""
vr = build_sql_proxy_connection['vr']