# Airplane Seating and Checking

## Problem

• You’ve been hired by Delta to write a program to book, assign seating, and track checked baggage for passengers for a flight
• The program should have a main menu:
• Add passenger (this just books them, not seats them)
• Lookup passenger by name (for seating, checking, etc)
• Lookup passenger by seat (for seating, checking, etc)
• Display all passengers (all booked, seated or not)
• Display seating chart
• Use a vector to track a list of all passengers and a 2D array to represent a seating chart
• When a passenger is looked up by name or seat, a passenger summary should appear and an edit menu should provide functionality to
• Assign seat
• Check baggage
• The plane has 10 rows and 4 seats per row (A, B, C, & D)

## Solution

### Source.cpp

/*
Any comment labeled "TASK" is something we implemented in class and represents material that
uniquely demonstrates the use of vectors of pointers

Test Cases

Test cases should test each of the main menu options, each of the edit menu options, with 0, 1, and >1
passengers added, with 0, 1, and >1 passengers assigned seating.

It should test assigning a seat to someone who already has a seat.

It should test assigning an already occupied seat to someone.

It should test lookup people that don't exist, both by seat and by name
*/

#include <iostream>
#include <vector>
#include "Passenger.h"

using namespace std;

const int LOOKUP_PASSENGER_BY_NAME = 2;
const int LOOKUP_PASSENGER_BY_SEAT = 3;
const int DISPLAY_ALL_PASSENGERS = 4;
const int DISPLAY_SEATING_CHART = 5;

const int ASSIGN_SEAT = 1;
const int CHECK_BAG = 2;

// AIRPLANE SEATING CONSTRAINTS
const int ROWS = 10;
const int SEATS_PER_ROW = 4;
const char FIRST_SEAT = 'A';

// DISPLAY AND PROMPTING FUNCTIONS (implemented below)
string prompt_for_name();
int prompt_for_row();
char prompt_for_seat_in_row();

// HELPER FUNCTIONS (implemented below)
void initialize_seating_chart(Passenger * seating_chart[][SEATS_PER_ROW]);
Passenger * create_new_passenger();
Passenger * lookup_passenger_by_name(vector<Passenger *> & all_passengers);
void display_all_passengers(vector<Passenger *> & all_passengers);
void edit_passenger(Passenger * passenger_to_edit, Passenger * seating_chart[][SEATS_PER_ROW]);
Passenger * lookup_passenger_by_seat(Passenger * seating_chart[][SEATS_PER_ROW]);
void display_seating_chart(Passenger * seating_chart[][SEATS_PER_ROW]);

int main()
{
// TASK: Use a vector to track a list of all passengers and
// a 2D array to represent a seating chart
vector<Passenger *> all_passengers;
Passenger * seating_chart[ROWS][SEATS_PER_ROW];

initialize_seating_chart(seating_chart);

while (true)
{

{
cout << "ADD PASSENGER" << endl;

// TASK: create_new_passenger (using function which also prompts for input)
Passenger * new_passenger = create_new_passenger();

all_passengers.push_back(new_passenger);

cout << "PASSENGER ADDED" << endl;
}
else if (choice == LOOKUP_PASSENGER_BY_NAME)
{
cout << "LOOKUP PASSENGER BY NAME" << endl;

Passenger * passenger_to_edit = lookup_passenger_by_name(all_passengers);

// TASK: edit_passenger (print passenger info, display edit menu, implement edit options)
edit_passenger(passenger_to_edit, seating_chart);
}
else if (choice == LOOKUP_PASSENGER_BY_SEAT)
{
cout << "LOOKUP PASSENGER BY SEAT" << endl;

// TASK: lookup_passenger_by_seat (using function wich also prompts for row and seat to look up)
Passenger * passenger_to_edit = lookup_passenger_by_seat(seating_chart);

// TASK: edit_passenger (same as above)
edit_passenger(passenger_to_edit, seating_chart);
}
else if (choice == DISPLAY_ALL_PASSENGERS)
{
cout << "DISPLAY ALL PASSENGERS" << endl;

// TASK: display_all_passengers (list of all passengers, w/ or w/o seats)
display_all_passengers(all_passengers);
}
else if (choice == DISPLAY_SEATING_CHART)
{
cout << "DISPLAY SEATING CHART" << endl;

// TASK: display_seating_chart as formatted 2D matrix
display_seating_chart(seating_chart);
}
cout << endl;
}

system("pause");
return 0;
}

/*
Print main menu and prompt for a choice (no input validation)
@return user's choice of the menu options
*/
{
cout << "************WELCOME TO CS AIRWAYS****************" << endl
<< LOOKUP_PASSENGER_BY_NAME << ". Look up passenger by name" << endl
<< LOOKUP_PASSENGER_BY_SEAT << ". Look up passenger by seat" << endl
<< DISPLAY_ALL_PASSENGERS << ". Display all passengers" << endl
<< DISPLAY_SEATING_CHART << ". Display seating chart" << endl
<< "Choice:";
int choice;
cin >> choice;

cout << "**************************************************" << endl << endl;

return choice;
}

/*
Print passenger edit menu and prompt for a choice (no input validation)
@return user's choice of the menu options
*/
{
cout << ASSIGN_SEAT << ". Assign seat" << endl
<< CHECK_BAG << ". Check bag" << endl
<< "Choice: ";
int choice;
cin >> choice;
return choice;
}

/*
Prompt for a passenger name
@return a multi-word string input by user
*/
string prompt_for_name()
{
cout << "Passenger name: ";
string full_name;
cin.sync();
getline(cin, full_name);
return full_name;
}

/*
Prompt for a row number (no input validation)
@return row input by user
*/
int prompt_for_row()
{
cout << "Row number: ";
int row;
cin >> row;
return row;
}

/*
Prompt for a seat in a row  (no input validation)
@return seat input by user
*/
char prompt_for_seat_in_row()
{
cout << "Seat in row:";
char seat_in_row;
cin >> seat_in_row;
return seat_in_row;
}

/*
Set all values in seating_chart to NULL
@param seating_chart 2D matrix representing seating chart
*/
void initialize_seating_chart(Passenger * seating_chart[][SEATS_PER_ROW])
{
// TASK: fill the seating_chart with NULL
for (int row = 0; row < ROWS; row++)
{
for (int seat = 0; seat < SEATS_PER_ROW; seat++)
{
seating_chart[row][seat] = NULL;
}
}
}

/*
Prompt for a name of a passenger to add, create the new passenger,
and return a pointer to the new passenger
NOTE: in order to return a pointer to a local variable, you have to use "new"
@return pointer to newly created passenger
*/
Passenger * create_new_passenger()
{
string full_name = prompt_for_name();

// TASK: Create a new passenger and return a pointer to it
Passenger * new_passenger = new Passenger(full_name);

return new_passenger;
}

/*
Prompt for name to lookup, lookup name in list of all passenger
@param all_passengers list to search for user-inputted name
@return pointer to Passenger object representing passenger
*/
Passenger * lookup_passenger_by_name(vector<Passenger *> & all_passengers)
{
string full_name = prompt_for_name();

// TASK: find passenger in list matching full_name and return a pointer to the passenger
for (int i = 0; i < all_passengers.size(); i++)
{
if (all_passengers[i]->get_full_name() == full_name)
{
return all_passengers[i];
}
}

return NULL;
}

/*
Prompt for row, seat to lookup, lookup seat in seating chart
@param seating_chart 2D matrix to search for user-inputted row and name
@return pointer to Passenger object representing passenger (NULL if seat unoccupied)
*/
Passenger * lookup_passenger_by_seat(Passenger * seating_chart[][SEATS_PER_ROW])
{
int row = prompt_for_row();
char seat_in_row = prompt_for_seat_in_row();

// TASK: return a passenger pointer representing the person at row and seat_in_row (NULL if no one is there)
// NOTE: a char is really just an int, so to get the seat index from the seat name (e.g., 'A'),
//       we can subtract the integer representing 'A' from the integer representing the seat
//       For example, 'A' - 'A' is 0; 'B' - 'A' = 1; 'C' - 'A' = 2; etc. This is because the integer
//       representation of the capital letters are consecutive integers (e.g., 'A' = 64, 'B' = 65, etc)
int seat_index = seat_in_row - FIRST_SEAT;
return seating_chart[row][seat_index];
}

/*
Given a passenger pointer, edit a passenger according to user-input instructions
Note that this involves printing a menu of edit options, and may require modifying the seating chart
@param passenger the passenger to edit
@param seating_chart the 2D matrix of Passenger pointers representing the seating chart
*/
void edit_passenger(Passenger * passenger, Passenger * seating_chart[][SEATS_PER_ROW])
{
cout << endl;
// TASK: Return if passenger is NULL
if (passenger == NULL)
{
cout << "NO PASSENGER FOUND" << endl;
return;
}
cout << "************EDIT PASSENGER************" << endl;

cout << passenger->to_string() << endl;

// Print menu options (assign seat, check bag) and prompt for choice

if (choice == ASSIGN_SEAT)
{
int row = prompt_for_row();
char seat_in_row = prompt_for_seat_in_row();

// TASK: Check if seat is taken
// NOTE: the NOTE in the lookup_passenger_by_seat function explains how to find a seat
//       index from the seat label (e.g., 'A')
int seat_index = seat_in_row - FIRST_SEAT;
if (seating_chart[row][seat_index] != NULL)
{
// sorry, charlie, no assignment
cout << "SEAT IS TAKEN" << endl;
}
// else assign the seat
else
{
if (passenger->is_assigned_a_seat())
{
// NOTE: the NOTE in the lookup_passenger_by_seat function explains how to find a seat
//       index from the seat label (e.g., 'A')
int old_seat_index = passenger->get_seat_in_row() - FIRST_SEAT;
seating_chart[passenger->get_row()][old_seat_index] = NULL;
}
// TASK: Update the seating assignment with the new assignment
seating_chart[row][seat_index] = passenger;
// TASK: Update the passenger object's seat assignemnt to the new assignment
passenger->assign_a_seat(row, seat_in_row);
}
}
else if (choice == CHECK_BAG)
{
passenger->check_a_bag();

cout << "Bag Checked" << endl;
}
// else if choice == RETURN_TO_MAIN_MENU (we don't need to implement this; why?)
}

/*
Print list of all passenger names to the console
@param all_passengers list of all passengers
*/
void display_all_passengers(vector<Passenger *> & all_passengers)
{
// TASK: Display all passengers (just to_string() is fine)
for (int i = 0; i < all_passengers.size(); i++)
{
cout << all_passengers[i]->get_full_name() << endl;
}
cout << endl;
}

/*
Print a formatted version of the seating chart (to look like a plane) to the console
Prints 'X' for occupied seats and '_' for unnoccupied seats
Also prints row and seat labels for easy reference
@param seating_chart current seating chart
*/
void display_seating_chart(Passenger * seating_chart[][SEATS_PER_ROW])
{
//First print a row of seat labels (e.g., A, B, C, D)
cout << "    ";
for (int seat = 0; seat < SEATS_PER_ROW; seat++)
{
if (seat == SEATS_PER_ROW / 2)
{
cout << "   ";
}
// NOTE: the NOTE in the lookup_passenger_by_seat function explains
//       the relationship between the seat label (e.g., 'A') and the seat index (e.g., 0)
char seat_char = FIRST_SEAT + seat;
cout << seat_char << " ";
}
cout << endl;

// Print the 2D seating chart matrix
for (int row = 0; row < ROWS; row++)
{
cout << row << " | "; // row label and left cabin wall
for (int seat = 0; seat < SEATS_PER_ROW; seat++)
{
if (seat == SEATS_PER_ROW / 2)
{
cout << "   "; // aisle
}
if (seating_chart[row][seat] == NULL) // if seat is unoccupied
{
cout << "_ "; // unoccupied
}
else
{
cout << "X "; // occupied
}
}
cout << "|" << endl; // right cabin wall
}

}

### Passenger.h

#include <string>

using namespace std;

#ifndef _PASSENGER_H
#define _PASSENGER_H

class Passenger
{
public:
// CONSTRUCTOR

/*
Create a new passenger from just their full name with 0 checked bags,
and no seat assignment
@param _full_name value to assign as full name of *this* Passenger object
*/
Passenger(string _full_name);

// MEMBER FUNCTIONS

/*
@return the value of the full name of *this* Passenger object
*/
string get_full_name() const;

/*
@return true if *this* Passenger object is assigned a seat
*/
bool is_assigned_a_seat() const;

/*
@return row number of seat assignment (or -1 if there's no assignment)
*/
int get_row() const;

/*
@return seat in row of seat assignment (or '$' if there's no assignment) */ char get_seat_in_row() const; /* increments the number of checked bags for *this* passenger */ void check_a_bag(); /* updates the seat assignment for *this* passenger @param _row the new row @param _seat_in_row the new seat in the new row */ void assign_a_seat(int _row, char _seat_in_row); /* @return a string representation of this object including name, seat assignment, bags checked */ string to_string() const; private: // DATA MEMBERS string full_name; int row; char seat_in_row; int checked_bags; // static means that not every object carries its own copy of the variable // const means that the variable's value can't change // NOTE: only ints can be initialized this way in the .h file // (others must be initialized in .cpp file) static const int UNASSIGNED_ROW = -1; static const char UNASSIGNED_SEAT = '$';

};

#endif

### Passenger.cpp

#include <sstream>
#include "Passenger.h"

Passenger::Passenger(string _full_name)
{
full_name = _full_name;
row = UNASSIGNED_ROW; // Initially passenger doesn't have seat
seat_in_row = UNASSIGNED_SEAT; // Initially passenger doesn't have seat
checked_bags = 0;
}

string Passenger::get_full_name() const
{
return full_name;
}

bool Passenger::is_assigned_a_seat() const
{
return (row != UNASSIGNED_ROW);
}

int Passenger::get_row() const
{
return row;
}

char Passenger::get_seat_in_row() const
{
return seat_in_row;
}

void Passenger::check_a_bag()
{
checked_bags++;
}

void Passenger::assign_a_seat(int _row, char _seat_in_row)
{
row = _row;
seat_in_row = _seat_in_row;
}

string Passenger::to_string() const
{
ostringstream strm;

strm << full_name;
if (row == UNASSIGNED_ROW)
{
strm << " (no seat assigned)";
}
else
{
strm << " (seat " << row << seat_in_row << ")";
}
strm << " - " << checked_bags << " checked bags";

return strm.str();
}