diff --git a/build.gradle b/build.gradle index e9e8a46a70..8d5309ead4 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,7 @@ repositories { dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.5.0' + implementation 'com.google.code.gson:gson:2.8.6' } application { diff --git a/src/main/java/executor/command/CommandConvert.java b/src/main/java/executor/command/CommandConvert.java new file mode 100644 index 0000000000..e5189636a0 --- /dev/null +++ b/src/main/java/executor/command/CommandConvert.java @@ -0,0 +1,192 @@ +package executor.command; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.math.RoundingMode; +import java.net.URL; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import executor.task.TaskList; +import interpreter.Parser; +import ui.Ui; +import ui.Wallet; +import java.math.BigDecimal; + +/** + * This command helps to convert user entered currency amount into another country's currency amount using api call. + */ +public class CommandConvert extends Command { + private String from; + private String to; + private Double amount; + private Double exchangeRate = 0.00; + + /** + * Constructor for the CommandConvert class. + * @param userInput this is the userInput from the CLI + */ + public CommandConvert(String userInput) { + this.userInput = userInput; + this.commandType = CommandType.CONVERT; + this.amount = extractAmount(this.commandType, userInput); + this.from = getCurrencyCovertFrom(userInput); + this.to = getCurrencyConvertTo(userInput); + this.description = "Command that converts the user input cash amount from" + + " one currency to another and print it in the User Interface."; + } + + + @Override + public void execute(Wallet wallet) { + Double convertedAmount = this.convertCurrency(this.getFrom(), this.getTo(), this.getAmount()); + Ui.dukeSays(this.result(convertedAmount) + rateUsed()); + Ui.printSeparator(); + } + + + @Override + public void execute(TaskList taskList) { + + } + + + /** + * extractAmount parses the user input from CLI to get the amount which the user wishes to convert. + * @param commandType this is the type of command + * @param userInput takes the user entered input from CLI + * @return the amount which user wishes to convert is returned + */ + private Double extractAmount(CommandType commandType, String userInput) { + String amountStr = Parser.parseForPrimaryInput(commandType, userInput); + return Double.parseDouble(amountStr); + } + + /** + * getCurrencyConvertFrom parses user input for the flag "from". + * @param userInput this is the user entered input from CLI + * @return this function returns the 3 character unique string representing the currency to convert from + */ + private String getCurrencyCovertFrom(String userInput) { + String fromStr = Parser.parseForFlag("from", userInput); + return fromStr; + } + + /** + * getCurrencyConvertTo parses the user input for the flag "to". + * @param userInput this is the user entered input from CLI + * @return this function return the 3 character unique string representing the currency to covert to + */ + private String getCurrencyConvertTo(String userInput) { + String toStr = Parser.parseForFlag("to", userInput); + return toStr; + } + + /** + * consultCurrencyApi is a function which gets the JSON object from the api. + * @param from String is the country code from which we are converting currency + * @param to String is the country code to which we are converting the currency + * @return this function returns a string version of the json object or else it will return null + */ + private String consultCurrencyApi(String from, String to) { + try { + URL url = new URL("https://api.ratesapi.io/api/latest?base=" + from + "&symbols=" + to); + BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); + String line; + String completeJson = ""; + while (null != (line = reader.readLine())) { + completeJson += line; + } + return completeJson; + } catch (Exception ex) { + ex.printStackTrace(); + return null; + } + } + + /** + * convertCurrency is a function used to loop through the string version of the json. + * @param from String is the country code from which we are converting currency + * @param to String is the country code to which we are converting the currency + * @param amount this is amount of currency which the user wants to convert + * @return this function returns the converted amount of the currency or else returns null + */ + private Double convertCurrency(String from, String to, Double amount) { + try { + String json = consultCurrencyApi(from,to); + if (json != null) { + JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject(); + String rate = jsonObject.getAsJsonObject("rates").get(to).getAsString(); + BigDecimal exchangeRate = new BigDecimal(rate); + double exRate = exchangeRate.doubleValue(); + setExchangeRate(exRate); + double convertedAmount = exRate * amount; + return convertedAmount; + } + } catch (Exception e) { + Ui.dukeSays(e.getMessage()); + Ui.dukeSays(Ui.LINE); + Ui.dukeSays("Please enter in the following format : " + + "convert 2000 /from USD /to EUR"); + } + return null; + } + + /** + * result basically returns the to.string() version of the output that the user will be shown + * @param convertedAmount this is amount which was converted into + * @return string of output is returned + */ + private String result(Double convertedAmount) { + convertedAmount = roundByDecimalPlace(convertedAmount, 2); + return "DUKE$$$ has converted " + this.from + + " " + roundByDecimalPlace(this.amount, 2) + " " + + "to" + " " + + this.to + " " + convertedAmount + "\n"; + } + + /** + * roundByDecimalPlace is basically a function to round the values to a specific number of decimal places. + * @param value this is the value which we want to round + * @param places number of decimal places + * @return the rounded double value is returned as the output + */ + private double roundByDecimalPlace(double value, int places) { + if (places < 0) { + throw new IllegalArgumentException(); + } + + BigDecimal bd = BigDecimal.valueOf(value); + bd = bd.setScale(places, RoundingMode.HALF_UP); + return bd.doubleValue(); + } + + + /** + * rateUsed is a function that helps to display the exchange rate which was used for the conversion. + * @return string version of the exchange rate is displayed + */ + private String rateUsed() { + return "Exchange rate used = " + this.getExchangeRate().toString() + "\n"; + } + + private String getFrom() { + return from; + } + + private String getTo() { + return to; + } + + private Double getAmount() { + return amount; + } + + public Double getExchangeRate() { + return exchangeRate; + } + + private void setExchangeRate(Double exchangeRate) { + exchangeRate = roundByDecimalPlace(exchangeRate, 3); + this.exchangeRate = exchangeRate; + } +} diff --git a/src/main/java/executor/command/CommandGetSpendingByMonth.java b/src/main/java/executor/command/CommandGetSpendingByMonth.java new file mode 100644 index 0000000000..8af74217d8 --- /dev/null +++ b/src/main/java/executor/command/CommandGetSpendingByMonth.java @@ -0,0 +1,77 @@ +package executor.command; + +import executor.task.TaskList; +import interpreter.Parser; +import ui.ReceiptTracker; +import ui.Ui; +import ui.Wallet; + +public class CommandGetSpendingByMonth extends Command { + protected String userInput; + + /** + * Constructor to explain about the command. + * @param userInput is the input from the user + */ + public CommandGetSpendingByMonth(String userInput) { + this.commandType = CommandType.EXPENDED; + this.userInput = userInput; + this.description = "Provides the user the total expenditure for the month stated. " + + "FORMAT: expended /year"; + } + + @Override + public void execute(TaskList taskList) { + } + + @Override + public void execute(Wallet wallet) { + ReceiptTracker receiptsInMonth = new ReceiptTracker(); + String monthStr = Parser.parseForPrimaryInput(CommandType.EXPENDED, userInput); + int month = monthStrToInt(monthStr); + if (month != 0) { + int year = Integer.parseInt(Parser.parseForFlag("year", userInput)); + receiptsInMonth = wallet.getReceipts().findReceiptByMonthYear(month, year); + Double totalMoney = receiptsInMonth.getTotalCashSpent(); + Ui.dukeSays("The total amount of money spent in " + monthStr + " " + year + " : " + totalMoney); + } else { + Ui.dukeSays("Invalid input, CORRECT FORMAT : expended "); + } + } + + /** + * Returns the corresponding month value. + * @param month is the name of month from the userInput + * @return the value of month, eg: march --> 3. + */ + public int monthStrToInt(String month) { + switch (month) { + case "january": + return 1; + case "february": + return 2; + case "march": + return 3; + case "april": + return 4; + case "may": + return 5; + case "june": + return 6; + case "july": + return 7; + case "august": + return 8; + case "september": + return 9; + case "october": + return 10; + case "november": + return 11; + case "december": + return 12; + default: + return 0; + } + } +} diff --git a/src/main/java/executor/command/CommandType.java b/src/main/java/executor/command/CommandType.java index 6425e6abd6..bd62d8a74f 100644 --- a/src/main/java/executor/command/CommandType.java +++ b/src/main/java/executor/command/CommandType.java @@ -23,6 +23,8 @@ public enum CommandType { RECUR(CommandNewTask.class), FDURATION(CommandNewTask.class), TAGLIST(CommandListTag.class), + EXPENDED(CommandGetSpendingByMonth.class), + CONVERT(CommandConvert.class), ERROR(CommandError.class); private final Class commandClass; diff --git a/src/main/java/ui/ReceiptTracker.java b/src/main/java/ui/ReceiptTracker.java index befaab2659..a14761ece5 100644 --- a/src/main/java/ui/ReceiptTracker.java +++ b/src/main/java/ui/ReceiptTracker.java @@ -2,6 +2,7 @@ import duke.exception.DukeException; +import java.time.LocalDate; import java.util.ArrayList; import java.util.HashMap; @@ -90,6 +91,22 @@ public ReceiptTracker findReceiptsByTag(String tag) { return taggedReceipts; } + /** + * Finds all the receipts that corresponds to that month and year. + * @param month is the month given by the user + * @param year is the year given by the user + * @return ArrayList containing all the receipts which corresponds to year and month + */ + public ReceiptTracker findReceiptByMonthYear(int month, int year) { + ReceiptTracker receiptByMonthYear = new ReceiptTracker(); + for (Receipt receipt : this) { + if ((receipt.getDate().getMonthValue() == month) && (receipt.getDate().getYear() == year)) { + receiptByMonthYear.addReceipt(receipt); + } + } + return receiptByMonthYear; + } + // -- Boolean Functions /** * Checks if a tag has been registered previously.