1import { Link, useLocation, useParams } from "react-router-dom";
2import { BenchmarkTable } from "../components/benchmark/table/BenchmarkTable";
3import { useEffect, useRef, useState } from "react";
4import TimeseriesView from "../components/dataset/TimeseriesView";
5import { BenchmarkCharts } from "../components/benchmark/charts/BenchmarkCharts";
6import { useBenchmarkChartData } from "../hooks/useBenchmarkChartData";
7import { TagFilter } from "../components/TagFilter";
8import { useTagFilter } from "../hooks/useTagFilter";
9import { BenchmarkData } from "../types";
11interface HomeProps {
12 benchmarkData: BenchmarkData | null;
13}
15export default function Home({ benchmarkData }: HomeProps) {
16 const location = useLocation();
17 const { datasetName, algorithmName } = useParams<{
18 datasetName?: string;
19 algorithmName?: string;
20 }>();
21 const containerRef = useRef<HTMLDivElement>(null);
22 const [containerWidth, setContainerWidth] = useState(1200);
24 useEffect(() => {
25 if (!containerRef.current) return;
27 const resizeObserver = new ResizeObserver((entries) => {
28 for (const entry of entries) {
29 setContainerWidth(entry.contentRect.width - 32);
30 }
31 });
33 resizeObserver.observe(containerRef.current);
35 return () => {
36 resizeObserver.disconnect();
37 };
38 }, []);
40 // Determine active tab based on URL
41 const getActiveTab = () => {
42 if (datasetName) return `dataset-${datasetName}`;
43 if (algorithmName) return `algorithm-${algorithmName}`;
44 if (location.pathname.includes("/algorithms")) return "algorithms";
45 return "datasets";
46 };
48 const activeTab = getActiveTab();
50 // Get specific dataset or algorithm if viewing one
51 const dataset = datasetName
52 ? benchmarkData?.datasets.find((d) => d.name === datasetName)
53 : undefined;
54 const algorithm = algorithmName
55 ? benchmarkData?.algorithms.find((a) => a.name === algorithmName)
56 : undefined;
58 // Get chart data for specific dataset or algorithm view
59 const chartData = useBenchmarkChartData(
60 benchmarkData?.results || [],
61 dataset?.name || null,
62 algorithm?.name || null,
63 );
65 // Set up tag filtering for datasets
66 const {
67 selectedTags: datasetTags,
68 availableTags: availableDatasetTags,
69 filteredItems: filteredDatasets,
70 toggleTag: toggleDatasetTag,
71 } = useTagFilter(benchmarkData?.datasets || []);
73 // Set up tag filtering for algorithms
74 const {
75 selectedTags: algorithmTags,
76 availableTags: availableAlgorithmTags,
77 filteredItems: filteredAlgorithms,
78 toggleTag: toggleAlgorithmTag,
79 } = useTagFilter(benchmarkData?.algorithms || []);
81 const renderDatasets = () => (
82 <div style={{ overflowX: "auto" }}>
83 <div style={{ marginBottom: "1rem" }}>
84 <TagFilter
85 availableTags={availableDatasetTags}
86 selectedTags={datasetTags}
87 onTagToggle={toggleDatasetTag}
88 label="Filter datasets"
89 />
90 </div>
91 <table style={{ width: "100%", borderCollapse: "collapse" }}>
92 <thead>
93 <tr style={{ backgroundColor: "#f5f5f5" }}>
94 <th
95 style={{
96 padding: "8px 12px",
97 textAlign: "left",
98 borderBottom: "1px solid #ddd",
99 fontSize: "0.9rem",
100 whiteSpace: "nowrap",
101 }}
102 >
103 Name
104 </th>
105 <th
106 style={{
107 padding: "8px 12px",
108 textAlign: "left",
109 borderBottom: "1px solid #ddd",
110 fontSize: "0.9rem",
111 whiteSpace: "nowrap",
112 }}
113 >
114 Version
115 </th>
116 <th
117 style={{
118 padding: "8px 12px",
119 textAlign: "left",
120 borderBottom: "1px solid #ddd",
121 fontSize: "0.9rem",
122 whiteSpace: "nowrap",
123 }}
124 >
125 Description
126 </th>
127 <th
128 style={{
129 padding: "8px 12px",
130 textAlign: "left",
131 borderBottom: "1px solid #ddd",
132 fontSize: "0.9rem",
133 whiteSpace: "nowrap",
134 }}
135 >
136 Tags
137 </th>
138 <th
139 style={{
140 padding: "8px 12px",
141 textAlign: "left",
142 borderBottom: "1px solid #ddd",
143 fontSize: "0.9rem",
144 whiteSpace: "nowrap",
145 }}
146 >
147 Source
148 </th>
149 <th
150 style={{
151 padding: "8px 12px",
152 textAlign: "left",
153 borderBottom: "1px solid #ddd",
154 fontSize: "0.9rem",
155 whiteSpace: "nowrap",
156 }}
157 >
158 Data
159 </th>
160 </tr>
161 </thead>
162 <tbody>
163 {filteredDatasets.map((dataset, index) => (
164 <tr
165 key={`${dataset.name}-${dataset.version}`}
166 style={{ backgroundColor: index % 2 === 0 ? "white" : "#fafafa" }}
167 >
168 <td
169 style={{
170 padding: "6px 12px",
171 borderBottom: "1px solid #ddd",
172 fontSize: "0.9rem",
173 }}
174 >
175 <Link
176 to={`/dataset/${encodeURIComponent(dataset.name)}`}
177 style={{
178 color: "#0066cc",
179 textDecoration: "none",
180 fontWeight: "500",
181 }}
182 >
183 {dataset.name}
184 </Link>
185 </td>
186 <td
187 style={{
188 padding: "6px 12px",
189 borderBottom: "1px solid #ddd",
190 fontSize: "0.9rem",
191 }}
192 >
193 {dataset.version}
194 </td>
195 <td
196 style={{
197 padding: "6px 12px",
198 borderBottom: "1px solid #ddd",
199 fontSize: "0.9rem",
200 }}
201 >
202 {dataset.description}
203 </td>
204 <td
205 style={{
206 padding: "6px 12px",
207 borderBottom: "1px solid #ddd",
208 fontSize: "0.9rem",
209 }}
210 >
211 {dataset.tags.map((tag) => (
212 <span
213 key={tag}
214 style={{
215 display: "inline-block",
216 backgroundColor: "#e1e1e1",
217 padding: "2px 6px",
218 borderRadius: "3px",
219 margin: "1px",
220 fontSize: "0.8rem",
221 }}
222 >
223 {tag}
224 </span>
225 ))}
226 </td>
227 <td
228 style={{
229 padding: "6px 12px",
230 borderBottom: "1px solid #ddd",
231 fontSize: "0.9rem",
232 }}
233 >
234 {dataset.source_file && (
235 <a
236 href={dataset.source_file}
237 target="_blank"
238 rel="noopener noreferrer"
239 style={{ color: "#0066cc", textDecoration: "none" }}
240 >
241 View Source
242 </a>
243 )}
244 </td>
245 <td
246 style={{
247 padding: "6px 12px",
248 borderBottom: "1px solid #ddd",
249 fontSize: "0.9rem",
250 }}
251 >
252 {dataset.data_url_npy && (
253 <a
254 href={dataset.data_url_npy}
255 download={`${dataset.name}-${dataset.version}.npy`}
256 style={{ color: "#0066cc", textDecoration: "none" }}
257 >
258 Download
259 </a>
260 )}
261 </td>
262 </tr>
263 ))}
264 </tbody>
265 </table>
266 </div>
267 );
269 const renderAlgorithms = () => (
270 <div style={{ overflowX: "auto" }}>
271 <div style={{ marginBottom: "1rem" }}>
272 <TagFilter
273 availableTags={availableAlgorithmTags}
274 selectedTags={algorithmTags}
275 onTagToggle={toggleAlgorithmTag}
276 label="Filter algorithms"
277 />
278 </div>
279 <table style={{ width: "100%", borderCollapse: "collapse" }}>
280 <thead>
281 <tr style={{ backgroundColor: "#f5f5f5" }}>
282 <th
283 style={{
284 padding: "8px 12px",
285 textAlign: "left",
286 borderBottom: "1px solid #ddd",
287 fontSize: "0.9rem",
288 whiteSpace: "nowrap",
289 }}
290 >
291 Name
292 </th>
293 <th
294 style={{
295 padding: "8px 12px",
296 textAlign: "left",
297 borderBottom: "1px solid #ddd",
298 fontSize: "0.9rem",
299 whiteSpace: "nowrap",
300 }}
301 >
302 Version
303 </th>
304 <th
305 style={{
306 padding: "8px 12px",
307 textAlign: "left",
308 borderBottom: "1px solid #ddd",
309 fontSize: "0.9rem",
310 whiteSpace: "nowrap",
311 }}
312 >
313 Description
314 </th>
315 <th
316 style={{
317 padding: "8px 12px",
318 textAlign: "left",
319 borderBottom: "1px solid #ddd",
320 fontSize: "0.9rem",
321 whiteSpace: "nowrap",
322 }}
323 >
324 Tags
325 </th>
326 <th
327 style={{
328 padding: "8px 12px",
329 textAlign: "left",
330 borderBottom: "1px solid #ddd",
331 fontSize: "0.9rem",
332 whiteSpace: "nowrap",
333 }}
334 >
335 Source
336 </th>
337 </tr>
338 </thead>
339 <tbody>
340 {filteredAlgorithms.map((algorithm, index) => (
341 <tr
342 key={`${algorithm.name}-${algorithm.version}`}
343 style={{ backgroundColor: index % 2 === 0 ? "white" : "#fafafa" }}
344 >
345 <td
346 style={{
347 padding: "6px 12px",
348 borderBottom: "1px solid #ddd",
349 fontSize: "0.9rem",
350 }}
351 >
352 <Link
353 to={`/algorithm/${encodeURIComponent(algorithm.name)}`}
354 style={{
355 color: "#0066cc",
356 textDecoration: "none",
357 fontWeight: "500",
358 }}
359 >
360 {algorithm.name}
361 </Link>
362 </td>
363 <td
364 style={{
365 padding: "6px 12px",
366 borderBottom: "1px solid #ddd",
367 fontSize: "0.9rem",
368 }}
369 >
370 {algorithm.version}
371 </td>
372 <td
373 style={{
374 padding: "6px 12px",
375 borderBottom: "1px solid #ddd",
376 fontSize: "0.9rem",
377 }}
378 >
379 {algorithm.description}
380 </td>
381 <td
382 style={{
383 padding: "6px 12px",
384 borderBottom: "1px solid #ddd",
385 fontSize: "0.9rem",
386 }}
387 >
388 {algorithm.tags.map((tag) => (
389 <span
390 key={tag}
391 style={{
392 display: "inline-block",
393 backgroundColor: "#e1e1e1",
394 padding: "2px 6px",
395 borderRadius: "3px",
396 margin: "1px",
397 fontSize: "0.8rem",
398 }}
399 >
400 {tag}
401 </span>
402 ))}
403 </td>
404 <td
405 style={{
406 padding: "6px 12px",
407 borderBottom: "1px solid #ddd",
408 fontSize: "0.9rem",
409 }}
410 >
411 {algorithm.source_file && (
412 <a
413 href={algorithm.source_file}
414 target="_blank"
415 rel="noopener noreferrer"
416 style={{ color: "#0066cc", textDecoration: "none" }}
417 >
418 View Source
419 </a>
420 )}
421 </td>
422 </tr>
423 ))}
424 </tbody>
425 </table>
426 </div>
427 );
429 return (
430 <div>
431 <header style={{ marginBottom: "2rem" }}>
432 <h1 style={{ fontSize: "2rem", fontWeight: "bold", color: "#333" }}>
433 Benchcompress
434 </h1>
435 <p style={{ color: "#666", marginTop: "0.5rem" }}>
436 Comparing compression algorithms for numeric arrays
437 </p>
438 </header>
439 <main>
440 <div style={{ marginBottom: "1rem" }}>
441 <div
442 style={{
443 borderBottom: "1px solid #ddd",
444 display: "flex",
445 gap: "4px",
446 overflowX: "auto",
447 }}
448 >
449 <Link
450 to="/datasets"
451 style={{
452 padding: "8px 16px",
453 border: "none",
454 background: "none",
455 borderBottom:
456 activeTab === "datasets" ? "2px solid #0066cc" : "none",
457 color: activeTab === "datasets" ? "#0066cc" : "#666",
458 fontWeight: activeTab === "datasets" ? "600" : "normal",
459 cursor: "pointer",
460 textDecoration: "none",
461 whiteSpace: "nowrap",
462 }}
463 >
464 Datasets
465 </Link>
466 <Link
467 to="/algorithms"
468 style={{
469 padding: "8px 16px",
470 border: "none",
471 background: "none",
472 borderBottom:
473 activeTab === "algorithms" ? "2px solid #0066cc" : "none",
474 color: activeTab === "algorithms" ? "#0066cc" : "#666",
475 fontWeight: activeTab === "algorithms" ? "600" : "normal",
476 cursor: "pointer",
477 textDecoration: "none",
478 whiteSpace: "nowrap",
479 }}
480 >
481 Algorithms
482 </Link>
483 {dataset && (
484 <Link
485 to={`/dataset/${dataset.name}`}
486 style={{
487 padding: "8px 16px",
488 border: "none",
489 background: "none",
490 borderBottom:
491 activeTab === `dataset-${dataset.name}`
492 ? "2px solid #0066cc"
493 : "none",
494 color:
495 activeTab === `dataset-${dataset.name}`
496 ? "#0066cc"
497 : "#666",
498 fontWeight:
499 activeTab === `dataset-${dataset.name}` ? "600" : "normal",
500 cursor: "pointer",
501 textDecoration: "none",
502 whiteSpace: "nowrap",
503 }}
504 >
505 {dataset.name}
506 </Link>
507 )}
508 {algorithm && (
509 <Link
510 to={`/algorithm/${algorithm.name}`}
511 style={{
512 padding: "8px 16px",
513 border: "none",
514 background: "none",
515 borderBottom:
516 activeTab === `algorithm-${algorithm.name}`
517 ? "2px solid #0066cc"
518 : "none",
519 color:
520 activeTab === `algorithm-${algorithm.name}`
521 ? "#0066cc"
522 : "#666",
523 fontWeight:
524 activeTab === `algorithm-${algorithm.name}`
525 ? "600"
526 : "normal",
527 cursor: "pointer",
528 textDecoration: "none",
529 whiteSpace: "nowrap",
530 }}
531 >
532 {algorithm.name}
533 </Link>
534 )}
535 </div>
536 </div>
538 <div style={{ padding: "1rem 0" }}>
539 {dataset ? (
540 <div>
541 <div style={{ marginBottom: "1.5rem" }}>
542 <p style={{ fontSize: "0.9rem", lineHeight: "1.5" }}>
543 {dataset.description}
544 </p>
545 </div>
546 <div
547 style={{
548 marginBottom: "1.5rem",
549 display: "flex",
550 gap: "2rem",
551 flexWrap: "wrap",
552 }}
553 >
554 <div>
555 <span style={{ fontWeight: "bold", fontSize: "0.9rem" }}>
556 Version:{" "}
557 </span>
558 <span style={{ fontSize: "0.9rem" }}>{dataset.version}</span>
559 </div>
560 <div>
561 <span style={{ fontWeight: "bold", fontSize: "0.9rem" }}>
562 Tags:{" "}
563 </span>
564 {dataset.tags.map((tag) => (
565 <span
566 key={tag}
567 style={{
568 display: "inline-block",
569 backgroundColor: "#e1e1e1",
570 padding: "2px 6px",
571 borderRadius: "3px",
572 margin: "2px",
573 fontSize: "0.8rem",
574 }}
575 >
576 {tag}
577 </span>
578 ))}
579 </div>
580 <div>
581 <span style={{ fontWeight: "bold", fontSize: "0.9rem" }}>
582 Download:{" "}
583 </span>
584 <span style={{ display: "inline-flex", gap: "0.5rem" }}>
585 {dataset.data_url_npy && (
586 <a
587 href={dataset.data_url_npy}
588 download={`${dataset.name}-${dataset.version}.npy`}
589 style={{
590 color: "#0066cc",
591 textDecoration: "none",
592 padding: "2px 6px",
593 backgroundColor: "#f0f0f0",
594 borderRadius: "4px",
595 fontSize: "0.9rem",
596 }}
597 >
598 NPY
599 </a>
600 )}
601 {dataset.data_url_raw && (
602 <a
603 href={dataset.data_url_raw}
604 download={`${dataset.name}-${dataset.version}.dat`}
605 style={{
606 color: "#0066cc",
607 textDecoration: "none",
608 padding: "2px 6px",
609 backgroundColor: "#f0f0f0",
610 borderRadius: "4px",
611 fontSize: "0.9rem",
612 }}
613 >
614 RAW
615 </a>
616 )}
617 </span>
618 </div>
619 {dataset.source_file && (
620 <div>
621 <span style={{ fontWeight: "bold", fontSize: "0.9rem" }}>
622 Source:{" "}
623 </span>
624 <a
625 href={dataset.source_file}
626 target="_blank"
627 rel="noopener noreferrer"
628 style={{
629 color: "#0066cc",
630 textDecoration: "none",
631 padding: "2px 6px",
632 backgroundColor: "#f0f0f0",
633 borderRadius: "4px",
634 fontSize: "0.9rem",
635 }}
636 >
637 View
638 </a>
639 </div>
640 )}
641 </div>
642 <div style={{ marginBottom: "1.5rem" }}>
643 <div
644 ref={containerRef}
645 style={{
646 width: "100%",
647 height: "300px",
648 backgroundColor: "#f5f5f5",
649 borderRadius: "4px",
650 padding: "1rem",
651 }}
652 >
653 <TimeseriesView
654 width={containerWidth}
655 height={250}
656 dataset={dataset}
657 />
658 </div>
659 </div>
660 {benchmarkData && (
661 <>
662 <div style={{ marginBottom: "1.5rem" }}>
663 <h2
664 style={{
665 fontSize: "1.2rem",
666 fontWeight: "bold",
667 marginBottom: "0.5rem",
668 }}
669 >
670 Benchmark Results
671 </h2>
672 <BenchmarkCharts chartData={chartData} />
673 </div>
674 <div style={{ marginBottom: "1.5rem" }}>
675 <BenchmarkTable
676 results={benchmarkData.results.filter(
677 (result) => result.dataset === dataset.name,
678 )}
679 />
680 </div>
681 </>
682 )}
683 </div>
684 ) : algorithm ? (
685 <div>
686 <div style={{ marginBottom: "1.5rem" }}>
687 <p style={{ fontSize: "0.9rem", lineHeight: "1.5" }}>
688 {algorithm.description}
689 </p>
690 </div>
691 <div
692 style={{
693 marginBottom: "1.5rem",
694 display: "flex",
695 gap: "2rem",
696 flexWrap: "wrap",
697 }}
698 >
699 <div>
700 <span style={{ fontWeight: "bold", fontSize: "0.9rem" }}>
701 Version:{" "}
702 </span>
703 <span style={{ fontSize: "0.9rem" }}>
704 {algorithm.version}
705 </span>
706 </div>
707 <div>
708 <span style={{ fontWeight: "bold", fontSize: "0.9rem" }}>
709 Tags:{" "}
710 </span>
711 {algorithm.tags.map((tag) => (
712 <span
713 key={tag}
714 style={{
715 display: "inline-block",
716 backgroundColor: "#e1e1e1",
717 padding: "2px 6px",
718 borderRadius: "3px",
719 margin: "2px",
720 fontSize: "0.8rem",
721 }}
722 >
723 {tag}
724 </span>
725 ))}
726 </div>
727 {algorithm.source_file && (
728 <div>
729 <span style={{ fontWeight: "bold", fontSize: "0.9rem" }}>
730 Source:{" "}
731 </span>
732 <a
733 href={algorithm.source_file}
734 target="_blank"
735 rel="noopener noreferrer"
736 style={{
737 color: "#0066cc",
738 textDecoration: "none",
739 padding: "2px 6px",
740 backgroundColor: "#f0f0f0",
741 borderRadius: "4px",
742 fontSize: "0.9rem",
743 }}
744 >
745 View
746 </a>
747 </div>
748 )}
749 </div>
750 {benchmarkData && (
751 <>
752 <div style={{ marginBottom: "1.5rem" }}>
753 <h2
754 style={{
755 fontSize: "1.2rem",
756 fontWeight: "bold",
757 marginBottom: "0.5rem",
758 }}
759 >
760 Benchmark Results
761 </h2>
762 <BenchmarkCharts chartData={chartData} />
763 </div>
764 <div style={{ marginBottom: "1.5rem" }}>
765 <BenchmarkTable
766 results={benchmarkData.results.filter(
767 (result) => result.algorithm === algorithm.name,
768 )}
769 />
770 </div>
771 </>
772 )}
773 </div>
774 ) : activeTab === "datasets" ? (
775 renderDatasets()
776 ) : (
777 renderAlgorithms()
778 )}
779 </div>
780 </main>
781 </div>
782 );
783}