activity-simulation / src /components /MlModelCard.jsx
Augusto Diaz
Space: dashboard only
5b7eaab
Raw
History Blame Contribute Delete
3.53 kB
import React from 'react';
import { formatNumber, getProgressBarStyle } from '../utils/formatters';
const MlModelCard = ({ riskAssessment, modelMeta, onRefresh, onShowHelp, loading }) => {
const mlScore = riskAssessment?.evidence?.onnxScore;
const heuristicScore = riskAssessment?.evidence?.heuristicRisk;
// Calculate model confidence based on agreement between ML and heuristic scores
const calculateConfidence = () => {
if (mlScore === null || mlScore === undefined || heuristicScore === null || heuristicScore === undefined) {
return 0;
}
const difference = Math.abs(mlScore - heuristicScore);
if (difference < 0.2) return 0.9; // High confidence if scores agree
if (difference < 0.4) return 0.6; // Medium confidence
return 0.3; // Low confidence
};
const confidence = calculateConfidence();
// Determine model status
const getModelStatus = () => {
if (!modelMeta) return 'Loading...';
if (modelMeta.modelPresent && modelMeta.oneClassSvmPresent) {
return 'Level 2 Active (Isolation Forest + One-Class SVM)';
} else if (modelMeta.modelPresent) {
return 'Level 2 Partial (Isolation Forest only)';
} else {
return 'Level 1 Only (Heuristics)';
}
};
return (
<div className="card">
<h3>
ML Model (Level 2)
<button className="help-btn" onClick={onShowHelp} title="Help">?</button>
</h3>
<div className="content">
{/* ML Anomaly Score */}
<div style={{ marginBottom: '16px' }}>
<div className="muted" style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px' }}>
<span>ML Anomaly Score</span>
<span>{mlScore !== null && mlScore !== undefined ? formatNumber(mlScore, 3) : '–'}</span>
</div>
<div className="bar">
<div
style={{
...getProgressBarStyle(mlScore || 0, 'ml-score'),
height: '100%',
borderRadius: '999px',
}}
/>
</div>
</div>
{/* Model Confidence */}
<div style={{ marginBottom: '16px' }}>
<div className="muted" style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px' }}>
<span>Model Confidence</span>
<span>{formatNumber(confidence, 2)}</span>
</div>
<div className="bar">
<div
style={{
...getProgressBarStyle(confidence, 'confidence'),
height: '100%',
borderRadius: '999px',
}}
/>
</div>
</div>
{/* Model Status */}
<div className="muted" style={{ fontSize: '12px', marginBottom: '12px' }}>
Model Status: <span style={{ fontWeight: '500' }}>{getModelStatus()}</span>
</div>
{/* Refresh Button */}
<div>
<button
className="btn btn-secondary"
onClick={onRefresh}
disabled={loading}
style={{
width: '100%',
opacity: loading ? 0.6 : 1,
cursor: loading ? 'not-allowed' : 'pointer'
}}
>
{loading ? (
<>
<span className="spinner" />
Refreshing...
</>
) : (
'Refresh Model'
)}
</button>
</div>
</div>
</div>
);
};
export default MlModelCard;