ex-col-04-training/exam_cal_mgmt/ExamCalendar/ExamList.cs

180 lines
No EOL
4.9 KiB
C#

namespace ExamCalendar;
/// <summary>
/// Represents a linked list of exams
/// </summary>
public sealed class ExamList
{
private Node? _head;
/// <summary>
/// Gets the number of exams currently stored in the list
/// </summary>
public int Count { get; private set; }
/// <summary>
/// Insert a new exam into the list. Exams are stored sorted by their date.
/// Exams cannot occur on weekends, must have a subject and cannot be null.
/// There also cannot be two exams at the same day.
/// </summary>
/// <param name="exam">Exam to add</param>
/// <returns>True if the exam could be added; false otherwise</returns>
public bool Insert(Exam? exam)
{
if (exam == null || string.IsNullOrEmpty(exam.Subject) ||
exam.Date.DayOfWeek == DayOfWeek.Saturday || exam.Date.DayOfWeek == DayOfWeek.Sunday)
{
return false;
}
var newNode = new Node(exam);
if (_head == null || _head.Data.Date > exam.Date)
{
newNode.Next = _head;
_head = newNode;
Count++;
return true;
}
var current = _head;
while (current != null)
{
if (current.Data.Date == exam.Date)
{
return false;
}
if (current.Next == null || current.Next.Data.Date > exam.Date)
{
newNode.Next = current.Next;
current.Next = newNode;
Count++;
return true;
}
current = current.Next;
}
return false;
}
/// <summary>
/// Returns the exam at the specified position if there is any
/// </summary>
/// <param name="position">Index of the exam in the list</param>
/// <returns>The exam at this position or null if there is none</returns>
public Exam? GetAt(int position)
{
if (position < 0 || position >= Count)
{
return null;
}
var current = _head;
for (int i = 0; i < position && current != null; i++)
{
current = current.Next;
}
return current?.Data;
}
/// <summary>
/// Returns an array containing the exams stored in this list.
/// This array contains the references, not copies.
/// </summary>
/// <returns>An array containing the elements of the list</returns>
public Exam[] ToArray()
{
var array = new Exam[Count];
var current = _head;
int index = 0;
while (current != null)
{
array[index++] = current.Data;
current = current.Next;
}
return array;
}
/// <summary>
/// Returns exams within the specified time frame
/// </summary>
/// <param name="from">Inclusive lower bound</param>
/// <param name="to">Inclusive upper bound</param>
/// <returns>An array of exams which are planned in the specified time frame</returns>
public Exam[] GetTestsInInterval(DateTime from, DateTime to)
{
int count = 0;
var counter = _head;
while (counter != null && counter.Data.Date <= to)
{
if (counter.Data.Date >= from)
{
count++;
}
counter = counter.Next;
}
var results = new Exam[count];
var current = _head;
int index = 0;
while (current != null && index < count)
{
if (current.Data.Date >= from && current.Data.Date <= to)
{
results[index++] = current.Data;
}
current = current.Next;
}
return results;
}
/// <summary>
/// Removes and returns the exam which is planned at the specified date from the list.
/// Exam can only be removed if it exists.
/// </summary>
/// <param name="removeDate">Date of the exam which to remove</param>
/// <param name="removedTest">Reference to the removed exam, if any</param>
/// <returns>True if the exam could be removed; false otherwise</returns>
public bool Remove(DateTime removeDate, out Exam? removedTest)
{
removedTest = null;
if (_head == null)
{
return false;
}
if (_head.Data.Date == removeDate)
{
removedTest = _head.Data;
_head = _head.Next;
Count--;
return true;
}
var current = _head;
while (current.Next != null)
{
if (current.Next.Data.Date == removeDate)
{
removedTest = current.Next.Data;
current.Next = current.Next.Next;
Count--;
return true;
}
current = current.Next;
}
return false;
}
}