import { useRef, useState } from 'react';
import { ready, ink } from '../../lib/mrly.js';
import { mount, Page, Row, Pick, Slider, Check, Stats, Stat, Note, Group } from '../../lib/app.jsx';
import { Markup, Sketch } from '../../lib/draw.jsx';
import { useQuery } from '../../lib/query.js';
import { useSeeds, seeded, Picker } from '../../lib/select.jsx';
import { board, bars, axis } from '../../lib/chart.js';
const m = await ready();
const PAD = 12;
function App() {
const s = useSeeds();
const [pick, set] = useQuery({ code: seeded(s, 3, 2, '126'), level: 5 });
const [height, setHeight] = useState(null);
const [both, setBoth] = useState(false);
const [view, setView] = useState('points');
const shown = useRef(null);
const top = m.level_cap(2, 1, view === 'section' ? 64 : 512);
const level = Math.min(pick.level, top);
const code = pick.code.trim();
let error = null, art = null, drawn = '';
try {
const cut = JSON.parse(m.diagonal_profile(code, 2, level, 2));
const [low, high] = cut.support;
const at = Math.min(high, Math.max(low, height ?? cut.central[0]));
const heights = both ? cut.central : [at];
shown.current = {
cut, low, high, at, heights,
name: m.name_of(code, 3, 2),
here: heights.map((h) => m.diagonal_count(code, 2, level, 2, h)).join(' and '),
digits: heights.map((h) => m.diagonal_digits(code, 2, level, 2, h)).join(' and '),
};
const svg = view === 'section'
? m.hex_svg(code, 2, level, 2, 'cut', Math.max(1, Math.round(256 / 2 ** level)))
: m.diagonal_svg(code, 2, level, 2, heights, Math.max(1, Math.round(512 / 2 ** level)));
if (svg.length > 4000000) throw new Error('that drawing is larger than this page serves; lower the level.');
art = svg;
drawn = view === 'section' ? '-' : m.diagonal_total(code, 2, level, 2, heights);
} catch (fault) {
error = fault;
}
const chart = (canvas) => {
const v = shown.current;
if (!v) return;
const b = board(canvas, 180, { pad: PAD, top: 12, bottom: 20 });
const counts = v.cut.counts.map(Number);
bars(b, counts, { color: (i) => (v.heights.includes(v.low + i) ? ink.yellow : ink.blue) });
axis(b, [[0, v.low], [1, v.low + counts.length - 1]]);
};
const onSeek = (frac) => {
const v = shown.current;
if (both || !v) return;
setHeight(Math.min(v.high, Math.max(v.low, Math.round(v.low + frac * (v.high - v.low)))));
};
const onView = (value) => {
const cap = m.level_cap(2, 1, value === 'section' ? 64 : 512);
setView(value);
if (pick.level > cap) {
set({ level: cap });
setHeight(null);
}
};
const v = shown.current;
const controls = (
<>
{ set(patch); setHeight(null); }} />
{ set({ level: value }); setHeight(null); }} />
>
);
return (
A plane x + y + z = s slides through the solid of bang dim 3, code 126 at the level and meets exactly 3^level cells at every height it meets at all. The binary digits of the height say which corners each scale may use, so every cut is a Sierpinski gasket, and the two central heights together fall into six of them tiling a hexagon. Drag the bar chart to move the plane.>}
foot={<>The profile is the coefficient list of the digit polynomial, so a height is counted without building a single cell; the points are enumerated on the plane itself and projected down the (1,1,1) axis in Rust, one circle per cell, coloured by height and by top-scale corner. The section view is the crate's own triangular mesh through the same solid. Why every one of these cuts is a gasket, and which one the height's binary digits pick, is in the cuts note.>}>
{v?.name}{v?.cut.side}{v && `[${v.low}, ${v.high}]`}{v && `${v.cut.nonempty} of ${v.cut.heights}`}{v?.here}{v?.cut.min}{v?.cut.max}{v && (v.cut.constant ? 'yes' : 'no')}{v?.digits}{drawn}
);
}
mount();