private async Task <IOrderedEnumerable <int> > GetAvailablePilots(PilotScheduleRequest request) { var reservationExpiry = _timeProvider.UtcNow().AddMinutes(-10); var date = request.DepartureDateTime.DayOfWeek; var workSchedules = (await _fileService.GetPilotWorkSchedules()).Where(p => p.Base == request.Location && p.WorkDays.Any(d => d == date)); if (!workSchedules.Any()) { return(null); } var pilotSchedules = await _fileService.GetPilotSchedulesForDay(request.DepartureDateTime.Date); var unAvailable = pilotSchedules.Where(p => (p.IsConfirmed || p.ReservationTime > reservationExpiry) && !((p.DepartureDateTime < request.DepartureDateTime && p.ReturnDateTime < request.DepartureDateTime) || (p.DepartureDateTime > request.ReturnDateTime)) ) .Select(p => p.PilotId); var availablePilots = workSchedules.Where(ws => !unAvailable.Contains(ws.PilotId)).Select(p => p.PilotId); if (!availablePilots.Any()) { return(null); } var pilotsBySchedule = pilotSchedules.GroupBy(p => p.PilotId).ToDictionary(i => i.Key, g => g.Count()); return(availablePilots.OrderBy(p => pilotsBySchedule.TryGetValue(p, out var count) ? count : 0)); }
public async Task NoPilotsAvailable_ForThisDay_ReturnsNull() { SetDefaultNow(); var pilots = new[] { new PilotWorkSchedule() { Base = Base.Munich, PilotId = Pilot1, WorkDays = new[] { DayOfWeek.Monday } } }; _fileServiceMock.Setup(x => x.GetPilotWorkSchedules()).Returns(Task.FromResult <IEnumerable <PilotWorkSchedule> >(pilots)); var request = new PilotScheduleRequest() { Location = Base.Berlin, DepartureDateTime = TwoPm, ReturnDateTime = FourPm }; var result = await _service.GetNextAvailablePilot(request); Assert.Null(result.PilotId); Assert.Null(result.ReservationKey); }
public async Task PilotOnLongTrip_EitherSideOfRequestWindow_Unavailable() { SetDefaultNow(); var pilots = new[] { new PilotWorkSchedule() { Base = Base.Berlin, PilotId = Pilot1, WorkDays = AllDays } }; var schedules = new[] { new PilotScheduleInfo() { PilotId = Pilot1, DepartureDateTime = TwoPm, ReturnDateTime = EightPm, IsConfirmed = true } }; _fileServiceMock.Setup(x => x.GetPilotWorkSchedules()).ReturnsAsync(pilots); _fileServiceMock.Setup(x => x.GetPilotSchedulesForDay(TwoPm.Date)).ReturnsAsync(schedules); var request = new PilotScheduleRequest() { Location = Base.Berlin, DepartureDateTime = FourPm, ReturnDateTime = SixPm }; var result = await _service.GetNextAvailablePilot(request); Assert.Null(result.PilotId); Assert.Null(result.ReservationKey); }
public async Task OnePilot_NothingScheduled_GetsReturned() { SetDefaultNow(); var pilots = new[] { new PilotWorkSchedule() { Base = Base.Berlin, PilotId = Pilot1, WorkDays = AllDays } }; var schedules = Enumerable.Empty <PilotScheduleInfo>(); _fileServiceMock.Setup(x => x.GetPilotWorkSchedules()).ReturnsAsync(pilots); _fileServiceMock.Setup(x => x.GetPilotSchedulesForDay(TwoPm.Date)).ReturnsAsync(schedules); var request = new PilotScheduleRequest() { Location = Base.Berlin, DepartureDateTime = TwoPm, ReturnDateTime = FourPm }; var result = await _service.GetNextAvailablePilot(request); Assert.Equal(Pilot1, result.PilotId); Assert.NotNull(result.ReservationKey); }
public async Task <ActionResult <GetNextAvailablePilotResponse> > Post(PilotScheduleRequest request) { if (request.DepartureDateTime < _timeProvider.UtcNow() || request.ReturnDateTime < request.DepartureDateTime) { return(BadRequest()); } return(await _scheduleService.GetNextAvailablePilot(request)); }
public async Task TwoPilots_BothAvailable_ReturnsPilotWithFewerTrips() { SetDefaultNow(); var pilots = new[] { new PilotWorkSchedule() { Base = Base.Berlin, PilotId = Pilot1, WorkDays = AllDays }, new PilotWorkSchedule() { Base = Base.Berlin, PilotId = Pilot2, WorkDays = AllDays } }; var schedules = new[] { new PilotScheduleInfo() { PilotId = Pilot1, DepartureDateTime = SixPm, ReturnDateTime = EightPm, IsConfirmed = true }, new PilotScheduleInfo() { PilotId = Pilot2, DepartureDateTime = SixPm, ReturnDateTime = EightPm, IsConfirmed = true }, new PilotScheduleInfo() { PilotId = Pilot2, DepartureDateTime = EightPm, ReturnDateTime = EightPm.AddHours(2), IsConfirmed = true } }; _fileServiceMock.Setup(x => x.GetPilotWorkSchedules()).ReturnsAsync(pilots); _fileServiceMock.Setup(x => x.GetPilotSchedulesForDay(TwoPm.Date)).ReturnsAsync(schedules); var request = new PilotScheduleRequest() { Location = Base.Berlin, DepartureDateTime = TwoPm, ReturnDateTime = FourPm }; var result = await _service.GetNextAvailablePilot(request); Assert.Equal(Pilot1, result.PilotId); Assert.NotNull(result.ReservationKey); }
public async Task <GetNextAvailablePilotResponse> GetNextAvailablePilot(PilotScheduleRequest request) { var nextAvailablePilot = (await GetAvailablePilots(request))?.FirstOrDefault(); if (nextAvailablePilot == null) { return(new GetNextAvailablePilotResponse(null, null)); } string reservationKey = Guid.NewGuid().ToString(); await PencilInPilotSchedule(nextAvailablePilot.Value, reservationKey, request.DepartureDateTime, request.ReturnDateTime); return(new GetNextAvailablePilotResponse(nextAvailablePilot, reservationKey)); }
public async Task NoPilotsAvailable_ReturnsNull() { SetDefaultNow(); _fileServiceMock.Setup(x => x.GetPilotWorkSchedules()).Returns(Task.FromResult(Enumerable.Empty <PilotWorkSchedule>())); var request = new PilotScheduleRequest() { Location = Base.Berlin, DepartureDateTime = TwoPm, ReturnDateTime = FourPm }; var result = await _service.GetNextAvailablePilot(request); Assert.Null(result.PilotId); Assert.Null(result.ReservationKey); }
public async Task GetAvailablePilot_IgnoresUnconfirmedExpiredReservations() { SetDefaultNow(); var pilots = new[] { new PilotWorkSchedule() { Base = Base.Berlin, PilotId = Pilot1, WorkDays = AllDays } }; var schedules = new[] { new PilotScheduleInfo() { PilotId = Pilot1, DepartureDateTime = TwoPm, ReturnDateTime = FourPm, IsConfirmed = false, ReservationTime = ExpiredDate, ReservationKey = "test" } }; _fileServiceMock.Setup(x => x.GetPilotWorkSchedules()).ReturnsAsync(pilots); _fileServiceMock.Setup(x => x.GetPilotSchedulesForDay(TwoPm.Date)).ReturnsAsync(schedules); var request = new PilotScheduleRequest() { Location = Base.Berlin, DepartureDateTime = TwoPm, ReturnDateTime = FourPm }; var result = await _service.GetNextAvailablePilot(request); Assert.Equal(Pilot1, result.PilotId); Assert.NotNull(result.ReservationKey); }
public async Task GetAvailablePilot_ExcludesUnconfirmedReservations() { SetDefaultNow(); const string reservationKey = "hello"; var pilots = new[] { new PilotWorkSchedule() { Base = Base.Berlin, PilotId = Pilot1, WorkDays = AllDays } }; var schedules = new[] { new PilotScheduleInfo() { PilotId = Pilot1, DepartureDateTime = TwoPm, ReturnDateTime = FourPm, IsConfirmed = false, ReservationKey = reservationKey, ReservationTime = Now.AddSeconds(-1) } }; _fileServiceMock.Setup(x => x.GetPilotWorkSchedules()).ReturnsAsync(pilots); _fileServiceMock.Setup(x => x.GetPilotSchedulesForDay(TwoPm.Date)).ReturnsAsync(schedules); var request = new PilotScheduleRequest() { Location = Base.Berlin, DepartureDateTime = TwoPm, ReturnDateTime = FourPm }; var result = await _service.GetNextAvailablePilot(request); Assert.Null(result.PilotId); }