Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b2e75e6
feat: display menu options
Chloe070196 May 22, 2024
245cd7b
feat: TodoItem class
Chloe070196 May 22, 2024
9e8f6f1
feat: TodoList class
Chloe070196 May 22, 2024
1efeb7d
fix: remove irrelevant properties from constructor
Chloe070196 May 22, 2024
78ad50e
feat: implement incremental id
Chloe070196 May 22, 2024
cafb9e4
feat: link todoItem instances
Chloe070196 May 22, 2024
e33afeb
feat: view list
Chloe070196 May 22, 2024
c085aa3
feat: read completion status
Chloe070196 May 22, 2024
c9f23de
feat: log completion status
Chloe070196 May 22, 2024
7c3f50b
fix: prevent reading of property on potentially null object
Chloe070196 May 22, 2024
4a3550f
feat: log exit option on menu
Chloe070196 May 22, 2024
5b43bc7
feat: app listens to input
Chloe070196 May 22, 2024
8c4c737
feat: get command reference number
Chloe070196 May 22, 2024
9c1bfe4
feat: get inputed todo item name
Chloe070196 May 22, 2024
5e2be2d
feat: new todos can be created from the command line
Chloe070196 May 22, 2024
ec2eae6
feat: delete item
Chloe070196 May 22, 2024
5a1d610
feat: option 2 triggers item deletion
Chloe070196 May 22, 2024
f5dbd62
feat: update option 3 action description
Chloe070196 May 22, 2024
b1f71b9
feat: toggle item completion status
Chloe070196 May 22, 2024
02072c7
feat: option 3 triggers item completion status toggle
Chloe070196 May 22, 2024
b2ff1e2
refactor: rename method for clarity
Chloe070196 May 23, 2024
f04cf67
fix: amend return type for GetTodoItemByName
Chloe070196 May 23, 2024
2ba3dc9
feat: handle incorrect names passed as input
Chloe070196 May 23, 2024
eb30b17
docs: comment to categorise todo list methods
Chloe070196 May 23, 2024
bda67b3
feat: return if first check failed
Chloe070196 May 23, 2024
b3e3f40
style: remove empty line
Chloe070196 May 23, 2024
f4479ba
refactor: TodoList implements IEnumerable
Chloe070196 May 28, 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
22 changes: 22 additions & 0 deletions Todo-Challenge/Todo-Challenge/CommandHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Todo_Challenge
{
internal class CommandHandler
{
public static char GetCommandRefNum(string line)
{
return line[0];
}
public static string GetTodoItemName(string line)
{
string lineWithoutRefNum = line.Remove(0, 1);
string name = lineWithoutRefNum.Trim();
return name;
}
}
}
25 changes: 25 additions & 0 deletions Todo-Challenge/Todo-Challenge/Menu.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Todo_Challenge
{
class Menu
{
public static void DisplayOptions()
{
Console.WriteLine("Your current todo list is:");
Console.WriteLine();
Console.WriteLine("To edit it, use the options below");
Console.WriteLine();
Console.WriteLine("OPTIONS");
Console.WriteLine("input: action:");
Console.WriteLine(" 1 <todo name> -> create a new todo");
Console.WriteLine(" 2 <todo name> -> delete a todo");
Console.WriteLine(" 3 <todo name> -> toggle an item's completion status");
Console.WriteLine(" exit -> stop running this app");
}
}
}
32 changes: 30 additions & 2 deletions Todo-Challenge/Todo-Challenge/Program.cs
Original file line number Diff line number Diff line change
@@ -1,2 +1,30 @@
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
using System.Text;
using Todo_Challenge;

new Menu();
Menu.DisplayOptions();

string? line = Console.ReadLine();

var list = new TodoList("Todo list");

while (line != "exit")
{
if (line == null) break;
char refNum = CommandHandler.GetCommandRefNum(line);
string itemName = CommandHandler.GetTodoItemName(line);
switch (refNum)
{
case '1':
new TodoItem(itemName, list);
break;
case '2':
TodoList.DeleteItemWhereNameIs(itemName, list);
break;
case '3':
TodoList.ToggleItemCompletionStatusWhereNameIs(itemName, list);
break;
}
TodoList.View(list);
line = Console.ReadLine();
}
48 changes: 48 additions & 0 deletions Todo-Challenge/Todo-Challenge/TodoItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace Todo_Challenge
{
internal class TodoItem
{
public int Id { get; set; }
public string? Name { get; set; }
public bool Completed { get; set; } = false;
public TodoItem? NextTodoItem { get; set; } = null;

private readonly TodoList _list;

private void LinkToPreviousItem()
{
if (_list.DoesNotContainFirstTodoItem())
{
_list.Head = this;
return;
}
if (_list.Tail != null)
{
_list.Tail.NextTodoItem = this;
}
}

public string ReadCompletionStatus()
{
return Completed ? "done" : "to do";
}

public TodoItem(string name, TodoList todoList)
{
Id = todoList.NextId;
Name = name;
_list = todoList;
todoList.IncreaseNextIdByOne();
LinkToPreviousItem();
todoList.Tail = this;
}
}
}
129 changes: 129 additions & 0 deletions Todo-Challenge/Todo-Challenge/TodoList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace Todo_Challenge
{
internal class TodoList : IEnumerable
{
public string Name;
public TodoItem? Head { get; set; }
public TodoItem? Tail { get; set; }
public TodoItem? Current { get; set; }
public int NextId { get; set; }

IEnumerator IEnumerable.GetEnumerator()
{
Current = Head;

while (Current != null)
{
yield return Current;
Current = Current.NextTodoItem;
}
}


// private retrieval operations executed prior to modifying the list
private static TodoItem? GetTodoItemByName(string name, TodoList todoList)
{
foreach (TodoItem item in todoList)
{
if (item != null && item.Name == name)
{
return item;
}
}
return null;
}

private static TodoItem? GetPreviousTodoItemByName(string name, TodoList todoList)
{
if (todoList.Head != null && todoList.Head.Name == name)
{
return null;
}

foreach (TodoItem item in todoList)
{
if (item != null && item.NextTodoItem != null && item.NextTodoItem.Name == name)
{
return item;
}
}
return null;
}

// is ran upon the start of the application
public TodoList(string name)
{
Name = name;
Head = null;
Tail = null;
Current = null;
NextId = 1;
}

// methods ran when a todo item is created
public void IncreaseNextIdByOne()
{
NextId++;
}

public bool DoesNotContainFirstTodoItem() { return Head == null; }

// method ran after each list modification so the user may visualise the result
public static void View(TodoList todoList)
{
Console.WriteLine();
Console.WriteLine("TODO LIST");
Console.WriteLine();

foreach (TodoItem item in todoList)
{
var isComplete = item.ReadCompletionStatus();
Console.WriteLine(item.Name + " completion status: " + isComplete);
}
}

// list modification operations triggered by commands
public static void DeleteItemWhereNameIs(string name, TodoList todoList)
{
var item = GetTodoItemByName(name, todoList);
if (item == null)
{
Console.WriteLine($"failed to delete ${name}, no such item found");
return;
}
var previousItem = GetPreviousTodoItemByName(name, todoList);
if (previousItem == null)
{
todoList.Head = item.NextTodoItem;
return;
}
else
{
// if I got this right redirecting the pointer is enough to remove
// any references to said item, and set it up for garbage collection (since it becomes unreachable)
previousItem.NextTodoItem = item.NextTodoItem;
}
}

public static void ToggleItemCompletionStatusWhereNameIs(string name, TodoList todoList)
{
var item = GetTodoItemByName(name, todoList);
if (item == null)
{
Console.WriteLine($"failed to toggle completion status of {name}, no such item found");
return;
}
item.Completed = !item.Completed;
}

}
}