blob: b751f67797236dea56d9a71a680147963d26404f [file] [log] [blame]
<script lang="ts">
import { createEventDispatcher } from "svelte";
import { writable, type Writable } from "svelte/store";
import { readBenchmarks } from "../files.js";
import { ChartDataTransforms } from "../transforms/data-transforms.js";
import { Transforms } from "../transforms/metric-transforms.js";
import { STANDARD_MAPPER } from "../transforms/standard-mappers.js";
import type { Data, Series } from "../types/chart.js";
import type { Metrics } from "../types/data.js";
import type { FileMetadataEvent, Selection } from "../types/events.js";
import type { FileMetadata } from "../types/files.js";
import { Session, type IndexedWrapper } from "../wrappers/session.js";
import Chart from "./Chart.svelte";
import Group from "./Group.svelte";
export let fileEntries: FileMetadata[];
// State
let eventDispatcher = createEventDispatcher<FileMetadataEvent>();
let session: Session;
let metrics: Metrics<number>;
let series: Series[];
let chartData: Data;
let classGroups: Record<string, IndexedWrapper[]>;
let size: number;
// Stores
let activeDragDrop: Writable<boolean> = writable(false);
let suppressed: Writable<Set<string>> = writable(new Set());
// Events
let handler = function (event: CustomEvent<Selection[]>) {
const selections: Selection[] = event.detail;
for (let i = 0; i < selections.length; i += 1) {
const selection = selections[i];
if (!selection.enabled) {
$suppressed.add(selection.name);
} else {
$suppressed.delete(selection.name);
}
}
$suppressed = $suppressed;
};
$: {
session = new Session(fileEntries);
metrics = Transforms.buildMetrics(session, $suppressed);
series = ChartDataTransforms.mapToSeries(metrics, STANDARD_MAPPER);
chartData = ChartDataTransforms.mapToDataset(series);
classGroups = session.classGroups;
size = session.fileNames.size;
}
// Helpers
function onDropFile(event: DragEvent) {
handleFileDragDrop(event); // async
$activeDragDrop = false;
event.preventDefault();
}
function onDragOver(event: DragEvent) {
$activeDragDrop = true;
event.preventDefault();
}
function onDragLeave(event: DragEvent) {
$activeDragDrop = false;
event.preventDefault();
}
async function handleFileDragDrop(event: DragEvent) {
const items = [...event.dataTransfer.items];
const newFiles: FileMetadata[] = [];
if (items) {
for (let i = 0; i < items.length; i += 1) {
if (items[i].kind === "file") {
const file = items[i].getAsFile();
if (file.name.endsWith(".json")) {
const benchmarks = await readBenchmarks(file);
const entry: FileMetadata = {
enabled: true,
file: file,
container: benchmarks,
};
newFiles.push(entry);
}
}
}
// Deep copy & notify
eventDispatcher("entries", [...fileEntries, ...newFiles]);
}
}
</script>
{#if size <= 0}
<article
id="drop"
class="drop"
class:active={$activeDragDrop}
on:drop={onDropFile}
on:dragover={onDragOver}
on:dragleave={onDragLeave}
>
<h5>Drag and drop benchmark results to get started.</h5>
</article>
{:else}
<article
id="drop"
class="drop"
class:active={$activeDragDrop}
on:drop={onDropFile}
on:dragover={onDragOver}
on:dragleave={onDragLeave}
>
<h5>Benchmarks</h5>
{#each Object.entries(classGroups) as [className, wrappers]}
<Group {className} datasetGroup={wrappers} on:selections={handler} />
{/each}
</article>
{#if series.length > 0}
<Chart data={chartData} />
{/if}
{/if}
<style>
.active {
outline: beige;
outline-style: dashed;
}
</style>