45edcf5e5f
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.
201 lines
7.0 KiB
C#
201 lines
7.0 KiB
C#
using Core.Entities;
|
|
using Core.Models;
|
|
using System.Text.Json;
|
|
|
|
namespace Core.Validation;
|
|
|
|
/// <summary>
|
|
/// Configuration for validation thresholds and rules
|
|
/// </summary>
|
|
public class ValidationConfiguration
|
|
{
|
|
// Event count thresholds
|
|
/// <summary>
|
|
/// Minimum recommended number of events per student (Warning if below)
|
|
/// </summary>
|
|
public int MinRecommendedEvents { get; set; } = 2;
|
|
|
|
/// <summary>
|
|
/// Maximum recommended number of events per student (Warning if above)
|
|
/// </summary>
|
|
public int MaxRecommendedEvents { get; set; } = 4;
|
|
|
|
/// <summary>
|
|
/// Minimum critical number of events per student (Error if below)
|
|
/// </summary>
|
|
public int MinCriticalEvents { get; set; } = 1;
|
|
|
|
/// <summary>
|
|
/// Maximum critical number of events per student (Error if above)
|
|
/// </summary>
|
|
public int MaxCriticalEvents { get; set; } = 6;
|
|
|
|
/// <summary>
|
|
/// Maximum recommended number of regional events per student (Warning if above)
|
|
/// </summary>
|
|
public int MaxRegionalEvents { get; set; } = 3;
|
|
|
|
// Required event types
|
|
/// <summary>
|
|
/// Whether to require students to have at least one regional event
|
|
/// </summary>
|
|
public bool RequireRegionalEvent { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// Whether to require students to have at least one on-site activity
|
|
/// </summary>
|
|
public bool RequireOnSiteActivity { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// Whether to require students to have at least one individual event
|
|
/// </summary>
|
|
public bool RequireIndividualEvent { get; set; } = false;
|
|
|
|
/// <summary>
|
|
/// Whether to require team-based events to have an assigned captain
|
|
/// </summary>
|
|
public bool RequireTeamCaptain { get; set; } = true;
|
|
|
|
// Severity levels for each rule type
|
|
/// <summary>
|
|
/// Severity level for "No Regional Event" warnings
|
|
/// </summary>
|
|
public ValidationSeverity NoRegionalEventSeverity { get; set; } = ValidationSeverity.Warning;
|
|
|
|
/// <summary>
|
|
/// Severity level for "No On-Site Activity" warnings
|
|
/// </summary>
|
|
public ValidationSeverity NoOnSiteActivitySeverity { get; set; } = ValidationSeverity.Warning;
|
|
|
|
/// <summary>
|
|
/// Severity level for "No Individual Event" warnings
|
|
/// </summary>
|
|
public ValidationSeverity NoIndividualEventSeverity { get; set; } = ValidationSeverity.Warning;
|
|
|
|
/// <summary>
|
|
/// Severity level for team size warnings
|
|
/// </summary>
|
|
public ValidationSeverity TeamSizeSeverity { get; set; } = ValidationSeverity.Warning;
|
|
|
|
/// <summary>
|
|
/// Severity level for event count warnings
|
|
/// </summary>
|
|
public ValidationSeverity EventCountSeverity { get; set; } = ValidationSeverity.Warning;
|
|
|
|
/// <summary>
|
|
/// Severity level for missing captain warnings
|
|
/// </summary>
|
|
public ValidationSeverity MissingCaptainSeverity { get; set; } = ValidationSeverity.Warning;
|
|
|
|
/// <summary>
|
|
/// Severity level for too many regional events warnings
|
|
/// </summary>
|
|
public ValidationSeverity TooManyRegionalEventsSeverity { get; set; } = ValidationSeverity.Warning;
|
|
|
|
/// <summary>
|
|
/// Default configuration matching current app behavior
|
|
/// </summary>
|
|
public static ValidationConfiguration Default => new()
|
|
{
|
|
RequireRegionalEvent = true,
|
|
RequireOnSiteActivity = true,
|
|
RequireIndividualEvent = false,
|
|
MinRecommendedEvents = 2,
|
|
MaxRecommendedEvents = 4,
|
|
MinCriticalEvents = 1,
|
|
MaxCriticalEvents = 6,
|
|
MaxRegionalEvents = 3,
|
|
RequireTeamCaptain = true,
|
|
NoRegionalEventSeverity = ValidationSeverity.Warning,
|
|
NoOnSiteActivitySeverity = ValidationSeverity.Warning,
|
|
NoIndividualEventSeverity = ValidationSeverity.Warning,
|
|
TeamSizeSeverity = ValidationSeverity.Warning,
|
|
EventCountSeverity = ValidationSeverity.Warning,
|
|
MissingCaptainSeverity = ValidationSeverity.Warning,
|
|
TooManyRegionalEventsSeverity = ValidationSeverity.Warning
|
|
};
|
|
|
|
/// <summary>
|
|
/// Create validation configuration from assignment parameters
|
|
/// </summary>
|
|
/// <param name="parameters">Assignment parameters to convert</param>
|
|
/// <returns>Validation configuration matching the assignment parameters</returns>
|
|
public static ValidationConfiguration FromAssignmentParameters(AssignmentParameters parameters)
|
|
{
|
|
return new ValidationConfiguration
|
|
{
|
|
RequireRegionalEvent = parameters.RequireRegional,
|
|
RequireOnSiteActivity = parameters.RequireOnSite,
|
|
MinRecommendedEvents = parameters.EventsLowerBound,
|
|
MaxRecommendedEvents = parameters.EventsUpperBound,
|
|
MinCriticalEvents = 1,
|
|
MaxCriticalEvents = 6,
|
|
RequireTeamCaptain = true,
|
|
NoRegionalEventSeverity = ValidationSeverity.Warning,
|
|
NoOnSiteActivitySeverity = ValidationSeverity.Warning,
|
|
NoIndividualEventSeverity = ValidationSeverity.Warning,
|
|
TeamSizeSeverity = ValidationSeverity.Warning,
|
|
EventCountSeverity = ValidationSeverity.Warning,
|
|
MissingCaptainSeverity = ValidationSeverity.Warning
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deserialize validation configuration from JSON string
|
|
/// </summary>
|
|
/// <param name="json">JSON string containing configuration</param>
|
|
/// <returns>ValidationConfiguration instance or Default if deserialization fails</returns>
|
|
public static ValidationConfiguration FromJson(string json)
|
|
{
|
|
try
|
|
{
|
|
var options = new JsonSerializerOptions
|
|
{
|
|
PropertyNameCaseInsensitive = true,
|
|
Converters = { new System.Text.Json.Serialization.JsonStringEnumConverter() }
|
|
};
|
|
return JsonSerializer.Deserialize<ValidationConfiguration>(json, options) ?? Default;
|
|
}
|
|
catch
|
|
{
|
|
return Default;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load validation configuration from a JSON file
|
|
/// </summary>
|
|
/// <param name="path">Path to the JSON configuration file</param>
|
|
/// <returns>ValidationConfiguration instance or Default if file doesn't exist or loading fails</returns>
|
|
public static async Task<ValidationConfiguration> LoadFromFileAsync(string path)
|
|
{
|
|
try
|
|
{
|
|
if (!File.Exists(path))
|
|
return Default;
|
|
|
|
var json = await File.ReadAllTextAsync(path);
|
|
return FromJson(json);
|
|
}
|
|
catch
|
|
{
|
|
return Default;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Save this validation configuration to a JSON file
|
|
/// </summary>
|
|
/// <param name="path">Path where the JSON file should be saved</param>
|
|
public async Task SaveToFileAsync(string path)
|
|
{
|
|
var options = new JsonSerializerOptions
|
|
{
|
|
WriteIndented = true,
|
|
Converters = { new System.Text.Json.Serialization.JsonStringEnumConverter() }
|
|
};
|
|
var json = JsonSerializer.Serialize(this, options);
|
|
await File.WriteAllTextAsync(path, json);
|
|
}
|
|
}
|