[feat:] overview of generated courses (pdf)

This commit is contained in:
2026-06-07 20:19:54 +02:00
parent 2910b1aeda
commit 9be546d25f
+101 -1
View File
@@ -38,6 +38,8 @@ public static class PdfExportUtility
return; return;
} }
RenderCoursesOverview(document, courses);
var studentsById = Settings.Instance.Students var studentsById = Settings.Instance.Students
.GroupBy(student => student.ID, StringComparer.OrdinalIgnoreCase) .GroupBy(student => student.ID, StringComparer.OrdinalIgnoreCase)
.ToDictionary(group => group.Key, group => group.First(), StringComparer.OrdinalIgnoreCase); .ToDictionary(group => group.Key, group => group.First(), StringComparer.OrdinalIgnoreCase);
@@ -109,7 +111,7 @@ public static class PdfExportUtility
if (pageIndex == 0) if (pageIndex == 0)
{ {
gfx.DrawString("Inkludiert nur SuS, die in mindestens einem Semester keine Zuordnung erhalten haben.", gfx.DrawString("Es werden nur Schülerinnen und Schüler aufgeführt, die in mindestens einem Semester keine Zuordnung erhalten haben.",
subtitleFont, XBrushes.Gray, new XRect(Margin, y, contentWidth, 20), XStringFormats.TopLeft); subtitleFont, XBrushes.Gray, new XRect(Margin, y, contentWidth, 20), XStringFormats.TopLeft);
y += 24; y += 24;
} }
@@ -178,6 +180,104 @@ public static class PdfExportUtility
DrawFooter(gfx, page); DrawFooter(gfx, page);
} }
private static void RenderCoursesOverview(
PdfDocument document,
IReadOnlyList<(int Semester, CourseCrafter.CourseInstance Instance)> courses)
{
var overviewFont = new XFont(FontFamily, 18, XFontStyleEx.Bold);
var subtitleFont = new XFont(FontFamily, 10, XFontStyleEx.Regular);
var tableHeaderFont = new XFont(FontFamily, 9, XFontStyleEx.Bold);
var tableBodyFont = new XFont(FontFamily, 8.5, XFontStyleEx.Regular);
int count = 0;
var coursesPerSemester = courses
.GroupBy(course => course.Semester)
.ToDictionary(group => group.Key, group => group.Count());
var courseIndexBySemester = new Dictionary<int, int>();
var rows = courses.Select(course =>
{
count++;
var key = course.Semester;
courseIndexBySemester.TryGetValue(key, out var index);
index++;
courseIndexBySemester[key] = index;
return new[]
{
count.ToString(),
course.Semester.ToString(),
course.Instance.Sport.Name,
$"{index}/{coursesPerSemester[key]}",
course.Instance.Students.Count.ToString()
};
}).ToList();
var columns = new[] { 50.0, 70.0, 150.0, 150.0, 100.0 };
var headerRow = new[]
{
"Nr.",
"Semester",
"Sportart",
"Kurs (Semester)",
"Anzahl SuS"
};
int rowIndex = 0;
int pageIndex = 0;
while (rowIndex < rows.Count || pageIndex == 0)
{
var page = document.AddPage();
ConfigurePage(page);
using var gfx = XGraphics.FromPdfPage(page);
double pageWidth = page.Width.Point;
double pageHeight = page.Height.Point;
double contentWidth = pageWidth - (Margin * 2);
double contentBottom = pageHeight - Margin - FooterHeight;
double y = Margin;
var headerTitle = pageIndex == 0
? "Übersicht generierter Kurse"
: "Fortsetzung: Übersicht generierter Kurse";
gfx.DrawString(headerTitle, overviewFont, XBrushes.Black,
new XRect(Margin, y, contentWidth, 24), XStringFormats.TopLeft);
y += 26;
if (pageIndex == 0)
{
gfx.DrawString("Tabellarische Übersicht aller generierten Kurse nach Semester und Sportart.",
subtitleFont, XBrushes.Gray, new XRect(Margin, y, contentWidth, 20), XStringFormats.TopLeft);
y += 24;
}
y += DrawTableRow(gfx, y, columns, headerRow, tableHeaderFont, fillHeader: true);
while (rowIndex < rows.Count)
{
var row = rows[rowIndex];
double rowHeight = MeasureRowHeight(gfx, columns, row, tableBodyFont);
if (y + rowHeight > contentBottom)
break;
y += DrawTableRow(gfx, y, columns, row, tableBodyFont, fillHeader: false);
rowIndex++;
}
DrawFooter(gfx, page);
pageIndex++;
if (rowIndex >= rows.Count)
break;
}
}
private static void RenderCourse( private static void RenderCourse(
PdfDocument document, PdfDocument document,
(int Semester, CourseCrafter.CourseInstance Instance) course, (int Semester, CourseCrafter.CourseInstance Instance) course,