Files
Ely-GPUI-Components/frontend/src/iso/models.ts
T

96 lines
4.3 KiB
TypeScript

export type Tone = "paper" | "ink" | "soft" | "accent";
/** A box on the table: cell, footprint, lift, height, tone, the beat it grows on. */
export interface Block {
x: number;
z: number;
w: number;
d: number;
y: number;
h: number;
tone: Tone;
beat: number;
}
export type Model = { blocks: Block[]; span: [number, number] };
const block = (x: number, z: number, w: number, d: number, h: number, tone: Tone, y = 0): Block => ({
x, z, w, d, y, h, tone, beat: 0,
});
/** Beats from the far corner toward the eye, one diagonal a step. */
function sweep(blocks: Block[], pace = 1): Block[] {
return blocks.map((b) => ({ ...b, beat: b.beat || Math.round((b.x + b.z) * pace) }));
}
/** A small app on its slab: a sidebar, a chart, a chat, a switch. */
export function app(): Model {
const b: Block[] = [block(0, 0, 18, 12, 0.5, "paper")];
b.push(block(0.5, 0.5, 17, 1, 0.3, "soft", 0.5));
for (let i = 0; i < 3; i++) b.push(block(1 + i * 0.9, 0.8, 0.5, 0.4, 0.3, i === 0 ? "accent" : "ink", 0.8));
for (let i = 0; i < 6; i++) b.push(block(0.8, 2.2 + i * 1.5, 3.4, 1, 0.3, i === 1 ? "accent" : "soft", 0.5));
b.push(block(5, 2.2, 7.4, 1, 0.25, "soft", 0.5));
b.push(block(5, 4, 7.4, 5.6, 0.12, "soft", 0.5));
const bars = [0.9, 1.5, 1.2, 2.1, 1.7, 2.8, 2.3, 3.2];
bars.forEach((h, i) => b.push(block(5.4 + i * 0.85, 7.2, 0.55, 1.2, h, i === 5 ? "accent" : "ink", 0.62)));
b.push(block(5.4, 10.4, 6.6, 0.3, 0.15, "soft", 0.5));
b.push(block(8.4, 10.3, 0.5, 0.5, 0.5, "accent", 0.5));
for (let i = 0; i < 4; i++) {
const mine = i % 2 === 1;
b.push(block(mine ? 14.2 : 13, 2.2 + i * 1.7, mine ? 2.8 : 3.6, 1.2, 0.5, mine ? "ink" : "soft", 0.5));
}
b.push(block(13, 9.6, 1.6, 0.8, 0.35, "soft", 0.5));
b.push(block(13.9, 9.6, 0.7, 0.8, 0.7, "accent", 0.5));
return { blocks: sweep(b, 0.9), span: [18, 12] };
}
/** Twenty candles and their volume, rising in the accent, falling in ink. */
export function candles(): Model {
const b: Block[] = [block(0, 0, 21, 8, 0.3, "paper")];
const days: Array<[number, number, number, number]> = [];
let close = 0;
for (let i = 0; i < 20; i++) {
const open = close;
close = open + Math.sin(i * 1.7) * 1.1 + Math.cos(i * 0.6) * 0.6 + 0.25;
days.push([open, close, Math.min(open, close) - 0.4 - (i % 3) * 0.2, Math.max(open, close) + 0.35 + (i % 2) * 0.3]);
}
// Prices fill 0.9 to 4.5 above the slab.
const floor = Math.min(...days.map((d) => d[2]));
const range = Math.max(...days.map((d) => d[3])) - floor;
const lift = (price: number) => 0.9 + ((price - floor) / range) * 3.6;
days.forEach(([open, close, low, high], i) => {
const x = 0.7 + i;
b.push({ ...block(x + 0.33, 2.73, 0.14, 0.14, lift(high) - lift(low), "soft", lift(low)), beat: 2 + i * 2 });
const [bottom, top] = [lift(Math.min(open, close)), lift(Math.max(open, close))];
b.push({ ...block(x, 2.4, 0.8, 0.8, Math.max(top - bottom, 0.2), close >= open ? "accent" : "ink", bottom), beat: 3 + i * 2 });
b.push({ ...block(x, 5, 0.8, 1.6, 0.2 + ((i * 7) % 5) * 0.22, "soft", 0.3), beat: 3 + i * 2 });
});
return { blocks: sweep(b), span: [21, 8] };
}
/** Five series of eight months, one in the accent. */
export function bars(): Model {
const b: Block[] = [block(0, 0, 11, 8, 0.3, "paper")];
for (let z = 0; z < 5; z++) {
for (let x = 0; x < 8; x++) {
const h = 0.4 + 2.2 * (0.5 + 0.5 * Math.sin(x * 0.7 + z * 1.1)) * (1 + z * 0.12);
const tone: Tone = z === 2 ? "accent" : z === 4 ? "ink" : "soft";
b.push({ ...block(1 + x * 1.2, 1 + z * 1.3, 0.8, 0.8, h, tone, 0.3), beat: x * 2 + z });
}
}
return { blocks: b, span: [11, 8] };
}
/** A conversation: turns left and right, and three dots still typing. */
export function chat(): Model {
const b: Block[] = [block(0, 0, 10, 12, 0.3, "paper")];
const turns: Array<[boolean, number]> = [[false, 6], [true, 4.4], [false, 7.2], [true, 3.2], [false, 5.4]];
turns.forEach(([mine, w], i) => {
const z = 1 + i * 2;
if (!mine) b.push({ ...block(0.8, z + 0.3, 0.8, 0.8, 0.8, "ink", 0.3), beat: i * 4 });
b.push({ ...block(mine ? 9.2 - w : 2, z, w, 1.4, 0.45, mine ? "accent" : "soft", 0.3), beat: i * 4 + 1 });
});
for (let i = 0; i < 3; i++) b.push({ ...block(2.2 + i * 0.7, 10.9, 0.45, 0.45, 0.45, "ink", 0.3), beat: 21 + i });
return { blocks: b, span: [10, 12] };
}