Skip to content
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
42 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
f8bb5fb
Level-0
mikolajed Aug 21, 2024
4b6a8b1
Add Level-1: echoing
mikolajed Aug 25, 2024
66187d7
Add Level-2: adding, listing
mikolajed Aug 26, 2024
e62452e
Add Level-3: marking
mikolajed Aug 26, 2024
934dabd
Add minor code quality changes
mikolajed Sep 4, 2024
5089664
Add new Task derived class
mikolajed Sep 4, 2024
266dda4
Add Level-4: ToDos, Events, Deadlines
mikolajed Sep 8, 2024
37e3f9b
Improve code quality
mikolajed Sep 8, 2024
97047ec
Add automated testing
mikolajed Sep 8, 2024
f4594ed
Minor UI change
mikolajed Sep 8, 2024
c7d735b
Add Level-5: error handling
mikolajed Sep 8, 2024
7aead71
Merge branch 'branch-Level-5'
mikolajed Sep 8, 2024
5682555
Add A-Packages
mikolajed Sep 8, 2024
73d4c22
Add Level-6: deleting
mikolajed Sep 18, 2024
e117036
Add Level-7: saving
mikolajed Sep 18, 2024
a76c9ad
Merge branch 'branch-Level-6'
mikolajed Sep 19, 2024
f1a9136
Merge branch 'branch-Level-7'
mikolajed Sep 19, 2024
bb903a4
A-MoreOOP: Add TaskList class
mikolajed Sep 28, 2024
7119092
A-MoreOOP: Add Storage
mikolajed Sep 29, 2024
bcd72f0
Update pythia.txt
mikolajed Sep 29, 2024
7cb4643
A-MoreOOP: Update Ui
mikolajed Sep 29, 2024
a144c7c
A-MoreOOP: Refactor Parser
mikolajed Sep 29, 2024
a58e2d5
Add Level-9: finding tasks
mikolajed Oct 3, 2024
6702bb4
Add Level-8
mikolajed Oct 3, 2024
4f34a67
Merge pull request #1 from mikolajed/branch-Level-8
mikolajed Oct 3, 2024
acf8c93
Merge pull request #2 from mikolajed/branch-Level-9
mikolajed Oct 3, 2024
44da9b8
Add JavaDoc comments
mikolajed Oct 7, 2024
2c38341
Update README.md
mikolajed Oct 8, 2024
ed28a9d
Update README.md
mikolajed Oct 8, 2024
3b5a414
Update README.md
mikolajed Oct 8, 2024
1031f84
Minor bug fix
mikolajed Oct 8, 2024
ede59cb
Update README.md
mikolajed Oct 8, 2024
cbc2fdc
Update README.md
mikolajed Oct 8, 2024
2f33e97
Update README.md
mikolajed Oct 8, 2024
cb9105a
Update README.md
mikolajed Oct 8, 2024
7762786
Update README.md
mikolajed Oct 8, 2024
5e18e76
Bug fix
mikolajed Oct 8, 2024
e561e10
Bug fix
mikolajed Oct 8, 2024
a754e2e
Merge branch 'add-gradle-support'
mikolajed Oct 8, 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
2 changes: 2 additions & 0 deletions data/pythia.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1 | swim
0 | read a book
5 changes: 1 addition & 4 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
# Duke User Guide

// Update the title above to match the actual product name

# Pythia User Guide
// Product screenshot goes here

// Product intro goes here
Expand Down
10 changes: 0 additions & 10 deletions src/main/java/Duke.java

This file was deleted.

132 changes: 132 additions & 0 deletions src/main/java/pythia/Pythia.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package pythia;

import pythia.io.Parser;
import pythia.io.IO;
import pythia.task.Task;
import pythia.task.ToDo;
import pythia.task.Deadline;
import pythia.task.Event;
import pythia.exceptions.PythiaException;
import java.util.ArrayList;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class Pythia {
private static String botName = "Pythia";
private static String dataPath = "data/pythia.txt";
private static String logo =
"____ _ _ _ \n" +
"| _ \\ _ _| |_| |__ (_) __ _ \n" +
"| |_) | | | | __| '_ \\| |/ _` |\n" +
"| __/| |_| | |_| | | | | (_| |\n" +
"|_| \\__, |\\__|_| |_|_|\\__,_|\n" +
" |___/ ";

private static boolean isByeSaid = false;
private static ArrayList<Task> taskList = new ArrayList<Task>();
private static int remainingTasks = 0;

public static int getNumberOfRemainingTasks() {
return remainingTasks;
}

public static void greet() {
String helloMsg = "Welcome, seeker. I am " + botName + ".\n" +
"What brings you here?";
IO.printResponse(helloMsg);
}

public static void echo(String text) {
IO.printResponse(text);
}

public static void sayBye() {
String byeMsg = "Your path is set. Until we meet again.";
IO.printResponse(byeMsg);
isByeSaid = true;
}

public static void listTasks() {
IO.printTaskList(taskList);
}

public static void addTask(String taskName) {
taskList.add(new Task(taskName));
remainingTasks++;
IO.printAddedTask("added: " + taskName);
saveTasksToTxt();
}

public static void addToDo(String todoName) {
taskList.add(new ToDo(todoName));
remainingTasks++;
IO.printAddedTask("added: " + todoName);
saveTasksToTxt();
}

public static void addDeadline(String deadlineName, String dueDate) {
taskList.add(new Deadline(deadlineName, dueDate));
remainingTasks++;
IO.printAddedTask("added: " + deadlineName);
saveTasksToTxt();
}

public static void addEvent(String eventName, String startDate, String endDate) {
taskList.add(new Event(eventName, startDate, endDate));
remainingTasks++;
IO.printAddedTask("added: " + eventName);
saveTasksToTxt();
}

public static void markTask(Integer taskNumber) {
if (taskNumber <= taskList.size()) {
taskList.get(taskNumber - 1).markAsDone();
String msg = "Nice! I've marked this task as done:\n\t" + taskList.get(taskNumber - 1).toString();
IO.printResponse(msg);
saveTasksToTxt();
} else {
IO.printResponse("There is no such task :(");
}
remainingTasks--;
}

public static void deleteTask(Integer taskNumber) {
if (taskNumber <= taskList.size()) {
String msg = "Nice! I've deleted this task:\n\t" + taskList.get(taskNumber - 1).toString();
taskList.remove(taskNumber - 1);
IO.printResponse(msg);
} else {
IO.printResponse("There is no such task :(");
}
remainingTasks--;
}

public static void saveTasksToTxt() {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(dataPath, false))) {
for (Task task : taskList) {
writer.write(task.toTxt());
writer.newLine();
}
} catch (IOException e) {
System.err.println("Error writing to file: " + e.getMessage());
}
}


public static void main(String[] args) {
IO.init();
greet();
Parser parser = new Parser();

while (!isByeSaid) {
try {
String request = IO.getRequest();
parser.parse(request);
parser.execute();
} catch (PythiaException e) {
IO.printResponse(e.getUserMessage());
}
}
}
}
13 changes: 13 additions & 0 deletions src/main/java/pythia/exceptions/PythiaException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package pythia.exceptions;

public class PythiaException extends RuntimeException {
private String userMessage;
public PythiaException(String message, String userMessage) {
super(message);
this.userMessage = userMessage;
}

public String getUserMessage() {
return userMessage;
}
}
47 changes: 47 additions & 0 deletions src/main/java/pythia/io/IO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package pythia.io;

import java.util.ArrayList;
import java.util.Scanner;
import pythia.task.Task;
import pythia.Pythia;

public class IO {
private static Scanner scanner;;

public static void init() {
scanner = new Scanner(System.in);
}

public static void printResponse(String text) {
String lineSeparator = "____________________________________________________________";
text = lineSeparator + "\n" + text + "\n" + lineSeparator + "\n";
String formattedText = text.replaceAll("(?m)^", "\t");
System.out.print(formattedText);
}

public static String getRequest() {
return scanner.nextLine();
}

public static void printAddedTask(String text) {
printResponse(text.toLowerCase());
}

public static void printTaskList(ArrayList<Task> taskList) {
StringBuilder taskListString = new StringBuilder();
for (int i = 0; i < taskList.size(); i++) {
taskListString.append(i + 1).append(". ");
taskListString.append(taskList.get(i).toString());
taskListString.append("\n");
}

int remainingTasks = Pythia.getNumberOfRemainingTasks();
taskListString.append("Now you have ").append(remainingTasks);
if (remainingTasks == 1) {
taskListString.append(" pythia.task in the list.");
} else {
taskListString.append(" tasks in the list.");
}
printResponse(taskListString.toString());
}
}
171 changes: 171 additions & 0 deletions src/main/java/pythia/io/Parser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package pythia.io;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Collections;
import pythia.exceptions.PythiaException;
import pythia.Pythia;

public class Parser {
private String commandType = null;
private ArrayList<String> argumentList = null;
private String parsingErrorMessage = "Parsing of add command unsuccessful.";


public Parser() {

}

private String parseCommandType(String rawText) {
int spaceIndex = rawText.indexOf(' ');

String firstPart;
if (spaceIndex != -1) {
firstPart = rawText.substring(0, spaceIndex);
} else {
firstPart = rawText;
}
return firstPart;
}

private void parseBye(String rawText) {}

private void parseList(String rawText) {}

private void parseAdd(String rawText) throws PythiaException {
Pattern pattern = Pattern.compile("add\\s(.+)");
Matcher matcher = pattern.matcher(rawText);

String what = "";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Try to minimise duplicated codes to improve code quality.


if (matcher.find()) {
what = matcher.group(1);
} else {
throw new PythiaException(parsingErrorMessage, "I am not sure what to add.");
}

argumentList.clear();
Collections.addAll(argumentList, what);
}

private void parseMark(String rawText) throws PythiaException {
Pattern pattern = Pattern.compile("mark\\s(.+)");
Matcher matcher = pattern.matcher(rawText);

String what = "";

if (matcher.find()) {
what = matcher.group(1);
} else {
throw new PythiaException(parsingErrorMessage, "Please specify what should I mark as done.");
}

argumentList.clear();
Collections.addAll(argumentList, what);
}

private void parseToDo(String rawText) throws PythiaException {
Pattern pattern = Pattern.compile("todo\\s(.+)");
Matcher matcher = pattern.matcher(rawText);

String what = "";

if (matcher.find()) {
what = matcher.group(1);
} else {
throw new PythiaException(parsingErrorMessage, "Todo should have a description.");
}

argumentList.clear();
Collections.addAll(argumentList, what);
}

private void parseDeadline(String rawText) throws PythiaException {
Pattern pattern = Pattern.compile("deadline\\s(.+)\\s/by\\s(.+)");
Matcher matcher = pattern.matcher(rawText);

String what = "";
String byWhen = "";

if (matcher.find()) {
what = matcher.group(1);
byWhen = matcher.group(2);
} else {
throw new PythiaException(parsingErrorMessage, "Deadline should have description and a date.");
}

argumentList.clear();
Collections.addAll(argumentList, what, byWhen);
}

private void parseEvent(String rawText) throws PythiaException {
Pattern pattern = Pattern.compile("event\\s(.+)\\s/from\\s(.+)\\s/to\\s(.+)");
Matcher matcher = pattern.matcher(rawText);

String what = "";
String fromWhen = "";
String toWhen = "";

if (matcher.find()) {
what = matcher.group(1);
fromWhen = matcher.group(2);
toWhen = matcher.group(3);
} else {
throw new PythiaException(parsingErrorMessage, "Event should have description and from and to dates.");
}

argumentList.clear();
Collections.addAll(argumentList, what, fromWhen, toWhen);
}

public void parseDelete(String rawText) throws PythiaException {
Pattern pattern = Pattern.compile("delete\\s(.+)");
Matcher matcher = pattern.matcher(rawText);

String what = "";

if (matcher.find()) {
what = matcher.group(1);
} else {
throw new PythiaException(parsingErrorMessage, "Please specify what should I delete.");
}

argumentList.clear();
Collections.addAll(argumentList, what);
}

public void parse(String rawText) throws PythiaException {
commandType = parseCommandType(rawText);
argumentList = new ArrayList<>();

switch (commandType) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Note there is no indentation for case clauses.

case "bye" -> parseBye(rawText);
case "list" -> parseList(rawText);
case "add" -> parseAdd(rawText);
case "mark" -> parseMark(rawText);
case "todo" -> parseToDo(rawText);
case "deadline" -> parseDeadline(rawText);
case "event" -> parseEvent(rawText);
case "delete" -> parseDelete(rawText);
}
}

public void execute() throws PythiaException {
if (commandType == null) {
throw new PythiaException(parsingErrorMessage, "Sorry, I am busy.");
}

switch (commandType) {
case "bye" -> Pythia.sayBye();
case "list" -> Pythia.listTasks();
case "add" -> Pythia.addTask(argumentList.get(0));
case "mark" -> Pythia.markTask(Integer.parseInt(argumentList.get(0)));
case "todo" -> Pythia.addToDo(argumentList.get(0));
case "deadline" -> Pythia.addDeadline(argumentList.get(0), argumentList.get(1));
case "event" -> Pythia.addEvent(argumentList.get(0), argumentList.get(1), argumentList.get(2));
case "delete" -> Pythia.deleteTask(Integer.parseInt(argumentList.get(0)));
default -> throw new PythiaException(parsingErrorMessage, "Hmm. I am not sure what you mean.");
}
}
}
Loading