Skip to content

Commit adc2725

Browse files
CopilotabeckDev
andcommitted
Use GetFullChangesAsync for live delay data and extract changes per train
- Changed from GetRecentTimetableChangesAsync to GetFullChangesAsync to get all changes instead of just last 2 minutes - Implemented proper matching of changes data to each specific train by train ID - Extract live delay, cancellation status, platform changes, and messages from the full changes data - Added test case to verify live delay information is properly extracted and displayed Co-authored-by: abeckDev <8720854+abeckDev@users.noreply.github.com>
1 parent 4f884e6 commit adc2725

File tree

2 files changed

+124
-15
lines changed

2 files changed

+124
-15
lines changed

AbeckDev.DbTimetable.Mcp.Test/TimeTableServiceTests.cs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ public async Task FindTrainConnectionsAsync_WithValidStations_ReturnsAnalysisRep
390390
.ReturnsAsync(() =>
391391
{
392392
requestCount++;
393-
// First two calls are station lookups, third is timetable, fourth is changes
393+
// First two calls are station lookups, third is timetable, fourth is full changes
394394
if (requestCount <= 2)
395395
return new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = new StringContent(stationXml) };
396396
if (requestCount == 3)
@@ -410,6 +410,64 @@ public async Task FindTrainConnectionsAsync_WithValidStations_ReturnsAnalysisRep
410410
Assert.Contains("EVA: 8000105", result);
411411
}
412412

413+
[Fact]
414+
public async Task FindTrainConnectionsAsync_WithLiveDelayData_ReturnsDelayInformation()
415+
{
416+
// Arrange
417+
var stationXml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
418+
<stations>
419+
<station name=""Frankfurt Hbf"" eva=""8000105"" ds100=""FF""/>
420+
</stations>";
421+
422+
var timetableXml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
423+
<timetable station=""Frankfurt Hbf"">
424+
<s id=""123456"">
425+
<tl c=""ICE"" n=""123"" f=""Berlin Hbf""/>
426+
<dp pt=""2511061430"" pp=""7"" ppth=""Frankfurt Hbf|Mannheim|Berlin Hbf""/>
427+
</s>
428+
</timetable>";
429+
430+
// Changes XML with live delay data - train delayed by 10 minutes
431+
var changesXml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
432+
<timetable>
433+
<s id=""123456"">
434+
<tl c=""ICE"" n=""123"" f=""Berlin Hbf""/>
435+
<dp pt=""2511061430"" ct=""2511061440"" pp=""7"" cp=""8""/>
436+
<m t=""Train delayed due to technical issues""/>
437+
</s>
438+
</timetable>";
439+
440+
var mockHandler = new Mock<HttpMessageHandler>();
441+
var requestCount = 0;
442+
mockHandler.Protected()
443+
.Setup<Task<HttpResponseMessage>>(
444+
"SendAsync",
445+
ItExpr.IsAny<HttpRequestMessage>(),
446+
ItExpr.IsAny<CancellationToken>())
447+
.ReturnsAsync(() =>
448+
{
449+
requestCount++;
450+
// First two calls are station lookups, third is timetable, fourth is full changes
451+
if (requestCount <= 2)
452+
return new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = new StringContent(stationXml) };
453+
if (requestCount == 3)
454+
return new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = new StringContent(timetableXml) };
455+
return new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = new StringContent(changesXml) };
456+
});
457+
458+
var httpClient = new HttpClient(mockHandler.Object) { BaseAddress = new Uri(_config.BaseUrl) };
459+
var service = new TimeTableService(httpClient, _mockOptions.Object);
460+
461+
// Act
462+
var result = await service.FindTrainConnectionsAsync("Frankfurt", "Berlin");
463+
464+
// Assert
465+
Assert.Contains("Train Connection Analysis", result);
466+
Assert.Contains("Delay: +10 minutes", result);
467+
Assert.Contains("Train delayed due to technical issues", result);
468+
Assert.Contains("Platform: 8", result); // Changed platform
469+
}
470+
413471
[Fact]
414472
public async Task FindTrainConnectionsAsync_WithInvalidStationA_ReturnsError()
415473
{

AbeckDev.DbTimetable.Mcp/Services/TimeTableService.cs

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -146,18 +146,18 @@ public async Task<string> FindTrainConnectionsAsync(
146146
result.AppendLine(" ✓ Timetable retrieved");
147147
result.AppendLine();
148148

149-
// Step 4: Get changes for station A to check for delays/disruptions
149+
// Step 4: Get full changes for station A to check for delays/disruptions
150150
result.AppendLine($"Step 4: Checking for delays and disruptions at {stationAInfo.Name}...");
151151
string changesA;
152152
try
153153
{
154-
changesA = await GetRecentTimetableChangesAsync(stationAInfo.EvaNo, cancellationToken);
155-
result.AppendLine(" ✓ Recent changes retrieved");
154+
changesA = await GetFullChangesAsync(stationAInfo.EvaNo, cancellationToken);
155+
result.AppendLine(" ✓ Full changes retrieved");
156156
}
157157
catch
158158
{
159159
changesA = string.Empty;
160-
result.AppendLine(" ⚠ No recent changes available");
160+
result.AppendLine(" ⚠ No changes available");
161161
}
162162
result.AppendLine();
163163

@@ -353,21 +353,72 @@ private List<ConnectionInfo> FindConnectionsInTimetable(string timetableXml, str
353353
var departureTime = ParseTimetableDateTime(actualDeparture);
354354
var scheduledDepartureTime = ParseTimetableDateTime(scheduledDeparture);
355355

356-
// Calculate delay
356+
// Look up live changes for this specific train from the full changes data
357357
int delay = 0;
358-
if (scheduledDepartureTime.HasValue && departureTime.HasValue)
358+
bool isCancelled = departureElement.Attribute("cs")?.Value == "c";
359+
string messages = string.Join("; ", stop.Elements("m")
360+
.Select(m => m.Attribute("t")?.Value)
361+
.Where(m => !string.IsNullOrEmpty(m)));
362+
363+
// If we have changes data, look for this specific train and extract live information
364+
if (changesDoc != null)
365+
{
366+
var changeStop = changesDoc.Descendants("s")
367+
.FirstOrDefault(s => s.Attribute("id")?.Value == trainId);
368+
369+
if (changeStop != null)
370+
{
371+
var changeDp = changeStop.Element("dp");
372+
if (changeDp != null)
373+
{
374+
// Get live departure time from changes
375+
var liveActualDeparture = changeDp.Attribute("ct")?.Value;
376+
var liveScheduledDeparture = changeDp.Attribute("pt")?.Value;
377+
378+
if (!string.IsNullOrEmpty(liveActualDeparture) && !string.IsNullOrEmpty(liveScheduledDeparture))
379+
{
380+
var liveDepartureTime = ParseTimetableDateTime(liveActualDeparture);
381+
var liveScheduledTime = ParseTimetableDateTime(liveScheduledDeparture);
382+
383+
if (liveDepartureTime.HasValue && liveScheduledTime.HasValue)
384+
{
385+
delay = (int)(liveDepartureTime.Value - liveScheduledTime.Value).TotalMinutes;
386+
departureTime = liveDepartureTime; // Use live time
387+
}
388+
}
389+
390+
// Check for cancellation status in changes
391+
var liveStatus = changeDp.Attribute("cs")?.Value;
392+
if (liveStatus == "c")
393+
{
394+
isCancelled = true;
395+
}
396+
397+
// Get changed platform if available
398+
var liveChangedPlatform = changeDp.Attribute("cp")?.Value;
399+
if (!string.IsNullOrEmpty(liveChangedPlatform))
400+
{
401+
changedPlatform = liveChangedPlatform;
402+
}
403+
}
404+
405+
// Get messages from changes (these are more up-to-date)
406+
var changeMessages = string.Join("; ", changeStop.Elements("m")
407+
.Select(m => m.Attribute("t")?.Value)
408+
.Where(m => !string.IsNullOrEmpty(m)));
409+
410+
if (!string.IsNullOrEmpty(changeMessages))
411+
{
412+
messages = changeMessages;
413+
}
414+
}
415+
}
416+
// Fallback: if no changes data, calculate delay from timetable data
417+
else if (scheduledDepartureTime.HasValue && departureTime.HasValue)
359418
{
360419
delay = (int)(departureTime.Value - scheduledDepartureTime.Value).TotalMinutes;
361420
}
362421

363-
// Check for cancellation
364-
var isCancelled = departureElement.Attribute("cs")?.Value == "c";
365-
366-
// Get messages
367-
var messages = string.Join("; ", stop.Elements("m")
368-
.Select(m => m.Attribute("t")?.Value)
369-
.Where(m => !string.IsNullOrEmpty(m)));
370-
371422
connections.Add(new ConnectionInfo
372423
{
373424
TrainId = trainId,

0 commit comments

Comments
 (0)