using System.Text; using Core.Entities; using Core.Models; namespace GoogleSheetsScheduleImport; /// /// Emits PDF-style section headers Event Name - MS / Event Name - HS before occurrence lines, /// matching competition schedule imports. /// public static class GroupedImportTextEmitter { private readonly struct SectionKey(int eventDefinitionId, SchoolLevel level) : IEquatable { public int EventDefinitionId { get; } = eventDefinitionId; public SchoolLevel Level { get; } = level; public bool Equals(SectionKey other) => EventDefinitionId == other.EventDefinitionId && Level == other.Level; public override bool Equals(object? obj) => obj is SectionKey other && Equals(other); public override int GetHashCode() => HashCode.Combine(EventDefinitionId, Level); } public static string Build( IReadOnlyList<(string SheetTitle, string SectionHeader, List Lines)> sheets, IReadOnlyList matchableEvents, int year) { var idToDef = matchableEvents.Where(e => e.Id != 0).ToDictionary(e => e.Id); var sb = new StringBuilder(); foreach (var (sheetTitle, _, lines) in sheets) { sb.AppendLine($"# {sheetTitle}"); var general = new List(); var bySection = new Dictionary>(); foreach (var line in lines) { if (!OccurrenceEventMatcher.TryMatch(line.Name, matchableEvents, out var evt, out var lvl) || evt == null || !lvl.HasValue) { general.Add(line); continue; } var key = new SectionKey(evt.Id, lvl.Value); if (!bySection.TryGetValue(key, out var list)) { list = []; bySection[key] = list; } list.Add(line); } foreach (var key in bySection.Keys.OrderBy(k => HeaderSortKey(idToDef, k), StringComparer.OrdinalIgnoreCase)) { if (!idToDef.TryGetValue(key.EventDefinitionId, out var def)) continue; sb.AppendLine($"{def.Name} - {SchoolLevelPrefixParser.ToSectionSuffix(key.Level)}"); foreach (var line in OccurrenceChronologicalSort.Sort(bySection[key], year)) { var displayName = OccurrenceDisplayNameReducer.ReduceForSection(line.Name, def, key.Level); sb.AppendLine(ImportLineFormatter.FormatOccurrenceLine(line with { Name = displayName })); } } if (general.Count > 0) { sb.AppendLine("General Schedule"); foreach (var line in OccurrenceChronologicalSort.Sort(general, year)) sb.AppendLine(ImportLineFormatter.FormatOccurrenceLine(line)); } sb.AppendLine(); } return sb.ToString().TrimEnd(); } private static string HeaderSortKey(Dictionary idToDef, SectionKey key) { if (!idToDef.TryGetValue(key.EventDefinitionId, out var def)) return $"{key.EventDefinitionId} - {key.Level}"; return $"{def.Name} - {SchoolLevelPrefixParser.ToSectionSuffix(key.Level)}"; } }