using System; using System.Collections.Generic; using UnityEngine; /// /// BFI测试记录数据模型 /// 包含测试的基本信息、数据点和统计信息 /// [System.Serializable] public class BFITestRecord { [Header("基本信息")] public string TestId; // 测试ID public string TestName; // 测试名称 public DateTime StartTime; // 开始时间 public DateTime EndTime; // 结束时间 public long StartTimeTicks; // 开始时间Ticks(用于JSON持久化) public long EndTimeTicks; // 结束时间Ticks(用于JSON持久化) public string PatientId; // 患者ID public string PatientName; // 患者姓名 public string PatientGender; // 患者性别 public int PatientAge; // 患者年龄 public float PatientHeight; // 患者身高(cm) public float PatientWeight; // 患者体重(kg) [Header("测试配置")] public float LowThreshold; // 低阈值 public float HighThreshold; // 高阈值 public int AlarmPriority; // 报警优先级 public bool AlarmEnabled; // 是否启用报警 [Header("测试数据")] public List DataPoints; // BFI数据点集合 [Header("统计信息")] public BFIStatistics Statistics; // 统计数据 [Header("导出信息")] public DateTime ExportTime; // 导出时间 public string ExportFormat; // 导出格式 public string FilePath; // 文件路径 /// /// 构造函数 /// public BFITestRecord() { TestId = System.Guid.NewGuid().ToString(); TestName = $"BFI测试_{DateTime.Now:yyyyMMdd_HHmmss}"; StartTime = DateTime.Now; StartTimeTicks = StartTime.Ticks; EndTime = DateTime.MinValue; EndTimeTicks = 0; PatientGender = string.Empty; PatientAge = 0; PatientHeight = 0f; PatientWeight = 0f; DataPoints = new List(); Statistics = new BFIStatistics(); } /// /// 构造函数(带参数) /// public BFITestRecord(string testName, string patientId = null) { TestId = System.Guid.NewGuid().ToString(); TestName = testName; PatientId = patientId; StartTime = DateTime.Now; StartTimeTicks = StartTime.Ticks; EndTime = DateTime.MinValue; EndTimeTicks = 0; PatientGender = string.Empty; PatientAge = 0; PatientHeight = 0f; PatientWeight = 0f; DataPoints = new List(); Statistics = new BFIStatistics(); } /// /// 添加数据点 /// public void AddDataPoint(float bfiValue, string status = "正常", string notes = "") { var dataPoint = new BFIDataPoint { Timestamp = DateTime.Now, TimestampTicks = DateTime.Now.Ticks, BFI = bfiValue, Status = status, Notes = notes }; DataPoints.Add(dataPoint); UpdateStatistics(); } /// /// 结束测试 /// public void EndTest() { EndTest(DateTime.Now); } /// /// 使用指定时间结束测试 /// public void EndTest(DateTime endTime) { EndTime = endTime; EndTimeTicks = EndTime.Ticks; UpdateStatistics(); } /// /// 重新计算统计信息 /// public void RecalculateStatistics() { UpdateStatistics(); } /// /// 序列化前同步时间字段 /// public void PrepareForSerialization() { if (StartTime > DateTime.MinValue) { StartTimeTicks = StartTime.Ticks; } EndTimeTicks = EndTime > DateTime.MinValue ? EndTime.Ticks : 0; if (DataPoints != null) { foreach (var point in DataPoints) { point?.PrepareForSerialization(); } } } /// /// 反序列化后恢复时间字段 /// public void RestoreAfterDeserialization() { if (StartTimeTicks > 0) { StartTime = new DateTime(StartTimeTicks, DateTimeKind.Local); } if (EndTimeTicks > 0) { EndTime = new DateTime(EndTimeTicks, DateTimeKind.Local); } if (DataPoints != null) { foreach (var point in DataPoints) { point?.RestoreAfterDeserialization(); } } // 兼容旧数据:没有有效开始时间时,使用当前时间避免出现公元1年 if (StartTime <= DateTime.MinValue) { StartTime = DateTime.Now; StartTimeTicks = StartTime.Ticks; } // 避免结束时间早于开始时间导致负时长 if (EndTime > DateTime.MinValue && EndTime < StartTime) { EndTime = DateTime.MinValue; EndTimeTicks = 0; } UpdateStatistics(); } /// /// 更新统计信息 /// private void UpdateStatistics() { if (DataPoints == null || DataPoints.Count == 0) { Statistics = new BFIStatistics(); return; } var bfiValues = new List(); foreach (var point in DataPoints) { bfiValues.Add(point.BFI); } Statistics.Count = DataPoints.Count; Statistics.MinValue = bfiValues.Count > 0 ? Mathf.Min(bfiValues.ToArray()) : 0f; Statistics.MaxValue = bfiValues.Count > 0 ? Mathf.Max(bfiValues.ToArray()) : 0f; Statistics.Average = bfiValues.Count > 0 ? bfiValues.Average() : 0f; // 计算标准差 if (bfiValues.Count > 1) { float variance = bfiValues.Sum(x => Mathf.Pow(x - Statistics.Average, 2)) / bfiValues.Count; Statistics.StandardDeviation = Mathf.Sqrt(variance); } Statistics.Duration = EndTime > StartTime ? (EndTime - StartTime).TotalMinutes : 0; Statistics.LastUpdated = DateTime.Now; } /// /// 获取测试时长(分钟) /// public double GetDurationMinutes() { if (EndTime > StartTime) { return (EndTime - StartTime).TotalMinutes; } return (DateTime.Now - StartTime).TotalMinutes; } /// /// 检查是否有异常数据 /// public bool HasAbnormalData() { if (DataPoints == null) return false; foreach (var point in DataPoints) { if (point.BFI < LowThreshold || point.BFI > HighThreshold) { return true; } } return false; } /// /// 获取异常数据点数量 /// public int GetAbnormalDataCount() { if (DataPoints == null) return 0; int count = 0; foreach (var point in DataPoints) { if (point.BFI < LowThreshold || point.BFI > HighThreshold) { count++; } } return count; } } /// /// BFI数据点 /// [System.Serializable] public class BFIDataPoint { public DateTime Timestamp; // 时间戳 public long TimestampTicks; // 时间戳Ticks(用于JSON持久化) public float BFI; // BFI值 public string Status; // 状态(正常、异常、报警等) public string Notes; // 备注 public int AlarmLevel; // 报警级别 (0=正常, 1=低, 2=中, 3=高) public BFIDataPoint() { Timestamp = DateTime.Now; TimestampTicks = Timestamp.Ticks; Status = "正常"; Notes = ""; AlarmLevel = 0; } /// /// 序列化前同步时间字段 /// public void PrepareForSerialization() { if (Timestamp > DateTime.MinValue) { TimestampTicks = Timestamp.Ticks; } } /// /// 反序列化后恢复时间字段 /// public void RestoreAfterDeserialization() { if (TimestampTicks > 0) { Timestamp = new DateTime(TimestampTicks, DateTimeKind.Local); return; } if (Timestamp <= DateTime.MinValue) { Timestamp = DateTime.Now; TimestampTicks = Timestamp.Ticks; } } } /// /// BFI统计信息 /// [System.Serializable] public class BFIStatistics { public int Count; // 数据点总数 public float MinValue; // 最小值 public float MaxValue; // 最大值 public float Average; // 平均值 public float StandardDeviation; // 标准差 public double Duration; // 测试时长(分钟) public DateTime LastUpdated; // 最后更新时间 public BFIStatistics() { Count = 0; MinValue = 0f; MaxValue = 0f; Average = 0f; StandardDeviation = 0f; Duration = 0; LastUpdated = DateTime.Now; } } /// /// 扩展方法 /// public static class ListExtensions { public static float Average(this List source) { if (source == null || source.Count == 0) return 0f; float sum = 0f; foreach (float value in source) { sum += value; } return sum / source.Count; } public static float Sum(this List source, System.Func selector) { if (source == null || source.Count == 0) return 0f; float sum = 0f; foreach (float value in source) { sum += selector(value); } return sum; } }