aboutsummaryrefslogtreecommitdiff
path: root/src/Enmarcha.Backend/Services/Processors/NextStopsProcessor.cs
blob: 517faae021e0ce7ac02f6315be371ac03b6f364f (plain)
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" or "lugo")
        {
            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}) {item}";
                    }

                    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]);
    }
}