// fill the database with fake data for last month, using a test clock public static void FillLastMonthData(ParkingDatabase database, IClock testClock) { try { // fill with database with fake data for (int i = 0; i < 80; i++) { CustomerAccount testAccount = new CustomerAccount(RandomString(), RandomString(), "555-555-5555", RandomString() + "@tester.com", "password"); Billing.CreditCard.CreditCardType randomCardType = (Billing.CreditCard.CreditCardType)random.Next(3); Billing.CreditCard testCard = new Billing.CreditCard(1234123412349876, Billing.CreditCard.CreditCardType.MASTERCARD); Accounts.Vehicle testVehicle = new Accounts.Vehicle(RandomString() + " " + RandomString(), RandomString()); DateTime startDate = new DateTime(2012, 11, 25, 10, 0, 0); // 11-25-12 @ 10a DateTime testResDate = RandomTime(startDate); database.AddAccount(testAccount); database.AddCreditCard(testCard, testAccount.CustomerID); database.AddVehicle(testVehicle, testAccount.CustomerID); ParkingReservation testReservation = new ParkingReservation(testAccount, testVehicle, testResDate, 120); // generate a random transaction date in the past int hours = random.Next(1, 500); TimeSpan timeSpan = new TimeSpan(hours, 0, 0); DateTime transactionDate = testResDate.Subtract(timeSpan); // add reservation (and transaction) to database database.AddReservation(testReservation, testCard.CardID, transactionDate); } } catch (Exception) { } // confict when adding reservation (ignore) }
static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // set up the print, mailer, and barrier external components to be used (stubs for now) ITerminalPrinter printer = new TerminalPrinterStub(); IMailer mailer = new MailerStub(); IBarrier barrier = new BarrierStub(); // set up test environment // source: http://stackoverflow.com/questions/43711/whats-a-good-way-to-overwrite-datetime-now-during-testing DateTime testTime = new DateTime(2012, 12, 30, 13, 1, 0); IClock testClock = new TestClock(testTime); // a static clock for testing ParkingDatabase database = new ParkingDatabase(testClock, mailer); // fill with database with fake data for (int i = 0; i < 80; i++) { // create a random customer (including vehicle and billing info) and reservation CustomerAccount testAccount = new CustomerAccount(RandomString(), RandomString(), "555-555-5555", RandomString() + "@tester.com", "password"); Billing.CreditCard.CreditCardType randomCardType = (Billing.CreditCard.CreditCardType)random.Next(3); Billing.CreditCard testCard = new Billing.CreditCard(1234123412349876, Billing.CreditCard.CreditCardType.MASTERCARD); Accounts.Vehicle testVehicle = new Accounts.Vehicle(RandomString() + " " + RandomString(), RandomString()); DateTime startDate = new DateTime(2012, 12, 30, 10, 0, 0); // date to start generating from DateTime testResDate = RandomTime(startDate); // add fake customer data to database database.AddAccount(testAccount); database.AddCreditCard(testCard, testAccount.CustomerID); database.AddVehicle(testVehicle, testAccount.CustomerID); ParkingReservation testReservation = new ParkingReservation(testAccount, testVehicle, testResDate, 120); // generate a random transaction date in the past int hours = random.Next(1, 500); TimeSpan timeSpan = new TimeSpan(hours, 0, 0); DateTime transactionDate = testResDate.Subtract(timeSpan); try { // add fake reservation data to the database database.AddReservation(testReservation, testCard.CardID, transactionDate); // check in with 50% chance if (random.Next(2) == 0) { // change status of reservation, if reservation is not in the future if (testReservation.Date < testClock.Now) { database.ModifyReservation(testReservation, testReservation.ParkingSpotID, testReservation.Date, testReservation.DurationMinutes, true, testReservation.ReservationVehicle.CarID); // change status of parking garage spot database.SetParkingSpotStatus(testReservation.ParkingSpotID, 1); } } } catch (Exception) { } // conflict when adding reservation (ignore) } // fill database with fake data for last month FillLastMonthData(database, testClock); // reminder of admin credentials, for testing System.Windows.Forms.MessageBox.Show( string.Format("You can login as admin with\nemail: {0}\npassword: {1}", "*****@*****.**", "password")); Application.Run(new UserForm(testClock, mailer, database, true)); }
// modify a reservation with the given information public void ModifyReservation(ParkingReservation oldReservation, int newParkingSpot, DateTime newDateTime, int newDuration, bool newStatus, int newVehicleID) { // update the reservation in the database table reservationTableAdapter.UpdateReservation(newVehicleID, newDateTime, newDuration, newParkingSpot, newStatus, oldReservation.ReservationID); }
// return true if the reservation modification from oldRes to newRes is valid. // this is the case if it doesn't conflict with other existing reservations public bool ReservationModificationValid(ParkingReservation oldRes, ParkingReservation newRes) { // Query for available spots during given time ParkingManagementDataContext db = new ParkingManagementDataContext(); Table<Reservation> Reservations = db.GetTable<Reservation>(); // find possible conflicts var conflicts = from res in Reservations where ((res.DateTime < newRes.ReservationEndTime) && (res.DateTime >= newRes.Date)) || ((res.DateTime < newRes.Date) && (res.DateTime.Add(new TimeSpan(0, res.DurationMinutes, 0)) > newRes.Date)) where res.ParkingSpot.ParkingSpotID == newRes.ParkingSpotID where res.CustomerID != oldRes.Customer.CustomerID select res; // if there any conflicts, then return true; else, false if (!conflicts.Any()) { return true; } else { return false; } }
// get a reservation object for the given reservation number public ParkingReservation GetReservation(int reservationNumber) { ParkingReservation reservation = null; try { // Query for customers with given email ParkingManagementDataContext db = new ParkingManagementDataContext(); Table<Reservation> Reservations = db.GetTable<Reservation>(); var query = from res in Reservations where res.ReservationID == reservationNumber select res; // check if any results were found if (query.Any()) { Reservation dbRes = query.First(); // create a new reservation, based on the database information reservation = new ParkingReservation(dbRes.ReservationID, GetCustomerFromID(dbRes.CustomerID), GetVehicleFromID(dbRes.VehicleID), dbRes.DateTime, dbRes.DurationMinutes, dbRes.ParkingSpotID, dbRes.TicketKey, dbRes.IsCheckedIn); } else { throw new ReservationException("Reservation number could not be found."); } } catch (Exception e) { throw new ReservationException(e.Message); } return reservation; }
// return true if there are other available parking spots for the given reservation period public bool IsOtherParkingSpots(ParkingReservation desiredReservation) { // retrieve the reservation and parking spot tables ParkingManagementDataContext db = new ParkingManagementDataContext(); Table<Reservation> Reservations = db.GetTable<Reservation>(); Table<ParkingSpot> ParkingSpots = db.GetTable<ParkingSpot>(); // find unavailable spots var unavailableSpots = from spot in ParkingSpots join res in Reservations on spot.ParkingSpotID equals res.ParkingSpotID // if res start < des start && res end >= des start, then no where ((res.DateTime < desiredReservation.Date) && res.DateTime.AddMinutes(res.DurationMinutes) >= desiredReservation.Date) || // if res start = des start, then no (res.DateTime == desiredReservation.Date) || // res start > des start && res start <= des end, then no ((res.DateTime > desiredReservation.Date) && res.DateTime <= desiredReservation.ReservationEndTime) || // must be available res.ParkingSpot.AvailabilityStatus != 0 select spot; // find those spots that not unavailable (i.e. are available) var result = from spot in ParkingSpots where !unavailableSpots.Contains(spot) select new { spot.ParkingSpotID, spot.AvailabilityStatus }; // if there is at list one other spot, return true if (!result.Any()) { return false; } else { return true; } }
// Get a list of available parking spots for the given reservation period public List<Garage.ParkingSpot> GetAvailableParkingSpots(ParkingReservation desiredReservation) { List<Garage.ParkingSpot> spotList = null; try { // Query for spots that are not reserved during given time ParkingManagementDataContext db = new ParkingManagementDataContext(); Table<Reservation> Reservations = db.GetTable<Reservation>(); Table<ParkingSpot> ParkingSpots = db.GetTable<ParkingSpot>(); var unavailableSpots = from spot in ParkingSpots join res in Reservations on spot.ParkingSpotID equals res.ParkingSpotID // if res start < desred start && res end >= desired start, then no where ((res.DateTime < desiredReservation.Date) && res.DateTime.AddMinutes(res.DurationMinutes) >= desiredReservation.Date) || // if res start = des start, then no (res.DateTime == desiredReservation.Date) || // res start > des start && res start <= des end, then no ((res.DateTime > desiredReservation.Date) && res.DateTime <= desiredReservation.ReservationEndTime) || // must be available res.ParkingSpot.AvailabilityStatus != 0 select spot; // get those spots not found in the above list var result = from spot in ParkingSpots where !unavailableSpots.Contains(spot) select new { spot.ParkingSpotID, spot.AvailabilityStatus }; // if none available, throw an exception if (!result.Any()) { throw new ParkingSpotException("No available parking spots during the specified time period."); } // convert LINQ-to-SQL result list to a parking spot list spotList = result.AsEnumerable() .Select(o => new Garage.ParkingSpot { ParkingSpotID = o.ParkingSpotID, AvailabilityStatus = (Garage.ParkingSpot.Availibility)o.AvailabilityStatus }).ToList(); } catch (Exception) { throw new ParkingSpotException("Attempt to get available parking spots failed."); } return spotList; }
/** * Get the relevant reservation for a parking spot. * Relevant is defined as: * * if occupied, show reservation for person occcupying. * if not occupied, show reservation any current reservation * otherwise, show nothing * */ public ParkingReservation GetRelevantReservation(int parkingSpot) { ParkingReservation resToReturn = null; Reservation dbResToReturn = null; try { // Query for spots that are not reserved during given time ParkingManagementDataContext db = new ParkingManagementDataContext(); Table<Reservation> Reservations = db.GetTable<Reservation>(); Table<ParkingSpot> ParkingSpots = db.GetTable<ParkingSpot>(); // get parking spot from ID var reservationsStillCheckedIn = from spot in ParkingSpots join res in Reservations on spot.ParkingSpotID equals res.ParkingSpotID where spot.ParkingSpotID == parkingSpot where res.IsCheckedIn == true select res; // check if customer has overstaid bool customerOverstaid = false; if (reservationsStillCheckedIn.Any()) { var resCheckedIn = reservationsStillCheckedIn.First(); TimeSpan resDuration = new TimeSpan(0, resCheckedIn.DurationMinutes, 0); DateTime resEnd = resCheckedIn.DateTime.Add(resDuration); if (resEnd < DatabaseClock.Now) { customerOverstaid = true; dbResToReturn = resCheckedIn; } } // if customer has not overstaid, find current reservation in effect if (!customerOverstaid) { var reservationsInEffect = from res in Reservations where ((res.DateTime <= DatabaseClock.Now) && res.DateTime.AddMinutes(res.DurationMinutes) > DatabaseClock.Now) where res.ParkingSpot.ParkingSpotID == parkingSpot select res; if (reservationsInEffect.Any()) { dbResToReturn = reservationsInEffect.First(); } } // create a ParkingReservation from the LINQ-to-SQL Reservation class if (dbResToReturn != null) { resToReturn = new ParkingReservation(dbResToReturn.ReservationID, GetCustomerFromID(dbResToReturn.CustomerID), GetVehicleFromID(dbResToReturn.VehicleID), dbResToReturn.DateTime, dbResToReturn.DurationMinutes, dbResToReturn.ParkingSpotID, dbResToReturn.TicketKey, dbResToReturn.IsCheckedIn); } } catch (Exception) { throw new ParkingSpotException("Attempt to get reservation failed."); } return resToReturn; }
// cancel and delete a reservation public void CancelReservation(ParkingReservation reservation) { // deletion in the reservation table should also cascade to transaction reservationTableAdapter.DeleteReservation(reservation.ReservationID); }
// add a reservation to the database (does not specifiy spotID, but specifies the transaction date) public ParkingReservation AddReservation(ParkingReservation res, int cardID, DateTime transactionDate) { int spotID = 1; try { // find random open spot List<Garage.ParkingSpot> availableSpots = GetAvailableParkingSpots(res); int spotIndex = rand.Next(0, availableSpots.Count); spotID = availableSpots[spotIndex].ParkingSpotID; res.ParkingSpotID = spotID; } catch (Exception) { throw new ReservationException("Could not add reservation to database."); } return AddReservation(res, cardID, spotID, transactionDate); }
// add a reservation to the database (specifices spotID) public ParkingReservation AddReservation(ParkingReservation res, int cardID, int spotID) { return AddReservation(res, cardID, spotID, DatabaseClock.Now); }
// add a reservation to the database public ParkingReservation AddReservation(ParkingReservation res, int cardID, int spotID, DateTime transactionDate) { try { res.ParkingSpotID = spotID; // generate random key int key = GenerateTicketKey(); res.TicketKey = key; // insert reservation into table int resID = Convert.ToInt32(reservationTableAdapter.InsertAndGetID( res.Customer.CustomerID, res.ReservationVehicle.CarID, res.Date, res.DurationMinutes, spotID, key, false)); // set reservation ID res.ReservationID = resID; // add transaction for reservation decimal cost = res.DurationMinutes * (HOURLY_RATE / 60); transactionTableAdapater.Insert(res.Customer.CustomerID, Decimal.Round(cost, 2), resID, 0, cardID, transactionDate); } catch (Exception) { throw new ReservationException("Could not add reservation to database."); } // mail receipt of the reservation to the customer Mailer.MailReservationReceipt(res); return res; }
// check the availability of the provided reservation and add (if available) private void checkAvailabilityButton_Click(object sender, EventArgs e) { if (InputIsValid()) { // retrieve the desired date based on the input DateTime desiredDate = new DateTime( desiredMonthCalendar.SelectionStart.Year, desiredMonthCalendar.SelectionStart.Month, desiredMonthCalendar.SelectionStart.Day, desiredTimeDateTimePicker.Value.Hour, desiredTimeDateTimePicker.Value.Minute, 0); // retrieve the vehicle based on the input Accounts.Vehicle desiredVehicle = vehicleComboBox.SelectedItem as Accounts.Vehicle; // create the reservation, based on the input ParkingReservation reservation = null; try { reservation = new ParkingReservation(Customer, desiredVehicle, desiredDate, Convert.ToInt32( DurationIndexToMinutes(durationComboBox.SelectedIndex))); // add reservation to database Billing.CreditCard chosenCard = paymentMethodComboBox.SelectedItem as Billing.CreditCard; int cardID = chosenCard.CardID; reservation = Database.AddReservation(reservation, cardID); // display result MessageBox.Show(String.Format("Successfully created new reservation:\nReservation ID: {0}\nDate and Time: {1}\nDuration: {2} minutes\nParking Spot: {3}\nTicket Key: {4}", reservation.ReservationID, reservation.Date, reservation.DurationMinutes, reservation.ParkingSpotID, reservation.TicketKey)); this.Close(); } catch (ReservationException ex) { MessageBox.Show(ex.Message); } } }