Add diagnosis eval baseline diff
This commit is contained in:
@@ -0,0 +1,252 @@
|
||||
package com.superbiz.agent.eval;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DiagnosisEvalBaselineDiffer {
|
||||
|
||||
private static final String REGRESSION = "REGRESSION";
|
||||
private static final String IMPROVEMENT = "IMPROVEMENT";
|
||||
private static final String CHANGED = "CHANGED";
|
||||
|
||||
public DiagnosisEvalDiffReport compare(DiagnosisEvalReport baseline, DiagnosisEvalReport current) {
|
||||
List<DiagnosisEvalDiffItem> items = new ArrayList<>();
|
||||
|
||||
compareDouble(items, "aggregate", null, "passRate",
|
||||
baseline.getPassRate(), current.getPassRate(), true);
|
||||
compareDouble(items, "aggregate", null, "averageToolCallCount",
|
||||
baseline.getAverageToolCallCount(), current.getAverageToolCallCount(), false);
|
||||
compareDouble(items, "aggregate", null, "averageDurationMs",
|
||||
baseline.getAverageDurationMs(), current.getAverageDurationMs(), false);
|
||||
compareVerdictDistribution(items, baseline.getVerdictDistribution(), current.getVerdictDistribution());
|
||||
compareCases(items, safeResults(baseline), safeResults(current));
|
||||
|
||||
int regressionCount = countType(items, REGRESSION);
|
||||
int improvementCount = countType(items, IMPROVEMENT);
|
||||
int changedCount = countType(items, CHANGED);
|
||||
|
||||
return DiagnosisEvalDiffReport.builder()
|
||||
.baselineTotalCases(baseline.getTotalCases())
|
||||
.currentTotalCases(current.getTotalCases())
|
||||
.baselinePassedCases(baseline.getPassedCases())
|
||||
.currentPassedCases(current.getPassedCases())
|
||||
.baselinePassRate(baseline.getPassRate())
|
||||
.currentPassRate(current.getPassRate())
|
||||
.regressionCount(regressionCount)
|
||||
.improvementCount(improvementCount)
|
||||
.changedCount(changedCount)
|
||||
.hasRegression(regressionCount > 0)
|
||||
.items(items)
|
||||
.build();
|
||||
}
|
||||
|
||||
private void compareVerdictDistribution(List<DiagnosisEvalDiffItem> items,
|
||||
Map<String, Long> baseline,
|
||||
Map<String, Long> current) {
|
||||
Set<String> verdicts = new LinkedHashSet<>();
|
||||
verdicts.addAll(safeMap(baseline).keySet());
|
||||
verdicts.addAll(safeMap(current).keySet());
|
||||
for (String verdict : verdicts) {
|
||||
long baselineCount = safeMap(baseline).getOrDefault(verdict, 0L);
|
||||
long currentCount = safeMap(current).getOrDefault(verdict, 0L);
|
||||
if (baselineCount != currentCount) {
|
||||
items.add(item(CHANGED, "aggregate", null, "verdictDistribution." + verdict,
|
||||
String.valueOf(baselineCount), String.valueOf(currentCount),
|
||||
(double) currentCount - baselineCount,
|
||||
"verdict count changed for " + verdict));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void compareCases(List<DiagnosisEvalDiffItem> items,
|
||||
List<DiagnosisEvalResult> baselineResults,
|
||||
List<DiagnosisEvalResult> currentResults) {
|
||||
Map<String, DiagnosisEvalResult> baselineById = byCaseId(baselineResults);
|
||||
Map<String, DiagnosisEvalResult> currentById = byCaseId(currentResults);
|
||||
Set<String> caseIds = new LinkedHashSet<>();
|
||||
caseIds.addAll(baselineById.keySet());
|
||||
caseIds.addAll(currentById.keySet());
|
||||
|
||||
for (String caseId : caseIds) {
|
||||
DiagnosisEvalResult baseline = baselineById.get(caseId);
|
||||
DiagnosisEvalResult current = currentById.get(caseId);
|
||||
if (baseline == null) {
|
||||
items.add(item(CHANGED, "case", caseId, "casePresence",
|
||||
"missing", "present", null, "new case appears in current report"));
|
||||
continue;
|
||||
}
|
||||
if (current == null) {
|
||||
items.add(item(REGRESSION, "case", caseId, "casePresence",
|
||||
"present", "missing", null, "baseline case is missing from current report"));
|
||||
continue;
|
||||
}
|
||||
|
||||
comparePassState(items, baseline, current);
|
||||
compareVerdict(items, baseline, current);
|
||||
compareInteger(items, caseId, "matchedKeywordCount",
|
||||
baseline.getMatchedKeywordCount(), current.getMatchedKeywordCount(), true);
|
||||
compareInteger(items, caseId, "toolCallCount",
|
||||
baseline.getToolCallCount(), current.getToolCallCount(), false);
|
||||
compareInteger(items, caseId, "durationMs",
|
||||
baseline.getDurationMs(), current.getDurationMs(), false);
|
||||
compareEvidenceCoverage(items, baseline, current);
|
||||
}
|
||||
}
|
||||
|
||||
private void comparePassState(List<DiagnosisEvalDiffItem> items,
|
||||
DiagnosisEvalResult baseline,
|
||||
DiagnosisEvalResult current) {
|
||||
if (baseline.isPassed() == current.isPassed()) {
|
||||
return;
|
||||
}
|
||||
String type = baseline.isPassed() ? REGRESSION : IMPROVEMENT;
|
||||
items.add(item(type, "case", baseline.getCaseId(), "passed",
|
||||
String.valueOf(baseline.isPassed()), String.valueOf(current.isPassed()), null,
|
||||
baseline.getCaseId() + " pass state changed"));
|
||||
}
|
||||
|
||||
private void compareVerdict(List<DiagnosisEvalDiffItem> items,
|
||||
DiagnosisEvalResult baseline,
|
||||
DiagnosisEvalResult current) {
|
||||
if (Objects.equals(baseline.getVerdict(), current.getVerdict())) {
|
||||
return;
|
||||
}
|
||||
int baselineRank = verdictRank(baseline.getVerdict());
|
||||
int currentRank = verdictRank(current.getVerdict());
|
||||
String type = currentRank < baselineRank ? REGRESSION : currentRank > baselineRank ? IMPROVEMENT : CHANGED;
|
||||
items.add(item(type, "case", baseline.getCaseId(), "verdict",
|
||||
value(baseline.getVerdict()), value(current.getVerdict()), (double) currentRank - baselineRank,
|
||||
baseline.getCaseId() + " verdict changed"));
|
||||
}
|
||||
|
||||
private void compareEvidenceCoverage(List<DiagnosisEvalDiffItem> items,
|
||||
DiagnosisEvalResult baseline,
|
||||
DiagnosisEvalResult current) {
|
||||
Set<String> tools = new LinkedHashSet<>();
|
||||
tools.addAll(safeMap(baseline.getEvidenceCoverage()).keySet());
|
||||
tools.addAll(safeMap(current.getEvidenceCoverage()).keySet());
|
||||
for (String tool : tools) {
|
||||
boolean baselineCovered = Boolean.TRUE.equals(safeMap(baseline.getEvidenceCoverage()).get(tool));
|
||||
boolean currentCovered = Boolean.TRUE.equals(safeMap(current.getEvidenceCoverage()).get(tool));
|
||||
if (baselineCovered == currentCovered) {
|
||||
continue;
|
||||
}
|
||||
String type = baselineCovered ? REGRESSION : IMPROVEMENT;
|
||||
items.add(item(type, "case", baseline.getCaseId(), "evidenceCoverage." + tool,
|
||||
String.valueOf(baselineCovered), String.valueOf(currentCovered), null,
|
||||
baseline.getCaseId() + " evidence coverage changed for " + tool));
|
||||
}
|
||||
}
|
||||
|
||||
private void compareDouble(List<DiagnosisEvalDiffItem> items,
|
||||
String scope,
|
||||
String caseId,
|
||||
String metric,
|
||||
double baseline,
|
||||
double current,
|
||||
boolean higherIsBetter) {
|
||||
if (Double.compare(baseline, current) == 0) {
|
||||
return;
|
||||
}
|
||||
double delta = current - baseline;
|
||||
String type = classifyDelta(delta, higherIsBetter);
|
||||
items.add(item(type, scope, caseId, metric,
|
||||
String.valueOf(baseline), String.valueOf(current), delta,
|
||||
metric + " changed"));
|
||||
}
|
||||
|
||||
private void compareInteger(List<DiagnosisEvalDiffItem> items,
|
||||
String caseId,
|
||||
String metric,
|
||||
Integer baseline,
|
||||
Integer current,
|
||||
boolean higherIsBetter) {
|
||||
if (Objects.equals(baseline, current)) {
|
||||
return;
|
||||
}
|
||||
if (baseline == null || current == null) {
|
||||
items.add(item(CHANGED, "case", caseId, metric,
|
||||
value(baseline), value(current), null, caseId + " " + metric + " changed"));
|
||||
return;
|
||||
}
|
||||
int delta = current - baseline;
|
||||
items.add(item(classifyDelta(delta, higherIsBetter), "case", caseId, metric,
|
||||
String.valueOf(baseline), String.valueOf(current), (double) delta,
|
||||
caseId + " " + metric + " changed"));
|
||||
}
|
||||
|
||||
private String classifyDelta(double delta, boolean higherIsBetter) {
|
||||
if (delta == 0.0) {
|
||||
return CHANGED;
|
||||
}
|
||||
boolean improved = higherIsBetter ? delta > 0 : delta < 0;
|
||||
return improved ? IMPROVEMENT : REGRESSION;
|
||||
}
|
||||
|
||||
private DiagnosisEvalDiffItem item(String type,
|
||||
String scope,
|
||||
String caseId,
|
||||
String metric,
|
||||
String baselineValue,
|
||||
String currentValue,
|
||||
Double delta,
|
||||
String message) {
|
||||
return DiagnosisEvalDiffItem.builder()
|
||||
.type(type)
|
||||
.scope(scope)
|
||||
.caseId(caseId)
|
||||
.metric(metric)
|
||||
.baselineValue(baselineValue)
|
||||
.currentValue(currentValue)
|
||||
.delta(delta)
|
||||
.message(message)
|
||||
.build();
|
||||
}
|
||||
|
||||
private Map<String, DiagnosisEvalResult> byCaseId(List<DiagnosisEvalResult> results) {
|
||||
return results.stream()
|
||||
.sorted(Comparator.comparing(DiagnosisEvalResult::getCaseId))
|
||||
.collect(Collectors.toMap(
|
||||
DiagnosisEvalResult::getCaseId,
|
||||
Function.identity(),
|
||||
(left, right) -> right,
|
||||
LinkedHashMap::new));
|
||||
}
|
||||
|
||||
private List<DiagnosisEvalResult> safeResults(DiagnosisEvalReport report) {
|
||||
return report.getResults() == null ? List.of() : report.getResults();
|
||||
}
|
||||
|
||||
private <T> Map<String, T> safeMap(Map<String, T> value) {
|
||||
return value == null ? Map.of() : value;
|
||||
}
|
||||
|
||||
private int countType(List<DiagnosisEvalDiffItem> items, String type) {
|
||||
return (int) items.stream().filter(item -> type.equals(item.getType())).count();
|
||||
}
|
||||
|
||||
private int verdictRank(String verdict) {
|
||||
if ("PASS".equals(verdict)) {
|
||||
return 3;
|
||||
}
|
||||
if ("LOW_CONFID".equals(verdict)) {
|
||||
return 2;
|
||||
}
|
||||
if ("REJECT".equals(verdict)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private String value(Object value) {
|
||||
return value == null ? "-" : String.valueOf(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.superbiz.agent.eval;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DiagnosisEvalDiffItem {
|
||||
|
||||
private String type;
|
||||
private String scope;
|
||||
private String caseId;
|
||||
private String metric;
|
||||
private String baselineValue;
|
||||
private String currentValue;
|
||||
private Double delta;
|
||||
private String message;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.superbiz.agent.eval;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DiagnosisEvalDiffReport {
|
||||
|
||||
private int baselineTotalCases;
|
||||
private int currentTotalCases;
|
||||
private int baselinePassedCases;
|
||||
private int currentPassedCases;
|
||||
private double baselinePassRate;
|
||||
private double currentPassRate;
|
||||
private int regressionCount;
|
||||
private int improvementCount;
|
||||
private int changedCount;
|
||||
private boolean hasRegression;
|
||||
private List<DiagnosisEvalDiffItem> items;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.superbiz.agent.eval;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class DiagnosisEvalDiffReportWriter {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public DiagnosisEvalDiffReportWriter(ObjectMapper objectMapper) {
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
public void writeJson(DiagnosisEvalDiffReport report, Path outputFile) throws IOException {
|
||||
Files.createDirectories(outputFile.getParent());
|
||||
objectMapper.writerWithDefaultPrettyPrinter().writeValue(outputFile.toFile(), report);
|
||||
}
|
||||
|
||||
public void writeMarkdown(DiagnosisEvalDiffReport report, Path outputFile) throws IOException {
|
||||
Files.createDirectories(outputFile.getParent());
|
||||
Files.writeString(outputFile, toMarkdown(report), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public String toMarkdown(DiagnosisEvalDiffReport report) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("# Diagnosis Eval Baseline Diff\n\n");
|
||||
builder.append("- Baseline pass rate: ").append(formatPercent(report.getBaselinePassRate())).append("\n");
|
||||
builder.append("- Current pass rate: ").append(formatPercent(report.getCurrentPassRate())).append("\n");
|
||||
builder.append("- Baseline passed cases: ").append(report.getBaselinePassedCases()).append("/")
|
||||
.append(report.getBaselineTotalCases()).append("\n");
|
||||
builder.append("- Current passed cases: ").append(report.getCurrentPassedCases()).append("/")
|
||||
.append(report.getCurrentTotalCases()).append("\n");
|
||||
builder.append("- Regressions: ").append(report.getRegressionCount()).append("\n");
|
||||
builder.append("- Improvements: ").append(report.getImprovementCount()).append("\n");
|
||||
builder.append("- Other changes: ").append(report.getChangedCount()).append("\n\n");
|
||||
|
||||
builder.append("## Diff Items\n\n");
|
||||
if (report.getItems() == null || report.getItems().isEmpty()) {
|
||||
builder.append("- No differences\n");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
builder.append("| Type | Scope | Case | Metric | Baseline | Current | Delta | Message |\n");
|
||||
builder.append("| --- | --- | --- | --- | --- | --- | ---: | --- |\n");
|
||||
for (DiagnosisEvalDiffItem item : report.getItems()) {
|
||||
builder.append("| ")
|
||||
.append(valueOrDash(item.getType()))
|
||||
.append(" | ")
|
||||
.append(valueOrDash(item.getScope()))
|
||||
.append(" | ")
|
||||
.append(valueOrDash(item.getCaseId()))
|
||||
.append(" | ")
|
||||
.append(valueOrDash(item.getMetric()))
|
||||
.append(" | ")
|
||||
.append(valueOrDash(item.getBaselineValue()))
|
||||
.append(" | ")
|
||||
.append(valueOrDash(item.getCurrentValue()))
|
||||
.append(" | ")
|
||||
.append(item.getDelta() == null ? "-" : String.format("%.3f", item.getDelta()))
|
||||
.append(" | ")
|
||||
.append(valueOrDash(item.getMessage()))
|
||||
.append(" |\n");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String formatPercent(double value) {
|
||||
return String.format("%.2f%%", value * 100);
|
||||
}
|
||||
|
||||
private String valueOrDash(String value) {
|
||||
return value == null || value.isBlank() ? "-" : value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.superbiz.agent.eval;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class DiagnosisEvalBaselineDiffTest {
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private final DiagnosisEvalBaselineDiffer differ = new DiagnosisEvalBaselineDiffer();
|
||||
|
||||
@Test
|
||||
void compareReportsDetectsAggregateAndCaseRegressions() throws Exception {
|
||||
DiagnosisEvalReport baseline = readBaselineReport();
|
||||
DiagnosisEvalReport current = readBaselineReport();
|
||||
degradeRedisCase(current);
|
||||
|
||||
DiagnosisEvalDiffReport diff = differ.compare(baseline, current);
|
||||
|
||||
assertTrue(diff.isHasRegression());
|
||||
assertEquals(6, diff.getRegressionCount());
|
||||
assertEquals(2, diff.getChangedCount());
|
||||
assertTrue(hasItem(diff, "REGRESSION", "aggregate", null, "passRate"));
|
||||
assertTrue(hasItem(diff, "REGRESSION", "aggregate", null, "averageToolCallCount"));
|
||||
assertTrue(hasItem(diff, "REGRESSION", "case", "redis-timeout", "passed"));
|
||||
assertTrue(hasItem(diff, "REGRESSION", "case", "redis-timeout", "verdict"));
|
||||
assertTrue(hasItem(diff, "REGRESSION", "case", "redis-timeout", "matchedKeywordCount"));
|
||||
assertTrue(hasItem(diff, "REGRESSION", "case", "redis-timeout", "evidenceCoverage.query_logs"));
|
||||
assertTrue(hasItem(diff, "CHANGED", "aggregate", null, "verdictDistribution.LOW_CONFID"));
|
||||
assertTrue(hasItem(diff, "CHANGED", "aggregate", null, "verdictDistribution.REJECT"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void compareReportsDetectsMissingAndNewCases() throws Exception {
|
||||
DiagnosisEvalReport baseline = readBaselineReport();
|
||||
DiagnosisEvalReport current = readBaselineReport();
|
||||
DiagnosisEvalResult removed = current.getResults().remove(0);
|
||||
current.getResults().add(DiagnosisEvalResult.builder()
|
||||
.caseId("new-case")
|
||||
.title("New case")
|
||||
.passed(true)
|
||||
.failedChecks(List.of())
|
||||
.verdict("PASS")
|
||||
.matchedKeywordCount(1)
|
||||
.requiredKeywordCount(1)
|
||||
.evidenceCoverage(new LinkedHashMap<>())
|
||||
.toolCallCount(1)
|
||||
.durationMs(1000)
|
||||
.build());
|
||||
|
||||
DiagnosisEvalDiffReport diff = differ.compare(baseline, current);
|
||||
|
||||
assertTrue(hasItem(diff, "REGRESSION", "case", removed.getCaseId(), "casePresence"));
|
||||
assertTrue(hasItem(diff, "CHANGED", "case", "new-case", "casePresence"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void compareSameReportHasNoDiff() throws Exception {
|
||||
DiagnosisEvalReport baseline = readBaselineReport();
|
||||
|
||||
DiagnosisEvalDiffReport diff = differ.compare(baseline, readBaselineReport());
|
||||
|
||||
assertFalse(diff.isHasRegression());
|
||||
assertEquals(0, diff.getRegressionCount());
|
||||
assertTrue(diff.getItems().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void writerOutputsJsonAndMarkdown(@TempDir Path tempDir) throws Exception {
|
||||
DiagnosisEvalReport baseline = readBaselineReport();
|
||||
DiagnosisEvalReport current = readBaselineReport();
|
||||
degradeRedisCase(current);
|
||||
DiagnosisEvalDiffReport diff = differ.compare(baseline, current);
|
||||
DiagnosisEvalDiffReportWriter writer = new DiagnosisEvalDiffReportWriter(objectMapper);
|
||||
|
||||
Path json = tempDir.resolve("baseline-diff.json");
|
||||
Path markdown = tempDir.resolve("baseline-diff.md");
|
||||
writer.writeJson(diff, json);
|
||||
writer.writeMarkdown(diff, markdown);
|
||||
|
||||
assertTrue(Files.exists(json));
|
||||
assertTrue(Files.readString(json).contains("\"hasRegression\" : true"));
|
||||
assertTrue(Files.readString(markdown).contains("# Diagnosis Eval Baseline Diff"));
|
||||
assertTrue(Files.readString(markdown).contains("redis-timeout"));
|
||||
}
|
||||
|
||||
private DiagnosisEvalReport readBaselineReport() throws Exception {
|
||||
return objectMapper.readValue(Path.of("mvp/eval/reports/baseline-report.json").toFile(),
|
||||
DiagnosisEvalReport.class);
|
||||
}
|
||||
|
||||
private void degradeRedisCase(DiagnosisEvalReport report) {
|
||||
report.setPassedCases(4);
|
||||
report.setPassRate(0.8);
|
||||
report.setAverageToolCallCount(3.0);
|
||||
report.setAverageDurationMs(45800.0);
|
||||
report.setVerdictDistribution(new LinkedHashMap<>());
|
||||
report.getVerdictDistribution().put("PASS", 2L);
|
||||
report.getVerdictDistribution().put("LOW_CONFID", 2L);
|
||||
report.getVerdictDistribution().put("REJECT", 1L);
|
||||
|
||||
DiagnosisEvalResult redis = result(report, "redis-timeout");
|
||||
redis.setPassed(false);
|
||||
redis.setFailedChecks(new ArrayList<>(List.of("missing required evidence tool: query_logs")));
|
||||
redis.setVerdict("REJECT");
|
||||
redis.setMatchedKeywordCount(1);
|
||||
redis.getEvidenceCoverage().put("query_logs", false);
|
||||
redis.setToolCallCount(1);
|
||||
redis.setDurationMs(36000);
|
||||
}
|
||||
|
||||
private DiagnosisEvalResult result(DiagnosisEvalReport report, String caseId) {
|
||||
return report.getResults().stream()
|
||||
.filter(item -> caseId.equals(item.getCaseId()))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
private boolean hasItem(DiagnosisEvalDiffReport diff,
|
||||
String type,
|
||||
String scope,
|
||||
String caseId,
|
||||
String metric) {
|
||||
return diff.getItems().stream().anyMatch(item ->
|
||||
type.equals(item.getType())
|
||||
&& scope.equals(item.getScope())
|
||||
&& java.util.Objects.equals(caseId, item.getCaseId())
|
||||
&& metric.equals(item.getMetric()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user