first commit

This commit is contained in:
2025-08-01 14:10:44 -04:00
commit cf32cfcbcd
149 changed files with 80416 additions and 0 deletions
+356
View File
@@ -0,0 +1,356 @@
using System.Diagnostics;
using System.Text.Json;
using System.Text.RegularExpressions;
using Core.Calculation;
using Core.Entities;
using Core.Parsers;
using Core.Utility;
using Microsoft.AspNetCore.Mvc;
using Web.Models;
namespace Web.Controllers
{
public partial class HomeController : Controller
{
private const string ContentDirectory = @"C:\Users\james\source\TSA Chapter Organizer\Tests\Parsers\TestInput\";
private CompetitiveEvent[] GetCompetitiveEvents()
{
var fileInfo = FileUtility.GetContentFile(ContentDirectory, "2024-25 RMS TSA student & event - Event Definitions.csv");
var eventRankingsParser = new EventDefinitionParser(fileInfo);
return eventRankingsParser.Parse();
}
private Student[] GetStudents(IList<CompetitiveEvent> events)
{
var fileInfo = FileUtility.GetContentFile(ContentDirectory, "2024-25 RMS TSA student & event - Nationals Student Event Rankings.csv");
var eventRankingsParser = new StudentParser(fileInfo);
return eventRankingsParser.Parse(events);
}
public Team[] GetTeams(IList<CompetitiveEvent> competitiveEvents, IList<Student> students)
{
var studentEventRankingsCsv = "2024-25 RMS TSA student & event - Nationals Teams.csv";
var fileInfo = FileUtility.GetContentFile(ContentDirectory, studentEventRankingsCsv);
var eventRankingsParser = new TeamParser(fileInfo);
var teams = eventRankingsParser.Parse(competitiveEvents, students);
foreach (var student in students)
{
student.Teams = teams.Where(t => t.Students.Contains(student)).ToList();
}
return teams;
}
public AssignmentAssumption[] GetAssignmentAssumptions(IList<CompetitiveEvent> competitiveEvents, IList<Student> students)
{
var assumptionsCsv = "2024-25 RMS TSA student & event - assumptions.csv";
var fileInfo = FileUtility.GetContentFile(ContentDirectory, assumptionsCsv);
var assumptionParser = new AssignmentAssumptionParser(fileInfo);
var assumptions = assumptionParser.Parse(competitiveEvents, students);
return assumptions;
}
public IDictionary<CompetitiveEvent, List<EventOccurrence>> GetStateEventOccurrences(IList<CompetitiveEvent> competitiveEvents)
{
var eventTimesFilename = "2025 TN TSA State Competition Event Times.txt";
var fileInfo = FileUtility.GetContentFile(ContentDirectory, eventTimesFilename);
var parser = new EventOccurrenceParser(fileInfo, competitiveEvents);
return parser.Parse();
}
public IDictionary<CompetitiveEvent, List<EventOccurrence>> GetNationalEventOccurrences(IList<CompetitiveEvent> competitiveEvents)
{
var eventTimesFilename = "2025 TSA Nationals Competition Event Times.txt";
var fileInfo = FileUtility.GetContentFile(ContentDirectory, eventTimesFilename);
var parser = new EventOccurrenceParser(fileInfo, competitiveEvents);
var nationalEventOccurrences = parser.Parse();
var locationPrefixes = new[] { "Cheekwood", "Ryman", "Lincoln", "Canal", "Online", "Magnolia", "Tennessee", "Bayou", "Hermitage", "Belmont", "Davidson", "Washington", "Belle Meade"};
var oredLocations = string.Join("|", locationPrefixes);
var regex = new Regex($"^(.*)((?:{oredLocations}).*)");
foreach (var occurrence in nationalEventOccurrences)
{
foreach (var eventOccurrence in occurrence.Value)
{
if (!string.IsNullOrEmpty(eventOccurrence.Location))
continue;
var match = regex.Match(eventOccurrence.Name);
if (!match.Success)
continue;
eventOccurrence.Name = match.Groups[1].Value.Trim();
eventOccurrence.Location = match.Groups[2].Value.Trim();
}
}
return nationalEventOccurrences;
}
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
return View();
}
public IActionResult Events()
{
var competitiveEvents = GetCompetitiveEvents().Where(e => e.Name != "Chapter Team").ToArray();
return View(competitiveEvents);
}
public IActionResult StudentEventHandout()
{
var competitiveEvents = GetCompetitiveEvents();
var students = GetStudents(competitiveEvents);
var teams = GetTeams(competitiveEvents, students);
return View(Tuple.Create(students));
}
public IActionResult StudentEvents()
{
var competitiveEvents = GetCompetitiveEvents();
var students = GetStudents(competitiveEvents);
var eventStudentPicksArray = DataProcessing.GetEventStudentPicks(competitiveEvents, students);
var assignmentParameters = new AssignmentParameters
{
EffortUpperBound = 9,
RequireOnSite = true,
RequireRegional = true,
TeamSizeLimit = 4
};
var eventAssignment = new EventAssigner(competitiveEvents, students, assignmentParameters);
var assignmentAssumptions = GetAssignmentAssumptions(competitiveEvents, students);
foreach (var assumption in assignmentAssumptions)
{
switch (assumption.Assumption)
{
case Assumption.Exclude:
eventAssignment.ExcludeFromEvent(assumption.EventAssignment);
break;
case Assumption.Include:
eventAssignment.AssignToEvent(assumption.EventAssignment);
break;
}
}
eventAssignment.RemoveEvent(new List<CompetitiveEvent>
{
competitiveEvents.First(e => e.Name == "Chapter Team")
});
eventAssignment.IncludedEvents(new List<CompetitiveEvent>
{
//competitiveEvents.First(e => e.Name == "System Control Technology")
});
var eventAssignmentsList = eventAssignment.Solve();
return View(Tuple.Create(competitiveEvents, students, eventStudentPicksArray, eventAssignmentsList, assignmentParameters));
}
public IActionResult Teams()
{
var competitiveEvents = GetCompetitiveEvents();
var students = GetStudents(competitiveEvents);
var teams = GetTeams(competitiveEvents, students);
//teams = teams.Where(t => t.Event.RegionalEvent).ToArray();
return View(Tuple.Create(teams));
}
public IActionResult Regionals()
{
var competitiveEvents = GetCompetitiveEvents();
var students = GetStudents(competitiveEvents);
var teams = GetTeams(competitiveEvents, students);
teams = teams.Where(t => t.Event.RegionalEvent).ToArray();
var enumerable = students.Where(s => !teams.SelectMany(ts => ts.Students).Contains(s)).ToArray();
return View(Tuple.Create(teams, enumerable));
}
public IActionResult State()
{
var competitiveEvents = GetCompetitiveEvents();
var students = GetStudents(competitiveEvents);
var teams = GetTeams(competitiveEvents, students);
var eventOccurrences = GetStateEventOccurrences(competitiveEvents);
// Filter out pre-conference
eventOccurrences =
(from kv in eventOccurrences
let newV = kv.Value.Where(eo => !eo.Name.Contains("Pre-Conference"))
select Tuple.Create(kv.Key, newV))
.ToDictionary(s => s.Item1, s => s.Item2.ToList());
return View(Tuple.Create(teams, students, eventOccurrences));
}
public IActionResult Nationals()
{
var competitiveEvents = GetCompetitiveEvents();
var students = GetStudents(competitiveEvents);
var teams = GetTeams(competitiveEvents, students);
var eventOccurrences = GetNationalEventOccurrences(competitiveEvents);
// Filter out pre-conference
eventOccurrences =
(from kv in eventOccurrences
let newV = kv.Value.Where(eo => !eo.Name.Contains("Pre-Conference"))
select Tuple.Create(kv.Key, newV))
.ToDictionary(s => s.Item1, s => s.Item2.ToList());
return View(Tuple.Create(teams, students, eventOccurrences));
}
public IActionResult TeamGrid()
{
var competitiveEvents = GetCompetitiveEvents();
var students = GetStudents(competitiveEvents);
var teams = GetTeams(competitiveEvents, students);
return View(Tuple.Create(teams, students));
}
public IActionResult Students()
{
var competitiveEvents = GetCompetitiveEvents();
var students = GetStudents(competitiveEvents);
GetTeams(competitiveEvents, students);
return View(Tuple.Create(students));
}
public static Func<T, bool> And<T>(params Func<T, bool>[] predicates)
{
return t => predicates.All(predicate => predicate(t));
}
public IActionResult Schedule()
{
var scheduleOptions =
new ScheduleOptions(
timeSlots: 3,
mustIncludeEvents:new []
{
"Medical Technology", "Electrical Applications" //, "RegionalTeam",
,"Dragster", "Flight"
},
extended: new string[]
{
"Invention", "Construction Challenge", "Mechanical", "Mass", "Micro"
//"STEM"
//"Community", "Vlogging"// "Microcontroller"
},
omittedEvents: new string[]
{
"Vlogging", "Junior", "Community Service Video", "Digital Photography",
"STEM"
//"Leadership",// "Electrical", //"Construction"
// "Forensic",
//"CAD"
//"I&I Team 1", "I&I Team 2"//, "Website Design",
},
absentStudents: new string[]
{
//"Eliam"
},
reverse: true,
slotPush:0);
var events = GetCompetitiveEvents();
var students = GetStudents(events);
var allTeams = GetTeams(events, students);
var omittedEvents = allTeams.Where(t => scheduleOptions.OmittedEvents?.Any(s => t.Name.Contains(s)) == true).ToArray();
allTeams = allTeams.Where(t => !omittedEvents.Contains(t)).ToArray();
bool RegionalPredicate(Team t) => t.Event.RegionalEvent;
bool TeamPredicate(Team t) => t.Event.Format is EventFormat.Team;
bool RegionalTeamPredicate(Team t) => RegionalPredicate(t) && TeamPredicate(t);
bool HighEffort(Team t) => t.Event.LevelOfEffort == 3;
bool LowEffort(Team t) => t.Event.LevelOfEffort == 1;
bool RegionalTeamSomeEffortPredicate(Team t) => RegionalTeamPredicate(t) && !LowEffort(t);
bool IndividualPredicate(Team t) => t.Event.Format is EventFormat.Individual;
bool negativePredicate(Team t) => false;
var mustIncludeTeams =
from e in events
from t in allTeams
where t.Event == e &&
(scheduleOptions.MustIncludeEvents?.Any(s => s == "RegionalTeam") == true && RegionalTeamSomeEffortPredicate(t)
|| scheduleOptions.MustIncludeEvents?.Any( t.Event.Name.Contains) == true
|| HighEffort(t))
select t;
Debug.WriteLine("Must Include: " + string.Join(", ", mustIncludeTeams.Select(t => t.ToStringWithIndividualAndRegional())));
Debug.WriteLine("Omitted: " + string.Join(", ", omittedEvents.Select(t => t.ToStringWithIndividualAndRegional())));
var teamScheduler = new TeamScheduler(mustIncludeTeams.ToArray(), scheduleOptions.TimeSlots);
var schedule = teamScheduler.Solve();
//schedule = schedule.OrderByDescending(ts => new Random(schedule.GetHashCode() + 1).Next()).ToArray();
if (scheduleOptions.SlotPush != 0)
{
schedule = schedule.Skip(scheduleOptions.SlotPush).Concat(schedule.Take(scheduleOptions.SlotPush))
.ToArray();
}
if (scheduleOptions.Reverse)
schedule = schedule.Reverse().ToArray();
////// extend schedules
var extendedTeams =
from t in allTeams
where
scheduleOptions.MustIncludeEvents?.Any(s => scheduleOptions.ExtendedTeams?.Any(et => t.Name.Contains(et)) == true) == true
select t;
foreach (var extendedTeam in extendedTeams)
{
schedule = new UnassignedStudentScheduler(allTeams, schedule).AddAdditionalTimeSlot(extendedTeam);
}
schedule = new UnassignedStudentScheduler(allTeams, schedule).ScheduleStrategy(UnassignedScheduleStrategy.LevelOfEffort);
schedule = new UnassignedStudentScheduler(allTeams, schedule).ScheduleStrategy(UnassignedScheduleStrategy.BiggestGroup);
schedule = new UnassignedStudentScheduler(allTeams, schedule).ScheduleStrategy(UnassignedScheduleStrategy.IndividualEvents);
//schedule = new UnassignedStudentScheduler(allTeams, schedule).ScheduleStrategy(UnassignedScheduleStrategy.AnyNotMeetingAlready);
var unassignedStudents = UnassignedStudentScheduler.UnassignedStudents(students, schedule).ToArray();
return View(Tuple.Create(schedule, unassignedStudents, scheduleOptions));
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}