377 lines
10 KiB
C#
377 lines
10 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// BFI测试记录数据模型
|
||
/// 包含测试的基本信息、数据点和统计信息
|
||
/// </summary>
|
||
[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<BFIDataPoint> DataPoints; // BFI数据点集合
|
||
|
||
[Header("统计信息")]
|
||
public BFIStatistics Statistics; // 统计数据
|
||
|
||
[Header("导出信息")]
|
||
public DateTime ExportTime; // 导出时间
|
||
public string ExportFormat; // 导出格式
|
||
public string FilePath; // 文件路径
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
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<BFIDataPoint>();
|
||
Statistics = new BFIStatistics();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 构造函数(带参数)
|
||
/// </summary>
|
||
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<BFIDataPoint>();
|
||
Statistics = new BFIStatistics();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加数据点
|
||
/// </summary>
|
||
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();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 结束测试
|
||
/// </summary>
|
||
public void EndTest()
|
||
{
|
||
EndTest(DateTime.Now);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 使用指定时间结束测试
|
||
/// </summary>
|
||
public void EndTest(DateTime endTime)
|
||
{
|
||
EndTime = endTime;
|
||
EndTimeTicks = EndTime.Ticks;
|
||
UpdateStatistics();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重新计算统计信息
|
||
/// </summary>
|
||
public void RecalculateStatistics()
|
||
{
|
||
UpdateStatistics();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 序列化前同步时间字段
|
||
/// </summary>
|
||
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();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 反序列化后恢复时间字段
|
||
/// </summary>
|
||
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();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新统计信息
|
||
/// </summary>
|
||
private void UpdateStatistics()
|
||
{
|
||
if (DataPoints == null || DataPoints.Count == 0)
|
||
{
|
||
Statistics = new BFIStatistics();
|
||
return;
|
||
}
|
||
|
||
var bfiValues = new List<float>();
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取测试时长(分钟)
|
||
/// </summary>
|
||
public double GetDurationMinutes()
|
||
{
|
||
if (EndTime > StartTime)
|
||
{
|
||
return (EndTime - StartTime).TotalMinutes;
|
||
}
|
||
return (DateTime.Now - StartTime).TotalMinutes;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否有异常数据
|
||
/// </summary>
|
||
public bool HasAbnormalData()
|
||
{
|
||
if (DataPoints == null) return false;
|
||
|
||
foreach (var point in DataPoints)
|
||
{
|
||
if (point.BFI < LowThreshold || point.BFI > HighThreshold)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取异常数据点数量
|
||
/// </summary>
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// BFI数据点
|
||
/// </summary>
|
||
[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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 序列化前同步时间字段
|
||
/// </summary>
|
||
public void PrepareForSerialization()
|
||
{
|
||
if (Timestamp > DateTime.MinValue)
|
||
{
|
||
TimestampTicks = Timestamp.Ticks;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 反序列化后恢复时间字段
|
||
/// </summary>
|
||
public void RestoreAfterDeserialization()
|
||
{
|
||
if (TimestampTicks > 0)
|
||
{
|
||
Timestamp = new DateTime(TimestampTicks, DateTimeKind.Local);
|
||
return;
|
||
}
|
||
|
||
if (Timestamp <= DateTime.MinValue)
|
||
{
|
||
Timestamp = DateTime.Now;
|
||
TimestampTicks = Timestamp.Ticks;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// BFI统计信息
|
||
/// </summary>
|
||
[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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 扩展方法
|
||
/// </summary>
|
||
public static class ListExtensions
|
||
{
|
||
public static float Average(this List<float> 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<float> source, System.Func<float, float> selector)
|
||
{
|
||
if (source == null || source.Count == 0)
|
||
return 0f;
|
||
|
||
float sum = 0f;
|
||
foreach (float value in source)
|
||
{
|
||
sum += selector(value);
|
||
}
|
||
return sum;
|
||
}
|
||
}
|