aboutsummaryrefslogtreecommitdiff
path: root/src/Costasdev.Busurbano.Backend/Services/FareService.cs
blob: 9a11a569a702f3ee27ef01d0f852d88582a2b8f3 (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
using Costasdev.Busurbano.Backend.Configuration;
using Costasdev.Busurbano.Backend.Types.Planner;
using Microsoft.Extensions.Options;

namespace Costasdev.Busurbano.Backend.Services;

public record FareResult(double CashFareEuro, double CardFareEuro);

public class FareService
{
    private readonly AppConfiguration _config;

    public FareService(IOptions<AppConfiguration> config)
    {
        _config = config.Value;
    }

    public FareResult CalculateFare(IEnumerable<Leg> legs)
    {
        var busLegs = legs.Where(l => l.Mode != null && l.Mode.ToUpper() != "WALK").ToList();

        // Cash fare logic
        double cashFare = 0;
        foreach (var leg in busLegs)
        {
            // TODO: In the future, this should depend on the operator/feed
            if (leg.FeedId == "vitrasa")
            {
                cashFare += 1.63;
            }
            else
            {
                cashFare += 1.63; // Default fallback
            }
        }

        // Card fare logic (45-min transfer window)
        int cardTicketsRequired = 0;
        DateTime? lastTicketPurchased = null;
        int tripsPaidWithTicket = 0;
        string? lastFeedId = null;

        foreach (var leg in busLegs)
        {
            // If no ticket purchased, ticket expired (no free transfers after 45 mins), or max trips with ticket reached
            // Also check if we changed operator (assuming no free transfers between different operators for now)
            if (lastTicketPurchased == null ||
                (leg.StartTime - lastTicketPurchased.Value).TotalMinutes > 45 ||
                tripsPaidWithTicket >= 3 ||
                leg.FeedId != lastFeedId)
            {
                cardTicketsRequired++;
                lastTicketPurchased = leg.StartTime;
                tripsPaidWithTicket = 1;
                lastFeedId = leg.FeedId;
            }
            else
            {
                tripsPaidWithTicket++;
            }
        }

        return new FareResult(cashFare, cardTicketsRequired * 0.67);
    }
}