Implemented Model

This commit is contained in:
MarcUs7i 2025-04-24 23:34:37 +02:00
parent 9331aaf8d0
commit 8aa236233a
8 changed files with 143 additions and 26 deletions

View file

@ -16,7 +16,20 @@ public sealed class ByHourComparer : ComparerBase, IComparer<Teacher>
public int Compare(Teacher? x, Teacher? y)
{
// TODO
return -1;
int nullCheck = CheckNull(x, y);
if (nullCheck != 2)
{
return nullCheck;
}
// Ignore possibility of null, bc we already checked it above
int dayComparison = CompareEnum(x!.ConsultingHourWeekDay, y!.ConsultingHourWeekDay);
if (dayComparison != 0)
{
return ApplyCorrectDirection(dayComparison);
}
int unitComparison = CompareEnum(x.ConsultingHourUnit, y.ConsultingHourUnit);
return ApplyCorrectDirection(unitComparison);
}
}

View file

@ -16,7 +16,12 @@ public sealed class ByNameComparer : ComparerBase, IComparer<Teacher>
public int Compare(Teacher? x, Teacher? y)
{
// TODO
return -1;
int nullCheck = CheckNull(x, y);
if (nullCheck != 2)
{
return nullCheck;
}
return ApplyCorrectDirection(string.Compare(x!.Name, y!.Name, StringComparison.Ordinal));
}
}

View file

@ -8,7 +8,19 @@ public sealed class ByRoomComparer : IComparer<Teacher>
{
public int Compare(Teacher? x, Teacher? y)
{
// TODO
if (x == null && y == null)
{
return 0;
}
if (x == null)
{
return 1;
}
if (y == null)
{
return -1;
}
return string.Compare(x!.Room, y!.Room, StringComparison.Ordinal);
}
}

View file

@ -19,6 +19,58 @@ public abstract class ComparerBase
/// </summary>
protected bool Ascending { get; }
// TODO: consider moving the basic RefEquals code of CompareTo from the subclasses here
// maybe also rename this to SortOrderComparerBase or something and introduce another, common base class for all three?
/// <summary>
/// Checks if a <see cref="Teacher"/> is null
/// </summary>
/// <param name="x">Teacher x</param>
/// <param name="y">Teacher y</param>
/// <returns>0 if both are null, the comparison if only one is null and 2 if both are NOT null</returns>
protected int CheckNull(Teacher? x, Teacher? y)
{
if (x == null && y == null)
{
return 0;
}
if (x == null)
{
return Ascending ? 1 : -1;
}
if (y == null)
{
return Ascending ? -1 : 1;
}
return 2;
}
/// <summary>
/// Compares the two enums
/// </summary>
/// <param name="x">First enum</param>
/// <param name="y">Second enum</param>
/// <typeparam name="TEnum">Enum Type</typeparam>
/// <returns>The comparison</returns>
protected int CompareEnum<TEnum>(TEnum? x, TEnum? y) where TEnum : struct, Enum
{
if (!x.HasValue && !y.HasValue)
{
return 0;
}
if (!x.HasValue)
{
return -1;
}
if (!y.HasValue)
{
return 1;
}
return x.Value.CompareTo(y.Value);
}
/// <summary>
/// Applies the correct direction
/// </summary>
/// <param name="comparison">The comparison</param>
/// <returns><param name="comparison"> if <see cref="Ascending"/> is true, else returns negated value</param></returns>
protected int ApplyCorrectDirection(int comparison) => Ascending ? comparison : -comparison;
}

View file

@ -35,13 +35,13 @@ public sealed class CsvData
/// Gets a CSV header based on <see cref="HeaderNames" />
/// </summary>
/// <returns>A CSV header line</returns>
public string GetHeader() => null!; // TODO
public string GetHeader() => string.Join(Separator.ToString(), HeaderNames);
/// <summary>
/// Gets a CSV data line based on <see cref="Data" />
/// </summary>
/// <returns>A CSV data line</returns>
public string GetData() => null!; // TODO
public string GetData() => string.Join(Separator.ToString(), Data);
/// <summary>
/// Allows to deconstruct the object into its header and data parts
@ -50,8 +50,7 @@ public sealed class CsvData
/// <param name="data">Set to <see cref="Data" /></param>
public void Deconstruct(out IReadOnlyList<string> headerNames, out IReadOnlyList<string> data)
{
// TODO
headerNames = null!;
data = null!;
headerNames = HeaderNames;
data = Data;
}
}

View file

@ -45,10 +45,25 @@ public class Teacher : ICsvRepresentable
{
get
{
// TODO
return null!;
if (ConsultingHour == null)
{
return null;
}
return ConsultingHourUnit == null ? ConsultingHour.ToString() : $"{ConsultingHour} ({ConsultingHourUnit})";
}
}
public virtual CsvData ToCsvData() => null!; // TODO
public virtual CsvData ToCsvData()
{
List<string> headerNames = ["Name", "Day", "ConsultingHour", "Room"];
List<string> dataLine = [
Name,
ConsultingHourWeekDay?.ToString() ?? string.Empty,
ConsultingHourTime ?? string.Empty,
Room ?? string.Empty
];
var data = new CsvData(headerNames, dataLine);
return data;
}
}

View file

@ -26,7 +26,16 @@ public sealed class TeacherWithBusinessCard : Teacher
public override CsvData ToCsvData()
{
// TODO (remember to maybe use the base implementation...)
return null!;
var data = base.ToCsvData();
(IReadOnlyList<string> headerNamesBase, IReadOnlyList<string> dataLineBase) = data;
var headerNames = (List<string>)headerNamesBase;
var dataLine = (List<string>)dataLineBase;
headerNames.Add("Image");
dataLine.Add($"{BaseUrl}/{Id}");
var csvData = new CsvData(headerNames, dataLine);
return csvData;
}
}

View file

@ -21,18 +21,30 @@ public readonly record struct TimeFrame(TimeOnly Start, TimeOnly End)
/// <returns>True if time frame could be parsed successfully; false otherwise</returns>
public static bool TryParse(string timeFrame, out TimeFrame? result)
{
// TODO
result = null;
string[] timeFrames = timeFrame.Split("-");
if (timeFrames.Length != 2)
{
return false;
}
if (!TimeOnly.TryParse(timeFrames[0], out TimeOnly start) || !TimeOnly.TryParse(timeFrames[1], out TimeOnly end))
{
return false;
}
if (start > end)
{
(start, end) = (end, start);
}
result = new TimeFrame(start, end);
return true;
}
/// <summary>
/// Returns a string representation of the time frame in format HH:MM-HH:MM
/// </summary>
/// <returns></returns>
public override string ToString()
{
// TODO
return null!;
}
public override string ToString() => $"{Start}-{End}";
}