rearrange tabs
6 changed files+752−631
web-ui/src/App.tsxmodified+18−87View file
@@ -1,12 +1,8 @@
1-import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
1+import { BrowserRouter, Routes, Route, Link, Navigate } from "react-router-dom";
22 import { useEffect, useState } from "react";
33 import axios from "axios";
44 import { ScrollToTop } from "./components/ScrollToTop";
55 import Home from "./pages/Home";
6-import Datasets from "./pages/Datasets";
7-import Dataset from "./pages/Dataset";
8-import Algorithms from "./pages/Algorithms";
9-import Algorithm from "./pages/Algorithm";
106 import About from "./pages/About";
117 import { BenchmarkData } from "./types";
128
@@ -63,64 +59,18 @@ function App() {
6359 boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
6460 }}
6561 >
66- <ul
67- style={{
68- listStyle: "none",
69- padding: 0,
70- margin: 0,
71- display: "flex",
72- gap: "1.5rem",
73- }}
74- >
75- <li>
76- <Link
77- to="/home"
78- style={{
79- color: "#0066cc",
80- textDecoration: "none",
81- fontWeight: "500",
82- }}
83- >
84- Home
85- </Link>
86- </li>
87- <li>
88- <Link
89- to="/datasets"
90- style={{
91- color: "#0066cc",
92- textDecoration: "none",
93- fontWeight: "500",
94- }}
95- >
96- Datasets
97- </Link>
98- </li>
99- <li>
100- <Link
101- to="/algorithms"
102- style={{
103- color: "#0066cc",
104- textDecoration: "none",
105- fontWeight: "500",
106- }}
107- >
108- Algorithms
109- </Link>
110- </li>
111- <li>
112- <Link
113- to="/about"
114- style={{
115- color: "#0066cc",
116- textDecoration: "none",
117- fontWeight: "500",
118- }}
119- >
120- About
121- </Link>
122- </li>
123- </ul>
62+ <div style={{ display: "flex", justifyContent: "flex-end" }}>
63+ <Link
64+ to="/about"
65+ style={{
66+ color: "#0066cc",
67+ textDecoration: "none",
68+ fontWeight: "500",
69+ }}
70+ >
71+ About
72+ </Link>
73+ </div>
12474 </nav>
12575 <main>
12676 {isLoading ? (
@@ -129,41 +79,22 @@ function App() {
12979 <div>Error: {error}</div>
13080 ) : (
13181 <Routes>
132- <Route
133- path="/home"
134- element={<Home benchmarkData={benchmarkData} />}
135- />
136- <Route
137- path="/"
138- element={<Home benchmarkData={benchmarkData} />}
139- />
82+ <Route path="/" element={<Navigate to="/datasets" replace />} />
14083 <Route
14184 path="/datasets"
142- element={<Datasets datasets={benchmarkData?.datasets || []} />}
85+ element={<Home benchmarkData={benchmarkData} />}
14386 />
14487 <Route
14588 path="/algorithms"
146- element={
147- <Algorithms algorithms={benchmarkData?.algorithms || []} />
148- }
89+ element={<Home benchmarkData={benchmarkData} />}
14990 />
15091 <Route
15192 path="/dataset/:datasetName"
152- element={
153- <Dataset
154- datasets={benchmarkData?.datasets || []}
155- benchmarkData={benchmarkData}
156- />
157- }
93+ element={<Home benchmarkData={benchmarkData} />}
15894 />
15995 <Route
16096 path="/algorithm/:algorithmName"
161- element={
162- <Algorithm
163- algorithms={benchmarkData?.algorithms || []}
164- benchmarkData={benchmarkData}
165- />
166- }
97+ element={<Home benchmarkData={benchmarkData} />}
16798 />
16899 <Route path="/about" element={<About />} />
169100 </Routes>
web-ui/src/components/dataset/TimeseriesView.tsxmodified+1−1View file
@@ -91,7 +91,7 @@ const TimeseriesView: React.FC<TimeseriesViewProps> = ({
9191 const shape = client.getShape();
9292 dispatch({
9393 type: "SET_X_RANGE",
94- range: { min: 0, max: Math.min(149, shape - 1) },
94+ range: { min: 0, max: Math.min(999, shape - 1) },
9595 });
9696 }
9797 }, [client]);
web-ui/src/components/dataset/timeseriesViewReducer.tsmodified+1−1View file
@@ -13,7 +13,7 @@ export const initialState: TimeseriesViewState = {
1313 selectedIndex: -1,
1414 isDragging: false,
1515 lastDragX: 0,
16- xRange: { min: 0, max: 149 },
16+ xRange: { min: 0, max: 999 },
1717 };
1818
1919 // Action Types Union
web-ui/src/pages/Algorithms.tsxdeleted+0−196View file
@@ -1,196 +0,0 @@
1-import { Algorithm } from "../types";
2-import { Link } from "react-router-dom";
3-import { TagFilter } from "../components/TagFilter";
4-import { useTagFilter } from "../hooks/useTagFilter";
5-
6-interface AlgorithmsProps {
7- algorithms: Algorithm[];
8-}
9-
10-function Algorithms({ algorithms }: AlgorithmsProps) {
11- const {
12- selectedTags,
13- availableTags,
14- filteredItems: filteredAlgorithms,
15- toggleTag,
16- } = useTagFilter(algorithms);
17-
18- return (
19- <div>
20- <div style={{ marginBottom: "2rem" }}>
21- <h1
22- style={{
23- fontSize: "2rem",
24- fontWeight: "bold",
25- color: "#333",
26- marginBottom: "1rem",
27- }}
28- >
29- Compression Algorithms
30- </h1>
31- <TagFilter
32- availableTags={availableTags}
33- selectedTags={selectedTags}
34- onTagToggle={toggleTag}
35- label="Filter algorithms"
36- />
37- </div>
38- <div style={{ overflowX: "auto" }}>
39- <table style={{ width: "100%", borderCollapse: "collapse" }}>
40- <thead>
41- <tr style={{ backgroundColor: "#f5f5f5" }}>
42- <th
43- style={{
44- padding: "8px 12px",
45- textAlign: "left",
46- borderBottom: "1px solid #ddd",
47- fontSize: "0.9rem",
48- whiteSpace: "nowrap",
49- }}
50- >
51- Name
52- </th>
53- <th
54- style={{
55- padding: "8px 12px",
56- textAlign: "left",
57- borderBottom: "1px solid #ddd",
58- fontSize: "0.9rem",
59- whiteSpace: "nowrap",
60- }}
61- >
62- Version
63- </th>
64- <th
65- style={{
66- padding: "8px 12px",
67- textAlign: "left",
68- borderBottom: "1px solid #ddd",
69- fontSize: "0.9rem",
70- whiteSpace: "nowrap",
71- }}
72- >
73- Description
74- </th>
75- <th
76- style={{
77- padding: "8px 12px",
78- textAlign: "left",
79- borderBottom: "1px solid #ddd",
80- fontSize: "0.9rem",
81- whiteSpace: "nowrap",
82- }}
83- >
84- Tags
85- </th>
86- <th
87- style={{
88- padding: "8px 12px",
89- textAlign: "left",
90- borderBottom: "1px solid #ddd",
91- fontSize: "0.9rem",
92- whiteSpace: "nowrap",
93- }}
94- >
95- Source
96- </th>
97- </tr>
98- </thead>
99- <tbody>
100- {filteredAlgorithms.map((algorithm, index) => (
101- <tr
102- key={`${algorithm.name}-${algorithm.version}`}
103- style={{
104- backgroundColor: index % 2 === 0 ? "white" : "#fafafa",
105- }}
106- >
107- <td
108- style={{
109- padding: "6px 12px",
110- borderBottom: "1px solid #ddd",
111- fontSize: "0.9rem",
112- }}
113- >
114- <Link
115- to={`/algorithm/${encodeURIComponent(algorithm.name)}`}
116- style={{
117- color: "#0066cc",
118- textDecoration: "none",
119- fontWeight: "500",
120- }}
121- >
122- {algorithm.name}
123- </Link>
124- </td>
125- <td
126- style={{
127- padding: "6px 12px",
128- borderBottom: "1px solid #ddd",
129- fontSize: "0.9rem",
130- }}
131- >
132- {algorithm.version}
133- </td>
134- <td
135- style={{
136- padding: "6px 12px",
137- borderBottom: "1px solid #ddd",
138- fontSize: "0.9rem",
139- }}
140- >
141- {algorithm.description}
142- </td>
143- <td
144- style={{
145- padding: "6px 12px",
146- borderBottom: "1px solid #ddd",
147- fontSize: "0.9rem",
148- }}
149- >
150- {algorithm.tags.map((tag) => (
151- <span
152- key={tag}
153- style={{
154- display: "inline-block",
155- backgroundColor: "#e1e1e1",
156- padding: "2px 6px",
157- borderRadius: "3px",
158- margin: "1px",
159- fontSize: "0.8rem",
160- }}
161- >
162- {tag}
163- </span>
164- ))}
165- </td>
166- <td
167- style={{
168- padding: "6px 12px",
169- borderBottom: "1px solid #ddd",
170- fontSize: "0.9rem",
171- }}
172- >
173- {algorithm.source_file && (
174- <a
175- href={algorithm.source_file}
176- target="_blank"
177- rel="noopener noreferrer"
178- style={{
179- color: "#0066cc",
180- textDecoration: "none",
181- }}
182- >
183- View Source
184- </a>
185- )}
186- </td>
187- </tr>
188- ))}
189- </tbody>
190- </table>
191- </div>
192- </div>
193- );
194-}
195-
196-export default Algorithms;
web-ui/src/pages/Datasets.tsxdeleted+0−227View file
@@ -1,227 +0,0 @@
1-import { Dataset } from "../types";
2-import { Link } from "react-router-dom";
3-import { TagFilter } from "../components/TagFilter";
4-import { useTagFilter } from "../hooks/useTagFilter";
5-
6-interface DatasetsProps {
7- datasets: Dataset[];
8-}
9-
10-function Datasets({ datasets }: DatasetsProps) {
11- const {
12- selectedTags,
13- availableTags,
14- filteredItems: filteredDatasets,
15- toggleTag,
16- } = useTagFilter(datasets);
17-
18- return (
19- <div>
20- <div style={{ marginBottom: "2rem" }}>
21- <h1
22- style={{
23- fontSize: "2rem",
24- fontWeight: "bold",
25- color: "#333",
26- marginBottom: "1rem",
27- }}
28- >
29- Benchmark Datasets
30- </h1>
31- <TagFilter
32- availableTags={availableTags}
33- selectedTags={selectedTags}
34- onTagToggle={toggleTag}
35- label="Filter datasets"
36- />
37- </div>
38- <div style={{ overflowX: "auto" }}>
39- <table style={{ width: "100%", borderCollapse: "collapse" }}>
40- <thead>
41- <tr style={{ backgroundColor: "#f5f5f5" }}>
42- <th
43- style={{
44- padding: "8px 12px",
45- textAlign: "left",
46- borderBottom: "1px solid #ddd",
47- fontSize: "0.9rem",
48- whiteSpace: "nowrap",
49- }}
50- >
51- Name
52- </th>
53- <th
54- style={{
55- padding: "8px 12px",
56- textAlign: "left",
57- borderBottom: "1px solid #ddd",
58- fontSize: "0.9rem",
59- whiteSpace: "nowrap",
60- }}
61- >
62- Version
63- </th>
64- <th
65- style={{
66- padding: "8px 12px",
67- textAlign: "left",
68- borderBottom: "1px solid #ddd",
69- fontSize: "0.9rem",
70- whiteSpace: "nowrap",
71- }}
72- >
73- Description
74- </th>
75- <th
76- style={{
77- padding: "8px 12px",
78- textAlign: "left",
79- borderBottom: "1px solid #ddd",
80- fontSize: "0.9rem",
81- whiteSpace: "nowrap",
82- }}
83- >
84- Tags
85- </th>
86- <th
87- style={{
88- padding: "8px 12px",
89- textAlign: "left",
90- borderBottom: "1px solid #ddd",
91- fontSize: "0.9rem",
92- whiteSpace: "nowrap",
93- }}
94- >
95- Source
96- </th>
97- <th
98- style={{
99- padding: "8px 12px",
100- textAlign: "left",
101- borderBottom: "1px solid #ddd",
102- fontSize: "0.9rem",
103- whiteSpace: "nowrap",
104- }}
105- >
106- Data
107- </th>
108- </tr>
109- </thead>
110- <tbody>
111- {filteredDatasets.map((dataset, index) => (
112- <tr
113- key={`${dataset.name}-${dataset.version}`}
114- style={{
115- backgroundColor: index % 2 === 0 ? "white" : "#fafafa",
116- }}
117- >
118- <td
119- style={{
120- padding: "6px 12px",
121- borderBottom: "1px solid #ddd",
122- fontSize: "0.9rem",
123- }}
124- >
125- <Link
126- to={`/dataset/${encodeURIComponent(dataset.name)}`}
127- style={{
128- color: "#0066cc",
129- textDecoration: "none",
130- fontWeight: "500",
131- }}
132- >
133- {dataset.name}
134- </Link>
135- </td>
136- <td
137- style={{
138- padding: "6px 12px",
139- borderBottom: "1px solid #ddd",
140- fontSize: "0.9rem",
141- }}
142- >
143- {dataset.version}
144- </td>
145- <td
146- style={{
147- padding: "6px 12px",
148- borderBottom: "1px solid #ddd",
149- fontSize: "0.9rem",
150- }}
151- >
152- {dataset.description}
153- </td>
154- <td
155- style={{
156- padding: "6px 12px",
157- borderBottom: "1px solid #ddd",
158- fontSize: "0.9rem",
159- }}
160- >
161- {dataset.tags.map((tag) => (
162- <span
163- key={tag}
164- style={{
165- display: "inline-block",
166- backgroundColor: "#e1e1e1",
167- padding: "2px 6px",
168- borderRadius: "3px",
169- margin: "1px",
170- fontSize: "0.8rem",
171- }}
172- >
173- {tag}
174- </span>
175- ))}
176- </td>
177- <td
178- style={{
179- padding: "6px 12px",
180- borderBottom: "1px solid #ddd",
181- fontSize: "0.9rem",
182- }}
183- >
184- {dataset.source_file && (
185- <a
186- href={dataset.source_file}
187- target="_blank"
188- rel="noopener noreferrer"
189- style={{
190- color: "#0066cc",
191- textDecoration: "none",
192- }}
193- >
194- View Source
195- </a>
196- )}
197- </td>
198- <td
199- style={{
200- padding: "6px 12px",
201- borderBottom: "1px solid #ddd",
202- fontSize: "0.9rem",
203- }}
204- >
205- {dataset.data_url_npy && (
206- <a
207- href={dataset.data_url_npy}
208- download={`${dataset.name}-${dataset.version}.npy`}
209- style={{
210- color: "#0066cc",
211- textDecoration: "none",
212- }}
213- >
214- Download
215- </a>
216- )}
217- </td>
218- </tr>
219- ))}
220- </tbody>
221- </table>
222- </div>
223- </div>
224- );
225-}
226-
227-export default Datasets;
web-ui/src/pages/Home.tsxmodified+732−119View file
@@ -1,6 +1,9 @@
1-import { useMemo } from "react";
2-import { useNavigate } from "react-router-dom";
1+import { Link, useLocation, useParams } from "react-router-dom";
32 import { BenchmarkTable } from "../components/benchmark/table/BenchmarkTable";
3+import { useEffect, useRef, useState } from "react";
4+import TimeseriesView from "../components/dataset/TimeseriesView";
5+import { BenchmarkCharts } from "../components/benchmark/charts/BenchmarkCharts";
6+import { useBenchmarkChartData } from "../hooks/useBenchmarkChartData";
47 import { TagFilter } from "../components/TagFilter";
58 import { useTagFilter } from "../hooks/useTagFilter";
69 import { BenchmarkData } from "../types";
@@ -9,11 +12,59 @@ interface HomeProps {
912 benchmarkData: BenchmarkData | null;
1013 }
1114
12-function Home({ benchmarkData }: HomeProps) {
13- const navigate = useNavigate();
15+export 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);
23+
24+ useEffect(() => {
25+ if (!containerRef.current) return;
26+
27+ const resizeObserver = new ResizeObserver((entries) => {
28+ for (const entry of entries) {
29+ setContainerWidth(entry.contentRect.width - 32);
30+ }
31+ });
32+
33+ resizeObserver.observe(containerRef.current);
34+
35+ return () => {
36+ resizeObserver.disconnect();
37+ };
38+ }, []);
39+
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+ };
47+
48+ const activeTab = getActiveTab();
49+
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;
57+
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+ );
64+
1465 // Set up tag filtering for datasets
1566 const {
16- selectedTags: selectedDatasetTags,
67+ selectedTags: datasetTags,
1768 availableTags: availableDatasetTags,
1869 filteredItems: filteredDatasets,
1970 toggleTag: toggleDatasetTag,
@@ -21,150 +72,712 @@ function Home({ benchmarkData }: HomeProps) {
2172
2273 // Set up tag filtering for algorithms
2374 const {
24- selectedTags: selectedAlgorithmTags,
75+ selectedTags: algorithmTags,
2576 availableTags: availableAlgorithmTags,
2677 filteredItems: filteredAlgorithms,
2778 toggleTag: toggleAlgorithmTag,
2879 } = useTagFilter(benchmarkData?.algorithms || []);
2980
30- // Filter benchmark results based on selected tags
31- const filteredResults = useMemo(() => {
32- if (!benchmarkData) return [];
33-
34- let filtered = benchmarkData.results;
35-
36- if (selectedDatasetTags.length > 0) {
37- const datasetNames = filteredDatasets.map((d) => d.name);
38- filtered = filtered.filter((result) =>
39- datasetNames.includes(result.dataset),
40- );
41- }
42-
43- if (selectedAlgorithmTags.length > 0) {
44- const algorithmNames = filteredAlgorithms.map((a) => a.name);
45- filtered = filtered.filter((result) =>
46- algorithmNames.includes(result.algorithm),
47- );
48- }
49-
50- return filtered;
51- }, [
52- benchmarkData,
53- selectedDatasetTags,
54- selectedAlgorithmTags,
55- filteredDatasets,
56- filteredAlgorithms,
57- ]);
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+ );
268+
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+ );
58428
59429 return (
60430 <div>
61431 <header style={{ marginBottom: "2rem" }}>
62- <h1
63- style={{
64- fontSize: "2rem",
65- fontWeight: "bold",
66- color: "#333",
67- }}
68- >
69- Benchmark Results
432+ <h1 style={{ fontSize: "2rem", fontWeight: "bold", color: "#333" }}>
433+ Benchcompress
70434 </h1>
71- <p
72- style={{
73- color: "#666",
74- marginTop: "0.5rem",
75- }}
76- >
435+ <p style={{ color: "#666", marginTop: "0.5rem" }}>
77436 Comparing compression algorithms for numeric arrays
78437 </p>
79438 </header>
80439 <main>
81- <div style={{ marginBottom: "2rem" }}>
440+ <div style={{ marginBottom: "1rem" }}>
82441 <div
83442 style={{
443+ borderBottom: "1px solid #ddd",
84444 display: "flex",
85- alignItems: "center",
86- gap: "12px",
87- marginBottom: "1rem",
445+ gap: "4px",
446+ overflowX: "auto",
88447 }}
89448 >
90- <div style={{ display: "flex", alignItems: "center", gap: "6px" }}>
91- <label htmlFor="dataset-select">Dataset:</label>
92- <select
93- id="dataset-select"
94- value={undefined}
95- onChange={(e) => {
96- if (e.target.value) {
97- navigate(`/dataset/${e.target.value}`);
98- }
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",
99503 }}
504+ >
505+ {dataset.name}
506+ </Link>
507+ )}
508+ {algorithm && (
509+ <Link
510+ to={`/algorithm/${algorithm.name}`}
100511 style={{
101- padding: "4px 8px",
102- borderRadius: "4px",
103- border: "1px solid #ccc",
104- minWidth: "150px",
105- backgroundColor: "#fff",
106- fontSize: "0.9rem",
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",
107530 }}
108531 >
109- <option value="">All Datasets</option>
110- {filteredDatasets.map((dataset) => (
111- <option key={dataset.name} value={dataset.name}>
112- {dataset.name}
113- </option>
114- ))}
115- </select>
116- </div>
117- <div style={{ display: "flex", alignItems: "center", gap: "10px" }}>
118- <label htmlFor="algorithm-select">Algorithm:</label>
119- <select
120- id="algorithm-select"
121- value={undefined}
122- onChange={(e) => {
123- if (e.target.value) {
124- navigate(`/algorithm/${e.target.value}`);
125- }
532+ {algorithm.name}
533+ </Link>
534+ )}
535+ </div>
536+ </div>
537+
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",
126552 }}
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
127692 style={{
128- padding: "4px 8px",
129- borderRadius: "4px",
130- border: "1px solid #ccc",
131- minWidth: "150px",
132- backgroundColor: "#fff",
133- fontSize: "0.9rem",
693+ marginBottom: "1.5rem",
694+ display: "flex",
695+ gap: "2rem",
696+ flexWrap: "wrap",
134697 }}
135698 >
136- <option value="">All Algorithms</option>
137- {filteredAlgorithms.map((algorithm) => (
138- <option key={algorithm.name} value={algorithm.name}>
139- {algorithm.name}
140- </option>
141- ))}
142- </select>
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+ )}
143773 </div>
144- </div>
145-
146- <div
147- style={{ display: "flex", flexDirection: "column", gap: "1rem" }}
148- >
149- <TagFilter
150- availableTags={availableDatasetTags}
151- selectedTags={selectedDatasetTags}
152- onTagToggle={toggleDatasetTag}
153- label="Filter datasets"
154- />
155- <TagFilter
156- availableTags={availableAlgorithmTags}
157- selectedTags={selectedAlgorithmTags}
158- onTagToggle={toggleAlgorithmTag}
159- label="Filter algorithms"
160- />
161- </div>
774+ ) : activeTab === "datasets" ? (
775+ renderDatasets()
776+ ) : (
777+ renderAlgorithms()
778+ )}
162779 </div>
163-
164- {benchmarkData && <BenchmarkTable results={filteredResults} />}
165780 </main>
166781 </div>
167782 );
168783 }
169-
170-export default Home;