180 lines
No EOL
4.9 KiB
C#
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;
|
|
}
|
|
} |