Files
Emil_Shanayev_Resume/lib/plan.ts
T
EmilandClaude Sonnet 5 b5ffc67a82
Deploy to GitHub Pages / build (push) Canceled after 0s
Deploy to GitHub Pages / deploy (push) Canceled after 0s
Redesign the resume site as a 3D-editor viewport
New design: studio backdrop with a perspective floor and X/Z axis lines, an
orientation gizmo that orbits on scroll, Bricolage Grotesque and Instrument
Sans (bundled, no build-time network). Projects are laid out as plates by a
row planner that keeps every row full for any count; a demo image from the
repo root is shown when present, otherwise a generated voxel sculpture.
Text and projects still come live from Gitea.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XtcZtnG4GQA1d6mW5PNrS9
2026-09-20 21:37:35 +03:00

40 lines
1.1 KiB
TypeScript

export type Span = 2 | 3 | 4 | 6
/**
* Column spans (out of 6) for `count` projects, so that every row is exactly full whatever the count:
* rows of two or three, a feature row first, and never a lone project in the last row (a single project
* spans the whole width). Two-project rows alternate 4+2 and 2+4 for rhythm.
*/
export function planSpans(count: number): Span[] {
if (count <= 0) return []
if (count === 1) return [6]
const sizes: number[] = []
const pattern = [2, 3, 3]
let remaining = count
for (let i = 0; remaining > 0; i++) {
const size = Math.min(pattern[i % pattern.length], remaining)
sizes.push(size)
remaining -= size
}
const last = sizes.length - 1
if (sizes[last] === 1) {
if (sizes[last - 1] === 3) {
sizes[last - 1] = 2
sizes[last] = 2
} else {
sizes[last - 1] = 3
sizes.pop()
}
}
const spans: Span[] = []
let pairs = 0
for (const size of sizes) {
if (size === 3) spans.push(2, 2, 2)
else spans.push(...(pairs++ % 2 === 0 ? ([4, 2] as const) : ([2, 4] as const)))
}
return spans
}