using System.Collections.Generic;
using System.Threading.Tasks;
namespace FlightRoutesCalculatorApp
public class HomeController : Controller
private IFlightCatalogService _flightCatalogService { get; set; }
private IRoutesCatalogService _routesCatalogService { get; set; }
private ICheapestFlightRouteService _cheapestFlightRouteService { get; set; }
_flightCatalogService = new FlightCatalogService();
_routesCatalogService = new RoutesCatalogService();
_cheapestFlightRouteService = new CheapestFlightRouteService(_routesCatalogService);
public async Task<ActionResult> Index()
var flightsCatalog = await _flightCatalogService.GetCatalog();
var cheapestFlightRoute = _cheapestFlightRouteService.SearchCheapestFlightRoute(flightsCatalog.OutboundFlights, flightsCatalog.InboundFlights);
var validInboundFlights = _routesCatalogService.GetAllowedFlightRoutesIds(cheapestFlightRoute.OutboundFlight, flightsCatalog.InboundFlights);
FlightRoutesViewModel model = new FlightRoutesViewModel(flightsCatalog.OutboundFlights, flightsCatalog.InboundFlights, cheapestFlightRoute, validInboundFlights);
public async Task<ActionResult> Index(FlightRoutesViewModel frm)
var flightsCatalog = await _flightCatalogService.GetCatalog();
int outboundFlightId = int.Parse(frm.OutboundFlightSelectedId);
var outboundFlight = flightsCatalog.OutboundFlights.Where(c => c.Id == outboundFlightId).FirstOrDefault();
IList<Flight> singleOutboundFlightList = new List<Flight>();
singleOutboundFlightList.Add(outboundFlight);
var cheapestFlightRoute = _cheapestFlightRouteService.SearchCheapestFlightRoute(singleOutboundFlightList, flightsCatalog.InboundFlights);
var validInboundFlights = _routesCatalogService.GetAllowedFlightRoutesIds(cheapestFlightRoute?.OutboundFlight, flightsCatalog?.InboundFlights);
FlightRoutesViewModel vm = new FlightRoutesViewModel(flightsCatalog.OutboundFlights, flightsCatalog.InboundFlights, cheapestFlightRoute, validInboundFlights);
#region Flight Catalog Service
public interface IFlightCatalogService
Task<FlightCatalog> GetCatalog();
public class FlightCatalogService : IFlightCatalogService
static readonly HttpClient client = new HttpClient();
public async Task<FlightCatalog> GetCatalog()
FlightCatalog flightCatalog = null;
HttpResponseMessage response = await client.GetAsync("http://www.mocky.io/v2/5cebcb7d330000cc296d7772");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
flightCatalog = JsonConvert.DeserializeObject<FlightCatalog>(responseBody);
Console.WriteLine("\nException Caught!");
Console.WriteLine("Message :{0} ", e.Message);
public class FlightCatalog
public IList<Flight> OutboundFlights { get; set; }
public IList<Flight> InboundFlights { get; set; }
public int Id { get; set; }
public string Airline { get; set; }
public string DepartureAirportCode { get; set; }
public string ArrivalAirportCode { get; set; }
public decimal Price { get; set; }
#region Routes Catalog Service
public interface IRoutesCatalogService
IEnumerable<FlightRoutes> GetAllRoutes(IList<Flight> outboundFlights, IList<Flight> inboundFlights);
IList<int> GetAllowedFlightRoutesIds(Flight outboundFlight, IList<Flight> inboundFlights);
public class RoutesCatalogService : IRoutesCatalogService
public IEnumerable<FlightRoutes> GetAllRoutes(IList<Flight> outboundFlights, IList<Flight> inboundFlights)
if (outboundFlights == null || inboundFlights == null) return null;
var routesWithAirLineMatchCatalog = from outbound in outboundFlights
join inbound in inboundFlights on new { X1 = outbound.DepartureAirportCode, X2 = outbound.ArrivalAirportCode, X3 = outbound.Airline } equals new { X1 = inbound.ArrivalAirportCode, X2 = inbound.DepartureAirportCode, X3 = inbound.Airline }
select new FlightRoutes(outbound, inbound);
if (routesWithAirLineMatchCatalog != null)
return routesWithAirLineMatchCatalog;
var routesWithoutAirLineMatchCatalog = from outbound in outboundFlights
join inbound in inboundFlights on new { X1 = outbound.DepartureAirportCode, X2 = outbound.ArrivalAirportCode } equals new { X1 = inbound.ArrivalAirportCode, X2 = inbound.DepartureAirportCode }
select new FlightRoutes(outbound, inbound);
return routesWithoutAirLineMatchCatalog;
public IList<int> GetAllowedFlightRoutesIds(Flight outboundFlight, IList<Flight> inboundFlights)
if (outboundFlight == null || inboundFlights == null)
IList<Flight> singleOutboundFligthList = new List<Flight>();
singleOutboundFligthList.Add(outboundFlight);
var flightRoutes = GetAllRoutes(singleOutboundFligthList, inboundFlights);
if (flightRoutes == null)
IList<int> validInboundFlightsIdsList = new List<int>();
foreach (var route in flightRoutes)
validInboundFlightsIdsList.Add(route.InboundFlight.Id);
return validInboundFlightsIdsList;
public class FlightRoutes
public Flight OutboundFlight { get; set;}
public Flight InboundFlight { get; set;}
public FlightRoutes(Flight outboundFlight, Flight inboundFlight)
OutboundFlight = outboundFlight;
InboundFlight = inboundFlight;
#region Cheapest Flight Route
public interface ICheapestFlightRouteService
CheapestFlightRoute SearchCheapestFlightRoute(IList<Flight> outboundFlights, IList<Flight> inboundFlights);
public class CheapestFlightRouteService : ICheapestFlightRouteService
private IRoutesCatalogService _routeCatalogService;
public CheapestFlightRouteService(IRoutesCatalogService routeCatalogService)
_routeCatalogService = routeCatalogService;
public CheapestFlightRoute SearchCheapestFlightRoute(IList<Flight> outboundFlights, IList<Flight> inboundFlights)
IList<CheapestFlightRoute> routesTotalPriceList = new List<CheapestFlightRoute>();
var routes = _routeCatalogService.GetAllRoutes(outboundFlights, inboundFlights);
foreach (var item in routes)
routesTotalPriceList.Add(new CheapestFlightRoute(item.OutboundFlight, item.InboundFlight, item.OutboundFlight.Price + item.InboundFlight.Price));
return routesTotalPriceList.OrderBy(c => c.TotalPrice).FirstOrDefault();
public class CheapestFlightRoute
public Flight OutboundFlight { get; set;}
public Flight InboundFlight { get; set;}
public decimal TotalPrice { get; set;}
public CheapestFlightRoute(Flight outboundFlight, Flight inboundFlight, decimal totalPrice)
OutboundFlight = outboundFlight;
InboundFlight = inboundFlight;
public class FligthRoutesTest
private IFlightCatalogService _flightCatalogService { get; set; }
private IRoutesCatalogService _routesCatalogService { get; set; }
private ICheapestFlightRouteService _cheapestFlightRouteService { get; set; }
private FlightCatalog _catalogFlights { get; set; }
public FligthRoutesTest()
_flightCatalogService = new FlightCatalogService();
_routesCatalogService = new RoutesCatalogService();
_cheapestFlightRouteService = new CheapestFlightRouteService(_routesCatalogService);
[InlineData(1, "AMS", "BCN")]
public async Task Should_Get_From_OutboundFlightId_1_A_Valid_Inbound_Flight_Route_AMS_BCN(int outboundFlightId, string inboundDepartureExpected, string inboundArribalExpected)
_catalogFlights = await _flightCatalogService.GetCatalog();
Flight outboundFlight = _catalogFlights.OutboundFlights.Where(c => c.Id == outboundFlightId).FirstOrDefault();
IRoutesCatalogService sut = new RoutesCatalogService();
var result = sut.GetAllowedFlightRoutesIds(outboundFlight, _catalogFlights.InboundFlights);
foreach(var id in result)
Flight inboundFlight = _catalogFlights.InboundFlights.Where(c => c.Id == id).FirstOrDefault();
Assert.Equal(inboundDepartureExpected, inboundFlight.DepartureAirportCode);
Assert.Equal(inboundArribalExpected, inboundFlight.ArrivalAirportCode);
[InlineData(2, "AMS", "BCN")]
public async Task Should_Get_A_OutboundFlightId_2_Valid_Inbound_Flight_Route_AMS_BCN(int outboundFlightId, string inboundDepartureExpected, string inboundArribalExpected)
_catalogFlights = await _flightCatalogService.GetCatalog();
Flight outboundFlight = _catalogFlights.OutboundFlights.Where(c => c.Id == outboundFlightId).FirstOrDefault();
IRoutesCatalogService sut = new RoutesCatalogService();
var result = sut.GetAllowedFlightRoutesIds(outboundFlight, _catalogFlights.InboundFlights);
foreach (var id in result)
Flight inboundFlight = _catalogFlights.InboundFlights.Where(c => c.Id == id).FirstOrDefault();
Assert.Equal(inboundDepartureExpected, inboundFlight.DepartureAirportCode);
Assert.Equal(inboundArribalExpected, inboundFlight.ArrivalAirportCode);
[InlineData(3, "AMS", "GIR")]
public async Task Should_Get_A_OutboundFlightId_2_Valid_Inbound_Flight_Route_AMS_GIR(int outboundFlightId, string inboundDepartureExpected, string inboundArribalExpected)
_catalogFlights = await _flightCatalogService.GetCatalog();
Flight outboundFlight = _catalogFlights.OutboundFlights.Where(c => c.Id == outboundFlightId).FirstOrDefault();
IRoutesCatalogService sut = new RoutesCatalogService();
var result = sut.GetAllowedFlightRoutesIds(outboundFlight, _catalogFlights.InboundFlights);
foreach (var id in result)
Flight inboundFlight = _catalogFlights.InboundFlights.Where(c => c.Id == id).FirstOrDefault();
Assert.Equal(inboundDepartureExpected, inboundFlight.DepartureAirportCode);
Assert.Equal(inboundArribalExpected, inboundFlight.ArrivalAirportCode);