KI-Feature 4.5.14: Feld-Diff für geänderte Stunden im AiAssistDialog
Statt Vorschläge nur pauschal als "Neu"/"Geändert" zu markieren, zeigt der Dialog jetzt je geänderter Stunde, was sich konkret unterscheidet (Thema, Datum, Beginn, Stundennummer, Hausaufgabe/Reflexion, Verlaufsplan) — AiPlanningService.DescribeChanges vergleicht bestehende Lesson und KI-Vorschlag feldweise und listet nur echte Unterschiede auf. Granulare Übernahme einzelner Phasen und Schutz vor Überschreiben eigener zwischenzeitlicher Änderungen als 4.5.19 zurückgestellt (größerer Umbau). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -155,15 +155,7 @@ public class AiPlanningService(HttpClient http, ILessonRepository lessons,
|
||||
StartTime = l.StartTime,
|
||||
Homework = l.Homework,
|
||||
Reflection = l.Reflection,
|
||||
Phases = l.Phases.Select(p => new AiPhaseStep
|
||||
{
|
||||
Name = p.Name,
|
||||
DurationMinutes = p.DurationMinutes,
|
||||
Activity = p.Activity,
|
||||
Material = p.Material,
|
||||
Shorthand = p.Shorthand,
|
||||
AlternativePathName = p.AlternativePathId is { } pathId ? pathNames.GetValueOrDefault(pathId) : null,
|
||||
}).ToList(),
|
||||
Phases = ToAiPhases(l.Phases, pathNames),
|
||||
})
|
||||
.ToList();
|
||||
|
||||
@@ -187,6 +179,76 @@ public class AiPlanningService(HttpClient http, ILessonRepository lessons,
|
||||
};
|
||||
}
|
||||
|
||||
private static List<AiPhaseStep> ToAiPhases(List<LessonPhaseStep> phases, Dictionary<Guid, string> pathNames) =>
|
||||
phases.Select(p => new AiPhaseStep
|
||||
{
|
||||
Name = p.Name,
|
||||
DurationMinutes = p.DurationMinutes,
|
||||
Activity = p.Activity,
|
||||
Material = p.Material,
|
||||
Shorthand = p.Shorthand,
|
||||
AlternativePathName = p.AlternativePathId is { } pathId ? pathNames.GetValueOrDefault(pathId) : null,
|
||||
}).ToList();
|
||||
|
||||
private static bool PhasesEqual(List<AiPhaseStep> a, List<AiPhaseStep> b)
|
||||
{
|
||||
if (a.Count != b.Count) return false;
|
||||
for (var i = 0; i < a.Count; i++)
|
||||
{
|
||||
var x = a[i]; var y = b[i];
|
||||
if (x.Name != y.Name || x.DurationMinutes != y.DurationMinutes || x.Activity != y.Activity
|
||||
|| x.Material != y.Material || x.Shorthand != y.Shorthand || x.AlternativePathName != y.AlternativePathName)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Vergleicht eine bestehende Lesson mit dem KI-Vorschlag für dieselbe Id auf Feldebene und
|
||||
/// beschreibt die Unterschiede in kurzen, menschenlesbaren Sätzen — Grundlage für die
|
||||
/// Detailanzeige im AiAssistDialog (4.5.14 Planungsdiff), statt Änderungen nur pauschal als
|
||||
/// "Geändert" zu markieren. Nur echte Unterschiede werden aufgeführt, Felder ohne Änderung
|
||||
/// tauchen nicht auf. Rein (kein I/O außer dem bereits im Speicher gehaltenen Alternativpfad-
|
||||
/// Katalog), daher ohne echtes Deployment testbar.
|
||||
/// </summary>
|
||||
public List<string> DescribeChanges(Lesson existing, AiLesson proposed)
|
||||
{
|
||||
var diffs = new List<string>();
|
||||
|
||||
if (!string.Equals(existing.Topic, proposed.Topic, StringComparison.Ordinal))
|
||||
diffs.Add($"Thema: „{existing.Topic}“ → „{proposed.Topic}“");
|
||||
|
||||
if (proposed.Date is { } date && date != existing.Date)
|
||||
diffs.Add($"Datum: {existing.Date:dd.MM.yyyy} → {date:dd.MM.yyyy}");
|
||||
|
||||
if (proposed.StartTime != existing.StartTime)
|
||||
{
|
||||
var oldText = existing.StartTime?.ToString("HH:mm") ?? "kein Beginn";
|
||||
var newText = proposed.StartTime?.ToString("HH:mm") ?? "kein Beginn";
|
||||
diffs.Add($"Beginn: {oldText} → {newText}");
|
||||
}
|
||||
|
||||
if (proposed.LessonNumber != existing.LessonNumber)
|
||||
diffs.Add($"Stundennummer: {existing.LessonNumber?.ToString() ?? "–"} → {proposed.LessonNumber?.ToString() ?? "–"}");
|
||||
|
||||
if (!string.Equals(existing.Homework, proposed.Homework, StringComparison.Ordinal))
|
||||
diffs.Add("Hausaufgabe geändert");
|
||||
|
||||
if (!string.Equals(existing.Reflection, proposed.Reflection, StringComparison.Ordinal))
|
||||
diffs.Add("Reflexion geändert");
|
||||
|
||||
var pathNames = altPaths.GetAll().ToDictionary(p => p.Id, p => p.Name);
|
||||
var existingPhases = ToAiPhases(existing.Phases, pathNames);
|
||||
if (!PhasesEqual(existingPhases, proposed.Phases))
|
||||
{
|
||||
diffs.Add(existingPhases.Count == proposed.Phases.Count
|
||||
? "Verlaufsplan geändert"
|
||||
: $"Verlaufsplan geändert ({existingPhases.Count} → {proposed.Phases.Count} Phase(n))");
|
||||
}
|
||||
|
||||
return diffs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ersetzt in <paramref name="saved"/> (dem tatsächlichen Datenbankstand) jede Lesson, deren Id
|
||||
/// auch in <paramref name="draft"/> vorkommt, durch die Entwurfsversion, und hängt Entwürfe ohne
|
||||
|
||||
Reference in New Issue
Block a user