Files
poprhythmandCursor 3712dba974 feat: merge event rankings and attribute badges into the page printer
Interview notes can print each student's ranked events and a shared attribute legend from the same catalog as the ranking index, without leftover table markup or collapsed answer space.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-30 23:03:10 -04:00

90 lines
3.0 KiB
C#

using Core.Entities;
namespace Core.Printing;
/// <summary>
/// Ranking-index style badges: colored rank dot plus a short label.
/// Student pages list ranked events; event pages list students who ranked them.
/// </summary>
public static class PrintRankBadgeHtml
{
public static string ForStudentEvents(IEnumerable<StudentEventRanking>? rankings)
{
if (rankings is null)
return string.Empty;
var badges = rankings
.Where(r => r.Rank is >= 1 and <= StudentEventRanking.MaxRank)
.OrderBy(r => r.Rank)
.Select(EventBadge)
.ToList();
return Wrap(badges);
}
public static string ForEventStudents(IEnumerable<StudentEventRanking>? rankings)
{
if (rankings is null)
return string.Empty;
var badges = rankings
.Where(r => r.Student is not null && r.Rank is >= 1 and <= StudentEventRanking.MaxRank)
.OrderBy(r => r.Rank)
.ThenByDescending(r => r.Student.Grade + r.Student.TsaYear)
.Select(r => StudentBadge(r.Student.FirstName, r.Rank))
.ToList();
return Wrap(badges);
}
internal static string EventBadge(StudentEventRanking ranking)
{
var evt = ranking.EventDefinition;
var label = !string.IsNullOrWhiteSpace(evt?.ShortName)
? evt.ShortName
: evt?.Name;
var attributes = EventAttributeMarks.For(evt);
var attrsHtml = string.IsNullOrEmpty(attributes)
? string.Empty
: $"<span class=\"print-event-attrs\">{PrintTokenMap.EscapeHtml(attributes)}</span>";
return Badge(ranking.Rank, PrintTokenMap.EscapeHtml(label), attrsHtml);
}
internal static string StudentBadge(string? firstName, int rank) =>
Badge(rank, PrintTokenMap.EscapeHtml(firstName), string.Empty);
private static string Badge(int rank, string labelHtml, string extraHtml)
{
var extra = string.IsNullOrEmpty(extraHtml) ? string.Empty : $" {extraHtml}";
return
$"<span class=\"print-rank-badge\">" +
$"<span class=\"print-rank-dot event-rank-{rank}\"></span> " +
$"{labelHtml}{extra}" +
"</span>";
}
public static string Legend()
{
var marks = EventAttributeMarks.LegendItems
.Select(mark =>
"<span class=\"print-legend-mark\">" +
$"<span class=\"print-event-attrs\">{PrintTokenMap.EscapeHtml(mark.Symbol)}</span> " +
PrintTokenMap.EscapeHtml(mark.Label) +
"</span>");
return
"<div class=\"print-badge-legend\">" +
$"<div class=\"print-attr-legend\">{string.Join(" &middot; ", marks)}</div>" +
"</div>";
}
private static string Wrap(IReadOnlyList<string> badges, string separator = " ")
{
if (badges.Count == 0)
return string.Empty;
return $"<div class=\"print-rank-badges\">{string.Join(separator, badges)}</div>";
}
}