From 9be546d25f6760a9a2104f3a29d1e9e7f5750798 Mon Sep 17 00:00:00 2001 From: Elias Fierke Date: Sun, 7 Jun 2026 20:19:54 +0200 Subject: [PATCH] [feat:] overview of generated courses (pdf) --- PdfExportUtility.cs | 102 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/PdfExportUtility.cs b/PdfExportUtility.cs index 1a8b8ef..5365dae 100644 --- a/PdfExportUtility.cs +++ b/PdfExportUtility.cs @@ -38,6 +38,8 @@ public static class PdfExportUtility return; } + RenderCoursesOverview(document, courses); + var studentsById = Settings.Instance.Students .GroupBy(student => student.ID, StringComparer.OrdinalIgnoreCase) .ToDictionary(group => group.Key, group => group.First(), StringComparer.OrdinalIgnoreCase); @@ -109,7 +111,7 @@ public static class PdfExportUtility 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); y += 24; } @@ -178,6 +180,104 @@ public static class PdfExportUtility 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(); + 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( PdfDocument document, (int Semester, CourseCrafter.CourseInstance Instance) course,