1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
using System.Text;
using Enmarcha.Sources.OpenTripPlannerGql.Queries;
namespace Enmarcha.Backend.Services.Processors;
public class NextStopsProcessor : IArrivalsProcessor
{
private readonly FeedService _feedService;
public NextStopsProcessor(FeedService feedService)
{
_feedService = feedService;
}
public Task ProcessAsync(ArrivalsContext context)
{
if (context.IsNano) return Task.CompletedTask;
var feedId = context.StopId.Split(':')[0];
foreach (var arrival in context.Arrivals)
{
if (arrival.RawOtpTrip is not ArrivalsAtStopResponse.Arrival otpArrival) continue;
if (arrival.Headsign.Marquee is not null) continue;
// Filter stoptimes that are after the current stop's departure
var currentStopDeparture = otpArrival.ScheduledDepartureSeconds;
if (feedId == "xunta")
{
arrival.NextStops = otpArrival.Trip.Stoptimes
.Where(s => s.ScheduledDeparture > currentStopDeparture)
.OrderBy(s => s.ScheduledDeparture)
.Select(s => s.Stop.Description)
.Distinct()
.ToList();
}
else
{
arrival.NextStops = otpArrival.Trip.Stoptimes
.Where(s => s.ScheduledDeparture > currentStopDeparture)
.OrderBy(s => s.ScheduledDeparture)
.Select(s => FeedService.NormalizeStopName(feedId, s.Stop.Name))
.ToList();
}
arrival.Headsign.Marquee = GenerateMarquee(feedId, arrival.NextStops);
}
return Task.CompletedTask;
}
private static string? GenerateMarquee(string feedId, List<string> nextStops)
{
if (nextStops.Count == 0) return null;
if (feedId is "vitrasa" or "tranvias" or "tussa" or "ourense")
{
var streets = nextStops
.Select(FeedService.GetStreetName)
.Where(s => !string.IsNullOrWhiteSpace(s))
.Distinct()
.ToList();
return string.Join(" - ", streets);
}
if (feedId == "xunta")
{
var points = nextStops
.Select(SplitXuntaStopDescription)
.ToList();
List<string> seenConcellos = new();
List<string> seenParroquias = new();
List<string> items = [];
foreach (var (parroquia, concello) in points)
{
// Santiago de Compostela -- Santiago de Compostela > Conxo -- Santiago de Compostela > Biduído -- Ames > Calo -- Teo > Bugallido -- Ames
// Santiago de Compostela -> Conxo -> Bidueiro (Ames) -> Calo (Teo) -> Bugallido
string item = "";
if (!seenParroquias.Contains(parroquia))
{
seenParroquias.Add(parroquia);
item += $"{parroquia}";
if (parroquia == concello)
{
seenConcellos.Add(concello);
}
if (!seenConcellos.Contains(concello))
{
seenConcellos.Add(concello);
item += $" ({concello})";
}
items.Add(item);
}
}
return string.Join(" > ", items);
}
return feedId switch
{
"renfe" => string.Join(" - ", nextStops),
_ => string.Join(", ", nextStops.Take(4))
};
}
private static (string parroquia, string concello) SplitXuntaStopDescription(string stopName)
{
var parts = stopName.Split(" -- ", 2);
if (parts.Length != 2)
{
return ("", ""); // TODO: Throw
}
return (parts[0], parts[1]);
}
}
|