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 events, string finalDroneStatus, float duration) { var droneSpecs = _db.Table().ToDictionary(d => d.Id); var fireUnitSpecs = _db.Table().ToDictionary(f => f.Id); var sensorSpecs = _db.Table().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(id); } public void DeleteReport(string id) { _db.Delete(id); } public PagedResult 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().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 { Items = items, TotalCount = total, Page = page, PageSize = pageSize, }; } public string ExportToFile(string reportId, string outputDir) { var report = _db.Find(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; } } }