@johnmorrisdotca/uchusen-rockets 0.19.1 → 0.20.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 (128) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSES/Orbiter-MIT.txt +21 -0
  3. package/NOTICE.md +37 -1
  4. package/README.md +13 -6
  5. package/dist/assets/falcon-heavy-test-flight-apart.painted.svg +1 -0
  6. package/dist/assets/falcon-heavy-test-flight-apart.svg +1 -0
  7. package/dist/assets/falcon-heavy-test-flight-apart.thick.svg +1 -0
  8. package/dist/assets/falcon-heavy-test-flight-car.glb +0 -0
  9. package/dist/assets/falcon-heavy-test-flight-car.painted.svg +1 -0
  10. package/dist/assets/falcon-heavy-test-flight-car.svg +1 -0
  11. package/dist/assets/falcon-heavy-test-flight-car.thick.svg +1 -0
  12. package/dist/assets/falcon-heavy-test-flight-centre.glb +0 -0
  13. package/dist/assets/falcon-heavy-test-flight-centre.painted.svg +1 -0
  14. package/dist/assets/falcon-heavy-test-flight-centre.svg +1 -0
  15. package/dist/assets/falcon-heavy-test-flight-centre.thick.svg +1 -0
  16. package/dist/assets/falcon-heavy-test-flight-side-left.glb +0 -0
  17. package/dist/assets/falcon-heavy-test-flight-side-left.painted.svg +1 -0
  18. package/dist/assets/falcon-heavy-test-flight-side-left.svg +1 -0
  19. package/dist/assets/falcon-heavy-test-flight-side-left.thick.svg +1 -0
  20. package/dist/assets/falcon-heavy-test-flight-side-right.glb +0 -0
  21. package/dist/assets/falcon-heavy-test-flight-side-right.painted.svg +1 -0
  22. package/dist/assets/falcon-heavy-test-flight-side-right.svg +1 -0
  23. package/dist/assets/falcon-heavy-test-flight-side-right.thick.svg +1 -0
  24. package/dist/assets/falcon-heavy-test-flight-starman.glb +0 -0
  25. package/dist/assets/falcon-heavy-test-flight-starman.painted.svg +1 -0
  26. package/dist/assets/falcon-heavy-test-flight-starman.svg +1 -0
  27. package/dist/assets/falcon-heavy-test-flight-starman.thick.svg +1 -0
  28. package/dist/assets/falcon-heavy-test-flight.glb +0 -0
  29. package/dist/assets/falcon-heavy-test-flight.painted.svg +1 -0
  30. package/dist/assets/falcon-heavy-test-flight.svg +1 -0
  31. package/dist/assets/falcon-heavy-test-flight.thick.svg +1 -0
  32. package/dist/assets/models/roadster-first-generation-car.glb +0 -0
  33. package/dist/assets/models/roadster-second-generation-2-car.glb +0 -0
  34. package/dist/assets/models/roadster-second-generation-car.glb +0 -0
  35. package/dist/assets/roadster-first-generation-apart.painted.svg +1 -0
  36. package/dist/assets/roadster-first-generation-apart.svg +1 -0
  37. package/dist/assets/roadster-first-generation-apart.thick.svg +1 -0
  38. package/dist/assets/roadster-first-generation-car.glb +0 -0
  39. package/dist/assets/roadster-first-generation-car.painted.svg +1 -0
  40. package/dist/assets/roadster-first-generation-car.svg +1 -0
  41. package/dist/assets/roadster-first-generation-car.thick.svg +1 -0
  42. package/dist/assets/roadster-first-generation-starman.glb +0 -0
  43. package/dist/assets/roadster-first-generation-starman.painted.svg +1 -0
  44. package/dist/assets/roadster-first-generation-starman.svg +1 -0
  45. package/dist/assets/roadster-first-generation-starman.thick.svg +1 -0
  46. package/dist/assets/roadster-first-generation.glb +0 -0
  47. package/dist/assets/roadster-first-generation.painted.svg +1 -0
  48. package/dist/assets/roadster-first-generation.svg +1 -0
  49. package/dist/assets/roadster-first-generation.thick.svg +1 -0
  50. package/dist/assets/roadster-second-generation-2-apart.painted.svg +1 -0
  51. package/dist/assets/roadster-second-generation-2-apart.svg +1 -0
  52. package/dist/assets/roadster-second-generation-2-apart.thick.svg +1 -0
  53. package/dist/assets/roadster-second-generation-2-car.glb +0 -0
  54. package/dist/assets/roadster-second-generation-2-car.painted.svg +1 -0
  55. package/dist/assets/roadster-second-generation-2-car.svg +1 -0
  56. package/dist/assets/roadster-second-generation-2-car.thick.svg +1 -0
  57. package/dist/assets/roadster-second-generation-2-starman.glb +0 -0
  58. package/dist/assets/roadster-second-generation-2-starman.painted.svg +1 -0
  59. package/dist/assets/roadster-second-generation-2-starman.svg +1 -0
  60. package/dist/assets/roadster-second-generation-2-starman.thick.svg +1 -0
  61. package/dist/assets/roadster-second-generation-2.glb +0 -0
  62. package/dist/assets/roadster-second-generation-2.painted.svg +1 -0
  63. package/dist/assets/roadster-second-generation-2.svg +1 -0
  64. package/dist/assets/roadster-second-generation-2.thick.svg +1 -0
  65. package/dist/assets/roadster-second-generation-apart.painted.svg +1 -0
  66. package/dist/assets/roadster-second-generation-apart.svg +1 -0
  67. package/dist/assets/roadster-second-generation-apart.thick.svg +1 -0
  68. package/dist/assets/roadster-second-generation-car.glb +0 -0
  69. package/dist/assets/roadster-second-generation-car.painted.svg +1 -0
  70. package/dist/assets/roadster-second-generation-car.svg +1 -0
  71. package/dist/assets/roadster-second-generation-car.thick.svg +1 -0
  72. package/dist/assets/roadster-second-generation-starman.glb +0 -0
  73. package/dist/assets/roadster-second-generation-starman.painted.svg +1 -0
  74. package/dist/assets/roadster-second-generation-starman.svg +1 -0
  75. package/dist/assets/roadster-second-generation-starman.thick.svg +1 -0
  76. package/dist/assets/roadster-second-generation.glb +0 -0
  77. package/dist/assets/roadster-second-generation.painted.svg +1 -0
  78. package/dist/assets/roadster-second-generation.svg +1 -0
  79. package/dist/assets/roadster-second-generation.thick.svg +1 -0
  80. package/dist/data/countries.d.ts +51 -0
  81. package/dist/data/countries.js +91 -0
  82. package/dist/data/credits.d.ts +36 -0
  83. package/dist/data/credits.js +36 -0
  84. package/dist/data/falcon.js +26 -14
  85. package/dist/data/makers.js +1 -0
  86. package/dist/data/roadster.d.ts +13 -0
  87. package/dist/data/roadster.js +73 -0
  88. package/dist/data/sources.d.ts +56 -0
  89. package/dist/data/sources.js +7 -0
  90. package/dist/element/flag.d.ts +30 -0
  91. package/dist/element/flag.js +23 -0
  92. package/dist/element/scene.d.ts +7 -0
  93. package/dist/element/scene.js +35 -1
  94. package/dist/element.d.ts +5 -0
  95. package/dist/element.js +58 -2
  96. package/dist/index.d.ts +3 -0
  97. package/dist/index.js +2 -0
  98. package/dist/inspace.js +1 -0
  99. package/dist/model/registry.js +6 -4
  100. package/dist/model/roadster.d.ts +31 -0
  101. package/dist/model/roadster.js +112 -0
  102. package/dist/parts.d.ts +1 -1
  103. package/dist/physics/atmosphere.d.ts +182 -0
  104. package/dist/physics/atmosphere.js +246 -0
  105. package/dist/physics/attitude.d.ts +342 -0
  106. package/dist/physics/attitude.js +351 -0
  107. package/dist/physics/burns.d.ts +194 -0
  108. package/dist/physics/burns.js +157 -0
  109. package/dist/physics/elements.d.ts +133 -0
  110. package/dist/physics/elements.js +239 -0
  111. package/dist/physics/gravity.d.ts +53 -0
  112. package/dist/physics/gravity.js +78 -0
  113. package/dist/physics/index.d.ts +17 -0
  114. package/dist/physics/index.js +8 -0
  115. package/dist/physics/propagate.d.ts +110 -0
  116. package/dist/physics/propagate.js +122 -0
  117. package/dist/physics/rocket.d.ts +105 -0
  118. package/dist/physics/rocket.js +102 -0
  119. package/dist/physics/transfers.d.ts +128 -0
  120. package/dist/physics/transfers.js +155 -0
  121. package/dist/physics/vector.d.ts +20 -0
  122. package/dist/physics/vector.js +9 -0
  123. package/dist/react.d.ts +1 -1
  124. package/dist/rockets.d.ts +5 -0
  125. package/dist/rockets.js +9 -4
  126. package/dist/sun.d.ts +13 -0
  127. package/dist/sun.js +25 -0
  128. package/package.json +11 -1
@@ -0,0 +1,51 @@
1
+ import type { MakerId } from "./makers.ts";
2
+ import { type Figure } from "./types.ts";
3
+ /**
4
+ * Every country code that ISO 3166-1 assigns, two capital letters each, in order.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { COUNTRY_CODES } from "@johnmorrisdotca/uchusen-rockets";
9
+ *
10
+ * console.log(COUNTRY_CODES.length, COUNTRY_CODES.includes("JP"));
11
+ * ```
12
+ */
13
+ export declare const COUNTRY_CODES: readonly ["AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "ZA", "ZM", "ZW"];
14
+ /**
15
+ * An ISO 3166-1 alpha-2 country code.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import type { CountryCode } from "@johnmorrisdotca/uchusen-rockets";
20
+ *
21
+ * const japan: CountryCode = "JP";
22
+ * console.log(japan);
23
+ * ```
24
+ */
25
+ export type CountryCode = (typeof COUNTRY_CODES)[number];
26
+ /** By rocket id: the built ones and the planned ones. A ship of the SPX fleet is the package's own design and has none (see `countryOf`). */
27
+ export declare const ROCKET_COUNTRIES: Readonly<Record<string, Figure<CountryCode>>>;
28
+ /**
29
+ * Each maker group's country as an ISO 3166-1 alpha-2 code with its source. The SPX fleet is this package's own design, and the sites are a group of places, not one maker: both are blank.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * import { MAKER_COUNTRIES } from "@johnmorrisdotca/uchusen-rockets";
34
+ *
35
+ * console.log(MAKER_COUNTRIES.spacex.value, MAKER_COUNTRIES.fleet.value);
36
+ * ```
37
+ */
38
+ export declare const MAKER_COUNTRIES: Readonly<Record<MakerId, Figure<CountryCode>>>;
39
+ /**
40
+ * A rocket's country, as an ISO 3166-1 alpha-2 code with its source, or a blank that says why there is none: a craft of several countries or an international body, or a ship of the SPX fleet.
41
+ *
42
+ * @param rocket A rocket's id, built or planned.
43
+ * @returns The figure: `value` is the code, or null.
44
+ * @example
45
+ * ```ts
46
+ * import { countryOf } from "@johnmorrisdotca/uchusen-rockets";
47
+ *
48
+ * console.log(countryOf("falcon-9").value, countryOf("iss").value, countryOf("iss").brief);
49
+ * ```
50
+ */
51
+ export declare function countryOf(rocket: string): Figure<CountryCode>;
@@ -0,0 +1,91 @@
1
+ import { blank } from "./types.js";
2
+ /**
3
+ * Every country code that ISO 3166-1 assigns, two capital letters each, in order.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * import { COUNTRY_CODES } from "@johnmorrisdotca/uchusen-rockets";
8
+ *
9
+ * console.log(COUNTRY_CODES.length, COUNTRY_CODES.includes("JP"));
10
+ * ```
11
+ */
12
+ export const COUNTRY_CODES = [
13
+ "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ",
14
+ "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR",
15
+ "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP",
16
+ "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS",
17
+ "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS",
18
+ "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW",
19
+ "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "ZA", "ZM", "ZW",
20
+ ];
21
+ const us = (source, note) => ({ value: "US", source, ...(note ? { note } : {}) });
22
+ const SPACEX = "SpaceX, whose headquarters are at Starbase, Texas, United States.";
23
+ /** By rocket id: the built ones and the planned ones. A ship of the SPX fleet is the package's own design and has none (see `countryOf`). */
24
+ export const ROCKET_COUNTRIES = {
25
+ starship: us("wikipedia-spacex", SPACEX),
26
+ "falcon-9": us("wikipedia-falcon-9"),
27
+ "falcon-heavy": us("wikipedia-falcon-heavy"),
28
+ dragon: us("wikipedia-dragon-2"),
29
+ grasshopper: us("wikipedia-spacex", SPACEX),
30
+ "falcon-1": us("wikipedia-falcon-1"),
31
+ "saturn-v": us("wikipedia-saturn-v"),
32
+ "space-shuttle": us("wikipedia-space-shuttle"),
33
+ sls: us("wikipedia-sls"),
34
+ "new-glenn": us("wikipedia-new-glenn"),
35
+ electron: blank("Its source names two countries of origin, New Zealand and the United States.", "two countries"),
36
+ soyuz: { value: "RU", source: "wikipedia-soyuz-2" },
37
+ "lunar-module": us("wikipedia-lunar-module"),
38
+ "apollo-soyuz": blank("Flown by NASA and the Soviet space program together.", "two countries"),
39
+ gemini: us("wikipedia-gemini"),
40
+ mercury: us("wikipedia-mercury"),
41
+ "jupiter-c": us("wikipedia-jupiter-c"),
42
+ iss: blank("Built and run by the space agencies of several countries.", "international"),
43
+ hubble: blank("A NASA and ESA space telescope.", "international"),
44
+ tiangong: { value: "CN", source: "wikipedia-tiangong" },
45
+ roadster: us("wikipedia-roadster-in-space"),
46
+ droneship: us("wikipedia-asds", "Based at Port Canaveral, the Port of Long Beach and the Port of Brownsville."),
47
+ "landing-zone": us("wikipedia-lz", "At Cape Canaveral Space Force Station; Landing Zone 4 is at Vandenberg."),
48
+ "launch-tower": us("wikipedia-starbase", "The tower at Starbase, Texas."),
49
+ starbase: us("wikipedia-starbase"),
50
+ "vulcan-centaur": us("wikipedia-vulcan"),
51
+ "ariane-6": blank("Its source gives its origin as European multi-national.", "international"),
52
+ };
53
+ /**
54
+ * Each maker group's country as an ISO 3166-1 alpha-2 code with its source. The SPX fleet is this package's own design, and the sites are a group of places, not one maker: both are blank.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * import { MAKER_COUNTRIES } from "@johnmorrisdotca/uchusen-rockets";
59
+ *
60
+ * console.log(MAKER_COUNTRIES.spacex.value, MAKER_COUNTRIES.fleet.value);
61
+ * ```
62
+ */
63
+ export const MAKER_COUNTRIES = {
64
+ spacex: us("wikipedia-spacex"),
65
+ nasa: us("wikipedia-nasa"),
66
+ "blue-origin": us("wikipedia-blue-origin"),
67
+ "rocket-lab": us("wikipedia-rocket-lab", "Headquartered in Long Beach, California; founded in Auckland, New Zealand."),
68
+ russia: { value: "RU", source: "wikipedia-soyuz-2" },
69
+ "us-army": us("wikipedia-jupiter-c"),
70
+ china: { value: "CN", source: "wikipedia-tiangong" },
71
+ fleet: blank("The SPX fleet is this package's own design.", "none"),
72
+ sites: blank("A group of places, not one maker.", "none"),
73
+ };
74
+ const FLEET = blank("A ship of the SPX fleet, this package's own design.", "none");
75
+ /**
76
+ * A rocket's country, as an ISO 3166-1 alpha-2 code with its source, or a blank that says why there is none: a craft of several countries or an international body, or a ship of the SPX fleet.
77
+ *
78
+ * @param rocket A rocket's id, built or planned.
79
+ * @returns The figure: `value` is the code, or null.
80
+ * @example
81
+ * ```ts
82
+ * import { countryOf } from "@johnmorrisdotca/uchusen-rockets";
83
+ *
84
+ * console.log(countryOf("falcon-9").value, countryOf("iss").value, countryOf("iss").brief);
85
+ * ```
86
+ */
87
+ export function countryOf(rocket) {
88
+ if (Object.hasOwn(ROCKET_COUNTRIES, rocket))
89
+ return ROCKET_COUNTRIES[rocket];
90
+ return rocket.startsWith("fleet-") ? FLEET : blank("Not read for this id.");
91
+ }
@@ -142,6 +142,42 @@ export declare const MODEL_CREDITS: {
142
142
  readonly "nasa-curiosity": ModelCredit;
143
143
  readonly "nasa-hete": ModelCredit;
144
144
  readonly "nasa-grease-gun": ModelCredit;
145
+ readonly "the86guy-roadster": {
146
+ readonly title: "2008 Roadster";
147
+ readonly creator: "the 86 guy";
148
+ readonly creatorUrl: "https://sketchfab.com/the_86_guy";
149
+ readonly sourceUrl: "https://sketchfab.com/3d-models/2008-tesla-roadster-317dabbe5e824948a92091f7bd39c2de";
150
+ readonly licence: "CC BY 4.0";
151
+ readonly licenceUrl: "https://creativecommons.org/licenses/by/4.0/";
152
+ readonly changes: "Reduced from 502,492 triangles; the badges, lettering and dial faces removed with the materials that carried them; the roof panel, the lamps' insides and the wheel nuts left out; rescaled to the sourced length; the bonnet made bare carbon; materials merged and renamed.";
153
+ };
154
+ readonly "metarex4d-roadster": {
155
+ readonly title: "Roadster 2020";
156
+ readonly creator: "metarex.4d";
157
+ readonly creatorUrl: "https://sketchfab.com/metarex.4d";
158
+ readonly sourceUrl: "https://sketchfab.com/3d-models/tesla-roadster-2020-1fbf29e297bd4a17ac39a00a378441d8";
159
+ readonly licence: "CC BY 4.0";
160
+ readonly licenceUrl: "https://creativecommons.org/licenses/by/4.0/";
161
+ readonly changes: "Reduced from 608,850 triangles; the badge on the nose, the lettering on the tail and the marks on the wheels and the steering wheel removed; its textures left out; rescaled to the sourced wheelbase; repainted in the first generation's red; materials merged and renamed.";
162
+ };
163
+ readonly "gmmichaelonearth-roadster": {
164
+ readonly title: "Roadster 2.0 (Will be enchanced soon)";
165
+ readonly creator: "Michael (gmmichaelonearth)";
166
+ readonly creatorUrl: "https://sketchfab.com/gmmichaelonearth";
167
+ readonly sourceUrl: "https://sketchfab.com/3d-models/tesla-roadster-20-will-be-enchanced-soon-8d5da3904e434fc3830edf558cb9014d";
168
+ readonly licence: "CC BY 4.0";
169
+ readonly licenceUrl: "https://creativecommons.org/licenses/by/4.0/";
170
+ readonly changes: "Reduced from 552,876 triangles; the wheels' middle caps, which carry a mark, removed; its body's picture shrunk and its white made the first generation's red; rescaled to the sourced wheelbase; materials merged and renamed. Its wheels are minchou19's, credited on their own.";
171
+ };
172
+ readonly "minchou19-wheels": {
173
+ readonly title: "Roadster fly wheels";
174
+ readonly creator: "minchou19";
175
+ readonly creatorUrl: "https://sketchfab.com/minchou19";
176
+ readonly sourceUrl: "https://sketchfab.com/3d-models/tesla-roadster-fly-wheels-31a0476f5fd14fc282e799b8ae4ae4f3";
177
+ readonly licence: "CC BY 4.0";
178
+ readonly licenceUrl: "https://creativecommons.org/licenses/by/4.0/";
179
+ readonly changes: "Used as Michael's model has them, on its second-generation Roadster: their middle caps, which carry a mark, removed; reduced; rescaled with the car; materials merged and renamed.";
180
+ };
145
181
  };
146
182
  /**
147
183
  * The id of one model's credit in `MODEL_CREDITS`.
@@ -134,6 +134,42 @@ export const MODEL_CREDITS = {
134
134
  "nasa-curiosity": nasa("Curiosity Rover (Detailed)", "https://science.nasa.gov/3d-resources/curiosity-rover-detailed/", "Only the arm's two links, its tool turret and a swivel kept, from NASA's printable parts (STL, no textures); painted by this package; moved and scaled to the drone's arms. No mark was on it."),
135
135
  "nasa-hete": nasa("High Energy Transient Explorer", "https://science.nasa.gov/3d-resources/high-energy-transient-explorer/", "Its body kept as the drone's equipment block, turned and scaled; its materials made into one picture with this package's own. No mark was on it."),
136
136
  "nasa-grease-gun": nasa("Grease Gun", "https://science.nasa.gov/3d-resources/grease-gun/", "Scaled from millimetres to the drone's welding tool and given a welding nozzle of this package's own; its materials made into one picture. No mark was on it."),
137
+ "the86guy-roadster": {
138
+ title: "2008 Roadster",
139
+ creator: "the 86 guy",
140
+ creatorUrl: "https://sketchfab.com/the_86_guy",
141
+ sourceUrl: "https://sketchfab.com/3d-models/2008-tesla-roadster-317dabbe5e824948a92091f7bd39c2de",
142
+ licence: "CC BY 4.0",
143
+ licenceUrl: LICENCE_URL,
144
+ changes: "Reduced from 502,492 triangles; the badges, lettering and dial faces removed with the materials that carried them; the roof panel, the lamps' insides and the wheel nuts left out; rescaled to the sourced length; the bonnet made bare carbon; materials merged and renamed.",
145
+ },
146
+ "metarex4d-roadster": {
147
+ title: "Roadster 2020",
148
+ creator: "metarex.4d",
149
+ creatorUrl: "https://sketchfab.com/metarex.4d",
150
+ sourceUrl: "https://sketchfab.com/3d-models/tesla-roadster-2020-1fbf29e297bd4a17ac39a00a378441d8",
151
+ licence: "CC BY 4.0",
152
+ licenceUrl: LICENCE_URL,
153
+ changes: "Reduced from 608,850 triangles; the badge on the nose, the lettering on the tail and the marks on the wheels and the steering wheel removed; its textures left out; rescaled to the sourced wheelbase; repainted in the first generation's red; materials merged and renamed.",
154
+ },
155
+ "gmmichaelonearth-roadster": {
156
+ title: "Roadster 2.0 (Will be enchanced soon)",
157
+ creator: "Michael (gmmichaelonearth)",
158
+ creatorUrl: "https://sketchfab.com/gmmichaelonearth",
159
+ sourceUrl: "https://sketchfab.com/3d-models/tesla-roadster-20-will-be-enchanced-soon-8d5da3904e434fc3830edf558cb9014d",
160
+ licence: "CC BY 4.0",
161
+ licenceUrl: LICENCE_URL,
162
+ changes: "Reduced from 552,876 triangles; the wheels' middle caps, which carry a mark, removed; its body's picture shrunk and its white made the first generation's red; rescaled to the sourced wheelbase; materials merged and renamed. Its wheels are minchou19's, credited on their own.",
163
+ },
164
+ "minchou19-wheels": {
165
+ title: "Roadster fly wheels",
166
+ creator: "minchou19",
167
+ creatorUrl: "https://sketchfab.com/minchou19",
168
+ sourceUrl: "https://sketchfab.com/3d-models/tesla-roadster-fly-wheels-31a0476f5fd14fc282e799b8ae4ae4f3",
169
+ licence: "CC BY 4.0",
170
+ licenceUrl: LICENCE_URL,
171
+ changes: "Used as Michael's model has them, on its second-generation Roadster: their middle caps, which carry a mark, removed; reduced; rescaled with the car; materials merged and renamed.",
172
+ },
137
173
  // new rows go here
138
174
  };
139
175
  /**
@@ -1,4 +1,5 @@
1
1
  // Falcon 9 and Falcon Heavy as the sources give them. r/SpaceX's SpaceX-API (Apache-2.0, archived in 2024) has one row per rocket, not per version, read from its repository's docs. A blank stays blank.
2
+ import { ROADSTER_FLIGHT } from "./roadster.js";
2
3
  import { blank } from "./types.js";
3
4
  const F9 = "wikipedia-falcon-9";
4
5
  const V10 = "wikipedia-falcon-9-v1-0";
@@ -121,21 +122,32 @@ export const FALCON_9_VARIANTS = [
121
122
  },
122
123
  },
123
124
  ];
125
+ const FALCON_HEAVY = {
126
+ id: "falcon-heavy",
127
+ rocket: "falcon-heavy",
128
+ name: "Falcon Heavy",
129
+ status: "flown",
130
+ firstFlight: said("2018-02-06", FH, { note: "The test flight." }),
131
+ slots: ["centre", "side-left", "side-right"],
132
+ note: "The painted model is one merged mesh. Its side boosters separate by their own connected pieces, and its centre core, upper stage and fairing are one continuous shell, so they stay one part: nothing is cut to fake a separation. Low detail: a low-poly model.",
133
+ facts: {
134
+ height: m(70, FH, { others: [{ value: 70, source: API, note: "SpaceX-API says the same." }] }),
135
+ diameter: m(12.2, FH, { brief: "across the three cores; 3.7 m each" }),
136
+ parts: { centre: m(70, FH), "side-left": blank("No source read here gives a side booster's height."), "side-right": blank("No source read here gives a side booster's height.") },
137
+ engines: { centre: said("9 Merlin 1D, and 1 vacuum Merlin above", FH), "side-left": said("9 Merlin 1D", FH), "side-right": said("9 Merlin 1D", FH) },
138
+ more: { engines: num(27, FH, { note: "On the three cores." }) },
139
+ },
140
+ };
124
141
  export const FALCON_HEAVY_VARIANTS = [
142
+ FALCON_HEAVY,
125
143
  {
126
- id: "falcon-heavy",
127
- rocket: "falcon-heavy",
128
- name: "Falcon Heavy",
129
- status: "flown",
130
- firstFlight: said("2018-02-06", FH, { note: "The test flight." }),
131
- slots: ["centre", "side-left", "side-right"],
132
- note: "The painted model is one merged mesh. Its side boosters separate by their own connected pieces, and its centre core, upper stage and fairing are one continuous shell, so they stay one part: nothing is cut to fake a separation. Low detail: a low-poly model.",
133
- facts: {
134
- height: m(70, FH, { others: [{ value: 70, source: API, note: "SpaceX-API says the same." }] }),
135
- diameter: m(12.2, FH, { brief: "across the three cores; 3.7 m each" }),
136
- parts: { centre: m(70, FH), "side-left": blank("No source read here gives a side booster's height."), "side-right": blank("No source read here gives a side booster's height.") },
137
- engines: { centre: said("9 Merlin 1D, and 1 vacuum Merlin above", FH), "side-left": said("9 Merlin 1D", FH), "side-right": said("9 Merlin 1D", FH) },
138
- more: { engines: num(27, FH, { note: "On the three cores." }) },
139
- },
144
+ ...FALCON_HEAVY,
145
+ id: ROADSTER_FLIGHT.id,
146
+ name: ROADSTER_FLIGHT.name,
147
+ firstFlight: ROADSTER_FLIGHT.firstFlight,
148
+ slots: ["centre", "side-left", "side-right", "car", "starman"],
149
+ partIds: { "side-left": "falcon-heavy-falcon-heavy-side-left", "side-right": "falcon-heavy-falcon-heavy-side-right" },
150
+ note: `${ROADSTER_FLIGHT.note} ${FALCON_HEAVY.note}`,
151
+ facts: { ...FALCON_HEAVY.facts, parts: { ...FALCON_HEAVY.facts.parts, ...ROADSTER_FLIGHT.payload } },
140
152
  },
141
153
  ];
@@ -31,6 +31,7 @@ export const MADE_BY = {
31
31
  mercury: { maker: "nasa", madeBy: { value: "NASA; built by McDonnell Aircraft", source: "wikipedia-mercury" } },
32
32
  "jupiter-c": { maker: "us-army", madeBy: { value: "Designed by the US Army Ballistic Missile Agency; built by Chrysler", source: "wikipedia-jupiter-c" } },
33
33
  iss: { maker: "nasa", madeBy: { value: "Its US segment built by NASA, ESA, JAXA and CSA, its Russian segment developed by Roscosmos", source: "wikipedia-iss" } },
34
+ roadster: { maker: "spacex", madeBy: { value: "Launched by SpaceX on Falcon Heavy's test flight", source: "wikipedia-roadster-in-space" } },
34
35
  hubble: { maker: "nasa", madeBy: { value: "NASA's Great Observatories program; operated by STScI; built by Lockheed Martin and Perkin-Elmer", source: "wikipedia-hubble" } },
35
36
  tiangong: { maker: "china", madeBy: { value: "China Manned Space Agency; its modules built by the China Academy of Space Technology", source: "wikipedia-tiangong" } },
36
37
  "fleet-ship-01": { maker: "fleet", madeBy: { value: "SPX", source: "uchusen-design" } },
@@ -0,0 +1,13 @@
1
+ import { type Figure, type Variant } from "./types.ts";
2
+ export declare const ROADSTER_VARIANTS: readonly Variant[];
3
+ /** Falcon Heavy as it flew on its test flight: the Roadster and Starman on its upper stage, inside the fairing. */
4
+ export declare const ROADSTER_FLIGHT: {
5
+ readonly id: "test-flight";
6
+ readonly name: "Test flight, with the Roadster";
7
+ readonly firstFlight: Figure<string>;
8
+ readonly note: "The test flight's payload: the Roadster, with Starman at the wheel, on the upper stage inside the fairing. Together, the fairing hides them, as it did; apart, or in space, they show. The car was mounted inclined above its payload adapter; here it stands level where the fairing begins, and the adapter is not drawn. In space the upper stage it stayed on is not drawn either: in the painted model it is one shell with the centre core.";
9
+ readonly payload: {
10
+ readonly car: Figure<number>;
11
+ readonly starman: Figure<number>;
12
+ };
13
+ };
@@ -0,0 +1,73 @@
1
+ // The Roadster, the car that a Falcon Heavy carried on its test flight with Starman at the wheel, and two models of the second generation of the same car, which has not flown. The first generation's
2
+ // sizes are its own article's; the second generation's article gives only its wheelbase and an approximate width. The flight's date, mass and orbit are the launched car's own article's.
3
+ import { blank } from "./types.js";
4
+ const SPACE = "wikipedia-roadster-in-space";
5
+ const FIRST = "wikipedia-roadster-first-generation";
6
+ const SECOND = "wikipedia-roadster-second-generation";
7
+ const m = (value, source, extra = {}) => ({ value, source, ...extra });
8
+ /** Starman: a mannequin in a pressure suit, in the driver's seat. No source gives his size: he is drawn at a grown man's size, seated. */
9
+ const STARMAN = blank("A mannequin in a pressure suit, in the driver's seat. No source read here gives its size.", "not given");
10
+ const SECOND_FACTS = {
11
+ height: blank("No source read here gives its height. The model, at the sourced wheelbase, stands 1.1 m.", "not given"),
12
+ diameter: m(2, SECOND, { brief: "about", note: "About 79 in, the article's own approximate width. The model, at the sourced wheelbase, is 1.85 m across." }),
13
+ parts: { car: blank("No source read here gives its height."), starman: STARMAN },
14
+ engines: {},
15
+ more: {},
16
+ sizes: { Wheelbase: m(2.825, SECOND, { note: "111.2 in. The model is scaled to it." }) },
17
+ };
18
+ const SECOND_NOTE = "The second generation has not flown: it was shown as a prototype and has not been produced. Starman sits in it for comparison only. Its length and height have no source here: the model is scaled to the sourced wheelbase. Painted in the first generation's red, so the three compare under one light.";
19
+ export const ROADSTER_VARIANTS = [
20
+ {
21
+ id: "first-generation",
22
+ rocket: "roadster",
23
+ name: "First generation, the one in space",
24
+ status: "flown",
25
+ firstWord: "Launched",
26
+ firstFlight: { value: "2018-02-06", source: SPACE, note: "20:45 UTC, on Falcon Heavy's test flight, FH-001, from Kennedy LC-39A." },
27
+ slots: ["car", "starman"],
28
+ note: "The car that flew, with Starman at the wheel, roof off, its bonnet bare carbon. Its article calls it a 2010 car of the first generation; the model is its author's 2008 car of the same generation, scaled to the generation's sourced length, and the years' small differences are not drawn. Starman is this package's own plain shapes in every look; no source gives his size.",
29
+ facts: {
30
+ height: m(1.127, FIRST, { note: "44.4 in, with its roof on. It flew with the roof off: the model, without it, stands 1.07 m." }),
31
+ diameter: m(1.873, FIRST, { note: "73.7 in, its width." }),
32
+ parts: { car: blank("The sourced height is the whole car's, with its roof on."), starman: STARMAN },
33
+ engines: {},
34
+ more: {
35
+ mass: m(1300, SPACE, { brief: "about", note: "About 1,300 kg launched; about 5,900 kg with the upper stage it stayed on." }),
36
+ perihelion: m(0.98613, SPACE, { note: "In astronomical units, epoch 1 May 2018." }),
37
+ aphelion: m(1.6637, SPACE, { note: "In astronomical units, epoch 1 May 2018." }),
38
+ period: m(1.525, SPACE, { note: "In years round the Sun." }),
39
+ },
40
+ sizes: { Length: m(3.946, FIRST, { note: "155.4 in. The model is scaled to it." }), Wheelbase: m(2.352, FIRST, { note: "92.6 in." }) },
41
+ },
42
+ },
43
+ {
44
+ id: "second-generation",
45
+ rocket: "roadster",
46
+ name: "Second generation, not flown",
47
+ status: "announced",
48
+ firstWord: "Shown",
49
+ firstFlight: { value: "2017-11-16", source: SECOND, brief: "shown, not flown", note: "Shown as a prototype. It has not been produced and has not flown." },
50
+ slots: ["car", "starman"],
51
+ note: SECOND_NOTE,
52
+ facts: SECOND_FACTS,
53
+ },
54
+ {
55
+ id: "second-generation-2",
56
+ rocket: "roadster",
57
+ name: "Second generation, another model",
58
+ status: "announced",
59
+ firstWord: "Shown",
60
+ firstFlight: { value: "2017-11-16", source: SECOND, brief: "shown, not flown", note: "Shown as a prototype. It has not been produced and has not flown." },
61
+ slots: ["car", "starman"],
62
+ note: `${SECOND_NOTE} A second model of the same car, by another author, its wheels by a third.`,
63
+ facts: SECOND_FACTS,
64
+ },
65
+ ];
66
+ /** Falcon Heavy as it flew on its test flight: the Roadster and Starman on its upper stage, inside the fairing. */
67
+ export const ROADSTER_FLIGHT = {
68
+ id: "test-flight",
69
+ name: "Test flight, with the Roadster",
70
+ firstFlight: { value: "2018-02-06", source: SPACE, note: "20:45 UTC, FH-001, from Kennedy LC-39A." },
71
+ note: "The test flight's payload: the Roadster, with Starman at the wheel, on the upper stage inside the fairing. Together, the fairing hides them, as it did; apart, or in space, they show. The car was mounted inclined above its payload adapter; here it stands level where the fairing begins, and the adapter is not drawn. In space the upper stage it stayed on is not drawn either: in the painted model it is one shell with the centre core.",
72
+ payload: { car: blank("The car's own height is in the Roadster's facts."), starman: STARMAN },
73
+ };
@@ -427,6 +427,38 @@ export declare const SOURCES: {
427
427
  readonly read: "direct";
428
428
  readonly licence: "CC BY-SA 4.0";
429
429
  };
430
+ readonly "wikipedia-spacex": {
431
+ readonly title: "SpaceX (the infobox: its headquarters)";
432
+ readonly publisher: "Wikipedia";
433
+ readonly url: "https://en.wikipedia.org/wiki/SpaceX";
434
+ readonly date: "2026-11-11";
435
+ readonly read: "direct";
436
+ readonly licence: "CC BY-SA 4.0";
437
+ };
438
+ readonly "wikipedia-nasa": {
439
+ readonly title: "NASA (the infobox and first lines: an agency of the United States government)";
440
+ readonly publisher: "Wikipedia";
441
+ readonly url: "https://en.wikipedia.org/wiki/NASA";
442
+ readonly date: "2026-11-11";
443
+ readonly read: "direct";
444
+ readonly licence: "CC BY-SA 4.0";
445
+ };
446
+ readonly "wikipedia-blue-origin": {
447
+ readonly title: "Blue Origin (the infobox: its headquarters)";
448
+ readonly publisher: "Wikipedia";
449
+ readonly url: "https://en.wikipedia.org/wiki/Blue_Origin";
450
+ readonly date: "2026-11-11";
451
+ readonly read: "direct";
452
+ readonly licence: "CC BY-SA 4.0";
453
+ };
454
+ readonly "wikipedia-rocket-lab": {
455
+ readonly title: "Rocket Lab (the infobox: its headquarters and where it was founded)";
456
+ readonly publisher: "Wikipedia";
457
+ readonly url: "https://en.wikipedia.org/wiki/Rocket_Lab";
458
+ readonly date: "2026-11-11";
459
+ readonly read: "direct";
460
+ readonly licence: "CC BY-SA 4.0";
461
+ };
430
462
  readonly "wikipedia-asds": {
431
463
  readonly title: "Autonomous spaceport drone ship";
432
464
  readonly publisher: "Wikipedia";
@@ -698,6 +730,30 @@ export declare const SOURCES: {
698
730
  readonly read: "direct";
699
731
  readonly licence: "CC BY-SA 4.0";
700
732
  };
733
+ readonly "wikipedia-roadster-in-space": {
734
+ readonly title: "The Roadster launched on Falcon Heavy's test flight (the infobox, and its background and trajectory sections)";
735
+ readonly publisher: "Wikipedia";
736
+ readonly url: "https://en.wikipedia.org/wiki/Elon_Musk%27s_Tesla_Roadster";
737
+ readonly date: "2026-11-11";
738
+ readonly read: "direct";
739
+ readonly licence: "CC BY-SA 4.0";
740
+ };
741
+ readonly "wikipedia-roadster-first-generation": {
742
+ readonly title: "The Roadster, first generation (the infobox)";
743
+ readonly publisher: "Wikipedia";
744
+ readonly url: "https://en.wikipedia.org/wiki/Tesla_Roadster_(first_generation)";
745
+ readonly date: "2026-11-11";
746
+ readonly read: "direct";
747
+ readonly licence: "CC BY-SA 4.0";
748
+ };
749
+ readonly "wikipedia-roadster-second-generation": {
750
+ readonly title: "The Roadster, second generation (the infobox and its history)";
751
+ readonly publisher: "Wikipedia";
752
+ readonly url: "https://en.wikipedia.org/wiki/Tesla_Roadster_(second_generation)";
753
+ readonly date: "2026-11-11";
754
+ readonly read: "direct";
755
+ readonly licence: "CC BY-SA 4.0";
756
+ };
701
757
  readonly "wikipedia-discovery": {
702
758
  readonly title: "Space Shuttle Discovery (the infobox)";
703
759
  readonly publisher: "Wikipedia";
@@ -62,6 +62,10 @@ export const SOURCES = {
62
62
  "wikipedia-soyuz-2": { title: "Soyuz-2 (the infobox)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Soyuz-2", date: "2026-11-02", read: "direct", licence: "CC BY-SA 4.0" },
63
63
  "wikipedia-vulcan": { title: "Vulcan Centaur (the infobox)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Vulcan_Centaur", date: "2026-11-02", read: "direct", licence: "CC BY-SA 4.0" },
64
64
  "wikipedia-ariane-6": { title: "Ariane 6 (the infobox)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Ariane_6", date: "2026-11-02", read: "direct", licence: "CC BY-SA 4.0" },
65
+ "wikipedia-spacex": { title: "SpaceX (the infobox: its headquarters)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/SpaceX", date: "2026-11-11", read: "direct", licence: "CC BY-SA 4.0" },
66
+ "wikipedia-nasa": { title: "NASA (the infobox and first lines: an agency of the United States government)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/NASA", date: "2026-11-11", read: "direct", licence: "CC BY-SA 4.0" },
67
+ "wikipedia-blue-origin": { title: "Blue Origin (the infobox: its headquarters)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Blue_Origin", date: "2026-11-11", read: "direct", licence: "CC BY-SA 4.0" },
68
+ "wikipedia-rocket-lab": { title: "Rocket Lab (the infobox: its headquarters and where it was founded)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Rocket_Lab", date: "2026-11-11", read: "direct", licence: "CC BY-SA 4.0" },
65
69
  "wikipedia-asds": { title: "Autonomous spaceport drone ship", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Autonomous_spaceport_drone_ship", date: "2026-11-02", read: "direct", licence: "CC BY-SA 4.0" },
66
70
  "wikipedia-lz": { title: "Landing Zones 1 and 2", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Landing_Zones_1_and_2", date: "2026-11-02", read: "direct", licence: "CC BY-SA 4.0" },
67
71
  "wikipedia-slc-4": { title: "Vandenberg Space Launch Complex 4", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Vandenberg_Space_Launch_Complex_4", date: "2026-11-02", read: "direct", licence: "CC BY-SA 4.0" },
@@ -96,6 +100,9 @@ export const SOURCES = {
96
100
  "wikipedia-tranquility": { title: "Tranquility (ISS module) (the infobox)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Tranquility_(ISS_module)", date: "2026-11-11", read: "direct", licence: "CC BY-SA 4.0" },
97
101
  "wikipedia-cupola": { title: "Cupola (ISS module) (the infobox)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Cupola_(ISS_module)", date: "2026-11-11", read: "direct", licence: "CC BY-SA 4.0" },
98
102
  "wikipedia-leonardo": { title: "Leonardo (ISS module) (the infobox)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Leonardo_(ISS_module)", date: "2026-11-11", read: "direct", licence: "CC BY-SA 4.0" },
103
+ "wikipedia-roadster-in-space": { title: "The Roadster launched on Falcon Heavy's test flight (the infobox, and its background and trajectory sections)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Elon_Musk%27s_Tesla_Roadster", date: "2026-11-11", read: "direct", licence: "CC BY-SA 4.0" },
104
+ "wikipedia-roadster-first-generation": { title: "The Roadster, first generation (the infobox)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Tesla_Roadster_(first_generation)", date: "2026-11-11", read: "direct", licence: "CC BY-SA 4.0" },
105
+ "wikipedia-roadster-second-generation": { title: "The Roadster, second generation (the infobox and its history)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Tesla_Roadster_(second_generation)", date: "2026-11-11", read: "direct", licence: "CC BY-SA 4.0" },
99
106
  "wikipedia-discovery": { title: "Space Shuttle Discovery (the infobox)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Space_Shuttle_Discovery", date: "2026-11-02", read: "direct", licence: "CC BY-SA 4.0" },
100
107
  "wikipedia-falcon-heavy": { title: "Falcon Heavy", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Falcon_Heavy", date: "2026-10-31", read: "direct", licence: "CC BY-SA 4.0" },
101
108
  "wikipedia-flight-5": { title: "Starship flight test 5 (its flight timeline, read as raw wikitext)", publisher: "Wikipedia", url: "https://en.wikipedia.org/wiki/Starship_flight_test_5", date: "2026-11-02", read: "direct", licence: "CC BY-SA 4.0" },
@@ -0,0 +1,30 @@
1
+ /**
2
+ * What the element takes from hata's `/load` entry: a flag's SVG by its code. Written out here, so no type of this package reaches the optional peer.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import type { FlagSource } from "@johnmorrisdotca/uchusen-rockets/element";
7
+ *
8
+ * const none: FlagSource = { flag: () => Promise.resolve(null) };
9
+ * console.log(await none.flag("US"));
10
+ * ```
11
+ */
12
+ export interface FlagSource {
13
+ flag(code: string, options?: {
14
+ shape?: "4:3" | "1:1" | "round";
15
+ }): Promise<string | null>;
16
+ }
17
+ /**
18
+ * Where the flags come from, if a page wants to hand them over itself (before the first element with `flags` connects): a module with hata's `flag(code, { shape })`, such as one that imports only the flags the page shows.
19
+ *
20
+ * @param load Returns hata's `/load` entry, or a module with the same `flag`, as a promise.
21
+ * @example
22
+ * ```ts no-run
23
+ * import { setFlagLoader } from "@johnmorrisdotca/uchusen-rockets/element";
24
+ *
25
+ * setFlagLoader(() => import("@johnmorrisdotca/hata/load"));
26
+ * ```
27
+ */
28
+ export declare function setFlagLoader(load: () => Promise<FlagSource>): void;
29
+ /** A country's flag at 4:3 as SVG markup, or null when hata is not there, failed to load or has no flag for the code. It never rejects. */
30
+ export declare function flagSvg(code: string): Promise<string | null>;
@@ -0,0 +1,23 @@
1
+ // A country's flag for the `flags` attribute, from @johnmorrisdotca/hata, an optional peer loaded only when a flag is first wanted. Without it, or when it fails to load, there is no flag and nothing is logged.
2
+ let loader = () => import("@johnmorrisdotca/hata/load");
3
+ let loaded;
4
+ /**
5
+ * Where the flags come from, if a page wants to hand them over itself (before the first element with `flags` connects): a module with hata's `flag(code, { shape })`, such as one that imports only the flags the page shows.
6
+ *
7
+ * @param load Returns hata's `/load` entry, or a module with the same `flag`, as a promise.
8
+ * @example
9
+ * ```ts no-run
10
+ * import { setFlagLoader } from "@johnmorrisdotca/uchusen-rockets/element";
11
+ *
12
+ * setFlagLoader(() => import("@johnmorrisdotca/hata/load"));
13
+ * ```
14
+ */
15
+ export function setFlagLoader(load) {
16
+ loader = load;
17
+ loaded = undefined;
18
+ }
19
+ /** A country's flag at 4:3 as SVG markup, or null when hata is not there, failed to load or has no flag for the code. It never rejects. */
20
+ export function flagSvg(code) {
21
+ loaded ??= loader().catch(() => null);
22
+ return loaded.then((hata) => (hata ? hata.flag(code, { shape: "4:3" }) : null)).catch(() => null);
23
+ }
@@ -216,6 +216,13 @@ export declare class RocketViewer {
216
216
  private offScreen;
217
217
  /** The words added to a floating name when that craft is outside the frame. Empty adds nothing. */
218
218
  setOffScreen(text: string | null): void;
219
+ /** The direction towards the Sun, in the craft's own frame, when a page gives one; null keeps the showroom light. */
220
+ private sunFrom;
221
+ /** One light from the Sun's real direction, as in space: the far side dark, with at most a faint fill. Null puts the showroom light back. */
222
+ setSun(direction: readonly [number, number, number] | null): void;
223
+ /** The key light comes from the Sun when there is one, else from the showroom's upper front. */
224
+ private keyDirection;
225
+ private aimKey;
219
226
  /** Open space lets a craft leave the frame. Wrap, the older float, brings it back on the other side. */
220
227
  private edgesOpen;
221
228
  setEdges(open: boolean): void;
@@ -421,6 +421,31 @@ export class RocketViewer {
421
421
  this.offScreen = next;
422
422
  this.wake();
423
423
  }
424
+ /** The direction towards the Sun, in the craft's own frame, when a page gives one; null keeps the showroom light. */
425
+ sunFrom = null;
426
+ /** One light from the Sun's real direction, as in space: the far side dark, with at most a faint fill. Null puts the showroom light back. */
427
+ setSun(direction) {
428
+ const before = this.sunFrom;
429
+ this.sunFrom = direction ? new Vector3(...direction) : null;
430
+ this.canvas.dataset.sun = this.sunFrom ? "on" : "off";
431
+ if (before === this.sunFrom || (before && this.sunFrom && before.equals(this.sunFrom)))
432
+ return;
433
+ this.nightSide();
434
+ this.aimKey();
435
+ this.wake();
436
+ }
437
+ /** The key light comes from the Sun when there is one, else from the showroom's upper front. */
438
+ keyDirection() {
439
+ return (this.sunFrom ?? new Vector3(3, 5, 4)).clone().normalize();
440
+ }
441
+ aimKey() {
442
+ if (this.shadows && this.built) {
443
+ this.fitShadow();
444
+ return;
445
+ }
446
+ this.sun.position.copy(this.sun.target.position).addScaledVector(this.keyDirection(), 7);
447
+ this.sun.target.updateMatrixWorld();
448
+ }
424
449
  /** Open space lets a craft leave the frame. Wrap, the older float, brings it back on the other side. */
425
450
  edgesOpen = false;
426
451
  setEdges(open) {
@@ -1075,6 +1100,15 @@ export class RocketViewer {
1075
1100
  /** The Lit look of a named SPX ship is the night side. Daylight stays the default, so lamps glow in the sun, and a kit module stays in daylight. */
1076
1101
  nightSide() {
1077
1102
  const night = this.shipNight && this.lightsMode !== "off" && this.glowOn;
1103
+ if (this.sunFrom && !night) {
1104
+ // in space there is one light: the Sun, a little stronger than the showroom's key, and next to nothing from anywhere else
1105
+ this.sun.intensity = 2.4;
1106
+ this.rim.intensity = 0;
1107
+ this.fill.intensity = 0;
1108
+ this.sky.intensity = 0.03;
1109
+ this.scene.environmentIntensity = 0.06;
1110
+ return;
1111
+ }
1078
1112
  this.sun.intensity = night ? 0.16 : 1.6;
1079
1113
  this.rim.intensity = night ? 0.04 : 1.1;
1080
1114
  this.fill.intensity = night ? 0.03 : 0.35;
@@ -1601,7 +1635,7 @@ export class RocketViewer {
1601
1635
  const { min, max } = this.built.boundsOf(this.show);
1602
1636
  const centre = new Vector3((min[0] + max[0]) / 2, (min[1] + max[1]) / 2, (min[2] + max[2]) / 2);
1603
1637
  const radius = Math.max(1, Math.hypot(max[0] - min[0], max[1] - min[1], max[2] - min[2]) / 2);
1604
- const direction = new Vector3(3, 5, 4).normalize();
1638
+ const direction = this.keyDirection();
1605
1639
  this.sun.position.copy(centre).addScaledVector(direction, radius * 2);
1606
1640
  this.sun.target.position.copy(centre);
1607
1641
  const shadow = this.sun.shadow;