Files
poprhythm 45edcf5e5f Refactor event assignment structure and introduce new models for assignment parameters and requirements
This commit removes the obsolete EventAssignment class from Core.Entities and introduces new models in Core.Models, including AssignmentParameters, AssignmentRequirement, PartialTeam, and StudentEventStatistics. The changes enhance the organization of assignment-related data and improve the overall structure of the codebase. Additionally, several files have been updated to include references to the new Core.Models namespace, ensuring consistency across the application.
2026-01-10 18:36:52 -05:00

132 lines
5.0 KiB
C#

using Core.Entities;
using Core.Models;
using System.Reflection;
namespace Core.Validation;
/// <summary>
/// Main service for executing validation rules and generating warnings
/// </summary>
public class ValidationService
{
private readonly ValidationConfiguration _config;
private readonly List<IValidationRule<Student>> _studentRules;
private readonly List<IValidationRule<Team>> _teamRules;
private readonly List<IValidationRule<StudentEventStatistics>> _statisticsRules;
// Lazy static singletons for rule definitions (instantiated once per application lifetime)
private static readonly Lazy<List<IValidationRule<Student>>> _studentRuleDefinitions =
new(() => DiscoverRules<Student>());
private static readonly Lazy<List<IValidationRule<Team>>> _teamRuleDefinitions =
new(() => DiscoverRules<Team>());
private static readonly Lazy<List<IValidationRule<StudentEventStatistics>>> _statisticsRuleDefinitions =
new(() => DiscoverRules<StudentEventStatistics>());
/// <summary>
/// Create a new validation service with the specified configuration
/// </summary>
/// <param name="config">Validation configuration (uses Default if null)</param>
public ValidationService(ValidationConfiguration? config = null)
{
_config = config ?? ValidationConfiguration.Default;
// Use the shared rule definitions (singleton pattern)
_studentRules = _studentRuleDefinitions.Value;
_teamRules = _teamRuleDefinitions.Value;
_statisticsRules = _statisticsRuleDefinitions.Value;
}
/// <summary>
/// Discover all validation rules for a given entity type using reflection
/// </summary>
/// <typeparam name="TEntity">The entity type to find rules for</typeparam>
/// <returns>List of discovered validation rules</returns>
private static List<IValidationRule<TEntity>> DiscoverRules<TEntity>()
{
var ruleType = typeof(IValidationRule<TEntity>);
return Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.IsClass && !t.IsAbstract && ruleType.IsAssignableFrom(t))
.Select(t => (IValidationRule<TEntity>)Activator.CreateInstance(t)!)
.ToList();
}
/// <summary>
/// Validate a student's event rankings
/// </summary>
/// <param name="student">Student to validate</param>
/// <param name="context">Validation context</param>
/// <returns>List of validation warnings</returns>
public List<ValidationWarning> ValidateStudentRankings(Student student, ValidationContext context)
{
return _studentRules
.Where(rule => rule.AppliesTo(context))
.Select(rule => rule.Validate(student, _config))
.Where(warning => warning != null)
.Cast<ValidationWarning>()
.ToList();
}
/// <summary>
/// Validate a team configuration
/// </summary>
/// <param name="team">Team to validate</param>
/// <param name="context">Validation context (defaults to Team)</param>
/// <returns>List of validation warnings</returns>
public List<ValidationWarning> ValidateTeam(Team team, ValidationContext context = ValidationContext.Team)
{
return _teamRules
.Where(rule => rule.AppliesTo(context))
.Select(rule => rule.Validate(team, _config))
.Where(warning => warning != null)
.Cast<ValidationWarning>()
.ToList();
}
/// <summary>
/// Validate student event assignment statistics
/// </summary>
/// <param name="stats">Student statistics to validate</param>
/// <param name="context">Validation context</param>
/// <returns>List of validation warnings</returns>
public List<ValidationWarning> ValidateStudentStatistics(StudentEventStatistics stats, ValidationContext context)
{
return _statisticsRules
.Where(rule => rule.AppliesTo(context))
.Select(rule => rule.Validate(stats, _config))
.Where(warning => warning != null)
.Cast<ValidationWarning>()
.ToList();
}
/// <summary>
/// Validate all students in a collection
/// </summary>
/// <param name="students">Students to validate</param>
/// <param name="context">Validation context</param>
/// <returns>Dictionary mapping each student to their warnings</returns>
public Dictionary<Student, List<ValidationWarning>> ValidateStudents(
IEnumerable<Student> students,
ValidationContext context)
{
return students.ToDictionary(
student => student,
student => ValidateStudentRankings(student, context)
);
}
/// <summary>
/// Validate all teams in a collection
/// </summary>
/// <param name="teams">Teams to validate</param>
/// <returns>Dictionary mapping each team to their warnings</returns>
public Dictionary<Team, List<ValidationWarning>> ValidateTeams(IEnumerable<Team> teams)
{
return teams.ToDictionary(
team => team,
team => ValidateTeam(team)
);
}
}