first commit
This commit is contained in:
@@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user