def test_parsing_output(): inputs = parse_args([ "--config", "tests/test_files/cli/config.json", "--history", "tests/test_files/cli/history.json", "--output", "tests/test_files/cli/output.json", "--evaluate", ]) assert inputs.output_path == "tests/test_files/cli/output.json" assert inputs.output == [ AssignedShift( person=Person("Admiral Ackbar"), day=date(2019, 11, 29), name="ops", shift_type=ShiftType.STANDARD, ), AssignedShift( person=Person("Admiral Ackbar"), day=date(2019, 11, 30), name="ops", shift_type=ShiftType.STANDARD, ), AssignedShift( person=Person("Admiral Ackbar"), day=date(2019, 12, 1), name="ops", shift_type=ShiftType.SPECIAL_A, ), ]
def test_date_last_on_shift(): person_a = Person("a") person_b = Person("b") person_c = Person("c") person_d = Person("d") history = History.build([ AssignedShift( "shift", ShiftType.SPECIAL_A, date(2019, 8, 31), person_a, ), AssignedShift( "shift", ShiftType.SPECIAL_B, date(2019, 9, 1), person_b, ), AssignedShift( "shift", ShiftType.STANDARD, date(2019, 9, 2), person_a, ), AssignedShift( "shift", ShiftType.STANDARD, date(2019, 9, 3), person_b, ), AssignedShift( "shift", ShiftType.STANDARD, date(2019, 9, 4), person_a, ), AssignedShift( "shift", ShiftType.STANDARD, date(2019, 9, 5), person_c, ), ]) metrics = HistoryMetrics.build(history, [person_a, person_b, person_d], date(2019, 9, 8)) assert metrics.date_last_on_shift == { person_a: date(2019, 9, 4), person_b: date(2019, 9, 3), person_d: NEVER, }
def test_basic_assignment(): shifts = [ Shift(name="shift", shift_type=ShiftType.STANDARD, day=date(2019, 1, 1)), Shift(name="shift", shift_type=ShiftType.STANDARD, day=date(2019, 1, 2)), Shift(name="shift", shift_type=ShiftType.STANDARD, day=date(2019, 1, 3)), Shift(name="shift", shift_type=ShiftType.STANDARD, day=date(2019, 1, 4)), Shift(name="shift", shift_type=ShiftType.STANDARD, day=date(2019, 1, 5)), Shift(name="shift", shift_type=ShiftType.STANDARD, day=date(2019, 1, 6)), Shift(name="shift", shift_type=ShiftType.STANDARD, day=date(2019, 1, 7)), ] config = Config.build( people=[Person(name=f"person_{index}") for index in range(7)], max_shifts_per_person=1, shifts_by_day={shift.day: [shift] for shift in shifts}, history=History.build(), ) solution = solve(config) assert len(list(solution)) == 7
def from_json(cls, serialised: Dict[str, Any]) -> "AssignedShift": return AssignedShift( name=serialised["name"], shift_type=ShiftType.from_json(serialised["type"]), day=datetime.fromisoformat(serialised["day"]).date(), person=Person(name=serialised["person"]), )
def test_json_round_trip(): shift = AssignedShift( person=Person(name="A"), day=date(2019, 1, 1), name="ops", shift_type=ShiftType.STANDARD, ) assert shift == AssignedShift.from_json(shift.to_json())
def test_num_of_shifts(): person_a = Person("a") person_b = Person("b") person_c = Person("c") history = History.build([ AssignedShift( "shift", ShiftType.SPECIAL_A, date(2019, 8, 31), person_a, ), AssignedShift( "shift", ShiftType.SPECIAL_B, date(2019, 9, 1), person_b, ), AssignedShift( "shift", ShiftType.STANDARD, date(2019, 9, 2), person_a, ), AssignedShift( "shift", ShiftType.STANDARD, date(2019, 9, 3), person_b, ), AssignedShift( "shift", ShiftType.STANDARD, date(2019, 9, 4), person_a, ), AssignedShift( "shift", ShiftType.STANDARD, date(2019, 9, 5), person_c, ), ]) metrics = HistoryMetrics.build(history, [person_a, person_b], date(2019, 9, 5)) assert metrics.num_of_shifts == { ShiftType.STANDARD: { person_a: 2, person_b: 1 }, ShiftType.SPECIAL_A: { person_a: 1, person_b: 0 }, ShiftType.SPECIAL_B: { person_a: 0, person_b: 1 }, }
def test_num_of_shifts_with_offsets(): person_a = Person("a") person_b = Person("b") person_c = Person("c") history = History.build( past_shifts=[ AssignedShift( "shift", ShiftType.SPECIAL_A, date(2019, 8, 31), person_a, ), AssignedShift( "shift", ShiftType.SPECIAL_B, date(2019, 9, 1), person_b, ), AssignedShift( "shift", ShiftType.STANDARD, date(2019, 9, 2), person_a, ), AssignedShift( "shift", ShiftType.STANDARD, date(2019, 9, 3), person_b, ), AssignedShift( "shift", ShiftType.STANDARD, date(2019, 9, 4), person_a, ), AssignedShift( "shift", ShiftType.STANDARD, date(2019, 9, 5), person_c, ), ], offsets=[ PastShiftOffset(person=person_a, shift_type=ShiftType.STANDARD, offset=2), PastShiftOffset(person=person_b, shift_type=ShiftType.SPECIAL_A, offset=1), PastShiftOffset(person=person_c, shift_type=ShiftType.SPECIAL_B, offset=5), ], ) metrics = HistoryMetrics.build(history, [person_a, person_b], date(2019, 9, 5)) assert metrics.num_of_shifts == { ShiftType.STANDARD: { person_a: 4, person_b: 1 }, ShiftType.SPECIAL_A: { person_a: 1, person_b: 1 }, ShiftType.SPECIAL_B: { person_a: 0, person_b: 1, person_c: 5 }, }
def people(): return [Person("A"), Person("B")]
def _parse_people(config) -> List[Person]: return [Person(name=person["name"]) for person in config["people"]]
def from_json(cls, serialised: Dict[str, Any]) -> "PastShiftOffset": return PastShiftOffset( person=Person(name=serialised["person"]), shift_type=ShiftType.from_json(serialised["shift_type"]), offset=int(serialised["offset"]), )
def test_parsing_inputs(): inputs = parse_args([ "--config", "tests/test_files/cli/config.json", "--history", "tests/test_files/cli/history.json", ]) assert set(inputs.people) == { Person(name="Admiral Ackbar"), Person(name="Mon Mothma"), } assert inputs.shifts_by_day == { date(2019, 11, 29): [ Shift(day=date(2019, 11, 29), name="ops", shift_type=ShiftType.STANDARD) ], date(2019, 11, 30): [ Shift(day=date(2019, 11, 30), name="ops", shift_type=ShiftType.STANDARD) ], date(2019, 12, 1): [ Shift(day=date(2019, 12, 1), name="ops", shift_type=ShiftType.SPECIAL_A) ], } assert inputs.constraints == [ EachPersonWorksAtMostXShiftsPerAssignmentPeriod(priority=0, x=1), ThereShouldBeAtLeastXDaysBetweenOps(priority=1, x=4), RespectPersonRestrictionsPerShiftType( priority=2, forbidden_by_shift_type={"special_a": ["Admiral Ackbar"]}), RespectPersonRestrictionsPerDay( priority=3, name="Holidays", restrictions={"Admiral Ackbar": ["2019-11-01"]}), ] assert inputs.history.past_shifts == ( AssignedShift( person=Person("Admiral Ackbar"), day=date(2019, 11, 28), name="ops", shift_type=ShiftType.SPECIAL_A, ), AssignedShift( person=Person("Admiral Ackbar"), day=date(2019, 11, 27), name="ops", shift_type=ShiftType.SPECIAL_B, ), AssignedShift( person=Person("Admiral Ackbar"), day=date(2019, 11, 26), name="ops", shift_type=ShiftType.STANDARD, ), AssignedShift( person=Person("Mon Mothma"), day=date(2019, 11, 25), name="ops", shift_type=ShiftType.STANDARD, ), AssignedShift( person=Person("Mon Mothma"), day=date(2019, 11, 24), name="ops", shift_type=ShiftType.STANDARD, ), AssignedShift( person=Person("Admiral Ackbar"), day=date(2019, 11, 23), name="ops", shift_type=ShiftType.STANDARD, ), ) assert inputs.output_path is None assert inputs.output is None