import { useEffect, useRef, useState } from 'react'
import { IconChartBar, IconCpu, IconDatabase, IconRobot, IconServer } from '@tabler/icons-react'
import CircularGauge from '~/components/systeminfo/CircularGauge'
import StyledButton from '~/components/StyledButton'
import { getScoreDisplay } from '~/lib/benchmarkScore'
import BenchmarkResult from '#models/benchmark_result'
interface ScoreRevealProps {
result: BenchmarkResult
scoreScale?: { max: number; caption: string }
onDone: () => void
}
// Same thresholds as the NOMAD Score section on the benchmark page.
const getScoreColor = (score: number) => {
if (score >= 70) return 'text-green-600'
if (score >= 40) return 'text-yellow-600'
return 'text-red-600'
}
// AI tokens/sec normalized to 0-100 (30 tok/s = 50, 60 tok/s = 100),
// mirroring the benchmark page's getAIScore.
const getAIScore = (tokensPerSecond: number): number =>
Math.min(100, Math.max(0, (tokensPerSecond / 60) * 100))
/** rAF count-up from 0 to `target` with ease-out, for the big score number. */
function useCountUp(target: number, durationMs = 1200): number {
const [value, setValue] = useState(0)
useEffect(() => {
let raf = 0
const start = performance.now()
const tick = (now: number) => {
const t = Math.min(1, (now - start) / durationMs)
const eased = 1 - Math.pow(1 - t, 3)
setValue(target * eased)
if (t < 1) raf = requestAnimationFrame(tick)
}
raf = requestAnimationFrame(tick)
return () => cancelAnimationFrame(raf)
}, [target, durationMs])
return value
}
/**
* End-of-run score reveal. Replaces the abrupt unmount of the live run view
* with a deliberate report: big NOMAD score gauge + count-up number, then the
* sub-score gauges cascading in. Dismisses via the Continue button or an
* auto-dismiss timer.
*/
export default function ScoreReveal({
result,
scoreScale = { max: 100, caption: 'out of 100' },
onDone,
}: ScoreRevealProps) {
const displayScore = useCountUp(result.nomad_score)
// A partial (System/AI Only) run is not the NOMAD Score -- relabel + flag it.
const scoreInfo = getScoreDisplay(result.benchmark_type)
// Sub-score gauges, mirroring the System Performance / AI Performance grids.
const gauges: {
label: string
value: number
variant: 'cpu' | 'memory' | 'disk'
icon: React.ReactNode
}[] = [
{ label: 'CPU', value: result.cpu_score * 100, variant: 'cpu', icon:
{scoreInfo.isPartial ? scoreInfo.cta : 'Your NOMAD Score is a weighted composite of all benchmark results.'}