PageSourceSearch

https://starwarsdatabase.com/gallery/src/jukebox-motion.js?v=0.67.1

js starwarsdatabase.com collected 2026-10-07 19:31:02 UTC 3,668 bytes, 61 lines download raw bytes

1// Dimensions in Gallery metres. Arc-length parameterization keeps chain speed
2// constant through both turnarounds. Carriers translate; they never rotate.
3export const JUKEBOX_CAPACITY=120;
4export const JUKEBOX=Object.freeze({radius:.34,low:.76,high:1.90,trayDepth:.28,trayHeight:.05,slotPitch:.255,photoDepth:.23,depth:1.16});
5export const JUKEBOX_LOOP=2*(JUKEBOX.high-JUKEBOX.low)+2*Math.PI*JUKEBOX.radius;
6export function jukeboxLayout(count,groups=[count]){
7  if(!Number.isSafeInteger(count)||count<0||count>JUKEBOX_CAPACITY)throw new Error('Invalid Jukebox population.');
8  if(groups.some(n=>!Number.isSafeInteger(n)||n<0)||groups.reduce((a,b)=>a+b,0)!==count)throw new Error('Invalid Jukebox tray groups.');
9  const columns=[6,7,8,9,10].find(c=>groups.reduce((n,g)=>n+Math.ceil(g/c),0)<=12);
10  if(!columns)throw new Error('Too many Jukebox tray groups.');
11  const trays=Math.max(6,groups.reduce((n,g)=>n+Math.ceil(g/columns),0));
12  return {columns,trays,width:columns*JUKEBOX.slotPitch+.30,depth:2.8,pitch:JUKEBOX_LOOP/trays};
13}
14export function jukeboxPoint(distance){
15  const {radius:r,low,high}=JUKEBOX,h=high-low,arc=Math.PI*r;
16  let s=((distance%JUKEBOX_LOOP)+JUKEBOX_LOOP)%JUKEBOX_LOOP;
17  if(s<h)return {y:low+s,z:r,front:true};
18  s-=h;if(s<arc){const a=s/r;return {y:high+r*Math.sin(a),z:r*Math.cos(a),front:false};}
19  s-=arc;if(s<h)return {y:high-s,z:-r,front:false};
20  const a=(s-h)/r;return {y:low-r*Math.sin(a),z:-r*Math.cos(a),front:false};
21}
22// A held motor ramps velocity with a smoothstep curve. Integrating the curve
23// analytically keeps the same travelled distance at 30, 60, 120 or 144 Hz.
24export function driveJukebox(motion,direction){
25  if(![-1,0,1].includes(direction)||motion.drive===direction)return;
26  motion.drive=direction;motion.fromVelocity=motion.velocity;
27  motion.toVelocity=direction*.34;motion.elapsed=0;
28  motion.duration=direction===0?.12:.20;
29}
30export function advanceJukebox(motion,dt){
31  if(!(dt>0)||!Number.isFinite(dt))return false;
32  const before=motion.position;
33  if(motion.elapsed<motion.duration){
34    const step=Math.min(dt,motion.duration-motion.elapsed),t0=motion.elapsed/motion.duration,t1=(motion.elapsed+step)/motion.duration;
35    const primitive=t=>t*t*t-.5*t*t*t*t,difference=motion.toVelocity-motion.fromVelocity;
36    motion.position+=motion.fromVelocity*step+difference*motion.duration*(primitive(t1)-primitive(t0));
37    motion.elapsed+=step;motion.velocity=motion.fromVelocity+difference*(3*t1*t1-2*t1*t1*t1);dt-=step;
38    if(motion.elapsed>=motion.duration)motion.velocity=motion.toVelocity;
39  }
40  motion.position+=motion.velocity*dt;
41  return motion.position!==before;
42}
43export function jukeboxMotor(){return {position:0,velocity:0,drive:0,fromVelocity:0,toVelocity:0,elapsed:0,duration:0};}
44
45// Adjacent groups of one maker/country/category/presentation policy may share
46// a cabinet. Start every group on a fresh tray; never consume another group's
47// remaining row slots. Split a large group only at a fixture boundary.
48export function packJukeboxGroups(groups,start=0){
49  const units=[];let parts=[];
50  const flush=()=>
50{if(!parts.length)return;const count=parts.reduce((n,p)=>n+p.count,0),layout=jukeboxLayout(count,parts.map(p=>p.count));units.push({start:parts[0].start,count,parts,layout});parts=[];};
51  for(const group of groups){
52    let remaining=group.total;
53    while(remaining){
54      const free=(12-parts.reduce((n,p)=>n+Math.ceil(p.count/10),0))*10;
55      if(!free){flush();continue;}
56      const count=Math.min(remaining,free),{items,...metadata}=group;parts.push({...metadata,start,count});start+=count;remaining-=count;
57      if(remaining)flush();
58    }
59  }
60  flush();return units;
61}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.