@johnmorrisdotca/uchusen-rockets 0.3.0 → 0.4.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 +16 -5
- package/README.md +241 -4
- package/dist/attrs.d.ts +70 -4
- package/dist/attrs.js +59 -4
- package/dist/build/glb.d.ts +25 -0
- package/dist/build/glb.js +14 -0
- package/dist/build/index.d.ts +89 -4
- package/dist/build/index.js +55 -4
- package/dist/build/lineup.d.ts +56 -2
- package/dist/build/lineup.js +23 -2
- package/dist/builder.d.ts +47 -1
- package/dist/builder.js +14 -1
- package/dist/crossfade.d.ts +44 -2
- package/dist/crossfade.js +44 -2
- package/dist/data/credits.d.ts +44 -1
- package/dist/data/credits.js +22 -1
- package/dist/data/flight-log.d.ts +33 -1
- package/dist/data/flight-log.js +22 -1
- package/dist/data/flights.d.ts +54 -2
- package/dist/data/flights.js +10 -0
- package/dist/data/makers.d.ts +21 -0
- package/dist/data/makers.js +10 -0
- package/dist/data/sources.d.ts +32 -0
- package/dist/data/sources.js +10 -0
- package/dist/data/types.d.ts +81 -1
- package/dist/data/types.js +26 -1
- package/dist/element.d.ts +61 -3
- package/dist/element.js +50 -3
- package/dist/embed.d.ts +110 -5
- package/dist/embed.js +88 -5
- package/dist/engines.d.ts +86 -4
- package/dist/engines.js +75 -4
- package/dist/fit.d.ts +68 -0
- package/dist/fit.js +13 -0
- package/dist/flight.d.ts +134 -9
- package/dist/flight.js +122 -9
- package/dist/flightbar.d.ts +12 -0
- package/dist/flightbar.js +12 -0
- package/dist/framing.d.ts +182 -8
- package/dist/framing.js +127 -6
- package/dist/layout.d.ts +65 -1
- package/dist/layout.js +43 -1
- package/dist/looks.d.ts +64 -1
- package/dist/looks.js +42 -1
- package/dist/model/materials.d.ts +32 -0
- package/dist/model/materials.js +10 -0
- package/dist/model/registry.d.ts +22 -0
- package/dist/model/registry.js +22 -0
- package/dist/parts.d.ts +33 -1
- package/dist/pixels.d.ts +44 -4
- package/dist/pixels.js +44 -4
- package/dist/react.d.ts +24 -0
- package/dist/react.js +13 -0
- package/dist/rockets.d.ts +91 -3
- package/dist/rockets.js +58 -2
- package/dist/spin.d.ts +57 -2
- package/dist/spin.js +35 -2
- package/dist/tilt.d.ts +48 -4
- package/dist/tilt.js +26 -4
- package/package.json +10 -5
package/dist/build/index.d.ts
CHANGED
|
@@ -5,11 +5,36 @@ import { type PartMesh, type Bounds, type Piece } from "../model/pieces.ts";
|
|
|
5
5
|
import type { PartRecord } from "../parts.ts";
|
|
6
6
|
import { type LitBell } from "../engines.ts";
|
|
7
7
|
import { type Glb, toGlb } from "./glb.ts";
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Raised by `build` when a description does not fit. Its `report` says why, in the same words `check` gives.
|
|
10
|
+
*
|
|
11
|
+
* @param report The report of the fit check that failed.
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { build, FitError } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
15
|
+
*
|
|
16
|
+
* try {
|
|
17
|
+
* build({ rocket: "starship", variant: "v3", parts: { booster: "starship-v3-ship" } });
|
|
18
|
+
* } catch (error) {
|
|
19
|
+
* if (error instanceof FitError) console.log(error.report.issues[0]?.message);
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
9
23
|
export declare class FitError extends Error {
|
|
10
24
|
readonly report: FitReport;
|
|
11
25
|
constructor(report: FitReport);
|
|
12
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* One part of a built rocket: its slot, its record, the pieces it is made of, its mesh and its bounds in metres.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { build, type BuiltPart } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
33
|
+
*
|
|
34
|
+
* const first: BuiltPart | undefined = build({ rocket: "falcon-9", variant: "block-5" }).parts[0];
|
|
35
|
+
* console.log(first?.slot, first?.record.name);
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
13
38
|
export interface BuiltPart {
|
|
14
39
|
slot: string;
|
|
15
40
|
record: PartRecord;
|
|
@@ -17,6 +42,17 @@ export interface BuiltPart {
|
|
|
17
42
|
mesh: PartMesh;
|
|
18
43
|
bounds: Bounds;
|
|
19
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* What a drawing is asked for: the look, the view, what to show and whether the engines are lit. Anything left out takes its default.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* import { build, type SvgOptions } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
51
|
+
*
|
|
52
|
+
* const options: SvgOptions = { look: "thick", view: "below", show: "booster" };
|
|
53
|
+
* console.log(build({ rocket: "starship", variant: "v3" }).svg(options).startsWith("<svg"));
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
20
56
|
export interface SvgOptions {
|
|
21
57
|
look?: LookName;
|
|
22
58
|
view?: ViewName | Angle;
|
|
@@ -24,6 +60,18 @@ export interface SvgOptions {
|
|
|
24
60
|
/** A flame at each engine that is showing, or as many as a count names for each part. The length is a picture, not a measured flame. Left out, the drawing is unchanged. */
|
|
25
61
|
engines?: boolean | Readonly<Record<string, number>>;
|
|
26
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* A rocket built from a description: the fit report, its parts, and the ways to ask for its size, where each part stands, its lit engines, a `.glb` file and a drawing.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* import { build, type Built } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
69
|
+
*
|
|
70
|
+
* const rocket: Built = build({ rocket: "starship", variant: "v3" });
|
|
71
|
+
* console.log(rocket.shows.join(", "));
|
|
72
|
+
* console.log(rocket.boundsOf("together").max);
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
27
75
|
export interface Built {
|
|
28
76
|
report: FitReport;
|
|
29
77
|
parts: readonly BuiltPart[];
|
|
@@ -44,14 +92,51 @@ export interface Built {
|
|
|
44
92
|
/** The drawing, in a look, from an angle. */
|
|
45
93
|
svg(options?: SvgOptions): string;
|
|
46
94
|
}
|
|
47
|
-
/**
|
|
95
|
+
/**
|
|
96
|
+
* What a drawing draws of a part: in a stack, what nests inside the part below is out of sight.
|
|
97
|
+
*
|
|
98
|
+
* @param part A built part: its record and its pieces.
|
|
99
|
+
* @param together True when the part stands in a stack, false when it is shown alone.
|
|
100
|
+
* @returns The pieces to draw. In a stack, what nests inside the part below is left out.
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* import { build, drawnPieces } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
104
|
+
*
|
|
105
|
+
* const [first] = build({ rocket: "falcon-9", variant: "block-5" }).parts;
|
|
106
|
+
* if (first) console.log(drawnPieces(first, true).length, drawnPieces(first, false).length);
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
48
109
|
export declare function drawnPieces(part: {
|
|
49
110
|
record: PartRecord;
|
|
50
111
|
pieces: readonly Piece[];
|
|
51
112
|
}, together: boolean): readonly Piece[];
|
|
52
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* A rocket from a description. Throws FitError when it does not go together.
|
|
115
|
+
*
|
|
116
|
+
* @param description The rocket, its variant and any other part in a slot.
|
|
117
|
+
* @returns The built rocket. It throws a `FitError` when the description does not go together.
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* import { build } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
121
|
+
*
|
|
122
|
+
* const rocket = build({ rocket: "falcon-heavy" });
|
|
123
|
+
* console.log(rocket.report.label, rocket.glb().bytes.length > 1000);
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
53
126
|
export declare function build(description: Description): Built;
|
|
54
|
-
/**
|
|
127
|
+
/**
|
|
128
|
+
* One part on its own, by its id.
|
|
129
|
+
*
|
|
130
|
+
* @param id A part's id, as `PART_ENTRIES` lists it.
|
|
131
|
+
* @returns The part's record and bounds, a function for its `.glb` and one for its drawing. It throws for an id that is not a part.
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* import { buildPart } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
135
|
+
*
|
|
136
|
+
* const raptor = buildPart("raptor-vacuum");
|
|
137
|
+
* console.log(raptor.record.name, raptor.bounds.max);
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
55
140
|
export declare function buildPart(id: string): {
|
|
56
141
|
record: PartRecord;
|
|
57
142
|
bounds: Bounds;
|
package/dist/build/index.js
CHANGED
|
@@ -9,7 +9,21 @@ import { plumeMarkup } from "../draw/plume.js";
|
|
|
9
9
|
import { defsOf, drawPart, perspective } from "../draw/svg.js";
|
|
10
10
|
import { bellsOf, litBells, pickBells, plumeLength } from "../engines.js";
|
|
11
11
|
import { toGlb } from "./glb.js";
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Raised by `build` when a description does not fit. Its `report` says why, in the same words `check` gives.
|
|
14
|
+
*
|
|
15
|
+
* @param report The report of the fit check that failed.
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { build, FitError } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
19
|
+
*
|
|
20
|
+
* try {
|
|
21
|
+
* build({ rocket: "starship", variant: "v3", parts: { booster: "starship-v3-ship" } });
|
|
22
|
+
* } catch (error) {
|
|
23
|
+
* if (error instanceof FitError) console.log(error.report.issues[0]?.message);
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
13
27
|
export class FitError extends Error {
|
|
14
28
|
report;
|
|
15
29
|
constructor(report) {
|
|
@@ -108,21 +122,58 @@ function assembled(report) {
|
|
|
108
122
|
},
|
|
109
123
|
};
|
|
110
124
|
}
|
|
111
|
-
/**
|
|
125
|
+
/**
|
|
126
|
+
* What a drawing draws of a part: in a stack, what nests inside the part below is out of sight.
|
|
127
|
+
*
|
|
128
|
+
* @param part A built part: its record and its pieces.
|
|
129
|
+
* @param together True when the part stands in a stack, false when it is shown alone.
|
|
130
|
+
* @returns The pieces to draw. In a stack, what nests inside the part below is left out.
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* import { build, drawnPieces } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
134
|
+
*
|
|
135
|
+
* const [first] = build({ rocket: "falcon-9", variant: "block-5" }).parts;
|
|
136
|
+
* if (first) console.log(drawnPieces(first, true).length, drawnPieces(first, false).length);
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
112
139
|
export function drawnPieces(part, together) {
|
|
113
140
|
const joint = part.record.joints.bottom?.y ?? 0;
|
|
114
141
|
if (!together || joint <= 0)
|
|
115
142
|
return part.pieces;
|
|
116
143
|
return part.pieces.filter((piece) => !(piece.kind === "lathe" && piece.under && Math.max(...piece.profile.map(([, y]) => y)) <= joint + 0.01));
|
|
117
144
|
}
|
|
118
|
-
/**
|
|
145
|
+
/**
|
|
146
|
+
* A rocket from a description. Throws FitError when it does not go together.
|
|
147
|
+
*
|
|
148
|
+
* @param description The rocket, its variant and any other part in a slot.
|
|
149
|
+
* @returns The built rocket. It throws a `FitError` when the description does not go together.
|
|
150
|
+
* @example
|
|
151
|
+
* ```ts
|
|
152
|
+
* import { build } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
153
|
+
*
|
|
154
|
+
* const rocket = build({ rocket: "falcon-heavy" });
|
|
155
|
+
* console.log(rocket.report.label, rocket.glb().bytes.length > 1000);
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
119
158
|
export function build(description) {
|
|
120
159
|
const report = check(description);
|
|
121
160
|
if (!report.ok)
|
|
122
161
|
throw new FitError(report);
|
|
123
162
|
return assembled(report);
|
|
124
163
|
}
|
|
125
|
-
/**
|
|
164
|
+
/**
|
|
165
|
+
* One part on its own, by its id.
|
|
166
|
+
*
|
|
167
|
+
* @param id A part's id, as `PART_ENTRIES` lists it.
|
|
168
|
+
* @returns The part's record and bounds, a function for its `.glb` and one for its drawing. It throws for an id that is not a part.
|
|
169
|
+
* @example
|
|
170
|
+
* ```ts
|
|
171
|
+
* import { buildPart } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
172
|
+
*
|
|
173
|
+
* const raptor = buildPart("raptor-vacuum");
|
|
174
|
+
* console.log(raptor.record.name, raptor.bounds.max);
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
126
177
|
export function buildPart(id) {
|
|
127
178
|
const entry = partEntry(id);
|
|
128
179
|
if (!entry)
|
package/dist/build/lineup.d.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { type ViewName } from "../framing.ts";
|
|
2
2
|
import { type LookName } from "../looks.ts";
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Comparison shapes: plain round sizes, for scale, not facts about anything.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { COMPARES } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
9
|
+
*
|
|
10
|
+
* console.log(COMPARES.person.height, COMPARES.building.height);
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
4
13
|
export declare const COMPARES: {
|
|
5
14
|
readonly person: {
|
|
6
15
|
readonly name: "A person, 1.8 m";
|
|
@@ -13,13 +22,46 @@ export declare const COMPARES: {
|
|
|
13
22
|
readonly width: 18;
|
|
14
23
|
};
|
|
15
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* The name of a comparison shape that can stand in a lineup: `person` or `building`.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* import type { CompareId } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
31
|
+
*
|
|
32
|
+
* const id: CompareId = "person";
|
|
33
|
+
* console.log(id);
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
16
36
|
export type CompareId = keyof typeof COMPARES;
|
|
37
|
+
/**
|
|
38
|
+
* One thing standing in a lineup: its key (`starship:v3` or a comparison's name), its label and its height in metres.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* import { lineupSvg, type LineupItem } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
43
|
+
*
|
|
44
|
+
* const items: LineupItem[] = lineupSvg({ items: ["starship:v3", "person"], unit: 3 }).items;
|
|
45
|
+
* console.log(items.map((item) => item.label));
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
17
48
|
export interface LineupItem {
|
|
18
49
|
/** "starship:v3" or a comparison's name. */
|
|
19
50
|
key: string;
|
|
20
51
|
label: string;
|
|
21
52
|
height: number;
|
|
22
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* What a lineup is asked for: the items by key, how many pixels make a metre, and optionally the look, the view, what to show, a ruler and labels.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* import { lineupSvg, type LineupOptions } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
60
|
+
*
|
|
61
|
+
* const options: LineupOptions = { items: ["starship:v2", "starship:v3", "building"], unit: 3, ruler: true, labels: true };
|
|
62
|
+
* console.log(lineupSvg(options).width);
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
23
65
|
export interface LineupOptions {
|
|
24
66
|
/** "starship:v1,starship:v3,person,building". */
|
|
25
67
|
items: readonly string[];
|
|
@@ -31,7 +73,19 @@ export interface LineupOptions {
|
|
|
31
73
|
ruler?: boolean;
|
|
32
74
|
labels?: boolean;
|
|
33
75
|
}
|
|
34
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* The whole picture as SVG text. Unknown items are left out.
|
|
78
|
+
*
|
|
79
|
+
* @param options The items and how they are drawn.
|
|
80
|
+
* @returns The picture as SVG text, the items it holds, and its width and height.
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* import { lineupSvg } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
84
|
+
*
|
|
85
|
+
* const picture = lineupSvg({ items: ["falcon-9:block-5", "falcon-heavy:falcon-heavy", "person"], unit: 4, ruler: true });
|
|
86
|
+
* console.log(picture.items.length, picture.svg.startsWith("<svg"));
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
35
89
|
export declare function lineupSvg(options: LineupOptions): {
|
|
36
90
|
svg: string;
|
|
37
91
|
items: LineupItem[];
|
package/dist/build/lineup.js
CHANGED
|
@@ -6,7 +6,16 @@ import { DEFAULT_LOOK, LOOKS } from "../looks.js";
|
|
|
6
6
|
import { defsOf, drawPart, orthographic } from "../draw/svg.js";
|
|
7
7
|
import { MATERIALS } from "../model/materials.js";
|
|
8
8
|
import { variantOf } from "../rockets.js";
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Comparison shapes: plain round sizes, for scale, not facts about anything.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { COMPARES } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
15
|
+
*
|
|
16
|
+
* console.log(COMPARES.person.height, COMPARES.building.height);
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
10
19
|
export const COMPARES = {
|
|
11
20
|
person: { name: "A person, 1.8 m", height: 1.8, width: 0.5 },
|
|
12
21
|
building: { name: "A ten-storey building, 30 m", height: 30, width: 18 },
|
|
@@ -33,7 +42,19 @@ function comparison(id, x, base, unit, line, fill) {
|
|
|
33
42
|
floors += `M${n(x)} ${n(base - (h * i) / 10)}h${n(w)}`;
|
|
34
43
|
return `<rect x="${n(x)}" y="${n(base - h)}" width="${n(w)}" height="${n(h)}" fill="${fill}" stroke="${line}" stroke-width=".9"/><path d="${floors}" stroke="${line}" stroke-width=".35" opacity=".6"/>`;
|
|
35
44
|
}
|
|
36
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* The whole picture as SVG text. Unknown items are left out.
|
|
47
|
+
*
|
|
48
|
+
* @param options The items and how they are drawn.
|
|
49
|
+
* @returns The picture as SVG text, the items it holds, and its width and height.
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import { lineupSvg } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
53
|
+
*
|
|
54
|
+
* const picture = lineupSvg({ items: ["falcon-9:block-5", "falcon-heavy:falcon-heavy", "person"], unit: 4, ruler: true });
|
|
55
|
+
* console.log(picture.items.length, picture.svg.startsWith("<svg"));
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
37
58
|
export function lineupSvg(options) {
|
|
38
59
|
const { items, unit, look = DEFAULT_LOOK, view = "front", ruler = true, labels = true } = options;
|
|
39
60
|
const angle = VIEWS[cleanView(view)];
|
package/dist/builder.d.ts
CHANGED
|
@@ -1,10 +1,32 @@
|
|
|
1
1
|
import { type Description, type FitReport } from "./fit.ts";
|
|
2
|
+
/**
|
|
3
|
+
* One part a row of the builder offers: its id, its name and the rocket it comes from.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { builderState, type BuilderOption } from "@johnmorrisdotca/uchusen-rockets";
|
|
8
|
+
*
|
|
9
|
+
* const first: BuilderOption | undefined = builderState().rows[0]?.options[0];
|
|
10
|
+
* console.log(first);
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
2
13
|
export interface BuilderOption {
|
|
3
14
|
id: string;
|
|
4
15
|
name: string;
|
|
5
16
|
/** Which rocket it comes from, to group a long list. */
|
|
6
17
|
rocket: string;
|
|
7
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* One row of the builder, from the bottom: what it chooses, the parts it offers, the one chosen, and whether the builder made the choice because only one part fits.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { builderState, type BuilderRow } from "@johnmorrisdotca/uchusen-rockets";
|
|
25
|
+
*
|
|
26
|
+
* const row: BuilderRow | undefined = builderState().rows[0];
|
|
27
|
+
* console.log(row?.label, row?.chosen, row?.auto);
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
8
30
|
export interface BuilderRow {
|
|
9
31
|
/** What this row chooses. */
|
|
10
32
|
label: string;
|
|
@@ -13,10 +35,34 @@ export interface BuilderRow {
|
|
|
13
35
|
/** One answer only: the builder made the choice. */
|
|
14
36
|
auto: boolean;
|
|
15
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* What the builder shows for a set of picks: its rows, the description they make and the fit report for it.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { builderState, type BuilderState } from "@johnmorrisdotca/uchusen-rockets";
|
|
44
|
+
*
|
|
45
|
+
* const state: BuilderState = builderState();
|
|
46
|
+
* console.log(state.rows.length, state.report.ok);
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
16
49
|
export interface BuilderState {
|
|
17
50
|
rows: readonly BuilderRow[];
|
|
18
51
|
description: Description;
|
|
19
52
|
report: FitReport;
|
|
20
53
|
}
|
|
21
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* The rows for these picks, from the bottom. A pick that is not offered, for a change lower down or a hostile value, gives way to the part that belongs with what is below, or else the first that fits.
|
|
56
|
+
*
|
|
57
|
+
* @param picks The part ids chosen so far, row by row from the bottom. Leave it out to start.
|
|
58
|
+
* @returns The rows to show, the description they make and its fit report.
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* import { builderState } from "@johnmorrisdotca/uchusen-rockets";
|
|
62
|
+
*
|
|
63
|
+
* const start = builderState();
|
|
64
|
+
* const next = builderState([start.rows[0]?.chosen ?? ""]);
|
|
65
|
+
* console.log(next.description, next.report.label);
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
22
68
|
export declare function builderState(picks?: readonly string[]): BuilderState;
|
package/dist/builder.js
CHANGED
|
@@ -24,7 +24,20 @@ const fitsOn = (part, below) => {
|
|
|
24
24
|
};
|
|
25
25
|
const REAL_PARTS = () => PART_ENTRIES.map(({ record }) => record).filter((record) => record.trueTo.length > 0);
|
|
26
26
|
const optionOf = (part) => ({ id: part.id, name: part.name, rocket: ROCKETS[part.rocket]?.name ?? part.rocket });
|
|
27
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* The rows for these picks, from the bottom. A pick that is not offered, for a change lower down or a hostile value, gives way to the part that belongs with what is below, or else the first that fits.
|
|
29
|
+
*
|
|
30
|
+
* @param picks The part ids chosen so far, row by row from the bottom. Leave it out to start.
|
|
31
|
+
* @returns The rows to show, the description they make and its fit report.
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* import { builderState } from "@johnmorrisdotca/uchusen-rockets";
|
|
35
|
+
*
|
|
36
|
+
* const start = builderState();
|
|
37
|
+
* const next = builderState([start.rows[0]?.chosen ?? ""]);
|
|
38
|
+
* console.log(next.description, next.report.label);
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
28
41
|
export function builderState(picks = []) {
|
|
29
42
|
const every = framesOf();
|
|
30
43
|
const parts = REAL_PARTS();
|
package/dist/crossfade.d.ts
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* The drawing stays at least this long after it first comes on screen.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { DRAWING_HOLD_MS } from "@johnmorrisdotca/uchusen-rockets";
|
|
7
|
+
*
|
|
8
|
+
* console.log(DRAWING_HOLD_MS);
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
2
11
|
export declare const DRAWING_HOLD_MS = 1200;
|
|
12
|
+
/**
|
|
13
|
+
* How long the drawing and the 3D view cross-fade, in milliseconds.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { CROSSFADE_MS } from "@johnmorrisdotca/uchusen-rockets";
|
|
18
|
+
*
|
|
19
|
+
* console.log(CROSSFADE_MS);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
3
22
|
export declare const CROSSFADE_MS = 1500;
|
|
23
|
+
/**
|
|
24
|
+
* How long the cross-fade lasts for a reader who asked for reduced motion, in milliseconds.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { REDUCED_FADE_MS } from "@johnmorrisdotca/uchusen-rockets";
|
|
29
|
+
*
|
|
30
|
+
* console.log(REDUCED_FADE_MS);
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
4
33
|
export declare const REDUCED_FADE_MS = 400;
|
|
5
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* How long to wait, once the 3D view is ready at `readyAt`, before it takes over from a drawing first seen at `shownAt` (0 under reduced motion).
|
|
36
|
+
*
|
|
37
|
+
* @param shownAt When the drawing first came on screen, in milliseconds.
|
|
38
|
+
* @param readyAt When the 3D view became ready, on the same clock.
|
|
39
|
+
* @param reducedMotion True when the reader asked for reduced motion.
|
|
40
|
+
* @returns The milliseconds to wait before the 3D view takes over.
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { revealDelay } from "@johnmorrisdotca/uchusen-rockets";
|
|
44
|
+
*
|
|
45
|
+
* console.log(revealDelay(0, 300, false), revealDelay(0, 300, true));
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
6
48
|
export declare function revealDelay(shownAt: number, readyAt: number, reducedMotion: boolean): number;
|
package/dist/crossfade.js
CHANGED
|
@@ -1,9 +1,51 @@
|
|
|
1
1
|
// The change from a rocket's drawing to its 3D view: the drawing stays a moment even when the 3D view is ready sooner, then a slow crossfade; under reduced motion, a plain short fade. Pure.
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* The drawing stays at least this long after it first comes on screen.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { DRAWING_HOLD_MS } from "@johnmorrisdotca/uchusen-rockets";
|
|
8
|
+
*
|
|
9
|
+
* console.log(DRAWING_HOLD_MS);
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
3
12
|
export const DRAWING_HOLD_MS = 1200;
|
|
13
|
+
/**
|
|
14
|
+
* How long the drawing and the 3D view cross-fade, in milliseconds.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { CROSSFADE_MS } from "@johnmorrisdotca/uchusen-rockets";
|
|
19
|
+
*
|
|
20
|
+
* console.log(CROSSFADE_MS);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
4
23
|
export const CROSSFADE_MS = 1500;
|
|
24
|
+
/**
|
|
25
|
+
* How long the cross-fade lasts for a reader who asked for reduced motion, in milliseconds.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { REDUCED_FADE_MS } from "@johnmorrisdotca/uchusen-rockets";
|
|
30
|
+
*
|
|
31
|
+
* console.log(REDUCED_FADE_MS);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
5
34
|
export const REDUCED_FADE_MS = 400;
|
|
6
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* How long to wait, once the 3D view is ready at `readyAt`, before it takes over from a drawing first seen at `shownAt` (0 under reduced motion).
|
|
37
|
+
*
|
|
38
|
+
* @param shownAt When the drawing first came on screen, in milliseconds.
|
|
39
|
+
* @param readyAt When the 3D view became ready, on the same clock.
|
|
40
|
+
* @param reducedMotion True when the reader asked for reduced motion.
|
|
41
|
+
* @returns The milliseconds to wait before the 3D view takes over.
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* import { revealDelay } from "@johnmorrisdotca/uchusen-rockets";
|
|
45
|
+
*
|
|
46
|
+
* console.log(revealDelay(0, 300, false), revealDelay(0, 300, true));
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
7
49
|
export function revealDelay(shownAt, readyAt, reducedMotion) {
|
|
8
50
|
if (reducedMotion)
|
|
9
51
|
return 0;
|
package/dist/data/credits.d.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The credit for one licensed model: its title, its creator and their page, where it came from, its licence and what this package changed.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { MODEL_CREDITS, type ModelCredit } from "@johnmorrisdotca/uchusen-rockets";
|
|
7
|
+
*
|
|
8
|
+
* const credit: ModelCredit = MODEL_CREDITS["clarence365-block3"];
|
|
9
|
+
* console.log(credit.creator, credit.licence);
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
1
12
|
export interface ModelCredit {
|
|
2
13
|
title: string;
|
|
3
14
|
creator: string;
|
|
@@ -8,6 +19,16 @@ export interface ModelCredit {
|
|
|
8
19
|
/** What this package changed. */
|
|
9
20
|
changes: string;
|
|
10
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Every licensed model this package paints with, by credit id. A painted rocket must carry the credit of the parts that are showing; `embedCode` writes it for you.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* import { MODEL_CREDITS } from "@johnmorrisdotca/uchusen-rockets";
|
|
28
|
+
*
|
|
29
|
+
* console.log(Object.keys(MODEL_CREDITS).length > 10);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
11
32
|
export declare const MODEL_CREDITS: {
|
|
12
33
|
readonly "clarence365-block3": {
|
|
13
34
|
readonly title: "SpaceX Starship Block 3";
|
|
@@ -100,6 +121,28 @@ export declare const MODEL_CREDITS: {
|
|
|
100
121
|
readonly "nasa-iss": ModelCredit;
|
|
101
122
|
readonly "nasa-hubble": ModelCredit;
|
|
102
123
|
};
|
|
124
|
+
/**
|
|
125
|
+
* The id of one model's credit in `MODEL_CREDITS`.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* import type { CreditId } from "@johnmorrisdotca/uchusen-rockets";
|
|
130
|
+
*
|
|
131
|
+
* const id: CreditId = "clarence365-block3";
|
|
132
|
+
* console.log(id);
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
103
135
|
export type CreditId = keyof typeof MODEL_CREDITS;
|
|
104
|
-
/**
|
|
136
|
+
/**
|
|
137
|
+
* One credit as a line of text.
|
|
138
|
+
*
|
|
139
|
+
* @param id The id of a credit in `MODEL_CREDITS`.
|
|
140
|
+
* @returns The credit as one line of text.
|
|
141
|
+
* @example
|
|
142
|
+
* ```ts
|
|
143
|
+
* import { creditLine } from "@johnmorrisdotca/uchusen-rockets";
|
|
144
|
+
*
|
|
145
|
+
* console.log(creditLine("clarence365-block3"));
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
105
148
|
export declare function creditLine(id: CreditId): string;
|
package/dist/data/credits.js
CHANGED
|
@@ -11,6 +11,16 @@ const nasa = (title, slug, changes) => ({
|
|
|
11
11
|
licenceUrl: "https://www.nasa.gov/nasa-brand-center/images-and-media/",
|
|
12
12
|
changes,
|
|
13
13
|
});
|
|
14
|
+
/**
|
|
15
|
+
* Every licensed model this package paints with, by credit id. A painted rocket must carry the credit of the parts that are showing; `embedCode` writes it for you.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { MODEL_CREDITS } from "@johnmorrisdotca/uchusen-rockets";
|
|
20
|
+
*
|
|
21
|
+
* console.log(Object.keys(MODEL_CREDITS).length > 10);
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
14
24
|
export const MODEL_CREDITS = {
|
|
15
25
|
"clarence365-block3": {
|
|
16
26
|
title: "SpaceX Starship Block 3",
|
|
@@ -104,7 +114,18 @@ export const MODEL_CREDITS = {
|
|
|
104
114
|
"nasa-hubble": nasa("Hubble Space Telescope", "nasa-3d-models-hubble-space-telescope", "A lettered plate painted out of its picture; rescaled to the sourced length; its materials made into one picture."),
|
|
105
115
|
// new rows go here
|
|
106
116
|
};
|
|
107
|
-
/**
|
|
117
|
+
/**
|
|
118
|
+
* One credit as a line of text.
|
|
119
|
+
*
|
|
120
|
+
* @param id The id of a credit in `MODEL_CREDITS`.
|
|
121
|
+
* @returns The credit as one line of text.
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* import { creditLine } from "@johnmorrisdotca/uchusen-rockets";
|
|
125
|
+
*
|
|
126
|
+
* console.log(creditLine("clarence365-block3"));
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
108
129
|
export function creditLine(id) {
|
|
109
130
|
const c = MODEL_CREDITS[id];
|
|
110
131
|
return `"${c.title}" by ${c.creator} (${c.sourceUrl}), ${c.licence} (${c.licenceUrl}). ${c.changes}`;
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import type { SourceId } from "./sources.ts";
|
|
2
|
+
/**
|
|
3
|
+
* One flight from the flight log: its name, the rocket and variant that show it, the date, whether the launch succeeded, the source's own words on the outcome, and the source.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { FLIGHT_LOG, type LoggedFlight } from "@johnmorrisdotca/uchusen-rockets";
|
|
8
|
+
*
|
|
9
|
+
* const flight: LoggedFlight | undefined = FLIGHT_LOG[0];
|
|
10
|
+
* console.log(flight?.name, flight?.launch);
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
2
13
|
export interface LoggedFlight {
|
|
3
14
|
id: string;
|
|
4
15
|
name: string;
|
|
@@ -13,6 +24,27 @@ export interface LoggedFlight {
|
|
|
13
24
|
outcome: string;
|
|
14
25
|
source: SourceId;
|
|
15
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* The flights this package keeps a record of, each from a named source. Use `flightLogOf` for one rocket.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { FLIGHT_LOG } from "@johnmorrisdotca/uchusen-rockets";
|
|
33
|
+
*
|
|
34
|
+
* console.log(FLIGHT_LOG.length > 0);
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
16
37
|
export declare const FLIGHT_LOG: readonly LoggedFlight[];
|
|
17
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* A rocket's flights, in order.
|
|
40
|
+
*
|
|
41
|
+
* @param rocket A rocket's id, such as `falcon-1`.
|
|
42
|
+
* @returns That rocket's logged flights, in order. It is empty for a rocket with none.
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* import { flightLogOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
46
|
+
*
|
|
47
|
+
* console.log(flightLogOf("falcon-1").map((flight) => flight.name));
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
18
50
|
export declare const flightLogOf: (rocket: string) => readonly LoggedFlight[];
|