diff --git a/.idea/misc.xml b/.idea/misc.xml index fdc35ea..efb1e13 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -8,7 +8,7 @@ - + \ No newline at end of file diff --git a/pom.xml b/pom.xml index fad9976..de5362c 100644 --- a/pom.xml +++ b/pom.xml @@ -13,5 +13,13 @@ 21 UTF-8 + + + junit + junit + RELEASE + test + + \ No newline at end of file diff --git a/src/main/java/org/codedifferently/IssueType.java b/src/main/java/org/codedifferently/IssueType.java new file mode 100644 index 0000000..e3ac3ae --- /dev/null +++ b/src/main/java/org/codedifferently/IssueType.java @@ -0,0 +1,8 @@ +package org.codedifferently; + +public enum IssueType { + ELECTRICAL, + PLUMBING, + HVAC, + APPLIANCE +} \ No newline at end of file diff --git a/src/main/java/org/codedifferently/Main.java b/src/main/java/org/codedifferently/Main.java index 435139b..6641b75 100644 --- a/src/main/java/org/codedifferently/Main.java +++ b/src/main/java/org/codedifferently/Main.java @@ -1,17 +1,9 @@ package org.codedifferently; -//TIP To Run code, press or -// click the icon in the gutter. +import java.util.Scanner; + public class Main { public static void main(String[] args) { - //TIP Press with your caret at the highlighted text - // to see how IntelliJ IDEA suggests fixing it. - System.out.printf("Hello and welcome!"); - - for (int i = 1; i <= 5; i++) { - //TIP Press to start debugging your code. We have set one breakpoint - // for you, but you can always add more by pressing . - System.out.println("i = " + i); - } + MaintenanceTracker.displayMenu(new Scanner(System.in)); } } \ No newline at end of file diff --git a/src/main/java/org/codedifferently/MaintenanceOffice.java b/src/main/java/org/codedifferently/MaintenanceOffice.java new file mode 100644 index 0000000..6bb395f --- /dev/null +++ b/src/main/java/org/codedifferently/MaintenanceOffice.java @@ -0,0 +1,146 @@ +package org.codedifferently; + +import java.util.ArrayList; +import java.util.Scanner; +import java.util.EnumMap; + +public class MaintenanceOffice { + private static ArrayList requests; + EnumMap severityCounts; + EnumMap issueCounts; + private static int closures = 0; + + public MaintenanceOffice() { + requests = new ArrayList<>(); + + severityCounts = new EnumMap<>(Severity.class); + issueCounts = new EnumMap<>(IssueType.class); + + // Initialize all enum values to 0 + for (Severity s : Severity.values()) { + severityCounts.put(s, 0); + } + + for (IssueType type : IssueType.values()) { + issueCounts.put(type, 0); + } + } + + public void assignTechnician(MaintenanceRequest request) { + if (request.getAssignedTechnician().equals("None")) { + if (request.getSeverity() == Severity.HIGH) { + request.setAssignedTechnician("Senior Technician"); + System.out.println("\nSenior Technician assigned to request #" + request.getRequestId()); + } else { + request.setAssignedTechnician("Junior Technician"); + System.out.println("\nJunior Technician to request #" + request.getRequestId()); + } + request.setStatus(Status.IN_PROGRESS); + } else { + System.out.println("\nA technician has already been assigned to this request."); + } + } + + public void addRequest(MaintenanceRequest request) { + requests.add(request); + + // Update severity count + Severity severity = request.getSeverity(); + severityCounts.put(severity, severityCounts.get(severity) + 1); + + // Update issue type count + IssueType type = request.getIssueType(); + issueCounts.put(type, issueCounts.get(type) + 1); + } + + public void getProgressUpdate() { + System.out.println("\nReceiving progress report. Type \"View\" to see updates."); + for (MaintenanceRequest request : requests) { + if (request.getStatus() == Status.IN_PROGRESS) { + request.setStatus(Status.DONE); + } + } + } + + public MaintenanceRequest searchRequest(int aptNum, Scanner sc) { + ArrayList requestsFound = new ArrayList<>(); + for (MaintenanceRequest request : requests) { + if (request.getApartmentNumber() == aptNum) { + requestsFound.add(request); + } + } + // Returns null if the customer is not found. + if (requestsFound.isEmpty()) { + return null; + // Returns the customer if there are no duplicate phone numbers. + } else if (requestsFound.size() == 1) { + return requestsFound.getFirst(); + // Prompts the user to select by customer id since more than one customer used the same phone number. + } else { + System.out.println("\nMultiple requests found: " + requestsFound + "\n"); + while(true) { + System.out.print("Enter request id: "); + int requestId = sc.nextInt(); + sc.nextLine(); + for (MaintenanceRequest request : requests) { + if (request.getRequestId() == requestId) { + return request; + } + } + System.out.println("Invalid tenant name. Try again.\n"); + } + } + } + + public void printDailyReport() { + System.out.println("=== DAILY REPORT ==="); + System.out.println("Total Requests: " + MaintenanceRequest.getCount()); + System.out.println("Number of Open Requests: " + requests.size()); + System.out.println("Number of Closed Requests: " + closures); + + System.out.println("\nSeverity Breakdown:"); + for (Severity s : severityCounts.keySet()) { + System.out.println(s + " CASES: " + severityCounts.get(s)); + } + + System.out.println("\nMost Common Issue Type: " + getMostCommonIssueType()); + + if (severityCounts.get(Severity.HIGH) > 3) { + System.out.println("WARNING: SYSTEM OVERLOADED."); + } + } + + private IssueType getMostCommonIssueType() { + IssueType mostCommon = null; + int max = 0; + + for (IssueType type : issueCounts.keySet()) { + int count = issueCounts.get(type); + + if (count > max) { + max = count; + mostCommon = type; + } + } + return mostCommon; + } + + public void closeRequest(MaintenanceRequest request) { + if (request.getStatus() == Status.DONE) { + requests.remove(request); + System.out.println("\nRequest closed successfully."); + closures++; + } else { + System.out.println("\nCannot close request unless it is DONE."); + } + } + + public void viewRequests() { + System.out.println("\nActive Requests"); + System.out.println(requests); + } + + public ArrayList getRequests() { + return requests; + } +} diff --git a/src/main/java/org/codedifferently/MaintenanceRequest.java b/src/main/java/org/codedifferently/MaintenanceRequest.java new file mode 100644 index 0000000..7f04839 --- /dev/null +++ b/src/main/java/org/codedifferently/MaintenanceRequest.java @@ -0,0 +1,209 @@ +package org.codedifferently; + +import java.util.ArrayList; +import java.util.Scanner; + +public class MaintenanceRequest { + private static int count = 0; + + private String tenantName; + private int apartmentNumber; + private IssueType issueType; + private Severity severity; + private Status status; + private String assignedTechnician; + private int requestId; + + public MaintenanceRequest(String tenantName, int apartmentNumber, IssueType issueType, int severity) { + this.tenantName = tenantName; + this.apartmentNumber = apartmentNumber; + this.issueType = issueType; + if (severity == 1 || severity == 2) { + this.severity = Severity.LOW; + } else if (severity == 3 || severity == 4) { + this.severity = Severity.MEDIUM; + } else { + this.severity = Severity.HIGH; + } + this.status = Status.NEW; + this.requestId = count + 1; + this.assignedTechnician = "None"; + } + + public String getTenantName() { + return tenantName; + } + + public void setTenantName(String tenantName) { + this.tenantName = tenantName; + } + + public int getApartmentNumber() { + return apartmentNumber; + } + + public void setApartmentNumber(int apartmentNumber) { + this.apartmentNumber = apartmentNumber; + } + + public IssueType getIssueType() { + return issueType; + } + + + public Severity getSeverity() { + return severity; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public int getRequestId() { + return requestId; + } + + public static int getCount() { + return count; + } + + public static void setCount(int count) { + MaintenanceRequest.count = count; + } + + public static MaintenanceRequest createRequest(Scanner sc) { + String name = validateName(sc); + int apt = validateAptNum(sc); + IssueType type = validateIssueType(sc); + int severity = validateSeverity(sc); + + MaintenanceRequest ticket = new MaintenanceRequest(name, apt, type, severity); + + System.out.print("\nMaintenance request created.\n"); + + System.out.println("\nMaintenance Request"); + System.out.println("Name: " + ticket.getTenantName()); + System.out.println("Apartment Number: " + ticket.getApartmentNumber()); + System.out.println("Issue Type: " + ticket.getIssueType()); + System.out.println("Severity: " + ticket.getSeverity()); + + if (severity >= 5 && type == IssueType.ELECTRICAL) { + System.out.println("WARNING! THIS REQUEST REQUIRES URGENT ATTENTION"); + } + + setCount(count + 1); + return ticket; + } + + + @Override + public String toString() { + return "[Name: " + this.tenantName + + ", Request Id: " + this.requestId + + ", Apartment Number: " + this.apartmentNumber + + ", Issue Type: " + this.issueType + + ", Severity: " + this.severity + + ", Status: " + this.getStatus() + + ", Technician: " + this.getAssignedTechnician() + "]\n"; + } + + // Validates that the user's name input contains only permitted characters. + public static String validateName(Scanner sc) { + // Repeats continuously until valid input is provided. + while (true) { + // Prompts the user to enter their name. + System.out.print("\nEnter a name: "); + String name = sc.nextLine(); + + // Checks whether the input matches the required name pattern. + // Allows letters and optionally single spaces, hyphens, or apostrophes between words. + if (name.matches("^[a-zA-Z]+([ '-][a-zA-Z]+)*$")) { + // Returns the validated name if it meets the pattern requirements. + return name; + } else { + // Displays an error message if validation fails. + System.out.println("\nInvalid name. Please use letters only."); + } + } + } + + public static int validateAptNum(Scanner sc) { + // Repeats continuously until valid input is provided. + while (true) { + // Prompts the user to enter a severity level. + System.out.print("Enter an apartment number: "); + // Captures the full line of user input. + String input = sc.nextLine(); + + try { + return Integer.parseInt(input); + } catch (NumberFormatException e) { + // Displays an error message if the input cannot be parsed as a number. + System.out.println("\nInvalid input. Please enter a number.\n"); + } + } + } + + public static int validateSeverity(Scanner sc) { + // Repeats continuously until valid input is provided. + while (true) { + // Prompts the user to enter a severity level. + System.out.print("Rate its severity on a scale from 1-5: "); + // Captures the full line of user input. + String input = sc.nextLine(); + + try { + // Attempts to convert the input into an integer. + int severity = Integer.parseInt(input); + // Checks whether the integer falls within the valid range. + if (severity >= 1 && severity <= 5) { + // Returns the validated severity level. + return severity; + } else { + // Displays an error message if the number is outside the valid range. + System.out.println("\nInvalid input. Please enter a number from 1-5.\n"); + } + } catch (NumberFormatException e) { + // Displays an error message if the input cannot be parsed as a number. + System.out.println("\nInvalid input. Please enter a number from 1-5.\n"); + } + } + } + + public static IssueType validateIssueType(Scanner sc) { + // Repeats continuously until valid input is provided. + while (true) { + // Prompts the user to enter their name. + System.out.print("Enter issue type: "); + String issueType = sc.nextLine(); + + if (issueType.equalsIgnoreCase("Electrical")) { + return IssueType.ELECTRICAL; + } else if (issueType.equalsIgnoreCase("HVAC")) { + return IssueType.HVAC; + } else if (issueType.equalsIgnoreCase("PLUMBING")) { + return IssueType.PLUMBING; + } else if (issueType.equalsIgnoreCase("APPLIANCE")) { + return IssueType.APPLIANCE; + } else { + System.out.println(""" + + Invalid issue type. We only handle Electrical,\ + HVAC, Plumbing, or Appliance related inquiries. + """); + } + } + } + + public String getAssignedTechnician() { + return assignedTechnician; + } + + public void setAssignedTechnician(String assignedTechnician) { + this.assignedTechnician = assignedTechnician; + } +} diff --git a/src/main/java/org/codedifferently/MaintenanceTracker.java b/src/main/java/org/codedifferently/MaintenanceTracker.java new file mode 100644 index 0000000..ff270c6 --- /dev/null +++ b/src/main/java/org/codedifferently/MaintenanceTracker.java @@ -0,0 +1,75 @@ +package org.codedifferently; + +import java.sql.SQLOutput; +import java.util.Scanner; + +public class MaintenanceTracker { + private static MaintenanceOffice office = new MaintenanceOffice(); + + public static void displayMenu(Scanner sc) { + String input; + int aptNum; + do { + // Displays the main menu options to the user. + System.out.println("\n=== Maintenance Management Menu ==="); + System.out.println("Type \"Enter\" to make a new request."); + System.out.println("Type \"View\" to view all current requests."); + System.out.println("Type \"Assign\" to assign a technician."); + System.out.println("Type \"Status\" to get a status update on all requests."); + System.out.println("Type \"Close\" to close a request."); + System.out.println("Type \"Report\" to print a daily report."); + System.out.println("Type \"Done\" to exit out."); + System.out.print("Selection: "); + + // Validates numeric input before processing. + input = sc.nextLine().toLowerCase(); + switch (input) { + case "enter": + MaintenanceRequest request = MaintenanceRequest.createRequest(sc); + office.addRequest(request); + if (request.getIssueType() == IssueType.ELECTRICAL && request.getSeverity() == Severity.HIGH) { + office.assignTechnician(request); + } + break; + case "view": + office.viewRequests(); + break; + case "assign": + System.out.print("Enter an apt number: "); + aptNum = sc.nextInt(); + sc.nextLine(); + MaintenanceRequest toAssign = office.searchRequest(aptNum, sc); + if (toAssign != null) { + office.assignTechnician(toAssign); + } else { + System.out.println("Apartment Number not found. Please try again."); + } + break; + case "status": + office.getProgressUpdate(); + break; + case "close": + System.out.print("Enter an apt number: "); + aptNum = sc.nextInt(); + sc.nextLine(); + MaintenanceRequest toClose = office.searchRequest(aptNum, sc); + if (toClose != null) { + office.closeRequest(toClose); + } else { + System.out.println("Apartment Number not found. Please try again"); + } + break; + case "report": + office.printDailyReport(); + break; + case "done": + break; + default: + System.out.println("\nPlease select a valid option."); + } + // Stopping condition. Program will exit when the user inputs 0. + } while (!(input.equalsIgnoreCase("Done"))); + System.out.println("\nGoodbye."); + sc.close(); + } +} diff --git a/src/main/java/org/codedifferently/Severity.java b/src/main/java/org/codedifferently/Severity.java new file mode 100644 index 0000000..7daa6d4 --- /dev/null +++ b/src/main/java/org/codedifferently/Severity.java @@ -0,0 +1,7 @@ +package org.codedifferently; + +public enum Severity { + LOW, + MEDIUM, + HIGH +} diff --git a/src/main/java/org/codedifferently/Status.java b/src/main/java/org/codedifferently/Status.java new file mode 100644 index 0000000..98b186b --- /dev/null +++ b/src/main/java/org/codedifferently/Status.java @@ -0,0 +1,7 @@ +package org.codedifferently; + +public enum Status { + NEW, + IN_PROGRESS, + DONE +}