Initial commit

This commit is contained in:
2026-07-13 09:25:40 +07:00
parent c08ff54676
commit bccfb156d7
1938 changed files with 641646 additions and 0 deletions

View File

@@ -0,0 +1,258 @@
using Microsoft.EntityFrameworkCore;
using RobotNet10.NavigationTune.Shared.Interfaces;
using RobotNet10.NavigationTune.Shared.Models;
namespace RobotNet10.NavigationTune.Data;
/// <summary>
/// Repository for test runs
/// </summary>
public class TestRepository(TuningDbContext context) : ITestRepository
{
public async Task<TestRun?> GetByIdAsync(Guid id)
{
var testRun = await context.TestRuns
.Include(r => r.Metrics)
.Include(r => r.SafetyViolations)
.FirstOrDefaultAsync(r => r.Id == id);
if (testRun != null)
{
// Load scenario and parameter set separately
var scenarioEntity = await context.TestScenarios.FindAsync(testRun.ScenarioId);
if (scenarioEntity != null)
testRun.Scenario = scenarioEntity.ToTestScenario();
testRun.ParameterSet = await context.ParameterSets.FindAsync(testRun.ParameterSetId);
}
return testRun;
}
public async Task<List<TestRun>> GetAllAsync()
{
var testRuns = await context.TestRuns
.Include(r => r.Metrics)
.OrderByDescending(r => r.StartTime)
.ToListAsync();
// Load scenarios and parameter sets
foreach (var testRun in testRuns)
{
var scenarioEntity = await context.TestScenarios.FindAsync(testRun.ScenarioId);
if (scenarioEntity != null)
testRun.Scenario = scenarioEntity.ToTestScenario();
testRun.ParameterSet = await context.ParameterSets.FindAsync(testRun.ParameterSetId);
}
return testRuns;
}
public async Task<int> GetCountAsync()
{
return await context.TestRuns.CountAsync();
}
public async Task<List<TestRun>> GetPagedAsync(int skip, int take)
{
var testRuns = await context.TestRuns
.Include(r => r.Metrics)
.OrderByDescending(r => r.StartTime)
.Skip(skip)
.Take(take)
.ToListAsync();
var scenarioIds = testRuns.Select(r => r.ScenarioId).Distinct().ToList();
var parameterSetIds = testRuns.Select(r => r.ParameterSetId).Distinct().ToList();
var scenarios = await context.TestScenarios
.Where(s => scenarioIds.Contains(s.Id))
.ToListAsync();
var parameterSets = await context.ParameterSets
.Where(p => parameterSetIds.Contains(p.Id))
.ToListAsync();
foreach (var testRun in testRuns)
{
var scenarioEntity = scenarios.FirstOrDefault(s => s.Id == testRun.ScenarioId);
if (scenarioEntity != null)
testRun.Scenario = scenarioEntity.ToTestScenario();
testRun.ParameterSet = parameterSets.FirstOrDefault(p => p.Id == testRun.ParameterSetId);
}
return testRuns;
}
public async Task<List<TestRun>> GetByScenarioAsync(Guid scenarioId)
{
var testRuns = await context.TestRuns
.Include(r => r.Metrics)
.Where(r => r.ScenarioId == scenarioId)
.OrderByDescending(r => r.StartTime)
.ToListAsync();
// Load scenarios and parameter sets
var scenarioEntity = await context.TestScenarios.FindAsync(scenarioId);
foreach (var testRun in testRuns)
{
if (scenarioEntity != null)
testRun.Scenario = scenarioEntity.ToTestScenario();
testRun.ParameterSet = await context.ParameterSets.FindAsync(testRun.ParameterSetId);
}
return testRuns;
}
public async Task<List<TestRun>> GetByParameterSetAsync(Guid parameterSetId)
{
var testRuns = await context.TestRuns
.Include(r => r.Metrics)
.Where(r => r.ParameterSetId == parameterSetId)
.OrderByDescending(r => r.StartTime)
.ToListAsync();
// Load scenarios and parameter sets
var parameterSet = await context.ParameterSets.FindAsync(parameterSetId);
foreach (var testRun in testRuns)
{
var scenarioEntity = await context.TestScenarios.FindAsync(testRun.ScenarioId);
if (scenarioEntity != null)
testRun.Scenario = scenarioEntity.ToTestScenario();
testRun.ParameterSet = parameterSet;
}
return testRuns;
}
public async Task<List<TestRun>> GetByDateRangeAsync(DateTime from, DateTime to)
{
var testRuns = await context.TestRuns
.Include(r => r.Metrics)
.Where(r => r.StartTime >= from && r.StartTime <= to)
.OrderByDescending(r => r.StartTime)
.ToListAsync();
// Load scenarios and parameter sets
var scenarioIds = testRuns.Select(r => r.ScenarioId).Distinct().ToList();
var parameterSetIds = testRuns.Select(r => r.ParameterSetId).Distinct().ToList();
var scenarios = await context.TestScenarios
.Where(s => scenarioIds.Contains(s.Id))
.ToListAsync();
var parameterSets = await context.ParameterSets
.Where(p => parameterSetIds.Contains(p.Id))
.ToListAsync();
foreach (var testRun in testRuns)
{
var scenarioEntity = scenarios.FirstOrDefault(s => s.Id == testRun.ScenarioId);
if (scenarioEntity != null)
testRun.Scenario = scenarioEntity.ToTestScenario();
testRun.ParameterSet = parameterSets.FirstOrDefault(p => p.Id == testRun.ParameterSetId);
}
return testRuns;
}
public async Task<Guid> SaveAsync(TestRun testRun)
{
context.TestRuns.Add(testRun);
await context.SaveChangesAsync();
return testRun.Id;
}
public async Task UpdateAsync(TestRun testRun)
{
var entry = context.Entry(testRun);
if (entry.State == EntityState.Detached)
context.TestRuns.Update(testRun);
await context.SaveChangesAsync();
}
/// <summary>
/// Update test run from execution result without loading/replacing navigation properties,
/// to avoid DbUpdateConcurrencyException when entity was created in another scope.
/// </summary>
public async Task UpdateFromResultAsync(
Guid testRunId,
TestStatus status,
DateTime? endTime,
double duration,
string? errorMessage,
TestMetrics? metrics,
List<SafetyViolation>? safetyViolations)
{
var testRun = await context.TestRuns
.AsNoTracking()
.FirstOrDefaultAsync(r => r.Id == testRunId);
if (testRun == null)
return;
testRun.Status = status;
testRun.EndTime = endTime;
testRun.Duration = duration;
testRun.ErrorMessage = errorMessage;
context.TestRuns.Update(testRun);
await context.SaveChangesAsync();
var existingMetrics = await context.TestMetrics.Where(m => m.TestRunId == testRunId).ToListAsync();
if (existingMetrics.Count > 0)
context.TestMetrics.RemoveRange(existingMetrics);
var existingViolations = await context.SafetyViolations.Where(v => v.TestRunId == testRunId).ToListAsync();
if (existingViolations.Count > 0)
context.SafetyViolations.RemoveRange(existingViolations);
if (metrics != null)
{
metrics.TestRunId = testRunId;
if (metrics.Id == default)
metrics.Id = Guid.NewGuid();
context.TestMetrics.Add(metrics);
}
if (safetyViolations != null && safetyViolations.Count > 0)
{
foreach (var v in safetyViolations)
{
v.TestRunId = testRunId;
if (v.Id == default)
v.Id = Guid.NewGuid();
}
context.SafetyViolations.AddRange(safetyViolations);
}
await context.SaveChangesAsync();
}
public async Task DeleteAsync(Guid id)
{
var testRun = await GetByIdAsync(id);
if (testRun != null)
{
context.TestRuns.Remove(testRun);
await context.SaveChangesAsync();
}
}
public async Task DeleteManyAsync(IEnumerable<Guid> ids)
{
var idList = ids.Distinct().ToList();
if (idList.Count == 0)
return;
var toRemove = await context.TestRuns
.Where(r => idList.Contains(r.Id))
.ToListAsync();
if (toRemove.Count > 0)
{
context.TestRuns.RemoveRange(toRemove);
await context.SaveChangesAsync();
}
}
}