Skip to content

Commit bc34e55

Browse files
committed
Allow null oilLevel and confidence in CLOEResult
The cloe analyzer now emits null for oilLevel and confidence when the prediction confidence is below threshold. Loosen the DTO to float? and guard the MQTT projection so low-confidence results publish null Value/Confidence instead of throwing on deserialize.
1 parent 6f7c622 commit bc34e55

2 files changed

Lines changed: 59 additions & 4 deletions

File tree

api.Tests/Services/ResultHandlers/WorkflowResultHandlers/CLOEResultHandlerTests.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,59 @@ public async Task OnWorkflowCompleted_NullResultJson_PublishesMessageWithNullVal
130130
Assert.Null(published.Value);
131131
Assert.Null(published.Confidence);
132132
}
133+
134+
[Fact]
135+
public async Task OnWorkflowCompleted_LowConfidenceResultWithNullFields_PublishesNullValueAndConfidence()
136+
{
137+
var record = await _db.NewInspectionRecord(inspectionId: "insp-123");
138+
var analysis = await _db.NewAnalysis(inspectionRecords: [record]);
139+
var run = await _db.NewAnalysisRun(analysis);
140+
var workflow = await _db.NewWorkflow(run, workflowType: "cloe");
141+
workflow.ResultJson = JsonSerializer.Serialize(
142+
new { oilLevel = (float?)null, confidence = (float?)null }
143+
);
144+
await _context.SaveChangesAsync(TestContext.Current.CancellationToken);
145+
146+
using var scope = _factory.Services.CreateScope();
147+
var handler = ResolveHandler(scope);
148+
149+
await handler.OnWorkflowCompleted(workflow);
150+
151+
var published = Assert.Single(_factory.MqttPublisher.AnalysisResultMessages);
152+
Assert.Null(published.Value);
153+
Assert.Null(published.Confidence);
154+
Assert.Null(published.Warning);
155+
}
156+
157+
[Fact]
158+
public async Task OnWorkflowCompleted_ResultWithWarning_PublishesWarning()
159+
{
160+
const float oilLevel = 0.02f;
161+
const float confidence = 0.80f;
162+
const string warning = "Oil level is below 5 %";
163+
164+
var record = await _db.NewInspectionRecord(inspectionId: "insp-123");
165+
var analysis = await _db.NewAnalysis(inspectionRecords: [record]);
166+
var run = await _db.NewAnalysisRun(analysis);
167+
var workflow = await _db.NewWorkflow(run, workflowType: "cloe");
168+
workflow.ResultJson = JsonSerializer.Serialize(
169+
new
170+
{
171+
oilLevel = oilLevel,
172+
confidence = confidence,
173+
warning = warning,
174+
}
175+
);
176+
await _context.SaveChangesAsync(TestContext.Current.CancellationToken);
177+
178+
using var scope = _factory.Services.CreateScope();
179+
var handler = ResolveHandler(scope);
180+
181+
await handler.OnWorkflowCompleted(workflow);
182+
183+
var published = Assert.Single(_factory.MqttPublisher.AnalysisResultMessages);
184+
Assert.Equal(oilLevel.ToString("F2"), published.Value);
185+
Assert.Equal(confidence * 100, published.Confidence);
186+
Assert.Equal(warning, published.Warning);
187+
}
133188
}

api/Services/ResultHandlers/WorkflowResultHandlers/CLOEResultHandler.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ namespace api.Services.ResultHandlers.WorkflowResultHandlers;
77

88
internal sealed class CLOEResult
99
{
10-
public float OilLevel { get; set; }
11-
public float Confidence { get; set; }
10+
public float? OilLevel { get; set; }
11+
public float? Confidence { get; set; }
1212
public string? Warning { get; set; }
1313
}
1414

@@ -58,9 +58,9 @@ public async Task OnWorkflowCompleted(Workflow workflow)
5858
AnalysisRunId = workflow.AnalysisRunId,
5959
AnalysisId = workflow.AnalysisRun.AnalysisId,
6060
AnalysisType = workflow.WorkflowType,
61-
Value = result?.OilLevel.ToString("F2"),
61+
Value = result?.OilLevel?.ToString("F2"),
6262
Unit = "fraction [oilLevel]",
63-
Confidence = result is null ? null : result.Confidence * 100,
63+
Confidence = result?.Confidence is { } c ? c * 100 : null,
6464
Warning = result?.Warning,
6565
};
6666

0 commit comments

Comments
 (0)