Files
WCTDataMiner/docs/data-model/entities/Ploss记录.md

240 lines
8.7 KiB
Markdown
Raw Normal View History

# ploss_record 实体
> 所属模块:[数据模型概览](../概览.md)
---
## 1. 表定义
**表名**`ploss_record`
**描述**:存储 Ploss FOD 格式解析数据,对应两行日志格式:
```
pow_loss = X, delta_p = Y
FOD-> (1) (2) ... (16)
```
---
## 2. 字段定义
| 列名 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | UUID | PK, NOT NULL | 主键 |
| scenario_id | UUID | FK, NOT NULL | 关联测试场景 |
| pow_loss | INT | NULL | 第一行:功率损耗值 |
| delta_p | INT | NULL | 第一行:功率差值 |
| field_1 | INT | NOT NULL | Field1语义待定义 |
| field_2 | INT | NOT NULL | Field2语义待定义 |
| field_3 | INT | NOT NULL | Field3语义待定义 |
| field_4 | INT | NOT NULL | Field4: RX power - 接收端功率 |
| field_5 | INT | NOT NULL | Field5: TX power - 发射端功率 |
| field_6 | INT | NOT NULL | Field6语义待定义 |
| field_7 | INT | NOT NULL | Field7语义待定义 |
| field_8 | INT | NOT NULL | Field8语义待定义 |
| field_9 | INT | NOT NULL, DEFAULT 0 | Field9: ploss - 功率损耗计算值 |
| field_10 | INT | NOT NULL, DEFAULT 0 | Field10: threshold - 阈值 |
| field_11 | INT | NOT NULL | Field11: 触发次数 - 当 Field9 > Field10 时计数超过5次触发FOD保护 |
| field_12 | INT | NOT NULL | Field12: PFOD result 标志 - 触发时置位 |
| field_13 | INT | NOT NULL, DEFAULT 0 | Field13语义待定义 |
| field_14 | INT | NOT NULL, DEFAULT 0 | Field14语义待定义 |
| field_15 | INT | NOT NULL, DEFAULT 0 | Field15语义待定义 |
| field_16 | INT | NOT NULL, DEFAULT 0 | Field16语义待定义 |
| is_deleted | BOOLEAN | NOT NULL, DEFAULT FALSE | 软删除标记 |
| created_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | 创建时间 |
> **字段语义**以 `PlossRecord` 实体注释为准。
---
## 3. 外键
| 外键 | 引用表 | 说明 |
|------|--------|------|
| scenario_id | test_scenario.id | 关联测试场景(必需) |
---
## 4. 派生字段
> **注意**:以下字段不落库,查询时动态计算
| 字段 | 计算公式 | 说明 |
|------|----------|------|
| margin | field_10 - field_9 | 安全余量(>0 安全,<0 危险) |
> **使用限制**`Margin` 属性通过 EF Core `Ignore()` 排除映射,仅用于内存计算。不可在数据库查询中直接使用(如 `WHERE Margin > 0`),需改用 `WHERE (field_10 - field_9) > 0` 或先加载到内存再计算。
---
## 5. 索引
| 索引名 | 字段 | 用途 |
|--------|------|------|
| idx_ploss_scenario | scenario_id | 按测试场景查询 |
| idx_ploss_field_2 | field_2 | 字段查询 |
| idx_ploss_field_7 | field_7 | 字段查询 |
| idx_ploss_field_8 | field_8 | 字段查询 |
| idx_ploss_field_10 | field_10 | 字段查询 |
| idx_ploss_pow_loss | pow_loss | 第一行损耗值查询 |
| idx_ploss_delta_p | delta_p | 第一行功率差值查询 |
---
## 6. EF Core 模型
### 实体类
```csharp
// Domain/Local/PlossRecord.cs
namespace Gpulse.WCT.DataAnalyzer.Core.Domain.Local;
public class PlossRecord
{
public Guid Id { get; set; } = Guid.NewGuid();
public Guid ScenarioId { get; set; }
// ===== 第一行字段nullable兼容旧数据 =====
/// <summary>功率损耗值(来自第一行)</summary>
public int? PowLoss { get; set; }
/// <summary>功率差值(来自第一行)</summary>
public int? DeltaP { get; set; }
// ===== 第二行字段16个通用字段均支持负数 =====
public int Field1 { get; set; }
public int Field2 { get; set; }
public int Field3 { get; set; }
/// <summary>Field4: RX power - 接收端功率</summary>
public int Field4 { get; set; }
/// <summary>Field5: TX power - 发射端功率</summary>
public int Field5 { get; set; }
public int Field6 { get; set; }
public int Field7 { get; set; }
public int Field8 { get; set; }
/// <summary>Field9: ploss - 功率损耗计算值</summary>
public int Field9 { get; set; }
/// <summary>Field10: threshold - 阈值</summary>
public int Field10 { get; set; }
/// <summary>Field11: 触发次数 - 当 Field9 > Field10ploss 大于阈值时计数超过5次触发FOD保护</summary>
public int Field11 { get; set; }
/// <summary>Field12: PFOD result 标志 - 触发时置位</summary>
public int Field12 { get; set; }
public int Field13 { get; set; }
public int Field14 { get; set; }
public int Field15 { get; set; }
public int Field16 { get; set; }
public bool IsDeleted { get; set; } = false;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
// Navigation Properties
public TestScenario Scenario { get; set; } = null!;
/// <summary>派生属性:安全余量(不落库) = Field10 - Field9</summary>
public int Margin => Field10 - Field9;
}
```
### 配置类
```csharp
// Infrastructure/LocalData/Configurations/PlossRecordConfiguration.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Gpulse.WCT.DataAnalyzer.Core.Domain.Local;
namespace Gpulse.WCT.DataAnalyzer.Core.Infrastructure.LocalData.Configurations;
public class PlossRecordConfiguration : IEntityTypeConfiguration<PlossRecord>
{
public void Configure(EntityTypeBuilder<PlossRecord> builder)
{
builder.ToTable("ploss_record");
builder.HasKey(e => e.Id);
builder.Property(e => e.Id).HasColumnName("id");
builder.Property(e => e.ScenarioId)
.IsRequired()
.HasColumnName("scenario_id");
// ===== 第一行字段nullable =====
builder.Property(e => e.PowLoss).IsRequired(false).HasColumnName("pow_loss");
builder.Property(e => e.DeltaP).IsRequired(false).HasColumnName("delta_p");
// ===== 第二行字段(通用命名) =====
builder.Property(e => e.Field1).IsRequired().HasColumnName("field_1");
builder.Property(e => e.Field2).IsRequired().HasColumnName("field_2");
builder.Property(e => e.Field3).IsRequired().HasColumnName("field_3");
builder.Property(e => e.Field4).IsRequired().HasColumnName("field_4");
builder.Property(e => e.Field5).IsRequired().HasColumnName("field_5");
builder.Property(e => e.Field6).IsRequired().HasColumnName("field_6");
builder.Property(e => e.Field7).IsRequired().HasColumnName("field_7");
builder.Property(e => e.Field8).IsRequired().HasColumnName("field_8");
builder.Property(e => e.Field9).IsRequired().HasDefaultValue(0).HasColumnName("field_9");
builder.Property(e => e.Field10).IsRequired().HasDefaultValue(0).HasColumnName("field_10");
builder.Property(e => e.Field11).IsRequired().HasColumnName("field_11");
builder.Property(e => e.Field12).IsRequired().HasColumnName("field_12");
builder.Property(e => e.Field13).IsRequired().HasDefaultValue(0).HasColumnName("field_13");
builder.Property(e => e.Field14).IsRequired().HasDefaultValue(0).HasColumnName("field_14");
builder.Property(e => e.Field15).IsRequired().HasDefaultValue(0).HasColumnName("field_15");
builder.Property(e => e.Field16).IsRequired().HasDefaultValue(0).HasColumnName("field_16");
builder.Property(e => e.IsDeleted)
.IsRequired()
.HasDefaultValue(false)
.HasColumnName("is_deleted");
builder.Property(e => e.CreatedAt)
.IsRequired()
.HasDefaultValueSql("datetime('now')")
.HasColumnName("created_at");
// 派生属性不落库
builder.Ignore(e => e.Margin);
// 索引
builder.HasIndex(e => e.ScenarioId).HasDatabaseName("idx_ploss_scenario");
builder.HasIndex(e => e.Field2).HasDatabaseName("idx_ploss_field_2");
builder.HasIndex(e => e.Field7).HasDatabaseName("idx_ploss_field_7");
builder.HasIndex(e => e.Field8).HasDatabaseName("idx_ploss_field_8");
builder.HasIndex(e => e.Field10).HasDatabaseName("idx_ploss_field_10");
builder.HasIndex(e => e.PowLoss).HasDatabaseName("idx_ploss_pow_loss");
builder.HasIndex(e => e.DeltaP).HasDatabaseName("idx_ploss_delta_p");
// 关系配置
builder.HasOne(e => e.Scenario)
.WithMany(e => e.PlossRecords)
.HasForeignKey(e => e.ScenarioId)
.OnDelete(DeleteBehavior.Cascade);
// 全局查询过滤器
builder.HasQueryFilter(e => !e.IsDeleted);
}
}
```
---
## 7. 动态阈值表
> 阈值根据 RxPower 动态查表(不落库,业务规则)
| Rx Power 区间 | Threshold | 备注 |
|---------------|-----------|------|
| 0-5000 mW | 350 mW | 低功率最敏感 |
| 5000-10000 mW | 500 mW | |
| 10000-15000 mW | 750 mW | |
| 15000-30000 mW | 1000 mW | |
| 30000-50000 mW | 1250 mW | 高功率 |