Change strings to date time offset
This commit is contained in:
parent
cc81cacda8
commit
3ad9e48fcd
11 changed files with 79 additions and 71 deletions
|
|
@ -4,11 +4,11 @@ namespace ShiftScheduler.Services
|
||||||
{
|
{
|
||||||
public interface ITransportService
|
public interface ITransportService
|
||||||
{
|
{
|
||||||
Task<TransportConnection?> GetConnectionAsync(DateTime shiftStartTime);
|
Task<TransportConnection?> GetConnectionAsync(DateTimeOffset shiftStartTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ITransportApiService
|
public interface ITransportApiService
|
||||||
{
|
{
|
||||||
Task<TransportConnection?> GetConnectionAsync(DateTime shiftStartTime);
|
Task<TransportConnection?> GetConnectionAsync(DateTimeOffset shiftStartTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ namespace ShiftScheduler.Services
|
||||||
var summary = $"{shift.Name} (Morning)";
|
var summary = $"{shift.Name} (Morning)";
|
||||||
var description = "";
|
var description = "";
|
||||||
|
|
||||||
if (shiftWithTransport.MorningTransport != null && !string.IsNullOrEmpty(shiftWithTransport.MorningTransport.DepartureTime))
|
if (shiftWithTransport.MorningTransport != null)
|
||||||
{
|
{
|
||||||
var transportSummary = FormatTransportInfo(shiftWithTransport.MorningTransport);
|
var transportSummary = FormatTransportInfo(shiftWithTransport.MorningTransport);
|
||||||
description = $"Transport: {transportSummary}";
|
description = $"Transport: {transportSummary}";
|
||||||
|
|
@ -47,7 +47,7 @@ namespace ShiftScheduler.Services
|
||||||
var summary = $"{shift.Name} (Afternoon)";
|
var summary = $"{shift.Name} (Afternoon)";
|
||||||
var description = "";
|
var description = "";
|
||||||
|
|
||||||
if (shiftWithTransport.AfternoonTransport != null && !string.IsNullOrEmpty(shiftWithTransport.AfternoonTransport.DepartureTime))
|
if (shiftWithTransport.AfternoonTransport != null)
|
||||||
{
|
{
|
||||||
var transportSummary = FormatTransportInfo(shiftWithTransport.AfternoonTransport);
|
var transportSummary = FormatTransportInfo(shiftWithTransport.AfternoonTransport);
|
||||||
description = $"Transport: {transportSummary}";
|
description = $"Transport: {transportSummary}";
|
||||||
|
|
@ -68,9 +68,8 @@ namespace ShiftScheduler.Services
|
||||||
|
|
||||||
private string FormatTransportInfo(TransportConnection transport)
|
private string FormatTransportInfo(TransportConnection transport)
|
||||||
{
|
{
|
||||||
var departure = DateTime.TryParse(transport.DepartureTime, out var dep) ? dep.ToString("HH:mm") : transport.DepartureTime;
|
var departure =transport.DepartureTime.ToString("HH:mm");
|
||||||
var arrival = DateTime.TryParse(transport.ArrivalTime, out var arr) ? arr.ToString("HH:mm") : transport.ArrivalTime;
|
var arrival = transport.ArrivalTime.ToString("HH:mm");
|
||||||
|
|
||||||
return $"{departure} → {arrival}";
|
return $"{departure} → {arrival}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -176,13 +176,13 @@ namespace ShiftScheduler.Services
|
||||||
|
|
||||||
var transportLines = new List<string>();
|
var transportLines = new List<string>();
|
||||||
|
|
||||||
if (shiftWithTransport.MorningTransport != null && !string.IsNullOrEmpty(shiftWithTransport.MorningTransport.DepartureTime))
|
if (shiftWithTransport.MorningTransport != null)
|
||||||
{
|
{
|
||||||
var morningInfo = FormatTransportConnection(shiftWithTransport.MorningTransport);
|
var morningInfo = FormatTransportConnection(shiftWithTransport.MorningTransport);
|
||||||
transportLines.Add(morningInfo);
|
transportLines.Add(morningInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shiftWithTransport.AfternoonTransport != null && !string.IsNullOrEmpty(shiftWithTransport.AfternoonTransport.DepartureTime))
|
if (shiftWithTransport.AfternoonTransport != null)
|
||||||
{
|
{
|
||||||
var afternoonInfo = FormatTransportConnection(shiftWithTransport.AfternoonTransport);
|
var afternoonInfo = FormatTransportConnection(shiftWithTransport.AfternoonTransport);
|
||||||
transportLines.Add(afternoonInfo);
|
transportLines.Add(afternoonInfo);
|
||||||
|
|
@ -193,9 +193,8 @@ namespace ShiftScheduler.Services
|
||||||
|
|
||||||
private static string FormatTransportConnection(TransportConnection transport)
|
private static string FormatTransportConnection(TransportConnection transport)
|
||||||
{
|
{
|
||||||
var departure = DateTime.TryParse(transport.DepartureTime, out var dep) ? dep.ToString("HH:mm") : transport.DepartureTime;
|
var departure = transport.DepartureTime.ToString("HH:mm");
|
||||||
var arrival = DateTime.TryParse(transport.ArrivalTime, out var arr) ? arr.ToString("HH:mm") : transport.ArrivalTime;
|
var arrival = transport.ArrivalTime.ToString("HH:mm");
|
||||||
|
|
||||||
return $"🚂 {departure}→{arrival}";
|
return $"🚂 {departure}→{arrival}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Globalization;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using ShiftScheduler.Shared;
|
using ShiftScheduler.Shared;
|
||||||
|
|
@ -6,7 +7,7 @@ namespace ShiftScheduler.Services
|
||||||
{
|
{
|
||||||
public class TransportApiService(HttpClient httpClient, IConfigurationService configurationService, ILogger<TransportApiService> logger) : ITransportApiService
|
public class TransportApiService(HttpClient httpClient, IConfigurationService configurationService, ILogger<TransportApiService> logger) : ITransportApiService
|
||||||
{
|
{
|
||||||
public async Task<TransportConnection?> GetConnectionAsync(DateTime shiftStartTime)
|
public async Task<TransportConnection?> GetConnectionAsync(DateTimeOffset shiftStartTime)
|
||||||
{
|
{
|
||||||
var config = configurationService.GetTransportConfiguration();
|
var config = configurationService.GetTransportConfiguration();
|
||||||
|
|
||||||
|
|
@ -45,11 +46,12 @@ namespace ShiftScheduler.Services
|
||||||
if (apiConnection == null)
|
if (apiConnection == null)
|
||||||
return new TransportConnection();
|
return new TransportConnection();
|
||||||
|
|
||||||
|
var formats = new[] { @"dd'd'hh\:mm\:ss", @"d'd'hh\:mm\:ss" };
|
||||||
return new TransportConnection
|
return new TransportConnection
|
||||||
{
|
{
|
||||||
DepartureTime = apiConnection.From?.Departure ?? string.Empty,
|
DepartureTime = DateTimeOffset.Parse(apiConnection.From!.Departure),
|
||||||
ArrivalTime = apiConnection.To?.Arrival ?? string.Empty,
|
ArrivalTime = DateTimeOffset.Parse(apiConnection.To!.Arrival),
|
||||||
Duration = apiConnection.Duration,
|
Duration = TimeSpan.ParseExact(apiConnection.Duration, formats, CultureInfo.InvariantCulture),
|
||||||
Platform = apiConnection.From?.Platform ?? string.Empty,
|
Platform = apiConnection.From?.Platform ?? string.Empty,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
using System.Globalization;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using ShiftScheduler.Shared;
|
using ShiftScheduler.Shared;
|
||||||
|
|
||||||
namespace ShiftScheduler.Services;
|
namespace ShiftScheduler.Services;
|
||||||
|
|
||||||
public record ConnectionPickArgument(
|
public record ConnectionPickArgument(
|
||||||
DateTime ShiftStartTime,
|
DateTimeOffset ShiftStartTime,
|
||||||
int SafetyBufferMinutes,
|
int SafetyBufferMinutes,
|
||||||
int MaxEarlyArrivalMinutes,
|
int MaxEarlyArrivalMinutes,
|
||||||
int MaxLateArrivalMinutes)
|
int MaxLateArrivalMinutes)
|
||||||
|
|
@ -35,16 +34,13 @@ public static class TransportConnectionCalculator
|
||||||
|
|
||||||
foreach (var connection in connections)
|
foreach (var connection in connections)
|
||||||
{
|
{
|
||||||
if (DateTime.TryParse(connection.ArrivalTime, out var arrivalTime))
|
if (connection.ArrivalTime <= latestArrivalTime)
|
||||||
{
|
{
|
||||||
if (arrivalTime <= latestArrivalTime)
|
validConnections.Add(connection);
|
||||||
{
|
}
|
||||||
validConnections.Add(connection);
|
else if (connection.ArrivalTime <= latestAcceptableTime)
|
||||||
}
|
{
|
||||||
else if (arrivalTime <= latestAcceptableTime)
|
lateValidConnections.Add(connection);
|
||||||
{
|
|
||||||
lateValidConnections.Add(connection);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,18 +48,17 @@ public static class TransportConnectionCalculator
|
||||||
if (validConnections.Count > 0)
|
if (validConnections.Count > 0)
|
||||||
{
|
{
|
||||||
var sortedValid = validConnections
|
var sortedValid = validConnections
|
||||||
.OrderBy(c => DateTime.Parse(c.ArrivalTime ?? "00:00"))
|
.OrderBy(c => c.ArrivalTime)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var bestValidConnection = sortedValid.Last();
|
var bestValidConnection = sortedValid.Last();
|
||||||
var bestValidArrivalTime = DateTime.Parse(bestValidConnection.ArrivalTime!);
|
|
||||||
|
|
||||||
// Check if the best valid connection arrives too early (more than maxEarlyArrivalMinutes before shift)
|
// Check if the best valid connection arrives too early (more than maxEarlyArrivalMinutes before shift)
|
||||||
if (bestValidArrivalTime < earliestAcceptableTime && lateValidConnections.Count > 0)
|
if (bestValidConnection.ArrivalTime < earliestAcceptableTime && lateValidConnections.Count > 0)
|
||||||
{
|
{
|
||||||
// Return the earliest connection that arrives after latest arrival time but within acceptable range
|
// Return the earliest connection that arrives after latest arrival time but within acceptable range
|
||||||
var sortedLateValid = lateValidConnections
|
var sortedLateValid = lateValidConnections
|
||||||
.OrderBy(c => DateTime.Parse(c.ArrivalTime ?? "23:59"))
|
.OrderBy(c => c.ArrivalTime)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
return sortedLateValid.First();
|
return sortedLateValid.First();
|
||||||
|
|
@ -76,7 +71,7 @@ public static class TransportConnectionCalculator
|
||||||
if (lateValidConnections.Count > 0)
|
if (lateValidConnections.Count > 0)
|
||||||
{
|
{
|
||||||
var sortedLateValid = lateValidConnections
|
var sortedLateValid = lateValidConnections
|
||||||
.OrderBy(c => DateTime.Parse(c.ArrivalTime ?? "23:59"))
|
.OrderBy(c => c.ArrivalTime)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
return sortedLateValid.First();
|
return sortedLateValid.First();
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ namespace ShiftScheduler.Services
|
||||||
{
|
{
|
||||||
public class TransportService(ITransportApiService transportService, IConfigurationService configurationService, IMemoryCache cache) : ITransportService
|
public class TransportService(ITransportApiService transportService, IConfigurationService configurationService, IMemoryCache cache) : ITransportService
|
||||||
{
|
{
|
||||||
public async Task<TransportConnection?> GetConnectionAsync(DateTime shiftStartTime)
|
public async Task<TransportConnection?> GetConnectionAsync(DateTimeOffset shiftStartTime)
|
||||||
{
|
{
|
||||||
var config = configurationService.GetTransportConfiguration();
|
var config = configurationService.GetTransportConfiguration();
|
||||||
var searchDate = shiftStartTime.ToString("yyyy-MM-dd");
|
var searchDate = shiftStartTime.ToString("yyyy-MM-dd");
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,8 @@ namespace ShiftScheduler.Shared
|
||||||
|
|
||||||
private string FormatTransportSummary(TransportConnection connection)
|
private string FormatTransportSummary(TransportConnection connection)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(connection.DepartureTime)) return string.Empty;
|
var departure = connection.DepartureTime.ToString("HH:mm");
|
||||||
|
var arrival = connection.ArrivalTime.ToString("HH:mm");
|
||||||
var departure = DateTime.TryParse(connection.DepartureTime, out var dep) ? dep.ToString("HH:mm") : connection.DepartureTime;
|
|
||||||
var arrival = DateTime.TryParse(connection.ArrivalTime, out var arr) ? arr.ToString("HH:mm") : connection.ArrivalTime;
|
|
||||||
return $"{departure}→{arrival}";
|
return $"{departure}→{arrival}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,12 @@ namespace ShiftScheduler.Shared
|
||||||
|
|
||||||
public TransportConnection(string arrivalTime)
|
public TransportConnection(string arrivalTime)
|
||||||
{
|
{
|
||||||
ArrivalTime = arrivalTime;
|
ArrivalTime = DateTimeOffset.Parse(arrivalTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string DepartureTime { get; set; } = string.Empty;
|
public DateTimeOffset DepartureTime { get; set; }
|
||||||
public string ArrivalTime { get; set; } = string.Empty;
|
public DateTimeOffset ArrivalTime { get; set; }
|
||||||
public string Duration { get; set; } = string.Empty;
|
public TimeSpan Duration { get; set; }
|
||||||
public string? Platform { get; set; } = string.Empty;
|
public string? Platform { get; set; } = string.Empty;
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,9 @@ public class TransportApiServiceTests
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.ShouldNotBeNull();
|
result.ShouldNotBeNull();
|
||||||
result.DepartureTime.ShouldBe("2023-12-15T06:45:00");
|
result.DepartureTime.ShouldBe(T("2023-12-15T06:45:00"));
|
||||||
result.ArrivalTime.ShouldBe("2023-12-15T07:30:00");
|
result.ArrivalTime.ShouldBe(T("2023-12-15T07:30:00"));
|
||||||
result.Duration.ShouldBe("00:45:00");
|
result.Duration.ShouldBe(TimeSpan.Parse("00:45:00"));
|
||||||
result.Platform.ShouldBe("5");
|
result.Platform.ShouldBe("5");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,7 +115,7 @@ public class TransportApiServiceTests
|
||||||
// Latest acceptable arrival: 8:00 - 30 min = 7:30
|
// Latest acceptable arrival: 8:00 - 30 min = 7:30
|
||||||
// Valid connections: 07:15 and 07:25 (both arrive before 7:30)
|
// Valid connections: 07:15 and 07:25 (both arrive before 7:30)
|
||||||
// Algorithm should return the latest valid: 07:25
|
// Algorithm should return the latest valid: 07:25
|
||||||
result.ArrivalTime.ShouldBe("2023-12-15T07:25:00");
|
result.ArrivalTime.ShouldBe(T("2023-12-15T07:25:00"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupHttpMockResponse(HttpStatusCode statusCode, string content)
|
private void SetupHttpMockResponse(HttpStatusCode statusCode, string content)
|
||||||
|
|
@ -151,7 +151,7 @@ public class TransportApiServiceTests
|
||||||
Arrival = "2023-12-15T07:30:00",
|
Arrival = "2023-12-15T07:30:00",
|
||||||
Platform = "3"
|
Platform = "3"
|
||||||
},
|
},
|
||||||
Duration = "00:45:00",
|
Duration = "00d00:45:00",
|
||||||
Sections = new List<TransportApiSection>
|
Sections = new List<TransportApiSection>
|
||||||
{
|
{
|
||||||
new TransportApiSection
|
new TransportApiSection
|
||||||
|
|
@ -202,7 +202,7 @@ public class TransportApiServiceTests
|
||||||
Arrival = "2023-12-15T07:15:00",
|
Arrival = "2023-12-15T07:15:00",
|
||||||
Platform = "3"
|
Platform = "3"
|
||||||
},
|
},
|
||||||
Duration = "00:45:00"
|
Duration = "00d00:45:00"
|
||||||
},
|
},
|
||||||
// Later valid connection - should be selected as best
|
// Later valid connection - should be selected as best
|
||||||
new TransportApiConnection
|
new TransportApiConnection
|
||||||
|
|
@ -219,7 +219,7 @@ public class TransportApiServiceTests
|
||||||
Arrival = "2023-12-15T07:25:00",
|
Arrival = "2023-12-15T07:25:00",
|
||||||
Platform = "2"
|
Platform = "2"
|
||||||
},
|
},
|
||||||
Duration = "00:45:00"
|
Duration = "00d00:45:00"
|
||||||
},
|
},
|
||||||
// Too late connection - invalid (arrives after 07:30 which is shift start - 30 min buffer)
|
// Too late connection - invalid (arrives after 07:30 which is shift start - 30 min buffer)
|
||||||
new TransportApiConnection
|
new TransportApiConnection
|
||||||
|
|
@ -236,9 +236,14 @@ public class TransportApiServiceTests
|
||||||
Arrival = "2023-12-15T07:35:00",
|
Arrival = "2023-12-15T07:35:00",
|
||||||
Platform = "1"
|
Platform = "1"
|
||||||
},
|
},
|
||||||
Duration = "00:45:00"
|
Duration = "00d00:45:00"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DateTimeOffset T(string dateTimeString)
|
||||||
|
{
|
||||||
|
return DateTimeOffset.Parse(dateTimeString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -20,7 +20,7 @@ public class TransportConnectionCalculatorTests
|
||||||
new(arrivalTime: "2023-12-15T07:25:00"), // Should be selected (latest valid)
|
new(arrivalTime: "2023-12-15T07:25:00"), // Should be selected (latest valid)
|
||||||
new(arrivalTime: "2023-12-15T08:05:00") // Too late
|
new(arrivalTime: "2023-12-15T08:05:00") // Too late
|
||||||
};
|
};
|
||||||
var shiftStartTime = new DateTime(2023, 12, 15, 8, 0, 0);
|
var shiftStartTime = T("2023-12-15T08:00:00");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = TransportConnectionCalculator.FindBestConnection(
|
var result = TransportConnectionCalculator.FindBestConnection(
|
||||||
|
|
@ -30,7 +30,7 @@ public class TransportConnectionCalculatorTests
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.ShouldNotBeNull();
|
result.ShouldNotBeNull();
|
||||||
result.ArrivalTime.ShouldBe("2023-12-15T07:25:00");
|
result.ArrivalTime.ShouldBe(T("2023-12-15T07:25:00"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -42,7 +42,7 @@ public class TransportConnectionCalculatorTests
|
||||||
new(arrivalTime: "2023-12-15T06:45:00"), // Too early (more than 60 min before 8:00)
|
new(arrivalTime: "2023-12-15T06:45:00"), // Too early (more than 60 min before 8:00)
|
||||||
new(arrivalTime: "2023-12-15T08:05:00") // Within acceptable late range (15 min after 8:00)
|
new(arrivalTime: "2023-12-15T08:05:00") // Within acceptable late range (15 min after 8:00)
|
||||||
};
|
};
|
||||||
var shiftStartTime = new DateTime(2023, 12, 15, 8, 0, 0);
|
var shiftStartTime = T("2023-12-15T08:00:00");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = TransportConnectionCalculator.FindBestConnection(
|
var result = TransportConnectionCalculator.FindBestConnection(
|
||||||
|
|
@ -52,7 +52,7 @@ public class TransportConnectionCalculatorTests
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.ShouldNotBeNull();
|
result.ShouldNotBeNull();
|
||||||
result.ArrivalTime.ShouldBe("2023-12-15T08:05:00");
|
result.ArrivalTime.ShouldBe(T("2023-12-15T08:05:00"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -65,7 +65,7 @@ public class TransportConnectionCalculatorTests
|
||||||
new(arrivalTime: "2023-12-15T08:05:00"), // Should be selected (earliest late)
|
new(arrivalTime: "2023-12-15T08:05:00"), // Should be selected (earliest late)
|
||||||
new(arrivalTime: "2023-12-15T08:12:00")
|
new(arrivalTime: "2023-12-15T08:12:00")
|
||||||
};
|
};
|
||||||
var shiftStartTime = new DateTime(2023, 12, 15, 8, 0, 0);
|
var shiftStartTime = T("2023-12-15T08:00:00");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = TransportConnectionCalculator.FindBestConnection(
|
var result = TransportConnectionCalculator.FindBestConnection(
|
||||||
|
|
@ -75,7 +75,7 @@ public class TransportConnectionCalculatorTests
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.ShouldNotBeNull();
|
result.ShouldNotBeNull();
|
||||||
result.ArrivalTime.ShouldBe("2023-12-15T08:05:00");
|
result.ArrivalTime.ShouldBe(T("2023-12-15T08:05:00"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -88,7 +88,7 @@ public class TransportConnectionCalculatorTests
|
||||||
new(arrivalTime: "2023-12-15T08:25:00"),
|
new(arrivalTime: "2023-12-15T08:25:00"),
|
||||||
new(arrivalTime: "2023-12-15T08:30:00")
|
new(arrivalTime: "2023-12-15T08:30:00")
|
||||||
};
|
};
|
||||||
var shiftStartTime = new DateTime(2023, 12, 15, 8, 0, 0);
|
var shiftStartTime = T("2023-12-15T08:00:00");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = TransportConnectionCalculator.FindBestConnection(
|
var result = TransportConnectionCalculator.FindBestConnection(
|
||||||
|
|
@ -109,7 +109,7 @@ public class TransportConnectionCalculatorTests
|
||||||
new(arrivalTime: "2023-12-15T07:20:00"), // 40 min before shift - acceptable
|
new(arrivalTime: "2023-12-15T07:20:00"), // 40 min before shift - acceptable
|
||||||
new(arrivalTime: "2023-12-15T08:05:00") // 5 min after shift
|
new(arrivalTime: "2023-12-15T08:05:00") // 5 min after shift
|
||||||
};
|
};
|
||||||
var shiftStartTime = new DateTime(2023, 12, 15, 8, 0, 0);
|
var shiftStartTime = T("2023-12-15T08:00:00");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = TransportConnectionCalculator.FindBestConnection(
|
var result = TransportConnectionCalculator.FindBestConnection(
|
||||||
|
|
@ -119,14 +119,14 @@ public class TransportConnectionCalculatorTests
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.ShouldNotBeNull();
|
result.ShouldNotBeNull();
|
||||||
result.ArrivalTime.ShouldBe("2023-12-15T07:20:00");
|
result.ArrivalTime.ShouldBe(T("2023-12-15T07:20:00"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void FindBestConnectionEnhanced_WithEmptyConnections_ShouldReturnNull()
|
public void FindBestConnectionEnhanced_WithEmptyConnections_ShouldReturnNull()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var shiftStartTime = new DateTime(2023, 12, 15, 8, 0, 0);
|
var shiftStartTime = T("2023-12-15T08:00:00");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = TransportConnectionCalculator.FindBestConnection(
|
var result = TransportConnectionCalculator.FindBestConnection(
|
||||||
|
|
@ -149,7 +149,7 @@ public class TransportConnectionCalculatorTests
|
||||||
new(arrivalTime: "2023-12-15T08:05:00"), // Late but acceptable
|
new(arrivalTime: "2023-12-15T08:05:00"), // Late but acceptable
|
||||||
new(arrivalTime: "2023-12-15T08:20:00") // Too late
|
new(arrivalTime: "2023-12-15T08:20:00") // Too late
|
||||||
};
|
};
|
||||||
var shiftStartTime = new DateTime(2023, 12, 15, 8, 0, 0);
|
var shiftStartTime = T("2023-12-15T08:00:00");
|
||||||
|
|
||||||
// Act - MaxEarlyArrivalMinutes = 30, so earliest acceptable is 7:30
|
// Act - MaxEarlyArrivalMinutes = 30, so earliest acceptable is 7:30
|
||||||
var result = TransportConnectionCalculator.FindBestConnection(
|
var result = TransportConnectionCalculator.FindBestConnection(
|
||||||
|
|
@ -159,6 +159,11 @@ public class TransportConnectionCalculatorTests
|
||||||
|
|
||||||
// Assert - 7:25 arrives at 7:25, which is 35 min before shift (more than 30 min), so should prefer late connection
|
// Assert - 7:25 arrives at 7:25, which is 35 min before shift (more than 30 min), so should prefer late connection
|
||||||
result.ShouldNotBeNull();
|
result.ShouldNotBeNull();
|
||||||
result.ArrivalTime.ShouldBe("2023-12-15T08:05:00");
|
result.ArrivalTime.ShouldBe(T("2023-12-15T08:05:00"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateTimeOffset T(string dateTimeString)
|
||||||
|
{
|
||||||
|
return DateTimeOffset.Parse(dateTimeString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -46,9 +46,9 @@ public class TransportServiceTests
|
||||||
var shiftStartTime = new DateTime(2023, 12, 15, 8, 0, 0);
|
var shiftStartTime = new DateTime(2023, 12, 15, 8, 0, 0);
|
||||||
var connection = new TransportConnection
|
var connection = new TransportConnection
|
||||||
{
|
{
|
||||||
DepartureTime = "2023-12-15T06:45:00",
|
DepartureTime = T("2023-12-15T06:45:00"),
|
||||||
ArrivalTime = "2023-12-15T07:30:00",
|
ArrivalTime = T("2023-12-15T07:30:00"),
|
||||||
Duration = "00:45:00",
|
Duration = TimeSpan.Parse("00:45:00"),
|
||||||
Platform = "5"
|
Platform = "5"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -100,11 +100,11 @@ public class TransportServiceTests
|
||||||
public async Task GetConnectionAsync_WithDifferentDates_ShouldCreateSeparateCacheEntries()
|
public async Task GetConnectionAsync_WithDifferentDates_ShouldCreateSeparateCacheEntries()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var shiftStartTime1 = new DateTime(2023, 12, 15, 8, 0, 0);
|
var shiftStartTime1 = T("2023-12-15T08:00:00");
|
||||||
var shiftStartTime2 = new DateTime(2023, 12, 16, 8, 0, 0);
|
var shiftStartTime2 = T("2023-12-16T08:00:00");
|
||||||
|
|
||||||
var connection1 = new TransportConnection { ArrivalTime = "2023-12-15T07:30:00" };
|
var connection1 = new TransportConnection { ArrivalTime = T("2023-12-15T07:30:00") };
|
||||||
var connection2 = new TransportConnection { ArrivalTime = "2023-12-16T07:30:00" };
|
var connection2 = new TransportConnection { ArrivalTime = T("2023-12-16T07:30:00") };
|
||||||
|
|
||||||
_transportServiceMock
|
_transportServiceMock
|
||||||
.Setup(x => x.GetConnectionAsync(shiftStartTime1))
|
.Setup(x => x.GetConnectionAsync(shiftStartTime1))
|
||||||
|
|
@ -121,10 +121,15 @@ public class TransportServiceTests
|
||||||
// Assert
|
// Assert
|
||||||
result1.ShouldNotBeNull();
|
result1.ShouldNotBeNull();
|
||||||
result2.ShouldNotBeNull();
|
result2.ShouldNotBeNull();
|
||||||
result1.ArrivalTime.ShouldBe("2023-12-15T07:30:00");
|
result1.ArrivalTime.ShouldBe(T("2023-12-15T07:30:00"));
|
||||||
result2.ArrivalTime.ShouldBe("2023-12-16T07:30:00");
|
result2.ArrivalTime.ShouldBe(T("2023-12-16T07:30:00"));
|
||||||
|
|
||||||
// Verify that transport service was called twice (different cache keys)
|
// Verify that transport service was called twice (different cache keys)
|
||||||
_transportServiceMock.Verify(x => x.GetConnectionAsync(It.IsAny<DateTime>()), Times.Exactly(2));
|
_transportServiceMock.Verify(x => x.GetConnectionAsync(It.IsAny<DateTimeOffset>()), Times.Exactly(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateTimeOffset T(string dateTimeString)
|
||||||
|
{
|
||||||
|
return DateTimeOffset.Parse(dateTimeString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue