Phase 1 of the cohesion refactor (behavior-preserving): Single source of truth: - New src/lib/theme.ts: category colors (moved from data.ts, re-exported for back-compat), derived hex strings, nebula palette, UI colors, CSS var map - New src/lib/config.ts: breakpoint, zoom, parallax, node radii, particle counts, animation timings (previously scattered magic numbers) - New src/lib/utils/tree.ts: getNodeById, getNodeRadius, getDistanceFromOrigin, getBeamIntensity (pure helpers lifted out of onMount) - New src/lib/utils/stats.ts: branch ids/labels, proficiency order, and the stats-panel aggregation helpers (deduped from inline copies) - SkillTree.svelte now imports all of the above; removed the duplicated getCategoryColorHex, stats helpers, branch id/label lists, and inline magic numbers - Populated src/lib/index.ts barrel Bug fixes: - data.ts: tmdbAPI pypiUrl pointed at tvdbAPI -> corrected to tmdbAPI - Removed/ gated stray console.log noise (skill-tree-loaded, SW logs) - Removed dead vars (maxAlpha, glowMaxAlpha) and unused catch binding Tooling: ESLint + Prettier now clean; added Vitest unit tests for the new pure utils (14 tests). svelte-check: 0 errors. build: ok. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
36 lines
1.4 KiB
TypeScript
36 lines
1.4 KiB
TypeScript
// ==========================================================================
|
||
// TREE UTILS — pure helpers over the tree node data (no PixiJS, no DOM).
|
||
// ==========================================================================
|
||
|
||
import { treeNodes, type TreeNode } from '$lib/data';
|
||
import { NODE_RADII, MOBILE_RADIUS_FACTOR } from '$lib/config';
|
||
|
||
/** Look up a node by id. */
|
||
export function getNodeById(id: string): TreeNode | undefined {
|
||
return treeNodes.find((node) => node.id === id);
|
||
}
|
||
|
||
/** Rendered radius for a node size, scaled down on mobile. */
|
||
export function getNodeRadius(size: TreeNode['size'], isMobile: boolean): number {
|
||
const base = NODE_RADII[size] ?? NODE_RADII.default;
|
||
return base * (isMobile ? MOBILE_RADIUS_FACTOR : 1);
|
||
}
|
||
|
||
/** Euclidean distance of a node from the tree centre (0, 0). */
|
||
export function getDistanceFromOrigin(node: TreeNode): number {
|
||
return Math.sqrt(node.x * node.x + node.y * node.y);
|
||
}
|
||
|
||
/**
|
||
* Plasma-beam intensity for the connection feeding a node. Skills scale with
|
||
* years of experience (0.3–1.0); other categories use fixed tiers.
|
||
*/
|
||
export function getBeamIntensity(node: TreeNode): number {
|
||
if (node.category === 'skills' && node.yearsOfExperience) {
|
||
return Math.min(0.3 + (node.yearsOfExperience / 10) * 0.7, 1.0);
|
||
}
|
||
if (node.category === 'experience') return 0.7;
|
||
if (node.category === 'origin') return 1.0;
|
||
return 0.5; // projects and education
|
||
}
|