@johnmorrisdotca/uchusen-rockets 0.3.0 → 0.5.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.
Files changed (120) hide show
  1. package/CHANGELOG.md +31 -5
  2. package/NOTICE.md +2 -0
  3. package/README.md +316 -4
  4. package/dist/assets/droneship-asog-landed.glb +0 -0
  5. package/dist/assets/droneship-asog.glb +0 -0
  6. package/dist/assets/droneship-jrti-landed.glb +0 -0
  7. package/dist/assets/droneship-jrti.glb +0 -0
  8. package/dist/assets/droneship-ocisly-landed.glb +0 -0
  9. package/dist/assets/droneship-ocisly.glb +0 -0
  10. package/dist/assets/falcon-9-block-5-dragon-2-first-stage.glb +0 -0
  11. package/dist/assets/falcon-9-block-5-dragon-2.glb +0 -0
  12. package/dist/assets/falcon-9-block-5-first-stage.glb +0 -0
  13. package/dist/assets/falcon-9-block-5.glb +0 -0
  14. package/dist/assets/falcon-9-ft-first-stage.glb +0 -0
  15. package/dist/assets/falcon-9-ft.glb +0 -0
  16. package/dist/assets/falcon-9-v1.1-first-stage.glb +0 -0
  17. package/dist/assets/falcon-9-v1.1.glb +0 -0
  18. package/dist/assets/falcon-heavy-falcon-heavy-centre.glb +0 -0
  19. package/dist/assets/falcon-heavy-falcon-heavy-side-left.glb +0 -0
  20. package/dist/assets/falcon-heavy-falcon-heavy-side-right.glb +0 -0
  21. package/dist/assets/falcon-heavy-falcon-heavy.glb +0 -0
  22. package/dist/assets/landing-zone-lz-1-landed.glb +0 -0
  23. package/dist/assets/landing-zone-lz-1.glb +0 -0
  24. package/dist/assets/landing-zone-lz-4-landed.glb +0 -0
  25. package/dist/assets/landing-zone-lz-4.glb +0 -0
  26. package/dist/assets/launch-tower-catch-booster.glb +0 -0
  27. package/dist/assets/launch-tower-catch.glb +0 -0
  28. package/dist/assets/launch-tower-stack-booster.glb +0 -0
  29. package/dist/assets/launch-tower-stack-ship.glb +0 -0
  30. package/dist/assets/launch-tower-stack.glb +0 -0
  31. package/dist/assets/starship-2019.glb +0 -0
  32. package/dist/assets/starship-v1-booster.glb +0 -0
  33. package/dist/assets/starship-v1-flight1-booster.glb +0 -0
  34. package/dist/assets/starship-v1-flight1-ship.glb +0 -0
  35. package/dist/assets/starship-v1-flight1.glb +0 -0
  36. package/dist/assets/starship-v1-ship.glb +0 -0
  37. package/dist/assets/starship-v1.glb +0 -0
  38. package/dist/assets/starship-v2-booster.glb +0 -0
  39. package/dist/assets/starship-v2-ship.glb +0 -0
  40. package/dist/assets/starship-v2.glb +0 -0
  41. package/dist/assets/starship-v3-booster.glb +0 -0
  42. package/dist/assets/starship-v3-ship.glb +0 -0
  43. package/dist/assets/starship-v3.glb +0 -0
  44. package/dist/assets/starship-v4-booster.glb +0 -0
  45. package/dist/assets/starship-v4-ship.glb +0 -0
  46. package/dist/assets/starship-v4.glb +0 -0
  47. package/dist/attrs.d.ts +70 -4
  48. package/dist/attrs.js +59 -4
  49. package/dist/build/glb.d.ts +25 -0
  50. package/dist/build/glb.js +29 -7
  51. package/dist/build/index.d.ts +94 -4
  52. package/dist/build/index.js +71 -7
  53. package/dist/build/lineup.d.ts +56 -2
  54. package/dist/build/lineup.js +23 -2
  55. package/dist/builder.d.ts +47 -1
  56. package/dist/builder.js +14 -1
  57. package/dist/crossfade.d.ts +44 -2
  58. package/dist/crossfade.js +44 -2
  59. package/dist/data/credits.d.ts +44 -1
  60. package/dist/data/credits.js +22 -1
  61. package/dist/data/flight-log.d.ts +33 -1
  62. package/dist/data/flight-log.js +22 -1
  63. package/dist/data/flights.d.ts +61 -2
  64. package/dist/data/flights.js +160 -3
  65. package/dist/data/makers.d.ts +21 -0
  66. package/dist/data/makers.js +10 -0
  67. package/dist/data/propellants.d.ts +59 -0
  68. package/dist/data/propellants.js +43 -0
  69. package/dist/data/sources.d.ts +102 -0
  70. package/dist/data/sources.js +19 -0
  71. package/dist/data/types.d.ts +81 -1
  72. package/dist/data/types.js +26 -1
  73. package/dist/draw/plume.d.ts +10 -1
  74. package/dist/draw/plume.js +15 -5
  75. package/dist/element/plumes.d.ts +7 -8
  76. package/dist/element/plumes.js +36 -21
  77. package/dist/element/scene.js +30 -5
  78. package/dist/element.d.ts +61 -3
  79. package/dist/element.js +53 -5
  80. package/dist/embed.d.ts +110 -5
  81. package/dist/embed.js +88 -5
  82. package/dist/engines.d.ts +86 -4
  83. package/dist/engines.js +75 -4
  84. package/dist/fit.d.ts +68 -0
  85. package/dist/fit.js +13 -0
  86. package/dist/flight.d.ts +136 -9
  87. package/dist/flight.js +130 -10
  88. package/dist/flightbar.d.ts +12 -0
  89. package/dist/flightbar.js +13 -1
  90. package/dist/framing.d.ts +182 -8
  91. package/dist/framing.js +127 -6
  92. package/dist/index.d.ts +3 -0
  93. package/dist/index.js +2 -0
  94. package/dist/layout.d.ts +65 -1
  95. package/dist/layout.js +43 -1
  96. package/dist/looks.d.ts +64 -1
  97. package/dist/looks.js +42 -1
  98. package/dist/model/falcon.js +2 -2
  99. package/dist/model/materials.d.ts +32 -0
  100. package/dist/model/materials.js +10 -0
  101. package/dist/model/moves.d.ts +36 -0
  102. package/dist/model/moves.js +70 -0
  103. package/dist/model/pieces.d.ts +31 -0
  104. package/dist/model/pieces.js +51 -9
  105. package/dist/model/registry.d.ts +22 -0
  106. package/dist/model/registry.js +22 -0
  107. package/dist/model/starship.d.ts +6 -3
  108. package/dist/model/starship.js +12 -7
  109. package/dist/parts.d.ts +33 -1
  110. package/dist/pixels.d.ts +44 -4
  111. package/dist/pixels.js +44 -4
  112. package/dist/react.d.ts +26 -2
  113. package/dist/react.js +13 -0
  114. package/dist/rockets.d.ts +91 -3
  115. package/dist/rockets.js +58 -2
  116. package/dist/spin.d.ts +57 -2
  117. package/dist/spin.js +35 -2
  118. package/dist/tilt.d.ts +48 -4
  119. package/dist/tilt.js +26 -4
  120. package/package.json +27 -7
package/dist/embed.d.ts CHANGED
@@ -1,26 +1,131 @@
1
1
  import { type RocketOptions } from "./attrs.ts";
2
+ /**
3
+ * The six ways `embedCode` writes a rocket for another page: `element`, `iframe`, `module`, `svg`, `data` and `link`.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * import { EMBED_KINDS } from "@johnmorrisdotca/uchusen-rockets";
8
+ *
9
+ * console.log(EMBED_KINDS.join(", "));
10
+ * ```
11
+ */
2
12
  export declare const EMBED_KINDS: readonly ["element", "iframe", "module", "svg", "data", "link"];
13
+ /**
14
+ * One of the ways in `EMBED_KINDS`.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import type { EmbedKind } from "@johnmorrisdotca/uchusen-rockets";
19
+ *
20
+ * const kind: EmbedKind = "iframe";
21
+ * console.log(kind);
22
+ * ```
23
+ */
3
24
  export type EmbedKind = (typeof EMBED_KINDS)[number];
25
+ /**
26
+ * Where the embed code points: the address of the demo that holds `embed.html`, and the CDN folder the element loads from. Both default to this package's own.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import { embedCode, type EmbedSettings } from "@johnmorrisdotca/uchusen-rockets";
31
+ *
32
+ * const settings: EmbedSettings = { site: "https://example.test/rockets/" };
33
+ * console.log(embedCode({ rocket: "starship" }, "iframe", settings));
34
+ * ```
35
+ */
4
36
  export interface EmbedSettings {
5
37
  /** The address of the published demo, where `embed.html` is. */
6
38
  site?: string;
7
39
  /** The CDN or package path the element is loaded from. */
8
40
  cdn?: string;
9
41
  }
42
+ /**
43
+ * The address of the published demo, where `embed.html` is.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * import { SITE } from "@johnmorrisdotca/uchusen-rockets";
48
+ *
49
+ * console.log(SITE);
50
+ * ```
51
+ */
10
52
  export declare const SITE = "https://johnmorrisdotca.github.io/uchusen-rockets/";
53
+ /**
54
+ * The folder on a CDN the element loads from when the embed is a plain script with no bundler.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * import { CDN } from "@johnmorrisdotca/uchusen-rockets";
59
+ *
60
+ * console.log(CDN);
61
+ * ```
62
+ */
11
63
  export declare const CDN = "https://cdn.jsdelivr.net/npm/@johnmorrisdotca/uchusen-rockets@0";
12
- /** The three.js a page with no bundler takes from the CDN: the version this package is built and tested with. */
64
+ /**
65
+ * The three.js a page with no bundler takes from the CDN: the version this package is built and tested with.
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * import { THREE_VERSION } from "@johnmorrisdotca/uchusen-rockets";
70
+ *
71
+ * console.log(THREE_VERSION);
72
+ * ```
73
+ */
13
74
  export declare const THREE_VERSION = "0.186.1";
14
- /** What an embed asks of the page around it, in words: a line for the demo to show. */
75
+ /**
76
+ * What an embed asks of the page around it, in words: a line for the demo to show.
77
+ *
78
+ * @param kind Which way of embedding.
79
+ * @param options The rocket being embedded.
80
+ * @returns A line of text for the demo to show beside the code.
81
+ * @example
82
+ * ```ts
83
+ * import { embedNote } from "@johnmorrisdotca/uchusen-rockets";
84
+ *
85
+ * console.log(embedNote("iframe", { rocket: "starship" }));
86
+ * ```
87
+ */
15
88
  export declare function embedNote(kind: EmbedKind, options: RocketOptions): string;
16
89
  /**
17
- * The CC BY line for a painted rocket, generated from the parts that are showing.
18
- * Empty when the look is not painted, or when those parts are this package's own paint.
90
+ * The CC BY line for a painted rocket, generated from the parts that are showing. Empty when the look is not painted, or when those parts are this package's own paint.
91
+ *
92
+ * @param options The rocket as it will be drawn.
93
+ * @returns The credit line, or an empty text when nothing needs crediting.
94
+ * @example
95
+ * ```ts
96
+ * import { paintedCredit } from "@johnmorrisdotca/uchusen-rockets";
97
+ *
98
+ * console.log(paintedCredit({ rocket: "starship", variant: "v3", look: "painted" }));
99
+ * console.log(paintedCredit({ rocket: "starship", variant: "v3", look: "line" }) === "");
100
+ * ```
19
101
  */
20
102
  export declare function paintedCredit(options: RocketOptions): string;
21
103
  /**
22
104
  * The shipped picture of these options, under the package's `dist/assets/`: `starship-v3.svg`, `falcon-9-block-5-apart.thick.svg`. These are drawn from the default view, with no flames. Null for a custom build, which has no file, or a variant, part or look that does not exist.
105
+ *
106
+ * @param options The rocket, variant, look, view and what to show.
107
+ * @returns The path of the shipped picture under `dist/assets/`, or null when none is shipped for those options.
108
+ * @example
109
+ * ```ts
110
+ * import { assetPathOf } from "@johnmorrisdotca/uchusen-rockets";
111
+ *
112
+ * console.log(assetPathOf({ rocket: "starship", variant: "v3" }));
113
+ * ```
23
114
  */
24
115
  export declare function assetPathOf(options: RocketOptions): string | null;
25
- /** The text of one embed. The `module` one imports the package; the `data` one is a `data:image/svg+xml` address for an `<img>`. */
116
+ /**
117
+ * The text of one embed. The `module` one imports the package; the `data` one is a `data:image/svg+xml` address for an `<img>`.
118
+ *
119
+ * @param options The rocket and how it looks.
120
+ * @param kind Which way to write it. Defaults to the element.
121
+ * @param settings Where the demo and the CDN are, if not the package's own.
122
+ * @returns The text to paste into a page. A painted rocket's credit is part of it.
123
+ * @example
124
+ * ```ts
125
+ * import { embedCode } from "@johnmorrisdotca/uchusen-rockets";
126
+ *
127
+ * console.log(embedCode({ rocket: "falcon-9", variant: "block-5", look: "thick" }));
128
+ * console.log(embedCode({ rocket: "falcon-9", variant: "block-5" }, "iframe"));
129
+ * ```
130
+ */
26
131
  export declare function embedCode(options: RocketOptions, kind?: EmbedKind, settings?: EmbedSettings): string;
package/dist/embed.js CHANGED
@@ -7,10 +7,49 @@ import { cleanView } from "./framing.js";
7
7
  import { cleanShow, showsOf } from "./layout.js";
8
8
  import { cleanLook, DEFAULT_LOOK } from "./looks.js";
9
9
  import { attributesFromOptions, rocketToParams } from "./attrs.js";
10
+ /**
11
+ * The six ways `embedCode` writes a rocket for another page: `element`, `iframe`, `module`, `svg`, `data` and `link`.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { EMBED_KINDS } from "@johnmorrisdotca/uchusen-rockets";
16
+ *
17
+ * console.log(EMBED_KINDS.join(", "));
18
+ * ```
19
+ */
10
20
  export const EMBED_KINDS = ["element", "iframe", "module", "svg", "data", "link"];
21
+ /**
22
+ * The address of the published demo, where `embed.html` is.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { SITE } from "@johnmorrisdotca/uchusen-rockets";
27
+ *
28
+ * console.log(SITE);
29
+ * ```
30
+ */
11
31
  export const SITE = "https://johnmorrisdotca.github.io/uchusen-rockets/";
32
+ /**
33
+ * The folder on a CDN the element loads from when the embed is a plain script with no bundler.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * import { CDN } from "@johnmorrisdotca/uchusen-rockets";
38
+ *
39
+ * console.log(CDN);
40
+ * ```
41
+ */
12
42
  export const CDN = "https://cdn.jsdelivr.net/npm/@johnmorrisdotca/uchusen-rockets@0";
13
- /** The three.js a page with no bundler takes from the CDN: the version this package is built and tested with. */
43
+ /**
44
+ * The three.js a page with no bundler takes from the CDN: the version this package is built and tested with.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * import { THREE_VERSION } from "@johnmorrisdotca/uchusen-rockets";
49
+ *
50
+ * console.log(THREE_VERSION);
51
+ * ```
52
+ */
14
53
  export const THREE_VERSION = "0.186.1";
15
54
  const THREE_CDN = `https://cdn.jsdelivr.net/npm/three@${THREE_VERSION}`;
16
55
  const IMPORT_MAP = `<script type="importmap">\n { "imports": { "three": "${THREE_CDN}/build/three.module.js", "three/addons/": "${THREE_CDN}/examples/jsm/" } }\n</script>`;
@@ -34,7 +73,19 @@ function descriptionOf(options) {
34
73
  }
35
74
  return { rocket: options.rocket ?? "starship", ...(options.variant ? { variant: options.variant } : {}) };
36
75
  }
37
- /** What an embed asks of the page around it, in words: a line for the demo to show. */
76
+ /**
77
+ * What an embed asks of the page around it, in words: a line for the demo to show.
78
+ *
79
+ * @param kind Which way of embedding.
80
+ * @param options The rocket being embedded.
81
+ * @returns A line of text for the demo to show beside the code.
82
+ * @example
83
+ * ```ts
84
+ * import { embedNote } from "@johnmorrisdotca/uchusen-rockets";
85
+ *
86
+ * console.log(embedNote("iframe", { rocket: "starship" }));
87
+ * ```
88
+ */
38
89
  export function embedNote(kind, options) {
39
90
  const notes = {
40
91
  element: "One script from the CDN and the tag. The import map names three.js, for the 3D view; a page with a bundler needs neither, only the package.",
@@ -47,8 +98,17 @@ export function embedNote(kind, options) {
47
98
  return notes[kind];
48
99
  }
49
100
  /**
50
- * The CC BY line for a painted rocket, generated from the parts that are showing.
51
- * Empty when the look is not painted, or when those parts are this package's own paint.
101
+ * The CC BY line for a painted rocket, generated from the parts that are showing. Empty when the look is not painted, or when those parts are this package's own paint.
102
+ *
103
+ * @param options The rocket as it will be drawn.
104
+ * @returns The credit line, or an empty text when nothing needs crediting.
105
+ * @example
106
+ * ```ts
107
+ * import { paintedCredit } from "@johnmorrisdotca/uchusen-rockets";
108
+ *
109
+ * console.log(paintedCredit({ rocket: "starship", variant: "v3", look: "painted" }));
110
+ * console.log(paintedCredit({ rocket: "starship", variant: "v3", look: "line" }) === "");
111
+ * ```
52
112
  */
53
113
  export function paintedCredit(options) {
54
114
  if (cleanLook(options.look) !== "painted")
@@ -68,6 +128,15 @@ export function paintedCredit(options) {
68
128
  }
69
129
  /**
70
130
  * The shipped picture of these options, under the package's `dist/assets/`: `starship-v3.svg`, `falcon-9-block-5-apart.thick.svg`. These are drawn from the default view, with no flames. Null for a custom build, which has no file, or a variant, part or look that does not exist.
131
+ *
132
+ * @param options The rocket, variant, look, view and what to show.
133
+ * @returns The path of the shipped picture under `dist/assets/`, or null when none is shipped for those options.
134
+ * @example
135
+ * ```ts
136
+ * import { assetPathOf } from "@johnmorrisdotca/uchusen-rockets";
137
+ *
138
+ * console.log(assetPathOf({ rocket: "starship", variant: "v3" }));
139
+ * ```
71
140
  */
72
141
  export function assetPathOf(options) {
73
142
  if (options.build)
@@ -103,7 +172,21 @@ function drawingOf(options) {
103
172
  }
104
173
  }
105
174
  const creditHtml = (credit) => (credit === "" ? "" : `\n<p>${esc(credit).replaceAll("\n", "<br>\n")}</p>`);
106
- /** The text of one embed. The `module` one imports the package; the `data` one is a `data:image/svg+xml` address for an `<img>`. */
175
+ /**
176
+ * The text of one embed. The `module` one imports the package; the `data` one is a `data:image/svg+xml` address for an `<img>`.
177
+ *
178
+ * @param options The rocket and how it looks.
179
+ * @param kind Which way to write it. Defaults to the element.
180
+ * @param settings Where the demo and the CDN are, if not the package's own.
181
+ * @returns The text to paste into a page. A painted rocket's credit is part of it.
182
+ * @example
183
+ * ```ts
184
+ * import { embedCode } from "@johnmorrisdotca/uchusen-rockets";
185
+ *
186
+ * console.log(embedCode({ rocket: "falcon-9", variant: "block-5", look: "thick" }));
187
+ * console.log(embedCode({ rocket: "falcon-9", variant: "block-5" }, "iframe"));
188
+ * ```
189
+ */
107
190
  export function embedCode(options, kind = "element", settings = {}) {
108
191
  const site = settings.site ?? SITE;
109
192
  const cdn = settings.cdn ?? CDN;
package/dist/engines.d.ts CHANGED
@@ -4,13 +4,57 @@ export declare const PLUME_EXITS = 34;
4
4
  export declare const PLUME_MOST_M = 26;
5
5
  /** How many shock diamonds a flame shows near the ground. A picture. */
6
6
  export declare const PLUME_DIAMONDS = 6;
7
- /** With no one touching anything, a flame stops moving after this long and nothing draws: a lit rocket at rest costs the same as a dark one. */
7
+ /**
8
+ * With no one touching anything, a flame stops moving after this long and nothing draws: a lit rocket at rest costs the same as a dark one.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { FLAME_SETTLE_MS } from "@johnmorrisdotca/uchusen-rockets";
13
+ *
14
+ * console.log(FLAME_SETTLE_MS / 1000, "seconds");
15
+ * ```
16
+ */
8
17
  export declare const FLAME_SETTLE_MS = 15000;
9
18
  /** A flame that only flickers is drawn at most this often. A turn or a move still draws once a frame. */
10
19
  export declare const FLAME_GAP_MS = 33;
20
+ /**
21
+ * How long a flame is drawn, in metres, for an engine whose bell is `exit` metres across at the mouth. The length is a picture, not a measured flame.
22
+ *
23
+ * @param exit The exit radius of the bell, in metres.
24
+ * @returns The flame's length in metres.
25
+ * @example
26
+ * ```ts
27
+ * import { plumeLength } from "@johnmorrisdotca/uchusen-rockets";
28
+ *
29
+ * console.log(plumeLength(0.45).toFixed(2));
30
+ * ```
31
+ */
11
32
  export declare function plumeLength(exit: number): number;
12
- /** `on` asks for them, and a reader who asked for reduced motion has them off whatever the page says. Anything else, or nothing, is off. */
33
+ /**
34
+ * `on` asks for them, and a reader who asked for reduced motion has them off whatever the page says. Anything else, or nothing, is off.
35
+ *
36
+ * @param attribute The value of the `engines` attribute, or null when it is missing.
37
+ * @param reduced True when the reader asked for reduced motion.
38
+ * @returns True when the flames should be drawn.
39
+ * @example
40
+ * ```ts
41
+ * import { enginesWanted } from "@johnmorrisdotca/uchusen-rockets";
42
+ *
43
+ * console.log(enginesWanted("on", false), enginesWanted("on", true), enginesWanted(null, false));
44
+ * ```
45
+ */
13
46
  export declare function enginesWanted(attribute: string | null, reduced: boolean): boolean;
47
+ /**
48
+ * One engine bell as the drawing has it: where it stands across the part, the height of its mouth and its exit radius, all in metres in the part's own frame.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * import { bellsOf, type Bell } from "@johnmorrisdotca/uchusen-rockets";
53
+ *
54
+ * const bells: Bell[] = bellsOf([]);
55
+ * console.log(bells.length);
56
+ * ```
57
+ */
14
58
  export interface Bell {
15
59
  x: number;
16
60
  z: number;
@@ -19,7 +63,20 @@ export interface Bell {
19
63
  /** Exit radius, metres. */
20
64
  exit: number;
21
65
  }
22
- /** One bell for every engine the pieces already draw. The mouth is the first point of the bell. */
66
+ /**
67
+ * One bell for every engine the pieces already draw. The mouth is the first point of the bell.
68
+ *
69
+ * @param pieces The pieces of a part, as the builder makes them.
70
+ * @returns The bells, one for each engine the pieces already draw.
71
+ * @example
72
+ * ```ts
73
+ * import { build } from "@johnmorrisdotca/uchusen-rockets/build";
74
+ * import { bellsOf } from "@johnmorrisdotca/uchusen-rockets";
75
+ *
76
+ * const booster = build({ rocket: "falcon-9", variant: "block-5" }).parts[0];
77
+ * console.log(booster ? bellsOf(booster.pieces).length : 0);
78
+ * ```
79
+ */
23
80
  export declare function bellsOf(pieces: readonly Piece[]): Bell[];
24
81
  export interface LitBell extends Bell {
25
82
  slot: string;
@@ -36,9 +93,34 @@ export declare function litBells(parts: readonly {
36
93
  beside?: boolean;
37
94
  dark?: boolean;
38
95
  }[], together: boolean): LitBell[];
39
- /** The bells grouped by how far they are from the part's axis, innermost ring first, and each ring in order round the axis. */
96
+ /**
97
+ * The bells grouped by how far they are from the part's axis, innermost ring first, and each ring in order round the axis.
98
+ *
99
+ * @param bells The bells of one part.
100
+ * @returns The rings, innermost first, each a list of bells.
101
+ * @example
102
+ * ```ts
103
+ * import { build } from "@johnmorrisdotca/uchusen-rockets/build";
104
+ * import { bellsOf, ringsOf } from "@johnmorrisdotca/uchusen-rockets";
105
+ *
106
+ * const booster = build({ rocket: "falcon-9", variant: "block-5" }).parts[0];
107
+ * console.log(booster ? ringsOf(bellsOf(booster.pieces)).map((ring) => ring.length) : []);
108
+ * ```
109
+ */
40
110
  export declare function ringsOf(bells: readonly Bell[]): Bell[][];
41
111
  /**
42
112
  * Which `count` engines burn: from the middle out, and a ring that is only partly used has them evenly round it, so three of a Falcon 9's nine are the middle one and two opposite. A source says how many; where they stand is this rule.
113
+ *
114
+ * @param bells All the bells of a part.
115
+ * @param count How many burn.
116
+ * @returns The bells that burn.
117
+ * @example
118
+ * ```ts
119
+ * import { build } from "@johnmorrisdotca/uchusen-rockets/build";
120
+ * import { bellsOf, pickBells } from "@johnmorrisdotca/uchusen-rockets";
121
+ *
122
+ * const booster = build({ rocket: "falcon-9", variant: "block-5" }).parts[0];
123
+ * console.log(booster ? pickBells(bellsOf(booster.pieces), 3).length : 0);
124
+ * ```
43
125
  */
44
126
  export declare function pickBells(bells: readonly Bell[], count: number): Bell[];
package/dist/engines.js CHANGED
@@ -3,18 +3,64 @@ export const PLUME_EXITS = 34;
3
3
  export const PLUME_MOST_M = 26;
4
4
  /** How many shock diamonds a flame shows near the ground. A picture. */
5
5
  export const PLUME_DIAMONDS = 6;
6
- /** With no one touching anything, a flame stops moving after this long and nothing draws: a lit rocket at rest costs the same as a dark one. */
6
+ /**
7
+ * With no one touching anything, a flame stops moving after this long and nothing draws: a lit rocket at rest costs the same as a dark one.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { FLAME_SETTLE_MS } from "@johnmorrisdotca/uchusen-rockets";
12
+ *
13
+ * console.log(FLAME_SETTLE_MS / 1000, "seconds");
14
+ * ```
15
+ */
7
16
  export const FLAME_SETTLE_MS = 15_000;
8
17
  /** A flame that only flickers is drawn at most this often. A turn or a move still draws once a frame. */
9
18
  export const FLAME_GAP_MS = 33;
19
+ /**
20
+ * How long a flame is drawn, in metres, for an engine whose bell is `exit` metres across at the mouth. The length is a picture, not a measured flame.
21
+ *
22
+ * @param exit The exit radius of the bell, in metres.
23
+ * @returns The flame's length in metres.
24
+ * @example
25
+ * ```ts
26
+ * import { plumeLength } from "@johnmorrisdotca/uchusen-rockets";
27
+ *
28
+ * console.log(plumeLength(0.45).toFixed(2));
29
+ * ```
30
+ */
10
31
  export function plumeLength(exit) {
11
32
  return Math.min(exit * PLUME_EXITS, PLUME_MOST_M);
12
33
  }
13
- /** `on` asks for them, and a reader who asked for reduced motion has them off whatever the page says. Anything else, or nothing, is off. */
34
+ /**
35
+ * `on` asks for them, and a reader who asked for reduced motion has them off whatever the page says. Anything else, or nothing, is off.
36
+ *
37
+ * @param attribute The value of the `engines` attribute, or null when it is missing.
38
+ * @param reduced True when the reader asked for reduced motion.
39
+ * @returns True when the flames should be drawn.
40
+ * @example
41
+ * ```ts
42
+ * import { enginesWanted } from "@johnmorrisdotca/uchusen-rockets";
43
+ *
44
+ * console.log(enginesWanted("on", false), enginesWanted("on", true), enginesWanted(null, false));
45
+ * ```
46
+ */
14
47
  export function enginesWanted(attribute, reduced) {
15
48
  return attribute === "on" && !reduced;
16
49
  }
17
- /** One bell for every engine the pieces already draw. The mouth is the first point of the bell. */
50
+ /**
51
+ * One bell for every engine the pieces already draw. The mouth is the first point of the bell.
52
+ *
53
+ * @param pieces The pieces of a part, as the builder makes them.
54
+ * @returns The bells, one for each engine the pieces already draw.
55
+ * @example
56
+ * ```ts
57
+ * import { build } from "@johnmorrisdotca/uchusen-rockets/build";
58
+ * import { bellsOf } from "@johnmorrisdotca/uchusen-rockets";
59
+ *
60
+ * const booster = build({ rocket: "falcon-9", variant: "block-5" }).parts[0];
61
+ * console.log(booster ? bellsOf(booster.pieces).length : 0);
62
+ * ```
63
+ */
18
64
  export function bellsOf(pieces) {
19
65
  const bells = [];
20
66
  for (const piece of pieces) {
@@ -44,7 +90,20 @@ export function litBells(parts, together) {
44
90
  }
45
91
  return bells;
46
92
  }
47
- /** The bells grouped by how far they are from the part's axis, innermost ring first, and each ring in order round the axis. */
93
+ /**
94
+ * The bells grouped by how far they are from the part's axis, innermost ring first, and each ring in order round the axis.
95
+ *
96
+ * @param bells The bells of one part.
97
+ * @returns The rings, innermost first, each a list of bells.
98
+ * @example
99
+ * ```ts
100
+ * import { build } from "@johnmorrisdotca/uchusen-rockets/build";
101
+ * import { bellsOf, ringsOf } from "@johnmorrisdotca/uchusen-rockets";
102
+ *
103
+ * const booster = build({ rocket: "falcon-9", variant: "block-5" }).parts[0];
104
+ * console.log(booster ? ringsOf(bellsOf(booster.pieces)).map((ring) => ring.length) : []);
105
+ * ```
106
+ */
48
107
  export function ringsOf(bells) {
49
108
  const sorted = [...bells].sort((a, b) => Math.hypot(a.x, a.z) - Math.hypot(b.x, b.z));
50
109
  const rings = [];
@@ -61,6 +120,18 @@ export function ringsOf(bells) {
61
120
  }
62
121
  /**
63
122
  * Which `count` engines burn: from the middle out, and a ring that is only partly used has them evenly round it, so three of a Falcon 9's nine are the middle one and two opposite. A source says how many; where they stand is this rule.
123
+ *
124
+ * @param bells All the bells of a part.
125
+ * @param count How many burn.
126
+ * @returns The bells that burn.
127
+ * @example
128
+ * ```ts
129
+ * import { build } from "@johnmorrisdotca/uchusen-rockets/build";
130
+ * import { bellsOf, pickBells } from "@johnmorrisdotca/uchusen-rockets";
131
+ *
132
+ * const booster = build({ rocket: "falcon-9", variant: "block-5" }).parts[0];
133
+ * console.log(booster ? pickBells(bellsOf(booster.pieces), 3).length : 0);
134
+ * ```
64
135
  */
65
136
  export function pickBells(bells, count) {
66
137
  const wanted = Math.max(0, Math.min(bells.length, Math.floor(count)));
package/dist/fit.d.ts CHANGED
@@ -1,6 +1,17 @@
1
1
  import { type CreditId, type ModelCredit } from "./data/credits.ts";
2
2
  import type { Variant } from "./data/types.ts";
3
3
  import type { PartRecord } from "./parts.ts";
4
+ /**
5
+ * A rocket to check or build: its id, its variant (left out: the rocket's default) and any other part in a slot, by part id.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { check, type Description } from "@johnmorrisdotca/uchusen-rockets";
10
+ *
11
+ * const description: Description = { rocket: "starship", variant: "v3", parts: { ship: "starship-v2-ship" } };
12
+ * console.log(check(description).label);
13
+ * ```
14
+ */
4
15
  export interface Description {
5
16
  rocket: string;
6
17
  /** Left out: the rocket's default variant. */
@@ -8,17 +19,61 @@ export interface Description {
8
19
  /** Another part in a slot, by its id. */
9
20
  parts?: Readonly<Record<string, string>>;
10
21
  }
22
+ /**
23
+ * Why a check said what it said: an unknown rocket, variant, slot or part, a part of the wrong kind, a joint that is missing, of another kind or of another width, or a custom build.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * import { check, type FitCode } from "@johnmorrisdotca/uchusen-rockets";
28
+ *
29
+ * const codes: FitCode[] = check({ rocket: "nowhere" }).issues.map((issue) => issue.code);
30
+ * console.log(codes);
31
+ * ```
32
+ */
11
33
  export type FitCode = "unknown-rocket" | "unknown-variant" | "unknown-slot" | "unknown-part" | "wrong-kind" | "no-joint" | "joint-kind" | "joint-diameter" | "custom";
34
+ /**
35
+ * One thing a check found: its code, its level (`error` stops a build, `note` says what was decided) and a sentence saying it.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * import { check, type FitIssue } from "@johnmorrisdotca/uchusen-rockets";
40
+ *
41
+ * const issue: FitIssue | undefined = check({ rocket: "starship", variant: "v3", parts: { booster: "starship-v3-ship" } }).issues[0];
42
+ * console.log(issue?.level, issue?.message);
43
+ * ```
44
+ */
12
45
  export interface FitIssue {
13
46
  code: FitCode;
14
47
  /** "error" stops the build. "note" says what the check decided. */
15
48
  level: "error" | "note";
16
49
  message: string;
17
50
  }
51
+ /**
52
+ * A part standing in a slot of a checked rocket.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * import { check, type SlotPart } from "@johnmorrisdotca/uchusen-rockets";
57
+ *
58
+ * const bottom: SlotPart | undefined = check({ rocket: "starship", variant: "v3" }).parts[0];
59
+ * console.log(bottom?.slot, bottom?.part.name);
60
+ * ```
61
+ */
18
62
  export interface SlotPart {
19
63
  slot: string;
20
64
  part: PartRecord;
21
65
  }
66
+ /**
67
+ * The answer of `check`: whether the parts go together, the issues, the label to call the rocket, whether it is a custom build, the variant, the parts, the size and the credits of every licensed model.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * import { check, type FitReport } from "@johnmorrisdotca/uchusen-rockets";
72
+ *
73
+ * const report: FitReport = check({ rocket: "falcon-9", variant: "block-5" });
74
+ * console.log(report.ok, report.size);
75
+ * ```
76
+ */
22
77
  export interface FitReport {
23
78
  ok: boolean;
24
79
  issues: readonly FitIssue[];
@@ -42,4 +97,17 @@ export interface FitReport {
42
97
  }
43
98
  /** How far apart two joints may be in metres and still meet. */
44
99
  export declare const JOINT_TOLERANCE = 0.1;
100
+ /**
101
+ * Asks whether a rocket goes together, from the parts' records alone, with no three.js and no DOM. A rocket labelled as a real version uses only parts true for it; any mix is a custom build and says so.
102
+ *
103
+ * @param description The rocket, its variant and any other part in a slot.
104
+ * @returns A report that says whether it fits and why, with the size and the credits.
105
+ * @example
106
+ * ```ts
107
+ * import { check } from "@johnmorrisdotca/uchusen-rockets";
108
+ *
109
+ * const report = check({ rocket: "starship", variant: "v3", parts: { booster: "starship-v3-ship" } });
110
+ * console.log(report.ok, report.issues[0]?.message);
111
+ * ```
112
+ */
45
113
  export declare function check(description: Description): FitReport;
package/dist/fit.js CHANGED
@@ -20,6 +20,19 @@ function sizeOf(parts) {
20
20
  }
21
21
  return { height: Math.round(top * 1000) / 1000, diameter: Math.max(...parts.map(({ part }) => part.diameter)) };
22
22
  }
23
+ /**
24
+ * Asks whether a rocket goes together, from the parts' records alone, with no three.js and no DOM. A rocket labelled as a real version uses only parts true for it; any mix is a custom build and says so.
25
+ *
26
+ * @param description The rocket, its variant and any other part in a slot.
27
+ * @returns A report that says whether it fits and why, with the size and the credits.
28
+ * @example
29
+ * ```ts
30
+ * import { check } from "@johnmorrisdotca/uchusen-rockets";
31
+ *
32
+ * const report = check({ rocket: "starship", variant: "v3", parts: { booster: "starship-v3-ship" } });
33
+ * console.log(report.ok, report.issues[0]?.message);
34
+ * ```
35
+ */
23
36
  export function check(description) {
24
37
  const issues = [];
25
38
  const fail = (code, message) => issues.push({ code, level: "error", message });