Compare commits
4 Commits
25f13105f2
...
593840bd51
Author | SHA1 | Date | |
---|---|---|---|
593840bd51 | |||
a80fe72611 | |||
1e55218f47 | |||
ff2c9489bb |
29
hw2/.gitignore
vendored
Normal file
29
hw2/.gitignore
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
### IntelliJ IDEA ###
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
8
hw2/.idea/.gitignore
generated
vendored
Normal file
8
hw2/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
6
hw2/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
6
hw2/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
6
hw2/.idea/misc.xml
generated
Normal file
6
hw2/.idea/misc.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
8
hw2/.idea/modules.xml
generated
Normal file
8
hw2/.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/hw2.iml" filepath="$PROJECT_DIR$/hw2.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
6
hw2/.idea/vcs.xml
generated
Normal file
6
hw2/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
2
hw2/Users
Normal file
2
hw2/Users
Normal file
@ -0,0 +1,2 @@
|
||||
hi,PUBLIC,R3JlZXRlcg==,aGVsbG8=
|
||||
admin,ADMIN,YWRtaW4=,YWRtaW4=
|
1
hw2/googledoc.txt
Normal file
1
hw2/googledoc.txt
Normal file
@ -0,0 +1 @@
|
||||
https://docs.google.com/document/d/1JvaiUiMjBGCoZ_znD07hcGHm9pu1VZYskcvsJmrsNv4/edit?usp=sharing
|
11
hw2/hw2.iml
Normal file
11
hw2/hw2.iml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
417
hw2/src/ReservationSystem.java
Normal file
417
hw2/src/ReservationSystem.java
Normal file
@ -0,0 +1,417 @@
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Main entrypoint for the reservation system.
|
||||
* <p>
|
||||
* The reservation system allows users to make, cancel, and view reservations.
|
||||
* The system also allows administrators to view a manifest list of reservations.
|
||||
* <p>
|
||||
* 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>
|
||||
* The system saves reservations and users to the files when the admin exits the system.
|
||||
* <p>
|
||||
*/
|
||||
public class ReservationSystem {
|
||||
private static final Scanner stdin = new Scanner(System.in);
|
||||
private static final String ADMIN_USERNAME = "admin";
|
||||
private static final String ADMIN_PASSWORD = "admin";
|
||||
private static Map<String, User> users = new HashMap<>();
|
||||
private static ArrayList<String> seatReservations = new ArrayList<>(Stream.generate(() -> (String) null).limit(Seat.TOTAL_SEATS).toList());
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (args.length != 2) {
|
||||
System.out.println("Usage: java ReservationSystem <reservationFilename> <userFilename>");
|
||||
return;
|
||||
}
|
||||
loadFiles(args[0], args[1]);
|
||||
System.out.println(users.get(ADMIN_USERNAME).toCsvString());
|
||||
userSelectionMenu();
|
||||
saveFiles(args[0], args[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* User selection menu: [A]dministrator, [P]ublic User
|
||||
*/
|
||||
private static void userSelectionMenu() {
|
||||
String input = "";
|
||||
while (!input.equals("A")) {
|
||||
System.out.println(String.join(";\t ",
|
||||
"User:\t [A]dministrator",
|
||||
"[P]ublic User"
|
||||
));
|
||||
input = stdin.nextLine().toUpperCase();
|
||||
switch (input) {
|
||||
case "A" -> adminMenu(authenticateAdmin());
|
||||
case "P" -> publicUserMenu(authenticatePublicUser());
|
||||
default -> System.out.println("Invalid input");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
System.out.print("Enter admin password: ");
|
||||
String password = stdin.nextLine();
|
||||
|
||||
final User user = users.get(username);
|
||||
if (user == null || !user.isAdmin() || !user.checkPassword(password)) {
|
||||
System.out.println("Invalid user id or password");
|
||||
return authenticateAdmin();
|
||||
}
|
||||
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",
|
||||
"[L]og in"
|
||||
));
|
||||
String input = stdin.nextLine().toUpperCase();
|
||||
switch (input) {
|
||||
case "S" -> {
|
||||
System.out.print("Enter user id: ");
|
||||
// can't have commas in a csv because I'm too lazy to do escaping
|
||||
String id = stdin.nextLine().replace(",", "");
|
||||
System.out.print("Enter name: ");
|
||||
String name = stdin.nextLine();
|
||||
System.out.print("Enter password: ");
|
||||
String password = stdin.nextLine();
|
||||
User user = new User(id, User.Type.PUBLIC, name, password);
|
||||
users.put(id, user);
|
||||
return user;
|
||||
}
|
||||
case "L" -> {
|
||||
System.out.print("Enter user id: ");
|
||||
String id = stdin.nextLine();
|
||||
System.out.print("Enter user password: ");
|
||||
String password = stdin.nextLine();
|
||||
|
||||
final User user = users.get(id);
|
||||
if (user == null || user.isAdmin() || !user.checkPassword(password)) {
|
||||
System.out.println("Invalid user id or password");
|
||||
return authenticatePublicUser();
|
||||
}
|
||||
return users.get(id);
|
||||
}
|
||||
default -> {
|
||||
System.out.println("Invalid input");
|
||||
return authenticatePublicUser();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin menu: [M]anifest list, E[X]it
|
||||
*
|
||||
* @param user authenticated admin user
|
||||
*/
|
||||
private static void adminMenu(User user) {
|
||||
String input = "";
|
||||
while (true) {
|
||||
System.out.println(String.join(";\t ",
|
||||
"Show [M]anifest list",
|
||||
"E[X]it"
|
||||
));
|
||||
input = stdin.nextLine().toUpperCase();
|
||||
switch (input) {
|
||||
case "M" -> showManifestList();
|
||||
case "X" -> {
|
||||
return;
|
||||
}
|
||||
default -> System.out.println("Invalid input");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
System.out.println(String.join(";\t ",
|
||||
"Check [A]vailability",
|
||||
"Make [R]eservation",
|
||||
"[C]ancel Reservation",
|
||||
"[V]iew Reservations",
|
||||
"[D]one"
|
||||
));
|
||||
input = stdin.nextLine().toUpperCase();
|
||||
switch (input) {
|
||||
case "A" -> checkAvailability();
|
||||
case "R" -> makeReservation(user);
|
||||
case "C" -> cancelReservation(user);
|
||||
case "V" -> viewReservations(user);
|
||||
case "D" -> {
|
||||
return;
|
||||
}
|
||||
default -> System.out.println("Invalid input");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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++) {
|
||||
if (seatReservations.get(seat) != null) printManifestReservation(seat);
|
||||
}
|
||||
System.out.println("\nEconomy Plus");
|
||||
for (int seat = Seat.FIRST_CLASS_SEATS; seat < Seat.FIRST_CLASS_SEATS + Seat.ECONOMY_PLUS_SEATS; seat++) {
|
||||
if (seatReservations.get(seat) != null) printManifestReservation(seat);
|
||||
}
|
||||
System.out.println("\nEconomy");
|
||||
for (int seat = Seat.FIRST_CLASS_SEATS + Seat.ECONOMY_PLUS_SEATS; seat < Seat.TOTAL_SEATS; seat++) {
|
||||
if (seatReservations.get(seat) != null) printManifestReservation(seat);
|
||||
}
|
||||
}
|
||||
|
||||
private static void printManifestReservation(Integer seat) {
|
||||
User user = users.get(seatReservations.get(seat));
|
||||
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)");
|
||||
for (int seat = 0; seat < Seat.FIRST_CLASS_SEATS; seat++) {
|
||||
if (seat % Seat.ROW_SIZE == 0) {
|
||||
System.out.println();
|
||||
System.out.print(Seat.getSeatRow(seat) + ": ");
|
||||
}
|
||||
if (seatReservations.get(seat) == null) {
|
||||
System.out.print(Seat.getSeatColumn(seat) + ", ");
|
||||
}
|
||||
}
|
||||
System.out.print("\n\nEconomy Plus (price: $500/seat)");
|
||||
for (int seat = Seat.FIRST_CLASS_SEATS; seat < Seat.FIRST_CLASS_SEATS + Seat.ECONOMY_PLUS_SEATS; seat++) {
|
||||
if (seat % Seat.ROW_SIZE == 0) {
|
||||
System.out.println();
|
||||
System.out.print(Seat.getSeatRow(seat) + ": ");
|
||||
}
|
||||
if (seatReservations.get(seat) == null) {
|
||||
System.out.print(Seat.getSeatColumn(seat) + ", ");
|
||||
}
|
||||
}
|
||||
System.out.print("\n\nEconomy (price: $250/seat)");
|
||||
for (int seat = Seat.FIRST_CLASS_SEATS + Seat.ECONOMY_PLUS_SEATS; seat < Seat.TOTAL_SEATS; seat++) {
|
||||
if (seat % Seat.ROW_SIZE == 0) {
|
||||
System.out.println();
|
||||
System.out.print(Seat.getSeatRow(seat) + ": ");
|
||||
}
|
||||
if (seatReservations.get(seat) == null) {
|
||||
System.out.print(Seat.getSeatColumn(seat) + ", ");
|
||||
}
|
||||
}
|
||||
System.out.print("\n\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
System.out.print("Enter seat number: ");
|
||||
String seat = stdin.nextLine().toUpperCase();
|
||||
try {
|
||||
int seatNumber = Seat.getSeatNumber(seat);
|
||||
if (seatReservations.get(seatNumber) != null) {
|
||||
System.out.println("Seat is already reserved");
|
||||
makeReservation(user);
|
||||
return;
|
||||
}
|
||||
System.out.printf("Seat: %s\n", seat);
|
||||
System.out.printf("Service: %s, $%d\n", Seat.getServiceClass(seatNumber), Seat.getSeatPrice(seatNumber));
|
||||
System.out.println("Confirm reservation? [Y/N]");
|
||||
String confirm = stdin.nextLine().toUpperCase();
|
||||
while (!confirm.equals("Y") && !confirm.equals("N")) {
|
||||
System.out.println("Invalid input");
|
||||
System.out.println("Confirm reservation? [Y/N]");
|
||||
confirm = stdin.nextLine().toUpperCase();
|
||||
}
|
||||
switch (confirm) {
|
||||
case "Y" -> {
|
||||
seatReservations.set(seatNumber, user.getId());
|
||||
System.out.println("Reservation confirmed");
|
||||
}
|
||||
case "N" -> System.out.println("Reservation cancelled");
|
||||
}
|
||||
System.out.println("Make another reservation? [Y/N]");
|
||||
String another = stdin.nextLine().toUpperCase();
|
||||
while (!another.equals("Y") && !another.equals("N")) {
|
||||
System.out.println("Invalid input");
|
||||
System.out.println("Make another reservation? [Y/N]");
|
||||
another = stdin.nextLine().toUpperCase();
|
||||
}
|
||||
if (another.equals("Y")) {
|
||||
makeReservation(user);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.out.println("Invalid seat number");
|
||||
makeReservation(user);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [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) {
|
||||
System.out.println("Your reservations:");
|
||||
for (int seat = 0; seat < seatReservations.size(); seat++) {
|
||||
if (seatReservations.get(seat) != null && seatReservations.get(seat).equals(user.getId())) {
|
||||
System.out.printf("%d%c, %s, $%d\n", Seat.getSeatRow(seat), Seat.getSeatColumn(seat), Seat.getServiceClass(seat), Seat.getSeatPrice(seat));
|
||||
}
|
||||
}
|
||||
System.out.print("Enter seat number to cancel: ");
|
||||
String seat = stdin.nextLine().toUpperCase();
|
||||
try {
|
||||
int seatNumber = Seat.getSeatNumber(seat);
|
||||
if (seatReservations.get(seatNumber) == null || !seatReservations.get(seatNumber).equals(user.getId())) {
|
||||
System.out.println("Seat is not reserved by you");
|
||||
cancelReservation(user);
|
||||
return;
|
||||
}
|
||||
seatReservations.set(seatNumber, null);
|
||||
System.out.println("Reservation cancelled");
|
||||
System.out.println("Cancel another reservation? [Y/N]");
|
||||
String another = stdin.nextLine().toUpperCase();
|
||||
while (!another.equals("Y") && !another.equals("N")) {
|
||||
System.out.println("Invalid input");
|
||||
System.out.println("Cancel another reservation? [Y/N]");
|
||||
another = stdin.nextLine().toUpperCase();
|
||||
}
|
||||
if (another.equals("Y")) {
|
||||
cancelReservation(user);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.out.println("Invalid seat number");
|
||||
cancelReservation(user);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [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
|
||||
*
|
||||
* @param user
|
||||
*/
|
||||
private static void viewReservations(User user) {
|
||||
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())) {
|
||||
System.out.printf("%d%c $%d, ", Seat.getSeatRow(seat), Seat.getSeatColumn(seat), Seat.getSeatPrice(seat));
|
||||
totalBalanceDue += Seat.getSeatPrice(seat);
|
||||
}
|
||||
}
|
||||
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);
|
||||
File userFile = new File(userFilename);
|
||||
if (!reservationFile.isFile() || !userFile.isFile()) {
|
||||
users.put(ADMIN_USERNAME, new User(ADMIN_USERNAME, User.Type.ADMIN, ADMIN_USERNAME, ADMIN_PASSWORD));
|
||||
try {
|
||||
reservationFile.createNewFile();
|
||||
userFile.createNewFile();
|
||||
try (PrintWriter writer = new PrintWriter(userFile)) {
|
||||
users.values().forEach(user -> writer.println(user.toCsvString()));
|
||||
}
|
||||
System.out.println(reservationFilename + " and " + userFilename + " are now created.");
|
||||
System.out.println("Admin user created with username: \"" + ADMIN_USERNAME + "\" and password: \"" + ADMIN_PASSWORD + "\"");
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error creating files");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// load reservations from reservationFile
|
||||
try (Scanner scanner = new Scanner(new File(reservationFilename))) {
|
||||
while (scanner.hasNextLine()) {
|
||||
String line = scanner.nextLine();
|
||||
String[] parts = line.split(",");
|
||||
int seatNumber = Integer.parseInt(parts[0]);
|
||||
String passengerId = parts[1];
|
||||
seatReservations.set(seatNumber, passengerId);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println(reservationFilename + " not found");
|
||||
}
|
||||
|
||||
// load users from userFile
|
||||
try (Scanner scanner = new Scanner(new File(userFilename))) {
|
||||
while (scanner.hasNextLine()) {
|
||||
String line = scanner.nextLine();
|
||||
User user = User.fromCsvString(line);
|
||||
users.put(user.getId(), user);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println(userFilename + " not found");
|
||||
}
|
||||
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++) {
|
||||
if (seatReservations.get(seatNumber) != null) {
|
||||
reservationWriter.println(Seat.toCsvString(seatNumber, seatReservations.get(seatNumber)));
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println("Error saving reservations");
|
||||
}
|
||||
try (PrintWriter userWriter = new PrintWriter(userFilename)) {
|
||||
users.values().forEach(user -> userWriter.println(user.toCsvString()));
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println("Error saving users");
|
||||
}
|
||||
System.out.printf("Saved reservations to %s and users to %s%n", reservationFilename, userFilename);
|
||||
}
|
||||
}
|
124
hw2/src/Seat.java
Normal file
124
hw2/src/Seat.java
Normal file
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* 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;
|
||||
public static final int ROW_COUNT = TOTAL_SEATS / ROW_SIZE;
|
||||
public static final int FIRST_CLASS_SEATS = 40;
|
||||
public static final int ECONOMY_PLUS_SEATS = 110;
|
||||
public static final int ECONOMY_SEATS = TOTAL_SEATS - FIRST_CLASS_SEATS - ECONOMY_PLUS_SEATS;
|
||||
|
||||
public static final int FIRST_CLASS_PRICE = 1000;
|
||||
public static final int ECONOMY_PLUS_PRICE = 500;
|
||||
public static final int ECONOMY_PRICE = 250;
|
||||
|
||||
public enum ServiceClass {
|
||||
FIRST_CLASS,
|
||||
ECONOMY_PLUS,
|
||||
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");
|
||||
}
|
||||
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;
|
||||
} else if (seatNumber < FIRST_CLASS_SEATS + ECONOMY_PLUS_SEATS) {
|
||||
return ServiceClass.ECONOMY_PLUS;
|
||||
}
|
||||
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 -> {
|
||||
return FIRST_CLASS_PRICE;
|
||||
}
|
||||
case ECONOMY_PLUS -> {
|
||||
return ECONOMY_PLUS_PRICE;
|
||||
}
|
||||
case ECONOMY -> {
|
||||
return ECONOMY_PRICE;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
97
hw2/src/User.java
Normal file
97
hw2/src/User.java
Normal file
@ -0,0 +1,97 @@
|
||||
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,
|
||||
PUBLIC,
|
||||
}
|
||||
|
||||
private String id;
|
||||
private Type type;
|
||||
private String name;
|
||||
private String password;
|
||||
|
||||
public User(String id, Type type, String name, String password) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a User object from a CSV string.
|
||||
*
|
||||
* @param line The CSV string, should be in the format:
|
||||
* <code>id,type,base64(name),base64(password)</code>.
|
||||
* with escaped backslashes and commas.
|
||||
* @return a User object
|
||||
*/
|
||||
public static User fromCsvString(String line) {
|
||||
String[] parts = line.split(",");
|
||||
String id = parts[0];
|
||||
Type type = Type.valueOf(parts[1]);
|
||||
String name = new String(Base64.getDecoder().decode(parts[2]));
|
||||
String password = new String(Base64.getDecoder().decode(parts[3]));
|
||||
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());
|
||||
String csvPassword = Base64.getEncoder().encodeToString(password.getBytes());
|
||||
return String.join(",", id, type.toString(), csvName, csvPassword);
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
29
midterm1/.gitignore
vendored
Normal file
29
midterm1/.gitignore
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
### IntelliJ IDEA ###
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
8
midterm1/.idea/.gitignore
generated
vendored
Normal file
8
midterm1/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
6
midterm1/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
6
midterm1/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
6
midterm1/.idea/misc.xml
generated
Normal file
6
midterm1/.idea/misc.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
8
midterm1/.idea/modules.xml
generated
Normal file
8
midterm1/.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/midterm1.iml" filepath="$PROJECT_DIR$/midterm1.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
6
midterm1/.idea/vcs.xml
generated
Normal file
6
midterm1/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
11
midterm1/midterm1.iml
Normal file
11
midterm1/midterm1.iml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
30
midterm1/src/Animation.java
Normal file
30
midterm1/src/Animation.java
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Animation Program that draws and moves a simple shape (e.g. butterfly, kite, etc.) on a timer event.
|
||||
*/
|
||||
public class Animation {
|
||||
public static void main(String[] args) {
|
||||
javax.swing.SwingUtilities.invokeLater(() -> {
|
||||
javax.swing.JFrame frame = new javax.swing.JFrame("Animation");
|
||||
frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
|
||||
frame.setSize(400, 400);
|
||||
|
||||
javax.swing.JPanel panel = new javax.swing.JPanel() {
|
||||
@Override
|
||||
protected void paintComponent(java.awt.Graphics g) {
|
||||
super.paintComponent(g);
|
||||
g.setColor(java.awt.Color.RED);
|
||||
g.fillOval(getX(), getY(), 30, 30);
|
||||
}
|
||||
};
|
||||
frame.add(panel);
|
||||
|
||||
javax.swing.Timer timer = new javax.swing.Timer(100, (e) -> {
|
||||
panel.setLocation((panel.getX() + 1) % 20, (panel.getY() + 1) % 20);
|
||||
panel.repaint();
|
||||
});
|
||||
timer.start();
|
||||
|
||||
frame.setVisible(true);
|
||||
});
|
||||
}
|
||||
}
|
58
midterm1/src/C4Q14.java
Normal file
58
midterm1/src/C4Q14.java
Normal file
@ -0,0 +1,58 @@
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
* Write a program that shows a frame with three buttons labeled “Red”,
|
||||
* “Green”, and “Blue”, and a label containing an icon showing a circle that is
|
||||
* initially red. As the user clicks the buttons, the fill color of the circle should
|
||||
* change. When you change the color, you need to invoke the repaint
|
||||
* method on the label. The call to repaint ensures that the paintIcon method
|
||||
* is called so that the icon can be repainted with the new color.
|
||||
*/
|
||||
public class C4Q14 {
|
||||
public static void main(String[] args) {
|
||||
javax.swing.SwingUtilities.invokeLater(() -> {
|
||||
javax.swing.JFrame frame = new javax.swing.JFrame("C4Q14");
|
||||
frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
|
||||
frame.setSize(400, 400);
|
||||
// frame.setLayout(new java.awt.BorderLayout());
|
||||
|
||||
javax.swing.JLabel label = new javax.swing.JLabel(new CircleIcon(java.awt.Color.RED, 300));
|
||||
frame.add(label, java.awt.BorderLayout.CENTER);
|
||||
|
||||
javax.swing.JPanel panel = new javax.swing.JPanel();
|
||||
panel.setLayout(new java.awt.FlowLayout());
|
||||
|
||||
javax.swing.JButton redButton = new javax.swing.JButton("Red");
|
||||
redButton.addActionListener((e) -> {
|
||||
label.setIcon(new CircleIcon(java.awt.Color.RED, 300));
|
||||
label.repaint();
|
||||
});
|
||||
panel.add(redButton);
|
||||
|
||||
javax.swing.JButton greenButton = new javax.swing.JButton("Green");
|
||||
greenButton.addActionListener((e) -> {
|
||||
label.setIcon(new CircleIcon(java.awt.Color.GREEN, 300));
|
||||
label.repaint();
|
||||
});
|
||||
greenButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
label.setIcon(new CircleIcon(java.awt.Color.GREEN, 300));
|
||||
label.repaint();
|
||||
}
|
||||
});
|
||||
panel.add(greenButton);
|
||||
|
||||
javax.swing.JButton blueButton = new javax.swing.JButton("Blue");
|
||||
blueButton.addActionListener((e) -> {
|
||||
label.setIcon(new CircleIcon(java.awt.Color.BLUE, 300));
|
||||
label.repaint();
|
||||
});
|
||||
panel.add(blueButton);
|
||||
|
||||
// frame.add(panel, java.awt.BorderLayout.SOUTH);
|
||||
frame.setVisible(true);
|
||||
});
|
||||
}
|
||||
}
|
29
midterm1/src/C4Q6.java
Normal file
29
midterm1/src/C4Q6.java
Normal file
@ -0,0 +1,29 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class C4Q6 {
|
||||
public static void main(String[] args) {
|
||||
ArrayList<String> a = new ArrayList<>(10);
|
||||
a.add("a");
|
||||
a.add("aa");
|
||||
a.add("aaa");
|
||||
a.add("aaaaa");
|
||||
a.add("aaaa");
|
||||
|
||||
String max = maximum(a, (s1, s2) -> {
|
||||
return Integer.compare(s1.length(), s2.length());
|
||||
});
|
||||
|
||||
System.out.println(max);
|
||||
}
|
||||
|
||||
public static String maximum(ArrayList<String> a, Comparator<String> c) {
|
||||
String max = a.getFirst();
|
||||
for (String s : a) {
|
||||
if (c.compare(s, max) > 0) {
|
||||
max = s;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
}
|
21
midterm1/src/C4Q9.java
Normal file
21
midterm1/src/C4Q9.java
Normal file
@ -0,0 +1,21 @@
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class C4Q9 {
|
||||
public static void main(String[] args) {
|
||||
String[] a = {"a", "aa", "aaa", "aaaa", "aaaaa"};
|
||||
String[] res = filter(a, (s) -> {
|
||||
return s.length() <= 3;
|
||||
});
|
||||
|
||||
for (String s : res) {
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] filter(String[] a, Filter f) {
|
||||
return Arrays.stream(a).filter((s) -> {
|
||||
return f.accept(s);
|
||||
}).toArray(String[]::new);
|
||||
}
|
||||
}
|
29
midterm1/src/CircleIcon.java
Normal file
29
midterm1/src/CircleIcon.java
Normal file
@ -0,0 +1,29 @@
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class CircleIcon implements Icon {
|
||||
private Color color;
|
||||
private int size;
|
||||
|
||||
public CircleIcon(Color color, int size) {
|
||||
this.color = color;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||
g.setColor(color);
|
||||
g.fillOval(x, y, size, size);
|
||||
}
|
||||
|
||||
public int getIconWidth() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public int getIconHeight() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setColor(Color color) {
|
||||
this.color = color;
|
||||
}
|
||||
}
|
3
midterm1/src/Filter.java
Normal file
3
midterm1/src/Filter.java
Normal file
@ -0,0 +1,3 @@
|
||||
public interface Filter {
|
||||
boolean accept(String x);
|
||||
}
|
24
midterm1/src/MidtermQ1.java
Normal file
24
midterm1/src/MidtermQ1.java
Normal file
@ -0,0 +1,24 @@
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class MidtermQ1 {
|
||||
public static void main(String[] args) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class CirclePanel extends JPanel {
|
||||
private Color color;
|
||||
|
||||
public void paintComponent(Graphics g) {
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
g2.setColor(color);
|
||||
g2.draw(new Ellipse2D.Double(0, 0, 100, 100));
|
||||
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user