hw2: add JavaDoc, required runs

This commit is contained in:
Yuri Tatishchev 2025-02-24 21:16:08 -08:00
parent 1e55218f47
commit a80fe72611
Signed by: CaZzzer
GPG Key ID: E0EBF441EA424369
6 changed files with 145 additions and 141 deletions

View File

@ -1,2 +1,6 @@
143,caz
191,caz
16,hi
34,hi
64,hi
91,hi
195,hi
489,hi

View File

@ -1,2 +1,2 @@
hi,PUBLIC,R3JlZXRlcg==,aGVsbG8=
admin,ADMIN,YWRtaW4=,YWRtaW4=
caz,PUBLIC,WXVyaSBU,aGVsbG8=

1
hw2/googledoc.txt Normal file
View File

@ -0,0 +1 @@
https://docs.google.com/document/d/1JvaiUiMjBGCoZ_znD07hcGHm9pu1VZYskcvsJmrsNv4/edit?usp=sharing

View File

@ -5,103 +5,16 @@ import java.util.*;
import java.util.stream.Stream;
/**
* In this assignment, you will design and implement an airplane seat reservation system.
* Main entrypoint for the reservation system.
* <p>
* For simplicity, this assignment does not require to consider reservations made on multiple days. That is, we assume all transactions made during the given program execution until the admin exits the system are for one particular day.
* I. Program Execution and Command Line Arguments
* Before exploring the system's functionality, let's understand the expected way of program runs which will help you grasp the use of the reservation file (e.g., CL34) and user file (e.g., Users) at the beginning and the end of the program execution.
* The reservation system allows users to make, cancel, and view reservations.
* The system also allows administrators to view a manifest list of reservations.
* <p>
* First, name the tester (with the main method) ReservationSystem. Use a command line argument to read the name of a file that holds reservations from a prior program run. If the file does not exist, the program should create one. You may use the exists() method of the File class to check. The following shows how you would run the program on a command prompt (e.g. prompt of CMD or Mac terminal).
* The system loads reservations and users from files specified as command line arguments.
* If the files do not exist, the system creates them and creates an admin user with the username "admin" and password "admin".
* <p>
* java ReservationSystem CL34 Users
* The system saves reservations and users to the files when the admin exits the system.
* <p>
* where CL34 holds reservations and Users hold the registered user information (user id, password, name) from the previous program run.
* <p>
* In Eclipse, follow Run-> Run Configurations -> Arguments, enter the command line arguments, in our case CL34 and Users, in the box named Program Arguments, and run the program.
* <p>
* Here is a simple scenario to understand this requirement. Suppose you run the program as shown below:
* <p>
* java ReservationSystem CL34 Users
* <p>
* When the program starts, it will check if there exists CL34 and Users. If they do not exist (because this is the very first run), the program creates them and prompts "CL34 and Users are now created.". If they exist (because the previous run created them), the program will populate the in-memory data structures, which you chose to hold reservations and user information, with data from these files, and prompt "Existing Reservations and Users are loaded.". During the current program execution, adding and canceling reservations will change the content of the in-memory data structure, not the content of the file CL34. Only when the Exit option is chosen by the admin, the latest snapshot of the data structure(s) will be saved in the file CL34 and Users in a format of your choice. (You don't have to preserve the prior content of the file. The file can be overwritten.)
* <p>
* For example, suppose a user named Bill Smith signed in and made reservations X, Y, and Z during this first run, and the admin exits the program. Then, X, Y, and Z will be stored in the file CL34 along with the user id of Bill Smith and the Users file should record Bill Smith's information including user id, name, and password. In the second time of program execution, the ReservationSystem gets the existing reservations (X, Y, Z) from CL34 and populates them in the corresponding in-memory data structure. Also, the program loads the data from the Users file into the corresponding data structure. In this second run, let's say, the same user signed in and canceled Y, and reserved A and B. Then the in-memory data structure will hold X, Z, A, and B, and thus the CL4 will contain X, Z, A, and B only after this second run exits.
* <p>
* Checking, creating, or loading from the reservation file (e.g. CS34) should be done when the program starts without any user's request.
* II. System Functionality
* An airplane has three classes of service (First, Economy Plus and Economy). Each class has a sequence of seat rows. The prices of the classes of service are set to $1000, $500, and $250, for the First, Economy Plus and Economy, respectively. The following figure shows the simpified seat chart of the airplane.
* <p>
* <p>
* There are two different types of the users: public users and admin. The system's initial menu page asks for the type of user. The rest of scenarios will follow different paths depending on the entered user type.
* Scenario for public users
* <p>
* A first-timer should sign up for this reservation system by entering user id, name, password, Assume the entered inputs are valid and correct.
* <p>
* To access the reservation system, all public users should sign in using their id and password. The system checks the validity of both id and password and asks for valid id and password until the user enters valid ones.
* <p>
* After the user successfully signed in, the system prompts the following transaction menu. During this transaction, the user can select any of the following options multiple times until the user is done with this transaction by selecting D. The following transaction menu will be displayed after each option is fulfilled until the user is done. The user makes a selection by entering the uppercase letter inside of the brackets such as R to make a reservation.
* <p>
* Check [A]availability Make [R]eservation [C]ancel Reservation [V]iew Reservations [D]one
* <p>
* Each option fulfills the following function:
* <p>
* Check [A]availability: This option shows a seat availability list which shows the available seats of each class along with the seat price as shown below. You can guess the rest of the seat availability list based on the example for First Class.
* <p>
* Seat Availability
* <p>
* First (price: $1000/seat)
* 1: C, D, G, H
* 2: A, B
* <p>
* Economy Plus (price: $500/seat)
* ...
* <p>
* Economy (price: $250/seat)
* <p>
* ..
* <p>
* Make [R]eservation: With this option, the user can make multiple reservations but one seat at a time. The user enters the seat number consisting of a number and a letter (e.g., 1K for a first-class seat). If the seat number is not valid (specifically, not an existing seat number in the plane), the system asks for another one until the user enters a valid one. If the seat is not available, the system prompts an error and asks for another seat. If the seat is available, the system prompts the seat number, the type of service corresponding to this seat, and the price, and asks for the user's confirmation. If the user confirms the reservation, the seat will be reserved. If not, the reservation request will be void. The system asks if the user wants to make another one or not and proceeds with the user's request.
* [C]ancel Reservation: With this option, the system first shows all the seats the user reserved. The user can cancel multiple seat reservations but one seat at a time. The user is supposed to enter a seat number from the list. If the user enters an unlisted number, the system asks for another one until the user enters one of the listed numbers.
* [V]iew Reservations: It shows all reservations made by the current transaction. It doesn't show any cancelled reservation. The following format is suggested:
* <p>
* Name: Bill Smith
* Seats: 2I $1000, 17J $500, 42k $250
* Total Balance Due: $1750
* <p>
* [D]one: The current transaction is done and the system goes back to the initial page asking the type of the next user.
* <p>
* Scenario for Administrator
* <p>
* The administrator doesn't need to sign up for the system but uses the employee id to sign in the system. The system maintains the list of all employee ids of the company so that the entered user id can be checked for validity. If the entered id is invalid, the system asks for another one until a valid one is entered. It is upto you how to maintain the list of all employee ids.
* <p>
* The system prompts the following administration menu. The administrator can select any of the following options multiple times until the administrator exits the system.
* <p>
* Show [M]anifest list E[X]it
* <p>
* Each option fulfills the following function:
* <p>
* Show [M]anifest list: A manifest lists the reserved seats (only) and the corresponding passenger name.
* <p>
* First
* <p>
* 1A: John Williams
* 1B: Harry Hacker
* 2H: Sarah Michaels
* 3C: Jonah Arks
* <p>
* ...
* <p>
* Economy Plus
* ...
* <p>
* Economy
* <p>
* E[X]it: All reservations and registered users saved in the data structures will be persisted to CL34 and Users files, respectively. Only valid reservations, without cancelled ones, should be saved. You are free to choose the format of the data in these files.
*/
/**
* Q: does the admin sign in with a password?
* Q: are the user ids numeric or usernames?
*/
public class ReservationSystem {
private static final Scanner stdin = new Scanner(System.in);
@ -121,6 +34,9 @@ public class ReservationSystem {
saveFiles(args[0], args[1]);
}
/**
* User selection menu: [A]dministrator, [P]ublic User
*/
private static void userSelectionMenu() {
String input = "";
while (!input.equals("A")) {
@ -137,6 +53,11 @@ public class ReservationSystem {
}
}
/**
* Authenticate admin user with username and password.
*
* @return authenticated user
*/
private static User authenticateAdmin() {
System.out.print("Enter admin user id: ");
String username = stdin.nextLine();
@ -151,6 +72,11 @@ public class ReservationSystem {
return users.get(username);
}
/**
* Authenticate or create public user with id, name, and password.
*
* @return authenticated or created user
*/
private static User authenticatePublicUser() {
System.out.println(String.join(";\t ",
"[S]ign up",
@ -190,6 +116,11 @@ public class ReservationSystem {
}
}
/**
* Admin menu: [M]anifest list, E[X]it
*
* @param user authenticated admin user
*/
private static void adminMenu(User user) {
String input = "";
while (true) {
@ -208,6 +139,11 @@ public class ReservationSystem {
}
}
/**
* Public user menu: [A]vailability, [R]eservation, [C]ancel Reservation, [V]iew Reservations, [D]one
*
* @param user authenticated public user
*/
private static void publicUserMenu(User user) {
String input = "";
while (true) {
@ -233,6 +169,9 @@ public class ReservationSystem {
}
/**
* Show [M]anifest list: A manifest lists the reserved seats (only) and the corresponding passenger name.
*/
private static void showManifestList() {
System.out.println("First");
for (int seat = 0; seat < Seat.FIRST_CLASS_SEATS; seat++) {
@ -253,6 +192,9 @@ public class ReservationSystem {
System.out.printf("%d%c: %s%n", Seat.getSeatRow(seat), Seat.getSeatColumn(seat), user.getName());
}
/**
* Check [A]vailability: This option shows a seat availability list which shows the available seats of each class along with the seat price.
*/
private static void checkAvailability() {
System.out.println("Seat Availability\n");
System.out.print("First (price: $1000/seat)");
@ -290,6 +232,7 @@ public class ReservationSystem {
/**
* Make [R]eservation: With this option, the user can make multiple reservations but one seat at a time. The user enters the seat number consisting of a number and a letter (e.g., 1K for a first-class seat). If the seat number is not valid (specifically, not an existing seat number in the plane), the system asks for another one until the user enters a valid one. If the seat is not available, the system prompts an error and asks for another seat. If the seat is available, the system prompts the seat number, the type of service corresponding to this seat, and the price, and asks for the user's confirmation. If the user confirms the reservation, the seat will be reserved. If not, the reservation request will be void. The system asks if the user wants to make another one or not and proceeds with the user's request.
*
* @param user
*/
private static void makeReservation(User user) {
@ -336,6 +279,7 @@ public class ReservationSystem {
/**
* [C]ancel Reservation: With this option, the system first shows all the seats the user reserved. The user can cancel multiple seat reservations but one seat at a time. The user is supposed to enter a seat number from the list. If the user enters an unlisted number, the system asks for another one until the user enters one of the listed numbers.
*
* @param user
*/
private static void cancelReservation(User user) {
@ -378,10 +322,11 @@ public class ReservationSystem {
* Name: Bill Smith
* Seats: 2I $1000, 17J $500, 42k $250
* Total Balance Due: $1750
*
* @param user
*/
private static void viewReservations(User user) {
System.out.printf("Name: %s\n Seats:", user.getName());
System.out.printf("Name: %s\n Seats: ", user.getName());
int totalBalanceDue = 0;
for (int seat = 0; seat < seatReservations.size(); seat++) {
if (seatReservations.get(seat) != null && seatReservations.get(seat).equals(user.getId())) {
@ -392,6 +337,13 @@ public class ReservationSystem {
System.out.printf("\nTotal Balance Due: $%d\n", totalBalanceDue);
}
/**
* Load reservations and users from files.
* If the files do not exist, create them and create an admin user with the username "admin" and password "admin".
*
* @param reservationFilename reservation file name
* @param userFilename user file name
*/
private static void loadFiles(String reservationFilename, String userFilename) {
// check if files exist
File reservationFile = new File(reservationFilename);
@ -439,6 +391,12 @@ public class ReservationSystem {
System.out.println("Existing Reservations and Users are loaded.");
}
/**
* Save reservations and users to files.
*
* @param reservationFilename reservation file name
* @param userFilename user file name
*/
private static void saveFiles(String reservationFilename, String userFilename) {
try (PrintWriter reservationWriter = new PrintWriter(reservationFilename)) {
for (int seatNumber = 0; seatNumber < seatReservations.size(); seatNumber++) {

View File

@ -1,5 +1,14 @@
import java.util.Map;
/**
* Seat class - static methods for seat number conversion, seat class and price calculation.
* row numbers are 1 to 50, column letters are 'A' to 'J'. This is represented by numbers 0 to 499.
* <p>
* Defines constants for total seats (500), row size (10), row count (50), first class seats (40),
* economy plus seats (110), economy seats (350), first class price ($1000), economy plus price ($500),
* economy price ($250).
*
* @author Yuri Tatishchev
* @version 0.1 2025-02-24
*/
public class Seat {
public static final int TOTAL_SEATS = 500;
public static final int ROW_SIZE = 10;
@ -18,6 +27,14 @@ public class Seat {
ECONOMY,
}
/**
* Get seat number from row and column.
*
* @param row 1 to 50 row number
* @param column 'A' to 'J' column letter
* @return seat number from 0 to 499
* @throws IllegalArgumentException if row or column is out of range
*/
public static int getSeatNumber(int row, char column) {
if (row < 1 || row > ROW_COUNT || column < 'A' || column >= 'A' + ROW_SIZE) {
throw new IllegalArgumentException("Invalid seat number");
@ -25,24 +42,56 @@ public class Seat {
return (row - 1) * 10 + (column - 'A');
}
/**
* Get seat number from seat string.
*
* @param seat seat string like "1A"
* @return seat number from 0 to 499
* @throws IllegalArgumentException if seat string is invalid
*/
public static int getSeatNumber(String seat) {
String seatNumber = seat.substring(0, seat.length() - 1);
char seatColumn = seat.charAt(seat.length() - 1);
return getSeatNumber(Integer.parseInt(seatNumber), seatColumn);
}
/**
* Get row number from seat number.
*
* @param seatNumber 0 to 499 seat number
* @return 1 to 50 row number
*/
public static int getSeatRow(int seatNumber) {
return (seatNumber / 10) + 1;
}
/**
* Get column letter from seat number.
*
* @param seatNumber 0 to 499 seat number
* @return 'A' to 'J' column letter
*/
public static char getSeatColumn(int seatNumber) {
return (char) ('A' + seatNumber % 10);
}
/**
* Get a csv formatted string from seat number and passenger id.
*
* @param seatNumber 0 to 499 seat number
* @param passengerId passenger id
* @return csv formatted string like "1A,user123"
*/
public static String toCsvString(int seatNumber, String passengerId) {
return String.format("%d,%s", seatNumber, passengerId);
}
/**
* Get the service class for a given seat number.
*
* @param seatNumber 0 to 499 seat number
* @return service class
*/
public static ServiceClass getServiceClass(int seatNumber) {
if (seatNumber < FIRST_CLASS_SEATS) {
return ServiceClass.FIRST_CLASS;
@ -52,6 +101,12 @@ public class Seat {
return ServiceClass.ECONOMY;
}
/**
* Get the price for a given seat number, based on the service class.
*
* @param seatNumber 0 to 499 seat number
* @return price
*/
public static int getSeatPrice(int seatNumber) {
switch (getServiceClass(seatNumber)) {
case FIRST_CLASS -> {
@ -67,44 +122,3 @@ public class Seat {
return 0;
}
}
// public class Seat {
// private int seatNumber;
// private User passenger;
//
// public Seat(int seatNumber) {
// this.seatNumber = seatNumber;
// this.passenger = null;
// }
// public Seat(int seatNumber, User passenger) {
// this.seatNumber = seatNumber;
// this.passenger = passenger;
// }
//
// public int getSeatNumber() {
// return seatNumber;
// }
//
// public int getSeatRow() {
// return (seatNumber / 10) + 1;
// }
//
// public char getSeatColumn() {
// return (char) ('A' + seatNumber % 10);
// }
//
// public Optional<User> getPassenger() {
// return Optional.ofNullable(passenger);
// }
//
// public boolean isOccupied() {
// return passenger != null;
// }
//
// public String toCsvString() {
// if (passenger == null) {
// return String.format("%d,", seatNumber);
// }
// return String.format("%d,%d", seatNumber, passenger.getId());
// }
// }

View File

@ -1,6 +1,16 @@
import java.util.Arrays;
import java.util.Base64;
/**
* A class representing a user in the system.
* <p>
* A user has an id, a type, a name, and a password.
* The id is a unique identifier (string) for the user.
* The type can be either ADMIN or PUBLIC.
* The name and password are stored as base64-encoded strings.
*
* @author Yuri Tatishchev
* @version 0.1 2025-02-24
*/
public class User {
public enum Type {
ADMIN,
@ -36,6 +46,12 @@ public class User {
return new User(id, type, name, password);
}
/**
* Get a CSV formatted string from the user object.
*
* @return a CSV formatted string in the format:
* <code>id,type,base64(name),base64(password)</code>.
*/
public String toCsvString() {
// don't forget to escape commas in name and password
String csvName = Base64.getEncoder().encodeToString(name.getBytes());
@ -59,10 +75,21 @@ public class User {
return password;
}
/**
* Check if the given password matches the user's password.
*
* @param password the inputted password to check
* @return true if the password matches, false otherwise
*/
public boolean checkPassword(String password) {
return this.password.equals(password);
}
/**
* Check if the user is an admin.
*
* @return true if the user is an admin, false otherwise
*/
public boolean isAdmin() {
return type == Type.ADMIN;
}