# Scheduler
A test scheduler for the NJTH which compiles a best schedule according to the rules and priority of the tests. Moniters the test results and if there is failed or invalid tests, it calculates estimated time for rerun and reschedules the tests according to user's requests. 

## Inputs
- Target tests csv
  - Keys: Priority, Index, Interferer, COE Pair , Rotation, TC ID, Victim Band, 6GHz Power Mode, 5G Test Point, 5G Channel, 5G Bandwidth, 5G RSSI, 5G Direction, 5G STA, 6G Test Point, 6G Channel, 6G Bandwidth, 6G RSSI ,6G Direction, 6G STA, 2G Test Point, 2G Channel, 2G Bandwidth, 2G RSSI, 2G Direction, 2G STA

- DUT test result directory path, REF test result directory path
- Estimated runtime for each type of test for calculations
- Test config definition
- Test exclusions
- Top priority tests 
  - Allow user to manually override and enter tests that needs to be run tonight
- Day time testing 

## Output
### Backend
- Compile a schedule that would require the lowest amount of time and least amount of wasted time in total according to the following rules and priority:
  - **Rules**
    - Test Windows
      - Weekday night time test window: Monday - Thursday
        - Starts 5PM of that day, ends 9AM the next day
        - Capcity: 17 hrs (16hrs + 1hr margin)
        - Ex. Monday 6/29 5PM - Tuesday 6/30 9AM
      - Weekday day time test window: Monday-Thursday
        - Starts 9AM - 5PM of that day
        - Capacity: 8 hrs
      - Weekend test window: Friday - Sunday
        - Starts Friday 5PM, ends Monday 9AM
        - Capcity: 65 hrs (64hrs + 1hr margin)
      - Holiday test window
    - All tests in the same test window needs to have the same test config
    - Tests are performed on one device in each test window, unless overrides by user
    - Some tests needs to be run back to back
      - P2P COE pairings
        - Run P2P first then its COE pairings
      - P2P up link (RX) and down link (TX)
        - Ex. P2PRXAX001 and P2PTXAX001
      - P3P throttled(TH) and unthrottled(UT)
    - Same tests, different devices(DUT, REF) needs to be run in back to back test windows
      - Ex. Monday
  - **Priority**
    - Default priority: COE P2P pair -> P2P only -> P3P
      - 1: highest priority (must run tonight)
      - 2: COE/P2P pairs
      - 3: P2P only
      - 4: P3P
      - 5: lowest priority
    - Priority 1 and 5 needs to be entered manually
  - **Calculation**
    - Use the estimate run time for each type of test to fit as many tests as possible in a shift of testing. 
    - Weekdays are 16hrs, weekends are 24 hours with 1hr margin
      - If day time testing for today is on, today will be counted as 24 hours
      - Holidays will be counted as 24 hours
    - Estimate run time
      - P2P: 85 mins
      - COE: 115 mins
      - P3P: 105 mins
  - **Failed test management**
    - After there's a modification to the result directories (results are in), and there are tests that are scheduled for last night but were not added to the result directories, meaning the test failed/invalid
    - Estimate how much time for rerun:
      - If user choose to rerun for next day, move the whole schedule down by a day
      - If user choose to rerun during the day, schedule unchanged

### Frontend Components

- **Calendar**
  - Display the schedule that the tests should be conducted after compiling
  - Split one day into 3 eight-hour shift
    - Shift 1: 1AM - 9AM
    - Shift 2: 9AM - 5PM 
      - On weekdays don't include unless day time testing is on. On weekends it is included
    - Shifi 3: 5PM - 1AM
  - Hover over each tests to see test details: type, rotation
  - Display one week at a time, arrows to go to prev/next week
  - Today will be hightlighted or boxed
  - Colors:
    - Pending tests: gray
    - Completed tests: green
    - Failed tests: red
    - Invalid tests: yellow
- **Options** (on the right of the calendar)
    - Day time testing for today: Yes or No
        - If yes, include shift 1 in todays testing
    - Top priority tests
        - Enter a list of comma separated TestIDs to make those tests priority 1
    - Lowest priority tests
      - Enter a list of comma separated TestIDs to make those tests priority 5
- **Estimated Completion Date**
- **Settings**
  - Paths to target and result directories
  - Test exclusion
      - User can enter rules to exclude tests that will not be run
  - Manual priority override
  - Holidays
    - User can enter holidays and that day will be counted as a weekend (24hrs)
- **Failed Tests**
  - Display a red banner with:
    - A message saying what tests failed last night and requires a rerun
    - Estimate rerun time
    - Yes/No button for rerun during the day

### Frontend Layout
```
┌──────────────────────────────────────────────────────────────┐
| CGW453 Scheduler                            [⚙ Settings]    |
|──────────────────────────────────────────────────────────────|
│ ⚠ Tests[____] failed last night — est time required to      |
│    rerun: [_____] Rerun these tests during the day today?    │
|                                                  [Yes/No]    |
├──────────────────────────────────────────────────────────────┤
|           Jun 7th - June 13th      <  >                      |
|   ┌────────────────────────────────────┐                     |
|   | SUN  MON  TUE  WED  THU  FRI  SAT  |  COMPLETION DATE    |
|   |────────────────────────────────────|  Day time [Y/N]     |
|   |                                    |  Top priority:[]    |
|   |────────────────────────────────────|  Lowest Priority:[] |
|   |                                    |                     |
|   |────────────────────────────────────|                     |
|   |                                    |  [Remake Schedule]  |
|   └────────────────────────────────────┘                     |
└──────────────────────────────────────────────────────────────┘
```


Scheduler.py implementation
Graph:
- Only built once, don't exclude any tests, implement using adjacency list
dut_active_priority, ref_active_priority:
- 2 dicts, one for active DUT tests one for active reference tests, dict {testId: priority, testId: priority, ...}
- Default priorities
  - P2P with COE pairs: 2
  - P2P only, COE tests: 3
  - P3P tests: 4
- Remove tests when they are completed
  - When result directories are modified
- Rebuild full dict when exclusion rules are modified
  - When user updates exclusion rules in settings(frontend)

Methods:
build_test_bundles():
- Create bundles of tests that needs to be run back to back
- Types of test bundles and their order
   1. Failed tests rerun if exist
   2. The P2P and COE pairs: P2P -> COE pairings 
   3. P2P tests without COE pairs: P2PRX on DUT -> P2PTX on DUT -> P2PRX on REF -> P2PTX on REF
   4. P3P tests (ALL ROT's)
  ```
    test_bundles: {
      base: base test
      bundled_tests: tests that are bundled to the base test
      total_time: total time of all tests base + bundled_tests
      priority: priority of base test
    }
  ```
- sort test_bundles first with priority then with least total_time

create_schedule():
  - General rules:
    - Monday to Thursday, starts on shift 3 of that day (5pm-1am), fill in test bundles untill shift 3 and shift 1 of next day(1am-9am) is filled. 
      - use an array of shifts: [3,1]
      - total 16hr +1 hr margin
        - tests needs to fit into 17hrs
      - All tests bundles needs to be compatible
        - Check compatibility between current test bundle base and the first test bundle base
    - Friday, starts on shift 3 of Friday, fill in test bundles untill shift 1 of Monday
      - use an array of shifts: [3,1,2,3,1,2,3,1]
      - total 64hr + 1hr margin
        - tests need to fit into 65 hours
      - All tests bundles needs to be compatible
        - Check compatibility between current test bundle base and the first test bundle base
    - For frontend to easily fetch schedule and display it, create a Schedule structured like:
    ```
      Schedule: {
        date: {
          Shift1: list[ScheduleTest] or []
          Shift2: list[ScheduleTest] or []
          Shift3: list[ScheduleTest] or []
        },
        date: {
          Shift1: list[ScheduleTest] or []
          Shift2: list[ScheduleTest] or []
          Shift3: list[ScheduleTest] or []
        }, ...
      }
    ```