diff --git a/build.gradle b/build.gradle index fbdd30592c..b258772071 100644 --- a/build.gradle +++ b/build.gradle @@ -46,7 +46,7 @@ test { } application { - mainClass.set("dude.Dude") + mainClass.set("dude.Launcher") } shadowJar { diff --git a/src/main/java/dude/Dude.java b/src/main/java/dude/Dude.java index a76bf44682..8b28f385de 100644 --- a/src/main/java/dude/Dude.java +++ b/src/main/java/dude/Dude.java @@ -1,16 +1,12 @@ package dude; import java.io.IOException; -import java.util.NoSuchElementException; -import java.util.Scanner; import dude.commands.Command; -import dude.commands.CommandTypes; import dude.commands.Parser; import dude.exceptions.DudeException; import dude.tasks.TaskList; import dude.utils.Storage; -import dude.utils.Ui; /** @@ -22,12 +18,12 @@ * parsing it into a command, executing the command and saving the task list to disk. **/ public class Dude { + private static final String STORAGE_LOADING_ERROR_MESSAGE = "An error occurred while loading the tasks. " + + "Deleting the storage and starting with an empty task list."; + private static final String STORAGE_SAVING_ERROR_MESSAGE = "An error occurred while saving the tasks to disk."; private final TaskList taskList; private final Storage storage; - private final Ui ui; - private boolean isRunning = true; - /** * Constructor for the Dude class. *
@@ -38,72 +34,27 @@ public class Dude { */ public Dude(String filePath) { this.storage = new Storage(filePath); - this.ui = new Ui(); - - TaskList temp = null; - try { - temp = this.storage.loadTasks(); - } catch (Exception e) { //Thrown when file gets corrupted - System.out.println("An error occurred while loading the tasks. Deleting the storage and starting with " - + "an empty task list."); - this.storage.deleteStorage(); - temp = new TaskList(); - } - - this.taskList = temp; + this.taskList = loadTaskList(); } + /** + * The main method used to interact with dude. User input is passed to this method to execute the + * appropriate command and send back a response from dude. + *
+ * + * @param input The user input to be processed. + */ public String getResponse(String input) { Command c = Parser.parse(input, taskList); String response = executeCommand(c); try { - saveToDisk(); + saveTaskListToDisk(); } catch (IOException e) { - return "An error occurred while saving the tasks to disk."; + return STORAGE_SAVING_ERROR_MESSAGE; } return response; } - /** - * This method runs the main loop of the application. - *
- * This method is responsible for reading user input, parsing it into a command,
- * executing the command and saving the task list to disk.
- */
- public void run() {
-
- ui.showWelcome();
- Scanner sc = new Scanner(System.in);
- while (this.isRunning) {
- String input = extractInput(sc);
- Command command = Parser.parse(input, taskList);
-
- String response = executeCommand(command);
- ui.showMessage(response);
-
- try {
- saveToDisk();
- } catch (IOException e) {
- System.out.println("An error occurred while saving the tasks to disk.");
- }
-
- if (command.getCommandType() == CommandTypes.BYE) {
- this.isRunning = false;
- }
- }
- }
-
- private static String extractInput(Scanner sc) {
- String input = "";
- try {
- input = sc.nextLine();
- } catch (NoSuchElementException e) {
- //this will not be handled. App will only exit at bye command.
- input = "";
- }
- return input;
- }
-
private static String executeCommand(Command command) {
try {
return command.execute();
@@ -112,8 +63,20 @@ private static String executeCommand(Command command) {
}
}
- private void saveToDisk() throws IOException, SecurityException {
+ private void saveTaskListToDisk() throws IOException, SecurityException {
this.storage.saveTasks(taskList);
}
+ private TaskList loadTaskList() {
+ TaskList temp;
+ try {
+ temp = this.storage.loadTasks();
+ } catch (Exception e) { //Thrown when file gets corrupted
+ System.out.println(STORAGE_LOADING_ERROR_MESSAGE);
+ this.storage.deleteStorage();
+ temp = new TaskList();
+ }
+ return temp;
+ }
+
}
diff --git a/src/main/java/dude/Launcher.java b/src/main/java/dude/Launcher.java
index 97dd1dafc9..ec85912d2e 100644
--- a/src/main/java/dude/Launcher.java
+++ b/src/main/java/dude/Launcher.java
@@ -2,8 +2,16 @@
import javafx.application.Application;
+/**
+ * A Launcher class that acts as the entry point for the application.
+ */
public class Launcher {
+ /**
+ * Launches the application.
+ *
+ * @param args The command line arguments.
+ */
public static void main(String[] args) {
Application.launch(Main.class, args);
}
diff --git a/src/main/java/dude/Main.java b/src/main/java/dude/Main.java
index 7baf14ade9..1ae8e5c750 100644
--- a/src/main/java/dude/Main.java
+++ b/src/main/java/dude/Main.java
@@ -1,20 +1,40 @@
package dude;
+import java.io.IOException;
+
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
-import java.io.IOException;
-
+/**
+ * The Main class is used to boot up the GUI for the application.
+ */
public class Main extends Application {
+ /**
+ * Method caled to start the application. It initializes the UI and sets up the javafx stage
+ *
+ * @param stage The stage to be used for the application.
+ */
@Override
public void start(Stage stage) {
stage.setTitle("Dude");
stage.setResizable(false);
+ Scene scene = loadMainScene();
+ stage.setScene(scene);
+
+ stage.show();
+ }
+
+ /**
+ * Loads the main scene of the application from the FXML file.
+ *
+ * @return The scene that is loaded.
+ */
+ private Scene loadMainScene() {
FXMLLoader fxmlLoader = new FXMLLoader(Main.class.getResource("/view/MainView.fxml"));
AnchorPane anchorPane = null;
try {
@@ -22,9 +42,8 @@ public void start(Stage stage) {
} catch (IOException e) {
throw new RuntimeException(e);
}
-
Scene scene = new Scene(anchorPane);
- stage.setScene(scene);
- stage.show();
+ return scene;
}
}
+
diff --git a/src/main/java/dude/DialogBox.java b/src/main/java/dude/gui/DialogBox.java
similarity index 92%
rename from src/main/java/dude/DialogBox.java
rename to src/main/java/dude/gui/DialogBox.java
index c120231ffd..d0147e4700 100644
--- a/src/main/java/dude/DialogBox.java
+++ b/src/main/java/dude/gui/DialogBox.java
@@ -1,25 +1,27 @@
-package dude;
+package dude.gui;
-import javafx.scene.control.Label;
-import javafx.scene.layout.HBox;
-import javafx.fxml.FXML;
import java.io.IOException;
import java.util.Collections;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
-
+import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Node;
+import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
+import javafx.scene.layout.HBox;
+
+// @@author Jeffry Lum
+// Solution below is reused from https://se-education.org/guides/tutorials/javaFxPart4.html
/**
- * An example of a custom control using FXML.
* This control represents a dialog box consisting of an ImageView to represent the speaker's face and a label
* containing text from the speaker.
+ *
*/
public class DialogBox extends HBox {
@FXML
diff --git a/src/main/java/dude/MainView.java b/src/main/java/dude/gui/MainView.java
similarity index 55%
rename from src/main/java/dude/MainView.java
rename to src/main/java/dude/gui/MainView.java
index ac95d82d3b..3508e85e0f 100644
--- a/src/main/java/dude/MainView.java
+++ b/src/main/java/dude/gui/MainView.java
@@ -1,5 +1,6 @@
-package dude;
+package dude.gui;
+import dude.Dude;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
@@ -12,6 +13,8 @@
* Controller for MainView. Provides the layout for the other controls.
*/
public class MainView extends AnchorPane {
+ private static final String USER_IMAGE_PATH = "/images/user.png";
+ private static final String DUDE_IMAGE_PATH = "/images/dude.png";
@FXML
private ScrollPane scrollPane;
@@ -24,37 +27,50 @@ public class MainView extends AnchorPane {
@FXML
private VBox dialogContainer;
- private Image userImage = new Image(this.getClass().getResourceAsStream("/images/user.png"));
- private Image dudeImage = new Image(this.getClass().getResourceAsStream("/images/dude.png"));
-
+ private Image userImage;
+ private Image dudeImage;
private Dude dude;
+ /**
+ * Initializes the MainView, setting up the images and the Dude object.
+ */
@FXML
public void initialize() {
- dude = new Dude("data/tasks.ser");
+ this.dude = new Dude("data/tasks.ser");
+ this.userImage = new Image(this.getClass().getResourceAsStream(USER_IMAGE_PATH));
+ this.dudeImage = new Image(this.getClass().getResourceAsStream(DUDE_IMAGE_PATH));
}
+ /**
+ * Creates two dialog boxes, one echoing user input and the other containing Dude's reply and then appends them to
+ * the dialog container. Clears the user input after processing.
+ */
@FXML
public void handleUserInput() {
String input = userInputField.getText();
- String response = dude.getResponse(input);
+ if (input.equals("bye")) {
+ System.exit(0);
+ }
- System.out.println("User input: " + input);
+ String response = dude.getResponse(input);
+ ;
userInputField.clear();
- dialogContainer.getChildren().addAll(
- DialogBox.getUserDialog(input, userImage),
- DialogBox.getDukeDialog(response, dudeImage)
- );
+ showInputAndResponse(input, response);
+ scrollDown();
+ }
+ private void scrollDown() {
dialogContainer.heightProperty().addListener((observable) -> {
scrollPane.setVvalue(1.0);
});
+ }
- if (input.equals("bye")) {
- System.exit(0);
- }
-
+ private void showInputAndResponse(String input, String response) {
+ dialogContainer.getChildren().addAll(
+ DialogBox.getUserDialog(input, userImage),
+ DialogBox.getDukeDialog(response, dudeImage)
+ );
}
}
diff --git a/src/main/java/dude/tasks/Deadline.java b/src/main/java/dude/tasks/Deadline.java
index e8a560035e..b94b70aeda 100644
--- a/src/main/java/dude/tasks/Deadline.java
+++ b/src/main/java/dude/tasks/Deadline.java
@@ -44,34 +44,30 @@ public Deadline(String description, LocalDateTime by) {
*/
public static Deadline from(String s) throws InvalidFormatException,
InvalidDescriptionException, InvalidArgumentException {
-
assert (s != null);
-
- //get rid of the command
String rest = Utils.discardFirstWord(s.trim()).trim();
-
String[] arr = rest.split(" ");
- int byOccurences = Utils.countOccurrences(arr, "/by");
+ validateBy(arr);
+ int byIndex = Utils.findIndex(arr, "/by");
- if (byOccurences == 0 || byOccurences > 1) {
- throw new InvalidFormatException("deadline", "format: deadline