diff --git a/domain-model.md b/domain-model.md new file mode 100644 index 000000000..9ef9ee1af --- /dev/null +++ b/domain-model.md @@ -0,0 +1,81 @@ +# Core + +## Class: TodoList + +| Method | Member Variable | Scenario | Result | +|-------------------------------------------------------|--------------------------------|------------------------------------------------------------|------------------------------------| +| boolean add(String name) | HashMap tasks | Task with the provided name is not already in the todolist | true | +| | | Task with the provided name is already in the todolist | false | +| | | | | +| String listTasks() | | There are tasks in the todolist | string with all tasks | +| | | There are no tasks in the todolist | string with error message | +| | | | | +| boolean updateTaskStatus(String name, Boolean status) | | There is a task with the provided name | true | +| | | There is no task with the provided name | false | +| | | | | +| ArrayList getCompletedTasks() | | There are completed tasks in the todolist | string with all completed tasks | +| | | There are no completed tasks in the todolist | string with error message | +| | | | | +| ArrayList getUnCompletedTasks() | | There are uncompleted tasks in the todolist | List with all uncompleted tasks | +| | | There are no uncompleted tasks in the todolist | Empty list | +| | | | | +| boolean searchTask(String name) | | There was a task with the provided name | true | +| | | There was no task with the provided name | false | +| | | | | +| boolean removeTask(String name) | | Task with the provided name is not in the todolist | false | +| | | Task with the provided name is in the todolist | true | +| | | | | +| taskDescending() | | There are tasks in the todolist | string in descending order by name | +| | | There are no tasks in the todolist | string with error message | +| | | | | +| taskAscending() | | There are tasks in the todolist | string in ascending order by name | +| | | There are no tasks in the todolist | string with error message | + +*Note: "error message" means something like "The list is empty".* + +# Extension + +## Class: TodoList + +| Method | Member Variable | Scenario | Result | +|-------------------------------------------------------|-----------------------------|------------------------------------------------------------|------------------------------------| +| boolean add(String name) | HashMap tasks | Task with the provided name is not already in the todolist | true | +| | | Task with the provided name is already in the todolist | false | +| | | | | +| String listTasks() | | There are tasks in the todolist | string with all tasks | +| | | There are no tasks in the todolist | string with error message | +| | | | | +| boolean updateTaskStatus(String name, Boolean status) | | There is a task with the provided name | true | +| | | There is no task with the provided name | false | +| | | | | +| ArrayList getCompletedTasks() | | There are completed tasks in the todolist | string with all completed tasks | +| | | There are no completed tasks in the todolist | string with error message | +| | | | | +| ArrayList getUnCompletedTasks() | | There are uncompleted tasks in the todolist | List with all uncompleted tasks | +| | | There are no uncompleted tasks in the todolist | Empty list | +| | | | | +| boolean searchTask(String name) | | There was a task with the provided name | true | +| | | There was no task with the provided name | false | +| | | | | +| boolean removeTask(String name) | | Task with the provided name is not in the todolist | false | +| | | Task with the provided name is in the todolist | true | +| | | | | +| taskDescending() | | There are tasks in the todolist | string in descending order by name | +| | | There are no tasks in the todolist | string with error message | +| | | | | +| taskAscending() | | There are tasks in the todolist | string in ascending order by name | +| | | There are no tasks in the todolist | string with error message | +| | | | | +| getTaskById(int id) | | Task with the given ID exists | return task object | +| | | Task with the given ID does not exist | return null | +| updateTaskName(int id, String newName) | | Task with ID exists/does not exist | return true/false | +| updateTaskStatusById(int id, Boolean status) | | Task with ID exists/does not exist | return true/false | +| getTaskId(String name) | | Task with name exists/does not exist | Return int/return -1 | + +## Task + +| Method | Member Variable | Scenario | Result | +|--------|-------------------|----------|--------| +| | int id | | | +| | boolean completed | | | +| | String name | | | \ No newline at end of file diff --git a/src/main/java/com/booleanuk/core/TodoList.java b/src/main/java/com/booleanuk/core/TodoList.java index 675adaf0b..0c79a0850 100644 --- a/src/main/java/com/booleanuk/core/TodoList.java +++ b/src/main/java/com/booleanuk/core/TodoList.java @@ -1,5 +1,108 @@ package com.booleanuk.core; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public class TodoList { + private Map todo = new HashMap<>(); + // + + public boolean add(String name) { + if (this.todo.containsKey(name)) { + return false; + } + this.todo.put(name, false); + return true; + } + + public String listTasks() { + if (todo.isEmpty()) + return "There is nothing to do!"; + + StringBuilder sb = new StringBuilder(); + for (String s : todo.keySet()) { + sb.append(s) + .append(": ") + .append(todo.get(s) ? "completed" : "uncompleted") + .append("\n"); + } + return sb.toString(); + } + + public boolean updateTaskStatus(String name, boolean updatedStatus) { + if (!todo.containsKey(name)) + return false; + todo.replace(name, updatedStatus); + return true; + } + + public boolean getTaskStatus(String name) { + if (!todo.containsKey(name)) + return false; + return todo.get(name); + } + + public boolean searchTask(String name) { + return todo.containsKey(name); + } + + public boolean removeTask(String name) { + if (!todo.containsKey(name)) { + return false; + } + todo.remove(name); + return true; + } + + public String taskDescending() { + if (todo.isEmpty()) + return "There is nothing to do!"; + + List sortedKeys = todo.keySet().stream().sorted().toList(); + StringBuilder sb = new StringBuilder(); + for (String s : sortedKeys) { + sb.append(s) + .append(": ") + .append(todo.get(s) ? "completed" : "uncompleted") + .append("\n"); + } + return sb.toString(); + } + + public String taskAscending() { + if (todo.isEmpty()) + return "There is nothing to do!"; + + List sortedKeys = todo.keySet().stream().sorted().toList().reversed(); + StringBuilder sb = new StringBuilder(); + for (String s : sortedKeys) { + sb.append(s) + .append(": ") + .append(todo.get(s) ? "completed" : "uncompleted") + .append("\n"); + } + return sb.toString(); + } + + public ArrayList getCompletedTasks() { + ArrayList tasks = new ArrayList<>(); + for (String k : todo.keySet()) { + if (todo.get(k)) { + tasks.add(k); + } + } + return tasks; + } + public ArrayList getUncompletedTasks() { + ArrayList tasks = new ArrayList<>(); + for (String k : todo.keySet()) { + if (!todo.get(k)) { + tasks.add(k); + } + } + return tasks; + } } diff --git a/src/main/java/com/booleanuk/extension/Task.java b/src/main/java/com/booleanuk/extension/Task.java new file mode 100644 index 000000000..9be675063 --- /dev/null +++ b/src/main/java/com/booleanuk/extension/Task.java @@ -0,0 +1,39 @@ +package com.booleanuk.extension; + +public class Task { + private static int nextId = 0; + private int id; + private boolean completed; + private String name; + + public Task(String name) { + completed = false; + this.id = nextId; + nextId++; + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public boolean isCompleted() { + return completed; + } + + public void setCompleted(boolean completed) { + this.completed = completed; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/java/com/booleanuk/extension/TodoList.java b/src/main/java/com/booleanuk/extension/TodoList.java new file mode 100644 index 000000000..511f72018 --- /dev/null +++ b/src/main/java/com/booleanuk/extension/TodoList.java @@ -0,0 +1,151 @@ +package com.booleanuk.extension; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class TodoList { + private Map todo = new HashMap<>(); + // + + public boolean add(String name) { + if (this.todo.containsKey(name)) { + return false; + } + this.todo.put(name, new Task(name)); + return true; + } + + public String listTasks() { + if (todo.isEmpty()) + return "There is nothing to do!"; + + StringBuilder sb = new StringBuilder(); + for (String s : todo.keySet()) { + sb.append(s) + .append(": ") + .append(todo.get(s).isCompleted() ? "completed" : "uncompleted") + .append("\n"); + } + return sb.toString(); + } + + public boolean updateTaskStatus(String name, boolean updatedStatus) { + if (!todo.containsKey(name)) + return false; + todo.get(name).setCompleted(updatedStatus); + return true; + } + + public boolean getTaskStatus(String name) { + if (!todo.containsKey(name)) + return false; + return todo.get(name).isCompleted(); + } + + public boolean searchTask(String name) { + return todo.containsKey(name); + } + + public boolean removeTask(String name) { + if (!todo.containsKey(name)) { + return false; + } + todo.remove(name); + return true; + } + + public String taskDescending() { + if (todo.isEmpty()) + return "There is nothing to do!"; + + List sortedKeys = todo.keySet().stream().sorted().toList(); + StringBuilder sb = new StringBuilder(); + for (String s : sortedKeys) { + sb.append(s) + .append(": ") + .append(todo.get(s).isCompleted() ? "completed" : "uncompleted") + .append("\n"); + } + return sb.toString(); + } + + public String taskAscending() { + if (todo.isEmpty()) + return "There is nothing to do!"; + + List sortedKeys = todo.keySet().stream().sorted().toList().reversed(); + StringBuilder sb = new StringBuilder(); + for (String s : sortedKeys) { + sb.append(s) + .append(": ") + .append(todo.get(s).isCompleted() ? "completed" : "uncompleted") + .append("\n"); + } + return sb.toString(); + } + + public ArrayList getCompletedTasks() { + ArrayList tasks = new ArrayList<>(); + for (String k : todo.keySet()) { + if (todo.get(k).isCompleted()) { + tasks.add(k); + } + } + return tasks; + } + + public ArrayList getUncompletedTasks() { + ArrayList tasks = new ArrayList<>(); + for (String k : todo.keySet()) { + if (!todo.get(k).isCompleted()) { + tasks.add(k); + } + } + return tasks; + } + + public int getTaskId(String name) { + if (!todo.containsKey(name)) { + return -1; + } + return todo.get(name).getId(); + } + + public Task getTaskById(int id) { + for (String name : todo.keySet()) { + if (todo.get(name).getId() == id) { + return todo.get(name); + } + } + return null; + } + + public boolean updateTaskName(int id, String newName) { + Task task = null; + boolean found = false; + for (String name : todo.keySet()) { + if (todo.get(name).getId() == id) { + task = todo.get(name); + task.setName(newName); + found = true; + } + } + if (found) { + todo.remove(task.getName()); + todo.put(newName, task); + } + return found; + } + + public boolean updateTaskStatusById(int id, boolean newStatus) { + for (String name : todo.keySet()) { + if (todo.get(name).getId() == id) { + todo.get(name).setCompleted(newStatus); + return true; + } + } + return false; + } +} diff --git a/src/test/java/com/booleanuk/core/TodoListTest.java b/src/test/java/com/booleanuk/core/TodoListTest.java index 0bef779a4..5d51c77a6 100644 --- a/src/test/java/com/booleanuk/core/TodoListTest.java +++ b/src/test/java/com/booleanuk/core/TodoListTest.java @@ -3,11 +3,138 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.ArrayList; + class TodoListTest { @Test - public void exampleTest() { - String hello = "Hello"; - Assertions.assertEquals("Hello", hello); - Assertions.assertNotEquals("Goodbye", hello); + public void canAddTask() { + String name = "Study"; + TodoList todo = new TodoList(); + Assertions.assertTrue(todo.add(name)); + } + + @Test + public void cannotAddDuplicateTasks() { + TodoList todo = new TodoList(); + todo.add("Study"); + Assertions.assertFalse(todo.add("Study")); + } + + @Test + public void emptyListShouldReturnError() { + TodoList todo = new TodoList(); + Assertions.assertEquals("There is nothing to do!", todo.listTasks()); + } + + @Test + public void nonemptyListShouldListAll() { + TodoList todo = new TodoList(); + todo.add("Study"); + todo.add("Cook"); + todo.add("Sleep"); + Assertions.assertTrue(todo.listTasks().contains("Study: uncompleted")); + Assertions.assertTrue(todo.listTasks().contains("Cook: uncompleted")); + Assertions.assertTrue(todo.listTasks().contains("Sleep: uncompleted")); + } + + @Test + public void updateNonexistentTask() { + TodoList todo = new TodoList(); + Assertions.assertFalse(todo.updateTaskStatus("Eat cake", true)); + } + + @Test + public void updateTaskUpdatesTask() { + TodoList todo = new TodoList(); + todo.add("Study"); + Assertions.assertFalse(todo.getTaskStatus("Study")); + Assertions.assertTrue(todo.updateTaskStatus("Study", true)); + Assertions.assertTrue(todo.getTaskStatus("Study")); + } + + @Test + public void searchingWorksCorrectly() { + TodoList todo = new TodoList(); + todo.add("Study"); + todo.add("Cook"); + todo.add("Sleep"); + Assertions.assertTrue(todo.searchTask("Study")); + Assertions.assertTrue(todo.searchTask("Cook")); + Assertions.assertTrue(todo.searchTask("Sleep")); + Assertions.assertFalse(todo.searchTask("Tidy")); + } + + @Test + public void cannotRemoveNonexistentTask() { + TodoList todo = new TodoList(); + Assertions.assertFalse(todo.removeTask("Study")); + } + + @Test + public void removesTaskIfExists() { + TodoList todo = new TodoList(); + todo.add("Study"); + Assertions.assertTrue(todo.removeTask("Study")); + Assertions.assertFalse(todo.searchTask("Study")); + } + + @Test + public void tasksAreDescending() { + TodoList todo = new TodoList(); + todo.add("Cook"); + todo.add("Eat"); + todo.add("Tidy up"); + Assertions.assertEquals( + "Cook: uncompleted", + todo.taskDescending().split("\n")[0]); + Assertions.assertEquals( + "Eat: uncompleted", + todo.taskDescending().split("\n")[1]); + Assertions.assertEquals( + "Tidy up: uncompleted", + todo.taskDescending().split("\n")[2]); + } + + @Test + public void tasksAreAscending() { + TodoList todo = new TodoList(); + todo.add("Cook"); + todo.add("Eat"); + todo.add("Tidy up"); + Assertions.assertEquals( + "Cook: uncompleted", + todo.taskAscending().split("\n")[2]); + Assertions.assertEquals( + "Eat: uncompleted", + todo.taskAscending().split("\n")[1]); + Assertions.assertEquals( + "Tidy up: uncompleted", + todo.taskAscending().split("\n")[0]); + } + + @Test + public void onlyGettingCompletedTasks() { + TodoList todo = new TodoList(); + todo.add("Study"); + todo.add("Cook"); + todo.add("Sleep"); + todo.updateTaskStatus("Sleep", true); + ArrayList completedTasks = todo.getCompletedTasks(); + Assertions.assertTrue(completedTasks.contains("Sleep")); + Assertions.assertFalse(completedTasks.contains("Study")); + Assertions.assertFalse(completedTasks.contains("Cook")); + } + + @Test + public void onlyGettingUncompletedTasks() { + TodoList todo = new TodoList(); + todo.add("Study"); + todo.add("Cook"); + todo.add("Sleep"); + todo.updateTaskStatus("Sleep", true); + ArrayList tasks = todo.getUncompletedTasks(); + Assertions.assertFalse(tasks.contains("Sleep")); + Assertions.assertTrue(tasks.contains("Study")); + Assertions.assertTrue(tasks.contains("Cook")); } } diff --git a/src/test/java/com/booleanuk/extension/TodoListTest.java b/src/test/java/com/booleanuk/extension/TodoListTest.java new file mode 100644 index 000000000..f73533310 --- /dev/null +++ b/src/test/java/com/booleanuk/extension/TodoListTest.java @@ -0,0 +1,205 @@ +package com.booleanuk.extension; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; + +class TodoListTest { + @Test + public void canAddTask() { + String name = "Study"; + TodoList todo = new TodoList(); + Assertions.assertTrue(todo.add(name)); + } + + @Test + public void cannotAddDuplicateTasks() { + TodoList todo = new TodoList(); + todo.add("Study"); + Assertions.assertFalse(todo.add("Study")); + } + + @Test + public void emptyListShouldReturnError() { + TodoList todo = new TodoList(); + Assertions.assertEquals("There is nothing to do!", todo.listTasks()); + } + + @Test + public void nonemptyListShouldListAll() { + TodoList todo = new TodoList(); + todo.add("Study"); + todo.add("Cook"); + todo.add("Sleep"); + Assertions.assertTrue(todo.listTasks().contains("Study: uncompleted")); + Assertions.assertTrue(todo.listTasks().contains("Cook: uncompleted")); + Assertions.assertTrue(todo.listTasks().contains("Sleep: uncompleted")); + } + + @Test + public void updateNonexistentTask() { + TodoList todo = new TodoList(); + Assertions.assertFalse(todo.updateTaskStatus("Eat cake", true)); + } + + @Test + public void updateTaskUpdatesTask() { + TodoList todo = new TodoList(); + todo.add("Study"); + Assertions.assertFalse(todo.getTaskStatus("Study")); + Assertions.assertTrue(todo.updateTaskStatus("Study", true)); + Assertions.assertTrue(todo.getTaskStatus("Study")); + } + + @Test + public void searchingWorksCorrectly() { + TodoList todo = new TodoList(); + todo.add("Study"); + todo.add("Cook"); + todo.add("Sleep"); + Assertions.assertTrue(todo.searchTask("Study")); + Assertions.assertTrue(todo.searchTask("Cook")); + Assertions.assertTrue(todo.searchTask("Sleep")); + Assertions.assertFalse(todo.searchTask("Tidy")); + } + + @Test + public void cannotRemoveNonexistentTask() { + TodoList todo = new TodoList(); + Assertions.assertFalse(todo.removeTask("Study")); + } + + @Test + public void removesTaskIfExists() { + TodoList todo = new TodoList(); + todo.add("Study"); + Assertions.assertTrue(todo.removeTask("Study")); + Assertions.assertFalse(todo.searchTask("Study")); + } + + @Test + public void tasksAreDescending() { + TodoList todo = new TodoList(); + todo.add("Cook"); + todo.add("Eat"); + todo.add("Tidy up"); + Assertions.assertEquals( + "Cook: uncompleted", + todo.taskDescending().split("\n")[0]); + Assertions.assertEquals( + "Eat: uncompleted", + todo.taskDescending().split("\n")[1]); + Assertions.assertEquals( + "Tidy up: uncompleted", + todo.taskDescending().split("\n")[2]); + } + + @Test + public void tasksAreAscending() { + TodoList todo = new TodoList(); + todo.add("Cook"); + todo.add("Eat"); + todo.add("Tidy up"); + Assertions.assertEquals( + "Cook: uncompleted", + todo.taskAscending().split("\n")[2]); + Assertions.assertEquals( + "Eat: uncompleted", + todo.taskAscending().split("\n")[1]); + Assertions.assertEquals( + "Tidy up: uncompleted", + todo.taskAscending().split("\n")[0]); + } + + @Test + public void onlyGettingCompletedTasks() { + TodoList todo = new TodoList(); + todo.add("Study"); + todo.add("Cook"); + todo.add("Sleep"); + todo.updateTaskStatus("Sleep", true); + ArrayList completedTasks = todo.getCompletedTasks(); + Assertions.assertTrue(completedTasks.contains("Sleep")); + Assertions.assertFalse(completedTasks.contains("Study")); + Assertions.assertFalse(completedTasks.contains("Cook")); + } + + @Test + public void onlyGettingUncompletedTasks() { + TodoList todo = new TodoList(); + todo.add("Study"); + todo.add("Cook"); + todo.add("Sleep"); + todo.updateTaskStatus("Sleep", true); + ArrayList tasks = todo.getUncompletedTasks(); + Assertions.assertFalse(tasks.contains("Sleep")); + Assertions.assertTrue(tasks.contains("Study")); + Assertions.assertTrue(tasks.contains("Cook")); + } + + @Test + public void firstTaskIdShouldBeValid() { + TodoList todo = new TodoList(); + todo.add("Drink coffee"); + Assertions.assertTrue(-1 < todo.getTaskId("Drink coffee")); + } + + @Test + public void sndTaskIdShouldBeGtr() { + TodoList todo = new TodoList(); + todo.add("Drink coffee"); + todo.add("Start working"); + Assertions.assertTrue( + todo.getTaskId("Drink coffee") + < todo.getTaskId("Start working")); + } + + @Test + public void getByIdReturnsRightTask() { + TodoList todo = new TodoList(); + todo.add("Study"); + todo.add("Cook"); + todo.add("Sleep"); + Assertions.assertEquals("Study", todo.getTaskById(todo.getTaskId("Study")).getName()); + } + + @Test + public void getNonexistentTaskByIdShouldBeNull() { + TodoList todo = new TodoList(); + todo.add("Study"); + todo.add("Cook"); + todo.add("Sleep"); + Assertions.assertNull(todo.getTaskById(todo.getTaskId("Walk"))); + } + + @Test + public void updateNonexistentTaskName() { + TodoList todo = new TodoList(); + Assertions.assertFalse(todo.updateTaskName(0, "Say hi")); + } + + @Test + public void verifyUpdatedTaskName() { + TodoList todo = new TodoList(); + todo.add("Say hi"); + int id = todo.getTaskId("Say hi"); + todo.updateTaskName(id,"Say bye"); + Assertions.assertEquals("Say bye", todo.getTaskById(id).getName()); + } + + @Test + public void updateNonexistentTaskStatus() { + TodoList todo = new TodoList(); + Assertions.assertFalse(todo.updateTaskStatusById(0, true)); + } + + @Test + public void verifyUpdatedTaskStatus() { + TodoList todo = new TodoList(); + todo.add("Write a todo list"); + int id = todo.getTaskId("Write a todo list"); + todo.updateTaskStatusById(id,true); + Assertions.assertTrue((todo.getTaskById(id).isCompleted())); + } +}