feat(小宝预警): 增加日报证据与风险趋势
This commit is contained in:
@@ -13,3 +13,81 @@ export interface XiaobaoRiskSnapshot {
|
||||
confidence: number;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface RiskTrendSummary {
|
||||
direction: 'up' | 'down' | 'flat' | 'unknown';
|
||||
delta: number;
|
||||
summary: string;
|
||||
pattern: 'continuous_rising' | 'continuous_falling' | 'score_delta' | 'stable' | 'unknown';
|
||||
}
|
||||
|
||||
export function summarizeRiskTrend(snapshots: XiaobaoRiskSnapshot[]): RiskTrendSummary {
|
||||
const sorted = [...snapshots].sort((a, b) => getSnapshotTime(a) - getSnapshotTime(b));
|
||||
if (sorted.length < 2) {
|
||||
return { direction: 'unknown', delta: 0, summary: 'No historical risk snapshots yet.', pattern: 'unknown' };
|
||||
}
|
||||
|
||||
const first = sorted[0];
|
||||
const latest = sorted[sorted.length - 1];
|
||||
const delta = clampScore(latest.riskScore) - clampScore(first.riskScore);
|
||||
const recentThree = sorted.slice(-3);
|
||||
|
||||
if (recentThree.length === 3) {
|
||||
const [a, b, c] = recentThree.map((snapshot) => clampScore(snapshot.riskScore));
|
||||
if (a < b && b < c) {
|
||||
return {
|
||||
direction: 'up',
|
||||
delta,
|
||||
summary: `Risk rose continuously from ${a} to ${c}.`,
|
||||
pattern: 'continuous_rising',
|
||||
};
|
||||
}
|
||||
if (a > b && b > c) {
|
||||
return {
|
||||
direction: 'down',
|
||||
delta,
|
||||
summary: `Risk fell continuously from ${a} to ${c}.`,
|
||||
pattern: 'continuous_falling',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (delta >= 10) {
|
||||
return { direction: 'up', delta, summary: `Risk rose by ${delta} points.`, pattern: 'score_delta' };
|
||||
}
|
||||
if (delta <= -10) {
|
||||
return { direction: 'down', delta, summary: `Risk fell by ${Math.abs(delta)} points.`, pattern: 'score_delta' };
|
||||
}
|
||||
return { direction: 'flat', delta, summary: 'Risk is stable.', pattern: 'stable' };
|
||||
}
|
||||
|
||||
export function summarizeRiskTrendWithCurrent(
|
||||
snapshots: XiaobaoRiskSnapshot[] = [],
|
||||
current: XiaobaoRiskSnapshot,
|
||||
): RiskTrendSummary {
|
||||
return summarizeRiskTrend([...snapshots, current]);
|
||||
}
|
||||
|
||||
export function buildRiskSignature(snapshot: XiaobaoRiskSnapshot): string {
|
||||
return [
|
||||
snapshot.versionId,
|
||||
snapshot.date,
|
||||
clampScore(snapshot.riskScore),
|
||||
snapshot.riskLevel,
|
||||
snapshot.forecastReleaseDate ?? '',
|
||||
snapshot.openBugCount,
|
||||
snapshot.failedTestCount,
|
||||
snapshot.blockedCount,
|
||||
snapshot.silentRiskCount,
|
||||
clampScore(snapshot.confidence),
|
||||
].join('|');
|
||||
}
|
||||
|
||||
function getSnapshotTime(snapshot: XiaobaoRiskSnapshot): number {
|
||||
const date = new Date(snapshot.createdAt || snapshot.date).getTime();
|
||||
return Number.isFinite(date) ? date : 0;
|
||||
}
|
||||
|
||||
function clampScore(score: number): number {
|
||||
return Math.max(0, Math.min(100, Math.round(score)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user