Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d95d684
Finished domain model
Aug 7, 2025
4349e53
Completes first two user stories and updates domain model
Aug 7, 2025
8046607
Small bug fix
Aug 7, 2025
0a46f54
Change list of tasks to a dictionary
Aug 7, 2025
832c9e8
Minor adjustments
Aug 7, 2025
b26a59d
Adds tests for ToggleComplete
Aug 7, 2025
028a647
Implements complete status for tasks
Aug 7, 2025
88e5405
Adds tests and implementation for getting all complete and incomplete…
Aug 7, 2025
77763a5
Minor updates
Aug 7, 2025
ad5a495
Tests and implements search by name
Aug 7, 2025
3a12959
Tests and implements task removal
Aug 7, 2025
2383828
Tests and implements sorting (ascending and descending)
Aug 7, 2025
58d289d
Tests and implements giving priority to specified task
Aug 7, 2025
6ebd276
Tests and implements sorting by priority, and switch to numeric prior…
Aug 7, 2025
9cb3aa8
Tests and implements retrieval by ID
Aug 8, 2025
271c2f0
Adds support for nonexisting ID
Aug 8, 2025
28f9ca5
Tests and implements name update
Aug 8, 2025
662b741
Tests and implements toggle status by id and name
Aug 8, 2025
78b52f4
Separates core and extension tests
Aug 8, 2025
e4cdbab
Tests and implements get all time created
Aug 8, 2025
8f50471
Tests and implements list of task completion time
Aug 8, 2025
6f11863
Tests and implements getting task with shortest completion time
Aug 8, 2025
85e0a5b
Tests and implements get tasks with completion time higher than a giv…
Aug 8, 2025
6190a8f
Tests and implements setting category of specific task
Aug 8, 2025
1e6b647
Tests and implements list with tasks corresponding to specified category
Aug 8, 2025
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
24 changes: 24 additions & 0 deletions domain-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Domain Model

|Classes|Method/Properties|Scenario|Outputs|
|-------|-----------------|--------|-------|
|`TodoList`|`AddTask(string name)`|Add task with name to todo list| int ID of new task|
|`TodoList`|`TodoList.Tasks`|Provide all tasks in todo list | Dictionary<int, Task> |
|`TodoList`|`ToggleComplete(string name)` | Toggle status of give task from complete to incomplete or incomplete to complete| bool |
|`TodoList`|`GetCompleteTasks()`| Provide all complete tasks in todo list | List<Task>|
|`TodoList`|`GetIncompleteTasks()`| Provide all incomplete tasks in todo list | List<Task>|
|`TodoList`|`GetTaskByName(string name)`| Search for Task with given name | Task, provide message if not found |
|`TodoList`|`RemoveTask(string name)` | Remove task with given name from TodoList | bool |
|`TodoList`|`GetAllTasksSortedByName(bool useAscendingOrder)` | Return sorted version of tasks by name, either ascending or descending alphabetical order, to user | Sorted List<Task>|
|`TodoList`|`GiveTaskPriority(string name, int priority)` | Add priority (1, 2, 3) to a given task | bool |
|`TodoList`|`SortTasksByPriority()` | Return sorted version of tasks sorted by priority | Sorted List<Taks> |
|`TodoList`|`GetTaskByID(int id)` | Provide task with given id | Task |
|`TodoList`|`UpdateTaskName(int id, string newName)` | Update the name of a task with given id | bool |
|`TodoList`|`UpdateTaskStatus(int id)` | Toggle the status of task with given ID | bool |
|`TodoList`|`GetAllTaskTimeCreated()` | Provide all tasks along with time of creation | (List<Task>, datetime) |
|`TodoList`|`GetAllTaskTimeCompleted()` | Provide all tasks along with time of completion | (List<Task>, datetime) |
|`TodoList`|`GetTaskWithLongestCompletionTime()` | Provide the task with the longest completion time | `Task` |
|`TodoList`|`GetTaskWithShortestCompletionTime()` | Provide the task with the shortest completion time | `Task` |
|`TodoList`|`GetTasksByCompletionTime(int numDaysToComplete)` | Provide all tasks with completion time longer than given time | List<Task> |
|`TodoList`| `SetTaskCategory(string name, string category)` | Set category of task | bool |
|`TodoList`|`GetTasksByCategory(string category)` | Get all tasks matching the given category | List<Task> |
43 changes: 43 additions & 0 deletions tdd-todo-list.CSharp.Main/Task.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace tdd_todo_list.CSharp.Main
{
public class Task
{
private string _name;
private int _id;
private bool _isCompleted = false;
private int _priority = 3;
private string _category = String.Empty;
private DateTime _timeCreated;
private DateTime _timeCompleted;
private int? _completionTime = null;

public Task(int count, string name)
{
_id = count;
_name = name;
_timeCreated = DateTime.Today;
}

public void CalculateCompletionTime()
{
if (IsCompleted) {
_completionTime = (int)(_timeCompleted - _timeCreated).TotalDays;
}
}

public string Name { get { return _name; } set { _name = value; } }
public int ID { get { return _id; } }
public bool IsCompleted { get { return _isCompleted; } set { _isCompleted = value; } }
public int Priority { get { return _priority; } set { _priority = value; } }
public DateTime TimeCreated { get { return _timeCreated; } set { _timeCreated = value;} }
public DateTime TimeCompleted { get { return _timeCompleted; } set { _timeCompleted = value; } }
public int? CompletionTime { get { return _completionTime; } }
public string Category { get { return _category; } set { _category = value; } }
}
}
254 changes: 254 additions & 0 deletions tdd-todo-list.CSharp.Main/ToDoList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,259 @@
{
public class TodoList
{
private Dictionary<int, Task> _tasks = new Dictionary<int, Task>();
private int _taskCount = 0;

public Dictionary<int, Task> Tasks { get { return _tasks; } }
public int TaskCount { get { return _taskCount; } }

public void AddTask(string name)
{
Task newTask = new Task(_taskCount, name);
_tasks.Add(_taskCount, newTask);
_taskCount++;
}

public bool ToggleComplete(string taskName)
{
Task? task = GetTaskByName(taskName);
if (task != null) {
task.IsCompleted = !task.IsCompleted;
task.TimeCompleted = DateTime.Today;
return true;
}
return false;
}

public List<Task> GetCompleteTasks()
{
List<Task> completeTasks = new List<Task>();
foreach (Task task in _tasks.Values) {
if (task.IsCompleted)
{
completeTasks.Add(task);
}
}
return completeTasks;
}

public List<Task> GetIncompleteTasks()
{
List<Task> incompleteTasks = new List<Task>();
foreach (Task task in _tasks.Values)
{
if (!task.IsCompleted)
{
incompleteTasks.Add(task);
}
}
return incompleteTasks;
}

public Task? GetTaskByName(string taskName)
{
Task? resultTask = null;
foreach (KeyValuePair<int, Task> task in _tasks)
{
if (task.Value.Name == taskName)
{
resultTask = task.Value;
break;
}
}

if (resultTask == null)
{
Console.WriteLine($"Task {taskName} not found");
}

return resultTask;
}

public bool RemoveTask(string taskName)
{
Task? task = GetTaskByName(taskName);

if (task == null)
{
return false;
}

return _tasks.Remove(task.ID);

}

public List<Task> GetAllTasksSortedByName(bool useAscendingOrder)
{
if (useAscendingOrder)
{
return _tasks.Values.OrderBy(task => task.Name).ToList();
}
return _tasks.Values.OrderByDescending(task => task.Name).ToList();

}

public bool GiveTaskPriority(string taskName, int priority)
{
Task? task = GetTaskByName(taskName);
if (task == null)
{
return false;
}
task.Priority = priority;
return true;
}

public List<Task> SortTasksByPriority()
{
return _tasks.Values.OrderBy(task => task.Priority).ToList();
}

public Task? GetTaskByID(int taskID)
{
if (_tasks.ContainsKey(taskID))
{
return _tasks[taskID];
}
return null;
}

public bool UpdateTaskName(int taskID, string newName)
{
if (_tasks.ContainsKey(taskID))
{
_tasks[taskID].Name = newName;
return true;
}
return false;
}

public bool UpdateTaskStatus(int taskID)
{
if (_tasks.ContainsKey(taskID))
{
_tasks[taskID].IsCompleted = !_tasks[taskID].IsCompleted;
return true;
}
return false;
}

public List<(Task, DateTime)> GetAllTaskTimeCreated()
{
List<(Task, DateTime)> timeCreatedList = new List<(Task, DateTime)> ();
foreach (Task task in _tasks.Values)
{
timeCreatedList.Add((task, task.TimeCreated));
}
return timeCreatedList;
}

public List<(Task, DateTime)> GetAllTaskTimeCompleted()
{
List<(Task, DateTime)> timeCompletedList = new List<(Task, DateTime)> ();
foreach (Task task in _tasks.Values)
{
if (task.IsCompleted)
{
timeCompletedList.Add((task, task.TimeCompleted));
}
}
return timeCompletedList;
}

public Task GetTaskWithLongestCompletionTime()
{
int longestCompletionTime = 0;
Task? longestCompletionTask = null;
List<(Task, DateTime)> completedTaskList = GetAllTaskTimeCompleted();
foreach ((Task, DateTime) listItem in completedTaskList)
{
Task task = listItem.Item1;
if (task.CompletionTime == null)
{
task.CalculateCompletionTime();
}
if (task.CompletionTime > longestCompletionTime)
{
longestCompletionTime = (int)task.CompletionTime;
longestCompletionTask = task;
}

}
return longestCompletionTask!;

}

public Task GetTaskWithShortestCompletionTime()
{
// Assuming no completion times will exceed 100 days
int shortestCompletionTime = 100;
Task? shortestCompletionTask = null;
List<(Task, DateTime)> completedTaskList = GetAllTaskTimeCompleted();
foreach ((Task, DateTime) listItem in completedTaskList)
{
Task task = listItem.Item1;
if (task.CompletionTime == null)
{
task.CalculateCompletionTime();
}
if (task.CompletionTime < shortestCompletionTime)
{
shortestCompletionTime = (int)task.CompletionTime;
shortestCompletionTask = task;
}

}
return shortestCompletionTask!;
}

public List<Task> GetTasksByCompletionTime(int daysLimit)
{
List<Task> tasks = new List<Task>();
List<(Task, DateTime)> completedTaskList = GetAllTaskTimeCompleted();
foreach ((Task, DateTime) listItem in completedTaskList)
{
Task task = listItem.Item1;
if (task.CompletionTime == null)
{
task.CalculateCompletionTime();
}
if (task.CompletionTime > daysLimit)
{
tasks.Add(task);
}
}
return tasks;

}

public bool SetTaskCategory(string taskName, string category)
{
Task task = GetTaskByName(taskName);

Check warning on line 239 in tdd-todo-list.CSharp.Main/ToDoList.cs

View workflow job for this annotation

GitHub Actions / build

Converting null literal or possible null value to non-nullable type.

Check warning on line 239 in tdd-todo-list.CSharp.Main/ToDoList.cs

View workflow job for this annotation

GitHub Actions / build

Converting null literal or possible null value to non-nullable type.

Check warning on line 239 in tdd-todo-list.CSharp.Main/ToDoList.cs

View workflow job for this annotation

GitHub Actions / build

Converting null literal or possible null value to non-nullable type.

Check warning on line 239 in tdd-todo-list.CSharp.Main/ToDoList.cs

View workflow job for this annotation

GitHub Actions / build

Converting null literal or possible null value to non-nullable type.

if (task == null) {
return false;
}

task.Category = category;
return true;

}

public List<Task> GetTasksByCategory(string category)
{
List<Task > tasks = new List<Task>();
foreach (Task task in _tasks.Values)
{
if (task.Category == String.Empty)
{
continue;
}
if (task.Category == category) {
tasks.Add(task);
}
}
return tasks;
}
}
}
Loading
Loading