-
Notifications
You must be signed in to change notification settings - Fork 435
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Seng Zhen Hong] iP #468
base: master
Are you sure you want to change the base?
[Seng Zhen Hong] iP #468
Changes from 12 commits
55f9f9f
f837ddb
a6f7324
b2a586c
943d23f
0744083
3788eb8
0e044fd
b8eff85
b9b266d
ac52d32
a229714
be64ce0
7fa2323
0855b3d
1eec1b6
0e069f1
458a7bc
a850dc8
d062dc1
7db053c
48a711e
27951d6
ae1320a
7d94a89
0d04ccd
57fc714
f827e1c
a5202ae
cef5727
5576363
e1e239e
940e034
ada747a
a584e66
130a9ea
c71765f
981ea66
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
D | 0 | a | 1100 | ||
D | 0 | a | 1100 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,283 @@ | ||
import java.io.File; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can consider ordering imports in lexical order |
||
import java.io.IOException; | ||
import java.io.PrintWriter; | ||
import java.util.ArrayList; | ||
import java.util.Scanner; | ||
import java.time.LocalDate; | ||
import java.time.LocalTime; | ||
import java.time.format.DateTimeFormatter; | ||
|
||
class DukeException extends Exception { | ||
public DukeException(String message) { | ||
super(message); | ||
} | ||
} | ||
|
||
public class Duke { | ||
private static final String FILE_PATH = "duke.txt"; | ||
private static ArrayList<Task> tasks; | ||
public Duke() { | ||
tasks = loadTasksFromFile(); | ||
} | ||
|
||
public static void main(String[] args) { | ||
Duke duke = new Duke(); | ||
String logo = " ____ _ \n" | ||
+ "| _ \\ _ _| | _____ \n" | ||
+ "| | | | | | | |/ / _ \\\n" | ||
+ "| |_| | |_| | < __/\n" | ||
+ "|____/ \\__,_|_|\\_\\___|\n"; | ||
+ "| _ \\ _ _| | _____ \n" | ||
+ "| | | | | | | |/ / _ \\\n" | ||
+ "| |_| | |_| | < __/\n" | ||
+ "|____/ \\__,_|_|\\_\\___|\n"; | ||
System.out.println("Hello from\n" + logo); | ||
System.out.println("____________________________________________________________"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can consider making linebreaks into a constant variable which can make code cleaner |
||
System.out.println("Hello! I'm CharmBot "); | ||
System.out.println("What can I do for you?"); | ||
System.out.println("____________________________________________________________"); | ||
|
||
Scanner scanner = new Scanner(System.in); | ||
String command = scanner.nextLine(); | ||
// Initialize tasks list here | ||
|
||
while (!command.equals("bye")) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can consider breaking down this function into smaller functions to make it more readable for others, might be a little too long currently. Can break down into like two functions like run and commands |
||
System.out.println("____________________________________________________________"); | ||
try { | ||
if (command.equals("list")) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code seems to be too long for me. Try to divide each commands into different functions. |
||
if (tasks.isEmpty()) { | ||
System.out.println("You have no tasks in your list."); | ||
} else { | ||
System.out.println("Here are the tasks in your list:"); | ||
for (int i = 0; i < tasks.size(); i++) { | ||
System.out.println((i + 1) + "." + tasks.get(i)); | ||
} | ||
} | ||
} else if (command.startsWith("mark")) { | ||
int taskIndex = Integer.parseInt(command.split(" ")[1]) - 1; | ||
if (taskIndex < 0 || taskIndex >= tasks.size()) { | ||
throw new DukeException("Invalid task index."); | ||
} | ||
tasks.get(taskIndex).markAsDone(); | ||
System.out.println("Nice! I've marked this task as done:"); | ||
System.out.println(tasks.get(taskIndex)); | ||
} else if (command.startsWith("unmark")) { | ||
int taskIndex = Integer.parseInt(command.split(" ")[1]) - 1; | ||
if (taskIndex < 0 || taskIndex >= tasks.size()) { | ||
throw new DukeException("Invalid task index."); | ||
} | ||
tasks.get(taskIndex).markAsNotDone(); | ||
System.out.println("OK, I've marked this task as not done yet:"); | ||
System.out.println(tasks.get(taskIndex)); | ||
} else if (command.startsWith("delete")) { | ||
int taskIndex = Integer.parseInt(command.split(" ")[1]) - 1; | ||
if (taskIndex < 0 || taskIndex >= tasks.size()) { | ||
throw new DukeException("Invalid task index."); | ||
} | ||
Task deletedTask = tasks.remove(taskIndex); | ||
System.out.println("Noted. I've removed this task:"); | ||
System.out.println(" " + deletedTask); | ||
System.out.println("Now you have " + tasks.size() + " tasks in the list."); | ||
} else { | ||
if (command.startsWith("todo")) { | ||
String description = command.substring(5).trim(); | ||
if (description.isEmpty()) { | ||
throw new DukeException("The description of a todo cannot be empty."); | ||
} | ||
tasks.add(new ToDoTask(description)); | ||
System.out.println("Got it. I've added this task:"); | ||
System.out.println(tasks.get(tasks.size() - 1)); | ||
System.out.println("Now you have " + tasks.size() + " tasks in the list."); | ||
} else if (command.startsWith("deadline ")) { | ||
String[] parts = command.substring(9).split("/by"); | ||
if (parts.length != 2 || parts[0].trim().isEmpty() || parts[1].trim().isEmpty()) { | ||
throw new DukeException("Invalid command format. Please use 'deadline <description> /by <time in hhmm format>'. For example, 'deadline Finish project /by 1800'."); | ||
} | ||
String description = parts[0].trim(); | ||
String by = parts[1].trim(); | ||
LocalTime byTime = LocalTime.parse(by, DateTimeFormatter.ofPattern("HHmm")); | ||
tasks.add(new DeadlineTask(description, byTime)); | ||
System.out.println("Got it. I've added this task:"); | ||
System.out.println(tasks.get(tasks.size() - 1)); | ||
System.out.println("Now you have " + tasks.size() + " tasks in the list."); | ||
} else if (command.startsWith("event ")) { | ||
String[] parts = command.substring(6).split("/from"); | ||
if (parts.length != 2 || parts[0].trim().isEmpty() || parts[1].trim().isEmpty()) { | ||
throw new DukeException("Invalid command format. Please use 'event <description> /from <start time> /to <end time>'."); | ||
} | ||
String description = parts[0].trim(); | ||
String[] eventParts = parts[1].split("/to"); | ||
if (eventParts.length != 2 || eventParts[0].trim().isEmpty() || eventParts[1].trim().isEmpty()) { | ||
throw new DukeException("Invalid command format. Please use 'event <description> /from <start time> /to <end time>'."); | ||
} | ||
String from = eventParts[0].trim(); | ||
String to = eventParts[1].trim(); | ||
LocalTime startTime = LocalTime.parse(from, DateTimeFormatter.ofPattern("HHmm")); | ||
LocalTime endTime = LocalTime.parse(to, DateTimeFormatter.ofPattern("HHmm")); | ||
tasks.add(new EventTask(description, startTime, endTime)); | ||
System.out.println("Got it. I've added this task:"); | ||
System.out.println(tasks.get(tasks.size() - 1)); | ||
System.out.println("Now you have " + tasks.size() + " tasks in the list."); | ||
} else { | ||
throw new DukeException("I'm sorry, but I don't know what that means :-("); | ||
} | ||
} | ||
} catch (NumberFormatException e) { | ||
System.out.println("Invalid command format. Please provide a valid task index."); | ||
} catch (DukeException e) { | ||
System.out.println("____________________________________________________________"); | ||
System.out.println("OOPS!!! " + e.getMessage()); | ||
System.out.println("____________________________________________________________"); | ||
} | ||
System.out.println("____________________________________________________________"); | ||
command = scanner.nextLine(); | ||
} | ||
duke.saveTasksToFile(tasks); | ||
|
||
System.out.println("____________________________________________________________"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe consider connecting this three println statements using +. |
||
System.out.println("Bye. Hope to see you again soon!"); | ||
System.out.println("____________________________________________________________"); | ||
} | ||
|
||
|
||
private ArrayList<Task> loadTasksFromFile() { | ||
ArrayList<Task> tasks = new ArrayList<>(); | ||
try { | ||
File file = new File(FILE_PATH); | ||
if (!file.exists()) { | ||
file.createNewFile(); | ||
} else { | ||
Scanner scanner = new Scanner(file); | ||
while (scanner.hasNextLine()) { | ||
String line = scanner.nextLine(); | ||
Task task = parseTaskFromString(line); | ||
tasks.add(task); | ||
} | ||
scanner.close(); | ||
} | ||
} catch (IOException e) { | ||
System.out.println("Error loading tasks from file: " + e.getMessage()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can consider making this into your own exception class and include the additional error messages as part of the new exception |
||
} | ||
return tasks; | ||
} | ||
|
||
private Task parseTaskFromString(String line) { | ||
String[] parts = line.split("\\|"); | ||
String type = parts[0].trim(); | ||
boolean isDone = parts[1].trim().equals("1"); // Assuming "1" represents task is done | ||
String description = parts[2].trim(); | ||
|
||
switch (type) { | ||
case "D": | ||
String by = parts[3].trim(); | ||
LocalTime byTime = LocalTime.parse(by, DateTimeFormatter.ofPattern("HHmm")); | ||
return new DeadlineTask(description, byTime); | ||
case "E": | ||
String from = parts[3].trim(); | ||
String to = parts[4].trim(); | ||
LocalTime startTime = LocalTime.parse(from, DateTimeFormatter.ofPattern("HHmm")); | ||
LocalTime endTime = LocalTime.parse(to, DateTimeFormatter.ofPattern("HHmm")); | ||
return new EventTask(description, startTime, endTime); | ||
default: | ||
return new ToDoTask(description); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider the case when the file is corrupted |
||
} | ||
} | ||
|
||
|
||
|
||
|
||
private void saveTasksToFile(ArrayList<Task> tasks) { | ||
try (PrintWriter writer = new PrintWriter(FILE_PATH)) { | ||
for (Task task : tasks) { | ||
writer.println(task.toFileString()); | ||
} | ||
} catch (IOException e) { | ||
System.out.println("Error saving tasks to file: " + e.getMessage()); | ||
} | ||
} | ||
} | ||
|
||
// Task, ToDoTask, DeadlineTask, EventTask classes remain unchanged | ||
|
||
class Task { | ||
protected String description; | ||
protected boolean isDone; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice boolean naming👍 |
||
|
||
public Task(String description) { | ||
this.description = description; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason why you added this. infront in task and not in Duke class? Can consider having a constant reference standard. |
||
this.isDone = false; | ||
} | ||
|
||
public void markAsDone() { | ||
this.isDone = true; | ||
} | ||
|
||
public void markAsNotDone() { | ||
this.isDone = false; | ||
} | ||
|
||
public String toFileString() { | ||
return "[" + (isDone ? "X" : " ") + "] " + description; | ||
} | ||
|
||
|
||
@Override | ||
public String toString() { | ||
return "[" + (isDone ? "X" : " ") + "] " + description; | ||
} | ||
} | ||
|
||
|
||
|
||
class ToDoTask extends Task { | ||
public ToDoTask(String description) { | ||
super(description); | ||
} | ||
|
||
@Override | ||
public String toFileString() { | ||
return "T | " + (isDone ? "1" : "0") + " | " + description; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "[T][" + (isDone ? "X" : " ") + "] " + description; | ||
} | ||
} | ||
|
||
class DeadlineTask extends Task { | ||
|
||
private LocalTime deadline; | ||
|
||
public DeadlineTask(String description, LocalTime by) { | ||
super(description); | ||
this.deadline = by; | ||
} | ||
|
||
@Override | ||
public String toFileString() { | ||
return "D | " + (isDone ? "1" : "0") + " | " + description + " | " + deadline.format(DateTimeFormatter.ofPattern("HHmm")); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "[D][" + (isDone ? "X" : " ") + "] " + description + " (by: " +deadline + ")"; | ||
} | ||
} | ||
|
||
class EventTask extends Task { | ||
private LocalTime startTime; | ||
private LocalTime endTime; | ||
|
||
public EventTask(String description, LocalTime startTime, LocalTime endTime) { | ||
super(description); | ||
this.startTime = startTime; | ||
this.endTime = endTime; | ||
} | ||
|
||
@Override | ||
public String toFileString() { | ||
return "E | " + (isDone ? "1" : "0") + " | " + description + " | " + startTime.format(DateTimeFormatter.ofPattern("HHmm")) + " | " + endTime.format(DateTimeFormatter.ofPattern("HHmm")); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "[E][" + (isDone ? "X" : " ") + "] " + description + " (from: " + startTime.format(DateTimeFormatter.ofPattern("HH:mm")) + " to: " + endTime.format(DateTimeFormatter.ofPattern("HH:mm")) + ")"; | ||
} | ||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good naming of functions and variables and all in all LGTM but just some minor nits