Karolis' playground dv-svelte / master src / components / controllable / rWye.svelte
master

Tree @master (Download .tar.gz)

rWye.svelte @masterraw · history · blame

<script lang="ts">
    import { derived, type Readable } from "svelte/store";
    import { getSwitchControllerContext } from "../../lib/switchControl";
    import Wye from "../wye.svelte";
    import { getScale } from "../../Display.svelte";

    export let pos: [number, number];
    export let line: [number, number];
    export let siding: number;
    export let reverseID: [boolean, boolean, boolean] = [false, false, false];
    export let ids: [number, number, number];
    const swCtx = getSwitchControllerContext();

    const switches = ids.map(swCtx.getStore);

    const nextLookup: [boolean, boolean, boolean][] = [
        [true, false, false],
        [false, true, true],
        [false, true, true],
        [false, false, false],
    ];

    const d = derived<
        Readable<boolean>[],
        {
            thrown: boolean;
            reverseMainline: boolean;
            invalid: boolean;
            idx: number;
        }
    >(switches, (switches, set) => {
        const [m, rm, s] = switches.map((x, i) => x !== reverseID[i]);
        const thrown = (m && !s) || (rm && s);
        const reverseMainline = rm && s;
        const invalid = (m && !rm && s) || (!m && rm && !s);

        const idx = (reverseMainline ? 0b10 : 0) | (thrown ? 1 : 0);
        set({
            thrown,
            reverseMainline,
            invalid,
            idx: invalid ? 3 : idx,
        });
    });

    const s = getScale();

    let nextidx = 0;
    let thrown = false;
    let reverseMainline = true;
    let invalid = false;

    d.subscribe((x) => {
        nextidx = x.idx;
        thrown = x.thrown;
        reverseMainline = x.reverseMainline;
        invalid = x.invalid;
    });
    const click = () => {
        const next = nextLookup[nextidx].map((x,i)=>x !== reverseID[i]);
        switches.forEach((v, i) => v.set(next[i]));
    };
</script>

<Wye {pos} {line} {siding} {thrown} {reverseMainline} />

<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<circle
    class="trigger"
    class:invalid
    on:click={click}
    cx={(pos[0] + 0.5) * $s}
    cy={(pos[1] + 0.5) * $s}
    r={$s / 2}
></circle>

<style lang="scss">
    .trigger {
        fill: rgba($color: green, $alpha: 0.1);
        &.invalid {
            fill: rgba($color: red, $alpha: 0.5);
            stroke: red;
        }
        &:hover {
            fill: rgba($color: red, $alpha: 0.5);
        }
    }
</style>