import React, { useMemo } from 'react'; import { Bar, BarChart, XAxis, YAxis, CartesianGrid, Cell, ResponsiveContainer } from 'recharts'; import { useGridStore } from '../../store/gridStore'; import { Card, CardContent, CardHeader, CardTitle } from '../ui/card'; import { Button } from '../ui/button'; import { BarChart3, Activity, Clock, HardDrive, Route, Play, RefreshCw, Check, FlaskConical, Trophy, Medal, TrendingDown, } from 'lucide-react'; export const ComparisonDashboard: React.FC = () => { const { comparisonResults, runComparison, isLoading, grid } = useGridStore(); // Sort results by cost (best to worst) const sortedResults = useMemo(() => { if (!comparisonResults) return null; return [...comparisonResults].sort((a, b) => { if (a.cost === Infinity && b.cost === Infinity) return 0; if (a.cost === Infinity) return 1; if (b.cost === Infinity) return -1; return a.cost - b.cost; }); }, [comparisonResults]); // Prepare sorted chart data for each metric const chartDataByMetric = useMemo(() => { if (!comparisonResults) return null; const baseData = comparisonResults.map((r) => ({ name: r.algorithm, fullName: r.name, nodesExpanded: r.nodesExpanded, runtime: r.runtimeMs, cost: r.cost === Infinity ? 0 : r.cost, memory: r.memoryKb, isOptimal: r.isOptimal, })); return { nodes: [...baseData].sort((a, b) => b.nodesExpanded - a.nodesExpanded), runtime: [...baseData].sort((a, b) => b.runtime - a.runtime), cost: [...baseData].sort((a, b) => b.cost - a.cost), memory: [...baseData].sort((a, b) => b.memory - a.memory), }; }, [comparisonResults]); if (!grid) { return (

Generate a grid first

Then compare all algorithms

); } if (!comparisonResults) { return (

Compare Search Algorithms

); } const getRankIcon = (index: number) => { if (index === 0) return ; if (index === 1) return ; if (index === 2) return ; return {index + 1}; }; // Custom tooltip const CustomTooltip = ({ active, payload }: any) => { if (active && payload && payload.length) { const data = payload[0].payload; return (

{data.fullName}

{payload[0].name}: {typeof payload[0].value === 'number' ? payload[0].value.toLocaleString(undefined, { maximumFractionDigits: 2 }) : payload[0].value}

); } return null; }; // Chart component with gradient const GradientBarChart = ({ data, dataKey, title, icon: Icon, gradientId, }: { data: any[]; dataKey: string; title: string; icon: React.ElementType; gradientId: string; unit?: string; }) => { return (
{title}
Sorted high to low
value.toLocaleString()} /> {data.map((entry, index) => { // Highlight the best performer (lowest value for cost, or mark optimal) const isBest = entry.isOptimal || (dataKey === 'cost' && entry[dataKey] === Math.min(...data.filter(d => d[dataKey] > 0).map(d => d[dataKey]))); return ( ); })}
); }; return (

Algorithm Comparison

8 algorithms on the same problem instance

{/* Charts Grid */}
{/* Results Table - Sorted by best to worst */} Rankings (Best to Worst by Path Cost)
{sortedResults?.map((result, index) => ( ))}
Rank Algorithm Cost Nodes Runtime Memory Optimal
{getRankIcon(index)} {result.name} ({result.algorithm}) {result.cost === Infinity ? 'No path' : result.cost} {result.nodesExpanded.toLocaleString()} {result.runtimeMs.toFixed(2)}ms {result.memoryKb.toFixed(2)}KB {result.isOptimal && ( )}
); }; export default ComparisonDashboard;