@jinhanfromNUS We did an automated analysis of your code to detect potential areas to improve the code quality. We are sharing the results below, to help you improve the iP code further.
IMPORTANT: Note that the script looked for just a few easy-to-detect problems only, and at-most three example are given i.e., there can be other areas/places to improve.
Aspect: Tab Usage
No easy-to-detect issues 👍
Aspect: Naming boolean variables/methods
No easy-to-detect issues 👍
Aspect: Brace Style
No easy-to-detect issues 👍
Aspect: Package Name Style
No easy-to-detect issues 👍
Aspect: Class Name Style
No easy-to-detect issues 👍
Aspect: Dead Code
Example from src/main/java/duke/Duke.java lines 80-80:
// public void run() throws IOException {
Example from src/main/java/duke/Duke.java lines 81-81:
Example from src/main/java/duke/Duke.java lines 82-82:
Suggestion: Remove dead code from the codebase.
Aspect: Method Length
Example from src/main/java/duke/Duke.java lines 93-172:
public void start(Stage stage) {
//Step 1. Setting up required components
//The container for the content of the chat to scroll.
scrollPane = new ScrollPane();
dialogContainer = new VBox();
scrollPane.setContent(dialogContainer);
userInput = new TextField();
sendButton = new Button("Send");
AnchorPane mainLayout = new AnchorPane();
mainLayout.getChildren().addAll(scrollPane, userInput, sendButton);
scene = new Scene(mainLayout);
stage.setScene(scene);
stage.show();
//Step 2. Formatting the window to look as expected
stage.setTitle("Duke");
stage.setResizable(false);
stage.setMinHeight(600.0);
stage.setMinWidth(400.0);
mainLayout.setPrefSize(400.0, 600.0);
scrollPane.setPrefSize(385, 535);
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
scrollPane.setVvalue(1.0);
scrollPane.setFitToWidth(true);
//You will need to import `javafx.scene.layout.Region` for this.
dialogContainer.setPrefHeight(Region.USE_COMPUTED_SIZE);
userInput.setPrefWidth(325.0);
sendButton.setPrefWidth(55.0);
AnchorPane.setTopAnchor(scrollPane, 1.0);
AnchorPane.setBottomAnchor(sendButton, 1.0);
AnchorPane.setRightAnchor(sendButton, 1.0);
AnchorPane.setLeftAnchor(userInput, 1.0);
AnchorPane.setBottomAnchor(userInput, 1.0);
//Step 3. Add functionality to handle user input.
sendButton.setOnMouseClicked((event) -> {
dialogContainer.getChildren().add(getDialogLabel(userInput.getText()));
userInput.clear();
});
userInput.setOnAction((event) -> {
dialogContainer.getChildren().add(getDialogLabel(userInput.getText()));
userInput.clear();
});
//Scroll down to the end every time dialogContainer's height changes.
dialogContainer.heightProperty().addListener((observable) -> scrollPane.setVvalue(1.0));
//Part 3. Add functionality to handle user input.
sendButton.setOnMouseClicked((event) -> {
try {
handleUserInput();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
userInput.setOnAction((event) -> {
try {
handleUserInput();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
Example from src/main/java/duke/parser/Parser.java lines 64-169:
public String execute(String userInput) throws IOException {
String[] words = userInput.split(" ");
String command = words[0].toLowerCase();
switch (command) {
case "bye":
this.storage.saveTasksToFile(taskList.getTasks());
return response.sendGoodbye();
case "list":
ArrayList<Task> tasks = taskList.getTasks();
if (words.length == 1) {
return response.showTaskList(tasks);
}
String listMethod = userInput.substring(command.length()).trim();
if (listMethod.equals("done")) {
return response.showDoneTaskList(tasks);
} else if (listMethod.equals("undone")) {
return response.showUndoneTaskList(tasks);
} else if (listMethod.equals("undone top") || listMethod.equals("top undone")) {
return response.undoneDoneList(tasks);
} else if (listMethod.equals("done top") || listMethod.equals("top done")) {
return response.doneUndoneList(tasks);
} else if (listMethod.equals("a") || listMethod.equals("alphabetically")) {
return response.sortAlphabetically(tasks);
} else {
return response.showTaskList(tasks);
}
case "done":
if (words.length == 1) {
return response.noIndexMarkAsDone();
}
int doneTaskIndex = Integer.parseInt(words[1]);
return this.taskList.markTaskAsDone(doneTaskIndex);
case "undone":
if (words.length == 1) {
return response.noIndexMarkAsUndone();
}
int undoneTaskIndex = Integer.parseInt(words[1]);
return this.taskList.markTaskAsUndone(undoneTaskIndex);
// case "delete mass":
// if (words.length <= 2) {
// return response.noIndexDeleteTask();
// }
// String[] indexesString = words[2].split(",");
// int[] taskIndices = new int[words.length - 1];
// for (int i = words.length; i > 0; i--) {
// taskIndices[i - 1] = Integer.parseInt(words[i]);
// }
case "delete":
if (words.length == 1) {
return response.noIndexDeleteTask();
}
int deleteTaskIndex = Integer.parseInt(words[1]);
return this.taskList.deleteTask(deleteTaskIndex);
case "todo":
if (words.length == 1) {
return response.insufficientTodoDescription();
}
String todoDescription = userInput.substring(command.length()).trim();
Task newTodo = new TodoTask(todoDescription);
return this.taskList.addTask(newTodo);
case "deadline":
if (words.length == 1 || !userInput.contains("/by")) {
return response.insufficientDeadline();
}
String deadlineDescription = userInput.substring(command.length() + 1, userInput.indexOf("/by")).trim();
String byString = userInput.substring(userInput.indexOf("/by") + 3).trim();
if (!checkValidDate(byString)) {
return response.invalidDateInput();
}
LocalDate by = LocalDate.parse(byString);
Task newDeadline = new DeadlineTask(deadlineDescription, by);
return this.taskList.addTask(newDeadline);
case "event":
if (words.length == 1 || (!userInput.contains("/from") && !userInput.contains("/to"))) {
return response.insufficientEventStartTimeEndTime();
}
if (!userInput.contains("/from")) {
return response.insufficientEventStartTime();
}
if (!userInput.contains("/to")) {
return response.insufficientEventEndTime();
}
String eventDescription = userInput.substring(command.length() + 1, userInput.indexOf("/from")).trim();
String fromString = userInput.substring(userInput.indexOf("/from") + 5, userInput.indexOf("/to")).trim();
String toString = userInput.substring(userInput.indexOf("/to") + 3).trim();
LocalDate from = LocalDate.parse(fromString);
LocalDate to = LocalDate.parse(toString);
if (!checkValidDates(from, to)) {
return response.invalidEventStartingTimeAndEndingTime();
}
Task newEvent = new EventTask(eventDescription, from, to);
return this.taskList.addTask(newEvent);
case "search":
if (words.length == 1) {
return response.noKeywordsForSearching();
}
String keyword = userInput.substring(command.length()).trim();
return this.taskList.searchTasks(keyword);
case "help":
return response.help();
default:
return response.badUserInput();
}
}
Example from src/main/java/duke/storage/Storage.java lines 48-180:
public ArrayList<Task> loadTasksFromFile() {
File file = new File(filePath);
if (!file.exists()) {
System.out.println("File path is incorrect... Quitting...");
return null; // Handle the case where the file doesn't exist
}
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.length() < 7) {
System.out.println("Error found: Bad input");
System.out.println(line);
}
char taskType = line.charAt(1);
char isDoneX = line.charAt(4);
if (taskType == 'T') {
String todoDescription = line.substring(7);
if (isDoneX == 'X') {
Task newTodo = new TodoTask(todoDescription, true);
this.tasks.add(newTodo);
} else if (isDoneX == ' ') {
Task newTodo = new TodoTask(todoDescription);
this.tasks.add(newTodo);
} else {
System.out.println("____________________________________________________________");
System.out.println("Error found: Unrecognized todo's Done.");
System.out.println("--> " + line);
System.out.println("Removed from list");
System.out.println("____________________________________________________________");
}
} else if (taskType == 'D') {
if (!line.contains(" (by: ")) {
System.out.println("____________________________________________________________");
System.out.println("Error found: Deadline task without a deadline.");
System.out.println("--> " + line);
System.out.println("Removed from list");
System.out.println("____________________________________________________________");
continue;
}
String deadlineDescription = line.substring(7, line.indexOf(" (by: "));
Pattern pattern = Pattern.compile("\\(by: (.*?)\\)");
Matcher matcher = pattern.matcher(line);
String deadlineString = "";
if (matcher.find()) {
deadlineString = matcher.group(1);
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM d yyyy");
LocalDate deadline = LocalDate.parse(deadlineString, formatter);
if (isDoneX == 'X') {
Task newDeadline = new DeadlineTask(deadlineDescription, deadline, true);
this.tasks.add(newDeadline);
} else if (isDoneX == ' ') {
Task newDeadline = new DeadlineTask(deadlineDescription, deadline);
this.tasks.add(newDeadline);
} else {
System.out.println("____________________________________________________________");
System.out.println("Error found: Unrecognized deadline's Done.");
System.out.println("--> " + line);
System.out.println("Removed from list");
System.out.println("____________________________________________________________");
}
} else if (taskType == 'E') {
if (!line.contains(" (from: ") && !line.contains(" to: ")) {
System.out.println("____________________________________________________________");
System.out.println("Error found: Event task without a starting time and an ending time.");
System.out.println("--> " + line);
System.out.println("Removed from list");
System.out.println("____________________________________________________________");
continue;
}
if (!line.contains(" (from: ")) {
System.out.println("____________________________________________________________");
System.out.println("Error found: Event task without a starting time.");
System.out.println("--> " + line);
System.out.println("Removed from list");
System.out.println("____________________________________________________________");
continue;
}
if (!line.contains(" to: ")) {
System.out.println("____________________________________________________________");
System.out.println("Error found: Deadline task without an ending time.");
System.out.println("--> " + line);
System.out.println("Removed from list");
System.out.println("____________________________________________________________");
continue;
}
String eventDescription = line.substring(7, line.indexOf(" (from: "));
Pattern pattern = Pattern.compile("\\(from: (.*?) to: (.*?)\\)");
Matcher matcher = pattern.matcher(line);
String startTimeString = "";
String endTimeString = "";
if (matcher.find()) {
startTimeString = matcher.group(1);
endTimeString = matcher.group(2);
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM d yyyy");
LocalDate startTime = LocalDate.parse(startTimeString, formatter);
LocalDate endTime = LocalDate.parse(endTimeString, formatter);
if (!checkValidDates(startTime, endTime)) {
System.out.println("____________________________________________________________");
System.out.println("Error found: Start time should be earlier than end time.");
System.out.println("--> " + line);
System.out.println("Removed from list");
System.out.println("____________________________________________________________");
continue;
}
if (isDoneX == 'X') {
Task newEvent = new EventTask(eventDescription, startTime, endTime, true);
this.tasks.add(newEvent);
} else if (isDoneX == ' ') {
Task newEvent = new EventTask(eventDescription, startTime, endTime);
this.tasks.add(newEvent);
} else {
System.out.println("____________________________________________________________");
System.out.println("Error found: Unrecognized event's Done.");
System.out.println("--> " + line);
System.out.println("Removed from list");
System.out.println("____________________________________________________________");
}
} else {
System.out.println("____________________________________________________________");
System.out.println("Error found: Unrecognized task type (task type should be one of T, D, E).");
System.out.println("--> " + line);
System.out.println("Removed from list");
System.out.println("____________________________________________________________");
}
}
} catch (IOException e) {
System.err.println("Error loading tasks from file: " + e.getMessage());
}
return tasks;
}
Suggestion: Consider applying SLAP (and other abstraction mechanisms) to shorten methods e.g., extract some code blocks into separate methods. You may ignore this suggestion if you think a longer method is justified in a particular case.
Aspect: Class size
No easy-to-detect issues 👍
Aspect: Header Comments
Example from src/main/java/duke/Duke.java lines 174-180:
/**
* Iteration 1:
* Creates a label with the specified text and adds it to the dialog container.
*
* @param text String containing text to add
* @return a label with the specified text that has word wrap enabled.
*/
Example from src/main/java/duke/Duke.java lines 188-192:
/**
* Iteration 2:
* Creates two dialog boxes, one echoing user input and the other containing Duke's reply and then appends them to
* the dialog container. Clears the user input after processing.
*/
Suggestion: Ensure method/class header comments follow the format specified in the coding standard, in particular, the phrasing of the overview statement.
Aspect: Recent Git Commit Message
No easy-to-detect issues 👍
Aspect: Binary files in repo
No easy-to-detect issues 👍
ℹ️ The bot account used to post this issue is un-manned. Do not reply to this post (as those replies will not be read). Instead, contact cs2103@comp.nus.edu.sg if you want to follow up on this post.
@jinhanfromNUS We did an automated analysis of your code to detect potential areas to improve the code quality. We are sharing the results below, to help you improve the iP code further.
IMPORTANT: Note that the script looked for just a few easy-to-detect problems only, and at-most three example are given i.e., there can be other areas/places to improve.
Aspect: Tab Usage
No easy-to-detect issues 👍
Aspect: Naming boolean variables/methods
No easy-to-detect issues 👍
Aspect: Brace Style
No easy-to-detect issues 👍
Aspect: Package Name Style
No easy-to-detect issues 👍
Aspect: Class Name Style
No easy-to-detect issues 👍
Aspect: Dead Code
Example from
src/main/java/duke/Duke.javalines80-80:// public void run() throws IOException {Example from
src/main/java/duke/Duke.javalines81-81:// ui.sendWelcome();Example from
src/main/java/duke/Duke.javalines82-82:// while (true) {Suggestion: Remove dead code from the codebase.
Aspect: Method Length
Example from
src/main/java/duke/Duke.javalines93-172:Example from
src/main/java/duke/parser/Parser.javalines64-169:Example from
src/main/java/duke/storage/Storage.javalines48-180:Suggestion: Consider applying SLAP (and other abstraction mechanisms) to shorten methods e.g., extract some code blocks into separate methods. You may ignore this suggestion if you think a longer method is justified in a particular case.
Aspect: Class size
No easy-to-detect issues 👍
Aspect: Header Comments
Example from
src/main/java/duke/Duke.javalines174-180:Example from
src/main/java/duke/Duke.javalines188-192:Suggestion: Ensure method/class header comments follow the format specified in the coding standard, in particular, the phrasing of the overview statement.
Aspect: Recent Git Commit Message
No easy-to-detect issues 👍
Aspect: Binary files in repo
No easy-to-detect issues 👍
ℹ️ The bot account used to post this issue is un-manned. Do not reply to this post (as those replies will not be read). Instead, contact
cs2103@comp.nus.edu.sgif you want to follow up on this post.