diff --git a/src/main/java/org/keith/core/Amortization.java b/src/main/java/org/keith/core/Amortization.java index 164c42e..6abb411 100644 --- a/src/main/java/org/keith/core/Amortization.java +++ b/src/main/java/org/keith/core/Amortization.java @@ -5,7 +5,6 @@ import java.lang.Math; import java.text.DecimalFormat; import java.text.NumberFormat; -import java.util.Scanner; public class Amortization extends LoanDetails { private final int ifFavorable = 35, @@ -17,12 +16,13 @@ public class Amortization extends LoanDetails { adequate = "Adequate", highRisk = "High Risk!", yes = "Y", - no = "N"; - private final String valueFormat = "0.##"; - private final String ANSI_RESET = "\u001B[0m", - ANSI_GREEN = "\u001B[32m", - ANSI_RED = "\u001B[31m", - ANSI_YELLOW = "\u001B[33m"; + no = "N", + scheduleNeedInput = "Do you want a Schedule(Y/N): ", + valueFormat = "0.##", + ANSI_RESET = "\u001B[0m", + ANSI_GREEN = "\u001B[32m", + ANSI_RED = "\u001B[31m", + ANSI_YELLOW = "\u001B[33m"; private String input; LoanDetails loanDetails = new LoanDetails(); @@ -55,7 +55,7 @@ private void checkIfSchedulerNeeded(){ loanDetails.getAnnualInterestRate(), loanDetails.getNumberPayment()); Menu menu = new Menu(); - getInput(); + input = getInput(); switch (input.toUpperCase()){ case yes -> scheduler.getTable(); @@ -82,11 +82,9 @@ public String formatToTwoDigits(Double value){ return df.format(value); } - private void getInput(){ + private String getInput(){ SingletonScanner singletonScanner = SingletonScanner.getInstance(); - Scanner scanner = singletonScanner.getScanner(); - System.out.print("Do you want a Schedule(Y/N): "); - input = scanner.nextLine(); + return singletonScanner.getString(scheduleNeedInput); } public Double calculateInterestInDecimals(){ diff --git a/src/main/java/org/keith/core/LoanInput.java b/src/main/java/org/keith/core/LoanInput.java index 658dd42..5a4a22c 100644 --- a/src/main/java/org/keith/core/LoanInput.java +++ b/src/main/java/org/keith/core/LoanInput.java @@ -1,5 +1,4 @@ package org.keith.core; -import java.util.Scanner; public class LoanInput{ private Integer principle , @@ -7,38 +6,35 @@ public class LoanInput{ paymentAmount, grossIncome; private Double interest; - private boolean isRunningterms = true; + private final String paymentAmountInput = "Number of payments in a single year: ", + principleInput = "Loan amount: ", + termsInput = "Terms(year): ", + grossIncomeInput = "Gross income: ", + interestInput = "Interest rate: "; + private boolean isRunningTerms = true; SingletonScanner singletonScanner = SingletonScanner.getInstance(); - Scanner scanner = singletonScanner.getScanner(); // Check Terms based on the type of loan private void checkTerms(Integer maxTerms){ - while(isRunningterms) { - if (mustBeLessThanMaxTerms(maxTerms)) { - paymentAmount = getPaymentAmount(); - isRunningterms = false; - } else if(ifGreaterThanMaxTerms(maxTerms)){ - System.out.println("Maximum allowed term is " + maxTerms + " years"); - terms = getTermsAmount(); + while(isRunningTerms) { + terms = getTermsAmount(); + + if(checkIfLessThanMaxTerms(maxTerms)){ + break; } -// break; } } - private Boolean mustBeLessThanMaxTerms(Integer maxTerms){ + private Boolean checkIfLessThanMaxTerms(Integer maxTerms){ return terms <= maxTerms; } - private Boolean ifGreaterThanMaxTerms(Integer maxTerms){ - return terms >= maxTerms; - } - public void getLoanInfo(Integer maxTerms){ + System.out.println("Enter your loan information."); principle = getPrincipleAmount(); - terms = getTermsAmount(); checkTerms(maxTerms); - + paymentAmount = getPaymentAmount(); interest = getInterest(); grossIncome = getGrossIncome(); Amortization amortization = new Amortization(principle, @@ -50,31 +46,30 @@ public void getLoanInfo(Integer maxTerms){ } private Integer getPrincipleAmount(){ - System.out.print(""" - Enter your loan information. - Loan amount:\s"""); - return Integer.parseInt(scanner.nextLine()); + return parseInteger(singletonScanner.getString(principleInput)); } private Integer getTermsAmount(){ - System.out.print("Terms(year): "); - return Integer.parseInt(scanner.nextLine()); + return parseInteger(singletonScanner.getString(termsInput)); } private Integer getPaymentAmount(){ - System.out.print("Number of payments in a single year: "); - return Integer.parseInt(scanner.nextLine()); + return parseInteger(singletonScanner.getString(paymentAmountInput)); } private Double getInterest(){ - System.out.print("Interest rate: "); - return Double.parseDouble(scanner.nextLine()); + return parseDouble(singletonScanner.getString(interestInput)); } private Integer getGrossIncome(){ + return parseInteger(singletonScanner.getString(grossIncomeInput)); + } + + private Integer parseInteger(String value){ + return Integer.parseInt(value); + } - System.out.print("Gross income: "); - return Integer.parseInt(scanner.nextLine()); -// scanner.nextLine(); + private Double parseDouble(String value){ + return Double.parseDouble(value); } } \ No newline at end of file diff --git a/src/main/java/org/keith/core/Scheduler.java b/src/main/java/org/keith/core/Scheduler.java index 062f3e0..46f5740 100644 --- a/src/main/java/org/keith/core/Scheduler.java +++ b/src/main/java/org/keith/core/Scheduler.java @@ -9,8 +9,8 @@ public class Scheduler{ private Integer principle; private Integer endPeriod, numberPayment; - private Double monthlyPayments; - private Double balance, + private Double monthlyPayments, + balance, annualInterest, periodInterest, principlePaid = 0.0, @@ -33,9 +33,12 @@ protected void getTable(){ balance = convertToDouble(principle); periodInterest = calculatePeriodInterest(annualInterest, numberPayment); for(int period = startPeriod; period <= endPeriod; period++){ - interestPaid = balance * periodInterest; - principlePaid = monthlyPayments - interestPaid; - balance -= principlePaid; +// interestPaid = balance * periodInterest; + interestPaid = calculateInterestPaid(); +// principlePaid = monthlyPayments - interestPaid; + principlePaid = calculatePrinciplePaid(); +// balance -= principlePaid; + balance = calculateNewBalance(); System.out.println("Period: " + period + ", Principle: " + formatToCurrency(principlePaid) + ", Interest: " + formatToCurrency(interestPaid) + ", Balance: " + formatToCurrency(balance)); } System.out.println("Monthly Payment: " + formatToCurrency(monthlyPayments)); @@ -63,4 +66,15 @@ private String formatToCurrency(Double value){ NumberFormat cf = NumberFormat.getCurrencyInstance(); return cf.format(value); } + + private Double calculateInterestPaid(){ + return balance * periodInterest; + } + + private Double calculatePrinciplePaid(){ + return monthlyPayments - interestPaid; + } + private Double calculateNewBalance(){ + return balance -= principlePaid; + } } diff --git a/src/main/java/org/keith/core/SingletonScanner.java b/src/main/java/org/keith/core/SingletonScanner.java index 3f8f23e..16ec21f 100644 --- a/src/main/java/org/keith/core/SingletonScanner.java +++ b/src/main/java/org/keith/core/SingletonScanner.java @@ -5,20 +5,26 @@ public class SingletonScanner{ private static SingletonScanner instance = null; - private static Scanner scanner = null; + private Scanner scanner; - private SingletonScanner() {} + // Guarantees that no scanner object can be created outside SingletonScanner class + private SingletonScanner() { + scanner = new Scanner(System.in); + scanner.useLocale(Locale.US); // makes . for decimal input possible + } public static SingletonScanner getInstance() { if (instance == null) { instance = new SingletonScanner(); - scanner = new Scanner(System.in); - scanner.useLocale(Locale.US); } return instance; } - public Scanner getScanner() { - return scanner; + public String getString(String sPrompt) { + System.out.print(sPrompt); + scanner.useDelimiter("\r\n"); // Setting this delimiter ensures that we capture everything up to the key. Without this, input stops at the next whitespace (space, tab, newline etc.). + String sInput = scanner.nextLine(); + scanner.reset(); // The preceding use of useDelimiter() changed the state of the Scanner object. reset() re-establishes the original state. + return sInput; } } \ No newline at end of file diff --git a/src/main/java/org/keith/menu/Menu.java b/src/main/java/org/keith/menu/Menu.java index 7381770..aab9559 100644 --- a/src/main/java/org/keith/menu/Menu.java +++ b/src/main/java/org/keith/menu/Menu.java @@ -3,7 +3,6 @@ import org.keith.core.LoanInput; import org.keith.core.SingletonScanner; import org.keith.menu.enums.MenuCommand; -import java.util.Scanner; public class Menu { private final String MENU = """ @@ -25,7 +24,7 @@ public void LOGO() { """); } public final String WELCOME_MSG = """ - LOAN CLI v1.0.2 + LOAN CLI v1.0.3 © Keith Atmodimedjo Type "help" to list command options. """; @@ -42,9 +41,9 @@ public void LOGO() { LoanInput mi = new LoanInput(); public void getMenuInput(){ - while(isRunning){ + MAIN_LOOP:while(isRunning){ try { - getInput(); + input = getInput(); // if input is empty continue to print the option number message above if (ifInputIsEmpty()) { @@ -57,7 +56,9 @@ public void getMenuInput(){ case MORTGAGE -> mi.getLoanInfo(maxMortgageTerms); case CAR -> mi.getLoanInfo(maxVehicleTerms); case HELP -> showMenu(); - case EXIT -> isRunning = false; + case EXIT -> { + break MAIN_LOOP; + } default -> getInput(); } @@ -85,10 +86,8 @@ private void showMenu(){ System.out.print(MENU); } - public void getInput(){ + public String getInput(){ SingletonScanner singletonScanner = SingletonScanner.getInstance(); - Scanner scanner = singletonScanner.getScanner(); - System.out.print(cmdLine); - input = scanner.nextLine(); + return singletonScanner.getString(cmdLine); } } \ No newline at end of file