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

[Qin Nanxin] iP #572

Open
wants to merge 76 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
28ad2b8
Add Gradle support
May 24, 2020
ed6d4d2
Bump gradle and lib version
Eclipse-Dominator Aug 5, 2023
abfac81
[Level 0. Rename, Greet, Exit]
InfiBeyond Aug 24, 2023
517a3a2
[Level 1. Echo]
InfiBeyond Aug 24, 2023
5130bfd
[Level 2. Add, List]
InfiBeyond Aug 24, 2023
5823330
[Level 3. Mark as Done]
InfiBeyond Aug 24, 2023
59f198a
[Level 4. ToDos, Events, Deadlines]
InfiBeyond Aug 24, 2023
5f799dd
[Automated Text UI Testing]
InfiBeyond Aug 24, 2023
227c818
[Level 5. Handle Errors]
InfiBeyond Aug 24, 2023
c8a51aa
[Level 6. Delete]
InfiBeyond Aug 24, 2023
b60464f
Add DukeException class
InfiBeyond Aug 24, 2023
fb28447
Previous files corrupted -> Have to fork project again [Level-0]
InfiBeyond Sep 7, 2023
cb37643
[Level 1. Echo]
InfiBeyond Sep 7, 2023
06d749e
[Level 2. Add, List]
InfiBeyond Sep 7, 2023
ccefdd8
[Level 3. Mark as Done]
InfiBeyond Sep 7, 2023
c5e5035
[Level 4. ToDos, Events, Deadlines]
InfiBeyond Sep 7, 2023
f6fa252
[Level 5. Handle Errors]
InfiBeyond Sep 7, 2023
268ecd1
[Level 6. Delete]
InfiBeyond Sep 7, 2023
ec71f5a
[Level 7. Save]
InfiBeyond Sep 15, 2023
2832520
Merge branch 'branch-Level-7'
InfiBeyond Sep 15, 2023
8e0a3da
[Level 8. Dates and Times
InfiBeyond Sep 19, 2023
bc254bf
Merge branch 'branch-Level-8'
InfiBeyond Sep 19, 2023
bc20f51
[Level 8. Dates and Times]
InfiBeyond Sep 19, 2023
5591645
Merge branch 'branch-Level-8'
InfiBeyond Sep 19, 2023
90fb38b
OOP part 1
InfiBeyond Sep 24, 2023
b0c2294
[A-MoreOOP]
InfiBeyond Sep 24, 2023
e1e5352
Merge branch 'branch-A-MoreOOP'
InfiBeyond Sep 24, 2023
1b46958
[A-Packages]
InfiBeyond Sep 24, 2023
60851c5
Merge branch 'branch-A-Packages'
InfiBeyond Sep 24, 2023
9ee8913
Merge branch 'add-gradle-support'
InfiBeyond Sep 24, 2023
13f7891
Fix renaming import package error
InfiBeyond Sep 24, 2023
0915f76
[A-Gradle]
InfiBeyond Sep 24, 2023
f1b52a4
[A-JUnit]
InfiBeyond Sep 24, 2023
48e1b39
Merge branch 'branch-A-JUnit'
InfiBeyond Sep 24, 2023
3e9730d
[A-Jar]
InfiBeyond Sep 24, 2023
e3f32d4
[A-JavaDoc]
InfiBeyond Sep 25, 2023
4ef7983
[A-CodingStandard]
InfiBeyond Sep 25, 2023
cbba5e0
[Level 9. Find]
InfiBeyond Sep 25, 2023
14daed2
Merge branch 'branch-A-JavaDoc'
InfiBeyond Sep 25, 2023
454b9ec
Merge branch 'branch-A-CodingStandard'
InfiBeyond Sep 25, 2023
83021ff
Merge branch 'branch-Level-9'
InfiBeyond Sep 25, 2023
202d315
[A-CheckStyle]
InfiBeyond Sep 25, 2023
3a6c213
Merge branch 'branch-A-CheckStyle'
InfiBeyond Sep 25, 2023
f270bbc
[Level 10. GUI]
InfiBeyond Sep 25, 2023
87585ce
[Level 10. GUI]
InfiBeyond Sep 28, 2023
0264fab
Add MainWindow.java
InfiBeyond Sep 28, 2023
64cd33a
Merge branch 'branch-Level-10'
InfiBeyond Sep 28, 2023
677a0a3
Generate a new JAR file using Gradle
InfiBeyond Sep 28, 2023
e9c434c
[A-Assertions]
InfiBeyond Sep 28, 2023
c9b3825
[A-CheckStyle]
InfiBeyond Sep 28, 2023
e62e810
Merge pull request #2 from InfiBeyond/branch-A-Assertions
InfiBeyond Sep 28, 2023
9c23bc9
Merge branch 'master' of https://github.com/InfiBeyond/ip
InfiBeyond Sep 28, 2023
f1ca54a
Merge pull request #3 from InfiBeyond/branch-A-CodeQuality
InfiBeyond Sep 28, 2023
59dedbd
Merge branch 'master' of https://github.com/InfiBeyond/ip
InfiBeyond Sep 28, 2023
7c5fc1f
[C-DetectDuplicates]
InfiBeyond Sep 28, 2023
8cc478f
Merge branch 'branch-C-DetectDuplicates'
InfiBeyond Sep 28, 2023
69a2e5d
Fix GUI for display text by changing height and width.
InfiBeyond Sep 28, 2023
96b6642
Merge branch 'branch-A-BetterGui'
InfiBeyond Sep 28, 2023
17e9d8b
Add Ui.png
InfiBeyond Sep 28, 2023
066511a
Update README.md
InfiBeyond Sep 28, 2023
34a161e
Update README.md
InfiBeyond Sep 28, 2023
22fc82a
Merge branch 'master' of https://github.com/InfiBeyond/ip
InfiBeyond Sep 28, 2023
91503fa
Update GUI
InfiBeyond Oct 3, 2023
77e2a1d
Update GUI
InfiBeyond Oct 3, 2023
47711eb
Fix missing Ui.png
InfiBeyond Oct 3, 2023
ca6addc
Update UI.png location
InfiBeyond Oct 3, 2023
618da5b
Fix styling errors
InfiBeyond Oct 3, 2023
f7d2b25
Update README.md
InfiBeyond Oct 3, 2023
6182e16
Update README.md
InfiBeyond Oct 3, 2023
ad511a3
Update README.md
InfiBeyond Oct 3, 2023
a87b8a8
Update README.md
InfiBeyond Oct 3, 2023
c77c2bb
Update README.md
InfiBeyond Oct 3, 2023
27af30c
Improve JUnit Testing
InfiBeyond Oct 5, 2023
55a69f3
Update Jar file
InfiBeyond Oct 5, 2023
699769d
Update credits for code Reuse
InfiBeyond Nov 7, 2023
722c222
Update credits for code reuse
InfiBeyond Nov 7, 2023
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
10 changes: 10 additions & 0 deletions data/tasks.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
T | 1 | task1
E | 1 | task3 | startTime-endTime
T | 0 | task4
D | 0 | task5 | ddl2
E | 0 | task6 | startTime1-endTime2
E | 0 | task1 | a-a
E | 0 | task 2 | a-a
E | 0 | task 1 | a-a
E | 0 | task 1 | a-a
D | 0 | test | a
25 changes: 25 additions & 0 deletions src/main/java/Deadline.java

Choose a reason for hiding this comment

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

Overall good job! Good use of abstraction using the Task class! However, it might be a better idea to have even more abstraction through the addition of a UI class that handles all the printing and a TaskList class that handles the list of Tasks.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
public class Deadline extends Task {
private String deadline;

public Deadline(String task, String deadline) throws DukeException{
super(task);
this.deadline = deadline;
}

@Override
public String getStatus(){
String time = "(by: " + deadline + ")";
return "[Deadline]" + super.getStatus() + " " + time;
}

@Override
public String getTime() {
return deadline;
}

@Override
public String toFileString() {
return super.isDone ? ("D | 1 | " + super.task + " | " + this.deadline)
: ("D | 0 | " + super.task + " | " + this.deadline);
}
}
295 changes: 288 additions & 7 deletions src/main/java/Duke.java

Choose a reason for hiding this comment

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

The indentation for the case blocks inside the switch statement within the try block does not follow the coding standard

Original file line number Diff line number Diff line change
@@ -1,10 +1,291 @@
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

import java.util.ArrayList;
import java.util.Scanner;

public class Duke {
public static void main(String[] args) {
String logo = " ____ _ \n"
+ "| _ \\ _ _| | _____ \n"
+ "| | | | | | | |/ / _ \\\n"
+ "| |_| | |_| | < __/\n"
+ "|____/ \\__,_|_|\\_\\___|\n";
System.out.println("Hello from\n" + logo);
public static final String PARTITION = "------------------------------------------------------------";
public static final String NAME = "Duke Max";
public static final Scanner SCANNER = new Scanner(System.in);
public static final String FILEPATH = "./data/tasks.txt";

public static ArrayList<Task> taskList = new ArrayList<Task>();

public static void main(String[] args) throws DukeException{
load(FILEPATH);
greet();
String input = SCANNER.next();
while(!input.equals("bye")) {
try {
switch(input){
case "list":
print();
break;
case "print":
String time = SCANNER.nextLine();
if (time.isBlank() || time.isEmpty()) {
print();
break;
}

time = formatTime(time);
if (time == null) {
String messageSorry = "Sorry, you have entered the wrong format for time.";
String messageFormat = "Please enter in the format of yyyy-MM-dd HH:mm:ss or yyyy-MM-dd";
throw new DukeException(messageSorry + "\n" + messageFormat);
}

print(time);
break;
case "mark":
int markItem = SCANNER.nextInt();
taskList.get(markItem - 1).markItem(true);
save(FILEPATH);
break;
case "unmark":
int unmarkItem = SCANNER.nextInt();
taskList.get(unmarkItem - 1).markItem(false);
save(FILEPATH);
break;
case "delete":
Copy link

@andrefoo andrefoo Sep 10, 2023

Choose a reason for hiding this comment

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

Consider making inputs case-insensitive!

This way, if I requested to add a todo writing: tOdO it would still add the task into the list.
Try using 'String' 's equalsIgnoreCase() method compares two strings, ignoring lower case and upper case differences.

int deleteItem = SCANNER.nextInt();
if (deleteItem >= taskList.size()) {
throw new DukeException("Sorry, seleted event is out of range.");
}
delete(deleteItem);
save(FILEPATH);
break;
case "todo":
String toDoEvent = SCANNER.nextLine();
if (toDoEvent.isBlank() || toDoEvent.isEmpty()) {
throw new DukeException("Sorry, the todo task must have a title.");
}
add(new ToDo(toDoEvent));
save(FILEPATH);
break;
case "event":
String eventCommand = SCANNER.nextLine();
//when user didn't provide title and start & end time
if (eventCommand.isBlank() || eventCommand.isEmpty()
|| !eventCommand.contains(" /from ") || !eventCommand.contains(" /to ")) {
throw new DukeException("Sorry, this event must have a title, start time, and end time.");
}
String[] event = new String[3];
try {
event[0] = eventCommand.substring(1, eventCommand.indexOf(" /"));
event[1] = eventCommand.substring(eventCommand.indexOf("/from") + 6,
eventCommand.indexOf(" /to"));
event[2] = eventCommand.substring(eventCommand.indexOf("/to") + 4);
}
catch (StringIndexOutOfBoundsException e) {
System.out.println("Sorry, this event must have a title, start time, and end time.");
}
//when user provide empty title
if (event[0].isBlank() || event[0].isEmpty()) {
throw new DukeException("Sorry, the event must have a title.");
}
//when user didn't provide the starting time
if (event[1].isBlank() || event[1].isEmpty()) {
throw new DukeException("Sorry, the event must have a starting time");
}
//when user didn't provide the end time
if (event[2].isBlank() || event[2].isEmpty()) {
throw new DukeException("Sorry, the event must have an end time");
}
//when user provide wrong time format
String startTime = formatTime(event[1]);
String endTime = formatTime(event[2]);
if (startTime.isBlank() || startTime.isEmpty() || endTime.isBlank() || endTime.isEmpty()) {
throw new DukeException("Please enter the time with this format: yyyy-MM-dd HH:mm:ss");
}
add(new Event(event[0], startTime, endTime));
save(FILEPATH);
break;
case "deadline":
String ddlCommand = SCANNER.nextLine();
//when user didn't provide title & ddl
if (ddlCommand.isBlank() || ddlCommand.isEmpty() || !ddlCommand.contains(" /by ")) {
throw new DukeException("Sorry, the deadline task must have a title and a deadline.");
}
String[] ddl = new String[2];
try {
ddl = ddlCommand.split(" /by ");
}
catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Sorry, this deadline task must have a title and a deadline.");
}
//when user provide empty title
if (ddl[0].isBlank() || ddl[0].isEmpty()) {
throw new DukeException("Sorry, the deadline event must have a title.");
}
//when user didn't provide ddl
if (ddl[1].isBlank() || ddl[1].isEmpty()) {
throw new DukeException("Sorry, the deadline event must have a dealine");
}
String ddlTime = formatTime(ddl[1]);
//when user provide wrong time format
if (ddlTime.isBlank() || ddlTime.isEmpty()) {
throw new DukeException("Please enter the time with this format: yyyy-MM-dd HH:mm:ss");
}
add(new Deadline(ddl[0].substring(1), ddlTime));
save(FILEPATH);
break;
case "clear":
clear();
break;
default:
throw new DukeException("Sorry, I don't recognize this input. Please try again.");
}
}

catch (DukeException e) {
System.out.println(e.getMessage());

Choose a reason for hiding this comment

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

I think your method is too long here. Maybe try to create some other methods?😎

//help();
}

finally {
System.out.println(PARTITION);
input = SCANNER.next();
}
}

exit();
}

public static void greet() {
System.out.println(PARTITION);
System.out.println("Hello! I'm " + NAME + ".");
System.out.println("What can I do for you?");
System.out.println(PARTITION);
}

public static void add(Task input) {
taskList.add(input);
System.out.println("Got it! This task has been added: ");
System.out.println(input.getStatus());
System.out.println("Current # of " + plural(taskList.size(), "task") + ": " + taskList.size());
}

public static void delete(int num) {
System.out.println("I've removed this task:");
taskList.get(num-1).getStatus();
taskList.remove(num - 1);
System.out.println("Current # of " + plural(taskList.size(), "task") + ": " + taskList.size());
}

public static void print() {
int index = 1;
for (Task task: taskList) {
System.out.println(index + ". " + task.getStatus());
index ++;
}
System.out.println("Current # of " + plural(taskList.size(), "task") + ": " + taskList.size());
}

public static void print(String time) {
int count = 0;
for(Task task: taskList) {
if(task.getTime().contains(time)) {
System.out.println(task.getStatus());
count += 1;
}
}
System.out.println("Current # of " + plural(count, "task") + ": " + taskList.size());
}

public static void clear() {
taskList.clear();
System.out.println("Okay, I have cleared all tasks.");
}

public static void exit() {
System.out.println("Bye. Hope to see you again soon!");
System.out.println(PARTITION);
}

private static String plural(int count, String word) {
return (count <= 1) ? word : (word + "s");
}

private static void save(String path) {
try (PrintWriter printwriter = new PrintWriter(new FileWriter(path))) {
for (Task task : taskList) {
printwriter.write(task.toFileString() +"\n");
}
} catch (IOException e) {
System.out.println("There is an error saving this file: " + e.getMessage());
}
}

private static ArrayList<Task> load(String path) throws DukeException{
handleMissing(path);

try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
String text = reader.readLine();
while (text != null) {
Task task = Task.convertStringToTask(text);
taskList.add(task);
text = reader.readLine();
}
} catch (IOException e) {
System.out.println("There is an error loading tasks from file: " + e.getMessage());
}
return taskList;
}

private static void handleMissing(String testPath) {
try{
//if directory or path doesn't exist
Path directoryPath = Paths.get(".", "data");
if (!Files.exists(directoryPath)) {
Files.createDirectories(directoryPath);
}

Path path = directoryPath.resolve("tasks.txt");
if (!Files.exists(path)) {
Files.createFile(path);
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("There is an error loading file: " + e.getMessage());
}
}

private static String formatTime(String input) {
try {
// when input have a date and a time
// convert string to LocalDateTime then convert to another format
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse(input, formatter);
return dateTime.format(DateTimeFormatter.ofPattern("MMM d yyyy HH:mm"));
} catch (DateTimeParseException notDateTime) {
try {
// input is only a date
LocalDate date = LocalDate.parse(input);
return date.format(DateTimeFormatter.ofPattern("MMM d yyyy"));
} catch (DateTimeParseException notDate) {
try {
// input is only a time
LocalTime time = LocalTime.parse(input);
return time.format(DateTimeFormatter.ofPattern("HH:mm"));
} catch (DateTimeParseException nullError) {
return null;
}
}
}
}
}
Copy link

Choose a reason for hiding this comment

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

Indentation & Formatting:

The code seems to be properly indented, which makes it easier to read.
The consistent use of brackets {} and their placement adheres to the Java coding conventions.
Variable Naming:

Names like input, eventCommand, and ddlCommand are meaningful, but some variables like ddl could have a more descriptive name.
Variables should be named in a manner that makes their purpose clear. For instance, ddl might be better named as deadlineDetails or similar.
sc has not been defined in the given snippet, so it's unclear what it represents. If it's a Scanner object, a more intuitive name like scanner might be more appropriate.

10 changes: 10 additions & 0 deletions src/main/java/DukeException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
public class DukeException extends Exception {
public DukeException(String message) {
super(message);
}

@Override
public String getMessage() {
return ":( Oh no! " + super.getMessage();
}
}
27 changes: 27 additions & 0 deletions src/main/java/Event.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
public class Event extends Task {
private String from;
private String to;

public Event(String task, String from, String to) throws DukeException {
super(task);
this.from = from;
this.to = to;
}

@Override
public String getStatus(){
String time = "(from: " + from + " to: " + to + ")";
return "[Event]" + super.getStatus() + " " + time;
}

@Override
public String getTime() {
return this.from + " " + this.to;
}

@Override
public String toFileString() {
return super.isDone ? ("E | 1 | " + super.task + " | " + this.from + "-" + this.to)
: ("E | 0 | " + super.task + " | " + this.from + "-" + this.to);
}
}
Loading