update logistices
This commit is contained in:
179
src/components/logisticsbrain/theme.ts
Normal file
179
src/components/logisticsbrain/theme.ts
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* Shared design tokens, scroll-phase thresholds and the cinematic camera path
|
||||
* for the "Logistics Brain" scroll-storytelling section.
|
||||
*
|
||||
* The whole experience is driven by ONE normalized scroll progress value
|
||||
* (0 → 1) shared between GSAP ScrollTrigger, the R3F render loop and the
|
||||
* Framer-Motion HTML overlay — so every layer stays perfectly in sync and the
|
||||
* journey reads as one continuous shot with no scene cuts.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Doormile brand palette: near-black + brand red, with green reserved for the
|
||||
* "delivered / optimized" success state.
|
||||
*
|
||||
* NOTE ON TOKEN NAMES: the keys below (cyan/blue/violet/…) are the original
|
||||
* cool-palette slot names, kept ONLY so the many `C.cyan`-style references in
|
||||
* the scene files don't all have to change. Their *values* are now brand reds
|
||||
* and neutral steels — read the inline comment, not the key name. New code
|
||||
* should prefer the semantic aliases (red / redBright / redSoft / steel).
|
||||
*/
|
||||
export const C = {
|
||||
bg: "#08080c", // near-black scene background
|
||||
|
||||
red: "#C01227", // PRIMARY brand red
|
||||
cyan: "#E2354A", // redBright — main glowing red accent (roads, rings, brain, scooter)
|
||||
blue: "#7E1420", // crimson — dim deep-red structural glow (grid, links, soft glows)
|
||||
sky: "#F2667A", // redSoft — light coral highlight points
|
||||
magenta: "#C8102E", // secondary brand red
|
||||
violet: "#3c3c46", // steel — neutral grey structure (losing routes, secondary shell)
|
||||
purple: "#6a6a76", // steelLight — lighter neutral grey
|
||||
|
||||
steel: "#43434d", // losing-route grey
|
||||
gray: "#7c7c86", // losing-route grey (lighter)
|
||||
|
||||
green: "#22C55E", // success / delivered (unchanged)
|
||||
amber: "#F59E0B", // transitional (battery mid-charge) (unchanged)
|
||||
white: "#FFFFFF",
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Palette for the six competing route simulations. Index 0 (Multi-Trip) is the
|
||||
* winner and gets the brand red so it stands out; the five losing strategies
|
||||
* are neutral greys that recede, then fade out entirely.
|
||||
*/
|
||||
export const ROUTE_COLORS = [
|
||||
C.red, // 0 — the eventual winner (brand red)
|
||||
C.steel,
|
||||
C.gray,
|
||||
C.steel,
|
||||
C.gray,
|
||||
C.steel,
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* The six strategies the "Parallel Universe Engine" benchmarks (index-aligned
|
||||
* to ROUTE_COLORS). Index 0 = Multi-Trip is the winner — it's also what solves
|
||||
* the EV paradox (59/59 vs 34/59), tying the routes beat to the EV beat.
|
||||
*/
|
||||
export const STRATEGIES = [
|
||||
"Multi-Trip",
|
||||
"Proximity",
|
||||
"Balanced",
|
||||
"Fuel Saver",
|
||||
"EV-Aware",
|
||||
"Time-Aware",
|
||||
] as const;
|
||||
export const WINNER_INDEX = 0;
|
||||
|
||||
/** The constraints the VRP solver optimizes together (Mathematical Precision). */
|
||||
export const CONSTRAINTS = ["Capacity", "Distance", "Battery", "Traffic", "SLA"] as const;
|
||||
|
||||
/** Plain-language constraints shown in the EV / constraints beat. */
|
||||
export const CONSTRAINT_LIST = [
|
||||
{ icon: "🔋", label: "Battery", note: "EV range & recharge stops" },
|
||||
{ icon: "📍", label: "Distance", note: "Total km per route" },
|
||||
{ icon: "📦", label: "Capacity", note: "Orders each vehicle can carry" },
|
||||
{ icon: "⏱️", label: "Time / SLA", note: "Promised delivery windows" },
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Scored leaderboard for the "Score & Compare" beat. Higher = better total
|
||||
* delivery cost/outcome. Multi-Trip wins; EV-Aware (the naive baseline) scores
|
||||
* worst — it's the one that only delivered 34/59 in the EV paradox beat.
|
||||
*/
|
||||
export const STRATEGY_SCORES: { name: string; score: number; win?: boolean }[] = [
|
||||
{ name: "Multi-Trip", score: 98, win: true },
|
||||
{ name: "Time-Aware", score: 90 },
|
||||
{ name: "Balanced", score: 84 },
|
||||
{ name: "Proximity", score: 76 },
|
||||
{ name: "Fuel Saver", score: 68 },
|
||||
{ name: "EV-Aware", score: 58 },
|
||||
];
|
||||
|
||||
/** Layout anchors (world units). */
|
||||
export const BRAIN_Y = 3.0; // depot beacon hovers low over the map centre
|
||||
export const CITY_RADIUS = 19;
|
||||
|
||||
/**
|
||||
* Scroll-phase thresholds (normalized 0 → 1). These are *story beats*, not hard
|
||||
* cuts — every element cross-fades across a window around its beat so the scene
|
||||
* morphs continuously.
|
||||
*/
|
||||
export const P = {
|
||||
birth: 0.0, // glowing brain + city form, energy roads grow
|
||||
routes: 0.13, // six route simulations race through the city
|
||||
ev: 0.28, // EV battery drains → recalc → charging station → green route
|
||||
network: 0.44, // camera rises to eagle-eye; full live network
|
||||
sla: 0.6, // holographic SLA clock; delayed routes dissolve
|
||||
ecosystem: 0.74, // pull back; warehouses + fleet come alive
|
||||
finale: 0.88, // fly up; stats + logo + tagline reveal
|
||||
} as const;
|
||||
|
||||
export type PhaseKey = keyof typeof P;
|
||||
|
||||
/**
|
||||
* The six steps of the routing engine, in plain language — the spine of the
|
||||
* on-screen story. The persistent step rail and the per-beat content cards both
|
||||
* read from this so a non-technical viewer can follow the workflow. `at` is the
|
||||
* scroll-progress threshold where each step becomes the active one.
|
||||
*/
|
||||
export const ENGINE_STEPS = [
|
||||
{ n: "01", at: P.routes, title: "Generate Routes", caption: "Many delivery plans created at once" },
|
||||
{ n: "02", at: P.ev, title: "Check Constraints", caption: "Battery, distance, capacity & time" },
|
||||
{ n: "03", at: P.network, title: "Score & Compare", caption: "Every plan ranked by total cost" },
|
||||
{ n: "04", at: P.sla, title: "Guarantee On-Time", caption: "Late plans rejected automatically" },
|
||||
{ n: "05", at: P.ecosystem, title: "Pick & Dispatch", caption: "Best plan sent to the fleet" },
|
||||
{ n: "06", at: P.finale, title: "Delivered", caption: "Real business results" },
|
||||
] as const;
|
||||
|
||||
export const PHASE_CAPTIONS: Record<PhaseKey, string> = {
|
||||
birth: "Initializing the logistics brain",
|
||||
routes: "Simulating delivery strategies",
|
||||
ev: "Recalculating around EV constraints",
|
||||
network: "Mapping the live delivery network",
|
||||
sla: "Enforcing on-time SLA reliability",
|
||||
ecosystem: "Autonomous fleet in motion",
|
||||
finale: "",
|
||||
};
|
||||
|
||||
export function captionFor(p: number): string {
|
||||
if (p >= P.finale) return PHASE_CAPTIONS.finale;
|
||||
if (p >= P.ecosystem) return PHASE_CAPTIONS.ecosystem;
|
||||
if (p >= P.sla) return PHASE_CAPTIONS.sla;
|
||||
if (p >= P.network) return PHASE_CAPTIONS.network;
|
||||
if (p >= P.ev) return PHASE_CAPTIONS.ev;
|
||||
if (p >= P.routes) return PHASE_CAPTIONS.routes;
|
||||
return PHASE_CAPTIONS.birth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Camera waypoints sampled by scroll progress. Each has an eye position and a
|
||||
* look-at target. The rig lerps between adjacent waypoints (smoothstep eased)
|
||||
* and then exponentially damps toward the result — giving a smooth spline-like
|
||||
* dolly with no jerk on fast scroll.
|
||||
*/
|
||||
export type Waypoint = {
|
||||
at: number;
|
||||
pos: [number, number, number];
|
||||
look: [number, number, number];
|
||||
};
|
||||
|
||||
/**
|
||||
* NEAR-STATIC MAP VIEW. The camera holds a consistent elevated 3/4 "control
|
||||
* room" angle on the depot/map the whole way through — only small, slow shifts
|
||||
* between beats (≈70% less travel than a cinematic fly-through). The story is
|
||||
* told by the OBJECTS on the map (nodes, candidate routes, scores, vehicles),
|
||||
* not by camera moves. Keep these positions clustered; large deltas reintroduce
|
||||
* the "city fly-through" feel we're removing.
|
||||
*/
|
||||
export const WAYPOINTS: Waypoint[] = [
|
||||
{ at: 0.0, pos: [0, 20, 27], look: [0, 1.4, 0] }, // establish the map
|
||||
{ at: 0.13, pos: [-2.5, 20, 26.5], look: [-0.5, 1.2, 0] }, // routes generate
|
||||
{ at: 0.28, pos: [3, 18.5, 25.5], look: [0.6, 0.8, -0.8] }, // constraints — ease toward street
|
||||
{ at: 0.44, pos: [0, 23, 24.5], look: [0, 1.0, 0] }, // score — lift slightly to read labels
|
||||
{ at: 0.6, pos: [2.5, 21, 25.5], look: [0, 1.2, 0] }, // SLA — small lateral drift
|
||||
{ at: 0.74, pos: [-2, 20, 26.5], look: [0, 1.2, 0] }, // dispatch
|
||||
{ at: 0.88, pos: [0, 22, 25.5], look: [0, 1.8, 0] }, // results
|
||||
{ at: 1.0, pos: [0, 21.5, 25.5], look: [0, 2.0, 0] },
|
||||
];
|
||||
Reference in New Issue
Block a user