frontend
This commit is contained in:
+61
-15
@@ -136,25 +136,37 @@ def compile_schedule(
|
||||
ref_active_priority: dict[TestKey, int] = dict(_ACTIVE_REF)
|
||||
entries: list[ScheduleEntry] = []
|
||||
|
||||
current_date = _parse_date(start_date)
|
||||
window_start_date = _parse_date(start_date)
|
||||
current_date = window_start_date
|
||||
last_date: str | None = None
|
||||
daytime_shift2_window_pending = daytime_testing_today
|
||||
|
||||
while dut_active_priority or ref_active_priority:
|
||||
is_special_daytime_shift2_window = (
|
||||
daytime_shift2_window_pending
|
||||
and current_date == window_start_date
|
||||
and current_date.weekday() < 5
|
||||
and current_date.isoformat() not in holiday_dates
|
||||
)
|
||||
|
||||
# Get the shift sequence for current date (respects Mon/Fri/weekend rules)
|
||||
shift_sequence = _get_shift_sequence(current_date, holiday_dates)
|
||||
shift_sequence = _get_shift_sequence(
|
||||
current_date,
|
||||
holiday_dates,
|
||||
daytime_shift2_only=is_special_daytime_shift2_window,
|
||||
)
|
||||
|
||||
if not shift_sequence:
|
||||
break # No valid shift sequence
|
||||
|
||||
dut_active_test_ids: set[TestKey] = set(dut_active_priority.keys())
|
||||
ref_active_test_ids: set[TestKey] = set(ref_active_priority.keys())
|
||||
bundles = _create_bundles(dut_active_test_ids, ref_active_test_ids, _TESTS_BY_ID)
|
||||
bundles = _create_bundles(dut_active_test_ids, ref_active_test_ids, _TESTS_BY_ID, top_priority_tests)
|
||||
shift_capacities = {
|
||||
(date_obj, shift_idx): _shift_capacity_for_date(
|
||||
current_date=date_obj,
|
||||
holiday_dates=holiday_dates,
|
||||
start_date_override=start_date,
|
||||
daytime_testing_today=daytime_testing_today,
|
||||
daytime_shift2_only=is_special_daytime_shift2_window and date_obj == current_date,
|
||||
).get(shift_idx, 0)
|
||||
for date_obj, shift_idx in shift_sequence
|
||||
}
|
||||
@@ -173,6 +185,9 @@ def compile_schedule(
|
||||
if placed_last_date is not None:
|
||||
last_date = placed_last_date
|
||||
|
||||
# Daytime testing special handling applies only to the first scheduling window.
|
||||
daytime_shift2_window_pending = False
|
||||
|
||||
# Move to next scheduling window start date
|
||||
# After shift 1 (1am-9am), there's shift 2 if daytime testing, then shift 3 (5pm)
|
||||
# After shift 3 (5pm), shift 1 is next day (1am)
|
||||
@@ -347,6 +362,7 @@ def _create_bundles(
|
||||
dut_active_test_ids: set[TestKey],
|
||||
ref_active_test_ids: set[TestKey],
|
||||
tests: dict[TestKey, SchedulerTest],
|
||||
top_priority_tests: set[str] | None = None,
|
||||
) -> list[TestBundle]:
|
||||
"""Create bundles of tests that must run together, sorted by priority tier and efficiency.
|
||||
|
||||
@@ -358,6 +374,9 @@ def _create_bundles(
|
||||
|
||||
Returned list is sorted by (priority_tier, total_minutes) to place small/high-priority bundles first.
|
||||
"""
|
||||
if top_priority_tests is None:
|
||||
top_priority_tests = set()
|
||||
|
||||
bundles: list[TestBundle] = []
|
||||
processed: set[TestKey] = set()
|
||||
|
||||
@@ -393,7 +412,12 @@ def _create_bundles(
|
||||
if not bundle_test_ids:
|
||||
continue
|
||||
processed.update(bundle_test_ids)
|
||||
priority_tier = BUNDLE_PRIORITY_P2P_WITH_COE
|
||||
# Check if any test in bundle is top priority
|
||||
bundle_test_ids_only = {key[0] for key in bundle_test_ids}
|
||||
if bundle_test_ids_only & top_priority_tests:
|
||||
priority_tier = BUNDLE_PRIORITY_FAILED # Highest priority (0)
|
||||
else:
|
||||
priority_tier = BUNDLE_PRIORITY_P2P_WITH_COE
|
||||
bundles.append(TestBundle(
|
||||
test_ids=bundle_test_ids,
|
||||
priority_tier=priority_tier,
|
||||
@@ -415,7 +439,12 @@ def _create_bundles(
|
||||
if not bundle_test_ids:
|
||||
continue
|
||||
processed.update(bundle_test_ids)
|
||||
priority_tier = BUNDLE_PRIORITY_P2P_ONLY
|
||||
# Check if any test in bundle is top priority
|
||||
bundle_test_ids_only = {key[0] for key in bundle_test_ids}
|
||||
if bundle_test_ids_only & top_priority_tests:
|
||||
priority_tier = BUNDLE_PRIORITY_FAILED # Highest priority (0)
|
||||
else:
|
||||
priority_tier = BUNDLE_PRIORITY_P2P_ONLY
|
||||
bundles.append(TestBundle(
|
||||
test_ids=bundle_test_ids,
|
||||
priority_tier=priority_tier,
|
||||
@@ -425,7 +454,12 @@ def _create_bundles(
|
||||
bundle_test_ids = [key for key in (_active_key(test_id, DUT), _active_key(test_id, REF)) if key is not None and key not in processed]
|
||||
if not bundle_test_ids:
|
||||
continue
|
||||
priority_tier = BUNDLE_PRIORITY_P3P
|
||||
# Check if any test in bundle is top priority
|
||||
bundle_test_ids_only = {key[0] for key in bundle_test_ids}
|
||||
if bundle_test_ids_only & top_priority_tests:
|
||||
priority_tier = BUNDLE_PRIORITY_FAILED # Highest priority (0)
|
||||
else:
|
||||
priority_tier = BUNDLE_PRIORITY_P3P
|
||||
bundles.append(TestBundle(
|
||||
test_ids=bundle_test_ids,
|
||||
priority_tier=priority_tier,
|
||||
@@ -439,8 +473,12 @@ def _create_bundles(
|
||||
if key in processed:
|
||||
continue
|
||||
test = tests[key]
|
||||
priority_tier = BUNDLE_PRIORITY_COE_ONLY
|
||||
bundle_test_ids = [key]
|
||||
# Check if this test is top priority
|
||||
if key[0] in top_priority_tests:
|
||||
priority_tier = BUNDLE_PRIORITY_FAILED # Highest priority (0)
|
||||
else:
|
||||
priority_tier = BUNDLE_PRIORITY_COE_ONLY
|
||||
bundles.append(TestBundle(
|
||||
test_ids=bundle_test_ids,
|
||||
priority_tier=priority_tier,
|
||||
@@ -466,8 +504,7 @@ def _rx_tx_pair_id(test_id: str, active: set[str]) -> str | None:
|
||||
def _shift_capacity_for_date(
|
||||
current_date: date,
|
||||
holiday_dates: set[str],
|
||||
start_date_override: str | None,
|
||||
daytime_testing_today: bool,
|
||||
daytime_shift2_only: bool,
|
||||
) -> dict[int, int]:
|
||||
iso = current_date.isoformat()
|
||||
if iso in holiday_dates:
|
||||
@@ -477,8 +514,8 @@ def _shift_capacity_for_date(
|
||||
if is_weekend:
|
||||
return {1: 480, 2: 480, 3: 480}
|
||||
|
||||
if start_date_override and iso == _parse_date(start_date_override).isoformat() and daytime_testing_today:
|
||||
return {1: 480, 2: 480, 3: 480}
|
||||
if daytime_shift2_only:
|
||||
return {1: 0, 2: 480, 3: 0}
|
||||
|
||||
return {1: 600, 2: 0, 3: 420}
|
||||
|
||||
@@ -489,15 +526,20 @@ def _parse_date(value: str | None) -> date:
|
||||
return datetime.strptime(value, "%Y-%m-%d").date()
|
||||
|
||||
|
||||
def _get_shift_sequence(start_date: date, holiday_dates: set[str]) -> list[tuple[date, int]]:
|
||||
def _get_shift_sequence(
|
||||
start_date: date,
|
||||
holiday_dates: set[str],
|
||||
daytime_shift2_only: bool = False,
|
||||
) -> list[tuple[date, int]]:
|
||||
"""Generate the sequence of (date, shift_index) tuples for a scheduling window.
|
||||
|
||||
Rules per design:
|
||||
- Daytime testing first window (weekday only): [2] (shift 2 today only)
|
||||
- Monday-Thursday: [3, 1] (shift 3 today, shift 1 next day) = 16 hours
|
||||
- Friday: [3, 1, 2, 3, 1, 2, 3, 1] (Fri-Mon) = 24 hours continuous
|
||||
- Saturday/Sunday/Holiday weekday: all 3 shifts
|
||||
|
||||
Always starts on shift 3 for weekdays.
|
||||
Weekday default starts on shift 3 unless daytime testing shift-2-only is enabled.
|
||||
Returns ordered list of (date, shift_index) pairs.
|
||||
"""
|
||||
iso = start_date.isoformat()
|
||||
@@ -505,6 +547,10 @@ def _get_shift_sequence(start_date: date, holiday_dates: set[str]) -> list[tuple
|
||||
weekday = start_date.weekday() # 0=Mon, 4=Fri, 5=Sat, 6=Sun
|
||||
|
||||
shifts: list[tuple[date, int]] = []
|
||||
|
||||
if daytime_shift2_only and weekday < 5 and not is_holiday:
|
||||
shifts.append((start_date, 2))
|
||||
return shifts
|
||||
|
||||
# If holiday on a weekday, treat as weekend (all 3 shifts)
|
||||
if is_holiday and weekday < 5:
|
||||
|
||||
Reference in New Issue
Block a user