@page "/teams/assignment" @using Core.Calculation @using Microsoft.EntityFrameworkCore @using WebApp.Models @using EventAssignment = Core.Calculation.EventAssignment @inject AppDbContext Context @inject NavigationManager NavigationManager Event Assignment - TSA Chapter Organizer Assignment Optimized team assignments based on the student event rankings Edit Student Event Rankings Event Count LOE Assignment Requirements @item.Student.FirstName @item.EventDefinition.ShortName @if (item.Requirement == Requirement.Include) { } @if (item.Requirement == Requirement.Exclude) { } Two Team Events @item.ShortName Omitted Events @item.ShortName Solve Students Student Event Count LOE Sum Warnings @context.Student.FirstName @context.EventCount @context.TotalLevelOfEffort @if (!context.HasOnSiteActivity) { } @if (!context.HasRegionalEvent) { } @{ var allStudentEvents = context.Student.EventRankings .OrderBy(e => e.Rank) .Select(e => e.EventDefinition) .Concat(context.Events) .Distinct(); } @foreach (var e in allStudentEvents .OrderBy(e => context.Student.EventRankings .Find(ser => ser.EventDefinition == e)?.Rank ?? 10)) { var eventRank = context.Student.EventRankings.Find(er => er.EventDefinition == e)?.Rank; var isAssigned = context.Events.Contains(e); var color = AppIcons.RankedEventColor(eventRank ?? 0); var style = string.Empty; if (isAssigned) { style += "border-color:black; border-width:thin;"; if (eventRank.HasValue) { style += $"background:{color};"; if (eventRank == 1) style += $"color:black"; } else style += $"background:{Colors.Gray.Lighten3};"; } else { if (eventRank.HasValue) style += $"border-color:{color}; border-width:medium; color:{Colors.Gray.Lighten1};"; } @e.ShortName  @AppIcons.EventAttributes(e) @{ var isIncluded = _assignmentRequirements .Find(ar => ar.EventDefinition == e && ar.Student == context.Student && ar.Requirement == Requirement.Include) == null; var isExcluded = _assignmentRequirements .Find(ar => ar.EventDefinition == e && ar.Student == context.Student && ar.Requirement == Requirement.Exclude) == null; } @if (isIncluded) { } else { } @if (isExcluded) { } else { } } TimeSlots Team R, # [LB-UB] @{ var thresholds = _eventAssignmentThresholds.First(e => e.Event == context.Event); } @context.Event.Name  @AppIcons.EventEffort(context.Event) @AppIcons.EventAttributes(context.Event) @thresholds.StudentRankingCount, [@thresholds.LowerBound-@thresholds.UpperBound] × @thresholds.TeamCount @if (_eventTwoTeams.Contains(context.Event)) { } else if (thresholds.TeamCount != 2 && context.Event.EventFormat == EventFormat.Team) { } @foreach (var student in context.Students .OrderBy(e => e.EventRankings .Find(er => er.EventDefinition == context.Event)?.Rank ?? 10) .ThenBy(s => s.Grade + s.TsaYear)) { var eventRank = student.EventRankings .Find(e => e.EventDefinition == context.Event)?.Rank; var color = AppIcons.RankedEventColor(eventRank ?? 0); @student.FirstName } Solution status: @_solutionStatus Loading... Save @code { public bool TestSwitch { get; set; } = false; private readonly AssignmentParameters _parameters = new() { RequireOnSite = false, RequireRegional = false }; private List? _events; private List? _students; private List _eventAssignmentThresholds = []; MudTable _teamData; private Team[] _teams = []; MudTable _statisticData; private List _statistics = []; MudTable _assignmentRequirementData; private List _assignmentRequirements = []; MudTable _eventTwoTeamData; private List _eventTwoTeams = []; MudTable _eventOmittedData; private List _eventOmitted = []; private string _solutionStatus = string.Empty; private bool _isSolving = false; protected override async Task OnInitializedAsync() { _events = await Context.Events .OrderBy(e => e.Name) .ToListAsync(); _students = await Context.Students .Where(e => e.FirstName != "test") .Include(e => e.EventRankings) .ThenInclude(e => e.EventDefinition) .Where(e => e.EventRankings.Any()) .OrderBy(e => e.FirstName).ToListAsync(); } private async Task AddTeam() { //Context.TimeSlots.Add(Team); await Context.SaveChangesAsync(); //NavigationManager.NavigateTo("/teams"); } private void Solve() { _teamData.ReloadServerData(); } private async Task> SolveAssignments(TableState arg1, CancellationToken arg2) { _isSolving = true; var eventAssignment = new EventAssignment(_events, _students, _parameters); foreach (var requirement in _assignmentRequirements) { eventAssignment.AddAssignmentRequirement(requirement); } eventAssignment.RemoveEvents(_eventOmitted); eventAssignment.AllowTwoTeams(_eventTwoTeams); var solution = await eventAssignment.Solve(); _solutionStatus = solution.Status; _statistics = StudentEventStatistics.Generate(solution.Teams) .OrderByDescending(s => s.Student.Grade + s.Student.TsaYear) .ThenBy(s => s.Student.FirstName).ToList(); _eventAssignmentThresholds = solution.AssignmentThresholds; await _statisticData.ReloadServerData(); _isSolving = false; await InvokeAsync(StateHasChanged); // let the UI know that the solution has been found _teams = solution.Teams; return new TableData { Items = _teams }; } private async Task> ReloadStatistics(TableState arg1, CancellationToken arg2) { return new TableData {Items = _statistics}; } private async Task> ReloadAssignmentRequirements(TableState arg1, CancellationToken arg2) { return new TableData { Items = _assignmentRequirements }; } private async Task> ReloadEventTwoTeam(TableState arg1, CancellationToken arg2) { return new TableData { Items = _eventTwoTeams }; } private async Task> ReloadOmittedEvents(TableState arg1, CancellationToken arg2) { return new TableData { Items = _eventOmitted }; } private void RequireEvent(EventDefinition evt, Student student, Requirement requirement) { _assignmentRequirements.Add(new AssignmentRequirement(evt, student, requirement)); _assignmentRequirementData.ReloadServerData(); } private void RemoveRequireEvent(EventDefinition evt, Student student, Requirement requirement) { var assignmentRequirement = _assignmentRequirements .Find(ar => ar.EventDefinition == evt && ar.Student == student && ar.Requirement == requirement); if (assignmentRequirement != null) RemoveRequireEvent(assignmentRequirement); } private void RemoveRequireEvent(AssignmentRequirement assignmentRequirement) { _assignmentRequirements.Remove(assignmentRequirement); _assignmentRequirementData.ReloadServerData(); } private void AddTwoTeam(EventDefinition evt) { _eventTwoTeams.Add(evt); _eventTwoTeamData.ReloadServerData(); } private void RemoveTwoTeam(EventDefinition evt) { _eventTwoTeams.Remove(evt); _eventTwoTeamData.ReloadServerData(); } private void AddOmitted(EventDefinition evt) { _eventOmitted.Add(evt); _eventOmittedData.ReloadServerData(); } private void RemoveOmitted(EventDefinition evt) { _eventOmitted.Remove(evt); _eventOmittedData.ReloadServerData(); } public async Task SaveTeams() { var teams = await Context.Teams.ExecuteDeleteAsync(); await Context.Teams.AddRangeAsync(_teams); await Context.SaveChangesAsync(); NavigationManager.NavigateTo("/teams"); } }