zenno/race/skillzone: new tool for viewing skill activation locations
Fixes #48.
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
<script lang="ts">
|
||||
import * as Plot from '@observablehq/plot';
|
||||
import type { Attachment } from 'svelte/attachments';
|
||||
import type { ClassValue } from 'svelte/elements';
|
||||
import * as race from '$lib/race';
|
||||
import * as racecourse from '$lib/data/racecourse';
|
||||
|
||||
export interface DrawSpan {
|
||||
fy: string;
|
||||
x1: number;
|
||||
x2: number;
|
||||
color: string;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
course: racecourse.Course;
|
||||
title?: string;
|
||||
class?: ClassValue | null;
|
||||
plotOptions?: Omit<Plot.PlotOptions, 'marks' | 'x' | 'y'>;
|
||||
fontColor?: string;
|
||||
draw: DrawSpan[];
|
||||
}
|
||||
|
||||
let { course, title, class: className, plotOptions, fontColor, draw }: Props = $props();
|
||||
|
||||
let width = $state(0);
|
||||
let height = $state(0);
|
||||
|
||||
const phases = $derived(race.phases(course.distance));
|
||||
const phaseX = $derived([
|
||||
0,
|
||||
phases[race.Phase.EarlyRace],
|
||||
phases[race.Phase.MidRace],
|
||||
phases[race.Phase.LateRace],
|
||||
phases[race.Phase.LastSpurt],
|
||||
]);
|
||||
const sectionX = $derived([0, ...racecourse.SECTIONS.map((s) => course.distance * s.endRate)]);
|
||||
|
||||
const drawTitles = $derived(draw.map((d) => d.fy));
|
||||
|
||||
const makeChart: Attachment = (el) => {
|
||||
$effect(() => {
|
||||
el?.firstChild?.remove();
|
||||
el?.append(
|
||||
Plot.plot({
|
||||
width: width,
|
||||
height,
|
||||
clip: true,
|
||||
title,
|
||||
marginLeft: 50,
|
||||
x: {
|
||||
domain: [0, course.distance],
|
||||
ticks: phaseX,
|
||||
},
|
||||
fy: {
|
||||
label: null,
|
||||
padding: 0,
|
||||
domain: drawTitles,
|
||||
},
|
||||
...plotOptions,
|
||||
marks: [
|
||||
Plot.barX(draw, {
|
||||
x1: 'x1',
|
||||
x2: 'x2',
|
||||
fy: 'fy',
|
||||
fill: 'color',
|
||||
fillOpacity: 0.8,
|
||||
title: 'label',
|
||||
}),
|
||||
Plot.text(draw, { x: 'x1', fy: 'fy', text: 'label', dx: 2, textAnchor: 'start', fontSize: 16, fill: 'black' }),
|
||||
Plot.ruleX(sectionX, { opacity: 0.25 }),
|
||||
Plot.ruleX([phases[0], phases[1]], { opacity: 0.5 }),
|
||||
],
|
||||
}),
|
||||
);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<div bind:clientWidth={width} bind:clientHeight={height} class={['flex h-full w-full flex-col md:flex-row', className]}>
|
||||
<div role="img" {@attach makeChart}>
|
||||
<span>the chart seems to have didn't</span>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user