Beispiel #1
0
        public static void HandlePurchase(FlightPath leavingPath, FlightPath?returningPath, DateTime leavingDate, DateTime?returningDate, PaymentType paymentType, bool oneWay)
        {
            List <Ticket> tickets = new();

            // make tickets for the appropriate flight paths
            if (oneWay)
            {
                tickets = CreateListOfTickets(leavingPath, paymentType, leavingDate);
            }
            else
            {
                if (returningDate != null)
                {
                    var nonNullable = (DateTime)returningDate;
                    tickets = CreateListOfTickets(leavingPath, paymentType, leavingDate);
                    tickets.AddRange(CreateListOfTickets(returningPath, paymentType, nonNullable));
                }
            }

            // determine the total cost by whether or not the trip is one way
            int totalCost = oneWay ? leavingPath.IntPrice : leavingPath.IntPrice + returningPath.IntPrice;



            // add the trip to the db table, and to the customer in the db
            using (var db = new AirContext())
            {
                var custInfo = db.Users.Include(user => user.CustInfo).Single(dbuser => dbuser.UserId == UserSession.userId).CustInfo;
                // make a new trip with the appropriate info
                Trip trip = new()
                {
                    OriginAirportId      = leavingPath.flights[0].Origin.AirportId,
                    DestinationAirportId = leavingPath.flights[^ 1].Destination.AirportId,
Beispiel #2
0
        public static List <Ticket> CreateListOfTickets(FlightPath path, PaymentType paymentType, DateTime date)
        {
            var scheduledFlights = new List <ScheduledFlight>();

            using var db = new AirContext();
            foreach (Flight flight in path.flights)
            {
                // see if a scheduled flight exists for this flight on this day already
                var sf = db.ScheduledFlights.Include(sf => sf.Flight).ThenInclude(fl => fl.PlaneType).Where(sf => sf.Flight.FlightId == flight.FlightId).SingleOrDefault(sf => sf.DepartureTime.Date == date);
                if (sf != null)
                {
                    // If a flight exists already, simply add it to our list of scheduled flights
                    scheduledFlights.Add(sf);
                }
                else
                {
                    // Otherwise, we need to make a scheduled flight for it
                    var sfNew = new ScheduledFlight
                    {
                        FlightId         = flight.FlightId,
                        DepartureTime    = date.Add(flight.DepartureTime),
                        TicketsPurchased = 1
                    };
                    // add it to our list
                    scheduledFlights.Add(sfNew);
                    // and the db
                    db.ScheduledFlights.Add(sfNew);
                    db.SaveChanges();
                }
            }

            var tickets = new List <Ticket>();

            foreach (ScheduledFlight sf in scheduledFlights)
            {
                // Now we need to make a ticket for each scheduled flight
                var ticket = new Ticket
                {
                    Flight      = sf,
                    PaymentType = paymentType
                };
                // Increment the amount of tickets purchased
                sf.TicketsPurchased++;
                // add it to our list to return
                tickets.Add(ticket);
                // and add it to the db
                db.Tickets.Add(ticket);
                db.SaveChanges();
            }

            // return the tickets we made
            return(tickets);
        }
Beispiel #3
0
        public static List <FlightPath> GenerateRoutes(Airport originAirport, Airport destinationAirport, DateTime date)
        {
            // This method generates all flights with 0, 1, or 2 connections
            // returning after it finds flights with the smallest amount of connections,
            // because they will always be ideal
            // This does not return a single best path to take, as we want to provide
            // options to our consumers, so we provide ALL paths from originAirport
            // to destinationAirport with the smallest amount of connections possible

            TimeSpan minLayover  = new(0, 40, 0);          // 40 minute minimum layover
            TimeSpan maxLayover  = new(8, 0, 0);           // 8 hour maximum layover -- not in specification, but will make for nicer trips
            TimeSpan currentTime = DateTime.Now.TimeOfDay; // current time, so we don't show you flights from earlier in the day
            DateTime today       = DateTime.Today.Date;    // current date, used with current time to not show flights you can't get to

            using (var db = new AirContext())
            {
                // This query grabs all direct flights, comments follow inline
                var direct = db.Flights                             // on the entire flights table of the db
                             .Include(flight => flight.Origin)      // ensure that we have access to the origin airports info later
                             .Include(flight => flight.Destination) // ensure that we have access to the destination airports info later
                             .Where(flight => !flight.IsCanceled && // only take flights that are not canceled (by staff member)
                                    flight.Origin == originAirport && // the origin of the flight should match the origin airport passed in
                                    flight.Destination == destinationAirport) // and the destination airports should match
                             .ToList();                                       // then turn it into a list
                var directPaths = direct.Select(flight => new FlightPath(flight)).ToList();
                var toRemoveOne = new List <FlightPath>();
                for (int i = 0; i < directPaths.Count; i++)
                {
                    var f1 = directPaths[i].flights[0];
                    // remove flights that have already taken off
                    if (date == today && f1.DepartureTime < currentTime)
                    {
                        toRemoveOne.Add(directPaths[i]);
                        continue;
                    }
                    var sf1 = db.ScheduledFlights.Include(sf => sf.Flight).ThenInclude(fl => fl.PlaneType).Where(sf => sf.Flight.FlightId == f1.FlightId).SingleOrDefault(sf => sf.DepartureTime.Date == date);
                    if (sf1 != null && sf1.TicketsPurchased >= sf1.Flight.PlaneType.MaxSeats)
                    {
                        // Flight 1 already exists in db & is full
                        toRemoveOne.Add(directPaths[i]);
                        continue;
                    }
                }

                foreach (FlightPath spot in toRemoveOne)
                {
                    directPaths.Remove(spot);
                }

                if (directPaths.Count > 0)
                {
                    // If we have direct flights, they will literally always be better
                    // than non-direct in both cost and time so we can just return them and not
                    // calculate any worse flights
                    // also convert them to a FlightPath with a single flight, so that
                    // we can display them properly
                    return(directPaths);
                }

                // this query grabs all non canceled flights from the db
                var flights = db.Flights                             // on the entire flights table of the db
                              .Include(flight => flight.Origin)      // ensure that we have access to the origin airports info later
                              .Include(flight => flight.Destination) // ensure that we have access to the destination airports info later
                              .Where(flight => !flight.IsCanceled);  // only take flights that are not canceled (by staff member)
                // this query uses the flights query we just made to grab all flights
                // with 2 legs, i.e. 1 connection from the db
                TimeSpan ts             = new(0, 40, 0);
                var      twoLeggedQuery = from flight in flights               // for each flight in the flights variable
                                          where flight.Origin == originAirport // where the origin of the flight is our origin airport
                                                                               // join in a new flight "connection" from the flights variable, that has the same origin as our first flights destination
                                          join connection in flights on flight.Destination equals connection.Origin
                                          where connection.Destination == destinationAirport
                                          // only do this where the connections destination, is the overall destination of the trip
                                          select new FlightPath(flight, connection); // turn the results into a new flight path, with both the first flight and the connection

                var twoLeggedFlights = twoLeggedQuery.ToList();                      // turn the results of our query into a list so that we can return it nicely

                var toRemoveTwo = new List <FlightPath>();
                for (int i = 0; i < twoLeggedFlights.Count; i++)
                {
                    FlightPath route = twoLeggedFlights[i];
                    Flight     f1    = route.flights[0];
                    Flight     f2    = route.flights[1];
                    // remove flight paths where 1 or more flights have already taken off
                    if (date == today && f1.DepartureTime < currentTime || f2.DepartureTime < currentTime)
                    {
                        toRemoveTwo.Add(route);
                        continue;
                    }

                    TimeSpan f1Arrive = f1.GetArrivalTime();
                    if (f1Arrive > f2.DepartureTime)
                    {
                        // Arrival time is after departure of the other flight
                        toRemoveTwo.Add(route);
                        continue;
                    }

                    if (f2.DepartureTime - f1.GetArrivalTime() < minLayover)
                    {
                        // Arrival time is less than 40 minutes before next flight would take off, so we don't offer
                        toRemoveTwo.Add(route);
                        continue;
                    }

                    if (f2.DepartureTime - f1.GetArrivalTime() > maxLayover)
                    {
                        // Arrival time is more than 8 hours before next flight would take off, so we don't offer
                        toRemoveTwo.Add(route);
                        continue;
                    }

                    var sf1 = db.ScheduledFlights.Include(sf => sf.Flight).ThenInclude(fl => fl.PlaneType).Where(sf => sf.Flight.FlightId == f1.FlightId).SingleOrDefault(sf => sf.DepartureTime.Date == date);
                    var sf2 = db.ScheduledFlights.Include(sf => sf.Flight).ThenInclude(fl => fl.PlaneType).Where(sf => sf.Flight.FlightId == f2.FlightId).SingleOrDefault(sf => sf.DepartureTime.Date == date);
                    if (sf1 != null && sf1.TicketsPurchased >= sf1.Flight.PlaneType.MaxSeats)
                    {
                        // Flight 1 already exists in db & is full
                        toRemoveTwo.Add(route);
                        continue;
                    }
                    if (sf2 != null && sf2.TicketsPurchased >= sf2.Flight.PlaneType.MaxSeats)
                    {
                        // Flight 2 already exists in db & is full
                        toRemoveTwo.Add(route);
                        continue;
                    }
                }

                foreach (FlightPath spot in toRemoveTwo)
                {
                    twoLeggedFlights.Remove(spot);
                }

                if (twoLeggedFlights.Count > 0)
                {
                    // Again if we have 2 legged flights, they will always be better
                    // than 3 legged flights in cost & time, so we can return them
                    // and not calculate any worse flights
                    return(twoLeggedFlights);
                }

                // this query uses the flights query we made earlier to grab all flights
                // with 3 legs, i.e. 2 connections from the db
                var threeLeggedQuery = from flight in flights               // for each flight in the flights variable
                                       where flight.Origin == originAirport // where the origin of our flight is our origin airport
                                                                            // join in a new flight "connection" from the flights variable, that has the same origin as our first flights destination
                                       join connection in flights on flight.Destination equals connection.Origin
                                                                            // join in a new flight "secondConnection" from the flights variable, that has the same origin as our first connections destination
                                       join secondConnection in flights on connection.Destination equals secondConnection.Origin
                                       where secondConnection.Destination == destinationAirport
                                       // only do this where the secondConnections destination is the overall destination of the trip
                                       select new FlightPath(flight, connection, secondConnection); // turn the results into a new flight path, with all 3 flights

                var threeLeggedFlights = threeLeggedQuery.ToList();                                 // turn the results of our query into a list so that we can return it nicely
                var toRemoveThree      = new List <FlightPath>();
                for (int i = 0; i < threeLeggedFlights.Count; i++)
                {
                    FlightPath route = threeLeggedFlights[i];
                    Flight     f1    = route.flights[0];
                    Flight     f2    = route.flights[1];
                    Flight     f3    = route.flights[2];
                    // remove paths where 1 or more flights have already taken off
                    if (date == today && f1.DepartureTime < currentTime || f2.DepartureTime < currentTime || f3.DepartureTime < currentTime)
                    {
                        toRemoveThree.Add(route);
                        continue;
                    }

                    TimeSpan f1Arrive = f1.GetArrivalTime();
                    TimeSpan f2Arrive = f2.GetArrivalTime();

                    if (f1Arrive > f2.DepartureTime || f2Arrive > f3.DepartureTime)
                    {
                        // Arrival time is after departure of the other flight
                        // on either leg, so we remove
                        toRemoveThree.Add(route);
                        continue;
                    }

                    if (f2.DepartureTime - f1Arrive < minLayover || f3.DepartureTime - f2Arrive < minLayover)
                    {
                        // Arrival time is less than 40 minutes before next flight would take off, so we don't offer
                        // on either leg
                        toRemoveThree.Add(route);
                        continue;
                    }

                    if (f2.DepartureTime - f1Arrive > maxLayover || f3.DepartureTime - f2Arrive > maxLayover)
                    {
                        // Arrival time is more than 8 hours before next flight would take off, so we don't offer
                        // on either leg
                        toRemoveThree.Add(route);
                        continue;
                    }

                    var sf1 = db.ScheduledFlights.Include(sf => sf.Flight).ThenInclude(fl => fl.PlaneType).Where(sf => sf.Flight.FlightId == f1.FlightId).SingleOrDefault(sf => sf.DepartureTime.Date == date);
                    var sf2 = db.ScheduledFlights.Include(sf => sf.Flight).ThenInclude(fl => fl.PlaneType).Where(sf => sf.Flight.FlightId == f2.FlightId).SingleOrDefault(sf => sf.DepartureTime.Date == date);
                    var sf3 = db.ScheduledFlights.Include(sf => sf.Flight).ThenInclude(fl => fl.PlaneType).Where(sf => sf.Flight.FlightId == f3.FlightId).SingleOrDefault(sf => sf.DepartureTime.Date == date);
                    if (sf1 != null && sf1.TicketsPurchased >= sf1.Flight.PlaneType.MaxSeats)
                    {
                        // Flight 1 already exists in db & is full
                        toRemoveThree.Add(route);
                        continue;
                    }
                    if (sf2 != null && sf2.TicketsPurchased >= sf2.Flight.PlaneType.MaxSeats)
                    {
                        // Flight 2 already exists in db & is full
                        toRemoveThree.Add(route);
                        continue;
                    }
                    if (sf3 != null && sf3.TicketsPurchased >= sf3.Flight.PlaneType.MaxSeats)
                    {
                        // Flight 3 already exists in db & is full
                        toRemoveThree.Add(route);
                        continue;
                    }
                }

                foreach (FlightPath spot in toRemoveThree)
                {
                    threeLeggedFlights.Remove(spot);
                }

                if (threeLeggedFlights.Count > 0)
                {
                    // Finally return our 3 legged flights
                    return(threeLeggedFlights);
                }
            }
            // if we made it out of the algorithm without returning, then that means
            // that it is not possible to get from originAirport to destinationAirport
            // with 2 or fewer connections.
            // according to the specifications of this project, we cannot have more
            // than 2 connections, so we error out and return a blank list
            return(new List <FlightPath>());
        }