Skip to content

Commit

Permalink
Merge branch 'branch-A-CodeQuality' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
tahsinhasem authored Mar 3, 2024
2 parents 0f81339 + 1066bae commit b0e6667
Show file tree
Hide file tree
Showing 12 changed files with 207 additions and 166 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ test {
}

application {
mainClass.set("dude.Dude")
mainClass.set("dude.Launcher")
}

shadowJar {
Expand Down
89 changes: 26 additions & 63 deletions src/main/java/dude/Dude.java
Original file line number Diff line number Diff line change
@@ -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;


/**
Expand All @@ -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.
* <p>
Expand All @@ -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.
* <p>
*
* @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.
* <p>
* 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();
Expand All @@ -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;
}

}
8 changes: 8 additions & 0 deletions src/main/java/dude/Launcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
29 changes: 24 additions & 5 deletions src/main/java/dude/Main.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,49 @@
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 {
anchorPane = fxmlLoader.load();
} catch (IOException e) {
throw new RuntimeException(e);
}

Scene scene = new Scene(anchorPane);
stage.setScene(scene);
stage.show();
return scene;
}
}

Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;

Expand All @@ -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)
);
}

}
Loading

0 comments on commit b0e6667

Please sign in to comment.