feat: Anhänge je Stunde, Klausur-Sitzplan mischen, Gefährdungsbeurteilungs-Assistent
Lesson bekommt dieselbe Anhang-Infrastruktur wie Documentation (Material, Arbeitsblätter, Experimentunterlagen), samt Fix einer Sync-Lücke, die Anhang- Dateibytes bisher nur für Documentation statt generisch übertragen hat (IHasAttachments). Sitzplan-Tab bekommt einen "Plätze mischen"-Button für Klausursitzpläne. Neu: mehrschrittiger Gefährdungsbeurteilungs-Assistent mit optionalem KI-Entwurf (ai-backend/gbu.php) und PDF-Export, Format bewusst als JSON-Anhang statt eigener Datenbank-Entität. Details und Architekturentscheidungen in TODO.md (4.2, 7.1.5, 10.1.8). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -398,6 +398,40 @@ public partial class SeatingPlanTabViewModel : ObservableObject
|
||||
ReloadPlans();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Klausur-Sitzplan mischen (14, Nutzer-Idee): erzeugt aus dem aktuell gewählten Plan einen
|
||||
/// neuen, unabhängigen Plan mit gleichem Raster/Raum, aber zufällig vertauschten Insassen der
|
||||
/// belegten Plätze (Fisher-Yates via <see cref="Random.Shared"/>) — die Platzkoordinaten selbst
|
||||
/// bleiben unverändert, nur wer wo sitzt wird neu gewürfelt. Der ursprüngliche Plan bleibt
|
||||
/// unangetastet erhalten, damit er bei Bedarf für den nächsten regulären Unterricht weiter
|
||||
/// genutzt werden kann.
|
||||
/// </summary>
|
||||
[RelayCommand(CanExecute = nameof(CanEditSelected))]
|
||||
private void ShuffleSeats()
|
||||
{
|
||||
if (_currentPlan is null) return;
|
||||
|
||||
var studentIds = _currentPlan.Assignments.Select(a => a.StudentId).ToArray();
|
||||
Random.Shared.Shuffle(studentIds);
|
||||
|
||||
var shuffled = new SeatingPlan
|
||||
{
|
||||
GroupId = _currentPlan.GroupId,
|
||||
Name = $"{_currentPlan.Name} (Klausur gemischt {DateTime.Now:dd.MM. HH:mm})",
|
||||
Room = _currentPlan.Room,
|
||||
Rows = _currentPlan.Rows,
|
||||
Columns = _currentPlan.Columns,
|
||||
ColumnGapWidths = [.. _currentPlan.ColumnGapWidths],
|
||||
IsBoardAtBottom = _currentPlan.IsBoardAtBottom,
|
||||
HiddenSeats = _currentPlan.HiddenSeats.Select(h => new HiddenSeat { Row = h.Row, Column = h.Column }).ToList(),
|
||||
Assignments = _currentPlan.Assignments
|
||||
.Select((a, i) => new SeatAssignment { Row = a.Row, Column = a.Column, StudentId = studentIds[i] })
|
||||
.ToList(),
|
||||
};
|
||||
_plans.Save(shuffled);
|
||||
ReloadPlans(shuffled.Id);
|
||||
}
|
||||
|
||||
partial void OnIsEditModeChanged(bool value)
|
||||
{
|
||||
OnPropertyChanged(nameof(CanEditLayout));
|
||||
@@ -417,6 +451,7 @@ public partial class SeatingPlanTabViewModel : ObservableObject
|
||||
AddPlanCommand.NotifyCanExecuteChanged();
|
||||
EditPlanCommand.NotifyCanExecuteChanged();
|
||||
DeletePlanCommand.NotifyCanExecuteChanged();
|
||||
ShuffleSeatsCommand.NotifyCanExecuteChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user