Paste a quote, get a Veer Factor score. How far outside their expertise is the speaker? From 'In Lane' to 'Car Crash'.
import React, { useState, useEffect, useRef } from "react";
import { createRoot } from "react-dom/client";
interface Insight {
person: string;
quote: string;
score: number;
field: string;
expertise: string;
explanation: string;
experts: { name: string; credential: string }[];
expertsSummary: string;
}
function veerLabel(score: number): string {
if (score <= 15) return "In Lane";
if (score <= 35) return "Drifting";
if (score <= 55) return "Swerving";
if (score <= 75) return "Wrong Lane";
return "Car Crash";
}
function veerColor(score: number): string {
if (score <= 20) return "#16a34a";
if (score <= 40) return "#22c55e";
if (score <= 60) return "#fbbf24";
if (score <= 80) return "#f97316";
return "#ef4444";
}
function Road({ score, expertise, field, numExperts }: { score: number; expertise: string; field: string; numExperts: number }) {
const roadRef = useRef<HTMLDivElement>(null);
const walshRef = useRef<HTMLDivElement>(null);
const expertRefs = useRef<(HTMLDivElement | null)[]>([]);
useEffect(() => {
const road = roadRef.current;
const walsh = walshRef.current;
if (!road || !walsh) return;
let frame: number;
const start = performance.now();
const walshCycle = 4;
const expertCycle = 8;
const carH = 34;
const carW = 18;
const crashCooldowns = new Set<number>();
const animate = () => {
const t = (performance.now() - start) / 1000;
const roadH = road.clientHeight;
// Walsh: top to bottom
const walshProgress = (t % walshCycle) / walshCycle;
const walshY = -carH + walshProgress * (roadH + carH);
const maxSwerve = (score / 100) * 30;
const swerve =
Math.sin(t * 1.7) * 0.5 +
Math.sin(t * 2.9) * 0.3 +
Math.sin(t * 4.3) * 0.2;
const walshX = 6 + maxSwerve * (swerve + 1) / 2;
walsh.style.top = `${walshY}px`;
walsh.style.left = `${walshX}px`;
// Expert cars: bottom to top, staggered
let anyHit = false;
for (let i = 0; i < numExperts; i++) {
const el = expertRefs.current[i];
if (!el) continue;
const offset = i / numExperts;
const expertProgress = ((t / expertCycle + offset) % 1);
const expertY = roadH + carH - expertProgress * (roadH + carH * 2);
const expertX = 34;
el.style.top = `${expertY}px`;
el.style.left = `${expertX}px`;
const hit = Math.abs(walshY - expertY) < carH && Math.abs(walshX - expertX) < carW;
if (hit) {
anyHit = true;
if (!crashCooldowns.has(i)) {
crashCooldowns.add(i);
const burst = document.createElement('div');
burst.className = 'crash-burst';
burst.style.top = `${(walshY + expertY) / 2 + carH / 2}px`;
burst.style.left = `${(walshX + expertX) / 2 + carW / 2}px`;
road.appendChild(burst);
setTimeout(() => burst.remove(), 600);
}
el.style.filter = 'brightness(2)';
} else {
crashCooldowns.delete(i);
el.style.filter = '';
}
}
walsh.style.filter = anyHit ? 'brightness(2)' : '';
frame = requestAnimationFrame(animate);
};
frame = requestAnimationFrame(animate);
return () => cancelAnimationFrame(frame);
}, [score, numExperts]);
return (
<div className="road" ref={roadRef}>
<div className="lane">
<span className="lane-text" style={{ color: veerColor(score) }}>{expertise}</span>
</div>
<div className="lane-divider" />
<div className="lane">
<span className="lane-text lane-text-field">{field}</span>
</div>
<div className="car" ref={walshRef} style={{ backgroundColor: veerColor(score) }} />
{Array.from({ length: numExperts }, (_, i) => (
<div
key={i}
className="car car-expert"
ref={el => { expertRefs.current[i] = el; }}
/>
))}
</div>
);
}
function App() {
const [insight, setInsight] = useState<Insight | null>(() => {
try { return tb.insight<Insight>(); } catch { return null; }
});
const [isGenerating, setIsGenerating] = useState(false);
const handleAnalyze = async () => {
setIsGenerating(true);
try {
const result = await tb.infer<Insight>();
if (result) setInsight(result);
} finally {
setIsGenerating(false);
}
};
return (
<div className="app">
<header>
<div>
<h1>Veer Factor</h1>
<span className="tagline">Stay in your lane.</span>
</div>
<button className={`analyze-btn ${isGenerating ? "loading" : ""}`} onClick={handleAnalyze}>
{isGenerating ? "Analyzing..." : "Analyze Quote"}
</button>
</header>
{insight && (
<div className="card">
<div className="score-label" style={{ color: veerColor(insight.score) }}>
<div className="score-value">{Math.round(insight.score / 10)}/10</div>
<div className="score-text">{veerLabel(insight.score)}</div>
</div>
<div className="card-body">
<div className="body-left">
<div className="card-person" style={{ color: veerColor(insight.score) }}>{insight.person}</div>
<blockquote className="card-quote">"{insight.quote}"</blockquote>
</div>
<Road score={insight.score} expertise={insight.expertise} field={insight.field} numExperts={insight.experts?.length ?? 0} />
<div className="body-right">
{insight.experts && insight.experts.length > 0 && (
<>
<div className="experts-list">
{insight.experts.map((e, i) => (
<div key={i} className="expert-row">
<span className="expert-name" style={{ color: '#16a34a' }}>{e.name}</span>
<span className="expert-credential">{e.credential}</span>
</div>
))}
</div>
{insight.expertsSummary && (
<div className="experts-summary">{insight.expertsSummary}</div>
)}
</>
)}
<p className="card-explanation">{insight.explanation}</p>
</div>
</div>
</div>
)}
{!insight && (
<div className="empty">
<p>Paste a quote to the Data tab, then click "Analyze Quote".</p>
<p className="hint">Format: Name: "What they said"</p>
</div>
)}
</div>
);
}
createRoot(document.getElementById("root")!).render(<App />);