Skip to content
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

[bryancheny] iP #624

Open
wants to merge 39 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
68c58c1
Add Gradle support
May 24, 2020
03523ec
Bump gradle and lib version
Eclipse-Dominator Aug 5, 2023
81a9c53
build.gradle: Prevent generating a second JAR file
aureliony Jul 16, 2024
b41d2c2
Change name and greeting message
bryancheny Aug 22, 2024
fe3f1b4
add bot echoing and exit functionality
bryancheny Aug 22, 2024
4248d94
remove bye message from greeting
bryancheny Aug 22, 2024
0539e3d
add ability to store user text
bryancheny Aug 22, 2024
7da5153
add mark as done feature
bryancheny Aug 22, 2024
1cf5287
remove class files
bryancheny Aug 22, 2024
1e0eb5a
add todo, events, deadlines
bryancheny Aug 22, 2024
f868768
correct test script
bryancheny Aug 22, 2024
490cd5d
add more error handling cases
bryancheny Aug 22, 2024
c209de6
add delete function and update tests
bryancheny Aug 22, 2024
52914b1
add tasktype enum
bryancheny Aug 22, 2024
54a0bf5
Implement saving
bryancheny Sep 4, 2024
f95a3f8
modify gitignore
bryancheny Sep 4, 2024
7cf4601
Merge Level 7
bryancheny Sep 4, 2024
e80bdce
Add datetimes
bryancheny Sep 4, 2024
bb8a90d
Merge Level 8
bryancheny Sep 4, 2024
548cd6a
Refactor with Parser, Storage, TaskList and Ui class
bryancheny Sep 6, 2024
5fa11fd
Refactor into package
bryancheny Sep 6, 2024
bf860bb
Merge branch 'add-gradle-support'
bryancheny Sep 6, 2024
e158ccd
Merge gradle branch
bryancheny Sep 6, 2024
bccd063
Add Parser and TaskList tests
bryancheny Sep 6, 2024
ee99b35
Add Java docs
bryancheny Sep 6, 2024
de5dfe9
Tweak slightly to conform to coding standard
bryancheny Sep 6, 2024
daa7242
Add find task functionality
bryancheny Sep 6, 2024
74c696b
Add Checkstyle
bryancheny Sep 10, 2024
95e54bb
Add GUI with JavaFX
bryancheny Sep 16, 2024
6914638
Add assertions to document important assumptions throughout the codebase
bryancheny Sep 19, 2024
acae5c9
Fix style issues
bryancheny Sep 19, 2024
0b41690
Refactor Crack class to improve code quality and adhere to coding sta…
bryancheny Sep 19, 2024
3429ed1
Merge pull request #2 from bryancheny/A-Assertions
bryancheny Sep 19, 2024
53556f4
Merge pull request #3 from bryancheny/A-CodeQuality
bryancheny Sep 19, 2024
3df83f6
Implement B-Snooze feature for task postponement and refactor code
bryancheny Sep 19, 2024
22a7dc5
Modify README
bryancheny Sep 19, 2024
1d0d947
Merge tag 'B-Snooze'
bryancheny Sep 19, 2024
dc8edf1
Merge branch 'refs/heads/B-Snooze'
bryancheny Sep 19, 2024
e6bd7f2
Update README and add userguide
bryancheny Sep 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,11 @@ src/main/resources/docs/
*.iml
bin/

# Java class files
*.class

# Data files
/src/main/java/data

/text-ui-test/ACTUAL.TXT
text-ui-test/EXPECTED-UNIX.TXT
196 changes: 196 additions & 0 deletions src/main/java/Crack.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
import java.util.Scanner;
import java.io.File;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the imports be done in lexicographical order?

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class Crack {
private static final String FILE_PATH = "./data/crack.txt";
public static void main(String[] args) {
String divider = "____________________________________________________________\n";
String greeting = divider
+ " Hello! I'm Crack\n"
+ " What can I do for you?\n"
+ divider;
System.out.println(greeting);

Scanner scanner = new Scanner(System.in);
String input;
ArrayList<Task> tasks = new ArrayList<>();
loadTasksFromFile(tasks);

while (true) {
System.out.print("You: ");
input = scanner.nextLine().trim();

if (input.equals("bye")) {
System.out.println("Goodbye!");
break;
} else if (input.equals("list")) {
if (tasks.isEmpty()) {
System.out.println(divider + " Your task list is empty.\n" + divider);
} else {
System.out.println(divider + " Here are the tasks in your list:");
for (int i = 0; i < tasks.size(); i++) {
System.out.println((i + 1) + "." + tasks.get(i));
}
System.out.println(divider);
}
} else if (input.startsWith("mark ")) {
try {
int index = Integer.parseInt(input.split(" ")[1]) - 1;
if (index >= 0 && index < tasks.size()) {
tasks.get(index).markAsDone();
System.out.println(divider + " Nice! I've marked this task as done:\n " + tasks.get(index) + "\n" + divider);
saveTasksToFile(tasks);
} else {
System.out.println(divider + " Error: Task number out of range.\n" + divider);
}
} catch (Exception e) {
System.out.println(divider + " Error: Please provide a valid task number.\n" + divider);
}
} else if (input.startsWith("unmark ")) {
try {
int index = Integer.parseInt(input.split(" ")[1]) - 1;
if (index >= 0 && index < tasks.size()) {
tasks.get(index).unmark();
System.out.println(divider + " OK, I've marked this task as not done yet:\n " + tasks.get(index) + "\n" + divider);
saveTasksToFile(tasks);
} else {
System.out.println(divider + " Error: Task number out of range.\n" + divider);
}
} catch (Exception e) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we can be more specific with the Exception being caught here?

System.out.println(divider + " Error: Please provide a valid task number.\n" + divider);
}
} else if (input.startsWith("todo ")) {
String description = input.substring(5).trim();
if (description.isEmpty()) {
System.out.println(divider + " Error: The description of a todo cannot be empty.\n" + divider);
} else {
tasks.add(new Todo(description));
System.out.println(divider + " Got it. I've added this task:\n [T][ ] " + description + "\n"
+ " Now you have " + tasks.size() + " tasks in the list.\n" + divider);
saveTasksToFile(tasks);
}
} else if (input.startsWith("deadline ")) {
try {
String[] parts = input.substring(9).split(" /by ");
if (parts.length < 2 || parts[0].trim().isEmpty()) {
throw new IllegalArgumentException();
}
String description = parts[0].trim();
String by = parts[1].trim();
Deadline newDeadline = new Deadline(description, by);
tasks.add(newDeadline);
System.out.println(divider + " Got it. I've added this task:\n" + newDeadline + "\n"
+ " Now you have " + tasks.size() + " tasks in the list.\n" + divider);
saveTasksToFile(tasks);
} catch (Exception e) {
System.out.println(divider + " Error: Invalid format for deadline. Use: deadline <description> /by <yyyy-md-dd>.\n" + divider);
}
} else if (input.startsWith("event ")) {
try {
String[] parts = input.substring(6).split(" /from | /to ");
if (parts.length < 3 || parts[0].trim().isEmpty()) {
throw new IllegalArgumentException();
}
String description = parts[0].trim();
String from = parts[1].trim();
String to = parts[2].trim();
Event newEvent = new Event(description, from, to);
tasks.add(newEvent);
System.out.println(divider + " Got it. I've added this task:\n" + newEvent + "\n"
+ " Now you have " + tasks.size() + " tasks in the list.\n" + divider);
saveTasksToFile(tasks);
} catch (Exception e) {
System.out.println(divider + " Error: Invalid format for event. Use: event <description> /from <yyyy-mm-dd> /to <yyyy-mm-dd>.\n" + divider);
}
} else if (input.startsWith("delete ")) {
try {
int index = Integer.parseInt(input.split(" ")[1]) - 1;
if (index >= 0 && index < tasks.size()) {
Task removedTask = tasks.remove(index);
System.out.println(divider + " Noted. I've removed this task:\n " + removedTask + "\n"
+ " Now you have " + tasks.size() + " tasks in the list.\n" + divider);
saveTasksToFile(tasks);
} else {
System.out.println(divider + " Error: Task number out of range.\n" + divider);
}
} catch (Exception e) {
System.out.println(divider + " Error: Please provide a valid task number.\n" + divider);
}
} else {
System.out.println(divider + " Error: Invalid Command.\n" + divider);
}
}

scanner.close();
}

private static void saveTasksToFile(ArrayList<Task> tasks) {
try {
File dir = new File("./data");
if (!dir.exists()) {
dir.mkdirs();
}


File file = new File(FILE_PATH);
System.out.println("File path: " + file.getAbsolutePath());
if (!file.exists()) {
file.createNewFile();
}

FileWriter writer = new FileWriter(FILE_PATH);
for (Task task : tasks) {
writer.write(task.toSaveString() + System.lineSeparator());
}
writer.close();
} catch (IOException e) {
System.out.println(e);
System.out.println("Error: Unable to save tasks.");
}
}

private static void loadTasksFromFile(ArrayList<Task> tasks) {
try {
File file = new File(FILE_PATH);
if (!file.exists()) {
return; // No file yet, nothing to load
}
Scanner fileScanner = new Scanner(file);
while (fileScanner.hasNextLine()) {
String line = fileScanner.nextLine();
String[] parts = line.split(" \\| ");
switch (parts[0]) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the indentation of the "cases" be in line with "switch"?

case "T":
Todo todo = new Todo(parts[2]);
if (parts[1].equals("1")) {
todo.markAsDone();
}
tasks.add(todo);
break;
case "D":
Deadline deadline = new Deadline(parts[2], parts[3]);
if (parts[1].equals("1")) {
deadline.markAsDone();
}
tasks.add(deadline);
break;
case "E":
Event event = new Event(parts[2], parts[3], parts[4]);
if (parts[1].equals("1")) {
event.markAsDone();
}
tasks.add(event);
break;
default:
throw new IOException("Corrupted task format");
}
}
fileScanner.close();
} catch (IOException e) {
System.out.println("Error: Unable to load tasks or file is corrupted.");
}
}
}
10 changes: 0 additions & 10 deletions src/main/java/Duke.java

This file was deleted.

118 changes: 118 additions & 0 deletions src/main/java/Task.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

public class Task {
public enum TaskType {
TODO, DEADLINE, EVENT
}

protected String description;
protected boolean isDone;
protected TaskType type;

public Task(String description, TaskType type) {
this.description = description;
this.isDone = false;
this.type = type;
}

public String getStatusIcon() {
return (isDone ? "X" : " "); // mark done task with X
}

public void markAsDone() {
this.isDone = true;
}

public void unmark() {
this.isDone = false;
}

public TaskType getType() {
return type;
}

public String toSaveString() {
return getTypeIcon() + " | " + (isDone ? "1" : "0") + " | " + description;
}

@Override
public String toString() {
return "[" + getTypeIcon() + "][" + getStatusIcon() + "] " + description;
}

public String getTypeIcon() {
switch (type) {
case TODO:
return "T";
case DEADLINE:
return "D";
case EVENT:
return "E";
default:
return " ";
}
}
}

class Todo extends Task {
public Todo(String description) {
super(description, TaskType.TODO);
}

@Override
public String toSaveString() {
return "T | " + (isDone ? "1" : "0") + " | " + description;
}
}

class Deadline extends Task {
protected LocalDate by;

public Deadline(String description, String by) {
super(description, TaskType.DEADLINE);
try {
this.by = LocalDate.parse(by); // Parse date in yyyy-mm-dd format
} catch (DateTimeParseException e) {
System.out.println("Error: Invalid date format. Please use yyyy-mm-dd.");
}
}

@Override
public String toSaveString() {
return "D | " + (isDone ? "1" : "0") + " | " + description + " | " + by;
}

@Override
public String toString() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd yyyy");
return super.toString() + " (by: " + by.format(formatter) + ")";
}
}

class Event extends Task {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think putting this in another file would make the code neater.

protected LocalDate from;
protected LocalDate to;

public Event(String description, String from, String to) {
super(description, TaskType.EVENT);
try {
this.from = LocalDate.parse(from); // Parse start date in yyyy-mm-dd format
this.to = LocalDate.parse(to); // Parse end date in yyyy-mm-dd format
} catch (DateTimeParseException e) {
System.out.println("Error: Invalid date format. Please use yyyy-mm-dd.");
}
}

@Override
public String toSaveString() {
return "E | " + (isDone ? "1" : "0") + " | " + description + " | " + from + " | " + to;
}

@Override
public String toString() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd yyyy");
return super.toString() + " (from: " + from.format(formatter) + " to: " + to.format(formatter) + ")";
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the naming of the variables and methods.

}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps consider adding some javadocs in your code?

Loading