- LaunchPlatformSpec(纯发射参数,无探测字段) - ScenarioUnit.FireUnitSpecId → LaunchPlatformSpecId - PlatformEntity/BuildFireUnits/BuildDetectionSources 适配 - ReportGenerator/ReportService 适配 - FireUnitSpec 保留但不使用 - 243/250 通过,7 个待修
103 lines
3.9 KiB
C#
103 lines
3.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using CounterDrone.Core.Models;
|
|
using SQLite;
|
|
using CounterDrone.Core.Simulation;
|
|
|
|
namespace CounterDrone.Core.Services
|
|
{
|
|
public class ReportService : IReportService
|
|
{
|
|
private readonly SQLiteConnection _db;
|
|
private readonly ReportGenerator _generator = new();
|
|
private readonly IPathProvider _paths;
|
|
|
|
public ReportService(SQLiteConnection db, IPathProvider paths)
|
|
{
|
|
_db = db;
|
|
_paths = paths;
|
|
}
|
|
|
|
public SimulationReport Generate(string scenarioId, ScenarioConfig config,
|
|
List<SimEvent> events, string finalDroneStatus, float duration)
|
|
{
|
|
var droneSpecs = _db.Table<DroneSpec>().ToDictionary(d => d.Id);
|
|
var fireUnitSpecs = _db.Table<LaunchPlatformSpec>().ToDictionary(f => f.Id);
|
|
var sensorSpecs = _db.Table<SensorSpec>().ToDictionary(s => s.Id);
|
|
|
|
var destroyed = events.Count(e => e.Type == SimEventType.DroneDestroyed);
|
|
var reached = events.Count(e => e.Type == SimEventType.DroneReachedTarget);
|
|
var intruded = events.Count(e => e.Type == SimEventType.ZoneIntruded);
|
|
var total = config.Drones.Sum(t => t.Quantity);
|
|
var result = _generator.DetermineInterceptResult(destroyed, reached + intruded, total);
|
|
|
|
var report = new SimulationReport
|
|
{
|
|
ScenarioId = scenarioId,
|
|
ScenarioName = config.Info.Name,
|
|
ScenarioNumber = config.Info.ScenarioNumber,
|
|
CompletedAt = DateTime.UtcNow.ToString("o"),
|
|
DroneCount = total,
|
|
UnitCount = config.Units.Count,
|
|
InterceptResult = (int)result,
|
|
Content = _generator.Generate(config, events, Simulation.DroneStatus.Flying, duration,
|
|
droneSpecs, fireUnitSpecs, sensorSpecs),
|
|
};
|
|
|
|
_db.Insert(report);
|
|
return report;
|
|
}
|
|
|
|
public SimulationReport GetReport(string id)
|
|
{
|
|
return _db.Find<SimulationReport>(id);
|
|
}
|
|
|
|
public void DeleteReport(string id)
|
|
{
|
|
_db.Delete<SimulationReport>(id);
|
|
}
|
|
|
|
public PagedResult<SimulationReport> SearchReports(string keyword, string? dateFrom, string? dateTo, int page, int pageSize)
|
|
{
|
|
if (page < 1) page = 1;
|
|
if (pageSize < 1) pageSize = 10;
|
|
var offset = (page - 1) * pageSize;
|
|
|
|
var query = _db.Table<SimulationReport>().AsQueryable();
|
|
if (!string.IsNullOrWhiteSpace(keyword))
|
|
query = query.Where(r => r.ScenarioName.Contains(keyword) || r.ScenarioNumber.Contains(keyword));
|
|
if (!string.IsNullOrWhiteSpace(dateFrom))
|
|
query = query.Where(r => r.CompletedAt.CompareTo(dateFrom) >= 0);
|
|
if (!string.IsNullOrWhiteSpace(dateTo))
|
|
query = query.Where(r => r.CompletedAt.CompareTo(dateTo) <= 0);
|
|
|
|
var total = query.Count();
|
|
var items = query.OrderByDescending(r => r.CompletedAt).Skip(offset).Take(pageSize).ToList();
|
|
|
|
return new PagedResult<SimulationReport>
|
|
{
|
|
Items = items,
|
|
TotalCount = total,
|
|
Page = page,
|
|
PageSize = pageSize,
|
|
};
|
|
}
|
|
|
|
public string ExportToFile(string reportId, string outputDir)
|
|
{
|
|
var report = _db.Find<SimulationReport>(reportId);
|
|
if (report == null) throw new ArgumentException($"报告 {reportId} 不存在");
|
|
|
|
Directory.CreateDirectory(outputDir);
|
|
var safeTime = DateTime.UtcNow.ToString("yyyyMMdd_HHmmss");
|
|
var fileName = $"{report.ScenarioName}_{safeTime}.md";
|
|
var filePath = Path.Combine(outputDir, fileName);
|
|
File.WriteAllText(filePath, report.Content);
|
|
return filePath;
|
|
}
|
|
}
|
|
}
|