@johnmorrisdotca/uchusen-rockets 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -4
- package/README.md +3 -2
- package/dist/beside.d.ts +76 -0
- package/dist/beside.js +83 -0
- package/dist/build/index.d.ts +9 -2
- package/dist/build/index.js +49 -23
- package/dist/build/lineup.d.ts +39 -1
- package/dist/build/lineup.js +70 -3
- package/dist/data/sources.d.ts +8 -0
- package/dist/data/sources.js +1 -0
- package/dist/element/scene.d.ts +5 -0
- package/dist/element/scene.js +62 -16
- package/dist/element.d.ts +2 -0
- package/dist/element.js +14 -6
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/journey/bodies.d.ts +47 -0
- package/dist/journey/bodies.js +2 -0
- package/dist/journey/constants.d.ts +115 -0
- package/dist/journey/constants.js +134 -0
- package/dist/journey/countdown.d.ts +49 -0
- package/dist/journey/countdown.js +56 -0
- package/dist/journey/crafts.d.ts +165 -0
- package/dist/journey/crafts.js +142 -0
- package/dist/journey/index.d.ts +11 -0
- package/dist/journey/index.js +8 -0
- package/dist/journey/physics.d.ts +114 -0
- package/dist/journey/physics.js +154 -0
- package/dist/journey/timeline.d.ts +115 -0
- package/dist/journey/timeline.js +193 -0
- package/dist/journey/trip.d.ts +213 -0
- package/dist/journey/trip.js +447 -0
- package/dist/journey/words.d.ts +96 -0
- package/dist/journey/words.js +144 -0
- package/package.json +7 -1
package/dist/element/scene.d.ts
CHANGED
|
@@ -92,6 +92,8 @@ export declare class RocketViewer {
|
|
|
92
92
|
private settled;
|
|
93
93
|
private marks;
|
|
94
94
|
private markHost;
|
|
95
|
+
/** The words that say what stands beside the craft: its name and length, under its foot. */
|
|
96
|
+
private besideEl;
|
|
95
97
|
private focusing;
|
|
96
98
|
private nearSaid;
|
|
97
99
|
private nearAt;
|
|
@@ -189,6 +191,9 @@ export declare class RocketViewer {
|
|
|
189
191
|
private wake;
|
|
190
192
|
/** Labels on the parts: each follows its part as the model turns, hides with its part, and gives way to a label drawn before it that it would cover. Null takes them away. */
|
|
191
193
|
setMarks(marks: readonly ViewerMark[] | null): void;
|
|
194
|
+
private hostOfMarks;
|
|
195
|
+
/** What stands beside the craft is named: a caption under its foot, kept inside the picture. */
|
|
196
|
+
private placeBeside;
|
|
192
197
|
/** Put the labels where their parts are now. */
|
|
193
198
|
private placeMarks;
|
|
194
199
|
/** Show only some slots and fly to look at them: an inset. Null puts the ship back as it was. */
|
package/dist/element/scene.js
CHANGED
|
@@ -14,6 +14,7 @@ import { pixelRatioFor } from "../pixels.js";
|
|
|
14
14
|
import { MATERIALS } from "../model/materials.js";
|
|
15
15
|
import { paintGlow, paintSky, paintSteel, paintTiles } from "./paint.js";
|
|
16
16
|
import { flightBounds, frameAt } from "../flight.js";
|
|
17
|
+
import { besideLabel } from "../beside.js";
|
|
17
18
|
import { GroundKit } from "./ground.js";
|
|
18
19
|
import { PartPlumes, PlumeKit } from "./plumes.js";
|
|
19
20
|
const IDLE_STOP_MS = 90_000;
|
|
@@ -142,6 +143,8 @@ export class RocketViewer {
|
|
|
142
143
|
settled = Promise.resolve();
|
|
143
144
|
marks = [];
|
|
144
145
|
markHost = null;
|
|
146
|
+
/** The words that say what stands beside the craft: its name and length, under its foot. */
|
|
147
|
+
besideEl = null;
|
|
145
148
|
focusing = false;
|
|
146
149
|
nearSaid = false;
|
|
147
150
|
nearAt = 0;
|
|
@@ -237,7 +240,7 @@ export class RocketViewer {
|
|
|
237
240
|
this.renderer.shadowMap.enabled = this.shadows;
|
|
238
241
|
this.sun.castShadow = this.shadows;
|
|
239
242
|
const places = built.placesOf(show);
|
|
240
|
-
for (const part of built.parts) {
|
|
243
|
+
for (const part of [...built.parts, ...built.beside]) {
|
|
241
244
|
const source = gltf.scene.getObjectByName(part.slot);
|
|
242
245
|
if (!source)
|
|
243
246
|
continue;
|
|
@@ -247,11 +250,13 @@ export class RocketViewer {
|
|
|
247
250
|
holder.add(code);
|
|
248
251
|
const view = {
|
|
249
252
|
slot: part.slot,
|
|
253
|
+
beside: built.beside.includes(part),
|
|
250
254
|
holder,
|
|
251
255
|
code,
|
|
252
256
|
model: null,
|
|
253
|
-
|
|
254
|
-
|
|
257
|
+
// the stack beside it is this package's own paint in every look: a licensed model shows only with its credit, which is the craft's
|
|
258
|
+
modelFile: built.beside.includes(part) ? null : (part.record.painted?.file ?? null),
|
|
259
|
+
ownNozzle: !built.beside.includes(part) && Boolean(part.record.painted?.ownNozzle),
|
|
255
260
|
modelState: "none",
|
|
256
261
|
nozzleShown: false,
|
|
257
262
|
faces: [],
|
|
@@ -292,7 +297,8 @@ export class RocketViewer {
|
|
|
292
297
|
this.setFlight(this.clockNow);
|
|
293
298
|
}
|
|
294
299
|
this.canvas.dataset.ready = "true";
|
|
295
|
-
this.canvas.dataset.parts = this.parts.map((part) => part.slot).join(" ");
|
|
300
|
+
this.canvas.dataset.parts = this.parts.filter((part) => !part.beside).map((part) => part.slot).join(" ");
|
|
301
|
+
this.canvas.dataset.beside = built.beside.length ? "on" : "off";
|
|
296
302
|
this.drivenDirty = this.driven !== null;
|
|
297
303
|
this.wake();
|
|
298
304
|
await this.settled;
|
|
@@ -606,6 +612,9 @@ export class RocketViewer {
|
|
|
606
612
|
this.ground = new GroundKit();
|
|
607
613
|
this.scene.add(this.ground.group);
|
|
608
614
|
}
|
|
615
|
+
for (const part of this.parts)
|
|
616
|
+
if (part.beside)
|
|
617
|
+
part.holder.visible = false;
|
|
609
618
|
const { min, max } = this.boundsNow();
|
|
610
619
|
this.ground.fit(this.built.boundsOf("together").max[0] * 2.4 + 4, Math.max(Math.abs(min[0]), Math.abs(max[0])));
|
|
611
620
|
this.ground.group.visible = true;
|
|
@@ -707,7 +716,7 @@ export class RocketViewer {
|
|
|
707
716
|
this.options.onPainted("");
|
|
708
717
|
return;
|
|
709
718
|
}
|
|
710
|
-
const states = this.parts.map((part) => (part.modelFile ? part.modelState : "code"));
|
|
719
|
+
const states = this.parts.filter((part) => !part.beside).map((part) => (part.modelFile ? part.modelState : "code"));
|
|
711
720
|
const state = states.some((s) => s === "loading" || s === "none") ? "loading" : states.every((s) => s === "ready") ? "model" : states.includes("ready") ? "mixed" : "code";
|
|
712
721
|
this.canvas.dataset.painted = state;
|
|
713
722
|
this.options.onPainted(state);
|
|
@@ -1106,18 +1115,13 @@ export class RocketViewer {
|
|
|
1106
1115
|
el.remove();
|
|
1107
1116
|
this.marks = [];
|
|
1108
1117
|
if (!marks || marks.length === 0) {
|
|
1109
|
-
this.
|
|
1110
|
-
|
|
1118
|
+
if (!this.besideEl) {
|
|
1119
|
+
this.markHost?.remove();
|
|
1120
|
+
this.markHost = null;
|
|
1121
|
+
}
|
|
1111
1122
|
return;
|
|
1112
1123
|
}
|
|
1113
|
-
|
|
1114
|
-
const host = document.createElement("div");
|
|
1115
|
-
host.className = "marks";
|
|
1116
|
-
host.setAttribute("aria-hidden", "true");
|
|
1117
|
-
host.style.cssText = "position:absolute;inset:0;overflow:hidden;pointer-events:none;font:11px/1.2 system-ui,sans-serif";
|
|
1118
|
-
this.holder.appendChild(host);
|
|
1119
|
-
this.markHost = host;
|
|
1120
|
-
}
|
|
1124
|
+
this.hostOfMarks();
|
|
1121
1125
|
for (const mark of marks) {
|
|
1122
1126
|
const el = document.createElement("span");
|
|
1123
1127
|
el.dataset.mark = mark.id;
|
|
@@ -1125,11 +1129,52 @@ export class RocketViewer {
|
|
|
1125
1129
|
el.style.cssText = mark.numbered
|
|
1126
1130
|
? "position:absolute;left:0;top:0;width:22px;height:22px;margin:-11px 0 0 -11px;border-radius:50%;background:#f2c14e;color:#0b111b;font-weight:700;text-align:center;line-height:22px;will-change:transform;display:none"
|
|
1127
1131
|
: "position:absolute;left:0;top:0;padding:1px 5px;border-left:2px solid #f2c14e;color:#e6edf6;background:rgba(11,17,27,0.72);white-space:nowrap;will-change:transform;display:none";
|
|
1128
|
-
this.
|
|
1132
|
+
this.hostOfMarks().appendChild(el);
|
|
1129
1133
|
this.marks.push({ mark, el });
|
|
1130
1134
|
}
|
|
1131
1135
|
this.wake();
|
|
1132
1136
|
}
|
|
1137
|
+
hostOfMarks() {
|
|
1138
|
+
if (!this.markHost) {
|
|
1139
|
+
const host = document.createElement("div");
|
|
1140
|
+
host.className = "marks";
|
|
1141
|
+
host.setAttribute("aria-hidden", "true");
|
|
1142
|
+
host.style.cssText = "position:absolute;inset:0;overflow:hidden;pointer-events:none;font:11px/1.2 system-ui,sans-serif";
|
|
1143
|
+
this.holder.appendChild(host);
|
|
1144
|
+
this.markHost = host;
|
|
1145
|
+
}
|
|
1146
|
+
return this.markHost;
|
|
1147
|
+
}
|
|
1148
|
+
/** What stands beside the craft is named: a caption under its foot, kept inside the picture. */
|
|
1149
|
+
placeBeside() {
|
|
1150
|
+
const view = this.parts.find((part) => part.beside);
|
|
1151
|
+
if (!view) {
|
|
1152
|
+
this.besideEl?.remove();
|
|
1153
|
+
this.besideEl = null;
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
if (!this.besideEl) {
|
|
1157
|
+
const el = document.createElement("span");
|
|
1158
|
+
el.dataset.besideLabel = "";
|
|
1159
|
+
el.textContent = besideLabel();
|
|
1160
|
+
el.style.cssText = "position:absolute;left:0;top:0;padding:1px 5px;color:#e6edf6;background:rgba(11,17,27,0.72);white-space:nowrap;will-change:transform;display:none";
|
|
1161
|
+
this.hostOfMarks().appendChild(el);
|
|
1162
|
+
this.besideEl = el;
|
|
1163
|
+
}
|
|
1164
|
+
const el = this.besideEl;
|
|
1165
|
+
if (!view.holder.visible || this.clockNow) {
|
|
1166
|
+
el.style.display = "none";
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
const width = this.canvas.clientWidth;
|
|
1170
|
+
const height = this.canvas.clientHeight;
|
|
1171
|
+
const point = new Vector3(view.holder.position.x, view.holder.position.y, view.holder.position.z).project(this.camera);
|
|
1172
|
+
const w = besideLabel().length * 6.2 + 12;
|
|
1173
|
+
const x = Math.min(Math.max(((point.x + 1) / 2) * width - w / 2, 4), Math.max(4, width - w - 4));
|
|
1174
|
+
const y = Math.min(((1 - point.y) / 2) * height + 6, height - 20);
|
|
1175
|
+
el.style.display = point.z < 1 ? "block" : "none";
|
|
1176
|
+
el.style.transform = `translate(${Math.round(x)}px,${Math.round(y)}px)`;
|
|
1177
|
+
}
|
|
1133
1178
|
/** Put the labels where their parts are now. */
|
|
1134
1179
|
placeMarks() {
|
|
1135
1180
|
if (this.marks.length === 0)
|
|
@@ -1282,6 +1327,7 @@ export class RocketViewer {
|
|
|
1282
1327
|
this.syncSizes();
|
|
1283
1328
|
this.renderer.render(this.scene, this.camera);
|
|
1284
1329
|
this.placeMarks();
|
|
1330
|
+
this.placeBeside();
|
|
1285
1331
|
if (this.options.onNear && !this.nearSaid && this.nearAt > 0 && this.camera.position.distanceTo(this.controls.target) < this.nearAt) {
|
|
1286
1332
|
this.nearSaid = true;
|
|
1287
1333
|
this.options.onNear();
|
package/dist/element.d.ts
CHANGED
|
@@ -144,6 +144,8 @@ export declare class UchusenRocket extends HTMLBase {
|
|
|
144
144
|
private flightStep;
|
|
145
145
|
/** Tells the page where the timeline is: at once for a new phase or a stop, otherwise at most 8 times a second. */
|
|
146
146
|
private noteFlight;
|
|
147
|
+
/** Whether Starship stands beside it: `beside="on"`, and never beside Starship itself. */
|
|
148
|
+
private besideOn;
|
|
147
149
|
/** Whether the engines are lit: `engines="on"`, and never for a reader who asked for reduced motion. */
|
|
148
150
|
private engineLights;
|
|
149
151
|
/** Hands the 3D view what the attributes say about the engines, and its reader's motion setting. */
|
package/dist/element.js
CHANGED
|
@@ -9,6 +9,7 @@ import { defineUchusenFlight, UchusenFlight } from "./flightbar.js";
|
|
|
9
9
|
import { lineupSvg } from "./build/lineup.js";
|
|
10
10
|
import { CROSSFADE_MS, REDUCED_FADE_MS, revealDelay } from "./crossfade.js";
|
|
11
11
|
import { cleanView, turnedBy, VIEWS } from "./framing.js";
|
|
12
|
+
import { canBeside } from "./beside.js";
|
|
12
13
|
import { cleanShow } from "./layout.js";
|
|
13
14
|
import { cleanLook } from "./looks.js";
|
|
14
15
|
import { ROCKETS, SLOT_NAMES } from "./rockets.js";
|
|
@@ -123,7 +124,7 @@ function whyNot(mode) {
|
|
|
123
124
|
* ```
|
|
124
125
|
*/
|
|
125
126
|
export class UchusenRocket extends HTMLBase {
|
|
126
|
-
static observedAttributes = ["rocket", "variant", "show", "look", "view", "build", "mode", "assets", "spin", "way", "label", "engines", "phase", "labels", "inspector"];
|
|
127
|
+
static observedAttributes = ["rocket", "variant", "show", "look", "view", "build", "mode", "assets", "spin", "way", "label", "engines", "phase", "labels", "inspector", "beside"];
|
|
127
128
|
descriptionValue = null;
|
|
128
129
|
picture = null;
|
|
129
130
|
holder = null;
|
|
@@ -440,6 +441,10 @@ export class UchusenRocket extends HTMLBase {
|
|
|
440
441
|
this.dataset.phase = this.flightState.active ? this.flightState.phase : "";
|
|
441
442
|
this.emit("uchusen-flight", this.flightState);
|
|
442
443
|
}
|
|
444
|
+
/** Whether Starship stands beside it: `beside="on"`, and never beside Starship itself. */
|
|
445
|
+
besideOn(description) {
|
|
446
|
+
return this.getAttribute("beside") === "on" && canBeside(description.rocket);
|
|
447
|
+
}
|
|
443
448
|
/** Whether the engines are lit: `engines="on"`, and never for a reader who asked for reduced motion. */
|
|
444
449
|
engineLights() {
|
|
445
450
|
return enginesWanted(this.getAttribute("engines"), media("(prefers-reduced-motion: reduce)"));
|
|
@@ -451,11 +456,11 @@ export class UchusenRocket extends HTMLBase {
|
|
|
451
456
|
}
|
|
452
457
|
update() {
|
|
453
458
|
const description = this.descriptionNow();
|
|
454
|
-
const key = JSON.stringify(description)
|
|
459
|
+
const key = `${JSON.stringify(description)}|${this.besideOn(description)}`;
|
|
455
460
|
if (key !== this.key || !this.builtNow) {
|
|
456
461
|
this.key = key;
|
|
457
462
|
try {
|
|
458
|
-
this.builtNow = build(description, { detail: this.detailFor(description) });
|
|
463
|
+
this.builtNow = build(description, { detail: this.detailFor(description), beside: this.besideOn(description) });
|
|
459
464
|
}
|
|
460
465
|
catch (error) {
|
|
461
466
|
this.builtNow = null;
|
|
@@ -557,6 +562,7 @@ export class UchusenRocket extends HTMLBase {
|
|
|
557
562
|
const { look, show, viewName } = this.settings(this.builtNow);
|
|
558
563
|
this.dataset.look = look;
|
|
559
564
|
this.dataset.engines = this.engineLights() ? "on" : "off";
|
|
565
|
+
this.dataset.beside = this.builtNow.beside.length ? "on" : "off";
|
|
560
566
|
this.dataset.flight = this.flight?.id ?? "";
|
|
561
567
|
this.dataset.show = show;
|
|
562
568
|
this.dataset.viewAngle = viewName;
|
|
@@ -604,7 +610,7 @@ export class UchusenRocket extends HTMLBase {
|
|
|
604
610
|
return;
|
|
605
611
|
this.fine = true;
|
|
606
612
|
try {
|
|
607
|
-
this.builtNow = build(description, { detail: "full" });
|
|
613
|
+
this.builtNow = build(description, { detail: "full", beside: this.besideOn(description) });
|
|
608
614
|
}
|
|
609
615
|
catch {
|
|
610
616
|
return;
|
|
@@ -871,7 +877,7 @@ svg { display: block; }
|
|
|
871
877
|
* ```
|
|
872
878
|
*/
|
|
873
879
|
export class UchusenLineup extends HTMLBase {
|
|
874
|
-
static observedAttributes = ["items", "unit", "look", "view", "show", "ruler", "labels", "filter", "fit"];
|
|
880
|
+
static observedAttributes = ["items", "unit", "look", "view", "show", "ruler", "labels", "filter", "fit", "real"];
|
|
875
881
|
connectedCallback() {
|
|
876
882
|
if (!this.shadowRoot)
|
|
877
883
|
adopt(this.attachShadow({ mode: "open" }), LINEUP_CSS, lineupSheet);
|
|
@@ -888,7 +894,8 @@ export class UchusenLineup extends HTMLBase {
|
|
|
888
894
|
const raw = Number.parseFloat(this.getAttribute("unit") ?? "3");
|
|
889
895
|
const unit = Number.isFinite(raw) && raw > 0 && raw <= 100 ? raw : 3;
|
|
890
896
|
const items = (this.getAttribute("items") ?? "").split(",").map((item) => item.trim()).filter(Boolean);
|
|
891
|
-
const { svg, items: shown, unit: drawnUnit } = lineupSvg({
|
|
897
|
+
const { svg, items: shown, real: shownReal, unit: drawnUnit } = lineupSvg({
|
|
898
|
+
real: this.getAttribute("real") === "on",
|
|
892
899
|
items,
|
|
893
900
|
unit,
|
|
894
901
|
look: cleanLook(this.getAttribute("look")),
|
|
@@ -909,6 +916,7 @@ export class UchusenLineup extends HTMLBase {
|
|
|
909
916
|
child.remove();
|
|
910
917
|
root.appendChild(node);
|
|
911
918
|
this.dataset.count = String(shown.length);
|
|
919
|
+
this.dataset.real = String(shownReal.length);
|
|
912
920
|
}
|
|
913
921
|
}
|
|
914
922
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export type { Angle, Framing, Vec3, ViewChoice, ViewName } from "./framing.ts";
|
|
|
22
22
|
export { cleanLook, DEFAULT_LOOK, LOOK_NAMES, LOOKS } from "./looks.ts";
|
|
23
23
|
export type { Look, LookName } from "./looks.ts";
|
|
24
24
|
export { cleanShow, placesFor, showsOf } from "./layout.ts";
|
|
25
|
+
export { BESIDE_ROCKET, besideBounds, besideLabel, besideLayout, canBeside } from "./beside.ts";
|
|
25
26
|
export type { Place, ShowName } from "./layout.ts";
|
|
26
27
|
export { CROSSFADE_MS, DRAWING_HOLD_MS, REDUCED_FADE_MS, revealDelay } from "./crossfade.ts";
|
|
27
28
|
export { MAX_PIXELS, MAX_RATIO, MAX_SIDE, pixelRatioFor } from "./pixels.ts";
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ export { check } from "./fit.js";
|
|
|
12
12
|
export { axesOf, cleanView, DEFAULT_VIEW, directionOf, FOV_DEG, frameFor, PICTURE_H, PICTURE_W, turnedBy, VIEW_NAMES, VIEWS } from "./framing.js";
|
|
13
13
|
export { cleanLook, DEFAULT_LOOK, LOOK_NAMES, LOOKS } from "./looks.js";
|
|
14
14
|
export { cleanShow, placesFor, showsOf } from "./layout.js";
|
|
15
|
+
export { BESIDE_ROCKET, besideBounds, besideLabel, besideLayout, canBeside } from "./beside.js";
|
|
15
16
|
export { CROSSFADE_MS, DRAWING_HOLD_MS, REDUCED_FADE_MS, revealDelay } from "./crossfade.js";
|
|
16
17
|
export { MAX_PIXELS, MAX_RATIO, MAX_SIDE, pixelRatioFor } from "./pixels.js";
|
|
17
18
|
export { tiltMode, tiltTurn } from "./tilt.js";
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A place a trip can start or end at: the Earth, the Moon or a planet, with what the arithmetic needs.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import type { Stop } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
7
|
+
*
|
|
8
|
+
* const mars: Stop = { id: "mars", name: { en: "Mars", ja: "火星" }, kind: "planet", radiusKm: 3396.19, colour: "#c76a3f" };
|
|
9
|
+
* console.log(mars.name.en);
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export interface Stop {
|
|
13
|
+
id: string;
|
|
14
|
+
name: {
|
|
15
|
+
en: string;
|
|
16
|
+
ja: string;
|
|
17
|
+
};
|
|
18
|
+
kind: "star" | "planet" | "dwarf-planet" | "moon";
|
|
19
|
+
/** The planet a moon goes round. */
|
|
20
|
+
parent?: string;
|
|
21
|
+
/** The equatorial radius, km. */
|
|
22
|
+
radiusKm: number;
|
|
23
|
+
/** The gravitational parameter, km^3/s^2. Left out, the journey's own table (`GM_KM3_S2`) is used. */
|
|
24
|
+
muKm3s2?: number;
|
|
25
|
+
/** The sidereal orbital period, days. Left out, the journey's own table (`PERIOD_DAYS`) is used. */
|
|
26
|
+
periodDays?: number;
|
|
27
|
+
/** The body's mean colour, `#rrggbb`. */
|
|
28
|
+
colour: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Where the stops are, and what they are. The journey's core takes one of these and imports nothing.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* import type { BodySource } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
36
|
+
*
|
|
37
|
+
* const empty: BodySource = { stops: [], positionAu: () => [0, 0, 0], offsetKm: () => [0, 0, 0] };
|
|
38
|
+
* console.log(empty.stops.length);
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export interface BodySource {
|
|
42
|
+
stops: readonly Stop[];
|
|
43
|
+
/** A planet's position round the Sun (ecliptic, astronomical units) at a time in milliseconds since 1970. */
|
|
44
|
+
positionAu(id: string, ms: number): readonly [number, number, number];
|
|
45
|
+
/** A moon's position from its planet's centre (ecliptic, kilometres) at a time. */
|
|
46
|
+
offsetKm(id: string, ms: number): readonly [number, number, number];
|
|
47
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The speed of light, metres a second (exact, by definition of the metre).
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { C } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
7
|
+
*
|
|
8
|
+
* console.log(C);
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export declare const C = 299792458;
|
|
12
|
+
/**
|
|
13
|
+
* One standard gravity, metres a second squared (exact, by definition).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { G0 } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
18
|
+
*
|
|
19
|
+
* console.log(G0);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare const G0 = 9.80665;
|
|
23
|
+
/**
|
|
24
|
+
* One astronomical unit, metres (exact, IAU 2012).
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { AU_M } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
29
|
+
*
|
|
30
|
+
* console.log(AU_M);
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare const AU_M = 149597870700;
|
|
34
|
+
/**
|
|
35
|
+
* One astronomical unit, kilometres.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* import { AU_KM } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
40
|
+
*
|
|
41
|
+
* console.log(AU_KM);
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare const AU_KM: number;
|
|
45
|
+
/**
|
|
46
|
+
* A day, seconds.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* import { DAY_S } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
51
|
+
*
|
|
52
|
+
* console.log(DAY_S);
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare const DAY_S = 86400;
|
|
56
|
+
/**
|
|
57
|
+
* A Julian year, seconds.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* import { YEAR_S } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
62
|
+
*
|
|
63
|
+
* console.log(YEAR_S);
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare const YEAR_S = 31557600;
|
|
67
|
+
/**
|
|
68
|
+
* A light year, metres.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* import { LY_M } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
73
|
+
*
|
|
74
|
+
* console.log(LY_M);
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export declare const LY_M: number;
|
|
78
|
+
/**
|
|
79
|
+
* Gravitational parameters (GM), cubic kilometres a second squared. NASA/JPL: "Planetary Satellite Physical Parameters" and "Planetary Physical Parameters"
|
|
80
|
+
* (https://ssd.jpl.nasa.gov/), read 2026-11-04. The Sun's is the IAU 2015 nominal value.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* import { GM_KM3_S2 } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
85
|
+
*
|
|
86
|
+
* console.log(GM_KM3_S2.earth, GM_KM3_S2.moon);
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare const GM_KM3_S2: Readonly<Record<string, number>>;
|
|
90
|
+
/**
|
|
91
|
+
* Sidereal orbital periods, days (NASA's planetary fact sheets, https://nssdc.gsfc.nasa.gov/planetary/factsheet/).
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* import { PERIOD_DAYS } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
96
|
+
*
|
|
97
|
+
* console.log(PERIOD_DAYS.mars);
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export declare const PERIOD_DAYS: Readonly<Record<string, number>>;
|
|
101
|
+
/**
|
|
102
|
+
* The height of the circular parking orbit round each kind of body, kilometres: 185 km above the Earth (Apollo's), 100 km above the Moon (Apollo's), 200 km above any other body.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```ts
|
|
106
|
+
* import { PARKING_ALTITUDE_KM } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
107
|
+
*
|
|
108
|
+
* console.log(PARKING_ALTITUDE_KM.earth);
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export declare const PARKING_ALTITUDE_KM: {
|
|
112
|
+
readonly earth: 185;
|
|
113
|
+
readonly moon: 100;
|
|
114
|
+
readonly other: 200;
|
|
115
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// The constants a trip needs, each with where it is from. Metres and seconds unless the name says otherwise. Pure.
|
|
2
|
+
/**
|
|
3
|
+
* The speed of light, metres a second (exact, by definition of the metre).
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { C } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
8
|
+
*
|
|
9
|
+
* console.log(C);
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export const C = 299_792_458;
|
|
13
|
+
/**
|
|
14
|
+
* One standard gravity, metres a second squared (exact, by definition).
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { G0 } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
19
|
+
*
|
|
20
|
+
* console.log(G0);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export const G0 = 9.80665;
|
|
24
|
+
/**
|
|
25
|
+
* One astronomical unit, metres (exact, IAU 2012).
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { AU_M } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
30
|
+
*
|
|
31
|
+
* console.log(AU_M);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export const AU_M = 149_597_870_700;
|
|
35
|
+
/**
|
|
36
|
+
* One astronomical unit, kilometres.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { AU_KM } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
41
|
+
*
|
|
42
|
+
* console.log(AU_KM);
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export const AU_KM = AU_M / 1000;
|
|
46
|
+
/**
|
|
47
|
+
* A day, seconds.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* import { DAY_S } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
52
|
+
*
|
|
53
|
+
* console.log(DAY_S);
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export const DAY_S = 86_400;
|
|
57
|
+
/**
|
|
58
|
+
* A Julian year, seconds.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* import { YEAR_S } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
63
|
+
*
|
|
64
|
+
* console.log(YEAR_S);
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export const YEAR_S = 31_557_600;
|
|
68
|
+
/**
|
|
69
|
+
* A light year, metres.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* import { LY_M } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
74
|
+
*
|
|
75
|
+
* console.log(LY_M);
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export const LY_M = C * YEAR_S;
|
|
79
|
+
/**
|
|
80
|
+
* Gravitational parameters (GM), cubic kilometres a second squared. NASA/JPL: "Planetary Satellite Physical Parameters" and "Planetary Physical Parameters"
|
|
81
|
+
* (https://ssd.jpl.nasa.gov/), read 2026-11-04. The Sun's is the IAU 2015 nominal value.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* import { GM_KM3_S2 } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
86
|
+
*
|
|
87
|
+
* console.log(GM_KM3_S2.earth, GM_KM3_S2.moon);
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export const GM_KM3_S2 = {
|
|
91
|
+
sun: 132_712_440_018,
|
|
92
|
+
mercury: 22_031.868,
|
|
93
|
+
venus: 324_858.592,
|
|
94
|
+
earth: 398_600.4418,
|
|
95
|
+
moon: 4_902.800,
|
|
96
|
+
mars: 42_828.375,
|
|
97
|
+
jupiter: 126_686_534,
|
|
98
|
+
saturn: 37_931_187,
|
|
99
|
+
uranus: 5_793_939,
|
|
100
|
+
neptune: 6_836_529,
|
|
101
|
+
pluto: 869.6,
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Sidereal orbital periods, days (NASA's planetary fact sheets, https://nssdc.gsfc.nasa.gov/planetary/factsheet/).
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* import { PERIOD_DAYS } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
109
|
+
*
|
|
110
|
+
* console.log(PERIOD_DAYS.mars);
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export const PERIOD_DAYS = {
|
|
114
|
+
mercury: 87.969,
|
|
115
|
+
venus: 224.701,
|
|
116
|
+
earth: 365.256,
|
|
117
|
+
mars: 686.98,
|
|
118
|
+
jupiter: 4332.589,
|
|
119
|
+
saturn: 10759.22,
|
|
120
|
+
uranus: 30685.4,
|
|
121
|
+
neptune: 60189,
|
|
122
|
+
pluto: 90560,
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* The height of the circular parking orbit round each kind of body, kilometres: 185 km above the Earth (Apollo's), 100 km above the Moon (Apollo's), 200 km above any other body.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* import { PARKING_ALTITUDE_KM } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
130
|
+
*
|
|
131
|
+
* console.log(PARKING_ALTITUDE_KM.earth);
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
export const PARKING_ALTITUDE_KM = { earth: 185, moon: 100, other: 200 };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Trip } from "./trip.ts";
|
|
2
|
+
/**
|
|
3
|
+
* The engine preheat bar before ignition: ten segments and a percent. It fills from 13 seconds before lift-off to 3 seconds before, and is full after.
|
|
4
|
+
* @param missionS Mission seconds from lift-off (negative before).
|
|
5
|
+
* @returns The percent (0 to 100), how many of the ten segments are full, and how full the next one is (0 to 1).
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { preheat } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
9
|
+
*
|
|
10
|
+
* console.log(preheat(-8.5));
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function preheat(missionS: number): {
|
|
14
|
+
percent: number;
|
|
15
|
+
full: number;
|
|
16
|
+
partial: number;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* The ignition count: IGNITION IN 3, 2, 1, then 0 from lift-off, with how far round the ring dial has gone.
|
|
20
|
+
* @param missionS Mission seconds from lift-off (negative before).
|
|
21
|
+
* @returns The number to show (3, 2, 1 or 0) and the ring's sweep (0 to 1).
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { ignition } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
25
|
+
*
|
|
26
|
+
* console.log(ignition(-2.2), ignition(0));
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function ignition(missionS: number): {
|
|
30
|
+
count: number;
|
|
31
|
+
ring: number;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The timer before and during the braking burn: DECELERATION BURN IN until it starts, DECELERATION COMPLETE IN while it runs, nothing after.
|
|
35
|
+
* @param trip A planned trip.
|
|
36
|
+
* @param missionS Mission seconds from lift-off.
|
|
37
|
+
* @returns Which timer, and its seconds; or null when there is none to show.
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts no-run
|
|
40
|
+
* import { burnTimer, type Trip } from "@johnmorrisdotca/uchusen-rockets/journey";
|
|
41
|
+
*
|
|
42
|
+
* declare const trip: Trip;
|
|
43
|
+
* console.log(burnTimer(trip, 10));
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function burnTimer(trip: Trip, missionS: number): {
|
|
47
|
+
kind: "burn-in" | "complete-in";
|
|
48
|
+
seconds: number;
|
|
49
|
+
} | null;
|